The per-face Phase-A core: build both columns TOP-DOWN on the open
window kb..kt (the whole column off the closed-face path), run the
sweep on its nk = kt-kb+1 layers, and store PoL/PoR/KoL/KoR/hEff in
the FULL top-down frame (Ko + nz - kt). The k-flip is confined to
the Phase-B scatter; keeping Po/Ko top-down here lets the flux re-use
the sweep’s interface-edge convention with no position arithmetic on
the flipped frame. A short window (nk < nz) leaves 2*(nz-nk)
trailing surfaces, filled as inert padding: the last surface
repeated and hEff = 0, which Phase B skips.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| integer, | intent(in) | :: | nz | |||
| integer, | intent(in) | :: | ns | |||
| integer, | intent(in) | :: | kb |
Native (bottom-up) open window, |
||
| integer, | intent(in) | :: | kt |
Native (bottom-up) open window, |
||
| real(kind=wp), | intent(in) | :: | hL(nz) | |||
| real(kind=wp), | intent(in) | :: | tL(nz) | |||
| real(kind=wp), | intent(in) | :: | sL(nz) | |||
| real(kind=wp), | intent(in) | :: | hR(nz) | |||
| real(kind=wp), | intent(in) | :: | tR(nz) | |||
| real(kind=wp), | intent(in) | :: | sR(nz) | |||
| type(eos_t), | intent(in) | :: | eos | |||
| real(kind=wp), | intent(out) | :: | PoLo(ns) | |||
| real(kind=wp), | intent(out) | :: | PoRo(ns) | |||
| integer, | intent(out) | :: | KoLo(ns) | |||
| integer, | intent(out) | :: | KoRo(ns) | |||
| real(kind=wp), | intent(out) | :: | hEffo(ns-1) |
| Type | Visibility | Attributes | Name | Initial | |||
|---|---|---|---|---|---|---|---|
| real(kind=wp), | private | :: | Pl(NZ_STACK_MAX+1) | ||||
| real(kind=wp), | private | :: | Pr(NZ_STACK_MAX+1) | ||||
| real(kind=wp), | private | :: | Sli(NZ_STACK_MAX+1) | ||||
| real(kind=wp), | private | :: | Sri(NZ_STACK_MAX+1) | ||||
| real(kind=wp), | private | :: | Tli(NZ_STACK_MAX+1) | ||||
| real(kind=wp), | private | :: | Tri(NZ_STACK_MAX+1) | ||||
| real(kind=wp), | private | :: | dRdSl(NZ_STACK_MAX+1) | ||||
| real(kind=wp), | private | :: | dRdSr(NZ_STACK_MAX+1) | ||||
| real(kind=wp), | private | :: | dRdTl(NZ_STACK_MAX+1) | ||||
| real(kind=wp), | private | :: | dRdTr(NZ_STACK_MAX+1) | ||||
| integer, | private | :: | koff | ||||
| integer, | private | :: | ks | ||||
| integer, | private | :: | nk | ||||
| integer, | private | :: | nsw | ||||
| real(kind=wp), | private | :: | pa_to_h |
pure subroutine redi_face_coeffs(nz, ns, kb, kt, hL, tL, sL, hR, tR, sR, eos, & PoLo, PoRo, KoLo, KoRo, hEffo) !! The per-face Phase-A core: build both columns TOP-DOWN on the open !! window `kb..kt` (the whole column off the closed-face path), run the !! sweep on its `nk = kt-kb+1` layers, and store PoL/PoR/KoL/KoR/hEff in !! the FULL top-down frame (`Ko + nz - kt`). The k-flip is confined to !! the Phase-B scatter; keeping Po/Ko top-down here lets the flux re-use !! the sweep's interface-edge convention with no position arithmetic on !! the flipped frame. A short window (`nk < nz`) leaves `2*(nz-nk)` !! trailing surfaces, filled as inert padding: the last surface !! repeated and `hEff = 0`, which Phase B skips. !$acc routine seq integer, intent(in) :: nz, ns integer, intent(in) :: kb, kt !! Native (bottom-up) open window, `1 <= kb <= kt <= nz`. real(wp), intent(in) :: hL(nz), tL(nz), sL(nz), hR(nz), tR(nz), sR(nz) type(eos_t), intent(in) :: eos real(wp), intent(out) :: PoLo(ns), PoRo(ns), hEffo(ns - 1) integer, intent(out) :: KoLo(ns), KoRo(ns) real(wp) :: Pl(NZ_STACK_MAX + 1), Tli(NZ_STACK_MAX + 1), Sli(NZ_STACK_MAX + 1) real(wp) :: dRdTl(NZ_STACK_MAX + 1), dRdSl(NZ_STACK_MAX + 1) real(wp) :: Pr(NZ_STACK_MAX + 1), Tri(NZ_STACK_MAX + 1), Sri(NZ_STACK_MAX + 1) real(wp) :: dRdTr(NZ_STACK_MAX + 1), dRdSr(NZ_STACK_MAX + 1) real(wp) :: pa_to_h integer :: ks, nk, nsw, koff nk = kt - kb + 1 nsw = 2*nk + 2 koff = nz - kt call redi_build_column(nz, kb, kt, hL, tL, sL, eos, Pl, Tli, Sli, dRdTl, dRdSl) call redi_build_column(nz, kb, kt, hR, tR, sR, eos, Pr, Tri, Sri, dRdTr, dRdSr) call redi_neutral_positions_continuous(nk, Pl, Tli, Sli, dRdTl, dRdSl, & Pr, Tri, Sri, dRdTr, dRdSr, & PoLo, PoRo, KoLo, KoRo, hEffo) ! The continuous sweep computes hEff from interface-PRESSURE differences ! (Pa, since the position coordinate is the hydrostatic pressure ! g*rho0*h), but the flux divergence and Coef consume hEff in THICKNESS ! units (m). Convert Pa -> m by dividing by H_to_pa = g*rho0 (MOM6 ! neutral_diffusion lines ~588: uhEff /= H_to_pa). Po/Ko stay TOP-DOWN; ! the only k-flip is the Phase-B scatter. pa_to_h = 1.0_wp/(GRAVITY*eos%rho0) do ks = 1, nsw - 1 hEffo(ks) = hEffo(ks)*pa_to_h end do ! Window frame -> full top-down frame (`koff = 0` off the closed-face ! path), then the inert padding of a short window. if (koff /= 0) then do ks = 1, nsw KoLo(ks) = KoLo(ks) + koff KoRo(ks) = KoRo(ks) + koff end do end if do ks = nsw + 1, ns PoLo(ks) = PoLo(nsw) PoRo(ks) = PoRo(nsw) KoLo(ks) = KoLo(nsw) KoRo(ks) = KoRo(nsw) hEffo(ks - 1) = 0.0_wp end do end subroutine redi_face_coeffs