set_bathymetry_island Subroutine

public subroutine set_bathymetry_island(b, grid, max_depth, half_frac)

Flat-bottom basin at max_depth everywhere, except a central square of LAND (b = 0, well below LAND_DEPTH_THRESHOLD). The land square is centred on the physical domain and spans the central 2*half_frac fraction of each axis (e.g. half_frac=0.2 ⇒ the middle 40 % is land). half_frac is taken from &ocean_topo_nml slope_scale at the call site (no new knob).

Fills the FULL array including ghost rows (the formula-bathy ghost-fill gotcha): a ghost b=0 at a wall-adjacent face sends the EOS into its ρ=ρ₀ fallback → spurious density jump → blowup. Ghost rows here inherit the flat max_depth (the land square is strictly interior), so every ghost is ocean.

MPI: the global physical-index offsets and the global domain extents come off grid (i_offset_global / j_offset_global, nx_global / ny_global), so the land square is centred on the WHOLE domain and each rank carves only the part of it that falls inside its own tile. On a single rank the offsets are 0 and global == local, so the fill is byte-identical.

Arguments

Type IntentOptional Attributes Name
real(kind=wp), intent(inout) :: b(:,:)
type(hgrid_t), intent(in) :: grid
real(kind=wp), intent(in) :: max_depth
real(kind=wp), intent(in) :: half_frac

Called by

proc~~set_bathymetry_island~~CalledByGraph proc~set_bathymetry_island set_bathymetry_island proc~ocean_state_seed_from_cfg ocean_state_seed_from_cfg proc~ocean_state_seed_from_cfg->proc~set_bathymetry_island proc~engine_setup engine_setup proc~engine_setup->proc~ocean_state_seed_from_cfg 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 :: ci0
integer, private :: ci1
integer, private :: cj0
integer, private :: cj1
integer, private :: half_i
integer, private :: half_j
real(kind=wp), private :: hf
integer, private :: i
integer, private :: i_phys
integer, private :: ioff
integer, private :: j
integer, private :: j_phys
integer, private :: joff
integer, private :: ng
integer, private :: nxg
integer, private :: nyg

Source Code

   subroutine set_bathymetry_island(b, grid, max_depth, half_frac)
      !! Flat-bottom basin at `max_depth` everywhere, except a central
      !! square of LAND (`b = 0`, well below `LAND_DEPTH_THRESHOLD`).  The
      !! land square is centred on the physical domain and spans the
      !! central `2*half_frac` fraction of each axis (e.g. `half_frac=0.2`
      !! ⇒ the middle 40 % is land).  `half_frac` is taken from
      !! `&ocean_topo_nml slope_scale` at the call site (no new knob).
      !!
      !! Fills the FULL array including ghost rows (the formula-bathy
      !! ghost-fill gotcha): a ghost `b=0` at a wall-adjacent face sends
      !! the EOS into its ρ=ρ₀ fallback → spurious density jump → blowup.
      !! Ghost rows here inherit the flat `max_depth` (the land square is
      !! strictly interior), so every ghost is ocean.
      !!
      !! MPI: the global physical-index offsets and the global domain
      !! extents come off `grid` (`i_offset_global` / `j_offset_global`,
      !! `nx_global` / `ny_global`), so the land square is centred on the
      !! WHOLE domain and each rank carves only the part of it that falls
      !! inside its own tile.  On a single rank the offsets are 0 and
      !! global == local, so the fill is byte-identical.
      real(wp), intent(inout) :: b(:, :)
      type(hgrid_t), intent(in) :: grid
      real(wp), intent(in) :: max_depth, half_frac
      integer :: i, j, i_phys, j_phys, ng, ci0, ci1, cj0, cj1, half_i, half_j
      integer :: ioff, joff, nxg, nyg
      real(wp) :: hf

      ioff = grid%i_offset_global
      joff = grid%j_offset_global
      nxg = grid%nx_global
      nyg = grid%ny_global

      ng = grid%nghost
      hf = half_frac
      if (hf <= 0.0_wp) hf = 0.2_wp     ! sensible default if knob left 0
      if (hf > 0.49_wp) hf = 0.49_wp    ! keep at least one wet ring inside

      ! Land-square physical-index bounds (centred on the GLOBAL domain), inclusive.
      half_i = nint(hf*real(nxg, wp))
      half_j = nint(hf*real(nyg, wp))
      ci0 = nxg/2 - half_i + 1
      ci1 = nxg/2 + half_i
      cj0 = nyg/2 - half_j + 1
      cj1 = nyg/2 + half_j

      ! Flat basin everywhere (incl. ghosts), then carve the interior land.
      ! The global physical index of local cell (i,j) is (i_phys + ioff).
      b = max_depth
      do j = 1, size(b, 2)
         j_phys = j - ng
         do i = 1, size(b, 1)
            i_phys = i - ng
            if ((i_phys + ioff) >= ci0 .and. (i_phys + ioff) <= ci1 .and. &
                (j_phys + joff) >= cj0 .and. (j_phys + joff) <= cj1) then
               b(i, j) = 0.0_wp   ! LAND (< LAND_DEPTH_THRESHOLD)
            end if
         end do
      end do
   end subroutine set_bathymetry_island