|
FhSim
3.1.0
Marine systems simulation
|
| ID | 0152 |
| Class | BUG |
| Severity | 2 |
| Status | blocked |
Models: —
Found: 2026-10-24 review r2 (R2-07) of 25024ce7
Decision needed: how to pay for, or live with, the lag (owner ruling r2-D2, 2026-10-25: deferred because the bench is over +10 %). Options: (a) accept the extra OdeFcn per accepted step; (b) evaluate only when needed (a SimObject overrides AcceptedStep, or diagnostics need ports; needs a flag in the SimObject API); (c) keep the lag and document it.
FhIntegratorSundials.cpp:202 (at 25024ce7) m_model->AcceptedStep(m_t, m_rawX); with no OdeFcn at the accepted state; the diagnostics run earlier, inside each solver branch (:182,190,198). The Engine order is OdeFcn, AcceptedStep, OnEngineStep (FhIntegrator.cpp:208-224, FHSIM-0066).
A SimObject that reads an input port in AcceptedStep sees the port value of the solver's last stage or iterate, not of the accepted state, and so does the diagnostics port snapshot. With the test input below the lag under CVODE BDF is 0.000179; ARKODE ERK and DIRK showed 0 (their last stage is at the accepted state).
After the SUNDIALS step returns, call m_model->OdeFcn(m_t, m_rawX, m_rawStateDerivative) once, then AcceptedStep, then the step diagnostics (move RunStepDiagnostics_(lastStepSize) out of the three solver branches; keep the step index it is given). It was implemented and measured on branch feature/r2-sundials (commit removed again), cost by callgrind instruction counts, with against without the extra call:
| Input | without | with | change |
|---|---|---|---|
fhsim_gauss CableChainRuntimeBench.xml (BDF) | 1,079,184,906 | 1,334,767,881 | +23.7 % |
fhsim_gauss GaussChainRuntimeBench.xml (BDF) | 411,571,973 | 429,214,662 | +4.3 % |
fhsim IntegratorConfig_BDF_in.xml | 4,471,462 | 4,478,182 | +0.15 % |
No existing golden of fhsim moved, and no consumer result (base, marine_elements, fishery, environment) moved.
A copy of ImplicitIntegration_RK45_AcceptedStepPortReading_in.xml with Method="BDF" (<Integrator Method="BDF" NumCores="1">, StepControl Step="0.1") and in tests/integrator/methods/ODE_test.cpp, next to AcceptedStepPortReading.PortReadInAcceptedStep_HoldsTheAcceptedState:
Red without the fix (lag 0.000179), green with it. The ERK copy of the input is green either way. Add the golden with run_golden.py --update --case ImplicitIntegration/ImplicitIntegration_BDF_AcceptedStepPortReading.
The extra call is one more right-hand-side evaluation per accepted step: about 1/7 more for a six-stage ERK method, and the benchmark numbers above for BDF. A SimObject with state in OdeFcn (counter, latch, random draw) can see its results change, as with the Engine (FHSIM-0066).