@@ -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