|
FhSim
3.1.0
Marine systems simulation
|
Status of every baseline below: reviewed and approved by the owner, 2026-09-25, except NetStructure_Regression and SimObject.Disk, which were regenerated on 2026-09-27 on branch review/A12-baselines after the net-hydrodynamics programme and approved by the owner on 2026-09-28 (MARE-0099, resolved; old against new in Regression baselines: review of the 2026-09-27 regeneration (MARE-0099, WP-A12)). Each one freezes what the code at the time produced, and the owner has confirmed the plots are correct. Cable_Regression and NetStructure_Regression were regenerated once more for 3.0.1 (2026-10-11, owner decision), with new inputs only, so that one baseline holds for every compiler; see Conditioning. NetStructure_Regression was regenerated again on 2026-10-13 for the owner's MARE-0110 ruling (the default law's lift from the MF2022 Eq. 10 lift-to-drag ratio, fhsim_environment 3.1.1); that change alone moves it (see its page). NetStructure_Regression and the NetStructureWithConstraints baselines (_Regression, _RegressionAppendices, _RegressionThreads) were regenerated on 2026-10-20 for the owner's revised R1 (MARE-0131, fhsim_environment 3.2.11): the LocalThroughFlow lift default b4 is 0.036 (was 0.10); the drag is unchanged. Only the accelerations of nodes of inclined panels move: NetStructure_Regression by at most 0.027 m in position (0.003 m in x) and 0.0026 m/s in velocity over 15 s, the three constrained nets in their free nodes and rigid elements (the driven nodes' frozen states do not move). They were regenerated again on 2026-10-21 for the owner's option O1 for the drag (ENV-0120, fhsim_environment 3.2.12): LocalThroughFlow a3 = 0.017 and a5 = 0.053 (were 0.07 and 0; a3 + a5 = 0.07, so the drag at 0 and 45 deg is unchanged, and the lift b4 = 0.036 too). Only the accelerations of nodes of inclined panels move: NetStructure_Regression by at most 0.049 m in position and 0.0026 m/s in velocity over 15 s, the constrained nets by at most 0.030 m (0.019 rad/s in the angular velocities). MARE-0032 is resolved; MARE-0033 stays open, narrowed to Cable/Branched, which has no baseline yet.
Each baseline is a gtest, SimObject.<ID>, that runs tests/in/<dir>/<ID>_in.xml with RunAndCompareRegressionXmlTiming (tests/TestUtils.h) and compares its output with <ID>_ref.csv under the limits in <ID>.ref, as SimObject.Disk does. Each page shows every compared output against time, says what should happen physically and checks the numbers against a hand calculation.
| Object | Issue | Test and page | Fixture | Compared outputs | Hand check |
|---|---|---|---|---|---|
Net/Sphere | MARE-0033 | Sphere_Regression | 1000 kg, 1 m sphere sinking from rest in a 0.5 m/s current, 5 s | Position, Velocity | RK4 of the drag law on the relative velocity, with the added mass 0.5 ρV in the inertia: within 5e-6 m |
Cable/LumpedMass | MARE-0033 | Cable_Regression | 10 m cable, ends 8 m apart, 0.5 m/s cross current, 10 s | Node states, ForceA, ForceB | Sideways drag 76.4 N against 76.9 N; vertical end forces 375.2 N, 0.99 of the 380.4 N wet weight (380.4 N in still water) |
RbCable/CableConnector | MARE-0033 | CableConnector_Regression | 50 kg connector under a decaying and a constant end force, 5 s | Pos, Vel, PosA, PosB | Closed form: within 5e-7 |
TrawlBeam | MARE-0033 | TrawlBeam_Regression | PID from rest to 1.5 m/s against a 2 × 2e4 N pull on a 0.3 rad track, 30 s | States, ShipForce, tow-point positions | Steady ShipForce 38212.7 N against 4e4 cos 0.3 = 38213.5 N |
TrawlCable | MARE-0003 | TrawlCable_HeunRegression (no page) | The TrawlCable smoke fixture under Heun_i at a fixed 1 ms step, one solver thread, 1 s | WinchForce, TopBridleEndForce, BottomBridleEndForce, TrawlDoorPosition | None: it guards the constraint solver's symplectic step under Heun_i (the full step, owner ruling 2026-10-13); made 2026-10-13, regenerated 2026-10-14 for owner rulings C3 Q10/Q1 (SolveCatenary initial layout; last printed digit only), not yet reviewed by the owner |
TrawlCable | plan C3 | TrawlCable_EulerRegression (no page) | TrawlCable_HeunRegression's fixture under Euler_i, 1 s | WinchForce, TopBridleEndForce, BottomBridleEndForce, TrawlDoorPosition | None: it pins the trawl rig wiring and the cable segment setup before task C3 of fhsim_workspace's plan architecture-deepening-2026-10; made 2026-10-14, regenerated the same day for owner rulings C3 Q10/Q1 (SolveCatenary initial layout), not yet reviewed by the owner |
RundDorg | plan C3 | RundDorg_Regression (no page) | The RundDorg smoke fixture (Euler_i, fixed 2 ms step, one solver thread) for the clump's first 2 s | MainForceVector, Line1ForceVector, Line2ForceVector, WeightPosition | None: as TrawlCable_EulerRegression; made 2026-10-14, regenerated the same day for owner rulings C3 Q10/Q1 (SolveCatenary initial layout), not yet reviewed by the owner |
TrawlCable + MooringCable | plan C3 | TrawlCable_JoinedRegression (no page) | A joined rig on one solver: CableS owns it, CableP (its mirror image) and a MooringCable join it; Euler_i, 1 ms, one solver thread, 1 s | Both cables' end forces and door positions, the mooring's ForceA and ForceB | None: it pins the owner/joined rule; made 2026-10-14, regenerated the same day for owner rulings C3 Q10/Q1 (SolveCatenary initial layout), not yet reviewed by the owner |
Net/NetStructure | MARE-0032 (b) | NetStructure_Regression | 1 m² panel, unstretched, in a 0.5 m/s current, pulled 2 N upstream, 15 s | Node positions and velocities | LocalThroughFlow drag at the steady drift 2.048 N against the 2.034 N it balances; without the pull the panel drifts at the current speed |
Net/NetStructureWithConstraints | plan C1 | NetStructureWithConstraints_Regression, NetStructureWithConstraints_RegressionThreads (no page) | Two quadrilaterals in a 0.5 m/s current and one Airy wave, the first's four nodes driven by the two rigid-element chains, the second's outer nodes free; 2 s serial, and 0.2 s on two threads with MassFactor 2 and MaxVelocity 5 | Every state | None: it pins the node-state reads (rigid elements against own states) before task C1 of fhsim_workspace's plan architecture-deepening-2026-10; made 2026-10-14, reviewed and accepted by the owner 2026-10-14 |
TrawlCable | plan D1 | TrawlCable_BedRegression (no page) | TrawlCable_EulerRegression's fixture with the seabed at 63.5 m: the lower bottom bridle rests on it (law L7), the cable starts above the bed; Euler_i, 1 ms, one solver thread, 1 s | WinchForce, TopBridleEndForce, BottomBridleEndForce, TrawlDoorPosition | None: it pins the bridle's seabed contact before the seabed-law refactor; made 2026-10-16, approved by the owner 2026-10-16; regenerated 2026-10-17 for env's soil law family (plan D1 phase 2, task M2, MARE-0392): the elements are rigid cylinders, the run was finite but the bridle forces swung by tens of kN after 1 s under the explicit 1 ms step; regenerated again 2026-10-17 for env's numerical constants (damping floor dampingTime and uplift speed scale upliftDampingLimit, plan D1 phase 2, task S1, MARE-0397): the bottom bridle end force now changes smoothly from 0.2 s to 0.6 s (largest step between 10 ms rows 1.4 kN, before 35 kN); the whole cable starts inside the sediment (the slack warp's catenary hangs up to 23 m below the seabed, the bridles 2 to 6 m), so the run is the expulsion from it and a few disturbances remain after 0.6 s; regenerated 2026-10-18 for the CoRiBo solver damping from env's ContactLoad::torsion (task O2): bottom bridle end force z over 0.5 to 1 s mean 2558 N, sd 587 N, largest step between rows 0.38 kN; regenerated 2026-10-21 for MARE-0405 (owner ruling, ENV-0115): the cable now starts on the bed (WarpLength 110 instead of 150, bridle ends at z = 53.8 and 58.8 instead of 60 and 65), the bottom bridle sags onto it, and there is no expulsion transient: bottom bridle end force z over 0.5 to 1 s mean 4380 N, sd 6 N |
Net/Disk | plan D1 | Disk_SeabedRegression (no page) | A 100 kg disk 2 mm into a seabed at 10 m, sliding at 1 m/s in still water (disk as a rigid cylinder); RK45_i, StepMax 0.01, 4 s | Every state | None: made 2026-10-16, approved by the owner 2026-10-16; regenerated 2026-10-17 for env's soil law family (plan D1 phase 2, task M2, MARE-0393): the start moved from 0.02 m to 2 mm, since the soil carries the disk at its capacity and a deep start is expelled; it now stops after 1.2 m and rests 0.4 mm deep |
Cable/Branched | plan D1 | CableBranched_BedRegression (no page) | CableBranched_Regression's fixture with the seabed at 9.95 m, so the junction nodes rest on it (laws L1, L2); RK45_i, StepMax 0.01, 2 s; no Jacobian check | Every state, the end forces | None: made 2026-10-16, approved by the owner 2026-10-16; regenerated 2026-10-17 for env's soil law family (plan D1 phase 2, task M1) |
Cable/LumpedMass | plan D1 | Cable_BedRegression (no page) | Cable_Regression's cable with the seabed at 5.6 m: it falls, touches down and rests on the soil of fhsim_environment, 0.09 to 0.22 mm deep (cable element law); RK45_i, fixed 1 ms, 10 s; no Jacobian check (drag is not in the analytical Jacobian; in contact it is withdrawn, MARE-0391) | Node states, ForceA, ForceB | None: made 2026-10-16, approved by the owner 2026-10-16; regenerated 2026-10-17 for env's soil law family (plan D1 phase 2, task M1; old seabed forces may change at will, owner ruling 2026-10-17) |
RbCable/Cable | plan D1 | CableRM_SeabedRegression (no page) | A 10 m, 50 mm, 3 kg/m cable between two fixed points 9.97 m apart at z = 9.95 m, 5 cm above a seabed at 10 m, in a 0.5 m/s current across the span (rigid cylinder per element); Euler_i, 1 ms, one solver thread, 5 s; axialBaumgarteRate 1000 (a rate of 1000 1/s, MARE-0395) | Every state, ForceA, ForceB | None: it pins the seabed contact of OdeFcn as it is; made 2026-10-16, variant approved by the owner 2026-10-16; regenerated for the explicit joint moments of RbCable/Cable (MARE-0395, plan D1 phase 2, task M0), updateFreq 1000 to 0.1 (the input is named axialBaumgarteRate since task O2); it is a rate since task A1 (the file did not change: 0.001 was the same rate of 1000 1/s); regenerated 2026-10-17 for env's soil law family (task M2, MARE-0392): the cable starts 0.3 m deep instead of 1.6 m (the soil pushes a buried cable out, env S1), axialBaumgarteRate 1000 [1/s] (the axial Baumgarte rate, task A1), it rests on the soil within 1 s (penetration below 2 mm) and the current moves it 0.41 m; regenerated 2026-10-21 for env's ENV-0124 and the catenary start of MARE-0398 (owner rulings), and checked by statistics since then (MARE-0400, see Tolerance): over 3 to 5 s ForceA x mean 249 N, sd 15 N (before MARE-0398 mean 305 N, sd 391 N), the middle elements rest at z = 9.974 m |
Cable/Branched has no baseline yet: it waits for MARE-0036 and MARE-0037, whose answers change its numbers.
Each fix regenerated the baselines it changed.
Cable/LumpedMass and Cable/Branched (MARE-0082): the end forces carried twice the cable's weight in water, as CableElBasics::CalcMassAndWeight gave each end node of an element the element's whole weight in water. Each node now carries half, as its mass already did.Net/Sphere (MARE-0084) read the current but took its drag on its own velocity. It now uses the velocity relative to the water, as Net/Disk does, and its fixture has a current.Net/NetStructure (MARE-0083): the panel drag scaled the water velocity, not the velocity relative to the net, by the Kristiansen-Faltinsen solidity factor (1.159 here), so a free panel drifted at 1.159 times the current. It now scales the relative velocity, and a free panel drifts at the current speed. Net/NetStructureWakeEffect and Net/NetStructureWithConstraints had the same defect and have the same fix.Sphere_Regression was regenerated once more when Net/Sphere got the added mass of a sphere, 0.5 ρV, in its inertia (MARE-0086, a known limitation, not a hand-check finding). The owner had approved the previous baseline; the change is that fix alone.
The harness (FhSim TestResult::CompareRegression) supports one limit, output_rms_max: the root mean square over time of the difference between run and baseline, absolute, applied to every column of the output file alike. There is no relative limit and no per-column limit, and it compares whole files: the columns are chosen by the fixture's <FileOutput Select=...>, and every column of the file is compared.
Every baseline uses output_rms_max 1e-8, the owner's "slightly looser than Disk's 1e-10". The compared columns are SI values whose peaks are between 0.37 and 7.7e5 (the smallest are the net's y positions and the Cable node velocities), so 1e-8 absolute is at most about 3e-8 of any column's peak. FhSim writes the result file with e, seven significant digits, so a change of one unit in the last printed digit of one row already exceeds 1e-8 in every column above about 0.1: in practice each test passes only while the output is unchanged to printed precision, as Disk's does. A relative 1e-8 would be below that print resolution and could not be checked.
Statistic checks (MARE-0400, owner ruling 2026-10-21). Where a trace compare is too fragile, a test compares the mean and the standard deviation of chosen columns over a late time window with those of the _ref.csv, each within absolute + relative * |reference| (RunAndCompareRegressionStatistics in tests/TestUtils.h; the .ref limit is not used). CableRM_SeabedRegression uses it on every platform (its seabed contact chatters); TrawlCable_EulerRegression, TrawlCable_HeunRegression, TrawlCable_JoinedRegression, TrawlCable_BedRegression, CableBranched_BedRegression and the OneThreadTwin references use it on MSVC only and keep the trace compare on Linux: on MSVC they agree to printed precision until an element switches between slack and taut or touches the bed, then drift (owner ruling 2026-10-22). The MSVC tolerances are kMsvc* in tests/TestUtils.h; the windows and the other tolerances are in the test comments.
A baseline can hold on every compiler only if a change of the inputs in their last bit moves the outputs by far less than 1e-8: other compilers and math libraries round differently, by about that much. In 3.0.0 Cable_Regression and NetStructure_Regression did not: on Linux a one-ulp change of one input position moved the cable's ForceA by 1.6e-3 N and the net's Vel_2_1 by 2e-3 m/s, and MSVC differed from the gcc baselines by up to 1.7e-3, so MSVC skipped the comparison. Two input choices caused it, not the models:
<StepControl Step="0.001"/>).Check (2026-10-11, gcc, Release): each input of each fixture (end and node positions, Density, E, Diameter, DampingRatio, Length, node forces, current) moved by 1 and by 4 ulp moves no column by more than an RMS of 1e-11; the only differences are single flips of the seventh printed digit of values below 1e-4. A relative change of 1e-8 moves them by an RMS of at most 1e-4 (cable ForceA) and 7e-7 (net), so the conditioning is that of the physics (the cable's end force goes with its axial stiffness), not of the integration. The hand checks did not move.
Sphere, CableConnector and TrawlBeam also run the default Jacobian check. Cable/LumpedMass and Net/NetStructure do not, see the comments in their tests.Delete <ID>.ref and <ID>_ref.csv and run the test: the harness writes both again (ReferenceMode::CreateIfMissing), with output_rms_max 1e-10; set it back to 1e-8. Then rerun python3 tests/plot_baselines.py from the repository root, which rewrites the pages here and prints the hand checks.