evaluation_document
Stable function · Evaluate the Jacobian
Tier: stable · Kind: function · Topic: Evaluate the Jacobian
| Julia | Python | Rust |
|---|---|---|
evaluation_document | evaluation_document | evaluation_document |
Note: The band fields are J_k in the derived model JacobianEval, in band order. For a flattened system the source’s scoped names are declared in its component tree (spec §8.1), so the document loads in every EarthSciAST binding; a source that mixes scoped and unscoped names, has a component named JacobianEval, a name that is both a variable and a component, or a variable named like a band field is refused. The source’s domain (its temporal, element_type and array_type) is carried through, so the document has the source’s time origin. The product documents (jvp_document, vjp_document, hvp_document) are laid out and carry the domain the same way, their inputs and outputs named with each . of the column’s name made _. Rust takes a SysView (sysview_flat for a flattened system) and the bands. A data-fed parameter (an update with a data rule) keeps those rules and the document carries the data_sources entries they name, so EarthSciAST builds it as an input (a forcing slot of rhs_program), not a constant; the product documents do the same. A flattened system carries no data_sources: pass the flattened document’s (Julia and Python data_sources = file.data_sources, Rust sysview_flat(&flat)?.with_data_sources(file.data_sources.as_ref())), or a named source that is not found is a BandError. An observed a kept rule reads (an expression unit_conversion, say) is kept. Julia’s jacobian_document of a flattened system writes the same rules and so takes the same data_sources keyword.
Julia
evaluation_document(input; wrt, model_name, forcing, cse, cse_min_nodes, data_sources)
evaluation_document(input; wrt = :states, model_name = nothing, forcing = nothing,
cse = true, data_sources = nothing) -> (doc, fields)
The derived evaluation document of the first-order bands on axis wrt
(esm-jacobian-spec.md §8, model "JacobianEval"): the source’s observed the
coefficients read, every source derivative zeroed, and one band-field state
J_k per entry whose D equation is that band’s coefficient field. One
right-hand-side call of an unmodified EarthSciAST evaluator at (u, p, t)
leaves every band value in du; fields[k] names entry k’s field.
Placing the values in a matrix is a scatter plan’s (bind_plan
).
With cse, repeated coefficient subtrees are hoisted into observed arrays
(hoist_observed).
A data-fed parameter (one whose update has a data rule) keeps those
rules, and the document carries the data_sources entries they name, so
EarthSciAST builds it as a forcing slot of rhs_program rather than a
constant. They come from data_sources when given, else from input: an
EsmFile’s own. A FlattenedSystem carries none, so pass the flattened
document’s data_sources when its parameters read data; a named source
that is not found is a BandError.
Example (evaluate)
# EarthSciASTDiff evaluates nothing: it emits ESM documents that EarthSciAST
# evaluates. The band fields J_k, as a derived model whose right-hand side,
# run once, leaves every band value in `du`. `fields[k]` names entry k's field.
doc, fields = evaluation_document(file)
@assert length(fields) == length(entries)
prob = EarthSciAST.esm_problem(
JSON3.read(stable_json(doc)), (0.0, 1.0)
)
du = zero(prob.u0)
prob.f!(du, prob.u0, prob.p, 0.0) # at the document's initial state
k = findfirst(en -> (en.u, en.v) == ("A", "A"), entries)
@assert du[prob.var_map["JacobianEval.$(fields[k])[1]"]] == -0.04 # -k1
# J·v as a derived model: inputs `_v_<C>`, outputs `_jvp_<R>`.
jdoc, (model, v, jvp) = jvp_document(file)
@assert model == "JvpEval"
J = jac_prototype(file) # sparse matrix on the fixed pattern
@assert size(J) == (12, 12) && nnz(J) == 24
# A scatter plan places the band fields in your own storage (here CSR),
# checked against the source before it is used.
bound = bind_plan(file, scatter_plan(file, Csr()))
@assert bound.len == 24
@assert all(1 <= k <= length(fields) for (k, _, _) in bound.pairs)
Python
evaluation_document(obj, model_name: str | None = None, wrt: str = 'states', forcing=None, cse: bool = True, cse_min_nodes: int = 12, data_sources=None)
The derived evaluation document of the first-order bands on axis
wrt (spec §8, model "JacobianEval"): the source’s observed the
coefficients read, every source derivative zeroed, and one band-field
state J_k per entry whose D equation is that band’s coefficient
field. One right-hand-side call of an unmodified EarthSciAST evaluator at
(u, p, t) leaves every band value in du.
Returns (doc, fields), fields[k] naming entry k’s field. With
cse, repeated coefficient subtrees are hoisted into observed arrays
(hoist_observed).
A data-fed parameter (one whose update has a data rule) keeps those
rules, and the document carries the data_sources entries they name, so
EarthSciAST builds it as an externally fed input rather than a constant.
They come from data_sources when given, else from obj: an
EsmFile’s own. A flattened system carries none, so pass the flattened
document’s data_sources when its parameters read data; a named source
that is not found raises BandError
.
Example (evaluate)
# EarthSciASTDiff evaluates nothing: it emits the band fields `J_k` as a derived
# ESM model that EarthSciAST evaluates.
doc, fields = earthsci_astdiff.evaluation_document(file)
assert "JacobianEval" in doc["models"]
assert len(fields) == len(entries)
# `J v` likewise: write `v` into the inputs io["v"], read `J v` from the
# derivatives of the outputs io["jvp"].
jdoc, io = earthsci_astdiff.jvp_document(file)
assert io["model"] in jdoc["models"]
assert io["v"]["A"] == "_v_A" and io["jvp"]["A"] == "_jvp_A"
Rust
pub fn evaluation_document(sv: &SysView<'_>, entries: &[JacEntry], cse: bool, cse_min_nodes: usize) -> Result<(Value, Vec<String>), BandError>
The derived evaluation document and its band-state names (J_1, …).
With cse, repeated coefficient subtrees are first hoisted into observed
(crate::eval_cse::hoist_observed).
Example (evaluate)
// EarthSciASTDiff evaluates nothing: it emits the band fields `J_k` as a
// derived ESM model that EarthSciAST evaluates.
let (doc, fields) = evaluation_document(&view, &entries, true, 12)?;
assert!(doc["models"]["JacobianEval"].is_object());
assert_eq!(fields.len(), entries.len());
// `J v` likewise: write `v` into the inputs `io.v`, read `J v` from the
// derivatives of the outputs `io.jvp`.
let (jdoc, io) = jvp_document(&view, &entries, Wrt::States, &ProductOptions::default())?;
assert!(jdoc["models"][io.model.as_str()].is_object());
assert_eq!(io.v["A"], "_v_A");
assert_eq!(io.jvp["A"], "_jvp_A");