source: CIVL/examples/omp/heated_plate_openmp.c@ abb7e049

1.23 2.0 main test-branch
Last change on this file since abb7e049 was 1a98987, checked in by Matthew B. Dwyer <matthewbdwyer@…>, 11 years ago

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

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