Basilisk CFD
Adaptive Cartesian mesh PDE framework
Loading...
Searching...
No Matches
multigrid.h
Go to the documentation of this file.
1/** @file multigrid.h
2 */
3#if SINGLE_PRECISION
4typedef float real;
5#else
6typedef double real;
7#endif
8
9#ifndef GRIDNAME
10# define GRIDNAME "Multigrid"
11#endif
12#define GHOSTS 2
13
14/* By default only one layer of ghost cells is used on the boundary to
15 optimise the cost of boundary conditions. */
16
17#ifndef BGHOSTS
19#endif
20
21#if _MPI
22# define ND(i) ((size_t)(1 << point.level))
23#else
24# define ND(i) ((size_t)(1 << point.level)*((int *)&Dimensions)[i])
25#endif
26
27#define _I (point.i - GHOSTS)
28#define _J (point.j - GHOSTS)
29#define _K (point.k - GHOSTS)
30
32#define _DELTA (1./((1 << point.level)*Dimensions_scale))
33
34typedef struct {
36 char * d;
37 size_t * shift;
38} Multigrid;
39
40struct _Point {
41 int i;
42#if dimension > 1
43 int j;
44#endif
45#if dimension > 2
46 int k;
47#endif
48 int level;
49#if dimension == 1
50 struct { int x; } n;
51#elif dimension == 2
52 struct { int x, y; } n;
53#elif dimension == 3
54 struct { int x, y, z; } n;
55#endif
56#if LAYERS
57 int l;
59#else
61#endif
62};
64
65#if LAYERS
66# include "grid/layers.h"
67#endif
68
69#define multigrid ((Multigrid *)grid)
70#define CELL(m,level,i) (*((Cell *) &m[level][(i)*datasize]))
71
72/***** Cartesian macros *****/
73#if dimension == 1
75@def val(a,k,l,m) (((real *)multigrid->d)[point.i + (k) +
76 multigrid->shift[point.level] +
77 _index(a,m)*multigrid->shift[depth() + 1]])
78@
79#elif dimension == 2
81@def val(a,k,l,m) (((real *)multigrid->d)[point.j + (l) +
82 (point.i + (k))*(ND(1) + 2*GHOSTS) +
83 multigrid->shift[point.level] +
84 _index(a,m)*multigrid->shift[depth() + 1]])
85@
86#elif dimension == 3
88@def val(a,l,m,o) (((real *)multigrid->d)[point.k + (o) +
89 (ND(2) + 2*GHOSTS)*
90 (point.j + (m) +
91 (point.i + (l))*(ND(1) + 2*GHOSTS)) +
92 multigrid->shift[point.level] +
93 _index(a,0)*multigrid->shift[depth() + 1]])
94@
95#endif
96
97/* low-level memory management */
98#if dimension == 1
99# if BGHOSTS == 1
100@define allocated(...) true
101# else // BGHOST != 1
102@define allocated(k,l,m) (point.i+(k) >= 0 && point.i+(k) < ND(0) + 2*GHOSTS)
103# endif // BGHOST != 1
105 point.i > 0 && point.i <= ND(0) + 2)
106@
107#elif dimension == 2
108# if BGHOSTS == 1
109@define allocated(...) true
110# else // BGHOST != 1
111@def allocated(k,l,m) (point.i+(k) >= 0 && point.i+(k) < ND(0) + 2*GHOSTS &&
112 point.j+(l) >= 0 && point.j+(l) < ND(1) + 2*GHOSTS)
113@
114# endif // BGHOST != 1
116 point.i > 0 && point.i <= ND(0) + 2 &&
117 point.j > 0 && point.j <= ND(1) + 2)
118@
119#else // dimension == 3
120# if BGHOSTS == 1
121@define allocated(...) true
122#else // BGHOST != 1
123@def allocated(a,l,m) (point.i+(a) >= 0 &&
124 point.i+(a) < ND(0) + 2*GHOSTS &&
125 point.j+(l) >= 0 &&
126 point.j+(l) < ND(1) + 2*GHOSTS &&
127 point.k+(m) >= 0 &&
128 point.k+(m) < ND(2) + 2*GHOSTS)
129@
130#endif // BGHOST != 1
132 point.i > 0 && point.i <= ND(0) + 2 &&
133 point.j > 0 && point.j <= ND(1) + 2 &&
134 point.k > 0 && point.k <= ND(2) + 2)
135@
136#endif // dimension == 3
137
138/***** Multigrid variables and macros *****/
140#if dimension == 1
141@def fine(a,k,l,m)
142(((real *)multigrid->d)[2*point.i - GHOSTS + (k) +
143 multigrid->shift[point.level + 1] +
144 _index(a,m)*multigrid->shift[depth() + 1]])
145@
146@def coarse(a,k,l,m)
147(((real *)multigrid->d)[(point.i + GHOSTS)/2 + (k) +
148 multigrid->shift[point.level - 1] +
149 _index(a,m)*multigrid->shift[depth() + 1]])
150@
151
153{
154 VARIABLES();
156 struct { int x; } child = { 2*((point.i+GHOSTS)%2)-1 }; NOT_UNUSED(child);
157 Point parent = point; NOT_UNUSED(parent);
158 parent.level--;
159 parent.i = (point.i + GHOSTS)/2;
160}
161
162#elif dimension == 2
163@def fine(a,k,l,m)
164(((real *)multigrid->d)[2*point.j - GHOSTS + (l) +
165 (2*point.i - GHOSTS + (k))*(ND(1)*2 + 2*GHOSTS) +
166 multigrid->shift[point.level + 1] +
167 _index(a,m)*multigrid->shift[depth() + 1]])
168@
169@def coarse(a,k,l,m)
170(((real *)multigrid->d)[(point.j + GHOSTS)/2 + (l) +
171 ((point.i + GHOSTS)/2 + (k))*(ND(1)/2 + 2*GHOSTS) +
172 multigrid->shift[point.level - 1] +
173 _index(a,m)*multigrid->shift[depth() + 1]])
174@
175
177 VARIABLES();
179 struct { int x, y; } child = {
180 2*((point.i+GHOSTS)%2)-1, 2*((point.j+GHOSTS)%2)-1
181 }; NOT_UNUSED(child);
182 Point parent = point; NOT_UNUSED(parent);
183 parent.level--;
184 parent.i = (point.i + GHOSTS)/2; parent.j = (point.j + GHOSTS)/2;
185}
186
187#elif dimension == 3
188@def fine(a,l,m,o)
189(((real *)multigrid->d)[2*point.k - GHOSTS + (o) +
190 (ND(2)*2 + 2*GHOSTS)*
191 (2*point.j - GHOSTS + (m) +
192 (2*point.i - GHOSTS + (l))*(ND(1)*2 + 2*GHOSTS)) +
193 multigrid->shift[point.level + 1] +
194 _index(a,0)*multigrid->shift[depth() + 1]])
195@
196@def coarse(a,l,m,o)
197(((real *)multigrid->d)[(point.k + GHOSTS)/2 + (o) +
198 (ND(2)/2 + 2*GHOSTS)*
199 ((point.j + GHOSTS)/2 + (m) +
200 ((point.i + GHOSTS)/2 + (l))*(ND(1)/2 + 2*GHOSTS)) +
201 multigrid->shift[point.level - 1] +
202 _index(a,0)*multigrid->shift[depth() + 1]])
203@
204
206{
207 VARIABLES();
209 struct { int x, y, z; } child = {
210 2*((point.i + GHOSTS)%2) - 1,
211 2*((point.j + GHOSTS)%2) - 1,
212 2*((point.k + GHOSTS)%2) - 1
213 }; NOT_UNUSED(child);
214 Point parent = point; NOT_UNUSED(parent);
215 parent.level--;
216 parent.i = (point.i + GHOSTS)/2;
217 parent.j = (point.j + GHOSTS)/2;
218 parent.k = (point.k + GHOSTS)/2;
219}
220
221#endif // dimension == 3
222
223#if _MPI
224#if dimension == 1
225# define SET_DIMENSIONS() point.n.x = 1 << point.level
226#elif dimension == 2
227# define SET_DIMENSIONS() point.n.x = point.n.y = 1 << point.level
228#elif dimension == 3
229# define SET_DIMENSIONS() point.n.x = point.n.y = point.n.z = 1 << point.level
230#endif
231#else // !_MPI
232#if dimension == 1
233# define SET_DIMENSIONS() point.n.x = (1 << point.level)*Dimensions.x
234#elif dimension == 2
235# define SET_DIMENSIONS() \
236 point.n.x = (1 << point.level)*Dimensions.x, \
237 point.n.y = (1 << point.level)*Dimensions.y
238#elif dimension == 3
239# define SET_DIMENSIONS() \
240 point.n.x = (1 << point.level)*Dimensions.x, \
241 point.n.y = (1 << point.level)*Dimensions.y, \
242 point.n.z = (1 << point.level)*Dimensions.z
243#endif
244#endif // !_MPI
245
246macro2 for (int _l = 0; _l < int l, char flags = 0, Reduce reductions = None; _l++) {
248 int ig = 0, jg = 0, kg = 0; NOT_UNUSED(ig); NOT_UNUSED(jg); NOT_UNUSED(kg);
249 Point point = {0};
250 point.level = l;
252 int _k;
253 OMP(omp for schedule(static))
254 for (_k = GHOSTS; _k < point.n.x + GHOSTS; _k++) {
255 point.i = _k;
256#if dimension > 1
257 for (point.j = GHOSTS; point.j < point.n.y + GHOSTS; point.j++)
258#if dimension > 2
259 for (point.k = GHOSTS; point.k < point.n.z + GHOSTS; point.k++)
260#endif
261#endif
262 {...}
263 }
264 }
265}
266
267macro2 foreach (char flags = 0, Reduce reductions = None) {
269 int ig = 0, jg = 0, kg = 0; NOT_UNUSED(ig); NOT_UNUSED(jg); NOT_UNUSED(kg);
270 Point point = {0};
271 point.level = depth();
273 int _k;
274 OMP(omp for schedule(static))
275 for (_k = GHOSTS; _k < point.n.x + GHOSTS; _k++) {
276 point.i = _k;
277#if dimension > 1
278 for (point.j = GHOSTS; point.j < point.n.y + GHOSTS; point.j++)
279#if dimension > 2
280 for (point.k = GHOSTS; point.k < point.n.z + GHOSTS; point.k++)
281#endif
282#endif
283 {...}
284 }
285 }
286}
287
290@define is_local(cell) (true)
291@define leaf 2
292@def refine_cell(...) do {
293 fprintf (stderr, "grid depths do not match. Aborting.\n");
294 assert (0);
295} while (0)
296@
298#include "foreach_cell.h"
299
301 const char * order = "xyz")
302{
304 int ig = 0, jg = 0, kg = 0; NOT_UNUSED(ig); NOT_UNUSED(jg); NOT_UNUSED(kg);
305 Point point = {0};
306 point.level = depth();
308 int _k;
309 OMP(omp for schedule(static))
310 for (_k = GHOSTS; _k <= point.n.x + GHOSTS; _k++) {
311 point.i = _k;
312#if dimension > 1
313 for (point.j = GHOSTS; point.j <= point.n.y + GHOSTS; point.j++)
314#if dimension > 2
315 for (point.k = GHOSTS; point.k <= point.n.z + GHOSTS; point.k++)
316#endif
317#endif
318 {...}
319 }
320 }
321}
322
324
325#if dimension == 1
327 {
328 int ig = -1; NOT_UNUSED(ig);
329 {...}
330 }
331}
332
333// foreach_edge?
334
335macro1 foreach_child (Point point = point, break = (_k = 2)) {
336 {
337 int _i = 2*point.i - GHOSTS;
338 point.level++;
339 point.n.x *= 2;
340 for (int _k = 0; _k < 2; _k++) {
341 point.i = _i + _k;
343 {...}
344 }
345 point.i = (_i + GHOSTS)/2;
346 point.level--;
347 point.n.x /= 2;
348 }
349}
350
351#elif dimension == 2
352#define foreach_edge() for (int _i = 0; _i < _N; _i++) /* foreach_face */
353
355 if (p.j < p.n.y + GHOSTS) {
356 int ig = -1; NOT_UNUSED(ig);
357 {...}
358 }
359}
360
362 if (p.i < p.n.x + GHOSTS) {
363 int jg = -1; NOT_UNUSED(jg);
364 {...}
365 }
366}
367
368macro1 foreach_child (Point point = point, break = (_k = _l = 2))
369{
370 {
371 int _i = 2*point.i - GHOSTS, _j = 2*point.j - GHOSTS;
372 point.level++;
373 point.n.x *= 2, point.n.y *= 2;
374 for (int _k = 0; _k < 2; _k++)
375 for (int _l = 0; _l < 2; _l++) {
376 point.i = _i + _k; point.j = _j + _l;
378 {...}
379 }
380 point.i = (_i + GHOSTS)/2; point.j = (_j + GHOSTS)/2;
381 point.level--;
382 point.n.x /= 2, point.n.y /= 2;
383 }
384}
385
386#elif dimension == 3
388 if (p.j < p.n.y + GHOSTS && p.k < p.n.z + GHOSTS) {
389 int ig = -1; NOT_UNUSED(ig);
390 {...}
391 }
392}
393
395 if (p.i < p.n.x + GHOSTS && p.k < p.n.z + GHOSTS) {
396 int jg = -1; NOT_UNUSED(jg);
397 {...}
398 }
399}
400
402 if (p.i < p.n.x + GHOSTS && p.j < p.n.y + GHOSTS) {
403 int kg = -1; NOT_UNUSED(kg);
404 {...}
405 }
406}
407
408macro1 foreach_child (Point point = point, break = (_l = _m = _n = 2))
409{
410 {
411 int _i = 2*point.i - GHOSTS;
412 int _j = 2*point.j - GHOSTS;
413 int _k = 2*point.k - GHOSTS;
414 point.level++;
415 point.n.x *= 2, point.n.y *= 2, point.n.z *= 2;
416 for (int _l = 0; _l < 2; _l++)
417 for (int _m = 0; _m < 2; _m++)
418 for (int _n = 0; _n < 2; _n++) {
419 point.i = _i + _l; point.j = _j + _m; point.k = _k + _n;
421 {...}
422 }
423 point.i = (_i + GHOSTS)/2;
424 point.j = (_j + GHOSTS)/2;
425 point.k = (_k + GHOSTS)/2;
426 point.level--;
427 point.n.x /= 2, point.n.y /= 2, point.n.z /= 2;
428 }
429}
430#endif
431
432@if TRASH
433@ undef trash
435@endif
436
437#include "neighbors.h"
438
439void reset (void * alist, double val)
440{
441 scalar * list = (scalar *) alist;
442 for (int _s = 0; _s < 1; _s++) /* scalar in list */
443 if (!is_constant(s))
444 for (int b = 0; b < s.block; b++) {
445 real * data = (real *) multigrid->d;
446 data += (s.i + b)*multigrid->shift[depth() + 1];
447 for (size_t i = 0; i < multigrid->shift[depth() + 1]; i++, data++)
448 *data = val;
449 }
450}
451
452// Boundaries
453
454#if dimension == 1
456{
457 {
458 int ig = 0, jg = 0, kg = 0; NOT_UNUSED(ig); NOT_UNUSED(jg); NOT_UNUSED(kg);
459 Point point = {0};
460 point.level = l < 0 ? depth() : l;
462 if (d == left) {
463 point.i = GHOSTS;
464 ig = -1;
465 }
466 else if (d == right) {
467 point.i = point.n.x + GHOSTS - 1;
468 ig = 1;
469 }
470 {...}
471 }
472}
473
476
477#elif dimension == 2
479{
481 int ig = 0, jg = 0, kg = 0; NOT_UNUSED(ig); NOT_UNUSED(jg); NOT_UNUSED(kg);
482 Point point = {0};
483 point.level = l < 0 ? depth() : l;
485 int * _i = &point.j, _n = point.n.y;
486 if (d == left) {
487 point.i = GHOSTS;
488 ig = -1;
489 }
490 else if (d == right) {
491 point.i = point.n.x + GHOSTS - 1;
492 ig = 1;
493 }
494 else if (d == bottom) {
495 point.j = GHOSTS;
496 _i = &point.i, _n = point.n.x;
497 jg = -1;
498 }
499 else if (d == top) {
500 point.j = point.n.y + GHOSTS - 1;
501 _i = &point.i, _n = point.n.x;
502 jg = 1;
503 }
504 int _l;
505 OMP(omp for schedule(static))
506 for (_l = 0; _l < _n + 2*GHOSTS; _l++) {
507 *_i = _l;
508 {...}
509 }
510 }
511}
512
513@def neighbor(o,p,q)
515@
516@def is_boundary(point) (point.i < GHOSTS || point.i >= point.n.x + GHOSTS ||
517 point.j < GHOSTS || point.j >= point.n.y + GHOSTS)
518@
519
520#elif dimension == 3
523 int ig = 0, jg = 0, kg = 0; NOT_UNUSED(ig); NOT_UNUSED(jg); NOT_UNUSED(kg);
524 Point point = {0};
525 point.level = l < 0 ? depth() : l;
527 int * _i = &point.j, * _j = &point.k;
528 int _n[2] = { point.n.y, point.n.z };
529 if (d == left) {
530 point.i = GHOSTS;
531 ig = -1;
532 }
533 else if (d == right) {
534 point.i = point.n.x + GHOSTS - 1;
535 ig = 1;
536 }
537 else if (d == bottom) {
538 point.j = GHOSTS;
539 _i = &point.i, _n[0] = point.n.x;
540 jg = -1;
541 }
542 else if (d == top) {
543 point.j = point.n.y + GHOSTS - 1;
544 _i = &point.i, _n[0] = point.n.x;
545 jg = 1;
546 }
547 else if (d == back) {
548 point.k = GHOSTS;
549 _i = &point.i; _j = &point.j;
550 _n[0] = point.n.x, _n[1] = point.n.y;
551 kg = -1;
552 }
553 else if (d == front) {
554 point.k = point.n.z + GHOSTS - 1;
555 _i = &point.i; _j = &point.j;
556 _n[0] = point.n.x, _n[1] = point.n.y;
557 kg = 1;
558 }
559 int _l;
560 OMP(omp for schedule(static))
561 for (_l = 0; _l < _n[0] + 2*GHOSTS; _l++) {
562 *_i = _l;
563 for (int _m = 0; _m < _n[1] + 2*GHOSTS; _m++) {
564 *_j = _m;
565 {...}
566 }
567 }
568 }
569}
570
571@def neighbor(o,p,q)
573@
574@def is_boundary(point) (point.i < GHOSTS || point.i >= point.n.x + GHOSTS ||
575 point.j < GHOSTS || point.j >= point.n.y + GHOSTS ||
576 point.k < GHOSTS || point.k >= point.n.z + GHOSTS)
577@
578
579#endif // dimension == 3
580
581extern double (* default_scalar_bc[]) (Point, Point, scalar, bool *);
582static double periodic_bc (Point point, Point neighbor, scalar s, bool * data);
583
584macro2 for (int _b = 0; _b < 1; _b++) /* boundary int b, Reduce reductions = None */
585{
588 if (!is_boundary(point))
589 {...}
590}
591
593
595{
597 for (int d = 0; d < 2*dimension; d++)
599 for (int _s = 0; _s < 1; _s++) /* scalar in scalars */
600 if (!is_constant(s) && s.block > 0) {
601 if (is_vertex_scalar (s))
602 s.boundary[d] = s.boundary_homogeneous[d] = NULL;
603 else if (s.face && s.v.x.i >= 0) {
604 vector v = s.v;
605 v.x.boundary[d] = v.x.boundary_homogeneous[d] = NULL;
606 }
607 }
608 for (int bghost = 1; bghost <= BGHOSTS; bghost++)
609 for (int d = 0; d < 2*dimension; d++) {
610
611 scalar * list = NULL, * listb = NULL;
612 for (int _s = 0; _s < 1; _s++) /* scalar in scalars */
613 if (!is_constant(s) && s.block > 0) {
614 scalar sb = s;
615#if dimension > 1
616 if (s.v.x.i >= 0) {
617 // vector component
618 int j = 0;
619 while ((&s.v.x)[j].i != s.i) j++;
620 sb = (&s.v.x)[(j - d/2 + dimension) % dimension];
621 }
622#endif
623 if (sb.i >= 0 && sb.boundary[d] && sb.boundary[d] != periodic_bc) {
624 list = list_append (list, s);
626 }
627 }
628
629 if (list) {
631 scalar s, sb;
632 for (s,sb in list,listb) {
633 if ((s.face && sb.i == s.v.x.i) || is_vertex_scalar (s)) {
634 // normal component of vector, or scalar
635 if (bghost == 1)
636 /* foreach_block */
637 s[(ig + 1)/2,(jg + 1)/2,(kg + 1)/2] =
638 sb.boundary[d] (point, neighborp(ig,jg,kg), s, NULL);
639 }
640 else
641 // tangential component of vector or centered
642 /* foreach_block */
644 sb.boundary[d] (neighborp((1 - bghost)*ig,
645 (1 - bghost)*jg,
646 (1 - bghost)*kg),
648 s, NULL);
649 }
650 }
651 free (list);
652 free (listb);
653 }
654 }
656}
657
658/* Periodic boundaries */
659
660#if !_MPI
661
662#if dimension == 1
663
664static void periodic_boundary_level_x (const Boundary * b, scalar * list, int l)
665{
666 scalar * list1 = NULL;
667 for (int _s = 0; _s < 1; _s++) /* scalar in list */
668 if (!is_constant(s) && s.block > 0 && s.boundary[right] == periodic_bc)
669 list1 = list_add (list1, s);
670 if (!list1)
671 return;
672
673 if (l == 0) {
674 for (int _l = 0; _l < 0, noauto; _l++)
675 for (int _s = 0; _s < 1; _s++) /* scalar in list1 */
676 for (int b = 0; b < s.block; b++) {
677 scalar sb = {s.i + b};
678 real v = sb[];
679 for (int _n = 0; _n < ; _n++)
680 sb[] = v;
681 }
682 free (list1);
683 return;
684 }
685
686 Point point = {0};
687 point.level = l < 0 ? depth() : l;
689 for (int i = 0; i < GHOSTS; i++)
690 for (int _s = 0; _s < 1; _s++) /* scalar in list1 */
691 for (int b = 0; b < s.block; b++) {
692 scalar sb = {s.i + b};
693 sb[i] = sb[i + point.n.x];
694 }
695 for (int i = point.n.x + GHOSTS; i < point.n.x + 2*GHOSTS; i++)
696 for (int _s = 0; _s < 1; _s++) /* scalar in list1 */
697 for (int b = 0; b < s.block; b++) {
698 scalar sb = {s.i + b};
699 sb[i] = sb[i - point.n.x];
700 }
701 free (list1);
702}
703
704#else // dimension != 1
705
707
708for (int _d = 0; _d < dimension; _d++)
709static void periodic_boundary_level_x (const Boundary * b, scalar * list, int l)
710{
711 scalar * list1 = NULL;
712 for (int _s = 0; _s < 1; _s++) /* scalar in list */
713 if (!is_constant(s) && s.block > 0) {
714 if (s.face) {
715 scalar vt = VT;
716 if (vt.i >= 0 && vt.boundary[right] == periodic_bc)
717 list1 = list_add (list1, s);
718 }
719 else if (s.boundary[right] == periodic_bc)
720 list1 = list_add (list1, s);
721 }
722 if (!list1)
723 return;
724
725 if (l == 0) {
726 for (int _l = 0; _l < 0, noauto; _l++)
727 for (int _s = 0; _s < 1; _s++) /* scalar in list1 */
728 for (int b = 0; b < s.block; b++) {
729 scalar sb = {s.i + b};
730 real v = sb[];
731 for (int _n = 0; _n < ; _n++)
732 sb[] = v;
733 }
734 free (list1);
735 return;
736 }
737
739 Point point = {0};
740 point.level = l < 0 ? depth() : l;
742#if dimension == 2
743 int j;
744 OMP(omp for schedule(static))
745 for (j = 0; j < point.n.y + 2*GHOSTS; j++) {
746 for (int i = 0; i < GHOSTS; i++)
747 for (int _s = 0; _s < 1; _s++) /* scalar in list1 */
748 for (int b = 0; b < s.block; b++) {
749 scalar sb = {s.i + b};
750 sb[i,j] = sb[i + point.n.x,j];
751 }
752 for (int i = point.n.x + GHOSTS; i < point.n.x + 2*GHOSTS; i++)
753 for (int _s = 0; _s < 1; _s++) /* scalar in list1 */
754 for (int b = 0; b < s.block; b++) {
755 scalar sb = {s.i + b};
756 sb[i,j] = sb[i - point.n.x,j];
757 }
758 }
759#else // dimension == 3
760 int j;
761 OMP(omp for schedule(static))
762 for (j = 0; j < point.n.y + 2*GHOSTS; j++)
763 for (int k = 0; k < point.n.z + 2*GHOSTS; k++) {
764 for (int i = 0; i < GHOSTS; i++)
765 for (int _s = 0; _s < 1; _s++) /* scalar in list1 */
766 for (int b = 0; b < s.block; b++) {
767 scalar sb = {s.i + b};
768 sb[i,j,k] = sb[i + point.n.x,j,k];
769 }
770 for (int i = point.n.x + GHOSTS; i < point.n.x + 2*GHOSTS; i++)
771 for (int _s = 0; _s < 1; _s++) /* scalar in list1 */
772 for (int b = 0; b < s.block; b++) {
773 scalar sb = {s.i + b};
774 sb[i,j,k] = sb[i - point.n.x,j,k];
775 }
776 }
777#endif
778 }
780}
781
782@undef VT
783
784#endif // dimension != 1
785
786#endif // !_MPI
787
788void free_grid (void)
789{
790 if (!grid)
791 return;
794 free (m->d);
795 free (m->shift);
796 free (m);
797 grid = NULL;
798}
799
800int log_base2 (int n) {
801 int m = n, r = 0;
802 while (m > 1)
803 m /= 2, r++;
804 return (1 << r) < n ? r + 1 : r;
805}
806
807void init_grid (int n)
808{
809 free_grid();
810 Multigrid * m = qmalloc (1, Multigrid);
811 grid = (Grid *) m;
813 N = (1 << grid->depth)*Dimensions.x;
814#if !_MPI
815 // mesh size
816 grid->n = 1 << dimension*depth();
817 for (int _d = 0; _d < dimension; _d++)
818 grid->n *= Dimensions.x;
819 grid->tn = grid->n;
820#endif // !_MPI
821 // box boundaries
822 Boundary * b = qcalloc (1, Boundary);
823 b->level = box_boundary_level;
824 add_boundary (b);
825#if _MPI
828#else
829 // periodic boundaries
830 for (int _d = 0; _d < dimension; _d++) {
831 Boundary * b = qcalloc (1, Boundary);
833 add_boundary (b);
834 }
835#endif
836 // allocate grid: this must be after mpi_boundary_new() since this modifies depth()
837 m->shift = qmalloc (depth() + 2, size_t);
838 size_t totalsize = 0;
839 for (int l = 0; l <= depth() + 1; l++) {
840 m->shift[l] = totalsize;
841 struct _Point point = { .level = l };
843 size_t size = 1;
844 for (int _d = 0; _d < dimension; _d++)
845 size *= point.n.x + 2*GHOSTS;
846 totalsize += size;
847 }
848 m->d = (char *) malloc(m->shift[depth() + 1]*datasize);
849 reset (all, 0.);
850}
851
853{
855 datasize += size;
856 qrealloc (p->d, p->shift[depth() + 1]*datasize, char);
857}
858
859#if _MPI
861#undef _I
862#undef _J
863#undef _K
864#define _I (point.i - GHOSTS + mpi_coords[0]*(1 << point.level))
865#define _J (point.j - GHOSTS + mpi_coords[1]*(1 << point.level))
866#define _K (point.k - GHOSTS + mpi_coords[2]*(1 << point.level))
867#endif
868
869Point locate (double xp = 0, double yp = 0, double zp = 0)
870{
871 Point point = {0};
872 point.level = depth();
874 point.level = -1;
875#if _MPI // fixme: can probably simplify with below
876 point.i = (xp - X0)/L0*point.n.x*Dimensions.x + GHOSTS - mpi_coords[0]*point.n.x;
877 if (point.i < GHOSTS || point.i >= point.n.x + GHOSTS)
878 return point;
879#if dimension >= 2
880 point.j = (yp - Y0)/L0*point.n.x*Dimensions.x + GHOSTS - mpi_coords[1]*point.n.x;
881 if (point.j < GHOSTS || point.j >= point.n.y + GHOSTS)
882 return point;
883#endif
884#if dimension >= 3
885 point.k = (zp - Z0)/L0*point.n.x*Dimensions.x + GHOSTS - mpi_coords[2]*point.n.x;
886 if (point.k < GHOSTS || point.k >= point.n.z + GHOSTS)
887 return point;
888#endif
889#else // !_MPI
890 point.i = (xp - X0)/L0*point.n.x + GHOSTS;
891 if (point.i < GHOSTS || point.i >= point.n.x + GHOSTS)
892 return point;
893#if dimension >= 2
894 point.j = (yp - Y0)/L0*point.n.x + GHOSTS;
895 if (point.j < GHOSTS || point.j >= point.n.y + GHOSTS)
896 return point;
897#endif
898#if dimension >= 3
899 point.k = (zp - Z0)/L0*point.n.x + GHOSTS;
900 if (point.k < GHOSTS || point.k >= point.n.z + GHOSTS)
901 return point;
902#endif
903#endif // !_MPI
904 point.level = depth();
905 return point;
906}
907
908#if _GPU
909# include "variables.h"
910#else
911# include "multigrid-common.h"
912#endif
913
914macro2 for (int _i = 0; _i < _N; _i++) /* foreach_vertex */ {
916 int ig = -1; NOT_UNUSED(ig);
917#if dimension > 1
918 int jg = -1; NOT_UNUSED(jg);
919#endif
920#if dimension > 2
921 int kg = -1; NOT_UNUSED(kg);
922#endif
923 {...}
924 }
925}
926
927#if dimension == 3
929 for (int _i = 0; _i < _N; _i++) /* foreach_vertex */ {
930 struct { int x, y, z; } _a = {point.i, point.j, point.k};
931 for (int _d = 0; _d < dimension; _d++)
932 if (_a.x < point.n.x + GHOSTS)
933 {...}
934 }
935}
936#endif // dimension == 3
937
938ivec dimensions (int nx = 0, int ny = 0, int nz = 0)
939{
940 if (nx != 0 || ny != 0 || nz != 0) {
942#if dimension > 1
943 Dimensions.y = max(ny, 1);
944#endif
945#if dimension > 2
946 Dimensions.z = max(nz, 1);
947#endif
948 }
949 return Dimensions;
950}
951
952#if _MPI
953# include "multigrid-mpi.h"
954#else // !_MPI
955
956#define for (int _i = 0; _i < _N; _i++) /* foreach_cell */ foreach_cell_restore()
957
958#endif // !_MPI
vector q[]
The primitive variables are the momentum , pressure , density , (face) specific volume ,...
Definition all-mach.h:44
const vector a
Definition all-mach.h:59
#define dimension
Definition bitree.h:3
void add_boundary(Boundary *b)
Definition boundaries.h:16
void free_boundaries()
Definition boundaries.h:27
BoundaryFunc default_scalar_bc[]
define k
define double double char flags
define double double char Reduce reductions
define m((k)==0 &&(l)==0 &&(m)==0) macro2 foreach_point(double _x=0.
static void periodic_boundary_level_x(const Boundary *b, scalar *list, int l)
macro1 is_face_x()
Definition cartesian1D.h:61
define neighbor(o, p, q)((Point)
Definition cartesian.h:146
double real
Definition cartesian.h:6
macro1 is_face_y(Point p=point)
Definition cartesian.h:86
if TRASH undef trash define trash(list) reset(list
macro2 foreach_face_generic(char flags=0, Reduce reductions=None, const char *order="xyz")
Definition cartesian.h:60
macro2 foreach_boundary_dir(int l, int d)
Definition cartesian.h:112
int y
Definition common.h:76
#define define
int x
Definition common.h:76
int z
Definition common.h:76
scalar * all
Definition common.h:342
double Z0
Definition common.h:34
static _Attributes * _attribute
Definition common.h:165
scalar * list_add(scalar *list, scalar s)
Definition common.h:208
ivec Dimensions
Definition common.h:173
double L0
Definition common.h:36
int N
Definition common.h:39
Grid * grid
Definition common.h:32
double X0
Definition common.h:34
scalar * list_append(scalar *list, scalar s)
Definition common.h:188
static bool is_vertex_scalar(scalar s)
Definition common.h:334
double Y0
Definition common.h:34
@ top
Definition common.h:123
@ bottom
Definition common.h:123
@ left
Definition common.h:123
@ right
Definition common.h:123
size_t datasize
Definition common.h:132
scalar * scalars
#define p
Definition tree.h:320
else define undefined((double) DBL_MAX) @ define enable_fpe(flags) @ define disable_fpe(flags) static void set_fpe(void)
Definition config.h:615
if __APPLE__ include< stdint.h > include fp_osx h endif if _GPU define enable_fpe(flags) @else @ define enable_fpe(flags) feenableexcept(flags) @endif @ define disable_fpe(flags) fedisableexcept(flags) static void set_fpe(void)
Definition config.h:603
#define qcalloc(size, type)
define _index(a, m)(a.i) @define val(a
#define qmalloc(size, type)
#define assert(a)
Definition config.h:107
Point point
Definition conserving.h:86
coord o
Definition curvature.h:672
else return n
Definition curvature.h:101
else fine(fs.x, 1, 0)
scalar s
Definition embed-tree.h:56
*cs[i, 0, 0] a *[i -1, 0, 0] j
Definition embed.h:88
double v[2]
Definition embed.h:383
double d[2]
Definition embed.h:383
scalar int i
Definition embed.h:74
#define BGHOSTS
Definition embed.h:15
#define depth()
Definition cartesian.h:14
#define realloc_scalar(size)
Definition gpu.h:480
#define reset(...)
Definition grid.h:1388
#define init_grid(n)
Definition grid.h:1402
macro
We also redefine the "per field" (inner) traversal.
Definition layers.h:18
#define data(k, l)
Definition linear.h:26
size_t max
Definition mtrace.h:8
size_t size
size *double * b
int int int level
Point locate(double xp=0, double yp=0, double zp=0)
Definition multigrid.h:869
double real
Definition multigrid.h:6
define is_active() cell(true) @define is_leaf(cell)(point.level
undef val def val(a, k, l, m)(((real *)((Multigrid *) grid) -> d)[point.j+(l)+(point.i+(k)) *(((size_t)(1<< point.level) *((int *)&Dimensions)[1])+2 *2)+((Multigrid *) grid) ->shift[point.level]+_index(a, m) *((Multigrid *) grid) ->shift[depth()+1]]) @ @define allocated(...) true @def allocated_child(k, l, m)(level< depth() &&point.i > 0 &&point.i<=((size_t)(1<< point.level) *((int *)&Dimensions)[0])+2 &&point.j > 0 &&point.j<=((size_t)(1<< point.level) *((int *)&Dimensions)[1])+2) @ @define depth()(grid->depth) @def fine(a, k, l, m)(((real *)((Multigrid *) grid) ->d)[2 *point.j - 2+(l)+(2 *point.i - 2+(k)) *(((size_t)(1<< point.level) *((int *)&Dimensions)[1]) *2+2 *2)+((Multigrid *) grid) ->shift[point.level+1]+_index(a, m) *((Multigrid *) grid) ->shift[depth()+1]]) @ @def coarse(a, k, l, m)(((real *)((Multigrid *) grid) ->d)[(point.j+2)/2+(l)+((point.i+2)/2+(k)) *(((size_t)(1<< point.level) *((int *)&Dimensions)[1])/2+2 *2)+((Multigrid *) grid) ->shift[point.level - 1]+_index(a, m) *((Multigrid *) grid) ->shift[depth()+1]]) @ macro POINT_VARIABLES(Point point=point)
Definition multigrid.h:81
define l
Definition multigrid.h:592
#define ND(i)
Definition multigrid.h:24
static Point last_point
Definition multigrid.h:63
int Dimensions_scale
Definition multigrid.h:31
undef VT void free_grid(void)
Definition multigrid.h:788
#define GHOSTS
Definition multigrid.h:12
#define multigrid
Definition multigrid.h:69
#define for
Similarly, on trees we need prolongation functions which also follow this definition.
Definition multigrid.h:246
static double periodic_bc(Point point, Point neighbor, scalar s, bool *data)
free(list1)
#define foreach_edge()
define VT _attribute[s.i] v y scalar * list
Definition multigrid.h:709
#define SET_DIMENSIONS()
Definition multigrid.h:235
define neighborp(k, l, o) neighbor(k
define static o void box_boundary_level(const Boundary *b, scalar *scalars, int l)
Definition multigrid.h:594
OMP_PARALLEL()
Definition multigrid.h:738
int log_base2(int n)
Definition multigrid.h:800
static FILE * dimensions
Definition qcc.c:62
def _i
Definition stencils.h:405
def _k
Definition stencils.h:405
def _j
Definition stencils.h:405
Definition common.h:26
long n
Definition common.h:27
long tn
Definition common.h:28
int depth
Definition common.h:29
int maxdepth
Definition common.h:30
char * d
Definition multigrid.h:36
size_t * shift
Definition multigrid.h:37
Definition linear.h:21
int level
Definition linear.h:23
int i
Definition linear.h:23
vector v
Definition common.h:158
int j
Definition cartesian.h:26
int y
Definition multigrid.h:52
int n
Definition cartesian.h:26
int level
Definition cartesian.h:26
int x
Definition multigrid.h:52
int i
Definition cartesian.h:26
Definition common.h:139
int y
Definition common.h:142
int x
Definition common.h:140
int i
Definition common.h:44
scalar y
Definition common.h:49
int refine_cell(Point point, scalar *list, int flag, Cache *refined)
Definition tree-common.h:23
void mpi_boundary_new()
Definition tree-mpi.h:508
define n k
Definition tree.h:319
define n n define coarse(a, k, p, n)((double *)(PARENT(k
def allocated(k, l, n)(mem_allocated(((Tree *) grid) -> L[point.level]->m, point.i+k, point.j+l)) @ @def NEIGHBOR(k, l, n)(((((Tree *) grid) ->L[point.level]->m) ->b[point.i+k][point.j+l])) @ @def PARENT(k, l, n)(((((Tree *) grid) ->L[point.level-1]->m) ->b[(point.i+2)/2+k][(point.j+2)/2+l])) @ @def allocated_child(k, l, n)(level< depth() &&mem_allocated(((Tree *) grid) ->L[point.level+1]->m, 2 *point.i- 2+k, 2 *point.j- 2+l)) @ @def CHILD(k, l, n)(((((Tree *) grid) ->L[point.level+1]->m) ->b[2 *point.i- 2+k][2 *point.j- 2+l])) @ @define CELL(m)(*((Cell *)(m))) @define depth()(grid->depth) @define aparent(k, l, n) CELL(PARENT(k, l, n)) @define child(k, l, n) CELL(CHILD(k, l, n)) @define cell CELL(NEIGHBOR(0, 0, 0)) @define neighbor(k, l, n) CELL(NEIGHBOR(k, l, n)) @def neighborp(l, m, n)(Point)
Definition tree.h:253
define n n define n n macro POINT_VARIABLES(Point point=point)
Definition tree.h:322
#define tree
Definition tree.h:184
macro1 foreach_child(Point point=point, break=(_k=_l=2))
Definition tree.h:370
@ leaf
Definition tree.h:60
define l
Definition tree.h:318
#define is_boundary(cell)
Definition tree.h:412
macro VARIABLES(Point point=point, int _ig=ig, int _jg=jg, int _kg=kg)
Definition variables.h:3