source: CIVL/mods/dev.civl.abc/examples/fevs/diffusion1d/diffusion1d_nb.c

main
Last change on this file was aad342c, checked in by Stephen Siegel <siegel@…>, 3 years ago

Performing huge refactor to incorporate ABC, GMC, and SARL into CIVL repo and use Java modules.

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

  • Property mode set to 100644
File size: 9.6 KB
RevLine 
[0966332]1/* FEVS: A Functional Equivalence Verification Suite for High-Performance
2 * Scientific Computing
3 *
[aad342c]4 * Copyright (C) 2010, Stephen F. Siegel, Timothy K. Zirkel,
[0966332]5 * University of Delaware
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License as
9 * published by the Free Software Foundation; either version 3 of the
10 * License, or (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
20 * 02110-1301 USA.
21 */
22
23
24/*
25 * diffusion1d.c: parallel 1d-diffusion simulation.
26 */
[aad342c]27
[0966332]28#include <stdlib.h>
29#include <stdio.h>
[aad342c]30#include <string.h>
[0966332]31#include <assert.h>
32#include <math.h>
33#include <mpi.h>
[aad342c]34#include "gd.h"
35#define MAXCOLORS 256
[0966332]36#define OWNER(index) ((nprocs*(index+1)-1)/nx)
[aad342c]37#define PWIDTH 1
38#define PHEIGHT 1
39#define M 10
[0966332]40
41/* Parameters: These are defined at the beginning of the input file:
42 *
43 * nx = number of points in x direction, including endpoints
44 * k = D*dt/(dx*dx)
45 * nsteps = number of time steps
46 * wstep = write frame every this many steps
47 *
48 * Compiling with the flag -DDEBUG will also cause the data to be written
49 * to a sequence of plain text files.
50 */
51
52/* Global variables */
53
54int nx = -1; /* number of discrete points including endpoints */
55double k = -1; /* D*dt/(dx*dx) */
56int nsteps = -1; /* number of time steps */
57int wstep = -1; /* write frame every this many time steps */
[aad342c]58double *u; /* temperature function */
59double *u_new; /* temp. used to update u */
60FILE *file; /* file containing animated GIF */
61gdImagePtr im, previm; /* pointers to GIF images */
62int *colors; /* colors we will use */
[0966332]63
64int nprocs; /* number of processes */
65int rank; /* the rank of this process */
66int left; /* rank of left neighbor */
67int right; /* rank of right neighbor on torus */
68int nxl; /* horizontal extent of one process */
69int first; /* global index for local index 0 */
70int start; /* first local index to update */
71int stop; /* last local index to update */
72double *buf; /* temp. buffer used on proc 0 only */
[aad342c]73MPI_Request requests[4]; /* for ghost cell exchange */
[0966332]74
75int firstForProc(int rank) {
76 return (rank*nx)/nprocs;
77}
78
79int countForProc(int rank) {
80 int a;
81 int b;
[aad342c]82
[0966332]83 a = firstForProc(rank+1);
84 b = firstForProc(rank);
85 return a-b;
86}
87
[aad342c]88void quit() {
[0966332]89 printf("Input file must have format:\n\n");
90 printf("nx = <INTEGER>\n");
91 printf("k = <DOUBLE>\n");
92 printf("nsteps = <INTEGER>\n");
93 printf("wstep = <INTEGER>\n");
94 printf("<DOUBLE> <DOUBLE> ...\n\n");
95 printf("where there are nx doubles at the end.\n");
96 fflush(stdout);
97 exit(1);
98}
99
100void readint(FILE *file, char *keyword, int *ptr) {
101 char buf[101];
102 int value;
103 int returnval;
104
105 returnval = fscanf(file, "%100s", buf);
[aad342c]106 if (returnval != 1) quit();
107 if (strcmp(keyword, buf) != 0) quit();
[0966332]108 returnval = fscanf(file, "%10s", buf);
[aad342c]109 if (returnval != 1) quit();
110 if (strcmp("=", buf) != 0) quit();
[0966332]111 returnval = fscanf(file, "%d", ptr);
[aad342c]112 if (returnval != 1) quit();
[0966332]113}
114
115void readdouble(FILE *file, char *keyword, double *ptr) {
116 char buf[101];
117 int value;
118 int returnval;
119
120 returnval = fscanf(file, "%100s", buf);
[aad342c]121 if (returnval != 1) quit();
122 if (strcmp(keyword, buf) != 0) quit();
[0966332]123 returnval = fscanf(file, "%10s", buf);
[aad342c]124 if (returnval != 1) quit();
125 if (strcmp("=", buf) != 0) quit();
[0966332]126 returnval = fscanf(file, "%lf", ptr);
[aad342c]127 if (returnval != 1) quit();
[0966332]128}
129
130/* init: initializes global variables. */
131void init(char* infilename) {
132 char keyword[101];
133 FILE *infile = fopen(infilename, "r");
[aad342c]134 int i,j;
[0966332]135
136 MPI_Comm_size(MPI_COMM_WORLD, &nprocs);
137 MPI_Comm_rank(MPI_COMM_WORLD, &rank);
138 if (rank == 0) {
[aad342c]139 assert(infile);
[0966332]140 readint(infile, "nx", &nx);
141 readdouble(infile, "k", &k);
142 readint(infile, "nsteps", &nsteps);
143 readint(infile, "wstep", &wstep);
144 printf("Diffusion1d with nx=%d, k=%f, nsteps=%d, wstep=%d nprocs=%d\n",
145 nx, k, nsteps, wstep, nprocs);
[aad342c]146 fflush(stdout);
[0966332]147 }
148 MPI_Bcast(&nx, 1, MPI_INT, 0, MPI_COMM_WORLD);
149 MPI_Bcast(&k, 1, MPI_DOUBLE, 0, MPI_COMM_WORLD);
150 MPI_Bcast(&nsteps, 1, MPI_INT, 0, MPI_COMM_WORLD);
151 MPI_Bcast(&wstep, 1, MPI_INT, 0, MPI_COMM_WORLD);
[aad342c]152
153 assert(nx>=nprocs); /* is this necessary ? */
[0966332]154 assert(k>0 && k<.5);
155 assert(nx>=2);
156 assert(nsteps>=1);
157 // nxl: number actual points (incl. end-points)
158 // nxl+2: size of array (incl. ghost cells)
159 first = firstForProc(rank);
160 nxl = countForProc(rank);
161 if (first == 0 || nxl == 0) left = MPI_PROC_NULL; else left = OWNER(first-1);
162 if (first+nxl >= nx || nxl == 0) right = MPI_PROC_NULL; else right = OWNER(first+nxl);
163 u = (double*)malloc((nxl+2)*sizeof(double));
[aad342c]164 assert(u);
[0966332]165 u_new = (double*)malloc((nxl+2)*sizeof(double));
166 assert(u_new);
167 if (rank == 0) {
168 buf = (double*)malloc((1+nx/nprocs)*sizeof(double));
169 for (i=1; i <= nxl; i++){
[aad342c]170 if (fscanf(infile, "%lf", u+i) != 1) quit();
[0966332]171 }
172 for (i=1; i < nprocs; i++){
173 for (j=0; j<countForProc(i); j++){
[aad342c]174 if (fscanf(infile, "%lf", buf+j) != 1) quit();
[0966332]175 }
[aad342c]176 MPI_Send(buf, countForProc(i), MPI_DOUBLE, i, 0, MPI_COMM_WORLD);
[0966332]177 }
178 }
179 else {
180 MPI_Recv(u+1, nxl, MPI_DOUBLE, 0, 0, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
181 }
182 if (rank == 0) {
183 buf = (double*)malloc((1+nx/nprocs)*sizeof(double));
184 assert(buf);
[aad342c]185 file = fopen("./nbout/out.gif", "wb");
186 assert(file);
187 colors = (int*)malloc(MAXCOLORS*sizeof(int));
188 assert(colors);
[0966332]189 } else {
190 buf = NULL;
191 }
192}
193
194void write_plain(int time) {
195 if (rank != 0) {
196 MPI_Send(u+1, nxl, MPI_DOUBLE, 0, 0, MPI_COMM_WORLD);
197 } else {
[aad342c]198 int source, i, count;
199 char filename[50];
200 FILE *plain = NULL;
[0966332]201 MPI_Status status;
202
[aad342c]203 sprintf(filename, "./nbout/out_%d", time);
204 plain = fopen(filename, "w");
205 assert(plain);
206 for (source = 0; source < nprocs; source++) {
207 if (source != 0) {
208 MPI_Recv(buf, 1+nx/nprocs, MPI_DOUBLE, source, 0, MPI_COMM_WORLD,
209 &status);
210 MPI_Get_count(&status, MPI_DOUBLE, &count);
211 } else {
212 for (i = 1; i <= nxl; i++) buf[i-1] = u[i];
213 count = nxl;
214 }
215 for (i = 0; i < count; i++) fprintf(plain, "%8.2f", buf[i]);
216 }
217 fprintf(plain, "\n");
218 fclose(plain);
219 }
220}
221
222void write_frame(int time) {
223 if (rank != 0) {
224 MPI_Send(u+1, nxl, MPI_DOUBLE, 0, 0, MPI_COMM_WORLD);
225 } else {
226 int source, i, j, count, global_index;
227 MPI_Status status;
228
229 im = gdImageCreate(nx*PWIDTH,PHEIGHT);
230 if (time == 0) {
231 for (j=0; j<MAXCOLORS; j++)
232 colors[j] = gdImageColorAllocate (im, j, 0, MAXCOLORS-j-1);
233 gdImageGifAnimBegin(im, file, 1, -1);
234 } else {
235 gdImagePaletteCopy(im, previm);
236 }
237 global_index = 0;
[0966332]238 for (source = 0; source < nprocs; source++) {
239 if (source != 0) {
240 MPI_Recv(buf, 1+nx/nprocs, MPI_DOUBLE, source, 0, MPI_COMM_WORLD,
241 &status);
242 MPI_Get_count(&status, MPI_DOUBLE, &count);
243 } else {
244 for (i = 1; i <= nxl; i++) buf[i-1] = u[i];
245 count = nxl;
246 }
247 for (i = 0; i < count; i++) {
[aad342c]248 int color = (int)(buf[i]*MAXCOLORS/M);
249
250 if (color < 0) {
251 printf("rank = %d, i = %d, buf[i] = %lf, color = %d, M = %d\n", rank, i, buf[i], color, M);
252 }
253 assert(color >= 0);
254 if (color >= MAXCOLORS) color = MAXCOLORS-1;
255 gdImageFilledRectangle
256 (im, global_index*PWIDTH, 0, (global_index+1)*PWIDTH-1,
257 PHEIGHT-1, colors[color]);
258 global_index++;
[0966332]259 }
260 }
[aad342c]261 if (time == 0) {
262 gdImageGifAnimAdd(im, file, 0, 0, 0, 0, gdDisposalNone, NULL);
263 } else {
264 gdImageGifAnimAdd(im, file, 0, 0, 0, 5, gdDisposalNone, previm);
265 gdImageDestroy(previm);
266 }
267 previm=im;
268 im=NULL;
[0966332]269 }
[aad342c]270#ifdef DEBUG
271 write_plain(time);
272#endif
[0966332]273}
274
275/* exchange_ghost_cells: updates ghost cells using MPI communication */
[aad342c]276void initiate_exchange() {
277 MPI_Isend(&u[1], 1, MPI_DOUBLE, left, 0, MPI_COMM_WORLD, &requests[0]);
278 MPI_Irecv(&u[nxl+1], 1, MPI_DOUBLE, right, 0, MPI_COMM_WORLD, &requests[1]);
279 MPI_Isend(&u[nxl], 1, MPI_DOUBLE, right, 0, MPI_COMM_WORLD, &requests[2]);
280 MPI_Irecv(&u[0], 1, MPI_DOUBLE, left, 0, MPI_COMM_WORLD, &requests[3]);
[0966332]281}
282
[aad342c]283void finalize_exchange() {
284 MPI_Waitall(4, requests, MPI_STATUSES_IGNORE);
285}
[0966332]286
[aad342c]287void update_interior() {
288 int i;
289
290 for (i = 2; i <= nxl-1; i++)
[0966332]291 u_new[i] = u[i] + k*(u[i+1] + u[i-1] -2*u[i]);
[aad342c]292 for (i = 3; i <= nxl-2; i++) u[i] = u_new[i];
293}
294
295void update_boundary() {
296 int i;
297
298 if (rank != OWNER(0))
299 u_new[1] = u[1]+k*(u[2] + u[0] - 2*u[1]);
300 if (rank != OWNER(nx-1))
301 u_new[nxl] = u[nxl]+k*(u[nxl+1] + u[nxl-1] - 2*u[nxl]);
302 if (rank != OWNER(0))
303 u[1] = u_new[1];
304 /* Can't update u[nxl-1] if nxl-1 is 1, or u[2] if nxl = 2 */
305 if (nxl - 1 > 1){
306 u[nxl-1] = u_new[nxl-1];
307 u[2] = u_new[2];
308 }
309 if (rank != OWNER(nx-1))
310 u[nxl] = u_new[nxl];
[0966332]311}
312
313/* main: executes simulation, creates one output file for each time
314 * step */
315int main(int argc,char *argv[]) {
316 int iter;
317
318 MPI_Init(&argc, &argv);
319 assert(argc==2);
320 init(argv[1]);
[aad342c]321 write_frame(0);
[0966332]322 for (iter = 1; iter <= nsteps; iter++) {
[aad342c]323 initiate_exchange(); /* post sends and recvs */
324 update_interior();
325 finalize_exchange(); /* wait on sends/recvs */
326 update_boundary(); /* positions 1,2,nxl-1,nxl */
327 if (iter%wstep==0) write_frame(iter);
[0966332]328 }
329 MPI_Finalize();
330 free(u);
331 free(u_new);
332 if (rank == 0) {
[aad342c]333 gdImageDestroy(previm);
334 gdImageGifAnimEnd(file);
335 fclose(file);
[0966332]336 free(buf);
[aad342c]337 free(colors);
[0966332]338 }
[46fedf0]339 return 0;
[0966332]340}
Note: See TracBrowser for help on using the repository browser.