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.
| Type | Intent | Optional | 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 |
| 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 |
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