      program cup1   !-------! MPI SAMPLE PROGRAM 1   (Section 16.1.2)
       implicit none
      include 'mpif.h'       ! This C-like inclusion is necessary
      INTEGER MY_ID, ierr, MASTER, NPROC,NLAST,NDIV, I,INFO,SN, N,
     +        status(MPI_STATUS_SIZE),K2,K1,K,REQUEST
      DOUBLE PRECISION SUM_all, TT1,TT2, WHO(2),WHO_ALL(2), SUM, SUM1
      CHARACTER*256 MY_NAME

      CALL MPI_INIT(ierr)                            ! Minimal CALL 1
      CALL MPI_COMM_RANK(MPI_COMM_WORLD, MY_ID,ierr) ! Minimal CALL 2
      CALL MPI_COMM_SIZE(MPI_COMM_WORLD, NPROC,ierr) ! Minimal CALL 3 
           NLAST = NPROC - 1 !  Proc ID for the last processor
           MASTER = 0        !  Master can be others say 1 if nproc>1 
      TT1 = MPI_WTIME()
C----------------------------!---------------------------------
      IF (MY_ID .EQ. 0) THEN ! Main Proc access the Screen ----
        PRINT*,'Type in N (the number of terms in the series)?'
ccccc   READ(*,*) N
        N = 80000000
        CALL MPI_GET_PROCESSOR_NAME(MY_NAME,ierr,INFO) 
	PRINT'(A,A)','=============cup1.f==========='
     +              ,'====cup1.f===================='
	PRINT*,'Number of processes started: ',NPROC
	PRINT*,'Main processor is: ID =',MY_ID,' on ', MY_NAME(1:13)
      ENDIF
      CALL MPI_barrier(MPI_COMM_WORLD, ierr)  ! Synchronize for N 
      IF (MY_ID .NE. 0) THEN ! Main Proc access the Screen ----
        CALL MPI_GET_PROCESSOR_NAME(my_name,ierr,INFO)
	PRINT*,'    and processor  ID =',MY_ID,' on ', MY_NAME(1:13)
      ENDIF 
c------------------------------------------------------------------
c Let other procs know about N (from the main MY_ID=0)
      CALL MPI_bcast(N,1,MPI_INTEGER, 0, MPI_COMM_WORLD, ierr)
      CALL MPI_barrier(MPI_COMM_WORLD, ierr)  ! Synchronize for N 
           NDIV = N / NPROC    ! Subtask for each processor
           K1 = MY_ID*NDIV+1   ! Start of series
           K2 = (MY_ID+1)*NDIV ! End of the series
      IF (NDIV*NPROC.LT.N .and. MY_ID.eq.NLAST) K2=N !Adjust the last subtask
           SN = -1  !! Sign for Even Terms or +1 for Odd terms
      IF (MOD((K1+1),2 ).eq.1 ) SN = 1  
c________________________________________Part 1
         SUM1 = 0.0D0
       DO K = K1+1, K2, 2
         SUM1 = SUM1 + SIN(DBLE(K))/DBLE(K)
       ENDDO
         SUM1 = SUM1*SN
           SN = -SN
c________________________________________Part 2 
          SUM = 0.0D0
       DO K = K1, K2, 2
          SUM = SUM + SIN(DBLE(K))/DBLE(K)
       ENDDO
          SUM = SUM1 + SUM*SN  !----------Partial Sum on Proc=My_ID Done

c----Collect all partial sums to get the answer on MASTER --------------
      CALL MPI_reduce(sum,sum_all,1,MPI_DOUBLE_PRECISION,
     +    MPI_SUM, MASTER, MPI_COMM_WORLD, ierr)  !---- SUM UP globally 
c__________________________________________STOP here to check CPU_______
      TT2 = MPI_WTIME() - TT1   !! Use reduce to compute max CPU

       who(1)=TT2
       who(2)=MY_ID
       CALL MPI_REDUCE(who,who_all,1,MPI_2DOUBLE_PRECISION,
     +   MPI_MAXLOC, MASTER, MPI_COMM_WORLD, ierr) 
       IF (MY_ID .EQ. MASTER) then
       WRITE(*,'(2X,''The series summing up to '',I9, '' terms ='',
     + G18.12)') N, sum_all
       WRITE(*,'(2X,''The Parallel CPU = '',G12.3,'' on Proc '',I2
     + '' [Method 1]'')') who_all(1),INT(who_all(2))
       ENDIF
c================================================================== END

c==================== Alternative if REDUCE is not used =========|----|
       IF (MY_ID .EQ. 0) then
         WRITE(*,'(/,2X,''The partial sum from P'',I2, '' is'',
     +   G12.3,'' using cpu:'',G10.2)') my_id,sum,TT2 
              TT1 = TT2
          SUM_All = SUM
       DO I = 1, NLAST
         call MPI_IRECV(TT2, 1, MPI_DOUBLE_PRECISION, MPI_ANY_SOURCE,
     +        I, MPI_COMM_WORLD, Request, ierr)
         call MPI_RECV(SUM, 1, MPI_DOUBLE_PRECISION, MPI_ANY_SOURCE,
     +        NPROC+I, MPI_COMM_WORLD, status, ierr)
         call MPI_WAIT(Request, status,ierr)
         TT1=MAX(TT1,TT2)
          SUM_All = SUM_All + SUM
         WRITE(*,'(2X,''The partial sum from P'',I2, '' is'',
     +   G12.3,'' using cpu:'',G10.2)') I,sum,TT2
       ENDDO

      WRITE(*,'(2X,''The series summing up to '',I9, '' terms ='',
     + G18.12,/,2X,''The Parallel CPU = '',G12.3, '' NPROC ='',I3,
     + '' [Method 2]'',/)') 
     + N, sum_all, TT1, NPROC
c---------------------------------
      ELSE ! MY_ID > 0 other procs
         call MPI_ISEND(TT2, 1, MPI_DOUBLE_PRECISION,MASTER,MY_ID,
     +        MPI_COMM_WORLD,Request, ierr)
         call MPI_SEND(SUM, 1, MPI_DOUBLE_PRECISION,MASTER,NPROC+my_id,
     +        MPI_COMM_WORLD, ierr)
         call MPI_WAIT(Request, status,ierr)
      ENDIF
c==================== Alternative if REDUCE is not used =========|----|
      CALL MPI_barrier(MPI_COMM_WORLD, ierr)  ! Synchronize for N 

      CALL MPI_FINALIZE(ierr)                         ! Minimal CALL 4
       STOP 
        END
