Skip to content

Fix/xfoil sort empty arrays#176

Open
AhmedMoustafaa wants to merge 2 commits into
peterdsharpe:developfrom
AhmedMoustafaa:fix/xfoil-sort-empty-arrays
Open

Fix/xfoil sort empty arrays#176
AhmedMoustafaa wants to merge 2 commits into
peterdsharpe:developfrom
AhmedMoustafaa:fix/xfoil-sort-empty-arrays

Conversation

@AhmedMoustafaa

Copy link
Copy Markdown
Contributor

Context

The XFoil 6.99 binary distributed via apt on Ubuntu is compiled with Fortran
FPE trapping enabled (-ftrapuv -fpe0), causing it to crash with SIGFPE
before producing any output. Users on Ubuntu who need a working XFoil must
build from source — typically XFoil 6.97, since 6.99 is no longer publicly
hosted. This PR fixes two parser bugs that surface when using a source-built
XFoil 6.97 on Ubuntu.

Fix 1 — 9-column polar output from source-built XFoil 6.97

XFoil 6.97 built from source with gfortran produces 9 data columns per row
against 8 header columns in the polar output file. This caused:

XFoilError: XFoil output file is malformed; the header and data
have different numbers of columns.

The exact cause is unclear — it may be related to how 6.97 handles the
cinc command or a formatting difference between 6.97 and 6.99. The fix
extends the existing monkey-patch block that already handles the analogous
XFoil 6.99 case (10 data columns against 8 header columns):

elif len(data) == 9 and len(columns) == 8:
    # Source-built XFoil 6.97 on Ubuntu produces 9 data columns against
    # 8 header columns. Remap accordingly.
    columns = ["alpha", "CL", "CD", "CDp", "CM", "Cpmin",
               "Chinge", "Top_Xtr", "Bot_Xtr"]

Fix 2 — IndexError when sorting output with unpopulated fields

After the column remapping in Fix 1, Xcpmin is absent from the 6.97 polar
and remains as an empty array in the output dict after parsing. The sort step
at the end of alpha() and cl() then raised:

IndexError: index 2 is out of bounds for axis 0 with size 0

sort_order has length N (number of converged points) but indexing a
zero-length array raises immediately.

The fix drops unpopulated fields before sorting rather than making the sort
step handle mismatched lengths:

output = {k: np.array(v, dtype=float) for k, v in output.items()}
output = {k: v for k, v in output.items() if len(v) > 0}

This is safe for callers: Cpmin and Xcpmin were never guaranteed to be
present in the output — the docstring for alpha() and cl() states only
that "dictionary values are arrays; they may not be the same shape as your
input array if some points did not converge", with no promise of specific
keys. Code that needs these fields should already be using .get().

Note that Fix 2 is also a general defensive fix — any future code path that
leaves output arrays empty would previously have triggered the same IndexError.

Reproduction

Both bugs are reproducible on Ubuntu with XFoil 6.97 built from source using
gfortran. The apt XFoil 6.99 binary crashes with SIGFPE before reaching the
parser, so these bugs are only reachable after resolving the apt binary issue
(see linked issue)

Tests

Added test_xfoil_polar_parsing.py with two regression tests using a mocked
polar file matching XFoil 6.97 output format:

  • test_xfoil_697_cinc_column_mismatch — verifies the 9-column polar is
    parsed correctly and returns valid CL/CD values without raising XFoilError
  • test_xfoil_polar_sort_with_unpopulated_fields — verifies alpha()
    returns correctly sorted results without IndexError when Xcpmin is absent

Test results

460 passed, same 2 pre-existing failures (test_airplane_optimization,
test_cadquery_export) present on develop before this PR.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant