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

main test-branch
Last change on this file since beab7f2 was ea777aa, checked in by Alex Wilton <awilton@…>, 3 years ago

Moved examples, include, build_default.properties, common.xml, and README out from dev.civl.com into the root of the repo.

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

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