xref: /phasta/phSolver/common/commu.f (revision 9b8a2b5301dae5602a16bed4b9abe8b4e50204bd)
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