model
Stable type · Document types
Tier: stable · Kind: type · Topic: Document types
| Julia | TypeScript | Python | Rust | Go |
|---|---|---|---|---|
Model | not exported | Model | Model | Model |
Julia
struct Model <: EarthSciAST.SubsystemNode
Model(variables::AbstractDict{String, ModelVariable}, equations::Vector{Equation}, discrete_events::Vector{DiscreteEvent}, continuous_events::Vector{ContinuousEvent}, subsystems::AbstractDict{String}; tolerance, tests, analyses, initialization_equations, guesses, system_kind, reference)
Model(variables::AbstractDict{String, ModelVariable}, equations::Vector{Equation}; discrete_events, continuous_events, subsystems, tolerance, tests, analyses, initialization_equations, guesses, system_kind, reference)
Model
ODE-based model component containing variables, equations, and optional subsystems.
Supports hierarchical composition through subsystems. A subsystem value is a
child Model or — only until references are resolved — a SubsystemRef; the
field is typed by their shared supertype, OrderedDict{String,SubsystemNode}.
variables and subsystems are OrderedDicts, and the parser populates them in
DOCUMENT ORDER. That is not a convenience: esm-libraries-spec §4.7.5 step 4 makes
the flattened system’s ordering normative (variables in the order their component
declares them), and a flattener can only inherit an order the IR preserved. A
plain Dict here leaked its hash order all the way out to flatten’s
parameters, which a consumer reads POSITIONALLY as the parameter vector.
Example (inspect)
model = doc.models["Decay"]
@assert sort(collect(keys(model.variables))) == ["N", "half_life", "lambda"]
# The two declared kinds...
@assert unknowns(model) == ["N", "half_life"]
@assert parameters(model) == ["lambda"]
# ...and what each unknown is, derived from the equations.
@assert ode_states(model) == ["N"] # has a D(N)/dt equation
@assert observed_unknowns(model) == ["half_life"] # defined explicitly
@assert algebraic_unknowns(model) == String[] # none solved implicitly
defs = observed_definitions(model)
@assert to_ascii(defs["half_life"]) == "log(2) / lambda"
TypeScript
TypeScript does not export this type.
Python
class Model
Model(name: str, variables: dict[str, ModelVariable] = dict(), equations: list[Equation] = list(), metadata: dict[str, Any] = dict(), subsystems: dict[str, Model] = dict(), tolerance: Tolerance | None = None, tests: list[Test] = list(), analyses: list[Analysis] = list(), initialization_equations: list[Equation] = list(), guesses: dict[str, float | Expr] = dict(), system_kind: str | None = None, continuous_events: list[ContinuousEvent] = list(), discrete_events: list[DiscreteEvent] = list(), reference: Reference | None = None)
A mathematical model containing variables and equations.
Example (inspect)
model = doc.models["Decay"]
for name, var in model.variables.items():
print(f"{name}: {var.type} [{var.units}]")
assert {n: v.type for n, v in model.variables.items()} == {
"N": "unknown",
"lambda": "parameter",
"half_life": "unknown",
}
# The file declares only "unknown" and "parameter"; the finer classes are derived.
assert earthsci_ast.ode_states(model) == ["N"]
assert earthsci_ast.observed_unknowns(model) == ["half_life"]
assert earthsci_ast.algebraic_unknowns(model) == []
assert earthsci_ast.constant_parameters(model) == ["lambda"]
assert earthsci_ast.unknowns(model) == ["N", "half_life"]
Rust
pub struct Model {
pub name: Option<String>,
pub reference: Option<Reference>,
pub variables: IndexMap<String, ModelVariable>,
pub equations: Vec<Equation>,
pub discrete_events: Option<Vec<DiscreteEvent>>,
pub continuous_events: Option<Vec<ContinuousEvent>>,
pub subsystems: Option<IndexMap<String, Value>>,
pub description: Option<String>,
pub tolerance: Option<Tolerance>,
pub tests: Option<Vec<ModelTest>>,
pub analyses: Option<Vec<ModelAnalysis>>,
pub initialization_equations: Option<Vec<Equation>>,
pub guesses: Option<HashMap<String, Value>>,
pub system_kind: Option<String>,
}
ODE-based model component
name / description are NOT schema keys
The schema’s Model is additionalProperties: false and declares neither
name (a model’s name is its key in the models map) nor description.
Both fields below are therefore schema-INVALID the moment they are set, and
save() will happily emit a document that fails its own schema. They are
harmless only while they stay None, which is what every load-parsed model
leaves them as — no deserializer ever fills them, because the wire form has
no such keys.
They are not dead, though: crate::update_model_metadata
— a tier-
extension, Rust-only entry in api-surface.json — sets both, so its ONLY
observable effect is to make a valid document invalid. graph.rs also reads
name for a component-node label, where it is always None in practice.
They are part of the published API surface, so they stay; leave them
None.
Go
type Model struct {
Reference *Reference `json:"reference,omitempty"`
Variables map[string]ModelVariable `json:"variables"`
Equations []Equation `json:"equations"`
DiscreteEvents []DiscreteEvent `json:"discrete_events,omitempty"`
ContinuousEvents []ContinuousEvent `json:"continuous_events,omitempty"`
Subsystems map[string]any `json:"subsystems,omitempty"`
// Tolerance is the model-level default numerical tolerance applied to
// inline tests that do not override it (esm-spec §6.6).
Tolerance *Tolerance `json:"tolerance,omitempty"`
// Tests are inline validation tests for this model (esm-spec §6.6).
Tests []Test `json:"tests,omitempty"`
// Analyses are inline illustrative runs + plot specs (esm-spec §6.7).
Analyses []Analysis `json:"analyses,omitempty"`
// InitializationEquations hold only at t=0 (not dynamically time-stepped).
// Used by models that must solve an auxiliary system before the main
// time-stepping begins (e.g. aerosol equilibrium, plume rise). See gt-ebuq.
InitializationEquations []Equation `json:"initialization_equations,omitempty"`
// Guesses provides initial-guess seeds for nonlinear solvers during
// initialization, keyed by variable name. Values may be numeric literals
// or Expression graphs (serialized as interface{}).
Guesses map[string]any `json:"guesses,omitempty"`
// SystemKind discriminates the MTK system type this model maps to.
// One of "ode" (default), "nonlinear", "sde", "pde".
SystemKind *string `json:"system_kind,omitempty"`
}
func (m *Model) UnmarshalJSON(data []byte) error
Model represents an ODE system
Methods
func (m *Model) UnmarshalJSON(data []byte) error
Custom JSON unmarshaling for Model. Decodes guesses values through UnmarshalExpression so integer-valued initial guesses keep their int wire shape (RFC §5.4.1); every other field decodes exactly as its struct tags specify (via the alias type, which does not carry this method and so uses the default struct decoder). The embedded Guesses shadows the alias’s field so the raw guess objects are captured here rather than decoded lossily.