Skip to content

Commit

Permalink
Merge pull request #127 from gustavo-marques/depth_scaled_khth
Browse files Browse the repository at this point in the history
Adds option to scale KHTH with depth
  • Loading branch information
alperaltuntas authored Oct 16, 2019
2 parents 3b957a7 + 1522ad0 commit 2bb321e
Show file tree
Hide file tree
Showing 3 changed files with 96 additions and 13 deletions.
5 changes: 4 additions & 1 deletion 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(G, 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(G, 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(G, 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
67 changes: 65 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, KHTH 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,44 @@ 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 the non-dimensional depth functions.
subroutine calc_depth_function(G, CS)
type(ocean_grid_type), intent(in) :: G !< Ocean grid structure
type(VarMix_CS), pointer :: CS !< Variable mixing coefficients

! Local variables
integer :: is, ie, js, je, Isq, Ieq, Jsq, Jeq
integer :: i, j
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
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 +957,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 +973,12 @@ 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, KHTH 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 +1028,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 +1211,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 2bb321e

Please sign in to comment.