ocean_fold_unpack_3d Subroutine

private subroutine ocean_fold_unpack_3d(fld, nxa, nya, nz, stagger, negate, device_resident)

Unpack the next field of the exchanged group: write every north ghost row (all storage columns) and, for v / corner, the fold-line row’s west half (self-conjugate column → 0 for a vector).

Arguments

Type IntentOptional Attributes Name
real(kind=wp), intent(inout) :: fld(nxa,nya,nz)

Field; same stagger and order as at pack.

integer, intent(in) :: nxa

Storage extents of fld.

integer, intent(in) :: nya

Storage extents of fld.

integer, intent(in) :: nz

Storage extents of fld.

integer, intent(in) :: stagger

FOLD_STAG_*.

logical, intent(in) :: negate

.true. for a true-vector component.

logical, intent(in), optional :: device_resident

.false. ⇒ host arrays; default device-resident.


Calls

proc~~ocean_fold_unpack_3d~~CallsGraph proc~ocean_fold_unpack_3d ocean_fold_unpack_3d proc~fold_stagger_family fold_stagger_family proc~ocean_fold_unpack_3d->proc~fold_stagger_family proc~fold_stagger_nrows fold_stagger_nrows proc~ocean_fold_unpack_3d->proc~fold_stagger_nrows

Called by

proc~~ocean_fold_unpack_3d~~CalledByGraph proc~ocean_fold_unpack_3d ocean_fold_unpack_3d interface~ocean_fold_unpack ocean_fold_unpack interface~ocean_fold_unpack->proc~ocean_fold_unpack_3d proc~ocean_fold_unpack_2d ocean_fold_unpack_2d interface~ocean_fold_unpack->proc~ocean_fold_unpack_2d proc~ocean_fold_unpack_2d->proc~ocean_fold_unpack_3d proc~barotropic_substep_nonlinear barotropic_substep_nonlinear proc~barotropic_substep_nonlinear->interface~ocean_fold_unpack interface~ocean_fold_north_v_face ocean_fold_north_v_face proc~barotropic_substep_nonlinear->interface~ocean_fold_north_v_face proc~fold_centre_2d fold_centre_2d proc~fold_centre_2d->interface~ocean_fold_unpack proc~fold_centre_3d fold_centre_3d proc~fold_centre_3d->interface~ocean_fold_unpack proc~fold_corner_2d fold_corner_2d proc~fold_corner_2d->interface~ocean_fold_unpack proc~fold_u_2d fold_u_2d proc~fold_u_2d->interface~ocean_fold_unpack proc~fold_u_3d fold_u_3d proc~fold_u_3d->interface~ocean_fold_unpack proc~fold_v_2d fold_v_2d proc~fold_v_2d->interface~ocean_fold_unpack proc~fold_v_3d fold_v_3d proc~fold_v_3d->interface~ocean_fold_unpack proc~ocean_fold_wrap_centre_3d_state ocean_fold_wrap_centre_3d_state proc~ocean_fold_wrap_centre_3d_state->interface~ocean_fold_unpack proc~ocean_fold_wrap_centre_flat ocean_fold_wrap_centre_flat proc~ocean_fold_wrap_centre_flat->interface~ocean_fold_unpack proc~ocean_fold_wrap_eta_2d ocean_fold_wrap_eta_2d proc~ocean_fold_wrap_eta_2d->interface~ocean_fold_unpack proc~ocean_fold_wrap_state ocean_fold_wrap_state proc~ocean_fold_wrap_state->interface~ocean_fold_unpack proc~ocean_fold_wrap_stress ocean_fold_wrap_stress proc~ocean_fold_wrap_stress->interface~ocean_fold_unpack proc~ocean_fold_wrap_time_means ocean_fold_wrap_time_means proc~ocean_fold_wrap_time_means->interface~ocean_fold_unpack proc~ocean_fold_wrap_visc_rem ocean_fold_wrap_visc_rem proc~ocean_fold_wrap_visc_rem->interface~ocean_fold_unpack interface~ocean_fold_north_centre ocean_fold_north_centre interface~ocean_fold_north_centre->proc~fold_centre_2d interface~ocean_fold_north_centre->proc~fold_centre_3d interface~ocean_fold_north_corner ocean_fold_north_corner interface~ocean_fold_north_corner->proc~fold_corner_2d interface~ocean_fold_north_u_face ocean_fold_north_u_face interface~ocean_fold_north_u_face->proc~fold_u_2d interface~ocean_fold_north_u_face->proc~fold_u_3d interface~ocean_fold_north_v_face->proc~fold_v_2d interface~ocean_fold_north_v_face->proc~fold_v_3d proc~barotropic_substep_nonlinear_interior barotropic_substep_nonlinear_interior proc~barotropic_substep_nonlinear_interior->proc~barotropic_substep_nonlinear proc~bt_wide_substep bt_wide_substep proc~bt_wide_substep->proc~barotropic_substep_nonlinear proc~configure_ocean_land_mask configure_ocean_land_mask proc~configure_ocean_land_mask->proc~ocean_fold_wrap_eta_2d proc~continuity_gm_apply continuity_gm_apply proc~continuity_gm_apply->proc~ocean_fold_wrap_centre_3d_state proc~continuity_gm_apply->interface~ocean_fold_north_v_face proc~continuity_tracer_step_split continuity_tracer_step_split proc~continuity_tracer_step_split->proc~ocean_fold_wrap_centre_3d_state proc~continuity_tracer_step_split->interface~ocean_fold_north_v_face proc~engine_setup engine_setup proc~engine_setup->proc~ocean_fold_wrap_eta_2d proc~engine_setup->proc~ocean_fold_wrap_state proc~engine_setup->interface~ocean_fold_north_corner proc~engine_setup->proc~configure_ocean_land_mask proc~ocean_halo_exchange_ice_state ocean_halo_exchange_ice_state proc~engine_setup->proc~ocean_halo_exchange_ice_state proc~configure_ocean_forcing configure_ocean_forcing proc~engine_setup->proc~configure_ocean_forcing proc~ocean_data_forcing_configure ocean_data_forcing_configure proc~engine_setup->proc~ocean_data_forcing_configure proc~ocean_halo_exchange_ice_fluxes ocean_halo_exchange_ice_fluxes proc~ocean_halo_exchange_ice_fluxes->proc~ocean_fold_wrap_centre_flat proc~ocean_halo_exchange_ice_state->proc~ocean_fold_wrap_centre_flat proc~ocean_halo_exchange_ice_transport ocean_halo_exchange_ice_transport proc~ocean_halo_exchange_ice_transport->proc~ocean_fold_wrap_centre_flat proc~ocean_seam_refresh_surface_stress ocean_seam_refresh_surface_stress proc~ocean_seam_refresh_surface_stress->proc~ocean_fold_wrap_stress proc~rdb_ocean_set_bathymetry rdb_ocean_set_bathymetry proc~rdb_ocean_set_bathymetry->proc~ocean_fold_wrap_eta_2d proc~refresh_tracer_ghosts refresh_tracer_ghosts proc~refresh_tracer_ghosts->proc~ocean_fold_wrap_centre_3d_state proc~run_continuity_chain run_continuity_chain proc~run_continuity_chain->proc~ocean_fold_wrap_state proc~run_continuity_chain->proc~continuity_tracer_step_split proc~run_continuity_chain->proc~refresh_tracer_ghosts proc~run_gm_step run_gm_step proc~run_gm_step->proc~ocean_fold_wrap_state proc~run_gm_step->proc~continuity_gm_apply proc~run_stage_split run_stage_split proc~run_stage_split->proc~ocean_fold_wrap_state proc~run_stage_split->proc~ocean_fold_wrap_time_means proc~run_stage_split->proc~barotropic_substep_nonlinear_interior proc~run_stage_split->proc~bt_wide_substep proc~run_stage_split->proc~refresh_tracer_ghosts proc~run_stage_split->proc~run_continuity_chain proc~visc_rem_precompute visc_rem_precompute proc~run_stage_split->proc~visc_rem_precompute proc~vmix_apply_in_stage vmix_apply_in_stage proc~run_stage_split->proc~vmix_apply_in_stage proc~visc_rem_halo_refresh visc_rem_halo_refresh proc~visc_rem_halo_refresh->proc~ocean_fold_wrap_visc_rem proc~complete_ocean_create complete_ocean_create proc~complete_ocean_create->proc~engine_setup proc~configure_ocean_forcing->proc~ocean_seam_refresh_surface_stress proc~driver_run_ocean driver_run_ocean proc~driver_run_ocean->proc~engine_setup proc~engine_step_ice engine_step_ice proc~driver_run_ocean->proc~engine_step_ice proc~driver_validate driver_validate proc~driver_validate->proc~engine_setup proc~engine_step_ice->proc~ocean_halo_exchange_ice_fluxes proc~engine_step_ice->proc~ocean_halo_exchange_ice_state proc~ice_ocean_stress_flux ice_ocean_stress_flux proc~engine_step_ice->proc~ice_ocean_stress_flux proc~ice_transport_step ice_transport_step proc~engine_step_ice->proc~ice_transport_step proc~ice_ocean_stress_flux->proc~ocean_seam_refresh_surface_stress proc~ice_transport_step->proc~ocean_halo_exchange_ice_transport proc~ocean_data_forcing_apply ocean_data_forcing_apply proc~ocean_data_forcing_apply->proc~ocean_seam_refresh_surface_stress proc~ocean_data_forcing_configure->proc~ocean_seam_refresh_surface_stress proc~ocean_dyn_step_split ocean_dyn_step_split proc~ocean_dyn_step_split->proc~run_gm_step proc~ocean_dyn_step_split->proc~run_stage_split proc~run_stage run_stage proc~run_stage->proc~continuity_tracer_step_split proc~run_stage->proc~vmix_apply_in_stage proc~visc_rem_precompute->proc~visc_rem_halo_refresh proc~vmix_apply_in_stage->proc~visc_rem_halo_refresh proc~vmix_apply_in_stage->proc~visc_rem_precompute proc~driver_run driver_run proc~driver_run->proc~driver_run_ocean proc~engine_step engine_step proc~engine_step->proc~ocean_data_forcing_apply proc~engine_step->proc~ocean_dyn_step_split proc~ocean_dyn_step ocean_dyn_step proc~ocean_dyn_step->proc~run_stage 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 proc~rdb_ocean_step rdb_ocean_step proc~rdb_ocean_step->proc~engine_step_ice

Variables

Type Visibility Attributes Name Initial
integer, private :: L
integer, private :: cap
integer, private :: cls
integer, private :: dbase
integer, private :: fam
integer, private :: g
integer, private :: g0
logical, private :: has_row
integer, private :: ib
integer, private :: ng_e
integer, private :: nrow
integer, private :: oT
integer, private :: oU
logical, private :: on_device
integer, private :: p
integer, private :: r
real(kind=wp), private :: sgn
real(kind=wp), private :: val

Source Code

   subroutine ocean_fold_unpack_3d(fld, nxa, nya, nz, stagger, negate, device_resident)
      !! Unpack the next field of the exchanged group: write every north
      !! ghost row (all storage columns) and, for v / corner, the fold-line
      !! row's west half (self-conjugate column → 0 for a vector).
      integer, intent(in) :: nxa, nya, nz
         !! Storage extents of `fld`.
      real(wp), intent(inout) :: fld(nxa, nya, nz)
         !! Field; same stagger and order as at pack.
      integer, intent(in) :: stagger
         !! `FOLD_STAG_*`.
      logical, intent(in) :: negate
         !! `.true.` for a true-vector component.
      logical, intent(in), optional :: device_resident
         !! `.false.` ⇒ host arrays; default device-resident.

      integer :: fam, nrow, dbase, g, g0, ng_e, L, r, p, cap, oT, oU, ib, cls
      logical :: on_device, has_row
      real(wp) :: sgn, val

      if (.not. fx_active) return
      if (.not. fx_open .or. .not. fx_sent) then
         error stop "rdb_ocean_fold_exchange: ocean_fold_unpack before ocean_fold_exchange"
      end if
      on_device = .true.
      if (present(device_resident)) on_device = device_resident

      fam = fold_stagger_family(stagger)
      nrow = fold_stagger_nrows(stagger, fx_ng)
      has_row = (nrow == fx_ng + 1)
      ! Destination row of message row r: ng+nyl+r for every stagger
      ! (`fold_row_map`: T/u ng+nyl+d, v/corner ng+nyl+1+d with d = r-1).
      dbase = fx_ng + fx_nyl
      g0 = fx_r0(fam)
      ng_e = fx_nr(fam)
      cap = fx_cap
      oT = fx_uoff(FOLD_FAM_T)
      oU = fx_uoff(FOLD_FAM_U)
      sgn = 1.0_wp
      if (negate) sgn = -1.0_wp

      if (ng_e > 0) then
         if (on_device) then
            !$acc parallel loop collapse(3) private(p, ib, cls, val) &
            !$acc& present(fx_rbuf, fx_rcol, fx_rpeer, fx_re, fx_rcls, fx_rn, fld)
            do L = 1, nz
               do r = 1, nrow
                  do g = g0 + 1, g0 + ng_e
                     p = fx_rpeer(g)
                     ib = (p - 1)*cap + oT*fx_rn(p, FOLD_FAM_T) + oU*fx_rn(p, FOLD_FAM_U) &
                          + ((L - 1)*nrow + (r - 1))*fx_rn(p, fam) + fx_re(g)
                     val = sgn*fx_rbuf(ib)
                     if (has_row .and. r == 1) then
                        cls = fx_rcls(g)
                        if (cls == FOLD_ROW_WEST) then
                           fld(fx_rcol(g), dbase + 1, L) = val
                        else if (cls == FOLD_ROW_SELF .and. negate) then
                           fld(fx_rcol(g), dbase + 1, L) = 0.0_wp
                        end if
                     else
                        fld(fx_rcol(g), dbase + r, L) = val
                     end if
                  end do
               end do
            end do
         else
            do L = 1, nz
               do r = 1, nrow
                  do g = g0 + 1, g0 + ng_e
                     p = fx_rpeer(g)
                     ib = (p - 1)*cap + oT*fx_rn(p, FOLD_FAM_T) + oU*fx_rn(p, FOLD_FAM_U) &
                          + ((L - 1)*nrow + (r - 1))*fx_rn(p, fam) + fx_re(g)
                     val = sgn*fx_rbuf(ib)
                     if (has_row .and. r == 1) then
                        cls = fx_rcls(g)
                        if (cls == FOLD_ROW_WEST) then
                           fld(fx_rcol(g), dbase + 1, L) = val
                        else if (cls == FOLD_ROW_SELF .and. negate) then
                           fld(fx_rcol(g), dbase + 1, L) = 0.0_wp
                        end if
                     else
                        fld(fx_rcol(g), dbase + r, L) = val
                     end if
                  end do
               end do
            end do
         end if
      end if
      fx_uoff(fam) = fx_uoff(fam) + nrow*nz
   end subroutine ocean_fold_unpack_3d