pure subroutine drain_limit_x(nx, ny, nz, areaT, h_min, uhr_x, hprev, uhh_x)
!! MOM6 hup/hlos/min_h two-test limiter on the zonal face transport
!! (volume units). Face i between cell (i-1) and cell (i).
!! Positive flow (uhr_x(i) > 0), donor = cell (i-1):
!! hup = areaT(i-1)·hprev(i-1) − areaT(i-1)·min_h
!! hlos = max(0, −uhr_x(i-1)) (already-committed outflow via the
!! donor's OTHER (west) face)
!! cap when (hup−hlos)−uhr < 0 AND 0.5·hup−uhr < 0.
!! Negative flow mirror, donor = cell (i).
integer, intent(in) :: nx, ny, nz
real(wp), intent(in) :: areaT(nx, ny)
real(wp), intent(in) :: h_min
real(wp), intent(in) :: uhr_x(nx + 1, ny, nz)
real(wp), intent(in) :: hprev(nx, ny, nz)
real(wp), intent(inout) :: uhh_x(nx + 1, ny, nz)
integer :: i, j, k
real(wp) :: uhr, hup, hlos
! Interior faces 2..nx (each has a left cell i-1 and right cell i).
do concurrent(k=1:nz, j=1:ny, i=2:nx) local(uhr, hup, hlos)
uhr = uhr_x(i, j, k)
if (uhr > 0.0_wp) then
hup = areaT(i - 1, j)*hprev(i - 1, j, k) - areaT(i - 1, j)*h_min
hlos = max(0.0_wp, -uhr_x(i - 1, j, k))
if (((hup - hlos) - uhr < 0.0_wp) .and. (0.5_wp*hup - uhr < 0.0_wp)) then
uhh_x(i, j, k) = max(0.0_wp, max(0.5_wp*hup, hup - hlos))
else
uhh_x(i, j, k) = uhr
end if
else if (uhr < 0.0_wp) then
hup = areaT(i, j)*hprev(i, j, k) - areaT(i, j)*h_min
hlos = max(0.0_wp, uhr_x(i + 1, j, k))
if (((hup - hlos) + uhr < 0.0_wp) .and. (0.5_wp*hup + uhr < 0.0_wp)) then
uhh_x(i, j, k) = -max(0.0_wp, max(0.5_wp*hup, hup - hlos))
else
uhh_x(i, j, k) = uhr
end if
else
uhh_x(i, j, k) = 0.0_wp
end if
end do
! Boundary faces 1 and nx+1: no interior donor on one side ⇒ no flux.
do concurrent(k=1:nz, j=1:ny)
uhh_x(1, j, k) = 0.0_wp
uhh_x(nx + 1, j, k) = 0.0_wp
end do
end subroutine drain_limit_x