/* Composite model of sequential and parallel 1d-diffusion solvers. * Compares the results of the sequential and parallel computation to * determine functional equivalence of the two versions. * * The initial values are taken as inputs. The two global boundary * points are fixed. * * Command line example: * * civl verify -inputNPROCSB=3 -inputNSTEPSB=3 \ -inputNXB=6 diffusion1d_good.cvl */ #include #include #include #include #include "mpi.cvl" // Definitions from programs: #define OWNER(index) ((nprocs*(index+1)-1)/nx) // inputs: $input int NPROCS; // number of processes for parallel version $input int NPROCSB; // upper bound on nprocs $input double K; // k = alpha^2 * dt/(dx^2) $input int NSTEPS; // number of time steps $input int WSTEP; // write every this many time steps $input int NSTEPSB; // upperbound on nsteps $input int NX; // global number of discrete spatial points $input int NXB; // upper bound on nx $input double u_init[NX]; // initial values for temperature (u) // assumptions: $assume 2 <= NX && NX <= NXB; $assume K>0 && K<.5; $assume WSTEP >= 1 && WSTEP <= NSTEPS; // $assume NX >= NPROCS; $assume 1 <= NPROCS && NPROCS <= NPROCSB; $assume 1 <= NSTEPS && NSTEPS <= NSTEPSB; // global variables: int output_seq[NX]; // final (color) result of sequential computation int output_par[NX]; // final (color) result of parallel computation CMPI_Gcomm MPI_GCOMM_WORLD; // the global communicator object /* Abstract function representing conversion from temperature to color */ $abstract int colorOf(double x); /* Sequential algorithm: performs simulation storing result of final * time step in output_seq */ void run_seq() { $scope seq_scope = $here; int nx, nsteps, wstep; double k, *u; void init_seq() { int i; int pos = 0; // file position // in place of reading these from file: nx = NX; nsteps = NSTEPS; wstep = WSTEP; k = K; printf("Diffusion1d (seq) with nx=%d, k=%f, nsteps=%d, wstep=%d\n", nx, k, nsteps, wstep); assert(nx>=2); assert(k>0 && k<.5); assert(nsteps >= 1); assert(wstep >= 1 && wstep <=nsteps); u = (double*)$malloc(seq_scope, nx*sizeof(double)); assert(u); for (i = 0; i < nx; i++) u[i] = u_init[pos++]; } void write_frame(int time) { for (int i=0; i=nprocs); assert(k>0 && k<.5); assert(nx>=2); assert(nsteps>=1); first = firstForProc(rank); nxl = countForProc(rank); if (first == 0 || nxl == 0) left = MPI_PROC_NULL; else left = OWNER(first-1); if (first+nxl >= nx || nxl == 0) right = MPI_PROC_NULL; else right = OWNER(first+nxl); u = (double*)$malloc(proc_scope, (nxl+2)*sizeof(double)); assert(u != NULL); u_new = (double*)$malloc(proc_scope, (nxl+2)*sizeof(double)); assert(u_new != NULL); if (rank == 0) { buf = (double*)$malloc(proc_scope, (1+nx/nprocs)*sizeof(double)); for (i=1; i <= nxl; i++) u[i] = u_init[pos++]; // instead of reading from file for (i=1; i < nprocs; i++) { int count_i = countForProc(i); for (j=0; j