-
Notifications
You must be signed in to change notification settings - Fork 0
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add 3d thermal forcing to OCN-GLC coupling #121
base: master
Are you sure you want to change the base?
Add 3d thermal forcing to OCN-GLC coupling #121
Conversation
b8b7531
to
c275d15
Compare
@cbegeman , @xylar , I marked you both as reviewers. I think a review from one of you is sufficient, but I wanted this on both of your radars. Other people who may want to look at this or weigh in on details (but I don't think a review is required): @irenavankova, @darincomeau , @alexolinhager, @trhille |
@jonbob , see note above about new OCN2GLC_TF_SMAPNAME mapping files. Let me know if you want me to create those or if you prefer to do so. |
After talking with @darincomeau , it became clear that there already is an unused coupler variable for ice-sheet runoff flux to the ocean, Here is a figure showing that the facemeling flux in MALI is being received by MPAS-Ocean properly. You have to zoom far in to see the nonzero facemelt flux values on the 8km MALI mesh, so they are highlighted with red circles. This run dies in sea ice, so more work needs to go into confirming the flux magnitude is reasonable (for reference, the value at the mouth of the Amazon is 2e-4) and if some sort of smoothing needs to be added (which might requires separating this flux from |
This commit adds the ability to support a variable number of ocean z-levels for coupling ocean state fields between OCN and GLC. The intended use case is passing profiles of thermal forcing (and possibly eventually temperature and salinity) from OCN to GLC, for MALI to use for driving parameterizations of marine melting that is unresolved in MPAS-Ocean (facemelting or ice shelves that are unresolved on the ocean mesh). The implementation closely mirrors that already existing for GLC multiple elevation classes used for coupling surface mass balance with the LND component. This commit introduces the changes to the coupler and configuration files needed to support multiple z-ocean classes, but no changes are made to introduce them into MPAS-Ocean or MALI.
The number of GLC z-levels defaults to 0 (meaning no z-level coupling), but it set to 30 for any compset where both MPAS-Ocean and MALI are active.
The commit that added glc_zocnclass_mod was a near exact copy of glc_elevclass_mod. This commit makes a number of changes for the functionality needed for z-levels: * Make initialization based on the center of a level * Add an array and an subroutine for initializing the bounds of each level based on assumed relationships to the center values * removal of a subroutine that is unlikely to be ever used * other minor adjustments
This routine initializes the z-levels in MALI using the new mct module
These fields are related to the new 3d thermal forcing and are needed to validate it is working properly. They will also be useful for model analysis.
This commit adds Registry options and MPAS-Ocean code to support a time-averaged 3d thermal forcing field. This follows the implementation of a 2d thermal forcing field at a single depth that was added recently. For now, both 2d and 3d TF functionalities are supported. The time-averaged 3d TF values are calculated in a new variable, avgThermalForcingAtZLevels. The z-levels at which to calculate TF are stored in a variable, glcZLevels. The size of glcZLevels is defined by a new dimension, nGlcZLevels, which is set by a new namelist option, config_n_glc_z_levels. The existing namelist option config_glc_thermal_forcing_coupling_mode is modified to support a ‘3d’ option. mpas_ocn_time_average_coupled.F is modified to calculate avgThermalForcingAtZLevels if the 3d calculation is enabled. Note that in this commit, there is no functionality to initialize glcZLevels. This will happen in a subsequent commit through the coupler. Also note that a package should probably be added for the new fields.
This commit makes it so MPAS-Ocean gets the value of glc_nzoc from the value the E3SM bld system assigns it (which comes from the compset definition). This commit modifies the files in the MPAS-Ocean namelist build system, but does not yet alter the way MPAS-Ocean interacts with coupler at runtime.
Have cime_comp determine it based on what components are active rather than basing it off of MPAS-Ocean namelist options
For the 2d thermal forcing, the OCN2GLC_TF_SMAPNAME map files needed to mask out ocean cells shallower than the coupling depth. For the new 3d thermal forcing coupling, standard mapping is appropriate.
This is needed to configure MPAS-Ocean to work with the 3d TF coupling.
Using ocn_c2_glctf to control TF didn't work, so switching to namelist options in each component.
For the extrapolation in MALI to work properly, extrapolation in the OCN2GLC_TF_SMAPNAME mapping file needs to be disabled. As an initial test, this commit switched from the bilin (which includes extrap) to the aave (which does not) mapping file. The correct behavior in MALI now occurs. A later commit will need to add bilin mapping files without extrapolation for the OCN2GLC_TF_SMAPNAME mapping file for each mesh that includes one.
These liquid runoff fluxes are currently added to the river runoff flux in the coupler before being passed to the ocean. If we want to change the horizontal or vertical distribution of how these are handled in the ocean, we'll need to separate them in the future. Also needed is time averaging of fluxes, which has not yet been implemented in MALI.
This way it will also extract latent heat from the ocean. Note that doing it this way, it will be combined with the calving flux. Long term, we will likely want to handle them separately so they can use different horizontal and vertical distributions. But at present MALI's calving flux is not even hooked up, so that will need to be addressed at a later date.
This updates GLC2OCN_LIQ_RMAPNAME and GLC2OCN_ICE_RMAPNAME mapping files to use nearest neighbor with runoff area rescaling. The old mapping files did not have the area-scaling applied. This needs to be updated for other meshes using these mappers once the updated mapping files are generated.
7243469
to
83c89bb
Compare
@cbegeman and @xylar , I tried changing the melt flux from MALI to MPAS-Ocean to occur through
For the intermediate step of this PR, do you think it is better to switch back to Also, are you sure that |
This commit adds a 3d mask field to MPAS-Ocean for tracking what fraction of time steps in the time average are valid. If the fraction exceeds 0.9, then the driver considers that location valid and passes the value to the coupler along with a coupler mask value of 1. This new coupler mask field matches the dimensionality of the 3d TF field and is passed to MALI. MALI evaluates the mask in its import routine and only uses TF from locations that have at least 50% overlap with MPAS-Ocean cells. In those locations, it uses the TF passed through the coupler, scaled by the area fraction. In location that don't satisfy that criterion, the MALI extrapolation mask is set to 0 and an invalid TF value is inserted in the 3d TF field.
|
I'm fine with switching back to |
@matthewhoffman, I would feel best about using |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@matthewhoffman, I have only partially looked through the code but wanted to flag a significant problem before I continue.
You are using a z-level approach to find the depth that each value in glcZLevels
corresponds to. This is not really a safe assumption anywhere in MPAS-Ocean but it is particularly poor for the Antarctic application because the vertical coordinate is very far from z-level inside of and within about a 20-cell ring around ice-shelf cavities. Instead, we need to find zMid that is closest to a given entry in glcZLevels
.
@@ -55,6 +55,7 @@ OPTIONS | |||
-ninst_glc NINST_GLC for this case | |||
-mali_dynamic turns on dynamic ice sheet mode | |||
Options are: FALSE, TRUE | |||
-glc_nzoc number of z-ocean classes [0 | 4 | 30] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just wanting to check that these are the only 3 supported values. It sounded in our discussion like the number was flexible.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I see, these are hard-coded in glc_zocnclass_init_default()
@@ -72,6 +72,7 @@ OPTIONS | |||
-ninst_ocn NINST_OCN for this case | |||
-ocn_tidal_mixing variable for defining if to run with parameterized tidal mixing | |||
Options are: false, true. Default is false | |||
-glc_nzoc number of z-ocean classes for indirect glc-ocn coupling [0 | 4 | 30] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same question as above: is this restricted to only these 3 values?
lines.append(' output_interval="none">') | ||
lines.append(' output_interval="00-00-01_00:00:00">') |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think we want to make this change.
iLevelCritDepth = nVertLevels ! default to deepest layer if we don't find the desired depth | ||
do iLevel = 1, nVertLevels | ||
if(refBottomDepth(iLevel) > glcZLevels(iLevelGlc)) then | ||
iLevelCritDepth = iLevel | ||
exit | ||
end if | ||
end do |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This determines the level using refBottomDepth
, which is only appropriate for a pure z-level coordinate. Anywhere near Antarctic ice shelves, this will be badly wrong. In cavities, it will be much worse.
Instead, the right level needs to be determined for each cell independently, based on which zMid is closest to the given glcZLevels
. I can help with this but this needs to be fixed before this PR can move over to E3SM.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Rather than finding the nearest depth, it might be worth linearly interpolating to glcZLevels
, but that could wait for a follow-up PR if you prefer.
! note: assuming no LandIce cavity, but we may want to support that | ||
freezingTemp = ocn_freezing_temperature(salinity=activeTracers(indexSalinity, iLevelCritDepth, iCell), & | ||
pressure=pressure(iLevelCritDepth, iCell), inLandIceCavity=.false.) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You always want to use inLandIceCavity=.true.
here. The freezing point when inLandIceCavity=.true.
is only appropriate for the sea surface and only for MPAS-Seaice. It does not vary with pressure, so quite problematic for your purposes.
! calculate thermal forcing at identified level for each cell | ||
do iCell = 1, nCells | ||
! ignore cells that are too shallow | ||
if (iLevelCritDepth <= maxLevelCell(iCell)) then |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This criterion should probably be:
if (iLevelCritDepth <= maxLevelCell(iCell)) then | |
if ((glcZLevels(iLevelGlc) < ssh(iCell)) .and. (glcZLevels(iLevelGlc) >= -bottomDepth(iCell))) then |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Then, iLevelCritDepth
(or some variable of a more appropriate name) should be found to minimize abs(zMid(iCell,:) - glcZLevels(iLevelGlc))
.
@@ -473,7 +490,52 @@ subroutine ocn_time_average_coupled_accumulate(statePool, forcingPool, timeLevel | |||
end do | |||
!$omp end do | |||
!$omp end parallel | |||
endif | |||
elseif (trim(config_glc_thermal_forcing_coupling_mode) == '3d') then |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this is getting complex enough that it may belong in its own subroutine.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Okay, I've looked through the code and what I've mentioned so far seem like my only concerns. I really appreciate what a heap of work this has been. It's really exciting!
|
||
type (mpas_pool_type), pointer :: tracersPool | ||
|
||
real (kind=RKIND), dimension(:,:,:), pointer :: activeTracers | ||
integer, pointer :: indexTemperature, indexSalinity | ||
integer :: iLevelCritDepth, iLevel | ||
integer :: iLevelCritDepth, iLevel, iLevelGlc |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe rename iLevelCritDepth
as used in the 3d code, as it makes less sense there.
@@ -55,6 +55,7 @@ OPTIONS | |||
-ninst_glc NINST_GLC for this case | |||
-mali_dynamic turns on dynamic ice sheet mode | |||
Options are: FALSE, TRUE | |||
-glc_nzoc number of z-ocean classes [0 | 4 | 30] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I see, these are hard-coded in glc_zocnclass_init_default()
select case (glc_nzoc) | ||
case(0) | ||
! do nothing | ||
case(4) | ||
zocn_levels = [-250._r8, -750._r8, -1250._r8, -1750._r8] | ||
case(30) | ||
zocn_levels = [ -30._r8, -90._r8, -150._r8, -210._r8, -270._r8, & | ||
-330._r8, -390._r8, -450._r8, -510._r8, -570._r8, & | ||
-630._r8, -690._r8, -750._r8, -810._r8, -870._r8, & | ||
-930._r8, -990._r8, -1050._r8, -1110._r8, -1170._r8, & | ||
-1230._r8, -1290._r8, -1350._r8, -1410._r8, -1470._r8, & | ||
-1530._r8, -1590._r8, -1650._r8, -1710._r8, -1770._r8] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Any way to make this more general (at least in the longer term)?
This pull request extends the existing thermal forcing functionality from a single depth to a predefined set of z-levels. The coupler implementation follows that of multiple elevation classes in the LND-GLC coupling. A new coupler variable is added, GLC_NZOC. It has a default value of 0, meaning TF coupling is disabled. The standard value for when the coupling is activated is 30, which follows the TF z-levels used by ISMIP6. Other values are supported, and an additional example with 4 levels is included. A new coupler module, glc_zocnclass_mod.F90, is added which is follows very closely from glc_elevclass_mod.F90. It contains subroutines and functions to initialize the ocean z-level classes and to access the z-level values. It also has subroutines to provide the z-level indices as strings, which the coupling field initialization code and the component import/export routines uses to create GLC_NZOC fields, one for each layer.
The intention is that this 3d TF coupling will be used for facemelting (melting at vertical glacier margins terminating in the ocean), and so is used for a process that we do not anticipate resolving explicitly in MPAS-Ocean. As such, this coupling should be included anytime both OCN and GLC are active, and logic has been added so that this is the case based on compset definition. There are versions of the GLC_NZOC variable in both the MPAS-Ocean and MALI Registries so that it can be set by namelist settings controlled by CIME/build operations.
The MPAS-Ocean mpas_ocn_time_average_coupled.F module has been modified to loop over the z-levels and calculate TF at each one. Then, the time-averaged 3d TF values are passed to the coupler, where they are remapped to the GLC mesh and passed to MALI. MALI assigns the values to the existing 3d TF field, and the uses its bathymetry-aware extrapolation routine to extrapolate the TF values from the edge of the MPAS-Ocean domain to wherever the ice-sheet margin is on the MALI mesh. From there, the TF is used to force the facemelting parameterization.
The facemelting flux in MALI is exported to the previously unused Fogg_rofl flux, which already gets combined in the coupler with river runoff to be imported in MPAS-Ocean in the Foxx_rofl flux. Long term, we may want to separate these runoff fluxes so that the horizontal and vertical distribution of facemelting can be handled differently than river runoff, but this provides a reasonable first approximation.
Note that this 3d TF can also be used to force the ISMIP6 ice-shelf basal melt parameterization in MALI, which provides a less sophisticated alternative to using ice-shelf basal melt rates calculated in the coupler (or MPAS-Ocean). This simpler approach will be used for the few, small ice shelves in Greenland, which are not included in the MPAS-Ocean meshes (and would not be resolved even if they were). This approach could also be used for Antarctica as an alternative that avoids grounding line migration issues in MPAS-Ocean by taking advantage of the TF extrapolation in MALI.
This PR is now functional, but some additional work is needed before this is complete and ready for review at the main E3SM repo: