Zero the extensive tracer content hTr on land T-cells
(wet_mask == 0). Wet cells untouched (bit-identical when
wet_mask ≡ 1).
h = H_VANISHED, hTr = 0seed_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:
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;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.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| real(kind=wp), | intent(inout) | :: | hTr(:,:,:) | |||
| real(kind=wp), | intent(in) | :: | wet_mask(:,:) | |||
| integer, | intent(in) | :: | nz |
| Type | Visibility | Attributes | Name | Initial | |||
|---|---|---|---|---|---|---|---|
| integer, | private | :: | i | ||||
| integer, | private | :: | j | ||||
| integer, | private | :: | k | ||||
| integer, | private | :: | nx | ||||
| integer, | private | :: | ny |
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