source: CIVL/examples/contracts/contractsMPI/diffusion2d.c@ 33368ee

1.23 2.0 main test-branch
Last change on this file since 33368ee was b5cfaf6, checked in by Manchun Zheng <zmanchun@…>, 10 years ago

minor corrections

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

  • Property mode set to 100644
File size: 6.8 KB
Line 
1double ** u_curr, ** u_next;
2int nxl, nyl, nx, ny;
3int rank, nprocsx, nprocsy;
4
5/*@ requires \valid(u_curr + (0 .. (nyl + 2)));
6 @ requires \valid(u_next + (0 .. (nyl + 2)));
7 @ requires \valid(u_curr[0 .. (nyl+2)] + (0 .. (nxl + 2)));
8 @ requires \valid(u_next[0 .. (nyl+2)] + (0 .. (nxl + 2)));
9 @ requires nxl > 0 && nyl > 0 && k > 0;
10 @ ensures \forall int i, j; 1 <= i <= nyl &&
11 @ 1 <= j <= nxl ==>
12 @ u_curr[i][j] == \old(u_curr[i][j] +
13 @ k*(u_curr[i+1][j] + u_curr[i-1][j] +
14 @ u_curr[i][j+1] + u_curr[i][j-1] - 4*u_curr[i][j]));
15 @
16 @*/
17void update() {
18 double **tmp;
19
20 /*@ loop invariants \forall int k, m; 1<= k < i && 1 <=m <= nxl ==>
21 @ u_next[k][m] == u_curr[k][m] +
22 @ k*(u_curr[k+1][m] + u_curr[k-1][m] +
23 @ u_curr[k][m+1] + u_curr[k][m-1] - 4*u_curr[k][m]);
24 */
25 for (int i = 1; i < nyl + 1; i++)
26 /*@ loop invariants \forall int k; 1 <= k < j ==>
27 @ u_next[i][k] = u_curr[i][k] +
28 @ k*(u_curr[i+1][k] + u_curr[i-1][k] +
29 @ u_curr[i][k+1] + u_curr[i][k-1] - 4*u_curr[i][k]);
30 @*/
31 for (int j = 1; j < nxl + 1; j++) {
32 u_next[i][j] = u_curr[i][j] +
33 k*(u_curr[i+1][j] + u_curr[i-1][j] +
34 u_curr[i][j+1] + u_curr[i][j-1] - 4*u_curr[i][j]);
35 }
36 // swap two pointers
37 tmp = u_curr;
38 u_curr = u_next;
39 u_next = tmp;
40}
41
42/* The processes are arranged geometrically as follows for the case
43 * NPROCSX = 3:
44 * row 0: 0 1 2
45 * row 1: 3 4 5
46 * ...
47 */
48
49/*@ \mpi_collective(MPI_COMM_WORLD, P2P):
50 @ requires \mpi_valid(u_curr[1], 0, MPI_DOUBLE);
51 @ && \mpi_valid(u_curr[nyl], MPI_DOUBLE, 0);
52 @ && \mpi_valid(u_next[1], 0, MPI_DOUBLE);
53 @ && \mpi_valid(u_next[nyl], 0, MPI_DOUBLE);
54 @ requires \mpi_valid(&u_curr[1][1], nxl, MPI_DOUBLE);
55 @ requires \mpi_valid(&u_curr[nyl][1], nxl, MPI_DOUBLE);
56 @ requires \mpi_valid(&u_next[1][1], nxl, MPI_DOUBLE);
57 @ requires \mpi_valid(&u_next[nyl][1], nxl, MPI_DOUBLE);
58 @ requires rank == \mpi_comm_rank;
59 @ requires nprocsx * nprocsy == \mpi_comm_size;
60 @ ensures top != MPI_PROC_NULL ==>
61 @ \mpi_equals(&u_curr[1][1], nxl, MPI_DOUBLE, \on(top, &u_curr[nyl+1][1])); // obtain
62 @ ensures bottom != MPI_PROC_NULL ==>
63 @ \mpi_equals(&u_curr[nyl][1], nxl, MPI_DOUBLE, \on(bottom, &u_curr[0][1])); // obtain
64 @ ensures left != MPI_PROC_NULL ==> (\forall int i; 1 <= i <= nyl
65 @ ==>
66 @ u_curr[i][1] == \remote(u_curr[i][nxl+1], left); // obtain
67 @ ensures right != MPI_PROC_NULL ==> (\forall int i; 1 <= i <= nyl
68 @ ==>
69 @ u_curr[i][nxl] == \remote(u_curr[i][0], right); // obtain
70 @ waitsfor top, bottom, left, right;
71 @ behavior rightmost
72 @ assume (rank + 1) % nprocsx == 0;
73 @ requires left == MPI_PROC_NULL;
74 @ behavior leftmost
75 @ assume rank % nprocsx == 0;
76 @ requires right = MPI_PROC_NULL;
77 @ behavior atButton
78 @ assume nprocsx * nprocsy - nprocsx <= rank
79 @ && rank < nprocsx * nprocsy;
80 @ requires button == MPI_PROC_NULL;
81 @ behavior atTop
82 @ assume 0<= rank && rank < nprocsx;
83 @ requires top == MPI_PROC_NULL;
84 @ behavior others
85 @ assume nprocsx <= rank && rank < (nprocsx * nprocsy - nprocsx)
86 @ && (rank + 1) % nprocs x != 0 && rank % nprocsx != 0;
87 @ requires right == rank + 1 && left == rank - 1
88 @ && top == rank - nprocsx && button == rank + nprocsx;
89 @*/
90void exchange() {
91 double sendbuf[nyl];
92 double recvbuf[nyl];
93
94 // sends top border row, receives into bottom ghost cell row
95 MPI_Sendrecv(&u_curr[1][1], nxl, MPI_DOUBLE, top, FROMBOTTOM, &u_curr[nyl+1][1], nxl,
96 MPI_DOUBLE, bottom, FROMBOTTOM, comm, MPI_STATUS_IGNORE);
97 // sends bottom border row, receives into top ghost cell row
98 MPI_Sendrecv(&u_curr[nyl][1], nxl, MPI_DOUBLE, bottom, FROMTOP, &u_curr[0][1], nxl,
99 MPI_DOUBLE, top, FROMTOP, comm, MPI_STATUS_IGNORE);
100 // sends left border column, receives into temporary buffer
101 for (int i = 0; i < nyl; i++) sendbuf[i] = u_curr[i+1][1];
102 MPI_Sendrecv(sendbuf, nyl, MPI_DOUBLE, left, FROMRIGHT, recvbuf, nyl,
103 MPI_DOUBLE, right, FROMRIGHT, comm, MPI_STATUS_IGNORE);
104 // copies temporary buffer into right ghost cell column
105 if (right != MPI_PROC_NULL)
106 for (int i = 0; i < nyl; i++) u_curr[i+1][nxl+1] = recvbuf[i];
107 // sends right border column, receives into temporary buffer
108 for (int i = 0; i < nyl; i++) sendbuf[i] = u_curr[i+1][nxl];
109 MPI_Sendrecv(sendbuf, nyl, MPI_DOUBLE, right, FROMLEFT, recvbuf, nyl,
110 MPI_DOUBLE, left, FROMLEFT, comm, MPI_STATUS_IGNORE);
111 // copies temporary buffer into left ghost cell column
112 if (left != MPI_PROC_NULL)
113 for (int i = 0; i < nyl; i++) u_curr[i+1][0] = recvbuf[i];
114}
115
116/*@ requires nx > 0 && ny > 0 && nyl > 0 && nxl > 0;
117 @ \mpi_collective[MPI_COMM_WORLD, P2P]:
118 @ requires \mpi_valid(u_curr[1], MPI_DOUBLE, 0);
119 @ && \mpi_valid(u_curr[nyl], MPI_DOUBLE, 0);
120 @ && \mpi_valid(u_next[1], MPI_DOUBLE, 0);
121 @ && \mpi_valid(u_next[nyl], MPI_DOUBLE, 0);
122 @ requires \mpi_valid(&u_curr[1][1], MPI_DOUBLE, nxl);
123 @ requires \mpi_valid(&u_curr[nyl][1], MPI_DOUBLE, nxl);
124 @ requires \mpi_valid(&u_next[1][1], MPI_DOUBLE, nxl);
125 @ requires \mpi_valid(&u_next[nyl][1], MPI_DOUBLE, nxl);
126 @ requires rank == \mpi_comm_rank;
127 @ requires nprocsx * nprocsy == \mpi_comm_size;
128 @ requires nx == \sum(0, \mpi_comm_size - 1, (\lambda int k; \remote(nxl, k)));
129 @ requires ny == \sum(0, \mpi_comm_size - 1, (\lambda int k; \remote(nyl, k)));
130 @ ensures \forall int i, j; 0 <= i < ny &&
131 @ 0 <= j < nx ==>
132 @ u_curr[i][j] == \old(u_curr[i][j] +
133 @ k*(u_curr[i+1][j] + u_curr[i-1][j] +
134 @ u_curr[i][j+1] + u_curr[i][j-1] - 4*u_curr[i][j]));
135 @ behavior rightmost
136 @ assume (rank + 1) % nprocsx == 0;
137 @ requires left == MPI_PROC_NULL;
138 @ behavior leftmost
139 @ assume rank % nprocsx == 0;
140 @ requires right = MPI_PROC_NULL;
141 @ behavior atButton
142 @ assume nprocsx * nprocsy - nprocsx <= rank
143 @ && rank < nprocsx * nprocsy;
144 @ requires button == MPI_PROC_NULL;
145 @ behavior atTop
146 @ assume 0<= rank && rank < nprocsx;
147 @ requires top == MPI_PROC_NULL;
148 @ behavior others
149 @ assume nprocsx <= rank && rank < (nprocsx * nprocsy - nprocsx)
150 @ && (rank + 1) % nprocs x != 0 && rank % nprocsx != 0;
151 @ requires right == rank + 1 && left == rank - 1
152 @ && top == rank - nprocsx && button == rank + nprocsx;
153 @*/
154void diff2dIter() {
155 exchange_ghost_cells();
156 update();
157}
Note: See TracBrowser for help on using the repository browser.