C **********************************************************************
C
C               Example 4 : Omp_Sumof_Elements.f
C
C   Objective : Sum of 'n' elements of one-dimensional real array.
C               This example demonstrates the use of
C               OMP_GET_THREAD_NUM library call,
C               PARALLEL, DO directive, PRIVATE and SHARED clause and
C               CRITICAL section.
C
C   Input     : Size of an array
C
C   Output    : Sum of 'n' elements
C
C   Necessary Condition : Number of threads should be less than or 
C                         equal to number of processors of a SMP node
C
C **********************************************************************


       program SumOfElements
       integer SIZE
       parameter (SIZE=100)
       real Sum, LocalSum, CheckSum
       real Array(SIZE)
       integer ThreadID, ValidOutput

       integer OMP_GET_THREAD_NUM, ThreadID
       integer ArraySize

       print*,"Input the Size of Array"
       read(*,*) ArraySize
       if((ArraySize .le. 0) .or. (ArraySize .gt. SIZE)) then 
          print*,"Input is Wrong." 
          print*,"Please try with another number less than",SIZE+1
          print*,"Or greater than 0"
          goto 100
       endif

       Sum = 0.0
       do j = 1, ArraySize
         Array(j) = float(j)
       enddo

C$OMP PARALLEL PRIVATE(LocalSum, j) SHARED(Sum, Array)

       LocalSum = 0.0

C$OMP DO
       do j = 1, ArraySize
          LocalSum = LocalSum+Array(j)
       enddo

C$OMP CRITICAL
      Sum = Sum + LocalSum
C$OMP END CRITICAL

       ThreadID = OMP_GET_THREAD_NUM()
       if(ThreadID .eq. 0) then
          print *, 'Sum:  ', Sum
       endif

C$OMP END PARALLEL

       CheckSum = 0.0
       do j = 1, ArraySize
          CheckSum = CheckSum + Array(j)
       enddo

       if(CheckSum .ne. Sum) then
         ValidOutput = 0
       else
         ValidOutput = 1
       endif

       if(ValidOutput .eq. 1) then
         print*,"------ Correct Result -----"
       endif

100    end

