Basilisk CFD
Adaptive Cartesian mesh PDE framework
Loading...
Searching...
No Matches
tree-common.h
Go to the documentation of this file.
1/** @file tree-common.h
2 */
3#define QUADTREE 1 // OBSOLETE: for backward-compatibility
4#define TREE 1
5
6#include "multigrid-common.h"
7
8// scalar attributes
9
11 void (* refine) (Point, scalar);
12}
13
14// Tree methods
15
16#define periodic_clamp(a, level) do { \
17 if (a < GHOSTS) a += 1 << level; \
18 else if (a >= GHOSTS + (1 << level)) a -= 1 << level; } while(0)
19
20/*
21 A cache of refined cells is maintained (if not NULL).
22*/
23int refine_cell (Point point, scalar * list, int flag, Cache * refined)
24{
25 int nr = 0;
26#if TWO_ONE
27 /* refine neighborhood if required */
28 if (level > 0)
29 for (int k = 0; k != 2*child.x; k += child.x)
30 #if dimension > 1
31 for (int l = 0; l != 2*child.y; l += child.y)
32 #endif
33 #if dimension > 2
34 for (int m = 0; m != 2*child.z; m += child.z)
35 #endif
36 if (aparent(k,l,m).pid >= 0 && is_leaf(aparent(k,l,m))) {
37 Point p = point;
38 /* fixme: this should be made
39 independent from the tree implementation */
40 p.level = point.level - 1;
41 p.i = (point.i + GHOSTS)/2 + k;
42 periodic_clamp (p.i, p.level);
43 #if dimension > 1
44 p.j = (point.j + GHOSTS)/2 + l;
45 periodic_clamp (p.j, p.level);
46 #endif
47 #if dimension > 2
48 p.k = (point.k + GHOSTS)/2 + m;
49 periodic_clamp (p.k, p.level);
50 #endif
51 nr += refine_cell (p, list, flag, refined);
52 aparent(k,l,m).flags |= flag;
53 }
54#endif
55
56 /* update neighborhood */
58
59 int cflag = is_active(cell) ? (active|leaf) : leaf;
60 for (int _c = 0; _c < 4; _c++) /* foreach_child */
61 cell.flags |= cflag;
62
63 /* initialise scalars */
64 for (int _s = 0; _s < 1; _s++) /* scalar in list */
65 if (is_local(cell) || s.face)
66 s.refine (point, s);
67
68 /* refine */
69 cell.flags &= ~leaf;
70
71@if _MPI
72 if (is_border(cell)) {
73 for (int _c = 0; _c < 4; _c++) /* foreach_child */ {
74 bool bord = false;
75 for (int _n = 0; _n < ; _n++) {
76 if (!is_local(cell) || (level > 0 && !is_local(aparent(0)))) {
77 bord = true; break;
78 }
79 if (is_refined_check())
80 for (int _c = 0; _c < 4; _c++) /* foreach_child */
81 if (!is_local(cell)) {
82 bord = true; break;
83 }
84 if (bord)
85 break;
86 }
87 if (bord)
88 cell.flags |= border;
89 }
90 if (refined)
91 cache_append (refined, point, cell.flags);
92 nr++;
93 }
94@endif
95 return nr;
96}
97
99 void (* coarsen) (Point, scalar);
100}
101
103{
104#if TWO_ONE
105 /* check that neighboring cells are not too fine.
106 check that children are not different boundaries */
107 int pid = cell.pid;
108 for (int _c = 0; _c < 4; _c++) /* foreach_child */
109 if (cell.neighbors || (cell.pid < 0 && cell.pid != pid))
110 return false; // cannot coarsen
111#endif
112
113 /* restriction/coarsening */
114 for (int _s = 0; _s < 1; _s++) /* scalar in list */ {
115 s.restriction (point, s);
116 if (s.coarsen)
117 s.coarsen (point, s);
118 }
119
120 /* coarsen */
121 cell.flags |= leaf;
122
123 /* update neighborhood */
125
126@if _MPI
127 if (!is_local(cell)) {
128 cell.flags &= ~(active|border);
129 for (int _n = 0; _n < 1; _n++)
130 if (cell.neighbors)
131 for (int _c = 0; _c < 4; _c++) /* foreach_child */
132 if (allocated(0) && is_local(cell) && !is_border(cell))
133 cell.flags |= border;
134 }
135@endif
136
137 return true;
138}
139
141{
142#if TWO_ONE
143 /* recursively coarsen children cells */
144 for (int _c = 0; _c < 4; _c++) /* foreach_child */
145 if (cell.neighbors)
146 for (int _n = 0; _n < 1; _n++)
147 if (is_refined (cell))
149#endif
151}
152
154void mpi_boundary_coarsen (int, int);
156
157static
159{
160 if (is_constant(s) || s.restriction == no_restriction)
161 return list;
162 for (int _t = 0; _t < 1; _t++) /* scalar in list */
163 if (t.i == s.i)
164 return list;
165 for (int _d = 0; _d < 1; _d++) /* scalar in s.depends */
167 return list_append (list, s);
168}
169
170typedef struct {
171 int nc, nf;
172} astats;
173
174trace
175astats adapt_wavelet (scalar * slist, // list of scalars
176 double * max, // tolerance for each scalar
177 int maxlevel, // maximum level of refinement
178 int minlevel = 1, // minimum level of refinement
179 scalar * list = all) // list of fields to update
180{
181 scalar * ilist = list;
182
183 if (is_constant(cm)) {
184 if (list == NULL || list == all)
185 list = list_copy (all);
186 boundary (list);
188 }
189 else {
190 if (list == NULL || list == all) {
191 list = list_copy ({cm, fm});
192 for (int _s = 0; _s < 1; _s++) /* scalar in all */
193 list = list_add (list, s);
194 }
195 boundary (list);
198 free (listr);
199 }
200
201 astats st = {0, 0};
202 scalar * listc = NULL;
203 for (int _s = 0; _s < 1; _s++) /* scalar in list */
204 listc = list_add_depend (listc, s);
205
206 // refinement
207 if (minlevel < 1)
208 minlevel = 1;
209 tree->refined.n = 0;
210 static const int refined = 1 << user, too_fine = 1 << (user + 1);
211 for (int _i = 0; _i < _N; _i++) /* foreach_cell */ {
212 if (is_active(cell)) {
213 static const int too_coarse = 1 << (user + 2);
214 if (is_leaf (cell)) {
215 if (cell.flags & too_coarse) {
216 cell.flags &= ~too_coarse;
217 refine_cell (point, listc, refined, &tree->refined);
218 st.nf++;
219 }
220 continue;
221 }
222 else { // !is_leaf (cell)
223 if (cell.flags & refined) {
224 // cell has already been refined, skip its children
225 cell.flags &= ~too_coarse;
226 continue;
227 }
228 // check whether the cell or any of its children is local
229 bool local = is_local(cell);
230 if (!local)
231 for (int _c = 0; _c < 4; _c++) /* foreach_child */
232 if (is_local(cell)) {
233 local = true; break;
234 }
235 if (local) {
236 int i = 0;
237 static const int just_fine = 1 << (user + 3);
238 for (int _s = 0; _s < 1; _s++) /* scalar in slist */ {
239 double emax = max[i++], sc[(1 << dimension)*s.block];
240 double * b = sc;
241 for (int _c = 0; _c < 4; _c++) /* foreach_child */
242 /* foreach_blockf */
243 *b++ = s[];
244 s.prolongation (point, s);
245 b = sc;
246 for (int _c = 0; _c < 4; _c++) /* foreach_child */
247 /* foreach_blockf */ {
248 double e = fabs(*b - s[]);
249 if (e > emax && level < maxlevel) {
250 cell.flags &= ~too_fine;
251 cell.flags |= too_coarse;
252 }
253 else if ((e <= emax/1.5 || level > maxlevel) &&
254 !(cell.flags & (too_coarse|just_fine))) {
255 if (level >= minlevel)
256 cell.flags |= too_fine;
257 }
258 else if (!(cell.flags & too_coarse)) {
259 cell.flags &= ~too_fine;
260 cell.flags |= just_fine;
261 }
262 s[] = *b++;
263 }
264 }
265 for (int _c = 0; _c < 4; _c++) /* foreach_child */ {
266 cell.flags &= ~just_fine;
267 if (!is_leaf(cell)) {
268 cell.flags &= ~too_coarse;
269 if (level >= maxlevel)
270 cell.flags |= too_fine;
271 }
272 else if (!is_active(cell))
273 cell.flags &= ~too_coarse;
274 }
275 }
276 }
277 }
278 else // inactive cell
279 continue;
280 }
281 mpi_boundary_refine (listc);
282
283 // coarsening
284 // the loop below is only necessary to ensure symmetry of 2:1 constraint
285 for (int l = depth(); l >= 0; l--) {
286 for (int _i = 0; _i < _N; _i++) /* foreach_cell */
287 if (!is_boundary(cell)) {
288 if (level == l) {
289 if (!is_leaf(cell)) {
290 if (cell.flags & refined)
291 // cell was refined previously, unset the flag
292 cell.flags &= ~(refined|too_fine);
293 else if (cell.flags & too_fine) {
294 if (is_local(cell) && coarsen_cell (point, listc))
295 st.nc++;
296 cell.flags &= ~too_fine; // do not coarsen parent
297 }
298 }
299 if (cell.flags & too_fine)
300 cell.flags &= ~too_fine;
301 else if (level > 0 && (aparent(0).flags & too_fine))
302 aparent(0).flags &= ~too_fine;
303 continue;
304 }
305 else if (is_leaf(cell))
306 continue;
307 }
309 }
310 free (listc);
311
314 if (st.nc || st.nf)
316
317 if (list != ilist)
318 free (list);
319
320 return st;
321}
322
324{
325 {
326 int refined;
327 do {
328 boundary (all);
329 refined = 0;
330 tree->refined.n = 0;
331 for (int _i = 0; _i < _N; _i++) /* foreach_leaf */
332 if (cond) {
333 refine_cell (point, all, 0, &tree->refined);
334 refined++;
335 continue;
336 }
337 mpi_all_reduce (refined, MPI_INT, MPI_SUM);
338 if (refined) {
341 }
342 } while (refined);
343 }
344}
345
346static void refine_level (int depth)
347{
348 int refined;
349 do {
350 refined = 0;
351 tree->refined.n = 0;
352 for (int _i = 0; _i < _N; _i++) /* foreach_leaf */
353 if (level < depth) {
354 refine_cell (point, NULL, 0, &tree->refined);
355 refined++;
356 continue;
357 }
358 mpi_all_reduce (refined, MPI_INT, MPI_SUM);
359 if (refined) {
362 }
363 } while (refined);
364}
365
367{
368 {
369 static const int too_fine = 1 << user;
370 for (int _i = 0; _i < _N; _i++) /* foreach_cell */ {
371 if (is_leaf(cell))
372 continue;
373 if (is_local(cell) && (cond))
374 cell.flags |= too_fine;
375 }
376 for (int _l = depth(); _l >= 0; _l--) {
377 for (int _i = 0; _i < _N; _i++) /* foreach_cell */ {
378 if (is_leaf(cell))
379 continue;
380 if (level == _l) {
381 if (is_local(cell) && (cell.flags & too_fine)) {
383 cell.flags &= ~too_fine;
384 }
385 continue;
386 }
387 }
389 }
391 }
392}
393
394trace
395static void halo_face (vectorl vl)
396{
397 for (int _d = 0; _d < dimension; _d++)
398 for (int _s = 0; _s < 1; _s++) /* scalar in vl.x */ {
399 s.stencil.bc |= s_face;
400 s.stencil.bc &= ~s_centered;
401 }
402
403 for (int l = depth() - 1; l >= 0; l--)
404 foreach_halo (prolongation, l)
405 for (int _d = 0; _d < dimension; _d++)
406 if (vl.x) {
407#if dimension == 1
408 if (is_refined (neighbor(-1)))
409 for (int _s = 0; _s < 1; _s++) /* scalar in vl.x */
410 /* foreach_blockf */
411 s[] = fine(s,0);
412 if (is_refined (neighbor(1)))
413 for (int _s = 0; _s < 1; _s++) /* scalar in vl.x */
414 /* foreach_blockf */
415 s[1] = fine(s,2);
416#elif dimension == 2
417 if (is_refined (neighbor(-1)))
418 for (int _s = 0; _s < 1; _s++) /* scalar in vl.x */
419 /* foreach_blockf */
420 s[] = (fine(s,0,0) + fine(s,0,1))/2.;
421 if (is_refined (neighbor(1)))
422 for (int _s = 0; _s < 1; _s++) /* scalar in vl.x */
423 /* foreach_blockf */
424 s[1] = (fine(s,2,0) + fine(s,2,1))/2.;
425#else // dimension == 3
426 if (is_refined (neighbor(-1)))
427 for (int _s = 0; _s < 1; _s++) /* scalar in vl.x */
428 /* foreach_blockf */
429 s[] = (fine(s,0,0,0) + fine(s,0,1,0) +
430 fine(s,0,0,1) + fine(s,0,1,1))/4.;
431 if (is_refined (neighbor(1)))
432 for (int _s = 0; _s < 1; _s++) /* scalar in vl.x */
433 /* foreach_blockf */
434 s[1] = (fine(s,2,0,0) + fine(s,2,1,0) +
435 fine(s,2,0,1) + fine(s,2,1,1))/4.;
436#endif
437 }
438}
439
440// Cartesian methods
441
442static scalar tree_init_scalar (scalar s, const char * name)
443{
444 s = multigrid_init_scalar (s, name);
445 s.refine = s.prolongation;
446 return s;
447}
448
450{
451 /* foreach_blockf */ {
452#if dimension == 2
453 fine(s,1,1) = (s[] + s[1] + s[0,1] + s[1,1])/4.;
454#else // dimension == 3
455 fine(s,1,1,1) = (s[] + s[1] + s[0,1] + s[1,1] +
456 s[0,0,1] + s[1,0,1] + s[0,1,1] + s[1,1,1])/8.;
457#endif
458
459 for (int i = 0; i <= 1; i++) {
460 for (int j = 0; j <= 1; j++)
461#if dimension == 3
462 for (int k = 0; k <= 1; k++)
463 if (allocated_child(2*i,2*j,2*k))
464 fine(s,2*i,2*j,2*k) = s[i,j,k];
465#else // dimension != 3
466 if (allocated_child(2*i,2*j))
467 fine(s,2*i,2*j) = s[i,j];
468#endif // dimension != 3
469
470 for (int _d = 0; _d < dimension; _d++)
471 if (neighbor(i).neighbors) {
472#if dimension == 2
473 fine(s,2*i,1) = (s[i,0] + s[i,1])/2.;
474#elif dimension == 3
475 fine(s,2*i,1,1) = (s[i,0,0] + s[i,1,0] + s[i,0,1] + s[i,1,1])/4.;
476 fine(s,2*i,1,0) = (s[i,0,0] + s[i,1,0])/2.;
477 fine(s,2*i,0,1) = (s[i,0,0] + s[i,0,1])/2.;
478 if (allocated_child(2*i,1,2))
479 fine(s,2*i,1,2) = (s[i,0,1] + s[i,1,1])/2.;
480 if (allocated_child(2*i,2,1))
481 fine(s,2*i,2,1) = (s[i,1,0] + s[i,1,1])/2.;
482#endif // dimension == 3
483 }
484 }
485 }
486}
487
488static scalar tree_init_vertex_scalar (scalar s, const char * name)
489{
491 s.refine = s.prolongation = prolongation_vertex;
492 return s;
493}
494
496{
497 for (int _d = 0; _d < dimension; _d++)
498 v.x.refine = v.x.prolongation;
499}
500
501static vector tree_init_vector (vector v, const char * name)
502{
503 v = multigrid_init_vector (v, name);
505 return v;
506}
507
508for (int _d = 0; _d < dimension; _d++)
510{
511 vector v = s.v;
512#if dimension <= 2
513 if (!is_refined(neighbor(-1)) &&
514 (is_local(cell) || is_local(neighbor(-1)))) {
515 /* foreach_blockf */ {
516 double g1 = (v.x[0,+1] - v.x[0,-1])/8.;
517 for (int j = 0; j <= 1; j++)
518 fine(v.x,0,j) = v.x[] + (2*j - 1)*g1;
519 }
520 }
521 if (!is_refined(neighbor(1)) && neighbor(1).neighbors &&
522 (is_local(cell) || is_local(neighbor(1)))) {
523 /* foreach_blockf */ {
524 double g1 = (v.x[1,+1] - v.x[1,-1])/8.;
525 for (int j = 0; j <= 1; j++)
526 fine(v.x,2,j) = v.x[1] + (2*j - 1)*g1;
527 }
528 }
530 /* foreach_blockf */ {
531 double g1 = (v.x[0,+1] - v.x[0,-1] + v.x[1,+1] - v.x[1,-1])/16.;
532 for (int j = 0; j <= 1; j++)
533 fine(v.x,1,j) = (v.x[] + v.x[1])/2. + (2*j - 1)*g1;
534 }
535 }
536#else // dimension > 2
537 if (!is_refined(neighbor(-1)) &&
538 (is_local(cell) || is_local(neighbor(-1)))) {
539 /* foreach_blockf */ {
540 double g1 = (v.x[0,+1] - v.x[0,-1])/8.;
541 double g2 = (v.x[0,0,+1] - v.x[0,0,-1])/8.;
542 for (int j = 0; j <= 1; j++)
543 for (int k = 0; k <= 1; k++)
544 fine(v.x,0,j,k) = v.x[] + (2*j - 1)*g1 + (2*k - 1)*g2;
545 }
546 }
547 if (!is_refined(neighbor(1)) && neighbor(1).neighbors &&
548 (is_local(cell) || is_local(neighbor(1)))) {
549 /* foreach_blockf */ {
550 double g1 = (v.x[1,+1] - v.x[1,-1])/8.;
551 double g2 = (v.x[1,0,+1] - v.x[1,0,-1])/8.;
552 for (int j = 0; j <= 1; j++)
553 for (int k = 0; k <= 1; k++)
554 fine(v.x,2,j,k) = v.x[1] + (2*j - 1)*g1 + (2*k - 1)*g2;
555 }
556 }
557 if (is_local(cell)) {
558 /* foreach_blockf */ {
559 double g1 = (v.x[0,+1] - v.x[0,-1] + v.x[1,+1] - v.x[1,-1])/16.;
560 double g2 = (v.x[0,0,+1] - v.x[0,0,-1] + v.x[1,0,+1] - v.x[1,0,-1])/16.;
561 for (int j = 0; j <= 1; j++)
562 for (int k = 0; k <= 1; k++)
563 fine(v.x,1,j,k) = (v.x[] + v.x[1])/2. + (2*j - 1)*g1 + (2*k - 1)*g2;
564 }
565 }
566#endif // dimension > 2
567}
568
570{
571 vector v = s.v;
572 for (int _d = 0; _d < dimension; _d++)
573 v.x.prolongation (point, v.x);
574}
575
577{
579#if dimension > 1
580 if (is_local(cell)) {
581 // local projection, see section 3.3 of Popinet, JCP, 2009
582 vector v = s.v;
583 double d[1 << dimension], p[1 << dimension];
584 int i = 0;
585 for (int _c = 0; _c < 4; _c++) /* foreach_child */ {
586 d[i] = 0.;
587 for (int _d = 0; _d < dimension; _d++)
588 d[i] += v.x[1] - v.x[];
589 i++;
590 }
591#if dimension == 2
592 p[0] = 0.;
593 p[1] = (3.*d[3] + d[0])/4. + d[2]/2.;
594 p[2] = (d[3] + 3.*d[0])/4. + d[2]/2.;
595 p[3] = (d[3] + d[0])/2. + d[2];
596 fine(v.x,1,1) += p[1] - p[0];
597 fine(v.x,1,0) += p[3] - p[2];
598 fine(v.y,0,1) += p[0] - p[2];
599 fine(v.y,1,1) += p[1] - p[3];
600#elif dimension == 3
601 static double m[7][7] = {
602 {7./12,5./24,3./8,5./24,3./8,1./4,1./3},
603 {5./24,7./12,3./8,5./24,1./4,3./8,1./3},
604 {3./8,3./8,3./4,1./4,3./8,3./8,1./2},
605 {5./24,5./24,1./4,7./12,3./8,3./8,1./3},
606 {3./8,1./4,3./8,3./8,3./4,3./8,1./2},
607 {1./4,3./8,3./8,3./8,3./8,3./4,1./2},
608 {1./3,1./3,1./2,1./3,1./2,1./2,5./6}
609 };
610 p[0] = 0.;
611 for (int i = 0; i < 7; i++) {
612 p[i + 1] = 0.;
613 for (int j = 0; j < 7; j++)
614 p[i + 1] += m[i][j]*d[j+1];
615 }
616 for (int k = 0; k <= 1; k++) {
617 fine(v.x,1,0,k) += p[4+k] - p[0+k];
618 fine(v.x,1,1,k) += p[6+k] - p[2+k];
619 fine(v.y,0,1,k) += p[2+k] - p[0+k];
620 fine(v.y,1,1,k) += p[6+k] - p[4+k];
621 }
622 fine(v.z,0,0,1) += p[1] - p[0];
623 fine(v.z,0,1,1) += p[3] - p[2];
624 fine(v.z,1,0,1) += p[5] - p[4];
625 fine(v.z,1,1,1) += p[7] - p[6];
626#endif // dimension == 3
627 }
628#endif // dimension > 1
629}
630
631static vector tree_init_face_vector (vector v, const char * name)
632{
634 for (int _d = 0; _d < dimension; _d++)
635 v.x.restriction = v.x.refine = no_restriction;
636 v.x.restriction = restriction_face;
637 v.x.refine = refine_face;
638 for (int _d = 0; _d < dimension; _d++)
639 v.x.prolongation = refine_face_x;
640 return v;
641}
642
643static tensor tree_init_tensor (tensor t, const char * name)
644{
645 t = multigrid_init_tensor (t, name);
646 for (int _d = 0; _d < dimension; _d++)
648 return t;
649}
650
651trace
652static void tree_boundary_level (scalar * list, int l)
653{
654 int depth = l < 0 ? depth() : l;
655
656 if (tree_is_full()) {
658 return;
659 }
660
661 scalar * listdef = NULL, * listc = NULL, * list2 = NULL, * vlist = NULL;
662 for (int _s = 0; _s < 1; _s++) /* scalar in list */
663 if (!is_constant (s)) {
664 if (s.restriction == restriction_average) {
666 list2 = list_add (list2, s);
667 }
668 else if (s.restriction != no_restriction) {
669 listc = list_add (listc, s);
670 if (s.face)
671 for (int _d = 0; _d < dimension; _d++)
672 list2 = list_add (list2, s.v.x);
673 else {
674 list2 = list_add (list2, s);
675 if (s.restriction == restriction_vertex)
676 vlist = list_add (vlist, s);
677 }
678 }
679 }
680
681 if (vlist) // vertex scalars
682#if dimension == 1
683 for (int _i = 0; _i < _N; _i++) /* foreach_vertex */
684 if (is_refined(cell) || is_refined(neighbor(-1)))
685 for (int _s = 0; _s < 1; _s++) /* scalar in vlist */
686 /* foreach_blockf */
687 s[] = is_vertex (child(0)) ? fine(s) : nodata;
688#elif dimension == 2
689 for (int _i = 0; _i < _N; _i++) /* foreach_vertex */ {
690 if (is_refined(cell) || is_refined(neighbor(-1)) ||
691 is_refined(neighbor(0,-1)) || is_refined(neighbor(-1,-1))) {
692 // corner
693 for (int _s = 0; _s < 1; _s++) /* scalar in vlist */
694 /* foreach_blockf */
695 s[] = is_vertex (child(0)) ? fine(s) : nodata;
696 }
697 else
698 for (int _d = 0; _d < dimension; _d++)
699 if (child.y == 1 &&
701 // center of refined edge
702 for (int _s = 0; _s < 1; _s++) /* scalar in vlist */
703 /* foreach_blockf */
704 s[] = is_vertex(neighbor(0,-1)) && is_vertex(neighbor(0,1)) ?
705 (s[0,-1] + s[0,1])/2. : nodata;
706 }
707 }
708#else // dimension == 3
709 for (int _i = 0; _i < _N; _i++) /* foreach_vertex */ {
710 if (is_refined(cell) || is_refined(neighbor(-1)) ||
711 is_refined(neighbor(0,-1)) || is_refined(neighbor(-1,-1)) ||
712 is_refined(neighbor(0,0,-1)) || is_refined(neighbor(-1,0,-1)) ||
713 is_refined(neighbor(0,-1,-1)) || is_refined(neighbor(-1,-1,-1))) {
714 // corner
715 for (int _s = 0; _s < 1; _s++) /* scalar in vlist */
716 /* foreach_blockf */
717 s[] = is_vertex (child(0)) ? fine(s) : nodata;
718 }
719 else
720 for (int _d = 0; _d < dimension; _d++) {
721 if (child.y == 1 && child.z == 1 &&
723 // center of refined face
724 for (int _s = 0; _s < 1; _s++) /* scalar in vlist */
725 /* foreach_blockf */
726 s[] = is_vertex(neighbor(0,-1,-1)) && is_vertex(neighbor(0,1,-1))
727 && is_vertex(neighbor(0,-1,1)) && is_vertex(neighbor(0,1,1)) ?
728 (s[0,-1,-1] + s[0,1,-1] + s[0,-1,1] + s[0,1,1])/4. : nodata;
729 }
730 else if (child.x == -1 && child.z == -1 && child.y == 1 &&
732 is_prolongation(neighbor(0,0,-1)) ||
733 is_prolongation(neighbor(-1,0,-1)))) {
734 // center of refined edge
735 for (int _s = 0; _s < 1; _s++) /* scalar in vlist */
736 /* foreach_blockf */
737 s[] = is_vertex(neighbor(0,-1)) && is_vertex(neighbor(0,1)) ?
738 (s[0,-1] + s[0,1])/2. : nodata;
739 }
740 }
741 }
742#endif // dimension == 3
743 free (vlist);
744
745 if (listdef || listc) {
747 for (int l = depth - 1; l >= 0; l--) {
748 for (int _l = 0; _l < l, nowarning; _l++) {
749 for (int _s = 0; _s < 1; _s++) /* scalar in listdef */
751 for (int _s = 0; _s < 1; _s++) /* scalar in listc */
752 s.restriction (point, s);
753 }
755 }
756 free (listdef);
757 free (listc);
758 free (list2);
759 }
760
761 scalar * listr = NULL;
762 vector * listf = NULL;
763 for (int _s = 0; _s < 1; _s++) /* scalar in list */
764 if (!is_constant (s) && s.refine != no_restriction) {
765 if (s.face)
766 listf = vectors_add (listf, s.v);
767 else
768 listr = list_add (listr, s);
769 }
770
771 if (listr || listf) {
773 for (int i = 0; i < depth; i++) {
774 foreach_halo (prolongation, i) {
775 for (int _s = 0; _s < 1; _s++) /* scalar in listr */
776 s.prolongation (point, s);
777 for (int _v = 0; _v < 1; _v++) /* vector in listf */
778 for (int _d = 0; _d < dimension; _d++)
779 v.x.prolongation (point, v.x);
780 }
782 }
783 free (listr);
784 free (listf);
785 }
786}
787
788double treex (Point point) {
789 if (level == 0)
790 return 0;
791#if dimension == 2
792 double i = 2*child.x - child.y;
793 if (i <= 1 && i >= -1) i = -i;
794#else
795 assert (false); // not implemented
796 double i = 0;
797#endif
798 return treex(parent) + i/(1 << 2*(level - 1));
799}
800
801double treey (Point point) {
802 if (level == 0)
803 return 0;
804 return treey(parent) + 4./(1 << 2*(level - 1));
805}
806
808{
809 for (int _i = 0; _i < _N; _i++) /* foreach_cell */
810 if (cell.neighbors)
811 for (int _c = 0; _c < 4; _c++) /* foreach_child */
812 if (is_local(cell))
813 fprintf (fp, "%g %g\n%g %g\n\n",
814 treex(parent), treey(parent), treex(point), treey(point));
815}
816
817trace
819{
820 // checks the consistency of the tree
821
822 long nleaves = 0, nactive = 0;
824 if (is_leaf(cell)) {
825 assert (cell.pid >= 0); // boundaries cannot be leaves
826 nleaves++;
827 }
828 if (is_local(cell))
830 if (is_active(cell))
831 nactive++;
832 // check number of refined neighbors
833 int neighbors = 0;
834 for (int _n = 0; _n < 1; _n++)
835 if (allocated(0) && is_refined(cell))
836 neighbors++;
837 assert (cell.neighbors == neighbors);
838
839 // checks that prolongation cells do not have children
840 if (!cell.neighbors)
842 }
843
844 // checks that all active cells are reachable
845 long reachable = 0;
846 for (int _i = 0; _i < _N; _i++) /* foreach_cell */ {
847 if (is_active(cell))
848 reachable++;
849 else
850 continue;
851 }
853
854 // checks that all leaf cells are reachable
855 reachable = 0;
856 for (int _i = 0; _i < _N; _i++) /* foreach_cell */
857 if (is_leaf(cell)) {
858 reachable++;
859 continue;
860 }
862}
863
864trace
865static void tree_restriction (scalar * list) {
866 boundary (list);
867 if (tree_is_full())
869}
870
#define dimension
Definition bitree.h:3
#define boundary_iterate(type,...)
Definition boundaries.h:40
define k
#define boundary(...)
void(* boundary_face)(vectorl)
define double double char flags
void(* boundary_level)(scalar *, int l)
define l
vector cartesian_init_face_vector(vector v, const char *name)
define m((k)==0 &&(l)==0 &&(m)==0) macro2 foreach_point(double _x=0.
define neighbor(o, p, q)((Point)
Definition cartesian.h:146
#define GHOSTS
Definition cartesian.h:13
free(list1)
define VT _attribute[s.i] v y scalar * list
Definition cartesian.h:276
int x
Definition common.h:76
vector(* init_vector)(vector, const char *)
Definition common.h:349
scalar(* init_vertex_scalar)(scalar, const char *)
Definition common.h:348
scalar * all
Definition common.h:342
const scalar cm[]
Definition common.h:397
vector * vectors_add(vector *list, vector v)
Definition common.h:267
#define nodata
Definition common.h:7
scalar * list_concat(scalar *l1, scalar *l2)
Definition common.h:234
scalar * list_add(scalar *list, scalar s)
Definition common.h:208
tensor(* init_tensor)(tensor, const char *)
Definition common.h:351
scalar * list_copy(scalar *l)
Definition common.h:225
vector(* init_face_vector)(vector, const char *)
Definition common.h:350
scalar * list_append(scalar *list, scalar s)
Definition common.h:188
scalar(* init_scalar)(scalar, const char *)
Definition common.h:347
const vector fm[]
Definition common.h:396
#define p
Definition tree.h:320
#define assert(a)
Definition config.h:107
Point point
Definition conserving.h:86
else fine(fs.x, 1, 0)
*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
double t
Definition events.h:24
macro2 foreach_cell_all()
#define depth()
Definition cartesian.h:14
macro
We also redefine the "per field" (inner) traversal.
Definition layers.h:18
size_t max
Definition mtrace.h:8
size_t nr
Definition mtrace.h:10
FILE * fp
Definition mtrace.h:7
static scalar multigrid_init_scalar(scalar s, const char *name)
static trace void multigrid_restriction(scalar *list)
static vector multigrid_init_vector(vector v, const char *name)
static scalar multigrid_init_vertex_scalar(scalar s, const char *name)
void multigrid_methods()
void(* restriction)(Point, scalar)
static void restriction_face(Point point, scalar s)
static void restriction_average(Point point, scalar s)
static tensor multigrid_init_tensor(tensor t, const char *name)
static void restriction_vertex(Point point, scalar s)
static void no_restriction(Point point, scalar s)
size *double * b
int int int level
define is_active() cell(true) @define is_leaf(cell)(point.level
def _i
Definition stencils.h:405
@ s_face
Definition stencils.h:20
Definition tree.h:109
Definition linear.h:21
int level
Definition linear.h:23
int i
Definition linear.h:23
int i
Definition common.h:44
static scalar tree_init_scalar(scalar s, const char *name)
static scalar tree_init_vertex_scalar(scalar s, const char *name)
static tensor tree_init_tensor(tensor t, const char *name)
void refine_face_solenoidal(Point point, scalar s)
static void prolongation_vertex(Point point, scalar s)
trace void tree_check()
void mpi_boundary_refine(scalar *)
Definition tree-mpi.h:1020
static scalar * list_add_depend(scalar *list, scalar s)
void coarsen_cell_recursive(Point point, scalar *list)
void mpi_boundary_update(scalar *)
Definition balance.h:396
bool coarsen_cell(Point point, scalar *list)
static trace void tree_boundary_level(scalar *list, int l)
#define periodic_clamp(a, level)
Definition tree-common.h:16
void mpi_boundary_coarsen(int, int)
Definition tree-mpi.h:1132
void refine_face(Point point, scalar s)
attribute
Definition tree-common.h:10
double treey(Point point)
static void refine_level(int depth)
static vector tree_init_vector(vector v, const char *name)
void tree_methods()
int refine_cell(Point point, scalar *list, int flag, Cache *refined)
Definition tree-common.h:23
void output_tree(FILE *fp)
macro refine(bool cond)
trace astats adapt_wavelet(scalar *slist, double *max, int maxlevel, int minlevel=1, scalar *list=all)
scalar s
static vector tree_init_face_vector(vector v, const char *name)
static trace void halo_face(vectorl vl)
macro unrefine(bool cond)
double treex(Point point)
static trace void tree_restriction(scalar *list)
static void tree_setup_vector(vector v)
def is_refined_check()((!is_leaf(cell) &&cell .neighbors &&cell .pid >=0) &&point.i > 0 &&point.i<(1<< level)+2 *2 - 1 &&point.j > 0 &&point.j<(1<< level)+2 *2 - 1) @ macro2 for(int _i=0
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 is_prolongation(cell)
Definition tree.h:411
#define foreach_halo(type, l)
Definition tree.h:514
void decrement_neighbors(Point point)
Definition tree.h:1054
static void cache_append(Cache *c, Point p, unsigned short flags)
Definition tree.h:215
#define is_refined(cell)
Definition tree.h:410
#define tree
Definition tree.h:184
@ user
Definition tree.h:63
@ active
Definition tree.h:59
@ leaf
Definition tree.h:60
@ border
Definition tree.h:61
bool tree_is_full()
Definition tree.h:1665
void increment_neighbors(Point point)
Definition tree.h:1043
#define is_boundary(cell)
Definition tree.h:412