From 4015a2d01414af15ccdbb10e5eeb820a54551f3d Mon Sep 17 00:00:00 2001 From: Matthew Hoffman Date: Wed, 20 Aug 2025 15:18:31 -0500 Subject: [PATCH 1/7] Move MALI calving flux from Fogg_rofi to Figg_rofi This moves the calving flux from being passed to the ocean to being passed to sea ice. --- components/mpas-albany-landice/driver/glc_comp_mct.F | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/components/mpas-albany-landice/driver/glc_comp_mct.F b/components/mpas-albany-landice/driver/glc_comp_mct.F index 72f827960636..81c00c328488 100644 --- a/components/mpas-albany-landice/driver/glc_comp_mct.F +++ b/components/mpas-albany-landice/driver/glc_comp_mct.F @@ -1554,12 +1554,12 @@ subroutine glc_export_mct(g2x_g, errorCode) do i = 1, nCellsSolve n = n + 1 - ! Fogg_rofl + ! Fogg_rofl - liquid runoff to ocean g2x_g % rAttr(index_g2x_Fogg_rofl,n) = avgBareIceAblationApplied(i) - ! Figg_rofi - g2x_g % rAttr(index_g2x_Figg_rofi,n) = 0.0 ! placeholder - ! Fogg_rofi - g2x_g % rAttr(index_g2x_Fogg_rofi,n) = avgCalvingFlux(i) + ! Figg_rofi - solid runoff to sea ice + g2x_g % rAttr(index_g2x_Figg_rofi,n) = avgCalvingFlux(i) + ! Fogg_rofi - solid runoff to ocean + g2x_g % rAttr(index_g2x_Fogg_rofi,n) = 0.0 g2x_g % rAttr(index_g2x_Fogg_rofi,n) = g2x_g % rAttr(index_g2x_Fogg_rofi,n) + avgFaceMeltFlux(i) if (trim(config_basal_mass_bal_float) == 'ismip6') then ! if MALI is calculating ISMF, add that to rofi From 23bd1d375fe77c771d21aff2a0091c1e48176be6 Mon Sep 17 00:00:00 2001 From: Matthew Hoffman Date: Wed, 27 Aug 2025 10:31:20 -0500 Subject: [PATCH 2/7] Attach Fixx_rofi to berg fluxes in MPAS-Seaice The Fixx_rofi solid runoff flux has existed in the coupler for some time, but it had not been attached to MPAS-Seaice. This commit adds the connection to MPAS-Seaice in the ice_comp_mct import routine. The Fixx_rofi flux is passed to bergFreshwaterFlux. bergLatentHeatFlux is then calculated using ice temperature specified by config_iceberg_temperature. This commit also changes ice_export_mct so that Fioi_bergw/h are always exported - they will now either come from the coupler or from data. --- components/mpas-seaice/driver/ice_comp_mct.F | 59 +++++++++++++++---- .../mpas-seaice/driver/mpassi_cpl_indices.F | 2 + 2 files changed, 48 insertions(+), 13 deletions(-) diff --git a/components/mpas-seaice/driver/ice_comp_mct.F b/components/mpas-seaice/driver/ice_comp_mct.F index 6aaf30708bc2..f6fc6afe57d5 100644 --- a/components/mpas-seaice/driver/ice_comp_mct.F +++ b/components/mpas-seaice/driver/ice_comp_mct.F @@ -2095,6 +2095,7 @@ subroutine ice_import_mct(x2i_i, errorCode)!{{{ ! The following fields are sometimes received from the coupler, ! depending on model options: ! +! o rofi -- frozen water flux into sea ice ! o algae1 -- ! o algae2 -- ! o algae3 -- @@ -2125,6 +2126,10 @@ subroutine ice_import_mct(x2i_i, errorCode)!{{{ ! !REVISION HISTORY: ! same as module + use seaice_constants, only: & + seaiceLatentHeatMelting, & ! latent heat of melting of fresh ice (J/kg) + seaiceFreshIceSpecificHeat ! specific heat of fresh ice (J/kg/K) + ! !INPUT/OUTPUT PARAMETERS: type(mct_aVect), intent(inout) :: x2i_i @@ -2161,6 +2166,7 @@ subroutine ice_import_mct(x2i_i, errorCode)!{{{ aerosols, & atmosCoupling, & oceanCoupling, & + icebergFluxes, & biogeochemistry integer, pointer :: nCellsSolve @@ -2170,7 +2176,11 @@ subroutine ice_import_mct(x2i_i, errorCode)!{{{ config_use_modal_aerosols, & config_use_zaerosols, & config_use_column_biogeochemistry, & - config_couple_biogeochemistry_fields + config_couple_biogeochemistry_fields, & + config_use_data_icebergs + + real(kind=RKIND), pointer :: & + bergTemperature ! iceberg temperature character(len=strKIND), pointer :: & config_column_physics_type, & @@ -2201,6 +2211,8 @@ subroutine ice_import_mct(x2i_i, errorCode)!{{{ snowfallRateField, & uAirVelocityField, & vAirVelocityField, & + bergFreshwaterFluxField, & + bergLatentHeatFluxField, & oceanNitrateConcField, & oceanSilicateConcField, & oceanAmmoniumConcField, & @@ -2246,6 +2258,8 @@ subroutine ice_import_mct(x2i_i, errorCode)!{{{ snowfallRate, & uAirVelocity, & vAirVelocity, & + bergFreshwaterFlux, & + bergLatentHeatFlux, & oceanNitrateConc, & oceanSilicateConc, & oceanAmmoniumConc, & @@ -2291,6 +2305,8 @@ subroutine ice_import_mct(x2i_i, errorCode)!{{{ call mpas_pool_get_config(configs, "config_column_physics_type", config_column_physics_type) call mpas_pool_get_config(configs, "config_thermodynamics_type", config_thermodynamics_type) call mpas_pool_get_config(configs, "config_ocean_surface_type", config_ocean_surface_type) + call MPAS_pool_get_config(configs, "config_use_data_icebergs", config_use_data_icebergs) + call MPAS_pool_get_config(configs, "config_iceberg_temperature", bergTemperature) call mpas_pool_get_config(configs, "config_use_aerosols", config_use_aerosols) call mpas_pool_get_config(configs, "config_use_modal_aerosols", config_use_modal_aerosols) call mpas_pool_get_config(configs, "config_use_column_biogeochemistry", config_use_column_biogeochemistry) @@ -2328,6 +2344,12 @@ subroutine ice_import_mct(x2i_i, errorCode)!{{{ call mpas_pool_get_array(atmosCoupling, 'uAirVelocity', uAirVelocity) call mpas_pool_get_array(atmosCoupling, 'vAirVelocity', vAirVelocity) + if (.not. config_use_data_icebergs) then + call MPAS_pool_get_subpool(block_ptr % structs, "berg_fluxes", icebergFluxes) + call MPAS_pool_get_array(icebergFluxes, "bergFreshwaterFlux", bergFreshwaterFlux) + call MPAS_pool_get_array(icebergFluxes, "bergLatentHeatFlux", bergLatentHeatFlux) + endif + if (config_use_aerosols) then call mpas_pool_get_subpool(block_ptr % structs, 'aerosols', aerosols) @@ -2417,6 +2439,13 @@ subroutine ice_import_mct(x2i_i, errorCode)!{{{ uAirVelocity(i) = x2i_i % rAttr(index_x2i_Sa_u, n) vAirVelocity(i) = x2i_i % rAttr(index_x2i_Sa_v, n) + ! if not using data icebergs, import icebergs here + if (.not. config_use_data_icebergs) then + bergFreshwaterFlux(i) = x2i_i % rAttr(index_x2i_Fixx_rofi, n) + bergLatentHeatFlux(i) = bergFreshwaterFlux(i) * & + (seaiceLatentHeatMelting - seaiceFreshIceSpecificHeat*bergTemperature) + endif + ! set aerosols, if configured if (config_use_aerosols) then if (config_use_modal_aerosols) then @@ -2641,6 +2670,14 @@ subroutine ice_import_mct(x2i_i, errorCode)!{{{ call mpas_dmpar_exch_halo_field(uAirVelocityField) call mpas_dmpar_exch_halo_field(vAirVelocityField) + if (.not. config_use_data_icebergs) then + call mpas_pool_get_subpool(domain % blocklist % structs, 'berg_fluxes', icebergFluxes) + call mpas_pool_get_field(icebergFluxes, 'bergFreshwaterFlux', bergFreshwaterFluxField) + call mpas_pool_get_field(icebergFluxes, 'bergLatentHeatFlux', bergLatentHeatFluxField) + call mpas_dmpar_exch_halo_field(bergFreshwaterFluxField) + call mpas_dmpar_exch_halo_field(bergLatentHeatFluxField) + endif + if (config_use_aerosols) then call mpas_dmpar_exch_halo_field(atmosAerosolFluxField) endif @@ -2742,8 +2779,7 @@ subroutine ice_export_mct(i2x_i, errorCode) !{{{ config_use_column_biogeochemistry, & config_use_zaerosols, & config_couple_biogeochemistry_fields, & - config_use_column_shortwave, & - config_use_data_icebergs + config_use_column_shortwave real(kind=RKIND), pointer :: & sphere_radius @@ -2818,7 +2854,6 @@ subroutine ice_export_mct(i2x_i, errorCode) !{{{ call MPAS_pool_get_config(configs, "config_use_column_biogeochemistry", config_use_column_biogeochemistry) call mpas_pool_get_config(configs, "config_couple_biogeochemistry_fields", config_couple_biogeochemistry_fields) call MPAS_pool_get_config(configs, "config_use_column_shortwave", config_use_column_shortwave) - call MPAS_pool_get_config(configs, "config_use_data_icebergs", config_use_data_icebergs) call MPAS_pool_get_subpool(block_ptr % structs, 'mesh', meshPool) call MPAS_pool_get_subpool(block_ptr % structs, "tracers_aggregate", tracersAggregate) @@ -2872,12 +2907,10 @@ subroutine ice_export_mct(i2x_i, errorCode) !{{{ call MPAS_pool_get_array(oceanFluxes, 'oceanFreshWaterFlux', oceanFreshWaterFlux) call MPAS_pool_get_array(oceanFluxes, 'oceanSaltFlux', oceanSaltFlux) - if (config_use_data_icebergs) then - call MPAS_pool_get_subpool(block_ptr % structs, "berg_fluxes", icebergFluxes) + call MPAS_pool_get_subpool(block_ptr % structs, "berg_fluxes", icebergFluxes) - call MPAS_pool_get_array(icebergFluxes, "bergFreshwaterFlux", bergFreshwaterFlux) - call MPAS_pool_get_array(icebergFluxes, "bergLatentHeatFlux", bergLatentHeatFlux) - endif + call MPAS_pool_get_array(icebergFluxes, "bergFreshwaterFlux", bergFreshwaterFlux) + call MPAS_pool_get_array(icebergFluxes, "bergLatentHeatFlux", bergLatentHeatFlux) if (config_use_column_biogeochemistry .and. config_couple_biogeochemistry_fields) then call mpas_pool_get_subpool(block_ptr % structs, 'biogeochemistry', biogeochemistry) @@ -2956,10 +2989,10 @@ subroutine ice_export_mct(i2x_i, errorCode) !{{{ !-------states-------------------- i2x_i % rAttr(index_i2x_Si_ifrac ,n) = ailohi - if (config_use_data_icebergs) then - i2x_i % rAttr(index_i2x_Fioi_bergw,n) = bergFreshwaterFlux(i) - i2x_i % rAttr(index_i2x_Fioi_bergh,n) = bergLatentHeatFlux(i) - endif + ! Always export berg fluxes - they are either from coupler or from data + ! but either way have been assigned at this point + i2x_i % rAttr(index_i2x_Fioi_bergw,n) = bergFreshwaterFlux(i) + i2x_i % rAttr(index_i2x_Fioi_bergh,n) = bergLatentHeatFlux(i) if ( ailohi > 0.0_RKIND ) then diff --git a/components/mpas-seaice/driver/mpassi_cpl_indices.F b/components/mpas-seaice/driver/mpassi_cpl_indices.F index 8646233475bb..b32fae41c04b 100644 --- a/components/mpas-seaice/driver/mpassi_cpl_indices.F +++ b/components/mpas-seaice/driver/mpassi_cpl_indices.F @@ -87,6 +87,7 @@ module mpassi_cpl_indices integer :: index_x2i_Faxa_swnet ! sw: net integer :: index_x2i_Fioo_q ! ocn freezing melting potential integer :: index_x2i_Fioo_frazil ! ocn frazil ice formation + integer :: index_x2i_Fixx_rofi ! flux: frozen water flux into sea ice integer :: index_x2i_Faxa_bcphidry ! flux: Black Carbon hydrophilic dry deposition integer :: index_x2i_Faxa_bcphodry ! flux: Black Carbon hydrophobic dry deposition integer :: index_x2i_Faxa_bcphiwet ! flux: Black Carbon hydrophilic wet deposition @@ -214,6 +215,7 @@ subroutine mpassi_cpl_indices_set( ) index_x2i_Faxa_swvdf = mct_avect_indexra(x2i,'Faxa_swvdf') index_x2i_Fioo_q = mct_avect_indexra(x2i,'Fioo_q') index_x2i_Fioo_frazil = mct_avect_indexra(x2i,'Fioo_frazil') + index_x2i_Fixx_rofi = mct_avect_indexra(x2i,'Fixx_rofi') index_x2i_Faxa_bcphidry = mct_avect_indexra(x2i,'Faxa_bcphidry') index_x2i_Faxa_bcphodry = mct_avect_indexra(x2i,'Faxa_bcphodry') index_x2i_Faxa_bcphiwet = mct_avect_indexra(x2i,'Faxa_bcphiwet') From 847a790ade27aed665a59ff58a90041510e1fe2d Mon Sep 17 00:00:00 2001 From: Matthew Hoffman Date: Wed, 27 Aug 2025 21:34:47 -0500 Subject: [PATCH 3/7] Remove berg package from berg variables With Fixx_rofi now being coupled to ice, the berg variables will be used all the time when running in E3SM, as opposed to just when data icebergs are active. Note that this is unlikely to be the most desirable solution; the berg variables would ideally be disabled for standalone MPAS-Seaice, but with this change they will always be allocated. I could not find an obvious way to make the package conditional on MPAS-Seaice being run within E3SM, which I think would be the preferred criterion. Also, if the solution of having the berg variables be always allocated is acceptable, then there is no longer a need for the berg package and it could be fully removed. So either way, this commit will need to be revisited. --- components/mpas-seaice/src/Registry.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/mpas-seaice/src/Registry.xml b/components/mpas-seaice/src/Registry.xml index ed94bb094e88..fa2a2dae6fb6 100644 --- a/components/mpas-seaice/src/Registry.xml +++ b/components/mpas-seaice/src/Registry.xml @@ -4967,7 +4967,7 @@ - + Date: Wed, 27 Aug 2025 22:48:10 -0500 Subject: [PATCH 4/7] Enable coupler var iceberg_prognostic from seaice driver This coupler flag is what tells the coupler to send rofi fluxes from ROF and GLC to ICE. This will allow seaice to act as a pass-through for rofi fluxes to the ocean. When an iceberg model is eventually added to MPAS-Seaice, it can redistribute icebergs before they are passed on to the ocean. --- components/mpas-seaice/driver/ice_comp_mct.F | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/mpas-seaice/driver/ice_comp_mct.F b/components/mpas-seaice/driver/ice_comp_mct.F index f6fc6afe57d5..a8a4b9bcd25f 100644 --- a/components/mpas-seaice/driver/ice_comp_mct.F +++ b/components/mpas-seaice/driver/ice_comp_mct.F @@ -874,7 +874,7 @@ end subroutine xml_stream_get_attributes call t_stopf ('mpassi_mct_init') - call seq_infodata_PutData( infodata, ice_prognostic=.true.) + call seq_infodata_PutData( infodata, ice_prognostic=.true., iceberg_prognostic=.true.) !----------------------------------------------------------------------- ! From 95613490937b358a0b5dd73fd0d420e518d0fca2 Mon Sep 17 00:00:00 2001 From: Matthew Hoffman Date: Fri, 29 Aug 2025 13:59:15 -0500 Subject: [PATCH 5/7] Fix field list in prep_ice_calc_g2x_ix Fixx_rofi had been specified in this list when Fixx_rofi coupling was partially implemented (but not tested) years ago. However, that is the wrong variable at this point in the coupling chain - Figg_rofi is the field that needs to be remapped at this stage. Note that usually a previously defined list of variables is used at this stage, as opposed to hardcoding a variable name/list, but I am modifying the existing implementation and not changing that here. --- driver-mct/main/prep_ice_mod.F90 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/driver-mct/main/prep_ice_mod.F90 b/driver-mct/main/prep_ice_mod.F90 index 36c478f6fc21..4e8a849c50c9 100644 --- a/driver-mct/main/prep_ice_mod.F90 +++ b/driver-mct/main/prep_ice_mod.F90 @@ -561,7 +561,7 @@ subroutine prep_ice_calc_g2x_ix(timer) do egi = 1,num_inst_glc g2x_gx => component_get_c2x_cx(glc(egi)) call seq_map_map(mapper_Rg2i, g2x_gx, g2x_ix(egi), & - fldlist='Fixx_rofi', norm=.true.) + fldlist='Figg_rofi', norm=.true.) enddo call t_drvstopf (trim(timer)) From 576a92d290bfb51cc09dc5c7a5d47781bd7daca1 Mon Sep 17 00:00:00 2001 From: Matthew Hoffman Date: Thu, 28 Aug 2025 10:17:04 -0500 Subject: [PATCH 6/7] Add new ROF2ICE_RMAPTYPE xml variable --- driver-mct/cime_config/config_component.xml | 17 +++++++++++ .../cime_config/namelist_definition_drv.xml | 29 +++++++++++++++++++ 2 files changed, 46 insertions(+) diff --git a/driver-mct/cime_config/config_component.xml b/driver-mct/cime_config/config_component.xml index b065cae41f40..b9df3738f8da 100644 --- a/driver-mct/cime_config/config_component.xml +++ b/driver-mct/cime_config/config_component.xml @@ -1738,6 +1738,23 @@ rof2ocn runoff mapping file decomp type + + char + idmap + run_domain + env_run.xml + rof2ice runoff mapping file + + + + char + X,Y + Y + run_domain + env_run.xml + rof2ice runoff mapping file decomp type + + char idmap diff --git a/driver-mct/cime_config/namelist_definition_drv.xml b/driver-mct/cime_config/namelist_definition_drv.xml index 227d4619869c..228f237dcd0b 100644 --- a/driver-mct/cime_config/namelist_definition_drv.xml +++ b/driver-mct/cime_config/namelist_definition_drv.xml @@ -4748,6 +4748,35 @@ + + char + mapping + abs + seq_maps + + runoff to ice mapping file + + + $ROF2ICE_RMAPNAME + + + + + 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. + + + $ROF2ICE_RMAPTYPE + X + + char From c7c4fc8bec319d4369e19325e2233aa3ba078abd Mon Sep 17 00:00:00 2001 From: Matthew Hoffman Date: Thu, 28 Aug 2025 10:17:39 -0500 Subject: [PATCH 7/7] Add new mapping file specifications - follow up reqd This commit adds mapping file specifications needed to run a LR G-case. This commit should be followed up with a more complete addition for other grids. --- cime_config/config_grids.xml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/cime_config/config_grids.xml b/cime_config/config_grids.xml index 179d8af39739..70641cd1c660 100755 --- a/cime_config/config_grids.xml +++ b/cime_config/config_grids.xml @@ -5910,6 +5910,7 @@ cpl/cpl6/map_JRA025_to_IcoswISC30E3r5_cstmnn.r150e300.20231121.nc cpl/cpl6/map_JRA025_to_IcoswISC30E3r5_cstmnn.r150e300.20231121.nc + cpl/cpl6/map_JRA025_to_IcoswISC30E3r5_cstmnn.r150e300.20231121.nc @@ -6486,6 +6487,7 @@ cpl/gridmaps/IcoswISC30E3r5/map_IcoswISC30E3r5-nomask_to_ais4to20_esmfaave.20240701.nc cpl/gridmaps/IcoswISC30E3r5/map_IcoswISC30E3r5-nomask_to_ais4to20_esmfbilin.20240701.nc cpl/gridmaps/IcoswISC30E3r5/map_IcoswISC30E3r5-nomask_to_ais4to20_esmfbilin.20250403.nc + cpl/gridmaps/mpas.ais4to20km/map_ais4to20_to_IcoswISC30E3r5-nomask_esmfaave.20240701.nc cpl/gridmaps/mpas.ais4to20km/map_ais4to20_to_IcoswISC30E3r5-nomask_esmfaave.20240701.nc cpl/gridmaps/mpas.ais4to20km/map_ais4to20_to_IcoswISC30E3r5-nomask_esmfbilin.20240701.nc cpl/gridmaps/mpas.ais4to20km/map_ais4to20_to_IcoswISC30E3r5-nomask_esmfaave.20240701.nc