159599516SKenneth E. Jansen subroutine commu (global, ilwork, n, code) 259599516SKenneth E. Jansenc--------------------------------------------------------------------- 359599516SKenneth E. Jansenc 459599516SKenneth E. Jansenc This subroutine is responsible for interprocessor communication of 559599516SKenneth E. Jansenc the residual and solution vectors. 659599516SKenneth E. Jansenc 759599516SKenneth E. Jansenc input: 859599516SKenneth E. Jansenc global(nshg,n): global vector to be communicated. Note that 959599516SKenneth E. Jansenc this vector is local to the processor, (i.e. 1059599516SKenneth E. Jansenc not distributed across processors) 1159599516SKenneth E. Jansenc ilwork(nlwork): this is the local interprocessor work array. 1259599516SKenneth E. Jansenc This array is local to the processor, (i.e. 1359599516SKenneth E. Jansenc each processor has a unique ilwork array. 1459599516SKenneth E. Jansenc n: second dimension of the array to be communicated 1559599516SKenneth E. Jansenc code: = 'in' for communicating with the residual 1659599516SKenneth E. Jansenc = 'out' for cummunicating the solution 1759599516SKenneth E. Jansenc 1859599516SKenneth E. Jansenc--------------------------------------------------------------------- 1959599516SKenneth E. Jansenc 2059599516SKenneth E. Jansenc The array ilwork describes the details of the communications. 2159599516SKenneth E. Jansenc Each communication step (call of this routine) consists of a 2259599516SKenneth E. Jansenc sequence of "tasks", where a task is defined as a communication 2359599516SKenneth E. Jansenc between two processors where data is exchanged. This would imply 2459599516SKenneth E. Jansenc that for a given processor, there will be as many tasks as there 2559599516SKenneth E. Jansenc are processors with which it must communicate. Details of the 2659599516SKenneth E. Jansenc ilwork array appear below. 2759599516SKenneth E. Jansenc 2859599516SKenneth E. Jansenc--------------------------------------------------------------------- 2959599516SKenneth E. Jansenc 3059599516SKenneth E. Jansen include "common.h" 3159599516SKenneth E. Jansen include "mpif.h" 3259599516SKenneth E. Jansen include "auxmpi.h" 3359599516SKenneth E. Jansen integer status(MPI_STATUS_SIZE), ierr 3459599516SKenneth E. Jansen integer stat(MPI_STATUS_SIZE, 2*maxtask), req(2*maxtask) 3559599516SKenneth E. Jansen real*8 rDelISend, rDelIRecv, rDelWaitAll 3659599516SKenneth E. Jansen 3759599516SKenneth E. Jansen dimension global(nshg,n), 3859599516SKenneth E. Jansen & rtemp(maxfront*n,maxtask), 3959599516SKenneth E. Jansen & ilwork(nlwork) 4059599516SKenneth E. Jansen 4159599516SKenneth E. Jansen character*3 code 4259599516SKenneth E. Jansen 4359599516SKenneth E. Jansen if(impistat2.eq.1) call MPI_BARRIER (MPI_COMM_WORLD, ierr) 4459599516SKenneth E. Jansen if(impistat.gt.0) rDelIRecv = zero 4559599516SKenneth E. Jansen if(impistat.gt.0) rDelISend = zero 4659599516SKenneth E. Jansen if(impistat.gt.0) rDelWaitAll = zero 4759599516SKenneth E. Jansen 48*9b8a2b53SCameron Smith if (code .ne. 'in ' .and. code .ne. 'out') then 49*9b8a2b53SCameron Smith if(myrank.eq.0) then 50*9b8a2b53SCameron Smith write(*,*) 'ERROR code != ''in '' || ''out''' 51*9b8a2b53SCameron Smith write(*,*) 'ERROR code =''', code,'''' 52*9b8a2b53SCameron Smith endif 53*9b8a2b53SCameron Smith call error ('commu ','code ',0) 54*9b8a2b53SCameron Smith endif 55*9b8a2b53SCameron Smith 5659599516SKenneth E. Jansen 5759599516SKenneth E. Jansen if (n .eq. 1) then ! like a scalar 5859599516SKenneth E. Jansen kdof = 1 5959599516SKenneth E. Jansen elseif (n .eq. nsd) then ! like the normal vectors 6059599516SKenneth E. Jansen kdof = 2 6159599516SKenneth E. Jansen elseif (n .eq. ndof) then ! res, y, ac, krylov vectors.... 6259599516SKenneth E. Jansen kdof = 3 6359599516SKenneth E. Jansen elseif (n .eq. nflow*nflow) then ! bdiag 6459599516SKenneth E. Jansen kdof = 4 6559599516SKenneth E. Jansen elseif (n .eq. (nflow-1)*nsd) then ! qres 6659599516SKenneth E. Jansen kdof = 5 6759599516SKenneth E. Jansen elseif (n .eq. nflow) then 6859599516SKenneth E. Jansen kdof = 6 6959599516SKenneth E. Jansen elseif (n .eq. 24 ) then 7059599516SKenneth E. Jansen kdof = 7 7159599516SKenneth E. Jansen elseif (n .eq. 9) then 7259599516SKenneth E. Jansen kdof = 8 7359599516SKenneth E. Jansen elseif (n .eq. 11 ) then 7459599516SKenneth E. Jansen kdof = 9 7559599516SKenneth E. Jansen elseif (n .eq. 7 ) then 7659599516SKenneth E. Jansen kdof = 10 7759599516SKenneth E. Jansen elseif (n .eq. 33 ) then 7859599516SKenneth E. Jansen kdof = 11 7959599516SKenneth E. Jansen elseif (n .eq. 22 ) then 8059599516SKenneth E. Jansen kdof = 12 8159599516SKenneth E. Jansen elseif (n .eq. 16 ) then 8259599516SKenneth E. Jansen kdof = 13 8359599516SKenneth E. Jansen elseif (n .eq. 10 ) then 8459599516SKenneth E. Jansen kdof = 14 8559599516SKenneth E. Jansen elseif (n .eq. nflow*nsd ) then !surface tension + qres 8659599516SKenneth E. Jansen kdof = 15 8759599516SKenneth E. Jansen else 8859599516SKenneth E. Jansen call error ('commu ','n ',n) 8959599516SKenneth E. Jansen endif 9059599516SKenneth E. Jansen 9159599516SKenneth E. Jansenc... Note that when adding another kdof to the above set, we must 9259599516SKenneth E. Jansenc... also make changes in ctypes.f and auxmpi.h 9359599516SKenneth E. Jansen 9459599516SKenneth E. Jansenc--------------------------------------------------------------------- 9559599516SKenneth E. Jansenc ilwork(1): number of tasks 9659599516SKenneth E. Jansenc 9759599516SKenneth E. Jansenc The following information is contained in ilwork for each task: 9859599516SKenneth E. Jansenc itag: tag of the communication 9959599516SKenneth E. Jansenc iacc: == 0 if task is a send 10059599516SKenneth E. Jansenc == 1 if task is a recieve 10159599516SKenneth E. Jansenc iother: rank of processor with which this communication occurs 10259599516SKenneth E. Jansenc numseg: number of data "segments" to be sent or recieved. A 10359599516SKenneth E. Jansenc segment is defined as a continuous section of the global 10459599516SKenneth E. Jansenc vector to be communicated, (i.e. a group of nodes (or, 10559599516SKenneth E. Jansenc rather, "shape function coefficients") which occur 10659599516SKenneth E. Jansenc sequentially in the array global(nshg,n)). 10759599516SKenneth E. Jansenc isbeg: location of the first segment in the array owned by the 10859599516SKenneth E. Jansenc current processor. 10959599516SKenneth E. Jansenc 11059599516SKenneth E. Jansenc The two types of communication are 'in', where the residual is being 11159599516SKenneth E. Jansenc communicated, and 'out', where the solution is being communicated. 11259599516SKenneth E. Jansenc Note that when the type is 'out', senders recieve and recievers send. 11359599516SKenneth E. Jansenc 11459599516SKenneth E. Jansenc The following comment pertains to a communication of type 'in': 11559599516SKenneth E. Jansenc 11659599516SKenneth E. Jansenc If the task is a send, then all of the numseg segments are 11759599516SKenneth E. Jansenc sent with a single call to MPI_SEND. Where these segments live in 11859599516SKenneth E. Jansenc the array is built into the array sevsegtype, which is a common 11959599516SKenneth E. Jansenc array constructed in the subroutine "ctypes.f". In other words, 12059599516SKenneth E. Jansenc sevsegtype is a data type that describes the indices of the blocks 12159599516SKenneth E. Jansenc to be sent, in terms of there beginning index, and the length of 12259599516SKenneth E. Jansenc each segment. Using this, we can make a single send to take care of 12359599516SKenneth E. Jansenc all the segments for this task. 12459599516SKenneth E. Jansenc 12559599516SKenneth E. Jansenc If the task is a recieve, then once the vector is recieved, the 12659599516SKenneth E. Jansenc recieved segments must be added to the correct locations in the 12759599516SKenneth E. Jansenc current array. These locations are described in ilwork as the 12859599516SKenneth E. Jansenc beginning position, then the length of the segment. 12959599516SKenneth E. Jansenc 13059599516SKenneth E. Jansenc--------------------------------------------------------------------- 13159599516SKenneth E. Jansen numtask = ilwork(1) 13259599516SKenneth E. Jansen 13359599516SKenneth E. Jansen itkbeg = 1 13459599516SKenneth E. Jansen m = 0 13559599516SKenneth E. Jansen idl=0 13659599516SKenneth E. Jansen 13759599516SKenneth E. Jansen DO itask = 1, numtask 13859599516SKenneth E. Jansen m = m + 1 13959599516SKenneth E. Jansen itag = ilwork (itkbeg + 1) 14059599516SKenneth E. Jansen iacc = ilwork (itkbeg + 2) 14159599516SKenneth E. Jansen iother = ilwork (itkbeg + 3) 14259599516SKenneth E. Jansen numseg = ilwork (itkbeg + 4) 14359599516SKenneth E. Jansen isgbeg = ilwork (itkbeg + 5) 14459599516SKenneth E. Jansenc 14559599516SKenneth E. Jansenc.... if iacc == 0, then this task is a send. 14659599516SKenneth E. Jansenc slave 14759599516SKenneth E. Jansenc 14859599516SKenneth E. Jansen if (iacc .EQ. 0) then 14959599516SKenneth E. Jansenc 15059599516SKenneth E. Jansenc.... residual communication 15159599516SKenneth E. Jansenc 15259599516SKenneth E. Jansen if (code .eq. 'in ') then 15359599516SKenneth E. Jansen if(impistat.eq.1) then 15459599516SKenneth E. Jansen iISend = iISend+1 15559599516SKenneth E. Jansen elseif(impistat.eq.2) then 15659599516SKenneth E. Jansen iISendScal = iISendScal+1 15759599516SKenneth E. Jansen endif 15859599516SKenneth E. Jansen if(impistat.gt.0) rmpitmr = TMRC() 15959599516SKenneth E. Jansen call MPI_ISEND(global(isgbeg, 1), 1, sevsegtype(itask,kdof), 16059599516SKenneth E. Jansen & iother, itag, MPI_COMM_WORLD, req(m), ierr) 16159599516SKenneth E. Jansen if(impistat.gt.0) rDelISend = TMRC()-rmpitmr 16259599516SKenneth E. Jansen if(impistat.eq.1) then 16359599516SKenneth E. Jansen rISend = rISend+rDelISend 16459599516SKenneth E. Jansen elseif(impistat.eq.2) then 16559599516SKenneth E. Jansen rISendScal = rISendScal+rDelISend 16659599516SKenneth E. Jansen endif 16759599516SKenneth E. Jansen endif 16859599516SKenneth E. Jansenc 16959599516SKenneth E. Jansenc.... solution communication 17059599516SKenneth E. Jansenc 17159599516SKenneth E. Jansen if (code .eq. 'out') then 17259599516SKenneth E. Jansen if(impistat.eq.1) then 17359599516SKenneth E. Jansen iIRecv = iIRecv+1 17459599516SKenneth E. Jansen elseif(impistat.eq.2) then 17559599516SKenneth E. Jansen iIRecvScal = iIRecvScal+1 17659599516SKenneth E. Jansen endif 17759599516SKenneth E. Jansen if(impistat.gt.0) rmpitmr = TMRC() 17859599516SKenneth E. Jansen call MPI_IRECV(global(isgbeg, 1), 1, sevsegtype(itask,kdof), 17959599516SKenneth E. Jansen & iother, itag, MPI_COMM_WORLD, req(m), ierr) 18059599516SKenneth E. Jansen if(impistat.gt.0) rDelIRecv = TMRC()-rmpitmr 18159599516SKenneth E. Jansen if(impistat.eq.1) then 18259599516SKenneth E. Jansen rIRecv = rIRecv+rDelIRecv 18359599516SKenneth E. Jansen elseif(impistat.eq.2) then 18459599516SKenneth E. Jansen rIRecvScal = rIRecvScal+rDelIRecv 18559599516SKenneth E. Jansen endif 18659599516SKenneth E. Jansen endif 18759599516SKenneth E. Jansenc 18859599516SKenneth E. Jansenc.... if iacc == 1, then this task is a recieve. 18959599516SKenneth E. Jansenc master 19059599516SKenneth E. Jansenc 19159599516SKenneth E. Jansen else 19259599516SKenneth E. Jansen if (code .eq. 'in ') then 19359599516SKenneth E. Jansenc 19459599516SKenneth E. Jansenc.... determine the number of total number of nodes involved in this 19559599516SKenneth E. Jansenc communication (lfront), including all segments 19659599516SKenneth E. Jansenc 19759599516SKenneth E. Jansen lfront = 0 19859599516SKenneth E. Jansen do is = 1,numseg 19959599516SKenneth E. Jansen lenseg = ilwork (itkbeg + 4 + 2*is) 20059599516SKenneth E. Jansen lfront = lfront + lenseg 20159599516SKenneth E. Jansen enddo 20259599516SKenneth E. Jansenc 20359599516SKenneth E. Jansenc.... recieve all segments for this task in a single step 20459599516SKenneth E. Jansenc 20559599516SKenneth E. Jansen idl=idl+1 ! stands for i Do Later, the number to fix later 20659599516SKenneth E. Jansen if(impistat.eq.1) then 20759599516SKenneth E. Jansen iIRecv = iIRecv+1 20859599516SKenneth E. Jansen elseif(impistat.eq.2) then 20959599516SKenneth E. Jansen iIRecvScal = iIRecvScal+1 21059599516SKenneth E. Jansen endif 21159599516SKenneth E. Jansen if(impistat.gt.0) rmpitmr = TMRC() 21259599516SKenneth E. Jansen call MPI_IRECV(rtemp(1,idl), lfront*n, MPI_DOUBLE_PRECISION, 21359599516SKenneth E. Jansen & iother, itag, MPI_COMM_WORLD, req(m), ierr) 21459599516SKenneth E. Jansen if(impistat.gt.0) rDelIRecv = TMRC()-rmpitmr 21559599516SKenneth E. Jansen if(impistat.eq.1) then 21659599516SKenneth E. Jansen rIRecv = rIRecv+rDelIRecv 21759599516SKenneth E. Jansen elseif(impistat.eq.2) then 21859599516SKenneth E. Jansen rIRecvScal = rIRecvScal+rDelIRecv 21959599516SKenneth E. Jansen endif 22059599516SKenneth E. Jansen endif 22159599516SKenneth E. Jansen if (code .eq. 'out') then 22259599516SKenneth E. Jansen if(impistat.eq.1) then 22359599516SKenneth E. Jansen iISend = iISend+1 22459599516SKenneth E. Jansen elseif(impistat.eq.2) then 22559599516SKenneth E. Jansen iISendScal = iISendScal+1 22659599516SKenneth E. Jansen endif 22759599516SKenneth E. Jansen if(impistat.gt.0) rmpitmr = TMRC() 22859599516SKenneth E. Jansen call MPI_ISEND(global(isgbeg, 1), 1, sevsegtype(itask,kdof), 22959599516SKenneth E. Jansen & iother, itag, MPI_COMM_WORLD, req(m), ierr) 23059599516SKenneth E. Jansen if(impistat.gt.0) rDelISend = TMRC()-rmpitmr 23159599516SKenneth E. Jansen if(impistat.eq.1) then 23259599516SKenneth E. Jansen rISend = rISend+rDelISend 23359599516SKenneth E. Jansen elseif(impistat.eq.2) then 23459599516SKenneth E. Jansen rISendScal = rISendScal+rDelISend 23559599516SKenneth E. Jansen endif 23659599516SKenneth E. Jansen endif 23759599516SKenneth E. Jansen endif 23859599516SKenneth E. Jansen 23959599516SKenneth E. Jansen itkbeg = itkbeg + 4 + 2*numseg 24059599516SKenneth E. Jansen 24159599516SKenneth E. Jansen enddo !! end tasks loop 24259599516SKenneth E. Jansen 24359599516SKenneth E. Jansen if(impistat.eq.1) then 24459599516SKenneth E. Jansen iWaitAll = iWaitAll+1 24559599516SKenneth E. Jansen elseif(impistat.eq.2) then 24659599516SKenneth E. Jansen iWaitAllScal = iWaitAllScal+1 24759599516SKenneth E. Jansen endif 24859599516SKenneth E. Jansen if(impistat.gt.0) rmpitmr = TMRC() 24959599516SKenneth E. Jansen call MPI_WAITALL(m, req, stat, ierr) 25059599516SKenneth E. Jansen if(impistat.gt.0) rDelWaitAll = TMRC()-rmpitmr 25159599516SKenneth E. Jansen if(impistat.eq.1) then 25259599516SKenneth E. Jansen rWaitAll = rWaitAll+rDelWaitAll 25359599516SKenneth E. Jansen rCommu = rCommu+rDelIRecv+rDelISend+rDelWaitAll 25459599516SKenneth E. Jansen elseif(impistat.eq.2) then 25559599516SKenneth E. Jansen rWaitAllScal = rWaitAllScal+rDelWaitAll 25659599516SKenneth E. Jansen rCommuScal = rCommuScal+rDelIRecv+rDelISend+rDelWaitAll 25759599516SKenneth E. Jansen endif 25859599516SKenneth E. Jansen 25959599516SKenneth E. Jansenc 26059599516SKenneth E. Jansenc Stuff added below is a delayed assembly of that which was communicated 26159599516SKenneth E. Jansenc above but due to the switch to non-blocking receivves could not be 26259599516SKenneth E. Jansenc assembled until after the waitall. Only necessary for commu "in" 26359599516SKenneth E. Jansenc 26459599516SKenneth E. Jansen 26559599516SKenneth E. Jansen if(code .eq. 'in ') then 26659599516SKenneth E. Jansen itkbeg=1 26759599516SKenneth E. Jansen jdl=0 26859599516SKenneth E. Jansen do j=1,numtask ! time to do all the segments that needed to be 26959599516SKenneth E. Jansen ! assembled into the global vector 27059599516SKenneth E. Jansen 27159599516SKenneth E. Jansen iacc = ilwork (itkbeg + 2) 27259599516SKenneth E. Jansen numseg = ilwork (itkbeg + 4) 27359599516SKenneth E. Jansen isgbeg = ilwork (itkbeg + 5) 27459599516SKenneth E. Jansen if(iacc.eq.1) then 27559599516SKenneth E. Jansen jdl=jdl+1 ! keep track of order of rtemp's 27659599516SKenneth E. Jansenc 27759599516SKenneth E. Jansenc... add the recieved data to the global array on the current processor. 27859599516SKenneth E. Jansenc Note that this involves splitting up the chunk of recieved data 27959599516SKenneth E. Jansenc into its correct segment locations for the current processor. 28059599516SKenneth E. Jansenc 28159599516SKenneth E. Jansen itemp = 1 28259599516SKenneth E. Jansen do idof = 1,n 28359599516SKenneth E. Jansen do is = 1,numseg 28459599516SKenneth E. Jansen isgbeg = ilwork (itkbeg + 3 + 2*is) 28559599516SKenneth E. Jansen lenseg = ilwork (itkbeg + 4 + 2*is) 28659599516SKenneth E. Jansen isgend = isgbeg + lenseg - 1 28759599516SKenneth E. Jansen global(isgbeg:isgend,idof) = global(isgbeg:isgend,idof) 28859599516SKenneth E. Jansen & + rtemp (itemp:itemp+lenseg-1,jdl) 28959599516SKenneth E. Jansen itemp = itemp + lenseg 29059599516SKenneth E. Jansen enddo 29159599516SKenneth E. Jansen enddo 29259599516SKenneth E. Jansen endif ! end of receive (iacc=1) 29359599516SKenneth E. Jansen itkbeg = itkbeg + 4 + 2*numseg 29459599516SKenneth E. Jansen enddo 29559599516SKenneth E. Jansen endif ! commu "in" 29659599516SKenneth E. Jansen return 29759599516SKenneth E. Jansen end 29859599516SKenneth E. Jansen 29959599516SKenneth E. Jansen 30059599516SKenneth E. Jansen 301