source: CIVL/examples/contracts/contractsMPI/diffusion2d.c@ 67bc1cf

1.23 2.0 main test-branch
Last change on this file since 67bc1cf 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: 4.5 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 < 2;
18 @ requires 0 <= nyl && nyl < 2;
19 @ assigns u[1 .. nyl][1 .. nxl];
20 @ ensures \forall int i, j; 1 <= i && i <= nyl &&
21 @ 1 <= j && 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 &&
52 @ nprocsx > 0 && nprocsx <= \mpi_comm_size &&
53 @ nprocsy > 0 && nprocsy <= \mpi_comm_size;
54 @ requires 0 <= nxl && nxl < 3 && 0 <= nyl && nyl < 3;
55 @ ensures top != MPI_PROC_NULL ==>
56 @ \mpi_equals(&u[0][1], nxl, MPI_DOUBLE, \on(top, &u[nyl][1]));
57 @ ensures bottom != MPI_PROC_NULL ==>
58 @ \mpi_equals(&u[nyl+1][1], nxl, MPI_DOUBLE, \on(bottom, &u[1][1]));
59 @ ensures left != MPI_PROC_NULL ==> (\forall int i; 1 <= i <= nyl ==>
60 @ u[i][0] == \on(left, u[i][nxl]));
61 @ ensures right != MPI_PROC_NULL ==> (\forall int i; 1 <= i <= nyl ==>
62 @ u[i][nxl+1] == \on(right, u[i][1]));
63 @ waitsfor bottom, top, right, left;
64 @ behavior assign_by_left:
65 @ assumes rank % nprocsx != 0;
66 @ requires left == rank - 1;
67 @ assigns u[1 .. nyl][0];
68 @ behavior no_left:
69 @ assumes rank % nprocsx == 0;
70 @ requires left == MPI_PROC_NULL;
71 @ behavior assign_by_right:
72 @ assumes (rank + 1) % nprocsx != 0;
73 @ requires right == rank + 1;
74 @ assigns u[1 .. nyl][nxl+1];
75 @ behavior no_right:
76 @ assumes (rank + 1) % nprocsx == 0;
77 @ requires right == MPI_PROC_NULL;
78 @ behavior assign_by_top:
79 @ assumes !(0 <= rank && rank < nprocsx);
80 @ requires top == rank - nprocsx;
81 @ assigns u[0][1 .. nxl];
82 @ behavior no_top:
83 @ assumes 0 <= rank && rank < nprocsx;
84 @ requires top == MPI_PROC_NULL;
85 @ behavior assign_by_bottom:
86 @ assumes !(nprocsx * nprocsy - nprocsx <= rank && rank < nprocsx * nprocsy);
87 @ requires bottom == rank + nprocsx;
88 @ assigns u[nyl+1][1 .. nxl];
89 @ behavior no_bottom:
90 @ assumes nprocsx * nprocsy - nprocsx <= rank && rank < nprocsx * nprocsy;
91 @ requires bottom == MPI_PROC_NULL;
92 @*/
93void exchange() {
94 // sends top border row, receives into bottom ghost cell row
95 MPI_Sendrecv(&u[1][1], nxl, MPI_DOUBLE, top, FROMBOTTOM, &u[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[nyl][1], nxl, MPI_DOUBLE, bottom, FROMTOP, &u[0][1], nxl,
99 MPI_DOUBLE, top, FROMTOP, comm, MPI_STATUS_IGNORE);
100
101 if (nyl > 0) {
102 double sendbuf[nyl];
103 double recvbuf[nyl];
104
105 // sends left border column, receives into temporary buffer
106 for (int i = 0; i < nyl; i++) sendbuf[i] = u[i+1][1];
107 MPI_Sendrecv(sendbuf, nyl, MPI_DOUBLE, left, FROMRIGHT, recvbuf, nyl,
108 MPI_DOUBLE, right, FROMRIGHT, comm, MPI_STATUS_IGNORE);
109 // copies temporary buffer into right ghost cell column
110 if (right != MPI_PROC_NULL)
111 for (int i = 0; i < nyl; i++) u[i+1][nxl+1] = recvbuf[i];
112 // sends right border column, receives into temporary buffer
113 for (int i = 0; i < nyl; i++) sendbuf[i] = u[i+1][nxl];
114 MPI_Sendrecv(sendbuf, nyl, MPI_DOUBLE, right, FROMLEFT, recvbuf, nyl,
115 MPI_DOUBLE, left, FROMLEFT, comm, MPI_STATUS_IGNORE);
116 // copies temporary buffer into left ghost cell column
117 if (left != MPI_PROC_NULL)
118 for (int i = 0; i < nyl; i++) u[i+1][0] = recvbuf[i];
119 }
120}
121
Note: See TracBrowser for help on using the repository browser.