configure_ocean_porous Subroutine

public subroutine configure_ocean_porous(cfg, ocean_state, grid, compute_rank, ierr)

Configure porous barriers (&ocean_porous_nml, Adcroft 2013). Grows the ocean_metrics_t porous arrays to full face size and fills the STATIC along-face d_min/d_max/d_avg statistics; the layer-averaged open fractions themselves are recomputed on the device every RK2 stage (they depend on the interface heights).

MUST run AFTER bathymetry is set (ocean_state%barotropic%b) and land masking, and BEFORE ocean_state_enter_data — the realloc has to happen before the device map, and the host fill is what the copyin captures. Leaves the placeholder-sized arrays untouched when the knob is off (bit-identical).

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
integer, intent(out), optional :: ierr

Non-zero on a porous-barrier configuration conflict when present; absent behaves as today (error stop).


Calls

proc~~configure_ocean_porous~~CallsGraph proc~configure_ocean_porous configure_ocean_porous info info proc~configure_ocean_porous->info proc~fail fail proc~configure_ocean_porous->proc~fail proc~metrics_porous_alloc metrics_porous_alloc proc~configure_ocean_porous->proc~metrics_porous_alloc proc~parse_porous_eta_interp parse_porous_eta_interp proc~configure_ocean_porous->proc~parse_porous_eta_interp proc~parse_porous_source parse_porous_source proc~configure_ocean_porous->proc~parse_porous_source proc~porous_fill_stats_resolved porous_fill_stats_resolved proc~configure_ocean_porous->proc~porous_fill_stats_resolved proc~porous_stats_are_ordered porous_stats_are_ordered proc~configure_ocean_porous->proc~porous_stats_are_ordered to_string to_string proc~configure_ocean_porous->to_string error error proc~fail->error proc~error_ring_push error_ring_push proc~fail->proc~error_ring_push proc~corner_is_wet corner_is_wet proc~porous_fill_stats_resolved->proc~corner_is_wet

Called by

proc~~configure_ocean_porous~~CalledByGraph proc~configure_ocean_porous configure_ocean_porous proc~engine_setup engine_setup proc~engine_setup->proc~configure_ocean_porous 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
integer, private :: interp
integer, private :: nx
integer, private :: ny
integer, private :: nz
integer, private :: src

Source Code

   subroutine configure_ocean_porous(cfg, ocean_state, grid, compute_rank, ierr)
      !! Configure porous barriers (`&ocean_porous_nml`, Adcroft 2013).
      !! Grows the `ocean_metrics_t` porous arrays to full face size and
      !! fills the STATIC along-face `d_min`/`d_max`/`d_avg` statistics;
      !! the layer-averaged open fractions themselves are recomputed on
      !! the device every RK2 stage (they depend on the interface
      !! heights).
      !!
      !! MUST run AFTER bathymetry is set (`ocean_state%barotropic%b`)
      !! and land masking, and BEFORE `ocean_state_enter_data` — the
      !! realloc has to happen before the device map, and the host fill
      !! is what the `copyin` captures.  Leaves the placeholder-sized
      !! arrays untouched when the knob is off (bit-identical).
      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, intent(out), optional :: ierr
         !! Non-zero on a porous-barrier configuration conflict when
         !! present; absent behaves as today (`error stop`).

      integer :: src, interp, nx, ny, nz

      if (.not. cfg%ocean%porous%enable) then
         if (present(ierr)) ierr = OCEAN_STATUS_OK
         return
      end if

      if (.not. ocean_state%multilayer%is_init) then
         call fail("&ocean_porous_nml enable requires the ocean multilayer "// &
                   "path (the open fractions are per-layer)", ierr, OCEAN_STATUS_ERR_SETUP)
         return
      end if

      src = parse_porous_source(cfg%ocean%porous%source)
      select case (src)
      case (POROUS_SOURCE_RESOLVED)
         continue
      case (POROUS_SOURCE_FILE)
         call fail("&ocean_porous_nml source='file' (an offline "// &
                   "subgrid-bathymetry file, MOM6 topog_edge.nc) is not "// &
                   "implemented — it needs the file-forcing backend that "// &
                   "&ocean_bt_nml wave_drag_form='file' also waits on. "// &
                   "Use source='resolved' (a documented proxy).", ierr, OCEAN_STATUS_ERR_SETUP)
         return
      case default
         call fail("&ocean_porous_nml source='"// &
                   trim(cfg%ocean%porous%source)//"' is not recognised", ierr, OCEAN_STATUS_ERR_SETUP)
         return
      end select

      interp = parse_porous_eta_interp(cfg%ocean%porous%eta_interp)
      if (interp < 0) then
         call fail("&ocean_porous_nml eta_interp='"// &
                   trim(cfg%ocean%porous%eta_interp)//"' is not recognised", ierr, OCEAN_STATUS_ERR_SETUP)
         return
      end if

      nx = grid%nx_total
      ny = grid%ny_total
      nz = ocean_state%multilayer%nz_ml

      call metrics_porous_alloc(ocean_state%metrics, grid, nz)
      ocean_state%metrics%porous_eta_interp = interp
      ! The namelist knob is a DEPTH (positive below the surface); the
      ! kernel gate compares HEIGHTS, so flip the sign once here.
      ocean_state%metrics%porous_mask_depth = -cfg%ocean%porous%masking_depth

      ! SIGN CONVENTION.  The Adcroft fit works in topographic HEIGHTS
      ! (positive up, negative below the sea surface) so that they compare
      ! directly against interface heights.  On the ocean path
      ! `barotropic%b` holds the reference column DEPTH, positive down
      ! (`SSH = sum(h_layer) - b`), so it is negated once, here, and every
      ! porous array downstream is a height.  Bathymetry is static, so a
      ! snapshot on the metrics slot is exact and lets the per-step
      ! recompute stay a metrics-only kernel.
      ocean_state%metrics%por_bed = -ocean_state%barotropic%b

      call porous_fill_stats_resolved(nx, ny, ocean_state%metrics%por_bed, &
                                      ocean_state%metrics%wet_T, &
                                      ocean_state%metrics%por_dmin_u, &
                                      ocean_state%metrics%por_dmax_u, &
                                      ocean_state%metrics%por_davg_u, &
                                      ocean_state%metrics%por_dmin_v, &
                                      ocean_state%metrics%por_dmax_v, &
                                      ocean_state%metrics%por_davg_v)

      ! READER-BOUNDARY ASSERTION.  `m = (d_avg-d_min)/(d_max-d_min)` is
      ! only a valid Adcroft parameter when `d_min <= d_avg <= d_max`.
      ! The resolved fill cannot break that (d_avg is a convex combination
      ! of the samples d_min/d_max bracket), but a FILE-backed source
      ! could, so the check sits here — at the boundary every source
      ! passes through — rather than inside one filler.
      if (.not. porous_stats_are_ordered(nx + 1, ny, &
                                         ocean_state%metrics%por_dmin_u, &
                                         ocean_state%metrics%por_dmax_u, &
                                         ocean_state%metrics%por_davg_u)) then
         call fail("&ocean_porous_nml: u-face subgrid statistics violate "// &
                   "d_min <= d_avg <= d_max", ierr, OCEAN_STATUS_ERR_SETUP)
         return
      end if
      if (.not. porous_stats_are_ordered(nx, ny + 1, &
                                         ocean_state%metrics%por_dmin_v, &
                                         ocean_state%metrics%por_dmax_v, &
                                         ocean_state%metrics%por_davg_v)) then
         call fail("&ocean_porous_nml: v-face subgrid statistics violate "// &
                   "d_min <= d_avg <= d_max", ierr, OCEAN_STATUS_ERR_SETUP)
         return
      end if

      ! Flip the master switch LAST: every kernel branches on it, and the
      ! stats must be in place before any of them can read a narrowed width.
      ocean_state%metrics%use_porous = .true.

      if (compute_rank == 0) then
         call logger%info("Porous barriers:  ON (Adcroft 2013), source='"// &
                          trim(cfg%ocean%porous%source)//"' eta_interp='"// &
                          trim(cfg%ocean%porous%eta_interp)//"' masking_depth="// &
                          to_string(cfg%ocean%porous%masking_depth)//" m")
         call logger%info("                  source='resolved' is an along-face "// &
                          "statistic of the RESOLVED bathymetry, a documented "// &
                          "proxy for true subgrid data")
      end if
      if (present(ierr)) ierr = OCEAN_STATUS_OK
   end subroutine configure_ocean_porous