|
FhSim
3.1.0
Marine systems simulation
|
| ID | 0036 |
| Class | BUG |
| Severity | 2 |
| Status | blocked |
| Models | Cable/Branched, Cable/LumpedMass |
| Found | 2026-09-24, rolling out the trajectory-sampling Jacobian checker (fhsim jacobian-checker-coverage) |
| Decision needed | Should the analytical Jacobian reproduce the clamp (a numeric change to every cable Jacobian that reaches it), or is the clamped region outside the Jacobian's scope, so that only the test fixture changes? |
OdeFcn clamps the element compression speed at ±100 m/s before it enters the damping force:
Both analytical cable Jacobians compute the compression speed c without the clamp and differentiate d_eff * c unconditionally: InternalCable::ComputeStructuralJacobian (src/cable/subroutines/InternalCable.cpp:307-322,344, used by Cable/LumpedMass and Cable/Branched) and InternalCable::AddEndpointJacobianContributions (:442-456,467, used by Cable/Branched). While the clamp is active, OdeFcn's damping force is constant in the velocities, the Jacobian still carries d_eff * e e^T in every velocity column, and its totalForce (used for the 0 < F < maxT test and the (I - e e^T) F / L position term) is built from the unclamped c.
Observed in SimObject.CableBranched_Jacobian (tests/in/CableBranched/), whose fixture stretches every section to roughly ten times its relaxed length of 0.5 m. At the three states the scenario's own integrator reaches (t = 0.0047, 0.0083, 0.0110) the system and CB checks fail with up to 40 mismatches, maxAbsErr 6493 and maxRelErr 1.67; e.g. at the first sample (3,3) analytical=-57.798 numerical=-1, (3,4) analytical=10.09 numerical=0: the numerical velocity derivative of junction node 5 is exactly the NumericalDamping="1" term and nothing else. A temporary print in CableElDynStiff::AddStructuralForces (not committed) showed ma_dCompressionSpeed = -100 in every finite-difference evaluation at these states, with the same damping force in all of them.
The same states pass in the checker's shifted-offset copy only because that copy is freshly built and its elements still have the default relaxed length, so the cable is slack there; see MARE-0037.
Cable/LumpedMass has the same omission in ComputeStructuralJacobian by code reading; SimObject.Cable_Jacobian passes because its fixture never reaches 100 m/s.
Wherever a cable element's compression speed exceeds 100 m/s, the analytical Jacobian disagrees with OdeFcn in every row and column of the element's end nodes. An implicit integrator that uses it gets a wrong Newton matrix there; whether that moves results depends on the integrator and was not examined.
|c| >= 100, use the clamped c in dampForce and drop the damping terms (d_eff * e e^T and the relVelPerp part of the position term). This changes the Jacobian numerics wherever the clamp is active, and nowhere else.SimObject.CableBranched_Jacobian with trajectorySamples back at the checker default of 3 (tests/CableBranched_Jacobian_Test.cpp sets it to 0 because of this issue).
The first fix moves Jacobian numerics for any model whose cable reaches the clamp; stored references change only if an implicit integrator in a reference scenario reaches it.
Re-confirmed at 8a1772d by code reading: CableElBasics.cpp:302 clamps the compression speed at +-100 m/s, and InternalCable.cpp differentiates the unclamped damping term. Unchanged reason: reproducing the clamp changes Jacobian numerics wherever it is active, and whether the clamped region is in the Jacobian's scope is the model owner's call.