Overwrite bathymetry b (m, POSITIVE DOWN) on the physical
interior, fill ghosts, re-wrap the periodic/fold seam, re-derive
bt_H_ref = b (the mode-split contract) and re-wrap IT too, then
narrow-push b (+ bt_H_ref) — mirrors the init-time sequence at
rdb_driver.F90 exactly, so a mid-run perturbation sees the same
seam/BT-reference treatment the setup path does. No prognostic
slot is touched.
CAVEAT (mid-run, not a re-seed): does NOT re-derive the ALE
z_ref table (ZSTAR_FULL) or the static land mask + C-grid face
metrics — for those, drive the case from a namelist/restart
instead (matches the recovered precedent’s documented limit).
REFUSED under an ice-shelf cavity (&ocean_cavity_dyn_nml
enable). There the mode-split contract is bt_H_ref = b −
z_draft, so the bt_H_ref = b re-derivation below would silently
delete the ice load from the datum — and even re-deriving it
correctly would not be enough: a new bed changes which columns
GROUND, and this entry point deliberately does not rebuild the wet
mask or the land-masked metrics. Re-seed from a namelist instead.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| type(c_ptr), | intent(in), | value | :: | c_handle | ||
| real(kind=c_double), | intent(in) | :: | b_data(nx_p,ny_p) | |||
| integer(kind=c_int), | intent(in), | value | :: | nx_p | ||
| integer(kind=c_int), | intent(in), | value | :: | ny_p |
| Type | Visibility | Attributes | Name | Initial | |||
|---|---|---|---|---|---|---|---|
| type(ocean_handle_t), | private, | pointer | :: | h | |||
| integer, | private | :: | ierr_local | ||||
| integer, | private | :: | ng | ||||
| logical, | private | :: | wrap_seam |
function rdb_ocean_set_bathymetry(c_handle, b_data, nx_p, ny_p) result(status) & bind(c, name="rdb_ocean_set_bathymetry") !! Overwrite bathymetry `b` (m, POSITIVE DOWN) on the physical !! interior, fill ghosts, re-wrap the periodic/fold seam, re-derive !! `bt_H_ref = b` (the mode-split contract) and re-wrap IT too, then !! narrow-push `b` (+ `bt_H_ref`) — mirrors the init-time sequence at !! `rdb_driver.F90` exactly, so a mid-run perturbation sees the same !! seam/BT-reference treatment the setup path does. No prognostic !! slot is touched. !! !! CAVEAT (mid-run, not a re-seed): does NOT re-derive the ALE !! `z_ref` table (ZSTAR_FULL) or the static land mask + C-grid face !! metrics — for those, drive the case from a namelist/restart !! instead (matches the recovered precedent's documented limit). !! !! REFUSED under an ice-shelf cavity (`&ocean_cavity_dyn_nml !! enable`). There the mode-split contract is `bt_H_ref = b − !! z_draft`, so the `bt_H_ref = b` re-derivation below would silently !! delete the ice load from the datum — and even re-deriving it !! correctly would not be enough: a new bed changes which columns !! GROUND, and this entry point deliberately does not rebuild the wet !! mask or the land-masked metrics. Re-seed from a namelist instead. type(c_ptr), intent(in), value :: c_handle integer(c_int), intent(in), value :: nx_p, ny_p real(c_double), intent(in) :: b_data(nx_p, ny_p) integer(c_int) :: status type(ocean_handle_t), pointer :: h integer :: ng, ierr_local logical :: wrap_seam status = resolve_ocean(c_handle, h) if (status /= OCEAN_STATUS_OK) return if (nx_p /= h%grid%nx_phys .or. ny_p /= h%grid%ny_phys) then call fail("rdb_ocean_set_bathymetry: shape mismatch against the physical interior", & ierr_local, OCEAN_STATUS_ERR_BAD_SHAPE) status = int(ierr_local, c_int) return end if if (h%state%metrics%use_cavity) then call fail("rdb_ocean_set_bathymetry: refused with &ocean_cavity_dyn_nml "// & "enable — the datum is bt_H_ref = b - z_draft, and a mid-run bed "// & "swap would both drop the ice load from it and change which "// & "columns ground (this entry point does not rebuild the wet mask). "// & "Re-seed from a namelist instead.", & ierr_local, OCEAN_STATUS_ERR_SETUP) status = int(ierr_local, c_int) return end if ng = h%grid%nghost ! Single-rank by construction: the API builds its engine through ! `engine_setup` with no compute rank/size (one rank, px = py = 1), so ! the local periodic wrap and the fold below hold the whole grid (the ! fold dispatcher takes its local-kernel branch). Audited for the ! distributed fold (plan site A1): no px > 1 path reaches this. wrap_seam = h%state%bc%periodic_x .or. h%state%bc%periodic_y .or. h%state%bc%north_fold associate (b => h%state%barotropic%b) b(ng + 1:ng + nx_p, ng + 1:ng + ny_p) = real(b_data, wp) call fill_bathymetry_ghosts_array(b, h%grid) if (wrap_seam) then call ocean_periodic_wrap_centre_2d(b, h%grid%nx_total, h%grid%ny_total, & h%grid%nx_phys, h%grid%ny_phys, h%grid%nghost, & h%state%bc%periodic_x, h%state%bc%periodic_y) call ocean_fold_wrap_eta_2d(h%grid, h%state%bc, b) end if !$acc update device(b) end associate ! The isopycnal slopes' bed datum is a copy of `b` (no-op when the ! slot is off); refresh it from the re-wrapped field. if (h%state%slopes%is_init) then call h%state%slopes%set_bathymetry(h%state%barotropic%b) !$acc update device(h%state%slopes%bathy) end if if (h%state%dyn%n_inner >= 1) then associate (bref => h%state%dyn%bt_work%bt_H_ref) bref = h%state%barotropic%b if (wrap_seam) then call ocean_periodic_wrap_centre_2d(bref, h%grid%nx_total, h%grid%ny_total, & h%grid%nx_phys, h%grid%ny_phys, h%grid%nghost, & h%state%bc%periodic_x, h%state%bc%periodic_y) call ocean_fold_wrap_eta_2d(h%grid, h%state%bc, bref) end if !$acc update device(bref) end associate end if status = int(OCEAN_STATUS_OK, c_int) end function rdb_ocean_set_bathymetry