source: CIVL/examples/contracts/contractsMPI/diffusion2d_dev.c@ e5cec5ae

1.23 2.0 main test-branch
Last change on this file since e5cec5ae was bca683b, checked in by Ziqing Luo <ziqing@…>, 10 years ago

commit remaining work

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

  • Property mode set to 100644
File size: 6.2 KB
Line 
1#include <mpi.h>
2#include <stdlib.h>
3
4#define FROMLEFT 0
5#define FROMRIGHT 1
6#define FROMBOTTOM 2
7#define FROMTOP 3
8#define comm MPI_COMM_WORLD
9
10#define FIRSTCOL(rank) ((((rank)-((rank)/nprocsx)*nprocsx)*nx)/nprocsx)
11
12#define FIRSTROW(rank) ((((rank)/nprocsx)*ny)/nprocsy)
13
14#define OWNER(col,row) \
15(((nprocsy*(row+1)-1)/ny)*nprocsx+((((col)+1)*nprocsx-1)/nx))
16
17#define LEFT(rank) \
18(FIRSTCOL(rank)!=0?OWNER(FIRSTCOL(rank)-1,FIRSTROW(rank)):MPI_PROC_NULL)
19
20#define TOP(rank) \
21(FIRSTROW(rank)!=0?OWNER(FIRSTCOL(rank),FIRSTROW(rank)-1):MPI_PROC_NULL)
22
23#define RIGHT(rank) \
24(((FIRSTCOL(rank)+nxl)<nx)?OWNER(FIRSTCOL(rank)+nxl,FIRSTROW(rank)):MPI_PROC_NULL)
25
26#define BOTTOM(rank) \
27(((FIRSTROW(rank)+nyl)<ny)?OWNER(FIRSTCOL(rank),FIRSTROW(rank)+nyl):MPI_PROC_NULL)
28
29double (*u)[];
30double (*u_new)[];
31double k;
32int nxl, nyl, nx, ny;
33int rank, nprocsx, nprocsy, left, right, top, bottom;
34
35/*@ requires \valid((double (*)[nxl+2])u + (0 .. (nyl + 1)));
36 @ requires \valid(((double (*)[nxl+2])u_new) + (0 .. (nyl + 1)));
37 @ requires k > 0;
38 @ requires 0 <= nxl && nxl < 4;
39 @ requires 0 <= nyl && nyl < 4;
40 @ assigns u[1 .. nyl][1 .. nxl];
41 @ ensures \forall int i, j; 1 <= i && i <= nyl &&
42 @ 1 <= j && j <= nxl ==>
43 @ u[i][j] == \old(u[i][j] +
44 @ k*(u[i+1][j] + u[i-1][j] +
45 @ u[i][j+1] + u[i][j-1] - 4*u[i][j]));
46 @*/
47void update() {
48 double (* tmp)[];
49
50 for (int i = 1; i < nyl + 1; i++)
51 for (int j = 1; j < nxl + 1; j++) {
52 u_new[i][j] = u[i][j] +
53 k*(u[i+1][j] + u[i-1][j] +
54 u[i][j+1] + u[i][j-1] - 4*u[i][j]);
55 }
56 tmp = u;
57 u = u_new;
58 u_new = tmp;
59}
60
61/* The processes are arranged geometrically as follows for the case
62 * NPROCSX = 3:
63 * row 0: 0 1 2
64 * row 1: 3 4 5
65 * ...
66 */
67
68/*@ requires \valid((double (*)[nxl+2])u + (0 .. (nyl + 1)));
69 @ requires \valid((double (*)[nxl+2])u_new + (0 .. (nyl + 1)));
70 @ \mpi_collective(MPI_COMM_WORLD, P2P):
71 @ requires rank == \mpi_comm_rank;
72 @ requires nprocsx * nprocsy == \mpi_comm_size &&
73 @ nprocsx > 0 && nprocsx <= \mpi_comm_size &&
74 @ nprocsy > 0 && nprocsy <= \mpi_comm_size;
75 @ requires 0 < nxl && nxl < 3 && 0 < nyl && nyl < 3;
76 @ requires nxl < nx < 6 && nyl < ny < 6;
77 @ requires \mpi_agree(nprocsx) && \mpi_agree(nprocsy);
78 @ requires \mpi_agree(nx) && \mpi_agree(ny);
79 @ behavior assign_by_left:
80 @ assumes rank % nprocsx != 0;
81 @ requires left == rank - 1;
82 @ requires nyl == \on(left, nyl);
83 @ assigns u[1 .. nyl][0];
84 @ ensures \forall int i; 1 <= i && i <= nyl ==>
85 @ u[i][0] == \on(left, u[i][nxl]);
86 @ waitsfor left;
87 @ behavior no_left:
88 @ assumes rank % nprocsx == 0;
89 @ requires left == MPI_PROC_NULL;
90 @ behavior assign_by_right:
91 @ assumes (rank + 1) % nprocsx != 0;
92 @ requires right == rank + 1;
93 @ requires nyl == \on(right, nyl);
94 @ assigns u[1 .. nyl][nxl+1];
95 @ ensures \forall int i; 1 <= i && i <= nyl ==>
96 @ u[i][nxl+1] == \on(right, u[i][1]);
97 @ waitsfor right;
98 @ behavior no_right:
99 @ assumes (rank + 1) % nprocsx == 0;
100 @ requires right == MPI_PROC_NULL;
101 @ behavior assign_by_top:
102 @ assumes !(0 <= rank && rank < nprocsx);
103 @ requires top == rank - nprocsx;
104 @ requires nxl == \on(top, nxl);
105 @ assigns u[0][1 .. nxl];
106 @ ensures \mpi_equals(&u[0][1], nxl, MPI_DOUBLE, \on(top, &u[nyl][1]));
107 @ waitsfor top;
108 @ behavior no_top:
109 @ assumes 0 <= rank && rank < nprocsx;
110 @ requires top == MPI_PROC_NULL;
111 @ behavior assign_by_bottom:
112 @ assumes !(nprocsx * nprocsy - nprocsx <= rank && rank < nprocsx * nprocsy);
113 @ requires bottom == rank + nprocsx;
114 @ requires nxl == \on(bottom, nxl);
115 @ assigns u[nyl+1][1 .. nxl];
116 @ ensures \mpi_equals(&u[nyl+1][1], nxl, MPI_DOUBLE, \on(bottom, &u[1][1]));
117 @ waitsfor bottom;
118 @ behavior no_bottom:
119 @ assumes nprocsx * nprocsy - nprocsx <= rank && rank < nprocsx * nprocsy;
120 @ requires bottom == MPI_PROC_NULL;
121 @*/
122void exchange() {
123 // sends top border row, receives into bottom ghost cell row
124 MPI_Sendrecv(&u[1][1], nxl, MPI_DOUBLE, top, FROMBOTTOM, &u[nyl+1][1], nxl,
125 MPI_DOUBLE, bottom, FROMBOTTOM, comm, MPI_STATUS_IGNORE);
126 // sends bottom border row, receives into top ghost cell row
127 MPI_Sendrecv(&u[nyl][1], nxl, MPI_DOUBLE, bottom, FROMTOP, &u[0][1], nxl,
128 MPI_DOUBLE, top, FROMTOP, comm, MPI_STATUS_IGNORE);
129
130 double * sendbuf;
131 double * recvbuf;
132
133 sendbuf = (double *)malloc(sizeof(double) * nyl);
134 recvbuf = (double *)malloc(sizeof(double) * nyl);
135 // sends left border column, receives into temporary buffer
136 for (int i = 0; i < nyl; i++) sendbuf[i] = u[i+1][1];
137 MPI_Sendrecv(sendbuf, nyl, MPI_DOUBLE, left, FROMRIGHT, recvbuf, nyl,
138 MPI_DOUBLE, right, FROMRIGHT, comm, MPI_STATUS_IGNORE);
139 // copies temporary buffer into right ghost cell column
140 if (right != MPI_PROC_NULL)
141 for (int i = 0; i < nyl; i++) u[i+1][nxl+1] = recvbuf[i];
142 // sends right border column, receives into temporary buffer
143 for (int i = 0; i < nyl; i++) sendbuf[i] = u[i+1][nxl];
144 MPI_Sendrecv(sendbuf, nyl, MPI_DOUBLE, right, FROMLEFT, recvbuf, nyl,
145 MPI_DOUBLE, left, FROMLEFT, comm, MPI_STATUS_IGNORE);
146 // copies temporary buffer into left ghost cell column
147 if (left != MPI_PROC_NULL)
148 for (int i = 0; i < nyl; i++) u[i+1][0] = recvbuf[i];
149 free(sendbuf);
150 free(recvbuf);
151}
152
153/*@ requires \valid((double (*)[nxl+2])u + (0 .. (nyl + 1)));
154 @ requires \valid(((double (*)[nxl+2])u_new) + (0 .. (nyl + 1)));
155 @ \mpi_collective(MPI_COMM_WORLD, P2P):
156 @ requires rank == \mpi_comm_rank;
157 @ requires k > 0;
158 @ requires 0 <= nxl && nxl < 3;
159 @ requires 0 <= nyl && nyl < 3;
160 @ requires nxl < nx && nx < 6;
161 @ requires nyl < ny && ny < 6;
162 @ requires rank == \mpi_comm_rank;
163 @ requires nprocsx * nprocsy == \mpi_comm_size &&
164 @ nprocsx > 0 && nprocsx <= \mpi_comm_size &&
165 @ nprocsy > 0 && nprocsy <= \mpi_comm_size;
166 @ requires \mpi_agree(nprocsx) && \mpi_agree(nprocsy);
167 @ && \mpi_agree(nx) && \mpi_agree(ny);
168 @ assigns u[0 .. nyl+1][0 .. nxl+1];
169 @*/
170void diff2dIter() {
171 exchange();
172 update();
173}
Note: See TracBrowser for help on using the repository browser.