FhSim  3.1.0
Marine systems simulation
Loading...
Searching...
No Matches
0056 — JAC_COMPRESS_THRESHOLD zeroes small entries in the dense pass only
ID 0056
Class BUG
Severity 1
Status blocked

Models: —

Found: 2026-10-20 F3 review of the fill paths (a406e955), re-located at df9569e8

Source plan: plans/arch-2026-10-20/f3-jacobian-assembler-split.md, finding 2 (workspace fhsim_workspace)

Decision needed: owner to rule (F3-Q2: file and leave). Unifying the paths moves results, so it is not part of the F3 refactor.

Evidence

static constexpr double JAC_COMPRESS_THRESHOLD = 1e-15; (src/engine/model/JacobianAssembler.cpp:241) is applied in three places, all in the dense OdeJacobian pass:

  • the composed and self-coupling blocks, applyComposedLink: if (std::abs(Jblock(i, j)) < JAC_COMPRESS_THRESHOLD) { Jblock(i, j) = 0.0; } (:412);
  • the direct link body (:495, same test);
  • the differenced columns, fillEntry: if (std::abs(val) >= JAC_COMPRESS_THRESHOLD && jacobian[row * nStates + j] == 0.0) (:558).

AssembleSparseJacobianValues (CSR) and AssembleBlockTridiagonalBlocks add the same link blocks (PortCouplingEvaluator) and the same differences without the test.

Effect

An entry below 1e-15 is 0 in the dense Jacobian and kept in the CSR values and in the block-tridiagonal blocks. The size is far below what a Newton iteration resolves, so no result is known to move; the paths do not return the same matrix, and a test that compares them bit for bit sees it. In the fixture a direct link of 1e-16 and a composed link of 2e-16 are 0 in the dense matrix and 1e-16 and 2e-16 elsewhere; a differenced slope of 1e-16 is dropped by the dense pass.

Possible fix

Owner to rule (F3-Q2: file and leave). Options: apply the threshold in every pass (one shared function after F3 task 3); or drop it from the dense pass.

Test that would prove it

JacobianFillPathDifferences.TinyLinkBlocks_DenseZeroesThemAndTheOtherPassesKeepThem and JacobianFillPathDifferences.TinyDifferencedEntry_DenseDropsItAndCsrKeepsIt pin today's values (green). JacobianFillPathDifferences.DISABLED_TinyLinkBlocks_PathsAgree asserts the paths agree and is red. All in tests/model/JacobianFillPathDifferences_test.cpp. tests/model/JacobianFillPaths_test.cpp records the same split on the larger reference model.

Risk

Low: entries of 1e-15 and below. Golden CSVs move only if a model has such an entry in a link block and a path other than dense reads it.