Basilisk CFD
Adaptive Cartesian mesh PDE framework
Loading...
Searching...
No Matches
multigrid-common.h
Go to the documentation of this file.
1/** @file multigrid-common.h
2 */
3#define MULTIGRID 1
4
5#include "variables.h"
6#include "cartesian-common.h"
7
8auto macro2 for (int _i = 0; _i < int l, char flags = 0, Reduce reductions = None; _i++)
9{
10 for (int _l = 0; _l < l, flags, reductions; _l++)
11 {...}
12}
13
14auto macro2 for (int _l = 0; _l < int l, char flags = 0, Reduce reductions = None; _l++)
15{
16 for (int _l = 0; _l < l, flags, reductions; _l++)
17 {...}
18}
19
20// scalar attributes
21
23 void (* prolongation) (Point, scalar);
25}
26
27void set_prolongation (scalar s, void (* prolongation) (Point, scalar))
28{
29 s.prolongation = prolongation;
31}
32
34{
35 s.restriction = restriction;
37}
38
39// Multigrid methods
40
41void (* restriction) (scalar *);
42
43static inline void restriction_average (Point point, scalar s)
44{
45 /* foreach_blockf */ {
46 double sum = 0.;
47 for (int _c = 0; _c < 4; _c++) /* foreach_child */
48 sum += s[];
49 s[] = sum/(1 << dimension);
50 }
51}
52
54{
55 /* foreach_blockf */ {
56 double sum = 0.;
57 for (int _c = 0; _c < 4; _c++) /* foreach_child */
58 sum += cm[]*s[];
59 s[] = sum/(1 << dimension)/(cm[] + 1e-30);
60 }
61}
62
63static inline void face_average (Point point, vector v)
64{
65 for (int _d = 0; _d < dimension; _d++)
66 /* foreach_blockf */ {
67 #if dimension == 1
68 v.x[] = fine(v.x,0);
69 v.x[1] = fine(v.x,2);
70 #elif dimension == 2
71 v.x[] = (fine(v.x,0,0) + fine(v.x,0,1))/2.;
72 v.x[1] = (fine(v.x,2,0) + fine(v.x,2,1))/2.;
73 #else // dimension == 3
74 v.x[] = (fine(v.x,0,0,0) + fine(v.x,0,1,0) +
75 fine(v.x,0,0,1) + fine(v.x,0,1,1))/4.;
76 v.x[1] = (fine(v.x,2,0,0) + fine(v.x,2,1,0) +
77 fine(v.x,2,0,1) + fine(v.x,2,1,1))/4.;
78 #endif
79 }
80}
81
82static inline void restriction_face (Point point, scalar s)
83{
84 face_average (point, s.v);
85}
86
87static inline void restriction_vertex (Point point, scalar s)
88{
89 /* foreach_blockf */
90 for (int i = 0; i <= 1; i++) {
91 s[i] = fine(s,2*i);
92#if dimension >= 2
93 s[i,1] = fine(s,2*i,2);
94#endif
95#if dimension >= 3
96 for (int j = 0; j <= 1; j++)
97 s[i,j,1] = fine(s,2*i,2*j,2);
98#endif
99 }
100}
101
102static inline void no_restriction (Point point, scalar s) {}
103
104static inline void no_data (Point point, scalar s) {
105 for (int _c = 0; _c < 4; _c++) /* foreach_child */
106 /* foreach_blockf */
107 s[] = nodata;
108}
109
111{
112 restriction ({s});
113 for (int l = grid->maxdepth - 1; l >= 0; l--) {
114 for (int _l = 0; _l < l, nowarning; _l++) {
115 for (int _c = 0; _c < 4; _c++) /* foreach_child */
116 w[] = s[];
117 s.prolongation (point, s);
118 for (int _c = 0; _c < 4; _c++) /* foreach_child */ {
119 double sp = s[];
120 s[] = w[];
121 /* difference between fine value and its prolongation */
122 w[] -= sp;
123 }
124 }
125 boundary_level ({w}, l + 1);
126 }
127 /* root cell */
128 for (int _l = 0; _l < 0; _l++)
129 w[] = s[];
130 boundary_level ({w}, 0);
131}
132
134{
135 for (int _l = 0; _l < 0; _l++)
136 s[] = w[];
137 boundary_level ({s}, 0);
138 for (int l = 0; l <= grid->maxdepth - 1; l++) {
139 for (int _l = 0; _l < l, nowarning; _l++) {
140 s.prolongation (point, s);
141 for (int _c = 0; _c < 4; _c++) /* foreach_child */
142 s[] += w[];
143 }
144 boundary_level ({s}, l + 1);
145 }
146}
147
148static inline double bilinear (Point point, scalar s)
149{
150 #if dimension == 1
151 return (3.*coarse(s) + coarse(s,child.x))/4.;
152 #elif dimension == 2
153 return (9.*coarse(s) +
154 3.*(coarse(s,child.x) + coarse(s,0,child.y)) +
155 coarse(s,child.x,child.y))/16.;
156 #else // dimension == 3
157 return (27.*coarse(s) +
158 9.*(coarse(s,child.x) + coarse(s,0,child.y) +
159 coarse(s,0,0,child.z)) +
160 3.*(coarse(s,child.x,child.y) + coarse(s,child.x,0,child.z) +
161 coarse(s,0,child.y,child.z)) +
162 coarse(s,child.x,child.y,child.z))/64.;
163 #endif
164}
165
166static inline void refine_bilinear (Point point, scalar s)
167{
168 for (int _c = 0; _c < 4; _c++) /* foreach_child */
169 /* foreach_blockf */
170 s[] = bilinear (point, s);
171}
172
173static inline double quadratic (double a, double b, double c)
174{
175 return (30.*a + 5.*b - 3.*c)/32.;
176}
177
178static inline double biquadratic (Point point, scalar s)
179{
180#if dimension == 1
181 return quadratic (coarse(s,0), coarse(s,child.x), coarse(s,-child.x));
182#elif dimension == 2
183 return
185 coarse(s,child.x,0),
186 coarse(s,-child.x,0)),
187 quadratic (coarse(s,0,child.y),
188 coarse(s,child.x,child.y),
189 coarse(s,-child.x,child.y)),
190 quadratic (coarse(s,0,-child.y),
191 coarse(s,child.x,-child.y),
192 coarse(s,-child.x,-child.y)));
193#else // dimension == 3
194 assert (false);
195 return 0.;
196#endif
197}
198
199static inline double biquadratic_vertex (Point point, scalar s)
200{
201#if dimension == 1
202 return (6.*s[] + 3.*s[-1] - s[1])/8.;
203#elif dimension == 2
204 return (36.*s[] + 18.*(s[-1] + s[0,-1]) - 6.*(s[1] + s[0,1]) +
205 9.*s[-1,-1] - 3.*(s[1,-1] + s[-1,1]) + s[1,1])/64.;
206#elif dimension == 3
207 assert (false);
208 return 0.;
209#endif
210}
211
212static inline void refine_biquadratic (Point point, scalar s)
213{
214 for (int _c = 0; _c < 4; _c++) /* foreach_child */
215 /* foreach_blockf */
216 s[] = biquadratic (point, s);
217}
218
220{
221 coord g;
222 if (s.gradient)
223 for (int _d = 0; _d < dimension; _d++)
224 g.x = s.gradient (s[-1], s[], s[1]);
225 else
226 for (int _d = 0; _d < dimension; _d++)
227 g.x = (s[1] - s[-1])/2.;
228
229 double sc = s[], cmc = 4.*cm[], sum = cm[]*(1 << dimension);
230 for (int _c = 0; _c < 4; _c++) /* foreach_child */ {
231 s[] = sc;
232 for (int _d = 0; _d < dimension; _d++)
233 s[] += child.x*g.x*cm[-child.x]/cmc;
234 sum -= cm[];
235 }
236 assert (fabs(sum) < 1e-10);
237}
238
239static inline void refine_linear (Point point, scalar s)
240{
241 /* foreach_blockf */
243}
244
245static inline void refine_reset (Point point, scalar v)
246{
247 for (int _c = 0; _c < 4; _c++) /* foreach_child */
248 /* foreach_blockf */
249 v[] = 0.;
250}
251
252static inline void refine_injection (Point point, scalar v)
253{
254 double val = v[];
255 for (int _c = 0; _c < 4; _c++) /* foreach_child */
256 /* foreach_blockf */
257 v[] = val;
258}
259
260static scalar multigrid_init_scalar (scalar s, const char * name)
261{
262 s = cartesian_init_scalar (s, name);
263 s.prolongation = refine_bilinear;
264 s.restriction = restriction_average;
265 return s;
266}
267
268static scalar multigrid_init_vertex_scalar (scalar s, const char * name)
269{
271 s.restriction = restriction_vertex;
272 return s;
273}
274
276{
277 for (int _d = 0; _d < dimension; _d++) {
278 v.x.prolongation = refine_bilinear;
279 v.x.restriction = restriction_average;
280 }
281}
282
283static vector multigrid_init_vector (vector v, const char * name)
284{
285 v = cartesian_init_vector (v, name);
287 return v;
288}
289
290static vector multigrid_init_face_vector (vector v, const char * name)
291{
293 for (int _d = 0; _d < dimension; _d++)
294 v.y.restriction = no_restriction;
295 v.x.restriction = restriction_face;
296 return v;
297}
298
299static tensor multigrid_init_tensor (tensor t, const char * name)
300{
301 t = cartesian_init_tensor (t, name);
302 for (int _d = 0; _d < dimension; _d++)
304 return t;
305}
306
308{
310
311 FILE * plot = fopen ("plot", "a");
312 if (point.level > 0) {
313 char name[80] = "coarse";
314 if (pid() > 0)
315 sprintf (name, "coarse-%d", pid());
316 FILE * fp = fopen (name, "w");
317 #if dimension == 1
318 double xc = x - child.x*Delta/2.;
319 for (int k = 0; k <= 1; k++)
320 for (int _v = 0; _v < 1; _v++) /* scalar in all */
321 fprintf (fp, "%g %g ",
322 xc + k*child.x*Delta*2. + v.d.x*Delta,
323 coarse(v,k*child.x));
324 fputc ('\n', fp);
325 fprintf (stderr, ", '%s' u 1+2*v:(0):2+2*v w labels tc lt 3 t ''", name);
326 fprintf (plot, ", '%s' u 1+2*v:(0):2+2*v w labels tc lt 3 t ''", name);
327 #elif dimension == 2
328 double xc = x - child.x*Delta/2., yc = y - child.y*Delta/2.;
329 for (int k = 0; k <= 1; k++)
330 for (int l = 0; l <= 1; l++) {
331 for (int _v = 0; _v < 1; _v++) /* scalar in all */
332 fprintf (fp, "%g %g %g ",
333 xc + k*child.x*Delta*2. + v.d.x*Delta,
334 yc + l*child.y*Delta*2. + v.d.y*Delta,
335 coarse(v,k*child.x,l*child.y));
336 fputc ('\n', fp);
337 }
338 fprintf (stderr, ", '%s' u 1+3*v:2+3*v:3+3*v w labels tc lt 3 t ''", name);
339 fprintf (plot, ", '%s' u 1+3*v:2+3*v:3+3*v w labels tc lt 3 t ''", name);
340 #elif dimension == 3
341 double xc = x - child.x*Delta/2., yc = y - child.y*Delta/2.;
342 double zc = z - child.z*Delta/2.;
343 for (int k = 0; k <= 1; k++)
344 for (int l = 0; l <= 1; l++)
345 for (int m = 0; m <= 1; m++) {
346 for (int _v = 0; _v < 1; _v++) /* scalar in all */
347 fprintf (fp, "%g %g %g %g ",
348 xc + k*child.x*Delta*2. + v.d.x*Delta,
349 yc + l*child.y*Delta*2. + v.d.y*Delta,
350 zc + m*child.z*Delta*2. + v.d.z*Delta,
351 coarse(v,k*child.x,l*child.y,m*child.z));
352 fputc ('\n', fp);
353 }
354 fprintf (stderr, ", '%s' u 1+4*v:2+4*v:3+4*v:4+4*v w labels tc lt 3 t ''",
355 name);
356 fprintf (plot, ", '%s' u 1+4*v:2+4*v:3+4*v:4+4*v w labels tc lt 3 t ''",
357 name);
358 #endif
359 fclose (fp);
360 }
361
362 if (is_coarse()) {
363 char name[80] = "fine";
364 if (pid() > 0)
365 sprintf (name, "fine-%d", pid());
366 FILE * fp = fopen (name, "w");
367 #if dimension == 1
368 double xf = x - Delta/4.;
369 for (int k = -2; k <= 3; k++)
370 for (int _v = 0; _v < 1; _v++) /* scalar in all */ {
371 fprintf (fp, "%g ", xf + k*Delta/2. + v.d.x*Delta/4.);
372 if (allocated_child(k))
373 fprintf (fp, "%g ", fine(v,k));
374 else
375 fputs ("n/a ", fp);
376 }
377 fputc ('\n', fp);
378 fprintf (stderr, ", '%s' u 1+2*v:(0):2+2*v w labels tc lt 2 t ''", name);
379 fprintf (plot, ", '%s' u 1+2*v:(0):2+2*v w labels tc lt 2 t ''", name);
380 #elif dimension == 2
381 double xf = x - Delta/4., yf = y - Delta/4.;
382 for (int k = -2; k <= 3; k++)
383 for (int l = -2; l <= 3; l++) {
384 for (int _v = 0; _v < 1; _v++) /* scalar in all */ {
385 fprintf (fp, "%g %g ",
386 xf + k*Delta/2. + v.d.x*Delta/4.,
387 yf + l*Delta/2. + v.d.y*Delta/4.);
388 if (allocated_child(k,l))
389 fprintf (fp, "%g ", fine(v,k,l));
390 else
391 fputs ("n/a ", fp);
392 }
393 fputc ('\n', fp);
394 }
395 fprintf (stderr, ", '%s' u 1+3*v:2+3*v:3+3*v w labels tc lt 2 t ''", name);
396 fprintf (plot, ", '%s' u 1+3*v:2+3*v:3+3*v w labels tc lt 2 t ''", name);
397 #elif dimension == 3
398 double xf = x - Delta/4., yf = y - Delta/4., zf = z - Delta/4.;
399 for (int k = -2; k <= 3; k++)
400 for (int l = -2; l <= 3; l++)
401 for (int m = -2; m <= 3; m++) {
402 for (int _v = 0; _v < 1; _v++) /* scalar in all */ {
403 fprintf (fp, "%g %g %g ",
404 xf + k*Delta/2. + v.d.x*Delta/4.,
405 yf + l*Delta/2. + v.d.y*Delta/4.,
406 zf + m*Delta/2. + v.d.z*Delta/4.);
407 if (allocated_child(k,l,m))
408 fprintf (fp, "%g ", fine(v,k,l,m));
409 else
410 fputs ("n/a ", fp);
411 }
412 fputc ('\n', fp);
413 }
414 fprintf (stderr, ", '%s' u 1+4*v:2+4*v:3+4*v:4+4*v w labels tc lt 2 t ''",
415 name);
416 fprintf (plot, ", '%s' u 1+4*v:2+4*v:3+4*v:4+4*v w labels tc lt 2 t ''",
417 name);
418 #endif
419 fclose (fp);
420 }
421 fflush (stderr);
422 fclose (plot);
423}
424
425trace
427{
428 scalar * listdef = NULL, * listc = NULL, * list2 = NULL;
429 for (int _s = 0; _s < 1; _s++) /* scalar in list */
430 if (!is_constant (s) && s.block > 0 && !(s.stencil.bc & s_restriction)) {
431 if (s.restriction == restriction_average) {
433 list2 = list_add (list2, s);
434 }
435 else if (s.restriction != no_restriction) {
436 listc = list_add (listc, s);
437 if (s.face)
438 for (int _d = 0; _d < dimension; _d++)
439 list2 = list_add (list2, s.v.x);
440 else
441 list2 = list_add (list2, s);
442 }
443 }
444
445 if (listdef || listc) {
446 for (int l = depth() - 1; l >= 0; l--) {
447 for (int _l = 0; _l < l, nowarning; _l++) {
448 for (int _s = 0; _s < 1; _s++) /* scalar in listdef */
450 for (int _s = 0; _s < 1; _s++) /* scalar in listc */
451 s.restriction (point, s);
452 }
454 }
455 free (listdef);
456 free (listc);
457 for (int _s = 0; _s < 1; _s++) /* scalar in list2 */
458 s.stencil.bc |= s_restriction;
459 free (list2);
460 }
461}
462
474
475/**
476## Size of subtrees
477
478The function below store in *size* the number of cells (or leaves if
479*leaves* is set to *true*) of each subtree. */
480
482{
483
484 /**
485 The size of leaf "subtrees" is one. */
486
487 for (int _i = 0; _i < _N; _i++) /* foreach */
488 size[] = 1;
489
490 /**
491 We do a (parallel) restriction to compute the size of non-leaf
492 subtrees. */
493
495 for (int l = depth() - 1; l >= 0; l--) {
496 for (int _l = 0; _l < l; _l++) {
497 double sum = !leaves;
498 for (int _c = 0; _c < 4; _c++) /* foreach_child */
499 sum += size[];
500 size[] = sum;
501 }
503 }
504}
vector g[]
We store the combined pressure gradient and acceleration field in g*.
Definition all-mach.h:65
const vector a
Definition all-mach.h:59
if TRASH define &&NewPid *& val(newpid, 0, 0, 0)) -> pid > 0) @else @ define is_newpid()(((NewPid *)&val(newpid, 0, 0, 0)) ->pid > 0) @endif Array *linear_tree(size_t size, scalar newpid)
Definition balance.h:13
bool leaves
Definition balance.h:193
#define dimension
Definition bitree.h:3
#define boundary_iterate(type,...)
Definition boundaries.h:40
define k
void cartesian_debug(Point point)
scalar cartesian_init_vertex_scalar(scalar s, const char *name)
tensor cartesian_init_tensor(tensor t, const char *name)
define double double char flags
vector cartesian_init_vector(vector v, const char *name)
void(* boundary_level)(scalar *, int l)
scalar cartesian_init_scalar(scalar s, const char *name)
void cartesian_methods()
define l
vector cartesian_init_face_vector(vector v, const char *name)
define double double char Reduce reductions
define m((k)==0 &&(l)==0 &&(m)==0) macro2 foreach_point(double _x=0.
free(list1)
define VT _attribute[s.i] v y scalar * list
Definition cartesian.h:276
int y
Definition common.h:76
int x
Definition common.h:76
int z
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
const scalar cm[]
Definition common.h:397
#define nodata
Definition common.h:7
scalar * list_add(scalar *list, scalar s)
Definition common.h:208
tensor(* init_tensor)(tensor, const char *)
Definition common.h:351
Grid * grid
Definition common.h:32
vector(* init_face_vector)(vector, const char *)
Definition common.h:350
scalar(* init_scalar)(scalar, const char *)
Definition common.h:347
vector w[]
#define assert(a)
Definition config.h:107
Point point
Definition conserving.h:86
#define debug(...)
Definition display.h:82
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
scalar int i
Definition embed.h:74
#define quadratic(x, a1, a2, a3)
Definition embed.h:373
double t
Definition events.h:24
#define depth()
Definition cartesian.h:14
double * sum
FILE * fp
Definition mtrace.h:7
static void restriction_volume_average(Point point, scalar s)
static double biquadratic(Point point, scalar s)
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 void face_average(Point point, vector v)
static scalar multigrid_init_vertex_scalar(scalar s, const char *name)
void inverse_wavelet(scalar s, scalar w)
void wavelet(scalar s, scalar w)
void multigrid_methods()
void(* restriction)(Point, scalar)
static void restriction_face(Point point, scalar s)
static void refine_reset(Point point, scalar v)
static void refine_bilinear(Point point, scalar s)
static void restriction_average(Point point, scalar s)
static void refine_injection(Point point, scalar v)
static void refine_linear(Point point, scalar s)
static void refine_biquadratic(Point point, scalar s)
void set_prolongation(scalar s, void(*prolongation)(Point, scalar))
static tensor multigrid_init_tensor(tensor t, const char *name)
void set_restriction(scalar s, void(*restriction)(Point, scalar))
attribute
static void restriction_vertex(Point point, scalar s)
void multigrid_debug(Point point)
static void multigrid_setup_vector(vector v)
static vector multigrid_init_face_vector(vector v, const char *name)
static void no_restriction(Point point, scalar s)
static void refine_linear_single(Point point, scalar s)
static double biquadratic_vertex(Point point, scalar s)
static void no_data(Point point, scalar s)
static double bilinear(Point point, scalar s)
void subtree_size(scalar size, bool leaves)
size_t size
size *double * b
int int int level
def _i
Definition stencils.h:405
static void set_dirty_stencil(scalar s)
Definition stencils.h:34
@ s_restriction
Definition stencils.h:21
int maxdepth
Definition common.h:30
Definition linear.h:21
int level
Definition linear.h:23
Definition common.h:78
scalar x
Definition common.h:47
define n n define coarse(a, k, p, n)((double *)(PARENT(k
scalar c
Definition vof.h:57
src vof fflush(ferr)