Skip to content

Add vertical mixing tendencies#410

Open
hyungyukang wants to merge 19 commits into
E3SM-Project:developfrom
hyungyukang:omega/vmix-hookup
Open

Add vertical mixing tendencies#410
hyungyukang wants to merge 19 commits into
E3SM-Project:developfrom
hyungyukang:omega/vmix-hookup

Conversation

@hyungyukang

@hyungyukang hyungyukang commented May 18, 2026

Copy link
Copy Markdown

This PR adds the velocity and tracer vertical mixing tendency terms. The implicit vertical mixing is solved by using TriDiagDiffSolver and is applied once at the end of each time step.

  • Implemented implicit vertical mixing using TriDiagDiffSolver.
  • Added VertMixImplicit to VertMix.
  • Applied vertical mixing once at the end of each time step.
  • Note: Tangential velocity, which is required by ComputeGradRichardsonNum in VertMix, is temporarily handled in VertMix.

This PR includes #352 for testing purposes.

Checklist

  • 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

@hyungyukang

Copy link
Copy Markdown
Author

Testing

CTest unit tests

  • Machine: frontier
  • Compiler: craygnu, craygnu-mphipcc
  • Build type: Release
  • Result: All tests passed

Polaris omega_pr suite

  • Baseline workdir: /lustre/orion/cli115/proj-shared/hgkang/E3SM/OMEGA/Polaris/work/pr_suite/260518_09_vMix_PR/baseline_omega
  • Baseline build: /lustre/orion/cli115/proj-shared/hgkang/E3SM/OMEGA/Polaris/polaris_main/e3sm_submodules/Omega
  • PR build: /lustre/orion/cli115/proj-shared/hgkang/E3SM/OMEGA/Omega_hyun_vmixHook_2
  • PR workdir: /lustre/orion/cli115/proj-shared/hgkang/E3SM/OMEGA/Polaris/work/pr_suite/260518_09_vMix_PR/branch_omega
  • Machine: frontier
  • Partition: batch
  • Compiler: craygnu
  • Build type: Release
  • Log: /lustre/orion/cli115/proj-shared/hgkang/E3SM/OMEGA/Polaris/work/pr_suite/260518_09_vMix_PR/branch_omega/polaris_omega_pr.o4609310
  • Result: All tests passed

@hyungyukang

hyungyukang commented May 18, 2026

Copy link
Copy Markdown
Author

Tested this branch using ocean/column/vmix_stable from E3SM-Project/polaris#435 and compared with MPAS-O.

Here are results of vmix_stable/forward:

  • Temperature at day 10:
image
  • Normal velocity at day 10:
image

@hyungyukang

Copy link
Copy Markdown
Author

@katsmith133 ,
Here're figures of VertVisc and VertDiff (vertViscTopOfCell and vertDiffTopOfCell in MPAS-O, respectively):

  • VertVisc at day 10:
image
  • VertDiff at day 10
image

I will retest your branch with this test case since you've updated it.

@katsmith133

Copy link
Copy Markdown

@katsmith133 , Here're figures of VertVisc and VertDiff (vertViscTopOfCell and vertDiffTopOfCell in MPAS-O, respectively):
...
I will retest your branch with this test case since you've updated it.

@hyungyukang, thanks for the plots! I doubt the updates I just made in #352 will result in any difference here, but doesn't hurt to check. Let me pull down this branch and take a look at things and see if anything pops out to me.

@hyungyukang hyungyukang force-pushed the omega/vmix-hookup branch 5 times, most recently from 7503bfb to 72ab187 Compare May 27, 2026 13:54
@hyungyukang hyungyukang force-pushed the omega/vmix-hookup branch 3 times, most recently from fd950d6 to 5abe72c Compare June 2, 2026 01:07
@katsmith133 katsmith133 self-requested a review June 3, 2026 15:35
@hyungyukang

hyungyukang commented Jun 4, 2026

Copy link
Copy Markdown
Author

Test results from column/vmix_stable/forward_no_vadv in Polaris is posted here: #352 (comment)

@hyungyukang

Copy link
Copy Markdown
Author

I fixed the bugs related to non-flat bottom topography and ran the overflow test to compare Omega with MPAS-O. MPAS-O was slightly modified to exclude horizontal FCT, since it has not yet been implemented in Omega.

The results below show temperature at 6 hours.

image

@sbrus89 sbrus89 requested a review from mwarusz June 17, 2026 15:18
@cbegeman

Copy link
Copy Markdown

@hyungyukang The PR doesn't include bottom drag in the implicit mixing, correct? So we will continue to use explicit bottom drag with implicit vmix?

@hyungyukang

Copy link
Copy Markdown
Author

@hyungyukang The PR doesn't include bottom drag in the implicit mixing, correct? So we will continue to use explicit bottom drag with implicit vmix?

@cbegeman , Yes, the implicit bottom drag is not included in this PR. I plan to open a separate PR for it after this one is merged.

@cbegeman cbegeman self-requested a review June 22, 2026 15:15

@katsmith133 katsmith133 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.

My comments aren't super major, except for whether we want to split the vertical mixing stuff up in some way in anticipation of having multiple parameterizations.

GradRichNumSmoothed = Array2DReal("GradRichNumSmoothed", Mesh->NCellsSize,
VCoord->NVertLayersP1);

// TODO: Temporary handling of TangentialVelocity

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Is this temporary handling to be addressed in a later PR?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Yes.
I haven’t identified an appropriate location for it yet, but I believe we will have a suitable place for those diagnostic computations by the time the split time stepper is implemented, if not sooner.


} // end defineIOFields

// Apply implicit velocity vertical mixing

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

In MPAS-O we have several files for the vertical mixing. One that handles the below calculations and several that do the computation of the coefficients (either from KPP or something else). Do we want to follow that design choice here in Omega? I feel like it might be good, as we add more mixing parameterizations, to have them split off more? Thoughts @vanroekel?

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.

Yes I think so. This is what I'm doing in the forthcoming KPP PR. It's its own class in its own file.

Comment thread components/omega/src/ocn/VertMix.h Outdated
0.5_Real * (VertVisc(JCell0, K + 1) + VertVisc(JCell1, K + 1)) /
(LocRhoSw * SpecVolEdgeTop);

G = DT * ViscAlphaEdgeTop / PseudoThickEdgeTop;

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Do we want more descriptive names for these variables (D, H, and X)?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

I tried to follow the naming conventions used in TriDiagDiffSolver:

I will consider whether more descriptive names would be appropriate. Otherwise, I can add more detailed comments to clarify the code.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

I added more detailed inline comments to VelVertMixSetup and TracerVertMixSetup to explain the tridiagonal diffusion system and the roles of the G, H, and X coefficients.

(PseudoThickEdgeK + PseudoThickEdgeKp1);

const Real ViscAlphaEdgeTop =
0.5_Real * (VertVisc(JCell0, K + 1) + VertVisc(JCell1, K + 1)) /

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Suggested change
0.5_Real * (VertVisc(JCell0, K + 1) + VertVisc(JCell1, K + 1)) /
0.5_Real * (VertVisc(JCell0, K) + VertVisc(JCell1, K)) /

I might be misremembering the indexing of the NVertLayersP1 variables. Would we be starting from K = MinLayerEdgeBot = 0 and then K + 1 corresponds to the VertVisc at the bottom of the top level? Should the index be changed or the name be changed to ViscAlphaEdgeBot?

@hyungyukang hyungyukang Jun 30, 2026

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Yes, that’s correct. The code is written for the K loop ranging from MinLayerEdgeBot to MaxLayerEdgeTop. I double checked both the equation and the implementation, and the K + 1 index is correct. As you suggested, ViscAlphaEdgeTop should be renamed to ViscAlphaEdgeBot to reflect its actual location (other variables as well).

If I use K instead of K + 1 for VertVisc, the result differs from the Omega and MPAS-O results shown above:

image

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Thanks for checking!

Comment thread components/omega/src/ocn/VertMix.cpp Outdated
VertMix *VertMixInstance = VertMix::getInstance();

if (!EosInstance) {
LOG_WARN("Eos has not been initialized. Skipping calculation of "

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.

Do we only want a warning here? Would it make more sense to do this check once at init and fail the model if this happens?

@hyungyukang hyungyukang Jun 30, 2026

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Thanks for catching that. That makes much more sense.

I updated the code so that the VertMix tendency is validated once during initialization in Tendencies.cpp rather than at every time step. Also, the model will now abort if vertical mixing tendencies are enabled without both Eos and VertMix being initialized.

https://github.com/hyungyukang/Omega/blob/b44936d15950a3b4b10b450f649d6c70d325a8ff/components/omega/src/ocn/Tendencies.cpp#L335-L347

Comment thread components/omega/src/ocn/VertMix.cpp Outdated

if (!EosInstance) {
LOG_WARN("Eos has not been initialized. Skipping calculation of "
"PresGradZ tendency");

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.

should this be VertMix?

@hyungyukang hyungyukang Jun 30, 2026

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

The code has been removed. VertMix tendency now checks Eos only during initialization.

Comment thread components/omega/src/ocn/VertMix.cpp Outdated
VertMix *VertMixInstance = VertMix::getInstance();

if (!EosInstance) {
LOG_WARN("Eos has not been initialized. Skipping calculation of "

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.

again i think an error would be better.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

The code has been removed, and the model will now abort if vertical mixing tendencies are enabled without both Eos and VertMix being initialized.

Comment thread components/omega/src/ocn/VertMix.cpp Outdated
"PresGradZ tendency");
} else if (!VertMixInstance) {
LOG_WARN("VertMix has not been initialized. Skipping calculation of "
"VelVertMix tendency");

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.

TracerVertMix?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

The code has been removed. VertMix tendency now checks VertMix only during initialization.

katsmith133 and others added 18 commits July 1, 2026 09:40
- Implemented implicit vertical mixing using TriDiagDiffSolver.
- Added applyVertMixImplicit to VertMix.
- Applied vertical mixing once at the end of each time step.
- Note: Tangential velocity is temporarily handled in VertMix.
Renaming cell-interface variables from 'Top' to 'Bot'.
- Validate the VertMix tendency once at initialization instead of
  during each time step.
- Abort the model if vertical mixing tendencies are enabled
  but Eos or VertMix has not been initialized.
- Improve the inline documentation in VertMixSetup
@hyungyukang

Copy link
Copy Markdown
Author

I ran into some CTest issues after rebasing, but they have been resolved. I am now running the Polaris Omega test suite.

@hyungyukang

Copy link
Copy Markdown
Author

Testing

CTest unit tests

  • Machine: Frontier
  • Compiler: craygnu, craygnu-mphipcc
  • Build type: Release
  • Result: All tests passed

Polaris omega_pr suite

  • Baseline workdir: /lustre/orion/cli115/proj-shared/hgkang/E3SM/OMEGA/Polaris/work/pr_suite/260701_14_vMix_PR/baseline_omega
  • Baseline build: /lustre/orion/cli115/proj-shared/hgkang/E3SM/OMEGA/Polaris/polaris_main_260701/e3sm_submodules/Omega
  • PR build: /lustre/orion/cli115/proj-shared/hgkang/E3SM/OMEGA/Omega_hyun_vmixHook_8
  • PR workdir: /lustre/orion/cli115/proj-shared/hgkang/E3SM/OMEGA/Polaris/work/pr_suite/260701_14_vMix_PR/branch_omega
  • Machine: frontier
  • Partition: batch
  • Compiler: craygnu
  • Build type: Release
  • Log: /lustre/orion/cli115/proj-shared/hgkang/E3SM/OMEGA/Polaris/work/pr_suite/260701_14_vMix_PR/branch_omega/polaris_omega_pr.o4927573
  • Result: All tests passed

@vanroekel vanroekel left a comment

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.

Approving based on visual inspection, developer testing, and my own testing with the single column test case.

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.

5 participants