Skip to content

Commit c54174f

Browse files
Hallberg-NOAAdougiesquire
authored andcommitted
*+Make Leith viscosity runs layout-invariant
Added the new function hor_visc_vel_stencil to return the velocity stencil of the velocity fields used by horizontal_viscosity depending on the options that are in use, and then use this information in the group_pass calls for the velocities that are passed to horizontal_viscosity. Also adjusted the size of the loops used to set up DX_dyBu and DY_dxBu in the hor_visc control structure depending on the horizontal viscosity options and added a test in hor_visc_init for a large enough halo size for the options that are in use. Both of these answer-changing modifications are necessary for MOM6 to reproduce across PE count and layout) when Leith viscosity parameterizations are in use. The MOM_hor_visc code was also revised slightly in several places to more closely adhere to MOM6 style with respect to using a 2-point indent and similar purely cosmetic considerations. This commit does change answers when a Leith viscosity is in use, and adds a new publicly visible function. Answers are bitwise identical when a Leith viscosity is not being used.
1 parent 19e8c1b commit c54174f

File tree

2 files changed

+58
-30
lines changed

2 files changed

+58
-30
lines changed

src/core/MOM_dynamics_split_RK2.F90

+7-6
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ module MOM_dynamics_split_RK2
4949
use MOM_grid, only : ocean_grid_type
5050
use MOM_harmonic_analysis, only : harmonic_analysis_CS
5151
use MOM_hor_index, only : hor_index_type
52-
use MOM_hor_visc, only : horizontal_viscosity, hor_visc_CS
52+
use MOM_hor_visc, only : horizontal_viscosity, hor_visc_CS, hor_visc_vel_stencil
5353
use MOM_hor_visc, only : hor_visc_init, hor_visc_end
5454
use MOM_interface_heights, only : thickness_to_dz, find_col_avg_SpV
5555
use MOM_lateral_mixing_coeffs, only : VarMix_CS
@@ -400,7 +400,7 @@ subroutine step_MOM_dyn_split_RK2(u_inst, v_inst, h, tv, visc, Time_local, dt, f
400400
logical :: showCallTree, sym
401401

402402
integer :: i, j, k, is, ie, js, je, Isq, Ieq, Jsq, Jeq, nz
403-
integer :: cont_stencil, obc_stencil
403+
integer :: cont_stencil, obc_stencil, vel_stencil
404404

405405
is = G%isc ; ie = G%iec ; js = G%jsc ; je = G%jec ; nz = GV%ke
406406
Isq = G%IscB ; Ieq = G%IecB ; Jsq = G%JscB ; Jeq = G%JecB
@@ -470,19 +470,20 @@ subroutine step_MOM_dyn_split_RK2(u_inst, v_inst, h, tv, visc, Time_local, dt, f
470470
if (associated(CS%OBC)) then
471471
if (CS%OBC%oblique_BCs_exist_globally) obc_stencil = 3
472472
endif
473+
vel_stencil = max(2, obc_stencil, hor_visc_vel_stencil(CS%hor_visc))
473474
call cpu_clock_begin(id_clock_pass)
474475
call create_group_pass(CS%pass_eta, eta, G%Domain, halo=1)
475476
call create_group_pass(CS%pass_visc_rem, CS%visc_rem_u, CS%visc_rem_v, G%Domain, &
476477
To_All+SCALAR_PAIR, CGRID_NE, halo=max(1,cont_stencil))
477478
call create_group_pass(CS%pass_uvp, up, vp, G%Domain, halo=max(1,cont_stencil))
478479
call create_group_pass(CS%pass_hp_uv, hp, G%Domain, halo=2)
479-
call create_group_pass(CS%pass_hp_uv, u_av, v_av, G%Domain, halo=max(2,obc_stencil))
480-
call create_group_pass(CS%pass_hp_uv, uh(:,:,:), vh(:,:,:), G%Domain, halo=max(2,obc_stencil))
480+
call create_group_pass(CS%pass_hp_uv, u_av, v_av, G%Domain, halo=vel_stencil)
481+
call create_group_pass(CS%pass_hp_uv, uh(:,:,:), vh(:,:,:), G%Domain, halo=vel_stencil)
481482

482483
call create_group_pass(CS%pass_uv, u_inst, v_inst, G%Domain, halo=max(2,cont_stencil))
483484
call create_group_pass(CS%pass_h, h, G%Domain, halo=max(2,cont_stencil))
484-
call create_group_pass(CS%pass_av_uvh, u_av, v_av, G%Domain, halo=max(2,obc_stencil))
485-
call create_group_pass(CS%pass_av_uvh, uh(:,:,:), vh(:,:,:), G%Domain, halo=max(2,obc_stencil))
485+
call create_group_pass(CS%pass_av_uvh, u_av, v_av, G%Domain, halo=vel_stencil)
486+
call create_group_pass(CS%pass_av_uvh, uh(:,:,:), vh(:,:,:), G%Domain, halo=vel_stencil)
486487
call cpu_clock_end(id_clock_pass)
487488
!--- end set up for group halo pass
488489

src/parameterizations/lateral/MOM_hor_visc.F90

+51-24
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ module MOM_hor_visc
3131

3232
#include <MOM_memory.h>
3333

34-
public horizontal_viscosity, hor_visc_init, hor_visc_end
34+
public horizontal_viscosity, hor_visc_init, hor_visc_end, hor_visc_vel_stencil
3535

3636
!> Control structure for horizontal viscosity
3737
type, public :: hor_visc_CS ; private
@@ -1296,10 +1296,9 @@ subroutine horizontal_viscosity(u, v, h, uh, vh, diffu, diffv, MEKE, VarMix, G,
12961296
if ((CS%Smagorinsky_Ah) .or. (CS%Leith_Ah) .or. (CS%use_Leithy)) then
12971297
if (CS%Smagorinsky_Ah) then
12981298
if (CS%bound_Coriolis) then
1299-
do j=js_Kh,je_Kh ; do i=is_Kh,ie_Kh
1299+
do j=js_Kh,je_Kh ; do i=is_Kh,ie_Kh
13001300
AhSm = Shear_mag(i,j) * (CS%Biharm_const_xx(i,j) &
1301-
+ CS%Biharm_const2_xx(i,j) * Shear_mag(i,j) &
1302-
)
1301+
+ CS%Biharm_const2_xx(i,j) * Shear_mag(i,j))
13031302
Ah(i,j) = max(Ah(i,j), AhSm)
13041303
enddo ; enddo
13051304
else
@@ -1565,10 +1564,7 @@ subroutine horizontal_viscosity(u, v, h, uh, vh, diffu, diffv, MEKE, VarMix, G,
15651564

15661565
! Pass the velocity gradients and thickness to ZB2020
15671566
if (CS%use_ZB2020) then
1568-
call ZB2020_copy_gradient_and_thickness( &
1569-
sh_xx, sh_xy, vort_xy, &
1570-
hq, &
1571-
G, GV, CS%ZB2020, k)
1567+
call ZB2020_copy_gradient_and_thickness(sh_xx, sh_xy, vort_xy, hq, G, GV, CS%ZB2020, k)
15721568
endif
15731569

15741570
if (CS%Laplacian) then
@@ -1721,8 +1717,7 @@ subroutine horizontal_viscosity(u, v, h, uh, vh, diffu, diffv, MEKE, VarMix, G,
17211717
if (CS%bound_Coriolis) then
17221718
do J=js-1,Jeq ; do I=is-1,Ieq
17231719
AhSm = Shear_mag(I,J) * (CS%Biharm_const_xy(I,J) &
1724-
+ CS%Biharm_const2_xy(I,J) * Shear_mag(I,J) &
1725-
)
1720+
+ CS%Biharm_const2_xy(I,J) * Shear_mag(I,J))
17261721
Ah(I,J) = max(Ah(I,J), AhSm)
17271722
enddo ; enddo
17281723
else
@@ -1751,8 +1746,7 @@ subroutine horizontal_viscosity(u, v, h, uh, vh, diffu, diffv, MEKE, VarMix, G,
17511746
! *Add* the MEKE contribution
17521747
do J=js-1,Jeq ; do I=is-1,Ieq
17531748
Ah(I,J) = Ah(I,J) + 0.25 * ( &
1754-
(MEKE%Au(i,j) + MEKE%Au(i+1,j+1)) + (MEKE%Au(i+1,j) + MEKE%Au(i,j+1)) &
1755-
)
1749+
(MEKE%Au(i,j) + MEKE%Au(i+1,j+1)) + (MEKE%Au(i+1,j) + MEKE%Au(i,j+1)) )
17561750
enddo ; enddo
17571751
endif
17581752

@@ -2228,11 +2222,15 @@ subroutine horizontal_viscosity(u, v, h, uh, vh, diffu, diffv, MEKE, VarMix, G,
22282222

22292223
if (CS%debug) then
22302224
if (CS%Laplacian) then
2225+
! In symmetric memory mode, Kh_h should also be valid with a haloshift of 1.
22312226
call hchksum(Kh_h, "Kh_h", G%HI, haloshift=0, unscale=US%L_to_m**2*US%s_to_T)
2232-
call Bchksum(Kh_q, "Kh_q", G%HI, haloshift=0, unscale=US%L_to_m**2*US%s_to_T)
2227+
call Bchksum(Kh_q, "Kh_q", G%HI, haloshift=0, symmetric=.true., unscale=US%L_to_m**2*US%s_to_T)
2228+
endif
2229+
if (CS%biharmonic) then
2230+
! In symmetric memory mode, Ah_h should also be valid with a haloshift of 1.
2231+
call hchksum(Ah_h, "Ah_h", G%HI, haloshift=0, unscale=US%L_to_m**4*US%s_to_T)
2232+
call Bchksum(Ah_q, "Ah_q", G%HI, haloshift=0, symmetric=.true., unscale=US%L_to_m**4*US%s_to_T)
22332233
endif
2234-
if (CS%biharmonic) call hchksum(Ah_h, "Ah_h", G%HI, haloshift=0, unscale=US%L_to_m**4*US%s_to_T)
2235-
if (CS%biharmonic) call Bchksum(Ah_q, "Ah_q", G%HI, haloshift=0, unscale=US%L_to_m**4*US%s_to_T)
22362234
endif
22372235

22382236
if (CS%id_FrictWorkIntz > 0) then
@@ -2793,14 +2791,31 @@ subroutine hor_visc_init(Time, G, GV, US, param_file, diag, CS, ADp)
27932791
ALLOC_(CS%m_leithy_max(isd:ied,jsd:jed)) ; CS%m_leithy_max(:,:) = 0.0
27942792
endif
27952793
if (CS%Re_Ah > 0.0) then
2796-
ALLOC_(CS%Re_Ah_const_xx(isd:ied,jsd:jed)); CS%Re_Ah_const_xx(:,:) = 0.0
2797-
ALLOC_(CS%Re_Ah_const_xy(IsdB:IedB,JsdB:JedB)); CS%Re_Ah_const_xy(:,:) = 0.0
2794+
ALLOC_(CS%Re_Ah_const_xx(isd:ied,jsd:jed)) ; CS%Re_Ah_const_xx(:,:) = 0.0
2795+
ALLOC_(CS%Re_Ah_const_xy(IsdB:IedB,JsdB:JedB)) ; CS%Re_Ah_const_xy(:,:) = 0.0
27982796
endif
27992797
endif
28002798
do J=js-2,Jeq+1 ; do I=is-2,Ieq+1
28012799
CS%dx2q(I,J) = G%dxBu(I,J)*G%dxBu(I,J) ; CS%dy2q(I,J) = G%dyBu(I,J)*G%dyBu(I,J)
2802-
CS%DX_dyBu(I,J) = G%dxBu(I,J)*G%IdyBu(I,J) ; CS%DY_dxBu(I,J) = G%dyBu(I,J)*G%IdxBu(I,J)
28032800
enddo ; enddo
2801+
2802+
if (((CS%Leith_Kh) .or. (CS%Leith_Ah) .or. (CS%use_Leithy)) .and. &
2803+
((G%isc-G%isd < 3) .or. (G%isc-G%isd < 3))) call MOM_error(FATAL, &
2804+
"The minimum halo size is 3 when a Leith viscosity is being used.")
2805+
if (CS%use_Leithy) then
2806+
do J=js-3,Jeq+2 ; do I=is-3,Ieq+2
2807+
CS%DX_dyBu(I,J) = G%dxBu(I,J)*G%IdyBu(I,J) ; CS%DY_dxBu(I,J) = G%dyBu(I,J)*G%IdxBu(I,J)
2808+
enddo ; enddo
2809+
elseif ((CS%Leith_Kh) .or. (CS%Leith_Ah)) then
2810+
do J=Jsq-2,Jeq+2 ; do I=Isq-2,Ieq+2
2811+
CS%DX_dyBu(I,J) = G%dxBu(I,J)*G%IdyBu(I,J) ; CS%DY_dxBu(I,J) = G%dyBu(I,J)*G%IdxBu(I,J)
2812+
enddo ; enddo
2813+
else
2814+
do J=js-2,Jeq+1 ; do I=is-2,Ieq+1
2815+
CS%DX_dyBu(I,J) = G%dxBu(I,J)*G%IdyBu(I,J) ; CS%DY_dxBu(I,J) = G%dyBu(I,J)*G%IdxBu(I,J)
2816+
enddo ; enddo
2817+
endif
2818+
28042819
do j=js-2,Jeq+2 ; do i=is-2,Ieq+2
28052820
CS%dx2h(i,j) = G%dxT(i,j)*G%dxT(i,j) ; CS%dy2h(i,j) = G%dyT(i,j)*G%dyT(i,j)
28062821
CS%DX_dyT(i,j) = G%dxT(i,j)*G%IdyT(i,j) ; CS%DY_dxT(i,j) = G%dyT(i,j)*G%IdxT(i,j)
@@ -2931,12 +2946,12 @@ subroutine hor_visc_init(Time, G, GV, US, param_file, diag, CS, ADp)
29312946
endif
29322947
endif
29332948
if (CS%Leith_Ah) then
2934-
CS%biharm6_const_xx(i,j) = Leith_bi_const * (grid_sp_h3 * grid_sp_h3)
2949+
CS%biharm6_const_xx(i,j) = Leith_bi_const * (grid_sp_h3 * grid_sp_h3)
29352950
endif
29362951
if (CS%use_Leithy) then
2937-
CS%biharm6_const_xx(i,j) = Leith_bi_const * max(G%dxT(i,j),G%dyT(i,j))**6
2938-
CS%m_const_leithy(i,j) = 0.5 * sqrt(CS%c_K) * max(G%dxT(i,j),G%dyT(i,j))
2939-
CS%m_leithy_max(i,j) = 4. / max(G%dxT(i,j),G%dyT(i,j))**2
2952+
CS%biharm6_const_xx(i,j) = Leith_bi_const * max(G%dxT(i,j),G%dyT(i,j))**6
2953+
CS%m_const_leithy(i,j) = 0.5 * sqrt(CS%c_K) * max(G%dxT(i,j),G%dyT(i,j))
2954+
CS%m_leithy_max(i,j) = 4. / max(G%dxT(i,j),G%dyT(i,j))**2
29402955
endif
29412956
CS%Ah_bg_xx(i,j) = MAX(Ah, Ah_vel_scale * grid_sp_h2 * sqrt(grid_sp_h2))
29422957
if (CS%Re_Ah > 0.0) CS%Re_Ah_const_xx(i,j) = grid_sp_h3 / CS%Re_Ah
@@ -2961,12 +2976,12 @@ subroutine hor_visc_init(Time, G, GV, US, param_file, diag, CS, ADp)
29612976
endif
29622977
endif
29632978
if ((CS%Leith_Ah) .or. (CS%use_Leithy))then
2964-
CS%biharm6_const_xy(I,J) = Leith_bi_const * (grid_sp_q3 * grid_sp_q3)
2979+
CS%biharm6_const_xy(I,J) = Leith_bi_const * (grid_sp_q3 * grid_sp_q3)
29652980
endif
29662981
CS%Ah_bg_xy(I,J) = MAX(Ah, Ah_vel_scale * grid_sp_q2 * sqrt(grid_sp_q2))
29672982
if (CS%Re_Ah > 0.0) CS%Re_Ah_const_xy(i,j) = grid_sp_q3 / CS%Re_Ah
29682983
if (Ah_time_scale > 0.) CS%Ah_bg_xy(i,j) = &
2969-
MAX(CS%Ah_bg_xy(i,j), (grid_sp_q2 * grid_sp_q2) / Ah_time_scale)
2984+
MAX(CS%Ah_bg_xy(i,j), (grid_sp_q2 * grid_sp_q2) / Ah_time_scale)
29702985
if (CS%bound_Ah .and. .not.CS%better_bound_Ah) then
29712986
CS%Ah_Max_xy(I,J) = Ah_Limit * (grid_sp_q2 * grid_sp_q2)
29722987
CS%Ah_bg_xy(I,J) = MIN(CS%Ah_bg_xy(I,J), CS%Ah_Max_xy(I,J))
@@ -3250,6 +3265,18 @@ subroutine hor_visc_init(Time, G, GV, US, param_file, diag, CS, ADp)
32503265

32513266
end subroutine hor_visc_init
32523267

3268+
!> hor_visc_vel_stencil returns the horizontal viscosity input velocity stencil size
3269+
function hor_visc_vel_stencil(CS) result(stencil)
3270+
type(hor_visc_CS), intent(in) :: CS !< Control structure for horizontal viscosity
3271+
integer :: stencil !< The horizontal viscosity velocity stencil size with the current settings.
3272+
3273+
stencil = 2
3274+
3275+
if ((CS%Leith_Kh) .or. (CS%Leith_Ah) .or. (CS%use_Leithy)) then
3276+
stencil = 3
3277+
endif
3278+
end function hor_visc_vel_stencil
3279+
32533280
!> Calculates factors in the anisotropic orientation tensor to be align with the grid.
32543281
!! With n1=1 and n2=0, this recovers the approach of Large et al, 2001.
32553282
subroutine align_aniso_tensor_to_grid(CS, n1, n2)

0 commit comments

Comments
 (0)