Skip to content

Add submesoscale eddy parametrization - #438

Open
mwarusz wants to merge 22 commits into
E3SM-Project:developfrom
mwarusz:omega/submesoscale-eddies
Open

Add submesoscale eddy parametrization#438
mwarusz wants to merge 22 commits into
E3SM-Project:developfrom
mwarusz:omega/submesoscale-eddies

Conversation

@mwarusz

@mwarusz mwarusz commented Jun 20, 2026

Copy link
Copy Markdown
Member

This PR adds the submesoscale eddy parametrization in the form presented in Fox-Kemper et al. 2011. The parametrization class provides three main methods that

  • determine mixed layer depth
  • compute buoyancy gradient
  • compute submesoscale induced velocity

respectively. A new auxiliary variable named NormalTransportVelocity has been added. This velocity variable is used to advect pseudo-thickness and tracers, and can optionally include the submesocale induced velocity.

Checklist

  • Documentation:
  • Linting
  • Building
    • CMake build does not produce any new warnings from changes in this PR
  • Testing
    • Add a comment to the PR titled Testing with the following:
      • Which machines CTest unit tests
        have been run on and indicate that are all passing.
      • The Polaris omega_pr test suite
        has passed, using the Polaris e3sm_submodules/Omega baseline
      • Document machine(s), compiler(s), and the build path(s) used for -p for both the baseline (Polaris e3sm_submodules/Omega) and the PR build
      • Indicate "All tests passed" or document failing tests
      • Document testing used to verify the changes including any tests that are added/modified/impacted.
    • New tests:
      • CTest unit tests for new features have been added per the approved design.

@mwarusz

mwarusz commented Jun 20, 2026

Copy link
Copy Markdown
Member Author

The parametrization unit tests are passing. However, after turning it on in the baroclinic channel polaris test with the default parameters, I see NaNs after about 3 hours of simulation time, so there is still some debugging to be done. Moreover, user and developer documentation needs to be added.

Copilot AI 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.

Pull request overview

This PR introduces a new submesoscale eddy parameterization module (Fox-Kemper
et al. 2011) into Omega’s ocean model, wires it into initialization/finalization
and tendency/auxiliary-state workflows, and adds a dedicated unit test plus
broad test-harness updates to support new analytic-field helper signatures.

Changes:

  • Add SubmesoEddies module (config-driven) and integrate it into ocean module
    init/finalize and auxiliary-state computation.
  • Introduce TransportAuxVars::NormalTransportVelocity and use it in thickness
    and tracer tendency computations as the transport velocity (optionally
    including submesoscale-induced velocity).
  • Update unit test utilities and many tests to accommodate updated analytic
    field setters; add SubmesoEddiesTest.

Reviewed changes

Copilot reviewed 21 out of 21 changed files in this pull request and generated 6 comments.

Show a summary per file
File Description
components/omega/test/timeStepping/TimeStepperTest.cpp Initialize/destroy SubmesoEddies in the time stepper test harness.
components/omega/test/ocn/TendencyTermsTest.cpp Update analytic-field lambdas to match updated setScalar/setVectorEdge signatures.
components/omega/test/ocn/TendenciesTest.cpp Initialize/destroy SubmesoEddies; update analytic-field lambdas and setScalar/setVectorEdge call signatures.
components/omega/test/ocn/SubmesoEddiesTest.cpp New unit test covering mixed-layer depth, buoyancy gradient, and eddy velocity computations.
components/omega/test/ocn/OceanTestCommon.h Extend setScalar/setVectorEdge helpers to pass element indices and optional Z coordinates.
components/omega/test/ocn/HorzOperatorsTest.cpp Update analytic-field lambdas to match updated helper signatures.
components/omega/test/ocn/AuxiliaryVarsTest.cpp Update analytic-field lambdas to match updated helper signatures.
components/omega/test/ocn/AuxiliaryStateTest.cpp Initialize/destroy SubmesoEddies; update analytic-field lambdas and helper call signatures.
components/omega/test/CMakeLists.txt Register new SUBMESOEDDIES_TEST.
components/omega/src/timeStepping/ForwardBackwardStepper.cpp Pass tracer array into thickness tendency computation.
components/omega/src/ocn/Tendencies.h Extend thickness tendency API to accept a tracer array (for aux-state computations).
components/omega/src/ocn/Tendencies.cpp Route thickness/tracer tendencies through new aux-state compute routines and use NormalTransportVelocity.
components/omega/src/ocn/SubmesoEddies.h New SubmesoEddies public interface.
components/omega/src/ocn/SubmesoEddies.cpp New implementation and IO field registration for SubmesoEddies.
components/omega/src/ocn/OceanInit.cpp Initialize SubmesoEddies during ocean module init.
components/omega/src/ocn/OceanFinal.cpp Destroy SubmesoEddies during ocean finalize.
components/omega/src/ocn/auxiliaryVars/TransportAuxVars.h New aux-var container for NormalTransportVelocity.
components/omega/src/ocn/auxiliaryVars/TransportAuxVars.cpp Register/unregister IO field for NormalTransportVelocity.
components/omega/src/ocn/AuxiliaryState.h Add TransportAuxVars member and new aux compute entry points.
components/omega/src/ocn/AuxiliaryState.cpp Compute Brunt–Väisälä frequency, compute transport velocity (optionally + submeso), and use it for vertical pseudo-velocity.
components/omega/configs/Default.yml Add Omega.Submeso configuration group and defaults.

Comment thread components/omega/src/ocn/AuxiliaryState.cpp Outdated
Comment on lines +173 to +182
KOKKOS_LAMBDA(int IEdge, const TeamMember &Team) {
const int KMin = MinLayerEdgeBot(IEdge);
const int KMax = MaxLayerEdgeTop(IEdge);
const int KRange = vertRangeChunked(KMin, KMax);

parallelForInner(
Team, KRange, INNER_LAMBDA(int KChunk) {
LocPseudoThicknessAux.computeVarsOnEdge(
IEdge, KChunk, PseudoThick, NormalVelEdge);
});
Comment on lines +18 to +22
/// Destroy instance of SubmesoEddies
void SubmesoEddies::destroyInstance() {
delete Instance;
Instance = nullptr;
}
Comment thread components/omega/src/ocn/SubmesoEddies.cpp
Comment thread components/omega/src/ocn/SubmesoEddies.cpp
Comment thread components/omega/test/ocn/SubmesoEddiesTest.cpp
@mwarusz
mwarusz force-pushed the omega/submesoscale-eddies branch 2 times, most recently from 1d3f283 to 9825eda Compare July 14, 2026 21:14
@mwarusz

mwarusz commented Jul 15, 2026

Copy link
Copy Markdown
Member Author

Testing

CTest unit tests

  • Machine: pm-cpu / pm-gpu / frontier
  • Compiler: gnu / gnugpu / craygnu-mphipcc
  • Build type: Release
  • Result: All tests passed (on all machines)

Polaris omega_pr suite

  • Baseline workdir: /pscratch/sd/m/mwarusz/omega-pr-testing/submeso/baseline-gnu
  • Baseline build: /pscratch/sd/m/mwarusz/omega-pr-testing/submeso/baseline-gnu/build
  • PR build: /pscratch/sd/m/mwarusz/omega-pr-testing/submeso/build-gnu
  • PR workdir: /pscratch/sd/m/mwarusz/omega-pr-testing/submeso/pr-gnu
  • Machine: pm-cpu
  • Compiler: gnu
  • Build type: Release
  • Log: /pscratch/sd/m/mwarusz/omega-pr-testing/submeso/pr-gnu/polaris_omega_pr.o55955301
  • Result: All tests passed

@mwarusz

mwarusz commented Jul 15, 2026

Copy link
Copy Markdown
Member Author

The baroclinic channel test is now running stably with the submesoscale eddy parametrization turned on. This PR is ready for review. However, I haven't checked that the parametrization has the intended effect, and I'm not sure that I'm the best person to do that. @vanroekel could you help with this kind of testing ?

@mwarusz
mwarusz requested review from katsmith133 and vanroekel July 15, 2026 23:29
@vanroekel

Copy link
Copy Markdown
Collaborator

@mwarusz I ran a couple tests with baroclinic channel and it's too hard to tell what the effects must be. We need to add a mixed layer. Let me look and see how straight forward that might be.

@vanroekel

Copy link
Copy Markdown
Collaborator

update - I have a mixed layer variant of baroclinic channel I have a test run in the queue on frontier. Hopefully will have results by Monday

PseudoThickML, GradBuoyML, BVFreqML);

GradBuoyML /= PseudoThickML;
BVFreqML /= PseudoThickML;

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

@mwarusz for small ML this could be be problematic, it's not clear above in the MLD code if there is a floor. maybe it's not an issue though

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

I agree that we should probably add a tiny value here. MPAS-O has it.

Team, Range{MinLyrEdgeBot, IndexMLEdge},
INNER_LAMBDA(int K, Real &AccumThick, Real &AccumGradBuoy,
Real &AccumBVFreq) {
const Real PseudoThickKm1 =

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

If your function starts at MinLyrEdgeBot can this lead to values lower than min layer edge?

@mwarusz mwarusz Aug 11, 2026

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

No, this variable is set to

((K - 1) >= MinLyrEdgeBot ? MeanPseudoThickEdge(IEdge, K - 1) : 0)

which is 0 for K = MinLyrEdgeBot. In the end an average of PseudoThickKm1 and PseudoThickK is used. This means that for K = MinLyrEdgeBot you get

PseudoThickAvg = 0.5 * (0 + MeanPseudoThickEdge(IEdge, MinLyrEdgeBot));

This is a kinda hacky treatment of the first half layer. I will add a comment to explain this.

@vanroekel

Copy link
Copy Markdown
Collaborator

@mwarusz in testing I'm getting NaN for EddyVelocity quickly. CoPilot added some guards on the ML average and zero initializing and it fixed the NaN issue. I can point you at what the changes made were if you'd like

@mwarusz

mwarusz commented Aug 11, 2026

Copy link
Copy Markdown
Member Author

@vanroekel

@mwarusz in testing I'm getting NaN for EddyVelocity quickly. CoPilot added some guards on the ML average and zero initializing and it fixed the NaN issue. I can point you at what the changes made were if you'd like

Please do.

@vanroekel

Copy link
Copy Markdown
Collaborator

here it is - https://github.com/vanroekel/E3SM/tree/temp-submeso-branch

There is some extra stuff that is adding more diagnostics as well.

@mwarusz

mwarusz commented Aug 11, 2026

Copy link
Copy Markdown
Member Author

Hmm, Copilot added this check

if (PseudoThickML > Tiny && MLDepthEdge > Tiny)

but afterwards it is also explicitly checking for NaNs and skipping calculations if it finds any. It would good to see if the first check is enough.

@mwarusz
mwarusz force-pushed the omega/submesoscale-eddies branch from 89aae38 to 3660296 Compare August 24, 2026 22:31
@mwarusz
mwarusz force-pushed the omega/submesoscale-eddies branch from 3660296 to a7bd36d Compare August 24, 2026 22:33
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.

4 participants