Add MOC stream function analysis capability - #481
Conversation
|
Sorry, @brian-oneill, I didn't get to this today. I'll try again tomorrow. Also, let me know what you need from me regarding both the dynamic streams here in Omega and the Polaris support. |
| ReductionPeriod: [1Month] | ||
| SnapshotPeriod: [1Day] |
There was a problem hiding this comment.
Can you help me understand what sets how often the MOC is computed? Is it the SnapshotPeriod? With the options above, ReductionPeriod would then be averaging daily instantaneous MOC values over 1 month?
There was a problem hiding this comment.
My understanding is that they are independent of one another. In practice, we would have:
ReductionPeriod: [1Month]
SnapshotPeriod: []
since we want monthly averages and don't need snapshots.
It's hard for me to imagine very much analysis where we want both time averages and snapshots at the same time, in practice.
There was a problem hiding this comment.
Yes, ReductionPeriod and SnapshotPeriod produce outputs independently. The ReductionPeriod outputs currently accumulate every timestep so the MOC is computed each timestep for time averages, but this can be extended to allow for a courser sampling frequency pretty easily.
| # Computes spatial reduction statistics (Mean, Min, Max, StdDev) | ||
| # for a set of ocean fields. Supports temporal reduction (time-averaged | ||
| # output over a window) and instantaneous snapshots (discrete sampling). | ||
| Fields: [NormalVelocity, PseudoThickness, Temperature, Salinity] |
There was a problem hiding this comment.
Do we need to test that when, e.g., LayerThickness_BinaryMultiply(NormalVelocity), is present here that the MOC chain uses the available field or is this kind of thing covered by existing CTests?
There was a problem hiding this comment.
Well, I guess not present here because GlobalStats reduces spatially.
There was a problem hiding this comment.
During the initial parsing, the parser checks if a Field that would be output by an operator has already been registered, to prevent building a duplicate operator. There is a unit test that checks this behavior, but it could be more robust.
xylar
left a comment
There was a problem hiding this comment.
@brian-oneill, I'll do some testing but here are a few comments to keep the process moving.
This looks great! A lot of the pieces are in place and just a few tweaks would be helpful, I think. Plus a few things that might be for now or might be postponed until later.
| ReductionPeriod: [1Month] | ||
| SnapshotPeriod: [1Day] |
There was a problem hiding this comment.
My understanding is that they are independent of one another. In practice, we would have:
ReductionPeriod: [1Month]
SnapshotPeriod: []
since we want monthly averages and don't need snapshots.
It's hard for me to imagine very much analysis where we want both time averages and snapshots at the same time, in practice.
There was a problem hiding this comment.
Could ScalarMultiply be generalized to take a model config option or known constant as its input, not just a hard-coded number? This would seem much more useful and general.
There was a problem hiding this comment.
For the use case here, this Op gets passed 1e-6 through a "config" that is programmatically defined in the parser. So 1e-6 is hard-coded into the MOC chain construction, but the Op itself is designed to take a configurable value to be compatible with the future composable framework.
There was a problem hiding this comment.
Sounds good. It's RhoSw in particular that I wanted to know about.
There was a problem hiding this comment.
Gotcha, that's possible but requires a little more work. Allowing users to request a defined constant from the config file would require defining a map between string labels and the variable names in GlobalConstants.h
std::map<std::string,Real> Constants = {
{"RhoSw", RhoSw},
{"Gravity", Gravity},
{"Pi", Pi},
...
};
There was a problem hiding this comment.
I think we should try to figure out how to automate that somehow but, yes, that's what I was anticipating. Nothing that needs to be in this PR.
There was a problem hiding this comment.
Yeah, automated would be best. Here's Claude's suggestion:
Yes, the X-macro pattern is exactly right. The idea: define a single list of constants once using a macro, then expand it in two ways — once to declare the constexpr values, and once to build the lookup.
In GlobalConstants.h, replace the individual constexpr declarations for the physical constants with:
// X-macro list: X(Name, Value)
#define OMEGA_PHYSICAL_CONSTANTS(X) \
X(RhoSw, pcd::seawater_density_reference) \
X(RhoFw, pcd::pure_water_density_reference) \
X(RhoAir, pcd::dry_air_density_at_standard_temperature_and_pressure) \
X(Gravity, pcd::standard_acceleration_of_gravity) \
X(RhoIce, pcd::sea_ice_density_reference) \
/* ... all others ... */
// Expand to constexpr declarations (same as before)
#define DECLARE_CONST(Name, Value) constexpr Real Name = (Value);
OMEGA_PHYSICAL_CONSTANTS(DECLARE_CONST)
#undef DECLARE_CONSTThen the lookup function writes itself:
inline std::optional<Real> getConstantByName(const std::string &Name) {
#define MATCH_CONST(CName, Value) if (Name == #CName) return CName;
OMEGA_PHYSICAL_CONSTANTS(MATCH_CONST)
#undef MATCH_CONST
return std::nullopt;
}#CName stringifies the identifier automatically, so the name in the config file ("RhoSw") matches the C++ variable name without any manual duplication.
Pros: Zero maintenance burden — adding a new constant to the list automatically makes it available by name to ScalarMultiplyOp and any future operator that calls getConstantByName.
Cons: Requires refactoring the existing constexpr declarations in GlobalConstants.h into the macro list format. The math-derived ones (TwoPi, SDay, etc.) are trickier since they depend on other constants — those would need to stay as regular constexpr or be added after the macro expansion.
The practical approach: put only the "leaf" physical constants (densities, heat capacities, etc.) in the X-macro list, and keep derived/compound ones (TwoPi, TkFrzSw, SDay) as regular constexpr declarations below. You could optionally add those to a second X-macro list if you want them accessible by name too.
There was a problem hiding this comment.
I successfully ran a 5-day test with the MOC on in:
/lcrc/group/e3sm/ac.xylar/polaris_1.0/chrysalis/test_20260804/ec30to60-global-moc/ocean/spherical/realistic_global/EC30to60E2r2/analysis_members_test
I used:
MOC:
Enable: true
# Meridional Overturning Circulation (MOC) streamfunction analysis group
# Computes MOC as a function of latitude and depth for regions,
# and as a function of depth for transects
NumBins: 180 # Number of latitude bins (default: 180, ~1 degree)
MinLat: -90.0 # Minimum latitude in degrees (default: -90.0)
MaxLat: 90.0 # Maximum latitude in degrees (default: 90.0)
Regions: [Global] # List of region names for regional MOC
# NOTE: Region masks not yet implemented
Transects: [] # List of transect names for transect-based MOC
# NOTE: Transect masks not yet implemented
ReductionPeriod: [1day] # Temporal reduction periods
SnapshotPeriod: [] # Instantaneous output periods
Filename: moc.$Y
Stream:
FileFreq: 1
FileFreqUnits: daysSo daily averaging rather than monthly for efficiency.
However, the latitude bins and depth are missing from the output file:
$ ncdump -h moc_1dayTimeStats.0001
netcdf moc_1dayTimeStats {
dimensions:
MaxCellsOnEdge = 2 ;
MaxEdges = 7 ;
MaxEdges2 = 14 ;
NCells = 236853 ;
NEdges = 719506 ;
NTracers = 2 ;
NVertLayers = 60 ;
NVertLayersP1 = 61 ;
NVertices = 482371 ;
NumBinsLatCell_BinIndex = 180 ;
Scalar = 1 ;
VertexDegree = 3 ;
time = UNLIMITED ; // (5 currently)
variables:
double MOC_streamfunction_Global_TimeMean1day(time, NumBinsLatCell_BinIndex, NVertLayersP1) ;
MOC_streamfunction_Global_TimeMean1day:Description = "Time average of VerticalPseudoVelocity_PseudoToGeometric_BinaryMultiply(AreaCell)_BinnedAccumulator(LatCell_BinIndex)_PrefixSum_ScalarMultiply(1.0e-6)" ;
MOC_streamfunction_Global_TimeMean1day:Name = "VerticalPseudoVelocity_PseudoToGeometric_BinaryMultiply(AreaCell)_BinnedAccumulator(LatCell_BinIndex)_PrefixSum_ScalarMultiply(1.0e-6)_TimeMean1day" ;
MOC_streamfunction_Global_TimeMean1day:StdName = "" ;
MOC_streamfunction_Global_TimeMean1day:Units = "" ;
MOC_streamfunction_Global_TimeMean1day:ValidMax = 1.79769313486232e+308 ;
MOC_streamfunction_Global_TimeMean1day:ValidMin = -1.79769313486232e+308 ;
MOC_streamfunction_Global_TimeMean1day:_FillValue = 9.96920996838687e+36 ;
MOC_streamfunction_Global_TimeMean1day:long_name = "Time average of VerticalPseudoVelocity_PseudoToGeometric_BinaryMultiply(AreaCell)_BinnedAccumulator(LatCell_BinIndex)_PrefixSum_ScalarMultiply(1.0e-6)" ;
MOC_streamfunction_Global_TimeMean1day:name = "VerticalPseudoVelocity_PseudoToGeometric_BinaryMultiply(AreaCell)_BinnedAccumulator(LatCell_BinIndex)_PrefixSum_ScalarMultiply(1.0e-6)_TimeMean1day" ;
MOC_streamfunction_Global_TimeMean1day:standard_name = "" ;
MOC_streamfunction_Global_TimeMean1day:units = "" ;
MOC_streamfunction_Global_TimeMean1day:valid_max = 1.79769313486232e+308 ;
MOC_streamfunction_Global_TimeMean1day:valid_min = -1.79769313486232e+308 ;
double time(time) ;
time:Description = "time" ;
time:Name = "time" ;
time:StdName = "time" ;
time:Units = "seconds since 0001-01-01 00:00:00" ;
time:ValidMax = 1.e+20 ;
time:ValidMin = 0. ;
time:_FillValue = 9.96920996838687e+36 ;
time:calendar = "noleap" ;
time:long_name = "time" ;
time:name = "time" ;
time:standard_name = "time" ;
time:units = "seconds since 0001-01-01 00:00:00" ;
time:valid_max = 1.e+20 ;
time:valid_min = 0. ;
// global attributes:
:SimulationTime = "0001-01-06_00:00:00" ;
:SimulationTime0 = "0001-01-02_00:00:00" ;
:SimulationTime1 = "0001-01-03_00:00:00" ;
:SimulationTime2 = "0001-01-04_00:00:00" ;
:SimulationTime3 = "0001-01-05_00:00:00" ;
:SimulationTime4 = "0001-01-06_00:00:00" ;
}
Also the file is missing a .nc extension.
Happy to rerun once this is fixed.
|
Is I've noticed the history and hifreq files that get created when running the omega ctests also no longer get the |
|
The problem with the current layer-wise approach is it implicitly assumes pure z-level layers. The best way to get depths given this approach is to get the area-weighted average of zInterface and use that as the vertical coordinate. For now, that's fine. With ice-shelf cavities, sigma coordinates, etc. in the future, we'll need to do vertical binning or interpolation to a z-level or density-level grid. |
|
I'm fine with whatever fix to the |
| # List of field names to compute statistics for | ||
| SpatialStats: [Max, Min, Mean, StdDev] | ||
| # Spatial statistics to compute (one per field) | ||
| ReductionPeriod: [1Day, 1Month] |
There was a problem hiding this comment.
| ReductionPeriod: [1Day, 1Month] | |
| ReductionPeriod: [] |
Should we remove reductions altogether from this analysis member to save compute time?
There was a problem hiding this comment.
I think we want 1Month reduction for the climatology plot, don't we?
There was a problem hiding this comment.
I guess it depends on what configuration Default.yml is aimed at -- typical standalone testing or a longer production run.
| # Spatial statistics to compute (one per field) | ||
| ReductionPeriod: [1Day, 1Month] | ||
| # Temporal reduction periods (time-averaged stats) | ||
| SnapshotPeriod: [6Hours] |
There was a problem hiding this comment.
MPAS-O is equivalent to 1Day but I like increasing the freq to 6 hours
@brian-oneill Is this ready for testing with the fix to this comment? |
@cbegeman I added the latitude bins. The depths will require a bit more thought and work, and I won’t have time to complete that piece until I’m back at the end of the week. |
Polaris
|
|
@brian-oneill I successfully ran a 10-day QU240 realistic_global test with this feature enabled and daily time reduction. I inspected the moc file's attributes and variables but didn't plot them, given that the latest changes would not have affected the MOC computation itself. |
cbegeman
left a comment
There was a problem hiding this comment.
Approving on the basis of visual inspection, my testing on chrysalis-intel, and @xylar testing and viz. Great work, @brian-oneill !
|
@brian-oneill, I'm reviewing but it's turning up a need to rebase this branch onto |
xylar
left a comment
There was a problem hiding this comment.
@brian-oneill, this is great and I think we're almost there!
How this was reviewed
I reviewed this by running the omega_analysis suite from the Polaris branch in E3SM-Project/polaris#743. That PR adds an ocean/analysis/moc step to Polaris' Omega analysis suite: it reads this group's output, averages the reductions over a range of years weighted by the length of each period, and plots the streamfunction against latitude and the interface elevations the group provides. Everything below came out of getting that to work.
The simulation. QU240, one simulated year from 0000-12-01, with
MOC:
Enable: true
NumBins: 60
MinLat: -90.0
MaxLat: 90.0
Regions: [Global]
Transects: []
ReductionPeriod: [1Month]
SnapshotPeriod: []
Filename: moc.$Y-$M.nc
Stream: {FileFreq: 1, FileFreqUnits: months}built from this branch rebased onto omega/develop, on chrysalis with intel (oneAPI 2025.2).
The analysis. Polaris' omega_analysis suite, all five tasks passed.
The plot, and the rest of the suite's products, are on the LCRC portal — the MOC is the moc_global_0001-0001 gallery:
https://web.lcrc.anl.gov/public/e3sm/diagnostic_output/xasaydavis/omega_analysis_moc_20260907/
Work directories: the run at /lcrc/group/e3sm/ac.xylar/polaris_1.1/chrysalis/test_20260907/qu240-moc-analysis-mockup, the analysis at .../test_20260907/qu240-moc-analysis.
What the previous review asked for, and what is now there
The previous review reported three things: latitude bins missing, depths missing, and no .nc extension. All three are addressed.
double MOC_streamfunction_Global_TimeMean1Month(time, NumBinsLatCell_BinIndex, NVertLayersP1) ;
double MOCLatBinBoundaries(time, NMocLatBinBoundaries) ;
double GeomZInterface_HorzMean(time, NVertLayersP1) ;
double time(time) ;
NumBinsLatCell_BinIndex = 60, NMocLatBinBoundaries = 61, NVertLayersP1 = 61. The file is moc_1MonthTimeStats.0001-01.nc, so the suffix is there too.
What works
Lots is working exactly as needed here!
The streamfunction closes exactly. In every month of the run, psi is exactly zero at the surface interface, exactly zero at the bottom interface, and exactly zero in the southernmost bin. The residual at the northernmost bin — the one place a global streamfunction has anything left to accumulate — is small and shrinking across the run (0.255, 0.138, 0.115 Sv over the first three months). The bottom-interface zero is the check the earlier cross-validation script used, and it holds to round-off.
Reductions are genuinely per-period. Consecutive monthly means differ substantially (up to 46 Sv between months 2 and 3), so the temporal accumulator is being reset between periods rather than producing a running average.
Reductions are stamped at the end of their period. The time values are 31, 62, 90 and 121 days since 0000-12-01, which are the ends of December, January, February and March. That makes the period each reduction covers recoverable from the stamps.
The file names are reconstructable from the config alone, as <prefix>_<period><TimeStats|Instants><template>, and the variable names as MOC_streamfunction_<Region>_TimeMean<period>. Polaris builds both from the simulation's own YAML without any of it being restated, which is what makes the analysis configuration-free.
Findings
1. MOCLatBinBoundaries should very likely not have a time dimension
It is static: computed once in the MOC constructor from NumBins, MinLat and MaxLat, and never updated. But it is attached to the output streams with addField() like any other field, so every reduction in every file carries a copy of the same 61 numbers.
The cost in bytes is nothing. The cost to a consumer is not: a reader that takes the variable as written gets NumBins + 1 boundaries per output time, and over a twelve-month range that flattens to twelve times as many latitudes as there are bins. Polaris now takes the first record and checks the rest agree, but that is a special case that exists only because the field claims to vary and does not.
GeomZInterface_HorzMean having a time dimension is correct — the interfaces move — so this is specifically about the bin boundaries.
2. The streamfunction still carries no units
MOC_streamfunction_Global_TimeMean1Month:Units = "" ;
MOC_streamfunction_Global_TimeMean1Month:units = "" ;
The chain ends in ScalarMultiply(1.0e-6), so the values are in Sverdrups, but nothing in the file says so and a consumer has to know it out of band. This was raised in the previous review and is unchanged. Both spellings need Sv: a PR addressing #529 will remove the capitalized Units in favor of the CF-compliant units, but until it lands both have to be correct.
3. GeomZInterface_HorzMean fills in only one of its two units attributes
GeomZInterface_HorzMean:Units = "" ;
GeomZInterface_HorzMean:units = "m" ;
The duplicated attributes are already tracked in #529; a fix would drop the capitalized set in favor of the CF-compliant ones. Until that lands both have to be right, and here only the lower-case one is, so a reader picking Units gets nothing. The same doubling appears on Name/name, StdName/standard_name and ValidMin/valid_min.
4. The written bin boundaries are not the edges the operator bins on
MOC.cpp writes the boundaries without the margin that CoordinateBinningOp applies before it bins:
// MOC.cpp
const Real BinWidthDeg = (MaxLat - MinLat) / static_cast<Real>(NumBins);
BinBoundHost(I) = MinLat + I * BinWidthDeg;// CoordinateBinningOp.h
const Real Margin = (MaxBin - MinBin) * 1.0e-6;
MinBin -= Margin;
MaxBin += Margin;
BinWidth = (MaxBin - MinBin) / NumBins;For the defaults the difference is about 1.8e-4 degrees, far below anything that matters for a plot. Even so, it's better write out what the code really uses. Deriving the written boundaries from the operator's own MinBin/BinWidth would make them agree by construction. Alternatively, we should build the margin into the input latitude range somehow.
5. Reductions carry no time bounds
The output has a CF time with units and calendar but no time_bnds, and no cell_methods saying the values are a time mean. A consumer averaging reductions over a range has to weight each by the length of its period — the streamfunction is linear in the velocity, so this is not optional, and monthly periods differ in length by up to a tenth. With bounds that is exact; without them Polaris infers each period from the gap to the next stamp, which is exact for every period except the first, whose length it has to assume.
This is not specific to the MOC group; it applies to any temporal reduction, and it is the same gap that makes ncclimo unusable on Omega history files without a pre-processing step.
6. The long_name is the operator chain
MOC_streamfunction_Global_TimeMean1Month:long_name =
"Time average of VerticalPseudoVelocity_PseudoToGeometric_BinaryMultiply(AreaCell)_BinnedAccumulator(LatCell_BinIndex)_PrefixSum_ScalarMultiply(1.0e-6)" ;
Excellent provenance and exactly what Description ( renamed to comment when #529 gets addressed) should say. As a long_name it is what ends up on a colorbar or in a variable listing, where "global meridional overturning streamfunction" would serve better.
7. Noted along the way
Running the MOC group with a monthly ReductionPeriod aborts unless RestartWrite uses a Months or Years interval, because AnalysisGroup validates the restart interval without checking that RestartWrite has a periodic alarm. Filed separately as #539.
de20a34 to
a48d53b
Compare
|
All six of the previous review's findings are fixed — confirmed against the output rather than the diff, thank you. The Verified fixedRe-ran the QU240 mock-up on this branch rebased onto The bin boundaries have lost their In a continuous run One small note rather than a request: Reduction streams segfault when they rewrite their own fileA continuation run crashes before its first time step. The trigger is not the restart itself but what the restart causes: the reduction alarm fires again at the restart instant and rewrites the output file the previous segment already wrote. It is not specific to MOC. The tightest reproducer has the The most informative line there is the one that succeeds. In the same pass, over the same restart, Seven runs, each continued from the identical
The last row is the attribution: the old code rewrites the same file in the same situation without crashing, so this is new in these commits. The sixth row rules out the Where I think it isThe only new code in the write path is the The comment in that block states the assumption I think breaks: // Define the CF-compliant time bounds variable (time_bnds) and attach the
// bounds attribute to the time variable. defineVar is called on every write
// (the file is re-entered in define mode each time) so TimeBndsID is valid
// for every frame; ...When the file already exists, IO::writeNDVar(Bnds, OutFileID, TimeBndsID, Frame, &BndLengths);which would put a bad variable id into the write and is consistent with a segfault rather than a clean error. I could not confirm this in a debugger — the compute nodes have no Worth checking in the same pass:
|
|
#548 adds a Posted by Claude Code on @xylar's behalf. The testing, analysis and wording above are AI-authored; please check them accordingly. |
|
Fixed the restart crash by moving the |
xylar
left a comment
There was a problem hiding this comment.
Ran a one-year QU240 run from d31f221 merged locally with #553 on Chrysalis (Intel, OpenMPI), at /lcrc/group/e3sm/ac.xylar/polaris_1.1/chrysalis/test_20260914/qu240-monthly-avgs/ocean/analysis_test/QU240/forward. Both the MOC files and #553's monthly means now carry time_bnds with time:bounds pointing at it and the right interval, which is what #549 asks for, so this PR could say Fixes #549 in its description. One CF nit inline; the interval-end naming and time value are #554, not this PR's.
Posted by Claude Code on @xylar's behalf. The testing, analysis and wording above are AI-authored; please check them accordingly.
| // Reuse the same units as the time variable (seconds since start). | ||
| std::string UnitString = | ||
| "seconds since " + StartTime.getString(4, 0, " "); | ||
| IO::writeMeta("units", UnitString, OutFileID, TimeBndsID); |
There was a problem hiding this comment.
cfchecks flags this: CF 7.1 says a boundary variable should not have a units attribute, since it takes the units of the variable it bounds. Dropping this line clears the warning.
There was a problem hiding this comment.
@brian-oneill, is this one you'd like to deal with here? I'll approve but I'd prefer having he units dropped here rather than having to do it in a follow-up PR. Bounds variables don't get units according to CF, they inherit them from the variable they are the bounds on.
Testing: restartI continued the one-year QU240 run (this branch at d31f221 merged with #553) from its With the clock started at the restart time, the monthly means and snapshots are bit for bit and With the clock left at the run's original start, every periodic alarm rang on the first step after the restart and the first Posted by Claude Code on @xylar's behalf. The testing, analysis and wording above are AI-authored; please check them accordingly. |
I replicated your test on Frontier with craygnu, and found everything BFB between analysis outputs of the continuous run and the restarts. The fact that the differences are near machine precision leads me to think it's Intel compiler optimizations that are responsible, though it's certainly strange it manifests specifically in the restart pipeline, and seems to wash out on subsequent outputs. Since the differences are so small and situationally specific, I lean toward tolerating the differences, while making a note of it. |
Okay, let's make a note of it. I think we won't typically rely on the analysis restart capability, so this may not matter anyway. We should also revisit after Phil's fix goes in because restarts are a little messy right now anyway. |
xylar
left a comment
There was a problem hiding this comment.
I'm approving based on my testing. This is excellent work!
See my final clean-up request above.
|
I posted #578 to keep track of the restart issue. |
TestingOn Chrysalis with Qualification: Builds ( Posted by Claude Code on @xylar's behalf. The testing, analysis and wording above are AI-authored; please check them accordingly. |
|
Aurora is down but tests on pm-cpu, pm-gpu, chrysalis, and frontier with CPU and GPU all passed (both CTests and omega_pr vs. develop as a baseline). |

Overview
This PR introduces a complete MOC (Meridional Overturning Circulation) analysis capability to Omega, enabling computation of the MOC streamfunction using two complementary methods:
The implementation adds 8 new analysis operators, enhanced analysis infrastructure with regional mask support, a new MOC analysis group, and comprehensive configuration templates.
Key Features
New Analysis Operators (8 total):
BinaryMultiplyOp: Element-wise field multiplication with vertical expansion supportBinnedAccumulatorOp: Accumulates field values into spatial bins (core MOC operator)CoordinateBinningOp: Assigns mesh entities to bins based on coordinate valuesExtractRegionOp: Applies regional masks to fieldsPrefixSumOp: Cumulative summation (integration) along specified dimensionPseudoToGeometricOp: Converts pseudo-height quantities to geometric coordinatesScalarMultiplyOp: Multiplies field by scalar constant for unit conversionTransectAccumulatorOp: Accumulates transport across transect edgesInfrastructure Enhancements:
setOutputIONamemethod and operator-specific configuration supportMOC Analysis Group:
MOC Computation Pipeline
Latitude-binned Regional MOC chain:
Transect-based MOC chain:
Technical Implementation
Design Features:
Output Format:
Limitations
Checklist
Documentation:
Linting
Building
Testing
aurora, oneapi-ifx, mpich
chrysalis, oneapi-ifx, openmpi
frontier, craygnu, mpich
frontier, craygnu-mphipcc, mpich
pm-cpu, gnu, mpich
pm-gpu, gnugpu, mpich
Provide relevant details in a comment to the PR titled
Testingwith the following:have been run on and indicate that are all passing.
has passed, using the Polaris
e3sm_submodules/Omegabaseline-pfor both the baseline (Polarise3sm_submodules/Omega) and the PR buildNew tests: