Skip to content

Commit 3ecd925

Browse files
Merge pull request #13 from flexcompute/docs/cleanup-and-polar-types
docs: remove legacy investigation pages, add polar types and differences-from-xfoil
2 parents 44ba888 + faf5da2 commit 3ecd925

6 files changed

Lines changed: 222 additions & 368 deletions

File tree

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
---
2+
title: Differences from XFOIL
3+
sidebar_label: Differences from XFOIL
4+
sidebar_position: 9
5+
description: Known behavioural differences between RustFoil and XFOIL
6+
---
7+
8+
# Differences from XFOIL
9+
10+
RustFoil is a faithful, function-by-function port of XFOIL. The goal is
11+
bit-level reproducibility of XFOIL's behaviour, including its known limitations
12+
and failure modes.
13+
14+
## Analysis (OPER)
15+
16+
The core analysis pipeline — inviscid panel method, boundary layer solver,
17+
viscous-inviscid coupling, and transition prediction — has no known behavioural
18+
differences from XFOIL. Validation results:
19+
20+
| Component | Agreement |
21+
|-----------|-----------|
22+
| Paneling (PANGEN) | ~4e-7 RMS position error |
23+
| Inviscid CL, Cp, γ | 5–6 significant figures |
24+
| Closure relations (Hk, Hs, Cf, DI) | Formula-identical |
25+
| Viscous-inviscid coupling | Same Newton system |
26+
| Transition (e^N) | Same DAMPL correlation |
27+
| Polar types 1/2/3 | Same Re-scaling formulas |
28+
29+
See [Inviscid Validation](./inviscid-validation), [Paneling Validation](./paneling-validation),
30+
and [Formula Comparison](./xfoil-formula-comparison) for detailed evidence.
31+
32+
## Design Modes
33+
34+
### QDES (Mixed-Inverse)
35+
36+
RustFoil's QDES uses **Gaussian basis functions with damped least-squares**
37+
rather than XFOIL's original `MIXED` Newton solver. The interface is the same
38+
(prescribe target Cp/velocity on a surface segment), but the internal algorithm
39+
differs. Results may not match XFOIL exactly for the same target distribution.
40+
This is an intentional choice for numerical robustness in the browser
41+
environment.
42+
43+
### MDES (Full-Inverse)
44+
45+
The circle-plane conformal mapping is ported from XFOIL, but with known gaps:
46+
47+
- Chord normalization is approximate — output chord may differ slightly from input
48+
- CL computation is approximate; full Karman-Tsien integration not yet ported
49+
- No interactive Fourier coefficient editing
50+
51+
MDES and QDES are marked **experimental** and have not been exhaustively
52+
validated against XFOIL reference cases.
53+
54+
### GDES (Geometry Design)
55+
56+
Geometry operations (flap deflection, TE gap, LE radius, thickness/camber
57+
scaling) match XFOIL's approach. Flap deflection uses a high-resolution
58+
intermediate representation for sub-0.001c precision at the hinge.
59+
60+
## Reporting Differences
61+
62+
If you find a case where RustFoil's analysis output differs from XFOIL's for
63+
the same airfoil and operating conditions, please report it as a bug at
64+
[github.com/flexcompute/flexfoil/issues](https://github.com/flexcompute/flexfoil/issues).
65+
Include the airfoil coordinates, operating conditions (Re, Mach, Ncrit, alpha),
66+
and both outputs.
Lines changed: 13 additions & 111 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,12 @@
11
---
22
sidebar_position: 6
33
title: Paneling Validation
4-
description: Comparison of XFOIL and RustFoil curvature-based paneling (PANGEN)
4+
description: Validation of RustFoil curvature-based paneling against XFOIL's PANGEN
55
---
66

7-
# Paneling Validation: XFOIL vs RustFoil
7+
# Paneling Validation
88

9-
This document compares the paneling algorithms between XFOIL's `PANGEN` subroutine and RustFoil's `resample_xfoil()` implementation.
10-
11-
## Algorithm Overview
12-
13-
Both implementations use **curvature-based panel distribution** with identical parameters:
9+
RustFoil's `resample_xfoil()` function is a faithful port of XFOIL's `PANGEN` subroutine. Both use **curvature-based panel distribution** with identical parameters:
1410

1511
| Parameter | Value | Description |
1612
|-----------|-------|-------------|
@@ -19,11 +15,11 @@ Both implementations use **curvature-based panel distribution** with identical p
1915
| `RDSTE` | 0.667 | TE panel spacing ratio (RTF = 0.334) |
2016
| `IPFAC` | 5 | Newton refinement factor |
2117

22-
### PANGEN Algorithm Steps
18+
### Algorithm Steps
2319

2420
1. Compute arc-length parameterization of buffer airfoil
2521
2. Calculate curvature at each buffer point: κ(s) = |d²r/ds²|
26-
3. **Find leading edge via Newton iteration** (tangent ⊥ to chord)
22+
3. Find leading edge via Newton iteration (tangent ⊥ to chord)
2723
4. Average curvature over 7 points near LE → κ_avg
2824
5. Set artificial TE curvature: κ_TE = κ_avg × CTERAT
2925
6. Smooth curvature with tridiagonal diffusion
@@ -34,115 +30,21 @@ Both implementations use **curvature-based panel distribution** with identical p
3430

3531
## Validation Results
3632

37-
### Symmetric Airfoils (NACA 0012)
33+
All tested airfoils match XFOIL's paneling to numerical precision (~4e-7 RMS position error):
3834

39-
**Perfect match achieved:**
35+
| Foil | XFOIL LE Index | RustFoil LE Index | RMS Error |
36+
|------|----------|-------------|-----------|
37+
| NACA 0012 | 79 | 79 | 4.05e-7 |
38+
| NACA 2412 | 81 | 81 | 3.97e-7 |
39+
| NACA 4412 | 82 | 82 | 4.42e-7 |
4040

41-
| Metric | Value |
42-
|--------|-------|
43-
| RMS Position Error | 4.05e-7 |
44-
| Max Position Error | 5.92e-7 |
45-
| LE Index Match | ✓ (idx=79) |
41+
### Point-by-Point Comparison (NACA 0012)
4642

4743
```
48-
First 5 points comparison:
4944
idx xfoil_x xfoil_y rustfoil_x rustfoil_y error
5045
0 1.00000000 0.00126000 1.00000000 0.00126000 0.00e0
5146
1 0.99167960 0.00242145 0.99167973 0.00242143 1.36e-7
5247
2 0.98036920 0.00398137 0.98036941 0.00398134 2.14e-7
5348
```
5449

55-
### Cambered Airfoils
56-
57-
**LE detection mismatch identified:**
58-
59-
| Foil | XFOIL LE | RustFoil LE | LE Diff | RMS Error |
60-
|------|----------|-------------|---------|-----------|
61-
| NACA 0012 | idx 79 | idx 79 | 0 | 4.05e-7 ✓ |
62-
| NACA 2412 | idx 81 | idx 83 | +2 | 7.29e-3 |
63-
| NACA 4412 | idx 82 | idx 85 | +3 | 1.13e-2 |
64-
65-
## Root Cause Analysis
66-
67-
The discrepancy for cambered airfoils originates in the **leading edge detection** (`lefind` function).
68-
69-
### XFOIL's LEFIND Algorithm
70-
71-
From `xgeom.f`:
72-
73-
```fortran
74-
C---- Find leading edge location (SBLE) using Newton iteration
75-
C to find where tangent is perpendicular to chord line
76-
XCHORD = X(N) - X(1)
77-
YCHORD = Y(N) - Y(1)
78-
79-
C---- Newton iteration
80-
DO 10 I=1, 50
81-
XPRIME = DEVAL(SBLE,X,XP,S,N)
82-
YPRIME = DEVAL(SBLE,Y,YP,S,N)
83-
84-
C------ Dot product of tangent with chord should be zero at LE
85-
RES = XCHORD*XPRIME + YCHORD*YPRIME
86-
DSLE = -RES / (XCHORD*X2 + YCHORD*Y2)
87-
SBLE = SBLE + DSLE
88-
89-
IF(ABS(DSLE) .LT. 1.0E-6) GO TO 11
90-
10 CONTINUE
91-
```
92-
93-
The key is finding where:
94-
95-
```text
96-
t(s_LE) · chord = 0
97-
```
98-
99-
where `t` is the tangent vector and `chord` connects TE upper to TE lower.
100-
101-
### Issue in RustFoil
102-
103-
RustFoil's `lefind` implementation may have subtle differences in:
104-
1. Initial guess for Newton iteration
105-
2. Convergence tolerance
106-
3. Spline derivative evaluation
107-
108-
## Fix Applied
109-
110-
The original RustFoil implementation had **incorrect symmetry enforcement** in the final node positions (lines 484-492 of `spline.rs`). This worked for symmetric airfoils but caused LE drift for cambered airfoils.
111-
112-
**Fix**: Removed the symmetry enforcement, matching XFOIL's behavior which relies purely on curvature-based distribution without post-processing symmetry.
113-
114-
## Final Results (All Fixed!)
115-
116-
| Foil | XFOIL LE | RustFoil LE | RMS Error | Status |
117-
|------|----------|-------------|-----------|--------|
118-
| NACA 0012 | idx 79 | idx 79 | 4.05e-7 | ✓ Perfect |
119-
| NACA 2412 | idx 81 | idx 81 | 3.97e-7 | ✓ Perfect |
120-
| NACA 4412 | idx 82 | idx 82 | 4.42e-7 | ✓ Perfect |
121-
122-
**All three airfoils now match XFOIL to numerical precision (~4e-7)!**
123-
124-
## Root Cause & Fix
125-
126-
The bug was **forced curvature symmetry** in `resample_xfoil()`:
127-
128-
```rust
129-
// THIS WAS THE BUG (lines 241-247)
130-
for i in 0..n_buffer / 2 {
131-
let avg = (curv_buffer[i] + curv_buffer[j]) / 2.0;
132-
curv_buffer[i] = avg; // WRONG for cambered airfoils!
133-
}
134-
```
135-
136-
**Why it mattered:** For cambered airfoils, the curvature is naturally asymmetric:
137-
- NACA 2412: 26% higher curvature on lower surface near LE
138-
- NACA 4412: 59% higher curvature on lower surface near LE
139-
140-
By forcing symmetry, we were averaging out this natural asymmetry, which caused the Newton iteration to place panels incorrectly.
141-
142-
**XFOIL does NOT force curvature symmetry** - it uses the natural asymmetric curvature for cambered airfoils.
143-
144-
## Conclusion
145-
146-
1. **All airfoils now match**: ~4e-7 RMS error (numerical precision)
147-
2. **Root cause**: Incorrect forced curvature symmetry
148-
3. **Fix**: Removed two forced symmetry operations in `spline.rs`
50+
Leading-edge detection, curvature distribution, and final node placement all match XFOIL exactly for both symmetric and cambered airfoils.

0 commit comments

Comments
 (0)