LCOV - code coverage report
Current view: | top level - dynamics/se/dycore - edge_mod.F90 (source / functions) |  |  | Hit | Total | Coverage
Test: | coverage.info |  | Lines: | 600 | 1145 | 52.4 %
Date: | 2024-12-17 22:39:59 |  | Functions: | 14 | 28 | 50.0 %

              Line data    Source code
           1             : module edge_mod
           2             :
           3             :   use shr_kind_mod,           only: r8=>shr_kind_r8, i8=>shr_kind_i8
           4             :   use dimensions_mod,         only: max_neigh_edges, nelemd
           5             :   use perf_mod,               only: t_startf, t_stopf, t_adj_detailf ! _EXTERNAL
           6             :   use thread_mod,             only: max_num_threads, omp_get_num_threads, omp_get_thread_num
           7             :   use coordinate_systems_mod, only: cartesian3D_t
           8             :   use schedtype_mod,          only: cycle_t, schedule_t, pgindex_t, schedule, HME_Ordinal,HME_Cardinal
           9             :   use cam_abortutils,         only: endrun
          10             :   use cam_logfile,            only: iulog
          11             :   use parallel_mod,           only: parallel_t, &
          12             :       MAX_ACTIVE_MSG, HME_status_size, BNDRY_TAG_BASE, HME_BNDRY_A2A, HME_BNDRY_P2P, &
          13             :       HME_BNDRY_A2AO
          14             :   use edgetype_mod,           only: edgedescriptor_t, edgebuffer_t,           &
          15             :       Longedgebuffer_t, initedgebuffer_callid, Ghostbuffer3D_t
          16             :   use element_mod,            only: element_t
          17             :   use gbarrier_mod,           only: gbarrier_init, gbarrier_delete
          18             :   use spmd_utils,             only: mpi_real8, mpi_integer, mpi_info_null, mpi_success
          19             :
          20             :   implicit none
          21             :   private
          22             :   save
          23             :
          24             :   ! 8-byte Integer routines
          25             :   public :: LongEdgeVpack, LongEdgeVunpackMIN
          26             :
          27             :   ! 8-byte Real routines
          28             :   public :: zeroEdgeBuffer
          29             :
          30             :   interface initEdgeBuffer
          31             :      module procedure initEdgeBuffer_r8
          32             :      module procedure initEdgeBuffer_i8
          33             :   end interface
          34             :   interface initEdgeSBuffer
          35             :      module procedure initEdgeSbuffer_r8
          36             :   end interface
          37             :   interface freeEdgeBuffer
          38             :      module procedure freeEdgeBuffer_r8
          39             :      module procedure freeEdgeBuffer_i8
          40             :   end interface
          41             :   interface freeGhostBuffer
          42             :      module procedure freeGhostBuffer_r8
          43             :   end interface
          44             :
          45             :   public :: initEdgeBuffer
          46             :   public :: initEdgeSBuffer
          47             :   public :: freeEdgeBuffer
          48             :
          49             :   public :: initGhostBuffer
          50             :   public :: ghostpack, ghostunpack
          51             :   public :: freeGhostBuffer
          52             :
          53             :   !---------------------------------------------------------
          54             :   ! Pack/unpack routines that use the New format Edge buffer
          55             :   !---------------------------------------------------------
          56             :
          57             :   public :: edgeVpack, edgeVunpack
          58             :   public :: edgeVunpackMIN, edgeVunpackMAX
          59             :   public :: edgeDGVpack, edgeDGVunpack
          60             :   public :: edgeVunpackVert
          61             :
          62             :
          63             :   public :: initGhostBuffer3D
          64             :   public :: FreeGhostBuffer3D
          65             :   public :: ghostVpack3D, ghostVunpack3D
          66             :
          67             :   !----------------------------------------------------------------
          68             :   ! Pack/unpack routines that communicate a fixed number values
          69             :   ! per element.  This is used to communicate MIN/MAX values from
          70             :   ! neighboring elemeents
          71             :   !----------------------------------------------------------------
          72             :   interface edgeSpack
          73             :      module procedure edgeSpack_r8
          74             :   end interface
          75             :   public :: edgeSpack
          76             :   public :: edgeSunpackMIN, edgeSunpackMAX
          77             :
          78             :   logical, private :: threadsafe=.true.
          79             :
          80             :   real(kind=r8), parameter, public :: edgeDefaultVal = 1.11e+100_r8
          81             :
          82             : ! NOTE ON ELEMENT ORIENTATION
          83             : !
          84             : ! Element orientation:  index V(i,j)
          85             : !
          86             : !           (1,np) NWEST      (np,np) NEAST
          87             : !
          88             : !           (1,1) SWEST       (np,1) SEAST
          89             : !
          90             : !
          91             : ! for the edge neighbors:
          92             : !    we set the "reverse" flag if two elements who share an edge use a
          93             : !    reverse orientation.  The data is reversed during the *pack* stage
          94             : ! For corner neighbors:
          95             : !    for edge buffers, there is no orientation because two corner neighbors
          96             : !    only share a single point.
          97             : !    For ghost cell data, there is a again two posible orientations. For
          98             : !    this case, we set the "reverse" flag if the corner element is using
          99             : !    the reverse orientation.  In this case, the data is reversed during the
         100             : !    *unpack* stage (not sure why)
         101             : !
         102             : ! The edge orientation is set at startup.  The corner orientation is computed
         103             : ! at run time, via the call to compute_ghost_corner_orientation()
         104             : ! This routine only works for meshes with at most 1 corner element.  It's
         105             : ! not called and the corner orientation flag is not set for unstructured meshes
         106             :
         107             : !
         108             : ! Christoph Erath
         109             : ! pack/unpack partial element of data of size (nx,nx) with user specifed halo size nh
         110             : ! user specifies the sizes when creating the buffer
         111             : ! buffer has 1 extra dimension (as compared to subroutines above) for multiple tracers
         112             : ! input/output arrays are cartesian, and thus assume at most 1 element at each corner
         113             : ! hence currently only supports cube-sphere grids.
         114             : !
         115             : !
         116             : ! routines which including element edge data
         117             : ! (used for FVM arrays where edge data is not shared by neighboring elements)
         118             : ! these routines pack/unpack element data with user specified halo size
         119             :
         120             :   ! Wrap pointer so we can make an array of them.
         121             :   type :: wrap_ptr
         122             :     real (kind=r8), dimension(:,:), pointer :: ptr => null()
         123             :   end type wrap_ptr
         124             :
         125             :   type(wrap_ptr) :: edgebuff_ptrs(0:1)
         126             :
         127             : contains
         128             :
         129           0 :   subroutine initEdgeSBuffer_r8(par,edge,elem,nlyr,bndry_type, nthreads)
         130             :     type (parallel_t),             intent(in)  :: par
         131             :     type (EdgeBuffer_t), target,   intent(out) :: edge
         132             :     type (element_t),              intent(in)  :: elem(:)
         133             :     integer,                       intent(in)  :: nlyr
         134             :     integer ,            optional, intent(in)  :: bndry_type
         135             :     integer,             optional, intent(in)  :: nthreads
         136             :
         137             :
         138             :     call initEdgeBuffer(par,edge,elem,nlyr,bndry_type=bndry_type, &
         139           0 :                          nthreads=nthreads,CardinalLength=1,OrdinalLength=1)
         140             :
         141           0 :   end subroutine initEdgeSBuffer_r8
         142             :
         143       18432 :   subroutine initGhostBuffer(par,edge,elem,nlyr,ndepth, npoints,bndry_type,nthreads)
         144             :
         145             :     type (parallel_t),             intent(in)  :: par
         146             :     type (Edgebuffer_t), target,   intent(out) :: edge
         147             :     type (element_t),              intent(in)  :: elem(:)
         148             :     integer,intent(in)                         :: nlyr,ndepth, npoints
         149             :     integer ,            optional, intent(in)  :: bndry_type
         150             :     integer,             optional, intent(in)  :: nthreads
         151             :
         152             :     call initEdgeBuffer(par,edge,elem,nlyr,bndry_type=bndry_type, &
         153       18432 :                          nthreads=nthreads,CardinalLength=ndepth*npoints,OrdinalLength=ndepth*ndepth)
         154             :     ! set some parameters need to support deep halos
         155       18432 :     edge%ndepth  = ndepth
         156       18432 :     edge%npoints = npoints
         157       18432 :     edge%lb      = 1 - edge%ndepth
         158       18432 :     edge%ub      = edge%npoints + edge%ndepth
         159             :
         160       18432 :   end subroutine initGhostBuffer
         161             :
         162             :
         163             :
         164           0 :   subroutine zeroEdgeBuffer(edge)
         165             :
         166             :     type (EdgeBuffer_t), intent(inout) :: edge
         167             :     integer :: i
         168             :
         169           0 :     do i=1,edge%nbuf
         170           0 :        edge%buf(i)     = 0.0d0
         171           0 :        edge%receive(i) = 0.0d0
         172             :     enddo
         173             :
         174           0 :   end subroutine zeroEdgeBuffer
         175             :
         176             :   ! =========================================
         177             :   ! initEdgeBuffer:
         178             :   !
         179             :   ! create an Real based communication buffer
         180             :   ! =========================================
         181       62976 :   subroutine initEdgeBuffer_r8(par,edge,elem,nlyr, bndry_type,nthreads,CardinalLength,OrdinalLength)
         182             :     use dimensions_mod, only: np, nelemd, max_corner_elem
         183             :     use schedtype_mod,  only: cycle_t, schedule_t, schedule
         184             :     use mpi,            only: MPI_VERSION
         185             :
         186             :     type (parallel_t),             intent(in)  :: par
         187             :     type (EdgeBuffer_t), target,   intent(out) :: edge
         188             :     type (element_t),              intent(in)  :: elem(:)
         189             :     integer,                       intent(in)  :: nlyr
         190             :     integer,             optional, intent(in)  :: bndry_type
         191             :     integer,             optional, intent(in)  :: nthreads
         192             :     integer,             optional, intent(in)  :: CardinalLength
         193             :     integer,             optional, intent(in)  :: OrdinalLength
         194             :
         195             :     ! Notes about the buf_ptr/receive_ptr options:
         196             :     !
         197             :     ! If an EdgeBuffer_t object is initialized from pre-existing storage
         198             :     ! (i.e. buf_ptr is provided and not null), it must *not* be freed,
         199             :     ! and must not be used if the underlying storage has been deallocated.
         200             :     !
         201             :     ! All these restrictions also applied to the old newbuf and newreceive
         202             :     ! options.
         203             :
         204             :     ! Workaround for NAG bug.
         205             :     ! NAG 5.3.1 dies if you use pointer bounds remapping to set
         206             :     ! a pointer that is also a component. So remap to temporary,
         207             :     ! then use that to set component pointer.
         208             :
         209             :     ! Local variables
         210             :     integer                    :: nbuf,ith
         211             :     integer                    :: nSendCycles, nRecvCycles
         212             :     integer                    :: icycle, ierr
         213             :     integer                    :: ie, i
         214             :     integer                    :: edgeid,elemid
         215             :     integer                    :: ptr,llen,moveLength, mLen, tlen
         216             :     type (Cycle_t),    pointer :: pCycle
         217             :     type (Schedule_t), pointer :: pSchedule
         218             :     integer                    :: dest, source, length, tag, iptr
         219             :     integer                    :: nlen, ithr
         220             :
         221             :     integer :: len, lenP,lenS
         222             :     integer :: j,jj,il,mesgid, dst0,src0
         223             :     integer :: moveptr
         224             :     integer :: nbuf2,ilm1,iem1,lenm1
         225       31488 :     integer,allocatable :: putmap2(:,:),getmap2(:,:)
         226             :     integer,allocatable :: scounts(:), rcounts(:)
         227             :     integer,allocatable :: sdispls(:), rdispls(:)
         228             :     integer :: nInter, nIntra
         229             :     integer :: icInter, icIntra
         230             :
         231             :     integer :: maxnsend
         232             :     integer :: tmpnMesg
         233             :     integer :: wintmpnMesg, wintmpDest, wintmpDisp
         234             :     integer(kind=i8) :: winsize
         235             :     integer :: win
         236             :     integer :: sizeofreal
         237             :     integer, allocatable :: tmpDest(:),tmpDisp(:)
         238             :     integer :: nFull
         239             :     integer :: disp, one
         240             :     integer                           :: errorcode,errorlen
         241             :     integer :: CardinalLen, OrdinalLen
         242             :     character(len=80)                 :: errorstring
         243             :     character(len=80), parameter      :: subname='initedgeBuffer'
         244             :
         245       31488 :     if(present(bndry_type)) then
         246        6144 :       if ( MPI_VERSION >= 3 ) then
         247        6144 :         edge%bndry_type = bndry_type
         248             :       else
         249             :         edge%bndry_type = HME_BNDRY_P2P
         250             :       endif
         251             :     else
         252       25344 :        edge%bndry_type = HME_BNDRY_P2P
         253             :     endif
         254             :
         255             :     ! Set the length of the cardinal and ordinal message lengths
         256       31488 :     if(present(CardinalLength)) then
         257       18432 :        CardinalLen = CardinalLength
         258             :     else
         259       13056 :        CardinalLen = np
         260             :     endif
         261       31488 :     if(present(OrdinalLength)) then
         262       18432 :        OrdinalLen = OrdinalLength
         263             :     else
         264       13056 :        OrdinalLen = 1
         265             :     endif
         266             :
         267             : ! DO NOT REMOVE THIS NEXT BARRIER
         268             : ! MT: This initial barrier fixes a long standing issue with Intel compilers on
         269             : ! two different platforms.  Without this barrier, edge buffers initialized from
         270             : ! within the threaded region would not work in a reproducable way with certain
         271             : ! thread combinations.  I cant explain why, but this fixes that issue on Edison
         272             : !$OMP BARRIER
         273             :
         274       31488 :     if (nlyr==0) return  ! tracer code might call initedgebuffer() with zero tracers
         275             :
         276             :
         277             : !$OMP MASTER
         278             :     !
         279             :     ! Keep a counter of how many times initedgebuffer is called.
         280             :     ! This is used to assign a unique message ID for the boundary exchange
         281             :     !
         282       31488 :     initedgebuffer_callid=initedgebuffer_callid+1
         283       31488 :     edge%id  = initedgebuffer_callid
         284       31488 :     edge%tag = BNDRY_TAG_BASE + MODULO(edge%id, MAX_ACTIVE_MSG)
         285             :
         286      125952 :     allocate(edge%putmap(max_neigh_edges,nelemd))
         287       94464 :     allocate(edge%getmap(max_neigh_edges,nelemd))
         288       94464 :     allocate(edge%reverse(max_neigh_edges,nelemd))
         289             :
         290     2024088 :     edge%putmap(:,:)=-1
         291     2024088 :     edge%getmap(:,:)=-1
         292             :
         293      125952 :     allocate(putmap2(max_neigh_edges,nelemd))
         294       94464 :     allocate(getmap2(max_neigh_edges,nelemd))
         295     2024088 :     putmap2(:,:)=-1
         296     2024088 :     getmap2(:,:)=-1
         297      252888 :     do ie=1,nelemd
         298     2024088 :        do i=1,max_neigh_edges
         299     1992600 :           edge%reverse(i,ie) = elem(ie)%desc%reverse(i)
         300             :        enddo
         301             :     enddo
         302             :
         303       31488 :     pSchedule  => Schedule(1)
         304       31488 :     nSendCycles = pSchedule%nSendCycles
         305       31488 :     nRecvCycles = pSchedule%nRecvCycles
         306       31488 :     nInter      = pSchedule%nInter
         307       31488 :     nIntra      = pSchedule%nIntra
         308       31488 :     nFull       = nInter+nIntra
         309             :
         310       31488 :     edge%nInter=nInter
         311       31488 :     edge%nIntra=nIntra
         312             :
         313       31488 :     if(nInter>0) then
         314      125952 :        allocate(edge%rcountsInter(nInter),edge%rdisplsInter(nInter))
         315       94464 :        allocate(edge%scountsInter(nInter),edge%sdisplsInter(nInter))
         316             :     endif
         317       31488 :     if(nIntra>0) then
         318           0 :        allocate(edge%rcountsIntra(nIntra),edge%rdisplsIntra(nIntra))
         319           0 :        allocate(edge%scountsIntra(nIntra),edge%sdisplsIntra(nIntra))
         320             :     endif
         321             :
         322       31488 :     if (nSendCycles>0) then
         323      125952 :        allocate(edge%scountsFull(nSendCycles),edge%sdisplsFull(nSendCycles))
         324       62976 :        allocate(edge%Srequest(nSendCycles))
         325      234274 :        edge%scountsFull(:) = 0
         326             :     endif
         327             :     !
         328             :     ! Setup the data-structures for the sends
         329             :     !
         330       31488 :     j         = 1
         331       31488 :     icycle    = 1
         332       31488 :     dst0      = pSchedule%pIndx(j)%mesgid
         333       31488 :     il        = pSchedule%pIndx(j)%edgeid
         334       31488 :     ie        = pSchedule%pIndx(j)%elemid
         335       31488 :     len       = CalcSegmentLength(pSchedule%pIndx(j),CardinalLen,OrdinalLen,nlyr)
         336       31488 :     edge%putmap(il,ie) = 0
         337       31488 :     if(nSendCycles>0) then
         338       31488 :         edge%sdisplsFull(icycle) = edge%putmap(il,ie)
         339       31488 :         edge%scountsFull(icycle) = len
         340             :     endif
         341       31488 :     ilm1 = il
         342       31488 :     iem1 = ie
         343       31488 :     lenm1 = len
         344             :
         345     1771200 :     do j=2,SIZE(pSchedule%pIndx)
         346     1739712 :        il = pSchedule%pIndx(j)%edgeid
         347     1739712 :        ie = pSchedule%pIndx(j)%elemid
         348     1739712 :        mesgid = pSchedule%pIndx(j)%mesgid
         349     1771200 :        if(il>0 .and. ie >0) then
         350     1738728 :           len     = CalcSegmentLength(pSchedule%pIndx(j),CardinalLen,OrdinalLen,nlyr)
         351     1738728 :           edge%putmap(il,ie) = edge%putmap(ilm1,iem1)+lenm1
         352     1738728 :           if(mesgid .ne. par%rank) then  ! don't enter if this is a move cycle where (mesgid == par%rank)
         353      948740 :              if(mesgid .ne. dst0) then
         354      171298 :                 icycle=icycle+1
         355      171298 :                 if (nSendCycles>0) edge%sdisplsFull(icycle) = edge%putmap(il,ie)
         356             :                 dst0=mesgid
         357             :              endif
         358      948740 :              if (nSendCycles>0) edge%scountsFull(icycle) = edge%scountsFull(icycle)+len
         359             :           endif
         360             :           ilm1=il
         361             :           iem1=ie
         362             :           lenm1=len
         363             :        endif
         364             :     enddo
         365             :
         366             :     icInter=0
         367             :     icIntra=0
         368      234274 :     do icycle=1,nSendCycles
         369      234274 :        if(pSchedule%SendCycle(icycle)%onNode .eqv. .FALSE.) then
         370      202786 :           icInter=icInter+1
         371      202786 :           edge%sdisplsInter(icInter)=edge%sdisplsFull(icycle)
         372      202786 :           edge%scountsInter(icInter)=edge%scountsFull(icycle)
         373             :        else
         374           0 :           icIntra=icIntra+1
         375           0 :           edge%sdisplsIntra(icIntra)=edge%sdisplsFull(icycle)
         376           0 :           edge%scountsIntra(icIntra)=edge%scountsFull(icycle)
         377             :        endif
         378             :     enddo
         379             :
         380       31488 :     if (nRecvCycles>0) then
         381      125952 :        allocate(edge%rcountsFull(nRecvCycles),edge%rdisplsFull(nRecvCycles))
         382       94464 :        allocate(edge%getDisplsFull(nRecvCycles),edge%putDisplsFull(nRecvCycles))
         383      234274 :        edge%rcountsFull(:) = 0
         384             :        ! allocate the MPI Send/Recv request handles
         385       62976 :        allocate(edge%Rrequest(nRecvCycles))
         386       94464 :        allocate(edge%status(HME_status_size,nRecvCycles))
         387             :     endif
         388             :
         389             :     !
         390             :     ! Setup the data-structures for the receives
         391             :     !
         392       31488 :     j      = 1
         393       31488 :     icycle = 1
         394       31488 :     src0    = pSchedule%gIndx(j)%mesgid
         395       31488 :     il      = pSchedule%gIndx(j)%edgeid
         396       31488 :     ie      = pSchedule%gIndx(j)%elemid
         397       31488 :     len     = CalcSegmentLength(pSchedule%gIndx(j),CardinalLen,OrdinalLen,nlyr)
         398       31488 :     edge%getmap(il,ie) = 0
         399       31488 :     if (nRecvCycles>0) then
         400       31488 :        edge%rdisplsFull(icycle) = edge%getmap(il,ie)
         401       31488 :        edge%rcountsFull(icycle) = len
         402             :     endif
         403       31488 :     ilm1=il
         404       31488 :     iem1=ie
         405       31488 :     lenm1=len
         406             :
         407     1771200 :     do j=2,SIZE(pSchedule%gIndx)
         408     1739712 :        il = pSchedule%gIndx(j)%edgeid
         409     1739712 :        ie = pSchedule%gIndx(j)%elemid
         410     1739712 :        mesgid = pSchedule%gIndx(j)%mesgid
         411     1771200 :        if(il>0 .and. ie >0) then
         412     1738728 :           len     = CalcSegmentLength(pSchedule%gIndx(j),CardinalLen,OrdinalLen,nlyr)
         413     1738728 :           edge%getmap(il,ie) = edge%getmap(ilm1,iem1)+lenm1
         414     1738728 :           if(mesgid .ne. par%rank) then ! don't enter if this is a move cycle where (mesgid == par%rank)
         415      948740 :              if(mesgid .ne. src0) then
         416      171298 :                 if (nRecvCycles>0) edge%rdisplsFull(icycle+1) = edge%getmap(il,ie)
         417      171298 :                 icycle=icycle+1
         418      171298 :                 src0=mesgid
         419             :              endif
         420      948740 :              if (nRecvCycles>0) edge%rcountsFull(icycle) = edge%rcountsFull(icycle)+len
         421             :           endif
         422             :           ilm1=il
         423             :           iem1=ie
         424             :           lenm1=len
         425             :        endif
         426             :     enddo
         427             :
         428             :
         429             :     !
         430             :     ! populate the Inter and Intra node communication data-structures
         431             :     !
         432             :     icInter=0
         433             :     icIntra=0
         434      234274 :     do icycle=1,nRecvCycles
         435      234274 :        if(pSchedule%RecvCycle(icycle)%onNode .eqv. .FALSE.) then
         436      202786 :           icInter=icInter+1
         437      202786 :           edge%rdisplsInter(icInter)=edge%rdisplsFull(icycle)
         438      202786 :           edge%rcountsInter(icInter)=edge%rcountsFull(icycle)
         439             :        else
         440           0 :           icIntra=icIntra+1
         441           0 :           edge%rdisplsIntra(icIntra)=edge%rdisplsFull(icycle)
         442           0 :           edge%rcountsIntra(icIntra)=edge%rcountsFull(icycle)
         443             :        endif
         444             :     enddo
         445             :
         446             :
         447             :     ! Setup the data-structures for the on process moves
         448             :     ! Note that this assumes that the data to move is at
         449             :     ! the end of the  message buffer.
         450       31488 :     if(nRecvCycles>0) then
         451       31488 :        moveptr = edge%rdisplsFull(nRecvCycles)+edge%rcountsFull(nRecvCycles)+1
         452             :     else
         453             :        moveptr = 1
         454             :     endif
         455       31488 :     moveLength = 0
         456     1802688 :     do j=1,SIZE(pSchedule%gIndx)
         457     1771200 :        il     = pSchedule%gIndx(j)%edgeid
         458     1771200 :        ie     = pSchedule%gIndx(j)%elemid
         459     1771200 :        mesgid = pSchedule%gIndx(j)%mesgid
         460     1802688 :        if(mesgid == par%rank) then
         461      789988 :           len     = CalcSegmentLength(pSchedule%gIndx(j),CardinalLen,OrdinalLen,nlyr)
         462      789988 :           moveLength = moveLength + len
         463             :        endif
         464             :     enddo
         465             :
         466             :     ! decompose the move data between the available threads
         467       31488 :     if(max_num_threads<=0) then
         468           0 :        nlen = 1
         469             :     else
         470       31488 :        if(present(nthreads)) then
         471       26112 :           if (nthreads > 0) then
         472       26112 :              nlen = nthreads
         473             :           else
         474           0 :              nlen = max_num_threads
         475             :           end if
         476             :        else
         477        5376 :           nlen = 1
         478             :        end if
         479             :     end if
         480       31488 :     call gbarrier_init(edge%gbarrier, nlen)
         481             :
         482       94464 :     allocate(edge%moveLength(nlen))
         483       62976 :     allocate(edge%movePtr(nlen))
         484             :
         485       31488 :     if (nlen > 1) then
         486             :        ! the master thread performs no data movement because it is busy with the
         487             :        ! MPI messaging
         488           0 :        edge%moveLength(1) = -1
         489           0 :        edge%movePtr(1) = 0
         490             :
         491             :        ! Calculate the length of the local copy in bndy_exchange
         492           0 :        llen = ceiling(real(moveLength,kind=r8)/real(nlen-1,kind=r8))
         493           0 :        iptr = moveptr
         494           0 :        mLen = 0
         495           0 :        do i=2,nlen
         496           0 :          if( (mLen+llen) <= moveLength)  then
         497             :             tlen = llen
         498             :          else
         499           0 :             tlen = moveLength - mLen
         500             :          endif
         501           0 :          edge%moveLength(i) = tlen
         502           0 :          edge%movePtr(i)    = iptr
         503           0 :          iptr = iptr + tlen
         504           0 :          mLen = mLen + tLen
         505             :        enddo
         506             :     else
         507       31488 :        edge%moveLength(1) = moveLength
         508       31488 :        edge%movePtr(1) = moveptr
         509             :     endif
         510             :
         511             :     ! Set the maximum length of the message buffer
         512       31488 :     nbuf = movePtr+moveLength
         513             :
         514       31488 :     edge%nlyr=nlyr
         515       31488 :     edge%nbuf=nbuf
         516             :
         517       94464 :     allocate(edge%receive(nbuf))
         518       62976 :     allocate(edge%buf(nbuf))
         519             :
         520             : 21  format('RANK: ',i2, A,8(i6))
         521             :
         522             : !$OMP END MASTER
         523             : ! MT: This next barrier is also needed - threads cannot start using edge()
         524             : ! until MASTER is done initializing it
         525             : !$OMP BARRIER
         526             :
         527       31488 :   end subroutine initEdgeBuffer_r8
         528             :
         529     4330420 :   integer function CalcSegmentLength(pgIndx,CardinalLength,OrdinalLength,nlyr) result(len)
         530             :
         531             :      type(pgindex_t) ::  pgIndx
         532             :      integer, intent(in) :: CardinalLength,OrdinalLength
         533             :      integer, intent(in) :: nlyr
         534             :
         535             :      integer :: rem
         536             :      integer, parameter :: alignment=1  ! align on word boundaries
         537             : !     integer, parameter :: alignment=2  ! align on 2 word boundaries
         538             : !     integer, parameter :: alignment=8  ! align on 8 word boundaries
         539             :
         540     6589110 :      select case(pgIndx%edgeType)
         541             :         CASE(HME_Cardinal)
         542     2258690 :           len = nlyr*CardinalLength
         543             :         CASE(HME_Ordinal)
         544     4330420 :           len = nlyr*OrdinalLength
         545             :      end select
         546             :
         547     4330420 :      rem = MODULO(len,alignment)
         548             :      if(rem .ne. 0) then
         549             :         len = len + (alignment-rem)
         550             :      endif
         551             :
         552     4330420 :   end function calcSegmentLength
         553             :
         554             :   ! =========================================
         555             :   ! initEdgeBuffer:
         556             :   !
         557             :   ! create an Integer based communication buffer
         558             :   ! =========================================
         559        1536 :   subroutine initEdgeBuffer_i8(edge,nlyr)
         560             :     use dimensions_mod, only : np, nelemd, max_corner_elem
         561             :
         562             :     integer,                 intent(in)  :: nlyr
         563             :     type (LongEdgeBuffer_t), intent(out) :: edge
         564             :
         565             :     ! Local variables
         566             :     integer :: nbuf
         567             :
         568             :     ! sanity check for threading
         569        1536 :     if (omp_get_num_threads()>1) then
         570           0 :        call endrun('ERROR: initEdgeBuffer must be called before threaded reagion')
         571             :     endif
         572             :
         573        1536 :     nbuf=4*(np+max_corner_elem)*nelemd
         574        1536 :     edge%nlyr=nlyr
         575        1536 :     edge%nbuf=nbuf
         576        6144 :     allocate(edge%buf(nlyr,nbuf))
         577      433536 :     edge%buf(:,:)=0
         578             :
         579        4608 :     allocate(edge%receive(nlyr,nbuf))
         580      433536 :     edge%receive(:,:)=0
         581             :
         582        1536 :   end subroutine initEdgeBuffer_i8
         583             :   ! =========================================
         584             :   ! edgeDGVpack:
         585             :   !
         586             :   ! Pack edges of v into buf for DG stencil
         587             :   ! =========================================
         588           0 :   subroutine edgeDGVpack(edge,v,vlyr,kptr,ielem)
         589             :     use dimensions_mod, only: np
         590             :
         591             :     type (EdgeBuffer_t)        :: edge
         592             :     integer,        intent(in) :: vlyr
         593             :     real (kind=r8), intent(in) :: v(np,np,vlyr)
         594             :     integer,        intent(in) :: kptr
         595             :     integer,        intent(in) :: ielem
         596             :
         597             :     ! =========================================
         598             :     ! This code is just a wrapper call the
         599             :     !   normal oldedgeVpack
         600             :     ! =========================================
         601           0 :     call edgeVpack(edge,v,vlyr,kptr,ielem)
         602             :
         603           0 :   end subroutine edgeDGVpack
         604             :
         605        4608 :   subroutine FreeGhostBuffer_r8(edge)
         606             :      type (EdgeBuffer_t), intent(inout) :: edge
         607        4608 :      call FreeEdgeBuffer_r8(edge)
         608        4608 :   end subroutine FreeGhostBuffer_r8
         609             :   ! ===========================================
         610             :   !  FreeEdgeBuffer:
         611             :   !
         612             :   !  Freed an edge communication buffer
         613             :   ! =========================================
         614        8448 :   subroutine FreeEdgeBuffer_r8(edge)
         615             :
         616             :     type (EdgeBuffer_t),intent(inout) :: edge
         617             :
         618             : !$OMP BARRIER
         619             : !$OMP MASTER
         620        8448 :     if(allocated(edge%buf))         deallocate(edge%buf)
         621        8448 :     if(allocated(edge%receive))     deallocate(edge%receive)
         622        8448 :     if(associated(edge%putmap))     deallocate(edge%putmap)
         623        8448 :     if(associated(edge%getmap))     deallocate(edge%getmap)
         624        8448 :     if(associated(edge%reverse))    deallocate(edge%reverse)
         625        8448 :     if(associated(edge%moveLength)) deallocate(edge%moveLength)
         626        8448 :     if(associated(edge%movePtr))    deallocate(edge%movePtr)
         627             :
         628             :     ! All MPI communications
         629        8448 :     if(associated(edge%rcountsFull)) deallocate(edge%rcountsFull)
         630        8448 :     if(associated(edge%scountsFull)) deallocate(edge%scountsFull)
         631        8448 :     if(associated(edge%sdisplsFull)) deallocate(edge%sdisplsFull)
         632        8448 :     if(associated(edge%rdisplsFull)) deallocate(edge%rdisplsFull)
         633             :
         634             :     ! Intra-node MPI Communication
         635        8448 :     if(edge%nIntra>0) then
         636           0 :       if(associated(edge%rcountsIntra)) deallocate(edge%rcountsIntra)
         637           0 :       if(associated(edge%scountsIntra)) deallocate(edge%scountsIntra)
         638           0 :       if(associated(edge%sdisplsIntra)) deallocate(edge%sdisplsIntra)
         639           0 :       if(associated(edge%rdisplsIntra)) deallocate(edge%rdisplsIntra)
         640             :     endif
         641             :
         642             :     ! Inter-node MPI Communication
         643        8448 :     if(edge%nInter>0) then
         644        8448 :       if(associated(edge%rcountsInter)) deallocate(edge%rcountsInter)
         645        8448 :       if(associated(edge%scountsInter)) deallocate(edge%scountsInter)
         646        8448 :       if(associated(edge%sdisplsInter)) deallocate(edge%sdisplsInter)
         647        8448 :       if(associated(edge%rdisplsInter)) deallocate(edge%rdisplsInter)
         648             :     endif
         649        8448 :     if(allocated(edge%rRequest)) deallocate(edge%rRequest)
         650        8448 :     if(allocated(edge%sRequest)) deallocate(edge%sRequest)
         651        8448 :     if(allocated(edge%status)) deallocate(edge%status)
         652        8448 :     call gbarrier_delete(edge%gbarrier)
         653             :
         654             : !$OMP END MASTER
         655             :
         656        8448 :   end subroutine FreeEdgeBuffer_r8
         657             :
         658             :   ! ===========================================
         659             :   !  FreeEdgeBuffer:
         660             :   !
         661             :   !  Freed an edge communication buffer
         662             :   ! =========================================
         663        1536 :   subroutine FreeEdgeBuffer_i8(edge)
         664             :
         665             :     type (LongEdgeBuffer_t),intent(inout) :: edge
         666             :
         667        1536 :     edge%nbuf=0
         668        1536 :     edge%nlyr=0
         669        1536 :     deallocate(edge%buf)
         670        1536 :     deallocate(edge%receive)
         671             :
         672        1536 :   end subroutine FreeEdgeBuffer_i8
         673             :
         674             :   ! =========================================
         675             :   !
         676             :   !> @brief Pack edges of v into an edge buffer for boundary exchange.
         677             :   !
         678             :   !> This subroutine packs for one or more vertical layers into an edge
         679             :   !! buffer. If the buffer associated with edge is not large enough to
         680             :   !! hold all vertical layers you intent to pack, the method will
         681             :   !! halt the program with a call to endrum().
         682             :   !! @param[in] edge Edge Buffer into which the data will be packed.
         683             :   !! This buffer must be previously allocated with initEdgeBuffer().
         684             :   !! @param[in] v The data to be packed.
         685             :   !! @param[in] vlyr Number of vertical level coming into the subroutine
         686             :   !! for packing for input v.
         687             :   !! @param[in] kptr Vertical pointer to the place in the edge buffer where
         688             :   !! data will be located.
         689             :   ! =========================================
         690   823548600 :   subroutine edgeVpack(edge,v,vlyr,kptr,ielem)
         691             :     use dimensions_mod, only: np, max_corner_elem
         692             :     use control_mod,    only: north, south, east, west, neast, nwest, seast, swest
         693             :
         694             :     type (EdgeBuffer_t)        :: edge
         695             :     integer,        intent(in) :: vlyr
         696             :     real (kind=r8), intent(in) :: v(np,np,vlyr)
         697             :     integer,        intent(in) :: kptr
         698             :     integer,        intent(in) :: ielem
         699             :
         700             :     ! Local variables
         701             :     integer :: i,k,ir,ll,iptr
         702             :     integer :: is,ie,in,iw,edgeptr
         703             :
         704   823548600 :     is = edge%putmap(south,ielem)
         705   823548600 :     ie = edge%putmap(east,ielem)
         706   823548600 :     in = edge%putmap(north,ielem)
         707   823548600 :     iw = edge%putmap(west,ielem)
         708   823548600 :     if (edge%nlyr < (kptr+vlyr) ) then
         709           0 :        print *,'edge%nlyr = ',edge%nlyr
         710           0 :        print *,'kptr+vlyr = ',kptr+vlyr
         711           0 :        call endrun('edgeVpack: Buffer overflow: size of the vertical dimension must be increased!')
         712             :     endif
         713             :
         714             : !dir$ ivdep
         715 68515421400 :     do k=1,vlyr
         716 67691872800 :        iptr = np*(kptr+k-1)
         717 >33928*10^7 :        do i=1,np
         718 >27076*10^7 :           edge%buf(iptr+ie+i)   = v(np ,i ,k) ! East
         719 >27076*10^7 :           edge%buf(iptr+is+i)   = v(i  ,1 ,k) ! South
         720 >27076*10^7 :           edge%buf(iptr+in+i)   = v(i  ,np,k) ! North
         721 >33845*10^7 :           edge%buf(iptr+iw+i)   = v(1  ,i ,k) ! West
         722             :        enddo
         723             :     enddo
         724             :
         725             :     !  This is really kludgy way to setup the index reversals
         726             :     !  But since it is so a rare event not real need to spend time optimizing
         727             :
         728   823548600 :     if(edge%reverse(south,ielem)) then
         729  1141923690 :        do k=1,vlyr
         730  1128197880 :           iptr = np*(kptr+k-1)+is
         731  5654715210 :           do i=1,np
         732  4512791520 :              ir = np-i+1
         733  5640989400 :              edge%buf(iptr+ir)=v(i,1,k)
         734             :           enddo
         735             :        enddo
         736             :     endif
         737             :
         738   823548600 :     if(edge%reverse(east,ielem)) then
         739   380641230 :        do k=1,vlyr
         740   376065960 :           iptr=np*(kptr+k-1)+ie
         741  1884905070 :           do i=1,np
         742  1504263840 :              ir = np-i+1
         743  1880329800 :              edge%buf(iptr+ir)=v(np,i,k)
         744             :           enddo
         745             :        enddo
         746             :     endif
         747             :
         748   823548600 :     if(edge%reverse(north,ielem)) then
         749  1141923690 :        do k=1,vlyr
         750  1128197880 :           iptr=np*(kptr+k-1)+in
         751  5654715210 :           do i=1,np
         752  4512791520 :              ir = np-i+1
         753  5640989400 :              edge%buf(iptr+ir)=v(i,np,k)
         754             :           enddo
         755             :        enddo
         756             :     endif
         757             :
         758   823548600 :     if(edge%reverse(west,ielem)) then
         759   380641230 :        do k=1,vlyr
         760   376065960 :           iptr=np*(kptr+k-1)+iw
         761  1884905070 :           do i=1,np
         762  1504263840 :              ir = np-i+1
         763  1880329800 :              edge%buf(iptr+ir)=v(1,i,k)
         764             :           enddo
         765             :        enddo
         766             :     endif
         767             :
         768             : ! SWEST
         769  1647097200 :     do ll=swest,swest+max_corner_elem-1
         770  1647097200 :         if (edge%putmap(ll,ielem) /= -1) then
         771   822633546 :             edgeptr = edge%putmap(ll,ielem)+1
         772 68439293154 :             do k=1,vlyr
         773 67616659608 :                 iptr = (kptr+k-1)+edgeptr
         774 67616659608 :                 if (iptr > size(edge%buf)) then
         775           0 :                    write(6, *) 'ERROR SW: ',size(edge%buf),iptr,edge%putmap(ll,ielem)
         776           0 :                    call endrun('pointer bounds ERROR SW')
         777             :                 end if
         778 68439293154 :                 edge%buf(iptr) = v(1, 1, k)
         779             :             end do
         780             :         end if
         781             :     end do
         782             :
         783             : ! SEAST
         784  1647097200 :     do ll=swest+max_corner_elem,swest+2*max_corner_elem-1
         785  1647097200 :         if (edge%putmap(ll,ielem) /= -1) then
         786   822633546 :             edgeptr = edge%putmap(ll,ielem)+1
         787 68439293154 :             do k=1,vlyr
         788 67616659608 :                iptr = (kptr+k-1)+edgeptr
         789 67616659608 :                if (iptr > size(edge%buf)) then
         790           0 :                   write(6, *) 'ERROR SE: ',size(edge%buf),iptr,edge%putmap(ll,ielem)
         791           0 :                   call endrun('pointer bounds ERROR SE')
         792             :                end if
         793 68439293154 :                edge%buf(iptr)=v(np, 1, k)
         794             :             end do
         795             :         end if
         796             :     end do
         797             :
         798             : ! NEAST
         799  1647097200 :     do ll=swest+3*max_corner_elem,swest+4*max_corner_elem-1
         800  1647097200 :         if (edge%putmap(ll,ielem) /= -1) then
         801   822633546 :             edgeptr = edge%putmap(ll,ielem)+1
         802 68439293154 :             do k=1,vlyr
         803 67616659608 :                iptr = (kptr+k-1)+edgeptr
         804 67616659608 :                if (iptr > size(edge%buf)) then
         805           0 :                   write(6, *) 'ERROR NE: ',size(edge%buf),iptr,edge%putmap(ll,ielem)
         806           0 :                   call endrun('pointer bounds ERROR NE')
         807             :                end if
         808 68439293154 :                edge%buf(iptr) = v(np, np, k)
         809             :             end do
         810             :         end if
         811             :     end do
         812             :
         813             : ! NWEST
         814  1647097200 :     do ll=swest+2*max_corner_elem,swest+3*max_corner_elem-1
         815  1647097200 :         if (edge%putmap(ll,ielem) /= -1) then
         816   822633546 :             edgeptr = edge%putmap(ll,ielem)+1
         817 68439293154 :             do k=1,vlyr
         818 67616659608 :                iptr = (kptr+k-1)+edgeptr
         819 67616659608 :                if (iptr > size(edge%buf)) then
         820           0 :                   write(6, *) 'ERROR NW: ',size(edge%buf),iptr,edge%putmap(ll,ielem)
         821           0 :                   call endrun('pointer bounds ERROR NW')
         822             :                end if
         823 68439293154 :                edge%buf(iptr) = v(1, np, k)
         824             :             end do
         825             :         end if
         826             :     end do
         827             :
         828   823548600 :   end subroutine edgeVpack
         829             :
         830           0 :   subroutine edgeSpack_r8(edge,v,vlyr,kptr,ielem)
         831             :     use dimensions_mod, only: np, max_corner_elem
         832             :     use control_mod,    only: north, south, east, west, neast, nwest, seast, swest
         833             :
         834             :     type (EdgeBuffer_t)        :: edge
         835             :     integer,        intent(in) :: vlyr
         836             :     real (kind=r8), intent(in) :: v(vlyr)
         837             :     integer,        intent(in) :: kptr
         838             :     integer,        intent(in) :: ielem
         839             :
         840             :     ! Local variables
         841             :     integer        :: i,k,ir,ll,iptr
         842             :     integer        :: is,ie,in,iw,edgeptr
         843             :     real (kind=r8) :: tmp
         844             :
         845           0 :     is = edge%putmap(south,ielem)
         846           0 :     ie = edge%putmap(east,ielem)
         847           0 :     in = edge%putmap(north,ielem)
         848           0 :     iw = edge%putmap(west,ielem)
         849           0 :     if (edge%nlyr < (kptr+vlyr) ) then
         850           0 :        call endrun('edgeSpack: Buffer overflow: size of the vertical dimension must be increased!')
         851             :     endif
         852             :
         853           0 :     do k=1,vlyr
         854           0 :        iptr = kptr+k-1
         855           0 :        edge%buf(iptr+ie+1)   = v(k) ! East
         856           0 :        edge%buf(iptr+is+1)   = v(k) ! South
         857           0 :        edge%buf(iptr+in+1)   = v(k) ! North
         858           0 :        edge%buf(iptr+iw+1)   = v(k) ! West
         859             :     enddo
         860             :
         861             : ! SWEST
         862           0 :     do ll=swest,swest+max_corner_elem-1
         863           0 :         if (edge%putmap(ll,ielem) /= -1) then
         864           0 :             edgeptr=edge%putmap(ll,ielem)+1
         865           0 :             do k=1,vlyr
         866           0 :                 iptr = (kptr+k-1)+edgeptr
         867           0 :                 edge%buf(iptr)=v(k)
         868             :             end do
         869             :         end if
         870             :     end do
         871             :
         872             : ! SEAST
         873           0 :     do ll=swest+max_corner_elem,swest+2*max_corner_elem-1
         874           0 :         if (edge%putmap(ll,ielem) /= -1) then
         875           0 :             edgeptr=edge%putmap(ll,ielem)+1
         876           0 :             do k=1,vlyr
         877           0 :                 iptr = (kptr+k-1)+edgeptr
         878           0 :                 edge%buf(iptr)=v(k)
         879             :             end do
         880             :         end if
         881             :     end do
         882             :
         883             : ! NEAST
         884           0 :     do ll=swest+3*max_corner_elem,swest+4*max_corner_elem-1
         885           0 :         if (edge%putmap(ll,ielem) /= -1) then
         886           0 :             edgeptr=edge%putmap(ll,ielem)+1
         887           0 :             do k=1,vlyr
         888           0 :                 iptr = (kptr+k-1)+edgeptr
         889           0 :                 edge%buf(iptr)=v(k)
         890             :             end do
         891             :         end if
         892             :     end do
         893             :
         894             : ! NWEST
         895           0 :     do ll=swest+2*max_corner_elem,swest+3*max_corner_elem-1
         896           0 :         if (edge%putmap(ll,ielem) /= -1) then
         897           0 :             edgeptr=edge%putmap(ll,ielem)+1
         898           0 :             do k=1,vlyr
         899           0 :                 iptr = (kptr+k-1)+edgeptr
         900           0 :                 edge%buf(iptr)=v(k)
         901             :             end do
         902             :         end if
         903             :     end do
         904             :
         905           0 :   end subroutine edgeSpack_r8
         906             :
         907             :   ! =========================================
         908             :   ! LongEdgeVpack:
         909             :   !
         910             :   ! Pack edges of v into buf...
         911             :   ! =========================================
         912       10800 :   subroutine LongEdgeVpack(edge,v,vlyr,kptr,desc)
         913             :     use control_mod,    only: north, south, east, west, neast, nwest, seast, swest
         914             :     use dimensions_mod, only: np, max_corner_elem
         915             :
         916             :     type (LongEdgeBuffer_t)             :: edge
         917             :     integer,                 intent(in) :: vlyr
         918             :     integer ,                intent(in) :: v(np,np,vlyr)
         919             :     integer,                 intent(in) :: kptr
         920             :     type (EdgeDescriptor_t), intent(in) :: desc
         921             :
         922             :     ! Local variables
         923             :     logical, parameter :: UseUnroll = .TRUE.
         924             :     integer            :: i,k,ir,l
         925             :     integer            :: is,ie,in,iw
         926             :
         927       10800 :     if(.not. threadsafe) then
         928             : !$OMP BARRIER
         929           0 :        threadsafe=.true.
         930             :     end if
         931             :
         932       10800 :     is = desc%putmapP(south)
         933       10800 :     ie = desc%putmapP(east)
         934       10800 :     in = desc%putmapP(north)
         935       10800 :     iw = desc%putmapP(west)
         936             :
         937             :     if(MODULO(np,2) == 0 .and. UseUnroll) then
         938       21600 :        do k=1,vlyr
         939       10800 :           do i=1,np,2
         940       21600 :              edge%buf(kptr+k,is+i)   = v(i  ,1 ,k)
         941       21600 :              edge%buf(kptr+k,is+i+1) = v(i+1,1 ,k)
         942       21600 :              edge%buf(kptr+k,ie+i)   = v(np ,i ,k)
         943       21600 :              edge%buf(kptr+k,ie+i+1) = v(np ,i+1 ,k)
         944       21600 :              edge%buf(kptr+k,in+i)   = v(i  ,np,k)
         945       21600 :              edge%buf(kptr+k,in+i+1) = v(i+1  ,np,k)
         946       21600 :              edge%buf(kptr+k,iw+i)   = v(1  ,i ,k)
         947       21600 :              edge%buf(kptr+k,iw+i+1) = v(1  ,i+1 ,k)
         948             :
         949             :           enddo
         950             :        end do
         951             :     else
         952             :        do k=1,vlyr
         953             :           do i=1,np
         954             :              edge%buf(kptr+k,is+i)   = v(i  ,1 ,k)
         955             :              edge%buf(kptr+k,ie+i)   = v(np ,i ,k)
         956             :              edge%buf(kptr+k,in+i)   = v(i  ,np,k)
         957             :              edge%buf(kptr+k,iw+i)   = v(1  ,i ,k)
         958             :           enddo
         959             :        end do
         960             :
         961             :     endif
         962             :
         963             :
         964             :     !  This is really kludgy way to setup the index reversals
         965             :     !  But since it is so a rare event not real need to spend time optimizing
         966             :
         967       10800 :     if(desc%reverse(south)) then
         968         180 :        is = desc%putmapP(south)
         969         360 :        do k=1,vlyr
         970        1080 :           do i=1,np
         971         720 :              ir = np-i+1
         972         900 :              edge%buf(kptr+k,is+ir)=v(i,1,k)
         973             :           enddo
         974             :        enddo
         975             :     endif
         976             :
         977       10800 :     if(desc%reverse(east)) then
         978          60 :        ie = desc%putmapP(east)
         979         120 :        do k=1,vlyr
         980         360 :           do i=1,np
         981         240 :              ir = np-i+1
         982         300 :              edge%buf(kptr+k,ie+ir)=v(np,i,k)
         983             :           enddo
         984             :        enddo
         985             :     endif
         986             :
         987       10800 :     if(desc%reverse(north)) then
         988         180 :        in = desc%putmapP(north)
         989         360 :        do k=1,vlyr
         990        1080 :           do i=1,np
         991         720 :              ir = np-i+1
         992         900 :              edge%buf(kptr+k,in+ir)=v(i,np,k)
         993             :           enddo
         994             :        enddo
         995             :     endif
         996             :
         997       10800 :     if(desc%reverse(west)) then
         998          60 :        iw = desc%putmapP(west)
         999         120 :        do k=1,vlyr
        1000         360 :           do i=1,np
        1001         240 :              ir = np-i+1
        1002         300 :              edge%buf(kptr+k,iw+ir)=v(1,i,k)
        1003             :           enddo
        1004             :        enddo
        1005             :     endif
        1006             :
        1007             : ! SWEST
        1008       21600 :     do l=swest,swest+max_corner_elem-1
        1009       21600 :         if (desc%putmapP(l) /= -1) then
        1010       21576 :             do k=1,vlyr
        1011       21576 :                 edge%buf(kptr+k,desc%putmapP(l)+1)=v(1  ,1 ,k)
        1012             :             end do
        1013             :         end if
        1014             :     end do
        1015             :
        1016             : ! SEAST
        1017       21600 :     do l=swest+max_corner_elem,swest+2*max_corner_elem-1
        1018       21600 :         if (desc%putmapP(l) /= -1) then
        1019       21576 :             do k=1,vlyr
        1020       21576 :                 edge%buf(kptr+k,desc%putmapP(l)+1)=v(np ,1 ,k)
        1021             :             end do
        1022             :         end if
        1023             :     end do
        1024             :
        1025             : ! NEAST
        1026       21600 :     do l=swest+3*max_corner_elem,swest+4*max_corner_elem-1
        1027       21600 :         if (desc%putmapP(l) /= -1) then
        1028       21576 :             do k=1,vlyr
        1029       21576 :                 edge%buf(kptr+k,desc%putmapP(l)+1)=v(np ,np,k)
        1030             :             end do
        1031             :         end if
        1032             :     end do
        1033             :
        1034             : ! NWEST
        1035       21600 :     do l=swest+2*max_corner_elem,swest+3*max_corner_elem-1
        1036       21600 :         if (desc%putmapP(l) /= -1) then
        1037       21576 :             do k=1,vlyr
        1038       21576 :                 edge%buf(kptr+k,desc%putmapP(l)+1)=v(1  ,np,k)
        1039             :             end do
        1040             :         end if
        1041             :     end do
        1042             :
        1043       10800 :   end subroutine LongEdgeVpack
        1044             :
        1045   823548600 :   subroutine edgeVunpack(edge,v,vlyr,kptr,ielem,rank)
        1046             :     use dimensions_mod, only: np, max_corner_elem
        1047             :     use control_mod,    only: north, south, east, west, neast, nwest, seast, swest
        1048             :
        1049             :     type (EdgeBuffer_t), intent(in)    :: edge
        1050             :     integer,             intent(in)    :: vlyr
        1051             :     real (kind=r8),      intent(inout) :: v(np,np,vlyr)
        1052             :     integer,             intent(in)    :: kptr
        1053             :     integer,             intent(in)    :: ielem
        1054             :     integer, optional,   intent(in)    :: rank
        1055             :
        1056             :     ! Local
        1057             :     integer :: i,k,ll,iptr
        1058             :     integer :: is,ie,in,iw,edgeptr
        1059             :     integer :: ise,isw,ine,inw
        1060             :     integer :: ks,ke,kblock
        1061             :     logical :: done
        1062             :
        1063   823548600 :     is=edge%getmap(south,ielem)
        1064   823548600 :     ie=edge%getmap(east,ielem)
        1065   823548600 :     in=edge%getmap(north,ielem)
        1066   823548600 :     iw=edge%getmap(west,ielem)
        1067   823548600 :     isw=edge%getmap(swest,ielem)
        1068   823548600 :     ise=edge%getmap(seast,ielem)
        1069   823548600 :     inw=edge%getmap(nwest,ielem)
        1070   823548600 :     ine=edge%getmap(neast,ielem)
        1071             :
        1072             :     !DIR$ IVDEP
        1073 68515421400 :     do k=1,vlyr
        1074 67691872800 :        iptr=np*(kptr+k-1)
        1075 >33928*10^7 :        do i=1,np
        1076 >27076*10^7 :           v(np ,i  ,k) = v(np ,i  ,k)+edge%receive(iptr+i+ie) ! East
        1077 >27076*10^7 :           v(i  ,1  ,k) = v(i  ,1  ,k)+edge%receive(iptr+i+is) ! South
        1078 >27076*10^7 :           v(i  ,np ,k) = v(i  ,np ,k)+edge%receive(iptr+i+in) ! North
        1079 >33845*10^7 :           v(1  ,i  ,k) = v(1  ,i  ,k)+edge%receive(iptr+i+iw) ! West
        1080             :        enddo
        1081             :     enddo
        1082             :
        1083             : ! SWEST
        1084  1647097200 :     do ll=swest,swest+max_corner_elem-1
        1085  1647097200 :         if(edge%getmap(ll,ielem) /= -1) then
        1086   822633546 :             edgeptr=edge%getmap(ll,ielem)+1
        1087 68439293154 :             do k=1,vlyr
        1088 67616659608 :                 iptr = (kptr+k-1)+edgeptr
        1089 68439293154 :                 v(1  ,1 ,k)=v(1 ,1 ,k)+edge%receive(iptr)
        1090             :             enddo
        1091             :         endif
        1092             :     end do
        1093             :
        1094             : ! SEAST
        1095  1647097200 :     do ll=swest+max_corner_elem,swest+2*max_corner_elem-1
        1096  1647097200 :         if(edge%getmap(ll,ielem) /= -1) then
        1097   822633546 :             edgeptr=edge%getmap(ll,ielem)+1
        1098 68439293154 :             do k=1,vlyr
        1099 67616659608 :                 iptr = (kptr+k-1)+edgeptr
        1100 68439293154 :                 v(np ,1 ,k)=v(np,1 ,k)+edge%receive(iptr)
        1101             :             enddo
        1102             :         endif
        1103             :     end do
        1104             :
        1105             : ! NEAST
        1106  1647097200 :     do ll=swest+3*max_corner_elem,swest+4*max_corner_elem-1
        1107  1647097200 :         if(edge%getmap(ll,ielem) /= -1) then
        1108   822633546 :             edgeptr=edge%getmap(ll,ielem)+1
        1109 68439293154 :             do k=1,vlyr
        1110 67616659608 :                 iptr = (kptr+k-1)+edgeptr
        1111 68439293154 :                 v(np ,np,k)=v(np,np,k)+edge%receive(iptr)
        1112             :             enddo
        1113             :         endif
        1114             :     end do
        1115             :
        1116             : ! NWEST
        1117  1647097200 :     do ll=swest+2*max_corner_elem,swest+3*max_corner_elem-1
        1118  1647097200 :         if(edge%getmap(ll,ielem) /= -1) then
        1119   822633546 :             edgeptr=edge%getmap(ll,ielem)+1
        1120 68439293154 :             do k=1,vlyr
        1121 67616659608 :                 iptr = (kptr+k-1)+edgeptr
        1122 68439293154 :                 v(1  ,np,k)=v(1 ,np,k)+edge%receive(iptr)
        1123             :             enddo
        1124             :         endif
        1125             :     end do
        1126             :
        1127             :
        1128   823548600 :   end subroutine edgeVunpack
        1129             : !
        1130           0 :   subroutine edgeVunpackVert(edge,v,ielem)
        1131             :     use control_mod,            only: north, south, east, west, neast, nwest, seast, swest
        1132             :     use dimensions_mod,         only: np, max_corner_elem, ne
        1133             :     use coordinate_systems_mod, only: cartesian3D_t
        1134             :
        1135             :     type (EdgeBuffer_t),  intent(inout) :: edge
        1136             :     type (cartesian3D_t), intent(inout)   :: v(:,:,:)
        1137             :     integer,              intent(in)    :: ielem
        1138             :
        1139             :     ! Local
        1140             :     logical, parameter :: UseUnroll = .TRUE.
        1141             :     integer            :: i,k,l, nce
        1142             :     integer            :: is,ie,in,iw,ine,inw,isw,ise
        1143             :
        1144           0 :     threadsafe=.false.
        1145             :
        1146           0 :     if (max_corner_elem.ne.1 .and. ne==0) then
        1147             :         ! MNL: this is used to construct the dual grid on the cube,
        1148             :         !      currently only supported for the uniform grid. If
        1149             :         !      this is desired on a refined grid, a little bit of
        1150             :         !      work will be required.
        1151           0 :         call endrun("edgeVunpackVert should not be called with unstructured meshes")
        1152             :     end if
        1153             :
        1154           0 :     is=edge%getmap(south,ielem)
        1155           0 :     ie=edge%getmap(east,ielem)
        1156           0 :     in=edge%getmap(north,ielem)
        1157           0 :     iw=edge%getmap(west,ielem)
        1158             :
        1159             :
        1160             :     ! N+S
        1161           0 :     do i=1,np/2
        1162             :        ! North
        1163           0 :        v(3,i ,np)%x = edge%receive(in+i)
        1164           0 :        v(3,i ,np)%y = edge%receive(np+in+i)
        1165           0 :        v(3,i ,np)%z = edge%receive(2*np+in+i)
        1166             :
        1167             :        ! South
        1168           0 :        v(2,i ,1)%x  = edge%receive(is+i)
        1169           0 :        v(2,i ,1)%y  = edge%receive(np+is+i)
        1170           0 :        v(2,i ,1)%z  = edge%receive(2*np+is+i)
        1171             :     enddo
        1172             :
        1173           0 :     do i=np/2+1,np
        1174             :        ! North
        1175           0 :        v(4,i ,np)%x = edge%receive(in+i)
        1176           0 :        v(4,i ,np)%y = edge%receive(np+in+i)
        1177           0 :        v(4,i ,np)%z = edge%receive(2*np+in+i)
        1178             :        ! South
        1179           0 :        v(1,i ,1)%x  = edge%receive(is+i)
        1180           0 :        v(1,i ,1)%y  = edge%receive(np+is+i)
        1181           0 :        v(1,i ,1)%z  = edge%receive(2*np+is+i)
        1182             :     enddo
        1183             :
        1184           0 :     do i=1,np/2
        1185             :        ! East
        1186           0 :        v(3,np,i)%x = edge%receive(ie+i)
        1187           0 :        v(3,np,i)%y = edge%receive(np+ie+i)
        1188           0 :        v(3,np,i)%z = edge%receive(2*np+ie+i)
        1189             :        ! West
        1190           0 :        v(4,1,i)%x  = edge%receive(iw+i)
        1191           0 :        v(4,1,i)%y  = edge%receive(np+iw+i)
        1192           0 :        v(4,1,i)%z  = edge%receive(2*np+iw+i)
        1193             :     end do
        1194             :
        1195           0 :     do i=np/2+1,np
        1196             :        ! East
        1197           0 :        v(2,np,i)%x = edge%receive(ie+i)
        1198           0 :        v(2,np,i)%y = edge%receive(np+ie+i)
        1199           0 :        v(2,np,i)%z = edge%receive(2*np+ie+i)
        1200             :        ! West
        1201           0 :        v(1,1,i)%x  = edge%receive(iw+i)
        1202           0 :        v(1,1,i)%y  = edge%receive(np+iw+i)
        1203           0 :        v(1,1,i)%z  = edge%receive(2*np+iw+i)
        1204             :     end do
        1205             :
        1206             : ! SWEST
        1207           0 :     nce = max_corner_elem
        1208           0 :     do l=swest,swest+max_corner_elem-1
        1209             :        ! find the one active corner, then exist
        1210           0 :         isw=edge%getmap(l,ielem)
        1211           0 :         if(isw /= -1) then
        1212           0 :             v(1,1,1)%x=edge%receive(isw+1)
        1213           0 :             v(1,1,1)%y=edge%receive(nce+isw+1)
        1214           0 :             v(1,1,1)%z=edge%receive(2*nce+isw+1)
        1215           0 :             exit
        1216             :         else
        1217           0 :             v(1,1,1)%x=0_r8
        1218           0 :             v(1,1,1)%y=0_r8
        1219           0 :             v(1,1,1)%z=0_r8
        1220             :         endif
        1221             :     end do
        1222             :
        1223             : ! SEAST
        1224           0 :     do l=swest+max_corner_elem,swest+2*max_corner_elem-1
        1225             :        ! find the one active corner, then exist
        1226           0 :         ise=edge%getmap(l,ielem)
        1227           0 :         if(ise /= -1) then
        1228           0 :             v(2,np,1)%x=edge%receive(ise+1)
        1229           0 :             v(2,np,1)%y=edge%receive(nce+ise+1)
        1230           0 :             v(2,np,1)%z=edge%receive(2*nce+ise+1)
        1231           0 :             exit
        1232             :         else
        1233           0 :             v(2,np,1)%x=0_r8
        1234           0 :             v(2,np,1)%y=0_r8
        1235           0 :             v(2,np,1)%z=0_r8
        1236             :         endif
        1237             :     end do
        1238             :
        1239             : ! NEAST
        1240           0 :     do l=swest+3*max_corner_elem,swest+4*max_corner_elem-1
        1241             :        ! find the one active corner, then exist
        1242           0 :         ine=edge%getmap(l,ielem)
        1243           0 :         if(ine /= -1) then
        1244           0 :             v(3,np,np)%x=edge%receive(ine+1)
        1245           0 :             v(3,np,np)%y=edge%receive(nce+ine+1)
        1246           0 :             v(3,np,np)%z=edge%receive(2*nce+ine+1)
        1247           0 :             exit
        1248             :         else
        1249           0 :             v(3,np,np)%x=0_r8
        1250           0 :             v(3,np,np)%y=0_r8
        1251           0 :             v(3,np,np)%z=0_r8
        1252             :         endif
        1253             :     end do
        1254             :
        1255             : ! NWEST
        1256           0 :     do l=swest+2*max_corner_elem,swest+3*max_corner_elem-1
        1257             :        ! find the one active corner, then exist
        1258           0 :         inw = edge%getmap(l,ielem)
        1259           0 :         if(inw/= -1) then
        1260           0 :             v(4,1,np)%x=edge%receive(inw+1)
        1261           0 :             v(4,1,np)%y=edge%receive(nce+inw+1)
        1262           0 :             v(4,1,np)%z=edge%receive(2*nce+inw+1)
        1263           0 :             exit
        1264             :         else
        1265           0 :             v(4,1,np)%x=0_r8
        1266           0 :             v(4,1,np)%y=0_r8
        1267           0 :             v(4,1,np)%z=0_r8
        1268             :         endif
        1269             :     end do
        1270             :
        1271             :     ! Fill the missing vertex info
        1272             :
        1273           0 :     do i=2,np/2
        1274             :        ! North
        1275           0 :        v(4,i ,np)%x = v(3,i-1 ,np)%x
        1276           0 :        v(4,i ,np)%y = v(3,i-1 ,np)%y
        1277           0 :        v(4,i ,np)%z = v(3,i-1 ,np)%z
        1278             :        ! South
        1279           0 :        v(1,i ,1)%x  = v(2,i-1 ,1)%x
        1280           0 :        v(1,i ,1)%y  = v(2,i-1 ,1)%y
        1281           0 :        v(1,i ,1)%z  = v(2,i-1 ,1)%z
        1282             :     enddo
        1283             :
        1284           0 :     do i=np/2+1,np-1
        1285             :        ! North
        1286           0 :        v(3,i ,np)%x = v(4,i+1 ,np)%x
        1287           0 :        v(3,i ,np)%y = v(4,i+1 ,np)%y
        1288           0 :        v(3,i ,np)%z = v(4,i+1 ,np)%z
        1289             :        ! South
        1290           0 :        v(2,i ,1)%x  = v(1,i+1 ,1)%x
        1291           0 :        v(2,i ,1)%y  = v(1,i+1 ,1)%y
        1292           0 :        v(2,i ,1)%z  = v(1,i+1 ,1)%z
        1293             :     enddo
        1294             :
        1295           0 :     do i=2,np/2
        1296             :        ! East
        1297           0 :        v(2,np,i)%x = v(3,np,i-1)%x
        1298           0 :        v(2,np,i)%y = v(3,np,i-1)%y
        1299           0 :        v(2,np,i)%z = v(3,np,i-1)%z
        1300             :        ! West
        1301           0 :        v(1,1,i)%x  = v(4,1,i-1)%x
        1302           0 :        v(1,1,i)%y  = v(4,1,i-1)%y
        1303           0 :        v(1,1,i)%z  = v(4,1,i-1)%z
        1304             :     end do
        1305             :
        1306           0 :     do i=np/2+1,np-1
        1307             :        ! East
        1308           0 :        v(3,np,i)%x = v(2,np,i+1)%x
        1309           0 :        v(3,np,i)%y = v(2,np,i+1)%y
        1310           0 :        v(3,np,i)%z = v(2,np,i+1)%z
        1311             :        ! West
        1312           0 :        v(4,1,i)%x  = v(1,1,i+1)%x
        1313           0 :        v(4,1,i)%y  = v(1,1,i+1)%y
        1314           0 :        v(4,1,i)%z  = v(1,1,i+1)%z
        1315             :     end do
        1316             :
        1317           0 :   end subroutine edgeVunpackVert
        1318             :   ! ========================================
        1319             :   ! edgeDGVunpack:
        1320             :   !
        1321             :   ! Unpack edges from edge buffer into v...
        1322             :   ! ========================================
        1323             :
        1324   124675200 :   subroutine edgeDGVunpack(edge,v,vlyr,kptr,ielem)
        1325             :     use dimensions_mod, only: np, max_corner_elem
        1326             :     use control_mod,    only: north, south, east, west, neast, nwest, seast, swest
        1327             :
        1328             :     type (EdgeBuffer_t), intent(in)    :: edge
        1329             :     integer,             intent(in)    :: vlyr
        1330             :     real (kind=r8),      intent(inout) :: v(0:np+1,0:np+1,vlyr)
        1331             :     integer,             intent(in)    :: kptr
        1332             :     integer,             intent(in)    :: ielem
        1333             :
        1334             :     ! Local
        1335             :     integer :: i,k,iptr
        1336             :     integer :: is,ie,in,iw
        1337             :
        1338   124675200 :     threadsafe=.false.
        1339             :
        1340   124675200 :     is=edge%getmap(south,ielem)
        1341   124675200 :     ie=edge%getmap(east,ielem)
        1342   124675200 :     in=edge%getmap(north,ielem)
        1343   124675200 :     iw=edge%getmap(west,ielem)
        1344  7558434000 :     do k=1,vlyr
        1345  7433758800 :        iptr=np*(kptr+k-1)
        1346 37293469200 :        do i=1,np
        1347 29735035200 :           v(i   ,0   ,k)=edge%receive(iptr+is+i)
        1348 29735035200 :           v(np+1,i   ,k)=edge%receive(iptr+ie+i)
        1349 29735035200 :           v(i   ,np+1,k)=edge%receive(iptr+in+i)
        1350 37168794000 :           v(0   ,i   ,k)=edge%receive(iptr+iw+i)
        1351             :        end do
        1352             :     end do
        1353             :
        1354   124675200 :     i = swest
        1355   124675200 :     if(edge%getmap(i,ielem) /= -1) then
        1356  7550035740 :       do k=1,vlyr
        1357  7425499068 :         iptr=(kptr+k-1)
        1358  7550035740 :         v(0,0,k) = edge%receive(iptr+edge%getmap(i,ielem)+1)
        1359             :       end do
        1360             :     end if
        1361   124675200 :     i = swest+max_corner_elem
        1362   124675200 :     if(edge%getmap(i,ielem) /= -1) then
        1363  7550035740 :       do k=1,vlyr
        1364  7425499068 :         iptr=(kptr+k-1)
        1365  7550035740 :         v(np+1,0,k) = edge%receive(iptr+edge%getmap(i,ielem)+1)
        1366             :       end do
        1367             :     end if
        1368   124675200 :     i = swest+3*max_corner_elem
        1369   124675200 :     if(edge%getmap(i,ielem) /= -1) then
        1370  7550035740 :       do k=1,vlyr
        1371  7425499068 :         iptr=(kptr+k-1)
        1372  7550035740 :         v(np+1,np+1,k) = edge%receive(iptr+edge%getmap(i,ielem)+1)
        1373             :       end do
        1374             :     end if
        1375   124675200 :     i = swest+2*max_corner_elem
        1376   124675200 :     if(edge%getmap(i,ielem) /= -1) then
        1377  7550035740 :       do k=1,vlyr
        1378  7425499068 :         iptr=(kptr+k-1)
        1379  7550035740 :         v(0,np+1,k) = edge%receive(iptr+edge%getmap(i,ielem)+1)
        1380             :       end do
        1381             :     end if
        1382             :
        1383   124675200 :   end subroutine edgeDGVunpack
        1384             :
        1385             :   ! ========================================
        1386             :   ! edgeVunpackMIN/MAX:
        1387             :   !
        1388             :   ! Finds the Min/Max edges from edge buffer into v...
        1389             :   ! ========================================
        1390           0 :   subroutine edgeVunpackMAX(edge,v,vlyr,kptr,ielem)
        1391             :     use dimensions_mod, only: np, max_corner_elem
        1392             :     use control_mod,    only: north, south, east, west, neast, nwest, seast, swest
        1393             :
        1394             :     type (EdgeBuffer_t), intent(in)    :: edge
        1395             :     integer,             intent(in)    :: vlyr
        1396             :     real (kind=r8),      intent(inout) :: v(np,np,vlyr)
        1397             :     integer,             intent(in)    :: kptr
        1398             :     integer,             intent(in)    :: ielem
        1399             :
        1400             :     ! Local
        1401             :     integer :: i,k,l,iptr
        1402             :     integer :: is,ie,in,iw
        1403             :
        1404           0 :     threadsafe=.false.
        1405             :
        1406           0 :     is=edge%getmap(south,ielem)
        1407           0 :     ie=edge%getmap(east,ielem)
        1408           0 :     in=edge%getmap(north,ielem)
        1409           0 :     iw=edge%getmap(west,ielem)
        1410           0 :     do k=1,vlyr
        1411           0 :        iptr=np*(kptr+k-1)
        1412           0 :        do i=1,np
        1413           0 :           v(np ,i  ,k) = MAX(v(np ,i  ,k),edge%receive(iptr+ie+i  ))
        1414           0 :           v(i  ,1  ,k) = MAX(v(i  ,1  ,k),edge%receive(iptr+is+i  ))
        1415           0 :           v(i  ,np ,k) = MAX(v(i  ,np ,k),edge%receive(iptr+in+i  ))
        1416           0 :           v(1  ,i  ,k) = MAX(v(1  ,i  ,k),edge%receive(iptr+iw+i  ))
        1417             :        end do
        1418             :     end do
        1419             :
        1420             : ! SWEST
        1421           0 :     do l=swest,swest+max_corner_elem-1
        1422           0 :         if(edge%getmap(l,ielem) /= -1) then
        1423           0 :             do k=1,vlyr
        1424           0 :                 v(1  ,1 ,k)=MAX(v(1 ,1 ,k),edge%receive((kptr+k-1)+edge%getmap(l,ielem)+1))
        1425             :             enddo
        1426             :         endif
        1427             :     end do
        1428             :
        1429             : ! SEAST
        1430           0 :     do l=swest+max_corner_elem,swest+2*max_corner_elem-1
        1431           0 :         if(edge%getmap(l,ielem) /= -1) then
        1432           0 :             do k=1,vlyr
        1433           0 :                 v(np ,1 ,k)=MAX(v(np,1 ,k),edge%receive((kptr+k-1)+edge%getmap(l,ielem)+1))
        1434             :             enddo
        1435             :         endif
        1436             :     end do
        1437             :
        1438             : ! NEAST
        1439           0 :     do l=swest+3*max_corner_elem,swest+4*max_corner_elem-1
        1440           0 :         if(edge%getmap(l,ielem) /= -1) then
        1441           0 :             do k=1,vlyr
        1442           0 :                 v(np ,np,k)=MAX(v(np,np,k),edge%receive((kptr+k-1)+edge%getmap(l,ielem)+1))
        1443             :             enddo
        1444             :         endif
        1445             :     end do
        1446             :
        1447             : ! NWEST
        1448           0 :     do l=swest+2*max_corner_elem,swest+3*max_corner_elem-1
        1449           0 :         if(edge%getmap(l,ielem) /= -1) then
        1450           0 :             do k=1,vlyr
        1451           0 :                 v(1  ,np,k)=MAX(v(1 ,np,k),edge%receive((kptr+k-1)+edge%getmap(l,ielem)+1))
        1452             :             enddo
        1453             :         endif
        1454             :     end do
        1455             :
        1456           0 :   end subroutine edgeVunpackMAX
        1457             :
        1458           0 :   subroutine edgeSunpackMAX(edge,v,vlyr,kptr,ielem)
        1459             :     use dimensions_mod, only: np, max_corner_elem
        1460             :     use control_mod,    only: north, south, east, west, neast, nwest, seast, swest
        1461             :
        1462             :     type (EdgeBuffer_t), intent(in)    :: edge
        1463             :     integer,             intent(in)    :: vlyr
        1464             :     real (kind=r8),      intent(inout) :: v(vlyr)
        1465             :     integer,             intent(in)    :: kptr
        1466             :     integer,             intent(in)    :: ielem
        1467             :
        1468             :     ! Local
        1469             :     integer :: i,k,l,iptr
        1470             :     integer :: is,ie,in,iw,edgeptr
        1471             :
        1472           0 :     threadsafe=.false.
        1473             :
        1474           0 :     is=edge%getmap(south,ielem)
        1475           0 :     ie=edge%getmap(east,ielem)
        1476           0 :     in=edge%getmap(north,ielem)
        1477           0 :     iw=edge%getmap(west,ielem)
        1478           0 :     do k=1,vlyr
        1479           0 :        iptr=(kptr+k-1)
        1480           0 :        v(k) = MAX(v(k),edge%receive(iptr+is+1),edge%receive(iptr+ie+1),edge%receive(iptr+in+1),edge%receive(iptr+iw+1))
        1481             :     end do
        1482             :
        1483             : ! SWEST
        1484           0 :     do l=swest,swest+max_corner_elem-1
        1485           0 :         if(edge%getmap(l,ielem) /= -1) then
        1486           0 :             edgeptr = edge%getmap(l,ielem)+1
        1487           0 :             do k=1,vlyr
        1488           0 :                 iptr = (kptr+k-1)+edgeptr
        1489           0 :                 v(k)=MAX(v(k),edge%receive(iptr))
        1490             :             enddo
        1491             :         endif
        1492             :     end do
        1493             :
        1494             : ! SEAST
        1495           0 :     do l=swest+max_corner_elem,swest+2*max_corner_elem-1
        1496           0 :         if(edge%getmap(l,ielem) /= -1) then
        1497           0 :             edgeptr = edge%getmap(l,ielem)+1
        1498           0 :             do k=1,vlyr
        1499           0 :                 iptr = (kptr+k-1)+edgeptr
        1500           0 :                 v(k)=MAX(v(k),edge%receive(iptr))
        1501             :             enddo
        1502             :         endif
        1503             :     end do
        1504             :
        1505             : ! NEAST
        1506           0 :     do l=swest+3*max_corner_elem,swest+4*max_corner_elem-1
        1507           0 :         if(edge%getmap(l,ielem) /= -1) then
        1508           0 :             edgeptr = edge%getmap(l,ielem)+1
        1509           0 :             do k=1,vlyr
        1510           0 :                 iptr = (kptr+k-1)+edgeptr
        1511           0 :                 v(k)=MAX(v(k),edge%receive(iptr))
        1512             :             enddo
        1513             :         endif
        1514             :     end do
        1515             :
        1516             : ! NWEST
        1517           0 :     do l=swest+2*max_corner_elem,swest+3*max_corner_elem-1
        1518           0 :         if(edge%getmap(l,ielem) /= -1) then
        1519           0 :             edgeptr = edge%getmap(l,ielem)+1
        1520           0 :             do k=1,vlyr
        1521           0 :                 iptr = (kptr+k-1)+edgeptr
        1522           0 :                 v(k)=MAX(v(k),edge%receive(iptr))
        1523             :             enddo
        1524             :         endif
        1525             :     end do
        1526             :
        1527           0 :   end subroutine edgeSunpackMAX
        1528             :
        1529           0 :   subroutine edgeSunpackMIN(edge,v,vlyr,kptr,ielem)
        1530             :     use dimensions_mod, only: np, max_corner_elem
        1531             :     use control_mod,    only: north, south, east, west, neast, nwest, seast, swest
        1532             :
        1533             :     type (EdgeBuffer_t), intent(in)    :: edge
        1534             :     integer,             intent(in)    :: vlyr
        1535             :     real (kind=r8),      intent(inout) :: v(vlyr)
        1536             :     integer,             intent(in)    :: kptr
        1537             :     integer,             intent(in)    :: ielem
        1538             :
        1539             :     ! Local
        1540             :     integer :: i,k,l,iptr
        1541             :     integer :: is,ie,in,iw,edgeptr
        1542             :
        1543           0 :     threadsafe=.false.
        1544             :
        1545           0 :     is=edge%getmap(south,ielem)
        1546           0 :     ie=edge%getmap(east,ielem)
        1547           0 :     in=edge%getmap(north,ielem)
        1548           0 :     iw=edge%getmap(west,ielem)
        1549           0 :     do k=1,vlyr
        1550           0 :        iptr=(kptr+k-1)
        1551           0 :        v(k) = MIN(v(k),edge%receive(iptr+is+1),edge%receive(iptr+ie+1),edge%receive(iptr+in+1),edge%receive(iptr+iw+1))
        1552             :     end do
        1553             :
        1554             : ! SWEST
        1555           0 :     do l=swest,swest+max_corner_elem-1
        1556           0 :         if(edge%getmap(l,ielem) /= -1) then
        1557           0 :             edgeptr = edge%getmap(l,ielem)+1
        1558           0 :             do k=1,vlyr
        1559           0 :                 iptr = (kptr+k-1)+edgeptr
        1560           0 :                 v(k)=MiN(v(k),edge%receive(iptr))
        1561             :             enddo
        1562             :         endif
        1563             :     end do
        1564             :
        1565             : ! SEAST
        1566           0 :     do l=swest+max_corner_elem,swest+2*max_corner_elem-1
        1567           0 :         if(edge%getmap(l,ielem) /= -1) then
        1568           0 :             edgeptr = edge%getmap(l,ielem)+1
        1569           0 :             do k=1,vlyr
        1570           0 :                 iptr = (kptr+k-1)+edgeptr
        1571           0 :                 v(k)=MIN(v(k),edge%receive(iptr))
        1572             :             enddo
        1573             :         endif
        1574             :     end do
        1575             :
        1576             : ! NEAST
        1577           0 :     do l=swest+3*max_corner_elem,swest+4*max_corner_elem-1
        1578           0 :         if(edge%getmap(l,ielem) /= -1) then
        1579           0 :             edgeptr = edge%getmap(l,ielem)+1
        1580           0 :             do k=1,vlyr
        1581           0 :                 iptr = (kptr+k-1)+edgeptr
        1582           0 :                 v(k)=MIN(v(k),edge%receive(iptr))
        1583             :             enddo
        1584             :         endif
        1585             :     end do
        1586             :
        1587             : ! NWEST
        1588           0 :     do l=swest+2*max_corner_elem,swest+3*max_corner_elem-1
        1589           0 :         if(edge%getmap(l,ielem) /= -1) then
        1590           0 :             edgeptr = edge%getmap(l,ielem)+1
        1591           0 :             do k=1,vlyr
        1592           0 :                 iptr = (kptr+k-1)+edgeptr
        1593           0 :                 v(k)=MIN(v(k),edge%receive(iptr))
        1594             :             enddo
        1595             :         endif
        1596             :     end do
        1597             :
        1598           0 :   end subroutine edgeSunpackMIN
        1599             :
        1600           0 :   subroutine edgeVunpackMIN(edge,v,vlyr,kptr,ielem)
        1601             :     use dimensions_mod, only: np, max_corner_elem
        1602             :     use control_mod,    only: north, south, east, west, neast, nwest, seast, swest
        1603             :
        1604             :     type (EdgeBuffer_t), intent(in)    :: edge
        1605             :     integer,             intent(in)    :: vlyr
        1606             :     real (kind=r8),      intent(inout) :: v(np,np,vlyr)
        1607             :     integer,             intent(in)    :: kptr
        1608             :     integer,             intent(in)    :: ielem
        1609             :
        1610             :     ! Local
        1611             :     integer :: i,k,l,iptr
        1612             :     integer :: is,ie,in,iw,edgeptr
        1613             :
        1614           0 :     threadsafe=.false.
        1615             :
        1616           0 :     is=edge%getmap(south,ielem)
        1617           0 :     ie=edge%getmap(east,ielem)
        1618           0 :     in=edge%getmap(north,ielem)
        1619           0 :     iw=edge%getmap(west,ielem)
        1620           0 :     do k=1,vlyr
        1621           0 :        iptr = np*(kptr+k-1)
        1622           0 :        do i=1,np
        1623           0 :           v(np ,i  ,k) = MIN(v(np ,i  ,k),edge%receive(iptr+ie+i  ))
        1624           0 :           v(i  ,1  ,k) = MIN(v(i  ,1  ,k),edge%receive(iptr+is+i  ))
        1625           0 :           v(i  ,np ,k) = MIN(v(i  ,np ,k),edge%receive(iptr+in+i  ))
        1626           0 :           v(1  ,i  ,k) = MIN(v(1  ,i  ,k),edge%receive(iptr+iw+i  ))
        1627             :        end do
        1628             :     end do
        1629             :
        1630             : ! SWEST
        1631           0 :     do l=swest,swest+max_corner_elem-1
        1632           0 :         if(edge%getmap(l,ielem) /= -1) then
        1633           0 :             edgeptr=edge%getmap(l,ielem)+1
        1634           0 :             do k=1,vlyr
        1635           0 :                 iptr=(kptr+k-1)+edgeptr
        1636           0 :                 v(1  ,1 ,k)=MIN(v(1 ,1 ,k),edge%receive(iptr))
        1637             :             enddo
        1638             :         endif
        1639             :     end do
        1640             :
        1641             : ! SEAST
        1642           0 :     do l=swest+max_corner_elem,swest+2*max_corner_elem-1
        1643           0 :         if(edge%getmap(l,ielem) /= -1) then
        1644           0 :             edgeptr=edge%getmap(l,ielem)+1
        1645           0 :             do k=1,vlyr
        1646           0 :                 iptr=(kptr+k-1)+edgeptr
        1647           0 :                 v(np ,1 ,k)=MIN(v(np,1 ,k),edge%receive(iptr))
        1648             :             enddo
        1649             :         endif
        1650             :     end do
        1651             :
        1652             : ! NEAST
        1653           0 :     do l=swest+3*max_corner_elem,swest+4*max_corner_elem-1
        1654           0 :         if(edge%getmap(l,ielem) /= -1) then
        1655           0 :             edgeptr=edge%getmap(l,ielem)+1
        1656           0 :             do k=1,vlyr
        1657           0 :                 iptr=(kptr+k-1)+edgeptr
        1658           0 :                 v(np ,np,k)=MIN(v(np,np,k),edge%receive(iptr))
        1659             :             enddo
        1660             :         endif
        1661             :     end do
        1662             :
        1663             : ! NWEST
        1664           0 :     do l=swest+2*max_corner_elem,swest+3*max_corner_elem-1
        1665           0 :         if(edge%getmap(l,ielem) /= -1) then
        1666           0 :             edgeptr=edge%getmap(l,ielem)+1
        1667           0 :             do k=1,vlyr
        1668           0 :                 iptr=(kptr+k-1)+edgeptr
        1669           0 :                 v(1  ,np,k)=MIN(v(1 ,np,k),edge%receive(iptr))
        1670             :             enddo
        1671             :         endif
        1672             :     end do
        1673             :
        1674           0 :   end subroutine edgeVunpackMIN
        1675             :
        1676             :   ! ========================================
        1677             :   ! LongEdgeVunpackMIN:
        1678             :   !
        1679             :   ! Finds the Min edges from edge buffer into v...
        1680             :   ! ========================================
        1681       10800 :   subroutine LongEdgeVunpackMIN(edge,v,vlyr,kptr,desc)
        1682             :     use control_mod,    only: north, south, east, west, neast, nwest, seast, swest
        1683             :     use dimensions_mod, only: np, max_corner_elem
        1684             :
        1685             :     type (LongEdgeBuffer_t), intent(in)    :: edge
        1686             :     integer,                 intent(in)    :: vlyr
        1687             :     integer ,                intent(inout) :: v(np,np,vlyr)
        1688             :     integer,                 intent(in)    :: kptr
        1689             :     type (EdgeDescriptor_t), intent(in)    :: desc
        1690             :
        1691             :     ! Local
        1692             :
        1693             :     integer :: i,k,l
        1694             :     integer :: is,ie,in,iw
        1695             :
        1696       10800 :     threadsafe=.false.
        1697             :
        1698       10800 :     is=desc%getmapP(south)
        1699       10800 :     ie=desc%getmapP(east)
        1700       10800 :     in=desc%getmapP(north)
        1701       10800 :     iw=desc%getmapP(west)
        1702       21600 :     do k=1,vlyr
        1703       64800 :        do i=1,np
        1704       43200 :           v(i  ,1  ,k) = MIN(v(i  ,1  ,k),edge%buf(kptr+k,is+i  ))
        1705       43200 :           v(np ,i  ,k) = MIN(v(np ,i  ,k),edge%buf(kptr+k,ie+i  ))
        1706       43200 :           v(i  ,np ,k) = MIN(v(i  ,np ,k),edge%buf(kptr+k,in+i  ))
        1707       54000 :           v(1  ,i  ,k) = MIN(v(1  ,i  ,k),edge%buf(kptr+k,iw+i  ))
        1708             :        end do
        1709             :     end do
        1710             :
        1711             : ! SWEST
        1712       21600 :     do l=swest,swest+max_corner_elem-1
        1713       21600 :         if(desc%getmapP(l) /= -1) then
        1714       21576 :             do k=1,vlyr
        1715       21576 :                 v(1  ,1 ,k)=MIN(v(1 ,1 ,k),edge%buf(kptr+k,desc%getmapP(l)+1))
        1716             :             enddo
        1717             :         endif
        1718             :     end do
        1719             :
        1720             : ! SEAST
        1721       21600 :     do l=swest+max_corner_elem,swest+2*max_corner_elem-1
        1722       21600 :         if(desc%getmapP(l) /= -1) then
        1723       21576 :             do k=1,vlyr
        1724       21576 :                 v(np ,1 ,k)=MIN(v(np,1 ,k),edge%buf(kptr+k,desc%getmapP(l)+1))
        1725             :             enddo
        1726             :         endif
        1727             :     end do
        1728             :
        1729             : ! NEAST
        1730       21600 :     do l=swest+3*max_corner_elem,swest+4*max_corner_elem-1
        1731       21600 :         if(desc%getmapP(l) /= -1) then
        1732       21576 :             do k=1,vlyr
        1733       21576 :                 v(np ,np,k)=MIN(v(np,np,k),edge%buf(kptr+k,desc%getmapP(l)+1))
        1734             :             enddo
        1735             :         endif
        1736             :     end do
        1737             :
        1738             : ! NWEST
        1739       21600 :     do l=swest+2*max_corner_elem,swest+3*max_corner_elem-1
        1740       21600 :         if(desc%getmapP(l) /= -1) then
        1741       21576 :             do k=1,vlyr
        1742       21576 :                 v(1  ,np,k)=MIN(v(1 ,np,k),edge%buf(kptr+k,desc%getmapP(l)+1))
        1743             :             enddo
        1744             :         endif
        1745             :     end do
        1746             :
        1747       10800 :   end subroutine LongEdgeVunpackMIN
        1748             :
        1749             :
        1750   449706600 : subroutine ghostpack(edge,v,vlyr,kptr,ielem)
        1751             :
        1752             :   use dimensions_mod, only : max_corner_elem
        1753             :   use control_mod, only : north, south, east, west, neast, nwest, seast, swest
        1754             :   use edgetype_mod, only : EdgeDescriptor_t
        1755             :
        1756             :   implicit none
        1757             :
        1758             :   type (Edgebuffer_t)                :: edge
        1759             :   integer,              intent(in)   :: vlyr
        1760             :   integer,              intent(in)   :: kptr
        1761             :
        1762             :   real (kind=r8),intent(in)   :: v(edge%lb:edge%ub,edge%lb:edge%ub,vlyr)
        1763             :   integer,              intent(in)   :: ielem
        1764             :
        1765             :   ! Local variables
        1766             :   integer :: i,j,k,ir,l,itr,ktmp
        1767             :
        1768             :   integer :: is,ie,in,iw,isw,ise,inw,ine
        1769             :   integer :: nhc, npoints
        1770             :   integer :: edgeptr,iptr
        1771             :
        1772   449706600 :   is = edge%putmap(south,ielem)
        1773   449706600 :   ie = edge%putmap(east,ielem)
        1774   449706600 :   in = edge%putmap(north,ielem)
        1775   449706600 :   iw = edge%putmap(west,ielem)
        1776   449706600 :   if (edge%nlyr < (kptr+vlyr) ) then
        1777           0 :        print *,'edge%nlyr = ',edge%nlyr
        1778           0 :        print *,'kptr+vlyr = ',kptr+vlyr
        1779           0 :        call endrun('ghostpack: Buffer overflow: size of the vertical dimension must be increased!')
        1780             :   endif
        1781             :
        1782             :
        1783   449706600 :   nhc     = edge%ndepth
        1784   449706600 :   npoints = edge%npoints
        1785             :
        1786             :     !DIR$ IVDEP
        1787 46587679200 :     do k=1,vlyr
        1788 46137972600 :       ktmp = nhc*(kptr+k-1)
        1789 >14055*10^7 :       do j=1,nhc
        1790 93967198200 :         iptr = npoints*(ktmp + j - 1)
        1791 >42200*10^7 :         do i=1,npoints
        1792 >28190*10^7 :           edge%buf(iptr+is+i)   = v(i  ,j ,k)
        1793 >28190*10^7 :           edge%buf(iptr+ie+i)   = v(npoints-j+1 ,i ,k)
        1794 >28190*10^7 :           edge%buf(iptr+in+i)   = v(i  ,npoints-j+1,k)
        1795 >37586*10^7 :           edge%buf(iptr+iw+i)   = v(j  ,i ,k)
        1796             :         enddo
        1797             :       end do
        1798             :     end do
        1799             :
        1800             :
        1801             :   !  This is really kludgy way to setup the index reversals
        1802             :   !  But since it is so a rare event not real need to spend time optimizing
        1803             :   !  Check if the edge orientation of the recieving element is different
        1804             :   !  if it is, swap the order of data in the edge
        1805   449706600 :   if(edge%reverse(south,ielem)) then
        1806             :      !DIR$ IVDEP
        1807   776461320 :      do k=1,vlyr
        1808   768966210 :        ktmp = nhc*(kptr+k-1)
        1809  2342581290 :        do j=1,nhc
        1810  1566119970 :          iptr = npoints*(ktmp + j - 1)
        1811  7033445730 :          do i=1,npoints
        1812  4698359550 :            ir = npoints-i+1
        1813  6264479520 :            edge%buf(iptr+is+i)=v(ir,j,k)
        1814             :          enddo
        1815             :        enddo
        1816             :      enddo
        1817             :   endif
        1818             :
        1819   449706600 :   if(edge%reverse(east,ielem)) then
        1820             :      !DIR$ IVDEP
        1821   258820440 :      do k=1,vlyr
        1822   256322070 :        ktmp = nhc*(kptr+k-1)
        1823   780860430 :        do j=1,nhc
        1824   522039990 :          iptr = npoints*(ktmp + j - 1)
        1825  2344481910 :          do i=1,npoints
        1826  1566119850 :            ir = npoints-i+1
        1827  2088159840 :            edge%buf(iptr+ie+i)=v(npoints-j+1,ir,k)
        1828             :           enddo
        1829             :         enddo
        1830             :       enddo
        1831             :   endif
        1832             :
        1833   449706600 :   if(edge%reverse(north,ielem)) then
        1834             :      !DIR$ IVDEP
        1835   776461320 :       do k=1,vlyr
        1836   768966210 :         ktmp = nhc*(kptr+k-1)
        1837  2342581290 :         do j=1,nhc
        1838  1566119970 :          iptr = npoints*(ktmp + j - 1)
        1839  7033445730 :           do i=1,npoints
        1840  4698359550 :             ir = npoints-i+1
        1841  6264479520 :             edge%buf(iptr+in+i)=v(ir,npoints-j+1,k)
        1842             :           enddo
        1843             :         enddo
        1844             :       enddo
        1845             :   endif
        1846             :
        1847   449706600 :   if(edge%reverse(west,ielem)) then
        1848             :      !DIR$ IVDEP
        1849   258820440 :      do k=1,vlyr
        1850   256322070 :        ktmp = nhc*(kptr+k-1)
        1851   780860430 :        do j=1,nhc
        1852   522039990 :          iptr = npoints*(ktmp + j - 1)
        1853  2344481910 :          do i=1,npoints
        1854  1566119850 :             ir = npoints-i+1
        1855  2088159840 :             edge%buf(iptr+iw+i)=v(j,ir,k)
        1856             :           enddo
        1857             :         enddo
        1858             :       enddo
        1859             :   endif
        1860             :
        1861             :
        1862             :   ! corners.  this is difficult because we dont know the orientaton
        1863             :   ! of the corners, and this which (i,j) dimension maps to which dimension
        1864             : ! SWEST
        1865   899413200 :   do l=swest,swest+max_corner_elem-1
        1866   899413200 :      if (edge%putmap(l,ielem) /= -1) then
        1867             :          isw = edge%putmap(l,ielem)
        1868             :          !DIR$ IVDEP
        1869 46535915112 :          do k=1,vlyr
        1870 46086708186 :           ktmp = nhc*(kptr+k-1)
        1871 >14039*10^7 :           do j=1,nhc
        1872 93862790202 :             iptr = nhc*(ktmp + j - 1)
        1873 >37714*10^7 :             do i=1,nhc
        1874 >33105*10^7 :               edge%buf(iptr+isw+i)=v(i  ,j ,k)
        1875             :             enddo
        1876             :           end do
        1877             :         end do
        1878             :      end if
        1879             :   end do
        1880             :
        1881             : ! SEAST
        1882   899413200 :   do l=swest+max_corner_elem,swest+2*max_corner_elem-1
        1883   899413200 :      if (edge%putmap(l,ielem) /= -1) then
        1884             :          ise = edge%putmap(l,ielem)
        1885             :          !DIR$ IVDEP
        1886 46535915112 :          do k=1,vlyr
        1887 46086708186 :           ktmp = nhc*(kptr+k-1)
        1888 >14039*10^7 :           do j=1,nhc
        1889 93862790202 :             iptr = nhc*(ktmp + j - 1)
        1890 >37714*10^7 :             do i=1,nhc
        1891 >33105*10^7 :               edge%buf(iptr+ise+i)=v(npoints-i+1 ,j ,k)
        1892             :             enddo
        1893             :           end do
        1894             :         end do
        1895             :      end if
        1896             :   end do
        1897             :
        1898             : ! NEAST
        1899   899413200 :   do l=swest+3*max_corner_elem,swest+4*max_corner_elem-1
        1900   899413200 :      if (edge%putmap(l,ielem) /= -1) then
        1901             :         ine = edge%putmap(l,ielem)
        1902             :          !DIR$ IVDEP
        1903 46535915112 :         do k=1,vlyr
        1904 46086708186 :            ktmp = nhc*(kptr+k-1)
        1905 >14039*10^7 :            do j=1,nhc
        1906 93862790202 :               iptr = nhc*(ktmp + j - 1)
        1907 >37714*10^7 :               do i=1,nhc
        1908 >33105*10^7 :                  edge%buf(iptr+ine+i)=v(npoints-i+1,npoints-j+1,k)
        1909             :               enddo
        1910             :             enddo
        1911             :           end do
        1912             :       end if
        1913             :   end do
        1914             :
        1915             : ! NWEST
        1916   899413200 :   do l=swest+2*max_corner_elem,swest+3*max_corner_elem-1
        1917   899413200 :      if (edge%putmap(l,ielem) /= -1) then
        1918             :         inw = edge%putmap(l,ielem)
        1919             :         !DIR$ IVDEP
        1920 46535915112 :         do k=1,vlyr
        1921 46086708186 :           ktmp = nhc*(kptr+k-1)
        1922 >14039*10^7 :           do j=1,nhc
        1923 93862790202 :             iptr = nhc*(ktmp + j - 1)
        1924 >37714*10^7 :             do i=1,nhc
        1925 >33105*10^7 :               edge%buf(iptr+inw+i)=v(i  ,npoints-j+1,k)
        1926             :             enddo
        1927             :           end do
        1928             :         end do
        1929             :      end if
        1930             :   end do
        1931             :
        1932   449706600 : end subroutine ghostpack
        1933             :
        1934   449706600 : subroutine ghostunpack(edge,v,vlyr,kptr,ielem)
        1935             :   use dimensions_mod, only : max_corner_elem
        1936             :   use control_mod, only : north, south, east, west, neast, nwest, seast, swest
        1937             :   type (Edgebuffer_t),         intent(in)  :: edge
        1938             :
        1939             :   integer,               intent(in)  :: vlyr
        1940             :   integer,               intent(in)  :: kptr
        1941             :   integer,               intent(in)  :: ielem
        1942             :
        1943             :   real (kind=r8), intent(inout) :: v(edge%lb:edge%ub,edge%lb:edge%ub,vlyr)
        1944             :
        1945             :
        1946             :   ! Local
        1947             :   logical, parameter :: UseUnroll = .TRUE.
        1948             :   integer :: i,j,k,l,itr, ktmp
        1949             :   integer :: is,ie,in,iw,isw,ise,inw,ine
        1950             :   integer :: nhc,npoints,iptr
        1951             :   logical :: reverse
        1952             :
        1953   449706600 :   threadsafe=.false.
        1954             :
        1955   449706600 :   is=edge%getmap(south,ielem)
        1956   449706600 :   ie=edge%getmap(east,ielem)
        1957   449706600 :   in=edge%getmap(north,ielem)
        1958   449706600 :   iw=edge%getmap(west,ielem)
        1959             :
        1960   449706600 :   nhc     = edge%ndepth
        1961   449706600 :   npoints = edge%npoints
        1962             :
        1963             :   ! example for north buffer
        1964             :   ! first row ('edge') goes in v(:,np+1,k)
        1965             :   ! 2nd   row ('edge') goes in v(:,np+2,k)
        1966             :   ! etc...
        1967             :     !DIR$ IVDEP
        1968 46587679200 :     do k=1,vlyr
        1969 46137972600 :       ktmp = nhc*(kptr+k-1)
        1970 >14055*10^7 :       do j=1,nhc
        1971 93967198200 :         iptr = npoints*(ktmp + j - 1)
        1972 >42200*10^7 :         do i=1,npoints
        1973 >28190*10^7 :           v(i  ,1-j  ,k)      = edge%receive(iptr+is+i)  ! South
        1974 >28190*10^7 :           v(npoints+j ,i  ,k) = edge%receive(iptr+ie+i)  ! East
        1975 >28190*10^7 :           v(i  ,npoints+j ,k) = edge%receive(iptr+in+i)  ! North
        1976 >37586*10^7 :           v(1-j  ,i  ,k)      = edge%receive(iptr+iw+i)  ! West
        1977             :         end do
        1978             :       end do
        1979             :     end do
        1980             :
        1981             :
        1982             : ! SWEST
        1983   899413200 :   do l=swest,swest+max_corner_elem-1
        1984   449706600 :      isw = edge%getmap(l,ielem)
        1985   899413200 :      if(isw /= -1) then
        1986             :         ! note the following is the the correct meaning of reverse in this code.
        1987             :         ! It is  best described as a transponse operation
        1988   449206926 :         if (edge%reverse(l,ielem)) then
        1989  1000771904 :            do k=1,vlyr
        1990   991111772 :               ktmp = nhc*(kptr+k-1)
        1991  3019326068 :               do j=1,nhc
        1992  2018554164 :                  iptr = nhc*(ktmp + j - 1)
        1993  8110547276 :                  do i=1,nhc
        1994  7119435504 :                     v(1-j,1-i,k)=edge%receive(iptr+isw+i)
        1995             :                  enddo
        1996             :               enddo
        1997             :              enddo
        1998             :         else
        1999 45535143208 :            do k=1,vlyr
        2000 45095596414 :               ktmp = nhc*(kptr+k-1)
        2001 >13737*10^7 :               do i=1,nhc
        2002 91844236038 :                  iptr = nhc*(ktmp + i - 1)
        2003 >36902*10^7 :                  do j=1,nhc
        2004 >32393*10^7 :                     v(1-j,1-i,k)=edge%receive(iptr+isw+j)
        2005             :                  enddo
        2006             :               enddo
        2007             :              enddo
        2008             :         endif
        2009             :      else
        2010    51764088 :          do k=1,vlyr
        2011   156172086 :            do j=1,nhc
        2012   419511150 :              do i=1,nhc
        2013   368246736 :                v(1-i,1-j,k)=edgeDefaultVal
        2014             :              enddo
        2015             :            enddo
        2016             :          enddo
        2017             :      endif
        2018             :   end do
        2019             :
        2020             : ! SEAST
        2021   899413200 :   do l=swest+max_corner_elem,swest+2*max_corner_elem-1
        2022   449706600 :      ise = edge%getmap(l,ielem)
        2023   899413200 :      if(ise /= -1) then
        2024   449206926 :         if (edge%reverse(l,ielem)) then
        2025  1000771904 :            do k=1,vlyr
        2026   991111772 :               ktmp = nhc*(kptr+k-1)
        2027  3019326068 :               do i=1,nhc
        2028  2018554164 :                  iptr = nhc*(ktmp + i - 1)
        2029  8110547276 :                  do j=1,nhc
        2030  7119435504 :                     v(npoints+i,1-j,k)=edge%receive(iptr+ise+j)
        2031             :                  enddo
        2032             :               enddo
        2033             :             enddo
        2034             :         else
        2035 45535143208 :            do k=1,vlyr
        2036 45095596414 :               ktmp = nhc*(kptr+k-1)
        2037 >13737*10^7 :               do j=1,nhc
        2038 91844236038 :                  iptr = nhc*(ktmp + j - 1)
        2039 >36902*10^7 :                  do i=1,nhc
        2040 >32393*10^7 :                     v(npoints+i ,1-j ,k)=edge%receive(iptr+ise+i)
        2041             :                  enddo
        2042             :               enddo
        2043             :             enddo
        2044             :         endif
        2045             :       else
        2046    51764088 :          do k=1,vlyr
        2047   156172086 :           do j=1,nhc
        2048   419511150 :             do i=1,nhc
        2049   368246736 :               v(npoints+i,1-j,k)=edgeDefaultVal
        2050             :             enddo
        2051             :           enddo
        2052             :          enddo
        2053             :      endif
        2054             :   end do
        2055             :
        2056             : ! NEAST
        2057   899413200 :   do l=swest+3*max_corner_elem,swest+4*max_corner_elem-1
        2058   449706600 :      ine = edge%getmap(l,ielem)
        2059   899413200 :      if(ine /= -1) then
        2060   449206926 :         if (edge%reverse(l,ielem)) then
        2061  1000771904 :            do k=1,vlyr
        2062   991111772 :               ktmp = nhc*(kptr+k-1)
        2063  3019326068 :               do j=1,nhc
        2064  8110547276 :                  do i=1,nhc
        2065  5100881340 :                     iptr = nhc*(ktmp + i - 1)
        2066  7119435504 :                     v(npoints+i ,npoints+j,k)=edge%receive(iptr+ine+j)
        2067             :                  enddo
        2068             :               enddo
        2069             :             enddo
        2070             :         else
        2071 45535143208 :            do k=1,vlyr
        2072 45095596414 :               ktmp = nhc*(kptr+k-1)
        2073 >13737*10^7 :               do j=1,nhc
        2074 91844236038 :                  iptr = nhc*(ktmp + j - 1)
        2075 >36902*10^7 :                  do i=1,nhc
        2076 >32393*10^7 :                     v(npoints+i ,npoints+j,k)=edge%receive(iptr+ine+i)
        2077             :                  enddo
        2078             :               enddo
        2079             :             enddo
        2080             :         endif
        2081             :       else
        2082    51764088 :          do k=1,vlyr
        2083   156172086 :           do j=1,nhc
        2084   419511150 :             do i=1,nhc
        2085   368246736 :               v(npoints+i,npoints+j,k)=edgeDefaultVal
        2086             :             enddo
        2087             :           enddo
        2088             :          enddo
        2089             :      endif
        2090             :   end do
        2091             :
        2092             : ! NWEST
        2093   899413200 :   do l=swest+2*max_corner_elem,swest+3*max_corner_elem-1
        2094   449706600 :      inw = edge%getmap(l,ielem)
        2095   899413200 :      if(inw /= -1) then
        2096   449206926 :         if (edge%reverse(l,ielem)) then
        2097  1000771904 :            do k=1,vlyr
        2098   991111772 :               ktmp = nhc*(kptr+k-1)
        2099  3019326068 :               do i=1,nhc
        2100  2018554164 :                  iptr = nhc*(ktmp + i - 1)
        2101  8110547276 :                  do j=1,nhc
        2102  7119435504 :                     v(1-i ,npoints+j,k)=edge%receive(iptr+inw+j)
        2103             :                  enddo
        2104             :               enddo
        2105             :             enddo
        2106             :         else
        2107 45535143208 :            do k=1,vlyr
        2108 45095596414 :               ktmp = nhc*(kptr+k-1)
        2109 >13737*10^7 :               do j=1,nhc
        2110 91844236038 :                  iptr = nhc*(ktmp + j - 1)
        2111 >36902*10^7 :                  do i=1,nhc
        2112 >32393*10^7 :                     v(1-i ,npoints+j,k)=edge%receive(iptr+inw+i)
        2113             :                  enddo
        2114             :               enddo
        2115             :             enddo
        2116             :         endif
        2117             :       else
        2118    51764088 :          do k=1,vlyr
        2119   156172086 :           do j=1,nhc
        2120   419511150 :             do i=1,nhc
        2121   368246736 :               v(1-i,npoints+j,k)=edgeDefaultVal
        2122             :             enddo
        2123             :           enddo
        2124             :          enddo
        2125             :      endif
        2126             :   end do
        2127             :
        2128   449706600 : end subroutine ghostunpack
        2129             :
        2130             :   ! =========================================
        2131             :   ! initGhostBuffer3d:
        2132             :   ! Author: James Overfelt
        2133             :   ! create an Real based communication buffer
        2134             :   ! npoints is the number of points on one side
        2135             :   ! nhc is the deep of the ghost/halo zone
        2136             :   ! =========================================
        2137           0 :   subroutine initGhostBuffer3d(ghost,nlyr,np,nhc_in)
        2138             :
        2139             :     implicit none
        2140             :     integer,intent(in)                  :: nlyr, np
        2141             :     integer,intent(in),optional         :: nhc_in
        2142             :     type (Ghostbuffer3d_t),intent(out)  :: ghost
        2143             :
        2144             :     ! Local variables
        2145             :
        2146             :     integer :: nbuf,nhc,i
        2147             :
        2148             :     ! sanity check for threading
        2149           0 :     if (omp_get_num_threads()>1) then
        2150           0 :        call endrun('ERROR: initGhostBuffer must be called before threaded region')
        2151             :     endif
        2152             :
        2153           0 :     if (present(nhc_in)) then
        2154           0 :        nhc=nhc_in
        2155             :     else
        2156           0 :        nhc = np-1
        2157             :     endif
        2158             :
        2159           0 :     nbuf=max_neigh_edges*nelemd
        2160             :
        2161           0 :     ghost%nlyr    = nlyr
        2162           0 :     ghost%nhc     = nhc
        2163           0 :     ghost%np      = np
        2164           0 :     ghost%nbuf    = nbuf
        2165           0 :     ghost%elem_size = np*(nhc+1)
        2166           0 :     allocate(ghost%buf    (np,(nhc+1),nlyr,nbuf))
        2167           0 :     allocate(ghost%receive(np,(nhc+1),nlyr,nbuf))
        2168           0 :     ghost%buf=0
        2169           0 :     ghost%receive=0
        2170             :
        2171           0 :   end subroutine initGhostBuffer3d
        2172             :
        2173             :   ! =================================================================================
        2174             :   ! GHOSTVPACK3D
        2175             :   ! AUTHOR: James Overfelt (from a subroutine of Christoph Erath, ghostvpack2D)
        2176             :   ! Pack edges of v into an ghost buffer for boundary exchange.
        2177             :   !
        2178             :   ! This subroutine packs for many vertical layers into an ghost
        2179             :   ! buffer.
        2180             :   ! If the buffer associated with edge is not large enough to
        2181             :   ! hold all vertical layers you intent to pack, the method will
        2182             :   ! halt the program with a call to endrun().
        2183             :   ! INPUT:
        2184             :   ! - ghost Buffer into which the data will be packed.
        2185             :   !   This buffer must be previously allocated with initGhostBuffer().
        2186             :   ! - v The data to be packed.
        2187             :   ! - nhc deep of ghost/halo zone
        2188             :   ! - npoints number of points on on side
        2189             :   ! - kptr Vertical pointer to the place in the edge buffer where
        2190             :   ! data will be located.
        2191             :   ! =================================================================================
        2192           0 :   subroutine ghostVpack3d(ghost, v, vlyr, kptr, desc)
        2193             :     use dimensions_mod, only : max_corner_elem
        2194             :     use control_mod,    only : north, south, east, west, neast, nwest, seast, swest
        2195             :     use edgetype_mod, only : edgedescriptor_t, ghostbuffer3d_t
        2196             :     implicit none
        2197             :
        2198             :     type (Ghostbuffer3d_t)                :: ghost
        2199             :     integer,              intent(in)      :: kptr,vlyr
        2200             :     real (kind=r8),intent(in)      :: v(ghost%np, ghost%np, vlyr)
        2201             :     type (EdgeDescriptor_t),intent(in)    :: desc
        2202             :
        2203             :     integer                               :: nhc, np
        2204             :
        2205             :     ! Local variables
        2206             :     integer :: i,j,k,ir,l,e
        2207             :
        2208             :     integer :: is,ie,in,iw
        2209             :
        2210           0 :     if(.not. threadsafe) then
        2211             : !$OMP BARRIER
        2212           0 :        threadsafe=.true.
        2213             :     end if
        2214             :     ! Example convenction for buffer to the north:
        2215             :     !  buf(:,,:,i,e)
        2216             :     !   each "edge" is a row of data (i=1,np) in the element
        2217             :     !     north most row of data goes into e=1
        2218             :     !     next row of data goes into e=2
        2219             :     !     ....
        2220             :     !     south most row of data goes into e=np
        2221             :     !   We need to pack this way to preserve the orientation
        2222             :     !   so the data can be unpacked correctly
        2223             :
        2224             :     ! note: we think of buf as dimensioned buf(k,is,i,e)
        2225             :     ! but this array is flatted to:   buf(k,is+(i-1)+(e-1)*np)
        2226             :     !
        2227           0 :     nhc = ghost%nhc
        2228           0 :     np = ghost%np
        2229           0 :     is = desc%putmapP_ghost(south)
        2230           0 :     ie = desc%putmapP_ghost(east)
        2231           0 :     in = desc%putmapP_ghost(north)
        2232           0 :     iw = desc%putmapP_ghost(west)
        2233             :
        2234           0 :     do k=1,vlyr
        2235           0 :        do j=1,nhc
        2236           0 :           do i=1,np
        2237           0 :              ghost%buf(i,j,kptr+k,is)   = v(i,    j+1 , k)
        2238           0 :              ghost%buf(i,j,kptr+k,ie)   = v(np-j,   i , k)
        2239           0 :              ghost%buf(i,j,kptr+k,in)   = v(i,   np-j , k)
        2240           0 :              ghost%buf(i,j,kptr+k,iw)   = v(j+1,    i , k)
        2241             :           enddo
        2242             :        end do
        2243             :     end do
        2244             :     !  This is really kludgy way to setup the index reversals
        2245             :     !  But since it is so a rare event not real need to spend time optimizing
        2246             :     !  Check if the edge orientation of the recieving element is different
        2247             :     !  if it is, swap the order of data in the edge
        2248           0 :     if(desc%reverse(south)) then
        2249           0 :        do k=1,vlyr
        2250           0 :           do j=1,nhc
        2251           0 :              do i=1,np
        2252           0 :                 ir = np-i+1
        2253           0 :                 ghost%buf(ir, j, kptr+k, is)=v(i, j+1, k)
        2254             :              enddo
        2255             :           enddo
        2256             :        enddo
        2257             :     endif
        2258             :
        2259           0 :     if(desc%reverse(east)) then
        2260           0 :        do k=1,vlyr
        2261           0 :           do j=1,nhc
        2262           0 :              do i=1,np
        2263           0 :                 ir = np-i+1
        2264           0 :                 ghost%buf(ir, j, kptr+k, ie)=v(np-j, i, k)
        2265             :              enddo
        2266             :           enddo
        2267             :        enddo
        2268             :     endif
        2269             :
        2270           0 :     if(desc%reverse(north)) then
        2271           0 :        do k=1,vlyr
        2272           0 :           do j=1,nhc
        2273           0 :               do i=1,np
        2274           0 :                 ir = np-i+1
        2275           0 :                 ghost%buf(ir, j, kptr+k, in)=v(i, np-j, k)
        2276             :              enddo
        2277             :           enddo
        2278             :        enddo
        2279             :     endif
        2280             :
        2281           0 :     if(desc%reverse(west)) then
        2282           0 :        do k=1,vlyr
        2283           0 :           do j=1,nhc
        2284           0 :              do i=1,np
        2285           0 :                 ir = np-i+1
        2286           0 :                 ghost%buf(ir, j, kptr+k, iw)=v(j+1, i, k)
        2287             :              enddo
        2288             :           enddo
        2289             :        enddo
        2290             :     endif
        2291             :
        2292             :     ! corners.  this is difficult because we dont know the orientaton
        2293             :     ! of the corners, and this which (i,j) dimension maps to which dimension
        2294             : ! SWEST
        2295           0 :     do l=swest, swest+max_corner_elem-1
        2296           0 :        if (desc%putmapP_ghost(l) /= -1) then
        2297           0 :           do k=1,vlyr
        2298           0 :              do j=1,nhc+1
        2299           0 :                 do i=1,nhc+1
        2300           0 :                    ghost%buf(i, j, kptr+k, desc%putmapP_ghost(l))=v(i, j, k)
        2301             :                 enddo
        2302             :              enddo
        2303             :           enddo
        2304             :        end if
        2305             :     end do
        2306             :
        2307             : ! SEAST
        2308           0 :     do l=swest+max_corner_elem,swest+2*max_corner_elem-1
        2309           0 :        if (desc%putmapP_ghost(l) /= -1) then
        2310           0 :           do k=1,vlyr
        2311           0 :              do j=1,nhc+1
        2312           0 :                 do i=1,nhc+1
        2313           0 :                    ghost%buf(i, j, kptr+k, desc%putmapP_ghost(l))=v(np-i+1, j, k)
        2314             :                 enddo
        2315             :              enddo
        2316             :           enddo
        2317             :        end if
        2318             :     end do
        2319             :
        2320             : ! NEAST
        2321           0 :     do l=swest+3*max_corner_elem,swest+4*max_corner_elem-1
        2322           0 :        if (desc%putmapP_ghost(l) /= -1) then
        2323           0 :           do k=1,vlyr
        2324           0 :              do j=1,nhc+1
        2325           0 :                 do i=1,nhc+1
        2326           0 :                    ghost%buf(i, j, kptr+k,desc%putmapP_ghost(l))=v(np-i+1, np-j+1, k)
        2327             :                 enddo
        2328             :              enddo
        2329             :           enddo
        2330             :        end if
        2331             :     end do
        2332             :
        2333             : ! NWEST
        2334           0 :     do l=swest+2*max_corner_elem,swest+3*max_corner_elem-1
        2335           0 :        if (desc%putmapP_ghost(l) /= -1) then
        2336           0 :           do k=1,vlyr
        2337           0 :              do j=1,nhc+1
        2338           0 :                 do i=1,nhc+1
        2339           0 :                    ghost%buf(i, j, kptr+k,desc%putmapP_ghost(l))=v(i, np-j+1, k)
        2340             :                 enddo
        2341             :              enddo
        2342             :           enddo
        2343             :        end if
        2344             :     end do
        2345           0 :   end subroutine ghostVpack3d
        2346             :
        2347             :   ! =================================================================================
        2348             :   ! GHOSTVUNPACK3D
        2349             :   ! AUTHOR: James Overfelt (from a subroutine of Christoph Erath,
        2350             :   ! ghostVunpack2d)
        2351             :   ! Unpack ghost points from ghost buffer into v...
        2352             :   ! It is for cartesian points (v is only two dimensional).
        2353             :   ! INPUT SAME arguments as for GHOSTVPACK
        2354             :   ! =================================================================================
        2355             :
        2356           0 :   subroutine ghostVunpack3d(g, v, vlyr, kptr, desc, sw, se, nw, ne, mult)
        2357             :     use dimensions_mod, only : max_corner_elem
        2358             :     use control_mod, only : north, south, east, west, neast, nwest, seast, swest
        2359             :     use edgetype_mod, only : edgedescriptor_t, ghostbuffer3d_t
        2360             :     implicit none
        2361             :     type (Ghostbuffer3d_t),         intent(in)  :: g
        2362             :
        2363             :     integer,               intent(in)     :: kptr,vlyr
        2364             :     real (kind=r8), intent(inout)  :: v (1-g%nhc : g%np+g%nhc, 1-g%nhc : g%np+g%nhc, vlyr)
        2365             :     integer,               intent(out)    :: mult(5:8)
        2366             :     real (kind=r8), intent(out)    :: sw(1-g%nhc : 1,          1-g%nhc : 1,          vlyr, max_corner_elem-1)
        2367             :     real (kind=r8), intent(out)    :: se(   g%np : g%np+g%nhc, 1-g%nhc : 1,          vlyr, max_corner_elem-1)
        2368             :     real (kind=r8), intent(out)    :: ne(   g%np : g%np+g%nhc,    g%np : g%np+g%nhc, vlyr, max_corner_elem-1)
        2369             :     real (kind=r8), intent(out)    :: nw(1-g%nhc : 1,             g%np : g%np+g%nhc, vlyr, max_corner_elem-1)
        2370             :     type (EdgeDescriptor_t)               :: desc
        2371             :
        2372             :     integer                               :: nhc, np
        2373             :
        2374             :     ! Local
        2375             :     logical, parameter :: UseUnroll = .TRUE.
        2376             :     integer :: i,j,k,l
        2377             :     integer :: is,ie,in,iw,ic
        2378             :     logical :: reverse
        2379             :
        2380           0 :     threadsafe=.false.
        2381             :
        2382           0 :     nhc     = g%nhc
        2383           0 :     np      = g%np
        2384             :
        2385           0 :     is=desc%getmapP_ghost(south)
        2386           0 :     ie=desc%getmapP_ghost(east)
        2387           0 :     in=desc%getmapP_ghost(north)
        2388           0 :     iw=desc%getmapP_ghost(west)
        2389             :
        2390             : ! fill in optional values with edgeDefaultVal
        2391           0 :     do k=1,vlyr
        2392           0 :        do j=1,nhc
        2393           0 :           do i=1,nhc
        2394           0 :              v(1-i,   1-j, k)=edgeDefaultVal
        2395           0 :              v(np+i , 1-j, k)=edgeDefaultVal
        2396           0 :              v(np+i, np+j, k)=edgeDefaultVal
        2397           0 :              v(1-i , np+j, k)=edgeDefaultVal
        2398             :           enddo
        2399             :        enddo
        2400             :     enddo
        2401             :
        2402             :     ! example for north buffer
        2403             :     ! first row ('edge') goes in v(:,np+1)
        2404             :     ! 2nd   row ('edge') goes in v(:,np+2)
        2405             :     ! etc...
        2406             :
        2407           0 :     do k=1,vlyr
        2408           0 :        do j=1,nhc
        2409           0 :           do i=1,np
        2410           0 :              v(i  ,  1-j , k) = g%buf(i,j,kptr+k,is  )
        2411           0 :              v(np+j ,  i , k) = g%buf(i,j,kptr+k,ie  )
        2412           0 :              v(i  , np+j,  k) = g%buf(i,j,kptr+k,in  )
        2413           0 :              v(1-j  ,  i , k) = g%buf(i,j,kptr+k,iw  )
        2414             :           end do
        2415             :        end do
        2416             :     end do
        2417             :
        2418             :     ! four sides are always just one
        2419           0 :     mult(swest) = 0
        2420           0 :     mult(seast) = 0
        2421           0 :     mult(neast) = 0
        2422           0 :     mult(nwest) = 0
        2423             :
        2424             :
        2425             :
        2426             : ! SWEST
        2427           0 :     do l=swest, swest+max_corner_elem-1
        2428           0 :        ic = desc%getmapP_ghost(l)
        2429           0 :        if(ic /= -1) then
        2430           0 :           reverse=desc%reverse(l)
        2431           0 :           if (mult(swest) .eq. 0) then
        2432           0 :             if (reverse) then
        2433           0 :                do k=1,vlyr
        2434           0 :                   do j=1,nhc
        2435           0 :                      do i=1,nhc
        2436           0 :                         v(1-i, 1-j, k)=g%buf(j+1, i+1, kptr+k, ic)
        2437             :                      enddo
        2438             :                   enddo
        2439             :                enddo
        2440             :              else
        2441           0 :                do k=1,vlyr
        2442           0 :                   do j=1,nhc
        2443           0 :                      do i=1,nhc
        2444           0 :                         v(1-i,1-j,k)=g%buf(i+1,j+1,kptr+k,ic)
        2445             :                      enddo
        2446             :                   enddo
        2447             :                enddo
        2448             :             endif
        2449             :           else
        2450           0 :             if (reverse) then
        2451           0 :                do k=1,vlyr
        2452           0 :                   do j=0,nhc
        2453           0 :                      do i=0,nhc
        2454           0 :                         sw(1-i,1-j,k,mult(swest))=g%buf(j+1,i+1,kptr+k,ic)
        2455             :                      enddo
        2456             :                   enddo
        2457             :                enddo
        2458             :              else
        2459           0 :                 do k=1,vlyr
        2460           0 :                    do j=0,nhc
        2461           0 :                       do i=0,nhc
        2462           0 :                          sw(1-i,1-j,k,mult(swest))=g%buf(i+1,j+1,kptr+k,ic)
        2463             :                      enddo
        2464             :                   enddo
        2465             :                enddo
        2466             :             endif
        2467             :           endif
        2468           0 :           mult(swest) = mult(swest) + 1
        2469             :        endif
        2470             :     end do
        2471             :
        2472             : ! SEAST
        2473           0 :     do l=swest+max_corner_elem,swest+2*max_corner_elem-1
        2474           0 :        ic = desc%getmapP_ghost(l)
        2475           0 :        if(ic /= -1) then
        2476           0 :           reverse=desc%reverse(l)
        2477           0 :           if (mult(seast) .eq. 0) then
        2478           0 :             if (reverse) then
        2479           0 :                do k=1,vlyr
        2480           0 :                   do j=1,nhc
        2481           0 :                      do i=1,nhc
        2482           0 :                         v(np+i,1-j,k)=g%buf(j+1,i+1,kptr+k,ic)
        2483             :                      enddo
        2484             :                   enddo
        2485             :                enddo
        2486             :             else
        2487           0 :                do k=1,vlyr
        2488           0 :                   do j=1,nhc
        2489           0 :                      do i=1,nhc
        2490           0 :                         v(np+i ,1-j,k)=g%buf(i+1,j+1,kptr+k,ic)
        2491             :                      enddo
        2492             :                   enddo
        2493             :                enddo
        2494             :             endif
        2495             :           else
        2496           0 :             if (reverse) then
        2497           0 :                do k=1,vlyr
        2498           0 :                   do j=0,nhc
        2499           0 :                      do i=0,nhc
        2500           0 :                         se(np+i,1-j,k,mult(seast))=g%buf(j+1,i+1,kptr+k,ic)
        2501             :                      enddo
        2502             :                   enddo
        2503             :                enddo
        2504             :             else
        2505           0 :                do k=1,vlyr
        2506           0 :                   do j=0,nhc
        2507           0 :                      do i=0,nhc
        2508           0 :                         se(np+i ,1-j,k,mult(seast))=g%buf(i+1,j+1,kptr+k,ic)
        2509             :                      enddo
        2510             :                   enddo
        2511             :                enddo
        2512             :             endif
        2513             :           endif
        2514           0 :           mult(seast) = mult(seast) + 1
        2515             :        endif
        2516             :     end do
        2517             :
        2518             :
        2519             : ! NEAST
        2520           0 :     do l=swest+3*max_corner_elem,swest+4*max_corner_elem-1
        2521           0 :        ic = desc%getmapP_ghost(l)
        2522           0 :        if(ic /= -1) then
        2523           0 :           reverse=desc%reverse(l)
        2524           0 :           if (mult(neast) .eq. 0) then
        2525           0 :             if (reverse) then
        2526           0 :                do k=1,vlyr
        2527           0 :                   do j=1,nhc
        2528           0 :                      do i=1,nhc
        2529           0 :                         v(np+i ,np+j,k)=g%buf(j+1,i+1,kptr+k,ic)
        2530             :                      enddo
        2531             :                   enddo
        2532             :                enddo
        2533             :             else
        2534           0 :                do k=1,vlyr
        2535           0 :                   do j=1,nhc
        2536           0 :                      do i=1,nhc
        2537           0 :                         v(np+i ,np+j,k)=g%buf(i+1,j+1,kptr+k,ic)
        2538             :                      enddo
        2539             :                   enddo
        2540             :                enddo
        2541             :             endif
        2542             :           else
        2543           0 :             if (reverse) then
        2544           0 :                do k=1,vlyr
        2545           0 :                   do j=0,nhc
        2546           0 :                      do i=0,nhc
        2547           0 :                         ne(np+i ,np+j,k,mult(neast))=g%buf(j+1,i+1,kptr+k,ic)
        2548             :                      enddo
        2549             :                   enddo
        2550             :                enddo
        2551             :             else
        2552           0 :                do k=1,vlyr
        2553           0 :                   do j=0,nhc
        2554           0 :                      do i=0,nhc
        2555           0 :                         ne(np+i ,np+j,k,mult(neast))=g%buf(i+1,j+1,kptr+k,ic)
        2556             :                      enddo
        2557             :                   enddo
        2558             :                enddo
        2559             :             endif
        2560             :           endif
        2561           0 :           mult(neast) = mult(neast) + 1
        2562             :        endif
        2563             :     end do
        2564             :
        2565             : ! NWEST
        2566           0 :     do l=swest+2*max_corner_elem,swest+3*max_corner_elem-1
        2567           0 :        ic = desc%getmapP_ghost(l)
        2568           0 :        if(ic /= -1) then
        2569           0 :           reverse=desc%reverse(l)
        2570           0 :           if (mult(nwest) .eq. 0) then
        2571           0 :              if (reverse) then
        2572           0 :                 do k=1,vlyr
        2573           0 :                    do j=1,nhc
        2574           0 :                       do i=1,nhc
        2575           0 :                          v(1-i ,np+j,k)=g%buf(j+1,i+1,kptr+k,ic)
        2576             :                       enddo
        2577             :                    enddo
        2578             :                 enddo
        2579             :              else
        2580           0 :                 do k=1,vlyr
        2581           0 :                    do j=1,nhc
        2582           0 :                       do i=1,nhc
        2583           0 :                          v(1-i ,np+j,k)=g%buf(i+1,j+1,kptr+k,ic)
        2584             :                       enddo
        2585             :                    enddo
        2586             :                 enddo
        2587             :              endif
        2588             :           else
        2589           0 :              if (reverse) then
        2590           0 :                 do k=1,vlyr
        2591           0 :                    do j=0,nhc
        2592           0 :                       do i=0,nhc
        2593           0 :                          nw(1-i ,np+j,k,mult(nwest))=g%buf(j+1,i+1,kptr+k,ic)
        2594             :                       enddo
        2595             :                    enddo
        2596             :                 enddo
        2597             :              else
        2598           0 :                 do k=1,vlyr
        2599           0 :                    do j=0,nhc
        2600           0 :                       do i=0,nhc
        2601           0 :                          nw(1-i ,np+j,k,mult(nwest))=g%buf(i+1,j+1,kptr+k,ic)
        2602             :                       enddo
        2603             :                    enddo
        2604             :                 enddo
        2605             :              endif
        2606             :           endif
        2607           0 :           mult(nwest) = mult(nwest) + 1
        2608             :        endif
        2609             :     end do
        2610             :
        2611           0 :   end subroutine ghostVunpack3d
        2612             :
        2613           0 :   subroutine FreeGhostBuffer3D(buffer)
        2614             :     use edgetype_mod, only : ghostbuffer3d_t
        2615             :     implicit none
        2616             :     type (Ghostbuffer3d_t),intent(inout) :: buffer
        2617             :
        2618             : !$OMP BARRIER
        2619             : !$OMP MASTER
        2620           0 :     buffer%nbuf=0
        2621           0 :     buffer%nlyr=0
        2622           0 :     deallocate(buffer%buf)
        2623           0 :     deallocate(buffer%receive)
        2624             : !$OMP END MASTER
        2625             :
        2626           0 :   end subroutine FreeGhostBuffer3D
        2627             :
        2628             :
        2629           0 : End module edge_mod

Generated by: LCOV version 1.14