|
FhSim
3.1.0
Marine systems simulation
|
| ID | 0004 |
| Class | BUG |
| Severity | 3 |
| Status | blocked |
| Models | Trawl/TrawlDoorAddedFoil |
| Found | 2026-09-15 audit (a7d080d) |
| Decision needed | Is the tabulated foil polar or the hard-coded roll moment the intended physics? |
src/trawl/TrawlDoorAddedFoil.cpp:68-98, the whole of AddExternalForces:
Four problems in one function:
-(r - 0.5) * 20000 N·m driven solely by FoilExposedAreaRatio, with the 4000 and the 5 hard-coded and unexplained.FoilHydro_Aoa, FoilHydro_CL, FoilHydro_CD, FoilHydro_Cord, FoilHydro_Span, FoilHydro_IsVertical and the input ports FoilRelativeAoa and FoilRelPosition have no effect on the simulation. FoilExposedAreaRatio is the only input that does anything (and in a visualization build also moves the foil mesh, :113-118).drag = 0 with the real expression commented out, so FoilHydro_CD is dead even in the pre-zeroing path.foilForce[0..2] are uninitialized when m_foilIsVertical is false, and line 92 (CalcMoment) reads them. Undefined behaviour, harmless only because line 93 then overwrites everything.The force-application line that would have used the computed pressure centre is itself commented out at line 90.
A user configures a foil with a tabulated lift/drag polar, a chord, a span and an angle-of-attack control input, and gets a door whose foil produces a fixed-magnitude roll moment proportional to the exposed-area ratio and nothing else. Changing the polar, the geometry or the commanded angle of attack changes nothing. Since the class exists to score control concepts, every such study is measuring the hard-coded moment, not the foil.
If the tabulated model is the intended physics:
double foilForce[6] = {0}; at line 71, so the non-vertical branch contributes nothing instead of reading uninitialized memory — and report a parameter error on FoilHydro_IsVertical == false in the constructor if the horizontal case is genuinely unsupported.0.5 * m_rhoWater * foilCD * pow(ma_dU, 2)), the same form as the lift term, using the FoilHydro_CD table the constructor already validates.foilArea (line 74) is computed and never used. Dimensionally 0.5 * rho * C * U^2 is a pressure, not a force; the sibling hydrodynamics in TrawlDoorBase multiply by the door area. Multiplying lift and drag by foilArea is what makes an exposed-area ratio of 0 produce no force, and makes the ratio physically meaningful rather than a pure mesh-position input.AddExternalForce(foilPressureCenter, foilForce), or keep the explicit CalcMoment + ArrayAdd pair, but not both.Owner question: is the tabulated polar the intended physics, or is the hard-coded moment? The zeroing plus the hard-coded foilForce[3] look like a deliberate debugging substitution ("ignore the foil model, apply a known roll moment") that was committed. Nothing else in the foil chain can be decided before this is answered.
Depends on FISH-0001 and on the owner's decision. Two cases in tests/in/SimObj-TrawlDoorAddedFoil*/, both built from examples/input/6DOFTrawlDoor.xml with the foil parameters added and a 2.5 m/s current. Sensitivity: two runs differing only in FoilHydro_CL (all zeros vs. a real polar) must produce different door trajectories — today they are bit-identical, which is the red test and the one sentence that states the defect. Regression: a _ref.csv baseline of door roll, pitch and angle of attack over 30 s, generated after the fix. Also add SimObj-TrawlDoorAddedFoil-Horizontal with FoilHydro_IsVertical = "0" — under a UBSan/MSan build that is the case exhibiting the uninitialized read today.
High for anyone using Trawl/TrawlDoorAddedFoil: results change completely, because today's results are a hard-coded moment and tomorrow's are a foil. No shipped input file uses the type (grep -rl TrawlDoorAddedFoil examples/ is empty), so nothing in-repo breaks, and the class is documented as a testbed for control concepts rather than a production model.
Re-confirmed at HEAD (TrawlDoorAddedFoil.cpp:93-95): the computed foil force is zeroed and a hard-coded roll moment -(r-0.5)*4000*5 is applied instead. Whether the tabulated foil polar or the hard-coded moment is the intended physics cannot be read from the code; the polar tables, the interpolation and the energy port suggest the polar was meant to be live, but the hard-coded moment may be a deliberate simplification the owner still relies on. Changing it moves every TrawlDoorAddedFoil result. This item also gates FISH-0005 and FISH-0006, which are unobservable until the computed force reaches the output. Owner question: tabulated polar or hard-coded moment?