Skip to content

Split horizontal mesh and initial state inputs for ocean tasks#544

Draft
xylar wants to merge 39 commits intoE3SM-Project:mainfrom
xylar:split-mesh-and-init
Draft

Split horizontal mesh and initial state inputs for ocean tasks#544
xylar wants to merge 39 commits intoE3SM-Project:mainfrom
xylar:split-mesh-and-init

Conversation

@xylar
Copy link
Copy Markdown
Collaborator

@xylar xylar commented Apr 18, 2026

Summary

This PR refactors Polaris ocean tasks to stage the horizontal mesh and initial-state files separately, rather than relying on a single combined input file. It also makes the runtime horizontal mesh the canonical home for the Coriolis fields fCell, fEdge, and fVertex, which are required by both MPAS-Ocean and newer Omega workflows.

This work is needed to support the HorzMeshIn stream E3SM-Project/Omega#382, where the horizontal mesh filename can be configured independently and must include the expected mesh-side Coriolis fields.

What Changed

  • added framework support for staging separate mesh and init files in OceanModelStep
  • added helpers for writing initial-state files without horizontal mesh variables
  • expanded MPAS-Omega variable mapping for horizontal mesh and Coriolis fields
  • added a shared Coriolis helper module for populating fCell, fEdge, and fVertex on mesh datasets
  • updated affected task families so Coriolis fields are written to the runtime mesh file (base_mesh.nc, culled_mesh.nc, or lts_mesh.nc, depending on the task) instead of existing only on the in-memory initial-state dataset
  • updated affected task families to link the correct mesh file explicitly instead of relying on OmegaMesh.nc
  • promoted remaining relevant init steps to OceanIOStep
  • added tests for filename replacement, split mesh/init behavior, and Coriolis mesh-field helpers
  • updated the generated API docs, user guide, and developer guide

Omega Motivation

With E3SM-Project/Omega#382, Omega can now read the horizontal mesh from a configurable NetCDF file via HorzMeshIn. This PR updates Polaris so it can take advantage of that capability by:

  • staging the horizontal mesh separately from the initial state
  • mapping MPAS-Ocean horizontal mesh variable names to the corresponding Omega names
  • ensuring the runtime mesh contains fCell, fEdge, and fVertex, which Omega expects as horizontal-mesh inputs
  • removing old symlink workarounds that depended on the hard-coded OmegaMesh.nc filename

Coriolis Motivation

Both MPAS-Ocean and Omega expect fCell, fEdge, and fVertex to be present on the horizontal mesh. In Polaris, tasks previously added these fields to the initial condition. However, with the new approach of splitting the horizontal-mesh variables from the initial condition, they need to live in the horizontal mesh and not the initial condition.

This PR fixes that by moving these fields to the mesh file used in forward runs. The implementation preserves each task's existing Coriolis semantics, including:

  • zero Coriolis cases
  • constant f-plane cases
  • beta-plane cases
  • rotated-sphere Coriolis cases

Notes

The refactor preserves each task's existing choice of mesh source (e.g. base_mesh.nc vs. culled_mesh.nc vs. lts_mesh.nc), so periodic vs. non-periodic mesh selection remains task-specific and is not changed by this PR.

The Coriolis update also preserves each task's existing Coriolis definition; this PR changes where those fields are written, not the physics each task uses.

Omega still defaults HorzMeshIn, InitialVertCoord, and InitialState to OmegaMesh.nc in Default.yml, and several Omega tests/docs still assume that filename. Polaris now overrides the filenames explicitly, but broader Omega testing (especially CTests) may still benefit from exercising truly separate mesh and init files. It probably makes sense to make this split when we rename LayerThickness to PseudoThickness, since new meshes and initial conditions will be needed in any case.

Validation

  • added and ran targeted mesh/init split tests
  • added and ran targeted tests for the Coriolis helper functions
  • ran pre-commit on the changed files

Checklist

  • User's Guide has been updated
  • Developer's Guide has been updated
  • API documentation in the Developer's Guide (api.md) has any new or modified class, method and/or functions listed
  • Documentation has been built locally and changes look as expected
  • Testing comment in the PR documents testing used to verify the changes

@xylar
Copy link
Copy Markdown
Collaborator Author

xylar commented Apr 18, 2026

This replaces #527

Comment on lines +12 to +13
InitialVertCoord:
Filename: {{ init_filename }}
Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

For now at least, we don't attempt to separate the vertical coordinate into its own file because:

  1. it's dynamic in time and
  2. MPAS-Ocean doesn't support this

@xylar xylar force-pushed the split-mesh-and-init branch 6 times, most recently from 4fe1a4a to 9daf3e9 Compare April 18, 2026 10:35
xylar added 10 commits April 18, 2026 12:51
Add config-driven local filenames for the horizontal mesh and initial condition, plus helper methods for staging them in OceanModelStep. Also centralize MPAS/Omega stream filename updates, expand MPAS-to-Omega horizontal mesh mappings, and add a helper for writing state files without horizontal mesh fields.
Cover placeholder filename resolution for model inputs, shared stream filename replacements, and writing Omega initial-state files without horizontal mesh variables.
Write the initial-state file without horizontal mesh variables and stage the culled mesh explicitly for forward runs. This keeps the family aligned with the shared split mesh/init model without changing its analysis and viz workflows.
Stage the culled mesh and initial state as separate model inputs and stop writing horizontal mesh fields into the initial-state file. This also removes the old OmegaMesh symlink workaround for this family.
Write the gyre initial state without horizontal mesh fields, stage the culled mesh explicitly for the forward step, and drop the old OmegaMesh compatibility symlink while keeping the coeffs input for Omega runs.
Write cosine-bell initial states without horizontal mesh fields and remove the old OmegaMesh symlink workaround from forward runs. The family still stages reconstruction coeffs for Omega, but now relies on the shared explicit mesh input path.
Write the geostrophic initial-state file without horizontal mesh variables so the family can rely on the shared explicit mesh input path during forward runs and visualization.
Pass the culled mesh explicitly through the shared ice-shelf ssh-adjustment workflow, write the initial state without horizontal mesh variables, and stage separate mesh/init inputs for the forward step. This keeps the iterative ssh-adjustment path aligned with the split mesh/init model.
Write the inertial-gravity-wave initial-state file without horizontal mesh variables so the family can use the shared explicit mesh staging path cleanly.
Write the internal-wave initial state without horizontal mesh fields, stage the culled mesh explicitly for forward runs, and update visualization to read mesh geometry from the dedicated mesh file instead of the initial state.
@xylar xylar force-pushed the split-mesh-and-init branch 2 times, most recently from 7af28c7 to e5cb093 Compare April 18, 2026 11:57
xylar added 10 commits April 18, 2026 16:37
Write the manufactured-solution initial state without horizontal mesh variables and remove the old OmegaMesh symlink workaround from forward runs while keeping the Omega coeffs input.
Write merry-go-round initial states without horizontal mesh variables and remove the old OmegaMesh symlink workaround from forward runs while preserving the Omega coeffs input.
Write the overflow initial state without horizontal mesh variables and stage the culled mesh explicitly for forward runs so the family follows the shared split mesh/init workflow.
Write the seamount initial state without horizontal mesh variables and stage the culled mesh explicitly for forward runs so the family uses separate mesh and init inputs.
Write the single-column initial state without horizontal mesh variables, stage the culled mesh explicitly for forward runs, and update the Ekman analysis to read edge geometry from the dedicated mesh file.
Write sphere-transport initial states without horizontal mesh variables and remove the old OmegaMesh symlink workaround from forward runs while preserving the Omega coeffs input.
Write the initial state without horizontal mesh variables, stage the base mesh explicitly for forward runs, and rework the local-time-step path so LTS region labeling reads mesh and state separately. The LTS input stream now follows the configured init filename instead of relying on the old combined file convention.
Expose the new public helper methods in the autosummary source so the generated developer API includes the mesh/state split support.

- add Ocean initial-state helper entries
- add OceanIOStep and OceanModelStep split-input helpers
Explain the staged ocean-model input filenames from a user perspective and document the new [ocean_model_files] config section.

- add the default mesh/init filenames to config-file docs
- note when users may want to override them for model-specific workflows
Refresh the framework guidance and examples so new ocean tasks follow the split mesh/init pattern consistently.

- document OceanIOStep.write_initial_state_dataset()
- document OceanModelStep helpers for staging mesh and init files
- update YAML and code examples to use mesh.nc separately from init.nc
xylar added 19 commits April 18, 2026 16:37
This module enables various types of computations of the Coriolis
paramers at cells, edges and vertices.
Write the baroclinic_channel Coriolis fields to culled_mesh.nc instead of carrying them only in the initial-state dataset.
Write the barotropic_channel Coriolis fields to culled_mesh.nc instead of carrying them only in the initial-state dataset.
Write the barotropic_gyre beta-plane Coriolis fields to culled_mesh.nc instead of keeping them only on the initial-state dataset.
Write a task-local base_mesh.nc with Coriolis fields in cosine_bell and stage that mesh from the init step in forward runs.
Write task-local runtime meshes for external_gravity_wave and stage the correct mesh input in both global and local time-stepping flows.
Write a task-local base_mesh.nc with rotated-sphere Coriolis fields in geostrophic and stage that mesh from the init step in forward runs.
Write the ice_shelf_2d Coriolis fields to culled_mesh.nc instead of carrying them only in the initial-state dataset.
Write the inertial_gravity_wave Coriolis fields to culled_mesh.nc instead of carrying them only in the initial-state dataset.
Write the internal_wave Coriolis fields to culled_mesh.nc instead of carrying them only in the initial-state dataset.
Write the manufactured_solution Coriolis fields to culled_mesh.nc instead of carrying them only in the initial-state dataset.
Write zero Coriolis fields to culled_mesh.nc in merry_go_round instead of carrying them only in the initial-state dataset.
Write zero Coriolis fields to culled_mesh.nc in overflow instead of carrying them only in the initial-state dataset.
Write the seamount Coriolis fields to culled_mesh.nc instead of carrying them only in the initial-state dataset.
Write the single_column Coriolis fields to culled_mesh.nc instead of carrying them only in the initial-state dataset.
Write a task-local base_mesh.nc with Coriolis fields in sphere_transport and stage that mesh from the init step in forward runs.
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.

1 participant