configure_ocean_wetdry Subroutine

public subroutine configure_ocean_wetdry(cfg, ocean_state, grid, compute_rank)

Dynamic wetting/drying (docs/ocean_wetdry_plan.md): copy the &ocean_wetdry_nml knobs onto the BT workstate, allocate the wd_* workspaces (lazy — absent when the knob is off, so the default path carries no new arrays and stays byte-identical), and seed the hysteresis wet mask from the seeded bathymetry (barotropic%b — the same array configure_ocean_bt_split later latches into bt_H_ref; bt_eta is still 0 here). Must run BEFORE the restart read (so wd_wet_dyn is allocated + registered when the registry walk runs and a warm restart overwrites the seed with the saved front state) and BEFORE ocean_state_enter_data (host seeding; the enter_data walk attaches whatever is allocated).

Arguments

Type IntentOptional Attributes Name
type(config_t), intent(in) :: cfg
type(ocean_state_t), intent(inout) :: ocean_state
type(hgrid_t), intent(in) :: grid
integer, intent(in) :: compute_rank

Calls

proc~~configure_ocean_wetdry~~CallsGraph proc~configure_ocean_wetdry configure_ocean_wetdry info info proc~configure_ocean_wetdry->info to_string to_string proc~configure_ocean_wetdry->to_string warning warning proc~configure_ocean_wetdry->warning

Called by

proc~~configure_ocean_wetdry~~CalledByGraph proc~configure_ocean_wetdry configure_ocean_wetdry proc~engine_setup engine_setup proc~engine_setup->proc~configure_ocean_wetdry 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
real(kind=wp), private :: d0
integer, private :: i
integer, private :: j
integer, private :: n_intertidal
integer, private :: ng
integer, private :: nx_w
integer, private :: ny_w

Source Code

   subroutine configure_ocean_wetdry(cfg, ocean_state, grid, compute_rank)
      !! Dynamic wetting/drying (docs/ocean_wetdry_plan.md): copy the
      !! `&ocean_wetdry_nml` knobs onto the BT workstate, allocate the
      !! wd_* workspaces (lazy — absent when the knob is off, so the
      !! default path carries no new arrays and stays byte-identical),
      !! and seed the hysteresis wet mask from the seeded bathymetry
      !! (`barotropic%b` — the same array `configure_ocean_bt_split`
      !! later latches into `bt_H_ref`; `bt_eta` is still 0 here).
      !! Must run BEFORE the restart read (so `wd_wet_dyn` is allocated
      !! + registered when the registry walk runs and a warm restart
      !! overwrites the seed with the saved front state) and BEFORE
      !! `ocean_state_enter_data` (host seeding; the enter_data walk
      !! attaches whatever is allocated).
      type(config_t), intent(in) :: cfg
      type(ocean_state_t), intent(inout) :: ocean_state
      type(hgrid_t), intent(in) :: grid
      integer, intent(in) :: compute_rank
      integer :: nx_w, ny_w, i, j, ng, n_intertidal
      real(wp) :: d0

      ocean_state%dyn%bt_work%wetdry_enable = cfg%ocean%wetdry%enable
      if (.not. cfg%ocean%wetdry%enable) return

      ocean_state%dyn%bt_work%wd_dry_depth = cfg%ocean%wetdry%dry_depth
      ocean_state%dyn%bt_work%wd_rewet_depth = cfg%ocean%wetdry%rewet_depth
      nx_w = grid%nx_total
      ny_w = grid%ny_total
      associate (bt_work => ocean_state%dyn%bt_work)
         allocate (bt_work%wd_wet_dyn(nx_w, ny_w), source=1.0_wp)
         allocate (bt_work%wd_theta(nx_w, ny_w), source=1.0_wp)
         allocate (bt_work%wd_flux_x(nx_w + 1, ny_w), source=0.0_wp)
         allocate (bt_work%wd_flux_y(nx_w, ny_w + 1), source=0.0_wp)
         allocate (bt_work%wd_open_u(nx_w + 1, ny_w), source=1.0_wp)
         allocate (bt_work%wd_open_v(nx_w, ny_w + 1), source=1.0_wp)
         ! Seed the hysteresis mask from the seeded bathymetry (host
         ! loop, pre-enter_data; eta = 0 at configure so D0 = b).  Cells
         ! inside the hysteresis band seed WET — the first substep's own
         ! update settles them.  A restart carrying `wd_wet_dyn`
         ! overwrites this seed (this configure runs BEFORE the registry
         ! read — see the driver ordering comment).
         do j = 1, ny_w
            do i = 1, nx_w
               d0 = ocean_state%barotropic%b(i, j)
               ! `d0 < dry_depth` is the live criterion.  The `wet_mask<=0`
               ! term is belt-and-suspenders: with the knob ON a static-land
               ! column has `b < -land_margin < 0 < dry_depth`, so the first
               ! test already fires — it only guards against a caller seeding
               ! wet_mask with a stricter cutoff than the depth test implies.
               if (d0 < cfg%ocean%wetdry%dry_depth .or. &
                   ocean_state%multilayer%wet_mask(i, j) <= 0.0_wp) then
                  bt_work%wd_wet_dyn(i, j) = 0.0_wp
               end if
            end do
         end do
      end associate
      if (compute_rank == 0) then
         call logger%info("Wet/dry:          ON  dry_depth = "// &
                          to_string(cfg%ocean%wetdry%dry_depth)// &
                          " m, rewet_depth = "// &
                          to_string(cfg%ocean%wetdry%rewet_depth)// &
                          " m (upwind BT faces + positive-definite "// &
                          "outflow limiter + bed-blocking gate)")
         ! v2 semantic trap (plan §10.1): with wet/dry ON the static land
         ! seed cutoff moves to `b < -land_margin`, so any column whose bed
         ! is in the band `[-land_margin, LAND_DEPTH_THRESHOLD)` is NOT
         ! static land any more — it becomes a dynamically-dry INTERTIDAL
         ! flat that floods once eta clears dry_depth.  This affects formula
         ! topos that flag land as b ≈ 0 (island / double_drake), file
         ! bathymetry with a b = 1 m land-flag convention, AND generated
         ! topos like neverworld2 that force continents into the band — so
         ! a name-based check is incomplete.  Scan the seeded interior
         ! bathymetry directly and warn (rank 0) with the exact count when
         ! ANY intertidal-band cell exists.  It's a WARNING, not an abort:
         ! intertidal flats can be intentional; the message just makes the
         ! regime change loud and specific.
         ng = grid%nghost
         n_intertidal = 0
         do j = ng + 1, ny_w - ng
            do i = ng + 1, nx_w - ng
               d0 = ocean_state%barotropic%b(i, j)
               if (d0 >= -cfg%ocean%wetdry%land_margin .and. &
                   d0 < LAND_DEPTH_THRESHOLD) then
                  n_intertidal = n_intertidal + 1
               end if
            end do
         end do
         if (n_intertidal > 0) then
            call logger%warning("Wet/dry: "//to_string(n_intertidal)// &
                                " interior cell(s) have bed elevations in the "// &
                                "intertidal band [-land_margin, "// &
                                "LAND_DEPTH_THRESHOLD) — under the wetdry-aware "// &
                                "static seed (land iff b < -land_margin) these "// &
                                "are LIVE intertidal flats that flood when eta "// &
                                "clears dry_depth, NOT static land.  If you "// &
                                "intended static continents, use bed elevations "// &
                                "b < -land_margin (= "// &
                                to_string(-cfg%ocean%wetdry%land_margin)//" m).")
         end if
      end if
   end subroutine configure_ocean_wetdry