pure subroutine drain_parabola_x(nx, ny, nz, wet_T, hTr, hprev, tr, aL, aR, a6)
!! Rebuild the per-cell zonal CW PPM parabola from the CURRENT Tr =
!! hTr/hprev (V2 — per pass). Interior cells (3..nx-2) use the
!! limited PPM edges; the 2-cell boundary band falls back to PCM
!! (aL=aR=Tr ⇒ swept reduces to the donor value, 1st order),
!! matching tracer_advect_zonal_one_impl's near-wall band.
!! TODO(MOM6-fidelity): MOM6 advect_tracer keeps full PPM up to the wall
!! (dropping to PCM only at genuine local extrema / zero `mask2dCu`
!! faces), so we are 1st-order in the 2 cells nearest a true WALL where
!! MOM6 is PPM-with-mask (periodic seams are fine — the wrap restores
!! full PPM). Tracked divergence; revisit if near-wall tracer
!! diffusion matters.
!! a6 = 6·Tr − 3·(aL+aR). Mirror-T at land neighbours (C2);
!! bit-identical for all-wet (`wet_T≡1`).
integer, intent(in) :: nx, ny, nz
real(wp), intent(in) :: wet_T(nx, ny)
real(wp), intent(in) :: hTr(nx, ny, nz), hprev(nx, ny, nz)
real(wp), intent(inout) :: tr(nx, ny, nz), aL(nx, ny, nz), aR(nx, ny, nz)
real(wp), intent(inout) :: a6(nx, ny, nz)
integer :: i, j, k
real(wp) :: Tr_m2, Tr_m1, Tr_0, Tr_p1, Tr_p2
real(wp) :: dh_m1, dh_0, dh_p1, Tr_left, Tr_right
! Concentration field (guard zero thickness).
do concurrent(k=1:nz, j=1:ny, i=1:nx)
tr(i, j, k) = hTr(i, j, k)/max(hprev(i, j, k), DRAIN_MIN_H)
end do
! Interior PPM parabola.
do concurrent(k=1:nz, j=1:ny, i=3:nx - 2) &
local(Tr_m2, Tr_m1, Tr_0, Tr_p1, Tr_p2, dh_m1, dh_0, dh_p1, Tr_left, Tr_right)
Tr_0 = tr(i, j, k)
Tr_m1 = ppm_mirror_h(tr(i - 1, j, k), Tr_0, wet_T(i - 1, j))
Tr_p1 = ppm_mirror_h(tr(i + 1, j, k), Tr_0, wet_T(i + 1, j))
Tr_m2 = ppm_mirror_h(tr(i - 2, j, k), Tr_m1, wet_T(i - 2, j))
Tr_p2 = ppm_mirror_h(tr(i + 2, j, k), Tr_p1, wet_T(i + 2, j))
call ppm_limited_slope(Tr_m2, Tr_m1, Tr_0, dh_m1)
call ppm_limited_slope(Tr_m1, Tr_0, Tr_p1, dh_0)
call ppm_limited_slope(Tr_0, Tr_p1, Tr_p2, dh_p1)
dh_0 = dh_0*wet_T(i - 1, j)*wet_T(i, j)*wet_T(i + 1, j)
Tr_left = 0.5_wp*(Tr_m1 + Tr_0) - (dh_0 - dh_m1)/6.0_wp
Tr_right = 0.5_wp*(Tr_0 + Tr_p1) - (dh_p1 - dh_0)/6.0_wp
call ppm_cell_limiter(Tr_0, Tr_left, Tr_right)
aL(i, j, k) = Tr_left
aR(i, j, k) = Tr_right
a6(i, j, k) = 6.0_wp*Tr_0 - 3.0_wp*(Tr_left + Tr_right)
end do
! Boundary band (i=1,2 and nx-1,nx): PCM donor (aL=aR=Tr, a6=0).
do concurrent(k=1:nz, j=1:ny, i=1:nx)
if (i <= 2 .or. i >= nx - 1) then
aL(i, j, k) = tr(i, j, k)
aR(i, j, k) = tr(i, j, k)
a6(i, j, k) = 0.0_wp
end if
end do
end subroutine drain_parabola_x