pure subroutine fill_tracer_ghosts_zonal(hTr, h_layer, u_layer, &
nx_total, ny_total, nz, &
i_w, i_e, j_s, j_n, nghost, &
bc_w, bc_e, &
clamped_tr_w, clamped_tr_e)
!! Upwind-aware tracer ghost fill for west and east open edges.
!! West inflow : u(i_w,j,k) > 0 → ghost = clamped_tr * h_ghost
!! West outflow : u(i_w,j,k) <= 0 → ghost = interior (zero-gradient)
!! East inflow : u(i_e,j,k) < 0
!! East outflow : u(i_e,j,k) >= 0
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)
real(wp), intent(in) :: u_layer(nx_total + 1, ny_total, nz)
integer, intent(in) :: i_w, i_e, j_s, j_n
integer, intent(in) :: bc_w, bc_e
real(wp), intent(in) :: clamped_tr_w, clamped_tr_e
integer :: j, k, g
real(wp) :: hTr_bc, hTr_int
! West ghosts
if (is_open_ish(bc_w)) then
do concurrent(k=1:nz, j=j_s:j_n, g=1:nghost) local(hTr_bc, hTr_int)
! Use wall-face velocity at u_layer(i_w, j, k).
! West inflow = u > 0 (eastward into domain).
if (u_layer(i_w, j, k) > 0.0_wp) then
! Inflow: set ghost hTr = boundary concentration * ghost h
hTr_bc = clamped_tr_w*h_layer(g, j, k)
hTr(g, j, k) = hTr_bc
else
! Outflow: zero-gradient — copy interior
hTr_int = hTr(i_w, j, k)
hTr(g, j, k) = hTr_int
end if
end do
end if
! East ghosts
if (is_open_ish(bc_e)) then
do concurrent(k=1:nz, j=j_s:j_n, g=1:nghost) local(hTr_bc, hTr_int)
! East inflow = u < 0 (westward into domain from east).
if (u_layer(i_e + 1, j, k) < 0.0_wp) then
hTr_bc = clamped_tr_e*h_layer(nx_total - g + 1, j, k)
hTr(nx_total - g + 1, j, k) = hTr_bc
else
hTr_int = hTr(i_e, j, k)
hTr(nx_total - g + 1, j, k) = hTr_int
end if
end do
end if
end subroutine fill_tracer_ghosts_zonal