xref: /phasta/phSolver/common/genbc.f (revision 6f04c980c0886178bf4f84a5c439b4bf7be67c88)
159599516SKenneth E. Jansen      subroutine genBC (iBC,  BC,   x,   ilwork, iper)
259599516SKenneth E. Jansenc
359599516SKenneth E. Jansenc----------------------------------------------------------------------
459599516SKenneth E. Jansenc  This routine generates the essential prescribed boundary conditions.
559599516SKenneth E. Jansenc
659599516SKenneth E. Jansenc input:
759599516SKenneth E. Jansenc  iBC   (nshg)        : boundary condition code
859599516SKenneth E. Jansenc  nBC   (nshg)        : boundary condition mapping array
959599516SKenneth E. Jansenc
1059599516SKenneth E. Jansenc output:
1159599516SKenneth E. Jansenc  BC    (nshg,ndofBC) : The constraint data for prescribed BC
1259599516SKenneth E. Jansenc
1359599516SKenneth E. Jansenc
1459599516SKenneth E. Jansenc Note: genBC1 reduces the input data for the velocity. In the
1559599516SKenneth E. Jansenc       case of varying velocity direction in the generation, the
1659599516SKenneth E. Jansenc       results may not be correct. (since a linearity assumption is
1759599516SKenneth E. Jansenc       made in the generation).
1859599516SKenneth E. Jansenc
1959599516SKenneth E. Jansenc
2059599516SKenneth E. Jansenc Farzin Shakib, Spring 1986.
2159599516SKenneth E. Jansenc Zdenek Johan,  Winter 1991.  (Fortran 90)
2259599516SKenneth E. Jansenc----------------------------------------------------------------------
2359599516SKenneth E. Jansenc
2459599516SKenneth E. Jansen      use slpw
2559599516SKenneth E. Jansen      use readarrays            ! used to access BCinp, nBC
2659599516SKenneth E. Jansen      use specialBC ! filling acs here
2759599516SKenneth E. Jansen      include "common.h"
2859599516SKenneth E. Jansenc
2959599516SKenneth E. Jansen      dimension iBC(nshg),                nsurf(nshg),
3059599516SKenneth E. Jansen     &            BC(nshg,ndofBC),
3159599516SKenneth E. Jansen     &            x(numnp,nsd),             ilwork(nlwork),
3259599516SKenneth E. Jansen     &            iper(nshg)
3359599516SKenneth E. Jansenc
3459599516SKenneth E. Jansenc BCinp for each point has:
3559599516SKenneth E. Jansenc   D T P c11 c12 c13 M1 c21 c22 c23 M2 theta S1 S2 S3...
3659599516SKenneth E. Jansenc   1 2 3 4   5   6   7  8   9   10  11 12    13 14 15...
3759599516SKenneth E. Jansenc Remember, ndof=nsd+2+nsclr
3859599516SKenneth E. Jansenc
3959599516SKenneth E. Jansenc Arrays in the following 1 line are now dimensioned in readnblk
4059599516SKenneth E. Jansenc        dimension BCinp(numpbc,ndof+7)
4159599516SKenneth E. Jansenc
4259599516SKenneth E. Jansen      dimension BCtmp(nshg,ndof+7)
4359599516SKenneth E. Jansenc
4459599516SKenneth E. Jansenc ndof+7= 3(thermos) + (nsd-1)*(nsd+1) + nscalars + 1 (theta)
4559599516SKenneth E. Jansenc                       #vect *(vec dir +mag)
4659599516SKenneth E. Jansenc
4759599516SKenneth E. Jansenc.... --------------------------->  Input  <---------------------------
4859599516SKenneth E. Jansenc
4959599516SKenneth E. Jansenc.... convert boundary condition data
5059599516SKenneth E. Jansenc
5159599516SKenneth E. Jansen      BCtmp = zero
5259599516SKenneth E. Jansenc
5359599516SKenneth E. Jansen      if(numpbc.ne.0) then
5459599516SKenneth E. Jansen         do i = 1, ndof+7
5559599516SKenneth E. Jansen            where (nBC(:) .ne. 0) BCtmp(:,i) = BCinp(nBC(:),i)
5659599516SKenneth E. Jansen         enddo
5759599516SKenneth E. Jansen         deallocate(BCinp)
5859599516SKenneth E. Jansen      endif
5959599516SKenneth E. Jansen
6059599516SKenneth E. Jansenc
6159599516SKenneth E. Jansen      if(any(BCtmp(:,12).ne.0)) then
6259599516SKenneth E. Jansen         iabc=1
6359599516SKenneth E. Jansen         allocate (acs(nshg,2))
6459599516SKenneth E. Jansen         where (btest(iBC,10))
6559599516SKenneth E. Jansen            acs(:,1) = cos(BCtmp(:,12))
6659599516SKenneth E. Jansen            acs(:,2) = sin(BCtmp(:,12))
6759599516SKenneth E. Jansen         endwhere
6859599516SKenneth E. Jansen      endif
6959599516SKenneth E. Jansen
7059599516SKenneth E. Jansenc
7159599516SKenneth E. Jansenc.... ----------------------> Wall Normals  <--------------------------
7259599516SKenneth E. Jansenc (calculate the normal and adjust BCinp to the true normal as needed)
7359599516SKenneth E. Jansenc
7459599516SKenneth E. Jansen      if(navier.eq.1)then
7559599516SKenneth E. Jansen         call genwnm (iBC,  BCtmp,   x,   ilwork, iper, nsurf)
7659599516SKenneth E. Jansen      endif
7759599516SKenneth E. Jansenc  determine the first point off the wall for each wall node
7859599516SKenneth E. Jansen      if(navier.eq.1)then
7959599516SKenneth E. Jansen         call genotwn (x,BCtmp, iBC, nsurf)
8059599516SKenneth E. Jansen      endif
8159599516SKenneth E. Jansenc.... ------------------------>  Conversion  <-------------------------
8259599516SKenneth E. Jansenc
8359599516SKenneth E. Jansenc.... convert the input boundary conditions to condensed version
8459599516SKenneth E. Jansenc
8559599516SKenneth E. Jansen      BC = zero
8659599516SKenneth E. Jansenc
8759599516SKenneth E. Jansen      if(navier.eq.1)then ! zero navier means Euler simulation
8859599516SKenneth E. Jansen         call genBC1 (BCtmp,  iBC,  BC)
8959599516SKenneth E. Jansen      else ! navier equals zero
9059599516SKenneth E. Jansen         allocate(BCtmpg(nshg,ndof+7))
9159599516SKenneth E. Jansen         allocate(BCg(nshg,ndofBC))
9259599516SKenneth E. Jansen         allocate(iBCg(nshg))
9359599516SKenneth E. Jansen         BCtmpg=BCtmp
9459599516SKenneth E. Jansen         iBCg=iBC
9559599516SKenneth E. Jansen         call genBC1 (BCtmp,  iBC,  BC)
9659599516SKenneth E. Jansenc... genBC1 convert BCtmp to BC
9759599516SKenneth E. Jansen         BCg=BC
9859599516SKenneth E. Jansen         icdg=icd
9959599516SKenneth E. Jansenc... find slip wall
10059599516SKenneth E. Jansen         call findslpw(x,ilwork,iper,iBC)
10159599516SKenneth E. Jansenc... apply slip wall condition to wall nodes
10259599516SKenneth E. Jansen         do i=1,nslpwnd
10359599516SKenneth E. Jansen            nn=idxslpw(i)
10459599516SKenneth E. Jansen            call slpwBC(mpslpw(nn,1),mpslpw(nn,2),iBCg(nn),
10559599516SKenneth E. Jansen     &               BCg(nn,:),  BCtmpg(nn,:),
10659599516SKenneth E. Jansen     &               iBC(nn),    BC(nn,:),
10759599516SKenneth E. Jansen     &               wlnorm(nn,:,:)                     )
10859599516SKenneth E. Jansen         enddo
10959599516SKenneth E. Jansen         icd=icdg
11059599516SKenneth E. Jansen      endif
11159599516SKenneth E. Jansen
11259599516SKenneth E. Jansen
11359599516SKenneth E. Jansenc
11459599516SKenneth E. Jansenc.... --------------------------->  Echo  <----------------------------
11559599516SKenneth E. Jansenc
11659599516SKenneth E. Jansenc.... echo the input data
11759599516SKenneth E. Jansenc
11859599516SKenneth E. Jansen      if (necho .lt. 3) then
11959599516SKenneth E. Jansen         nn = 0
12059599516SKenneth E. Jansen         do n = 1, nshg
12159599516SKenneth E. Jansen            if (nBC(n) .ne. 0) then
12259599516SKenneth E. Jansen               nn = nn + 1
12359599516SKenneth E. Jansen               if(mod(nn,50).eq.1)
12459599516SKenneth E. Jansen     &              write(iecho,1000)ititle,(j,j=1,ndofBC)
12559599516SKenneth E. Jansen               write (iecho,1100) n, (BC(n,i),i=1,ndofBC)
12659599516SKenneth E. Jansen            endif
12759599516SKenneth E. Jansen         enddo
12859599516SKenneth E. Jansen      endif
12959599516SKenneth E. Jansenc
13059599516SKenneth E. Jansenc.... return
13159599516SKenneth E. Jansenc
13259599516SKenneth E. Jansen      return
13359599516SKenneth E. Jansenc
13459599516SKenneth E. Jansen 1000 format(a80,//,
13559599516SKenneth E. Jansen     &' P r e s c r i b e d   B o u n d a r y   C o n d i t i o n s',//,
13659599516SKenneth E. Jansen     &  '    Node  ',/,
13759599516SKenneth E. Jansen     &  '   Number ',5x,6('BC',i1,:,10x))
13859599516SKenneth E. Jansen 1100 format(1p,2x,i5,3x,6(e12.5,1x))
13959599516SKenneth E. Jansenc
14059599516SKenneth E. Jansen      end
14159599516SKenneth E. Jansen
14259599516SKenneth E. Jansen
14359599516SKenneth E. Jansen
14459599516SKenneth E. Jansen
14559599516SKenneth E. Jansen
14659599516SKenneth E. Jansen
14759599516SKenneth E. Jansen
14859599516SKenneth E. Jansen
14959599516SKenneth E. Jansen
15059599516SKenneth E. Jansen
15159599516SKenneth E. Jansen      subroutine genwnm (iBC, BCtmp,    x,   ilwork, iper, nsurf)
15259599516SKenneth E. Jansenc----------------------------------------------------------------------
15359599516SKenneth E. Jansenc  This routine generates the normal to a wall
15459599516SKenneth E. Jansenc
15559599516SKenneth E. Jansenc input:
15659599516SKenneth E. Jansenc  iBC   (nshg)        : boundary condition code
15759599516SKenneth E. Jansenc  nBC   (nshg)        : boundary condition mapping array
15859599516SKenneth E. Jansenc
15959599516SKenneth E. Jansenc output:
16059599516SKenneth E. Jansenc  BCtmp    (nshg,ndof+6) : The constraint data for prescribed BC
16159599516SKenneth E. Jansenc
16259599516SKenneth E. Jansenc
16359599516SKenneth E. Jansenc----------------------------------------------------------------------
16459599516SKenneth E. Jansenc
16559599516SKenneth E. Jansen      use turbSA
16659599516SKenneth E. Jansen      use pointer_data          ! used for mienb, mibcb
16759599516SKenneth E. Jansen      include "common.h"
16859599516SKenneth E. Jansen      include "mpif.h"
16959599516SKenneth E. Jansenc
17059599516SKenneth E. Jansen      character*20 fname1,  fmt1
17159599516SKenneth E. Jansen      character*5  cname
17259599516SKenneth E. Jansen      dimension iBC(nshg),                  iper(nshg),
17359599516SKenneth E. Jansen     &            x(numnp,nsd),             ilwork(nlwork)
17459599516SKenneth E. Jansenc
17559599516SKenneth E. Jansen      dimension  BCtmpSAV(nshg,ndof+7)
17659599516SKenneth E. Jansen      dimension  BCtmp(nshg,ndof+7),      fBC(nshg,ndofBC),
17759599516SKenneth E. Jansen     &            e1(3),                    e2(3),
17859599516SKenneth E. Jansen     &            elnrm(3),                 asum(numnp)
17959599516SKenneth E. Jansenc
18059599516SKenneth E. Jansen      integer sid, nsidg
18159599516SKenneth E. Jansen      integer nsurf(nshg), ivec(nsd)
18259599516SKenneth E. Jansen      logical :: firstvisit(nshg)
18359599516SKenneth E. Jansen      real*8 BCvecs(2,nsd)
18459599516SKenneth E. Jansen      integer, allocatable :: ienb(:)
18559599516SKenneth E. Jansen      dimension wnmdb(nshg,nsd)
18659599516SKenneth E. Jansenc
18759599516SKenneth E. Jansenc  wnrm is dimensioned nshg but the math is only done for straight sided
18859599516SKenneth E. Jansenc  elements at this point so wnrm will not be calculated for the hierarchic
18959599516SKenneth E. Jansenc  modes.  Note that the wall model creates a p.w. linear representation
19059599516SKenneth E. Jansenc  only at this time.
19159599516SKenneth E. Jansenc
19259599516SKenneth E. Jansen      allocate ( wnrm(nshg,3) )
19359599516SKenneth E. Jansenc
19459599516SKenneth E. Jansenc.... ----------------------> Wall Normals  <--------------------------
19559599516SKenneth E. Jansenc (calculate the normal and adjust BCinp to the true normal as needed)
19659599516SKenneth E. Jansenc
19759599516SKenneth E. Jansenc
19859599516SKenneth E. Jansen      asum = zero
19959599516SKenneth E. Jansen      wnrm = zero
20059599516SKenneth E. Jansen
20159599516SKenneth E. Jansenc
20259599516SKenneth E. Jansenc....  Save a copy of BCtmp so that after we calculate the normals we
20359599516SKenneth E. Jansenc      can recover the comp3 information.
20459599516SKenneth E. Jansenc
20559599516SKenneth E. Jansen      BCtmpSAV=BCtmp
20659599516SKenneth E. Jansenc
20759599516SKenneth E. Jansenc Count out the number of surface ID's on-processor, and map them
20859599516SKenneth E. Jansen      call gensidcount(nsidg)
20959599516SKenneth E. Jansen
21059599516SKenneth E. Jansenc
21159599516SKenneth E. Jansen      if(nsidg.gt.0) then       ! if there are any surfID's
21259599516SKenneth E. Jansen         nsurf(:) = 0
21359599516SKenneth E. Jansen         do k = 1, nsidg        ! loop over Surface ID's
21459599516SKenneth E. Jansen            sid = sidmapg(k)
21559599516SKenneth E. Jansen            firstvisit(:)=.true.
21659599516SKenneth E. Jansen            wnrm(:,1:3)=zero
21759599516SKenneth E. Jansen            do iblk=1, nelblb   ! loop over boundary element blocks
21859599516SKenneth E. Jansen               npro = lcblkb(1,iblk+1)-lcblkb(1,iblk)
21959599516SKenneth E. Jansen               nenbl = lcblkb(6,iblk)
22059599516SKenneth E. Jansen               nshl = lcblkb(9,iblk)
22159599516SKenneth E. Jansen               allocate( ienb(nshl) )
22259599516SKenneth E. Jansen               do i = 1, npro   ! loop over boundary elements
22359599516SKenneth E. Jansen                  iBCB1=miBCB(iblk)%p(i,1)
22459599516SKenneth E. Jansen                  iBCB2=miBCB(iblk)%p(i,2)
22559599516SKenneth E. Jansen                  ienb(1:nshl)=mienb(iblk)%p(i,1:nshl)
22659599516SKenneth E. Jansenc don't bother with elements that aren't on modeled surfaces
22759599516SKenneth E. Jansenc              if ( not          (wall set  and   traction set)    )
22859599516SKenneth E. Jansen                  if (.not.(btest(iBCB1,2).and.btest(iBCB1,4)))
22959599516SKenneth E. Jansen     &                 cycle
23059599516SKenneth E. Jansenc don't bother with elements that don't lie on the current surface
23159599516SKenneth E. Jansen                  if (iBCB2.ne.sid) cycle
23259599516SKenneth E. Jansenc
23359599516SKenneth E. Jansenc.... calculate this element's area-weighted normal vector
23459599516SKenneth E. Jansenc
23559599516SKenneth E. Jansen                  e1 = x(ienb(2),:)-x(ienb(1),:)
23659599516SKenneth E. Jansen                  e2 = x(ienb(3),:)-x(ienb(1),:)
23759599516SKenneth E. Jansen                  elnrm(1) = e1(2)*e2(3)-e1(3)*e2(2)
23859599516SKenneth E. Jansen                  elnrm(2) = e1(3)*e2(1)-e1(1)*e2(3)
23959599516SKenneth E. Jansen                  elnrm(3) = e1(1)*e2(2)-e1(2)*e2(1)
24059599516SKenneth E. Jansenc Tetrahedral elements have negative volumes in phastaI, so
24159599516SKenneth E. Jansenc the normals calculated from the boundary faces must be inverted
24259599516SKenneth E. Jansenc to point into the fluid
24359599516SKenneth E. Jansen                  if(nenbl.eq.3) elnrm(:)=-elnrm(:)
24459599516SKenneth E. Jansenc
24559599516SKenneth E. Jansenc.... add area-weighted normals to the nodal tallies for this surface
24659599516SKenneth E. Jansenc
24759599516SKenneth E. Jansen                  do j = 1, nenbl ! loop over elt boundary nodes
24859599516SKenneth E. Jansen                     nn=ienb(j) ! global node number
24959599516SKenneth E. Jansen                     if(firstvisit(nn)) then
25059599516SKenneth E. Jansen                        firstvisit(nn)=.false.
25159599516SKenneth E. Jansen                        nsurf(nn)=nsurf(nn)+1
25259599516SKenneth E. Jansen                        if(nsurf(nn).eq.1) BCtmp(nn,4:6)=zero
25359599516SKenneth E. Jansen                        if(nsurf(nn).eq.2) BCtmp(nn,8:10)=zero
25459599516SKenneth E. Jansen                     endif
25559599516SKenneth E. Jansen                     wnrm(nn,:)=wnrm(nn,:)+elnrm
25659599516SKenneth E. Jansen                  enddo         ! loop over elt boundary nodes
25759599516SKenneth E. Jansen               enddo            ! end loop over boundary elements in block
25859599516SKenneth E. Jansen               deallocate(ienb)
25959599516SKenneth E. Jansen            enddo               ! end loop over boundary element blocks
26059599516SKenneth E. Jansenc Now we have all of this surface's contributions to wall normals
26159599516SKenneth E. Jansenc for all nodes, along with an indication of how many surfaces
26259599516SKenneth E. Jansenc each node has encountered so far.  Contributions from other processors
26359599516SKenneth E. Jansenc should now be accumulated for this surface
26459599516SKenneth E. Jansenc
26559599516SKenneth E. Jansenc axisymm BC's need BC (and we have not built it yet) so we need to create
26659599516SKenneth E. Jansenc the entries it needs.
26759599516SKenneth E. Jansenc
26859599516SKenneth E. Jansen            if(iabc==1) then
26959599516SKenneth E. Jansen               where (btest(iBC,10))
27059599516SKenneth E. Jansen                  fBC(:,1) = cos(BCtmp(:,12))
27159599516SKenneth E. Jansen                  fBC(:,2) = sin(BCtmp(:,12))
27259599516SKenneth E. Jansen               endwhere
27359599516SKenneth E. Jansen
27459599516SKenneth E. Jansenc before the commu we need to rotate the residual vector for axisymmetric
27559599516SKenneth E. Jansenc boundary conditions (so that off processor periodicity is a dof add instead
27659599516SKenneth E. Jansenc of a dof combination).  Take care of all nodes now so periodicity, like
27759599516SKenneth E. Jansenc commu is a simple dof add.
27859599516SKenneth E. Jansen               call rotabc(wnrm, iBC, 'in ')
27959599516SKenneth E. Jansen            endif
28059599516SKenneth E. Jansen
28159599516SKenneth E. Jansen            if (numpe.gt.1) then
28259599516SKenneth E. Jansenc.... add areas and norms contributed from other processors
28359599516SKenneth E. Jansen               call commu (wnrm, ilwork, 3, 'in ')
28459599516SKenneth E. Jansen            endif
28559599516SKenneth E. Jansenc.... account for periodicity and axisymmetry
28659599516SKenneth E. Jansen            call bc3per(iBC,wnrm, iper,ilwork, 3)
28759599516SKenneth E. Jansenc at this point the master has all the information (slaves are zeroed and
28859599516SKenneth E. Jansenc waiting to be told what the master has...lets do that).
28959599516SKenneth E. Jansenc
29059599516SKenneth E. Jansenc.... local periodic (and axisymmetric) boundary conditions (no communications)
29159599516SKenneth E. Jansen            wnmdb=wnrm
29259599516SKenneth E. Jansen            do i = 1,numnp      ! only use the vertices in the normal calc
29359599516SKenneth E. Jansen               wnrm(i,:) = wnrm(iper(i),:)
29459599516SKenneth E. Jansen            enddo
29559599516SKenneth E. Jansen            wnmdb=wnrm
29659599516SKenneth E. Jansen            if (numpe.gt.1) then
29759599516SKenneth E. Jansenc.... tell other processors the resulting (and now complete) sums
29859599516SKenneth E. Jansen               call commu (wnrm, ilwork, 3, 'out')
29959599516SKenneth E. Jansen            endif
30059599516SKenneth E. Jansenc Axisymmetric slaves need to be rotated back
30159599516SKenneth E. Jansen            if(iabc==1) then    !are there any axisym bc's
30259599516SKenneth E. Jansen               call rotabc(wnrm, iBC, 'out')
30359599516SKenneth E. Jansen            endif
30459599516SKenneth E. Jansenc Now all nodes have all the normal contributions for this surface,
30559599516SKenneth E. Jansenc including those from off-processor and periodic nodes.
30659599516SKenneth E. Jansenc We distribute these summed vectors to the proper slots in BCtmp,
30759599516SKenneth E. Jansenc according to how many surfaces each node has seen so far
30859599516SKenneth E. Jansen            do nn = 1, nshg
30959599516SKenneth E. Jansen               if(nsurf(nn).eq.1)
31059599516SKenneth E. Jansen     &              BCtmp(nn,4:6)=BCtmp(nn,4:6)+wnrm(nn,:)
31159599516SKenneth E. Jansen               if(nsurf(nn).eq.2)
31259599516SKenneth E. Jansen     &              BCtmp(nn,8:10)=BCtmp(nn,8:10)+wnrm(nn,:)
31359599516SKenneth E. Jansen               if(nsurf(nn).gt.2)
31459599516SKenneth E. Jansen     &              BCtmp(nn,4:6)=BCtmp(nn,4:6)+wnrm(nn,:)
31559599516SKenneth E. Jansen            enddo
31659599516SKenneth E. Jansenc That's all for this surface; move on to the next
31759599516SKenneth E. Jansen         enddo                  ! end loop over surface ID's
31859599516SKenneth E. Jansen
31959599516SKenneth E. Jansenc
32059599516SKenneth E. Jansenc.... complete the averaging, adjust iBC, adjust BCtmp
32159599516SKenneth E. Jansenc
32259599516SKenneth E. Jansen         wnrm(:,1:3)=zero
32359599516SKenneth E. Jansen         do nn = 1, numnp       ! loop over all nodes
32459599516SKenneth E. Jansenc leave nodes without wall-modeled surfaces unchanged
32559599516SKenneth E. Jansen            if(nsurf(nn).eq.0) cycle
32659599516SKenneth E. Jansenc
32759599516SKenneth E. Jansenc mark this as a node with comp3
32859599516SKenneth E. Jansenc
32959599516SKenneth E. Jansen            ikp=0
33059599516SKenneth E. Jansen            if(ibits(iBC(nn),3,3).eq.7 ) ikp=1
33159599516SKenneth E. Jansenc         if(ibits(ibc(nn),3,3).eq.7 .and. BCtmp(nn,7).eq.zero) cycle
33259599516SKenneth E. Jansenc find out which velocity BC's were set by the user, and cancel them
33359599516SKenneth E. Jansen            ixset=ibits(iBC(nn),3,1)
33459599516SKenneth E. Jansen            iyset=ibits(iBC(nn),4,1)
33559599516SKenneth E. Jansen            izset=ibits(iBC(nn),5,1)
33659599516SKenneth E. Jansen            iBC(nn)=iBC(nn)-ixset*8-iyset*16-izset*32
33759599516SKenneth E. Jansenc
33859599516SKenneth E. Jansenc save this stripped iBC for later un-fixing
33959599516SKenneth E. Jansenc
34059599516SKenneth E. Jansen            iBCSAV=iBC(nn)
34159599516SKenneth E. Jansenc
34259599516SKenneth E. Jansen            if(abs(itwmod).eq.1) then ! slip velocity wall-model
34359599516SKenneth E. Jansenc If we're using the slip-velocity wall-model, then the velocity
34459599516SKenneth E. Jansenc boundary condition for this node will depend on how many modeled
34559599516SKenneth E. Jansenc surfaces share it...
34659599516SKenneth E. Jansen               if(nsurf(nn).eq.1) then ! 1 modeled wall
34759599516SKenneth E. Jansenc   If this node is part of only one modeled wall, then the component
34859599516SKenneth E. Jansenc   of the velocity normal to the surface is set to zero.  In this case
34959599516SKenneth E. Jansenc   only the first vector of BCtmp received normal contributions
35059599516SKenneth E. Jansen                  iBC(nn)=iBC(nn)+8 ! assume normal is x-dominated first
35159599516SKenneth E. Jansen                  wnrm(nn,:)=BCtmp(nn,4:6)
35259599516SKenneth E. Jansen                  if(abs(wnrm(nn,3)).gt.abs(wnrm(nn,2)))then ! z beats y
35359599516SKenneth E. Jansen                     if(abs(wnrm(nn,3)).gt.abs(wnrm(nn,1)))then ! z beats x
35459599516SKenneth E. Jansen                        iBC(nn)=iBC(nn)+24
35559599516SKenneth E. Jansen                     endif      ! z beats x
35659599516SKenneth E. Jansen                  endif         ! z beats y
35759599516SKenneth E. Jansen                  if(abs(wnrm(nn,2)).ge.abs(wnrm(nn,3)))then ! y beats z
35859599516SKenneth E. Jansen                     if(abs(wnrm(nn,2)).gt.abs(wnrm(nn,1)))then ! y beats x
35959599516SKenneth E. Jansen                        iBC(nn)=iBC(nn)+8
36059599516SKenneth E. Jansen                     endif      ! y beats x
36159599516SKenneth E. Jansen                  endif         ! y beats z           !(adjusted iBC)
36259599516SKenneth E. Jansen                  BCtmp(nn,7)=zero
36359599516SKenneth E. Jansen               else if(nsurf(nn).eq.2) then
36459599516SKenneth E. Jansenc   If this node is shared by two modeled walls, then each wall
36559599516SKenneth E. Jansenc   provides a normal vector along which the velocity must be zero.
36659599516SKenneth E. Jansenc   This leaves only one "free" direction, along which the flow is nonzero.
36759599516SKenneth E. Jansenc   The two normal vectors define a plane.  Any pair of non-parallel
36859599516SKenneth E. Jansenc   vectors in this plane can also be specified, leaving the same free
36959599516SKenneth E. Jansenc   direction.  Area-weighted average normal vectors for the two surfaces
37059599516SKenneth E. Jansenc   sharing this node have been stored in BCtmp(4:6) and BCtmp(8:10)
37159599516SKenneth E. Jansenc   We normalize the first of these, and then orthogonalize the second
37259599516SKenneth E. Jansenc   against the first.  After then normalizing the second, we choose which
37359599516SKenneth E. Jansenc   cartesian direction dominates each of the vectors, and adjust iBC
37459599516SKenneth E. Jansenc   and BCtmp accordingly
37559599516SKenneth E. Jansen                  e1=BCtmp(nn,4:6)
37659599516SKenneth E. Jansen                  wmag=e1(1)*e1(1)+e1(2)*e1(2)+e1(3)*e1(3)
37759599516SKenneth E. Jansen                  wmag=1./sqrt(wmag)
37859599516SKenneth E. Jansen                  e1=e1*wmag    ! first vector is normalized
37959599516SKenneth E. Jansenc
38059599516SKenneth E. Jansen                  e2=BCtmp(nn,8:10)
38159599516SKenneth E. Jansen                  wmag=e2(1)*e1(1)+e2(2)*e1(2)+e2(3)*e1(3) ! wmag=e2.n1
38259599516SKenneth E. Jansen                  e2=e2-wmag*e1 ! second vector is orthogonalized
38359599516SKenneth E. Jansenc
38459599516SKenneth E. Jansen                  wmag=e2(1)*e2(1)+e2(2)*e2(2)+e2(3)*e2(3)
38559599516SKenneth E. Jansen                  wmag=1./sqrt(wmag)
38659599516SKenneth E. Jansen                  e2=e2*wmag    ! second vector is normalized
38759599516SKenneth E. Jansenc
38859599516SKenneth E. Jansen               ! idom tells us which component is currently dominant
38959599516SKenneth E. Jansen               ! ivec(n) tells us which vector is dominated by comp n
39059599516SKenneth E. Jansen                  ivec(:)=0     ! initialize
39159599516SKenneth E. Jansen                  idom=1        ! assume x-comp dominates e1
39259599516SKenneth E. Jansen                  bigcomp=abs(e1(1))
39359599516SKenneth E. Jansen                  ivec(idom)=1
39459599516SKenneth E. Jansen                  do i = 2, nsd
39559599516SKenneth E. Jansen                     if(abs(e1(i)).gt.bigcomp) then
39659599516SKenneth E. Jansen                        ivec(idom)=0
39759599516SKenneth E. Jansen                        bigcomp=abs(e1(i))
39859599516SKenneth E. Jansen                        idom=i
39959599516SKenneth E. Jansen                        ivec(i)=1
40059599516SKenneth E. Jansen                     endif
40159599516SKenneth E. Jansen                  enddo
40259599516SKenneth E. Jansen                  if(idom.ne.1) then
40359599516SKenneth E. Jansen                     idom=1     ! assume x-comp dominates e2
40459599516SKenneth E. Jansen                  else
40559599516SKenneth E. Jansen                     idom=3     ! assume z-comp dominates e2
40659599516SKenneth E. Jansen                  endif
40759599516SKenneth E. Jansen                  bigcomp=abs(e2(idom))
40859599516SKenneth E. Jansen
40959599516SKenneth E. Jansen                  ivec(idom)=2
41059599516SKenneth E. Jansen                  do i = 1, nsd
41159599516SKenneth E. Jansen                     if(abs(e2(i)).gt.bigcomp) then
41259599516SKenneth E. Jansen                        if(ivec(i).eq.1) cycle
41359599516SKenneth E. Jansen                        ivec(idom)=0
41459599516SKenneth E. Jansen                        bigcomp=abs(e2(i))
41559599516SKenneth E. Jansen                        idom=i
41659599516SKenneth E. Jansen                        ivec(i)=2
41759599516SKenneth E. Jansen                     endif
41859599516SKenneth E. Jansen                  enddo
41959599516SKenneth E. Jansen               ! now we know which components dominate each vector
42059599516SKenneth E. Jansen                  ixset=0       !
42159599516SKenneth E. Jansen                  iyset=0       ! initialize
42259599516SKenneth E. Jansen                  izset=0       !
42359599516SKenneth E. Jansen                  if(ivec(1).ne.0) ixset=1
42459599516SKenneth E. Jansen                  if(ivec(2).ne.0) iyset=1
42559599516SKenneth E. Jansen                  if(ivec(3).ne.0) izset=1
42659599516SKenneth E. Jansen                  ncomp=ixset+iyset+izset
42759599516SKenneth E. Jansen                  if(ncomp.ne.2) write(*,*) 'WARNING: TROUBLE IN GENBC'
42859599516SKenneth E. Jansen                  BCvecs(1,1:3)=e1(:)
42959599516SKenneth E. Jansen                  BCvecs(2,1:3)=e2(:)
43059599516SKenneth E. Jansen                  if((ixset.eq.1).and.(iyset.eq.1)) then
43159599516SKenneth E. Jansen                     BCtmp(nn,4:6)=BCvecs(ivec(1),1:3)
43259599516SKenneth E. Jansen                     BCtmp(nn,8:10)=BCvecs(ivec(2),1:3)
43359599516SKenneth E. Jansen                  else if((ixset.eq.1).and.(izset.eq.1)) then
43459599516SKenneth E. Jansen                     BCtmp(nn,4:6)=BCvecs(ivec(1),1:3)
43559599516SKenneth E. Jansen                     BCtmp(nn,8:10)=BCvecs(ivec(3),1:3)
43659599516SKenneth E. Jansen                  else if((iyset.eq.1).and.(izset.eq.1)) then
43759599516SKenneth E. Jansen                     BCtmp(nn,4:6)=BCvecs(ivec(2),1:3)
43859599516SKenneth E. Jansen                     BCtmp(nn,8:10)=BCvecs(ivec(3),1:3)
43959599516SKenneth E. Jansen                  endif
44059599516SKenneth E. Jansen                  iBC(nn)=iBC(nn)+ixset*8+iyset*16+izset*32
44159599516SKenneth E. Jansen                  BCtmp(nn,7)=zero
44259599516SKenneth E. Jansen                  BCtmp(nn,11)=zero
44359599516SKenneth E. Jansen                  wnrm(nn,:)=BCtmp(nn,4:6)+BCtmp(nn,8:10)
44459599516SKenneth E. Jansen               else if(nsurf(nn).gt.2) then
44559599516SKenneth E. Jansenc     If this node is shared by more than two modeled walls, then
44659599516SKenneth E. Jansenc     it is a corner node and it will be treated as having no slip
44759599516SKenneth E. Jansenc     The normals for all surfaces beyond the first two were
44859599516SKenneth E. Jansenc     contributed to the first vector of BCtmp
44959599516SKenneth E. Jansen                  wnrm(nn,:)=BCtmp(nn,4:6)+BCtmp(nn,8:10)
45059599516SKenneth E. Jansen                  iBC(nn)=iBC(nn)+56
45159599516SKenneth E. Jansen                  BCtmp(nn,7)=zero
45259599516SKenneth E. Jansen               endif            ! curved surface
45359599516SKenneth E. Jansen            else if(abs(itwmod).eq.2) then ! effective viscosity wall-model
45459599516SKenneth E. Jansenc Otherwise, we're using the effective-viscosity wall-model and the
45559599516SKenneth E. Jansenc nodes on modeled surfaces are treated as no-slip
45659599516SKenneth E. Jansen               iBC(nn)=iBC(nn)+56 ! set 3-comp
45759599516SKenneth E. Jansen               if(itwmod.eq.-2) BCtmp(nn,7)=zero ! no slip
45859599516SKenneth E. Jansen               if(nsurf(nn).eq.1)
45959599516SKenneth E. Jansen     &              wnrm(nn,:)=BCtmp(nn,4:6)
46059599516SKenneth E. Jansen               if(nsurf(nn).ge.2)
46159599516SKenneth E. Jansen     &              wnrm(nn,:)=BCtmp(nn,4:6)+BCtmp(nn,8:10)
46259599516SKenneth E. Jansen            endif
46359599516SKenneth E. Jansenc Now normalize the wall normal for this node
46459599516SKenneth E. Jansen            if(itwmod.ne.0) then
46559599516SKenneth E. Jansen               wmag=sqrt(wnrm(nn,1)*wnrm(nn,1)
46659599516SKenneth E. Jansen     &              +wnrm(nn,2)*wnrm(nn,2)+wnrm(nn,3)*wnrm(nn,3))
46759599516SKenneth E. Jansen               wnrm(nn,:)=wnrm(nn,:)/wmag
46859599516SKenneth E. Jansen            endif
46959599516SKenneth E. Jansenc
47059599516SKenneth E. Jansenc.... put back the comp3 info for bctmp
47159599516SKenneth E. Jansenc
47259599516SKenneth E. Jansen            if(ikp.eq.1) then
47359599516SKenneth E. Jansen               iBC(nn)=iBCSAV+56 ! put it back to a comp3
47459599516SKenneth E. Jansen               BCtmp(nn,:)=BCtmpSAV(nn,:) ! ditto
47559599516SKenneth E. Jansen            endif
47659599516SKenneth E. Jansen         enddo                  ! loop over all nodes
47759599516SKenneth E. Jansen      endif                     ! end "if there are any surfID's"
47859599516SKenneth E. Jansenc
47959599516SKenneth E. Jansenc  If you are using the turbulence wall with axisymmetry you
48059599516SKenneth E. Jansenc  need to modify the axisymmetry angle to account for the discrete
48159599516SKenneth E. Jansenc  normals at the wall being different than the exact normals
48259599516SKenneth E. Jansenc
48359599516SKenneth E. Jansenc find the my normal, my partners normal and correct the angle
48459599516SKenneth E. Jansenc$$$
48559599516SKenneth E. Jansenc$$$        do i=1,numnp
48659599516SKenneth E. Jansenc$$$           wmag = wnrm(i,1) * wnrm(i,1)
48759599516SKenneth E. Jansenc$$$     &          + wnrm(i,2) * wnrm(i,2)
48859599516SKenneth E. Jansenc$$$     &          + wnrm(i,3) * wnrm(i,3)
48959599516SKenneth E. Jansenc$$$c
49059599516SKenneth E. Jansenc$$$c  only "fix" wall nodes...other nodes still have a zero in wnrm
49159599516SKenneth E. Jansenc$$$c
49259599516SKenneth E. Jansenc$$$           if((btest(iBC(i),12)).and.(wmag.ne.zero)) then
49359599516SKenneth E. Jansenc$$$              BCtmp(i,1)=acos( wnrm(i,1) * wnrm(iper(i),1)
49459599516SKenneth E. Jansenc$$$     &                       + wnrm(i,2) * wnrm(iper(i),2)
49559599516SKenneth E. Jansenc$$$     &                       + wnrm(i,3) * wnrm(iper(i),3) )
49659599516SKenneth E. Jansenc$$$           endif
49759599516SKenneth E. Jansenc$$$        enddo
49859599516SKenneth E. Jansenc
49959599516SKenneth E. Jansenc.... return
50059599516SKenneth E. Jansenc
50159599516SKenneth E. Jansen      return
50259599516SKenneth E. Jansenc
50359599516SKenneth E. Jansen      end
50459599516SKenneth E. Jansen
50559599516SKenneth E. Jansen
50659599516SKenneth E. Jansen      subroutine gensidcount(nsidg)
50759599516SKenneth E. Jansenc---------------------------------------------------------------------
50859599516SKenneth E. Jansenc
50959599516SKenneth E. Jansenc This routine counts up the total number of surface ID's across
51059599516SKenneth E. Jansenc all processors and makes a list of them
51159599516SKenneth E. Jansenc
51259599516SKenneth E. Jansenc Inputs:
51359599516SKenneth E. Jansenc     iBCB        natural boundary condition switches and surfIDs
51459599516SKenneth E. Jansenc
51559599516SKenneth E. Jansenc Outputs:
51659599516SKenneth E. Jansenc     nsidg       number of surface ID's globally (including all procs)
51759599516SKenneth E. Jansenc     sidmapg     global list of surface ID's, lowest to highest
51859599516SKenneth E. Jansenc
51959599516SKenneth E. Jansenc---------------------------------------------------------------------
52059599516SKenneth E. Jansen      use pointer_data ! access to miBCB
52159599516SKenneth E. Jansen      use turbSA ! access to sidmapg
52259599516SKenneth E. Jansen      include "common.h"
52359599516SKenneth E. Jansen      include "mpif.h"
52459599516SKenneth E. Jansenc
52559599516SKenneth E. Jansen      integer newflag, i, j
52659599516SKenneth E. Jansen      integer nsidl             ! number of surface IDs on-proc
52759599516SKenneth E. Jansen      integer nsidt             ! sum of all nsidl's
52859599516SKenneth E. Jansen      integer nsidg             ! number of surface IDs globally
52959599516SKenneth E. Jansen      integer nsid(numpe)       ! array of nsidl's
53059599516SKenneth E. Jansen      integer idisp(numpe)      ! needed by mpi: see note below
53159599516SKenneth E. Jansen      type llnod                ! structure for one node in a linked list
53259599516SKenneth E. Jansen        integer :: value
53359599516SKenneth E. Jansen        type (llnod), pointer :: next
53459599516SKenneth E. Jansen      end type llnod
53559599516SKenneth E. Jansen      type (llnod), pointer :: sidlist ! points to first elt of linked list
53659599516SKenneth E. Jansen      type (llnod), pointer :: sidelt  ! points to generic elt of linked list
537*6f04c980SCameron Smith      type (llnod), pointer :: nextelt ! points to generic elt of linked list
53859599516SKenneth E. Jansen      integer, allocatable :: sidmapl(:) ! list of surfID's on-proc
53959599516SKenneth E. Jansen      integer, allocatable :: temp(:)    ! temp space
54059599516SKenneth E. Jansenc      integer iBCB(numelb,ndiBCB) ! column 1: naturalBC switches
54159599516SKenneth E. Jansen                                   ! column 2: surface ID's
54259599516SKenneth E. Jansenc Since we don't know a priori how many surface ID's there are,
54359599516SKenneth E. Jansenc on-processor or globally, we will store the ID's as an open-ended
54459599516SKenneth E. Jansenc link list while we determine the total number of distinct ID's
54559599516SKenneth E. Jansen      allocate (sidlist) ! allocate the first element of the sid
54659599516SKenneth E. Jansen                         ! linked list and point sidlist to it
54759599516SKenneth E. Jansen      nsidl=0            ! initialize # of sids on this processor
54859599516SKenneth E. Jansen      nsidg=0
549*6f04c980SCameron Smith      nullify(sidlist % next)    ! next does not exist yet
55059599516SKenneth E. Jansen      do iblk=1, nelblb  ! loop over boundary element blocks
55159599516SKenneth E. Jansen         npro = lcblkb(1,iblk+1)-lcblkb(1,iblk)
55259599516SKenneth E. Jansen         do i = 1, npro         ! loop over boundary elements (belts)
55359599516SKenneth E. Jansen            iBCB2=miBCB(iblk)%p(i,2)
55459599516SKenneth E. Jansen            if(iBCB2.ne.zero) then ! if a sid is given for this belt
55559599516SKenneth E. Jansen               if(nsidl.eq.0) then     !   if this is the first sid we've seen
55659599516SKenneth E. Jansen                  nsidl=1              !       increment our count and
55759599516SKenneth E. Jansen                  sidlist % value = iBCB2    ! record its value
558*6f04c980SCameron Smith                  nullify(sidlist % next)    ! next does not exist yet
55959599516SKenneth E. Jansen               else                    !   if this isn't the first sid
56059599516SKenneth E. Jansen                  newflag = 1          !     assume this is a new sid
56159599516SKenneth E. Jansen                  sidelt => sidlist    !     starting with the first sid
56259599516SKenneth E. Jansen                  do j = 1, nsidl      !     check the assumption
56359599516SKenneth E. Jansen                     if((sidelt % value).eq.iBCB2) then
56459599516SKenneth E. Jansen                        newflag=0      !        ...
56559599516SKenneth E. Jansen                     endif
56659599516SKenneth E. Jansen                     if(j.ne.nsidl) then !      ...
56759599516SKenneth E. Jansen                        sidelt => sidelt % next
56859599516SKenneth E. Jansen                     endif!                     ...
56959599516SKenneth E. Jansen                  enddo
57059599516SKenneth E. Jansen                  if(newflag.eq.1) then!     if it really is new to us
57159599516SKenneth E. Jansen                     nsidl = nsidl + 1 !         increment our count
57259599516SKenneth E. Jansen                     allocate (sidelt % next)!   tack a new element to the end
57359599516SKenneth E. Jansen                     sidelt => sidelt % next!    point to the new element
57459599516SKenneth E. Jansen                     sidelt % value = iBCB2    ! record the new sid
575*6f04c980SCameron Smith                     nullify(sidelt % next)    ! next does not exist yet
57659599516SKenneth E. Jansen                  endif ! (really is a new sid)
57759599516SKenneth E. Jansen               endif ! (first sid)
57859599516SKenneth E. Jansen            endif ! (belt has a sid)
57959599516SKenneth E. Jansen         enddo ! (loop over belts)
58059599516SKenneth E. Jansen      enddo ! (loop over boundary element blocks)
58159599516SKenneth E. Jansenc Copy the data from the linked list to a more easily-used array form
58259599516SKenneth E. Jansen      if(nsidl.gt.0) then
58359599516SKenneth E. Jansen         allocate( sidmapl(nsidl) )
58459599516SKenneth E. Jansen         sidelt => sidlist      !     starting with the first sid
58559599516SKenneth E. Jansen         do j = 1, nsidl
58659599516SKenneth E. Jansen            sidmapl(j)=sidelt%value
58759599516SKenneth E. Jansen            if(j.ne.nsidl) sidelt => sidelt%next
58859599516SKenneth E. Jansen         enddo
58959599516SKenneth E. Jansen      else
59059599516SKenneth E. Jansen         allocate( sidmapl(1)) ! some compilers/MPI don't like to send unallocated arrays
59159599516SKenneth E. Jansen      endif
592*6f04c980SCameron Smith!     Deallocate the link list
593*6f04c980SCameron Smith!     http://stackoverflow.com/questions/9184675/how-does-fortran-deallocate-linked-lists
594*6f04c980SCameron Smith      sidelt => sidlist
595*6f04c980SCameron Smith      nextelt => sidelt % next
596*6f04c980SCameron Smith      do
597*6f04c980SCameron Smith        deallocate(sidelt)
598*6f04c980SCameron Smith        if( .not. associated(nextelt) ) exit
599*6f04c980SCameron Smith        sidelt => nextelt
600*6f04c980SCameron Smith        nextelt => sidelt % next
601*6f04c980SCameron Smith      enddo
602*6f04c980SCameron Smith
60359599516SKenneth E. Jansenc Gather the number of surface ID's on each processor
60459599516SKenneth E. Jansen      if (numpe.gt.1) then      ! multiple processors
60559599516SKenneth E. Jansenc write the number of surfID's on the jth processor to slot j of nsid
60659599516SKenneth E. Jansen         call MPI_ALLGATHER(nsidl,1,MPI_INTEGER,nsid,1,
60759599516SKenneth E. Jansen     &          MPI_INTEGER,MPI_COMM_WORLD,ierr)
60859599516SKenneth E. Jansenc count up the total number of surfID's among all processes
60959599516SKenneth E. Jansen         nsidt=0
61059599516SKenneth E. Jansen         do j=1,numpe
61159599516SKenneth E. Jansen            nsidt=nsidt+nsid(j)
61259599516SKenneth E. Jansen         enddo
61359599516SKenneth E. Jansen      else                      ! single processor
61459599516SKenneth E. Jansenc the local information is the global information for single-processor
61559599516SKenneth E. Jansen         nsid=nsidl
61659599516SKenneth E. Jansen         nsidt=nsidl
61759599516SKenneth E. Jansen      endif                     ! if-else for multiple processors
61859599516SKenneth E. Jansen      if(nsidt.gt.0) then
61959599516SKenneth E. Jansenc
62059599516SKenneth E. Jansenc  Make all-processor surfID collage
62159599516SKenneth E. Jansenc
62259599516SKenneth E. Jansenc there will be some duplicate surface ID's when we gather, so we
62359599516SKenneth E. Jansenc will use a temporary array
62459599516SKenneth E. Jansen         allocate (temp(nsidt))
62559599516SKenneth E. Jansen         if (numpe.gt.1) then   ! multiple processors
62659599516SKenneth E. Jansenc we will gather surfID's from local on-proc sets to a global set
62759599516SKenneth E. Jansenc we will stack each processor's surfID list atop that of the previous
62859599516SKenneth E. Jansenc processor.  If the list for processor i is called sidmapi, then our
62959599516SKenneth E. Jansenc global coordinate list sidmap will look like this:
63059599516SKenneth E. Jansenc ---------------------------------------------------------------
63159599516SKenneth E. Jansenc | sidmap1       | sidmap2           | sidmap3   |   ...       |
63259599516SKenneth E. Jansenc ---------------------------------------------------------------
63359599516SKenneth E. Jansenc  <---nsid(1)---> <-----nsid(2)-----> <-nsid(3)->
63459599516SKenneth E. Jansenc  <------------------------nsidt-----------------------...---->
63559599516SKenneth E. Jansenc To accomplish this with MPI, we use MPI_ALLGATHERV, summarized as:
63659599516SKenneth E. JansencMPI_ALLGATHERV(sendbuf,sendcount,sendtype,recvbuf,recvcount,disp,recvtype,comm)
63759599516SKenneth E. Jansenc[ IN sendbuf] starting address of send buffer (choice)
63859599516SKenneth E. Jansenc[ IN sendcount] number of elements in send buffer (integer)
63959599516SKenneth E. Jansenc[ IN sendtype] data type of send buffer elements (handle)
64059599516SKenneth E. Jansenc[ OUT recvbuf] address of receive buffer (choice)
64159599516SKenneth E. Jansenc[ IN recvcount] number of elements received from each process (int array)
64259599516SKenneth E. Jansenc[ IN disp] displacement array
64359599516SKenneth E. Jansenc[ IN recvtype] data type of receive buffer elements (handle)
64459599516SKenneth E. Jansenc[ IN comm] communicator (handle)
64559599516SKenneth E. Jansenc The displacement array disp is an array of integers in which the jth
64659599516SKenneth E. Jansenc entry indicates which slot of sidmap marks beginning of sidmapj
64759599516SKenneth E. Jansenc So, first we will build this displacement array
64859599516SKenneth E. Jansen            idisp(:)=0      ! starting with zero, since MPI likes C-numbering
64959599516SKenneth E. Jansen            do j=2,numpe
65059599516SKenneth E. Jansen               idisp(j)=idisp(j-1)+nsid(j-1) ! see diagram above
65159599516SKenneth E. Jansen            enddo
65259599516SKenneth E. Jansenc Now, we gather the data
65359599516SKenneth E. Jansen            call MPI_ALLGATHERV(sidmapl(:),nsidl,
65459599516SKenneth E. Jansen     &           MPI_INTEGER,temp(:),nsid,idisp,
65559599516SKenneth E. Jansen     &           MPI_INTEGER,MPI_COMM_WORLD,ierr)
65659599516SKenneth E. Jansenc sort surfID's, lowest to highest
65759599516SKenneth E. Jansen            isorted = 0
65859599516SKenneth E. Jansen            do while (isorted.eq.0) ! while the list isn't sorted
65959599516SKenneth E. Jansen               isorted = 1      ! assume the list is sorted this time
66059599516SKenneth E. Jansen               do j = 2, nsidt  ! loop over ID's
66159599516SKenneth E. Jansen                  if(temp(j).lt.temp(j-1)) then ! ID exceeds predecessor
66259599516SKenneth E. Jansen                     itmp=temp(j-1)
66359599516SKenneth E. Jansen                     temp(j-1)=temp(j)
66459599516SKenneth E. Jansen                     temp(j)=itmp
66559599516SKenneth E. Jansen                     isorted=0  ! not sorted yet
66659599516SKenneth E. Jansen                  endif
66759599516SKenneth E. Jansen               enddo            !loop over ID's
66859599516SKenneth E. Jansen            enddo               ! while not sorted
66959599516SKenneth E. Jansenc determine the total number of distinct surfID's, globally
67059599516SKenneth E. Jansen            nsidg=nsidt         ! assume there are no duplicate SurfID's
67159599516SKenneth E. Jansen            do j = 2, nsidt
67259599516SKenneth E. Jansen               if(temp(j).eq.temp(j-1)) nsidg = nsidg - 1 ! correction
67359599516SKenneth E. Jansen            enddo
67459599516SKenneth E. Jansenc create duplicate-free surfID list
67559599516SKenneth E. Jansen            allocate( sidmapg(nsidg) )
67659599516SKenneth E. Jansen            sidmapg(1)=temp(1)
67759599516SKenneth E. Jansen            nsidg = 1
67859599516SKenneth E. Jansen            do j = 2, nsidt
67959599516SKenneth E. Jansen               if(temp(j).ne.temp(j-1)) then
68059599516SKenneth E. Jansen                  nsidg = nsidg + 1
68159599516SKenneth E. Jansen                  sidmapg(nsidg)=temp(j)
68259599516SKenneth E. Jansen               endif
68359599516SKenneth E. Jansen            enddo
68459599516SKenneth E. Jansen            deallocate( temp )
68559599516SKenneth E. Jansen         else                   ! single-processor
68659599516SKenneth E. Jansenc global data is local data in single processor case
68759599516SKenneth E. Jansen            nsidg=nsidl
68859599516SKenneth E. Jansen            allocate( sidmapg(nsidg) )
68959599516SKenneth E. Jansen            sidmapg=sidmapl
690*6f04c980SCameron Smith            deallocate(sidmapl)
69159599516SKenneth E. Jansen         endif                  ! if-else multiple processor
69259599516SKenneth E. Jansenc
69359599516SKenneth E. Jansen      endif                     ! if at least one surfid
69459599516SKenneth E. Jansenc
69559599516SKenneth E. Jansen      return
69659599516SKenneth E. Jansenc
69759599516SKenneth E. Jansen      end
69859599516SKenneth E. Jansen
69959599516SKenneth E. Jansen
70059599516SKenneth E. Jansen
70159599516SKenneth E. Jansen      subroutine genotwn(x, BCtmp, iBC, nsurf)
70259599516SKenneth E. Jansenc
70359599516SKenneth E. Jansenc----------------------------------------------------------------------
70459599516SKenneth E. Jansenc  This routine determines which node to use as the first node off the
70559599516SKenneth E. Jansenc  wall in near-wall modeling traction calculations for each wall node.
70659599516SKenneth E. Jansenc  Each wall node has a normal, calculated from the wall elements to
70759599516SKenneth E. Jansenc  which that node belongs.  We seek the node within the boundary
70859599516SKenneth E. Jansenc  element that lies closest to the line defined by the normal vector.
70959599516SKenneth E. Jansenc  We create normalized vectors pointing from the wall node in
71059599516SKenneth E. Jansenc  question to each of the nodes in the boundary element. The vector
71159599516SKenneth E. Jansenc  that has the largest projection onto the wall node's normal vector
71259599516SKenneth E. Jansenc  points to the node we want.  Nodes that are not on a wall point to
71359599516SKenneth E. Jansenc  themselves as their own off-the-wall node.
71459599516SKenneth E. Jansenc
71559599516SKenneth E. Jansenc input:
71659599516SKenneth E. Jansenc  x     (nshg,3)     :        : nodal position vectors
71759599516SKenneth E. Jansenc  wnrm  (nshg,3)     : (mod)  : normal vectors for each node
71859599516SKenneth E. Jansenc  iBCB5 (nshg)       : (file) : wall flag for belt
71959599516SKenneth E. Jansenc  ienb  (numelb,nen) : (file) : connectivity for belts
72059599516SKenneth E. Jansenc
72159599516SKenneth E. Jansenc output:
72259599516SKenneth E. Jansenc  otwn  (nshg)       : (mod)  : off-the-wall nodes for each node
72359599516SKenneth E. Jansenc
72459599516SKenneth E. Jansenc
72559599516SKenneth E. Jansenc Kenneth Jansen, Summer 2000 (algorithm)
72659599516SKenneth E. Jansenc Michael Yaworski, Summer 2000 (code)
72759599516SKenneth E. Jansenc----------------------------------------------------------------------
72859599516SKenneth E. Jansenc
72959599516SKenneth E. Jansen      use pointer_data          ! used for mienb, miBCB
73059599516SKenneth E. Jansen      use turbSA
73159599516SKenneth E. Jansen      include "common.h"
73259599516SKenneth E. Jansenc
73359599516SKenneth E. Jansen      integer iel, nod, can
73459599516SKenneth E. Jansen      real*8 vec(3), leng, dp, bigdp, lil
73559599516SKenneth E. Jansen      real*8 x(numnp,nsd),BCtmp(nshg,ndof+7)
73659599516SKenneth E. Jansen      integer iBC(nshg), nsurf(nshg)
73759599516SKenneth E. Jansen      integer gbits
73859599516SKenneth E. Jansen      integer, allocatable :: ienb(:)
73959599516SKenneth E. Jansen
74059599516SKenneth E. Jansen      allocate( otwn(nshg) )
74159599516SKenneth E. Jansenc
74259599516SKenneth E. Jansenc initialize otwn to oneself
74359599516SKenneth E. Jansenc
74459599516SKenneth E. Jansen      do nod = 1, nshg
74559599516SKenneth E. Jansen         otwn(nod)=nod
74659599516SKenneth E. Jansen      enddo
74759599516SKenneth E. Jansenc
74859599516SKenneth E. Jansenc determine otwn for each wall node
74959599516SKenneth E. Jansenc
75059599516SKenneth E. Jansen      do iblk=1, nelblb         ! loop over boundary element blocks
75159599516SKenneth E. Jansen         npro = lcblkb(1,iblk+1)-lcblkb(1,iblk)
75259599516SKenneth E. Jansen         nenl  = lcblkb(5,iblk)
75359599516SKenneth E. Jansen         nenbl = lcblkb(6,iblk)
75459599516SKenneth E. Jansen         nshl = lcblkb(9,iblk)
75559599516SKenneth E. Jansen         allocate( ienb(nshl) )
75659599516SKenneth E. Jansen         do i = 1, npro         ! loop over boundary elements
75759599516SKenneth E. Jansen            iBCB1=miBCB(iblk)%p(i,1)
75859599516SKenneth E. Jansen            iBCB2=miBCB(iblk)%p(i,2)
75959599516SKenneth E. Jansen            ienb(1:nshl)=mienb(iblk)%p(i,1:nshl)
76059599516SKenneth E. Jansen            if (btest(iBCB1,4)) then ! (on the wall)
76159599516SKenneth E. Jansen               do nod = 1, nenbl !   for each wall node in this belt
76259599516SKenneth E. Jansen                  bigdp = zero  !     initialize largest dot product
76359599516SKenneth E. Jansen                  do can=nenbl+1,nenl !  loop over off-the-wall candidates
76459599516SKenneth E. Jansen                     nn=ienb(can)
76559599516SKenneth E. Jansen                               !       don't bother with wall nodes
76659599516SKenneth E. Jansen                     if(nsurf(nn).ne.0) cycle
76759599516SKenneth E. Jansen                               !       don't bother with no-slip nodes
76859599516SKenneth E. Jansen                     if(ibits(iBC(nn),3,3).eq.7 .and.
76959599516SKenneth E. Jansen     &                    BCtmp(nn,7).eq.zero) cycle
77059599516SKenneth E. Jansenc                              !       calculate candidate vector
77159599516SKenneth E. Jansen                     vec(:)=x(ienb(can),:)-x(ienb(nod),:)
77259599516SKenneth E. Jansen                     leng=sqrt(vec(1)**2+vec(2)**2+vec(3)**2)
77359599516SKenneth E. Jansen                     vec(:)=vec(:)/leng
77459599516SKenneth E. Jansenc                              !       calculate dot product with wnrm
77559599516SKenneth E. Jansen                     vec(:)=vec(:)*wnrm(ienb(nod),:)
77659599516SKenneth E. Jansen                     dp=vec(1)+vec(2)+vec(3)
77759599516SKenneth E. Jansenc                              !       set candidate as otwn if necessary
77859599516SKenneth E. Jansenc                              !       (wnrm points into fluid, so
77959599516SKenneth E. Jansenc                              !        we want the most positive dp)
78059599516SKenneth E. Jansen                     if (dp.gt.bigdp) then
78159599516SKenneth E. Jansen                        otwn(ienb(nod)) = ienb(can)
78259599516SKenneth E. Jansen                        bigdp=dp
78359599516SKenneth E. Jansen                     endif
78459599516SKenneth E. Jansen                  enddo         !(loop over off-the-wall candidates)
78559599516SKenneth E. Jansen               enddo            !(loop over wall nodes in current belt)
78659599516SKenneth E. Jansen            endif
78759599516SKenneth E. Jansen         enddo                  !(loop over elts in block)
78859599516SKenneth E. Jansen         deallocate(ienb)
78959599516SKenneth E. Jansen      enddo                     !(loop over boundary element blocks)
79059599516SKenneth E. Jansen      do nn = 1, nshg
79159599516SKenneth E. Jansen         if((otwn(nn).eq.nn).and.(nsurf(nn).ne.0)) then ! if a node on a
79259599516SKenneth E. Jansen                                                    ! modeled surface
79359599516SKenneth E. Jansen                                                    ! didn't find a node
79459599516SKenneth E. Jansen                                                    ! off the wall
79559599516SKenneth E. Jansen            lil = 1.0e32 ! distance to current closest prospect
79659599516SKenneth E. Jansen            do can = 1, nshg ! loop over nodes
79759599516SKenneth E. Jansen               if(nsurf(can).eq.0) then ! if this candidate is off the
79859599516SKenneth E. Jansen                                        ! wall
79959599516SKenneth E. Jansen                  if(ibits(iBC(can),3,3).eq.7 .and.
80059599516SKenneth E. Jansen     &               BCtmp(can,7).eq.zero) then  ! no slip nodes not allowed
80159599516SKenneth E. Jansen                  else          ! not a forbidden node
80259599516SKenneth E. Jansen                     vec(:)=x(nn,:)-x(can,:)
80359599516SKenneth E. Jansen                     leng=vec(1)**2+vec(2)**2+vec(3)**2
80459599516SKenneth E. Jansen                     if(leng.lt.lil) then ! this candidate is closest so far
80559599516SKenneth E. Jansen                        lil=leng
80659599516SKenneth E. Jansen                        otwn(nn)=can
80759599516SKenneth E. Jansen                     endif      ! closest so far
80859599516SKenneth E. Jansen                  endif  ! end of no slip nodes
80959599516SKenneth E. Jansen               endif ! off-the-wall check
81059599516SKenneth E. Jansen            enddo ! loop over nodes
81159599516SKenneth E. Jansen         endif ! lonely wall-node check
81259599516SKenneth E. Jansen      enddo ! loop over nodes
81359599516SKenneth E. Jansenc
81459599516SKenneth E. Jansen      return
81559599516SKenneth E. Jansenc
81659599516SKenneth E. Jansen      end
81759599516SKenneth E. Jansen
818