PI calculation

The example approximates PI using numerical integration.

The source code is shown below:

!******************************************************************************
!    PI Calc example:
!    
!    In this example PI approximated using numerical integration. By dividing 
!    the interval [0..1] on the x-axis into n slices and calculating the area 
!    of the unit circle (radius = 1) in the first quadrant, the approximation 
!    is computed. The computation is distributed by letting each of the m MPI 
!    processes compute n/m slices.
!    
!    More specifically:
!   --------------------------------
!    - User is prompted for n (nIntervals) by the Master (rank 0)
!    - The Master sends n to the Slaves.
!    - Each process computes its slice and sends the result to the Master
!    - The Master collects the result and write the PI approximation to stdout.
!   --------------------------------
!
!    Copyright 2002 (c) Critical Software SA
!    . http://www.criticalsoftware.com
!    . http://www.criticalsoftware.com/hpc
!    . csWMPI@criticalsoftware.com
!******************************************************************************

      include "mpi_init.f"

!******************************************************************************
!    This function computes an interval for a single process.
!******************************************************************************
      subroutine ComputeInterval(n_my_rank,n_comm_size,n_intervals,
     +                              r_dPi)
      implicit none
      integer n_my_rank, n_comm_size, n_intervals
      real r_dPi,dWidth, dX, dLocalSum
      integer  nCounter

      dWidth = 1.0 / n_intervals
      dLocalSum = 0.0

      do nCounter=1,n_intervals,n_comm_size
            dX = (nCounter + 0.5) * dWidth
            dLocalSum = dLocalSum + (4 / (1 + (dX * dX)))
      enddo

      r_dPi = (dLocalSum * dWidth)

      end !subroutine ComputeInterval

!     Main program
      program main
      implicit none
      include "mpif.h"

      integer nCommRank, nCommSize, ierr, nIntervals, i, master
      real dPi, dIntervalArea

      master = 0

!     Initialize csWMPI II:
      call MPI_INIT(ierr)

!     Determine what the world looks like and our own position in it:
      call MPI_COMM_RANK(MPI_COMM_WORLD, nCommRank, ierr)
      call MPI_COMM_SIZE(MPI_COMM_WORLD, nCommSize, ierr)

      print *, 'I am rank',nCommRank,' of ',nCommSize,
     +         ' in MPI_COMM_WORLD'

!     If I am the Master (rank 0) then prompt the user for the number of
!     intervals to compute and send it to the Slaves.
      if ( nCommRank .eq. master ) then
            print *,'Calculation of PI by Numerical Integration'
            print *,'Input of intervals: '
            read  *, nIntervals
            print *,'Master: Sending # of intervals to MPI-Processes '
            do i=1,nCommSize-1 !Send for all the number of intervals 
                  call MPI_SEND(nintervals, 1, MPI_INTEGER, 
     +                  i,0,MPI_COMM_WORLD,ierr)
            enddo
      else
!     If I am a Slave just wait for the Master to tell me how many      
!     intervals we are going compute:
            call MPI_RECV(nintervals, 1, MPI_INTEGER, master, 0,
     +            MPI_COMM_WORLD, MPI_STATUS_IGNORE,ierr)
      endif
!     Compute my contribution:
      call ComputeInterval(nCommRank,nCommSize,nintervals,
     +                     dIntervalArea)

!     If I am the Master, I should collect results, compute the sum, and    
!     display the result:
      if ( nCommRank .eq. master ) then !recolher os resultados
            dPi = dIntervalArea
            do i=1,nCommSize-1
                  call MPI_RECV(dIntervalArea, 1, MPI_REAL,
     +                  MPI_ANY_SOURCE,0, MPI_COMM_WORLD, 
     +                  MPI_STATUS_IGNORE, ierr)
                  dPi = dPi + dIntervalArea
            enddo

            print *,'Master: Has collected results from MPI processes '
            print *,'PI approximation:',dPi
      else
!     If I am a Slave send my result to the Master                      
            print *,'Slave: Sending my contribution to Master'
            call MPI_SEND(dIntervalArea, 1, MPI_REAL, master, 0,
     +                  MPI_COMM_WORLD,ierr)
      end if

      call MPI_FINALIZE(ierr)

!     Pause rank 0 so that the output can be verified:
      if (nCommRank .eq. master) then
            pause 'Press ENTER to exit...'
      end if
      stop
      end



© 2009 Critical Software SA. All trademarks and copyrights on this page are owned by their respective owners.
cscsWMPI II™, cscsWMPI™ and PatentMPI™ are trademarks of Critical Software SA. All Rights Reserved.