subroutine ocean_slopes_compute_impl(grid, metrics, eos, slopes, ms, &
h_layer, t_htr, s_htr, dt)
!! Flat-impl: explicit-shape dummies for the prognostic arrays so
!! NVHPC doesn't descriptor-walk per launch.
type(hgrid_t), intent(in) :: grid
type(ocean_metrics_t), intent(in) :: metrics
type(eos_t), intent(in) :: eos
type(ocean_slopes_t), intent(inout) :: slopes
type(multilayer_state_t), intent(in) :: ms
integer :: nx, ny, nz
real(wp), intent(in) :: h_layer(slopes%nx_total, slopes%ny_total, slopes%nz_ml)
real(wp), intent(in) :: t_htr(slopes%nx_total, slopes%ny_total, slopes%nz_ml)
real(wp), intent(in) :: s_htr(slopes%nx_total, slopes%ny_total, slopes%nz_ml)
real(wp), intent(in) :: dt
nx = slopes%nx_total
ny = slopes%ny_total
nz = slopes%nz_ml
if (ms%nz_ml /= nz) return
! (1) Vert-fill T/S into the scratch (massless layers diffused).
call ocean_slopes_vert_fill_ts(nx, ny, nz, h_layer, t_htr, s_htr, &
slopes%kd_smooth, dt, &
slopes%t_fill, slopes%s_fill)
! (2) Geopotential interface heights: bed at -D, then Σ h_layer.
call ocean_slopes_build_e(nx, ny, nz, slopes%bathy, h_layer, slopes%e_int)
! (3) u-face slopes + N².
call ocean_slopes_pass_x(nx, ny, nz, eos, slopes%rho0, &
slopes%min_dz_for_n2, h_layer, &
slopes%t_fill, slopes%s_fill, slopes%e_int, &
metrics%idxCu, metrics%wet_u, &
slopes%slope_x, slopes%n2_u)
! (4) v-face slopes + N².
call ocean_slopes_pass_y(nx, ny, nz, eos, slopes%rho0, &
slopes%min_dz_for_n2, h_layer, &
slopes%t_fill, slopes%s_fill, slopes%e_int, &
metrics%idyCv, metrics%wet_v, &
slopes%slope_y, slopes%n2_v)
! (5) z-level closed faces: a slope / N² exists only at an interface
! STRICTLY INSIDE the face's open column — both layers it separates
! (`ka = K` above, `kb = K-1` below) open at that face. Anywhere
! else the four-cell stencil pairs a live cell with a filler (whose
! T/S is the vert-fill's invention, not water) and the value is
! meaningless; zeroing it is what lets GM's open-column recurrence,
! its `gm_src` and VarMix's SN read only real water. Assigned, not
! multiplied, so no non-finite value can survive behind a 0 mask.
! Host-gated: knob off ⇒ not taken, the `(1,1,1)` mask placeholders
! are never named ⇒ byte-identical. (This routine launches no
! `do concurrent` of its own, so the escaping-array cost of a gated
! call — CLAUDE.md — has nothing here to pessimise.)
if (metrics%use_closed_faces) then
call ocean_slopes_mask_open_column(nx, ny, nz, metrics%open_u, &
metrics%open_v, slopes%slope_x, &
slopes%slope_y, slopes%n2_u, &
slopes%n2_v)
end if
end subroutine ocean_slopes_compute_impl