source: CIVL/examples/messagePassing/diffusion1d_par.cvl@ e2f9e611

1.23 2.0 main test-branch
Last change on this file since e2f9e611 was f07bf40, checked in by Stephen Siegel <siegel@…>, 12 years ago

Fix variable names in diffusion1d to correspond to command line args in test.

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

  • Property mode set to 100644
File size: 5.2 KB
Line 
1/* Computing the solver for heat equation in multithreads, then compare the
2 * result with the solver got in a sequencial way.
3 *
4 * Command line example:
5 * civl verify -inputNPROCSB=10 -inputK=0.3 -inputNSTEPS=5 -inputNX=10 diffusion1d.cvl -showAmpleSet
6 * This diffusion1d program computing the diffusion1d equation in parallel and then compare the result with
7 * another result of diffution1d equation computed in sequential.
8 **/
9
10#include<civlc.h>
11#include<stdio.h>
12$input int nprocs;
13$input int NPROCSB;
14$input double k; /* k = alpha^2 * dt/(dx^2) */
15$input int nsteps; /* time */
16$input int NSTEPSB;
17$input int nx; /* the length of the array */
18$input int NXB;
19$input double initialU[nx];
20double seq_u[nx];
21$proc __procs[nprocs];
22$gcomm __MPI_COMM_WORLD;
23$assume nx > nprocs;
24$assume 0 < nprocs && nprocs <= NPROCSB;
25$assume 0 < nsteps && nsteps <= NSTEPSB;
26$assume 2 < nx && nx <= NXB;
27
28void MPI_Process (int rank);
29
30void send(void *buf, int count, int dest, int tag, $comm comm) {
31 $message out = $message_pack(comm->place, dest, tag, buf, count*sizeof(double));
32 $comm_enqueue(comm, out);
33}
34
35void recv(void *buf, int count, int source, int tag, $comm comm) {
36 $message in = $comm_dequeue(comm, source, tag);
37 $message_unpack(in, buf, count*sizeof(double));
38}
39
40void init() {
41 __MPI_COMM_WORLD = $gcomm_create($root, nprocs);
42 for (int i=0; i<nprocs; i++)
43 __procs[i] = $spawn MPI_Process(i);
44}
45
46void finalize() {
47 for (int i=0; i<nprocs; i++)
48 $wait(__procs[i]);
49}
50
51/* computing the solver in a sequential way*/
52void seqDiffusion1d(){
53 double u[nx], u_new[nx];
54 int i;
55
56 //Initiate
57 for(i=0; i<nx; i++){
58 u[i] = initialU[i];
59 u_new[i] = initialU[i];
60 }
61 //Jacobi Iteration
62 for(int iter=nsteps; iter>0; iter--){
63 //update
64 for(i=1; i<nx-1; i++){
65 u_new[i] = u[i] + k * (u[i-1] + u[i+1] - 2*u[i]);
66 }
67 for(i=1; i<nx-1; i++){
68 u[i] = u_new[i];
69 }
70 }
71 for(i=0 ;i<nx; i++){
72 seq_u[i] = u[i];
73 }
74}
75
76void main() {
77 seqDiffusion1d();
78 init();
79 finalize();
80}
81
82/* update the array */
83void update(double * u, double * u_new, int start, int nxl){
84 int i;
85 int u_length = nxl;
86
87 for(i=1; i<u_length+1; i++){
88 u_new[i] = u[i] + k * (u[i-1] + u[i+1] - 2*u[i]);
89 }
90 for(i=1; i<u_length+1; i++){
91 u[i] = u_new[i];
92 }
93}
94
95/* Communicate with left u and right u,
96 send the first interior element to left u and receive for
97 the last interior element */
98void exchange_ghost_cells(double * u, int left, int right, int start,
99 int nxl, $comm comm){
100 int u_length = nxl;
101 // the most left or right us just need to exchange with one side
102 if(left == -1 && right == -1)
103 return;
104 else if(left == -1){
105 send(&u[u_length], 1, right, 0, comm);
106 recv(&u[u_length + 1], 1, right, 0, comm);
107 }
108 else if(right == -1){
109 send(&u[1], 1, left, 0, comm);
110 recv(&u[0], 1, left, 0, comm);
111 }else{
112 send(&u[u_length], 1, right, 0, comm);
113 send(&u[1], 1, left, 0, comm);
114 recv(&u[u_length + 1], 1, right, 0, comm);
115 recv(&u[0], 1, left, 0, comm);
116 }
117}
118
119int firstAndCountForProc(int nx, int nprocs, int rank, int * left_u, int * right_u,
120 int * first){
121 int start, end, left, right;
122 int nxl;
123
124 nx = nx -2; // the first and last cells are not need to be dsitributed to processes
125 start = (rank * nx)/nprocs + 1;
126 end = ((rank+1)*nx)/nprocs + 1;
127 nxl = end - start;
128 left = rank - 1;
129 right = rank + 1;
130 if(right >= nprocs){
131 right = -1;
132 }
133 /* return the number of interior elements */
134 *first = start;
135 *left_u = left;
136 *right_u = right;
137 return nxl;
138}
139
140/* the numbers of elements in u and u_new are 2 more than u_length because of
141 ghost elements */
142void initU(double * u, double * u_new, int nxl, int first, int left, int right){
143 int i, j;
144
145 /* initiate interior array */
146 j = first;
147 for(i=1; i< nxl+1; i++){
148 u[i] = initialU[j];
149 u_new[i] = initialU[j];
150 j++;
151 }
152 /* for the most left or right Us, initiate the first ghost element and
153 the last ghost element */
154 if(left == -1){
155 u[0] = initialU[0];
156 u_new[0] = initialU[0];
157 }
158 if(right == -1){
159 i = nxl + 1;
160 u[i] = initialU[nx-1];
161 u_new[i] = initialU[nx-1];
162 }
163}
164
165void compare(int first, int nxl, double * u){
166 int i;
167
168 for(i=0; i<nxl; i++){
169 // compare starts from u[1],u[0] is the ghost cell
170 $assert ((seq_u[first + i] == u[i+1]), "i = %d\n", i);
171 }
172}
173
174void MPI_Process (int rank){
175 int first = -1; /* the index of the u*/
176 int left_u = -1, right_u = -1; /* the index of the left u
177 and right u*/
178 int nxl = -1; /* number of elements in this u*/
179 double * u;
180 double * u_new;
181
182 $comm MPI_COMM_WORLD = $comm_create($here, __MPI_COMM_WORLD, rank);
183
184 nxl = firstAndCountForProc(nx, nprocs, rank, &left_u, &right_u, &first);
185 u = (double*)$malloc($here, sizeof(double)*(nxl + 2));
186 u_new = (double*)$malloc($here, sizeof(double)*(nxl + 2));
187 initU(u, u_new, nxl, first, left_u, right_u);
188 /* Jacobi Iterations*/
189 for(int iter=nsteps; iter>0; iter--){
190 exchange_ghost_cells(u, left_u, right_u, first, nxl, MPI_COMM_WORLD);
191 update(u, u_new, first, nxl);
192 }
193 compare(first, nxl, u);
194}
195
196
Note: See TracBrowser for help on using the repository browser.