Easy regional & variable-resolution mesh creation#15
Open
daniloceano wants to merge 10 commits into
Open
Conversation
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- setup_environment.sh: stop inferring env existence from 'conda activate's exit code (which gives a misleading "Couldn't find the environment" when the env exists but a transient activate returns non-zero). Now: ensure the 'conda' shell function is loaded (source conda.sh if only the binary is on PATH), check the env in 'conda env list', then activate. Clearer not-found message. - install_conda_environment.sh: add '#!/usr/bin/env bash' shebang. It uses bash-only features (BASH_SOURCE, '[ == ]'); running it with sh/dash failed with "Bad substitution" / "unexpected operator" and left SCRIPT_DIR empty. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Make it much easier for non-specialists to build MPAS-Atmosphere meshes,
especially regional (limited-area) ones.
New - create_regional_grid.py: one command builds a true regional mesh.
It generates a global locally-refined mesh and cuts out the area of
interest with the NCAR MPAS-Limited-Area tool. Supports circle, ellipse,
box and custom-polygon regions. A smart-transition default keeps the whole
kept domain (interior + the 7-cell relaxation belt) at the target spacing
while discarding the coarse transition outside the cut, minimising grid
points that are generated but never used.
Shared library (usp-utils/libs/py):
- jigsaw_util.build_global_mesh(): the jigsaw -> NetCDF -> MPAS pipeline,
extracted so the global and regional scripts reuse it without
duplicating code.
- jigsaw_util.plot_resolution()/resolve_plot_path(): optional cartopy
quick-look plot of mesh resolution (coastlines + country borders, plus
state borders for regional), shared by both scripts.
- regional_util.py: region-spec ("points file") writers (circle/ellipse/
custom) and the limited-area cut wrapper.
create_spherical_grid.py: refactored into a thin CLI that calls
build_global_mesh. Same grid options and behaviour, with two improvements:
the old blocking interactive plot is gone (-p now saves a PNG next to the
grid), and a leftover debug print was removed.
Docs/tooling:
- grid_creation_scripts/README.md: global vs regional, every flag, and
examples for all region shapes.
- install_limited_area.sh: one-shot installer for the MPAS-Limited-Area
dependency (upstream ships no setup.py, so pip-from-URL does not work).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Add a "Partitioning for parallel runs" section explaining how to split the mesh graph.info with gpmetis (METIS) for both global and regional meshes, plus the one-time conda-forge install. Note gpmetis in the env setup list. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Document the higher-quality partitioning command recommended by the MPAS docs and explain what each flag does, noting plain gpmetis still works. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
New draw_region.py opens a cartopy map (coastlines, country and state borders) where left-clicking places polygon vertices; it writes the 'lat, lon' points file that create_regional_grid.py --shape polygon reads (auto-ordered counter-clockwise). Controls: left add, right undo, c clear, enter save, esc quit. Needs an interactive display. README documents it. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
This PR introduces a streamlined workflow for generating MPAS-Atmosphere meshes, adding a one-command regional (limited-area) mesh creator and refactoring global mesh creation into shared utilities. It also adds documentation and helper tooling (plotting, dependency installer, interactive polygon drawing) to make both global variable-resolution and regional workflows easier and more reproducible.
Changes:
- Added
create_regional_grid.py+regional_util.pyto automate the global locally-refined mesh +create_regioncut workflow for true regional meshes. - Refactored global mesh creation into
jigsaw_util.build_global_mesh()and added reusable resolution plotting helpers. - Added end-user docs (
README.md), an installer for MPAS-Limited-Area (install_limited_area.sh), and an interactive polygon drawing tool (draw_region.py).
Reviewed changes
Copilot reviewed 9 out of 10 changed files in this pull request and generated 8 comments.
Show a summary per file
| File | Description |
|---|---|
usp-utils/setup_environment.sh |
Improves conda detection/activation logic for the cgfd-usp-mpas environment. |
usp-utils/pre_proc/grid_creation_scripts/README.md |
New comprehensive documentation for global + regional grid workflows and flags. |
usp-utils/pre_proc/grid_creation_scripts/install_limited_area.sh |
Adds a one-shot installer for the external MPAS-Limited-Area create_region tool. |
usp-utils/pre_proc/grid_creation_scripts/draw_region.py |
Adds an interactive cartopy-based tool to click-draw polygon region files. |
usp-utils/pre_proc/grid_creation_scripts/create_spherical_grid.py |
Refactors global grid CLI into a thin wrapper around shared jigsaw_util code + non-interactive plotting. |
usp-utils/pre_proc/grid_creation_scripts/create_regional_grid.py |
New CLI that builds a locally-refined global mesh then cuts a limited-area region in one command. |
usp-utils/libs/py/regional_util.py |
New helpers to write MPAS-Limited-Area region specs and run create_region. |
usp-utils/libs/py/jigsaw_util.py |
Adds shared build_global_mesh(), cleanup helpers, and a mesh-resolution plotting utility. |
usp-utils/install_conda_environment.sh |
Adds bash shebang and clarifies that the installer must be run with bash. |
.gitignore |
Ignores large WPS geog datasets and stray per-user HOME artifacts that shouldn’t be committed. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Comment on lines
30
to
33
| out_dir=os.getenv('MPAS_ROOT')+"/grids/"+args.output | ||
| out_base=os.path.basename(args.output) | ||
| out_basepath=out_dir+"/"+out_base | ||
| out_filename=out_dir+"/"+out_base+".nc" |
Comment on lines
+387
to
+391
| write_netcdf( | ||
| convert(xarray.open_dataset(out_basepath + '_triangles.nc'), | ||
| dir=out_dir, | ||
| graphInfoFileName=out_basepath + "_graph.info"), | ||
| out_filename) |
Comment on lines
+444
to
+450
| # Approx. resolution from cell area. Meshes here live on a unit sphere | ||
| # (sphere_radius=1), so scale areas up to the real Earth before converting. | ||
| area = ds.variables['areaCell'][:] | ||
| sphere_radius = float(getattr(ds, 'sphere_radius', 1.0)) | ||
| earth_radius_m = 6371220.0 if sphere_radius == 1.0 else 1.0 | ||
| area_km2 = (area / 1.0e6) * earth_radius_m ** 2 | ||
| resolution_km = 2.0 * np.sqrt(area_km2 / np.pi) |
Comment on lines
+371
to
+375
| if level > 11: | ||
| print("Please provide a reasonable refinment level - from 1 to 15." | ||
| " Current value too large ", level) | ||
| print(" Setting level to 4") | ||
| level = 4 |
| if ! python -c "import jigsawpy, mpas_tools" >/dev/null 2>&1; then | ||
| echo "WARNING: 'jigsawpy'/'mpas_tools' not importable in the current python." | ||
| echo " You probably forgot to: conda activate cgfd-usp-mpas" | ||
| read -r -p "Continue anyway? [y/N] " ans |
Comment on lines
+64
to
+65
| echo "==> pip install -e $INSTALL_DIR" | ||
| pip install -e "$INSTALL_DIR" |
Comment on lines
+97
to
+102
| # use a user-given inside point, else the polygon centroid | ||
| if args.clat is not None and args.clon is not None: | ||
| clat, clon = args.clat, args.clon | ||
| else: | ||
| clat, clon = rutil.polygon_center(boundary_points) | ||
| area_radius = rutil.max_radius_km(clat, clon, boundary_points) |
Comment on lines
+9
to
+11
| These scripts run in the `cgfd-usp-mpas` conda env (it provides `jigsawpy`, | ||
| `mpas_tools`, the `jigsaw` binary, `create_region` for regional meshes, and | ||
| `gpmetis` for partitioning — see section 3). |
The env defaults matplotlib to the non-interactive 'Agg' backend, so the window never opened and the tool exited immediately. Now it selects a GUI backend at import (TkAgg then QtAgg), with a --backend override and a clear error if no display is available. Also make the module docstring real (the startup message printed 'None'). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Default view is now the whole world (zoom into any region, not just Brazil). Add mouse-wheel zoom centred on the cursor and guard clicks so navigating with the nav-toolbar pan/zoom does not drop stray vertices. Update the docstring and README controls. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
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.
What this adds
Makes building MPAS-Atmosphere meshes much easier, especially regional (limited-area) ones, and simplifies + improves the existing variable-resolution global workflow and its documentation.
Headline: regional meshes are now trivial
A new
create_regional_grid.pybuilds a true limited-area mesh in one command. Before, a regional mesh meant manually (1) generating a global variable-resolution mesh and (2) running the NCAR MPAS-Limited-Area tool by hand with a hand-written "points file". Now the script does both steps for you:create_region.Advantages
circle,ellipse,box(lat/lon) and custompolygon(from a file).-p(cartopy: coastlines, country and state borders) to visually verify the domain.Also: simpler & better global variable-resolution workflow
The global script still does everything it did (uniform / icosahedral / locally-refined), but the mesh-building logic now lives in a shared, reusable function, so:
Note on
create_spherical_grid.py(changed, on purpose)I refactored it into a thin CLI that calls the new shared
jigsaw_util.build_global_mesh(). The grid options and behaviour are unchanged — anyone already using it keeps the same commands and results. Purpose: avoid duplicating the jigsaw→NetCDF→MPAS pipeline so the regional script can reuse it.Two small, deliberate improvements while there:
-pis now a flag that saves a PNG of the final mesh resolution (next to the grid), instead of opening a blocking interactive window that only worked forlocalrefand hung on headless servers.print.Files
usp-utils/pre_proc/grid_creation_scripts/create_regional_grid.py— regional mesh CLI.usp-utils/libs/py/regional_util.py— region-spec writers + limited-area cut wrapper.usp-utils/pre_proc/grid_creation_scripts/README.md— full docs.usp-utils/pre_proc/grid_creation_scripts/install_limited_area.sh— one-shot installer for the MPAS-Limited-Area dependency (upstream has nosetup.py, sopip install git+urldoes not work).usp-utils/libs/py/jigsaw_util.py— added sharedbuild_global_mesh(),plot_resolution(),resolve_plot_path().usp-utils/pre_proc/grid_creation_scripts/create_spherical_grid.py— thin CLI on top of the shared code (see note above).Dependency
The cut step needs the NCAR MPAS-Limited-Area tool (
create_region). Runinstall_limited_area.shonce per machine (documented in the README). If it is missing, the script stops with clear instructions.Update: interactive region drawing
Added
draw_region.py— opens a cartopy map (coastlines, country and state borders) where you click the polygon vertices on the map instead of typing coordinates; it writes thelat, lonpoints file thatcreate_regional_grid.py --shape polygonreads (auto-ordered counter-clockwise). Controls: left-click add, right-click undo,cclear, enter save, esc quit. Needs an interactive display (run locally or viassh -X).Testing
All region shapes (circle/ellipse/box/polygon) and both scripts were run end-to-end: meshes generate, the cut produces valid
*.grid.nc+*.graph.infowith the expected 7-layer relaxation belt, and the whole regional domain comes out at the target spacing. The model source code was not touched and the model was not run.