idea[havogt]: align staggering with the shipped shift convention - #28
Merged
Conversation
A shift names the dimension the *result* lives on (the rule unstructured shifts already follow), not the field's own; staggered point i sits at i - 1/2. Flips the Staggered[D] overloads, the runtime index rule, the prototype and its static/runtime checks. Also corrects three claims in Part II: gtfn is not unaffected (it needs _add_staggered_aliases), the I + 0.7 gap is mypy-only, and check_dims (a dim and its counterpart may not co-occur) is not statically expressible.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Part II of
dimension-generic-fieldsspelled a staggering shift asa(I + 1/2)for
a: Field[Dims[I]]— naming the dimension the field is on. gt4py asshipped (#2667, ADR 0026) does the opposite, and the proposal's spelling is not
a different result there but a hard error:
The implementation is right and the proposal moves.
Why: a shift is precomposition
A field is a map
f: I → value, a connectivity a mapφ: D → I; applying oneis
f ∘ φ, a field onD. The connectivity's domain is therefore theresult's dimension and its codomain the field's — forced by composition, not
chosen. The index expression is written in the result's index space and must
evaluate to an index of the field's own dimension, which is exactly what the
in-tree test comment states:
a(IHalfDim + 0.5) # always pass an I-index to an IField.The unstructured connectivities already encode this in their names —
V2Eis"for each Vertex, its Edges", domain
Vertex, codomainEdge, so it consumesan edge field and produces a vertex field. Staggering is merely the first place
the convention becomes observable, because integer Cartesian shifts have
domain == codomain.
§4.2 records the discarded alternative (source-naming) with its one real
advantage and the reason it loses: it gives no rule for
a(E2C[0]), sounstructured shifts would have to become the exception.
What changed
a(Staggered[I] + 1/2)), the positionconvention becomes the shipped one (staggered point
iati - 1/2), and theindex rule is restated as
ceilwhen the shift names an unstaggered dimension/
floorwhen it names a staggered one — keyed on the result's dimension,which is what
connectivity_for_cartesian_shiftalready implements.typed_dimensions.py,static_checks.py,static_errors.py,test_typed_dimensions.py): overloads, runtime rule and every expectationflipped. 19/19 pass, mypy clean, the error oracle fires on exactly the
marked lines.
dualis now a typed function. This is the part that cost more thanswapping two type arguments: because the shift names the result grid, a
dual-generic body cannot shift on its own dimension and needs
dual(dim)—the type-level counterpart of gt4py's value-level
flip_staggered. It getsthe same overload pair, so it stays precise under a dimension variable
(
to_staggeredinstatic_checks.py).Three corrections found while verifying
_add_staggered_aliases(itir_to_gtfn_ir.py), emitting the staggered tag asa C++
usingalias of its base tag, because a gtfn shift can offset a SID butcannot rename its axis. The FOAST bullet also had
source/targetinverted; it now matches the shipped
source=conn.codomain, target=(conn.domain_dim,).I + 0.7gap is mypy-only, not runtime-only: the DSL already rejectsit at FOAST time with a
DSLErrorand a hint.check_dimsis not statically expressible — a dimension and its staggeredcounterpart may not co-occur, but
Field[Dims[I, Staggered[I]]]stayswritable for mypy. Added as a known gap.
Incidental
The prototype's
mypy.inipinnedpython_version = 3.10, which numpy's stubsnow reject outright, so both mypy-oracle tests were failing on
mainforreasons unrelated to any of this. Bumped to 3.12 (gt4py has dropped 3.10/3.11).
With that fixed, mypy 2.3 reproduces the metaclass quirk and its suppression
exactly as documented — §10 risk 1's "could break on a mypy upgrade" has not
materialised; pyright remains untested.
.gitignoregained__pycache__/,since the vendored prototypes are runnable.
Note for merge order
Touches
dimension-generic-fields.mdalongside #27 (which stubs out §3). Theedits are in disjoint sections; the only adjacency is the
> **Prototypes**:block near the top, where #27 inserts a note and this branch edits the mypy
version on the following line. Whichever lands second may need a trivial rebase.