FhSim  3.1.0
Marine systems simulation
Loading...
Searching...
No Matches
0014 — `Cable/RigidBarCable` binds both `ForceB<i>a` and `ForceB<i>b` to the same slot, and reads neither
ID 0014
Class BUG
Severity 3
Status blocked
Models Cable/RigidBarCable
Found 2026-09-15 audit (e3f3107)
Decision needed "implement" the end-B force input (then the sign convention and the b slot need specifying) or "remove the ports".

Evidence

src/cable/RigidBarCable.cpp:122-127

for (int i = 0; i < m_NofBarElements; i++) {
std::snprintf(str, sizeof(str), "ForceB%da", (i + 1));
creator->AddInport(str, 3, &m_forceBa[3 * i]);
std::snprintf(str, sizeof(str), "ForceB%db", (i + 1));
creator->AddInport(str, 3, &m_forceBa[3 * i]);
}

Both calls pass &m_forceBa[3 * i]. The second should plainly be m_forceBb: the two members exist side by side and are documented as the two ends, src/cable/RigidBarCable.h:161-162:

ISignalPort **m_forceBa;
ISignalPort **m_forceBb;

Both are allocated (src/cable/RigidBarCable.cpp:95-96) and both are freed (:151-152), and a grep for m_forceBa/m_forceBb across the class finds those six lines and nothing else — neither array is ever dereferenced to read a port value. The stride is also suspect: the arrays hold 3 * m_NofBarElements pointers and are indexed 3 * i, where i would be the natural index for one pointer per element.

Effect

Two things, and the second subsumes the first:

  • The b-end ports overwrite the a-end pointers in the same slots, so whichever of the pair the engine wires last is the one whose pointer survives.
  • It does not currently matter, because nothing reads these arrays. The class registers 2 * NofBarElements input ports whose values are silently discarded: a model can connect external forces to the bar elements, see the connection accepted at assembly, and get a simulation in which those forces have no effect at all.

The documented purpose (src/cable/RigidBarCable.h:41-42) says these are the forces on the bar ends, so silently ignoring them is a substantive modelling defect, not a cosmetic one.

Possible fix

  • (a) Bind the b ports to m_forceBb, index both arrays by i rather than 3 * i, size them m_NofBarElements, and then feed the port values into the bar-element force assembly in OdeFcn (src/cable/RigidBarCable.cpp:188). This is the full fix and it changes results for any model that connects these ports.
  • (b) Remove the ports and both members. Honest about what the class does, and it makes the omission visible at assembly (a connection to ForceB1a would then fail) instead of silent.
  • (c) Fix only the aliasing at :126 and the stride, leaving the arrays unread. This makes the code look correct without changing anything, which is the worst of the three.

Owner question, open

was external forcing on bar elements ever implemented? If the force-assembly code exists somewhere in history, (a) is a restoration; if it was never written, (b) is the honest state and (a) is a new feature. This must be answered before anything is changed — under (a) the class starts responding to inputs it has always ignored, which changes results for any existing model that connects them.

Test that would prove it

A test over examples/input/RigidBarCable.xml extended with a constant force connected to ForceB1a, asserting the bar element's acceleration differs from the unforced run. It fails today (no difference) and passes under (a). For the aliasing specifically: a test asserting that ForceB1a and ForceB1b resolve to distinct port slots.

Risk

High under (a): it turns on a force path that has never been exercised, so the constraint solver will see loads it has not seen before, and the sign convention for the two bar ends has to be derived rather than copied. Option (b) is low-risk but removes public ports.


Why not solved (fix pass 2026-09-15)

Re-confirmed at HEAD: both ForceBda and ForceBdb bind to &m_forceBa[3*i], and neither m_forceBa nor m_forceBb is read anywhere in RigidBarCable.cpp. Fixing only the alias would be cosmetic, because the values still go nowhere. Wiring the forces into OdeFcn would turn on a load path that has never been exercised and would change results for any input that happens to connect these ports. Removing the ports removes public interface. Only the owner can say whether external forcing of the bar elements was ever meant to exist. Smallest owner decision: "implement" (then the sign convention and the b slot need specifying) or "remove the ports".