system_kind (function)
Stable function · Variable classification
Tier: stable · Kind: function · Topic: Variable classification
| Julia | TypeScript | Python | Rust | Go |
|---|---|---|---|---|
system_kind | systemKind | system_kind | system_kind | SystemKind |
Julia
system_kind(model::Model)
system_kind(flat::FlattenedSystem)
system_kind(model::Model) -> String
Derive what the system_kind field declares (esm-spec §6.3.1). Four conditions
tested in this order, first match winning:
| # | Condition | Result |
|---|---|---|
| 1 | any parameter in brownian_parameters | "sde" |
| 2 | any equation contains a spatial derivative | "pde" |
| 3 | no time-derivative equation at all | "nonlinear" |
| 4 | otherwise | "ode" |
Both orderings are load-bearing. "pde" precedes "nonlinear" so a
steady-state PDE (laplacian(phi) ~ f, no ∂/∂t) is a PDE rather than falling
through to "nonlinear". "sde" precedes "pde" because there is no
SPDESystem constructor to select, so a model that is both assembles as an SDE.
The rule is stated over the EQUATIONS and not over a domain block: domain
says nothing about space, so a domain-based test is not implementable.
A binding uses this derivation when the system_kind field is absent — see
effective_system_kind
, which composes it with
declared_system_kind
— and reports system_kind_mismatch when a
present field contradicts it.
system_kind(flat::FlattenedSystem) -> String
Derive what a flattened system’s system_kind field would declare (esm-spec
§6.3.1), over the FLATTENED form rather than a component.
Row 1 of the derivation tests brownian_parameters FIRST, and it reads the
bucket the FlattenedSystem carries. That is precisely what the bucket is for: a
flattened representation that dropped it could not report "sde", and a consumer
would integrate a stochastic system as a deterministic one.
TypeScript
function systemKind(model: Model): SystemKind
The system kind DERIVED from the equations and the parameter updates.
FIRST match wins, and the order is normative
(tests/conformance/classification/manifest.json, system_kind_order):
sde— any Brownian parameter.pde— any equation contains a spatial derivative.nonlinear— no time-derivative equation at all.ode— otherwise.
Two orderings that look equivalent are not. pde is tested BEFORE
nonlinear, so a steady-state PDE (laplacian(phi) ~ f, no time derivative)
is pde. sde is tested BEFORE pde, so a model carrying both a wiener
parameter and a spatial derivative is sde — not because it is not spatial,
but because there is no SPDESystem constructor to select.
Detection is a property of the EQUATIONS and never of the domain block,
which carries nothing spatial.
Example (inspect)
const doc = loadPath(fixture('decay.esm'))
assert.deepEqual(Object.keys(doc.models ?? {}), ['Decay'])
const model = doc.models!.Decay
assert.ok(!('ref' in model)) // narrows away an unresolved `{ ref }` mount
// The document declares only `unknown` and `parameter`; everything else is derived.
assert.deepEqual(Object.keys(model.variables), ['N', 'lambda', 'half_life'])
assert.deepEqual(unknowns(model), ['N', 'half_life'])
assert.deepEqual(parameters(model), ['lambda'])
// N has a time derivative; half_life is defined by an explicit equation.
assert.deepEqual(odeStates(model), ['N'])
assert.deepEqual(observedUnknowns(model), ['half_life'])
assert.deepEqual(algebraicUnknowns(model), [])
assert.equal(isOdeState(model, 'N'), true)
assert.deepEqual(constantParameters(model), ['lambda'])
assert.equal(systemKind(model), 'ode')
// Each observed's defining expression:
const defs = observedDefinitions(model)
assert.equal(toAscii(defs.get('half_life')!), 'log(2) / lambda')
Python
system_kind(model: Any) -> str
Derive the model’s MTK system kind (esm-spec §6.3.1).
Four rows tested IN ORDER, first match wins — the order is normative:
- any Brownian parameter →
"sde"(there is no SPDESystem, so this wins even over a spatial derivative); - any spatial derivative in any equation →
"pde"; - no time-derivative equation at all →
"nonlinear"; - otherwise →
"ode".
A binding uses this derivation whenever the system_kind FIELD is absent,
and reports system_kind_mismatch when a present field contradicts it.
Example (system_kind)
assert earthsci_ast.system_kind(model) == "ode"
assert earthsci_ast.is_ode_state(model, "N")
assert not earthsci_ast.is_ode_state(model, "half_life")
definitions = earthsci_ast.observed_definitions(model)
assert earthsci_ast.to_ascii(definitions["half_life"]) == "log(2) / lambda"
Rust
pub fn system_kind(model: &Model) -> SystemKind
The DERIVED system kind (esm-spec §6.3.1), which a binding uses when the
system_kind field is absent and checks against when it is present.
Example (inspect)
let doc = load_path(fixture("decay.esm"))?;
let model = &doc.models.as_ref().unwrap()["Decay"];
// Declared variables, in document order, with their declared type.
for (name, var) in &model.variables {
println!("{name}: {:?} [{}]", var.var_type, var.units.as_deref().unwrap_or(""));
}
assert_eq!(model.variables.keys().collect::<Vec<_>>(), ["N", "lambda", "half_life"]);
assert_eq!(model.variables["lambda"].var_type, VariableType::Parameter);
// Both N and half_life are declared `unknown`; their equations decide
// the class. `D(N) = ...` makes N a state, `half_life = ...` makes
// half_life an observed.
assert_eq!(ode_states(model), ["N"]);
assert_eq!(observed_unknowns(model), ["half_life"]);
assert!(algebraic_unknowns(model).is_empty());
assert_eq!(constant_parameters(model), ["lambda"]);
assert!(is_ode_state(model, "N") && !is_ode_state(model, "half_life"));
assert_eq!(system_kind(model), SystemKind::Ode);
Go
func SystemKind(model *Model) string
SystemKind derives what the system_kind field declares (esm-spec §6.3.1), testing four conditions IN ORDER and taking the first that holds:
- any Brownian parameter => “sde”
- any equation holds a spatial derivative => “pde”
- no time-derivative equation at all => “nonlinear”
- otherwise => “ode”
The order is normative and two orderings that look interchangeable are not. “pde” is tested BEFORE “nonlinear” so a steady-state PDE (laplacian(phi) ~ f, which has no time derivative) does not fall through to “nonlinear”; “sde” is tested BEFORE “pde” because there is no SPDESystem constructor to select for a model that is both.
Detection is a property of the EQUATIONS, never of the domain block: v0.8.0 removed Domain.spatial, so domain carries nothing spatial and the earlier “spatial domain plus differential operators” rule named a test no binding could perform. A vestigial domain parameter outlived that removal by two releases, unread by this body and by EffectiveSystemKind’s, and is gone as of API_SPEC.md §8 item 11: system_kind(model) takes the model and nothing else in all five bindings.