Add SfcCoupling class as an interface layer to the coupler #458
Add SfcCoupling class as an interface layer to the coupler #458andrewdnolan wants to merge 27 commits into
SfcCoupling class as an interface layer to the coupler #458Conversation
Avg - for averaged fields Inst - for instantaneous fields (ie. SSH) Acc - for accumulated fields (to be added later)
Host array for the OcnToCplFields class were made private to protect from different units on host and device array. Needed to balance performance with correct units.
|
@andrewdnolan Besides the ctest, is testing this as a part of e3sm also possible (with cpl history output)? |
|
@cbegeman Not quite yet, there will be some work to get the coupled driver branch hook up to use this branch. I can try to get that working, but that testing would be pretty ad-hoc. I think it'd be best to get this in with just the CTest testing, with the understanding that this PR is just a first pass, and a follow on will be needed to fully "hook things up". That being said, I tried to be very thorough in the CTest and have mock pointers that mimic the raw attribute vectors passed by the coupler. I have tests for both unpacking (import) and packing (export) with both MCT and MOAB layouts. The data varies per-field and per cell, so a pretty reasonable test. I feel fairly confident in the code mechanics here, given the CTest, though there will absolutely be more work to get physically meaningful coupling. (But that will be dependent on a coupled driver). |
|
@andrewdnolan Thanks for clarifying! That all sounds good. |
|
|
||
| // Kokkok views created with a label are zero-initialized by default. | ||
| // We reset the fields here anyway to be explicit about the fact that the | ||
| // OcnToCpl fields need to being a coupling interval with all zeros. |
There was a problem hiding this comment.
Whoops, it should be "begin" not "being". With that I think the sentence makes sense. Thanks for catching that!
| deepCopy(InstSshCellH, SSHCellOwned); | ||
| } | ||
|
|
||
| // OcnToCpl fields need to being a coupling interval with all values set to 0. |
There was a problem hiding this comment.
I'm confused on what this is supposed to say... is it "...need to bring..."?
There was a problem hiding this comment.
Whoops, "begin" not "being". Fixed. Thanks for catching that!
| } | ||
|
|
||
| // OcnToCpl fields need to being a coupling interval with all values set to 0. | ||
| void OcnToCplFields::resetFields() { |
There was a problem hiding this comment.
Is resetting everything to 0 the safest thing here? Maybe I am misunderstanding, but is the a chance that these zeros could not be overwritten and get sent to the coupler?
There was a problem hiding this comment.
Yes, we need to be able to reset all field to zero. The field contained in OcnToCpl are averaged fields, so each ocean time step (within the coupling interval) we calculate the update average. Given the average function: if we did not have a way to reset values to zero at the end of a coupling interval, these values would continue accumulating over the whole simulation, which is no good.
So this should only be called at then end of coupling interval, after the SfcCoupling::exportToCoupler has been called.
There was a problem hiding this comment.
Ok, that makes sense. Now I understand the need to reset. I guess is there a change nothing gets accumulated in those averages and we send 0 to the coupler? I think for ssh or velocity that would be fine, but not so much for temp or salt.
There was a problem hiding this comment.
The checks we have in place ensure zero values will never be exported to the coupler.
A rough sketch of what the coupled version of ocnRun will look like is in the design doc. We check to make sure the ocean timestep is less than the coupling interval and that they are evenly divisible (see here). So we are guaranteed that at least one iteration of the while loop in the coupled version of ocnRun will run, so at least one call to SfcCoupling::updateExportFields will happen (i.e. non zero export fields).
And OcnToCplField.resetFields() is called at the end of SfcCoupling::exportToCoupler(), so there's no confusion about when it should be called.
The coupled version of ocnRun will be implemented in the coupled driver PR, in the coming week(s), but this should set us up nicely for it.
| return Array; | ||
| } | ||
|
|
||
| // Shaed index formula for packing/unpacking from rae coupler buffer |
There was a problem hiding this comment.
Thanks for catching that. "rae" was meant to be "raw".
|
Ran CTests on PM-CPU and GPU. All tests passed on CPU, but |
Rename SurfaceCoupling -> SfcCoupling throughout; document split CplToOcnFields/OcnToCplFields containers, Welford running-average accumulation, attachData's unmanaged strided views, and the import/apply/update/export method flow to match the implementation in #458. Document the once-per-interval unit conversion added in #458: device averages stay in native units for correct Welford math, conversion (temperature only; salinity is a TODO) happens once per interval in copyToHost via a local Teos10Eos, and the device arrays are private on OcnToCplFields so external code can't read unconverted data.
Co-authored-by: Carolyn Begeman <cbegeman@lanl.gov>
6e673da to
1e8058c
Compare
|
@andrewdnolan Let me know if it would be helpful to run the ctests on a particular machine. I imagine I should perhaps wait until we have a fix for the pm-gpu fail. |
|
@cbegeman I will work on debugging the But agreed, probably not worth testing on another machine till that's addressed. |
TestingCTest unit tests
Polaris
|
| KOKKOS_INLINE_FUNCTION Real updateAverage(const Real OldAvg, | ||
| const Real NewValue, | ||
| const I4 NAccumSteps) { | ||
| return OldAvg + (NewValue - OldAvg) / (NAccumSteps + 1); |
There was a problem hiding this comment.
I had to check:
(NAccumSteps + 1) makes sense because NAccumSteps is updated after updateAverage() is called (via updateFields()).
There was a problem hiding this comment.
Yeah NAccumSteps starts a coupling interval with a value of zero and is incremented at the end of the ocean timestep, so the +1 is necessary. This is following the MPAS-Ocean approach (see here).
alicebarthel
left a comment
There was a problem hiding this comment.
Approving after visual inspection.
alicebarthel
left a comment
There was a problem hiding this comment.
Approving after visual inspection.
|
@andrewdnolan Is this now ready to test on another machine? Any recommendations as to which? |
|
I'll test on Frontier today. |
Co-authored-by: alicebarthel <36741014+alicebarthel@users.noreply.github.com>
3dfd90f to
d0ac984
Compare
| parallelFor( | ||
| {(int)AvgSfcTemperature.extent(0)}, KOKKOS_LAMBDA(int Cell) { | ||
| const Real Ct = LocAvgSfcTemp(Cell); | ||
| const Real Sa = LocAvgSfcSalinity(Cell); |
There was a problem hiding this comment.
@andrewdnolan It doesn't have to be added now but a first order absolute salinity --> practical salinity can be done using the factor I put in GlobalConstants.h:
| const Real Sa = LocAvgSfcSalinity(Cell); | |
| const Real Sa = LocAvgSfcSalinity(Cell) / Psu2Gpkg; // AbsSal to Practical conversion |
The port that @katsmith133 was working on adds the spatial variability of the conversion, but that's second order. I'd recommend punting the full port to later.
Thoughts?
There was a problem hiding this comment.
I'm inclined to hold off until a follow up PR. This first one is primarily focused on code mechanics so that we can build out the coupled driver. Once the first pass at the coupled driver is finished, we can return to this and work improve the physical fidelity of the coupling.
There was a problem hiding this comment.
That's totally fine by me. I just wanted to flag this since I was talking about it to you and Kat both.
jonbob
left a comment
There was a problem hiding this comment.
We verified that the sequence changes in the initial routine are valid, by making ocn_comp_mct in mpaso work in a similar way and passing ERS tests
TestingCTest unit tests
Re-ran CTests on both |
Adds
SfcCoupling, which manages the variables exchanged to (o2x) and from (x2o) the coupler for a sub-domain of the global mesh.Changes
SfcCouplingclass supporting bothMCTandMOABcoupling layoutsCouplingLayoutEnum allows for CTesting ofMCT(column major) andMOAB(row major) layouts.applyImportFields()to push imported fields intoForcingupdateExportFields()to accumulate running averages of export fields on-deviceKnown limitations
Checklist
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 build