From b3e65c63533bf17ae3dd70243f8827fa277ff386 Mon Sep 17 00:00:00 2001 From: Henri Drake Date: Thu, 15 Aug 2024 10:18:27 -0700 Subject: [PATCH 1/4] Attempt to pass new seaice_melt field through the GFDL MOM6-SIS2 coupler See companion commit https://github.com/hdrake/SIS2/commit/1c8dc7e8f73aba6ba5109524fbd455c44b1ea2e7 --- .../FMS_cap/MOM_surface_forcing_gfdl.F90 | 20 ++++++++++++++----- .../STALE_mct_cap/mom_surface_forcing_mct.F90 | 2 +- .../nuopc_cap/mom_surface_forcing_nuopc.F90 | 12 +++++------ 3 files changed, 22 insertions(+), 12 deletions(-) diff --git a/config_src/drivers/FMS_cap/MOM_surface_forcing_gfdl.F90 b/config_src/drivers/FMS_cap/MOM_surface_forcing_gfdl.F90 index 825f0cc29a..3e467dd043 100644 --- a/config_src/drivers/FMS_cap/MOM_surface_forcing_gfdl.F90 +++ b/config_src/drivers/FMS_cap/MOM_surface_forcing_gfdl.F90 @@ -184,10 +184,11 @@ module MOM_surface_forcing_gfdl real, pointer, dimension(:,:) :: sw_flux_vis_dif =>NULL() !< diffuse visible sw radiation [W m-2] real, pointer, dimension(:,:) :: sw_flux_nir_dir =>NULL() !< direct Near InfraRed sw radiation [W m-2] real, pointer, dimension(:,:) :: sw_flux_nir_dif =>NULL() !< diffuse Near InfraRed sw radiation [W m-2] - real, pointer, dimension(:,:) :: lprec =>NULL() !< mass flux of liquid precip [kg m-2 s-1] - real, pointer, dimension(:,:) :: fprec =>NULL() !< mass flux of frozen precip [kg m-2 s-1] - real, pointer, dimension(:,:) :: runoff =>NULL() !< mass flux of liquid runoff [kg m-2 s-1] - real, pointer, dimension(:,:) :: calving =>NULL() !< mass flux of frozen runoff [kg m-2 s-1] + real, pointer, dimension(:,:) :: lprec =>NULL() !< mass flux of liquid precip [kg m-2 s-1] + real, pointer, dimension(:,:) :: fprec =>NULL() !< mass flux of frozen precip [kg m-2 s-1] + real, pointer, dimension(:,:) :: seaice_melt =>NULL() !< mass flux of melted sea ice [kg m-2 s-1] + real, pointer, dimension(:,:) :: runoff =>NULL() !< mass flux of liquid runoff [kg m-2 s-1] + real, pointer, dimension(:,:) :: calving =>NULL() !< mass flux of frozen runoff [kg m-2 s-1] real, pointer, dimension(:,:) :: stress_mag =>NULL() !< The time-mean magnitude of the stress on the ocean [Pa] real, pointer, dimension(:,:) :: ustar_berg =>NULL() !< frictional velocity beneath icebergs [m s-1] real, pointer, dimension(:,:) :: area_berg =>NULL() !< fractional area covered by icebergs [m2 m-2] @@ -446,6 +447,12 @@ subroutine convert_IOB_to_fluxes(IOB, fluxes, index_bounds, Time, valid_time, G, call check_mask_val_consistency(IOB%fprec(i-i0,j-j0), G%mask2dT(i,j), i, j, 'fprec', G) endif + if (associated(IOB%seaice_melt)) then + fluxes%seaice_melt(i,j) = kg_m2_s_conversion * IOB%seaice_melt(i-i0,j-j0) * G%mask2dT(i,j) + if (CS%check_no_land_fluxes) & + call check_mask_val_consistency(IOB%seaice_melt(i-i0,j-j0), G%mask2dT(i,j), i, j, 'seaice_melt', G) + endif + if (associated(IOB%q_flux)) then fluxes%evap(i,j) = - kg_m2_s_conversion * IOB%q_flux(i-i0,j-j0) * G%mask2dT(i,j) if (CS%check_no_land_fluxes) & @@ -604,7 +611,7 @@ subroutine convert_IOB_to_fluxes(IOB, fluxes, index_bounds, Time, valid_time, G, if (CS%use_net_FW_adjustment_sign_bug) sign_for_net_FW_bug = -1. do j=js,je ; do i=is,ie net_FW(i,j) = US%RZ_T_to_kg_m2s* & - (((fluxes%lprec(i,j) + fluxes%fprec(i,j)) + & + (((fluxes%lprec(i,j) + fluxes%fprec(i,j) + fluxes%seaice_melt(i,j)) + & (fluxes%lrunoff(i,j) + fluxes%frunoff(i,j))) + & (fluxes%evap(i,j) + fluxes%vprec(i,j)) ) * US%L_to_m**2*G%areaT(i,j) ! The following contribution appears to be calculating the volume flux of sea-ice @@ -828,6 +835,8 @@ subroutine convert_IOB_to_forces(IOB, forces, index_bounds, Time, G, US, CS, dt_ net_mass_src(i,j) = net_mass_src(i,j) + kg_m2_s_conversion * IOB%lprec(i-i0,j-j0) if (associated(IOB%fprec)) & net_mass_src(i,j) = net_mass_src(i,j) + kg_m2_s_conversion * IOB%fprec(i-i0,j-j0) + if (associated(IOB%seaice_melt)) & + net_mass_src(i,j) = net_mass_src(i,j) + kg_m2_s_conversion * IOB%seaice_melt(i-i0,j-j0) if (associated(IOB%runoff)) & net_mass_src(i,j) = net_mass_src(i,j) + kg_m2_s_conversion * IOB%runoff(i-i0,j-j0) if (associated(IOB%calving)) & @@ -1787,6 +1796,7 @@ subroutine ice_ocn_bnd_type_chksum(id, timestep, iobt) chks = field_chksum( iobt%sw_flux_nir_dif) ; if (root) write(outunit,100) 'iobt%sw_flux_nir_dif', chks chks = field_chksum( iobt%lprec ) ; if (root) write(outunit,100) 'iobt%lprec ', chks chks = field_chksum( iobt%fprec ) ; if (root) write(outunit,100) 'iobt%fprec ', chks + chks = field_chksum( iobt%seaice_melt ) ; if (root) write(outunit,100) 'iobt%seaice_melt ', chks chks = field_chksum( iobt%runoff ) ; if (root) write(outunit,100) 'iobt%runoff ', chks chks = field_chksum( iobt%calving ) ; if (root) write(outunit,100) 'iobt%calving ', chks chks = field_chksum( iobt%p ) ; if (root) write(outunit,100) 'iobt%p ', chks diff --git a/config_src/drivers/STALE_mct_cap/mom_surface_forcing_mct.F90 b/config_src/drivers/STALE_mct_cap/mom_surface_forcing_mct.F90 index bb57810f5b..88ba576cb6 100644 --- a/config_src/drivers/STALE_mct_cap/mom_surface_forcing_mct.F90 +++ b/config_src/drivers/STALE_mct_cap/mom_surface_forcing_mct.F90 @@ -1402,7 +1402,6 @@ subroutine ice_ocn_bnd_type_chksum(id, timestep, iobt) chks = field_chksum( iobt%t_flux ) ; if (root) write(outunit,100) 'iobt%t_flux ', chks chks = field_chksum( iobt%q_flux ) ; if (root) write(outunit,100) 'iobt%q_flux ', chks chks = field_chksum( iobt%seaice_melt_heat); if (root) write(outunit,100) 'iobt%seaice_melt_heat', chks - chks = field_chksum( iobt%seaice_melt) ; if (root) write(outunit,100) 'iobt%seaice_melt ', chks chks = field_chksum( iobt%salt_flux ) ; if (root) write(outunit,100) 'iobt%salt_flux ', chks chks = field_chksum( iobt%lw_flux ) ; if (root) write(outunit,100) 'iobt%lw_flux ', chks chks = field_chksum( iobt%sw_flux_vis_dir) ; if (root) write(outunit,100) 'iobt%sw_flux_vis_dir', chks @@ -1411,6 +1410,7 @@ subroutine ice_ocn_bnd_type_chksum(id, timestep, iobt) chks = field_chksum( iobt%sw_flux_nir_dif) ; if (root) write(outunit,100) 'iobt%sw_flux_nir_dif', chks chks = field_chksum( iobt%lprec ) ; if (root) write(outunit,100) 'iobt%lprec ', chks chks = field_chksum( iobt%fprec ) ; if (root) write(outunit,100) 'iobt%fprec ', chks + chks = field_chksum( iobt%seaice_melt) ; if (root) write(outunit,100) 'iobt%seaice_melt ', chks chks = field_chksum( iobt%rofl_flux ) ; if (root) write(outunit,100) 'rofl_flux ', chks chks = field_chksum( iobt%rofi_flux ) ; if (root) write(outunit,100) 'rofi_flux ', chks chks = field_chksum( iobt%p ) ; if (root) write(outunit,100) 'iobt%p ', chks diff --git a/config_src/drivers/nuopc_cap/mom_surface_forcing_nuopc.F90 b/config_src/drivers/nuopc_cap/mom_surface_forcing_nuopc.F90 index e7d6c9abc6..d6e7922f68 100644 --- a/config_src/drivers/nuopc_cap/mom_surface_forcing_nuopc.F90 +++ b/config_src/drivers/nuopc_cap/mom_surface_forcing_nuopc.F90 @@ -165,7 +165,6 @@ module MOM_surface_forcing_nuopc real, pointer, dimension(:,:) :: q_flux =>NULL() !< specific humidity flux [kg/m2/s] real, pointer, dimension(:,:) :: salt_flux =>NULL() !< salt flux [kg/m2/s] real, pointer, dimension(:,:) :: seaice_melt_heat =>NULL() !< sea ice and snow melt heat flux [W/m2] - real, pointer, dimension(:,:) :: seaice_melt =>NULL() !< water flux due to sea ice and snow melting [kg/m2/s] real, pointer, dimension(:,:) :: lw_flux =>NULL() !< long wave radiation [W/m2] real, pointer, dimension(:,:) :: sw_flux_vis_dir =>NULL() !< direct visible sw radiation [W/m2] real, pointer, dimension(:,:) :: sw_flux_vis_dif =>NULL() !< diffuse visible sw radiation [W/m2] @@ -173,6 +172,7 @@ module MOM_surface_forcing_nuopc real, pointer, dimension(:,:) :: sw_flux_nir_dif =>NULL() !< diffuse Near InfraRed sw radiation [W/m2] real, pointer, dimension(:,:) :: lprec =>NULL() !< mass flux of liquid precip [kg/m2/s] real, pointer, dimension(:,:) :: fprec =>NULL() !< mass flux of frozen precip [kg/m2/s] + real, pointer, dimension(:,:) :: seaice_melt =>NULL() !< water flux due to sea ice and snow melting [kg/m2/s] real, pointer, dimension(:,:) :: ustar_berg =>NULL() !< frictional velocity beneath icebergs [m/s] real, pointer, dimension(:,:) :: area_berg =>NULL() !< area covered by icebergs[m2/m2] real, pointer, dimension(:,:) :: mass_berg =>NULL() !< mass of icebergs(kg/m2) @@ -459,6 +459,10 @@ subroutine convert_IOB_to_fluxes(IOB, fluxes, index_bounds, Time, valid_time, G, if (associated(IOB%fprec)) & fluxes%fprec(i,j) = kg_m2_s_conversion * IOB%fprec(i-i0,j-j0) * G%mask2dT(i,j) + ! water flux due to sea ice and snow melt [kg/m2/s] + if (associated(IOB%seaice_melt)) & + fluxes%seaice_melt(i,j) = kg_m2_s_conversion * G%mask2dT(i,j) * IOB%seaice_melt(i-i0,j-j0) + if (associated(IOB%q_flux)) & fluxes%evap(i,j) = kg_m2_s_conversion * IOB%q_flux(i-i0,j-j0) * G%mask2dT(i,j) @@ -491,10 +495,6 @@ subroutine convert_IOB_to_fluxes(IOB, fluxes, index_bounds, Time, valid_time, G, if (associated(IOB%seaice_melt_heat)) & fluxes%seaice_melt_heat(i,j) = US%W_m2_to_QRZ_T * G%mask2dT(i,j) * IOB%seaice_melt_heat(i-i0,j-j0) - ! water flux due to sea ice and snow melt [kg/m2/s] - if (associated(IOB%seaice_melt)) & - fluxes%seaice_melt(i,j) = kg_m2_s_conversion * G%mask2dT(i,j) * IOB%seaice_melt(i-i0,j-j0) - fluxes%latent(i,j) = 0.0 ! notice minus sign since fprec is positive into the ocean if (associated(IOB%fprec)) then @@ -1493,7 +1493,6 @@ subroutine ice_ocn_bnd_type_chksum(id, timestep, iobt) chks = field_chksum( iobt%t_flux ) ; if (root) write(outunit,100) 'iobt%t_flux ', chks chks = field_chksum( iobt%q_flux ) ; if (root) write(outunit,100) 'iobt%q_flux ', chks chks = field_chksum( iobt%seaice_melt_heat); if (root) write(outunit,100) 'iobt%seaice_melt_heat', chks - chks = field_chksum( iobt%seaice_melt) ; if (root) write(outunit,100) 'iobt%seaice_melt ', chks chks = field_chksum( iobt%salt_flux ) ; if (root) write(outunit,100) 'iobt%salt_flux ', chks chks = field_chksum( iobt%lw_flux ) ; if (root) write(outunit,100) 'iobt%lw_flux ', chks chks = field_chksum( iobt%sw_flux_vis_dir) ; if (root) write(outunit,100) 'iobt%sw_flux_vis_dir', chks @@ -1502,6 +1501,7 @@ subroutine ice_ocn_bnd_type_chksum(id, timestep, iobt) chks = field_chksum( iobt%sw_flux_nir_dif) ; if (root) write(outunit,100) 'iobt%sw_flux_nir_dif', chks chks = field_chksum( iobt%lprec ) ; if (root) write(outunit,100) 'iobt%lprec ', chks chks = field_chksum( iobt%fprec ) ; if (root) write(outunit,100) 'iobt%fprec ', chks + chks = field_chksum( iobt%seaice_melt ) ; if (root) write(outunit,100) 'iobt%seaice_melt ', chks chks = field_chksum( iobt%lrunoff ) ; if (root) write(outunit,100) 'iobt%lrunoff ', chks chks = field_chksum( iobt%frunoff ) ; if (root) write(outunit,100) 'iobt%frunoff ', chks chks = field_chksum( iobt%p ) ; if (root) write(outunit,100) 'iobt%p ', chks From 202ff90d4ab0332c0d33c7ee45df9a2b05f2f231 Mon Sep 17 00:00:00 2001 From: Henri Drake Date: Thu, 15 Aug 2024 12:50:10 -0700 Subject: [PATCH 2/4] Pass `seaice_melt` through all ice-ocean couplers Some other minor bug fixes --- .../FMS_cap/MOM_surface_forcing_gfdl.F90 | 1 + .../STALE_mct_cap/mom_surface_forcing_mct.F90 | 10 ++-- .../drivers/STALE_mct_cap/ocn_cap_methods.F90 | 6 +-- .../drivers/STALE_mct_cap/ocn_comp_mct.F90 | 2 +- .../nuopc_cap/mom_surface_forcing_nuopc.F90 | 5 +- .../solo_driver/MESO_surface_forcing.F90 | 2 + .../solo_driver/MOM_surface_forcing.F90 | 50 +++++++++++-------- .../solo_driver/user_surface_forcing.F90 | 4 +- src/core/MOM_forcing_type.F90 | 48 ++++++++---------- .../vertical/MOM_diabatic_aux.F90 | 3 +- src/user/BFB_surface_forcing.F90 | 2 + src/user/dumbbell_surface_forcing.F90 | 2 + 12 files changed, 71 insertions(+), 64 deletions(-) diff --git a/config_src/drivers/FMS_cap/MOM_surface_forcing_gfdl.F90 b/config_src/drivers/FMS_cap/MOM_surface_forcing_gfdl.F90 index 3e467dd043..cfcddd6fb8 100644 --- a/config_src/drivers/FMS_cap/MOM_surface_forcing_gfdl.F90 +++ b/config_src/drivers/FMS_cap/MOM_surface_forcing_gfdl.F90 @@ -1796,6 +1796,7 @@ subroutine ice_ocn_bnd_type_chksum(id, timestep, iobt) chks = field_chksum( iobt%sw_flux_nir_dif) ; if (root) write(outunit,100) 'iobt%sw_flux_nir_dif', chks chks = field_chksum( iobt%lprec ) ; if (root) write(outunit,100) 'iobt%lprec ', chks chks = field_chksum( iobt%fprec ) ; if (root) write(outunit,100) 'iobt%fprec ', chks +! hfd/Gives error: "Program received signal SIGSEGV: Segmentation fault - invalid memory reference." chks = field_chksum( iobt%seaice_melt ) ; if (root) write(outunit,100) 'iobt%seaice_melt ', chks chks = field_chksum( iobt%runoff ) ; if (root) write(outunit,100) 'iobt%runoff ', chks chks = field_chksum( iobt%calving ) ; if (root) write(outunit,100) 'iobt%calving ', chks diff --git a/config_src/drivers/STALE_mct_cap/mom_surface_forcing_mct.F90 b/config_src/drivers/STALE_mct_cap/mom_surface_forcing_mct.F90 index 88ba576cb6..2a4de8ddd7 100644 --- a/config_src/drivers/STALE_mct_cap/mom_surface_forcing_mct.F90 +++ b/config_src/drivers/STALE_mct_cap/mom_surface_forcing_mct.F90 @@ -156,7 +156,6 @@ module MOM_surface_forcing_mct real, pointer, dimension(:,:) :: q_flux =>NULL() !< specific humidity flux [kg/m2/s] real, pointer, dimension(:,:) :: salt_flux =>NULL() !< salt flux [kg/m2/s] real, pointer, dimension(:,:) :: seaice_melt_heat =>NULL() !< sea ice and snow melt heat flux [W/m2] - real, pointer, dimension(:,:) :: seaice_melt =>NULL() !< water flux due to sea ice and snow melting [kg/m2/s] real, pointer, dimension(:,:) :: lw_flux =>NULL() !< long wave radiation [W/m2] real, pointer, dimension(:,:) :: sw_flux_vis_dir =>NULL() !< direct visible sw radiation [W/m2] real, pointer, dimension(:,:) :: sw_flux_vis_dif =>NULL() !< diffuse visible sw radiation [W/m2] @@ -164,6 +163,7 @@ module MOM_surface_forcing_mct real, pointer, dimension(:,:) :: sw_flux_nir_dif =>NULL() !< diffuse Near InfraRed sw radiation [W/m2] real, pointer, dimension(:,:) :: lprec =>NULL() !< mass flux of liquid precip [kg/m2/s] real, pointer, dimension(:,:) :: fprec =>NULL() !< mass flux of frozen precip [kg/m2/s] + real, pointer, dimension(:,:) :: seaice_melt =>NULL() !< water flux due to sea ice and snow melting [kg/m2/s] real, pointer, dimension(:,:) :: runoff =>NULL() !< mass flux of liquid runoff [kg/m2/s] real, pointer, dimension(:,:) :: calving =>NULL() !< mass flux of frozen runoff [kg/m2/s] real, pointer, dimension(:,:) :: ustar_berg =>NULL() !< frictional velocity beneath icebergs [m/s] @@ -428,6 +428,10 @@ subroutine convert_IOB_to_fluxes(IOB, fluxes, index_bounds, Time, valid_time, G, if (associated(IOB%fprec)) & fluxes%fprec(i,j) = kg_m2_s_conversion * IOB%fprec(i-i0,j-j0) * G%mask2dT(i,j) + ! water flux due to sea ice and snow melt + if (associated(IOB%seaice_melt)) & + fluxes%seaice_melt(i,j) = kg_m2_s_conversion * IOB%seaice_melt(i-i0,j-j0) * G%mask2dT(i,j) + ! evaporation if (associated(IOB%q_flux)) & fluxes%evap(i,j) = kg_m2_s_conversion * IOB%q_flux(i-i0,j-j0) * G%mask2dT(i,j) @@ -477,10 +481,6 @@ subroutine convert_IOB_to_fluxes(IOB, fluxes, index_bounds, Time, valid_time, G, if (associated(IOB%seaice_melt_heat)) & fluxes%seaice_melt_heat(i,j) = G%mask2dT(i,j) * US%W_m2_to_QRZ_T * IOB%seaice_melt_heat(i-i0,j-j0) - ! water flux due to sea ice and snow melt [kg/m2/s] - if (associated(IOB%seaice_melt)) & - fluxes%seaice_melt(i,j) = G%mask2dT(i,j) * kg_m2_s_conversion * IOB%seaice_melt(i-i0,j-j0) - ! latent heat flux (W/m^2) fluxes%latent(i,j) = 0.0 ! contribution from frozen ppt (notice minus sign since fprec is positive into the ocean) diff --git a/config_src/drivers/STALE_mct_cap/ocn_cap_methods.F90 b/config_src/drivers/STALE_mct_cap/ocn_cap_methods.F90 index 0b7a331458..8199c32cd6 100644 --- a/config_src/drivers/STALE_mct_cap/ocn_cap_methods.F90 +++ b/config_src/drivers/STALE_mct_cap/ocn_cap_methods.F90 @@ -62,6 +62,9 @@ subroutine ocn_import(x2o, ind, grid, ice_ocean_boundary, ocean_public, logunit, ! frozen precipitation (snow) ice_ocean_boundary%fprec(i,j) = x2o(ind%x2o_Faxa_snow,k) + ! water flux from snow&ice melt (kg/m2/s) + ice_ocean_boundary%seaice_melt(i,j) = x2o(ind%x2o_Fioi_meltw,k) + ! longwave radiation, sum up and down (W/m2) ice_ocean_boundary%lw_flux(i,j) = (x2o(ind%x2o_Faxa_lwdn,k) + x2o(ind%x2o_Foxx_lwup,k)) @@ -74,9 +77,6 @@ subroutine ocn_import(x2o, ind, grid, ice_ocean_boundary, ocean_public, logunit, ! snow&ice melt heat flux (W/m^2) ice_ocean_boundary%seaice_melt_heat(i,j) = x2o(ind%x2o_Fioi_melth,k) - ! water flux from snow&ice melt (kg/m2/s) - ice_ocean_boundary%seaice_melt(i,j) = x2o(ind%x2o_Fioi_meltw,k) - ! liquid runoff ice_ocean_boundary%rofl_flux(i,j) = x2o(ind%x2o_Foxx_rofl,k) * GRID%mask2dT(i,j) diff --git a/config_src/drivers/STALE_mct_cap/ocn_comp_mct.F90 b/config_src/drivers/STALE_mct_cap/ocn_comp_mct.F90 index 85b7350b77..2ed30e2ea9 100644 --- a/config_src/drivers/STALE_mct_cap/ocn_comp_mct.F90 +++ b/config_src/drivers/STALE_mct_cap/ocn_comp_mct.F90 @@ -858,7 +858,6 @@ subroutine IOB_allocate(IOB, isc, iec, jsc, jec) IOB% v_flux (isc:iec,jsc:jec), & IOB% t_flux (isc:iec,jsc:jec), & IOB% seaice_melt_heat (isc:iec,jsc:jec),& - IOB% seaice_melt (isc:iec,jsc:jec), & IOB% q_flux (isc:iec,jsc:jec), & IOB% salt_flux (isc:iec,jsc:jec), & IOB% lw_flux (isc:iec,jsc:jec), & @@ -868,6 +867,7 @@ subroutine IOB_allocate(IOB, isc, iec, jsc, jec) IOB% sw_flux_nir_dif (isc:iec,jsc:jec), & IOB% lprec (isc:iec,jsc:jec), & IOB% fprec (isc:iec,jsc:jec), & + IOB% seaice_melt (isc:iec,jsc:jec), & IOB% ustar_berg (isc:iec,jsc:jec), & IOB% area_berg (isc:iec,jsc:jec), & IOB% mass_berg (isc:iec,jsc:jec), & diff --git a/config_src/drivers/nuopc_cap/mom_surface_forcing_nuopc.F90 b/config_src/drivers/nuopc_cap/mom_surface_forcing_nuopc.F90 index d6e7922f68..c20efc5723 100644 --- a/config_src/drivers/nuopc_cap/mom_surface_forcing_nuopc.F90 +++ b/config_src/drivers/nuopc_cap/mom_surface_forcing_nuopc.F90 @@ -459,9 +459,8 @@ subroutine convert_IOB_to_fluxes(IOB, fluxes, index_bounds, Time, valid_time, G, if (associated(IOB%fprec)) & fluxes%fprec(i,j) = kg_m2_s_conversion * IOB%fprec(i-i0,j-j0) * G%mask2dT(i,j) - ! water flux due to sea ice and snow melt [kg/m2/s] - if (associated(IOB%seaice_melt)) & - fluxes%seaice_melt(i,j) = kg_m2_s_conversion * G%mask2dT(i,j) * IOB%seaice_melt(i-i0,j-j0) + if (associated(IOB%seaice_melt)) & + fluxes%seaice_melt(i,j) = kg_m2_s_conversion * IOB%seaice_melt(i-i0,j-j0) * G%mask2dT(i,j) if (associated(IOB%q_flux)) & fluxes%evap(i,j) = kg_m2_s_conversion * IOB%q_flux(i-i0,j-j0) * G%mask2dT(i,j) diff --git a/config_src/drivers/solo_driver/MESO_surface_forcing.F90 b/config_src/drivers/solo_driver/MESO_surface_forcing.F90 index f1f3daa52e..a7e169bde6 100644 --- a/config_src/drivers/solo_driver/MESO_surface_forcing.F90 +++ b/config_src/drivers/solo_driver/MESO_surface_forcing.F90 @@ -99,6 +99,7 @@ subroutine MESO_buoyancy_forcing(sfc_state, fluxes, day, dt, G, US, CS) call safe_alloc_ptr(fluxes%evap, isd, ied, jsd, jed) call safe_alloc_ptr(fluxes%lprec, isd, ied, jsd, jed) call safe_alloc_ptr(fluxes%fprec, isd, ied, jsd, jed) + call safe_alloc_ptr(fluxes%seaice_melt, isd, ied, jsd, jed) call safe_alloc_ptr(fluxes%lrunoff, isd, ied, jsd, jed) call safe_alloc_ptr(fluxes%frunoff, isd, ied, jsd, jed) call safe_alloc_ptr(fluxes%vprec, isd, ied, jsd, jed) @@ -142,6 +143,7 @@ subroutine MESO_buoyancy_forcing(sfc_state, fluxes, day, dt, G, US, CS) ! and are positive downward - i.e. evaporation should be negative. fluxes%evap(i,j) = -0.0 * G%mask2dT(i,j) fluxes%lprec(i,j) = CS%PmE(i,j) * CS%Rho0 * G%mask2dT(i,j) + fluxes%seaice_melt(i,j) = 0.0 * G%mask2dT(i,j) ! vprec will be set later, if it is needed for salinity restoring. fluxes%vprec(i,j) = 0.0 diff --git a/config_src/drivers/solo_driver/MOM_surface_forcing.F90 b/config_src/drivers/solo_driver/MOM_surface_forcing.F90 index 3de43eec85..cf23bb0f38 100644 --- a/config_src/drivers/solo_driver/MOM_surface_forcing.F90 +++ b/config_src/drivers/solo_driver/MOM_surface_forcing.F90 @@ -1180,15 +1180,16 @@ subroutine buoyancy_forcing_from_files(sfc_state, fluxes, day, dt, G, US, CS) ! assume solid runoff (calving) enters ocean at 0degC ! mass leaving the ocean has heat_content determined in MOM_diabatic_driver.F90 do j=js,je ; do i=is,ie - fluxes%evap(i,j) = fluxes%evap(i,j) * G%mask2dT(i,j) - fluxes%lprec(i,j) = fluxes%lprec(i,j) * G%mask2dT(i,j) - fluxes%fprec(i,j) = fluxes%fprec(i,j) * G%mask2dT(i,j) - fluxes%lrunoff(i,j) = fluxes%lrunoff(i,j) * G%mask2dT(i,j) - fluxes%frunoff(i,j) = fluxes%frunoff(i,j) * G%mask2dT(i,j) - fluxes%lw(i,j) = fluxes%lw(i,j) * G%mask2dT(i,j) - fluxes%sens(i,j) = fluxes%sens(i,j) * G%mask2dT(i,j) - fluxes%sw(i,j) = fluxes%sw(i,j) * G%mask2dT(i,j) - fluxes%latent(i,j) = fluxes%latent(i,j) * G%mask2dT(i,j) + fluxes%evap(i,j) = fluxes%evap(i,j) * G%mask2dT(i,j) + fluxes%lprec(i,j) = fluxes%lprec(i,j) * G%mask2dT(i,j) + fluxes%fprec(i,j) = fluxes%fprec(i,j) * G%mask2dT(i,j) + fluxes%seaice_melt(i,j) = fluxes%seaice_melt(i,j) * G%mask2dT(i,j) + fluxes%lrunoff(i,j) = fluxes%lrunoff(i,j) * G%mask2dT(i,j) + fluxes%frunoff(i,j) = fluxes%frunoff(i,j) * G%mask2dT(i,j) + fluxes%lw(i,j) = fluxes%lw(i,j) * G%mask2dT(i,j) + fluxes%sens(i,j) = fluxes%sens(i,j) * G%mask2dT(i,j) + fluxes%sw(i,j) = fluxes%sw(i,j) * G%mask2dT(i,j) + fluxes%latent(i,j) = fluxes%latent(i,j) * G%mask2dT(i,j) fluxes%latent_evap_diag(i,j) = fluxes%latent_evap_diag(i,j) * G%mask2dT(i,j) fluxes%latent_fprec_diag(i,j) = -fluxes%fprec(i,j)*CS%latent_heat_fusion @@ -1294,10 +1295,11 @@ subroutine buoyancy_forcing_from_data_override(sfc_state, fluxes, day, dt, G, US fluxes%latent_evap_diag(i,j) = fluxes%latent(i,j) enddo ; enddo - call data_override(G%Domain, 'snow', fluxes%fprec, day, scale=US%kg_m2s_to_RZ_T) - call data_override(G%Domain, 'rain', fluxes%lprec, day, scale=US%kg_m2s_to_RZ_T) - call data_override(G%Domain, 'runoff', fluxes%lrunoff, day, scale=US%kg_m2s_to_RZ_T) - call data_override(G%Domain, 'calving', fluxes%frunoff, day, scale=US%kg_m2s_to_RZ_T) + call data_override(G%Domain, 'snow', fluxes%fprec, day, scale=US%kg_m2s_to_RZ_T) + call data_override(G%Domain, 'rain', fluxes%lprec, day, scale=US%kg_m2s_to_RZ_T) + call data_override(G%Domain, 'seaice_melt', fluxes%seaice_melt, day, scale=US%kg_m2s_to_RZ_T) + call data_override(G%Domain, 'runoff', fluxes%lrunoff, day, scale=US%kg_m2s_to_RZ_T) + call data_override(G%Domain, 'calving', fluxes%frunoff, day, scale=US%kg_m2s_to_RZ_T) ! Read the SST and SSS fields for damping. if (CS%restorebuoy) then !#CTRL# .or. associated(CS%ctrl_forcing_CSp)) then @@ -1345,15 +1347,16 @@ subroutine buoyancy_forcing_from_data_override(sfc_state, fluxes, day, dt, G, US ! assume solid runoff (calving) enters ocean at 0degC ! mass leaving ocean has heat_content determined in MOM_diabatic_driver.F90 do j=js,je ; do i=is,ie - fluxes%evap(i,j) = fluxes%evap(i,j) * G%mask2dT(i,j) - fluxes%lprec(i,j) = fluxes%lprec(i,j) * G%mask2dT(i,j) - fluxes%fprec(i,j) = fluxes%fprec(i,j) * G%mask2dT(i,j) - fluxes%lrunoff(i,j) = fluxes%lrunoff(i,j) * G%mask2dT(i,j) - fluxes%frunoff(i,j) = fluxes%frunoff(i,j) * G%mask2dT(i,j) - fluxes%lw(i,j) = fluxes%lw(i,j) * G%mask2dT(i,j) - fluxes%latent(i,j) = fluxes%latent(i,j) * G%mask2dT(i,j) - fluxes%sens(i,j) = fluxes%sens(i,j) * G%mask2dT(i,j) - fluxes%sw(i,j) = fluxes%sw(i,j) * G%mask2dT(i,j) + fluxes%evap(i,j) = fluxes%evap(i,j) * G%mask2dT(i,j) + fluxes%lprec(i,j) = fluxes%lprec(i,j) * G%mask2dT(i,j) + fluxes%fprec(i,j) = fluxes%fprec(i,j) * G%mask2dT(i,j) + fluxes%seaice_melt(i,j) = fluxes%seaice_melt(i,j) * G%mask2dT(i,j) + fluxes%lrunoff(i,j) = fluxes%lrunoff(i,j) * G%mask2dT(i,j) + fluxes%frunoff(i,j) = fluxes%frunoff(i,j) * G%mask2dT(i,j) + fluxes%lw(i,j) = fluxes%lw(i,j) * G%mask2dT(i,j) + fluxes%latent(i,j) = fluxes%latent(i,j) * G%mask2dT(i,j) + fluxes%sens(i,j) = fluxes%sens(i,j) * G%mask2dT(i,j) + fluxes%sw(i,j) = fluxes%sw(i,j) * G%mask2dT(i,j) fluxes%latent_evap_diag(i,j) = fluxes%latent_evap_diag(i,j) * G%mask2dT(i,j) fluxes%latent_fprec_diag(i,j) = -fluxes%fprec(i,j)*CS%latent_heat_fusion @@ -1395,6 +1398,7 @@ subroutine buoyancy_forcing_zero(sfc_state, fluxes, day, dt, G, CS) fluxes%evap(i,j) = 0.0 fluxes%lprec(i,j) = 0.0 fluxes%fprec(i,j) = 0.0 + fluxes%seaice_melt(i,j) = 0.0 fluxes%vprec(i,j) = 0.0 fluxes%lrunoff(i,j) = 0.0 fluxes%frunoff(i,j) = 0.0 @@ -1438,6 +1442,7 @@ subroutine buoyancy_forcing_const(sfc_state, fluxes, day, dt, G, US, CS) fluxes%evap(i,j) = 0.0 fluxes%lprec(i,j) = 0.0 fluxes%fprec(i,j) = 0.0 + fluxes%seaice_melt(i,j) = 0.0 fluxes%vprec(i,j) = 0.0 fluxes%lrunoff(i,j) = 0.0 fluxes%frunoff(i,j) = 0.0 @@ -1486,6 +1491,7 @@ subroutine buoyancy_forcing_linear(sfc_state, fluxes, day, dt, G, US, CS) fluxes%evap(i,j) = 0.0 fluxes%lprec(i,j) = 0.0 fluxes%fprec(i,j) = 0.0 + fluxes%seaice_melt(i,j) = 0.0 fluxes%vprec(i,j) = 0.0 fluxes%lrunoff(i,j) = 0.0 fluxes%frunoff(i,j) = 0.0 diff --git a/config_src/drivers/solo_driver/user_surface_forcing.F90 b/config_src/drivers/solo_driver/user_surface_forcing.F90 index 7d4ea94603..291b52cf8a 100644 --- a/config_src/drivers/solo_driver/user_surface_forcing.F90 +++ b/config_src/drivers/solo_driver/user_surface_forcing.F90 @@ -154,6 +154,7 @@ subroutine USER_buoyancy_forcing(sfc_state, fluxes, day, dt, G, US, CS) call safe_alloc_ptr(fluxes%evap, isd, ied, jsd, jed) call safe_alloc_ptr(fluxes%lprec, isd, ied, jsd, jed) call safe_alloc_ptr(fluxes%fprec, isd, ied, jsd, jed) + call safe_alloc_ptr(fluxes%seaice_melt, isd, ied, jsd, jed) call safe_alloc_ptr(fluxes%lrunoff, isd, ied, jsd, jed) call safe_alloc_ptr(fluxes%frunoff, isd, ied, jsd, jed) call safe_alloc_ptr(fluxes%vprec, isd, ied, jsd, jed) @@ -177,6 +178,7 @@ subroutine USER_buoyancy_forcing(sfc_state, fluxes, day, dt, G, US, CS) ! and are positive downward - i.e. evaporation should be negative. fluxes%evap(i,j) = -0.0 * G%mask2dT(i,j) fluxes%lprec(i,j) = 0.0 * G%mask2dT(i,j) + fluxes%seaice_melt(i,j) = 0.0 * G%mask2dT(i,j) ! vprec will be set later, if it is needed for salinity restoring. fluxes%vprec(i,j) = 0.0 @@ -313,7 +315,7 @@ end subroutine USER_surface_forcing_init !! !! USER_buoyancy() forcing is used to set the surface buoyancy !! forcing, which may include a number of fresh water flux fields -!! (evap, lprec, fprec, lrunoff, frunoff, and +!! (evap, lprec, fprec, seaice_melt, lrunoff, frunoff, and !! vprec) and the surface heat fluxes (sw, lw, latent and sens) !! if temperature and salinity are state variables, or it may simply !! be the buoyancy flux if it is not. This routine also has coded a diff --git a/src/core/MOM_forcing_type.F90 b/src/core/MOM_forcing_type.F90 index 4ceb14fe11..3aa467a836 100644 --- a/src/core/MOM_forcing_type.F90 +++ b/src/core/MOM_forcing_type.F90 @@ -543,14 +543,17 @@ subroutine extractFluxes1d(G, GV, US, fluxes, optics, nsw, j, dt, & "MOM_forcing_type extractFluxes1d: fluxes%sens is not associated.") if (.not.associated(fluxes%evap)) call MOM_error(FATAL, & - "MOM_forcing_type extractFluxes1d: No evaporation defined.") + "MOM_forcing_type extractFluxes1d: fluxes%evap is not associated.") if (.not.associated(fluxes%vprec)) call MOM_error(FATAL, & - "MOM_forcing_type extractFluxes1d: fluxes%vprec not defined.") + "MOM_forcing_type extractFluxes1d: fluxes%vprec is not associated.") if ((.not.associated(fluxes%lprec)) .or. & (.not.associated(fluxes%fprec))) call MOM_error(FATAL, & - "MOM_forcing_type extractFluxes1d: No precipitation defined.") + "MOM_forcing_type extractFluxes1d: fluxes%lprec or fluxes%fprec not associated.") + + if (.not.associated(fluxes%seaice_melt)) call MOM_error(FATAL, & + "MOM_forcing_type extractFluxes1d: fluxes%seaice_melt is not associated.") do i=is,ie ; htot(i) = h(i,1) ; enddo do k=2,nz ; do i=is,ie ; htot(i) = htot(i) + h(i,k) ; enddo ; enddo @@ -630,8 +633,6 @@ subroutine extractFluxes1d(G, GV, US, fluxes, optics, nsw, j, dt, & if (fluxes%evap(i,j) < 0.0) netMassOut(i) = netMassOut(i) + fluxes%evap(i,j) ! if (associated(fluxes%heat_content_cond)) fluxes%heat_content_cond(i,j) = 0.0 !??? --AJA - ! lprec < 0 means sea ice formation taking water from the ocean. - ! smg: we should split the ice melt/formation from the lprec if (fluxes%lprec(i,j) < 0.0) netMassOut(i) = netMassOut(i) + fluxes%lprec(i,j) ! seaice_melt < 0 means sea ice formation taking water from the ocean. @@ -801,13 +802,8 @@ subroutine extractFluxes1d(G, GV, US, fluxes, optics, nsw, j, dt, & endif endif - ! smg: we should remove sea ice melt from lprec!!! - ! fluxes%lprec > 0 means ocean gains mass via liquid precipitation and/or sea ice melt. ! When atmosphere does not provide heat of this precipitation, the ocean assumes ! it enters the ocean at the SST. - ! fluxes%lprec < 0 means ocean loses mass via sea ice formation. As we do not yet know - ! the layer at which this mass is removed, we cannot compute it heat content. We must - ! wait until MOM_diabatic_driver.F90. if (associated(fluxes%heat_content_lprec)) then if (fluxes%lprec(i,j) > 0.0) then fluxes%heat_content_lprec(i,j) = tv%C_p*fluxes%lprec(i,j)*T(i,1) @@ -1571,15 +1567,6 @@ subroutine register_forcing_type_diags(Time, diag, US, use_temperature, handles, cmor_standard_name='water_evaporation_flux', & cmor_long_name='Water Evaporation Flux Where Ice Free Ocean over Sea') - ! smg: seaice_melt field requires updates to the sea ice model - handles%id_seaice_melt = register_diag_field('ocean_model', 'seaice_melt', & - diag%axesT1, Time, 'water flux to ocean from snow/sea ice melting(> 0) or formation(< 0)', & - 'kg m-2 s-1', conversion=US%RZ_T_to_kg_m2s, & - standard_name='water_flux_into_sea_water_due_to_sea_ice_thermodynamics', & - cmor_field_name='fsitherm', & - cmor_standard_name='water_flux_into_sea_water_due_to_sea_ice_thermodynamics',& - cmor_long_name='water flux to ocean from sea ice melt(> 0) or form(< 0)') - handles%id_precip = register_diag_field('ocean_model', 'precip', diag%axesT1, Time, & 'Liquid + frozen precipitation into ocean', 'kg m-2 s-1', conversion=US%RZ_T_to_kg_m2s) @@ -1596,6 +1583,14 @@ subroutine register_forcing_type_diags(Time, diag, US, use_temperature, handles, cmor_field_name='prlq', cmor_standard_name='rainfall_flux', & cmor_long_name='Rainfall Flux where Ice Free Ocean over Sea') + handles%id_seaice_melt = register_diag_field('ocean_model', 'seaice_melt', & + diag%axesT1, Time, 'water flux to ocean from snow/sea ice melting(> 0) or formation(< 0)', & + 'kg m-2 s-1', conversion=US%RZ_T_to_kg_m2s, & + standard_name='water_flux_into_sea_water_due_to_sea_ice_thermodynamics', & + cmor_field_name='fsitherm', & + cmor_standard_name='water_flux_into_sea_water_due_to_sea_ice_thermodynamics',& + cmor_long_name='water flux to ocean from sea ice melt(> 0) or form(< 0)') + handles%id_vprec = register_diag_field('ocean_model', 'vprec', diag%axesT1, Time, & 'Virtual liquid precip into ocean due to SSS restoring', & units='kg m-2 s-1', conversion=US%RZ_T_to_kg_m2s) @@ -1648,14 +1643,6 @@ subroutine register_forcing_type_diags(Time, diag, US, use_temperature, handles, cmor_standard_name='water_evaporation_flux_area_integrated', & cmor_long_name='Evaporation Where Ice Free Ocean over Sea Area Integrated') - ! seaice_melt field requires updates to the sea ice model - handles%id_total_seaice_melt = register_scalar_field('ocean_model', 'total_icemelt', Time, diag, & - long_name='Area integrated sea ice melt (>0) or form (<0)', units='kg s-1', & - standard_name='water_flux_into_sea_water_due_to_sea_ice_thermodynamics_area_integrated', & - cmor_field_name='total_fsitherm', & - cmor_standard_name='water_flux_into_sea_water_due_to_sea_ice_thermodynamics_area_integrated', & - cmor_long_name='Water Melt/Form from Sea Ice Area Integrated') - handles%id_total_precip = register_scalar_field('ocean_model', 'total_precip', Time, diag, & long_name='Area integrated liquid+frozen precip into ocean', units='kg s-1') @@ -1673,6 +1660,13 @@ subroutine register_forcing_type_diags(Time, diag, US, use_temperature, handles, cmor_standard_name='rainfall_flux_area_integrated', & cmor_long_name='Rainfall Flux where Ice Free Ocean over Sea Area Integrated') + handles%id_total_seaice_melt = register_scalar_field('ocean_model', 'total_icemelt', Time, diag, & + long_name='Area integrated sea ice melt (>0) or form (<0)', units='kg s-1', & + standard_name='water_flux_into_sea_water_due_to_sea_ice_thermodynamics_area_integrated', & + cmor_field_name='total_fsitherm', & + cmor_standard_name='water_flux_into_sea_water_due_to_sea_ice_thermodynamics_area_integrated', & + cmor_long_name='Water Melt/Form from Sea Ice Area Integrated') + handles%id_total_vprec = register_scalar_field('ocean_model', 'total_vprec', Time, diag, & long_name='Area integrated virtual liquid precip due to SSS restoring', units='kg s-1') diff --git a/src/parameterizations/vertical/MOM_diabatic_aux.F90 b/src/parameterizations/vertical/MOM_diabatic_aux.F90 index dadbf8206e..3ef46483f4 100644 --- a/src/parameterizations/vertical/MOM_diabatic_aux.F90 +++ b/src/parameterizations/vertical/MOM_diabatic_aux.F90 @@ -909,8 +909,7 @@ subroutine applyBoundaryFluxesInOut(CS, G, GV, US, dt, fluxes, optics, nsw, h, t ! The surface forcing is contained in the fluxes type. ! We aggregate the thermodynamic forcing for a time step into the following: ! netMassInOut = surface water fluxes [H ~> m or kg m-2] over time step - ! = lprec + fprec + vprec + evap + lrunoff + frunoff - ! note that lprec generally has sea ice melt/form included. + ! = lprec + fprec + seaice_melt + vprec + evap + lrunoff + frunoff ! netMassOut = net mass leaving ocean surface [H ~> m or kg m-2] over a time step. ! netMassOut < 0 means mass leaves ocean. ! netHeat = heat via surface fluxes [C H ~> degC m or degC kg m-2], excluding the part diff --git a/src/user/BFB_surface_forcing.F90 b/src/user/BFB_surface_forcing.F90 index fcbd66e1d8..fc4f686c7d 100644 --- a/src/user/BFB_surface_forcing.F90 +++ b/src/user/BFB_surface_forcing.F90 @@ -84,6 +84,7 @@ subroutine BFB_buoyancy_forcing(sfc_state, fluxes, day, dt, G, US, CS) call safe_alloc_ptr(fluxes%evap, isd, ied, jsd, jed) call safe_alloc_ptr(fluxes%lprec, isd, ied, jsd, jed) call safe_alloc_ptr(fluxes%fprec, isd, ied, jsd, jed) + call safe_alloc_ptr(fluxes%seaice_melt, isd, ied, jsd, jed) call safe_alloc_ptr(fluxes%lrunoff, isd, ied, jsd, jed) call safe_alloc_ptr(fluxes%frunoff, isd, ied, jsd, jed) call safe_alloc_ptr(fluxes%vprec, isd, ied, jsd, jed) @@ -104,6 +105,7 @@ subroutine BFB_buoyancy_forcing(sfc_state, fluxes, day, dt, G, US, CS) ! and are positive downward - i.e. evaporation should be negative. fluxes%evap(i,j) = -0.0 * G%mask2dT(i,j) fluxes%lprec(i,j) = 0.0 * G%mask2dT(i,j) + fluxes%seaice_melt(i,j) = 0.0 * G%mask2dT(i,j) ! vprec will be set later, if it is needed for salinity restoring. fluxes%vprec(i,j) = 0.0 diff --git a/src/user/dumbbell_surface_forcing.F90 b/src/user/dumbbell_surface_forcing.F90 index 288ccd89fa..a184ba17a2 100644 --- a/src/user/dumbbell_surface_forcing.F90 +++ b/src/user/dumbbell_surface_forcing.F90 @@ -69,6 +69,7 @@ subroutine dumbbell_buoyancy_forcing(sfc_state, fluxes, day, dt, G, US, CS) call safe_alloc_ptr(fluxes%evap, isd, ied, jsd, jed) call safe_alloc_ptr(fluxes%lprec, isd, ied, jsd, jed) call safe_alloc_ptr(fluxes%fprec, isd, ied, jsd, jed) + call safe_alloc_ptr(fluxes%seaice_melt, isd, ied, jsd, jed) call safe_alloc_ptr(fluxes%lrunoff, isd, ied, jsd, jed) call safe_alloc_ptr(fluxes%frunoff, isd, ied, jsd, jed) call safe_alloc_ptr(fluxes%vprec, isd, ied, jsd, jed) @@ -92,6 +93,7 @@ subroutine dumbbell_buoyancy_forcing(sfc_state, fluxes, day, dt, G, US, CS) ! and are positive downward - i.e. evaporation should be negative. fluxes%evap(i,j) = -0.0 * G%mask2dT(i,j) fluxes%lprec(i,j) = 0.0 * G%mask2dT(i,j) + fluxes%seaice_melt(i,j) = 0.0 * G%mask2dT(i,j) ! vprec will be set later, if it is needed for salinity restoring. fluxes%vprec(i,j) = 0.0 From c8dc42ea1484300d3b3a1fa498129b96b93ee382 Mon Sep 17 00:00:00 2001 From: Henri Drake Date: Mon, 19 Aug 2024 12:58:03 -0700 Subject: [PATCH 3/4] Check if `seaice_melt` is associated before the checksum --- config_src/drivers/FMS_cap/MOM_surface_forcing_gfdl.F90 | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/config_src/drivers/FMS_cap/MOM_surface_forcing_gfdl.F90 b/config_src/drivers/FMS_cap/MOM_surface_forcing_gfdl.F90 index cfcddd6fb8..ec3dcfa475 100644 --- a/config_src/drivers/FMS_cap/MOM_surface_forcing_gfdl.F90 +++ b/config_src/drivers/FMS_cap/MOM_surface_forcing_gfdl.F90 @@ -1796,8 +1796,9 @@ subroutine ice_ocn_bnd_type_chksum(id, timestep, iobt) chks = field_chksum( iobt%sw_flux_nir_dif) ; if (root) write(outunit,100) 'iobt%sw_flux_nir_dif', chks chks = field_chksum( iobt%lprec ) ; if (root) write(outunit,100) 'iobt%lprec ', chks chks = field_chksum( iobt%fprec ) ; if (root) write(outunit,100) 'iobt%fprec ', chks -! hfd/Gives error: "Program received signal SIGSEGV: Segmentation fault - invalid memory reference." - chks = field_chksum( iobt%seaice_melt ) ; if (root) write(outunit,100) 'iobt%seaice_melt ', chks + if (associated(iobt%seaice_melt)) then + chks = field_chksum( iobt%seaice_melt ) ; if (root) write(outunit,100) 'iobt%seaice_melt ', chks + endif chks = field_chksum( iobt%runoff ) ; if (root) write(outunit,100) 'iobt%runoff ', chks chks = field_chksum( iobt%calving ) ; if (root) write(outunit,100) 'iobt%calving ', chks chks = field_chksum( iobt%p ) ; if (root) write(outunit,100) 'iobt%p ', chks From 13b99607e518325046d686395057d1939548abeb Mon Sep 17 00:00:00 2001 From: Henri Drake Date: Tue, 20 Aug 2024 09:59:15 -0700 Subject: [PATCH 4/4] Revert changes to STALE_mct_cap and nuopc_cap As requested by @marshallward https://github.com/NOAA-GFDL/MOM6/pull/710#issuecomment-2299037849 --- .../STALE_mct_cap/mom_surface_forcing_mct.F90 | 12 ++++++------ config_src/drivers/STALE_mct_cap/ocn_cap_methods.F90 | 6 +++--- config_src/drivers/STALE_mct_cap/ocn_comp_mct.F90 | 2 +- .../drivers/nuopc_cap/mom_surface_forcing_nuopc.F90 | 11 ++++++----- 4 files changed, 16 insertions(+), 15 deletions(-) diff --git a/config_src/drivers/STALE_mct_cap/mom_surface_forcing_mct.F90 b/config_src/drivers/STALE_mct_cap/mom_surface_forcing_mct.F90 index 2a4de8ddd7..bb57810f5b 100644 --- a/config_src/drivers/STALE_mct_cap/mom_surface_forcing_mct.F90 +++ b/config_src/drivers/STALE_mct_cap/mom_surface_forcing_mct.F90 @@ -156,6 +156,7 @@ module MOM_surface_forcing_mct real, pointer, dimension(:,:) :: q_flux =>NULL() !< specific humidity flux [kg/m2/s] real, pointer, dimension(:,:) :: salt_flux =>NULL() !< salt flux [kg/m2/s] real, pointer, dimension(:,:) :: seaice_melt_heat =>NULL() !< sea ice and snow melt heat flux [W/m2] + real, pointer, dimension(:,:) :: seaice_melt =>NULL() !< water flux due to sea ice and snow melting [kg/m2/s] real, pointer, dimension(:,:) :: lw_flux =>NULL() !< long wave radiation [W/m2] real, pointer, dimension(:,:) :: sw_flux_vis_dir =>NULL() !< direct visible sw radiation [W/m2] real, pointer, dimension(:,:) :: sw_flux_vis_dif =>NULL() !< diffuse visible sw radiation [W/m2] @@ -163,7 +164,6 @@ module MOM_surface_forcing_mct real, pointer, dimension(:,:) :: sw_flux_nir_dif =>NULL() !< diffuse Near InfraRed sw radiation [W/m2] real, pointer, dimension(:,:) :: lprec =>NULL() !< mass flux of liquid precip [kg/m2/s] real, pointer, dimension(:,:) :: fprec =>NULL() !< mass flux of frozen precip [kg/m2/s] - real, pointer, dimension(:,:) :: seaice_melt =>NULL() !< water flux due to sea ice and snow melting [kg/m2/s] real, pointer, dimension(:,:) :: runoff =>NULL() !< mass flux of liquid runoff [kg/m2/s] real, pointer, dimension(:,:) :: calving =>NULL() !< mass flux of frozen runoff [kg/m2/s] real, pointer, dimension(:,:) :: ustar_berg =>NULL() !< frictional velocity beneath icebergs [m/s] @@ -428,10 +428,6 @@ subroutine convert_IOB_to_fluxes(IOB, fluxes, index_bounds, Time, valid_time, G, if (associated(IOB%fprec)) & fluxes%fprec(i,j) = kg_m2_s_conversion * IOB%fprec(i-i0,j-j0) * G%mask2dT(i,j) - ! water flux due to sea ice and snow melt - if (associated(IOB%seaice_melt)) & - fluxes%seaice_melt(i,j) = kg_m2_s_conversion * IOB%seaice_melt(i-i0,j-j0) * G%mask2dT(i,j) - ! evaporation if (associated(IOB%q_flux)) & fluxes%evap(i,j) = kg_m2_s_conversion * IOB%q_flux(i-i0,j-j0) * G%mask2dT(i,j) @@ -481,6 +477,10 @@ subroutine convert_IOB_to_fluxes(IOB, fluxes, index_bounds, Time, valid_time, G, if (associated(IOB%seaice_melt_heat)) & fluxes%seaice_melt_heat(i,j) = G%mask2dT(i,j) * US%W_m2_to_QRZ_T * IOB%seaice_melt_heat(i-i0,j-j0) + ! water flux due to sea ice and snow melt [kg/m2/s] + if (associated(IOB%seaice_melt)) & + fluxes%seaice_melt(i,j) = G%mask2dT(i,j) * kg_m2_s_conversion * IOB%seaice_melt(i-i0,j-j0) + ! latent heat flux (W/m^2) fluxes%latent(i,j) = 0.0 ! contribution from frozen ppt (notice minus sign since fprec is positive into the ocean) @@ -1402,6 +1402,7 @@ subroutine ice_ocn_bnd_type_chksum(id, timestep, iobt) chks = field_chksum( iobt%t_flux ) ; if (root) write(outunit,100) 'iobt%t_flux ', chks chks = field_chksum( iobt%q_flux ) ; if (root) write(outunit,100) 'iobt%q_flux ', chks chks = field_chksum( iobt%seaice_melt_heat); if (root) write(outunit,100) 'iobt%seaice_melt_heat', chks + chks = field_chksum( iobt%seaice_melt) ; if (root) write(outunit,100) 'iobt%seaice_melt ', chks chks = field_chksum( iobt%salt_flux ) ; if (root) write(outunit,100) 'iobt%salt_flux ', chks chks = field_chksum( iobt%lw_flux ) ; if (root) write(outunit,100) 'iobt%lw_flux ', chks chks = field_chksum( iobt%sw_flux_vis_dir) ; if (root) write(outunit,100) 'iobt%sw_flux_vis_dir', chks @@ -1410,7 +1411,6 @@ subroutine ice_ocn_bnd_type_chksum(id, timestep, iobt) chks = field_chksum( iobt%sw_flux_nir_dif) ; if (root) write(outunit,100) 'iobt%sw_flux_nir_dif', chks chks = field_chksum( iobt%lprec ) ; if (root) write(outunit,100) 'iobt%lprec ', chks chks = field_chksum( iobt%fprec ) ; if (root) write(outunit,100) 'iobt%fprec ', chks - chks = field_chksum( iobt%seaice_melt) ; if (root) write(outunit,100) 'iobt%seaice_melt ', chks chks = field_chksum( iobt%rofl_flux ) ; if (root) write(outunit,100) 'rofl_flux ', chks chks = field_chksum( iobt%rofi_flux ) ; if (root) write(outunit,100) 'rofi_flux ', chks chks = field_chksum( iobt%p ) ; if (root) write(outunit,100) 'iobt%p ', chks diff --git a/config_src/drivers/STALE_mct_cap/ocn_cap_methods.F90 b/config_src/drivers/STALE_mct_cap/ocn_cap_methods.F90 index 8199c32cd6..0b7a331458 100644 --- a/config_src/drivers/STALE_mct_cap/ocn_cap_methods.F90 +++ b/config_src/drivers/STALE_mct_cap/ocn_cap_methods.F90 @@ -62,9 +62,6 @@ subroutine ocn_import(x2o, ind, grid, ice_ocean_boundary, ocean_public, logunit, ! frozen precipitation (snow) ice_ocean_boundary%fprec(i,j) = x2o(ind%x2o_Faxa_snow,k) - ! water flux from snow&ice melt (kg/m2/s) - ice_ocean_boundary%seaice_melt(i,j) = x2o(ind%x2o_Fioi_meltw,k) - ! longwave radiation, sum up and down (W/m2) ice_ocean_boundary%lw_flux(i,j) = (x2o(ind%x2o_Faxa_lwdn,k) + x2o(ind%x2o_Foxx_lwup,k)) @@ -77,6 +74,9 @@ subroutine ocn_import(x2o, ind, grid, ice_ocean_boundary, ocean_public, logunit, ! snow&ice melt heat flux (W/m^2) ice_ocean_boundary%seaice_melt_heat(i,j) = x2o(ind%x2o_Fioi_melth,k) + ! water flux from snow&ice melt (kg/m2/s) + ice_ocean_boundary%seaice_melt(i,j) = x2o(ind%x2o_Fioi_meltw,k) + ! liquid runoff ice_ocean_boundary%rofl_flux(i,j) = x2o(ind%x2o_Foxx_rofl,k) * GRID%mask2dT(i,j) diff --git a/config_src/drivers/STALE_mct_cap/ocn_comp_mct.F90 b/config_src/drivers/STALE_mct_cap/ocn_comp_mct.F90 index 2ed30e2ea9..85b7350b77 100644 --- a/config_src/drivers/STALE_mct_cap/ocn_comp_mct.F90 +++ b/config_src/drivers/STALE_mct_cap/ocn_comp_mct.F90 @@ -858,6 +858,7 @@ subroutine IOB_allocate(IOB, isc, iec, jsc, jec) IOB% v_flux (isc:iec,jsc:jec), & IOB% t_flux (isc:iec,jsc:jec), & IOB% seaice_melt_heat (isc:iec,jsc:jec),& + IOB% seaice_melt (isc:iec,jsc:jec), & IOB% q_flux (isc:iec,jsc:jec), & IOB% salt_flux (isc:iec,jsc:jec), & IOB% lw_flux (isc:iec,jsc:jec), & @@ -867,7 +868,6 @@ subroutine IOB_allocate(IOB, isc, iec, jsc, jec) IOB% sw_flux_nir_dif (isc:iec,jsc:jec), & IOB% lprec (isc:iec,jsc:jec), & IOB% fprec (isc:iec,jsc:jec), & - IOB% seaice_melt (isc:iec,jsc:jec), & IOB% ustar_berg (isc:iec,jsc:jec), & IOB% area_berg (isc:iec,jsc:jec), & IOB% mass_berg (isc:iec,jsc:jec), & diff --git a/config_src/drivers/nuopc_cap/mom_surface_forcing_nuopc.F90 b/config_src/drivers/nuopc_cap/mom_surface_forcing_nuopc.F90 index c20efc5723..e7d6c9abc6 100644 --- a/config_src/drivers/nuopc_cap/mom_surface_forcing_nuopc.F90 +++ b/config_src/drivers/nuopc_cap/mom_surface_forcing_nuopc.F90 @@ -165,6 +165,7 @@ module MOM_surface_forcing_nuopc real, pointer, dimension(:,:) :: q_flux =>NULL() !< specific humidity flux [kg/m2/s] real, pointer, dimension(:,:) :: salt_flux =>NULL() !< salt flux [kg/m2/s] real, pointer, dimension(:,:) :: seaice_melt_heat =>NULL() !< sea ice and snow melt heat flux [W/m2] + real, pointer, dimension(:,:) :: seaice_melt =>NULL() !< water flux due to sea ice and snow melting [kg/m2/s] real, pointer, dimension(:,:) :: lw_flux =>NULL() !< long wave radiation [W/m2] real, pointer, dimension(:,:) :: sw_flux_vis_dir =>NULL() !< direct visible sw radiation [W/m2] real, pointer, dimension(:,:) :: sw_flux_vis_dif =>NULL() !< diffuse visible sw radiation [W/m2] @@ -172,7 +173,6 @@ module MOM_surface_forcing_nuopc real, pointer, dimension(:,:) :: sw_flux_nir_dif =>NULL() !< diffuse Near InfraRed sw radiation [W/m2] real, pointer, dimension(:,:) :: lprec =>NULL() !< mass flux of liquid precip [kg/m2/s] real, pointer, dimension(:,:) :: fprec =>NULL() !< mass flux of frozen precip [kg/m2/s] - real, pointer, dimension(:,:) :: seaice_melt =>NULL() !< water flux due to sea ice and snow melting [kg/m2/s] real, pointer, dimension(:,:) :: ustar_berg =>NULL() !< frictional velocity beneath icebergs [m/s] real, pointer, dimension(:,:) :: area_berg =>NULL() !< area covered by icebergs[m2/m2] real, pointer, dimension(:,:) :: mass_berg =>NULL() !< mass of icebergs(kg/m2) @@ -459,9 +459,6 @@ subroutine convert_IOB_to_fluxes(IOB, fluxes, index_bounds, Time, valid_time, G, if (associated(IOB%fprec)) & fluxes%fprec(i,j) = kg_m2_s_conversion * IOB%fprec(i-i0,j-j0) * G%mask2dT(i,j) - if (associated(IOB%seaice_melt)) & - fluxes%seaice_melt(i,j) = kg_m2_s_conversion * IOB%seaice_melt(i-i0,j-j0) * G%mask2dT(i,j) - if (associated(IOB%q_flux)) & fluxes%evap(i,j) = kg_m2_s_conversion * IOB%q_flux(i-i0,j-j0) * G%mask2dT(i,j) @@ -494,6 +491,10 @@ subroutine convert_IOB_to_fluxes(IOB, fluxes, index_bounds, Time, valid_time, G, if (associated(IOB%seaice_melt_heat)) & fluxes%seaice_melt_heat(i,j) = US%W_m2_to_QRZ_T * G%mask2dT(i,j) * IOB%seaice_melt_heat(i-i0,j-j0) + ! water flux due to sea ice and snow melt [kg/m2/s] + if (associated(IOB%seaice_melt)) & + fluxes%seaice_melt(i,j) = kg_m2_s_conversion * G%mask2dT(i,j) * IOB%seaice_melt(i-i0,j-j0) + fluxes%latent(i,j) = 0.0 ! notice minus sign since fprec is positive into the ocean if (associated(IOB%fprec)) then @@ -1492,6 +1493,7 @@ subroutine ice_ocn_bnd_type_chksum(id, timestep, iobt) chks = field_chksum( iobt%t_flux ) ; if (root) write(outunit,100) 'iobt%t_flux ', chks chks = field_chksum( iobt%q_flux ) ; if (root) write(outunit,100) 'iobt%q_flux ', chks chks = field_chksum( iobt%seaice_melt_heat); if (root) write(outunit,100) 'iobt%seaice_melt_heat', chks + chks = field_chksum( iobt%seaice_melt) ; if (root) write(outunit,100) 'iobt%seaice_melt ', chks chks = field_chksum( iobt%salt_flux ) ; if (root) write(outunit,100) 'iobt%salt_flux ', chks chks = field_chksum( iobt%lw_flux ) ; if (root) write(outunit,100) 'iobt%lw_flux ', chks chks = field_chksum( iobt%sw_flux_vis_dir) ; if (root) write(outunit,100) 'iobt%sw_flux_vis_dir', chks @@ -1500,7 +1502,6 @@ subroutine ice_ocn_bnd_type_chksum(id, timestep, iobt) chks = field_chksum( iobt%sw_flux_nir_dif) ; if (root) write(outunit,100) 'iobt%sw_flux_nir_dif', chks chks = field_chksum( iobt%lprec ) ; if (root) write(outunit,100) 'iobt%lprec ', chks chks = field_chksum( iobt%fprec ) ; if (root) write(outunit,100) 'iobt%fprec ', chks - chks = field_chksum( iobt%seaice_melt ) ; if (root) write(outunit,100) 'iobt%seaice_melt ', chks chks = field_chksum( iobt%lrunoff ) ; if (root) write(outunit,100) 'iobt%lrunoff ', chks chks = field_chksum( iobt%frunoff ) ; if (root) write(outunit,100) 'iobt%frunoff ', chks chks = field_chksum( iobt%p ) ; if (root) write(outunit,100) 'iobt%p ', chks