Unified Base-Mesh Steps and Tasks
This section of the Developer’s guide covers the code for creating the final MPAS base mesh in the unified-mesh workflow. The mesh is generated by JIGSAW using a cell-width (sizing) field and retained river polylines as geometric constraints, so that river channels are aligned with mesh edges.
Available tasks
The helper
polaris.tasks.mesh.spherical.unified.base_mesh.add_unified_base_mesh_tasks()
registers one standalone task for each mesh name in
polaris.mesh.spherical.unified.UNIFIED_MESH_NAMES:
polaris.tasks.mesh.spherical.unified.base_mesh.BaseMeshTaskatmesh/spherical/unified/<mesh_name>/base_mesh/task.
Implementation map
polaris.mesh.spherical.unified.UnifiedBaseMeshStep
The core mesh-generation step lives in the reusable polaris.mesh layer (not
under polaris.tasks) so it can be imported by downstream component tasks
without depending on the task-tree structure.
UnifiedBaseMeshStep.setup() links the sizing field and clipped river network
from the upstream steps, and sets self.cell_width to the finest configured
cell width (used by the parent class for JIGSAW parameter setup).
UnifiedBaseMeshStep.build_cell_width_lat_lon() reads lon, lat, and
cell_width directly from sizing_field.nc rather than computing a uniform
value, so the full variable-resolution field drives the mesh generation.
UnifiedBaseMeshStep.make_jigsaw_mesh() overrides the parent class to
additionally pass clipped_river_network.geojson to JIGSAW as polyline
geometric constraints, ensuring that mesh edges align with retained river
centerlines.
The snap tolerance used to pre-process these constraints is read directly from
the base_mesh_simplify_tolerance_km option in the [river_network] config
section (no fallback). Using the full simplify tolerance (rather than a
fraction of it) ensures that constraint vertices closer than the mesh’s
spatial resolution are merged before reaching JIGSAW, preventing thin-sliver
Delaunay triangles that would otherwise produce degenerate MPAS cell polygons.
steps.py and viz.py (task layer)
get_unified_base_mesh_steps() in polaris.tasks.mesh.spherical.unified.base_mesh
calls the sizing-field step factory, creates or retrieves the
UnifiedBaseMeshStep via component.get_or_create_shared_step, and
optionally creates VizBaseMeshStep.
VizBaseMeshStep reads the MPAS mesh, the sizing field, and the clipped river
network, and writes:
a global resolution map on the MPAS mesh;
a
dcEdgemap on the MPAS mesh;a sizing-field map on the lat-lon source grid; and
a river-alignment figure showing the retained river geometry overlaid on the mesh resolution.
A plain-text debug_summary.txt records key scalar diagnostics such as cell
count and min/max resolution.
Vertex-snapping and degenerate-polygon prevention
_read_geojson_line_mesh() applies a three-layer strategy to prevent JIGSAW
from receiving constraint geometry that would produce degenerate MPAS Voronoi
cells (circumcenters of Delaunay triangles that coincide exactly):
First-pass union-find snap (via
_union_find): raw constraint vertices from all polylines withinsnap_tolerance_kmof each other are merged into a single cluster; the cluster centroid becomes the representative vertex.snap_tolerance_kmequalsbase_mesh_simplify_tolerance_km.Second-pass centroid snap (via
_merge_close_centroids): after the first pass, cluster centroids are re-checked at the same tolerance. A multi-vertex cluster whose centroid drifted toward a neighbouring cluster will be merged in this pass.Edge deduplication: after both snapping passes, constraint edges where the start and end vertex map to the same cluster are removed (consecutive same-cluster entries), and any pair of edges that connect the same two clusters regardless of direction are deduplicated.
The earth radius used for the radian snap tolerance always comes from
get_constant('mean_radius') in the Physical Constants Dictionary; it is
never hard-coded.
Configuration plumbing
get_unified_base_mesh_steps() loads the mesh config with
get_unified_base_mesh_config(mesh_name), which extends the standard unified
mesh config with base_mesh.cfg defaults and sets the [spherical_mesh]
prefix, min_cell_width, and max_cell_width fields derived from the
sizing-field settings.
UnifiedBaseMeshStep inherits all JIGSAW options from
polaris.mesh.spherical.QuasiUniformSphericalMeshStep and the
[spherical_mesh] section of the config.
Extension points
Adding a new named mesh. Create a
.cfgfile underpolaris.mesh.spherical.unified. The mesh name is inferred from the filename;UNIFIED_MESH_NAMESis populated automatically.Customizing river alignment. Override
make_jigsaw_mesh()in a subclass ofUnifiedBaseMeshStepto add additional JIGSAW geometry constraints.Changing the sizing field. Modify the
[sizing_field]options in the mesh-specific config or overrideBuildSizingFieldStep.run()in the sizing field package.
Test coverage
Unit tests in tests/mesh/spherical/unified/test_base_mesh.py validate the
UnifiedBaseMeshStep setup and JIGSAW geometry construction.
Unit tests in tests/mesh/spherical/unified/test_base_mesh_tasks.py validate
task registration for all named unified meshes and that get_unified_base_mesh_steps
creates the expected shared steps.