ocean_isopycnal_config_t Derived Type

type, public :: ocean_isopycnal_config_t

&ocean_isopycnal_nml: grounding-stability controls for the Lagrangian (isopycnal-class, remap-free) vertical coordinate. Every knob here engages ONLY under sim_type=’ocean’ + VCOORD_LAGRANGIAN, so the whole group is bit-identical on every other vertical coordinate. All are default-OFF except pgf_skip_nonoverlap, which is a correctness fix and defaults ON.


Inherited by

type~~ocean_isopycnal_config_t~~InheritedByGraph type~ocean_isopycnal_config_t ocean_isopycnal_config_t type~ocean_config_t ocean_config_t type~ocean_config_t->type~ocean_isopycnal_config_t isopycnal type~config_t config_t type~config_t->type~ocean_config_t ocean type~ocean_handle_t ocean_handle_t type~ocean_handle_t->type~config_t cfg

Components

Type Visibility Attributes Name Initial
real(kind=wp), public :: angstrom_h = 0.0_wp

Phase 1: minimum-thickness floor (m) on the Lagrangian continuity h-update — MOM6 GV%Angstrom_H analogue used as the max(h_new, Angstrom_H) clamp. 0.0 ⇒ off ⇒ bit-identical (the floor loop is skipped). Physical floor (D4 taxonomy), NOT H_DIV_EPS (too small to bound 1/h) and NOT hardwired H_VANISHED (that is the skip/merge marker). Recommended run value 1e-3..1e-2 m. NOT strictly conservative: injects <= angstrom_h*areaT per floored layer-cell (zero on non-grounding steps). Thermo-on caveat (R7): the floor lifts h but not the companion hTr, so on a floored layer the implied Tr=hTr/h shifts — harmless for the adiabatic (enable_thermodynamics=.false.) isopycnal config; thermo-on isopycnal correctness is OUT OF SCOPE for v1.

logical, public :: cfl_ignore_vanished = .false.

Phase 3: exclude vanished layers from the console MaxCFL / panic / CFL truncation so a thin-layer velocity spike cannot falsely abort.

logical, public :: check_h_positive = .false.

DEBUG GUARD (vcoord-agnostic despite living in this group): abort on the FIRST negative h_layer, naming the pipeline stage that wrote it plus the offending (i,j,k) and that column’s full profile. Without it a negative thickness is only visible later and elsewhere — as a NaN in the console stats, or as an hourly diagnostic minimum — by which point the producing kernel is unidentifiable. Costs one device-side min-reduction over h_layer per instrumented stage (~6% of an outer step at 600x600x50); no H<-D traffic on the healthy path. Default .false. ⇒ not called ⇒ bit-identical.

logical, public :: conservative_floor = .false.

Conservative minimum-thickness mode. When .true. (requires angstrom_h > 0 and VCOORD_LAGRANGIAN — fail-loud otherwise) the non-conservative max(h, angstrom_h) injection is REPLACED by a per-column conservative borrow: a sub-floor layer’s deficit is taken from the surplus layers of the same column, so total thickness, momentum, and every tracer mass are preserved to round-off and the result is independent of the floor value. Fires only where a layer is below floor; a strict no-op elsewhere (isopycnals not pinned). Default .false. ⇒ the legacy injecting floor ⇒ bit-identical.

logical, public :: pgf_skip_nonoverlap = .true.

Grounded-layer PGF gate. Default ON — unlike every other knob in this group this one is a CORRECTNESS fix, not an opt-in, and it is still bit-identical everywhere except VCOORD_LAGRANGIAN (the only coordinate it is applied under).

The FV/Montgomery face PGF is a two-point Jacobian, -(1/ρ0)·[Δp_centre + g·ρ_layer·Δz_centre]/dx. Those two terms cancel AT REST only while the two abutting layer centres sit in a common z-interval whose ambient density IS ρ_layer. In an isopycnal column a layer grounded against sloping topography is squeezed onto the angstrom_h floor on the shallow side while staying massive on the deep side; the two centres are then hundreds of metres apart, the interval between them spans OTHER density classes, and the residual g·(ρ_layer − ρ̄_ambient)·∂z/∂x is a spurious acceleration on a motionless ocean. Nothing bounds it, so it spins a basin-scale current up out of nothing (the seamount_conservative_floor quiescent case reached 6.7 cm/s).

When .true. the face PGF is ZEROED wherever the layer’s z-extents in the two abutting columns do not overlap AND the layer is at the floor on at least one side (<= 2·max(angstrom_h, H_VANISHED), nonoverlap_vanish_tol_for) — i.e. exactly where the layer has wedged out against the bed and there is no common depth to difference the pressure across. Non-overlap ALONE is not grounding: a sigma-seeded stack over a bathymetric step puts layers that are massive on both sides in disjoint z-intervals, and zeroing their PGF while continuity keeps moving their mass breaks the PGF-work / PE exchange (the compat-matrix staircase grew to the CFL panic at step 178; test_ocean_lagrangian_staircase). Overlapping (physically shared) layers are untouched, so the isopycnal interior is unchanged; a wedged-out layer can still be re-wetted by continuity’s own upwind flux and by the barotropic correction. Set .false. to recover the pre-fix behaviour for comparison.

Covers the mont, fv_lite, fv_wright and fv_mom6 PGF forms. The first three build the layer-centre depth in their face passes anyway; fv_mom6 (layer-integrated FV-Bouss) does not, so the buffer is allocated and filled there for this gate ALONE, which is why the decision has to be taken before the PGF slot is initialised. The defect is the geometry, not the quadrature: fv_mom6 reproduces the same at-rest spin-up (En 2.17e-03 at day 2 on seamount_conservative_floor, → 1.9e-27 gated), and so does mont (En 2.242e-03 ungated, → 7.65e-31 gated) even though its Montgomery recursion is a third kind of face expression again — a grounded layer puts the two columns’ interface heights hundreds of metres apart, so M stops being horizontally uniform at rest. gprime differences interface positions directly and has nothing to gate — it is the one form that warns.

logical, public :: reset_vanished_u = .false.

Phase 2: zero the face velocity of a layer vanished on BOTH adjacent cells (a massless layer carries no independent momentum).


Source Code

   type :: ocean_isopycnal_config_t
      !! `&ocean_isopycnal_nml`: grounding-stability controls for the
      !! Lagrangian (isopycnal-class, remap-free) vertical coordinate.
      !! Every knob here engages ONLY under sim_type='ocean' +
      !! VCOORD_LAGRANGIAN, so the whole group is bit-identical on every other
      !! vertical coordinate.  All are default-OFF except
      !! `pgf_skip_nonoverlap`, which is a correctness fix and defaults ON.
      real(wp) :: angstrom_h = 0.0_wp
         !! Phase 1: minimum-thickness floor (m) on the Lagrangian
         !! continuity h-update — MOM6 GV%Angstrom_H analogue used as the
         !! max(h_new, Angstrom_H) clamp. 0.0 ⇒ off ⇒ bit-identical
         !! (the floor loop is skipped). Physical floor (D4 taxonomy), NOT
         !! H_DIV_EPS (too small to bound 1/h) and NOT hardwired H_VANISHED
         !! (that is the skip/merge marker). Recommended run value 1e-3..1e-2 m.
         !! NOT strictly conservative: injects <= angstrom_h*areaT per floored
         !! layer-cell (zero on non-grounding steps). Thermo-on caveat (R7):
         !! the floor lifts h but not the companion hTr, so on a floored layer
         !! the implied Tr=hTr/h shifts — harmless for the adiabatic
         !! (enable_thermodynamics=.false.) isopycnal config; thermo-on
         !! isopycnal correctness is OUT OF SCOPE for v1.
      logical :: reset_vanished_u = .false.
         !! Phase 2: zero the face velocity of a layer vanished on BOTH
         !! adjacent cells (a massless layer carries no independent momentum).
      logical :: cfl_ignore_vanished = .false.
         !! Phase 3: exclude vanished layers from the console MaxCFL / panic /
         !! CFL truncation so a thin-layer velocity spike cannot falsely abort.
      logical :: conservative_floor = .false.
         !! Conservative minimum-thickness mode.  When `.true.` (requires
         !! `angstrom_h > 0` and VCOORD_LAGRANGIAN — fail-loud otherwise) the
         !! non-conservative `max(h, angstrom_h)` injection is REPLACED by a
         !! per-column conservative borrow: a sub-floor layer's deficit is taken
         !! from the surplus layers of the same column, so total thickness,
         !! momentum, and every tracer mass are preserved to round-off and the
         !! result is independent of the floor value.  Fires only where a layer
         !! is below floor; a strict no-op elsewhere (isopycnals not pinned).
         !! Default `.false.` ⇒ the legacy injecting floor ⇒ bit-identical.
      logical :: pgf_skip_nonoverlap = .true.
         !! Grounded-layer PGF gate.  **Default ON** — unlike every other knob
         !! in this group this one is a CORRECTNESS fix, not an opt-in, and it
         !! is still bit-identical everywhere except VCOORD_LAGRANGIAN (the
         !! only coordinate it is applied under).
         !!
         !! The FV/Montgomery face PGF is a two-point Jacobian,
         !! `-(1/ρ0)·[Δp_centre + g·ρ_layer·Δz_centre]/dx`.  Those two terms
         !! cancel AT REST only while the two abutting layer centres sit in a
         !! common z-interval whose ambient density IS `ρ_layer`.  In an
         !! isopycnal column a layer grounded against sloping topography is
         !! squeezed onto the `angstrom_h` floor on the shallow side while
         !! staying massive on the deep side; the two centres are then hundreds
         !! of metres apart, the interval between them spans OTHER density
         !! classes, and the residual `g·(ρ_layer − ρ̄_ambient)·∂z/∂x` is a
         !! spurious acceleration on a motionless ocean.  Nothing bounds it, so
         !! it spins a basin-scale current up out of nothing (the
         !! `seamount_conservative_floor` quiescent case reached 6.7 cm/s).
         !!
         !! When `.true.` the face PGF is ZEROED wherever the layer's z-extents
         !! in the two abutting columns do not overlap AND the layer is at the
         !! floor on at least one side (`<= 2·max(angstrom_h, H_VANISHED)`,
         !! `nonoverlap_vanish_tol_for`) — i.e. exactly where the layer has
         !! wedged out against the bed and there is no common depth to
         !! difference the pressure across.  Non-overlap ALONE is not grounding:
         !! a sigma-seeded stack over a bathymetric step puts layers that are
         !! massive on both sides in disjoint z-intervals, and zeroing their PGF
         !! while continuity keeps moving their mass breaks the PGF-work / PE
         !! exchange (the compat-matrix staircase grew to the CFL panic at step
         !! 178; `test_ocean_lagrangian_staircase`).  Overlapping (physically shared)
         !! layers are untouched, so the isopycnal interior is unchanged; a
         !! wedged-out layer can still be re-wetted by continuity's own upwind
         !! flux and by the barotropic correction.  Set `.false.` to recover the
         !! pre-fix behaviour for comparison.
         !!
         !! Covers the `mont`, `fv_lite`, `fv_wright` and `fv_mom6` PGF forms.
         !! The first three build the layer-centre depth in their face passes
         !! anyway; `fv_mom6` (layer-integrated FV-Bouss) does not, so the
         !! buffer is allocated and filled there for this gate ALONE, which is
         !! why the decision has to be taken before the PGF slot is
         !! initialised.  The defect is the geometry, not the quadrature:
         !! `fv_mom6` reproduces the same at-rest spin-up (En 2.17e-03 at day 2
         !! on `seamount_conservative_floor`, → 1.9e-27 gated), and so does
         !! `mont` (En 2.242e-03 ungated, → 7.65e-31 gated) even though its
         !! Montgomery recursion is a third kind of face expression again —
         !! a grounded layer puts the two columns' interface heights hundreds
         !! of metres apart, so `M` stops being horizontally uniform at rest.
         !! `gprime` differences interface positions directly and has nothing
         !! to gate — it is the one form that warns.
      logical :: check_h_positive = .false.
         !! DEBUG GUARD (vcoord-agnostic despite living in this group): abort on
         !! the FIRST negative `h_layer`, naming the pipeline stage that wrote
         !! it plus the offending `(i,j,k)` and that column's full profile.
         !! Without it a negative thickness is only visible later and elsewhere
         !! — as a NaN in the console stats, or as an hourly diagnostic minimum
         !! — by which point the producing kernel is unidentifiable.
         !! Costs one device-side min-reduction over `h_layer` per instrumented
         !! stage (~6% of an outer step at 600x600x50); no H<-D traffic on the
         !! healthy path. Default `.false.` ⇒ not called ⇒ bit-identical.
   end type ocean_isopycnal_config_t