1 !Parallel_Trapezoid.
f90 -- Parallel Trapezoidal Rule, first version
2 ! Input: None.
3 ! Output: Estimate of the integral from a to b of f(x)
4 ! using the trapezoidal rule and n trapezoids.
5 ! Algorithm:
6 ! 1. Each process calculates "its" interval of integration.
7 ! 2. Each process estimates the integral of f(x)
8 ! over its interval using the trapezoidal rule.
9 ! 3a. Each process != 0 sends its integral to 0.
10 ! 3b. Process 0 sums the calculations received from
11 ! the individual processes and prints the result.
12 ! Modification: Program changed from original form to Fortran90
13 ! Additionally, the distribution of task among
14 ! processors changed.
15 ! Date: 05/09 ! Modification By: Carlos Andrés Acosta Berlinghieri
16 PROGRAM Parallel_Trapezoid
17 IMPLICIT NONE
18 include 'mpif.h'
19 integer my_rank ! My process rank.
20 integer p ! The number of processes.
21 real a ! Left endpoint.
22 real b ! Right endpoint.
23 integer n ! Number of trapezoids.
24 real h ! Trapezoid base length.
25 real local_a ! Left end point for my process.
26 real local_b ! Right endpoint my process.
27 integer local_n ! Number of trapezoids for my calculation.
28 real integral ! Integral over my interval.
29 real total ! Total integral.
30 integer source ! Process sending integral.
31 integer dest ! ID to send messages.
32 integer tag
33 integer status(MPI_STATUS_SIZE)
34 integer iproc, interval
35 integer ierr ! MPI error indicator
36 integer num_local
37 real Trap
38 data a, b, n, dest, tag /0.0, 1.0, 1000, 0, 50/ !Range,
39 !elements and destination to processors ID.
40 integer, allocatable :: ibegin(:), iend(:)
41 ! Let the system do what it needs to start up MPI.
42 CALL MPI_INIT(ierr) !Check MPI initialization errors
43 ! Get my process rank.
44 CALL MPI_COMM_RANK(MPI_COMM_WORLD, my_rank, ierr)
45 ! Find out how many processes are being used.
46 CALL MPI_COMM_SIZE(MPI_COMM_WORLD, p, ierr)
47 h = (b-a)/n ! h is the same for all processes.
48 local_n = n/p ! So is the number of trapezoids.
49 IF(my_rank == 0) THEN
50 interval = n/p
51 allocate(ibegin(p)) !Distribution of elements among processors
52 allocate(iend(p))
79
53
54 DO iproc = 1, p
55 ibegin(iproc) = (iproc-1)*interval + 1
56 iend (iproc) = ibegin(iproc) + interval – 1
57 END DO
58 write(*,'(a,i8)') ' ==> Elements= ', n
59 write(*,*) ' ==> This is the distribution'
60
61 DO iproc=1, p
62 write(*,'(a,i4,a,i5,1x,i5)') ' ==> Task ',iproc,':
63 Range= ',ibegin(iproc),iend(iproc)
64 END DO
65 ! Length of each process' interval of integration =local_n*h. So my interval
66 ! starts at:
67 local_a = a + my_rank*local_n*h
68 local_b = local_a + local_n*h
69 integral = Trap(local_a, local_b, local_n, h)
70 ! Add up the integals calculated by each process.
71 IF (my_rank .EQ. 0) THEN
72 total = integral
73 DO source = 1, p-1
74 CALL MPI_RECV(integral, 1, MPI_REAL, source, tag,
75 MPI_COMM_WORLD, status, ierr)
76 total = total + integral
77 END DO
78 CALL MPI_SEND(integral, 1, MPI_REAL, dest, tag, MPI_COMM_WORLD,ierr)
79 ENDIF
80 ¡Print the result.
81 IF (my_rank .EQ. 0) THEN
82 write(6,200) n
83 format(' ','With n = ',I4,' trapezoids, our estimate')
84 write(6,300) a, b, total
85 format(' ','of the integral from ',f6.2,' to ',f6.2,' = 97 ',f11.5)
86 ENDIF
87 ! Shut down MPI.
88 CALL MPI_FINALIZE(ierr)
89 END PROGRAM Parallel_Trapezoid
90 !Function Trap
91 real function Trap(local_a, local_b, local_n, h)
92 IMPLICIT NONE
93 real local_a, local_b
94 integer local_n
95 real integral ! Store result in integral.
96 real x, i, f, h
97 integral = (f(local_a) + f(local_b))/2.0
98 x = local_a
99 DO i = 1, local_n – 1
100 x = x + h
101 integral = integral + f(x)
102 ENDDO
103 integral = integral*h
104 Trap = integral
105 Return
106 End
107 real function f(x)
108 IMPLICIT NONE
109 real x
110 f = x*x