icon_sc.core.components — component taxonomy¶
Component taxonomy (§4.1), control-flow wrappers and the dynamical-core base (§4.2).
Component taxonomy with the Ubbiali ABI (architecture §4.1-§4.2, SPEC S03).
The five sympl kinds — DiagnosticComponent, TendencyComponent,
ImplicitTendencyComponent, Stepper, Monitor — with the
object-oriented ABI adopted from stubbiali/sympl oop (see REFERENCES.lock):
__call__(state, timestep, *, out=None)with caller-provided output DataArrays (outis one flatname -> DataArraymapping across the component’s output property dicts);array_call(inputs, outputs, timestep)receiving both input and output raw buffers and writing outputs in place;allocate_output(name, schema, ctx)invoked exactly once per output field the caller did not provide;the restart protocol (
restart_state/load_restart_state) and the explicit-carry schemafunctional_state()(§4.5, §8.5).
All checking routes through S02’s contracts machinery: __init_subclass__
runs the StaticChecker at class
creation; __call__ runs the
DynamicChecker + Ingress/
EgressPlan per call — T0’s fully dynamic reference semantics — with one
negotiation cached per (instance, state-schema) so an unchanged schema does not
renegotiate (PLAN item 2; not the S05 plan compiler: dicts and DataArrays stay
on the path).
- class icon_sc.core.components.base.Component(*, ctx=None, name=None)¶
Shared machinery of the four callable component kinds (frozen ABI, SPEC S03).
Subclasses declare property dicts as class attributes; they are validated by the
StaticCheckerat class creation (__init_subclass__), so a component declaring, e.g., non-canonical units never constructs. Concrete subclasses implementarray_call()only — the base owns negotiation, allocation and egress.- Parameters:
ctx (ComputeContext | None)
name (str | None)
- output_dict_names: ClassVar[tuple[str, ...]] = ()¶
Which property dicts are outputs of this kind, in egress order.
- timestep_required: ClassVar[bool] = False¶
Whether
__call__requires a timestep (Stepper/ImplicitTendencyComponent).
- property ctx: ComputeContext¶
The compute context this component allocates and checks against.
- property parsed_properties: Mapping[str, Mapping[str, PropertySpec]]¶
Parsed property dicts (per-class, produced by the StaticChecker).
- abstract array_call(inputs, outputs, timestep)¶
Compute on raw buffers, writing every output in place (frozen ABI).
inputs/outputsare keyed by contract field names (aliases already resolved);outputsis the flat union of the kind’s output dicts.
- allocate_output(name, schema, ctx)¶
Allocate one output buffer (frozen ABI); called only for fields not in
out=.Default: an uninitialized buffer from the context allocator. Override for framework-side allocation (gt4py fields, pooled buffers, …).
- Parameters:
name (str)
schema (OutputSchema)
ctx (ComputeContext)
- Return type:
FieldBuffer
- restart_state()¶
Component-private persistent fields to serialize (default: stateless).
- load_restart_state(restart)¶
Restore component-private fields from
restart_state()output.
- functional_state()¶
Schema of the private carry surfaced to the F-tier (§8.5; default empty).
- Return type:
- visit(plan_builder)¶
Double-dispatch hook of the S05 plan compiler (and later tree walks).
- Parameters:
plan_builder (PlanBuilder)
- Return type:
None
- class icon_sc.core.components.base.DiagnosticComponent(*, ctx=None, name=None)¶
Pure function of the state at one time: computes diagnostics (§4.1).
- Parameters:
ctx (ComputeContext | None)
name (str | None)
- class icon_sc.core.components.base.ImplicitTendencyComponent(*, ctx=None, name=None)¶
A
TendencyComponentwhose tendencies depend on the timestep (§4.1).- Parameters:
ctx (ComputeContext | None)
name (str | None)
- class icon_sc.core.components.base.Monitor(*, name=None)¶
Consumes states for output/inspection; never on the component call path.
- Parameters:
name (str | None)
- class icon_sc.core.components.base.OutputSchema(spec, shape, dtype)¶
What
Component.allocate_output()needs to allocate one output field.- Parameters:
spec (PropertySpec)
dtype (dtype[Any])
- class icon_sc.core.components.base.Stepper(*, ctx=None, name=None)¶
Steps the state forward by one timestep with its own numerics (§4.1).
- Parameters:
ctx (ComputeContext | None)
name (str | None)
- class icon_sc.core.components.base.TendencyComponent(*, ctx=None, name=None)¶
Computes instantaneous tendencies (+ diagnostics) of the state (§4.1).
- Parameters:
ctx (ComputeContext | None)
name (str | None)
DynamicalCore — the three-cadence-tier core base class (SPEC S04).
Tasmania’s base class for two-time-level, multi-stage cores (thesis §3.5, Fig. 3.8-3.10), whose tier terminology Tasmania itself borrowed from ICON:
slow tier — tendencies computed outside the core and consumed inside at the point the numerics dictate: the slow-tendency input port. Port slots are ordinary
input_propertiesentries (state fields,icon:ddt_*convention; theSlowTendencyBusis their checker); thetendency_portclass attribute maps each prognostic to its slot. Slow tendencies are held constant across the step — the port buffers are never written.fast tier — an optional per-stage
fast_tendency_component(ConcurrentCoupling) evaluated once per stage on the latest provisional state (FC within the core); its tendencies are summed onto the slow port values into per-stage scratch buffers. Empty in the ICON preset; the natural experiment port.super-fast tier — substepping with its own hook: stage
sperformsmax(1, round(substep_fraction[s] · N))substeps ofΔt/Neach, whereNcomes fromsubsteps(static) orratio_provider(adaptive, CFL-style; called once per step with the state — the semantics shared withSubcycle). Fig. 3.10’s example is a 3-stage Wicker-Skamarock core withN = 6and fractions (⅓, ½, 1) → 2, 3, 6 substeps.
Subclass contract (frozen, SPEC S04): implement
stage_array_call(stage, inputs, outputs, dt) and
substep_array_call(stage, substep, inputs, outputs, dt); declare n_stages
and substep_fraction. Hooks receive raw buffers (the S03 ABI): inputs
holds the latest provisional state plus the combined (slow + fast) tendency
values under the port slot names, and — inside substeps — the enclosing stage’s
outputs under "stage/<name>" keys.
The orchestration is numpy-level T0 reference semantics (scratch buffers via
numpy.empty_like); the S05 plan compiler unrolls the tiers into the op list.
- class icon_sc.core.components.dycore.DynamicalCore(*, fast_tendency_component=None, substeps=0, ratio_provider=None, ctx=None, name=None)¶
Multi-stage, three-tier dynamical core base (frozen interface, SPEC S04).
Stepper-shaped:
(state, timestep, *, out=None) -> (diagnostics, new_state). Subclasses declareinput_properties(prognostics + slow-port slots + any static fields),output_properties(the prognostics) and optionallydiagnostic_properties; every prognostic must also be an input, andtendency_portmaps prognostics to their slow-tendency slot names.- Parameters:
fast_tendency_component (ConcurrentCoupling | None)
substeps (int)
ctx (ComputeContext | None)
name (str | None)
- output_dict_names: ClassVar[tuple[str, ...]] = ('diagnostic_properties', 'output_properties')¶
Which property dicts are outputs of this kind, in egress order.
- timestep_required: ClassVar[bool] = True¶
Whether
__call__requires a timestep (Stepper/ImplicitTendencyComponent).
- substep_nesting: ClassVar[str] = 'stage_outer'¶
How the stage and super-fast tiers nest (S14, additive ClassVar):
"stage_outer"— the Fig. 3.10 default this base class orchestrates (each stage runs its own substep block);"substep_outer"— ICON’s nesting (every substep runs the full stage sequence,mo_nh_stepping.f90::perform_dyn_substepping). A substep-outer core overridesarray_callwith its own orchestration and implements the plan-hook quartet the S05/S14 compiler unrolls the step into (all follow the materialized(*prefix, inputs, outputs, timestep)BoundCall pack):plan_ingress(n_substeps, inputs, outputs, dt)— step entry: boundary buffers → component-private state (§4.5);dtis the full Δt;plan_substep_begin(substep, inputs, outputs, sub_dt)— the component-private carry swaps that precede the substep’s stages;substep_array_call(stage, substep, inputs, outputs, sub_dt)— the frozen S04 hook, one stage of one substep;plan_substep_end(substep, inputs, outputs, sub_dt)— the private time-level swap between substeps (not emitted after the last);plan_egress(inputs, outputs, dt)— step exit: private state → boundary output buffers, plus step bookkeeping.
Private swaps stay inside these BoundCalls — the vault only ever holds boundary fields and their step-level ping-pong (§8.2/§4.5).
- substep_fraction: ClassVar[float | tuple[float, ...]] = 1.0¶
Per-stage fraction of the total substep count
N(scalar broadcasts).
- tendency_port: ClassVar[Mapping[str, str]] = {}¶
Prognostic field name -> input slot carrying its slow tendency (may be partial).
- property fast_tendency_component: ConcurrentCoupling | None¶
The per-stage fast coupling (empty in the ICON preset).
- property ratio_provider: Callable[[Mapping[str, Any]], int] | None¶
The adaptive substep-count provider (shared semantics with Subcycle).
- visit(plan_builder)¶
S05 plan-compiler hook: unroll the stage/substep tiers (§8.2).
- Parameters:
plan_builder (PlanBuilder)
- Return type:
None
- abstract stage_array_call(stage, inputs, outputs, dt)¶
Integrate one stage on raw buffers, writing every output in place.
inputs: the latest provisional state (field names) plus the combined slow+fast tendencies under thetendency_portslot names.outputs: the stage’s prognostic buffers plus the core’s diagnostic buffers.dtis the full timestep; the stage’s own coefficients decide spans.
- abstract substep_array_call(stage, substep, inputs, outputs, dt)¶
Integrate one super-fast substep on raw buffers.
inputs: the current substepped state (field names), the combined tendencies (slot names) and the enclosing stage’s outputs under"stage/<name>"keys.dtis the substep sizeΔt/N.
Control-flow wrappers: CallingFrequency, Subcycle, ScalingWrapper (SPEC S03).
Pure control flow around the §4.1 kinds — at T0 they are ordinary callables
honoring the component ABI (__call__(state, timestep, *, out=None), property
dicts delegated to the wrapped component); at T1+ they dissolve into the
execution plan (§8.2: cadence masks, unrolled subcycles, folded constants).
Semantics donors (REFERENCES.lock): sympl UpdateFrequencyWrapper (firing
rule + cached output) for CallingFrequency; tasmania’s per-section
substeps for Subcycle; sympl ScalingWrapper verbatim in spirit.
- class icon_sc.core.components.wrappers.CallingFrequency(component, dt)¶
Reduced calling frequency with piecewise-constant cached output (§4.2 LFC).
CallingFrequency(component, dt)calls the wrapped component only whenstate["time"]has advanced at least one effective period past the last update, returning the cached output verbatim in between (ICON’s slow-physics choice: lazy evaluation stretched over N steps).Rounding-to-multiple rule: when a call supplies the loop
timestep, the effective period is the nearest positive integer multiple of it (exact integer-microsecond arithmetic, ties round up); without a timestep the raw per-processdtapplies. Phase (the last update time) and the cached output are component-private carry: surfaced byrestart_state()and declared infunctional_state()(S10 relies on this being carry).- Parameters:
component (Component | ComponentWrapper)
dt (timedelta)
- period_for(timestep)¶
Effective period under the rounding-to-multiple rule (SPEC S03).
- visit(plan_builder)¶
S05 plan-compiler hook: dissolve into a cadence mask (§8.2).
- Parameters:
plan_builder (PlanBuilder)
- Return type:
None
- class icon_sc.core.components.wrappers.ComponentWrapper(component)¶
Shared delegation base of the control-flow wrappers.
Property dicts, names and every other attribute delegate to the wrapped component via
__getattr__. Wrappers acceptComponent | ComponentWrapperso they compose (CallingFrequency(Subcycle(...), ...)) without casts.- Parameters:
component (Component | ComponentWrapper)
- property component: Component | ComponentWrapper¶
The wrapped component.
- visit(plan_builder)¶
Refuse plan compilation for unknown wrappers (S05).
Defined on the base so
__getattr__can never silently delegate the walk to the wrapped component (which would dissolve the wrapper’s semantics); the three known wrappers override with their real hooks.- Parameters:
plan_builder (PlanBuilder)
- Return type:
None
- class icon_sc.core.components.wrappers.ScalingWrapper(component, *, input_scale_factors=None, tendency_scale_factors=None, diagnostic_scale_factors=None, output_scale_factors=None)¶
Scale selected inputs/outputs of a wrapped component (sympl semantics).
Scale-factor dict keys are validated against the wrapped component’s property dicts at construction. Inputs are scaled into attr-preserving copies before the call (allocating — T0/debug affordance); outputs/tendencies/diagnostics are scaled in place after the call, so
out=pointer identity is preserved.- Parameters:
- property scale_factors: Mapping[str, Mapping[str, float]]¶
The validated scale-factor dicts, keyed by factor-dict name (S05 accessor).
- visit(plan_builder)¶
S05 plan-compiler hook: fold into bound constants (§8.2).
- Parameters:
plan_builder (PlanBuilder)
- Return type:
None
- class icon_sc.core.components.wrappers.Subcycle(stepper, n=None, ratio_provider=None)¶
Run a
Stepperntimes overtimestep / n(§4.2 combinator).Exactly one of
n(static) andratio_provider(adaptive: called once per outer step with the current state, must return an integer >= 1) is given. Intermediate sub-states chain through the stepper (tasmania’s substep semantics);out=is forwarded to the final substep only, so earlier substeps never alias the caller’s buffers.state["time"]is not advanced between substeps (deliberately dumb at T0; the plan compiler owns cadence).Note
Because time does not advance between substeps, a time-triggered wrapper inside a subcycle —
Subcycle(CallingFrequency(...), ...)— degenerates to at most one effective fire per outer step: every substep after the first sees an unchangedstate["time"]and replays the cache.- Parameters:
stepper (Stepper | ComponentWrapper)
n (int | None)
- property ratio_provider: Callable[[Mapping[str, Any]], int] | None¶
The adaptive substep-count provider (S05 accessor).
- visit(plan_builder)¶
S05 plan-compiler hook: unroll with bound dt (§8.2).
- Parameters:
plan_builder (PlanBuilder)
- Return type:
None