pure subroutine gm_clamp_khth(nx, ny, dt, khth, khth_max_cfl, use_ext, &
khth_ext_u, khth_ext_v, idxCu, idyCu, &
idxCv, idyCv, wet_u, wet_v, khth_u, khth_v)
!! Fill the 2D face KhTh fields from the per-face base, CFL-clamped
!! per face (native u-face idxCu/idyCu, v-face idxCv/idyCv) and zeroed
!! on wall faces. Base = VarMix `khth_ext_*` when `use_ext`, else the
!! scalar `khth`; the same diffusive-CFL `min` is applied either way.
integer, intent(in) :: nx, ny
real(wp), intent(in) :: dt, khth, khth_max_cfl
logical, intent(in) :: use_ext
real(wp), intent(in) :: khth_ext_u(nx + 1, ny)
real(wp), intent(in) :: khth_ext_v(nx, ny + 1)
real(wp), intent(in) :: idxCu(nx + 1, ny)
real(wp), intent(in) :: idyCu(nx + 1, ny)
real(wp), intent(in) :: idxCv(nx, ny + 1)
real(wp), intent(in) :: idyCv(nx, ny + 1)
real(wp), intent(in) :: wet_u(nx + 1, ny)
real(wp), intent(in) :: wet_v(nx, ny + 1)
real(wp), intent(out) :: khth_u(nx + 1, ny)
real(wp), intent(out) :: khth_v(nx, ny + 1)
integer :: i, j
real(wp) :: idy2, idx2, kh_cfl, denom, base
! u-faces: native idxCu/idyCu at the u-point.
do concurrent(j=1:ny, i=1:nx + 1) local(idy2, idx2, kh_cfl, denom, base)
khth_u(i, j) = 0.0_wp
if (i >= 2 .and. i <= nx .and. wet_u(i, j) > 0.0_wp) then
base = khth
if (use_ext) base = khth_ext_u(i, j)
idx2 = idxCu(i, j)*idxCu(i, j)
idy2 = idyCu(i, j)*idyCu(i, j)
denom = dt*(idx2 + idy2)
kh_cfl = base
if (denom > 0.0_wp) kh_cfl = min(base, 0.25_wp*khth_max_cfl/denom)
khth_u(i, j) = kh_cfl
end if
end do
! v-faces: native idxCv/idyCv at the v-point.
do concurrent(j=1:ny + 1, i=1:nx) local(idy2, idx2, kh_cfl, denom, base)
khth_v(i, j) = 0.0_wp
if (j >= 2 .and. j <= ny .and. wet_v(i, j) > 0.0_wp) then
base = khth
if (use_ext) base = khth_ext_v(i, j)
idy2 = idyCv(i, j)*idyCv(i, j)
idx2 = idxCv(i, j)*idxCv(i, j)
denom = dt*(idx2 + idy2)
kh_cfl = base
if (denom > 0.0_wp) kh_cfl = min(base, 0.25_wp*khth_max_cfl/denom)
khth_v(i, j) = kh_cfl
end if
end do
end subroutine gm_clamp_khth