rdb_ocean_obc.F90 Source File

Ocean open-boundary nesting state.


This file depends on

sourcefile~~rdb_ocean_obc.f90~~EfferentGraph sourcefile~rdb_ocean_obc.f90 rdb_ocean_obc.F90 sourcefile~rdb_constants.f90 rdb_constants.F90 sourcefile~rdb_ocean_obc.f90->sourcefile~rdb_constants.f90 sourcefile~rdb_grid.f90 rdb_grid.F90 sourcefile~rdb_ocean_obc.f90->sourcefile~rdb_grid.f90 sourcefile~rdb_mem_report.f90 rdb_mem_report.F90 sourcefile~rdb_ocean_obc.f90->sourcefile~rdb_mem_report.f90 sourcefile~rdb_grid.f90->sourcefile~rdb_constants.f90 sourcefile~rdb_mem_report.f90->sourcefile~rdb_constants.f90

Files dependent on this one

sourcefile~~rdb_ocean_obc.f90~~AfferentGraph sourcefile~rdb_ocean_obc.f90 rdb_ocean_obc.F90 sourcefile~rdb_ocean_state.f90 rdb_ocean_state.F90 sourcefile~rdb_ocean_state.f90->sourcefile~rdb_ocean_obc.f90 sourcefile~rdb_driver.f90 rdb_driver.F90 sourcefile~rdb_driver.f90->sourcefile~rdb_ocean_state.f90 sourcefile~rdb_ocean_engine.f90 rdb_ocean_engine.F90 sourcefile~rdb_driver.f90->sourcefile~rdb_ocean_engine.f90 sourcefile~rdb_handle.f90 rdb_handle.F90 sourcefile~rdb_handle.f90->sourcefile~rdb_ocean_state.f90 sourcefile~rdb_handle.f90->sourcefile~rdb_ocean_engine.f90 sourcefile~rdb_ocean_diag_derived.f90 rdb_ocean_diag_derived.F90 sourcefile~rdb_ocean_diag_derived.f90->sourcefile~rdb_ocean_state.f90 sourcefile~rdb_ocean_diag_fills.f90 rdb_ocean_diag_fills.F90 sourcefile~rdb_ocean_diag_derived.f90->sourcefile~rdb_ocean_diag_fills.f90 sourcefile~rdb_ocean_diag_fills.f90->sourcefile~rdb_ocean_state.f90 sourcefile~rdb_ocean_engine.f90->sourcefile~rdb_ocean_state.f90 sourcefile~rdb_ocean_engine.f90->sourcefile~rdb_ocean_diag_derived.f90 sourcefile~rdb_ocean_engine.f90->sourcefile~rdb_ocean_diag_fills.f90 sourcefile~rdb_ocean_setup.f90 rdb_ocean_setup.F90 sourcefile~rdb_ocean_engine.f90->sourcefile~rdb_ocean_setup.f90 sourcefile~rdb_ocean_setup.f90->sourcefile~rdb_ocean_state.f90 sourcefile~rdb_ocean_api.f90 rdb_ocean_api.F90 sourcefile~rdb_ocean_api.f90->sourcefile~rdb_handle.f90 sourcefile~rdb_ocean_api.f90->sourcefile~rdb_ocean_diag_derived.f90 sourcefile~rdb_ocean_api.f90->sourcefile~rdb_ocean_diag_fills.f90 sourcefile~rdb_ocean_api.f90->sourcefile~rdb_ocean_engine.f90

Source Code

!! Ocean open-boundary nesting state.
module rdb_ocean_obc
   !! Parent-state ingestion + interpolation state for nesting a regional
   !! ocean run inside a global/basin parent. Distinct from coastal
   !! `BC_NESTED`: parent state on a coarser mesh (ingest + remap onto our
   !! vertical grid), tides composed in via `rdb_ocean_tides`, mandatory
   !! T/S clamp, and a Flow-Relaxation-Scheme (FRS) zone of `nrelax` cells
   !! rather than a hard clamp. Scaffold (kernels not yet implemented).
   use rdb_constants, only: wp
   use rdb_grid, only: hgrid_t
   use, intrinsic :: iso_fortran_env, only: int64
   use rdb_mem_report, only: arr_bytes
   implicit none
   private

   public :: ocean_obc_t

   ! Edge-band tags.
   integer, parameter, public :: OBC_EDGE_WEST = 1
   integer, parameter, public :: OBC_EDGE_EAST = 2
   integer, parameter, public :: OBC_EDGE_SOUTH = 3
   integer, parameter, public :: OBC_EDGE_NORTH = 4

   type :: ocean_obc_t
      logical :: is_init = .false.
         !! True between `init` and `destroy` (tracks GPU device attachment).

      ! ---- Master switches ----
      logical :: enabled = .false.
         !! Master OBC switch.  Falls back to coastal BCs if false.
      logical :: clamp_tracers = .true.
         !! Apply the FRS clamp to T, S (not just SSH/UV).

      ! ---- FRS zone ----
      integer  :: nrelax = 8
         !! Width (in cells) of the Flow-Relaxation zone.
      real(wp) :: relax_inner = 0.0_wp
         !! Relaxation timescale (1/s) at the interior edge of FRS.
      real(wp) :: relax_outer = 1.0_wp/600.0_wp
         !! Relaxation timescale at the outer (boundary) edge.

      ! ---- Per-edge parent-state ring buffers ----
      ! Two-time-level buffers. Shape per edge:
      !   (nx, nz_ml [+1 for face arrays], 2 time levels)
      real(wp), allocatable :: parent_eta_west(:, :)
      real(wp), allocatable :: parent_eta_east(:, :)
      real(wp), allocatable :: parent_eta_south(:, :)
      real(wp), allocatable :: parent_eta_north(:, :)

      real(wp), allocatable :: parent_u_west(:, :, :)
      real(wp), allocatable :: parent_u_east(:, :, :)
      real(wp), allocatable :: parent_v_south(:, :, :)
      real(wp), allocatable :: parent_v_north(:, :, :)

      real(wp), allocatable :: parent_T_west(:, :, :)
      real(wp), allocatable :: parent_T_east(:, :, :)
      real(wp), allocatable :: parent_T_south(:, :, :)
      real(wp), allocatable :: parent_T_north(:, :, :)

      real(wp), allocatable :: parent_S_west(:, :, :)
      real(wp), allocatable :: parent_S_east(:, :, :)
      real(wp), allocatable :: parent_S_south(:, :, :)
      real(wp), allocatable :: parent_S_north(:, :, :)

      ! ---- Ingest timing ----
      real(wp) :: dt_ingest = 3600.0_wp
         !! Cadence at which the next parent slab is read (s).
      real(wp) :: t_next_ingest = 0.0_wp
   contains
      procedure, non_overridable :: init => ocean_obc_init
      procedure, non_overridable :: destroy => ocean_obc_destroy
      procedure, non_overridable :: bytes => ocean_obc_bytes
   end type ocean_obc_t

contains

   subroutine ocean_obc_init(this, grid)
      class(ocean_obc_t), intent(inout) :: this
      type(hgrid_t), intent(in) :: grid
      if (.false.) this%nrelax = grid%nx_total
      this%is_init = .true.
   end subroutine ocean_obc_init

   subroutine ocean_obc_destroy(this)
      class(ocean_obc_t), intent(inout) :: this
      this%is_init = .false.
      if (allocated(this%parent_eta_west)) deallocate (this%parent_eta_west)
      if (allocated(this%parent_eta_east)) deallocate (this%parent_eta_east)
      if (allocated(this%parent_eta_south)) deallocate (this%parent_eta_south)
      if (allocated(this%parent_eta_north)) deallocate (this%parent_eta_north)
      if (allocated(this%parent_u_west)) deallocate (this%parent_u_west)
      if (allocated(this%parent_u_east)) deallocate (this%parent_u_east)
      if (allocated(this%parent_v_south)) deallocate (this%parent_v_south)
      if (allocated(this%parent_v_north)) deallocate (this%parent_v_north)
      if (allocated(this%parent_T_west)) deallocate (this%parent_T_west)
      if (allocated(this%parent_T_east)) deallocate (this%parent_T_east)
      if (allocated(this%parent_T_south)) deallocate (this%parent_T_south)
      if (allocated(this%parent_T_north)) deallocate (this%parent_T_north)
      if (allocated(this%parent_S_west)) deallocate (this%parent_S_west)
      if (allocated(this%parent_S_east)) deallocate (this%parent_S_east)
      if (allocated(this%parent_S_south)) deallocate (this%parent_S_south)
      if (allocated(this%parent_S_north)) deallocate (this%parent_S_north)
   end subroutine ocean_obc_destroy

   pure function ocean_obc_bytes(this) result(nbytes)
      !! Counted allocatable footprint of the open boundary condition slot (0 when
      !! unallocated).
      class(ocean_obc_t), intent(in) :: this
      integer(int64) :: nbytes
      nbytes = arr_bytes(this%parent_eta_west) &
               + arr_bytes(this%parent_eta_east) &
               + arr_bytes(this%parent_eta_south) &
               + arr_bytes(this%parent_eta_north) &
               + arr_bytes(this%parent_u_west) &
               + arr_bytes(this%parent_u_east) &
               + arr_bytes(this%parent_v_south) &
               + arr_bytes(this%parent_v_north) &
               + arr_bytes(this%parent_T_west) &
               + arr_bytes(this%parent_T_east) &
               + arr_bytes(this%parent_T_south) &
               + arr_bytes(this%parent_T_north) &
               + arr_bytes(this%parent_S_west) &
               + arr_bytes(this%parent_S_east) &
               + arr_bytes(this%parent_S_south) &
               + arr_bytes(this%parent_S_north)
   end function ocean_obc_bytes

end module rdb_ocean_obc