Skip to content
Open
22 changes: 17 additions & 5 deletions config_src/drivers/FMS_cap/MOM_surface_forcing_gfdl.F90
Original file line number Diff line number Diff line change
Expand Up @@ -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]
Expand Down Expand Up @@ -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) &
Expand Down Expand Up @@ -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%seaice_melt(i,j)) + fluxes%fprec(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
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that seaice_melt might now be removed from the summation above, since the purpose of the code below appears to be to remove it from the net_FW flux.

We recently noticed some diagnosed imbalances in ice+ocean water conservation in OM5 with (CS%adjust_net_fresh_water_to_zero=.true.). If I understood the comments below, then I think this PR would take care of that non-conservation by no longer using the imperfect estimate for seaice_melt below.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, I see. I will try to replacenet_FW with fluxes%seaice_melt directly then.

Expand Down Expand Up @@ -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)) &
Expand Down Expand Up @@ -1792,6 +1801,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
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
Expand Down
10 changes: 5 additions & 5 deletions config_src/drivers/STALE_mct_cap/mom_surface_forcing_mct.F90
Original file line number Diff line number Diff line change
Expand Up @@ -424,6 +424,10 @@ subroutine convert_IOB_to_fluxes(IOB, fluxes, index_bounds, Time, valid_time, G,
if (associated(IOB%lprec)) &
fluxes%lprec(i,j) = kg_m2_s_conversion * IOB%lprec(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 * IOB%seaice_melt(i-i0,j-j0) * G%mask2dT(i,j)

! frozen precipitation (snow)
if (associated(IOB%fprec)) &
fluxes%fprec(i,j) = kg_m2_s_conversion * IOB%fprec(i-i0,j-j0) * G%mask2dT(i,j)
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -550,7 +550,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%seaice_melt(i,j)) + &
((((fluxes%lprec(i,j) + fluxes%seaice_melt(i,j)) + fluxes%fprec(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)

Expand Down
8 changes: 4 additions & 4 deletions config_src/drivers/nuopc_cap/mom_surface_forcing_nuopc.F90
Original file line number Diff line number Diff line change
Expand Up @@ -456,6 +456,10 @@ subroutine convert_IOB_to_fluxes(IOB, fluxes, index_bounds, Time, valid_time, G,
if (associated(IOB%lprec)) &
fluxes%lprec(i,j) = kg_m2_s_conversion * IOB%lprec(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%fprec)) &
fluxes%fprec(i,j) = kg_m2_s_conversion * IOB%fprec(i-i0,j-j0) * G%mask2dT(i,j)

Expand Down Expand Up @@ -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
Expand Down
4 changes: 3 additions & 1 deletion config_src/drivers/solo_driver/MESO_surface_forcing.F90
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ subroutine MESO_buoyancy_forcing(sfc_state, fluxes, day, dt, G, US, CS)
! can be simply set to zero. The net fresh water flux should probably be
! set in fluxes%evap and fluxes%lprec, with any salinity restoring
! appearing in fluxes%vprec, and the other water flux components
! (fprec, lrunoff and frunoff) left as arrays full of zeros.
! (fprec, lrunoff and frunoff, seaice_melt) left as arrays full of zeros.
! Evap is usually negative and precip is usually positive. All heat fluxes
! are in W m-2 and positive for heat going into the ocean. All fresh water
! fluxes are in kg m-2 s-1 and positive for water moving into the ocean.
Expand All @@ -98,6 +98,7 @@ subroutine MESO_buoyancy_forcing(sfc_state, fluxes, day, dt, G, US, CS)
if (CS%use_temperature) then
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%seaice_melt, isd, ied, jsd, jed)
call safe_alloc_ptr(fluxes%fprec, isd, ied, jsd, jed)
call safe_alloc_ptr(fluxes%lrunoff, isd, ied, jsd, jed)
call safe_alloc_ptr(fluxes%frunoff, isd, ied, jsd, jed)
Expand Down Expand Up @@ -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
Expand Down
51 changes: 29 additions & 22 deletions config_src/drivers/solo_driver/MOM_surface_forcing.F90
Original file line number Diff line number Diff line change
Expand Up @@ -1148,15 +1148,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%seaice_melt(i,j) = fluxes%seaice_melt(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%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
Expand Down Expand Up @@ -1261,10 +1262,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
Expand Down Expand Up @@ -1307,20 +1309,22 @@ subroutine buoyancy_forcing_from_data_override(sfc_state, fluxes, day, dt, G, US

! mask out land points and compute heat content of water fluxes
! assume liquid precip enters ocean at SST
! assume sea ice melt enters ocean at SST
! assume frozen precip enters ocean at 0degC
! assume liquid runoff enters ocean at SST
! 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%seaice_melt(i,j) = fluxes%seaice_melt(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%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
Expand Down Expand Up @@ -1361,6 +1365,7 @@ subroutine buoyancy_forcing_zero(sfc_state, fluxes, day, dt, G, CS)
do j=js,je ; do i=is,ie
fluxes%evap(i,j) = 0.0
fluxes%lprec(i,j) = 0.0
fluxes%seaice_melt(i,j) = 0.0
fluxes%fprec(i,j) = 0.0
fluxes%vprec(i,j) = 0.0
fluxes%lrunoff(i,j) = 0.0
Expand Down Expand Up @@ -1404,6 +1409,7 @@ subroutine buoyancy_forcing_const(sfc_state, fluxes, day, dt, G, US, CS)
do j=js,je ; do i=is,ie
fluxes%evap(i,j) = 0.0
fluxes%lprec(i,j) = 0.0
fluxes%seaice_melt(i,j) = 0.0
fluxes%fprec(i,j) = 0.0
fluxes%vprec(i,j) = 0.0
fluxes%lrunoff(i,j) = 0.0
Expand Down Expand Up @@ -1452,6 +1458,7 @@ subroutine buoyancy_forcing_linear(sfc_state, fluxes, day, dt, G, US, CS)
do j=js,je ; do i=is,ie
fluxes%evap(i,j) = 0.0
fluxes%lprec(i,j) = 0.0
fluxes%seaice_melt(i,j) = 0.0
fluxes%fprec(i,j) = 0.0
fluxes%vprec(i,j) = 0.0
fluxes%lrunoff(i,j) = 0.0
Expand Down
6 changes: 4 additions & 2 deletions config_src/drivers/solo_driver/user_surface_forcing.F90
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ subroutine USER_buoyancy_forcing(sfc_state, fluxes, day, dt, G, US, CS)
! can be simply set to zero. The net fresh water flux should probably be
! set in fluxes%evap and fluxes%lprec, with any salinity restoring
! appearing in fluxes%vprec, and the other water flux components
! (fprec, lrunoff and frunoff) left as arrays full of zeros.
! (fprec, lrunoff, frunoff, seaice_melt) left as arrays full of zeros.
! Evap is usually negative and precip is usually positive. All heat fluxes
! are in W m-2 and positive for heat going into the ocean. All fresh water
! fluxes are in [R Z T-1 ~> kg m-2 s-1] and positive for water moving into the ocean.
Expand Down Expand Up @@ -153,6 +153,7 @@ subroutine USER_buoyancy_forcing(sfc_state, fluxes, day, dt, G, US, CS)
if (CS%use_temperature) then
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%seaice_melt, isd, ied, jsd, jed)
call safe_alloc_ptr(fluxes%fprec, isd, ied, jsd, jed)
call safe_alloc_ptr(fluxes%lrunoff, isd, ied, jsd, jed)
call safe_alloc_ptr(fluxes%frunoff, isd, ied, jsd, jed)
Expand All @@ -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
Expand Down Expand Up @@ -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
Expand Down
Loading