|
FhSim
3.1.0
Marine systems simulation
|
The <VARIABLES> section defines named variables that can be referenced throughout the input file using $VarName substitution. This is useful for avoiding repetition and making input files easier to maintain.
$Var in an attribute outside that scope is not an error — the literal text $Var is handed to the numeric parser, which reads it as 0. See Where substitution applies before using a variable.Each <Var> element defines a single variable:
| Attribute | Required | Description |
|---|---|---|
Name | Yes | Variable name. May contain letters, digits, and underscores. Case-sensitive. |
Value | Yes | Replacement value. Can be any string — numbers, vectors, or text. |
<Var> or <var>. Any other child of <VARIABLES> is ignored without warning. If the same Name is defined twice, the first definition wins.Reference a variable by prefixing its name with $ in any attribute value inside the scope described below. The substitution happens at parse time, before SimObjects are created.
Substitution is applied attribute-by-attribute in exactly four places, and nowhere else:
| Where | What is substituted |
|---|---|
<OBJECTS> | Every attribute of every child element — including LibName, SimObject and Name, not just the model parameters. |
<INTERCONNECTIONS> | Every attribute of every <Connection> element (both port references and constants). |
<INITIALIZATION> | Every attribute of every <InitialCondition> element. |
<SIMULATION> | The attributes on the <Integrator> element itself — Method, NumCores, InitialStatesFile, FinalStatesFile. |
Everywhere else the $ text survives into the value that the option parser reads. In particular there is no substitution in:
<Timing> — TStart and TEnd.<Integrator> child elements: <StepControl>, <LinearSolver>, <Jacobian>, <Diagnostics> and its <Triggers>/<Settings> subtree, and <SundialsExtra>.<Replay>, <Network>, and the simulationSpeed attribute of <SIMULATION>.<OBSERVERS> section.<FromFile> and its <State> children inside <INITIALIZATION>.atof-style conversion, which yields 0 for text it cannot parse. So <Timing TEnd="$Duration"/> does not fail — it runs a simulation that ends at t = 0. Put the duration in the XML directly, or have the batch script that sets $Duration rewrite TEnd as well.$Mass and $mass are different variables._). The name ends at the first character that is not in this set.Multiple variables in one value: You can use multiple $ references in a single attribute value:
Inline mixing: Variables can appear anywhere in a value:
$Name reference does not match any defined variable, FhSim reports an error and stops.Value itself contains $Other is expanded further. This makes variables composable, but a variable that references itself never terminates — do not write <Var Name="A" Value="$A"/>.After substitution, values in <OBJECTS>, <INTERCONNECTIONS> and <INITIALIZATION> are passed through an arithmetic evaluator. It supports +, -, *, /, ^ and parentheses, so a value can be written as a calculation instead of a pre-computed number:
This applies to the three sections above only. <Integrator> attributes get variable substitution but no arithmetic, and nothing outside the four places listed above gets either.
<INTERCONNECTIONS> and <INITIALIZATION> carry numbers, so their values are evaluated while the input file is read. An <OBJECTS> attribute is different: it is stored exactly as written, and the arithmetic is evaluated when the SimObject asks for the parameter as a number (GetDoubleParam, GetIntParam and their array forms). A parameter the SimObject reads as text (GetStringParam) is handed over verbatim.
This is what lets an attribute carry structured text. A JSON document, a regular expression or a bracketed coordinate list contains punctuation the evaluator would rewrite — [0.0,3,6] would come out as [0.0,3,6 — so a value is only offered to the evaluator once it is known to be a number. Earlier versions evaluated every object attribute as it was read, and structured text had to be moved to a separate file.
The evaluator is deliberately conservative, because a numeric attribute may still carry a matrix, a unit string or an endpoint. The whole value is left untouched when it
;) — the row separator of a matrix parameter, and the marker for a path or unit string.Otherwise the value is split on commas and each field is evaluated on its own. A field is left untouched when it
. and none of * / ^ + -; ore/E (an underscore also counts as a letter here), so Simple/Black and tcp://*:5555 survive; ore/E before its first digit.Every field that passes those tests is evaluated — including one that is already a plain number.
The result is written back as the shortest decimal text that reads back as the same double, so an evaluated field keeps every digit it is worth: Mass="1.23456789" stays 1.23456789 and Ratio="1/3" becomes 0.3333333333333333. Scientific notation survives (1e-7 stays 1e-07). Earlier versions wrote six significant digits, which silently rounded both of those.
(, and after +/-. 2*-3 is not an expression the evaluator accepts; write 2*(0-3). A field the evaluator cannot read — 2*-3, 1+, an unbalanced parenthesis — stops the run with an error naming the parameter or the initial condition and quoting the value. It used to crash the process instead.Define key parameters as variables so they can be easily changed (or overridden by batch scripts that rewrite the <VARIABLES> section):
The simulated duration is not a candidate: <Timing TEnd> is outside the substitution scope.