FhSim  3.1.0
Marine systems simulation
Loading...
Searching...
No Matches
SIMULATION section

The <SIMULATION> section controls how the simulation is executed: the integration method, timing, tolerances, and state serialisation. It also supports alternative state providers (replay, network).

Note
Looking for a recipe rather than a reference? This page is the full schema for <SIMULATION>. If you are here because a simulation is slow, produces NaN, or needs its Jacobian checked, jump to the diagnostics cookbook at the end of the page.
Legacy compatibility: <INTEGRATION> is accepted as a deprecated alias for <SIMULATION> (same child elements and attributes). If both are present, FhSim reports an error. Rename <INTEGRATION> to <SIMULATION> — the legacy name will be removed in a future release.

Integrator provider (default)

The most common configuration uses the <Integrator> element to run an ODE integration:

<SIMULATION>
<Timing TStart="0.0" TEnd="10.0"/>
<Integrator Method="RK45_i" NumCores="1">
<StepControl AbsTol="1e-6" RelTol="1e-6" StepMax="0.1" StepMin="1e-10"/>
<!-- Implicit methods only: -->
<LinearSolver Type="auto"/>
<Jacobian Type="auto"/>
<!-- Optional diagnostics: -->
<Diagnostics>
<Triggers StepBelow="1e-4"/>
<Settings>
<BlockingState Count="3"/>
</Settings>
</Diagnostics>
<!-- Sundials methods only: -->
<SundialsExtra CVodeSetMaxStep="0.05"/>
</Integrator>
</SIMULATION>

Element Hierarchy

Element Parent Required Description
<Timing> <SIMULATION> Yes Simulation time span. Not enforced by the parser, but an absent <Timing> leaves TEnd at 0.
<Integrator> <SIMULATION> Yes Method selection and integrator settings.
<StepControl> <Integrator> No Step-size bounds, tolerances, order limits.
<LinearSolver> <Integrator> No Linear solver for implicit methods.
<Jacobian> <Integrator> No Jacobian matrix type/assembly strategy.
<Diagnostics> <Integrator> No Unified diagnostics configuration.
<SundialsExtra> <Integrator> No Expert passthrough for Sundials API calls.

<Timing> element

Attribute Default Description
TStart 0.0 Simulation start time (seconds).
TEnd 0.0 Simulation end time (seconds). Omitting it runs a simulation of zero length.
Warning
$Variable substitution does not reach <Timing>. TEnd="$Duration" is not rejected — the literal text is handed to the numeric conversion, which yields 0, and the run ends immediately. The same holds for every <Integrator> child element. See Where substitution applies.

<Integrator> element — attributes

Attribute Applies to Default Description
Method All — (required) Integration method name (see table below).
NumCores Engine "1" Thread count: "1", "perCpuCore", "perSimObject", or a positive integer.
InitialStatesFile All "" Binary file to load initial state (warm-start / chaining).
FinalStatesFile All "" Binary file to save final state (enables run chaining).

MaxOrder is a <StepControl> attribute (see below); on <Integrator> it is rejected.

Note
These four attributes — and only these — accept $Variable references inside <SIMULATION>. No <Integrator> child element does, and neither does <Timing>.

Available integration methods

All methods are selected via Method="<name>".

Note
Method is required and has no fallback: an <Integrator> without it stops the run with *"`<Integrator>` element is missing the required 'Method' attribute."* The recommendation below is a starting point, not a default that applies when the attribute is omitted.

Engine backend (internal library)

Method Type Order Description
RK45_i Explicit 4(5) Runge-Kutta Cash-Karp, adaptive step. Recommended starting choice for a non-stiff system.
DOPRI54_i Explicit 5(4) Dormand-Prince, adaptive step. Higher accuracy.
RKF45_i Explicit 4(5) Runge-Kutta-Fehlberg, adaptive. Classic embedded pair.
BS23_i Explicit 2(3) Bogacki-Shampine, adaptive. Good for mild problems.
Euler_i Explicit 1 Forward Euler, fixed step. Simplest integrator.
Heun_i Explicit 2 Heun's method (improved Euler), adaptive.
BackwardEuler_i Implicit 1 Backward (implicit) Euler, fixed step. L-stable.
StableSolver_i Explicit 1 Multi-stage stability-enhanced explicit scheme, fixed step. Takes no <LinearSolver>.

Sundials backend (SUNDIALS library)

Method Type Infrastructure Description
BDF Implicit CVODE Backward Differentiation Formula (orders 1–5). Best for stiff systems.
Adams Explicit CVODE Adams-Moulton multi-step. Best for non-stiff, smooth solutions.
DIRK Implicit ARKODE Diagonally Implicit Runge-Kutta. Configurable Butcher tables.
ERK Explicit ARKODE Explicit Runge-Kutta from ARKODE. High-order methods.

Choosing a method

Scenario Recommended
General-purpose, non-stiff RK45_i (Engine) or ERK (Sundials)
High accuracy, non-stiff DOPRI54_i or ERK with tight tolerances
Stiff system, production use BDF (Sundials)
Stiff system, moderate stiffness DIRK (Sundials)
Fixed-step, simplest possible Euler_i or BackwardEuler_i
Real-time with strict step budget BackwardEuler_i or StableSolver_i with fixed Step
Large sparse stiff systems BDF + <LinearSolver Type="SPGMR"/> + <Jacobian Type="sparse"/>

<StepControl> element

Controls step-size bounds, error tolerances, and solver order. All attributes are optional.

Attribute Default Description
AbsTol 1e-4 Absolute error tolerance (adaptive methods).
RelTol 1e-4 Relative error tolerance (adaptive methods).
StepMax Engine: 10.0; Sundials: 0 (no limit) Maximum internal step size.
StepMin Engine: 1e-60; Sundials: 0 (no limit) Minimum internal step size.
Step 0 (adaptive) Fixed step size. If > 0, disables adaptive stepping.
Step0 0 (auto) Initial step size suggestion (Sundials only).
MaxSteps 0 (solver default) Max internal steps between output points (Sundials).
MaxOrder 0 (solver default) Maximum BDF/Adams order, 1–5. CVODES only.
Note
The two backends start from different step bounds. The Engine methods always clamp the step, using StepMax = 10.0 and StepMin = 1e-60 when <StepControl> says nothing; the Sundials methods use 0, which means "impose no limit". An Engine run therefore never takes a step longer than 10 s even with no <StepControl> element at all.
AbsTol, RelTol, StepMax, StepMin and Step are applied only when given as a positive value. Writing StepMax="0" does not remove the Engine clamp — the attribute is ignored and the default stands.
MaxOrder reaches CVODES only, so it affects BDF and Adams. DIRK and ERK run on ARKODE, which never sees it; the Engine methods have no order setting. A value outside 1–5 is an error.
When Step > 0 (fixed-step mode), AbsTol, RelTol, StepMax, and StepMin are ignored. Fixed-step mode is mandatory for BackwardEuler_i, Euler_i, and StableSolver_i.

<LinearSolver> element

Configures the linear solver used inside Newton iterations of implicit methods. Ignored for explicit methods.

See also
Linear solver selection — what auto actually picks, when to override it, and the structure each named solver expects. SUNDIALS and linear-solver configuration has the matching Sundials-side reference and worked <Integrator> snippets.

Engine backend

Attribute Default Description
Type "auto" Solver type (see table below).
MaxIter 50 Max iterations (iterative solvers).
Tol 1e-10 Convergence tolerance (iterative solvers).
Restart 50 GMRES restart count.
BandUpper 0 (auto) Upper bandwidth (band type).
BandLower 0 (auto) Lower bandwidth (band type).
BorderMaxSize 64 Max number of dense border (global-coupling) states accepted by the bordered_schur solver (named or auto-selected).
BorderStates (auto) Comma-separated global state indices to force as border states for the bordered_schur solver; empty = auto-detect.

Engine linear solver types:

Type Description
auto Automatic selection based on system structure and size.
dense Direct dense LU. Best for small systems (< 100 states).
sparse Sparse LU with METIS ordering. Best for large sparse systems.
band Banded LU. Best for chain-coupled systems.
block_tridiagonal Thomas algorithm for block-tridiagonal structure.
near_tridiagonal Woodbury extension for near-tridiagonal systems.
bordered_schur Banded interior plus a few dense global-coupling "border" states, solved through a Schur complement. Tuned with BorderMaxSize / BorderStates.
component Direct solve per connected component of the SimObject coupling graph, with structured local solvers.
iterative BiCGSTAB with block-diagonal preconditioner.
iterative_gmres GMRES with block-diagonal preconditioner.

Note: auto picks bordered_schur itself when the Jacobian structure matches; naming it forces that path and fails clearly when the structure does not fit.

Sundials backend

Attribute Default Description
Type "SPGMR" Linear solver: "DENSE", "BAND", or "SPGMR".
Preconditioner "auto" SPGMR only. Model-side preconditioner, using the Engine linear solver names above (auto, component, block_tridiagonal, near_tridiagonal, iterative, iterative_gmres, ...).
NonlinearSolver "newton" Nonlinear solver: "newton" or "fixed_point".
FixedPointAccel 0 fixed_point only. Number of Anderson acceleration vectors (0 = plain fixed-point iteration).
FixedPointDamping 1.0 fixed_point only. Damping factor in (0, 1]; 1.0 disables damping.
BandUpper 0 (auto) Upper bandwidth (BAND type).
BandLower 0 (auto) Lower bandwidth (BAND type).

SUNDIALS and linear-solver configuration lists which <Jacobian Type> / <LinearSolver Type> pairs are valid and which are rejected at startup.


<Jacobian> element

Attribute Applies to Default Description
Type Sundials "auto" Jacobian matrix storage: "auto" (dense), "dense", "sparse", "band", "none". Engine methods derive storage from the linear solver.
Policy Sundials "auto" How Jacobians are computed: "auto", "analytical", "hybrid", "numeric". See Implicit Integration with Analytical Jacobians.
SparsityImageSize All 2000 Pixel-size cap for the sparsity image. A system with more states than this is written at one pixel per block of states rather than one per state.
Warning
SparsityImageSize is not the switch that turns the image on. The image is written by the <JacobianSparsityDump> diagnostic; this attribute only bounds its size. Setting SparsityImageSize="512" without a <Diagnostics><Settings><JacobianSparsityDump/> writes nothing. ="0" is ignored — only a value greater than zero is applied — so the way to suppress the image is <JacobianSparsityDump SparsityImageSize="0"/>, which does accept zero.
Note
Type="none" disables Jacobian assembly — the solver uses a matrix-free approach. Only valid with <LinearSolver Type="SPGMR"/>.

See Implicit Integration with Analytical Jacobians for details on analytical Jacobian implementation, SUNDIALS and linear-solver configuration for the storage formats and the valid Type/LinearSolver combinations, and Jacobian diagnostics and troubleshooting for checking a Jacobian that looks wrong.


<Diagnostics> element

Unified diagnostics for Engine and Sundials methods. Diagnostics are disabled by default; the element must be present to activate them.

See also
Jacobian diagnostics and troubleshooting — what <JacobianVerify> and <JacobianSparsityDump> print, the files they write, and how to read the result.

Top-level attributes

Attribute Default Description
Enabled True Set to False to parse but suppress all diagnostics output.
JsonOutput diagnostics.json Path for structured JSON output written incrementally during the run. Pass JsonOutput="" to disable JSON output.
Warning
Performance impact: enabling <Diagnostics> adds overhead at every accepted step. BlockingState, LogStates, and JacobianVerify each perform additional computation and/or I/O. For production or benchmarking runs, remove the <Diagnostics> element entirely.

The performance cost scales with:

  • Step frequency — high-frequency triggers (EveryNSteps="1", StepBelow that fires often) incur proportionally more overhead.
  • **JacobianVerify** — performs a full finite-difference Jacobian evaluation on each trigger, making it expensive for large models. It already fires only once by default; do not widen that with <Triggers EveryNSteps> unless you mean to.
  • **LogStates** — buffers all state values in memory; memory use grows proportionally to the number of accepted steps.
  • JSON streamingJsonOutput writes to disk at every accepted step; disable with JsonOutput="" if I/O is a bottleneck.

What a bare <Diagnostics/> does

An absent <Diagnostics> element disables all six diagnostics. A present one enables all six — each <Settings> child is an opportunity to configure or switch off a diagnostic that is already on, not a switch that turns one on. <Diagnostics Enabled="False"/> is parsed and then suppressed wholesale.

Per-diagnostic trigger defaults

There is no single "off" default. Each diagnostic has its own gates, chosen so that a bare <Diagnostics/> is useful without tuning:

Diagnostic Default gates Default settings
<BlockingState> StepBelow = 10 × <StepControl StepMin>, MinInterval = (TEndTStart) / 100 Count="3"
<JacobianVerify> Once = true TopSimObjects="5", TopPorts="5"
<JacobianSparsityDump> Once = true (fires at initialisation) Mode="block", SparsityImageSize="2000"
<LogStates> EveryNSteps = 100
<SundialsStepInfo> MinInterval = (TEndTStart) / 100 — (no-op for Engine methods)
<StatePrintOnNanInf> fires on NaN/Inf, once
Note
The BlockingState threshold is derived from the effective StepMin. An Engine run that leaves <StepControl StepMin> unset gets 10 × 1e-60, which no real step ever falls below, so the diagnostic stays quiet. Set <StepControl StepMin> to a realistic floor, or give <Triggers StepBelow> an explicit value.

<Triggers> sub-element

<Triggers> does not switch diagnostics on — it overrides the defaults in the table above. An attribute you omit leaves each diagnostic's own default in place; an attribute you give replaces it for every diagnostic that reads it.

Attribute Overrides the default for Description
StepBelow BlockingState only Emit when the step size falls below this threshold.
MinInterval all but StatePrintOnNanInf Minimum sim-time interval between emissions.
EveryNSteps all but StatePrintOnNanInf Emit every N accepted steps.
Once all but StatePrintOnNanInf Emit only once, then disable.
Warning
<StatePrintOnNanInf> ignores <Triggers> entirely. It always fires on the first NaN/Inf and only then, whatever the element says. <Triggers StepBelow> likewise reaches BlockingState alone — it does not gate JacobianVerify, LogStates or the rest. A negative or unparsable value is rejected with a warning and the default is kept.

<Settings> sub-element

Every child takes Enabled plus the three sink attributes described below, in addition to its own settings:

Element Own attributes Description
<BlockingState/> Count Print top-N states contributing to step rejection.
<LogStates/> Record accepted states in internal buffers.
<JacobianVerify/> TopSimObjects, TopPorts Compare analytical Jacobian against numerical.
<JacobianSparsityDump/> Mode (off/block/full), SparsityImageSize Write Jacobian sparsity diagnostics and a PNG image.
<SundialsStepInfo/> Print per-step Sundials diagnostics.
<StatePrintOnNanInf/> Print state values when NaN/Inf is detected.
Common attribute Default Description
Enabled true false switches this one diagnostic off while leaving the others on.
Console true Mirror this diagnostic to stdout (ANSI-coloured on a terminal).
Log true Mirror it to the main simulation log file.
Sidecar true Write it to a separate plain-text file — see below.

<JacobianSparsityDump Mode="off"/> writes nothing at all, and <JacobianSparsityDump SparsityImageSize="0"/> keeps the textual dump but suppresses the PNG. A SparsityImageSize given here takes precedence over the one on <Jacobian>.

Diagnostics output routing

Each diagnostic writes to three independent channels, all on by default. This is where the diag_*.log files that appear next to a run come from.

Sidecar value Effect
on / true / 1 (default) Append to the auto-named file diag_<Name>.log.
off / false / 0 Write no sidecar file.
anything else Treated as a filename and used verbatim.

The auto-named files are diag_BlockingState.log, diag_JacobianVerify.log, diag_JacobianSparsityDump.log, diag_LogStates.log, diag_SundialsStepInfo.log and diag_StatePrintOnNanInf.log, resolved like any other relative path (see Path resolution).

Warning
Sidecar files are opened in append mode and are never truncated, so repeated runs in the same directory keep growing the same files. Set Sidecar="off" on the diagnostics you do not need to keep, or clear the files between runs.
<Settings>
<!-- Console only; no log-file copy, no sidecar file. -->
<BlockingState Count="5" Log="false" Sidecar="off"/>
<!-- Sidecar only, under a name of your choosing. -->
<JacobianVerify Console="false" Log="false" Sidecar="jacobian_check.log"/>
<!-- On, but not wanted in this run. -->
<LogStates Enabled="false"/>
</Settings>

Full <Integrator> example with all diagnostics

The following example shows an <Integrator> element with every child element present and every <Diagnostics> sub-element configured. In practice you would only include the sub-elements you actually need.

<SIMULATION>
<Timing TStart="0.0" TEnd="60.0"/>
<Integrator Method="BDF" NumCores="1"
InitialStatesFile=""
FinalStatesFile="final_states.bin">
<StepControl AbsTol="1e-6" RelTol="1e-6"
StepMax="0.1" StepMin="1e-10"
Step0="0.001" MaxSteps="10000" MaxOrder="5"/>
<LinearSolver Type="SPGMR"
NonlinearSolver="newton"/>
<Jacobian Type="sparse" SparsityImageSize="512"/>
<Diagnostics Enabled="True" JsonOutput="diagnostics.json">
<!-- All trigger conditions are AND-composed.
A diagnostic fires only when every active gate passes. -->
<Triggers
EveryNSteps="10000"
MinInterval="1.0"
StepBelow="1e-6"
Once="false"/>
<Settings>
<!-- Report the top-N states contributing to step rejection. -->
<BlockingState Count="5"/>
<!-- Record accepted states for the JSON viewer. -->
<LogStates Enabled="true"/>
<!-- Compare analytical Jacobian against finite-difference
(expensive — use Once="true" to limit to one check). -->
<JacobianVerify TopSimObjects="5" TopPorts="5"/>
<!-- Write Jacobian sparsity pattern files. -->
<JacobianSparsityDump Mode="full"/>
<!-- Print per-step Sundials solver info (Sundials methods only). -->
<SundialsStepInfo/>
<!-- Print state values when NaN/Inf is detected. -->
<StatePrintOnNanInf/>
</Settings>
</Diagnostics>
<!-- Sundials-only expert passthrough. -->
<SundialsExtra CVodeSetMaxStep="0.1"/>
</Integrator>
</SIMULATION>
Note
EveryNSteps belongs on the <Triggers> element, not on <Diagnostics> itself. An attribute placed directly on <Diagnostics> is silently ignored and the diagnostics fall back to their defaults.

Diagnostics HTML viewer

The JSON output written by JsonOutput can be visualised in the browser using diagnostics.html, which is installed next to the executable — so in the directory the simulation writes the JSON file into. That is playpen/bin/diagnostics.html in the playpen layout, or share/fhsim/diagnostics.html in a plain install.

Usage:

  1. Run a simulation with JsonOutput set:
    <Diagnostics JsonOutput="diag.json"/>
  2. Open diagnostics.html in a web browser.
  3. Load the generated diag.json file via the file picker in the viewer.

Alternatively, fhsim_plot diag.json writes a copy of the viewer with the snapshot stream baked in and opens it for you.

The viewer renders time-series plots of step size, per-state error estimates, and any other structured data recorded in the JSON snapshot stream.

Note
The viewer loads Plotly from https://cdn.plot.ly. On a machine without internet access, put plotly-2.35.2.min.js next to it and that copy is used instead.

<SundialsExtra> element (Sundials only)

Expert passthrough for SUNDIALS optional-input API calls not covered by the structured schema.

Attribute Example Description
ARKodeSetTableNum "SDIRK_2_1_2" Select a specific DIRK Butcher table.
ARKodeSetFixedStep "0.005" Force fixed-step in ARKODE.
CVodeSetMaxStep "0.1" Override maximum step size in CVODE.
ERKStepSetTableNum "HEUN_EULER_2_1_2" Select explicit RK table for ERK.

See the SUNDIALS documentation for the full list of available API function names.

Note
The former pseudo-keys linear_solver and jacobian_policy are no longer accepted here. Use <LinearSolver Preconditioner="..."/> and <Jacobian Policy="..."/> instead; the parser reports an error naming the replacement.

State serialisation (run chaining)

To chain multiple simulation runs — save the end state of one run and resume from it in the next — use FinalStatesFile and InitialStatesFile:

Run 1 — save final state:

<Integrator Method="RK45_i" FinalStatesFile="run1_end.bin">
<StepControl AbsTol="1e-6" RelTol="1e-6" StepMax="0.05"/>
</Integrator>

Run 2 — resume from saved state:

<Integrator Method="RK45_i" InitialStatesFile="run1_end.bin">
<StepControl AbsTol="1e-6" RelTol="1e-6" StepMax="0.05"/>
</Integrator>
Note
The binary state file format is (1 + N) × 8 bytes: the first double is the simulation time; the following N doubles are the ODE state vector. The Engine backend also writes FinalStatesFile on SIGINT/SIGTERM (Ctrl-C), making it safe for long-running interruptible runs.
InitialStatesFile also sets the simulation start time from the time stored in the file, overriding <Timing TStart>. A file whose size does not match (1 + N) × 8 for the current model stops the run with an error reporting both sizes.

Redirecting state files with BROOM_INPUT_DIR

Both state-file paths honour the environment variable BROOM_INPUT_DIR, which lets a batch harness keep its chaining files outside the working directory without editing the XML. When the variable is set and non-empty:

  • InitialStatesFile is used as written if that path already exists; otherwise $BROOM_INPUT_DIR is prepended to it.
  • FinalStatesFile always has $BROOM_INPUT_DIR prepended, whether or not the bare path exists.

When the variable is unset or empty both paths are used as written, resolved against the working directory like any other relative path — see Path resolution. This applies to these two attributes only; no other path in the input file consults the variable.


Alternative providers

Instead of an <Integrator>, the <SIMULATION> section can host a <Replay> or <Network> provider. Use exactly one provider child.

<Replay> — replay a recorded CSV file

<SIMULATION>
<Replay csvFile="recorded_output.csv"/>
</SIMULATION>

Replays a previously recorded CSV file step by step. Useful for offline analysis and visualisation of past simulation results.

<Network> — receive state from the network

<SIMULATION>
<Network endpoint="tcp://192.168.1.10:5555" timeout="5000"/>
</SIMULATION>

Receives simulation state over ZeroMQ from a remote publisher. The timeout attribute (ms) controls how long to wait for data before raising an error.

Real-time pacing

The <SIMULATION> element supports a simulationSpeed attribute to enable real-time pacing:

<SIMULATION simulationSpeed="1.0">
<Timing TStart="0" TEnd="100"/>
<Integrator Method="RK45_i">
<StepControl AbsTol="1e-4" RelTol="1e-4"/>
</Integrator>
</SIMULATION>
Value Meaning
0 (default) Run as fast as possible.
1.0 Real-time.
2.0 Twice real-time speed.
0.5 Half real-time speed.

simulationSpeed is read from the <SIMULATION> element itself, not from <Integrator>, and it is the only way to pace a headless FhSim run: -s / --simulation-speed is compiled into the visualisation executable FhVis alone, and FhSim rejects it as an unknown option. FhSimUI spells the same control --rtf / --rt. Where a command-line pacing flag does exist, it overrides this attribute. See Real-time pacing for the flag tables.


Diagnostics cookbook

The <Diagnostics> element is most useful when a simulation behaves unexpectedly. Use the recipes below to identify the cause.

"I want to visualise step-size and state history in the browser"

Enable JSON output and open the diagnostics viewer:

<Diagnostics JsonOutput="diag.json">
<Settings>
<LogStates Enabled="true"/>
</Settings>
</Diagnostics>

Then open playpen/bin/diagnostics.html and load diag.json, or run fhsim_plot diag.json.

"Simulation is very slow / step size collapses"

Identify which states force small steps:

<Diagnostics>
<Triggers StepBelow="1e-6"/>
<Settings>
<BlockingState Count="5"/>
</Settings>
</Diagnostics>

Look at the reported states — they typically point to stiff couplings that need tighter modelling or an implicit method.

"Simulation produces NaN / Inf"

Print state values at the moment the error occurs:

<Diagnostics>
<Settings>
<StatePrintOnNanInf/>
</Settings>
</Diagnostics>

"I want to verify my analytical Jacobian"

Compare analytical entries against finite-difference estimates:

<Diagnostics>
<Triggers Once="true"/>
<Settings>
<JacobianVerify TopSimObjects="3" TopPorts="5"/>
</Settings>
</Diagnostics>

Run a short simulation and inspect the log output for discrepancies.

"I want to visualise coupling structure"

Dump the Jacobian sparsity pattern to an image file:

<Jacobian Type="sparse"/>
<Diagnostics>
<Settings>
<JacobianSparsityDump Mode="full" SparsityImageSize="512"/>
</Settings>
</Diagnostics>

This writes jacobian_sparsity.png into the working directory, showing which states are coupled. <JacobianSparsityDump> already fires once, at initialisation, so no <Triggers> element is needed. SparsityImageSize caps the image at 512 pixels per side; a larger system is drawn one pixel per block of states.

"I need periodic progress info from Sundials"

<Diagnostics>
<Triggers EveryNSteps="1000"/>
<Settings>
<SundialsStepInfo/>
<LogStates Enabled="true"/>
</Settings>
</Diagnostics>

See also