pure subroutine fill_tracer_ghosts_zerograd(hTr, h_layer, nx_total, ny_total, nz, &
i_w, i_e, j_s, j_n, nghost, &
bc_w, bc_e, bc_s, bc_n)
!! Zero-gradient CONCENTRATION fill of a tracer's hTr ghosts at open-ish
!! edges over the FULL cross-extent (ghost×ghost corners included):
!! hTr_ghost = (hTr_int / h_int) * h_ghost. Runs BEFORE the upwind-aware
!! per-edge fill, so corners keep this zero-gradient value (no corner T/S
!! blow-up under inflow). Same gating/corner coverage as fill_h_layer_ghosts.
integer, intent(in) :: nx_total, ny_total, nz, nghost
real(wp), intent(inout) :: hTr(nx_total, ny_total, nz)
real(wp), intent(in) :: h_layer(nx_total, ny_total, nz)
integer, intent(in) :: i_w, i_e, j_s, j_n
integer, intent(in) :: bc_w, bc_e, bc_s, bc_n
integer :: i, j, k, g
! West / East over the full j extent (covers corner rows).
if (is_open_ish(bc_w)) then
do concurrent(k=1:nz, j=1:ny_total, g=1:nghost)
hTr(g, j, k) = (hTr(i_w, j, k)/max(h_layer(i_w, j, k), H_VANISHED))*h_layer(g, j, k)
end do
end if
if (is_open_ish(bc_e)) then
do concurrent(k=1:nz, j=1:ny_total, g=1:nghost)
hTr(nx_total - g + 1, j, k) = &
(hTr(i_e, j, k)/max(h_layer(i_e, j, k), H_VANISHED))*h_layer(nx_total - g + 1, j, k)
end do
end if
! South / North over the full i extent (reads the x-filled corner cols).
if (is_open_ish(bc_s)) then
do concurrent(k=1:nz, j=1:nghost, i=1:nx_total)
hTr(i, j, k) = (hTr(i, j_s, k)/max(h_layer(i, j_s, k), H_VANISHED))*h_layer(i, j, k)
end do
end if
if (is_open_ish(bc_n)) then
do concurrent(k=1:nz, g=1:nghost, i=1:nx_total)
hTr(i, ny_total - g + 1, k) = &
(hTr(i, j_n, k)/max(h_layer(i, j_n, k), H_VANISHED))*h_layer(i, ny_total - g + 1, k)
end do
end if
end subroutine fill_tracer_ghosts_zerograd