diff --git a/cime_config/config_grids.xml b/cime_config/config_grids.xml
index 0f1c3512ec8a..fd9258051f75 100755
--- a/cime_config/config_grids.xml
+++ b/cime_config/config_grids.xml
@@ -1899,6 +1899,16 @@
IcoswISC30E3r5
+
+ TL319
+ TL319
+ oQU240wLI
+ JRA025
+ mpas.gis20km
+ null
+ oQU240wLI
+
+
TL319
TL319
@@ -1909,6 +1919,16 @@
IcoswISC30E3r5
+
+ TL319
+ TL319
+ IcoswISC30E3r5
+ JRA025
+ mpas.gis1to10kmR2
+ null
+ IcoswISC30E3r5
+
+
ne30np4.pg2
r05
@@ -5503,15 +5523,15 @@
-
-
+
+
-
-
+
+
@@ -5528,8 +5548,8 @@
-
-
+
+
@@ -5555,9 +5575,21 @@
+
+
+
+
+
+
+
+
+
+
+
+
-
-
+
+
@@ -5567,8 +5599,9 @@
-
-
+
+
+
@@ -5603,8 +5636,8 @@
-
-
+
+
@@ -5614,8 +5647,8 @@
-
-
+
+
@@ -5650,8 +5683,8 @@
-
-
+
+
@@ -5661,8 +5694,9 @@
-
-
+
+
+
@@ -5690,8 +5724,8 @@
-
-
+
+
@@ -5719,8 +5753,8 @@
-
-
+
+
@@ -5730,8 +5764,8 @@
-
-
+
+
@@ -5759,8 +5793,8 @@
-
-
+
+
@@ -5877,11 +5911,11 @@
-
+
-
+
@@ -5891,8 +5925,8 @@
-
-
+
+
@@ -5902,8 +5936,8 @@
-
-
+
+
diff --git a/cime_config/tests.py b/cime_config/tests.py
index 1cbf28b83974..5205d226998b 100644
--- a/cime_config/tests.py
+++ b/cime_config/tests.py
@@ -266,6 +266,7 @@
"SMS_D_Ld1.T62_oQU240wLI.GMPAS-IAF-PISMF.mpaso-impl_top_drag",
"SMS_D_Ld1.T62_oQU240.GMPAS-IAF.mpaso-harmonic_mean_drag",
"SMS_D_Ld1.T62_oQU240.GMPAS-IAF.mpaso-upwind_advection",
+ "ERS_Ld5.TL319_oQU240wLI_gis20.MPAS_LISIO_JRA1p5.mpaso-ocn_glc_tf_coupling",
)
},
diff --git a/components/mpas-albany-landice/bld/namelist_files/namelist_defaults_mali.xml b/components/mpas-albany-landice/bld/namelist_files/namelist_defaults_mali.xml
index 0450eb44f116..1b0a9b19195b 100644
--- a/components/mpas-albany-landice/bld/namelist_files/namelist_defaults_mali.xml
+++ b/components/mpas-albany-landice/bld/namelist_files/namelist_defaults_mali.xml
@@ -98,7 +98,7 @@
1.0
0.0
0.25
-'none'
+'ismip6'
.false.
1.18
0.0
diff --git a/components/mpas-albany-landice/cime_config/buildnml b/components/mpas-albany-landice/cime_config/buildnml
index 9489b6dfa8fd..4256df0f2830 100755
--- a/components/mpas-albany-landice/cime_config/buildnml
+++ b/components/mpas-albany-landice/cime_config/buildnml
@@ -88,7 +88,7 @@ def buildnml(case, caseroot, compname):
decomp_date += '051920'
decomp_prefix += 'mpasli.graph.info.'
elif glc_grid == 'mpas.gis1to10kmR2':
- grid_date += '20230202'
+ grid_date += '20240513'
grid_prefix += 'gis_1to10km_r02'
decomp_date += '020223'
decomp_prefix += 'mpasli.graph.info.'
@@ -247,6 +247,9 @@ def buildnml(case, caseroot, compname):
lines.append(' ')
lines.append(' ')
lines.append(' ')
+ lines.append(' ')
+ lines.append(' ')
+ lines.append(' ')
lines.append(' ')
lines.append(' ')
lines.append(' ')
diff --git a/components/mpas-albany-landice/driver/glc_comp_mct.F b/components/mpas-albany-landice/driver/glc_comp_mct.F
index ac33d17b1f31..aa96525661b8 100644
--- a/components/mpas-albany-landice/driver/glc_comp_mct.F
+++ b/components/mpas-albany-landice/driver/glc_comp_mct.F
@@ -80,6 +80,8 @@ module glc_comp_mct
integer :: glcLogUnit ! unit number for glc log
+ logical :: ocn_c2_glctf ! .true. => ocn to glc thermal forcing coupling on
+
! MPAS Datatypes
!type (dm_info), pointer :: dminfo
type (core_type), pointer :: corelist => null()
@@ -522,6 +524,9 @@ end subroutine xml_stream_get_attributes
! Determine coupling type (not currently needed by MALI)
call seq_infodata_GetData(infodata, cpl_seq_option=cpl_seq_option)
+ ! Determine if ocn to glc thermal forcing coupling is on
+ call seq_infodata_GetData(infodata, ocn_c2_glctf=ocn_c2_glctf)
+
! Initialize the MALI core
ierr = domain % core % core_init(domain, timeStamp)
if ( ierr /= 0 ) then
@@ -1383,7 +1388,8 @@ subroutine glc_import_mct(x2g_g, errorCode)
floatingBasalMassBal,&
surfaceTemperature,&
basalOceanHeatflx,&
- OceanDensity
+ OceanDensity, &
+ ismip6_2dThermalForcing
errorCode = 0
@@ -1401,6 +1407,7 @@ subroutine glc_import_mct(x2g_g, errorCode)
call mpas_pool_get_array(geometryPool, 'sfcMassBal', sfcMassBal)
call mpas_pool_get_array(geometryPool, 'floatingBasalMassBal',floatingBasalMassBal)
call mpas_pool_get_array(thermalPool, 'surfaceTemperature',surfaceTemperature)
+ call mpas_pool_get_array(geometryPool, 'ismip6_2dThermalForcing', ismip6_2dThermalForcing)
! call mpas_pool_get_array(thermalPool, 'basalOceanHeatflx',basalOceanHeatflx)
!call mpas_pool_get_array(geometryPool, 'OceanDensity',OceanDensity)
@@ -1408,6 +1415,8 @@ subroutine glc_import_mct(x2g_g, errorCode)
n = n + 1
sfcMassBal(i) = x2g_g % rAttr(index_x2g_Flgl_qice, n)
floatingBasalMassBal(i) = x2g_g % rAttr(index_x2g_Fogx_qiceli, n)
+ if (ocn_c2_glctf) &
+ ismip6_2dThermalForcing(i) = x2g_g % rAttr(index_x2g_So_tf2d, n)
! surfaceTemperature(i) = x2g_g % rAttr(index_x2g_Sl_tsrf, n)
!JW basalOceanHeatflx(i) = x2g_g % rAttr(index_x2g_Fogo_qiceh, n)
! basalOceanHeatflx(i) = x2g_g % rAttr(index_x2g_Fogx_qicehi, n)
diff --git a/components/mpas-albany-landice/driver/glc_cpl_indices.F b/components/mpas-albany-landice/driver/glc_cpl_indices.F
index 123185225f82..459b534a7e07 100644
--- a/components/mpas-albany-landice/driver/glc_cpl_indices.F
+++ b/components/mpas-albany-landice/driver/glc_cpl_indices.F
@@ -22,6 +22,7 @@ module glc_cpl_indices
integer, public :: index_x2g_So_htv = 0 !Ice shelf ocean heat transfer velocity
integer, public :: index_x2g_So_stv = 0 !Ice shelf ocean salinity transfer velocity
integer, public :: index_x2g_So_rhoeff = 0 !Ocean effective pressure
+ integer, public :: index_x2g_So_tf2d = 0 !Ocean thermal forcing at predefined critical depth
integer, public :: index_x2g_Fogx_qiceli = 0 !Subshelf mass flux
integer, public :: index_x2g_Fogx_qicehi = 0 !Subshelf heat flux for the ice sheet
@@ -70,6 +71,7 @@ subroutine glc_cpl_indices_set( )
index_x2g_Fogx_qiceli = mct_avect_indexra(x2g,'Fogx_qiceli',perrwith='quiet')
index_x2g_Fogx_qicehi = mct_avect_indexra(x2g,'Fogx_qicehi',perrwith='quiet')
index_x2g_So_rhoeff = mct_avect_indexra(x2g,'So_rhoeff',perrwith='quiet')
+ index_x2g_So_tf2d = mct_avect_indexra(x2g,'So_tf2d',perrwith='quiet')
!Following block of x2g/g2x vectors are used internally within coupler for subshelf melt flux
!calculations (and so do not have directly-related export-side arrays)
diff --git a/components/mpas-ocean/bld/build-namelist b/components/mpas-ocean/bld/build-namelist
index 460b9ecda428..e492acc89adf 100755
--- a/components/mpas-ocean/bld/build-namelist
+++ b/components/mpas-ocean/bld/build-namelist
@@ -731,6 +731,8 @@ if (($OCN_ICEBERG eq 'true') && ($OCN_FORCING eq 'active_atm')) {
} else {
add_default($nl, 'config_remove_ais_ice_runoff', 'val'=>".false.");
}
+add_default($nl, 'config_glc_thermal_forcing_coupling_mode');
+add_default($nl, 'config_2d_thermal_forcing_depth');
######################################
# Namelist group: shortwaveRadiation #
diff --git a/components/mpas-ocean/bld/build-namelist-section b/components/mpas-ocean/bld/build-namelist-section
index c5dad5d935a9..88e81ab25099 100644
--- a/components/mpas-ocean/bld/build-namelist-section
+++ b/components/mpas-ocean/bld/build-namelist-section
@@ -239,6 +239,8 @@ add_default($nl, 'config_sgr_salinity_prescribed');
add_default($nl, 'config_remove_ais_river_runoff');
add_default($nl, 'config_remove_ais_ice_runoff');
+add_default($nl, 'config_glc_thermal_forcing_coupling_mode');
+add_default($nl, 'config_2d_thermal_forcing_depth');
######################################
# Namelist group: shortwaveRadiation #
diff --git a/components/mpas-ocean/bld/namelist_files/namelist_defaults_mpaso.xml b/components/mpas-ocean/bld/namelist_files/namelist_defaults_mpaso.xml
index fd2785616655..09965cb8ac85 100644
--- a/components/mpas-ocean/bld/namelist_files/namelist_defaults_mpaso.xml
+++ b/components/mpas-ocean/bld/namelist_files/namelist_defaults_mpaso.xml
@@ -354,6 +354,8 @@
.false.
.false.
+'off'
+300.0
'jerlov'
diff --git a/components/mpas-ocean/bld/namelist_files/namelist_definition_mpaso.xml b/components/mpas-ocean/bld/namelist_files/namelist_definition_mpaso.xml
index bea1e98d9de8..ce48de48d5eb 100644
--- a/components/mpas-ocean/bld/namelist_files/namelist_definition_mpaso.xml
+++ b/components/mpas-ocean/bld/namelist_files/namelist_definition_mpaso.xml
@@ -1271,6 +1271,22 @@ Valid values: .true. or .false.
Default: Defined in namelist_defaults.xml
+
+If and how MPAS-Ocean sends thermal forcing to GLC (MALI) in E3SM. This is used for ocean coupling with a melt parameterization for grounded marine ice-cliffs in MALI. This is primarily relevant to the Greenland Ice Sheet, but also relevant to the Antarctic Ice Sheet. 'none' means no coupling of thermal forcing. '2d' means thermal forcing at a prescribed depth is passed to GLC. That depth is controlled by 'config_2d_thermal_forcing_depth', and the resulting thermal forcing field is calculated in the field 'avgThermalForcingAtCritDepth'.
+
+Valid values: 'off', '2d'
+Default: Defined in namelist_defaults.xml
+
+
+
+Depth at which to pass 2d thermal forcing to the coupler for use in the GLC component. Note that mapping files for this field must be created with a mask to exclude ocean grid cells shallower than this value and thus must be regenerated if this value is changed.
+
+Valid values: any non-negative value
+Default: Defined in namelist_defaults.xml
+
+
diff --git a/components/mpas-ocean/cime_config/testdefs/testmods_dirs/mpaso/ocn_glc_tf_coupling/README b/components/mpas-ocean/cime_config/testdefs/testmods_dirs/mpaso/ocn_glc_tf_coupling/README
new file mode 100644
index 000000000000..bd801c44f8af
--- /dev/null
+++ b/components/mpas-ocean/cime_config/testdefs/testmods_dirs/mpaso/ocn_glc_tf_coupling/README
@@ -0,0 +1,12 @@
+This testdef is used to test a stealth feature that enables coupling between
+OCN and GLC for Greenland, which passes ocean thermal forcing from OCN to GLC
+and uses that in a parameterization for marine melting of grounded vertical
+cliffs.
+
+It changes one mpaso namelist variable,
+ config_glc_thermal_forcing_coupling_mode
+from its default value to '2d'.
+This tests the ocn/glc TF coupling.
+
+It also specified that DATM forcing should be restricted to 1958.
+This allows JRA1p5 forcing to be used without a large input data requirement.
diff --git a/components/mpas-ocean/cime_config/testdefs/testmods_dirs/mpaso/ocn_glc_tf_coupling/shell_commands b/components/mpas-ocean/cime_config/testdefs/testmods_dirs/mpaso/ocn_glc_tf_coupling/shell_commands
new file mode 100644
index 000000000000..1d43ad8c5baf
--- /dev/null
+++ b/components/mpas-ocean/cime_config/testdefs/testmods_dirs/mpaso/ocn_glc_tf_coupling/shell_commands
@@ -0,0 +1,4 @@
+./xmlchange DATM_CLMNCEP_YR_START=1958
+./xmlchange DATM_CLMNCEP_YR_END=1958
+./xmlchange DROF_STRM_YR_START=1958
+./xmlchange DROF_STRM_YR_END=1958
diff --git a/components/mpas-ocean/cime_config/testdefs/testmods_dirs/mpaso/ocn_glc_tf_coupling/user_nl_mpaso b/components/mpas-ocean/cime_config/testdefs/testmods_dirs/mpaso/ocn_glc_tf_coupling/user_nl_mpaso
new file mode 100644
index 000000000000..0e1378620836
--- /dev/null
+++ b/components/mpas-ocean/cime_config/testdefs/testmods_dirs/mpaso/ocn_glc_tf_coupling/user_nl_mpaso
@@ -0,0 +1 @@
+config_glc_thermal_forcing_coupling_mode = '2d'
diff --git a/components/mpas-ocean/driver/mpaso_cpl_indices.F b/components/mpas-ocean/driver/mpaso_cpl_indices.F
index f099cf8ea46a..9802d526bc50 100644
--- a/components/mpas-ocean/driver/mpaso_cpl_indices.F
+++ b/components/mpas-ocean/driver/mpaso_cpl_indices.F
@@ -37,6 +37,7 @@ module mpaso_cpl_indices
integer :: index_o2x_So_htv !ocean heat-transfer velocity
integer :: index_o2x_So_stv !ocean salt-transfer velocity
integer :: index_o2x_So_rhoeff !ocean effective density
+ integer :: index_o2x_So_tf2d !ocean thermal forcing at predefined critical depth
! ocn -> drv (BGC)
@@ -208,6 +209,7 @@ subroutine mpaso_cpl_indices_set( )
index_o2x_So_htv = mct_avect_indexra(o2x,'So_htv')
index_o2x_So_stv = mct_avect_indexra(o2x,'So_stv')
index_o2x_So_rhoeff = mct_avect_indexra(o2x,'So_rhoeff')
+ index_o2x_So_tf2d = mct_avect_indexra(o2x,'So_tf2d',perrWith='quiet')
index_o2x_So_algae1 = mct_avect_indexra(o2x,'So_algae1',perrWith='quiet')
index_o2x_So_algae2 = mct_avect_indexra(o2x,'So_algae2',perrWith='quiet')
diff --git a/components/mpas-ocean/driver/ocn_comp_mct.F b/components/mpas-ocean/driver/ocn_comp_mct.F
index d1b140563bb7..b03b8cf72a91 100644
--- a/components/mpas-ocean/driver/ocn_comp_mct.F
+++ b/components/mpas-ocean/driver/ocn_comp_mct.F
@@ -108,6 +108,8 @@ module ocn_comp_mct
integer :: nsend, nrecv
+ logical :: ocn_c2_glctf ! .true. => ocn to glc thermal forcing coupling on
+
character(len=StrKIND) :: runtype, coupleTimeStamp
type(seq_infodata_type), pointer :: infodata
@@ -223,6 +225,7 @@ subroutine ocn_init_mct( EClock, cdata_o, x2o_o, o2x_o, NLFilename )!{{{
logical, pointer :: config_use_activeTracers_surface_restoring
logical, pointer :: config_use_surface_salinity_monthly_restoring
character (len=StrKIND), pointer :: config_land_ice_flux_mode
+ character (len=StrKIND), pointer :: config_glc_thermal_forcing_coupling_mode
! ssh coupling interval initialization
integer, pointer :: index_avgZonalSSHGradient, index_avgMeridionalSSHGradient
@@ -304,6 +307,9 @@ end subroutine xml_stream_get_attributes
! Determine coupling type
call seq_infodata_GetData(infodata, cpl_seq_option=cpl_seq_option)
+ ! Determine if ocn to glc thermal forcing coupling is on
+ call seq_infodata_GetData(infodata, ocn_c2_glctf=ocn_c2_glctf)
+
!-----------------------------------------------------------------------
!
! initialize the model run
@@ -878,6 +884,16 @@ end subroutine xml_stream_get_attributes
call mpas_log_write('ERROR: unknown land_ice_flux_mode: ' // trim(config_land_ice_flux_mode), MPAS_LOG_CRIT)
end if
+ call mpas_pool_get_config(domain % configs, 'config_glc_thermal_forcing_coupling_mode', config_glc_thermal_forcing_coupling_mode)
+ if ( trim(config_glc_thermal_forcing_coupling_mode) == 'off' ) then
+ call seq_infodata_PutData(infodata, ocn_c2_glctf=.false.)
+ else if ( trim(config_glc_thermal_forcing_coupling_mode) == '2d' ) then
+ call seq_infodata_PutData(infodata, ocn_c2_glctf=.true.)
+ else
+ call mpas_log_write('ERROR: unknown config_glc_thermal_forcing_coupling_mode: ' // &
+ trim(config_glc_thermal_forcing_coupling_mode), MPAS_LOG_CRIT)
+ end if
+
!-----------------------------------------------------------------------
!
! get initial state from driver
@@ -2689,7 +2705,8 @@ subroutine ocn_export_mct(o2x_o, errorCode) !{{{
avgRemovedRiverRunoffFlux, &
avgRemovedIceRunoffFlux, &
avgLandIceHeatFlux, &
- avgRemovedIceRunoffHeatFlux
+ avgRemovedIceRunoffHeatFlux, &
+ avgThermalForcingAtCritDepth
real (kind=RKIND), dimension(:,:), pointer :: avgTracersSurfaceValue, avgSurfaceVelocity, &
avgSSHGradient, avgOceanSurfacePhytoC, &
@@ -2708,6 +2725,7 @@ subroutine ocn_export_mct(o2x_o, errorCode) !{{{
config_use_MacroMoleculesTracers_sea_ice_coupling
character (len=StrKIND), pointer :: config_land_ice_flux_mode
+ character (len=StrKIND), pointer :: config_glc_thermal_forcing_coupling_mode
logical :: keepFrazil
@@ -2718,6 +2736,8 @@ subroutine ocn_export_mct(o2x_o, errorCode) !{{{
call mpas_pool_get_config(domain % configs, 'config_land_ice_flux_mode', config_land_ice_flux_mode)
call mpas_pool_get_config(domain % configs, 'config_remove_ais_river_runoff', config_remove_ais_river_runoff)
call mpas_pool_get_config(domain % configs, 'config_remove_ais_ice_runoff', config_remove_ais_ice_runoff)
+ call mpas_pool_get_config(domain % configs, 'config_glc_thermal_forcing_coupling_mode', &
+ config_glc_thermal_forcing_coupling_mode)
call mpas_pool_get_config(domain % configs, 'config_use_DMSTracers', config_use_DMSTracers)
call mpas_pool_get_config(domain % configs, 'config_use_MacroMoleculesTracers', config_use_MacroMoleculesTracers)
call mpas_pool_get_config(domain % configs, 'config_use_ecosysTracers_sea_ice_coupling', &
@@ -2772,6 +2792,9 @@ subroutine ocn_export_mct(o2x_o, errorCode) !{{{
call mpas_pool_get_array(forcingPool, 'avgRemovedIceRunoffFlux', avgRemovedIceRunoffFlux)
call mpas_pool_get_array(forcingPool, 'avgRemovedIceRunoffHeatFlux', avgRemovedIceRunoffHeatFlux)
endif
+ if (trim(config_glc_thermal_forcing_coupling_mode) == '2d') then
+ call mpas_pool_get_array(forcingPool, 'avgThermalForcingAtCritDepth', avgThermalForcingAtCritDepth)
+ endif
! BGC fields
if (config_use_ecosysTracers) then
@@ -2933,6 +2956,10 @@ subroutine ocn_export_mct(o2x_o, errorCode) !{{{
o2x_o % rAttr(index_o2x_So_stv, n) = landIceTracerTransferVelocities(indexSaltTrans,i)
o2x_o % rAttr(index_o2x_So_rhoeff, n) = 0.0_RKIND
endif
+ if (trim(config_glc_thermal_forcing_coupling_mode) == '2d' .and. ocn_c2_glctf) then
+ o2x_o % rAttr(index_o2x_So_tf2d, n) = avgThermalForcingAtCritDepth(i)
+ endif
+
!Fyke: test
!write(stderrUnit,*) 'n=',n
diff --git a/components/mpas-ocean/src/Registry.xml b/components/mpas-ocean/src/Registry.xml
index 2a21e22f40d2..d4cd8cbac5af 100644
--- a/components/mpas-ocean/src/Registry.xml
+++ b/components/mpas-ocean/src/Registry.xml
@@ -807,6 +807,14 @@
description="If true, solid runoff from the Antarctic Ice Sheet (below 60S latitude) coming from the coupled is zeroed in the coupler import routines. To be used with data iceberg fluxes coming from the sea ice model."
possible_values=".true. or .false."
/>
+
+
+
config_2d_thermal_forcing_depth) then
+ iLevelCritDepth = iLevel
+ exit
+ end if
+ end do
+ !$omp parallel
+ !$omp do schedule(runtime)
+ ! calculate thermal forcing at identified level for each cell
+ do iCell = 1, nCells
+ ! ignore cells that are too shallow
+ if (iLevelCritDepth <= maxLevelCell(iCell)) then
+ ! this uses the level shallower than the reference level. could interpolate instead
+ ! 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.)
+ avgThermalForcingAtCritDepth(iCell) = ( avgThermalForcingAtCritDepth(iCell) * nAccumulatedCoupled &
+ + activeTracers(indexTemperature, iLevelCritDepth, iCell) - freezingTemp ) / ( nAccumulatedCoupled + 1)
+ end if
+ end do
+ !$omp end do
+ !$omp end parallel
+ endif
+
! accumulate BGC coupling fields if necessary
if (config_use_ecosysTracers) then
diff --git a/driver-mct/cime_config/buildnml b/driver-mct/cime_config/buildnml
index 4938e9da0b18..c65a6047555c 100755
--- a/driver-mct/cime_config/buildnml
+++ b/driver-mct/cime_config/buildnml
@@ -41,6 +41,7 @@ def _create_drv_namelists(case, infile, confdir, nmlgen, files):
config['CPL_EPBAL'] = case.get_value('CPL_EPBAL')
config['FLDS_WISO'] = case.get_value('FLDS_WISO')
config['FLDS_POLAR'] = case.get_value('FLDS_POLAR')
+ config['FLDS_TF'] = case.get_value('FLDS_TF')
config['BUDGETS'] = case.get_value('BUDGETS')
config['MACH'] = case.get_value('MACH')
config['MPILIB'] = case.get_value('MPILIB')
diff --git a/driver-mct/cime_config/config_component.xml b/driver-mct/cime_config/config_component.xml
index 8cddad0abf89..6fb75609e5a9 100644
--- a/driver-mct/cime_config/config_component.xml
+++ b/driver-mct/cime_config/config_component.xml
@@ -1898,40 +1898,58 @@
glc2ocn runoff mapping file decomp type for ice runoff
-
+
char
idmap_ignore
run_domain
env_run.xml
- ocn2glc flux mapping file - the default value idmap_ignore, if set, will be ignored by buildnml and
+ ocn2glc shelf flux mapping file - the default value idmap_ignore, if set, will be ignored by buildnml and
will generate a runtime error if in fact a file is required for the given compset
-
+
char
X,Y
Y
run_domain
env_run.xml
- ocn2glc flux mapping file decomp type
+ ocn2glc shelf flux mapping file decomp type
-
+
char
idmap_ignore
run_domain
env_run.xml
- ocn2glc state mapping file - the default value idmap_ignore, if set, will be ignored by buildnml and
+ ocn2glc shelf state mapping file - the default value idmap_ignore, if set, will be ignored by buildnml and
will generate a runtime error if in fact a file is required for the given compset
-
+
char
X,Y
Y
run_domain
env_run.xml
- ocn2glc state mapping file decomp type
+ ocn2glc shelf state mapping file decomp type
+
+
+
+ char
+ idmap_ignore
+ run_domain
+ env_run.xml
+ ocn2glc state mapping file for thermal forcing - the default value idmap_ignore, if set, will be ignored by buildnml and
+ will generate a runtime error if in fact a file is required for the given compset
+
+
+
+ char
+ X,Y
+ Y
+ run_domain
+ env_run.xml
+ ocn2glc thermal forcing state mapping file decomp type
diff --git a/driver-mct/cime_config/config_component_e3sm.xml b/driver-mct/cime_config/config_component_e3sm.xml
index 8fc93b607d46..4964a3c427b3 100755
--- a/driver-mct/cime_config/config_component_e3sm.xml
+++ b/driver-mct/cime_config/config_component_e3sm.xml
@@ -185,6 +185,18 @@
Turn on the passing of polar fields through the coupler
+
+ logical
+ TRUE,FALSE
+ FALSE
+
+ TRUE
+
+ run_flags
+ env_run.xml
+ Turn on the passing of ocean thermal forcing fields through the coupler
+
+
char
minus1p8,linear_salt,mushy
diff --git a/driver-mct/cime_config/namelist_definition_drv.xml b/driver-mct/cime_config/namelist_definition_drv.xml
index 7fbf83688c8a..5995c5f482d8 100644
--- a/driver-mct/cime_config/namelist_definition_drv.xml
+++ b/driver-mct/cime_config/namelist_definition_drv.xml
@@ -149,6 +149,18 @@
+
+ logical
+ seq_flds
+ seq_cplflds_inparm
+
+ If set to .true. thermal forcing fields will be passed from the ocean to the coupler.
+
+
+ $FLDS_TF
+
+
+
logical
seq_flds
@@ -4530,20 +4542,50 @@
-
+
+ char
+ mapping
+ abs
+ seq_maps
+
+ ocn to glc shelf mapping file for fluxes
+
+
+ $OCN2GLC_SHELF_FMAPNAME
+
+
+
+
+ char
+ mapping
+ seq_maps
+
+ The type of mapping desired, either "source" or "destination" mapping.
+ X is associated with rearrangement of the source grid to the
+ destination grid and then local mapping. Y is associated with mapping
+ on the source grid and then rearrangement and sum to the destination
+ grid.
+
+
+ $OCN2GLC_SHELF_FMAPTYPE
+ X
+
+
+
+
char
mapping
abs
seq_maps
- ocn to glc flux mapping file for fluxes
+ ocn to glc shelf mapping file for states
- $OCN2GLC_FMAPNAME
+ $OCN2GLC_SHELF_SMAPNAME
-
+
char
mapping
seq_maps
@@ -4555,25 +4597,25 @@
grid.
- $OCN2GLC_FMAPTYPE
+ $OCN2GLC_SHELF_SMAPTYPE
X
-
+
char
mapping
abs
seq_maps
- ocn to glc state mapping file for states
+ ocn to glc state mapping file for thermal forcing state fields
- $OCN2GLC_SMAPNAME
+ $OCN2GLC_TF_SMAPNAME
-
+
char
mapping
seq_maps
@@ -4585,7 +4627,7 @@
grid.
- $OCN2GLC_SMAPTYPE
+ $OCN2GLC_TF_SMAPTYPE
X
diff --git a/driver-mct/main/cime_comp_mod.F90 b/driver-mct/main/cime_comp_mod.F90
index 2131d0c86844..f582f7bd5aa8 100644
--- a/driver-mct/main/cime_comp_mod.F90
+++ b/driver-mct/main/cime_comp_mod.F90
@@ -434,6 +434,7 @@ module cime_comp_mod
logical :: lnd_c2_glc ! .true. => lnd to glc coupling on
logical :: ocn_c2_atm ! .true. => ocn to atm coupling on
logical :: ocn_c2_ice ! .true. => ocn to ice coupling on
+ logical :: ocn_c2_glctf ! .true. => ocn to glc thermal forcing coupling on
logical :: ocn_c2_glcshelf ! .true. => ocn to glc ice shelf coupling on
logical :: ocn_c2_wav ! .true. => ocn to wav coupling on
logical :: ocn_c2_rof ! .true. => ocn to rof coupling on
@@ -1732,6 +1733,8 @@ subroutine cime_init()
lnd_c2_glc = .false.
ocn_c2_atm = .false.
ocn_c2_ice = .false.
+ ocn_c2_glctf = .false.
+ ocn_c2_glcshelf = .false.
ocn_c2_wav = .false.
ocn_c2_rof = .false.
ice_c2_atm = .false.
@@ -1867,6 +1870,7 @@ subroutine cime_init()
write(logunit,F0L)'lnd_c2_rof = ',lnd_c2_rof
write(logunit,F0L)'lnd_c2_glc = ',lnd_c2_glc
write(logunit,F0L)'ocn_c2_atm = ',ocn_c2_atm
+ write(logunit,F0L)'ocn_c2_glctf = ',ocn_c2_glctf
write(logunit,F0L)'ocn_c2_ice = ',ocn_c2_ice
write(logunit,F0L)'ocn_c2_glcshelf = ',ocn_c2_glcshelf
write(logunit,F0L)'ocn_c2_wav = ',ocn_c2_wav
@@ -1953,7 +1957,7 @@ subroutine cime_init()
endif
if ((ocn_c2_glcshelf .and. .not. glcshelf_c2_ocn) .or. (glcshelf_c2_ocn .and. .not. ocn_c2_glcshelf)) then
! Current logic will not allow this to be true, but future changes could make it so, which may be nonsensical
- call shr_sys_abort(subname//' ERROR: if glc_c2_ocn must also have ocn_c2_glc and vice versa. '//&
+ call shr_sys_abort(subname//' ERROR: if glcshelf_c2_ocn must also have ocn_c2_glcshelf and vice versa. '//&
'Boundary layer fluxes calculated in coupler require input from both components.')
endif
if (rofice_present .and. .not.rof_present) then
@@ -2022,7 +2026,7 @@ subroutine cime_init()
call prep_rof_init(infodata, lnd_c2_rof, atm_c2_rof, ocn_c2_rof)
- call prep_glc_init(infodata, lnd_c2_glc, ocn_c2_glcshelf)
+ call prep_glc_init(infodata, lnd_c2_glc, ocn_c2_glctf, ocn_c2_glcshelf)
call prep_wav_init(infodata, atm_c2_wav, ocn_c2_wav, ice_c2_wav)
@@ -4210,12 +4214,16 @@ subroutine cime_run_ocnglc_coupling()
if (glc_present) then
+ ! create o2x_gx for either ocn-glc coupling or ocn-glc shelf coupling
+ if (ocn_c2_glctf .or. (ocn_c2_glcshelf .and. glcshelf_c2_ocn)) then
+ call prep_glc_calc_o2x_gx(ocn_c2_glctf, ocn_c2_glcshelf, timer='CPL:glcprep_ocn2glc') !remap ocean fields to o2x_g at ocean couping interval
+ endif
+
+ ! if ice-shelf coupling is on, now proceed to handle those calculations here in the coupler
if (ocn_c2_glcshelf .and. glcshelf_c2_ocn) then
! the boundary flux calculations done in the coupler require inputs from both GLC and OCN,
! so they will only be valid if both OCN->GLC and GLC->OCN
- call prep_glc_calc_o2x_gx(timer='CPL:glcprep_ocn2glc') !remap ocean fields to o2x_g at ocean couping interval
-
call prep_glc_calculate_subshelf_boundary_fluxes ! this is actual boundary layer flux calculation
!this outputs
!x2g_g/g2x_g, where latter is going
@@ -4342,7 +4350,7 @@ subroutine cime_run_glc_setup_send(lnd2glc_averaged_now, prep_glc_accum_avg_call
if (drv_threading) call seq_comm_setnthreads(nthreads_CPLID)
! NOTE - only create appropriate input to glc if the avg_alarm is on
- if (lnd_c2_glc .or. ocn_c2_glcshelf) then
+ if (lnd_c2_glc .or. ocn_c2_glctf .or. ocn_c2_glcshelf) then
if (glcrun_avg_alarm) then
call prep_glc_accum_avg(timer='CPL:glcprep_avg', &
lnd2glc_averaged_now=lnd2glc_averaged_now)
@@ -4355,6 +4363,13 @@ subroutine cime_run_glc_setup_send(lnd2glc_averaged_now, prep_glc_accum_avg_call
call prep_glc_mrg_lnd(infodata, fractions_gx, timer_mrg='CPL:glcprep_mrgx2g')
endif
+ if (ocn_c2_glctf) then
+ ! note: o2x_gx is handled in prep_glc_calc_o2x_gx, which is called
+ ! from cime_run_ocnglc_coupling in this module
+ call prep_glc_mrg_ocn(infodata, fractions_gx, timer_mrg='CPL:glcprep_mrgocnx2g')
+ endif
+
+
call component_diag(infodata, glc, flow='x2c', comment='send glc', &
info_debug=info_debug, timer_diag='CPL:glcprep_diagav')
diff --git a/driver-mct/main/prep_glc_mod.F90 b/driver-mct/main/prep_glc_mod.F90
index 07aeb9890bda..6ce136305d0d 100644
--- a/driver-mct/main/prep_glc_mod.F90
+++ b/driver-mct/main/prep_glc_mod.F90
@@ -31,6 +31,7 @@ module prep_glc_mod
public :: prep_glc_init
public :: prep_glc_mrg_lnd
+ public :: prep_glc_mrg_ocn
public :: prep_glc_accum_lnd
public :: prep_glc_accum_ocn
@@ -53,8 +54,8 @@ module prep_glc_mod
public :: prep_glc_get_mapper_Sl2g
public :: prep_glc_get_mapper_Fl2g
- public :: prep_glc_get_mapper_So2g
- public :: prep_glc_get_mapper_Fo2g
+ public :: prep_glc_get_mapper_So2g_shelf
+ public :: prep_glc_get_mapper_Fo2g_shelf
public :: prep_glc_calculate_subshelf_boundary_fluxes
@@ -76,8 +77,9 @@ module prep_glc_mod
! mappers
type(seq_map), pointer :: mapper_Sl2g
type(seq_map), pointer :: mapper_Fl2g
- type(seq_map), pointer :: mapper_So2g
- type(seq_map), pointer :: mapper_Fo2g
+ type(seq_map), pointer :: mapper_So2g_shelf
+ type(seq_map), pointer :: mapper_Fo2g_shelf
+ type(seq_map), pointer :: mapper_So2g_tf
type(seq_map), pointer :: mapper_Fg2l
! attribute vectors
@@ -135,7 +137,7 @@ module prep_glc_mod
!================================================================================================
- subroutine prep_glc_init(infodata, lnd_c2_glc, ocn_c2_glcshelf)
+ subroutine prep_glc_init(infodata, lnd_c2_glc, ocn_c2_glctf, ocn_c2_glcshelf)
!---------------------------------------------------------------
! Description
@@ -144,7 +146,8 @@ subroutine prep_glc_init(infodata, lnd_c2_glc, ocn_c2_glcshelf)
! Arguments
type (seq_infodata_type) , intent(inout) :: infodata
logical , intent(in) :: lnd_c2_glc ! .true. => lnd to glc coupling on
- logical , intent(in) :: ocn_c2_glcshelf ! .true. => ocn to glc coupling on
+ logical , intent(in) :: ocn_c2_glctf ! .true. => ocn to glc thermal forcing coupling on
+ logical , intent(in) :: ocn_c2_glcshelf ! .true. => ocn to glc shelf coupling on
!
! Local Variables
integer :: eli, egi, eoi
@@ -178,8 +181,9 @@ subroutine prep_glc_init(infodata, lnd_c2_glc, ocn_c2_glcshelf)
allocate(mapper_Sl2g)
allocate(mapper_Fl2g)
- allocate(mapper_So2g)
- allocate(mapper_Fo2g)
+ allocate(mapper_So2g_shelf)
+ allocate(mapper_So2g_tf)
+ allocate(mapper_Fo2g_shelf)
allocate(mapper_Fg2l)
smb_renormalize = prep_glc_do_renormalize_smb(infodata)
@@ -249,8 +253,8 @@ subroutine prep_glc_init(infodata, lnd_c2_glc, ocn_c2_glcshelf)
end if
- if (glc_present .and. ocn_c2_glcshelf) then
-
+ ! setup needed for either kind of ocn2glc coupling
+ if (glc_present .and. (ocn_c2_glctf .or. ocn_c2_glcshelf)) then
call seq_comm_getData(CPLID, &
mpicom=mpicom_CPLID, iamroot=iamroot_CPLID)
@@ -275,21 +279,35 @@ subroutine prep_glc_init(infodata, lnd_c2_glc, ocn_c2_glcshelf)
x2gacc_gx_cnt = 0
samegrid_go = .true.
if (trim(ocn_gnam) /= trim(glc_gnam)) samegrid_go = .false.
+ end if
+
+ ! setup needed for ocn2glc TF coupling
+ if (glc_present .and. ocn_c2_glctf) then
if (iamroot_CPLID) then
write(logunit,*) ' '
- write(logunit,F00) 'Initializing mapper_So2g'
+ write(logunit,F00) 'Initializing mapper_So2g_tf'
end if
- call seq_map_init_rcfile(mapper_So2g, ocn(1), glc(1), &
- 'seq_maps.rc','ocn2glc_smapname:','ocn2glc_smaptype:',samegrid_go, &
- 'mapper_So2g initialization',esmf_map_flag)
+ call seq_map_init_rcfile(mapper_So2g_tf, ocn(1), glc(1), &
+ 'seq_maps.rc','ocn2glc_tf_smapname:','ocn2glc_tf_smaptype:',samegrid_go, &
+ 'mapper_So2g_tf initialization',esmf_map_flag)
+ end if
+
+ ! setup needed for ocn2glcshelf coupling
+ if (glc_present .and. ocn_c2_glcshelf) then
if (iamroot_CPLID) then
write(logunit,*) ' '
- write(logunit,F00) 'Initializing mapper_Fo2g'
+ write(logunit,F00) 'Initializing mapper_So2g_shelf'
end if
- call seq_map_init_rcfile(mapper_Fo2g, ocn(1), glc(1), &
- 'seq_maps.rc','ocn2glc_fmapname:','ocn2glc_fmaptype:',samegrid_go, &
- 'mapper_Fo2g initialization',esmf_map_flag)
-
+ call seq_map_init_rcfile(mapper_So2g_shelf, ocn(1), glc(1), &
+ 'seq_maps.rc','ocn2glc_shelf_smapname:','ocn2glc_shelf_smaptype:',samegrid_go, &
+ 'mapper_So2g_shelf initialization',esmf_map_flag)
+ if (iamroot_CPLID) then
+ write(logunit,*) ' '
+ write(logunit,F00) 'Initializing mapper_Fo2g_shelf'
+ end if
+ call seq_map_init_rcfile(mapper_Fo2g_shelf, ocn(1), glc(1), &
+ 'seq_maps.rc','ocn2glc_shelf_fmapname:','ocn2glc_shelf_fmaptype:',samegrid_go, &
+ 'mapper_Fo2g_shelf initialization',esmf_map_flag)
!Initialize module-level arrays associated with compute_melt_fluxes
allocate(oceanTemperature(lsize_g))
allocate(oceanSalinity(lsize_g))
@@ -307,10 +325,9 @@ subroutine prep_glc_init(infodata, lnd_c2_glc, ocn_c2_glcshelf)
! TODO: Can we allocate these only while used or are we worried about performance hit?
! TODO: add deallocates!
- call shr_sys_flush(logunit)
-
end if
+ call shr_sys_flush(logunit)
end subroutine prep_glc_init
@@ -521,6 +538,154 @@ subroutine prep_glc_accum_avg(timer, lnd2glc_averaged_now)
end subroutine prep_glc_accum_avg
+ !================================================================================================
+
+ subroutine prep_glc_mrg_ocn(infodata, fractions_gx, timer_mrg)
+
+ !---------------------------------------------------------------
+ ! Description
+ ! Merge glc inputs
+ !
+ ! Arguments
+ type(seq_infodata_type) , intent(in) :: infodata
+ type(mct_aVect) , intent(in) :: fractions_gx(:)
+ character(len=*) , intent(in) :: timer_mrg
+ !
+ ! Local Variables
+ integer :: egi, eoi, efi
+ type(mct_avect), pointer :: x2g_gx
+ character(*), parameter :: subname = '(prep_glc_mrg_ocn)'
+ !---------------------------------------------------------------
+
+ call t_drvstartf (trim(timer_mrg),barrier=mpicom_CPLID)
+ do egi = 1,num_inst_glc
+ ! Use fortran mod to address ensembles in merge
+ eoi = mod((egi-1),num_inst_ocn) + 1
+ efi = mod((egi-1),num_inst_frc) + 1
+
+ x2g_gx => component_get_x2c_cx(glc(egi))
+ call prep_glc_merge_ocn_forcing(o2x_gx(eoi), fractions_gx(efi), x2g_gx)
+ enddo
+ call t_drvstopf (trim(timer_mrg))
+
+ end subroutine prep_glc_mrg_ocn
+
+ !================================================================================================
+
+ subroutine prep_glc_merge_ocn_forcing( o2x_g, fractions_g, x2g_g )
+
+ !-----------------------------------------------------------------------
+ ! Description
+ ! "Merge" ocean forcing for glc input.
+ !
+ ! State fields are copied directly, meaning that averages are taken just over the
+ ! ocean-covered portion of the glc domain.
+ !
+ ! Flux fields are downweighted by landfrac, which effectively sends a 0 flux from the
+ ! non-ocean-covered portion of the glc domain.
+ !
+ ! Arguments
+ type(mct_aVect), intent(inout) :: o2x_g ! input
+ type(mct_aVect), intent(in) :: fractions_g
+ type(mct_aVect), intent(inout) :: x2g_g ! output
+ !-----------------------------------------------------------------------
+
+ integer :: num_flux_fields
+ integer :: num_state_fields
+ integer :: nflds
+ integer :: i,n
+ integer :: mrgstr_index
+ integer :: index_o2x
+ integer :: index_x2g
+ integer :: index_ofrac
+ integer :: lsize
+ logical :: iamroot
+ logical, save :: first_time = .true.
+ character(CL),allocatable :: mrgstr(:) ! temporary string
+ character(CL) :: field ! string converted to char
+ character(*), parameter :: subname = '(prep_glc_merge_ocn_forcing) '
+
+ !-----------------------------------------------------------------------
+
+ call seq_comm_getdata(CPLID, iamroot=iamroot)
+ lsize = mct_aVect_lsize(x2g_g)
+
+ !num_flux_fields = shr_string_listGetNum(trim(seq_flds_x2g_fluxes_from_ocn))
+ num_flux_fields = 0
+ num_state_fields = shr_string_listGetNum(trim(seq_flds_x2g_tf_states_from_ocn))
+
+ if (first_time) then
+ nflds = num_flux_fields + num_state_fields
+ allocate(mrgstr(nflds))
+ end if
+
+ mrgstr_index = 1
+
+ do i = 1, num_state_fields
+ call seq_flds_getField(field, i, seq_flds_x2g_tf_states_from_ocn)
+ index_o2x = mct_aVect_indexRA(o2x_g, trim(field))
+ index_x2g = mct_aVect_indexRA(x2g_g, trim(field))
+
+ if (first_time) then
+ mrgstr(mrgstr_index) = subname//'x2g%'//trim(field)//' =' // &
+ ' = o2x%'//trim(field)
+ end if
+
+ do n = 1, lsize
+ x2g_g%rAttr(index_x2g,n) = o2x_g%rAttr(index_o2x,n)
+ end do
+
+ mrgstr_index = mrgstr_index + 1
+ enddo
+
+ !index_lfrac = mct_aVect_indexRA(fractions_g,"lfrac")
+ !do i = 1, num_flux_fields
+
+ ! call seq_flds_getField(field, i, seq_flds_x2g_fluxes_from_lnd)
+ ! index_l2x = mct_aVect_indexRA(l2x_g, trim(field))
+ ! index_x2g = mct_aVect_indexRA(x2g_g, trim(field))
+
+ ! if (trim(field) == qice_fieldname) then
+
+ ! if (first_time) then
+ ! mrgstr(mrgstr_index) = subname//'x2g%'//trim(field)//' =' // &
+ ! ' = l2x%'//trim(field)
+ ! end if
+
+ ! ! treat qice as if it were a state variable, with a simple copy.
+ ! do n = 1, lsize
+ ! x2g_g%rAttr(index_x2g,n) = l2x_g%rAttr(index_l2x,n)
+ ! end do
+
+ ! else
+ ! write(logunit,*) subname,' ERROR: Flux fields other than ', &
+ ! qice_fieldname, ' currently are not handled in lnd2glc remapping.'
+ ! write(logunit,*) '(Attempt to handle flux field <', trim(field), '>.)'
+ ! write(logunit,*) 'Substantial thought is needed to determine how to remap other fluxes'
+ ! write(logunit,*) 'in a smooth, conservative manner.'
+ ! call shr_sys_abort(subname//&
+ ! ' ERROR: Flux fields other than qice currently are not handled in lnd2glc remapping.')
+ ! endif ! qice_fieldname
+
+ ! mrgstr_index = mrgstr_index + 1
+
+ !end do
+
+ if (first_time) then
+ if (iamroot) then
+ write(logunit,'(A)') subname//' Summary:'
+ do i = 1,nflds
+ write(logunit,'(A)') trim(mrgstr(i))
+ enddo
+ endif
+ deallocate(mrgstr)
+ endif
+
+ first_time = .false.
+
+ end subroutine prep_glc_merge_ocn_forcing
+
+
!================================================================================================
subroutine prep_glc_mrg_lnd(infodata, fractions_gx, timer_mrg)
@@ -604,7 +769,7 @@ subroutine prep_glc_merge_lnd_forcing( l2x_g, fractions_g, x2g_g )
mrgstr_index = 1
do i = 1, num_state_fields
- call seq_flds_getField(field, i, seq_flds_x2g_states)
+ call seq_flds_getField(field, i, seq_flds_x2g_states_from_lnd)
index_l2x = mct_aVect_indexRA(l2x_g, trim(field))
index_x2g = mct_aVect_indexRA(x2g_g, trim(field))
@@ -668,13 +833,15 @@ subroutine prep_glc_merge_lnd_forcing( l2x_g, fractions_g, x2g_g )
end subroutine prep_glc_merge_lnd_forcing
- subroutine prep_glc_calc_o2x_gx(timer)
+ subroutine prep_glc_calc_o2x_gx(ocn_c2_glctf, ocn_c2_glcshelf, timer)
!---------------------------------------------------------------
! Description
! Create o2x_gx
! Arguments
character(len=*), intent(in) :: timer
+ logical, intent(in) :: ocn_c2_glctf
+ logical, intent(in) :: ocn_c2_glcshelf
character(*), parameter :: subname = '(prep_glc_calc_o2x_gx)'
! Local Variables
@@ -684,8 +851,14 @@ subroutine prep_glc_calc_o2x_gx(timer)
call t_drvstartf (trim(timer),barrier=mpicom_CPLID)
do eoi = 1,num_inst_ocn
o2x_ox => component_get_c2x_cx(ocn(eoi))
- call seq_map_map(mapper_So2g, o2x_ox, o2x_gx(eoi), &
- fldlist=seq_flds_x2g_states_from_ocn,norm=.true.)
+ if (ocn_c2_glctf) then
+ call seq_map_map(mapper_So2g_tf, o2x_ox, o2x_gx(eoi), &
+ fldlist=seq_flds_x2g_tf_states_from_ocn,norm=.true.)
+ end if
+ if (ocn_c2_glcshelf) then
+ call seq_map_map(mapper_So2g_shelf, o2x_ox, o2x_gx(eoi), &
+ fldlist=seq_flds_x2g_shelf_states_from_ocn,norm=.true.)
+ end if
enddo
call t_drvstopf (trim(timer))
@@ -850,8 +1023,8 @@ subroutine prep_glc_calculate_subshelf_boundary_fluxes
!Done here instead of in glc-frequency mapping so it happens within ocean coupling interval.
! Also could map o2x_ox->o2x_gx(1) but using x2g_gx as destination allows us to see
! these fields on the GLC grid of the coupler history file, which helps with debugging.
- call seq_map_map(mapper_So2g, o2x_ox, x2g_gx, &
- fldlist=seq_flds_x2g_states_from_ocn,norm=.true.)
+ call seq_map_map(mapper_So2g_shelf, o2x_ox, x2g_gx, &
+ fldlist=seq_flds_x2g_shelf_states_from_ocn,norm=.true.)
! inputs to melt flux calculation
index_x2g_So_blt = mct_avect_indexra(x2g_gx,'So_blt',perrwith='quiet')
@@ -1449,15 +1622,15 @@ function prep_glc_get_mapper_Fl2g()
prep_glc_get_mapper_Fl2g => mapper_Fl2g
end function prep_glc_get_mapper_Fl2g
- function prep_glc_get_mapper_So2g()
- type(seq_map), pointer :: prep_glc_get_mapper_So2g
- prep_glc_get_mapper_So2g=> mapper_So2g
- end function prep_glc_get_mapper_So2g
+ function prep_glc_get_mapper_So2g_shelf()
+ type(seq_map), pointer :: prep_glc_get_mapper_So2g_shelf
+ prep_glc_get_mapper_So2g_shelf=> mapper_So2g_shelf
+ end function prep_glc_get_mapper_So2g_shelf
- function prep_glc_get_mapper_Fo2g()
- type(seq_map), pointer :: prep_glc_get_mapper_Fo2g
- prep_glc_get_mapper_Fo2g=> mapper_Fo2g
- end function prep_glc_get_mapper_Fo2g
+ function prep_glc_get_mapper_Fo2g_shelf()
+ type(seq_map), pointer :: prep_glc_get_mapper_Fo2g_shelf
+ prep_glc_get_mapper_Fo2g_shelf=> mapper_Fo2g_shelf
+ end function prep_glc_get_mapper_Fo2g_shelf
!***********************************************************************
!
diff --git a/driver-mct/shr/seq_flds_mod.F90 b/driver-mct/shr/seq_flds_mod.F90
index dbfba0889d0c..d0f46ed36e2a 100644
--- a/driver-mct/shr/seq_flds_mod.F90
+++ b/driver-mct/shr/seq_flds_mod.F90
@@ -212,7 +212,8 @@ module seq_flds_mod
character(CXX) :: seq_flds_g2o_ice_fluxes
character(CXX) :: seq_flds_x2g_states
character(CXX) :: seq_flds_x2g_states_from_lnd
- character(CXX) :: seq_flds_x2g_states_from_ocn
+ character(CXX) :: seq_flds_x2g_shelf_states_from_ocn
+ character(CXX) :: seq_flds_x2g_tf_states_from_ocn
character(CXX) :: seq_flds_x2g_fluxes
character(CXX) :: seq_flds_x2g_fluxes_from_lnd
@@ -347,7 +348,8 @@ subroutine seq_flds_set(nmlfile, ID, infodata)
character(CXX) :: g2o_ice_fluxes = ''
character(CXX) :: x2g_states = ''
character(CXX) :: x2g_states_from_lnd = ''
- character(CXX) :: x2g_states_from_ocn = ''
+ character(CXX) :: x2g_shelf_states_from_ocn = ''
+ character(CXX) :: x2g_tf_states_from_ocn = ''
character(CXX) :: x2g_fluxes = ''
character(CXX) :: x2g_fluxes_from_lnd = ''
character(CXX) :: xao_albedo = ''
@@ -380,11 +382,12 @@ subroutine seq_flds_set(nmlfile, ID, infodata)
logical :: flds_bgc_oi
logical :: flds_wiso
logical :: flds_polar
+ logical :: flds_tf
integer :: glc_nec
namelist /seq_cplflds_inparm/ &
- flds_co2a, flds_co2b, flds_co2c, flds_co2_dmsa, flds_wiso, flds_polar, glc_nec, &
- ice_ncat, seq_flds_i2o_per_cat, flds_bgc_oi, &
+ flds_co2a, flds_co2b, flds_co2c, flds_co2_dmsa, flds_wiso, flds_polar, flds_tf, &
+ glc_nec, ice_ncat, seq_flds_i2o_per_cat, flds_bgc_oi, &
nan_check_component_fields, rof_heat, atm_flux_method, atm_gustiness, &
rof2ocn_nutrients, lnd_rof_two_way, ocn_rof_two_way, rof_sed
@@ -418,6 +421,7 @@ subroutine seq_flds_set(nmlfile, ID, infodata)
flds_bgc_oi = .false.
flds_wiso = .false.
flds_polar = .false.
+ flds_tf = .false.
glc_nec = 0
ice_ncat = 1
seq_flds_i2o_per_cat = .false.
@@ -452,6 +456,7 @@ subroutine seq_flds_set(nmlfile, ID, infodata)
call shr_mpi_bcast(flds_bgc_oi , mpicom)
call shr_mpi_bcast(flds_wiso , mpicom)
call shr_mpi_bcast(flds_polar , mpicom)
+ call shr_mpi_bcast(flds_tf , mpicom)
call shr_mpi_bcast(glc_nec , mpicom)
call shr_mpi_bcast(ice_ncat , mpicom)
call shr_mpi_bcast(seq_flds_i2o_per_cat, mpicom)
@@ -2938,7 +2943,7 @@ subroutine seq_flds_set(nmlfile, ID, infodata)
name = 'So_blt'
call seq_flds_add(o2x_states,trim(name))
call seq_flds_add(x2g_states,trim(name))
- call seq_flds_add(x2g_states_from_ocn,trim(name))
+ call seq_flds_add(x2g_shelf_states_from_ocn,trim(name))
longname = 'Ice shelf boundary layer ocean temperature'
stdname = 'Ice_shelf_boundary_layer_ocean_temperature'
units = 'C'
@@ -2948,7 +2953,7 @@ subroutine seq_flds_set(nmlfile, ID, infodata)
name = 'So_bls'
call seq_flds_add(o2x_states,trim(name))
call seq_flds_add(x2g_states,trim(name))
- call seq_flds_add(x2g_states_from_ocn,trim(name))
+ call seq_flds_add(x2g_shelf_states_from_ocn,trim(name))
longname = 'Ice shelf boundary layer ocean salinity'
stdname = 'Ice_shelf_boundary_layer_ocean_salinity'
units = 'psu'
@@ -2958,7 +2963,7 @@ subroutine seq_flds_set(nmlfile, ID, infodata)
name = 'So_htv'
call seq_flds_add(o2x_states,trim(name))
call seq_flds_add(x2g_states,trim(name))
- call seq_flds_add(x2g_states_from_ocn,trim(name))
+ call seq_flds_add(x2g_shelf_states_from_ocn,trim(name))
longname = 'Ice shelf ocean heat transfer velocity'
stdname = 'Ice_shelf_ocean_heat_transfer_velocity'
units = 'm/s'
@@ -2968,7 +2973,7 @@ subroutine seq_flds_set(nmlfile, ID, infodata)
name = 'So_stv'
call seq_flds_add(o2x_states,trim(name))
call seq_flds_add(x2g_states,trim(name))
- call seq_flds_add(x2g_states_from_ocn,trim(name))
+ call seq_flds_add(x2g_shelf_states_from_ocn,trim(name))
longname = 'Ice shelf ocean salinity transfer velocity'
stdname = 'Ice_shelf_ocean_salinity_transfer_velocity'
units = 'm/s'
@@ -2978,13 +2983,27 @@ subroutine seq_flds_set(nmlfile, ID, infodata)
name = 'So_rhoeff'
call seq_flds_add(o2x_states,trim(name))
call seq_flds_add(x2g_states,trim(name))
- call seq_flds_add(x2g_states_from_ocn,trim(name))
+ call seq_flds_add(x2g_shelf_states_from_ocn,trim(name))
longname = 'Ocean effective pressure'
stdname = 'Ocean_effective_pressure'
units = 'Pa'
attname = 'So_rhoeff'
call metadata_set(attname, longname, stdname, units)
+ if (flds_tf) then
+
+ name = 'So_tf2d'
+ call seq_flds_add(o2x_states,trim(name))
+ call seq_flds_add(x2g_states,trim(name))
+ call seq_flds_add(x2g_tf_states_from_ocn,trim(name))
+ longname = 'ocean thermal forcing at predefined critical depth'
+ stdname = 'ocean_thermal_forcing_at_critical_depth'
+ units = 'C'
+ attname = name
+ call metadata_set(attname, longname, stdname, units)
+
+ end if
+
name = 'Fogx_qicelo'
call seq_flds_add(g2x_fluxes,trim(name))
call seq_flds_add(x2o_fluxes,trim(name))
@@ -3936,7 +3955,8 @@ subroutine seq_flds_set(nmlfile, ID, infodata)
seq_flds_g2x_states_to_lnd = trim(g2x_states_to_lnd)
seq_flds_x2g_states = trim(x2g_states)
seq_flds_x2g_states_from_lnd = trim(x2g_states_from_lnd)
- seq_flds_x2g_states_from_ocn = trim(x2g_states_from_ocn)
+ seq_flds_x2g_shelf_states_from_ocn = trim(x2g_shelf_states_from_ocn)
+ seq_flds_x2g_tf_states_from_ocn = trim(x2g_tf_states_from_ocn)
seq_flds_xao_states = trim(xao_states)
seq_flds_xao_albedo = trim(xao_albedo)
seq_flds_xao_diurnl = trim(xao_diurnl)
@@ -4003,7 +4023,8 @@ subroutine seq_flds_set(nmlfile, ID, infodata)
write(logunit,*) subname//': seq_flds_x2g_states= ',trim(seq_flds_x2g_states)
write(logunit,*) subname//': seq_flds_x2g_states_from_lnd= ',trim(seq_flds_x2g_states_from_lnd)
write(logunit,*) subname//': seq_flds_l2x_states_to_glc= ',trim(seq_flds_l2x_states_to_glc)
- write(logunit,*) subname//': seq_flds_x2g_states_from_ocn= ',trim(seq_flds_x2g_states_from_ocn)
+ write(logunit,*) subname//': seq_flds_x2g_shelf_states_from_ocn= ',trim(seq_flds_x2g_shelf_states_from_ocn)
+ write(logunit,*) subname//': seq_flds_x2g_tf_states_from_ocn= ',trim(seq_flds_x2g_tf_states_from_ocn)
write(logunit,*) subname//': seq_flds_x2g_fluxes= ',trim(seq_flds_x2g_fluxes)
write(logunit,*) subname//': seq_flds_x2g_fluxes_from_lnd= ',trim(seq_flds_x2g_fluxes_from_lnd)
write(logunit,*) subname//': seq_flds_l2x_fluxes_to_glc= ',trim(seq_flds_l2x_fluxes_to_glc)
diff --git a/driver-mct/shr/seq_infodata_mod.F90 b/driver-mct/shr/seq_infodata_mod.F90
index fcc6a21eef1f..01ff3c98880e 100644
--- a/driver-mct/shr/seq_infodata_mod.F90
+++ b/driver-mct/shr/seq_infodata_mod.F90
@@ -203,6 +203,7 @@ MODULE seq_infodata_mod
logical :: ocn_prognostic ! does component model need input data from driver
logical :: ocnrof_prognostic ! does component need rof data
logical :: ocn_c2_glcshelf ! will ocn component send data for ice shelf fluxes in driver
+ logical :: ocn_c2_glctf ! will ocn component send data for thermal forcing in driver
logical :: ice_present ! does component model exist
logical :: ice_prognostic ! does component model need input data from driver
logical :: iceberg_prognostic ! does the ice model support icebergs
@@ -765,6 +766,7 @@ SUBROUTINE seq_infodata_Init( infodata, nmlfile, ID, pioid, cpl_tag)
infodata%ocn_prognostic = .false.
infodata%ocnrof_prognostic = .false.
infodata%ocn_c2_glcshelf = .false.
+ infodata%ocn_c2_glctf = .false.
infodata%ice_prognostic = .false.
infodata%glc_prognostic = .false.
! It's safest to assume glc_coupled_fluxes = .true. if it's not set elsewhere,
@@ -1004,7 +1006,8 @@ SUBROUTINE seq_infodata_GetData_explicit( infodata, cime_model, case_name, case_
atm_present, atm_prognostic, &
lnd_present, lnd_prognostic, &
rof_present, rof_prognostic, rofocn_prognostic, &
- ocn_present, ocn_prognostic, ocnrof_prognostic, ocn_c2_glcshelf, &
+ ocn_present, ocn_prognostic, ocnrof_prognostic, &
+ ocn_c2_glcshelf, ocn_c2_glctf, &
ice_present, ice_prognostic, &
glc_present, glc_prognostic, &
iac_present, iac_prognostic, &
@@ -1179,6 +1182,7 @@ SUBROUTINE seq_infodata_GetData_explicit( infodata, cime_model, case_name, case_
logical, optional, intent(OUT) :: ocn_prognostic
logical, optional, intent(OUT) :: ocnrof_prognostic
logical, optional, intent(OUT) :: ocn_c2_glcshelf
+ logical, optional, intent(OUT) :: ocn_c2_glctf
logical, optional, intent(OUT) :: ice_present
logical, optional, intent(OUT) :: ice_prognostic
logical, optional, intent(OUT) :: iceberg_prognostic
@@ -1365,6 +1369,7 @@ SUBROUTINE seq_infodata_GetData_explicit( infodata, cime_model, case_name, case_
if ( present(ocn_prognostic) ) ocn_prognostic = infodata%ocn_prognostic
if ( present(ocnrof_prognostic) ) ocnrof_prognostic = infodata%ocnrof_prognostic
if ( present(ocn_c2_glcshelf) ) ocn_c2_glcshelf = infodata%ocn_c2_glcshelf
+ if ( present(ocn_c2_glctf) ) ocn_c2_glctf = infodata%ocn_c2_glctf
if ( present(ice_present) ) ice_present = infodata%ice_present
if ( present(ice_prognostic) ) ice_prognostic = infodata%ice_prognostic
if ( present(iceberg_prognostic)) iceberg_prognostic = infodata%iceberg_prognostic
@@ -1557,7 +1562,8 @@ SUBROUTINE seq_infodata_PutData_explicit( infodata, cime_model, case_name, case_
atm_present, atm_prognostic, &
lnd_present, lnd_prognostic, &
rof_present, rof_prognostic, rofocn_prognostic, &
- ocn_present, ocn_prognostic, ocnrof_prognostic, ocn_c2_glcshelf, &
+ ocn_present, ocn_prognostic, ocnrof_prognostic, &
+ ocn_c2_glcshelf, ocn_c2_glctf, &
ice_present, ice_prognostic, &
glc_present, glc_prognostic, &
glc_coupled_fluxes, &
@@ -1732,6 +1738,7 @@ SUBROUTINE seq_infodata_PutData_explicit( infodata, cime_model, case_name, case_
logical, optional, intent(IN) :: ocn_prognostic
logical, optional, intent(IN) :: ocnrof_prognostic
logical, optional, intent(IN) :: ocn_c2_glcshelf
+ logical, optional, intent(IN) :: ocn_c2_glctf
logical, optional, intent(IN) :: ice_present
logical, optional, intent(IN) :: ice_prognostic
logical, optional, intent(IN) :: iceberg_prognostic
@@ -1917,6 +1924,7 @@ SUBROUTINE seq_infodata_PutData_explicit( infodata, cime_model, case_name, case_
if ( present(ocn_prognostic) ) infodata%ocn_prognostic = ocn_prognostic
if ( present(ocnrof_prognostic)) infodata%ocnrof_prognostic = ocnrof_prognostic
if ( present(ocn_c2_glcshelf)) infodata%ocn_c2_glcshelf = ocn_c2_glcshelf
+ if ( present(ocn_c2_glctf)) infodata%ocn_c2_glctf = ocn_c2_glctf
if ( present(ice_present) ) infodata%ice_present = ice_present
if ( present(ice_prognostic) ) infodata%ice_prognostic = ice_prognostic
if ( present(iceberg_prognostic)) infodata%iceberg_prognostic = iceberg_prognostic
@@ -2229,6 +2237,7 @@ subroutine seq_infodata_bcast(infodata,mpicom)
call shr_mpi_bcast(infodata%ocn_prognostic, mpicom)
call shr_mpi_bcast(infodata%ocnrof_prognostic, mpicom)
call shr_mpi_bcast(infodata%ocn_c2_glcshelf, mpicom)
+ call shr_mpi_bcast(infodata%ocn_c2_glctf, mpicom)
call shr_mpi_bcast(infodata%ice_present, mpicom)
call shr_mpi_bcast(infodata%ice_prognostic, mpicom)
call shr_mpi_bcast(infodata%iceberg_prognostic, mpicom)
@@ -2515,6 +2524,7 @@ subroutine seq_infodata_Exchange(infodata,ID,type)
call shr_mpi_bcast(infodata%ocn_prognostic, mpicom, pebcast=cmppe)
call shr_mpi_bcast(infodata%ocnrof_prognostic, mpicom, pebcast=cmppe)
call shr_mpi_bcast(infodata%ocn_c2_glcshelf, mpicom, pebcast=cmppe)
+ call shr_mpi_bcast(infodata%ocn_c2_glctf, mpicom, pebcast=cmppe)
call shr_mpi_bcast(infodata%ocn_nx, mpicom, pebcast=cmppe)
call shr_mpi_bcast(infodata%ocn_ny, mpicom, pebcast=cmppe)
! dead_comps is true if it's ever set to true
@@ -2591,6 +2601,7 @@ subroutine seq_infodata_Exchange(infodata,ID,type)
call shr_mpi_bcast(infodata%ocn_prognostic, mpicom, pebcast=cplpe)
call shr_mpi_bcast(infodata%ocnrof_prognostic, mpicom, pebcast=cplpe)
call shr_mpi_bcast(infodata%ocn_c2_glcshelf, mpicom, pebcast=cplpe)
+ call shr_mpi_bcast(infodata%ocn_c2_glctf, mpicom, pebcast=cplpe)
call shr_mpi_bcast(infodata%ice_present, mpicom, pebcast=cplpe)
call shr_mpi_bcast(infodata%ice_prognostic, mpicom, pebcast=cplpe)
call shr_mpi_bcast(infodata%iceberg_prognostic, mpicom, pebcast=cplpe)
@@ -2948,6 +2959,7 @@ SUBROUTINE seq_infodata_print( infodata )
write(logunit,F0L) subname,'ocn_prognostic = ', infodata%ocn_prognostic
write(logunit,F0L) subname,'ocnrof_prognostic = ', infodata%ocnrof_prognostic
write(logunit,F0L) subname,'ocn_c2_glcshelf = ', infodata%ocn_c2_glcshelf
+ write(logunit,F0L) subname,'ocn_c2_glctf = ', infodata%ocn_c2_glctf
write(logunit,F0L) subname,'ice_present = ', infodata%ice_present
write(logunit,F0L) subname,'ice_prognostic = ', infodata%ice_prognostic
write(logunit,F0L) subname,'iceberg_prognostic = ', infodata%iceberg_prognostic