source: CIVL/examples/translation/mpi/wave1d.c@ 32172287

1.23 2.0 acw/focus-triggers main test-branch
Last change on this file since 32172287 was 52ed452, checked in by Ziqing Luo <ziqing@…>, 12 years ago

add a new example wave1d.c

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

  • Property mode set to 100644
File size: 7.6 KB
Line 
1#include <stdio.h>
2#include <stdlib.h>
3#include <string.h>
4#include <assert.h>
5#include <math.h>
6#include <mpi.h>
7
8#define SQR(x) ((x)*(x))
9/* MPI message tag */
10#define FROMLEFT 1
11#define FROMRIGHT 2
12#define DATAPASS 3
13
14/* Input parameters */
15#ifdef _CIVL
16
17const int NXB = 5;
18$input int nx; /* number of discrete points including endpoints */
19$assume 2 < nx && nx <= NXB; /* setting bounds */
20$input double c; /* physical constant to do with string */
21$assume c > 0.0;
22$input int height_init; /* max amplitude in initial state */
23$input int width_init; /* width of initial pulse */
24$assume 1 < width_init && width_init < nx;
25$assume width_init < nx;
26const int NSTEPSB = 5;
27$input int nsteps; /* number of iterations */
28$assume 0 < nsteps && nsteps <= NSTEPSB;
29const int wstep = 1;
30int _NPROCS_LOWER_BOUND = 1;
31int _NPROCS_UPPER_BOUND = 4;
32double oracle[nsteps][nx]; /* array stores the results of sequential run in every step */
33$input double u[nx]; /* arbitraty input data */
34
35#else
36
37int nx, height_init, width_init;
38int nsteps, wstep;
39double c;
40double * u;
41
42#endif
43
44/* Global varibales */
45double *u_prev, *u_curr, *u_next;
46double k;
47int nprocs, nxl, rank;
48int left, right; /* left neighbor and right neighbor */
49
50/* Returns the global index of the first cell owned
51 * by the process with given rank */
52int firstForProc(int rank) {
53 return (rank*nx)/nprocs;
54}
55
56/* Returns the number of cells
57 the given process owns */
58int countForProc(int rank) {
59 int a = firstForProc(rank);
60 int b = firstForProc(rank + 1);
61
62 return b - a;
63}
64
65/* Initialize data array for running in MPI */
66void init() {
67 int i;
68 double e = exp(1.0);
69
70 for(i = 0; i < nx; i++) {
71 if(i == 1 || i >= width_init)
72 u[i] = 0.0;
73 else
74 u[i] = height_init * e *
75 exp(-1.0/(1-SQR(2.0*(i-width_init/2.0)/width_init)));
76 }
77}
78
79/* Update cells owned by processes */
80void update() {
81 int i;
82 double *tmp;
83
84 for (i = 1; i < nxl + 1; i++){
85 u_next[i] = 2.0*u_curr[i] - u_prev[i] +
86 k*(u_curr[i+1] + u_curr[i-1] -2.0*u_curr[i]);
87 }
88 //cycle pointers
89 tmp = u_prev;
90 u_prev = u_curr;
91 u_curr = u_next;
92 u_next = tmp;
93}
94
95/* Initialization function, initializes all parameters and data array
96 process 0 is responsible run in sequential for computing data for
97 comparison */
98void initialization() {
99 int i, j;
100 int nxlLeft = 0;
101 int nxlRight = 0;
102 int neighborRank;
103
104#ifndef _CIVL
105
106 nx = 50;
107 c = 0.3;
108 height_init = 10;
109 width_init = 10;
110 nsteps = 500;
111 wstep = 5;
112 u = (double *)malloc(nx * sizeof(double));
113 init();
114#endif
115
116 printf("Wave1d with nx=%d, c=%f, height_init=%d, width_init=%d, \
117nsteps=%d, wstep=%d\n", nx, c, height_init, width_init, nsteps, wstep);
118 assert(nx >= 2);
119 assert(width_init < nx);
120 assert(c > 0);
121 assert(nsteps >= 1);
122 assert(wstep >= 1 && wstep <= nsteps);
123 k = c * c;
124
125#ifdef _CIVL
126
127 // If in CIVL verification mode and rank is 0,
128 // do a sequential run and store result in "oracle"
129 // for comparison later
130 if(rank == 0) {
131 double *seq_u_curr, *seq_u_prev, *seq_u_next;
132 double * tmp;
133
134 seq_u_prev = (double *)malloc((nx + 2) * sizeof(double));
135 assert(seq_u_prev);
136 seq_u_curr = (double *)malloc((nx + 2) * sizeof(double));
137 assert(seq_u_curr);
138 seq_u_next = (double *)malloc((nx + 2) * sizeof(double));
139 assert(seq_u_next);
140 //Initialize seq_u_curr and seq_u_prev
141 memcpy(&seq_u_curr[1], u, sizeof(double) * nx);
142 memcpy(&seq_u_prev[1], u, sizeof(double) * nx);
143 // run in sequential.
144 // wirte data in time 0.
145 for(i = 0; i < nx; i++)
146 oracle[0][i] = seq_u_curr[i + 1];
147 for(i = 1; i < nsteps; i++){
148 // exchange between head cell and tail cell.
149 seq_u_curr[0] = seq_u_curr[nx];
150 seq_u_curr[nx+1] = seq_u_curr[1];
151 // update
152 for (j = 1; j < nx + 1; j++){
153 seq_u_next[j] = 2.0*seq_u_curr[j] - seq_u_prev[j] +
154 k*(seq_u_curr[j+1] + seq_u_curr[j-1] -2.0*seq_u_curr[j]);
155 }
156 tmp = seq_u_prev;
157 seq_u_prev = seq_u_curr;
158 seq_u_curr = seq_u_next;
159 seq_u_next = tmp;
160 for(j = 0; j < nx; j++)
161 oracle[i][j] = seq_u_curr[j + 1];
162 }
163 free(seq_u_prev);
164 free(seq_u_curr);
165 free(seq_u_next);
166 }
167
168#endif
169
170 nxl = countForProc(rank);
171 u_prev = (double *)malloc((nxl + 2) * sizeof(double));
172 assert(u_prev);
173 u_curr = (double *)malloc((nxl + 2) * sizeof(double));
174 assert(u_curr);
175 u_next = (double *)malloc((nxl + 2) * sizeof(double));
176 assert(u_next);
177 // Skip processes with none assignment
178 neighborRank = rank;
179 while(nxlLeft == 0 && nxl != 0) {
180 neighborRank = neighborRank > 0 ? neighborRank-1 : nprocs - 1;
181 nxlLeft = countForProc(neighborRank);
182 }
183 left = neighborRank;
184 neighborRank = rank;
185 while(nxlRight == 0 && nxl != 0) {
186 neighborRank = neighborRank < nprocs - 1 ? neighborRank+1 : 0;
187 nxlRight = countForProc(neighborRank);
188 }
189 right = neighborRank;
190}
191
192/* Print out the value of data cells;
193 Do comparison in CIVL mode */
194void printData (int time, int first, int length, double * buf) {
195 int i;
196
197 for(i = 0; i < length; i++){
198 printf("u_curr[%d]=%8.8f ", first + i, buf[i]);
199#ifdef _CIVL
200
201 $assert (oracle[time][first + i] == buf[i]): \
202 "Error: disagreement at time %d position %d: saw %lf, expected %lf", \
203 time, first + i, buf[i], oracle[time][first + i];
204
205#endif
206 if(i%2 == 0) printf("\n");
207 }
208}
209
210/* receives data from other processes and wirte frames */
211void write_frame (int time, int * displs, int * counts) {
212 if(rank == 0) {
213 double buf[nx + 2];
214
215 printf("======= Time %d =======\n", time);
216 printData(time, displs[0], counts[0], &u_curr[1]);
217 for(int i=1; i < nprocs; i++) {
218 MPI_Recv(buf, counts[i], MPI_DOUBLE, i, DATAPASS, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
219 printData(time, displs[i], counts[i], buf);
220 }
221 printf("\n");
222 } else
223 MPI_Send(&u_curr[1], nxl, MPI_DOUBLE, 0, DATAPASS, MPI_COMM_WORLD);
224}
225
226/* Exchanging ghost cells */
227void communicate(){
228 MPI_Sendrecv(&u_curr[1], 1, MPI_DOUBLE, left, FROMRIGHT, &u_curr[nxl+1], 1, MPI_DOUBLE,
229 right, FROMRIGHT, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
230 MPI_Sendrecv(&u_curr[nxl], 1, MPI_DOUBLE, right, FROMLEFT, &u_curr[0], 1,
231 MPI_DOUBLE, left, FROMLEFT, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
232}
233
234int main(int argc, char * argv[]) {
235 int iter;
236 int * nxls; // array stores counts of data of all processes
237 int * displs; // array stores start points of data of all processes
238
239 // elaborate nx to concrete value...
240 for(int i=0; i<nx; i++);
241 MPI_Init(&argc, &argv);
242 MPI_Comm_rank(MPI_COMM_WORLD, &rank);
243 MPI_Comm_size(MPI_COMM_WORLD, &nprocs);
244 initialization();
245 displs = (int *)malloc(nprocs * sizeof(int));
246 assert(displs);
247 nxls = (int *)malloc(nprocs * sizeof(int));
248 assert(nxls);
249 if(rank == 0) {
250 for(int i=0; i < nprocs; i++) {
251 displs[i] = firstForProc(i);
252 nxls[i] = countForProc(i);
253 }
254 // Send every process their cells
255 for(int i=1; i < nprocs; i++) {
256 int first = displs[i];
257 int count = nxls[i];
258
259 MPI_Send(&u[first], count, MPI_DOUBLE, i, DATAPASS, MPI_COMM_WORLD);
260 }
261 memcpy(&u_prev[1], u, sizeof(double) * nxl);
262 memcpy(&u_curr[1], u, sizeof(double) * nxl);
263 } else {
264 MPI_Recv(&u_curr[1], nxl, MPI_DOUBLE, 0, DATAPASS, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
265 memcpy(&u_prev[1], &u_curr[1], sizeof(double) * nxl);
266 }
267 for(iter = 0; iter < nsteps; iter++) {
268 if(iter % wstep == 0)
269 write_frame(iter, displs, nxls);
270 communicate();
271 update();
272 }
273 free(u_curr);
274 free(u_prev);
275 free(u_next);
276 free(displs);
277 free(nxls);
278 MPI_Finalize();
279 return 0;
280}
Note: See TracBrowser for help on using the repository browser.