source: CIVL/examples/contracts/contractsMPI/diffusion2d.c@ e5ce0051

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

improve the contract transformer

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

  • Property mode set to 100644
File size: 4.4 KB
Line 
1#include <mpi.h>
2#define FROMLEFT 0
3#define FROMRIGHT 1
4#define FROMBOTTOM 2
5#define FROMTOP 3
6#define comm MPI_COMM_WORLD
7
8double (*u)[];
9double (*u_new)[];
10double k;
11int nxl, nyl, nx, ny;
12int rank, nprocsx, nprocsy, left, right, top, bottom;
13
14/*@ requires \valid((double (*)[nxl+2])u + (0 .. (nyl + 1)));
15 @ requires \valid(((double (*)[nxl+2])u_new) + (0 .. (nyl + 1)));
16 @ requires k > 0;
17 @ requires 0 <= nxl && nxl < 5;
18 @ requires 0 <= nyl && nyl < 5;
19 @ assigns u[1 .. nyl][1 .. nxl];
20 @ ensures \forall int i, j; 1 <= i <= nyl &&
21 @ 1 <= j <= nxl ==>
22 @ u[i][j] == \old(u[i][j] +
23 @ k*(u[i+1][j] + u[i-1][j] +
24 @ u[i][j+1] + u[i][j-1] - 4*u[i][j]));
25 @*/
26void update() {
27 double (* tmp)[];
28
29 for (int i = 1; i < nyl + 1; i++)
30 for (int j = 1; j < nxl + 1; j++) {
31 u_new[i][j] = u[i][j] +
32 k*(u[i+1][j] + u[i-1][j] +
33 u[i][j+1] + u[i][j-1] - 4*u[i][j]);
34 }
35 tmp = u;
36 u = u_new;
37 u_new = tmp;
38}
39
40/* The processes are arranged geometrically as follows for the case
41 * NPROCSX = 3:
42 * row 0: 0 1 2
43 * row 1: 3 4 5
44 * ...
45 */
46
47/*@ requires \valid((double (*)[nxl+2])u + (0 .. (nyl + 1)));
48 @ requires \valid((double (*)[nxl+2])u_new + (0 .. (nyl + 1)));
49 @ \mpi_collective(MPI_COMM_WORLD, P2P):
50 @ requires rank == \mpi_comm_rank;
51 @ requires nprocsx * nprocsy == \mpi_comm_size && nprocsx > 0
52 @ && nprocsy > 0;
53 @ requires (rank + 1) % nprocsx == 0 ==> right == MPI_PROC_NULL &&
54 @ !((rank + 1) % nprocsx == 0) ==> right == rank + 1;
55 @ requires rank % nprocsx == 0 ==> left == MPI_PROC_NULL &&
56 @ !(rank % nprocsx == 0) ==> left == rank - 1;
57 @ requires nprocsx * nprocsy - nprocsx <= rank && rank < nprocsx * nprocsy
58 @ ==> bottom == MPI_PROC_NULL &&
59 @ !(nprocsx * nprocsy - nprocsx <= rank && rank < nprocsx * nprocsy)
60 @ ==> bottom == rank + nprocsx;
61 @ requires 0<= rank && rank < nprocsx ==> top == MPI_PROC_NULL &&
62 @ !(0<= rank && rank < nprocsx) ==> top == rank - nprocsx;
63 @ ensures top != MPI_PROC_NULL ==>
64 @ \mpi_equals(&u[0][1], nxl, MPI_DOUBLE, \on(top, &u[nyl][1]));
65 @ ensures bottom != MPI_PROC_NULL ==>
66 @ \mpi_equals(&u[nyl+1][1], nxl, MPI_DOUBLE, \on(bottom, &u[1][1]));
67 @ ensures left != MPI_PROC_NULL ==> (\forall int i; 1 <= i <= nyl ==>
68 @ u[i][0] == \on(left, u[i][nxl]));
69 @ ensures right != MPI_PROC_NULL ==> (\forall int i; 1 <= i <= nyl ==>
70 @ u[i][nxl+1] == \on(right, u[i][1]));
71 @ waitsfor bottom, top, right, left;
72 @ behavior assign_by_left:
73 @ assumes rank % nprocsx != 0;
74 @ assigns u[1 .. nyl][0];
75 @ behavior assign_by_right:
76 @ assumes (rank + 1) % nprocsx != 0;
77 @ assigns u[1 .. nyl][nxl+1];
78 @ behavior assign_by_top:
79 @ assumes !(0 <= rank && rank < nprocsx);
80 @ assigns u[0][1 .. nxl];
81 @ behavior assign_by_bottom:
82 @ assumes !(nprocsx * nprocsy - nprocsx <= rank && rank < nprocsx * nprocsy);
83 @ assigns u[nyl+1][1 .. nxl];
84 @*/
85void exchange() {
86 double sendbuf[nyl];
87 double recvbuf[nyl];
88
89 // sends top border row, receives into bottom ghost cell row
90 MPI_Sendrecv(&u[1][1], nxl, MPI_DOUBLE, top, FROMBOTTOM, &u[nyl+1][1], nxl,
91 MPI_DOUBLE, bottom, FROMBOTTOM, comm, MPI_STATUS_IGNORE);
92 // sends bottom border row, receives into top ghost cell row
93 MPI_Sendrecv(&u[nyl][1], nxl, MPI_DOUBLE, bottom, FROMTOP, &u[0][1], nxl,
94 MPI_DOUBLE, top, FROMTOP, comm, MPI_STATUS_IGNORE);
95 // sends left border column, receives into temporary buffer
96 for (int i = 0; i < nyl; i++) sendbuf[i] = u[i+1][1];
97 MPI_Sendrecv(sendbuf, nyl, MPI_DOUBLE, left, FROMRIGHT, recvbuf, nyl,
98 MPI_DOUBLE, right, FROMRIGHT, comm, MPI_STATUS_IGNORE);
99 // copies temporary buffer into right ghost cell column
100 if (right != MPI_PROC_NULL)
101 for (int i = 0; i < nyl; i++) u[i+1][nxl+1] = recvbuf[i];
102 // sends right border column, receives into temporary buffer
103 for (int i = 0; i < nyl; i++) sendbuf[i] = u[i+1][nxl];
104 MPI_Sendrecv(sendbuf, nyl, MPI_DOUBLE, right, FROMLEFT, recvbuf, nyl,
105 MPI_DOUBLE, left, FROMLEFT, comm, MPI_STATUS_IGNORE);
106 // copies temporary buffer into left ghost cell column
107 if (left != MPI_PROC_NULL)
108 for (int i = 0; i < nyl; i++) u[i+1][0] = recvbuf[i];
109}
110
Note: See TracBrowser for help on using the repository browser.