pure subroutine surfstress_compute_impl(h_layer, wet_mask, tau_x, tau_y, &
du_stress, dv_stress, &
rho0, h_min, nx, ny, nz)
!! Flat-array surface-stress kernel. Explicit-shape dummies so
!! NVHPC stdpar can compile the device kernel against static
!! bounds.
integer, intent(in) :: nx, ny, nz
real(wp), intent(in) :: h_layer(nx, ny, nz), wet_mask(nx, ny)
real(wp), intent(in) :: tau_x(nx + 1, ny), tau_y(nx, ny + 1)
real(wp), intent(inout) :: du_stress(nx + 1, ny, nz), dv_stress(nx, ny + 1, nz)
real(wp), intent(in) :: rho0, h_min
integer :: i, j, k
real(wp) :: inv_rho0, h_top_face
inv_rho0 = 1.0_wp/rho0
do concurrent(k=1:nz, j=1:ny, i=1:nx + 1)
du_stress(i, j, k) = 0.0_wp
end do
do concurrent(k=1:nz, j=1:ny + 1, i=1:nx)
dv_stress(i, j, k) = 0.0_wp
end do
! Face wet-mask: only apply stress at faces between two ocean
! cells. `min(wet_left, wet_right)` zeros stress at any face
! that touches land. Default mask (all 1.0) preserves the
! flat-bottom / analytical behaviour bit-identically.
do concurrent(j=1:ny, i=2:nx) local(h_top_face)
h_top_face = 0.5_wp*(h_layer(i - 1, j, nz) + h_layer(i, j, nz))
h_top_face = max(h_top_face, h_min)
du_stress(i, j, nz) = &
min(wet_mask(i - 1, j), wet_mask(i, j))* &
tau_x(i, j)*inv_rho0/h_top_face
end do
do concurrent(j=2:ny, i=1:nx) local(h_top_face)
h_top_face = 0.5_wp*(h_layer(i, j - 1, nz) + h_layer(i, j, nz))
h_top_face = max(h_top_face, h_min)
dv_stress(i, j, nz) = &
min(wet_mask(i, j - 1), wet_mask(i, j))* &
tau_y(i, j)*inv_rho0/h_top_face
end do
end subroutine surfstress_compute_impl