Skip to content

Add UM mesh generation script and support differing input/output meshes in generate_rof_weights.py - #154

Open
anton-seaice wants to merge 7 commits into
mainfrom
142-part4
Open

anton-seaice wants to merge 7 commits into
mainfrom
142-part4

Conversation

@anton-seaice

Copy link
Copy Markdown
Contributor

Summary

  • Adds mesh_generation/generate_um_mesh.py to generate an ESMF mesh file for a UM atmosphere grid (n96/n96e style resolutions), adapted from create_landfrac.py in land-fraction-ancillary-suite. Related to Update drof weights to include spreading #142.
  • Updates generate_rof_weights.py to support a source (runoff-providing) mesh that differs from the destination mesh, via a new optional input_mesh_filename parameter. Default behaviour (input mesh == output mesh) is unchanged.
  • Adds pytest coverage: test/test_mesh/test_um_mesh.py for the new UM mesh script, and extends test/test_mesh/test_rof_weights.py to cover both same-mesh and differing-mesh (UM) cases, including different runoff placements on the source mesh (all on land, all on ocean, touching/not touching land, etc).

Test plan

  • black formatting passes
  • Standalone verification scripts confirm volume conservation to ~1e-16 relative error across same-mesh/different-mesh and spread/no-spread scenarios
  • pytest test/test_mesh/test_um_mesh.py and pytest test/test_mesh/test_rof_weights.py collect and run (previously blocked by an environment-level esmpy/regionmask import-order segfault in this session's shell, fixed by reordering imports)
  • CI checks on this PR

🤖 Generated with Claude Code

Part 4 of issue #142: move create_um_mesh() out of
land-fraction-ancillary-suite's create_landfrac.py into om3-scripts as a
standalone script, so it can be reused without the rest of that repo's
land-fraction-specific regridding. The core element/node/connectivity
logic is unchanged; wrapped with this repo's usual CLI/provenance
conventions. Includes pytest coverage of resolution parsing, mesh
geometry (dims, element types, total sphere area) and esmpy loadability.
Add an optional input_mesh_filename (CLI: --input_mesh_filename), so the
source (runoff-providing, e.g. a UM atmosphere mesh) and destination
(masked ocean) meshes can differ. Defaults to mesh_filename, preserving
existing default behaviour exactly.

Several places previously assumed source and destination were the same
mesh (only true by coincidence, since both were the same file): the
source cell mask/coordinates, the nospread_i/spread_i and col index
arrays, and - most importantly - the per-cell area used to scale weights
for volume conservation, which now correctly distinguishes source area
from destination area.

Verified with a standalone numerical check (esmpy-loaded meshes, exact
volume conservation to machine precision) for same-mesh and differing
-mesh cases, with and without spreading, since the existing pytest file
currently segfaults on this login node due to an unrelated
regionmask/cupy import conflict (reproduced on the pre-change file too).
Covers UM-style source meshes alongside the existing same-resolution case,
including different runoff placements on the source mesh. Also fixes a bug
where source_area was left as the input_mesh_filename string instead of
mesh_area(self.input_mesh_filename).
@anton-seaice anton-seaice self-assigned this Aug 17, 2026
@anton-seaice
anton-seaice marked this pull request as ready for review August 17, 2026 04:50
@anton-seaice

Copy link
Copy Markdown
Contributor Author

Should be ready to go @kieranricardo

Line wraps in generate_rof_weights.py bring it under black's 88-char width
(comments/docstrings/argparse strings aren't auto-wrapped by black).

mesh_in_um was too coarse (nlat=10, nlon=16) for any cell to fall within
SRC_DIST of a real SPREAD_POINTS location, so spread=True never actually
triggered spreading for that mesh in CI. Bumped to nlat=24, nlon=32 (n16),
verified to reliably intersect a spread point (Lena) and exercise the
spreading code path.
…read points

n16 (nlat=24, nlon=32) only had a single cell matching a SPREAD_POINTS location,
and it happened to be classified as land in the synthetic mask - so "Ocean" and
"Ocean_Touching_Land" test data never deposited anything there, and the "proof
spreading occurred" assertion failed for those cases in CI. n42 (nlat=63,
nlon=84) has multiple matching cells including both land- and ocean-classified
ones, verified against all 6 data placements with spread=True.

@kieranricardo kieranricardo left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good! Can SRC_DIST, SPREAD_N, FOLD, and SPREAD_POINTS be configurable? We'll definitely want to change at least SPREAD_POINTS for the UM

Comment thread mesh_generation/generate_rof_weights.py Outdated
Comment thread mesh_generation/generate_rof_weights.py Outdated
@anton-seaice

Copy link
Copy Markdown
Contributor Author

My naive hope is we can just settle on a list of points that works for both models.

With spread points, it's too long to make a command line input, so then there needs to be an input file of points. And then there needs to be a way to keep track of the input file, so they may as well just be written in the script.

@kieranricardo

Copy link
Copy Markdown

sounds good re spread points, especially if SRC_DIST is configurable (UM resolution is like 1.5 degrees) then we can probably come with a list that works for both.

Co-authored-by: Kieran Ricardo <kieran.ricardo@anu.edu.au>
@anton-seaice

Copy link
Copy Markdown
Contributor Author

What about making an overall option (e.g. model-config) and then that can be OM3, or CM3 (possibly including a resolution) and set all of SRC_DIST, SPREAD_N, FOLD, and SPREAD_POINTS ?

Just thinking the list of input arguments is already long, is continueing to make it longer better ?

@kieranricardo

Copy link
Copy Markdown

model-config option sounds good to me

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