FhSim  3.1.0
Marine systems simulation
Loading...
Searching...
No Matches
0037 — Until an output port runs CalcOutput, a CableBranched element keeps its default relaxed length, so the fixture's IC and shifted-offset Jacobian checks see a slack cable
ID 0037
Class TEST
Severity 2
Status blocked
Models Cable/Branched
Found 2026-09-24, rolling out the trajectory-sampling Jacobian checker (fhsim jacobian-checker-coverage)
Decision needed Is it intended that the Length<n> inputs take effect only once an output port has been read? If not, it is a model bug (OdeFcn should apply them); if so, the Jacobian fixture has to read a port before it is checked.

Evidence

The only call that applies the Length<n> input to the cable elements is m_cableSections[element]->UpdateCable(m_lengths[element], dT) in CableBranched::CalcOutput (src/cable/CableBranched.cpp:533). CalcOutput is the common computation behind the ExternalForce and ExternalTension output ports (:446, :453); CableBranched::OdeFcn and CableBranched::OdeJacobian do not call it. (Cable/LumpedMass differs: its OdeJacobian calls m_commonCalc->ComputeFunction, src/cable/Cable.cpp:79.)

A temporary print in CableElDynStiff::AddStructuralForces (not committed) during SimObject.CableBranched_Jacobian showed relaxed length L0 = 1000 in every evaluation of the freshly built models the checker uses for the IC, the random perturbations and the shifted-offset copy, and L0 = 0.5 (the fixture's CB.Length<n>="0.5") only in the model the checker integrates for its trajectory samples. At one and the same trajectory state the element saw L0 = 0.5 in the integrated model and L0 = 1000 in the shifted copy.

With L0 = 1000 and section lengths of 3 to 5.4 m every element is slack, so the force is clamped to zero and those checks compare only the position-velocity coupling and the numerical damping (worst error 3.6e-9).

Effect

SimObject.CableBranched_Jacobian passes at the IC and at the shifted offset without comparing any spring or damping term; only the trajectory samples, which the model's MARE-0036 limitation makes fail, see the taut cable.

Possible fix

  • If the lazy update is a bug: apply the lengths in OdeFcn (or call the common computation from it and from OdeJacobian, as Cable/LumpedMass does). This changes results for any scenario whose first evaluations happen before a port is read.
  • If it is intended: give the fixture an observer or a connection that reads ExternalForce before the checks, or check at trajectory states only.

Test that would prove it

SimObject.CableBranched_Jacobian reporting a nonzero spring block at the IC, e.g. an entry of order EA / L0 in a velocity row.

Risk

The model fix changes results of any scenario that relies on the default length until the first port read; the fixture fix changes only what the test covers.


Re-triage (fix pass 2026-09-24)

Re-confirmed at 8a1772d: CableBranched::CalcOutput (CableBranched.cpp:533) is still the only caller of UpdateCable. Unchanged reason: whether the lazy length update is intended decides between a model change (results move) and a fixture change; that is for the model owner.