icon_sc.icon.components — ICON process components¶
Public modules only; solver-internal helpers are not part of the reference.
ICON components hosted on icon_sc.core (architecture §4.3; S07+).
Subpackages mirror ICON’s process taxonomy: icon_sc.icon.components.fast
(fast physics, every Δt, sequential-update split);
icon_sc.icon.components.dycore (S12: the icon4py nonhydrostatic solver as a
DynamicalCore); icon_sc.icon.components.diffusion (S13: the icon4py
horizontal-diffusion granule as a Stepper). Real slow physics and transport
arrive with their own steps; icon_sc.icon.components.idealized carries the
S09 analytic stand-ins that exercise the slow-tendency bus.
ICON fast-physics components (every Δt; tutorial §3.7.2 sequential-update split).
SaturationAdjustment(Stepper) — the icon4py satad granule on ICON-sc state (S07).
The scientific kernel is icon4py’s saturation-adjustment granule (microphysics
package, REFERENCES.lock id icon4py-satad): Newton iteration on T at
constant total density with the latent-heat closure lwdocvd = L_v(T)/cvd
(cvd bookkeeping — satad’s ICON path implies cvd, never cpd; mo_satad.f90,
REFERENCES.lock id icon-fortran-satad). ICON-sc does not re-plumb the
granule’s internals: array_call builds zero-copy gt4py views of the
boundary buffers (icon_sc.core.ingress.gt4py) and invokes
granule.run(...) exactly as icon4py’s own integration test does, then
applies the returned tendencies over the timestep — x_new = x + dx/dt·Δt is
icon4py’s own verification arithmetic against the satad-exit savepoints.
Coupling position (tutorial §3.7.2, REFERENCES.lock id icon-tutorial-2025):
fast physics is time-split (“also known as sequential-update split”); satad
appears twice in the NWP fast-physics sequence — after the surface-transfer
scheme, and again after microphysics so that vapor and liquid are in
equilibrium before the slow physics. Hence
coupling_constraints.admissible_operators = {"sequential_update_splitting"}:
satad as an adjustment-type Stepper enters SUS chains directly and is not
admissible under the tendency-summing operator families.
Differentiability: differentiable: "custom" (architecture §8.6) — since S10
the granule is paired with a functional core co-located in this module
(_satad_functional(), invoked through functional_call): the saturation
fixed point f(T*) = T* - T + (L(T)/cvd)·(qsat_rho(T*, rho) - qv) = 0 is solved
by the granule’s own masked Newton iteration (same per-point freeze/convergence
semantics, bounded while_loop) wrapped in the
icon_sc.core.functional.rules.implicit_fixed_point() lax.custom_root
rule, so both AD modes differentiate through the implicit function — the
adjoint of the Newton solve via the IFT, never through recorded iterations
(which also sidesteps while_loop’s reverse-mode prohibition). Closures and
constants come from satad_constants.py (one scheme-constants module per
scheme, §11.8). jax imports stay inside the functional entry points.
- class icon_sc.icon.components.fast.satad.SaturationAdjustment(grid_or_column, cfg=None, ctx=None, *, name=None)¶
Saturation adjustment on the column/grid state (frozen interface, SPEC S07).
SaturationAdjustment(grid_or_column, cfg, ctx)—grid_or_columnis eithera
icon_sc.icon.grid.vertical.VerticalGrid(column path): the horizontal extent is discovered from the state at the first call and a trivial pointwise icon4py grid is built around it; oran
(icon4py_grid, icon4py_vertical_grid)pair (host-grid path): the granule is hosted on an existing icon4py grid exactly as icon4py’s own tests build it (the L2 datatest path).
State names are the S06 registry rows (
air_temperature,specific_humidity,specific_cloud_content,air_density); the T-based granule formulation was chosen because it is the variant with serialized ICON reference data (PLAN pitfall; the θv/exner-coupled variant does not exist as a granule — the muphys variant differs in physics, see REFERENCES.lockicon4py-muphys-satad).Adjustment happens on levels
kstart_moist ≤ k < nlev(moist physics domain); above it the outputs equal the inputs.- Parameters:
grid_or_column (VerticalGrid | tuple[Any, Any])
cfg (SaturationAdjustmentConfig | None)
ctx (ComputeContext | None)
name (str | None)
- coupling_constraints: ClassVar[CouplingConstraints] = CouplingConstraints(must_follow=(), must_precede=(), admissible_operators=('sequential_update_splitting',))¶
fast physics is sequential-update split; see module docstring.
- Type:
tutorial §3.7.2
- 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.
- functional_call(inputs, params, *, dt)¶
Pure JAX evaluation of one satad step (§8.6
custom; SPEC S10).Same boundary as
array_call(); reverse/forward derivatives cross the saturation fixed point through the IFTcustom_rootrule, not the Newton iterations. No tunableparams:max_iter/toleranceare solver controls, not scheme physics.
- class icon_sc.icon.components.fast.satad.SaturationAdjustmentConfig(max_iter=10, tolerance=0.001)¶
satad configuration (mirrors icon4py
SaturationAdjustmentConfig).Defaults transcribed from icon4py v0.2.0 (REFERENCES.lock
icon4py-satad): “in ICON, 10 is always used for max iteration when subroutine satad_v_3D is called” / “1.e-3 is always used for the tolerance”.
Microphysics(Stepper) — the icon4py graupel granule on ICON-sc state (S08).
The scientific kernel is icon4py’s single-moment six-class graupel granule
(single_moment_six_class_gscp_graupel.py, REFERENCES.lock id
icon4py-graupel), the gt4py port of ICON’s gscp_graupel.f90 (now at
src/granules/microphysics_1mom_schemes/, REFERENCES.lock id
icon-fortran-graupel). ICON-sc does not re-plumb the granule’s internals —
in particular the sedimentation/level-loop structure (one forward K-scan
carrying the rhoq{r,s,g,i}v_old_kup/vnew_* sedimentation state, plus
the two flux programs) stays exactly as the granule has it (SPEC S08 in-scope
clause): array_call builds zero-copy gt4py views of the boundary buffers
(icon_sc.core.ingress.gt4py) and invokes granule.run(...) exactly as
icon4py’s own integration test does, then applies the returned tendencies over
the timestep — x_new = x + dx/dt·Δt is icon4py’s own verification
arithmetic against the microphysics-exit savepoints.
Scheme selection (SPEC: “scheme selectable by registry name”): concrete schemes
subclass Microphysics and register under their name class attribute
via the S02 Factory machinery;
Microphysics(grid, cfg, ctx, scheme="graupel") (the architecture-§4.3 usage)
and Microphysics.factory("graupel", ...) both resolve through that registry.
"graupel" is the only registered scheme for now.
Coupling position (tutorial §3.7.2, REFERENCES.lock id icon-tutorial-2025):
fast physics is time-split (“also known as sequential-update split”);
microphysics sits between turbulent diffusion and the second saturation
adjustment in the NWP fast-physics sequence. Hence
coupling_constraints.admissible_operators = {"sequential_update_splitting"}.
Differentiability: differentiable: "native" (architecture §8.6) — since S10
the granule is paired with a JAX functional core co-located in this module
(_graupel_functional(), invoked through Graupel.functional_call): a
line-by-line port of the granule’s scan/flux programs (REFERENCES.lock
icon4py-graupel-stencils) sharing this scheme’s constants module
(graupel_constants.py) so the two implementations cannot drift (§11.8).
Tunable scheme constants are exposed as the §8.6 params declaration
(functional_params): the Seifert-Beheng autoconversion/accretion kernel
coefficients and the ICON tuning-namelist knobs of GraupelConfig;
coefficients the granule precomputes from them (math.gamma expressions) are
re-derived in-trace via gammaln so ParamTree gradients flow through them.
jax imports stay inside the functional entry points — the component itself never
requires jax (the [jax] extra is optional).
- class icon_sc.icon.components.fast.microphysics.Graupel(*args, scheme=None, **kwargs)¶
The single-moment six-class graupel scheme (registry name
"graupel").State names are the S06/S08 registry rows; the scheme steps T and the six moisture tracers, consumes p, rho, the layer thickness
icon:ddqz_z_full(the SPEC’s “dz from VerticalGrid via static-state input” — the S06 column builders put it in the state; the datatest takes it from the metrics savepoint) and the cloud droplet number concentrationicon:qnc, and diagnoses the four grid-scale surface precipitation rates (ground-level values of the granule’s precipitation-flux fields — icon4py’s own verification arithmetic;icon:*_gsp_rateper ICONprm_nwp_diag).Stepping happens on levels
kstart_moist ≤ k < nlev(moist physics domain); above it the outputs equal the inputs and the tendencies are an exact zero.- Parameters:
grid_or_column (VerticalGrid | tuple[Any, Any])
cfg (GraupelConfig | None)
ctx (ComputeContext | None)
scheme (str | None)
- coupling_constraints: ClassVar[CouplingConstraints] = CouplingConstraints(must_follow=(), must_precede=(), admissible_operators=('sequential_update_splitting',))¶
fast physics is sequential-update split; see module docstring.
- Type:
tutorial §3.7.2
- 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.
- functional_params()¶
Tunable scheme constants exposed to the ParamTree (§8.6
params).The Seifert-Beheng kernel coefficients (scheme constants, single source
graupel_constants.py) plus the ICON tuning-namelist knobs carried byGraupelConfig; every granule coefficient derived from these is re-derived in-trace by the functional core, so their gradients are real.
- functional_call(inputs, params, *, dt)¶
Pure JAX evaluation of one graupel step (§8.6
native; SPEC S10).Same boundary as
array_call(): contract-named inputs in, the flat union of outputs + diagnostics out (x_new = x + dx/dt·Δton the moist domain, surface precipitation rates from the ground-level fluxes).
- class icon_sc.icon.components.fast.microphysics.GraupelConfig(liquid_autoconversion_option=1, snow_intercept_option=2, do_latent_heat_nudging=False, use_constant_latent_heat=True, ice_stickeff_min=0.075, power_law_coeff_for_ice_mean_fall_speed=1.25, exponent_for_density_factor_in_ice_sedimentation=0.33, power_law_coeff_for_snow_fall_speed=20.0, rain_mu=0.0, rain_n0=1.0, snow2graupel_riming_coeff=0.5)¶
graupel configuration (mirrors icon4py
SingleMomentSixClassIconGraupelConfig).Field-for-field transcription of the icon4py v0.2.0 config (REFERENCES.lock
icon4py-graupel), whose defaults are the ICON namelist defaults; the two option enums are carried as their integer values so icon4py stays a lazy import (LiquidAutoConversionType/SnowInterceptParameterization). Options hardcoded toTruein ICON (lsedi_ice/lstickeff/lred_depgrow) are removed by icon4py and therefore absent here too.- Parameters:
liquid_autoconversion_option (int)
snow_intercept_option (int)
do_latent_heat_nudging (bool)
use_constant_latent_heat (bool)
ice_stickeff_min (float)
power_law_coeff_for_ice_mean_fall_speed (float)
exponent_for_density_factor_in_ice_sedimentation (float)
power_law_coeff_for_snow_fall_speed (float)
rain_mu (float)
rain_n0 (float)
snow2graupel_riming_coeff (float)
- liquid_autoconversion_option: int = 1¶
0 = Kessler (1969), 1 = Seifert & Beheng (2006).
- Type:
Liquid autoconversion mode
- snow_intercept_option: int = 2¶
1/2 = Field et al. (2005) best-fit/general moment.
- Type:
Snow intercept parameterization
- power_law_coeff_for_ice_mean_fall_speed: float = 1.25¶
v-qi power-law coefficient for ice fall speed (ICON
tune_zvz0i).
- exponent_for_density_factor_in_ice_sedimentation: float = 0.33¶
Density-factor exponent in ice sedimentation (ICON
tune_icesedi_exp).
- power_law_coeff_for_snow_fall_speed: float = 20.0¶
v-D power-law coefficient for snow fall speed (ICON
tune_v0snow).
- snow2graupel_riming_coeff: float = 0.5¶
Snow-to-graupel riming conversion coefficient (ICON
tune_zcsg).
- classmethod from_icon4py(config)¶
Transcribe an icon4py
SingleMomentSixClassIconGraupelConfig.Used by the L2 datatest to consume
experiment.config.graupel(the namelist the serialized data was produced with) through the ICON-sc component — the PLAN-pitfall path that pins the exact configuration.- Parameters:
config (Any)
- Return type:
- class icon_sc.icon.components.fast.microphysics.Microphysics(*args, scheme=None, **kwargs)¶
Grid-scale microphysics on the column/grid state (SPEC S08).
Registry root (S02
Factory): concrete schemes subclass this and set thenameclass attribute;Microphysics(grid_or_column, cfg, ctx, scheme=<registry name>)dispatches construction to the registered scheme class (default"graupel"), andMicrophysics.factory(name, ...)is the explicit registry path. Constructing a concrete subclass directly (Graupel(...)) is equivalent.Microphysics(grid_or_column, cfg, ctx)—grid_or_columnis eithera
icon_sc.icon.grid.vertical.VerticalGrid(column path): the horizontal extent is discovered from the state at the first call and a trivial pointwise icon4py grid is built around it; oran
(icon4py_grid, icon4py_vertical_grid)pair (host-grid path): the granule is hosted on an existing icon4py grid exactly as icon4py’s own tests build it (the L2 datatest path).
- Parameters:
args (Any)
scheme (str | None)
kwargs (Any)
- Return type:
NonhydroSolver(DynamicalCore) — icon4py solve_nonhydro hosted on ICON-sc (S12).
The icon4py nonhydrostatic solver + velocity advection as one ICON-sc component
(architecture §4.3): the predictor-corrector is the stage structure, ndyn_substeps
is the super-fast tier, slow physics enters through the tendency-bus port, and the
two prognostic time levels plus the velocity-advection carry-over are component-private
state behind the restart/functional-state protocols.
Hosting policy (wrap-don’t-rewrite, §4.4): the ~50 predictor/corrector stencil programs
stay icon4py granule internals (REFERENCES.lock icon4py-solve-nonhydro); ICON-sc
invokes run_predictor_step/run_corrector_step exactly the way icon4py’s own
integration tests and driver do (REFERENCES.lock icon4py-solve-nonhydro-tests,
icon4py-driver-dyn-substepping).
Tier nesting (declared deviation from the S04 default orchestration). The base
DynamicalCore unrolls Fig. 3.10 stage-outer
(each stage runs its own substep block). ICON nests the other way round: each of the
ndyn_substeps substeps runs the full predictor→corrector stage pair
(mo_nh_stepping.f90::perform_dyn_substepping, REFERENCES.lock
icon-fortran-solve-nonhydro-stepping). NonhydroSolver therefore overrides
array_call — the base class explicitly routes tier orchestration through that
method — while keeping the frozen S04 subclass hooks: substep_array_call(stage,
substep, ...) executes one stage of one substep and stage_array_call is its
degenerate single-substep form. Data flows through the component-private icon4py
state objects (communicates_internally=True, §4.3): the hook inputs/outputs
dicts are the boundary buffers ingested/egressed once per step by array_call.
Slow-tendency bus port (tutorial §3.7.2, REFERENCES.lock
icon-fortran-solve-nonhydro-stepping): the slots icon:ddt_vn_phy and
icon:ddt_exner_phy are ordinary input fields, held constant across the step and
consumed inside the substeps at the points ICON’s numerics dictate — ddt_vn_phy
in the vn update of every predictor and corrector (mo_solve_nonhydro.f90 l.1365,
l.1410), ddt_exner_phy in the explicit part of the vertically implicit solver
(l.2316/2340). Absent slots default to zeros so the S13 JW run needs no physics.
- class icon_sc.icon.components.dycore.NonhydroConfig(itime_scheme=4, iadv_rhotheta=2, igradp_method=3, rayleigh_type=2, divdamp_order=24, divdamp_type=3, ndyn_substeps=5, ndyn_substeps_max=12, rhotheta_offctr=-0.1, veladv_offctr=0.25, divdamp_fac=0.0025, divdamp_fac2=0.004, divdamp_fac3=0.004, divdamp_fac4=0.004, divdamp_z=32500.0, divdamp_z2=40000.0, divdamp_z3=60000.0, divdamp_z4=80000.0, extra_diffu=True, max_nudging_coefficient=0.1, l_vert_nested=False, deepatmos_mode=False, iau_init=False, second_order_divdamp_factor=0.032, prepare_advection=False)¶
solve_nonhydro configuration (SPEC S12: mirrors icon4py
NonHydrostaticConfig).Every field carries an
icon_namelist_originannotation (dataclass metadata, machine-readable viaicon_namelist_origins()). Defaults are icon4py v0.2.0 defaults, which transcribe the ICON Fortran namelist defaults (REFERENCES.lockicon4py-solve-nonhydro). The icon4py granule accepts only the operational slice (itime_scheme=4,iadv_rhotheta=2,igradp_method=3, Klemp Rayleigh damping,extra_diffu=True);to_icon4py()re-runs its validation, so an unsupported knob fails at component construction.- Parameters:
itime_scheme (int)
iadv_rhotheta (int)
igradp_method (int)
rayleigh_type (int)
divdamp_order (int)
divdamp_type (int)
ndyn_substeps (int)
ndyn_substeps_max (int)
rhotheta_offctr (float)
veladv_offctr (float)
divdamp_fac (float)
divdamp_fac2 (float)
divdamp_fac3 (float)
divdamp_fac4 (float)
divdamp_z (float)
divdamp_z2 (float)
divdamp_z3 (float)
divdamp_z4 (float)
extra_diffu (bool)
max_nudging_coefficient (float)
l_vert_nested (bool)
deepatmos_mode (bool)
iau_init (bool)
second_order_divdamp_factor (float)
prepare_advection (bool)
- ndyn_substeps: int = 5¶
Δτ = Δt/N (the DynamicalCore
substepsdefault).- Type:
The super-fast tier ratio N
- max_nudging_coefficient: float = 0.1¶
icon4py default = DEFAULT_DYNAMICS_TO_PHYSICS_TIMESTEP_RATIO(5) * 0.02.
- second_order_divdamp_factor: float = 0.032¶
ICON derives divdamp_fac_o2 from the spinup ramp at runtime; fixed per run here.
- prepare_advection: bool = False¶
ICON derives lprep_adv from ltransport; S12 hosts no transport — default off.
- to_icon4py()¶
The icon4py
NonHydrostaticConfig(runs the granule’s own validation).- Return type:
- classmethod from_icon4py(cfg, *, ndyn_substeps, second_order_divdamp_factor=0.032, prepare_advection=False)¶
Mirror an icon4py
NonHydrostaticConfig(e.g. a datatest archive’s).- Parameters:
- Return type:
- class icon_sc.icon.components.dycore.NonhydroSolver(grid, vgrid, static, cfg=None, ctx=None, *, substeps=0, ratio_provider=None, fast_tendency_component=None, edge_geometry=None, cell_geometry=None, owner_mask=None, exchange=None, name=None)¶
The ICON nonhydrostatic solver as a ICON-sc
DynamicalCore(SPEC S12).NonhydroSolver(grid, vgrid, static, cfg, ctx, *, substeps=..., ...)—grid: aicon_sc.icon.grid.IconGrid(production path: geometry and owner mask derived from it) or a raw icon4pyIconGrid(host-grid path, as icon4py’s own tests build it — thenedge_geometry/cell_geometry/owner_maskmust be passed explicitly);vgrid: aicon_sc.icon.grid.VerticalGridor a raw icon4pyVerticalGrid;static: mapping of theSTATIC_FIELDSregistry names to S11 static-state DataArrays (metrics(grid, vgrid) | interpolation(grid)) or to ready icon4py fields (savepoint parity path — used as-is, zero conversion);cfg:NonhydroConfig(namelist knobs, annotated origins);substep tier:
substepsfixes the ratio N (defaultcfg.ndyn_substeps);ratio_provider(state) -> intmakes it adaptive (called once per step, S04 semantics; bounded bycfg.ndyn_substeps_max). CFL exposure for adaptive providers is stubbed to the fixed ratio in this slice — the carry fieldcarry/max_vertical_cfl(ICONmax_vcfl_dyn) is serialized and readable viamax_vertical_cfl, but no provider ships until the CFL diagnostics land (declared, SPEC S12).
The component is a first-class sympl-style citizen: constructible and callable without any federation (acceptance 5). One
__call__advances one full Δt = N substeps of Δτ = Δt/N, each substep running predictor→corrector with the velocity-advection reuse of ICON’sitime_scheme=4(MOST_EFFICIENT).- Parameters:
grid (IconGrid | Any)
vgrid (VerticalGrid | Any)
static (Mapping[str, Any])
cfg (NonhydroConfig | None)
ctx (ComputeContext | None)
substeps (int)
fast_tendency_component (ConcurrentCoupling | None)
edge_geometry (Any | None)
cell_geometry (Any | None)
owner_mask (Any | None)
exchange (Any | None)
name (str | None)
- substep_fraction: ClassVar[float] = 1.0¶
Per-stage fraction of the total substep count
N(scalar broadcasts).
- substep_nesting: ClassVar[str] = 'substep_outer'¶
ICON nests substeps outer (module docstring); the S14 plan compiler unrolls the step through the plan-hook quartet below (contract documented on
DynamicalCore.substep_nesting).
- tendency_port: ClassVar[Mapping[str, str]] = {'icon:exner_function': 'icon:ddt_exner_phy', 'icon:normal_wind': 'icon:ddt_vn_phy'}¶
Prognostic field name -> input slot carrying its slow tendency (may be partial).
- communicates_internally: ClassVar[bool] = True¶
halo exchanges happen inside the hosted granule.
- Type:
§4.3 table
- hook_log: list[tuple[Any, ...]] | None¶
set to a list to record; None = off.
- Type:
Hook-order recording (acceptance 2)
- property max_vertical_cfl: float¶
ICON
max_vcfl_dyn— the CFL diagnostic an adaptive ratio provider reads.
- visit(plan_builder)¶
S05/S14 plan hook: unroll the ICON substep-outer nesting.
substep_nesting = "substep_outer"routes the compiler to the S14 per-substep op sequence (ingress → N x [carry swaps → predictor → corrector → time-level swap] → egress) via the plan-hook quartet; the component-private icon4py state never reaches the vault (§4.5, PLAN S14 pitfall) — the vault sees only the boundary prognostics’ step-level ping-pong.- Parameters:
plan_builder (PlanBuilder)
- Return type:
None
- plan_ingress(n_substeps, inputs, outputs, timestep)¶
T1 step entry: boundary buffers → private time levels + bus (S14).
Mirrors the
array_callpreamble exactly (the substep-count guards ran at bind; they are re-checked here so a mutated component fails loudly).
- plan_substep_begin(substep, inputs, outputs, timestep)¶
T1 substep entry: the MOST_EFFICIENT advective-tendency pair swaps.
Component-private carry swaps (never vault swaps); the initial-timestep exception lives in the private
_at_initial_timestepflag exactly as at T0 (§4.5 restart semantics are preserved verbatim).
- plan_substep_end(substep, inputs, outputs, timestep)¶
T1 inter-substep boundary: private nnow/nnew time-level swap.
- plan_egress(inputs, outputs, timestep)¶
T1 step exit: bookkeeping + private state → boundary output buffers.
- array_call(inputs, outputs, timestep)¶
ICON tier orchestration: substeps outer, predictor→corrector inner.
Mirrors
mo_nh_stepping.f90::perform_dyn_substeppingand the icon4py driver_do_dyn_substepping(REFERENCES.lockicon-fortran-solve-nonhydro-stepping,icon4py-driver-dyn-substepping): Δτ = Δt/N; tendency-pair swaps implement the MOST_EFFICIENT velocity-advection reuse; nnow/nnew swap between substeps but not after the last.
- substep_array_call(stage, substep, inputs, outputs, dt)¶
One stage (0 = predictor, 1 = corrector) of one substep, Δτ =
dt.Data flows through the component-private icon4py states (
communicates_internally);inputs/outputsare the step-level boundary buffers, ingested/egressed byarray_call().
- stage_array_call(stage, inputs, outputs, dt)¶
Degenerate single-substep form of
substep_array_call()(S04 hook).Not used by the ICON orchestration (
array_callalways substeps); provided so the frozen S04 subclass contract is complete.
- restart_state()¶
Both prognostic time levels + the velocity-advection carry (SPEC S12).
- load_restart_state(restart)¶
Restore the full private-state schema (strict: all keys, no extras).
- functional_state()¶
The restart schema as PropertySpecs (F-tier declaration; consumption is P6).
- Return type:
- icon_sc.icon.components.dycore.icon_namelist_origins(config)¶
Field name -> ICON namelist origin, from the dataclass metadata annotations.
Works for any origin-annotated config dataclass (
NonhydroConfig, S13’sDiffusionConfig, …) — a backward-compatible widening of the S12 signature (declared in the S13 STATUS).
HorizontalDiffusion(Stepper) — icon4py Diffusion hosted on ICON-sc (S13).
The ICON horizontal diffusion granule (Smagorinsky + 4th-order background,
mo_nh_diffusion.f90 / hdiff_order=5) as one ICON-sc component, following the
S12 hosting policy (wrap-don’t-rewrite, architecture §4.4): the ~16 stencil programs
stay icon4py granule internals (REFERENCES.lock icon4py-diffusion); ICON-sc invokes
the granule’s single public entry run(diagnostic_state, prognostic_state, dtime,
initial_run) exactly the way icon4py’s own integration tests and driver do
(REFERENCES.lock icon4py-diffusion-tests, icon4py-driver-jw).
Boundary: prognostics in/out on their locations — icon:normal_wind (edgexK),
upward_air_velocity_on_interface_levels (cellxK+1), icon:exner_function and
icon:virtual_potential_temperature (cellxK). air_density is deliberately not
part of the boundary: the granule never reads or writes rho (its PrognosticState
slot is satisfied by a private zero field). One __call__ = one diffusion step over
the full Δt — ICON applies diffusion once per physics timestep, after the dynamics
substepping (driver _integrate_one_time_step; mo_nh_stepping.f90).
ICON’s initial stabilization run (“for real-data runs, perform an extra diffusion
call before the first time step”) is exposed as initial_stabilization() — an
extra, explicitly requested call that uses the granule’s initial_run=True special
coefficients; it never happens implicitly.
The turbulence-coupling diagnostics the granule accumulates (hdef_ic, div_ic,
dwdx, dwdy; consumed by NWP turbulence, a P3 component) are component-private
state behind the restart/functional-state protocols (§4.5), zero-initialized at
construction exactly like the icon4py driver does.
- class icon_sc.icon.components.diffusion.DiffusionConfig(diffusion_type=5, hdiff_w=True, hdiff_vn=True, hdiff_temp=True, hdiff_smag_w=False, type_vn_diffu=1, smag_3d=False, type_t_diffu=2, hdiff_efdt_ratio=36.0, hdiff_w_efdt_ratio=15.0, smagorinski_scaling_factor=0.015, smagorinski_scaling_factor2=0.07137250670656087, smagorinski_scaling_factor3=0.0, smagorinski_scaling_factor4=1.0, smagorinski_scaling_height=32500.0, smagorinski_scaling_height2=60686.25335328044, smagorinski_scaling_height3=50000.0, smagorinski_scaling_height4=90000.0, ndyn_substeps=5, zdiffu_t=True, velocity_boundary_diffusion_denom=200.0, temperature_boundary_diffusion_denom=135.0, max_nudging_coefficient=0.1, shear_type=0, iforcing=0, a_hshr=1.0, loutshs=False)¶
Horizontal-diffusion configuration (SPEC S13: mirrors icon4py
DiffusionConfig).Every field carries an
icon_namelist_originannotation (machine-readable viaicon_namelist_origins()). Defaults are icon4py v0.2.0 defaults, which transcribe the ICON Fortran namelist defaults (REFERENCES.lockicon4py-diffusion). The icon4py granule accepts only the operational slice (diffusion_type=5,type_vn_diffu=1,type_t_diffu=2, no Smagorinsky-w, no 3d Smagorinsky,shear_type in (0, 1, 2));to_icon4py()re-runs its validation, so an unsupported knob fails at component construction.- Parameters:
diffusion_type (int)
hdiff_w (bool)
hdiff_vn (bool)
hdiff_temp (bool)
hdiff_smag_w (bool)
type_vn_diffu (int)
smag_3d (bool)
type_t_diffu (int)
hdiff_efdt_ratio (float)
hdiff_w_efdt_ratio (float)
smagorinski_scaling_factor (float)
smagorinski_scaling_factor2 (float)
smagorinski_scaling_factor3 (float)
smagorinski_scaling_factor4 (float)
smagorinski_scaling_height (float)
smagorinski_scaling_height2 (float)
smagorinski_scaling_height3 (float)
smagorinski_scaling_height4 (float)
ndyn_substeps (int)
zdiffu_t (bool)
velocity_boundary_diffusion_denom (float)
temperature_boundary_diffusion_denom (float)
max_nudging_coefficient (float)
shear_type (int)
iforcing (int)
a_hshr (float)
loutshs (bool)
- ndyn_substeps: int = 5¶
The diffusion coefficients scale with the substep ratio (must equal the dycore’s).
- max_nudging_coefficient: float = 0.1¶
icon4py default = DEFAULT_DYNAMICS_TO_PHYSICS_TIMESTEP_RATIO(5) * 0.02.
- to_icon4py()¶
The icon4py
DiffusionConfig(runs the granule’s own slice validation).- Return type:
- class icon_sc.icon.components.diffusion.HorizontalDiffusion(grid, vgrid, static, cfg=None, ctx=None, *, edge_geometry=None, cell_geometry=None, exchange=None, name=None)¶
The ICON horizontal diffusion as a ICON-sc
Stepper(SPEC S13).HorizontalDiffusion(grid, vgrid, static, cfg, ctx, *, ...)— constructor mirrors the S12NonhydroSolvershape (architecture §5.1 sketchesHorizontalDiffusion(grid, static, cfg.diffusion, ctx); the hosted granule additionally requires the vertical grid for its Smagorinsky enhancement profile, sovgridsits in the S12 position):grid: aicon_sc.icon.grid.IconGrid(production path — geometry derived from it) or a raw icon4pyIconGrid(host-grid path, geometry passed explicitly — how the parity tests mirror upstream);vgrid: aicon_sc.icon.grid.VerticalGridor a raw icon4pyVerticalGrid;static: mapping of theSTATIC_FIELDSregistry names to S11 static-state DataArrays (metrics(...) | interpolation(...)) or ready icon4py fields (savepoint parity path — zero conversion);cfg:DiffusionConfig.
One
__call__advances one full Δt (diffusion runs once per physics timestep, after the dynamics substepping — icon4py driver order). The granule mutates its state in place; ICON-sc ingests/egresses the boundary buffers around it (communicates_internally=True: halo exchanges happen inside the granule).- Parameters:
grid (IconGrid | Any)
vgrid (VerticalGrid | Any)
static (Mapping[str, Any])
cfg (DiffusionConfig | None)
ctx (ComputeContext | None)
edge_geometry (Any | None)
cell_geometry (Any | None)
exchange (Any | None)
name (str | None)
- communicates_internally: ClassVar[bool] = True¶
halo exchanges happen inside the hosted granule.
- Type:
§4.3 table
- initial_stabilization(state, timestep, *, out=None)¶
ICON’s extra pre-timeloop diffusion call (
linit=.TRUE.).“For real-data runs, perform an extra diffusion call before the first time step because no other filtering of the interpolated velocity field is done” (icon4py
Diffusion.rundocstring). Uses the granule’sinitial_run=Truecoefficients (setup_fields_for_initial_step,smag_offset=0); never invoked implicitly — the caller decides (driverapply_initial_stabilization).
- array_call(inputs, outputs, timestep)¶
One diffusion step over the full Δt (granule
run, in-place).
- restart_state()¶
The turbulence-coupling diagnostics the granule accumulates (SPEC S13).
- load_restart_state(restart)¶
Restore the full private-state schema (strict: all keys, no extras).
- functional_state()¶
The restart schema as PropertySpecs (F-tier declaration; consumption is P6).
- Return type:
- icon_sc.icon.components.diffusion.icon_namelist_origins(config)¶
Field name -> ICON namelist origin, from the dataclass metadata annotations.
Works for any origin-annotated config dataclass (
NonhydroConfig, S13’sDiffusionConfig, …) — a backward-compatible widening of the S12 signature (declared in the S13 STATUS).
Idealized forcing components for column presets (S09).
The S09 SCM composition exercises the slow-tendency bus end-to-end before a real
dynamical core exists to consume it (architecture §4.2 “the bus, reframed”; SPEC
S09 in-scope): a PrescribedCooling slow process publishes a
piecewise-constant temperature tendency into the icon:ddt_temperature_slow
slot (seeded for exactly this purpose in icon_sc.icon.names, S06), and a
trivial ApplySlowTendencies stepper stands in for the consumer the
tutorial describes (§3.7.2, REFERENCES.lock icon-tutorial-2025: slow-physics
tendencies are “kept constant between two successive calls” and act as forcing
terms integrated inside the dynamical core / tracer transport — here, at column
scale, a forward-Euler application is that integration).
PrescribedCooling is analytic (PLAN S09 item 1): Newtonian relaxation of the
temperature toward an offset ICON reference-atmosphere profile,
dT/dt = (T_eq(z) - T) / tau, T_eq(z) = T_ref(z) - offset,
with T_ref the decaying-isothermal reference temperature mined in S06
(mo_vertical_grid.f90; icon_sc.icon.grid.vertical.reference_temperature()).
The shape is the standard idealized radiative-cooling stand-in (relaxation-type
forcing); the default timescale/offset are test-fixture magnitudes chosen at
typical tropospheric cooling rates (~1-5 K/day), not mined scientific constants
(S06 moist_test_column precedent).
Neither component is an ICON scheme; real slow physics (radiation, convection, …) arrives in P3, the real consumer (the dycore’s slow port) in S12.
- class icon_sc.icon.components.idealized.ApplySlowTendencies(*, ctx=None, name=None)¶
Trivial bus consumer: forward-Euler application of the slow T tendency.
Stands in for the dynamical core’s slow-tendency input port (architecture §4.2/§4.3) until S12:
T_new = T + Δt · ddt_temperature_slow, with the slot value held piecewise-constant by the publisher’sCallingFrequencywrapper. Declared as an input (not recomputed), so the S04 bus checker can verify the publish/consume wiring of the preset.- Parameters:
ctx (ComputeContext | None)
name (str | None)
- 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.
- class icon_sc.icon.components.idealized.PrescribedCooling(cfg=None, ctx=None, *, name=None)¶
Analytic radiative-cooling stand-in publishing to the tendency bus (SPEC S09).
dT/dt = (T_eq(z) - T)/tauwithT_eq(z) = T_ref(z) - offset(module docstring). The tendency is published under the bus-slot nameicon:ddt_temperature_slow(canonical unitsK s-1), not as a plainair_temperaturetendency: slow-process output rides the §4.2 bus and is consumed by exactly one consumer, checked at composition time bySlowTendencyBus.- Parameters:
cfg (PrescribedCoolingConfig | None)
ctx (ComputeContext | None)
name (str | None)
- 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.
- functional_call(inputs, params, *, dt)¶
Pure evaluation of the relaxation tendency (§8.6
native; S10).reference_temperatureis array-namespace generic (S06), so the same formula traces under jax unchanged — one shared source for both tiers.
- class icon_sc.icon.components.idealized.PrescribedCoolingConfig(relaxation_timescale=datetime.timedelta(days=1), equilibrium_offset=5.0)¶
Newtonian-relaxation parameters (test-fixture magnitudes, see module note).