Basilisk CFD
Adaptive Cartesian mesh PDE framework
Loading...
Searching...
No Matches
multigrid-mpi.h
Go to the documentation of this file.
1/** @file multigrid-mpi.h
2 */
3#define MULTIGRID_MPI 1
4
5#if dimension == 1
6
7macro2 foreach_slice_x (int start, int end, int l) {
8 {
9 int ig = 0; NOT_UNUSED(ig);
10 Point point = {0};
12 for (point.i = start; point.i < end; point.i++)
13 {...}
14 }
15}
16
17#elif dimension == 2
18
19macro2 foreach_slice_x (int start, int end, int l) {
20 {
21 int ig = 0, jg = 0; NOT_UNUSED(ig); NOT_UNUSED(jg);
22 Point point = {0};
24 for (point.i = start; point.i < end; point.i++)
25 for (point.j = 0; point.j < point.n.y + 2*GHOSTS; point.j++)
26 {...}
27 }
28}
29
30macro2 foreach_slice_y (int start, int end, int l) {
31 {
32 int ig = 0, jg = 0; NOT_UNUSED(ig); NOT_UNUSED(jg);
33 Point point = {0};
35 for (point.i = 0; point.i < point.n.x + 2*GHOSTS; point.i++)
36 for (point.j = start; point.j < end; point.j++)
37 {...}
38 }
39}
40
41#elif dimension == 3
42
43macro2 foreach_slice_x (int start, int end, int l) {
44 {
45 int ig = 0, jg = 0, kg = 0; NOT_UNUSED(ig); NOT_UNUSED(jg); NOT_UNUSED(kg);
46 Point point = {0};
48 for (point.i = start; point.i < end; point.i++)
49 for (point.j = 0; point.j < point.n.y + 2*GHOSTS; point.j++)
50 for (point.k = 0; point.k < point.n.z + 2*GHOSTS; point.k++)
51 {...}
52 }
53}
54
55macro2 foreach_slice_y (int start, int end, int l) {
56 {
57 int ig = 0, jg = 0, kg = 0; NOT_UNUSED(ig); NOT_UNUSED(jg); NOT_UNUSED(kg);
58 Point point = {0};
60 for (point.i = 0; point.i < point.n.x + 2*GHOSTS; point.i++)
61 for (point.j = start; point.j < end; point.j++)
62 for (point.k = 0; point.k < point.n.z + 2*GHOSTS; point.k++)
63 {...}
64 }
65}
66
67macro2 foreach_slice_z (int start, int end, int l) {
68 {
69 int ig = 0, jg = 0, kg = 0; NOT_UNUSED(ig); NOT_UNUSED(jg); NOT_UNUSED(kg);
70 Point point = {0};
72 for (point.i = 0; point.i < point.n.x + 2*GHOSTS; point.i++)
73 for (point.j = 0; point.j < point.n.y + 2*GHOSTS; point.j++)
74 for (point.k = start; point.k < end; point.k++)
75 {...}
76 }
77}
78
79#endif // dimension == 3
80
85
86for (int _d = 0; _d < dimension; _d++)
87static void * snd_x (int i, int dst, int tag, int level, scalar * list,
89{
90 if (dst == MPI_PROC_NULL)
91 return NULL;
92 size_t size = 0;
93 for (int _s = 0; _s < 1; _s++) /* scalar in list */
94 size += s.block;
95 size *= pow((1 << level) + 2*GHOSTS, dimension - 1)*GHOSTS*sizeof(real);
96 double * buf = (double *) malloc (size), * b = buf;
98 for (int _s = 0; _s < 1; _s++) /* scalar in list */
99 for (scalar sb = s; sb.i < s.i + s.block; sb.i++, b++)
100 memcpy (b, &sb[], sizeof(real));
102 return buf;
103}
104
105for (int _d = 0; _d < dimension; _d++)
106static void rcv_x (int i, int src, int tag, int level, scalar * list)
107{
108 if (src == MPI_PROC_NULL)
109 return;
110 size_t size = 0;
111 for (int _s = 0; _s < 1; _s++) /* scalar in list */
112 size += s.block;
113 size *= pow((1 << level) + 2*GHOSTS, dimension - 1)*GHOSTS*sizeof(real);
114 double * buf = (double *) malloc (size), * b = buf;
118 for (int _s = 0; _s < 1; _s++) /* scalar in list */
119 for (scalar sb = s; sb.i < s.i + s.block; sb.i++, b++)
120 memcpy (&sb[], b, sizeof(real));
121 free (buf);
122}
123
124trace
125static void mpi_boundary_level (const Boundary * b, scalar * list, int level)
126{
127 scalar * list1 = NULL;
128 for (int _s = 0; _s < 1; _s++) /* scalar in list */
129 if (!is_constant(s) && s.block > 0)
130 list1 = list_add (list1, s);
131 if (!list1)
132 return;
133
134 prof_start ("mpi_boundary_level");
135
136 if (level < 0) level = depth();
138 struct { int x, y, z; } dir = {0,1,2};
139 for (int _d = 0; _d < dimension; _d++) {
140 int left, right;
141 MPI_Cart_shift (mpi->cartcomm, dir.x, 1, &left, &right);
142 MPI_Request reqs[2];
143 void * buf[2];
144 int npl = (1 << level) + 2*GHOSTS, nr = 0;
145 if ((buf[0] = snd_x (npl - 2*GHOSTS, right, 0, level, list1, &reqs[nr])))
146 nr++;
147 if ((buf[1] = snd_x (2, left, 1, level, list1, &reqs[nr])))
148 nr++;
149 rcv_x (0, left, 0, level, list1);
150 rcv_x (npl - GHOSTS, right, 1, level, list1);
153 free (buf[0]); free (buf[1]);
154 }
155
156 free (list1);
157
158 prof_stop();
159}
160
161static void mpi_boundary_destroy (Boundary * b)
162{
163 MpiBoundary * m = (MpiBoundary *) b;
164 MPI_Comm_free (&m->cartcomm);
165 free (m);
166}
167
168static void mpi_dimensions_error (int n)
169{
171 "%s:%d: error: the number of MPI processes must be equal to ",
173 if (n > 1)
174 fprintf (stderr, "%dx", n);
175 fprintf (stderr, "%d^i\n", 1 << dimension);
176 exit (1);
177}
178
180{
182 int n = 1;
183 for (int _d = 0; _d < dimension; _d++)
184 n *= Dimensions.x;
185 if (npe() % n)
187 int j = npe()/n, i = 0;
188 while (j > 1) {
189 if (j % (1 << dimension))
191 j /= 1 << dimension;
192 i++;
193 }
194 for (int _d = 0; _d < dimension; _d++)
195 Dimensions.x *= 1 << i;
198 &Dimensions.x, &Period.x, 0, &m->cartcomm);
199 MPI_Cart_coords (m->cartcomm, pid(), dimension, mpi_coords);
200
201 // make sure other boundary conditions are not applied
202 struct { int x, y, z; } dir = {0,1,2};
203 for (int _d = 0; _d < dimension; _d++) {
204 int l, r;
205 MPI_Cart_shift (m->cartcomm, dir.x, 1, &l, &r);
206 if (l != MPI_PROC_NULL)
208 if (r != MPI_PROC_NULL)
210 }
211
212 // rescale the resolution
214 N /= Dimensions.x;
215 int r = 0;
216 while (N > 1)
217 N /= 2, r++;
219 N = Dimensions.x*(1 << r);
221 grid->tn = npe()*grid->n;
222
223 // setup boundary methods and add to list of boundary conditions
224 Boundary * b = (Boundary *) m;
228
229 return b;
230}
231
232trace
234{
235 long i;
236 if (leaves)
237 i = pid()*(1L << (dimension*depth()));
238 else
239 i = pid()*((1L << (dimension*(depth() + 1))) - 1)/((1L << dimension) - 1);
240 for (int _i = 0; _i < _N; _i++) /* foreach_cell */ {
241 if (!leaves || is_leaf(cell))
242 index[] = i++;
243 if (is_leaf(cell))
244 continue;
245 }
246 boundary ({index});
247 return pid() == 0 ? i*npe() - 1 : -1;
248}
int npe
Definition balance.h:195
bool leaves
Definition balance.h:193
struct @5 mpi
#define dimension
Definition bitree.h:3
#define boundary(...)
static void periodic_boundary(int d)
define l
define m((k)==0 &&(l)==0 &&(m)==0) macro2 foreach_point(double _x=0.
double real
Definition cartesian.h:6
#define GHOSTS
Definition cartesian.h:13
free(list1)
int y
Definition common.h:76
int x
Definition common.h:76
int z
Definition common.h:76
scalar * list_add(scalar *list, scalar s)
Definition common.h:208
ivec Dimensions
Definition common.h:173
struct @0 Period
Grid * grid
Definition common.h:32
@ left
Definition common.h:123
@ right
Definition common.h:123
#define qcalloc(size, type)
#define LINENO
Definition config.h:105
Point point
Definition conserving.h:86
return hxx pow(1.+sq(hx), 3/2.)
scalar s
Definition embed-tree.h:56
*cs[i, 0, 0] a *[i -1, 0, 0] j
Definition embed.h:88
scalar int i
Definition embed.h:74
size_t nr
Definition mtrace.h:10
add_boundary(b)
int dst
int int tag
int int int scalar MPI_Request * req
size_t size
size *double * b
grid n
int int int level
trace double z_indexing(scalar index, bool leaves)
int int int scalar * list
_s< 1;_s++) for(scalar sb=s;sb.i< s.i+s.block;sb.i++, b++) memcpy(b, &sb[], sizeof(real));MPI_Isend(buf, size, MPI_BYTE, dst, tag, MPI_COMM_WORLD, req);return buf;}for(int _d=0;_d< 2;_d++) static void rcv_x(int i, int src, int tag, int level, scalar *list){ if(src==MPI_PROC_NULL) return;size_t size=0;for(int _s=0;_s< 1;_s++) size+=s.block;size *=pow((1<< level)+2 *GHOSTS, 2 - 1) *GHOSTS *sizeof(real);double *buf=(double *) malloc(size), *b=buf;MPI_Status s;MPI_Recv(buf, size, MPI_BYTE, src, tag, MPI_COMM_WORLD, &s);foreach_slice_x(i, i+GHOSTS, level) for(int _s=0;_s< 1;_s++) for(scalar sb=s;sb.i< s.i+s.block;sb.i++, b++) memcpy(&sb[], b, sizeof(real));free(buf);}tracestatic void mpi_boundary_level(const Boundary *b, scalar *list, int level){ scalar *list1=NULL;for(int _s=0;_s< 1;_s++) if(!is_constant(s) &&s.block > 0) list1=list_add(list1, s);if(!list1) return;prof_start("mpi_boundary_level");if(level< 0) level=depth();MpiBoundary *mpi=(MpiBoundary *) b;struct { int x, y, z;} dir={0, 1, 2};for(int _d=0;_d< 2;_d++) { int left, right;MPI_Cart_shift(mpi->cartcomm, dir.x, 1, &left, &right);MPI_Request reqs[2];void *buf[2];int npl=(1<< level)+2 *GHOSTS, nr=0;if((buf[0]=snd_x(npl - 2 *GHOSTS, right, 0, level, list1, &reqs[nr]))) nr++;if((buf[1]=snd_x(2, left, 1, level, list1, &reqs[nr]))) nr++;rcv_x(0, left, 0, level, list1);rcv_x(npl - GHOSTS, right, 1, level, list1);MPI_Status stats[nr];MPI_Waitall(nr, reqs, stats);free(buf[0]);free(buf[1]);} free(list1);prof_stop();}static void mpi_boundary_destroy(Boundary *b){ MpiBoundary *m=(MpiBoundary *) b;MPI_Comm_free(&m->cartcomm);free(m);}static void mpi_dimensions_error(int n){ fprintf(stderr, "%s:%d: error: the number of MPI processes must be equal to ", __FILE__, LINENO);if(n > 1) fprintf(stderr, "%dx", n);fprintf(stderr, "%d^i\n", 1<< 2);exit(1);}Boundary *mpi_boundary_new(){ MpiBoundary *m=qcalloc(1, MpiBoundary);int n=1;for(int _d=0;_d< 2;_d++) n *=Dimensions.x;if(npe() % n) mpi_dimensions_error(n);int j=npe()/n, i=0;while(j > 1) { if(j %(1<< 2)) mpi_dimensions_error(n);j/=1<< 2;i++;} for(int _d=0;_d< 2;_d++) Dimensions.x *=1<< i;MPI_Dims_create(npe(), 2, &Dimensions.x);MPI_Cart_create(MPI_COMM_WORLD, 2, &Dimensions.x, &Period.x, 0, &m->cartcomm);MPI_Cart_coords(m->cartcomm, pid(), 2, mpi_coords);struct { int x, y, z;} dir={0, 1, 2};for(int _d=0;_d< 2;_d++) { int l, r;MPI_Cart_shift(m->cartcomm, dir.x, 1, &l, &r);if(l !=MPI_PROC_NULL) periodic_boundary(left);if(r !=MPI_PROC_NULL) periodic_boundary(right);} Dimensions_scale=Dimensions.x;N/=Dimensions.x;int r=0;while(N > 1) N/=2, r++;grid-> depth
macro2 foreach_slice_y(int start, int end, int l)
size *double * buf
macro2 foreach_slice_x(int start, int end, int l)
define is_active() cell(true) @define is_leaf(cell)(point.level
int Dimensions_scale
Definition multigrid.h:31
#define SET_DIMENSIONS()
Definition multigrid.h:235
char dir[]
Definition qcc.c:64
def _i
Definition stencils.h:405
long n
Definition common.h:27
long tn
Definition common.h:28
int depth
Definition common.h:29
int maxdepth
Definition common.h:30
MPI_Comm cartcomm
Definition linear.h:21
int level
Definition linear.h:23
int i
Definition linear.h:23
void(* level)(const Boundary *b, scalar *list, int l)
Definition boundaries.h:9
int x
Definition common.h:140
int i
Definition common.h:44
The statsf() function returns the minimum, maximum, volume sum, standard deviation and volume for fie...
Definition utils.h:166
void mpi_boundary_new()
Definition tree-mpi.h:508
static trace void mpi_boundary_level(const Boundary *b, scalar *list, int l)
Definition tree-mpi.h:494
static void mpi_boundary_destroy(Boundary *b)
Definition tree-mpi.h:482
Array * index