check_vanished_invariant_or_die Subroutine

private subroutine check_vanished_invariant_or_die(grid, vcoord, ms, outer_step)

Fail-loud TRIPWIRE for invariant I1′ — h_layer <= H_VANISHED ⇒ hTr = h_layer·c_live (the donor live layer’s concentration; hTr = 0 in a column with no live layer) for every registered tracer. Gated on &vcoord_nml check_vanished_content (default .false.), which is the knob the stability suite turns on for the cases that actually have vanishing layers.

Pure scan + impure die, the check_h_positive_or_die pattern: the scan (ms%scan_vanished_content) is a pure device reduction returning two scalars, so the HEALTHY path costs two reductions per tracer and no H←D copy; only a violation reaches the logger.

Runs immediately AFTER enforce_vanished_content, so a hit means the enforcement point itself failed to establish the invariant — a bug in the rule or an unmapped array on the device, not a stray kernel. That is precisely what the tripwire is for: it guards the structural guarantee rather than re-stating it.

Arguments

Type IntentOptional Attributes Name
type(hgrid_t), intent(in) :: grid
type(ocean_vcoord_t), intent(in), optional :: vcoord
type(multilayer_state_t), intent(in) :: ms
integer, intent(in) :: outer_step

Calls

proc~~check_vanished_invariant_or_die~~CallsGraph proc~check_vanished_invariant_or_die check_vanished_invariant_or_die error error proc~check_vanished_invariant_or_die->error proc~multilayer_scan_vanished_content multilayer_state_t%multilayer_scan_vanished_content proc~check_vanished_invariant_or_die->proc~multilayer_scan_vanished_content proc~scan_vanished_one_impl scan_vanished_one_impl proc~multilayer_scan_vanished_content->proc~scan_vanished_one_impl rdb_vl_holds_live_conc rdb_vl_holds_live_conc proc~scan_vanished_one_impl->rdb_vl_holds_live_conc rdb_vl_is_live rdb_vl_is_live proc~scan_vanished_one_impl->rdb_vl_is_live

Called by

proc~~check_vanished_invariant_or_die~~CalledByGraph proc~check_vanished_invariant_or_die check_vanished_invariant_or_die proc~ocean_dyn_step_split ocean_dyn_step_split proc~ocean_dyn_step_split->proc~check_vanished_invariant_or_die proc~engine_step engine_step proc~engine_step->proc~ocean_dyn_step_split proc~driver_run_ocean driver_run_ocean proc~driver_run_ocean->proc~engine_step proc~rdb_ocean_step rdb_ocean_step proc~rdb_ocean_step->proc~engine_step proc~driver_run driver_run proc~driver_run->proc~driver_run_ocean

Variables

Type Visibility Attributes Name Initial
character(len=320), private :: msg
integer, private :: n_bad
real(kind=wp), private :: worst

Source Code

   subroutine check_vanished_invariant_or_die(grid, vcoord, ms, outer_step)
      !! Fail-loud TRIPWIRE for invariant I1′ — `h_layer <= H_VANISHED ⇒
      !! hTr = h_layer·c_live` (the donor live layer's concentration; `hTr = 0`
      !! in a column with no live layer) for every registered tracer.  Gated on
      !! `&vcoord_nml check_vanished_content` (default `.false.`), which is
      !! the knob the stability suite turns on for the cases that actually
      !! have vanishing layers.
      !!
      !! Pure scan + impure die, the `check_h_positive_or_die` pattern: the
      !! scan (`ms%scan_vanished_content`) is a `pure` device reduction
      !! returning two scalars, so the HEALTHY path costs two reductions per
      !! tracer and no H←D copy; only a violation reaches the logger.
      !!
      !! Runs immediately AFTER `enforce_vanished_content`, so a hit means the
      !! enforcement point itself failed to establish the invariant — a bug in
      !! the rule or an unmapped array on the device, not a stray kernel.  That
      !! is precisely what the tripwire is for: it guards the structural
      !! guarantee rather than re-stating it.
      type(hgrid_t), intent(in) :: grid
      type(ocean_vcoord_t), intent(in), optional :: vcoord
      type(multilayer_state_t), intent(in) :: ms
      integer, intent(in) :: outer_step
      integer :: n_bad
      real(wp) :: worst
      character(len=320) :: msg

      if (.not. present(vcoord)) return
      if (.not. vcoord%check_vanished_content) return
      call ms%scan_vanished_content(grid%nx_total, grid%ny_total, n_bad, worst)
      if (n_bad <= 0) return
      write (msg, "(a,i0,a,i0,a,es12.5)") &
         "[I1'] vanished-layer invariant violated at outer step ", outer_step, &
         ": ", n_bad, " filler cell(s) do not hold their donor's concentration; "// &
         "worst |hTr - h*c_live| = ", worst
      call logger%error(trim(msg))
      call logger%error( &
         "[I1'] `h <= H_VANISHED ⇒ hTr = h*c_live`. The enforcement point "// &
         "(multilayer_state_t%enforce_vanished_content) runs immediately before this "// &
         "check, so a hit is a bug in the rule or an off-device array, not a stray "// &
         "kernel write. See src/core/ocean/README.md, 'The vanished-layer content rule'.")
      error stop "I1' violated (&vcoord_nml check_vanished_content)"
   end subroutine check_vanished_invariant_or_die