Skip to content

Add MOAB coupler support for Omega - #523

Merged
sbrus89 merged 15 commits into
E3SM-Project:developfrom
vijaysm:vijaysm/omega/moab-support
Oct 20, 2026
Merged

sbrus89 merged 15 commits into
E3SM-Project:developfrom
vijaysm:vijaysm/omega/moab-support

Conversation

@vijaysm

@vijaysm vijaysm commented Aug 20, 2026

Copy link
Copy Markdown

Update interfaces to MOAB coupler by defining the Omega mesh in MOAB, and pushing/pulling data out of tags by defining and updating the data as needed by the driver. Tested only with a C-case, but I think it should work with any other case as well since the interface is uniform from the component standpoint.

Checklist

  • Documentation:

  • Linting

  • Building

    • CMake build does not produce any new warnings from changes in this PR
  • Testing

    aurora, oneapi-ifx, mpich

    • CTests Pass
    • Polaris omega_pr Pass

    chrysalis, oneapi-ifx, openmpi

    • CTests Pass
    • Polaris omega_pr Pass

    frontier, craygnu, mpich

    • CTests Pass
    • Polaris omega_pr Pass

    frontier, craygnu-mphipcc, mpich

    • CTests Pass
    • Polaris omega_pr Pass

    pm-cpu, gnu, mpich

    • CTests Pass
    • Polaris omega_pr Pass

    pm-gpu, gnugpu, mpich

    • CTests Pass
    • Polaris omega_pr Pass
  • Provide relevant details in 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.
  • Performance related PRs: Please include a relevant PACE experiment link documenting performance before and after.

  • New tests:

    • CTest unit tests for new features have been added per the approved design.
    • Polaris tests for new features have been added per the approved design (and included in a test suite)
  • Stealth Features

    • If any stealth features are included in the PR, please confirm that they have been documented.

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

@vijaysm Sorry this took me so long to get around to! Thanks for taking this on. Besides a few minor comments, this looks great!

While there aren't any conflicts; I think rebasing onto develop would be a good idea. We recently added support for G and B cases. Your thoughts of what sampling of test should use the moab vs. mct driver would be appreciated:

Omega/cime_config/tests.py

Lines 1150 to 1173 in c1aacdc

"e3sm_omega_developer" : {
"time" : "0:45:00",
"tests" : (
# --- C Cases (Data atm/ice forcing) ---
"ERS_Vmct.T62_oQU240.COMEGA-IAF",
"PEM_Vmct.T62_oQU240.COMEGA-IAF",
"SMS_Vmct_Ld3.TL319_EC30to60E2r2.COMEGA-JRA1p5.omega-jra_1958",
# --- G Cases (Active sea-ice MPASSI coupling) ---
"SMS_Vmct.T62_oQU240.GOMEGA-IAF",
"PEM_Vmct.T62_oQU240.GOMEGA-IAF",
"ERS_Vmct_Ln9.TL319_EC30to60E2r2.GOMEGA-JRA1p5.omega-jra_1958",
"PEM_Vmct_Ln9.TL319_EC30to60E2r2.GOMEGA-JRA1p5.omega-jra_1958",
# --- B Cases (Fully coupled EAM/ELM/MOSART/MPASSI/OMEGA) ---
"SMS_Vmct.ne4_oQU240.WCYCL1850NS-OMEGA",
"ERS_Vmct_Ld3.ne4_oQU240.WCYCL1850NS-OMEGA",
# --- Debug builds (TODO: enable once confirmed working) ---
#"SMS_D_Vmct_Ln3.T62_oQU240.COMEGA-IAF",
#"SMS_D_Vmct_Ln3.T62_oQU240.GOMEGA-IAF",
#"SMS_D_Vmct_Ln3.ne4_oQU240.WCYCL1850NS-OMEGA",
)
},

Comment thread components/omega/cime_config/buildlib_cmake Outdated
Comment thread components/omega/src/drivers/coupled/MoabInterface.cpp Outdated
Comment thread components/omega/src/drivers/coupled/MoabInterface.cpp Outdated
Comment thread components/omega/src/drivers/coupled/MoabInterface.cpp Outdated
Comment thread components/omega/src/drivers/coupled/ocn_comp_mct.F90 Outdated
Comment thread components/omega/src/drivers/coupled/ocn_comp_mct.F90 Outdated
Comment thread components/omega/src/drivers/coupled/omega_cxx2f_interface.cpp Outdated
Comment thread components/omega/src/drivers/coupled/omega_cxx2f_interface.cpp Outdated
@andrewdnolan

Copy link
Copy Markdown
Collaborator

I'll do the rebase onto develop locally and start doing some testing!

@vijaysm The instructions for installing the pre-commit environment are here: https://docs.e3sm.org/Omega/Omega/devGuide/Linting.html. With that you should be able to fix that failing CI test without much headache.

@vijaysm

vijaysm commented Sep 29, 2026

Copy link
Copy Markdown
Author

@andrewdnolan I'll take care of these tonight or tomorrow. Thanks for the comments

@andrewdnolan

Copy link
Copy Markdown
Collaborator

Sounds good!

BTW, I did some testing using SMS.ne4_oQU240.WCYCL1850NS-OMEGA.chrysalis_intel:

  1. First attempt had a build fail related to the outdated code in ocn_comp_mct.F90.
  2. After deleting the code within the ifdefs I was able to get the case to build successfully. But, I go a runtime failure. CoPilot was suggesting it something related to the MPI communicator passed in iMOAB_RegisterApplication. Attaching the e3sm.log file here for reference. e3sm.log.1298248.260929-123040.log

@vijaysm

vijaysm commented Sep 30, 2026 via email

Copy link
Copy Markdown
Author

andrewdnolan and others added 10 commits October 1, 2026 08:57
Detect MOAB via OMEGA_MOAB_ROOT when COMP_INTERFACE=moab, define HAVE_MOAB,
and conditionally add/link MoabInterface.cpp. No effect when MOAB is absent.
registerApplication only registered an app. Now builds an owned-cells mesh
(vertex compaction, polygon elements, GLOBAL_ID tags), domain tags, and
x2o/o2x tag get/set. Also fixes header typos that blocked compilation.
Pass full CIME field-name lists to the C++ side, pick MOAB vs MCT layout at
compile time, and call the mesh/tag-storage functions around ocean init and
run. Drops the unused runtime layout selection it replaces.
moabInit's app id was staying local to the C++ side. The coupler-side
migration/mapping code reads seq_comm_mct's mpoid to locate the ocean mesh,
so leaving it at -1 meant it never found it, causing the crash and memory
corruption seen at runtime. Fortran now copies the id into mpoid.
component_init_areacor_moab reads area:aream:mask as one combined tag; a
missing tag fails the whole read. aream gets a -9999 placeholder, same
convention MCT uses, since the coupler fills in the real value later.
iMOAB_CreateElements expects connectivity entries to be 1-based (it computes
firstVertex + connectivity[j] - 1). Compact vertex indices were written
0-based, so every vertex reference pointed one slot too early.
@vijaysm
vijaysm force-pushed the vijaysm/omega/moab-support branch from 6d6fe2b to a03b0ac Compare October 2, 2026 02:51
@andrewdnolan

Copy link
Copy Markdown
Collaborator

@vijaysm Tried testing on chrysalis with:

  • SMS.ne4_oQU240.WCYCL1850NS-OMEGA.chrysalis_intel
  • SMS_P64x1.ne4_oQU240.WCYCL1850NS-OMEGA.chrysalis_intel
  • SMS.T62_oQU240.COMEGA-IAF.chrysalis_intel
    but all test fail during runtime.

Stack trace for the C-Case is:

 14: forrtl: severe (174): SIGSEGV, segmentation fault occurred
 14: Image              PC                Routine            Line        Source             
 14: libpthread-2.28.s  000015554D718990  Unknown               Unknown  Unknown
 14: libmpi.so.40.30.8  0000155548542833  PMPI_Comm_group       Unknown  Unknown
 14: e3sm.exe           00000000006A3881  Unknown               Unknown  Unknown
 14: e3sm.exe           00000000006A3639  Unknown               Unknown  Unknown
 14: e3sm.exe           00000000005D03D9  Unknown               Unknown  Unknown
 14: e3sm.exe           0000000000491CF5  moab_send_mesh            111  cplcomp_moab_helpers_mod.F90
 14: e3sm.exe           000000000048C8AE  cplcomp_moab_init         462  cplcomp_exchange_mod.F90
 14: e3sm.exe           0000000000490D0C  cplcomp_moab_init        1063  cplcomp_exchange_mod.F90
 14: e3sm.exe           0000000000486951  component_init_cx         377  component_mod.F90
 14: e3sm.exe           000000000046860B  cime_init                1639  cime_comp_mod.F90
 14: e3sm.exe           000000000048513D  cime_driver               122  cime_driver.F90
 14: e3sm.exe           0000000000460FDD  Unknown               Unknown  Unknown
 14: libc-2.28.so       0000155547F16865  __libc_start_main     Unknown  Unknown
 14: e3sm.exe           0000000000460EFE  Unknown               Unknown  Unknown

Looks like it's crashing during moab init. This is looking pretty similar to the stack trace in the log file linked above. When I previously had CoPilot look at the error and it suggested it something related to the MPI communicator passed in iMOAB_RegisterApplication. But it's been a while, I'd have to track down that session to find some more info.

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

Testing

On chrysalis, I ran:

SMS.T62_oQU240.COMEGA-IAF.chrysalis_intel.20261007_110911_hylcq1
SMS.ne4pg2_oQU240.WCYCL1850NS-OMEGA.chrysalis_intel.20261007_134627_wy1es1

and both test pass! In order to use the ne4pg2_oQU240 grid alias I needed to cherry-pick e7e8960 from E3SM's master. Support for that grid alias will be brought into Omega's fork with #566.


@vijaysm Just a couple final comments. The only other thing I can think of is changing the tests in the test suite to run with MOAB:

Omega/cime_config/tests.py

Lines 1150 to 1173 in c1aacdc

"e3sm_omega_developer" : {
"time" : "0:45:00",
"tests" : (
# --- C Cases (Data atm/ice forcing) ---
"ERS_Vmct.T62_oQU240.COMEGA-IAF",
"PEM_Vmct.T62_oQU240.COMEGA-IAF",
"SMS_Vmct_Ld3.TL319_EC30to60E2r2.COMEGA-JRA1p5.omega-jra_1958",
# --- G Cases (Active sea-ice MPASSI coupling) ---
"SMS_Vmct.T62_oQU240.GOMEGA-IAF",
"PEM_Vmct.T62_oQU240.GOMEGA-IAF",
"ERS_Vmct_Ln9.TL319_EC30to60E2r2.GOMEGA-JRA1p5.omega-jra_1958",
"PEM_Vmct_Ln9.TL319_EC30to60E2r2.GOMEGA-JRA1p5.omega-jra_1958",
# --- B Cases (Fully coupled EAM/ELM/MOSART/MPASSI/OMEGA) ---
"SMS_Vmct.ne4_oQU240.WCYCL1850NS-OMEGA",
"ERS_Vmct_Ld3.ne4_oQU240.WCYCL1850NS-OMEGA",
# --- Debug builds (TODO: enable once confirmed working) ---
#"SMS_D_Vmct_Ln3.T62_oQU240.COMEGA-IAF",
#"SMS_D_Vmct_Ln3.T62_oQU240.GOMEGA-IAF",
#"SMS_D_Vmct_Ln3.ne4_oQU240.WCYCL1850NS-OMEGA",
)
},

We'll have to leave the Vmct modifier on all the B-cases, until #566 is merged. Maybe we leave:

SMS_Vmct_Ld3.TL319_EC30to60E2r2.COMEGA-JRA1p5.omega-jra_1958

and

PEM_Vmct.T62_oQU240.GOMEGA-IAF

with the Vmct modifier, but then drop it from the rest of the C and G cases? Sorry, I'd go ahead a make those changes myself, but since this branch is from your fork I can't. If you want to pass that off, could you add me as a collaborator on your fork?

Comment thread components/omega/cime_config/buildlib_cmake Outdated
Comment on lines 236 to 245
! Init import/export mct attribute vectors
! Initialize MCT AVs with the ocean decomposition. The MOAB driver
! uses their field lists during coupler-side initialization.
call mct_aVect_init(x2o, rList=seq_flds_x2o_fields, lsize=lsize)
call mct_aVect_init(o2x, rList=seq_flds_o2x_fields, lsize=lsize)

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.

I get that these are still needed even when using the MOAB driver, but it seems like a waste to allocate these with a lsize=lsize. Could we just get way with lsize=1 when using MOAB? Or do they need to be full sized?

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.

I'm not exactly sure what to do about this; given it's what all other components do I think this is OK for now.

Will investigate using an lsize=1 when using MOAB at a later date.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

They shouldn't need to be full sized.

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've tried with lsize=0 before and that fails. Yeah lsize=1 would be a good choice. Or we just create a better way to pass around field names without relying on MCT AVs?

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.

Agreed, the later seems like the best long term solution. But for now lsize=1 seems to work; at least of the C-Case. Will rerun the B-Case just to double check.

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.

FIxed in ee991bd. Testing with a B-Case now.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

The List datatype, which defines and operates on the colon delimited string that is part of an Av, can be used instead but doing that swap is something I was going to put off to the very end.

Maybe the latest Fortran standard has better ways to work with strings.

Comment thread components/omega/src/ocn/OceanRun.cpp Outdated
@andrewdnolan andrewdnolan added the Coupled Changes (should) only affect coupled configurations label Oct 14, 2026
@andrewdnolan

Copy link
Copy Markdown
Collaborator

Testing, chrysalis with intel compiler

I was able to produce BFB results between MOAB and MCT with:

  • SMS.T62_oQU240.COMEGA-IAF.chrysalis_intel

Also, ran:

  • ERS_Ln9.TL319_EC30to60E2r2.GOMEGA-JRA1p5.chrysalis_intel.20261014_151230_0f0n4d: PASS
  • SMS.ne4pg2_oQU240.WCYCL1850NS-OMEGA.chrysalis_intel.20261014_165641_wgzulq: PASS
    • Requires cherry-picking e7e8960 from develop.

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

I'm approving based on inspection and testing on chrysalis.

@andrewdnolan
andrewdnolan requested a review from jonbob October 14, 2026 22:12
@andrewdnolan

Copy link
Copy Markdown
Collaborator

@jonbob Would you be okay taking a quick peak at this? Some additional testing on a new machine could never hurt.

I think @vijaysm did his development on pm-cpu/pm-gpu, but would be good to maybe run some more tests on a gpu machine.

After that I think this is ready to go!

@andrewdnolan

Copy link
Copy Markdown
Collaborator

@vijaysm @rljacob Should be expect BFB results between MOAB and MCT for all cases?

I was able to get BFB results between the two for SMS.ne4pg2_oQU240.WCYCL1850NS-OMEGA.

But SMS_Ld10.TL319_EC30to60E2r2.COMEGA-JRA1p5 does not produce BFB results.

Both tests were run with this branch and e7e8960 cherry-picked from develop.

To set these up I just ran:

# from cime/scripts
./create_test -t mct --driver mct SMS.ne4pg2_oQU240.WCYCL1850NS-OMEGA
./create_test -t moab --driver moab SMS.ne4pg2_oQU240.WCYCL1850NS-OMEGA

cd /lcrc/group/e3sm/ac.anolan/scratch/chrys/

cprnc \
    SMS.ne4pg2_oQU240.WCYCL1850NS-OMEGA.chrysalis_intel.mct/run/SMS.ne4pg2_oQU240.WCYCL1850NS-OMEGA.chrysalis_intel.mct.cpl.hi.0001-01-06-00000.nc \
    SMS.ne4pg2_oQU240.WCYCL1850NS-OMEGA.chrysalis_intel.moab/run/SMS.ne4pg2_oQU240.WCYCL1850NS-OMEGA.chrysalis_intel.moab.cpl.hi.0001-01-06-00000.nc

and then the analogous command for SMS_Ld10.TL319_EC30to60E2r2.COMEGA-JRA1p5 but I added -gcase suffice to the test ID to avoid conflicts.

There seems to be something about the TL319_EC30to60E2r2 grid that causing the non-BFBness. @jonbob is running analogous tests with mpas-ocean right now.

@vijaysm

vijaysm commented Oct 15, 2026

Copy link
Copy Markdown
Author

There seems to be something about the TL319_EC30to60E2r2 grid that causing the non-BFBness.

Are there any custom commands that get run for this resolution? Can you also point me to the case that you set up? I'd like to see the diffs to understand which field is causing the error propagation.

@jonbob

jonbob commented Oct 15, 2026

Copy link
Copy Markdown

I ran similar tests but using MPASO instead of OMEGA. Those tests also showed diffs between the mct and moab runs, based on running cprnc on the coupler history files

@rljacob

rljacob commented Oct 15, 2026

Copy link
Copy Markdown
Member

This is a C-case? The test case for that should be BFB between MCT and MOAB. That was T62_oQU120.CMPASO-NYF. Also T62_oQU120.CMPASO-IAF. Not sure we tested any other C-cases.

@andrewdnolan

Copy link
Copy Markdown
Collaborator

@vijaysm there shouldn't be a need for any special commands on perlmutter.

On chrysalis you'll need to apply this diff:

diff --git a/cime_config/machines/config_machines.xml b/cime_config/machines/config_machines.xml
index 61a77a4766..a39f7715a7 100644
--- a/cime_config/machines/config_machines.xml
+++ b/cime_config/machines/config_machines.xml
@@ -2778,7 +2778,6 @@
         <command name="load">subversion/1.14.0-e4smcy3</command>
         <command name="load">perl/5.32.0-bsnc6lt</command>
         <command name="load">cmake/3.24.2-whgdv7y</command>
-        <command name="load">python/3.11.7-iexc6vq</command>
       </modules>
       <modules compiler="intel-classic">
         <command name="load">intel/20.0.4-kodw73g</command>

and then source:

/lcrc/soft/climate/e3sm-unified/load_latest_cime_env.sh

before running any CIME commands, to ensure pyyaml is available. After that nothing special; running ./create_test as above should work.


Existing cases are:

# These are BFB
/lcrc/group/e3sm/ac.anolan/scratch/chrys/SMS.ne4pg2_oQU240.WCYCL1850NS-OMEGA.chrysalis_intel.mct
/lcrc/group/e3sm/ac.anolan/scratch/chrys/SMS.ne4pg2_oQU240.WCYCL1850NS-OMEGA.chrysalis_intel.moab

# These are not BFB
/lcrc/group/e3sm/ac.anolan/scratch/chrys/SMS_Ld10.TL319_EC30to60E2r2.COMEGA-JRA1p5.chrysalis_intel.moab-gcase
/lcrc/group/e3sm/ac.anolan/scratch/chrys/SMS_Ld10.TL319_EC30to60E2r2.COMEGA-JRA1p5.chrysalis_intel.mct-gcase

@rljacob

rljacob commented Oct 15, 2026

Copy link
Copy Markdown
Member

This is a C-case because it has a data sea-ice model.

@andrewdnolan

Copy link
Copy Markdown
Collaborator

@rljacob Using the T62_oQU240 and ne4pg2_oQU240 grids, I can BFB between the different drivers for C and B cases, respectively.

It seems that the TL319_EC30to60E2r2 grid is culprit for non-BFBness. @jonbob tried G-Cases and I tried C-Cases with Omega and both had diffs in the coupler history files. Jon also ran tests (I'm guessing G?) with MPASO using TL319_EC30to60E2r2 and was able to reproduce the non-BFBness. Not sure what it is about that grid.

Unfortunately I'm not seeing a grid alias for T62_EC30to60E2r2 or TL319_oQU240; there are version with ice-shelf cavities and with landice (respecitvely), but we can't use those in Omega yet.

@vijaysm

vijaysm commented Oct 15, 2026 •

Copy link
Copy Markdown
Author

So I tested Jon's MCT/MOAB cases and they use the VECT_MAP=cart3d configuration, which is known to induce small machine precision diffs. @rljacob Anyway, I asked Claude to take a look at the diffs anyway and this is the explanation I got.

Verdict

The MOAB driver is not systematically different from MCT in this configuration. It reproduces MCT bit-for-bit for every offline map application, the fraction calculation, the x2o/x2i merges, and the atm/ocn flux algorithm. The entire 10‑day difference grows from a single 1‑ULP seed in the atm→ocn vector (patch) map, which a threshold in the data-ice model then amplifies by ~14 orders of magnitude.

Evidence: the divergence ladder

Counting cells that differ at all (not RMS) in cpl.hi (236853 ocn cells, 204800 atm cells):

┌──────────────────────────────────────────────────────────────────────────────────────────────────────────────┬───────────────┬──────────────────────┐
│                                                    field                                                     │    cells      │     max rel diff     │
│                                                                                                              │   differing   │                      │
├──────────────────────────────────────────────────────────────────────────────────────────────────────────────┼───────────────┼──────────────────────┤
│ x2i_Sa_u                                                                                                     │ 4             │ 1.85e-16 (exactly ±1 │
│                                                                                                              │               │  ULP)                │
├──────────────────────────────────────────────────────────────────────────────────────────────────────────────┼───────────────┼──────────────────────┤
│ x2i_Sa_v, all a2x_*, all r2x_*, x2i_Sa_{z,v,tbot,ptem,shum,pbot,dens}, x2i_Faxa_*, x2oacc_Sa_{pbot,pslv},    │ 0             │ —                    │
│ all doma_*/domo_*/domi_*/domr_*                                                                              │               │                      │
├──────────────────────────────────────────────────────────────────────────────────────────────────────────────┼───────────────┼──────────────────────┤
│ x2oacc_Foxx_swnet                                                                                            │ 5             │ 2.9e-09              │
├──────────────────────────────────────────────────────────────────────────────────────────────────────────────┼───────────────┼──────────────────────┤
│ x2oacc_Faxa_rain / _snow                                                                                     │ 9 / 27        │ 3e-04 / 1e-02        │
├──────────────────────────────────────────────────────────────────────────────────────────────────────────────┼───────────────┼──────────────────────┤
│ fraco_ifrac, fraci_ifrac, i2x_Si_ifrac                                                                       │ 30            │ 6.1e-02              │
├──────────────────────────────────────────────────────────────────────────────────────────────────────────────┼───────────────┼──────────────────────┤
│ o2x_So_t, x2oacc_Foxx_*, xaoo_Faox_*                                                                         │ ~all          │ 1e-3 … O(1)          │
└──────────────────────────────────────────────────────────────────────────────────────────────────────────────┴───────────────┴──────────────────────┘

x2i_Sa_u is the only field that is a pure function of bit-identical inputs and still differs. Everything else is downstream.

Root cause

mapper_Va2o (used only by seq_map_cart3d for Sa_u/Sa_v) loads the same map file in both runs — confirmed in both logs:
map_TL319_to_EC30to60E2r2_patch.201005.nc

That map is qualitatively different from every other map in the case:

┌───────┬─────────┬──────────────────┐
│  map  │ nnz/row │ negative weights │
├───────┼─────────┼──────────────────┤
│ aave  │ 3.31    │ 0 %              │
├───────┼─────────┼──────────────────┤
│ bilin │ 4.02    │ 0 %              │
├───────┼─────────┼──────────────────┤
│ patch │ 16.10   │ 43 %             │
└───────┴─────────┴──────────────────┘

MCT's mct_sMat_avMult (BFBFLAG=T) and MOAB's iMOAB_ApplyScalarProjectionWeights sum each row in different orders, and MOAB additionally repartitions the coupler meshes with Zoltan RCB (visible in e3sm.log). For the all-positive 3–4-term aave/bilin rows that reordering is bit-neutral — observed, since every aave/bilin-mapped field is bit-identical. For the 16-term patch rows with mixed signs, cancellation makes the row sum order-sensitive, and 4 of 236853 rows land on the other side of a rounding boundary in ux/uy/uz.

Why Sa_u and not Sa_v: the cart3d back-transform is
ue = -slon·ux + clon·uy and un = -clon·slat·ux - slon·slat·uy + clat·uz.
All 4 affected cells are at |lat| ≤ 12.2° (−1.2, −12.2, −5.9, +10.2), where sin(lat) damps the perturbation entering un below 1 ULP. The trig tables themselves are identical — domo_lat/lon and doma_lat/lon show zero differences, and the MOAB driver writes those from its own mesh tags (seq_hist_mod.F90:274,326), which proves the MOAB lat/lon tags equal MCT's domain values.

Why 1 ULP becomes 6 % in 10 days

1. Sa_u on the ocean grid is ubot in seq_flux_atmocn → taux/tauy/sen/lat/evap differ at 4 tropical cells on coupling step 1.
2. MPAS-O's barotropic solve and global reductions spread it globally within ~a day.
3. The dominant amplifier: DICE in prescribed ssmi mode derives ice fraction from the ocean's freeze potential through hard thresholds (components/data_comps/dice/src/dice_comp_mod.F90:793-802):
if (iFrac <= 0 .and. water(n) > 0) iFrac = min(1., water(n)/waterMax)
if (iFrac > 0)                     iFrac = max(0.01, iFrac)
   A roundoff change in Fioo_q flips a cell from 0 to ≥0.01 ice fraction. That is where the 30 differing cells come from, and they sit exactly where marginal ice lives: Barents/Norwegian Sea (69–77 N, 3–39 E) and Bohai/Yellow Sea (~40 N, 120–122 E).
4. The merge weights all atm→ocn fluxes by ofrac/ifrac, so those 30 cells inject O(1e‑2) relative flux differences back into the ocean.

Growth rate confirms chaos, not bias — mpaso...globalStats, temperatureMax: day 1 differs by 3e‑13 (1e‑14 rel), day 10 by 3e‑8 (1e‑9 rel), ~one e‑fold per day.

Separately found — real code discrepancies, not the cause here

1. driver-moab/main/prep_ocn_mod.F90:679 — with cpl_compute_maps_online = .true., wgtIdVa2o = wgtIdFa2o: the vector mapper silently falls back to the conservative map. Winds would then differ from MCT systematically, not at roundoff. The comment ("same map as Sa2o") also disagrees with the code (Fa2o).
2. driver-moab/main/seq_flux_mct.F90, seq_flux_atmocn_moab — the bad-data guard if (dens(n) < 1.0e-12 .or. tocn(n) < 1.0) emask(n) = 0 sits inside the mask(n) == 0 branch after dens/tocn are zeroed, so it can never deactivate an active ocean cell. In MCT it is inside mask(n) /= 0 and can.
3. prep_ocn_accum_avg_moab averages via x2oacc_om * (1/cnt). Inert here (ATM_NCPL = OCN_NCPL = 48 ⇒ cnt == 1), but a latent non-BFB risk whenever OCN_NCPL < ATM_NCPL; worth checking against mct_aVect_avg's rounding.
4. Metadata mismatch that silently skips comparison: MOAB writes xaoo_So_fswpen_ao/xaoa_So_fswpen_ao, MCT writes xaoo_So_fswpen/xaoa_So_fswpen, so cprnc reports 2 fields missing on each side and never compares them.
5. driver-moab/{main,shr} is a stale fork of driver-mct: missing IAC zfrac fractions and iacrun_avg alarm, missing WW3 two-way fields (Sw_Charn, Sw_Z0, Sw_Ustar), missing Sl_forc_hdm:Sl_hdd:Sl_cdd. Benign in this compset (stub wav/iac/lnd), but these paths will not match MCT when exercised.

I would retry with --xmlchange VECT_MAP=none for both cases and rerun and do a diff again. If it still diffs, then we have a problem. Or you could just run 1 step and see if only Sa_u differs by machine precision (grep for RMS in cprnc diff).

@rljacob

rljacob commented Oct 15, 2026

Copy link
Copy Markdown
Member

Oh yeah VECT_MAP. There are some cases/machines where that doesn't matter but in some cases it does.

@vijaysm

vijaysm commented Oct 15, 2026

Copy link
Copy Markdown
Author

Also, this is important and a good reason to move away from patch-based maps. Negative weights will notoriously induce spurious oscillatory modes when applied to fields with high gradients. Someone should do an analysis and replace the patch based maps with bilinear or something better.

┌───────┬─────────┬──────────────────┐
│  map  │ nnz/row │ negative weights │
├───────┼─────────┼──────────────────┤
│ aave  │ 3.31    │ 0 %              │
├───────┼─────────┼──────────────────┤
│ bilin │ 4.02    │ 0 %              │
├───────┼─────────┼──────────────────┤
│ patch │ 16.10   │ 43 %             │
└───────┴─────────┴──────────────────┘

Anyway, none of this has to do with the Omega-MOAB interface. But just wanted to note this.

@andrewdnolan

Copy link
Copy Markdown
Collaborator

Thanks for looking into that @vijaysm. After running ./xmlchange VECT_MAP=none in both case directories, I'm now getting BFB results for: SMS_Ld10.TL319_EC30to60E2r2.COMEGA-JRA1p5.

@andrewdnolan

Copy link
Copy Markdown
Collaborator

With the ./xmlchange VECT_MAP=none fix I was also able to get BFB results between the different drivers for:

  • SMS_Ld3.ne30pg2_r05_EC30to60E2r2.WCYCL1850NS-OMEGA.chrysalis_intel

As a final tests I ran:

./create_test --no-run SMS_Lm1.TL319_EC30to60E2r2.GOMEGA-JRA1p5

cd <CASE_DIR>

./xmlchange BUDGETS=TRUE
./case.submit

coupler budgets are working as expected:

(seq_diag_print_moab) NET AREA BUDGET (m2/m2): period =  monthly: date =     10201     0                                                                                                     
                           atm            lnd            ocn         ice nh         ice sh        *SUM*                                                                                      
            area    -1.00000000     0.00000000     0.64780740     0.02078990     0.03791557    -0.29348712                                                                                   
                                                           
(seq_diag_print_moab) NET HEAT BUDGET (W/m2): period =  monthly: date =     10201     0
                           atm            lnd            rof            ocn         ice nh         ice sh            glc        *SUM*                                                        
         hfreeze     0.00000000     0.00000000     0.00000000     0.00000000     0.00000000     0.00000000     0.00000000     0.00000000                                                     
           hmelt     0.00000000     0.00000000     0.00000000    -0.34672060     0.12790642     0.21897492     0.00000000     0.00016074                                                     
          hnetsw  -176.71098369     0.00000000     0.00000000   125.91456263     0.00013619     2.39678150     0.00000000   -48.39950337                                                     
           hlwdn  -330.23094692     0.00000000     0.00000000   233.51147417     3.78526515    10.46972144     0.00000000   -82.46448615                                                     
           hlwup     0.00000000     0.00000000     0.00000000  -273.59614280    -4.41357577   -11.67629113     0.00000000  -289.68600971                                                     
         hlatvap     0.00000000     0.00000000     0.00000000   -74.70734858     0.00044390    -0.03867825     0.00000000   -74.74558294                                                     
         hlatfus     0.67888429     0.00000000     0.00000000    -0.11637008    -0.06097936    -0.08686309     0.00000000     0.41467175                                                     
          hiroff     0.00000000     0.00000000     0.03512527    -0.03512547     0.00000000     0.00000000     0.00000000    -0.00000020                                                     
            hsen     0.00000000     0.00000000     0.00000000   -14.16326905     0.25689295     0.65028446     0.00000000   -13.25609164                                                     
          hpolar     0.00000000     0.00000000     0.00000000     0.00000000     0.00000000     0.00000000     0.00000000     0.00000000                                                     
        hh2otemp     0.00000000     0.00000000     0.00000000     0.00000000     0.00000000     0.00000000     0.00000000     0.00000000                                                     
           *SUM*  -506.26304631     0.00000000     0.03512527    -3.53893979    -0.30391052     1.93392984     0.00000000  -508.13684151                                                     
                                                                                                                                                                                             
(seq_diag_print_moab) NET WATER BUDGET (kg/m2s*1e6): period =  monthly: date =     10201     0                                                                                               
                           atm            lnd            rof            ocn         ice nh         ice sh            glc        *SUM*                                                        
         wfreeze     0.00000000     0.00000000     0.00000000     0.00000000     0.00000000     0.00000000     0.00000000     0.00000000                                                     
           wmelt     0.00000000     0.00000000     0.00000000    -0.57868198     1.46544307    -0.88908522     0.00000000    -0.00232413                                                     
           wrain   -31.56888152     0.00000000     0.00000000    24.64158370     0.02907618     0.39334980     0.00000000    -6.50487184                                                     
           wsnow    -2.03441502     0.00000000     0.00000000     0.34872664     0.18273708     0.26030295     0.00000000    -1.24264834                                                     
          wpolar     0.00000000     0.00000000     0.00000000     0.00000000     0.00000000     0.00000000     0.00000000     0.00000000                                                     
           wevap     0.00000000     0.00000000     0.00000000   -29.87099104     0.00001705    -0.01329525     0.00000000   -29.88426924                                                     
         wrunoff     0.00000000     0.00000000    -1.88149429     1.88140446     0.00000000     0.00000000     0.00000000    -0.00008983                                                     
         wfrzrof     0.00000000     0.00000000    -0.10526003     0.10526062     0.00000000     0.00000000     0.00000000     0.00000059                                                     
          wirrig     0.00000000     0.00000000     0.00000000     0.00000000     0.00000000     0.00000000     0.00000000     0.00000000                                                     
           *SUM*   -33.60329654     0.00000000    -1.98675432    -3.47269760     1.67727339    -0.24872772     0.00000000   -37.63420279                                                     
                                                                                                                                                                                             
(seq_diag_print_moab) NET SALT BUDGET (kg/m2s*1e8): period =  monthly: date =     10201     0                                                                                                
                           atm            lnd            rof            ocn         ice nh         ice sh            glc        *SUM*  
            salt     0.00000000     0.00000000     0.00000000    -0.82025844     0.67969147     0.13989521     0.00000000    -0.00067177 

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

Approved based on testing and a visual inspection

@sbrus89

sbrus89 commented Oct 20, 2026

Copy link
Copy Markdown
Collaborator

Passes:

ERS.T62_oQU240.COMEGA-IAF.aurora_intel
PEM.T62_oQU240.COMEGA-IAF.aurora_intel
SMS_Ld3.TL319_EC30to60E2r2.COMEGA-JRA1p5.aurora_intel.omega-jra_1958
SMS.T62_oQU240.GOMEGA-IAF.aurora_intel

@sbrus89

sbrus89 commented Oct 20, 2026

Copy link
Copy Markdown
Collaborator

Passes:

ERS_Ln9.TL319_EC30to60E2r2.GOMEGA-JRA1p5.frontier_craygnu.omega-jra_1958
ERS.T62_oQU240.COMEGA-IAF.frontier_craygnu
PEM.T62_oQU240.COMEGA-IAF.frontier_craygnu
PEM.T62_oQU240.GOMEGA-IAF.frontier_craygnu
SMS_Ld3.TL319_EC30to60E2r2.COMEGA-JRA1p5.frontier_craygnu.omega-jra_1958
SMS.T62_oQU240.GOMEGA-IAF.frontier_craygnu

@sbrus89

sbrus89 commented Oct 20, 2026

Copy link
Copy Markdown
Collaborator

Even though this shouldn't affect standalone runs, I ran omega_pr and CTests anyway:

Testing on aurora

Tested the merge of #523 (ee991bd224) into develop (135755f734) as efd33f7603, against Polaris' Omega submodule (cdb935bb5a).

Row CTests omega_pr New build warnings
aurora, intel, mpich 61 of 61 passed 32 of 32 passed 0
aurora, intelgpu, mpich 60 of 61 passed 32 of 32 passed 2
aurora, intel, mpich

Polaris omega_pr suite

  • Baseline workdir: /home/brus/run/omega_pr_test/baselines/aurora_intel_polaris-eea123e_omega-cdb935b/omega_pr
  • Baseline build: /home/brus/run/omega_pr_test/baselines/aurora_intel_polaris-eea123e_omega-cdb935b/build
  • PR build: /home/brus/run/omega_pr_test/pr523-ee991bd/aurora_intel/build
  • PR workdir: /home/brus/run/omega_pr_test/pr523-ee991bd/aurora_intel/omega_pr
  • Polaris: eea123efca8fc7a955a8f57029fab5aaa1d2296a (1.1.0-177-geea123efc)
  • Baseline Omega: cdb935bb5a8d995b0878616e001a2701a2627519 (Omega-v0.1.0-alpha.1-6142-gcdb935bb5a)
  • PR Omega: efd33f760307a9f2eede9ad03438732f40b8b7c7 (Omega-v0.1.0-alpha.1-6242-gefd33f7603)
  • Machine: aurora
  • Compiler: intel
  • Build type: Release
  • Log: /home/brus/run/omega_pr_test/pr523-ee991bd/aurora_intel/omega_pr/polaris_omega_pr.o8947856
  • Result: All tests passed
Recent commits

Polaris:

eea123efc Merge remote-tracking branch 'origin/main' into HEAD
8923dc202 Merge branch 'add-omega-testing-workflow' of https://github.com/xylar/polaris into HEAD
9dfb48ee5 Merge pull request #853 from xylar/add-co-drafted-signature
d6bf2af30 Merge pull request #849 from xylar/add-framework-for-pr-testing
9d6c837f9 Merge pull request #835 from xylar/update-to-mache-5.0.0

Baseline Omega:

cdb935bb5a Merge pull request #600 from xylar/omega/fix-pm-mpi-flags
b90c3dae8d Merge pull request #601 from andrewdnolan/omega/cxx20-for-coupled
9641c6cf9e Merge pull request #546 from xylar/omega/fix-cf-units
55c3de8c15 Merge pull request #566: e3sm/master into omega/develop
9aba4a8032 Merge pull request #597 from xylar/omega/fix-real-literal-nvcc

PR Omega:

efd33f7603 Test merge of E3SM-Project/Omega#523 (ee991bd224) into develop (135755f734)
135755f734 Merge pull request #438 from mwarusz/omega/submesoscale-eddies
a341e65245 Merge pull request #562 from andrewdnolan/omega/guard-division-by-zero
46aa54cd68 Merge pull request #603 from vanroekel/vanroekel/omega/kpp-bug-fix
9656466bb6 Merge PR #570 into develop, resolving Tendencies.cpp initializer order

CTest unit tests:

  • Machine: aurora
  • Compiler: intel
  • Build type: Release
  • Build: /home/brus/run/omega_pr_test/pr523-ee991bd/aurora_intel/build
  • Omega: efd33f760307a9f2eede9ad03438732f40b8b7c7 (Omega-v0.1.0-alpha.1-6242-gefd33f7603)
  • Result: All tests passed
  • Log: /home/brus/run/omega_pr_test/pr523-ee991bd/aurora_intel/build/ctests.log

Build warnings

No new warnings (14 in the PR build, 14 in the baseline build).

  • Baseline build log: /home/brus/run/omega_pr_test/baselines/aurora_intel_polaris-eea123e_omega-cdb935b/build/build_omega.log
  • PR build log: /home/brus/run/omega_pr_test/pr523-ee991bd/aurora_intel/build/build_omega.log
aurora, intelgpu, mpich

Polaris omega_pr suite

  • Baseline workdir: /home/brus/run/omega_pr_test/baselines/aurora_intelgpu_polaris-eea123e_omega-cdb935b/omega_pr
  • Baseline build: /home/brus/run/omega_pr_test/baselines/aurora_intelgpu_polaris-eea123e_omega-cdb935b/build
  • PR build: /home/brus/run/omega_pr_test/pr523-ee991bd/aurora_intelgpu/build
  • PR workdir: /home/brus/run/omega_pr_test/pr523-ee991bd/aurora_intelgpu/omega_pr
  • Polaris: eea123efca8fc7a955a8f57029fab5aaa1d2296a (1.1.0-177-geea123efc)
  • Baseline Omega: cdb935bb5a8d995b0878616e001a2701a2627519 (Omega-v0.1.0-alpha.1-6142-gcdb935bb5a)
  • PR Omega: efd33f760307a9f2eede9ad03438732f40b8b7c7 (Omega-v0.1.0-alpha.1-6242-gefd33f7603)
  • Machine: aurora
  • Compiler: intelgpu
  • Build type: Release
  • Log: /home/brus/run/omega_pr_test/pr523-ee991bd/aurora_intelgpu/omega_pr/polaris_omega_pr.o8947885
  • Result: All tests passed
Recent commits

Polaris:

eea123efc Merge remote-tracking branch 'origin/main' into HEAD
8923dc202 Merge branch 'add-omega-testing-workflow' of https://github.com/xylar/polaris into HEAD
9dfb48ee5 Merge pull request #853 from xylar/add-co-drafted-signature
d6bf2af30 Merge pull request #849 from xylar/add-framework-for-pr-testing
9d6c837f9 Merge pull request #835 from xylar/update-to-mache-5.0.0

Baseline Omega:

cdb935bb5a Merge pull request #600 from xylar/omega/fix-pm-mpi-flags
b90c3dae8d Merge pull request #601 from andrewdnolan/omega/cxx20-for-coupled
9641c6cf9e Merge pull request #546 from xylar/omega/fix-cf-units
55c3de8c15 Merge pull request #566: e3sm/master into omega/develop
9aba4a8032 Merge pull request #597 from xylar/omega/fix-real-literal-nvcc

PR Omega:

efd33f7603 Test merge of E3SM-Project/Omega#523 (ee991bd224) into develop (135755f734)
135755f734 Merge pull request #438 from mwarusz/omega/submesoscale-eddies
a341e65245 Merge pull request #562 from andrewdnolan/omega/guard-division-by-zero
46aa54cd68 Merge pull request #603 from vanroekel/vanroekel/omega/kpp-bug-fix
9656466bb6 Merge PR #570 into develop, resolving Tendencies.cpp initializer order

CTest unit tests:

  • Machine: aurora
  • Compiler: intelgpu
  • Build type: Release
  • Build: /home/brus/run/omega_pr_test/pr523-ee991bd/aurora_intelgpu/build
  • Omega: efd33f760307a9f2eede9ad03438732f40b8b7c7 (Omega-v0.1.0-alpha.1-6242-gefd33f7603)
  • Failures (1 of 61):
    • SUBMESOEDDIES_TEST
  • Log: /home/brus/run/omega_pr_test/pr523-ee991bd/aurora_intelgpu/build/ctests.log

Build warnings

2 new warnings, 0 in files this PR changes (244 in the PR build, 258 in the baseline build). Those in files the PR changes are marked *.

New warnings
  externals/scorpio/src/clib/core/pioc.cpp: variable length arrays in C++ are a Clang extension [-Wvla-cxx-extension][ 40%] Building C object _deps/libdwarf-build/src/lib/libdwarf/CMakeFiles/dwarf.dir/dwarf_ranges.c.o
  externals/scorpio/src/clib/core/pioc_support.cpp: variable length arrays in C++ are a Clang extension [-Wvla-cxx-extension]<omega>/externals/scorpio/src/clib/core/pio_getput_int.cpp
  • Baseline build log: /home/brus/run/omega_pr_test/baselines/aurora_intelgpu_polaris-eea123e_omega-cdb935b/build/build_omega.log
  • PR build log: /home/brus/run/omega_pr_test/pr523-ee991bd/aurora_intelgpu/build/build_omega.log

Notes

SUBMESOEDDIES_TEST fails on aurora intelgpu only (it passes on aurora intel). It aborts at SubmesoEddiesTest.cpp:747. That test comes from develop (Omega#438, merged since the Polaris pin) and is not part of this PR, so the failure is probably a SYCL/GPU issue in develop rather than something this PR caused. I did not confirm this against a build of develop alone. The two new warnings are Clang VLA-extension warnings in externals/scorpio, outside the files this PR changes.

@sbrus89
sbrus89 merged commit 1feac2f into E3SM-Project:develop Oct 20, 2026
8 checks passed
@rljacob

rljacob commented Oct 20, 2026

Copy link
Copy Markdown
Member

Yeah! Someone should make a PR to remove "Vmct" from the CIME-based tests.

@andrewdnolan

Copy link
Copy Markdown
Collaborator

@rljacob This was the last box to check for #604! I'll get work on getting a PR up to close that issue.

sbrus89 added a commit that referenced this pull request Oct 23, 2026
During coupled simulation standard output (stdout) is shared across all 
components and routed to e3sm.log. This PR adds an option to make stdout/stderr
redirection to the omega log optional, which we need during coupled builds.
Nothing about standalone logging in changed; redirection is true by default.

This came up while testing #523, which is another C++ library. This has not come
up previously, because all other coupled testing used all Fortran components.

Closes #605
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Coupled Changes (should) only affect coupled configurations

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants