c**********************************************************************
c     This program calculates the value of pi, using numerical integration
c     with parallel processing.  The user selects the number of points of
c     integration.  By selecting more points you get more accurate results
c     at the expense of additional computation
c     
c     This version is written using p4 calls to handle message passing
c     It should run without changes on most workstation clusters and MPPs.
c     
c     Each node: 
c     1) receives the number of rectangles used in the approximation.
c     2) calculates the areas of it's rectangles.
c     3) Synchronizes for a global summation.
c     Node 0 prints the result.
c     
c     Constants:
c     
c     SIZETYPE    initial message to the cube
c     ALLNODES    used to load all nodes in cube with a node process
c     INTSIZ      four bytes for an integer
c     DBLSIZ      eight bytes for double precision
c     
c     Variables:
c     
c     pi  the calculated result
c     n   number of points of integration.  
c     x           midpoint of each rectangle's interval
c     f           function to integrate
c     sum,pi      area of rectangles
c     tmp         temporary scratch space for global summation
c     i           do loop index
c****************************************************************************
      integer function worker( argc, argv )
      integer argc
      integer argv

      include "mpif.h"

      double precision  PI25DT
      parameter        (PI25DT = 3.141592653589793238462643d0)

      integer   INTSIZ , DBLSIZ,  ALLNODES,   ANYNODE
      parameter(INTSIZ=4,DBLSIZ=8,ALLNODES=-1,ANYNODE=-1)

      double precision  pi, h, sum, x, f, a, temp
      integer n, myid, numnodes, i, rc
      integer sumtype, sizetype, masternode
      integer status(3)

c     function to integrate
      f(a) = 4.d0 / (1.d0 + a*a)

      call MPI_INIT( ierr )
      call MPI_COMM_RANK( MPI_COMM_WORLD, myid, ierr )
      call MPI_COMM_SIZE( MPI_COMM_WORLD, numnodes, ierr )
c     print *, "Process ", myid, " of ", numnodes, " is alive"

      sizetype   = 10
      sumtype    = 17
      masternode =  0
      
 10   if ( myid .eq. 0 ) then

         write(6,98)
 98      format('Enter the number of intervals: (0 quits)')
         read(5,99)n
 99      format(i10)

         do i=1,numnodes-1
            call MPI_SEND(n,1,MPI_INTEGER,i,sizetype,MPI_COMM_WORLD,rc)
         enddo

      else
         
         call MPI_RECV(n,1,MPI_INTEGER,masternode,sizetype,
     +        MPI_COMM_WORLD,status,rc)

      endif

c     check for quit signal
      if ( n .le. 0 ) goto 30

c     calculate the interval size
      h = 1.0d0/n

      sum  = 0.0d0
      do 20 i = myid+1, n, numnodes
         x = h * (dble(i) - 0.5d0)
         sum = sum + f(x)
 20   continue
      pi = h * sum

c     collect all the partial sums
c     call p4globop(SUMTYPE,pi,1,DBLSIZ,p4dblsumop,P4DBL,rc)

      if (myid .ne. 0) then

         call MPI_SEND(pi,1,MPI_DOUBLE_PRECISION,masternode,sumtype,
     +        MPI_COMM_WORLD,rc)

      else

         do i=1,numnodes-1
            call MPI_RECV(temp,1,MPI_DOUBLE_PRECISION,i,sumtype,
     +           MPI_COMM_WORLD,status,rc)
            pi = pi + temp
         enddo
      endif

c     node 0 prints the answer.
      if (myid .eq. 0) then
         write(6, 97) pi, abs(pi - PI25DT)
 97      format('  pi is approximately: ', F18.16,
     +        '  Error is: ', F18.16)
      endif

      goto 10

 30   call MPI_FINALIZE(rc)
      return
      end




