Skip to content

Commit a3fd1f3

Browse files
Hallberg-NOAAmarshallward
authored andcommitted
+Rotationally symmetric epipycnal diffusion option
Added the option to do epipycnal tracer diffusion between a bulk mixed layer and the interior ocean with expressions that satisfy rotational symmetry. This option is enabled by setting the new runtime parameter HOR_DIFF_ANSWER_DATE to be greater than 20240330. By default, this parameter is set to use the previous expressions, although the default may be changed later to follow DEFAULT_ANSWER_DATE. Also corrected two bugs with the tracer limits used to repartition the fluxes between layers within tracer_epipycnal_ML_diff; this correction is enables by setting the new HOR_DIFF_LIMIT_BUG to .false., but to retain previous answers by default it is set to true. By default all answers are bitwise identical, but there are changes to some MOM_parameter_doc files due to the introduction of two new runtime parameters.
1 parent f9372f3 commit a3fd1f3

1 file changed

Lines changed: 149 additions & 68 deletions

File tree

src/tracer/MOM_tracer_hor_diff.F90

Lines changed: 149 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,14 @@ module MOM_tracer_hor_diff
6565
!! tracer_hor_diff.
6666
logical :: recalc_neutral_surf !< If true, recalculate the neutral surfaces if CFL has been
6767
!! exceeded
68+
logical :: limit_bug !< If true and the answer date is 20240330 or below, use a
69+
!! rotational symmetry breaking bug when limiting the tracer
70+
!! properties in tracer_epipycnal_ML_diff.
71+
integer :: answer_date !< The vintage of the order of arithmetic to use for the tracer
72+
!! diffusion. Values of 20240330 or below recover the answers
73+
!! from the original form of this code, while higher values use
74+
!! mathematically equivalent expressions that recover rotational symmetry
75+
!! when DIFFUSE_ML_TO_INTERIOR is true.
6876
type(neutral_diffusion_CS), pointer :: neutral_diffusion_CSp => NULL() !< Control structure for neutral diffusion.
6977
type(hbd_CS), pointer :: hor_bnd_diffusion_CSp => NULL() !< Control structure for
7078
!! horizontal boundary diffusion.
@@ -678,7 +686,7 @@ subroutine tracer_epipycnal_ML_diff(h, dt, Tr, ntr, khdt_epi_x, khdt_epi_y, G, &
678686
real, dimension(SZI_(G),SZJB_(G)), intent(in) :: khdt_epi_y !< Meridional epipycnal diffusivity times
679687
!! a time step and the ratio of the open face width over
680688
!! the distance between adjacent tracer points [L2 ~> m2]
681-
type(unit_scale_type), intent(in) :: US !< A dimensional unit scaling type
689+
type(unit_scale_type), intent(in) :: US !< A dimensional unit scaling type
682690
type(tracer_hor_diff_CS), intent(inout) :: CS !< module control structure
683691
type(thermo_var_ptrs), intent(in) :: tv !< thermodynamic structure
684692
integer, intent(in) :: num_itts !< number of iterations (usually=1)
@@ -706,13 +714,16 @@ subroutine tracer_epipycnal_ML_diff(h, dt, Tr, ntr, khdt_epi_x, khdt_epi_y, G, &
706714
k0b_Lv, k0a_Lv, & ! The original k-indices of the layers that participate
707715
k0b_Rv, k0a_Rv ! in each pair of mixing at v-faces.
708716

709-
!### Accumulating the converge into this array one face at a time may lead to a lack of rotational symmetry.
710-
real, dimension(SZI_(G), SZJ_(G), SZK_(GV)) :: &
711-
tr_flux_conv ! The flux convergence of tracers [conc H L2 ~> conc m3 or conc kg]
717+
real, dimension(SZI_(G),SZJ_(G),SZK_(GV)) :: &
718+
tr_flux_N, & ! The tracer flux through the northern face [conc H L2 ~> conc m3 or conc kg]
719+
tr_flux_S, & ! The tracer flux through the southern face [conc H L2 ~> conc m3 or conc kg]
720+
tr_flux_E, & ! The tracer flux through the eastern face [conc H L2 ~> conc m3 or conc kg]
721+
tr_flux_W, & ! The tracer flux through the western face [conc H L2 ~> conc m3 or conc kg]
722+
tr_flux_conv ! The flux convergence of tracers [conc H L2 ~> conc m3 or conc kg]
712723

713724
! The following 3-d arrays were created in 2014 in MOM6 PR#12 to facilitate openMP threading
714-
! on an i-loop, which might have been ill advised. The k-size extents here might also be problematic.
715-
real, dimension(SZI_(G),SZJB_(G),SZK_(GV)) :: &
725+
! on an i-loop, which might have been ill advised.
726+
real, dimension(SZI_(G),SZJB_(G),SZK_(GV)*2) :: &
716727
Tr_flux_3d, & ! The tracer flux through pairings at meridional faces [conc H L2 ~> conc m3 or conc kg]
717728
Tr_adj_vert_L, & ! Vertical adjustments to which layer the fluxes go into in the southern
718729
! columns at meridional face [conc H L2 ~> conc m3 or conc kg]
@@ -815,6 +826,7 @@ subroutine tracer_epipycnal_ML_diff(h, dt, Tr, ntr, khdt_epi_x, khdt_epi_y, G, &
815826
do k=2,nkmb ; do j=js-2,je+2 ; do i=is-2,ie+2
816827
if (Rml_max(i,j) < rho_coord(i,j,k)) Rml_max(i,j) = rho_coord(i,j,k)
817828
enddo ; enddo ; enddo
829+
818830
! Use bracketing and bisection to find the k-level that the densest of the
819831
! mixed and buffer layer corresponds to, such that:
820832
! GV%Rlay(max_kRho-1) < Rml_max <= GV%Rlay(max_kRho)
@@ -1191,12 +1203,7 @@ subroutine tracer_epipycnal_ML_diff(h, dt, Tr, ntr, khdt_epi_x, khdt_epi_y, G, &
11911203

11921204
endif ; enddo ; enddo ! i- & j- loops over meridional faces.
11931205

1194-
! The tracer-specific calculations start here.
1195-
1196-
! Zero out tracer tendencies.
1197-
do k=1,PEmax_kRho ; do j=js-1,je+1 ; do i=is-1,ie+1
1198-
tr_flux_conv(i,j,k) = 0.0
1199-
enddo ; enddo ; enddo
1206+
! The tracer-specific calculations start here.
12001207

12011208
do itt=1,max_itt
12021209

@@ -1205,12 +1212,19 @@ subroutine tracer_epipycnal_ML_diff(h, dt, Tr, ntr, khdt_epi_x, khdt_epi_y, G, &
12051212
endif
12061213

12071214
do m=1,ntr
1208-
!$OMP parallel do default(none) shared(is,ie,js,je,G,Tr,nkmb,nPu,m,max_kRho,nz,h,h_exclude, &
1209-
!$OMP k0b_Lu,k0b_Ru,deep_wt_Lu,k0a_Lu,deep_wt_Ru,k0a_Ru, &
1210-
!$OMP hP_Lu,hP_Ru,I_maxitt,khdt_epi_x,tr_flux_conv,Idt) &
1211-
!$OMP private(Tr_min_face,Tr_max_face,kLa,kLb,kRa,kRb,Tr_La, &
1212-
!$OMP Tr_Lb,Tr_Ra,Tr_Rb,Tr_av_L,wt_b,Tr_av_R,h_L,h_R, &
1213-
!$OMP Tr_flux,Tr_adj_vert,wt_a,vol)
1215+
! Zero out tracer tendencies.
1216+
if (CS%answer_date <= 20240330) then
1217+
tr_flux_conv(:,:,:) = 0.0
1218+
else
1219+
tr_flux_N(:,:,:) = 0.0 ; tr_flux_S(:,:,:) = 0.0
1220+
tr_flux_E(:,:,:) = 0.0 ; tr_flux_W(:,:,:) = 0.0
1221+
endif
1222+
tr_flux_3d(:,:,:) = 0.0
1223+
tr_adj_vert_R(:,:,:) = 0.0 ; tr_adj_vert_L(:,:,:) = 0.0
1224+
1225+
!$OMP parallel do default(shared) private(Tr_min_face,Tr_max_face,kLa,kLb,kRa,kRb,Tr_La, &
1226+
!$OMP Tr_Lb,Tr_Ra,Tr_Rb,Tr_av_L,wt_b,Tr_av_R,h_L,h_R, &
1227+
!$OMP Tr_flux,Tr_adj_vert,wt_a,vol)
12141228
do j=js,je ; do I=is-1,ie ; if (G%mask2dCu(I,j) > 0.0) then
12151229
! Determine the fluxes through the zonal faces.
12161230

@@ -1230,7 +1244,11 @@ subroutine tracer_epipycnal_ML_diff(h, dt, Tr, ntr, khdt_epi_x, khdt_epi_y, G, &
12301244
kRb = kRa ; if (max_kRho(i+1,j) < nz) kRb = max_kRho(i+1,j)+1
12311245
Tr_La = Tr_min_face ; Tr_Lb = Tr_La ; Tr_Ra = Tr_La ; Tr_Rb = Tr_La
12321246
if (h(i,j,kLa) > h_exclude) Tr_La = Tr(m)%t(i,j,kLa)
1233-
if (h(i,j,kLb) > h_exclude) Tr_La = Tr(m)%t(i,j,kLb)
1247+
if ((CS%answer_date <= 20240330) .and. CS%limit_bug) then
1248+
if (h(i,j,kLb) > h_exclude) Tr_La = Tr(m)%t(i,j,kLb)
1249+
else
1250+
if (h(i,j,kLb) > h_exclude) Tr_Lb = Tr(m)%t(i,j,kLb)
1251+
endif
12341252
if (h(i+1,j,kRa) > h_exclude) Tr_Ra = Tr(m)%t(i+1,j,kRa)
12351253
if (h(i+1,j,kRb) > h_exclude) Tr_Rb = Tr(m)%t(i+1,j,kRb)
12361254
Tr_min_face = min(Tr_min_face, Tr_La, Tr_Lb, Tr_Ra, Tr_Rb)
@@ -1264,12 +1282,20 @@ subroutine tracer_epipycnal_ML_diff(h, dt, Tr, ntr, khdt_epi_x, khdt_epi_y, G, &
12641282
endif
12651283

12661284
h_L = hP_Lu(j)%p(I,k) ; h_R = hP_Ru(j)%p(I,k)
1267-
Tr_flux = I_maxitt * khdt_epi_x(I,j) * (Tr_av_L - Tr_av_R) * &
1268-
((2.0 * h_L * h_R) / (h_L + h_R))
1269-
1285+
if (CS%answer_date <= 20240330) then
1286+
Tr_flux = I_maxitt * khdt_epi_x(I,j) * (Tr_av_L - Tr_av_R) * &
1287+
((2.0 * h_L * h_R) / (h_L + h_R))
1288+
else
1289+
Tr_flux = I_maxitt * ((2.0 * h_L * h_R) / (h_L + h_R)) * &
1290+
khdt_epi_x(I,j) * (Tr_av_L - Tr_av_R)
1291+
endif
12701292

12711293
if (deep_wt_Lu(j)%p(I,k) >= 1.0) then
1272-
tr_flux_conv(i,j,kLb) = tr_flux_conv(i,j,kLb) - Tr_flux
1294+
if (CS%answer_date <= 20240330) then
1295+
tr_flux_conv(i,j,kLb) = tr_flux_conv(i,j,kLb) - Tr_flux
1296+
else
1297+
tr_flux_E(i,j,kLb) = tr_flux_E(i,j,kLb) + Tr_flux
1298+
endif
12731299
else
12741300
Tr_adj_vert = 0.0
12751301
wt_b = deep_wt_Lu(j)%p(I,k) ; wt_a = 1.0 - wt_b
@@ -1299,12 +1325,21 @@ subroutine tracer_epipycnal_ML_diff(h, dt, Tr, ntr, khdt_epi_x, khdt_epi_y, G, &
12991325
endif
13001326
endif
13011327

1302-
tr_flux_conv(i,j,kLa) = tr_flux_conv(i,j,kLa) - (wt_a*Tr_flux + Tr_adj_vert)
1303-
tr_flux_conv(i,j,kLb) = tr_flux_conv(i,j,kLb) - (wt_b*Tr_flux - Tr_adj_vert)
1328+
if (CS%answer_date <= 20240330) then
1329+
tr_flux_conv(i,j,kLa) = tr_flux_conv(i,j,kLa) - (wt_a*Tr_flux + Tr_adj_vert)
1330+
tr_flux_conv(i,j,kLb) = tr_flux_conv(i,j,kLb) - (wt_b*Tr_flux - Tr_adj_vert)
1331+
else
1332+
tr_flux_E(i,j,kLa) = tr_flux_E(i,j,kLa) + (wt_a*Tr_flux + Tr_adj_vert)
1333+
tr_flux_E(i,j,kLb) = tr_flux_E(i,j,kLb) + (wt_b*Tr_flux - Tr_adj_vert)
1334+
endif
13041335
endif
13051336

13061337
if (deep_wt_Ru(j)%p(I,k) >= 1.0) then
1307-
tr_flux_conv(i+1,j,kRb) = tr_flux_conv(i+1,j,kRb) + Tr_flux
1338+
if (CS%answer_date <= 20240330) then
1339+
tr_flux_conv(i+1,j,kRb) = tr_flux_conv(i+1,j,kRb) + Tr_flux
1340+
else
1341+
tr_flux_W(i+1,j,kRb) = tr_flux_W(i+1,j,kRb) + Tr_flux
1342+
endif
13081343
else
13091344
Tr_adj_vert = 0.0
13101345
wt_b = deep_wt_Ru(j)%p(I,k) ; wt_a = 1.0 - wt_b
@@ -1334,23 +1369,22 @@ subroutine tracer_epipycnal_ML_diff(h, dt, Tr, ntr, khdt_epi_x, khdt_epi_y, G, &
13341369
endif
13351370
endif
13361371

1337-
tr_flux_conv(i+1,j,kRa) = tr_flux_conv(i+1,j,kRa) + &
1338-
(wt_a*Tr_flux - Tr_adj_vert)
1339-
tr_flux_conv(i+1,j,kRb) = tr_flux_conv(i+1,j,kRb) + &
1340-
(wt_b*Tr_flux + Tr_adj_vert)
1372+
if (CS%answer_date <= 20240330) then
1373+
tr_flux_conv(i+1,j,kRa) = tr_flux_conv(i+1,j,kRa) + (wt_a*Tr_flux - Tr_adj_vert)
1374+
tr_flux_conv(i+1,j,kRb) = tr_flux_conv(i+1,j,kRb) + (wt_b*Tr_flux + Tr_adj_vert)
1375+
else
1376+
tr_flux_W(i+1,j,kRa) = tr_flux_W(i+1,j,kRa) + (wt_a*Tr_flux - Tr_adj_vert)
1377+
tr_flux_W(i+1,j,kRb) = tr_flux_W(i+1,j,kRb) + (wt_b*Tr_flux + Tr_adj_vert)
1378+
endif
13411379
endif
13421380
if (associated(Tr(m)%df2d_x)) &
13431381
Tr(m)%df2d_x(I,j) = Tr(m)%df2d_x(I,j) + Tr_flux * Idt
13441382
enddo ! Loop over pairings at faces.
13451383
endif ; enddo ; enddo ! i- & j- loops over zonal faces.
13461384

1347-
!$OMP parallel do default(none) shared(is,ie,js,je,G,Tr,nkmb,nPv,m,max_kRho,nz,h,h_exclude, &
1348-
!$OMP k0b_Lv,k0b_Rv,deep_wt_Lv,k0a_Lv,deep_wt_Rv,k0a_Rv, &
1349-
!$OMP hP_Lv,hP_Rv,I_maxitt,khdt_epi_y,Tr_flux_3d, &
1350-
!$OMP Tr_adj_vert_L,Tr_adj_vert_R,Idt) &
1351-
!$OMP private(Tr_min_face,Tr_max_face,kLa,kLb,kRa,kRb, &
1352-
!$OMP Tr_La,Tr_Lb,Tr_Ra,Tr_Rb,Tr_av_L,wt_b,Tr_av_R, &
1353-
!$OMP h_L,h_R,Tr_flux,Tr_adj_vert,wt_a,vol)
1385+
!$OMP parallel do default(shared) private(Tr_min_face,Tr_max_face,kLa,kLb,kRa,kRb, &
1386+
!$OMP Tr_La,Tr_Lb,Tr_Ra,Tr_Rb,Tr_av_L,wt_b,Tr_av_R, &
1387+
!$OMP h_L,h_R,Tr_flux,Tr_adj_vert,wt_a,vol)
13541388
do J=js-1,je ; do i=is,ie ; if (G%mask2dCv(i,J) > 0.0) then
13551389
! Determine the fluxes through the meridional faces.
13561390

@@ -1370,7 +1404,11 @@ subroutine tracer_epipycnal_ML_diff(h, dt, Tr, ntr, khdt_epi_x, khdt_epi_y, G, &
13701404
kRb = kRa ; if (max_kRho(i,j+1) < nz) kRb = max_kRho(i,j+1)+1
13711405
Tr_La = Tr_min_face ; Tr_Lb = Tr_La ; Tr_Ra = Tr_La ; Tr_Rb = Tr_La
13721406
if (h(i,j,kLa) > h_exclude) Tr_La = Tr(m)%t(i,j,kLa)
1373-
if (h(i,j,kLb) > h_exclude) Tr_La = Tr(m)%t(i,j,kLb)
1407+
if ((CS%answer_date <= 20240330) .and. CS%limit_bug) then
1408+
if (h(i,j,kLb) > h_exclude) Tr_La = Tr(m)%t(i,j,kLb)
1409+
else
1410+
if (h(i,j,kLb) > h_exclude) Tr_Lb = Tr(m)%t(i,j,kLb)
1411+
endif
13741412
if (h(i,j+1,kRa) > h_exclude) Tr_Ra = Tr(m)%t(i,j+1,kRa)
13751413
if (h(i,j+1,kRb) > h_exclude) Tr_Rb = Tr(m)%t(i,j+1,kRb)
13761414
Tr_min_face = min(Tr_min_face, Tr_La, Tr_Lb, Tr_Ra, Tr_Rb)
@@ -1464,42 +1502,69 @@ subroutine tracer_epipycnal_ML_diff(h, dt, Tr, ntr, khdt_epi_x, khdt_epi_y, G, &
14641502
Tr(m)%df2d_y(i,J) = Tr(m)%df2d_y(i,J) + Tr_flux * Idt
14651503
enddo ! Loop over pairings at faces.
14661504
endif ; enddo ; enddo ! i- & j- loops over meridional faces.
1467-
!$OMP parallel do default(none) shared(is,ie,js,je,G,nPv,k0b_Lv,k0b_Rv,deep_wt_Lv, &
1468-
!$OMP tr_flux_conv,Tr_flux_3d,k0a_Lv,Tr_adj_vert_L,&
1469-
!$OMP deep_wt_Rv,k0a_Rv,Tr_adj_vert_R) &
1470-
!$OMP private(kLa,kLb,kRa,kRb,wt_b,wt_a)
1471-
do i=is,ie ; do J=js-1,je ; if (G%mask2dCv(i,J) > 0.0) then
1505+
1506+
!$OMP parallel do default(shared) private(kLa,kLb,kRa,kRb,wt_b,wt_a)
1507+
do J=js-1,je ; do i=is,ie ; if (G%mask2dCv(i,J) > 0.0) then
14721508
! The non-stride-1 loop order here is to facilitate openMP threading. However, it might be
14731509
! suboptimal when openMP threading is not used, at which point it might be better to fuse
1474-
! these loope with those that precede it and thereby eliminate the need for three 3-d arrays.
1475-
do k=1,nPv(i,J)
1476-
kLb = k0b_Lv(J)%p(i,k); kRb = k0b_Rv(J)%p(i,k)
1477-
if (deep_wt_Lv(J)%p(i,k) >= 1.0) then
1478-
tr_flux_conv(i,j,kLb) = tr_flux_conv(i,j,kLb) - Tr_flux_3d(i,J,k)
1479-
else
1480-
kLa = k0a_Lv(J)%p(i,k)
1481-
wt_b = deep_wt_Lv(J)%p(i,k) ; wt_a = 1.0 - wt_b
1482-
tr_flux_conv(i,j,kLa) = tr_flux_conv(i,j,kLa) - (wt_a*Tr_flux_3d(i,J,k) + Tr_adj_vert_L(i,J,k))
1483-
tr_flux_conv(i,j,kLb) = tr_flux_conv(i,j,kLb) - (wt_b*Tr_flux_3d(i,J,k) - Tr_adj_vert_L(i,J,k))
1484-
endif
1485-
if (deep_wt_Rv(J)%p(i,k) >= 1.0) then
1486-
tr_flux_conv(i,j+1,kRb) = tr_flux_conv(i,j+1,kRb) + Tr_flux_3d(i,J,k)
1487-
else
1488-
kRa = k0a_Rv(J)%p(i,k)
1489-
wt_b = deep_wt_Rv(J)%p(i,k) ; wt_a = 1.0 - wt_b
1490-
tr_flux_conv(i,j+1,kRa) = tr_flux_conv(i,j+1,kRa) + &
1491-
(wt_a*Tr_flux_3d(i,J,k) - Tr_adj_vert_R(i,J,k))
1492-
tr_flux_conv(i,j+1,kRb) = tr_flux_conv(i,j+1,kRb) + &
1493-
(wt_b*Tr_flux_3d(i,J,k) + Tr_adj_vert_R(i,J,k))
1494-
endif
1495-
enddo
1510+
! this loop with those that precede it and thereby eliminate the need for three 3-d arrays.
1511+
if (CS%answer_date <= 20240330) then
1512+
do k=1,nPv(i,J)
1513+
kLb = k0b_Lv(J)%p(i,k); kRb = k0b_Rv(J)%p(i,k)
1514+
if (deep_wt_Lv(J)%p(i,k) >= 1.0) then
1515+
tr_flux_conv(i,j,kLb) = tr_flux_conv(i,j,kLb) - Tr_flux_3d(i,J,k)
1516+
else
1517+
kLa = k0a_Lv(J)%p(i,k)
1518+
wt_b = deep_wt_Lv(J)%p(i,k) ; wt_a = 1.0 - wt_b
1519+
tr_flux_conv(i,j,kLa) = tr_flux_conv(i,j,kLa) - (wt_a*Tr_flux_3d(i,J,k) + Tr_adj_vert_L(i,J,k))
1520+
tr_flux_conv(i,j,kLb) = tr_flux_conv(i,j,kLb) - (wt_b*Tr_flux_3d(i,J,k) - Tr_adj_vert_L(i,J,k))
1521+
endif
1522+
if (deep_wt_Rv(J)%p(i,k) >= 1.0) then
1523+
tr_flux_conv(i,j+1,kRb) = tr_flux_conv(i,j+1,kRb) + Tr_flux_3d(i,J,k)
1524+
else
1525+
kRa = k0a_Rv(J)%p(i,k)
1526+
wt_b = deep_wt_Rv(J)%p(i,k) ; wt_a = 1.0 - wt_b
1527+
tr_flux_conv(i,j+1,kRa) = tr_flux_conv(i,j+1,kRa) + &
1528+
(wt_a*Tr_flux_3d(i,J,k) - Tr_adj_vert_R(i,J,k))
1529+
tr_flux_conv(i,j+1,kRb) = tr_flux_conv(i,j+1,kRb) + &
1530+
(wt_b*Tr_flux_3d(i,J,k) + Tr_adj_vert_R(i,J,k))
1531+
endif
1532+
enddo
1533+
else
1534+
do k=1,nPv(i,J)
1535+
kLb = k0b_Lv(J)%p(i,k); kRb = k0b_Rv(J)%p(i,k)
1536+
if (deep_wt_Lv(J)%p(i,k) >= 1.0) then
1537+
tr_flux_N(i,j,kLb) = tr_flux_N(i,j,kLb) + Tr_flux_3d(i,J,k)
1538+
else
1539+
kLa = k0a_Lv(J)%p(i,k)
1540+
wt_b = deep_wt_Lv(J)%p(i,k) ; wt_a = 1.0 - wt_b
1541+
tr_flux_N(i,j,kLa) = tr_flux_N(i,j,kLa) + (wt_a*Tr_flux_3d(i,J,k) + Tr_adj_vert_L(i,J,k))
1542+
tr_flux_N(i,j,kLb) = tr_flux_N(i,j,kLb) + (wt_b*Tr_flux_3d(i,J,k) - Tr_adj_vert_L(i,J,k))
1543+
endif
1544+
if (deep_wt_Rv(J)%p(i,k) >= 1.0) then
1545+
tr_flux_S(i,j+1,kRb) = tr_flux_S(i,j+1,kRb) + Tr_flux_3d(i,J,k)
1546+
else
1547+
kRa = k0a_Rv(J)%p(i,k)
1548+
wt_b = deep_wt_Rv(J)%p(i,k) ; wt_a = 1.0 - wt_b
1549+
tr_flux_S(i,j+1,kRa) = tr_flux_S(i,j+1,kRa) + (wt_a*Tr_flux_3d(i,J,k) - Tr_adj_vert_R(i,J,k))
1550+
tr_flux_S(i,j+1,kRb) = tr_flux_S(i,j+1,kRb) + (wt_b*Tr_flux_3d(i,J,k) + Tr_adj_vert_R(i,J,k))
1551+
endif
1552+
enddo
1553+
endif
14961554
endif ; enddo ; enddo
1555+
1556+
if (CS%answer_date >= 20240331) then
1557+
!$OMP parallel do default(shared)
1558+
do k=1,PEmax_kRho ; do j=js,je ; do i=is,ie
1559+
tr_flux_conv(i,j,k) = ((tr_flux_W(i,j,k) - tr_flux_E(i,j,k)) + &
1560+
(tr_flux_S(i,j,k) - tr_flux_N(i,j,k)))
1561+
enddo ; enddo ; enddo
1562+
endif
1563+
14971564
!$OMP parallel do default(shared)
14981565
do k=1,PEmax_kRho ; do j=js,je ; do i=is,ie
14991566
if ((G%mask2dT(i,j) > 0.0) .and. (h(i,j,k) > 0.0)) then
1500-
Tr(m)%t(i,j,k) = Tr(m)%t(i,j,k) + tr_flux_conv(i,j,k) / &
1501-
(h(i,j,k)*G%areaT(i,j))
1502-
tr_flux_conv(i,j,k) = 0.0
1567+
Tr(m)%t(i,j,k) = Tr(m)%t(i,j,k) + tr_flux_conv(i,j,k) / (h(i,j,k)*G%areaT(i,j))
15031568
endif
15041569
enddo ; enddo ; enddo
15051570

@@ -1546,6 +1611,7 @@ subroutine tracer_hor_diff_init(Time, G, GV, US, param_file, diag, EOS, diabatic
15461611
! This include declares and sets the variable "version".
15471612
# include "version_variable.h"
15481613
character(len=40) :: mdl = "MOM_tracer_hor_diff" ! This module's name.
1614+
integer :: default_answer_date
15491615

15501616
if (associated(CS)) then
15511617
call MOM_error(WARNING, "tracer_hor_diff_init called with associated control structure.")
@@ -1604,6 +1670,21 @@ subroutine tracer_hor_diff_init(Time, G, GV, US, param_file, diag, EOS, diabatic
16041670
"If true, then recalculate the neutral surfaces if the \n"//&
16051671
"diffusive CFL is exceeded. If false, assume that the \n"//&
16061672
"positions of the surfaces do not change \n", default=.false.)
1673+
call get_param(param_file, mdl, "DEFAULT_ANSWER_DATE", default_answer_date, &
1674+
"This sets the default value for the various _ANSWER_DATE parameters.", &
1675+
default=99991231, do_not_log=.true.)
1676+
call get_param(param_file, mdl, "HOR_DIFF_ANSWER_DATE", CS%answer_date, &
1677+
"The vintage of the order of arithmetic to use for the tracer diffusion. "//&
1678+
"Values of 20240330 or below recover the answers from the original form of the "//&
1679+
"along-isopycnal mixed layer to interior mixing code, while higher values use "//&
1680+
"mathematically equivalent expressions that recover rotational symmetry "//&
1681+
"when DIFFUSE_ML_TO_INTERIOR is true.", &
1682+
default=20240101, do_not_log=.not.CS%Diffuse_ML_interior)
1683+
!### Change the default later to default_answer_date.
1684+
call get_param(param_file, mdl, "HOR_DIFF_LIMIT_BUG", CS%limit_bug, &
1685+
"If true and the answer date is 20240330 or below, use a rotational symmetry "//&
1686+
"breaking bug when limiting the tracer properties in tracer_epipycnal_ML_diff.", &
1687+
default=.true., do_not_log=((.not.CS%Diffuse_ML_interior).or.(CS%answer_date>=20240331)))
16071688
CS%ML_KhTR_scale = 1.0
16081689
if (CS%Diffuse_ML_interior) then
16091690
call get_param(param_file, mdl, "ML_KHTR_SCALE", CS%ML_KhTR_scale, &

0 commit comments

Comments
 (0)