Shared flat-impl for any tracer concentration field.
P7 F5 fix: a vanishing layer used to write 0.0, and 0 degC / 0
PSU are both LEGAL ocean values — a vanished (below-bottom or
pinched-out) bed layer under ZSTAR_FULL therefore used to read
back as plausible ice-point freshwater rather than as missing
data (D3.2 of 06_python_surface_design.md). Now: the divisor
guard is H_VANISHED (the dynamic-vanish threshold, not the
pure 1/0 armour H_DIV_EPS — see rdb_constants’ D4 taxonomy),
and the fill is IEEE NaN, matching the Python concentration
accessor’s own convention (D3.2) so an in-memory read
(model.diagnostic(...)) and the NetCDF stream agree. This is
independent of &ocean_diag_nml mask_vanished_layers: that knob
only gates the conservative REMAP path’s below-target-cell fill
(remap_column via register_one_canonical’s has_missing);
at the default LAYER vgrid there is no remap, so this fill is
the only thing between “no water here” and a plausible-looking
number, unconditionally.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| real(kind=wp), | intent(in) | :: | h_layer(:,:,:) | |||
| real(kind=wp), | intent(in) | :: | hTr(:,:,:) | |||
| real(kind=wp), | intent(inout) | :: | buf(:,:,:) |
| Type | Visibility | Attributes | Name | Initial | |||
|---|---|---|---|---|---|---|---|
| real(kind=wp), | private | :: | h | ||||
| integer, | private | :: | i | ||||
| integer, | private | :: | j | ||||
| integer, | private | :: | k | ||||
| integer, | private | :: | nx | ||||
| integer, | private | :: | ny | ||||
| integer, | private | :: | nz | ||||
| integer, | private | :: | nz_h | ||||
| real(kind=wp), | private | :: | qnan |
pure subroutine fill_tracer_impl(h_layer, hTr, buf) !! Shared flat-impl for any tracer concentration field. !! !! P7 F5 fix: a vanishing layer used to write 0.0, and 0 degC / 0 !! PSU are both LEGAL ocean values — a vanished (below-bottom or !! pinched-out) bed layer under ZSTAR_FULL therefore used to read !! back as plausible ice-point freshwater rather than as missing !! data (D3.2 of `06_python_surface_design.md`). Now: the divisor !! guard is `H_VANISHED` (the dynamic-vanish threshold, not the !! pure 1/0 armour `H_DIV_EPS` — see `rdb_constants`' D4 taxonomy), !! and the fill is IEEE NaN, matching the Python concentration !! accessor's own convention (D3.2) so an in-memory read !! (`model.diagnostic(...)`) and the NetCDF stream agree. This is !! independent of `&ocean_diag_nml mask_vanished_layers`: that knob !! only gates the conservative REMAP path's below-target-cell fill !! (`remap_column` via `register_one_canonical`'s `has_missing`); !! at the default LAYER vgrid there is no remap, so this fill is !! the only thing between "no water here" and a plausible-looking !! number, unconditionally. ! assumed-shape-ok: diag fill — fires once per output frame (cadence-bounded). real(wp), intent(in) :: h_layer(:, :, :) real(wp), intent(in) :: hTr(:, :, :) ! assumed-shape-ok: diag fill — cadence-bounded real(wp), intent(inout) :: buf(:, :, :) ! assumed-shape-ok: diag fill — cadence-bounded integer :: i, j, k, nx, ny, nz, nz_h real(wp) :: h, qnan nx = size(buf, 1) ny = size(buf, 2) nz = size(buf, 3) nz_h = size(h_layer, 3) ! Sentinel computed once, host-side, before the do-concurrent body ! (ieee_value is a host intrinsic — see rdb_ocean_ghost_poison's ! qnan for the same pattern): pass a plain IEEE bit pattern into ! the device kernel rather than calling the intrinsic per-cell. qnan = ieee_value(0.0_wp, ieee_quiet_nan) do concurrent(k=1:min(nz, nz_h), j=1:ny, i=1:nx) h = h_layer(i, j, k) ! vanished-ok: a diagnostic substitutes the NaN missing-data ! sentinel on a vanished layer, not `rdb_vl_conc`'s copy of the ! donor's concentration (README ! consumer table); the live branch IS `rdb_vl_conc`. if (rdb_vl_is_live(h)) then buf(i, j, k) = rdb_vl_conc(hTr(i, j, k), h) else buf(i, j, k) = qnan end if end do end subroutine fill_tracer_impl