Fan the ONE configured Boussinesq reference density out to every
remaining slot that carries its own rho0 copy.
&ocean_ic_nml rho_0 lands on eos%rho0 in
ocean_state_init_from_config; that is the ρ₀ of record. EPBL,
kappa-shear, tidal mixing, wave speed, the eta_ib surface-pressure
seam, GM / MEKE / Redi / MLE, the isopycnal slopes and (since the
preceding commit) the PGF all copy it in their own
configure_ocean_*. The four slots wired here were the remainder:
they kept a hard 1035 type default that nothing ever assigned, so a
namelist with rho_0 /= 1035 ran the EOS on one reference density
and the surface forcing, wind stress and KPP buoyancy on another —
no warning, no fail-loud, just a 1035/ρ₀ scaling on every surface
heat/salt flux, every wind-stress acceleration, and N²/u*/B_0.
surface_flux%rho0 — the dt/(ρ₀·cp) heat and dt/ρ₀ salt
divisors for EVERY surface tracer source, including what the
sea-ice coupler delivers through Q_heat/Q_salt.surface_stress%rho0 — the τ/(ρ₀·h_top) acceleration (both
the top-layer and the DIRECT_STRESS distributed form).vmix%rho0 — KPP: N² = −g/ρ₀·∂ρ/∂z, u* = √(|τ|/ρ₀), the
kinematic surface fluxes q_T = Q_heat/(ρ₀·cp), q_S = Q_salt/ρ₀
feeding B_0, and the PP81 / convective-adjustment N².geothermal%rho0 — the dt·Q_geo/(ρ₀·cp) bed heat source.
The geothermal slot lives on the engine, not on ocean_state,
so it is passed in (optional: a caller with no geothermal slot
simply omits it).Device contract (mem:separate): surface_flux, surface_stress
and geothermal read their rho0 HOST-side (folded into the
inv_scale / src_T scalar or passed by value into a *_impl), so
those owe nothing. vmix%rho0 IS read on-device — this%rho0
appears inside the do concurrent bodies of vmix_compute_pp81,
vmix_kpp_overlay_impl and vmix_convective_impl — but this
routine runs in the configure phase, strictly BEFORE
ocean_state_enter_data’s copyin, exactly like the neighbouring
pp81_* / shear2_floor scalars it sits with. No
!$acc update device is owed. A configure step that ever moves
after enter_data must add one.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| type(ocean_state_t), | intent(inout) | :: | ocean_state | |||
| type(ocean_geothermal_t), | intent(inout), | optional | :: | geo |
Engine-held geothermal slot (the split driver’s |
subroutine configure_ocean_reference_density(ocean_state, geo) !! Fan the ONE configured Boussinesq reference density out to every !! remaining slot that carries its own `rho0` copy. !! !! `&ocean_ic_nml rho_0` lands on `eos%rho0` in !! `ocean_state_init_from_config`; that is the ρ₀ of record. EPBL, !! kappa-shear, tidal mixing, wave speed, the `eta_ib` surface-pressure !! seam, GM / MEKE / Redi / MLE, the isopycnal slopes and (since the !! preceding commit) the PGF all copy it in their own !! `configure_ocean_*`. The four slots wired here were the remainder: !! they kept a hard 1035 type default that nothing ever assigned, so a !! namelist with `rho_0 /= 1035` ran the EOS on one reference density !! and the surface forcing, wind stress and KPP buoyancy on another — !! no warning, no fail-loud, just a 1035/ρ₀ scaling on every surface !! heat/salt flux, every wind-stress acceleration, and N²/u*/B_0. !! !! * `surface_flux%rho0` — the `dt/(ρ₀·cp)` heat and `dt/ρ₀` salt !! divisors for EVERY surface tracer source, including what the !! sea-ice coupler delivers through `Q_heat`/`Q_salt`. !! * `surface_stress%rho0` — the `τ/(ρ₀·h_top)` acceleration (both !! the top-layer and the DIRECT_STRESS distributed form). !! * `vmix%rho0` — KPP: N² = −g/ρ₀·∂ρ/∂z, u* = √(|τ|/ρ₀), the !! kinematic surface fluxes q_T = Q_heat/(ρ₀·cp), q_S = Q_salt/ρ₀ !! feeding B_0, and the PP81 / convective-adjustment N². !! * `geothermal%rho0` — the `dt·Q_geo/(ρ₀·cp)` bed heat source. !! The geothermal slot lives on the engine, not on `ocean_state`, !! so it is passed in (optional: a caller with no geothermal slot !! simply omits it). !! !! Device contract (`mem:separate`): `surface_flux`, `surface_stress` !! and `geothermal` read their `rho0` HOST-side (folded into the !! `inv_scale` / `src_T` scalar or passed by value into a `*_impl`), so !! those owe nothing. `vmix%rho0` IS read on-device — `this%rho0` !! appears inside the `do concurrent` bodies of `vmix_compute_pp81`, !! `vmix_kpp_overlay_impl` and `vmix_convective_impl` — but this !! routine runs in the configure phase, strictly BEFORE !! `ocean_state_enter_data`'s `copyin`, exactly like the neighbouring !! `pp81_*` / `shear2_floor` scalars it sits with. No !! `!$acc update device` is owed. **A configure step that ever moves !! after `enter_data` must add one.** type(ocean_state_t), intent(inout) :: ocean_state type(ocean_geothermal_t), intent(inout), optional :: geo !! Engine-held geothermal slot (the split driver's `geo` argument). ocean_state%surface_flux%rho0 = ocean_state%eos%rho0 ocean_state%surface_stress%rho0 = ocean_state%eos%rho0 ocean_state%vmix%rho0 = ocean_state%eos%rho0 if (present(geo)) geo%rho0 = ocean_state%eos%rho0 end subroutine configure_ocean_reference_density