Timothy  0.9
Tissue Modelling Framework
 All Data Structures Files Functions Variables Typedefs Macros
comm.c
Go to the documentation of this file.
1 /* **************************************************************************
2  * This file is part of Timothy
3  *
4  * Copyright (c) 2014/15 Maciej Cytowski
5  * Copyright (c) 2014/15 ICM, University of Warsaw, Poland
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2 of the License, or
10  * (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
20  *
21  * *************************************************************************/
22 
23 #include <stdlib.h>
24 
25 #include "global.h"
26 
31 /* data type for IDs of exported cells */
32 struct expData {
33  int cell;
34  int proc;
35 };
36 
37 MPI_Request *reqSend;
38 MPI_Request *reqRecv;
39 
40 int64_t *sendOffset;
41 int64_t *recvOffset;
42 
43 struct expData *expList;
44 
45 int *recvCount;
46 int *sendCount;
47 
48 #define MAX_EXPORTED_PER_PROC 2*maxCellsPerProc
49 
54 int comm_compare_exp_list(const void *a, const void *b)
55 {
56  return ((struct expData *) a)->proc - ((struct expData *) b)->proc;
57 }
58 
65 {
66 
67  int i, p;
68  int procs[MPIsize];
69  int numprocs;
70 
71  numExp = 0;
72  numImp = 0;
73  if (nc < MPIsize || MPIsize == 1)
74  return;
75 
76  expList =
77  (struct expData *) malloc(sizeof(struct expData) *
79  recvCount = (int *) calloc(MPIsize, sizeof(int));
80  sendCount = (int *) calloc(MPIsize, sizeof(int));
81  sendOffset = (int64_t *) calloc(MPIsize, sizeof(int64_t));
82  recvOffset = (int64_t *) calloc(MPIsize, sizeof(int64_t));
83 
84  /* loop over local cells */
85  /*#pragma omp parallel for private(procs) */
86  for (p = 0; p < lnc; p++) {
87  double xmin, xmax, ymin, ymax, zmin, zmax;
88  double r;
89 
90  cells[p].halo = 0;
91 
92  if (nc < MPIsize)
93  continue;
94 
95  r = h * 1.5;
96 
97  /* compute neighbourhood box */
98  xmin = cells[p].x - r;
99  xmax = cells[p].x + r;
100  ymin = cells[p].y - r;
101  ymax = cells[p].y + r;
102  if (sdim == 3) {
103  zmin = cells[p].z - r;
104  zmax = cells[p].z + r;
105  } else {
106  zmin = 0.0;
107  zmax = 0.0;
108  }
109 
110  /* look for possible neighbours */
111  Zoltan_LB_Box_Assign(ztn, xmin, ymin, zmin, xmax, ymax, zmax, procs,
112  &numprocs);
113 
114  /* loop over receivers */
115  for (i = 0; i < numprocs; i++) {
116  if (procs[i] == MPIrank || tlnc[procs[i]] == 0)
117  continue;
118  expList[numExp].cell = p;
119  expList[numExp].proc = procs[i];
120  cells[p].halo = MPIrank + 1;
121  sendCount[procs[i]]++;
122  numExp++;
123  /* upps! too many refugees */
125  stopRun(110, NULL, __FILE__, __LINE__);
126  }
127  }
128 
129  /* sort export list with respect to process number */
130  qsort(expList, numExp, sizeof(struct expData), comm_compare_exp_list);
131 
132  /* distribute the information on transfer sizes between each process */
133  MPI_Alltoall(sendCount, 1, MPI_INT, recvCount, 1, MPI_INT,
134  MPI_COMM_WORLD);
135 
136  /* compute send offsets */
137  sendOffset[0] = 0;
138  for (i = 1; i < MPIsize; i++)
139  sendOffset[i] = sendOffset[i - 1] + sendCount[i - 1];
140 
141  /* compute receive offsets */
142  recvOffset[0] = 0;
143  for (i = 1; i < MPIsize; i++)
144  recvOffset[i] = recvOffset[i - 1] + recvCount[i - 1];
145 
146  /* count cells to be imported */
147  for (i = 0; i < MPIsize; i++)
148  numImp += recvCount[i];
149 
150 }
151 
157 {
158  if (nc < MPIsize || MPIsize == 1)
159  return;
160 
161  free(recvData);
162  free(recvDensPotData);
163 
164  free(expList);
165 
166  free(recvCount);
167  free(sendCount);
168 
169  free(sendOffset);
170  free(recvOffset);
171 
172 }
173 
178 {
179  int i;
180 
181  if (nc < MPIsize || MPIsize == 1)
182  return;
183 
184  /* allocate communication buffers */
185  sendData = (struct partData *) malloc(numExp * sizeof(struct partData));
186  recvData = (struct partData *) malloc(numImp * sizeof(struct partData));
187  reqSend = (MPI_Request *) malloc(sizeof(MPI_Request) * MPIsize);
188  reqRecv = (MPI_Request *) malloc(sizeof(MPI_Request) * MPIsize);
189 
190  /* create reduced particle data buffer for exporting */
191  for (i = 0; i < numExp; i++) {
192  sendData[i].x = cells[expList[i].cell].x;
193  sendData[i].y = cells[expList[i].cell].y;
194  sendData[i].z = cells[expList[i].cell].z;
195  sendData[i].size = cells[expList[i].cell].size;
196  sendData[i].h = h;
197  sendData[i].young = (double) cells[expList[i].cell].young;
198  }
199 
200  /* send cells - asynchronous MPI call */
201  for (i = 0; i < MPIsize; i++) {
202  if (sendCount[i] == 0 || tlnc[i] == 0 || lnc == 0)
203  continue;
204  MPI_Isend(&sendData[sendOffset[i]],
205  sendCount[i] * sizeof(struct partData), MPI_BYTE, i, MPIrank,
206  MPI_COMM_WORLD, &reqSend[i]);
207  }
208 
209  /* receive cells - asynchronous MPI call */
210  for (i = 0; i < MPIsize; i++) {
211  if (recvCount[i] == 0 || tlnc[i] == 0 || lnc == 0)
212  continue;
213  MPI_Irecv(&recvData[recvOffset[i]],
214  recvCount[i] * sizeof(struct partData), MPI_BYTE, i, i,
215  MPI_COMM_WORLD, &reqRecv[i]);
216  }
217 
218 }
219 
224 {
225  int i;
226  MPI_Status status;
227 
228  if (nc < MPIsize || MPIsize == 1)
229  return;
230 
231  /* wait for send completion */
232  for (i = 0; i < MPIsize; i++) {
233  if (sendCount[i] == 0 || tlnc[i] == 0 || lnc == 0)
234  continue;
235  if (MPI_Wait(&reqSend[i], &status) != MPI_SUCCESS)
236  stopRun(103, "reqSend", __FILE__, __LINE__);
237  }
238 
239  /* wait for receive completion */
240  for (i = 0; i < MPIsize; i++) {
241  if (recvCount[i] == 0 || tlnc[i] == 0 || lnc == 0)
242  continue;
243  if (MPI_Wait(&reqRecv[i], &status) != MPI_SUCCESS)
244  stopRun(103, "reqRecv", __FILE__, __LINE__);
245  }
246 
247  /* some of the buffers can be deallocated here */
248  free(sendData);
249  free(reqSend);
250  free(reqRecv);
251 }
252 
258 {
259  int i;
260 
261  if (nc < MPIsize || MPIsize == 1)
262  return;
263 
264  /* allocate communication buffers */
266  (struct densPotData *) malloc(numExp * sizeof(struct densPotData));
268  (struct densPotData *) malloc(numImp * sizeof(struct densPotData));
269  reqSend = (MPI_Request *) malloc(sizeof(MPI_Request) * MPIsize);
270  reqRecv = (MPI_Request *) malloc(sizeof(MPI_Request) * MPIsize);
271 
272  /* create density and potential buffer for exporting */
273  for (i = 0; i < numExp; i++) {
274  sendDensPotData[i].v = cells[expList[i].cell].v;
275  sendDensPotData[i].density = cells[expList[i].cell].density;
276  }
277 
278  /* send data - asynchronous MPI call */
279  for (i = 0; i < MPIsize; i++) {
280  if (sendCount[i] == 0 || tlnc[i] == 0 || lnc == 0)
281  continue;
282  MPI_Isend(&sendDensPotData[sendOffset[i]],
283  sendCount[i] * sizeof(struct densPotData), MPI_BYTE, i,
284  MPIrank, MPI_COMM_WORLD, &reqSend[i]);
285  }
286 
287  /* receive data - asynchronous MPI call */
288  for (i = 0; i < MPIsize; i++) {
289  if (recvCount[i] == 0 || tlnc[i] == 0 || lnc == 0)
290  continue;
291  MPI_Irecv(&recvDensPotData[recvOffset[i]],
292  recvCount[i] * sizeof(struct densPotData), MPI_BYTE, i, i,
293  MPI_COMM_WORLD, &reqRecv[i]);
294  }
295 
296 }
297 
302 {
303  int i;
304  MPI_Status status;
305 
306  if (nc < MPIsize || MPIsize == 1)
307  return;
308 
309  // Wait for send completion
310  for (i = 0; i < MPIsize; i++) {
311  if (sendCount[i] == 0 || tlnc[i] == 0 || lnc == 0)
312  continue;
313  if (MPI_Wait(&reqSend[i], &status) != MPI_SUCCESS)
314  stopRun(103, "sending", __FILE__, __LINE__);
315  }
316 
317  // Wait for receive completion
318  for (i = 0; i < MPIsize; i++) {
319  if (recvCount[i] == 0 || tlnc[i] == 0 || lnc == 0)
320  continue;
321  if (MPI_Wait(&reqRecv[i], &status) != MPI_SUCCESS)
322  stopRun(103, "receiving", __FILE__, __LINE__);
323  }
324 
325  /* some of the buffers can be deallocated */
326  free(sendDensPotData);
327  free(reqSend);
328  free(reqRecv);
329 }
double density
Definition: global.h:75
double h
Definition: global.h:120
int64_t * tlnc
Definition: global.h:111
int MPIrank
Definition: global.h:134
#define lnc
Definition: global.h:102
int64_t * sendOffset
Definition: comm.c:40
int cell
Definition: comm.c:33
struct partData * sendData
Definition: global.h:148
double z
Definition: global.h:119
int * recvCount
Definition: comm.c:45
int MPIsize
Definition: global.h:135
void cellsExchangeInit()
Definition: comm.c:177
void commCleanup()
Definition: comm.c:156
void densPotExchangeInit()
Definition: comm.c:257
HYPRE_SStructVector b
Definition: tempf.c:40
double size
Definition: global.h:72
struct partData * recvData
Definition: global.h:149
struct densPotData * sendDensPotData
Definition: global.h:150
struct Zoltan_Struct * ztn
Definition: global.h:146
contains the most important global variables, arrays and defines
Definition: comm.c:32
int numExp
Definition: global.h:153
int * sendCount
Definition: comm.c:46
void createExportList()
Definition: comm.c:64
void densPotExchangeWait()
Definition: comm.c:301
int sdim
Definition: global.h:160
double x
Definition: global.h:69
int64_t * recvOffset
Definition: comm.c:41
int numImp
Definition: global.h:154
struct cellData * cells
Definition: global.h:82
void cellsExchangeWait()
Definition: comm.c:223
MPI_Request * reqSend
Definition: comm.c:37
double v
Definition: global.h:127
double size
Definition: global.h:121
double z
Definition: global.h:71
#define MAX_EXPORTED_PER_PROC
Definition: comm.c:48
struct densPotData * recvDensPotData
Definition: global.h:151
double y
Definition: global.h:70
#define nc
Definition: global.h:93
MPI_Request * reqRecv
Definition: comm.c:38
double young
Definition: global.h:122
int proc
Definition: comm.c:34
struct expData * expList
Definition: comm.c:43
int halo
Definition: global.h:61
void stopRun(int ierr, char *name, char *file, int line)
Definition: utils.c:72
double x
Definition: global.h:117
double v
Definition: global.h:74
double y
Definition: global.h:118
int comm_compare_exp_list(const void *a, const void *b)
Definition: comm.c:54
double density
Definition: global.h:128
double h
Definition: global.h:200