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