What’s new in v0.2.1#

Added in version v0.2.1.

v0.2.1 is a focused patch release closing the three items that v0.2.0 explicitly deferred — sharded StaticArray runtime slicing, the pre-announced edge-validation warning→error flip, and the compile() advisory-noise cleanup. The first item unblocks MIME’s multi-GPU IBLBMFluidNode sharding, which is load-bearing for the de Boer step-out replication.

Warning

Semver carve-out. v0.2.1 includes one breaking change under strict semver: the edge-validation warning→error flip. This was pre-announced in v0.2.0 release notes and the migration guide; we ship it as a PATCH because (a) the change was published in advance, (b) the migration path is documented (see Edge validation: migration guide (v0.2 → v0.3.0)), and (c) the deprecated *Warning aliases stay importable through v0.2.x. If your CI pins maddening<0.3, expect this change; the aliases themselves are removed in v0.3.

The CHANGELOG entry ([0.2.1] - 2026-05-30 in CHANGELOG.md) has the itemised diff. This page is the narrative summary.

Highlights#

Sharded StaticArray actually slices now (StaticArray(replication="shard"))#

v0.2.0 stored replication="shard" / shard_axis=K as metadata only — GraphManager replicated the full StaticArray to every device regardless of the declaration. v0.2.1 closes the gap: ShardedStencilNode now materialises the per-device slice via jax.device_put + NamedSharding, halo-exchanges it with boundary="edge" (statics don’t evolve in time — periodic wrap would be wrong even when the state uses periodic), and delivers the sliced + padded slab as static_padded[<key>] to SimulationNode.update_padded.

Two new surfaces on SimulationNode:

  • update_padded(..., *, static_padded=None, shard_info=None) — the two new keyword-only optional kwargs. static_padded is {key: halo_padded_slab} for each sharded StaticArray on the inner node; shard_info is {spatial_axis: (global_offset, local_extent)} where global_offset is a traced JAX scalar (lax.axis_index * extent), usable in dynamic_slice but not in Python integer slicing.

  • domain_integral_fields() -> set[str] — declares outputs that are jnp.sum-over-lattice integrals (e.g. drag force / torque from an immersed-boundary node). The wrapper applies lax.psum across every mesh axis after update_padded returns. Default returns set() — pure additive.

Construction-time validation: ShardedStencilNode’s __init__ checks that each sharded StaticArray’s shard_axis matches one of the spatial axes the wrapper actually shards (via axis_map.values()), and that any node declaring sharded statics has the static_padded kwarg on its update_padded signature. Legacy v0.2-era nodes without sharded statics keep working — the wrapper skips passing the new kwargs to signatures that wouldn’t accept them.

Acceptance test in tests/cloud/multigpu/test_sharded_static_data.py covers bit-compat sharded-vs-unsharded, 50-step multi-step convergence, construction-time validation, and shard_info delivery.

Edge-validation warnings → errors (breaking — semver carve-out)#

GraphManager.compile() now raises :class:ExceptionGroup of EdgeValidationError subclasses on shape/dtype mismatches that v0.2.0 surfaced as warnings:

  • ShapeMismatchError

  • DtypeMismatchError

UnitMismatchWarning is unchanged — units are advisory by contract.

All mismatches detected during a single compile() call are aggregated into one :class:ExceptionGroup so the lab-newcomer “see every problem at once” property is preserved. Catch via except* on Python 3.11+:

from maddening.warnings import ShapeMismatchError, DtypeMismatchError

try:
    gm.compile()
except* ShapeMismatchError as eg:
    for err in eg.exceptions:
        ...
except* DtypeMismatchError as eg:
    ...

…or via explicit iteration on Python 3.10 (the exceptiongroup backport is now a base dependency for that lane). Full migration guide at Edge validation: migration guide (v0.2 → v0.3.0).

The deprecated ShapeMismatchWarning / DtypeMismatchWarning / EdgeValidationWarning classes remain importable through v0.2.x so existing pytest.warns(...) references resolve cleanly (nothing in MADDENING emits them as of v0.2.1). v0.3 removes the aliases.

compile() advisory-noise cleanup#

Two compile-time advisories that v0.2.0 emitted as UserWarning were noise more often than signal:

  • Single-node disconnected warning — fired for every one-node graph (the quickstart shape; every isolated unit test). v0.2.1 gates the advisory on len(node_names) > 1; a one-node graph is legitimately edge-free.

  • Uncovered cycle “WARNING:” prefix — back-edge staggering handles cycles correctly, and the warning was re-tripping downstream filterwarnings=["error"] configs. v0.2.1 demotes the message: validate() now emits an INFO:-prefixed entry, and the same line goes through logging.getLogger("maddening.core.graph_manager").info(...).

validate()’s issue list still surfaces both (programmatic inspection unchanged). Only the warning bubble is gone.

Migration playbook#

If you have v0.2.0 code:

  1. Edges that previously warned at compile() now raise. Either fix the mismatch or add a transform=. See Edge validation: migration guide (v0.2 → v0.3.0) for the full playbook — including except* (3.11+) and explicit-iteration (3.10) catch patterns, and how pytest.warns(ShapeMismatchWarning) updates to pytest.raises(ExceptionGroup).

  2. Sharded StaticArray nodes need extended update_padded. If your node declares any StaticArray(replication="shard") in its static_data, its update_padded must accept the new keyword-only static_padded=None kwarg or ShardedStencilNode refuses to construct. Add the kwarg (and shard_info=None while you’re there) — the wrapper enforces this at init time with a clear error.

  3. CI configs ignoring the deprecated *Warning classes can drop those lines (the warnings no longer fire) — see the migration guide’s “I’m running… and don’t want CI to fail” section.

For MIME consumers specifically: the IBLBMFluidNode port to sharded static_data (the de Boer M1 unblock) is a separate workstream on the MIME side; the MADDENING infrastructure is what shipped here.

New optional dependencies#

Extra

Pulls in

For

(base)

exceptiongroup; python_version < "3.11"

The 3.10 backport of ExceptionGroup used by compile()’s validation raise.

What’s still in flight#

See V0.2_PROGRESS.md in the repo root. Everything previously deferred to v0.2.1 has shipped; the remaining v0.3+ items (the deprecation tail, requires_halo hard-removal, ShardedNode alias removal, *Warning alias removal, and the new substantive v0.3 work — FMI 3.0 substrate, @stability audit, USD live-stage consolidation, IFT solver merge) are tracked outside the repo in the v0.3.0 plan.