FhSim  3.1.0
Marine systems simulation
Loading...
Searching...
No Matches
0049 — The SUNDIALS summary says Jacobian policy hybrid (resolved: hybrid) when no SimObject has a Jacobian and SUNDIALS difference quotients run
ID 0049
Class BUG
Severity 1
Status ready

Models: —

Found: 2026-10-15, E8 phase 0 (solver plan table test) against d715eace

Decision needed: —

Evidence

src/engine/integrator/sundials/FhIntegratorSundials.cpp:300-311 resolves the policy for the summary only when it is Auto; for any other policy it prints the policy itself:

if (m_jacobianPolicy == JacobianPolicy::Auto) {
...
} else {
jacResolved = jacPolicyStr;
}

The builder decides differently. src/engine/integrator/sundials/SundialsSolverBuilder.cpp:320-325 (ShouldUseJacobianFn, policy Hybrid) wires the Jacobian callback only when HasHybridJacobians() is true and otherwise returns false without a message, so SUNDIALS runs its own difference quotients. The summary still reads:

Jacobian policy : hybrid (resolved: hybrid)

Confirmed by SolverPlanSummary.DISABLED_HybridPolicyWithoutAnySimObjectJacobian_NamesTheNumericSourceThatRuns (tests/integrator/SolverPlanTable_test.cpp; red when run with --gtest_also_run_disabled_tests: the model's OdeJacobian is never called, the line reads hybrid (resolved: hybrid)). The table row Bdf_PolicyHybrid_NoneDense pins today's text.

Effect

<Jacobian Policy="hybrid"> on a model where no stateful SimObject supplies a Jacobian logs a hybrid Jacobian while SUNDIALS uses finite differences of the whole model. A user who checks the log to see why Newton setups are slow is told the assembled Jacobian is used. Same kind of drift as FHSIM-0029 (the log re-derives what the builder chose). No numerical effect.

Possible fix

Let the summary report what the builder decided (plan E8, phase 1: one solver plan decides the Jacobian source and the log text reads it). The line then reads hybrid (resolved: numeric (SUNDIALS built-in)). Optionally also log a warning at the silent fallback in ShouldUseJacobianFn. Log text only. It changes the table row Bdf_PolicyHybrid_NoneDense, so it is its own behaviour commit, not part of the bit-for-bit refactor.

Test that would prove it

Enable SolverPlanSummary.DISABLED_HybridPolicyWithoutAnySimObjectJacobian_NamesTheNumericSourceThatRuns and update the row Bdf_PolicyHybrid_NoneDense in the same commit.

Risk

Low: log text only. A script that matches resolved: hybrid would see the new text for this case.