! See copyright notice in the COPYRIGHT file.
??! We include two accesses to the pdf variables
??! - array of structures (AOS)
??! - structure of arrays (SOA)
??!
??IFNDEF (SOA) THEN
?? LOGICAL :: SOA = .false.
??ENDIF
??!
??! Streaming layout
??!   PUSH:  read element-local pdf and store to adjacent element
??!   PULL:  read adjacent element pdf and store to local element
??! Multi-level only works with Pull
??!
??!
??IFNDEF (PUSH) THEN
?? LOGICAL :: PUSH = .false.
??ENDIF
??! Macro to get neighbor element index from current element index, connectivity
??! array and direction
?? macro :: NghElemIDX(neigh, iDir, stencil, index, QQ, nElems) &
??   & = ?ElemIDX?(?neigh?(?NGPOS?(?NgDir?(?iDir?, ?stencil?), ?index?, ?nElems?)), &
??   & ?QQ?, ?nElems?)
??!
??!
??! NgDir: The ELEMENT direction with which the streaming operation takes places
??!        Mainly used in the reconstruct_connectivity routine to build the neighbor array.
??!        Also used in boundary routine
??! nScalars: number of scalars in state array
??! QQ: number of stencil directions
?? if(PUSH) then
?? macro :: FETCH(iDir,iField,node,QQ,nScalars,nElems)       &
??   &        = ?IDX?( ?iDir?+(?iField?-1)*?QQ?, ?node?, ?nScalars?, ?nElems?)
?? macro :: SAVE( iDir,iField,node,QQ,nScalars,nElems,neigh) &
??   &        = ?neigh?( ?NGPOS?(?iDir?,?node?,?nElems?) ) + ?NGOFFSET?(?iField?, ?QQ?, ?nElems?) + ?nScalars?*0
?? macro :: StreamName = push
?? macro :: NgDir(iDir) = ?iDir?
?? macro :: InvNgDir(iDir, stencil) = ?stencil?%cxDirInv( ?iDir? )
?? macro :: post2pre( omega ) = ( 1.0_rk + ?omega?*0.0_rk )
?? macro :: pre2post( omega ) = ( 1.0_rk + ?omega?*0.0_rk )
?? else !PULL
?? macro :: FETCH(iDir,iField,node,QQ,nScalars,nElems,neigh) &
??   &        = ?neigh?(?NGPOS?(?iDir?,?node?,?nElems?))+?NGOFFSET?(?iField?,?QQ?,?nElems?)+?nScalars?*0
?? macro :: SAVE( iDir,iField,node,QQ,nScalars,nElems)      &
??   &        = ?IDX?( ?iDir?+(?iField?-1)*?QQ?, ?node?, ?nScalars?, ?nElems?)
?? macro :: StreamName = pull
?? macro :: NgDir(iDir, stencil) = ?stencil?%cxDirInv( ?iDir? )
?? macro :: InvNgDir(iDir) = ?iDir?
?? macro :: post2pre( omega ) = ( 1.0_rk - ?omega? )
?? macro :: pre2post( omega ) = ( 1.0_rk - ?omega? )
?? endif
??
??! Access to the Connectivity Array
?? macro :: NGPOS(iDir,node,nElems) = (?iDir?-1)*?nElems? + ?node?
??!
?? IF(SOA) THEN
??!--------------------------------------------
??!    S O A - Structure of arrays layout
??!-------------------------------------------
??! These are the array index access macros
??! Access to the state array
?? macro :: IDX(varPosiDir,node, nScalars, nElems) = (?varPosiDir?-1)*?nElems? + ?node? + ?nScalars?*0
??! Offset in NGPOS
?? macro :: NGOFFSET( iField, QQ, nElems ) = (?iField?-1)*?QQ?*?nElems?
??! Position in Element list
?? macro :: ElemIDX(index, QQ, nElems) = mod(?index?-1,?nElems?) + 1 + ?QQ?*0
??! Direction
?? macro :: DirIDX(index, QQ, nElems)  = int((?index?-1)/?nElems?) + 1 + ?QQ?*0
??!
?? ELSE
??!--------------------------------------------
??!    A O S - Array of structures layout
??!-------------------------------------------
??! These are the Array index access macros
??! Access to the State Array
?? macro :: IDX(varPosiDir,node,nScalars) = (?node?-1)*?nScalars? + ?varPosiDir?
??! Offset after NGPOS
?? macro :: NGOFFSET( iField, QQ ) = (?iField?-1)*?QQ?
??! Position in Element list
?? macro :: ElemIDX(index, QQ) = int((?index?-1)/?QQ?) + 1
??! Direction
?? macro :: DirIDX(index, QQ, nElems)  = mod(?index?-1,?QQ?) + 1 + ?nElems?*0
?? ENDIF
??!
?? text :: dir_vector
!CDIR NODEP
!IBM* INDEPENDENT
!DIR$ IVDEP
!DIR$ VECTOR aligned NONTEMPORAL(outState)
?? end text dir_vector
??!
?? text :: dir_novec
!CDIR NODEP
!IBM* NOVECTOR
!DIR$ NOVECTOR
?? end text dir_novec
