|
FhSim
3.1.0
Marine systems simulation
|
This page is a decision-oriented guide to making simulations run faster. It does not repeat the full option reference — for exact attributes and defaults see SIMULATION section, and for analytical Jacobians see Implicit Integration with Analytical Jacobians.
Before tuning, first confirm where the time goes. Enable diagnostics (see Diagnostics cookbook) to see whether the step size is collapsing, whether the Jacobian is being rebuilt often, or whether a particular state is forcing small steps.
RK45_i) with sensible tolerances is usually fastest.BDF, DIRK) avoids the tiny steps explicit methods need.For the full method list (canonical names, order, explicit/implicit, Engine vs Sundials backend) and a "which method when" table, see the method reference in SIMULATION section.
Set tolerances no tighter than your accuracy requirement: over-tight AbsTol/RelTol in <StepControl> forces small steps and more work.
The linear-solver choice dominates cost for large implicit systems. There are two disjoint vocabularies, and which one applies depends on the integrator backend:
BDF, DIRK) — <LinearSolver Type="..."> takes only SPGMR, DENSE or BAND. The structured, model-side solvers below are then selected with <LinearSolver Preconditioner="...">, which is accepted for Type="SPGMR" only; a direct DENSE/BAND solver takes no preconditioner._i family, e.g. BackwardEuler_i) — <LinearSolver Type="..."> takes the structured names below directly.So the rules of thumb in this table name the value of Preconditioner for a Sundials run and of Type for an Engine run (full reference in SIMULATION section):
| System | Suggested structured solver |
|---|---|
| Small (< ~100 states) | dense |
| Large and sparse | sparse (METIS-ordered) |
| Chain-coupled (cables, moorings) | band, block_tridiagonal, or near_tridiagonal |
| Many weakly-coupled blocks | component |
| Very large, iterative convergence acceptable | iterative / iterative_gmres |
| Not sure | auto (lets FhSim decide from structure and size) |
A typical stiff, large, sparse configuration therefore reads:
RK45_i and friends) a <LinearSolver> element is irrelevant and is ignored with a warning.For large models, a sparse Jacobian avoids dense factorisation cost. Set <Jacobian Type="sparse"/>; to also visualise the coupling, add SparsityImageSize to the same element — <Jacobian Type="sparse" SparsityImageSize="512"/> — and check the structure is as expected (a dense-looking pattern means little is gained from a sparse solver). Only the first <Jacobian> element is read, so keep it to one.
Providing an analytical Jacobian (rather than the numerical default) is often the single biggest win for stiff systems — see Implicit Integration with Analytical Jacobians.
<Integrator NumCores="..."> parallelises SimObject evaluation:
| Value | Meaning |
|---|---|
1 | Single-threaded (default). |
perCpuCore | One thread per CPU core. |
perSimObject | One thread per state-carrying SimObject. |
| N | Exact thread count. |
Parallelism helps when there are many independent SimObjects; for a few tightly coupled objects the threading overhead can outweigh the benefit. Measure both.
Thread-safety note. With
NumCores > 1, SimObjectOdeFcn/port evaluations run concurrently. Shared computations must be registered as a common computation so the engine serialises and caches them (it wraps them in a mutex); do not share mutable state between SimObjects through other means.
Writing state/observer output every step is costly. Increase the output interval (dt / TOutput) and limit observers to what you actually need (see OBSERVERS section).
FhSim 3 has no built-in CPU profiler. Use an external profiler (perf, VTune, Instruments) for hot-spot analysis, and the diagnostics JSON/HTML viewer (Diagnostics cookbook) to understand solver behaviour over time.
<Integrator>, <LinearSolver>, <Jacobian> reference.