pure subroutine evp_str_s_relax_impl(areaT, zeta, sh_ds, mi_ratio_a_q, &
i_1pdt_t, dt_2tdamp, i_ec2, str_s, nx, ny)
!! str_s relax (:1137-1143). Corners in [1,nx+1]x[1,ny+1]; the 4
!! surrounding T-cells at an array-edge corner are handled by
!! `zeta`'s own ghost values (zero-mass ghost cells => zeta=0
!! there, contributing nothing) — no special-case branch needed.
integer, intent(in) :: nx, ny
real(wp), intent(in) :: areaT(nx, ny)
real(wp), intent(in) :: zeta(nx, ny)
real(wp), intent(in) :: sh_ds(nx + 1, ny + 1)
real(wp), intent(in) :: mi_ratio_a_q(nx + 1, ny + 1)
real(wp), intent(in) :: i_1pdt_t, dt_2tdamp, i_ec2
real(wp), intent(inout) :: str_s(nx + 1, ny + 1)
integer :: ic, jc
real(wp) :: zeta_sw, zeta_se, zeta_nw, zeta_ne, a_sw, a_se, a_nw, a_ne
real(wp) :: weighted_zeta
! Interior corners only. At an array-edge corner zeta/areaT have no
! defined 4th neighbour; these are ghost/land corners under the
! ghost policy, never read by a physical-interior momentum face, and
! str_s is left untouched there. The loop range, not an in-loop
! guard, excludes them -- see `evp_build_masks_impl` (nvfortran CPU
! vectoriser, four-way guard).
do concurrent(jc=2:ny, ic=2:nx) &
local(zeta_sw, zeta_se, zeta_nw, zeta_ne, a_sw, a_se, a_nw, a_ne, weighted_zeta)
zeta_sw = zeta(ic - 1, jc - 1)
zeta_se = zeta(ic, jc - 1)
zeta_nw = zeta(ic - 1, jc)
zeta_ne = zeta(ic, jc)
a_sw = areaT(ic - 1, jc - 1)
a_se = areaT(ic, jc - 1)
a_nw = areaT(ic - 1, jc)
a_ne = areaT(ic, jc)
weighted_zeta = ((a_sw*zeta_sw + a_ne*zeta_ne) + (a_se*zeta_se + a_nw*zeta_nw))
str_s(ic, jc) = i_1pdt_t*(str_s(ic, jc) + (i_ec2*dt_2tdamp)* &
(weighted_zeta*mi_ratio_a_q(ic, jc)*sh_ds(ic, jc)))
end do
end subroutine evp_str_s_relax_impl