seed_land_tracer_hold_impl Subroutine

private pure subroutine seed_land_tracer_hold_impl(hTr, wet_mask, nz)

Zero the extensive tracer content hTr on land T-cells (wet_mask == 0). Wet cells untouched (bit-identical when wet_mask ≡ 1).

The land-state contract: h = H_VANISHED, hTr = 0

seed_land_h_floor_impl pins a land layer’s thickness EXACTLY at H_VANISHED, which is the D4 vanished marker. Every vanished-gated operator in the tree tests h > H_VANISHED (strictly), so a land layer is on the VANISHED side of every one of those gates — in particular the ALE remap’s concentration step (rdb_ocean_remap::ocean_remap_tracer_field, c = hTr/h if h > H_FLOOR else c = 0), which therefore writes hTr = 0 on every land column at the first regrid.

So hTr = 0 is not a choice made here — it is the land content the running solver holds. The seed’s job is to hand the budget latch the SAME land state that every later step will have, and any other seeded value is content the first regrid discards silently and un-budgeted, which shows up as a step change in the console Error residual between step 0 and step 1.

This replaced a “recover val = hTr/max(h_old, H_VANISHED) and re-scale onto the floor” hold, which was wrong twice:

  • the max(...) divisor makes the re-scale an exact IDENTITY whenever h_old <= H_VANISHED — including h_old < 0, which is what an ice-shelf column GROUNDED by &ocean_cavity_dyn_nml h_min_cavity has (its water column b - z_draft is negative by hundreds of metres). Those columns kept a FULL-COLUMN, negative hTr next to a floored h, i.e. an implied concentration of order -1e7 PSU, and contributed it to the budget latch: 61 % of the initial salt content on validation_examples/ocean/isomip_plus/ocean0_idealised_draft.nml;
  • even where the re-scale DID work (ordinary land, 0 < h_old), the val*H_VANISHED it left is discarded by the first regrid, a ~1e-8 relative step change in every land-bearing case.

The 0*NaN hazard the old hold existed to avoid is avoided the same way: T = S = hTr/h = 0 is finite.

Arguments

Type IntentOptional Attributes Name
real(kind=wp), intent(inout) :: hTr(:,:,:)
real(kind=wp), intent(in) :: wet_mask(:,:)
integer, intent(in) :: nz

Called by

proc~~seed_land_tracer_hold_impl~~CalledByGraph proc~seed_land_tracer_hold_impl seed_land_tracer_hold_impl proc~ocean_state_seed_land_cells ocean_state_seed_land_cells proc~ocean_state_seed_land_cells->proc~seed_land_tracer_hold_impl proc~configure_ocean_land_mask configure_ocean_land_mask proc~configure_ocean_land_mask->proc~ocean_state_seed_land_cells proc~engine_setup engine_setup proc~engine_setup->proc~configure_ocean_land_mask proc~complete_ocean_create complete_ocean_create proc~complete_ocean_create->proc~engine_setup proc~driver_run_ocean driver_run_ocean proc~driver_run_ocean->proc~engine_setup proc~driver_validate driver_validate proc~driver_validate->proc~engine_setup proc~driver_run driver_run proc~driver_run->proc~driver_run_ocean proc~rdb_ocean_create_finalize rdb_ocean_create_finalize proc~rdb_ocean_create_finalize->proc~complete_ocean_create proc~rdb_ocean_create_from_string rdb_ocean_create_from_string proc~rdb_ocean_create_from_string->proc~complete_ocean_create

Variables

Type Visibility Attributes Name Initial
integer, private :: i
integer, private :: j
integer, private :: k
integer, private :: nx
integer, private :: ny

Source Code

   pure subroutine seed_land_tracer_hold_impl(hTr, wet_mask, nz)
      !! Zero the extensive tracer content `hTr` on land T-cells
      !! (`wet_mask == 0`).  Wet cells untouched (bit-identical when
      !! `wet_mask ≡ 1`).
      !!
      !! ### The land-state contract: `h = H_VANISHED`, `hTr = 0`
      !!
      !! `seed_land_h_floor_impl` pins a land layer's thickness EXACTLY at
      !! `H_VANISHED`, which is the D4 *vanished* marker.  Every
      !! vanished-gated operator in the tree tests `h > H_VANISHED`
      !! (strictly), so a land layer is on the VANISHED side of every one
      !! of those gates — in particular the ALE remap's concentration
      !! step (`rdb_ocean_remap::ocean_remap_tracer_field`, `c = hTr/h` if
      !! `h > H_FLOOR` else `c = 0`), which therefore writes `hTr = 0` on
      !! every land column at the first regrid.
      !!
      !! So `hTr = 0` is not a choice made here — it is the land content
      !! the running solver holds.  The seed's job is to hand the budget
      !! latch the SAME land state that every later step will have, and
      !! any other seeded value is content the first regrid discards
      !! silently and un-budgeted, which shows up as a step change in the
      !! console `Error` residual between step 0 and step 1.
      !!
      !! This replaced a "recover `val = hTr/max(h_old, H_VANISHED)` and
      !! re-scale onto the floor" hold, which was wrong twice:
      !!
      !!   * the `max(...)` divisor makes the re-scale an exact IDENTITY
      !!     whenever `h_old <= H_VANISHED` — including `h_old < 0`, which
      !!     is what an ice-shelf column GROUNDED by `&ocean_cavity_dyn_nml
      !!     h_min_cavity` has (its water column `b - z_draft` is negative
      !!     by hundreds of metres).  Those columns kept a FULL-COLUMN,
      !!     negative `hTr` next to a floored `h`, i.e. an implied
      !!     concentration of order `-1e7` PSU, and contributed it to the
      !!     budget latch: 61 % of the initial salt content on
      !!     `validation_examples/ocean/isomip_plus/ocean0_idealised_draft.nml`;
      !!   * even where the re-scale DID work (ordinary land, `0 < h_old`),
      !!     the `val*H_VANISHED` it left is discarded by the first regrid,
      !!     a ~1e-8 relative step change in every land-bearing case.
      !!
      !! The `0*NaN` hazard the old hold existed to avoid is avoided the
      !! same way: `T = S = hTr/h = 0` is finite.
      integer, intent(in) :: nz
      real(wp), intent(inout) :: hTr(:, :, :)
      real(wp), intent(in) :: wet_mask(:, :)
      integer :: i, j, k, nx, ny
      nx = size(hTr, 1)
      ny = size(hTr, 2)
      do k = 1, nz
         do j = 1, ny
            do i = 1, nx
               if (wet_mask(i, j) == 0.0_wp) hTr(i, j, k) = 0.0_wp
            end do
         end do
      end do
   end subroutine seed_land_tracer_hold_impl