Skip to content

Create coordinate bounds on the internal-calculation path (WCRP ATTR001) - #647

Merged
rbeucher merged 1 commit into
mainfrom
areacella_missing_bounds_issue
Aug 24, 2026
Merged

Create coordinate bounds on the internal-calculation path (WCRP ATTR001)#647
rbeucher merged 1 commit into
mainfrom
areacella_missing_bounds_issue

Conversation

@rhaegar325

Copy link
Copy Markdown
Collaborator

areacella was written with no lat_bnds/lon_bnds and no bounds attribute on either coordinate, failing two weight-3 WCRP checks:

[ATTR001] Required variable 'lat' attribute 'bounds' is missing.
[ATTR001] Required variable 'lon' attribute 'bounds' is missing.

The missing attribute was a symptom: the bounds variables were never created. select_and_process_variables returns early for calculation.type == "internal", skipping the
_get_required_bounds_variables / calculate_missing_bounds_variables pair that every other path reaches. The vocabulary was already correct — asked directly it reports must_have_bounds='yes' for both axes and bnds_required = ['lon_bnds', 'lat_bnds'] — the answer just had no consumer. reorder() already reserves slots for lat_bnds/lon_bnds, so their absence was the anomaly, not the design.

Separately, calculate_areacella builds a full (145, 2) lat_bnds array to derive the cell areas and then discards it, and never computes lon_bnds at all. Rather than return those, call the existing bounds machinery before the early return: it fixes the class rather than the one variable, and calculate_longitude_bounds already unwraps the 0°-crossing first cell (#635), so no new bounds arithmetic is introduced.

areacella is currently the only internal-calculation entry in the ESM1-5 and ESM1-6 mappings. ocean.py and sea_ice.py carry the same early return, but have no internal variables to exercise it; left alone rather than changing untestable paths.

Verified end to end: lat_bnds/lon_bnds are now bit-identical to orog's on the shared N96 grid (first lon cell [-0.9375, 0.9375], not the wrapped form), both ATTR001 bounds checks go [0, 1] -> [1, 1], and the two [VAR012] bounds-consistency checks — which could not run before — pass. orog output is byte-for-byte unchanged.

`areacella` was written with no `lat_bnds`/`lon_bnds` and no `bounds`
attribute on either coordinate, failing two weight-3 WCRP checks:

    [ATTR001] Required variable 'lat' attribute 'bounds' is missing.
    [ATTR001] Required variable 'lon' attribute 'bounds' is missing.

The missing attribute was a symptom: the bounds variables were never
created. `select_and_process_variables` returns early for
`calculation.type == "internal"`, skipping the
`_get_required_bounds_variables` / `calculate_missing_bounds_variables`
pair that every other path reaches. The vocabulary was already correct —
asked directly it reports `must_have_bounds='yes'` for both axes and
`bnds_required = ['lon_bnds', 'lat_bnds']` — the answer just had no
consumer. `reorder()` already reserves slots for `lat_bnds`/`lon_bnds`,
so their absence was the anomaly, not the design.

Separately, `calculate_areacella` builds a full (145, 2) `lat_bnds` array
to derive the cell areas and then discards it, and never computes
`lon_bnds` at all. Rather than return those, call the existing bounds
machinery before the early return: it fixes the class rather than the one
variable, and `calculate_longitude_bounds` already unwraps the 0°-crossing
first cell (#635), so no new bounds arithmetic is introduced.

`areacella` is currently the only internal-calculation entry in the
ESM1-5 and ESM1-6 mappings. `ocean.py` and `sea_ice.py` carry the same
early return, but have no internal variables to exercise it; left alone
rather than changing untestable paths.

Verified end to end: `lat_bnds`/`lon_bnds` are now bit-identical to
`orog`'s on the shared N96 grid (first lon cell `[-0.9375, 0.9375]`, not
the wrapped form), both ATTR001 bounds checks go `[0, 1]` -> `[1, 1]`, and
the two `[VAR012]` bounds-consistency checks — which could not run before —
pass. `orog` output is byte-for-byte unchanged.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@codecov

codecov Bot commented Aug 24, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 77.3%. Comparing base (9d78ebd) to head (4a37c51).

Additional details and impacted files
@@           Coverage Diff           @@
##            main    #647     +/-   ##
=======================================
+ Coverage   77.2%   77.3%   +0.1%     
=======================================
  Files         40      40             
  Lines       8522    8524      +2     
  Branches    1593    1593             
=======================================
+ Hits        6583    6590      +7     
+ Misses      1610    1604      -6     
- Partials     329     330      +1     
Flag Coverage Δ
unit 77.3% <100.0%> (+0.1%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@rbeucher
rbeucher merged commit b5d3b16 into main Aug 24, 2026
4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants