Skip to content

Commit

Permalink
Adds option to scale KHTH with depth
Browse files Browse the repository at this point in the history
This commit adds the option to scale KHTH with
depth by setting DEPTH_SCALED_KHTH = True. The scalling is applied
as follows:
KHTH = MIN(1,H/H_0)**N * KHTH,
where H_0 is defined by DEPTH_SCALED_KHTH_H0,
and N by DEPTH_SCALED_KHTH_EXP.
  • Loading branch information
gustavo-marques committed Oct 16, 2019
1 parent 3b957a7 commit bb785a8
Show file tree
Hide file tree
Showing 3 changed files with 103 additions and 15 deletions.
9 changes: 6 additions & 3 deletions src/core/MOM.F90
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ module MOM
use MOM_hor_index, only : hor_index_type, hor_index_init
use MOM_interface_heights, only : find_eta
use MOM_lateral_mixing_coeffs, only : calc_slope_functions, VarMix_init
use MOM_lateral_mixing_coeffs, only : calc_resoln_function, VarMix_CS
use MOM_lateral_mixing_coeffs, only : calc_resoln_function, calc_depth_function, VarMix_CS
use MOM_MEKE, only : MEKE_init, MEKE_alloc_register_restart, step_forward_MEKE, MEKE_CS
use MOM_MEKE_types, only : MEKE_type
use MOM_mixed_layer_restrat, only : mixedlayer_restrat, mixedlayer_restrat_init, mixedlayer_restrat_CS
Expand Down Expand Up @@ -565,6 +565,7 @@ subroutine step_MOM(forces, fluxes, sfc_state, Time_start, time_interval, CS, &
call enable_averaging(cycle_time, Time_start + real_to_time(cycle_time), &
CS%diag)
call calc_resoln_function(h, CS%tv, G, GV, US, CS%VarMix)
call calc_depth_function(h, CS%tv, G, GV, US, CS%VarMix)
call disable_averaging(CS%diag)
endif
endif
Expand Down Expand Up @@ -1403,6 +1404,7 @@ subroutine step_offline(forces, fluxes, sfc_state, Time_start, time_interval, CS
if (associated(CS%VarMix)) then
call pass_var(CS%h, G%Domain)
call calc_resoln_function(CS%h, CS%tv, G, GV, US, CS%VarMix)
call calc_depth_function(CS%h, CS%tv, G, GV, US, CS%VarMix)
call calc_slope_functions(CS%h, CS%tv, REAL(dt_offline), G, GV, US, CS%VarMix)
endif
call tracer_hordiff(CS%h, REAL(dt_offline), CS%MEKE, CS%VarMix, G, GV, US, &
Expand All @@ -1428,6 +1430,7 @@ subroutine step_offline(forces, fluxes, sfc_state, Time_start, time_interval, CS
if (associated(CS%VarMix)) then
call pass_var(CS%h, G%Domain)
call calc_resoln_function(CS%h, CS%tv, G, GV, US, CS%VarMix)
call calc_depth_function(CS%h, CS%tv, G, GV, US, CS%VarMix)
call calc_slope_functions(CS%h, CS%tv, REAL(dt_offline), G, GV, US, CS%VarMix)
endif
call tracer_hordiff(CS%h, REAL(dt_offline), CS%MEKE, CS%VarMix, G, GV, US, &
Expand Down Expand Up @@ -1674,8 +1677,8 @@ subroutine initialize_MOM(Time, Time_init, param_file, dirs, CS, restart_CSp, &
"faster by eliminating subroutine calls.", default=.false.)
call get_param(param_file, "MOM", "DO_DYNAMICS", CS%do_dynamics, &
"If False, skips the dynamics calls that update u & v, as well as "//&
"the gravity wave adjustment to h. This is a fragile feature and "//&
"thus undocumented.", default=.true., do_not_log=.true. )
"the gravity wave adjustment to h. This may be a fragile feature, "//&
"but can be useful during development", default=.true.)
call get_param(param_file, "MOM", "ADVECT_TS", advect_TS, &
"If True, advect temperature and salinity horizontally "//&
"If False, T/S are registered for advection. "//&
Expand Down
72 changes: 70 additions & 2 deletions src/parameterizations/lateral/MOM_lateral_mixing_coeffs.F90
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ module MOM_lateral_mixing_coeffs
!! when the deformation radius is well resolved.
logical :: Resoln_scaled_KhTh !< If true, scale away the thickness diffusivity
!! when the deformation radius is well resolved.
logical :: Depth_scaled_KhTh !< If true, the interface depth diffusivity is scaled away
!! when the depth is shallower than a reference depth.
logical :: Resoln_scaled_KhTr !< If true, scale away the tracer diffusivity
!! when the deformation radius is well resolved.
logical :: interpolate_Res_fn !< If true, interpolate the resolution function
Expand All @@ -48,6 +50,8 @@ module MOM_lateral_mixing_coeffs
!! This parameter is set depending on other parameters.
logical :: calculate_res_fns !< If true, calculate all the resolution factors.
!! This parameter is set depending on other parameters.
logical :: calculate_depth_fns !< If true, calculate all the depth factors.
!! This parameter is set depending on other parameters.
logical :: calculate_Eady_growth_rate !< If true, calculate all the Eady growth rate.
!! This parameter is set depending on other parameters.
real, dimension(:,:), pointer :: &
Expand All @@ -64,6 +68,10 @@ module MOM_lateral_mixing_coeffs
!! deformation radius to the grid spacing at u points [nondim].
Res_fn_v => NULL(), & !< Non-dimensional function of the ratio the first baroclinic
!! deformation radius to the grid spacing at v points [nondim].
Depth_fn_u => NULL(), & !< Non-dimensional function of the ratio of the depth to
!! a reference depth (maximum 1) at u points [nondim]
Depth_fn_v => NULL(), & !< Non-dimensional function of the ratio of the depth to
!! a reference depth (maximum 1) at v points [nondim]
beta_dx2_h => NULL(), & !< The magnitude of the gradient of the Coriolis parameter
!! times the grid spacing squared at h points [L T-1 ~> m s-1].
beta_dx2_q => NULL(), & !< The magnitude of the gradient of the Coriolis parameter
Expand Down Expand Up @@ -111,6 +119,8 @@ module MOM_lateral_mixing_coeffs
real :: Res_coef_visc !< A non-dimensional number that determines the function
!! of resolution, used for lateral viscosity, as:
!! F = 1 / (1 + (Res_coef_visc*Ld/dx)^Res_fn_power)
real :: depth_scaled_khth_h0 !< The depth above which KHTH is linearly scaled away [Z ~> m]
real :: depth_scaled_khth_exp !< The exponent used in the depth dependent scaling function for KHTH [nondim]
real :: kappa_smooth !< A diffusivity for smoothing T/S in vanished layers [Z2 T-1 ~> m2 s-1]
integer :: Res_fn_power_khth !< The power of dx/Ld in the KhTh resolution function. Any
!! positive integer power may be used, but even powers
Expand Down Expand Up @@ -140,10 +150,48 @@ module MOM_lateral_mixing_coeffs
end type VarMix_CS

public VarMix_init, calc_slope_functions, calc_resoln_function
public calc_QG_Leith_viscosity
public calc_QG_Leith_viscosity, calc_depth_function

contains

!> Calculates and stires the non-dimensional depth functions.
subroutine calc_depth_function(h, tv, G, GV, US, CS)
type(ocean_grid_type), intent(inout) :: G !< Ocean grid structure
real, dimension(SZI_(G),SZJ_(G),SZK_(G)), intent(in) :: h !< Layer thickness [H ~> m or kg m-2]
type(thermo_var_ptrs), intent(in) :: tv !< Thermodynamic variables
type(verticalGrid_type), intent(in) :: GV !< Vertical grid structure
type(unit_scale_type), intent(in) :: US !< A dimensional unit scaling type
type(VarMix_CS), pointer :: CS !< Variable mixing coefficients

! Local variables
integer :: is, ie, js, je, Isq, Ieq, Jsq, Jeq, nz
integer :: i, j, k
real :: H0 ! local variable for reference depth
real :: expo ! exponent used in the depth dependent scaling
is = G%isc ; ie = G%iec ; js = G%jsc ; je = G%jec ; nz = G%ke
Isq = G%IscB ; Ieq = G%IecB ; Jsq = G%JscB ; Jeq = G%JecB

if (.not. associated(CS)) call MOM_error(FATAL, "calc_depth_function:"// &
"Module must be initialized before it is used.")
if (.not. CS%calculate_depth_fns) return
if (.not. associated(CS%Depth_fn_u)) call MOM_error(FATAL, &
"calc_depth_function: %Depth_fn_u is not associated with Depth_scaled_KhTh.")
if (.not. associated(CS%Depth_fn_v)) call MOM_error(FATAL, &
"calc_depth_function: %Depth_fn_v is not associated with Depth_scaled_KhTh.")

H0 = CS%depth_scaled_khth_h0
expo = CS%depth_scaled_khth_exp
!$OMP do
do j=js,je ; do I=is-1,Ieq
CS%Depth_fn_u(I,j) = (MIN(1.0, 0.5*(G%bathyT(i,j) + G%bathyT(i+1,j))/H0))**expo
enddo ; enddo
!$OMP do
do J=js-1,Jeq ; do i=is,ie
CS%Depth_fn_v(i,J) = (MIN(1.0, 0.5*(G%bathyT(i,j) + G%bathyT(i,j+1))/H0))**expo
enddo ; enddo

end subroutine calc_depth_function

!> Calculates and stores the non-dimensional resolution functions
subroutine calc_resoln_function(h, tv, G, GV, US, CS)
type(ocean_grid_type), intent(inout) :: G !< Ocean grid structure
Expand Down Expand Up @@ -913,7 +961,7 @@ subroutine VarMix_init(Time, G, GV, US, param_file, diag, CS)
CS%calculate_Rd_dx = .false.
CS%calculate_res_fns = .false.
CS%calculate_Eady_growth_rate = .false.

CS%calculate_depth_fns = .false.
! Read all relevant parameters and write them to the model log.
call log_version(param_file, mdl, version, "")
call get_param(param_file, mdl, "USE_VARIABLE_MIXING", CS%use_variable_mixing,&
Expand All @@ -929,6 +977,13 @@ subroutine VarMix_init(Time, G, GV, US, param_file, diag, CS)
"If true, the Laplacian lateral viscosity is scaled away "//&
"when the first baroclinic deformation radius is well "//&
"resolved.", default=.false.)
call get_param(param_file, mdl, "DEPTH_SCALED_KHTH", CS%Depth_scaled_KhTh, &
"If true, the interface depth diffusivity is scaled away "//&
"when the depth is shallower than a reference depth: "//&
"KHTH = MIN(1,H/H0)**N * KHTH, where H0 is a reference"//&
"depth, controlled via DEPTH_SCALED_KHTH_H0, and the"//&
"exponent (N) is controlled via DEPTH_SCALED_KHTH_EXP.",&
default=.false.)
call get_param(param_file, mdl, "RESOLN_SCALED_KHTH", CS%Resoln_scaled_KhTh, &
"If true, the interface depth diffusivity is scaled away "//&
"when the first baroclinic deformation radius is well "//&
Expand Down Expand Up @@ -978,6 +1033,7 @@ subroutine VarMix_init(Time, G, GV, US, param_file, diag, CS)

call get_param(param_file, mdl, "DEBUG", CS%debug, default=.false., do_not_log=.true.)


if (CS%Resoln_use_ebt .or. CS%khth_use_ebt_struct) then
in_use = .true.
call get_param(param_file, mdl, "RESOLN_N2_FILTER_DEPTH", N2_filter_depth, &
Expand Down Expand Up @@ -1160,6 +1216,18 @@ subroutine VarMix_init(Time, G, GV, US, param_file, diag, CS)

endif

if (CS%Depth_scaled_KhTh) then
CS%calculate_depth_fns = .true.
allocate(CS%Depth_fn_u(IsdB:IedB,jsd:jed)) ; CS%Depth_fn_u(:,:) = 0.0
allocate(CS%Depth_fn_v(isd:ied,JsdB:JedB)) ; CS%Depth_fn_v(:,:) = 0.0
call get_param(param_file, mdl, "DEPTH_SCALED_KHTH_H0", CS%depth_scaled_khth_h0, &
"The depth above which KHTH is scaled away.",&
units="m", default=1000.)
call get_param(param_file, mdl, "DEPTH_SCALED_KHTH_EXP", CS%depth_scaled_khth_exp, &
"The exponent used in the depth dependent scaling function for KHTH.",&
units="nondim", default=3.0)
endif

! Resolution %Rd_dx_h
CS%id_Rd_dx = register_diag_field('ocean_model', 'Rd_dx', diag%axesT1, Time, &
'Ratio between deformation radius and grid spacing', 'm m-1')
Expand Down
37 changes: 27 additions & 10 deletions src/parameterizations/lateral/MOM_thickness_diffuse.F90
Original file line number Diff line number Diff line change
Expand Up @@ -137,12 +137,13 @@ subroutine thickness_diffuse(h, uhtr, vhtr, tv, dt, G, GV, US, MEKE, VarMix, CDp
real, dimension(SZI_(G), SZJB_(G)) :: &
KH_v_CFL ! The maximum stable interface height diffusivity at v grid points [L2 T-1 ~> m2 s-1]
real :: Khth_Loc_u(SZIB_(G), SZJ_(G))
real :: Khth_Loc_v(SZI_(G), SZJB_(G))
real :: Khth_Loc(SZIB_(G), SZJB_(G)) ! locally calculated thickness diffusivity [L2 T-1 ~> m2 s-1]
real :: h_neglect ! A thickness that is so small it is usually lost
! in roundoff and can be neglected [H ~> m or kg m-2].
real, dimension(:,:), pointer :: cg1 => null() !< Wave speed [L T-1 ~> m s-1]
real :: dt_in_T ! Time increment [T ~> s]
logical :: use_VarMix, Resoln_scaled, use_stored_slopes, khth_use_ebt_struct, use_Visbeck
logical :: use_VarMix, Resoln_scaled, Depth_scaled, use_stored_slopes, khth_use_ebt_struct, use_Visbeck
logical :: use_QG_Leith
integer :: i, j, k, is, ie, js, je, nz
real :: hu(SZI_(G), SZJ_(G)) ! u-thickness [H ~> m or kg m-2]
Expand All @@ -168,10 +169,12 @@ subroutine thickness_diffuse(h, uhtr, vhtr, tv, dt, G, GV, US, MEKE, VarMix, CDp

use_VarMix = .false. ; Resoln_scaled = .false. ; use_stored_slopes = .false.
khth_use_ebt_struct = .false. ; use_Visbeck = .false. ; use_QG_Leith = .false.
Depth_scaled = .false.

if (associated(VarMix)) then
use_VarMix = VarMix%use_variable_mixing .and. (CS%KHTH_Slope_Cff > 0.)
Resoln_scaled = VarMix%Resoln_scaled_KhTh
Depth_scaled = VarMix%Depth_scaled_KhTh
use_stored_slopes = VarMix%use_stored_slopes
khth_use_ebt_struct = VarMix%khth_use_ebt_struct
use_Visbeck = VarMix%use_Visbeck
Expand Down Expand Up @@ -238,6 +241,13 @@ subroutine thickness_diffuse(h, uhtr, vhtr, tv, dt, G, GV, US, MEKE, VarMix, CDp
enddo ; enddo
endif

if (Depth_scaled) then
!$OMP do
do j=js,je; do I=is-1,ie
Khth_loc_u(I,j) = Khth_loc_u(I,j) * VarMix%Depth_fn_u(I,j)
enddo ; enddo
endif

if (CS%Khth_Max > 0) then
!$OMP do
do j=js,je; do I=is-1,ie
Expand Down Expand Up @@ -284,55 +294,62 @@ subroutine thickness_diffuse(h, uhtr, vhtr, tv, dt, G, GV, US, MEKE, VarMix, CDp

!$OMP do
do J=js-1,je ; do i=is,ie
Khth_loc(i,j) = CS%Khth
Khth_loc_v(i,J) = CS%Khth
enddo ; enddo

if (use_VarMix) then
!$OMP do
if (use_Visbeck) then
do J=js-1,je ; do i=is,ie
Khth_loc(i,j) = Khth_loc(i,j) + CS%KHTH_Slope_Cff*VarMix%L2v(i,J)*VarMix%SN_v(i,J)
Khth_loc_v(i,J) = Khth_loc_v(i,J) + CS%KHTH_Slope_Cff*VarMix%L2v(i,J)*VarMix%SN_v(i,J)
enddo ; enddo
endif
endif
if (associated(MEKE)) then ; if (associated(MEKE%Kh)) then
!$OMP do
if (CS%MEKE_GEOMETRIC) then
do j=js-1,je ; do I=is,ie
Khth_loc(I,j) = Khth_loc(I,j) + G%mask2dCv(i,J) * CS%MEKE_GEOMETRIC_alpha * &
do J=js-1,je ; do i=is,ie
Khth_loc_v(i,J) = Khth_loc_v(i,J) + G%mask2dCv(i,J) * CS%MEKE_GEOMETRIC_alpha * &
0.5*(MEKE%MEKE(i,j)+MEKE%MEKE(i,j+1)) / &
(VarMix%SN_v(i,J) + CS%MEKE_GEOMETRIC_epsilon)
enddo ; enddo
else
do J=js-1,je ; do i=is,ie
Khth_loc(i,j) = Khth_loc(i,j) + MEKE%KhTh_fac*sqrt(MEKE%Kh(i,j)*MEKE%Kh(i,j+1))
Khth_loc_v(i,J) = Khth_loc_v(i,J) + MEKE%KhTh_fac*sqrt(MEKE%Kh(i,j)*MEKE%Kh(i,j+1))
enddo ; enddo
endif
endif ; endif

if (Resoln_scaled) then
!$OMP do
do J=js-1,je; do i=is,ie
Khth_loc_v(i,J) = Khth_loc_v(i,J) * VarMix%Res_fn_v(i,J)
enddo ; enddo
endif

if (Depth_scaled) then
!$OMP do
do J=js-1,je ; do i=is,ie
Khth_loc(i,j) = Khth_loc(i,j) * VarMix%Res_fn_v(i,J)
Khth_loc_v(i,J) = Khth_loc_v(i,J) * VarMix%Depth_fn_v(i,J)
enddo ; enddo
endif

if (CS%Khth_Max > 0) then
!$OMP do
do J=js-1,je ; do i=is,ie
Khth_loc(i,j) = max(CS%Khth_Min, min(Khth_loc(i,j), CS%Khth_Max))
Khth_loc_v(i,J) = max(CS%Khth_Min, min(Khth_loc_v(i,J), CS%Khth_Max))
enddo ; enddo
else
!$OMP do
do J=js-1,je ; do i=is,ie
Khth_loc(i,j) = max(CS%Khth_Min, Khth_loc(i,j))
Khth_loc_v(i,J) = max(CS%Khth_Min, Khth_loc_v(i,J))
enddo ; enddo
endif

if (CS%max_Khth_CFL > 0.0) then
!$OMP do
do J=js-1,je ; do i=is,ie
KH_v(i,J,1) = min(KH_v_CFL(i,J), Khth_loc(i,j))
KH_v(i,J,1) = min(KH_v_CFL(i,J), Khth_loc_v(i,J))
enddo ; enddo
endif

Expand Down

0 comments on commit bb785a8

Please sign in to comment.