fill_tracer_impl Subroutine

private 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.

Arguments

Type IntentOptional Attributes Name
real(kind=wp), intent(in) :: h_layer(:,:,:)
real(kind=wp), intent(in) :: hTr(:,:,:)
real(kind=wp), intent(inout) :: buf(:,:,:)

Calls

proc~~fill_tracer_impl~~CallsGraph proc~fill_tracer_impl fill_tracer_impl rdb_vl_conc rdb_vl_conc proc~fill_tracer_impl->rdb_vl_conc rdb_vl_is_live rdb_vl_is_live proc~fill_tracer_impl->rdb_vl_is_live

Called by

proc~~fill_tracer_impl~~CalledByGraph proc~fill_tracer_impl fill_tracer_impl proc~fill_age fill_age proc~fill_age->proc~fill_tracer_impl proc~fill_pseudo_salt fill_pseudo_salt proc~fill_pseudo_salt->proc~fill_tracer_impl proc~fill_salinity fill_salinity proc~fill_salinity->proc~fill_tracer_impl proc~fill_temperature fill_temperature proc~fill_temperature->proc~fill_tracer_impl

Variables

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

Source Code

   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