Version: dev

system_kind (function)

Stable function · Variable classification

Tier: stable · Kind: function · Topic: Variable classification

JuliaTypeScriptPythonRustGo
system_kindsystemKindsystem_kindsystem_kindSystemKind

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:

#ConditionResult
1any parameter in brownian_parameters"sde"
2any equation contains a spatial derivative"pde"
3no time-derivative equation at all"nonlinear"
4otherwise"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.

Source

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):

  1. sde — any Brownian parameter.
  2. pde — any equation contains a spatial derivative.
  3. nonlinear — no time-derivative equation at all.
  4. 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.

Source

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')

From docs/api/examples/typescript/inspect.ts

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:

  1. any Brownian parameter → "sde" (there is no SPDESystem, so this wins even over a spatial derivative);
  2. any spatial derivative in any equation → "pde";
  3. no time-derivative equation at all → "nonlinear";
  4. 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.

Source

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"

From docs/api/examples/python/documents.py

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.

Source · Rust docs

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);

From docs/api/examples/rust/inspect.rs

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:

  1. any Brownian parameter => “sde”
  2. any equation holds a spatial derivative => “pde”
  3. no time-derivative equation at all => “nonlinear”
  4. 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.

Source · Go docs