Skip to content

Commit 4869911

Browse files
Merge pull request #9 from marshallward/backscat_nodiv
MEKE: No-division implementation of src_btm_drag
2 parents f7fd633 + 174e8a3 commit 4869911

1 file changed

Lines changed: 56 additions & 39 deletions

File tree

src/parameterizations/lateral/MOM_MEKE.F90

Lines changed: 56 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -201,7 +201,7 @@ subroutine step_forward_MEKE(MEKE, h, SN_u, SN_v, visc, dt, G, GV, US, CS, hu, h
201201
src_GM, & ! The MEKE source/tendency from the thickness mixing (GM) [L2 T-3 ~> W kg-1] (= m2 s-3).
202202
src_mom_lp, & ! The MEKE source/tendency from the Laplacian of the resolved flow [L2 T-3 ~> W kg-1] (= m2 s-3).
203203
src_mom_bh, & ! The MEKE source/tendency from the biharmonic of the resolved flow [L2 T-3 ~> W kg-1] (= m2 s-3).
204-
ldamping_Strang1, & ! The MEKE damping rate computed at the 1st Strang splitting stage [T-1 ~> s-1].
204+
damp_rate_s1, & ! The MEKE damping rate computed at the 1st Strang splitting stage [T-1 ~> s-1].
205205
MEKE_current, & ! A copy of MEKE for use in computing the MEKE damping [L2 T-2 ~> m2 s-2].
206206
drag_rate_visc, & ! Near-bottom velocity contribution to bottom drag [H T-1 ~> m s-1 or kg m-2 s-1]
207207
drag_rate, & ! The MEKE spindown timescale due to bottom drag [T-1 ~> s-1].
@@ -233,11 +233,11 @@ subroutine step_forward_MEKE(MEKE, h, SN_u, SN_v, visc, dt, G, GV, US, CS, hu, h
233233
real :: cdrag2 ! The square of the drag coefficient times unit conversion factors [H2 L-2 ~> nondim or kg2 m-6]
234234
real :: advFac ! The product of the advection scaling factor and 1/dt [T-1 ~> s-1]
235235
real :: mass_neglect ! A negligible mass [R Z ~> kg m-2].
236-
real :: ldamping ! The MEKE damping rate [T-1 ~> s-1].
237236
real :: sdt ! dt to use locally [T ~> s] (could be scaled to accelerate)
238237
real :: sdt_damp ! dt for damping [T ~> s] (sdt could be split).
239-
real :: sfac ! A factor needed to compute damping due to Strang splitting [nondim]
240-
real :: Isfac ! Inverse of sfac [nondim]
238+
real :: damp_step ! Size of damping timestep relative to sdt [nondim]
239+
real :: damp_rate ! The MEKE damping rate [T-1 ~> s-1].
240+
real :: damping ! The net damping of a field after sdt_damp [nondim]
241241
logical :: use_drag_rate ! Flag to indicate drag_rate is finite
242242
integer :: i, j, k, is, ie, js, je, Isq, Ieq, Jsq, Jeq, nz
243243
real(kind=real32), dimension(size(MEKE%MEKE),NUM_FEATURES) :: features_array ! The array of features
@@ -287,7 +287,9 @@ subroutine step_forward_MEKE(MEKE, h, SN_u, SN_v, visc, dt, G, GV, US, CS, hu, h
287287

288288
! With a depth-dependent (and possibly strong) damping, it seems
289289
! advisable to use Strang splitting between the damping and diffusion.
290-
sdt_damp = sdt ; if (CS%MEKE_KH >= 0.0 .or. CS%MEKE_K4 >= 0.) sdt_damp = 0.5*sdt
290+
damp_step = 1.
291+
if (CS%MEKE_KH >= 0. .or. CS%MEKE_K4 >= 0.) damp_step = 0.5
292+
sdt_damp = sdt * damp_step
291293

292294
! Calculate depth integrated mass exchange if doing advection [R Z L2 ~> kg]
293295
if (CS%MEKE_advection_factor>0.) then
@@ -479,19 +481,29 @@ subroutine step_forward_MEKE(MEKE, h, SN_u, SN_v, visc, dt, G, GV, US, CS, hu, h
479481
! First stage of Strang splitting
480482
!$OMP parallel do default(shared)
481483
do j=js,je ; do i=is,ie
482-
ldamping = CS%MEKE_damping + drag_rate(i,j) * bottomFac2(i,j)
483-
if (MEKE%MEKE(i,j) < 0.) ldamping = 0.
484+
damp_rate = CS%MEKE_damping + drag_rate(i,j) * bottomFac2(i,j)
485+
if (MEKE%MEKE(i,j) < 0.) damp_rate = 0.
484486
! notice that the above line ensures a damping only if MEKE is positive,
485487
! while leaving MEKE unchanged if it is negative
486-
Isfac = 1. / (1. + sdt_damp * ldamping)
487-
MEKE%MEKE(i,j) = MEKE%MEKE(i,j) / (1.0 + sdt_damp*ldamping)
488-
MEKE_decay(i,j) = ldamping*G%mask2dT(i,j)
489-
ldamping_Strang1(i,j) = ldamping
490-
src_GM(i,j) = src_GM(i,j) * Isfac
491-
src_mom_lp(i,j) = src_mom_lp(i,j) * Isfac
492-
src_mom_bh(i,j) = src_mom_bh(i,j) * Isfac
493-
sfac = ( 1.0 + sdt_damp*ldamping )
494-
src_btm_drag(i,j) = MEKE_current(i,j) * ( (1.0 - sfac) / ( sdt * sfac ) )
488+
489+
damping = 1. / (1. + sdt_damp * damp_rate)
490+
491+
! NOTE: MEKE%MEKE should use `damping` but we must preserve the existing
492+
! expression for bit reproducibility
493+
MEKE%MEKE(i,j) = MEKE%MEKE(i,j) / (1. + sdt_damp * damp_rate)
494+
MEKE_decay(i,j) = damp_rate * G%mask2dT(i,j)
495+
496+
src_GM(i,j) = src_GM(i,j) * damping
497+
src_mom_lp(i,j) = src_mom_lp(i,j) * damping
498+
src_mom_bh(i,j) = src_mom_bh(i,j) * damping
499+
500+
src_btm_drag(i,j) = - MEKE_current(i,j) * ( &
501+
damp_step * (damp_rate * damping) &
502+
)
503+
504+
! Store the effective damping rate if sdt is split
505+
if (CS%MEKE_KH >= 0. .or. CS%MEKE_K4 >= 0.) &
506+
damp_rate_s1(i,j) = damp_rate * damping
495507
enddo ; enddo
496508

497509
if (CS%kh_flux_enabled .or. CS%MEKE_K4 >= 0.0) then
@@ -647,33 +659,38 @@ subroutine step_forward_MEKE(MEKE, h, SN_u, SN_v, visc, dt, G, GV, US, CS, hu, h
647659

648660
! Second stage of Strang splitting
649661
if (CS%MEKE_KH >= 0.0 .or. CS%MEKE_K4 >= 0.0) then
650-
if (sdt>sdt_damp) then
651-
! Recalculate the drag rate, since MEKE has changed.
652-
if (use_drag_rate) then
653-
!$OMP parallel do default(shared)
654-
do j=js,je ; do i=is,ie
655-
drag_rate(i,j) = (GV%H_to_RZ * I_mass(i,j)) * sqrt( drag_rate_visc(i,j)**2 + &
656-
cdrag2 * ( max(0.0, 2.0*bottomFac2(i,j)*MEKE%MEKE(i,j)) + CS%MEKE_Uscale**2 ) )
657-
enddo ; enddo
658-
endif
662+
! Recalculate the drag rate, since MEKE has changed.
663+
if (use_drag_rate) then
659664
!$OMP parallel do default(shared)
660665
do j=js,je ; do i=is,ie
661-
ldamping = CS%MEKE_damping + drag_rate(i,j) * bottomFac2(i,j)
662-
if (MEKE%MEKE(i,j) < 0.) ldamping = 0.
663-
! notice that the above line ensures a damping only if MEKE is positive,
664-
! while leaving MEKE unchanged if it is negative
665-
Isfac = 1. / (1. + sdt_damp*ldamping)
666-
MEKE%MEKE(i,j) = MEKE%MEKE(i,j) / (1.0 + sdt_damp*ldamping)
667-
MEKE_decay(i,j) = ldamping*G%mask2dT(i,j)
668-
src_GM(i,j) = src_GM(i,j) * Isfac
669-
src_mom_lp(i,j) = src_mom_lp(i,j) * Isfac
670-
src_mom_bh(i,j) = src_mom_bh(i,j) * Isfac
671-
src_adv(i,j) = src_adv(i,j) * Isfac
672-
src_mom_K4(i,j) = src_mom_K4(i,j) * Isfac
673-
sfac = ( 1.0 + sdt_damp*ldamping_Strang1(i,j) ) * ( 1.0 + sdt_damp*ldamping )
674-
src_btm_drag(i,j) = MEKE_current(i,j) * ( (1.0 - sfac) / ( sdt * sfac ) )
666+
drag_rate(i,j) = (GV%H_to_RZ * I_mass(i,j)) * sqrt( drag_rate_visc(i,j)**2 + &
667+
cdrag2 * ( max(0.0, 2.0*bottomFac2(i,j)*MEKE%MEKE(i,j)) + CS%MEKE_Uscale**2 ) )
675668
enddo ; enddo
676669
endif
670+
!$OMP parallel do default(shared)
671+
do j=js,je ; do i=is,ie
672+
damp_rate = CS%MEKE_damping + drag_rate(i,j) * bottomFac2(i,j)
673+
if (MEKE%MEKE(i,j) < 0.) damp_rate = 0.
674+
! notice that the above line ensures a damping only if MEKE is positive,
675+
! while leaving MEKE unchanged if it is negative
676+
677+
damping = 1. / (1. + sdt_damp * damp_rate)
678+
679+
! NOTE: As above, MEKE%MEKE should use `damping` but we must preserve
680+
! the existing expression for bit reproducibility.
681+
MEKE%MEKE(i,j) = MEKE%MEKE(i,j) / (1.0 + sdt_damp*damp_rate)
682+
MEKE_decay(i,j) = damp_rate*G%mask2dT(i,j)
683+
684+
src_GM(i,j) = src_GM(i,j) * damping
685+
src_mom_lp(i,j) = src_mom_lp(i,j) * damping
686+
src_mom_bh(i,j) = src_mom_bh(i,j) * damping
687+
src_adv(i,j) = src_adv(i,j) * damping
688+
src_mom_K4(i,j) = src_mom_K4(i,j) * damping
689+
690+
src_btm_drag(i,j) = -MEKE_current(i,j) * ( &
691+
damp_step * damping * (damp_rate + damp_rate_s1(i,j)) &
692+
)
693+
enddo ; enddo
677694
endif ! MEKE_KH>=0
678695

679696
if (CS%debug) then

0 commit comments

Comments
 (0)