source: CIVL/examples/omp/heated_plate_openmp.c@ 139c8d5

1.23 2.0 acw/focus-triggers main test-branch
Last change on this file since 139c8d5 was feadd65, checked in by Matthew B. Dwyer <matthewbdwyer@…>, 11 years ago

git-svn-id: svn://vsl.cis.udel.edu/civl/trunk@1929 fb995dde-84ed-4084-dfe6-e5aef3e2452c

  • Property mode set to 100644
File size: 7.3 KB
Line 
1# include <stdlib.h>
2# include <stdio.h>
3# include <math.h>
4# include <omp.h>
5
6int main ( int argc, char *argv[] );
7
8/******************************************************************************/
9
10int main ( int argc, char *argv[] )
11
12/******************************************************************************/
13/*
14 Purpose:
15
16 MAIN is the main program for HEATED_PLATE_OPENMP.
17
18 Discussion:
19
20 This code solves the steady state heat equation on a rectangular region.
21
22 The sequential version of this program needs approximately
23 18/epsilon iterations to complete.
24
25
26 The physical region, and the boundary conditions, are suggested
27 by this diagram;
28
29 W = 0
30 +------------------+
31 | |
32 W = 100 | | W = 100
33 | |
34 +------------------+
35 W = 100
36
37 The region is covered with a grid of M by N nodes, and an N by N
38 array W is used to record the temperature. The correspondence between
39 array indices and locations in the region is suggested by giving the
40 indices of the four corners:
41
42 I = 0
43 [0][0]-------------[0][N-1]
44 | |
45 J = 0 | | J = N-1
46 | |
47 [M-1][0]-----------[M-1][N-1]
48 I = M-1
49
50 The steady state solution to the discrete heat equation satisfies the
51 following condition at an interior grid point:
52
53 W[Central] = (1/4) * ( W[North] + W[South] + W[East] + W[West] )
54
55 where "Central" is the index of the grid point, "North" is the index
56 of its immediate neighbor to the "north", and so on.
57
58 Given an approximate solution of the steady state heat equation, a
59 "better" solution is given by replacing each interior point by the
60 average of its 4 neighbors - in other words, by using the condition
61 as an ASSIGNMENT statement:
62
63 W[Central] <= (1/4) * ( W[North] + W[South] + W[East] + W[West] )
64
65 If this process is repeated often enough, the difference between successive
66 estimates of the solution will go to zero.
67
68 This program carries out such an iteration, using a tolerance specified by
69 the user, and writes the final estimate of the solution to a file that can
70 be used for graphic processing.
71
72 Licensing:
73
74 This code is distributed under the GNU LGPL license.
75
76 Modified:
77
78 18 October 2011
79
80 Author:
81
82 Original C version by Michael Quinn.
83 This C version by John Burkardt.
84
85 Reference:
86
87 Michael Quinn,
88 Parallel Programming in C with MPI and OpenMP,
89 McGraw-Hill, 2004,
90 ISBN13: 978-0071232654,
91 LC: QA76.73.C15.Q55.
92
93 Local parameters:
94
95 Local, double DIFF, the norm of the change in the solution from one iteration
96 to the next.
97
98 Local, double MEAN, the average of the boundary values, used to initialize
99 the values of the solution in the interior.
100
101 Local, double U[M][N], the solution at the previous iteration.
102
103 Local, double W[M][N], the solution computed at the latest iteration.
104*/
105{
106# define M 500
107# define N 500
108
109 double diff;
110 double epsilon = 0.001;
111 int i;
112 int iterations;
113 int iterations_print;
114 int j;
115 double mean;
116 double my_diff;
117 double u[M][N];
118 double w[M][N];
119 double wtime;
120
121 printf ( "\n" );
122 printf ( "HEATED_PLATE_OPENMP\n" );
123 printf ( " C/OpenMP version\n" );
124 printf ( " A program to solve for the steady state temperature distribution\n" );
125 printf ( " over a rectangular plate.\n" );
126 printf ( "\n" );
127 printf ( " Spatial grid of %d by %d points.\n", M, N );
128 printf ( " The iteration will be repeated until the change is <= %e\n", epsilon );
129 printf ( " Number of processors available = %d\n", omp_get_num_procs ( ) );
130 printf ( " Number of threads = %d\n", omp_get_max_threads ( ) );
131/*
132 Set the boundary values, which don't change.
133*/
134 mean = 0.0;
135
136#pragma omp parallel shared ( w ) private ( i, j )
137 {
138#pragma omp for
139 for ( i = 1; i < M - 1; i++ )
140 {
141 w[i][0] = 100.0;
142 }
143#pragma omp for
144 for ( i = 1; i < M - 1; i++ )
145 {
146 w[i][N-1] = 100.0;
147 }
148#pragma omp for
149 for ( j = 0; j < N; j++ )
150 {
151 w[M-1][j] = 100.0;
152 }
153#pragma omp for
154 for ( j = 0; j < N; j++ )
155 {
156 w[0][j] = 0.0;
157 }
158/*
159 Average the boundary values, to come up with a reasonable
160 initial value for the interior.
161*/
162#pragma omp for reduction ( + : mean )
163 for ( i = 1; i < M - 1; i++ )
164 {
165 mean = mean + w[i][0] + w[i][N-1];
166 }
167#pragma omp for reduction ( + : mean )
168 for ( j = 0; j < N; j++ )
169 {
170 mean = mean + w[M-1][j] + w[0][j];
171 }
172 }
173/*
174 OpenMP note:
175 You cannot normalize MEAN inside the parallel region. It
176 only gets its correct value once you leave the parallel region.
177 So we interrupt the parallel region, set MEAN, and go back in.
178*/
179 mean = mean / ( double ) ( 2 * M + 2 * N - 4 );
180 printf ( "\n" );
181 printf ( " MEAN = %f\n", mean );
182/*
183 Initialize the interior solution to the mean value.
184*/
185#pragma omp parallel shared ( mean, w ) private ( i, j )
186 {
187#pragma omp for
188 for ( i = 1; i < M - 1; i++ )
189 {
190 for ( j = 1; j < N - 1; j++ )
191 {
192 w[i][j] = mean;
193 }
194 }
195 }
196/*
197 iterate until the new solution W differs from the old solution U
198 by no more than EPSILON.
199*/
200 iterations = 0;
201 iterations_print = 1;
202 printf ( "\n" );
203 printf ( " Iteration Change\n" );
204 printf ( "\n" );
205 wtime = omp_get_wtime ( );
206
207 diff = epsilon;
208
209 while ( epsilon <= diff )
210 {
211# pragma omp parallel shared ( u, w ) private ( i, j )
212 {
213/*
214 Save the old solution in U.
215*/
216# pragma omp for
217 for ( i = 0; i < M; i++ )
218 {
219 for ( j = 0; j < N; j++ )
220 {
221 u[i][j] = w[i][j];
222 }
223 }
224/*
225 Determine the new estimate of the solution at the interior points.
226 The new solution W is the average of north, south, east and west neighbors.
227*/
228# pragma omp for
229 for ( i = 1; i < M - 1; i++ )
230 {
231 for ( j = 1; j < N - 1; j++ )
232 {
233 w[i][j] = ( u[i-1][j] + u[i+1][j] + u[i][j-1] + u[i][j+1] ) / 4.0;
234 }
235 }
236 }
237/*
238 C and C++ cannot compute a maximum as a reduction operation.
239
240 Therefore, we define a private variable MY_DIFF for each thread.
241 Once they have all computed their values, we use a CRITICAL section
242 to update DIFF.
243*/
244 diff = 0.0;
245# pragma omp parallel shared ( diff, u, w ) private ( i, j, my_diff )
246 {
247 my_diff = 0.0;
248# pragma omp for
249 for ( i = 1; i < M - 1; i++ )
250 {
251 for ( j = 1; j < N - 1; j++ )
252 {
253 if ( my_diff < fabs ( w[i][j] - u[i][j] ) )
254 {
255 my_diff = fabs ( w[i][j] - u[i][j] );
256 }
257 }
258 }
259# pragma omp critical
260 {
261 if ( diff < my_diff )
262 {
263 diff = my_diff;
264 }
265 }
266 }
267
268 iterations++;
269 if ( iterations == iterations_print )
270 {
271 printf ( " %8d %f\n", iterations, diff );
272 iterations_print = 2 * iterations_print;
273 }
274 }
275 wtime = omp_get_wtime ( ) - wtime;
276
277 printf ( "\n" );
278 printf ( " %8d %f\n", iterations, diff );
279 printf ( "\n" );
280 printf ( " Error tolerance achieved.\n" );
281 printf ( " Wallclock time = %f\n", wtime );
282/*
283 Terminate.
284*/
285 printf ( "\n" );
286 printf ( "HEATED_PLATE_OPENMP:\n" );
287 printf ( " Normal end of execution.\n" );
288
289 return 0;
290
291# undef M
292# undef N
293}
Note: See TracBrowser for help on using the repository browser.