Recompute the porous-barrier layer-averaged open-area fractions
from the current layer thicknesses. No-op (and untouched
placeholder arrays) when &ocean_porous_nml enable is off.
Cadence: ONCE PER OUTER STEP, before the RK2 stages — the
fractions are then held fixed across both stages. That is
MOM6’s cadence (porous_widths_layer runs in step_MOM ahead
of the dynamics call and the porous type enters the split-RK2
driver intent(in)), and it keeps the widths consistent between
the two stages’ continuity and Coriolis transports.
Device-side do concurrent: every array it touches is already
mapped by ocean_metrics_enter_data / the multilayer state, so
there is no host round-trip and nothing to allocate.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| type(hgrid_t), | intent(in) | :: | grid | |||
| type(ocean_metrics_t), | intent(inout) | :: | metrics | |||
| type(multilayer_state_t), | intent(in) | :: | ms |
subroutine ocean_porous_refresh(grid, metrics, ms) !! Recompute the porous-barrier layer-averaged open-area fractions !! from the current layer thicknesses. No-op (and untouched !! placeholder arrays) when `&ocean_porous_nml enable` is off. !! !! Cadence: ONCE PER OUTER STEP, before the RK2 stages — the !! fractions are then held fixed across both stages. That is !! MOM6's cadence (`porous_widths_layer` runs in `step_MOM` ahead !! of the dynamics call and the porous type enters the split-RK2 !! driver `intent(in)`), and it keeps the widths consistent between !! the two stages' continuity and Coriolis transports. !! !! Device-side `do concurrent`: every array it touches is already !! mapped by `ocean_metrics_enter_data` / the multilayer state, so !! there is no host round-trip and nothing to allocate. type(hgrid_t), intent(in) :: grid type(ocean_metrics_t), intent(inout) :: metrics type(multilayer_state_t), intent(in) :: ms if (metrics%use_porous) then call porous_update_face_areas(grid%nx_total, grid%ny_total, ms%nz_ml, & metrics%porous_eta_interp, & metrics%porous_mask_depth, & metrics%por_bed, ms%h_layer, & metrics%por_dmin_u, metrics%por_dmax_u, & metrics%por_davg_u, & metrics%por_dmin_v, metrics%por_dmax_v, & metrics%por_davg_v, & metrics%dy_cu, metrics%dx_cv, & metrics%por_face_area_u, & metrics%por_face_area_v, & metrics%dy_cu_bt, metrics%dx_cv_bt) end if ! z-level closed faces: refresh the BAROTROPIC widths from the LIVE ! `h` at the same (per-outer-step) cadence. AFTER the porous write, ! which it SUPERSEDES rather than multiplies — the combined ! thickness-weighted fraction it computes already contains the ! porous one. See `closed_faces_update_bt_widths`. if (metrics%use_closed_faces) then ! Two branches, one per porous state: with porous OFF the ! `por_face_area_*` arrays are the `(1,1,1)` placeholder and must ! NOT reach the callee's explicit-shape dummy (see its `use_por` ! docstring -- the GPU build aborts, the CPU builds do not). The ! mask itself is the inert stand-in: right shape, already mapped, ! `intent(in)` at both dummies so the double association is legal. if (metrics%use_porous) then call closed_faces_update_bt_widths(grid%nx_total, grid%ny_total, ms%nz_ml, & .true., & metrics%dy_cu, metrics%dx_cv, & ms%h_layer, & metrics%por_face_area_u, & metrics%por_face_area_v, & metrics%open_u, metrics%open_v, & metrics%dy_cu_bt, metrics%dx_cv_bt) else call closed_faces_update_bt_widths(grid%nx_total, grid%ny_total, ms%nz_ml, & .false., & metrics%dy_cu, metrics%dx_cv, & ms%h_layer, & metrics%open_u, metrics%open_v, & metrics%open_u, metrics%open_v, & metrics%dy_cu_bt, metrics%dx_cv_bt) end if end if end subroutine ocean_porous_refresh