Skip to content

Commit 59fdc9c

Browse files
committed
Add depth-based tapering of Leith+E
1 parent 83cd133 commit 59fdc9c

1 file changed

Lines changed: 56 additions & 1 deletion

File tree

src/parameterizations/lateral/MOM_hor_visc.F90

Lines changed: 56 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,9 @@ module MOM_hor_visc
8787
!! that gets backscattered in the Leith+E scheme. [nondim]
8888
logical :: smooth_Ah !< If true (default), then Ah and m_leithy are smoothed.
8989
!! This smoothing requires a lot of blocking communication.
90+
logical :: taper_leithy !< If true, backscatter coeff is tapered to zero with depth
91+
real :: leithy_depth !< If tapering leith+E, taper is applied below this depth [Z ~> m]
92+
real :: leithy_width !< If tapering leith+E, backscatter is zero below leithy_depth+leithy_width [Z ~> m]
9093
logical :: use_QG_Leith_visc !< If true, use QG Leith nonlinear eddy viscosity.
9194
!! KH is the background value.
9295
logical :: bound_Coriolis !< If true & SMAGORINSKY_AH is used, the biharmonic
@@ -471,6 +474,9 @@ subroutine horizontal_viscosity(u, v, h, uh, vh, diffu, diffv, MEKE, VarMix, G,
471474
hrat_min, & ! h_min divided by the thickness at the stress point (h or q) [nondim]
472475
visc_bound_rem ! fraction of overall viscous bounds that remain to be applied (h or q) [nondim]
473476

477+
! Layer depth. Used to taper Leith+E backscatter coefficient with depth
478+
real, allocatable :: zc(:,:,:) ! depth at center of h cell [Z ~> m]
479+
474480
is = G%isc ; ie = G%iec ; js = G%jsc ; je = G%jec ; nz = GV%ke
475481
Isq = G%IscB ; Ieq = G%IecB ; Jsq = G%JscB ; Jeq = G%JecB
476482

@@ -651,6 +657,16 @@ subroutine horizontal_viscosity(u, v, h, uh, vh, diffu, diffv, MEKE, VarMix, G,
651657
call smooth_x9_uv(CS, G, u_smooth(:,:,k), v_smooth(:,:,k), zero_land=.false.)
652658
enddo
653659
call pass_vector(u_smooth, v_smooth, G%Domain)
660+
! If tapering the backscatter, calculate depths now
661+
if (CS%taper_leithy) then
662+
! allocate zc
663+
allocate(zc(SZI_(G),SZJ_(G),SZK_(GV))) ; zc(:,:,:) = 0.0
664+
! Compute zc. Not actual cell centers because it starts at 0 rather than at SSH.
665+
zc(:,:,1) = 0.5 * h(:,:,1)
666+
do k=2,nz
667+
zc(:,:,k) = zc(:,:,k-1) + 0.5 * (h(:,:,k-1) + h(:,:,k))
668+
enddo
669+
endif
654670
endif
655671

656672
if (CS%use_QG_Leith_visc .and. ((CS%Leith_Kh) .or. (CS%Leith_Ah))) then
@@ -674,7 +690,7 @@ subroutine horizontal_viscosity(u, v, h, uh, vh, diffu, diffv, MEKE, VarMix, G,
674690
!$OMP h_neglect, h_neglect3, inv_PI3, inv_PI6, &
675691
!$OMP diffu, diffv, Kh_h, Kh_q, Ah_h, Ah_q, FrictWork, FrictWork_bh, FrictWork_GME, &
676692
!$OMP div_xx_h, sh_xx_h, vort_xy_q, sh_xy_q, GME_coeff_h, GME_coeff_q, &
677-
!$OMP KH_u_GME, KH_v_GME, grid_Re_Kh, grid_Re_Ah, NoSt, ShSt, hu_cont, hv_cont, STOCH &
693+
!$OMP KH_u_GME, KH_v_GME, grid_Re_Kh, grid_Re_Ah, NoSt, ShSt, hu_cont, hv_cont, STOCH, zc &
678694
!$OMP ) &
679695
!$OMP private( &
680696
!$OMP i, j, k, n, tmp, &
@@ -1320,6 +1336,10 @@ subroutine horizontal_viscosity(u, v, h, uh, vh, diffu, diffv, MEKE, VarMix, G,
13201336
m_leithy(i,j) = CS%m_leithy_max(i,j)
13211337
endif
13221338
endif
1339+
if (CS%taper_leithy) then
1340+
! Multiply m_leithy by taper function of depth
1341+
m_leithy(:,:) = m_leithy(:,:) * leithy_taper_function(CS, zc(:,:,k))
1342+
endif
13231343
enddo ; enddo
13241344

13251345
if (CS%smooth_Ah) then
@@ -2286,6 +2306,8 @@ subroutine horizontal_viscosity(u, v, h, uh, vh, diffu, diffv, MEKE, VarMix, G,
22862306
CS%dx2h, CS%dy2h, CS%dx2q, CS%dy2q)
22872307
endif
22882308

2309+
if (allocated(zc)) deallocate(zc)
2310+
22892311
end subroutine horizontal_viscosity
22902312

22912313
!> Allocates space for and calculates static variables used by horizontal_viscosity.
@@ -2655,6 +2677,19 @@ subroutine hor_visc_init(Time, G, GV, US, param_file, diag, CS, ADp)
26552677
"If true, Ah and m_leithy are smoothed within Leith+E. This requires "//&
26562678
"lots of blocking communications, which can be expensive", &
26572679
default=.true., do_not_log=.not.CS%use_Leithy)
2680+
call get_param(param_file, mdl, "TAPER_LEITHY", CS%taper_leithy, &
2681+
"If true, Leith+E c_K coefficient is tapered to zero"//&
2682+
"below a threshold depth", &
2683+
default=.false., do_not_log=.not.CS%use_Leithy)
2684+
if (CS%taper_leithy) then
2685+
call get_param(param_file, mdl, "LEITHY_DEPTH", CS%leithy_depth, &
2686+
"Leith+E backscatter starts tapering below this depth.", &
2687+
units="m", scale=US%m_to_Z, default=800.0)
2688+
call get_param(param_file, mdl, "LEITHY_WIDTH", CS%leithy_width, &
2689+
"Leith+E backscatter is zero below LEITHY_DEPTH+LEITHY_WIDTH.", &
2690+
units="m", scale=US%m_to_Z, default=400.0)
2691+
if (CS%leithy_width <= 0.0) call MOM_error(FATAL,"ERROR: LEITHY_WIDTH must be positive ")
2692+
endif
26582693

26592694
if (CS%use_GME .and. .not.split) call MOM_error(FATAL,"ERROR: Currently, USE_GME = True "// &
26602695
"cannot be used with SPLIT=False.")
@@ -3265,6 +3300,26 @@ subroutine hor_visc_init(Time, G, GV, US, param_file, diag, CS, ADp)
32653300

32663301
end subroutine hor_visc_init
32673302

3303+
!> leithy_taper_function returns 1 if zc is shallower than leithy_depth; 0 if deeper than
3304+
!! leithy_depth+leithy_width; and an interpolating cubic spline in between.
3305+
function leithy_taper_function(CS, zc)
3306+
type(hor_visc_CS), intent(in) :: CS !< Control structure for horizontal viscosity
3307+
real, intent(in) :: zc(:,:) !< depth of h-cell centersi [Z ~> m]
3308+
real :: leithy_taper_function(size(zc,dim=1),size(zc,dim=2)) ! Taper function evaluated at zc [nondim]
3309+
3310+
! Local variables
3311+
real :: x(size(zc,dim=1),size(zc,dim=2)) ! 0 at top of transition and 1 at bottom [nondim]
3312+
3313+
x = (zc - CS%leithy_depth) / CS%leithy_width
3314+
where (zc <= CS%leithy_depth)
3315+
leithy_taper_function = 1.0
3316+
elsewhere (zc >= CS%leithy_depth + CS%leithy_width)
3317+
leithy_taper_function = 0.0
3318+
elsewhere
3319+
leithy_taper_function = (x - 1.0)**2 * (1.0 + 2 * x)
3320+
end where
3321+
end function leithy_taper_function
3322+
32683323
!> hor_visc_vel_stencil returns the horizontal viscosity input velocity stencil size
32693324
function hor_visc_vel_stencil(CS) result(stencil)
32703325
type(hor_visc_CS), intent(in) :: CS !< Control structure for horizontal viscosity

0 commit comments

Comments
 (0)