refactor(common): EdgeParams as a dataclass with explicit optional members - #1462
Conversation
…mbers EdgeParams was a hand-written class whose attribute annotations did not say which members a construction path may leave unset, and were wrong where it mattered: `primal_edge_lengths` and `dual_edge_lengths` are annotated as fields but are None in every path except the two diffusion tests. - EdgeParams becomes a frozen keyword-only dataclass. The six x/y pairs the old __init__ folded into tuples are now tuple fields, so the constructor and the attributes agree; attribute names and every consumer are unchanged. - `| None` now marks exactly the members some source cannot supply: `primal_edge_lengths`, `dual_edge_lengths` and `edge_cell_distances`, the last of which ICON's `grid_init` does not pass. CellParams is tightened the same way: only `mean_cell_area` is optional. - `edge_cell_distances` is new, from t_grid_edges%edge_cell_length. The savepoint and the metrics/geometry factory fill it; the Fortran bindings cannot. - The bindings comparison reads optionality off the annotation, so a member absent on one side is skipped only where the class says it may be, and every other member is still compared. Also fixes a copy-paste in two benchmark setups: `dual_normal_vert_y` was wired to EDGE_NORMAL_VERTEX_V rather than EDGE_TANGENT_VERTEX_V. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01QVSWPQauF9gNjADtuSTjxF
CellParams moves to the attribute-docstring style EdgeParams uses, gains a class docstring, and cites the ICON source of `mean_cell_area`. The convention sentence is stated once per class, so the per-field note on `mean_cell_area` goes. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01QVSWPQauF9gNjADtuSTjxF
ICON allocates `edge_vert_length(nproma, nblks_e, 2)` (mo_alloc_patches.f90 l.1026) and the grid file carries `edge_vert_distance` as (2, num_edges), so the savepoint holds two values per edge, not four. `E2C2VDim` is the 4-wide dimension. The label had no effect on the values, which is why `test_edge_vertex_distance` passes either way, but it contradicted the metadata of the attribute the field is registered under: `geometry_attributes.EDGE_VERTEX_DISTANCE` declares `(EdgeDim, E2VDim)`, and `common/tests/common/fixtures.py` feeds this accessor straight into `GridGeometry` under that name. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01QVSWPQauF9gNjADtuSTjxF
| defined in ICON in mo_model_domain.f90:t_grid_edges%dual_edge_length | ||
| """ | ||
|
|
||
| edge_cell_distances: gtx.Field[[dims.EdgeDim, dims.E2CDim], float] | None = None |
There was a problem hiding this comment.
this is added in preparation for tmx
| def edge_vert_length(self): | ||
| """length of edge midpoint to vertex""" | ||
| return self._get_field("edge_vert_length", dims.EdgeDim, dims.E2C2VDim) | ||
| return self._get_field("edge_vert_length", dims.EdgeDim, dims.E2VDim) |
There was a problem hiding this comment.
drive-by fix unrelated to this PR
There was a problem hiding this comment.
It seems that no one caught this because it is only used in cell_aw_verts, and only first two indices are used.
|
cscs-ci run default |
|
cscs-ci run default |
| defined in ICON in mo_model_domain.f90:t_grid_edges%dual_edge_length | ||
| """ | ||
|
|
||
| edge_cell_distances: gtx.Field[[dims.EdgeDim, dims.E2CDim], float] | None = None |
- bindings utils: keep only what the code does not say. For `_optional_fields` that is why 'get_type_hints' is not used; the rest of both comments was restating the lines below them. - states: drop the optional-member sentence from both class docstrings, and give `edge_cell_distances` the blank line before its ICON reference that every other member has. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01QVSWPQauF9gNjADtuSTjxF
|
When developing, you can test your changes on CSCS CI before merge with the You can pass options to override pipeline variables, for example:
Avoid running the pipeline for all tests when you are developing. Available options are:
For each option, Multiple values can be given to each option with See The Merging Once your PR is approved and ready for merging, add it to the merge queue. The Optional Tests To run benchmarks you can use:
For more detailed information please look at CI in the EXCLAIM universe. |
| def edge_vert_length(self): | ||
| """length of edge midpoint to vertex""" | ||
| return self._get_field("edge_vert_length", dims.EdgeDim, dims.E2C2VDim) | ||
| return self._get_field("edge_vert_length", dims.EdgeDim, dims.E2VDim) |
| def edge_vert_length(self): | ||
| """length of edge midpoint to vertex""" | ||
| return self._get_field("edge_vert_length", dims.EdgeDim, dims.E2C2VDim) | ||
| return self._get_field("edge_vert_length", dims.EdgeDim, dims.E2VDim) |
There was a problem hiding this comment.
It seems that no one caught this because it is only used in cell_aw_verts, and only first two indices are used.
`grid_states.EdgeParams` carries it as `edge_cell_distances` since #1462, so the granule's metric state no longer has to. `from_sources` needs only the metrics source now. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01QVSWPQauF9gNjADtuSTjxF
Brings in #1462, which makes CellParams.area required, ahead of binding it in the VelocityAdvection constructor. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017s66WxborSWhPes8eHxiSF
Cell areas are static geometry. Bind them with the other constant arguments that setup_program binds, next to area_edge, instead of passing them to both run methods on every call. The two asserts that existed only to narrow the Optional type of those arguments go as well: CellParams.area has been required since #1462, which the previous commit merged in. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017s66WxborSWhPes8eHxiSF
EdgeParamsis a hand-written class whose attribute annotations do not say which members a construction path may leave unset.What changes
EdgeParamsbecomes dataclass.| Nonenow means "some source cannot supply this"edge_cell_distancesis new, fromt_grid_edges%edge_cell_length. It's not needed required by dycore/diffusion, therefore not passed in via Fortran bindings and we make it optional in this PR. Alternative could be to still pass it from Fortran, but since the Fortran array has wrong layout it would require a copy.Why now
In #1457 it was originally added to tmx directly instead of EdgeParams, therefore we extracted this refactoring in preparation for that PR.