subroutine redi_calc_coeffs(grid, metrics, eos, this, ms)
!! Public entry: fill the Phase-A coefficient arrays. No-op if
!! absent / uninitialised / disabled. Run once per outer step at
!! THERMO cadence (a slow, tracer-independent geometry). Outer-shim:
!! dereference the tracer-registry hTr arrays on the host, pass the
!! flat top-level allocatables to the flat-impl kernels.
type(hgrid_t), intent(in) :: grid
type(ocean_metrics_t), intent(in) :: metrics
type(eos_t), intent(in) :: eos
type(ocean_redi_t), intent(inout) :: this
type(multilayer_state_t), intent(in) :: ms
integer :: nx, ny, nz
if (.not. this%is_init) return
if (.not. this%enable) return
if (ms%idx_temperature <= 0 .or. ms%idx_salinity <= 0) return
if (.not. allocated(ms%h_layer)) return
nx = grid%nx_total
ny = grid%ny_total
nz = ms%nz_ml
if (this%nz_ml /= nz) return
! z-level closed faces: refresh every face's open window first. A
! SEPARATE, host-gated pass, so the coefficient kernels below never
! name `open_u`/`open_v` — with the knob off those are the `(1,1,1)`
! placeholders, and NVHPC present-checks an array a kernel indexes
! over the kernel's LOOP range whether or not the branch is taken
! ("partially present" under `mem:separate`). Knob off ⇒ not called,
! the windows keep their `1..nz` init value. (`redi_calc_coeffs`
! itself launches no `do concurrent`, so the escaping-array cost of a
! gated call — CLAUDE.md — has nothing here to pessimise.)
if (metrics%use_closed_faces) then
call redi_open_windows_x(nx, ny, nz, ms%h_layer, metrics%open_u, &
this%uKb, this%uKt)
call redi_open_windows_y(nx, ny, nz, ms%h_layer, metrics%open_v, &
this%vKb, this%vKt)
end if
call redi_calc_coeffs_x(nx, ny, nz, this%nsurf, eos, &
ms%h_layer, &
ms%tracers(ms%idx_temperature)%hTr, &
ms%tracers(ms%idx_salinity)%hTr, &
metrics%wet_u, this%uKb, this%uKt, &
this%uPoL, this%uPoR, this%uKoL, this%uKoR, this%uhEff)
call redi_calc_coeffs_y(nx, ny, nz, this%nsurf, eos, &
ms%h_layer, &
ms%tracers(ms%idx_temperature)%hTr, &
ms%tracers(ms%idx_salinity)%hTr, &
metrics%wet_v, this%vKb, this%vKt, &
this%vPoL, this%vPoR, this%vKoL, this%vKoR, this%vhEff)
end subroutine redi_calc_coeffs