ocean_halo_init Subroutine

public subroutine ocean_halo_init(decomp, nghost, periodic_x, periodic_y, ierr)

Initialise topology and allocate persistent device-resident buffers. Idempotent: destroys prior state before re-init on grid change.

Arguments

Type IntentOptional Attributes Name
type(decomp_t), intent(in) :: decomp

Domain decomposition descriptor

integer, intent(in) :: nghost

Ghost cell width

logical, intent(in) :: periodic_x

Reentrant periodic in x

logical, intent(in) :: periodic_y

Reentrant periodic in y

integer, intent(out), optional :: ierr

Non-zero (OCEAN_STATUS_ERR_SETUP) on the decomposed-run nghost<3 seam-stencil guard when present; absent behaves as today (error stop). (F5 residual, P2.4)


Calls

proc~~ocean_halo_init~~CallsGraph proc~ocean_halo_init ocean_halo_init proc~fail fail proc~ocean_halo_init->proc~fail proc~ocean_halo_destroy ocean_halo_destroy proc~ocean_halo_init->proc~ocean_halo_destroy to_string to_string proc~ocean_halo_init->to_string error error proc~fail->error proc~error_ring_push error_ring_push proc~fail->proc~error_ring_push

Called by

proc~~ocean_halo_init~~CalledByGraph proc~ocean_halo_init ocean_halo_init proc~engine_setup engine_setup proc~engine_setup->proc~ocean_halo_init 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 :: cap_ew
integer, private :: cap_ns

Source Code

   subroutine ocean_halo_init(decomp, nghost, periodic_x, periodic_y, ierr)
      !! Initialise topology and allocate persistent device-resident buffers.
      !! Idempotent: destroys prior state before re-init on grid change.
      type(decomp_t), intent(in) :: decomp
         !! Domain decomposition descriptor
      integer, intent(in) :: nghost
         !! Ghost cell width
      logical, intent(in) :: periodic_x
         !! Reentrant periodic in x
      logical, intent(in) :: periodic_y
         !! Reentrant periodic in y
      integer, intent(out), optional :: ierr
         !! Non-zero (`OCEAN_STATUS_ERR_SETUP`) on the decomposed-run
         !! nghost<3 seam-stencil guard when present; absent behaves as
         !! today (`error stop`). (F5 residual, P2.4)

      integer :: cap_ew, cap_ns

      if (present(ierr)) ierr = OCEAN_STATUS_OK

      ! O4 seam-stencil guard (FAIL-LOUD): the ocean dyn-core's
      ! continuity/tracer PPM reconstruction is 5-point; a seam face's
      ! ghost-side donor cell needs two neighbours beyond itself, so
      ! full-order reconstruction at a rank-seam face needs THREE ghost
      ! columns.  With nghost < 3 the PPM local-array-edge fallback fires AT
      ! the seam and degrades the face to first order, producing a
      ! seam-inconsistent tracer mass flux: it conserves a UNIFORM tracer
      ! (Σ flux·C cancels) but LEAKS a STRUCTURED one — measured heat
      ! closure grew to +5e-11 by day 2 on seamount_bench_full np2 at
      ! nghost=2 (invisible to the mass/salt gates; the O4 heat-leak
      ! postmortem).  This is an ABORT, not a warning: a silent
      ! decomposition-dependent conservation leak is a correctness bug.
      ! `decomp%px/py` are the TRUE runtime decomposition (namelist px/py
      ! are auto-factored by then), so this gate sees the real seam even
      ! when the namelist left px=py=1.  The default nghost is now 3, so
      ! this only trips an EXPLICIT decomposed override below 3.  The ocean
      ! halo-primitive tests (test_halo_ocean_mpi) already init at nghost=3.
      if ((decomp%px > 1 .or. decomp%py > 1) .and. nghost < 3) then
         call fail("ocean_halo_init: decomposed ocean run (px="// &
                   to_string(decomp%px)//", py="//to_string(decomp%py)// &
                   ") requires nghost >= 3, got nghost = "//to_string(nghost)// &
                   ". The continuity/tracer PPM 5-point stencil degrades to "// &
                   "FIRST ORDER at rank-seam faces, leaking a structured tracer "// &
                   "(heat) while conserving a uniform one (salt). "// &
                   "Set &grid_nml nghost = 3 (the default) or higher.", &
                   ierr, OCEAN_STATUS_ERR_SETUP)
         return
      end if

      if (oh_initialised) call ocean_halo_destroy()

      oh_decomp = decomp
      oh_nghost = nghost
      oh_nx_local = decomp%nx_local
      oh_ny_local = decomp%ny_local
      oh_nx_total = decomp%nx_local + 2*nghost
      oh_ny_total = decomp%ny_local + 2*nghost
      oh_periodic_x = periodic_x
      oh_periodic_y = periodic_y
      oh_initialised = .true.

      ! Capacity: worst case is face-x send-east = (nghost+1)*ny_total for E/W.
      ! For face-y x-pass, ng*(ny_total+1) <= (ng+1)*ny_total when ny_total >= ng.
      cap_ew = (nghost + 1)*oh_ny_total
      cap_ns = (nghost + 1)*oh_nx_total

      allocate (oh_buf_send_east(cap_ew), oh_buf_recv_east(cap_ew))
      allocate (oh_buf_send_west(cap_ew), oh_buf_recv_west(cap_ew))
      allocate (oh_buf_send_north(cap_ns), oh_buf_recv_north(cap_ns))
      allocate (oh_buf_send_south(cap_ns), oh_buf_recv_south(cap_ns))
      !$acc enter data create(oh_buf_send_east, oh_buf_recv_east, &
      !$acc&                  oh_buf_send_west, oh_buf_recv_west, &
      !$acc&                  oh_buf_send_north, oh_buf_recv_north, &
      !$acc&                  oh_buf_send_south, oh_buf_recv_south)

      oh_cap_ew = cap_ew
      oh_cap_ns = cap_ns

   end subroutine ocean_halo_init