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