Roquet et al. (2015) SpV EOS evaluated at a single reference
pressure p_ref (a SCALAR by design — see the
horizontal-uniformity contract in eos_compute_arrays). Same
outer-shim signature as eos_linear_impl/eos_wright_impl —
bare 3D arrays, model (PT, SP) tracers, vanishing-layer fallback
to rho_0.
Density = 1 / SV(CT(SR,PT), SR, p_ref) with SR = SP·(35.16504/35)
and CT = ct_from_pt(SR, PT) — the conversions live inside the
fused roquet_spv_point point routine (the only sqrt path).
FV_LITE / FV_MOM6 PGF read rho_layer generically, so they pick
up Roquet automatically. (FV_WRIGHT re-evaluates Wright in its
Picard sweep → unsupported with Roquet; gated fail-loud at
configure in configure_ocean_pgf.)
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| real(kind=wp), | intent(in) | :: | h_layer(nx,ny,nz) | |||
| real(kind=wp), | intent(in) | :: | hS_layer(nx,ny,nz) | |||
| real(kind=wp), | intent(in) | :: | hT_layer(nx,ny,nz) | |||
| real(kind=wp), | intent(out) | :: | rho_layer(nx,ny,nz) | |||
| real(kind=wp), | intent(in) | :: | rho_0 | |||
| real(kind=wp), | intent(in) | :: | p_ref | |||
| integer, | intent(in) | :: | nx | |||
| integer, | intent(in) | :: | ny | |||
| integer, | intent(in) | :: | nz |
| Type | Visibility | Attributes | Name | Initial | |||
|---|---|---|---|---|---|---|---|
| real(kind=wp), | private | :: | S_k | ||||
| real(kind=wp), | private | :: | T_k | ||||
| integer, | private | :: | i | ||||
| real(kind=wp), | private | :: | inv_h | ||||
| integer, | private | :: | j | ||||
| integer, | private | :: | k | ||||
| real(kind=wp), | private | :: | sv_k |
pure subroutine eos_roquet_spv_impl(h_layer, hS_layer, hT_layer, rho_layer, & rho_0, p_ref, nx, ny, nz) !! Roquet et al. (2015) SpV EOS evaluated at a single reference !! pressure `p_ref` (a SCALAR by design — see the !! horizontal-uniformity contract in `eos_compute_arrays`). Same !! outer-shim signature as `eos_linear_impl`/`eos_wright_impl` — !! bare 3D arrays, model (PT, SP) tracers, vanishing-layer fallback !! to `rho_0`. !! !! Density = 1 / SV(CT(SR,PT), SR, p_ref) with SR = SP·(35.16504/35) !! and CT = ct_from_pt(SR, PT) — the conversions live inside the !! fused `roquet_spv_point` point routine (the only sqrt path). !! !! FV_LITE / FV_MOM6 PGF read `rho_layer` generically, so they pick !! up Roquet automatically. (FV_WRIGHT re-evaluates Wright in its !! Picard sweep → unsupported with Roquet; gated fail-loud at !! configure in `configure_ocean_pgf`.) integer, intent(in) :: nx, ny, nz real(wp), intent(in) :: h_layer(nx, ny, nz) real(wp), intent(in) :: hS_layer(nx, ny, nz) real(wp), intent(in) :: hT_layer(nx, ny, nz) real(wp), intent(out) :: rho_layer(nx, ny, nz) real(wp), intent(in) :: rho_0, p_ref integer :: i, j, k real(wp) :: inv_h, S_k, T_k, sv_k ! Value-only (`roquet_spv_value`): the derivatives `roquet_spv_point` ! also returns were discarded here. do concurrent(k=1:nz, j=1:ny, i=1:nx) & local(inv_h, S_k, T_k, sv_k) if (h_layer(i, j, k) > H_VANISHED) then inv_h = 1.0_wp/h_layer(i, j, k) S_k = hS_layer(i, j, k)*inv_h T_k = hT_layer(i, j, k)*inv_h sv_k = roquet_spv_value(T_k, S_k, p_ref) rho_layer(i, j, k) = 1.0_wp/sv_k else rho_layer(i, j, k) = rho_0 end if end do end subroutine eos_roquet_spv_impl