source: CIVL/examples/contracts/contractsMPI/diffusion2d_dev2.c@ f60252e

1.23 2.0 main test-branch
Last change on this file since f60252e 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: 5.0 KB
RevLine 
[bca683b]1#include <mpi.h>
2#include <stdlib.h>
3#include <civlc.cvh>
4
5#define FROMLEFT 0
6#define FROMRIGHT 1
7#define FROMBOTTOM 2
8#define FROMTOP 3
9#define comm MPI_COMM_WORLD
10
11#define FIRSTCOL(rank) \
12((((rank)-((rank)/nprocsx)*nprocsx)*nx)/nprocsx)
13
14#define FIRSTROW(rank) \
15((((rank)/nprocsx)*ny)/nprocsy)
16
17#define OWNER(col,row) \
18(((nprocsy*(row+1)-1)/ny)*nprocsx+((((col)+1)*nprocsx-1)/nx))
19
20#define LEFT(rank) \
21(FIRSTCOL(rank)!=0?OWNER(FIRSTCOL(rank)-1,FIRSTROW(rank)):MPI_PROC_NULL)
22
23#define TOP(rank) \
24(FIRSTROW(rank)!=0?OWNER(FIRSTCOL(rank),FIRSTROW(rank)-1):MPI_PROC_NULL)
25
26#define RIGHT(rank) \
27(((FIRSTCOL(rank)+nxl)<nx)?OWNER(FIRSTCOL(rank)+nxl,FIRSTROW(rank)):MPI_PROC_NULL)
28
29#define BOTTOM(rank) \
30(((FIRSTROW(rank)+nyl)<ny)?OWNER(FIRSTCOL(rank),FIRSTROW(rank)+nyl):MPI_PROC_NULL)
31
32double (*u)[];
33double (*u_new)[];
34double k;
35int nxl, nyl, nx, ny;
36int rank, nprocsx, nprocsy, left, right, top, bottom;
37
38/*@ requires \valid((double (*)[nxl+2])u + (0 .. (nyl + 1)));
39 @ requires \valid(((double (*)[nxl+2])u_new) + (0 .. (nyl + 1)));
40 @ requires k > 0;
41 @ requires 0 <= nxl && nxl < 4;
42 @ requires 0 <= nyl && nyl < 4;
43 @ assigns u[1 .. nyl][1 .. nxl];
44 @ ensures \forall int i, j; 1 <= i && i <= nyl &&
45 @ 1 <= j && j <= nxl ==>
46 @ u[i][j] == \old(u[i][j] +
47 @ k*(u[i+1][j] + u[i-1][j] +
48 @ u[i][j+1] + u[i][j-1] - 4*u[i][j]));
49 @*/
50void update() {
51 double (* tmp)[];
52
53 for (int i = 1; i < nyl + 1; i++)
54 for (int j = 1; j < nxl + 1; j++) {
55 u_new[i][j] = u[i][j] +
56 k*(u[i+1][j] + u[i-1][j] +
57 u[i][j+1] + u[i][j-1] - 4*u[i][j]);
58 }
59 tmp = u;
60 u = u_new;
61 u_new = tmp;
62}
63
64/* The processes are arranged geometrically as follows for the case
65 * NPROCSX = 3:
66 * row 0: 0 1 2
67 * row 1: 3 4 5
68 * ...
69 */
70
71/*@ requires \valid((double (*)[nxl+2])u + (0 .. (nyl + 1)));
72 @ requires \valid((double (*)[nxl+2])u_new + (0 .. (nyl + 1)));
73 @ \mpi_collective(MPI_COMM_WORLD, P2P):
74 @ requires rank == \mpi_comm_rank;
75 @ requires nprocsx * nprocsy == \mpi_comm_size &&
76 @ nprocsx > 0 && nprocsx <= \mpi_comm_size &&
77 @ nprocsy > 0 && nprocsy <= \mpi_comm_size;
78 @ requires 0 < nxl && nxl < 3 && 0 < nyl && nyl < 3;
79 @ requires nxl < nx < 4 && nyl < ny < 4;
80 @ requires \mpi_agree(nprocsx) && \mpi_agree(nprocsy);
81 @ requires \mpi_agree(nx) && \mpi_agree(ny);
82 @ requires left == LEFT(rank);
83 @ requires right == RIGHT(rank);
84 @ requires top == TOP(rank);
85 @ requires bottom == BOTTOM(rank);
86 @ behavior assign_by_left:
87 @ assumes FIRSTCOL(rank)*nprocsx != 0;
88 @ requires nyl == \on(left, nyl);
89 @ assigns u[1 .. nyl][0];
90 @ ensures \forall int i; 1 <= i && i <= nyl ==>
91 @ u[i][0] == \on(left, u[i][nxl]);
92 @ waitsfor left;
93 @ behavior assign_by_right:
94 @ assumes FIRSTCOL(rank) + nxl < nx;
95 @ requires nyl == \on(right, nyl);
96 @ assigns u[1 .. nyl][nxl+1];
97 @ ensures \forall int i; 1 <= i && i <= nyl ==>
98 @ u[i][nxl+1] == \on(right, u[i][1]);
99 @ waitsfor right;
100 @ behavior assign_by_top:
101 @ assumes FIRSTROW(rank) != 0;
102 @ requires nxl == \on(top, nxl);
103 @ assigns u[0][1 .. nxl];
104 @ ensures \mpi_equals(&u[0][1], nxl, MPI_DOUBLE, \on(top, &u[nyl][1]));
105 @ waitsfor top;
106 @ behavior assign_by_bottom:
107 @ assumes FIRSTROW(rank) + nyl < ny;
108 @ requires nxl == \on(bottom, nxl);
109 @ assigns u[nyl+1][1 .. nxl];
110 @ ensures \mpi_equals(&u[nyl+1][1], nxl, MPI_DOUBLE, \on(bottom, &u[1][1]));
111 @ waitsfor bottom;
112 @*/
113void exchange() {
114 // sends top border row, receives into bottom ghost cell row
115 MPI_Sendrecv(&u[1][1], nxl, MPI_DOUBLE, top, FROMBOTTOM, &u[nyl+1][1], nxl,
116 MPI_DOUBLE, bottom, FROMBOTTOM, comm, MPI_STATUS_IGNORE);
117 // sends bottom border row, receives into top ghost cell row
118 MPI_Sendrecv(&u[nyl][1], nxl, MPI_DOUBLE, bottom, FROMTOP, &u[0][1], nxl,
119 MPI_DOUBLE, top, FROMTOP, comm, MPI_STATUS_IGNORE);
120
121 double * sendbuf;
122 double * recvbuf;
123
124 sendbuf = (double *)malloc(sizeof(double) * nyl);
125 recvbuf = (double *)malloc(sizeof(double) * nyl);
126 // sends left border column, receives into temporary buffer
127 for (int i = 0; i < nyl; i++) sendbuf[i] = u[i+1][1];
128 MPI_Sendrecv(sendbuf, nyl, MPI_DOUBLE, left, FROMRIGHT, recvbuf, nyl,
129 MPI_DOUBLE, right, FROMRIGHT, comm, MPI_STATUS_IGNORE);
130 // copies temporary buffer into right ghost cell column
131 if (right != MPI_PROC_NULL)
132 for (int i = 0; i < nyl; i++) u[i+1][nxl+1] = recvbuf[i];
133 // sends right border column, receives into temporary buffer
134 for (int i = 0; i < nyl; i++) sendbuf[i] = u[i+1][nxl];
135 MPI_Sendrecv(sendbuf, nyl, MPI_DOUBLE, right, FROMLEFT, recvbuf, nyl,
136 MPI_DOUBLE, left, FROMLEFT, comm, MPI_STATUS_IGNORE);
137 // copies temporary buffer into left ghost cell column
138 if (left != MPI_PROC_NULL)
139 for (int i = 0; i < nyl; i++) u[i+1][0] = recvbuf[i];
140 free(sendbuf);
141 free(recvbuf);
142}
Note: See TracBrowser for help on using the repository browser.