From 0ca94f166b74d2c4ecbe3f4b32af423628b36fb9 Mon Sep 17 00:00:00 2001 From: "brandon.reichl" Date: Tue, 8 Jul 2025 07:38:37 -0400 Subject: [PATCH 1/3] Add conditional halo pass for frazil inside make_frazil Frazil may need an extra halo pass, but only when all of the following are true: (1) frazil is calculated and applied in the halo (e.g., vertex_shear is true) (2) the thermodynamic loop is called more than once before passing frazil to the sea-ice (dt_therm=dt_cpld), in which case the halo pass would be unnecessary. We needed an optional argument for make_frazil so we could flag to only do this update on the first call to make_frazil (which is needed because the previous call to make_frazil was after the diabatic loop, condition 4) --- src/core/MOM.F90 | 10 ++++++++-- src/core/MOM_variables.F90 | 3 ++- .../vertical/MOM_diabatic_aux.F90 | 17 +++++++++++++++-- .../vertical/MOM_diabatic_driver.F90 | 4 ++-- 4 files changed, 27 insertions(+), 7 deletions(-) diff --git a/src/core/MOM.F90 b/src/core/MOM.F90 index 08b4977f3a..debbef4221 100644 --- a/src/core/MOM.F90 +++ b/src/core/MOM.F90 @@ -767,7 +767,10 @@ subroutine step_MOM(forces_in, fluxes_in, sfc_state, Time_start, time_int_in, CS if (therm_reset) then CS%time_in_thermo_cycle = 0.0 - if (associated(CS%tv%frazil)) CS%tv%frazil(:,:) = 0.0 + if (associated(CS%tv%frazil)) then + CS%tv%frazil(:,:) = 0.0 + CS%tv%frazil_was_reset = .true. + endif if (associated(CS%tv%salt_deficit)) CS%tv%salt_deficit(:,:) = 0.0 if (associated(CS%tv%TempxPmE)) CS%tv%TempxPmE(:,:) = 0.0 if (associated(CS%tv%internal_heat)) CS%tv%internal_heat(:,:) = 0.0 @@ -2985,7 +2988,10 @@ subroutine initialize_MOM(Time, Time_init, param_file, dirs, CS, & endif if (use_p_surf_in_EOS) allocate(CS%tv%p_surf(isd:ied,jsd:jed), source=0.0) - if (use_frazil) allocate(CS%tv%frazil(isd:ied,jsd:jed), source=0.0) + if (use_frazil) then + allocate(CS%tv%frazil(isd:ied,jsd:jed), source=0.0) + CS%tv%frazil_was_reset = .true. + endif if (bound_salinity) allocate(CS%tv%salt_deficit(isd:ied,jsd:jed), source=0.0) allocate(CS%Hml(isd:ied,jsd:jed), source=0.0) diff --git a/src/core/MOM_variables.F90 b/src/core/MOM_variables.F90 index cc5059bd48..c6483f8cef 100644 --- a/src/core/MOM_variables.F90 +++ b/src/core/MOM_variables.F90 @@ -101,8 +101,9 @@ module MOM_variables ! These arrays are accumulated fluxes for communication with other components. real, dimension(:,:), pointer :: frazil => NULL() !< The energy needed to heat the ocean column to the - !! freezing point since calculate_surface_state was2 + !! freezing point since calculate_surface_state was !! last called [Q Z R ~> J m-2]. + logical :: frazil_was_reset !< If true, frazil has not accumulated since it was last reset. real, dimension(:,:), pointer :: salt_deficit => NULL() !< The salt needed to maintain the ocean column !! at a minimum salinity of MIN_SALINITY since the last time diff --git a/src/parameterizations/vertical/MOM_diabatic_aux.F90 b/src/parameterizations/vertical/MOM_diabatic_aux.F90 index b6d4dfa489..3e0e2c9803 100644 --- a/src/parameterizations/vertical/MOM_diabatic_aux.F90 +++ b/src/parameterizations/vertical/MOM_diabatic_aux.F90 @@ -8,6 +8,7 @@ module MOM_diabatic_aux use MOM_cpu_clock, only : CLOCK_MODULE_DRIVER, CLOCK_MODULE, CLOCK_ROUTINE use MOM_diag_mediator, only : post_data, register_diag_field, safe_alloc_ptr use MOM_diag_mediator, only : diag_ctrl, time_type +use MOM_domains, only : pass_var use MOM_EOS, only : calculate_density, calculate_TFreeze, EOS_domain use MOM_EOS, only : calculate_specific_vol_derivs, calculate_density_derivs use MOM_error_handler, only : MOM_error, FATAL, WARNING, callTree_showQuery @@ -107,7 +108,7 @@ module MOM_diabatic_aux !! This subroutine warms any water that is colder than the (currently !! surface) freezing point up to the freezing point and accumulates !! the required heat (in [Q R Z ~> J m-2]) in tv%frazil. -subroutine make_frazil(h, tv, G, GV, US, CS, p_surf, halo) +subroutine make_frazil(h, tv, G, GV, US, CS, p_surf, halo, frazil_halo_pass) type(ocean_grid_type), intent(in) :: G !< The ocean's grid structure type(verticalGrid_type), intent(in) :: GV !< The ocean's vertical grid structure real, dimension(SZI_(G),SZJ_(G),SZK_(GV)), & @@ -120,7 +121,7 @@ subroutine make_frazil(h, tv, G, GV, US, CS, p_surf, halo) real, dimension(SZI_(G),SZJ_(G)), & optional, intent(in) :: p_surf !< The pressure at the ocean surface [R L2 T-2 ~> Pa]. integer, optional, intent(in) :: halo !< Halo width over which to calculate frazil - + logical, optional, intent(in) :: frazil_halo_pass !< Indicates if frazil should be updated in halos ! Local variables real, dimension(SZI_(G)) :: & fraz_col, & ! The accumulated heat requirement due to frazil [Q R Z ~> J m-2]. @@ -137,6 +138,15 @@ subroutine make_frazil(h, tv, G, GV, US, CS, p_surf, halo) is = G%isc ; ie = G%iec ; js = G%jsc ; je = G%jec ; nz = GV%ke if (present(halo)) then is = G%isc-halo ; ie = G%iec+halo ; js = G%jsc-halo ; je = G%jec+halo + ! Frazil needs a halo pass only when all of the following are true: + ! (1) frazil is calculated and applied in the halo (e.g., vertex_shear is true) + ! (2) the thermodynamic loop is called more than once before passing frazil to the sea-ice (dt_therm Date: Tue, 8 Jul 2025 07:54:54 -0400 Subject: [PATCH 2/3] Shorten line in MOM_diabatic_driver --- src/parameterizations/vertical/MOM_diabatic_driver.F90 | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/parameterizations/vertical/MOM_diabatic_driver.F90 b/src/parameterizations/vertical/MOM_diabatic_driver.F90 index b8d8e95df0..8c74b34c84 100644 --- a/src/parameterizations/vertical/MOM_diabatic_driver.F90 +++ b/src/parameterizations/vertical/MOM_diabatic_driver.F90 @@ -374,7 +374,8 @@ subroutine diabatic(u, v, h, tv, BLD, fluxes, visc, ADp, CDp, dt, Time_end, & endif if (associated(fluxes%p_surf_full)) then - call make_frazil(h, tv, G, GV, US, CS%diabatic_aux_CSp, fluxes%p_surf_full, halo=CS%halo_TS_diff, frazil_halo_pass = .true.) + call make_frazil(h, tv, G, GV, US, CS%diabatic_aux_CSp, fluxes%p_surf_full, halo=CS%halo_TS_diff, & + frazil_halo_pass = .true.) else call make_frazil(h, tv, G, GV, US, CS%diabatic_aux_CSp, halo=CS%halo_TS_diff, frazil_halo_pass = .true.) endif From 82e06f0c7ec71a751fcc5d71044a0bff3136c1a9 Mon Sep 17 00:00:00 2001 From: "brandon.reichl" Date: Thu, 10 Jul 2025 13:52:23 -0400 Subject: [PATCH 3/3] Move halo update on frazil out of make_frazil and into post_diabatic_halo_updates --- src/core/MOM.F90 | 6 ++++++ src/parameterizations/vertical/MOM_diabatic_aux.F90 | 13 +------------ .../vertical/MOM_diabatic_driver.F90 | 5 ++--- 3 files changed, 9 insertions(+), 15 deletions(-) diff --git a/src/core/MOM.F90 b/src/core/MOM.F90 index debbef4221..e8910f3928 100644 --- a/src/core/MOM.F90 +++ b/src/core/MOM.F90 @@ -103,6 +103,7 @@ module MOM use MOM_interface_filter, only : interface_filter, interface_filter_init, interface_filter_end use MOM_interface_filter, only : interface_filter_CS use MOM_internal_tides, only : int_tide_CS +use MOM_kappa_shear, only : kappa_shear_at_vertex use MOM_lateral_mixing_coeffs, only : calc_slope_functions, VarMix_init, VarMix_end use MOM_lateral_mixing_coeffs, only : calc_resoln_function, calc_depth_function, VarMix_CS use MOM_MEKE, only : MEKE_alloc_register_restart, step_forward_MEKE @@ -229,6 +230,7 @@ module MOM logical :: rotate_index = .false. !< True if index map is rotated logical :: homogenize_forcings = .false. !< True if all inputs are homogenized logical :: update_ustar = .false. !< True to update ustar from homogenized tau + logical :: vertex_shear = .false. !< True if vertex shear is on type(verticalGrid_type), pointer :: & GV => NULL() !< structure containing vertical grid info @@ -1967,6 +1969,8 @@ subroutine post_diabatic_halo_updates(CS, G, GV, US, u, v, h, tv) call create_group_pass(pass_uv_T_S_h, h, G%Domain, halo=dynamics_stencil) call do_group_pass(pass_uv_T_S_h, G%Domain, clock=id_clock_pass) + if ((.not.tv%frazil_was_reset) .and. CS%vertex_shear) call pass_var(tv%frazil, G%Domain, halo=1) + ! Update derived thermodynamic quantities. if (allocated(tv%SpV_avg)) then call calc_derived_thermo(tv, h, G, GV, US, halo=dynamics_stencil, debug=CS%debug) @@ -3607,6 +3611,8 @@ subroutine initialize_MOM(Time, Time_init, param_file, dirs, CS, & CS%sponge_CSp, CS%ALE_sponge_CSp, CS%oda_incupd_CSp, CS%int_tide_CSp) endif + CS%vertex_shear = kappa_shear_at_vertex(param_file) + ! GMM, the following is needed to get BLDs into the dynamics module if (CS%split .and. fpmix) then call init_dyn_split_RK2_diabatic(CS%diabatic_CSp, CS%dyn_split_RK2_CSp) diff --git a/src/parameterizations/vertical/MOM_diabatic_aux.F90 b/src/parameterizations/vertical/MOM_diabatic_aux.F90 index 3e0e2c9803..8dc8edd2b9 100644 --- a/src/parameterizations/vertical/MOM_diabatic_aux.F90 +++ b/src/parameterizations/vertical/MOM_diabatic_aux.F90 @@ -8,7 +8,6 @@ module MOM_diabatic_aux use MOM_cpu_clock, only : CLOCK_MODULE_DRIVER, CLOCK_MODULE, CLOCK_ROUTINE use MOM_diag_mediator, only : post_data, register_diag_field, safe_alloc_ptr use MOM_diag_mediator, only : diag_ctrl, time_type -use MOM_domains, only : pass_var use MOM_EOS, only : calculate_density, calculate_TFreeze, EOS_domain use MOM_EOS, only : calculate_specific_vol_derivs, calculate_density_derivs use MOM_error_handler, only : MOM_error, FATAL, WARNING, callTree_showQuery @@ -108,7 +107,7 @@ module MOM_diabatic_aux !! This subroutine warms any water that is colder than the (currently !! surface) freezing point up to the freezing point and accumulates !! the required heat (in [Q R Z ~> J m-2]) in tv%frazil. -subroutine make_frazil(h, tv, G, GV, US, CS, p_surf, halo, frazil_halo_pass) +subroutine make_frazil(h, tv, G, GV, US, CS, p_surf, halo) type(ocean_grid_type), intent(in) :: G !< The ocean's grid structure type(verticalGrid_type), intent(in) :: GV !< The ocean's vertical grid structure real, dimension(SZI_(G),SZJ_(G),SZK_(GV)), & @@ -121,7 +120,6 @@ subroutine make_frazil(h, tv, G, GV, US, CS, p_surf, halo, frazil_halo_pass) real, dimension(SZI_(G),SZJ_(G)), & optional, intent(in) :: p_surf !< The pressure at the ocean surface [R L2 T-2 ~> Pa]. integer, optional, intent(in) :: halo !< Halo width over which to calculate frazil - logical, optional, intent(in) :: frazil_halo_pass !< Indicates if frazil should be updated in halos ! Local variables real, dimension(SZI_(G)) :: & fraz_col, & ! The accumulated heat requirement due to frazil [Q R Z ~> J m-2]. @@ -138,15 +136,6 @@ subroutine make_frazil(h, tv, G, GV, US, CS, p_surf, halo, frazil_halo_pass) is = G%isc ; ie = G%iec ; js = G%jsc ; je = G%jec ; nz = GV%ke if (present(halo)) then is = G%isc-halo ; ie = G%iec+halo ; js = G%jsc-halo ; je = G%jec+halo - ! Frazil needs a halo pass only when all of the following are true: - ! (1) frazil is calculated and applied in the halo (e.g., vertex_shear is true) - ! (2) the thermodynamic loop is called more than once before passing frazil to the sea-ice (dt_therm