configure_ocean_drag Subroutine

public subroutine configure_ocean_drag(cfg, ocean_state, compute_rank, ierr)

Bottom-drag variant + coefficients, the continuity PPM positivity guard, and the BT-budget diagnostic probe — plus their rank-0 log lines. All knobs default off/zero (bit-identical to pre-knob nmls).

Arguments

Type IntentOptional Attributes Name
type(config_t), intent(in) :: cfg
type(ocean_state_t), intent(inout) :: ocean_state
integer, intent(in) :: compute_rank
integer, intent(out), optional :: ierr

Non-zero on an isopycnal-floor configuration conflict when present; absent behaves as today (error stop).


Calls

proc~~configure_ocean_drag~~CallsGraph proc~configure_ocean_drag configure_ocean_drag info info proc~configure_ocean_drag->info proc~eos_apply_tfreeze_set eos_apply_tfreeze_set proc~configure_ocean_drag->proc~eos_apply_tfreeze_set proc~fail fail proc~configure_ocean_drag->proc~fail proc~parse_bdrag_variant parse_bdrag_variant proc~configure_ocean_drag->proc~parse_bdrag_variant proc~parse_eos_variant parse_eos_variant proc~configure_ocean_drag->proc~parse_eos_variant proc~parse_ocean_vcoord_type parse_ocean_vcoord_type proc~configure_ocean_drag->proc~parse_ocean_vcoord_type proc~parse_tfreeze_set parse_tfreeze_set proc~configure_ocean_drag->proc~parse_tfreeze_set to_string to_string proc~configure_ocean_drag->to_string warning warning proc~configure_ocean_drag->warning error error proc~fail->error proc~error_ring_push error_ring_push proc~fail->proc~error_ring_push proc~parse_vcoord_type parse_vcoord_type proc~parse_ocean_vcoord_type->proc~parse_vcoord_type

Called by

proc~~configure_ocean_drag~~CalledByGraph proc~configure_ocean_drag configure_ocean_drag proc~engine_setup engine_setup proc~engine_setup->proc~configure_ocean_drag 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

Source Code

   subroutine configure_ocean_drag(cfg, ocean_state, compute_rank, ierr)
      !! Bottom-drag variant + coefficients, the continuity PPM positivity
      !! guard, and the BT-budget diagnostic probe — plus their rank-0 log
      !! lines.  All knobs default off/zero (bit-identical to pre-knob nmls).
      type(config_t), intent(in) :: cfg
      type(ocean_state_t), intent(inout) :: ocean_state
      integer, intent(in) :: compute_rank
      integer, intent(out), optional :: ierr
         !! Non-zero on an isopycnal-floor configuration conflict when
         !! present; absent behaves as today (`error stop`).

      ! EOS variant FIRST: this is the earliest configure_ocean_* call, so
      ! `ocean_state%eos%variant` is set before the EOS-handle is copied into
      ! the vmix / EPBL / kappa-shear slots (in configure_ocean_lateral /
      ! _epbl / _kappa_shear).  The device-callable gate + the FV_WRIGHT
      ! cross-check run later, in configure_ocean_pgf (post pgf-variant parse).
      ocean_state%eos%variant = parse_eos_variant(cfg%ocean%eos%eos)
      ! Potential-density reference pressure.  Assigned HERE, in the
      ! earliest configure_ocean_* call, so the value is already on the
      ! handle when it is copied into the vmix / EPBL / kappa-shear slots
      ! further down — and before `enter_data`, so the mapped copies carry
      ! it.  `eos_t` is a flat POD read by value into the `_impl` calls, so
      ! this host assignment owes no `!$acc update device` under
      ! mem:separate (same contract as `rho0`/`rho_ref` on the PGF slot).
      ! Horizontally uniform by design — see the knob's FORD docstring.
      ocean_state%eos%p_ref = cfg%ocean%eos%p_ref
      ! Freezing-point (liquidus) coefficient set — same site, same
      ! reasons, and one more: the ICE slot reads the god-state handle
      ! directly (`engine%state%eos` is what `ice_frazil_accumulate`,
      ! `ice_frazil_uptake` and `ice_compute_basal_flux` are handed), so
      ! landing the set here puts it on the ONE handle every liquidus
      ! consumer sees, before any copy is taken and before `enter_data`.
      ! An unrecognised string is already fatal in `validate_config`;
      ! `eos_apply_tfreeze_set` leaves the handle untouched for it.
      call eos_apply_tfreeze_set(ocean_state%eos, &
                                 parse_tfreeze_set(cfg%ocean%eos%tfreeze_set))
      if (compute_rank == 0) then
         call logger%info("EOS variant:      "//trim(cfg%ocean%eos%eos))
         if (parse_tfreeze_set(cfg%ocean%eos%tfreeze_set) /= TFREEZE_SET_SEAICE) then
            call logger%info("Liquidus set:     "//trim(cfg%ocean%eos%tfreeze_set)// &
                             " (ISOMIP+ / Asay-Davis et al. 2016 Table 4; the "// &
                             "default 'seaice' SIS2 set is ~0.03 degC warmer at S=34.5)")
         end if
      end if

      ocean_state%bdrag%variant = parse_bdrag_variant(cfg%ocean%bdrag%form)
      ocean_state%bdrag%c_drag = cfg%ocean%bdrag%cd
      ocean_state%bdrag%r_linear = cfg%ocean%bdrag%r
      ocean_state%bdrag%hbbl = cfg%ocean%bdrag%hbbl
      ocean_state%bdrag%drag_bg_vel = cfg%ocean%bdrag%bg_vel
      ocean_state%bdrag%bbl_thick_min = cfg%ocean%bdrag%bbl_thick_min
      ocean_state%bdrag%bed_factor = cfg%ocean%bdrag%bed_factor
      ocean_state%bdrag%channel_drag = cfg%ocean%bdrag%channel_drag
      ocean_state%bdrag%cdrag_side = cfg%ocean%bdrag%cdrag_side
      ocean_state%bdrag%implicit = cfg%ocean%bdrag%implicit

      ! Continuity PPM positivity guard (MOM6 PPM_limit_pos analogue).
      ocean_state%continuity%use_ppm_limit_pos = cfg%ocean%continuity%ppm_limit_pos
      ocean_state%continuity%renorm_consistent_flux = cfg%ocean%continuity%renorm_consistent_flux
      ! Wet/dry composition: the Newton uhbt renormalisation's donor
      ! re-pick + CFL bracket destabilise the drying front (h_layer goes
      ! negative, test_ocean_wetdry_driver) — wet/dry keeps the legacy
      ! single-step form it was validated on.
      ocean_state%continuity%renorm_legacy_single_step = cfg%ocean%wetdry%enable
      ocean_state%continuity%h_min = cfg%ocean%continuity%h_min
      ocean_state%continuity%vol_cfl = cfg%ocean%continuity%vol_cfl
      if (compute_rank == 0 .and. cfg%ocean%continuity%ppm_limit_pos) then
         call logger%info("Continuity PPM:   positivity guard ON (MOM6 PPM_limit_pos), "// &
                          "h_min = "//to_string(cfg%ocean%continuity%h_min)//" m")
      end if
      ! Positive-definite split continuity (MOM6-prevention + Roundabout-conservation).
      ! h_lim = angstrom_h on VCOORD_LAGRANGIAN, else 0 (⇒ P1 floor inert on
      ! non-Lagrangian coords).  Default off ⇒ bit-identical.
      ocean_state%continuity%positive_definite = cfg%ocean%continuity%positive_definite
      if (parse_ocean_vcoord_type(cfg%vcoord_type) == VCOORD_LAGRANGIAN) then
         ocean_state%continuity%h_lim = cfg%ocean%isopycnal%angstrom_h
      else
         ocean_state%continuity%h_lim = 0.0_wp
      end if
      if (compute_rank == 0 .and. cfg%ocean%continuity%positive_definite) then
         call logger%info("Continuity PD:    positive_definite ON (h>=h_lim, zero mass "// &
                          "created), h_lim = "//to_string(ocean_state%continuity%h_lim)//" m")
      end if
      ! Phase-1 Lagrangian minimum-thickness floor (MOM6 Angstrom_H analogue).
      ! Only passed to the h-update kernels when the active vcoord is
      ! VCOORD_LAGRANGIAN (gated in rdb_ocean_dyn at the call site). 0 = off.
      ocean_state%continuity%angstrom_h = cfg%ocean%isopycnal%angstrom_h
      if (compute_rank == 0 .and. cfg%ocean%isopycnal%angstrom_h > 0.0_wp) then
         call logger%info("Isopycnal floor:  angstrom_h = "// &
                          to_string(cfg%ocean%isopycnal%angstrom_h)//" m (Lagrangian only)")
      end if
      ! Conservative minimum-thickness mode: replaces the injecting floor with a
      ! per-column borrow (rdb_ocean_min_thickness), invoked from the dyn
      ! continuity site. Fail-loud: needs angstrom_h > 0 AND VCOORD_LAGRANGIAN.
      ocean_state%continuity%conservative_floor = cfg%ocean%isopycnal%conservative_floor
      if (cfg%ocean%isopycnal%conservative_floor) then
         if (cfg%ocean%isopycnal%angstrom_h <= 0.0_wp) then
            call fail("ocean_isopycnal_nml: conservative_floor=.true. requires "// &
                      "angstrom_h > 0 (nothing to floor to).", ierr, OCEAN_STATUS_ERR_SETUP)
            return
         end if
         if (parse_ocean_vcoord_type(cfg%vcoord_type) /= VCOORD_LAGRANGIAN) then
            call fail("ocean_isopycnal_nml: conservative_floor=.true. is only "// &
                      "valid with vcoord_type='lagrangian' (isopycnal path).", ierr, OCEAN_STATUS_ERR_SETUP)
            return
         end if
         if (compute_rank == 0) then
            call logger%info("Isopycnal floor:  conservative_floor = ON "// &
                             "(per-column borrow, mass/momentum/tracer conserving)")
         end if
      end if
      ! Phase-2/3 Lagrangian grounding-stability knobs on ocean_dyn_t.
      ! Gates tested at the dyn call sites; bit-identical when off.
      ocean_state%dyn%angstrom_h = cfg%ocean%isopycnal%angstrom_h
      ocean_state%dyn%reset_vanished_u = cfg%ocean%isopycnal%reset_vanished_u
      ocean_state%dyn%cfl_ignore_vanished = cfg%ocean%isopycnal%cfl_ignore_vanished
      ocean_state%dyn%check_h_positive = cfg%ocean%isopycnal%check_h_positive
      if (compute_rank == 0) then
         if (cfg%ocean%isopycnal%reset_vanished_u) then
            call logger%info("Isopycnal reset:  reset_vanished_u = ON (Lagrangian only)")
         end if
         if (cfg%ocean%isopycnal%cfl_ignore_vanished) then
            call logger%info("Isopycnal CFL:    cfl_ignore_vanished = ON (Lagrangian only)")
         end if
      end if
      if (compute_rank == 0 .and. cfg%ocean%continuity%vol_cfl) then
         call logger%info("Continuity PPM:   swept-volume face thickness ON (MOM6 vol_CFL)")
      end if

      ! Ghost-band poison debug knob.
      ocean_state%dyn%poison_ghosts = cfg%ocean%mpi%poison_ghosts

      ! BT-budget diagnostic probe — heavy when on (D->H + 16 prints/step).
      ocean_state%dyn%debug_bt_budget = cfg%ocean%debug%budget
      if (compute_rank == 0 .and. cfg%ocean%debug%budget) then
         call logger%info("BT-budget probe:  ENABLED (per-step per-region "// &
                          "power decomposition)")
      end if

      ! KE attribution meter — heavy when on (serialises the apply chain).
      ocean_state%dyn%ke_probe%enable = cfg%ocean%debug%ke_attr
      ocean_state%dyn%ke_probe%start_step = cfg%ocean%debug%ke_attr_start_step
      ocean_state%dyn%ke_probe%end_step = cfg%ocean%debug%ke_attr_end_step
      ocean_state%dyn%chksum_probe%enable = cfg%ocean%debug%chksum
      ocean_state%dyn%chksum_probe%start_step = cfg%ocean%debug%chksum_start_step
      ocean_state%dyn%chksum_probe%end_step = cfg%ocean%debug%chksum_end_step
      ocean_state%dyn%chksum_probe%interior = cfg%ocean%debug%chksum_interior
      if (compute_rank == 0 .and. cfg%ocean%debug%ke_attr) then
         call logger%info("KE-attr meter:    ENABLED (per-segment layer-KE "// &
                          "rows, steps "//to_string(cfg%ocean%debug%ke_attr_start_step)// &
                          " to "//to_string(cfg%ocean%debug%ke_attr_end_step)//")")
      end if
      if (compute_rank == 0) then
         call logger%info("Bottom drag:      "//trim(cfg%ocean%bdrag%form)// &
                          "  C_d="//to_string(cfg%ocean%bdrag%cd)// &
                          "  r="//to_string(cfg%ocean%bdrag%r)//" 1/s")
         if (cfg%ocean%bdrag%hbbl > 0.0_wp) then
            call logger%info("Bottom drag BBL:  HBBL="//to_string(cfg%ocean%bdrag%hbbl)// &
                             " m  bg_vel="//to_string(cfg%ocean%bdrag%bg_vel)// &
                             " m/s  thick_min="//to_string(cfg%ocean%bdrag%bbl_thick_min)//" m")
         else
            call logger%info("Bottom drag BBL:  bed-layer only (HBBL=0)")
            ! Bed-only mode drags the face's first LIVE layer `k_bot_u/v`.
            ! Under z_fixed that index is filled at configure
            ! (`configure_ocean_k_bot`) and skips the static bed fillers, so
            ! the bed-only mode reaches water there.  `k_bot ≡ 1` under
            ! zstar_full (its bed-side layers vanish DYNAMICALLY, no static
            ! pattern) and, until `configure_ocean_k_bot` learns it, under
            ! zstar (static z_fixed fillers): k = 1 is an inert filler in
            ! every column shallower than the deepest nominal interface and
            ! almost the whole domain runs with NO bottom drag.  HBBL mode
            ! accumulates thickness from the bed up, skips those fillers and
            ! reaches the live bottom layer.
            if ((cfg%ocean%bdrag%cd > 0.0_wp .or. cfg%ocean%bdrag%r > 0.0_wp) .and. &
                (parse_ocean_vcoord_type(cfg%vcoord_type) == VCOORD_ZSTAR .or. &
                 parse_ocean_vcoord_type(cfg%vcoord_type) == VCOORD_ZSTAR_FULL)) then
               call logger%warning("&ocean_bdrag_nml hbbl = 0 (bed-layer-only drag) under "// &
                                   "vcoord_type = '"//trim(cfg%vcoord_type)//"': the drag "// &
                                   "acts on layer k = 1, an inert filler in every column "// &
                                   "shallower than the deepest nominal layer, so those "// &
                                   "columns get NO bottom drag.  Set hbbl > 0 (MOM6 "// &
                                   "OM4/OM_1deg: HBBL = 10 m, bg_vel = 0.1 m/s).")
            end if
         end if
         if (cfg%ocean%bdrag%channel_drag) then
            call logger%info("Channel drag:     ON  cdrag_side="// &
                             to_string(cfg%ocean%bdrag%cdrag_side))
         end if
      end if
      if (present(ierr)) ierr = OCEAN_STATUS_OK
   end subroutine configure_ocean_drag