Basilisk CFD
Adaptive Cartesian mesh PDE framework
Loading...
Searching...
No Matches
curvature.h
Go to the documentation of this file.
1/** @file curvature.h
2 */
3/**
4# Curvature of an interface
5
6The curvature field is defined only in interfacial cells. In all the
7other cells it takes the value *nodata*.
8
9On trees, we need to redefine the restriction function to take
10this into account i.e. the curvature of the parent cell is the average
11of the curvatures in the interfacial child cells. */
12
13#if TREE
15{
16 double k = 0., s = 0.;
17 for (int _c = 0; _c < 4; _c++) /* foreach_child */
18 if (kappa[] != nodata)
19 k += kappa[], s++;
20 kappa[] = s ? k/s : nodata;
21}
22
23/**
24The prolongation function performs a similar averaging, but using the
25same stencil as that used for bilinear interpolation, so that the
26symmetries of the volume fraction field and curvature field are
27preserved. */
28
30{
31 for (int _c = 0; _c < 4; _c++) /* foreach_child */ {
32 double sk = 0., s = 0.;
33 for (int i = 0; i <= 1; i++)
34 #if dimension > 1
35 for (int j = 0; j <= 1; j++)
36 #endif
37 #if dimension > 2
38 for (int k = 0; k <= 1; k++)
39 #endif
40 if (coarse(kappa,child.x*i,child.y*j,child.z*k) != nodata)
41 sk += coarse(kappa,child.x*i,child.y*j,child.z*k), s++;
42 kappa[] = s ? sk/s : nodata;
43 }
44}
45#endif // TREE
46
47#if dimension > 1
48
49/**
50## Height-function curvature and normal
51
52To compute the curvature, we estimate the derivatives of the height
53functions in a given direction (*x*, *y* or *z*). We first check that
54all the heights are defined and that their orientations are the
55same. We then compute the curvature as
56\f[
57\kappa = \frac{h_{xx}}{(1 + h_x^2)^{3/2}}
58\f]
59in two dimensions, or
60\f[
61\kappa = \frac{h_{xx}(1 + h_y^2) + h_{yy}(1 + h_x^2) - 2h_{xy}h_xh_y}
62{(1 + h_x^2 + h_y^2)^{3/2}}
63\f]
64in three dimensions.
65
66The normal is computed in a similar way, but also allowing for
67asymmetric 2-points stencils and taking into account the
68orientation. */
69
70#include "heights.h"
71
72#if dimension == 2
73for (int _d = 0; _d < dimension; _d++)
74static double kappa_y (Point point, vector h)
75{
76 int ori = orientation(h.y[]);
77 for (int i = -1; i <= 1; i++)
78 if (h.y[i] == nodata || orientation(h.y[i]) != ori)
79 return nodata;
80 double hx = (h.y[1] - h.y[-1])/2.;
81 double hxx = (h.y[1] + h.y[-1] - 2.*h.y[])/Delta;
82 return hxx/pow(1. + sq(hx), 3/2.);
83}
84
85for (int _d = 0; _d < dimension; _d++)
87{
89 if (h.y[] == nodata)
90 return n;
91 int ori = orientation(h.y[]);
92 if (h.y[-1] != nodata && orientation(h.y[-1]) == ori) {
93 if (h.y[1] != nodata && orientation(h.y[1]) == ori)
94 n.x = (h.y[-1] - h.y[1])/2.;
95 else
96 n.x = h.y[-1] - h.y[];
97 }
98 else if (h.y[1] != nodata && orientation(h.y[1]) == ori)
99 n.x = h.y[] - h.y[1];
100 else
101 return n;
102 double nn = (ori ? -1. : 1.)*sqrt(1. + sq(n.x));
103 n.x /= nn;
104 n.y = 1./nn;
105 return n;
106}
107#else // dimension == 3
108for (int _d = 0; _d < dimension; _d++)
109static double kappa_z (Point point, vector h)
110{
111 int ori = orientation(h.z[]);
112 for (int i = -1; i <= 1; i++)
113 for (int j = -1; j <= 1; j++)
114 if (h.z[i,j] == nodata || orientation(h.z[i,j]) != ori)
115 return nodata;
116 double hx = (h.z[1] - h.z[-1])/2.;
117 double hy = (h.z[0,1] - h.z[0,-1])/2.;
118
119 /**
120 We "filter" the curvature using a weighted sum of the three
121 second-derivatives in the \f$x\f$ and \f$y\f$ directions. This is necessary
122 to avoid a numerical mode when the curvature is used to compute
123 surface tension. */
124
125 double filter = 0.2;
126 double hxx = (filter*(h.z[1,1] + h.z[-1,1] - 2.*h.z[0,1]) +
127 (h.z[1] + h.z[-1] - 2.*h.z[]) +
128 filter*(h.z[1,-1] + h.z[-1,-1] - 2.*h.z[0,-1]))/
129 ((1. + 2.*filter)*Delta);
130 double hyy = (filter*(h.z[1,1] + h.z[1,-1] - 2.*h.z[1]) +
131 (h.z[0,1] + h.z[0,-1] - 2.*h.z[]) +
132 filter*(h.z[-1,1] + h.z[-1,-1] - 2.*h.z[-1]))/
133 ((1. + 2.*filter)*Delta);
134 double hxy = (h.z[1,1] + h.z[-1,-1] - h.z[1,-1] - h.z[-1,1])/(4.*Delta);
135 return (hxx*(1. + sq(hy)) + hyy*(1. + sq(hx)) - 2.*hxy*hx*hy)/
136 pow(1. + sq(hx) + sq(hy), 3/2.);
137}
138
139for (int _d = 0; _d < dimension; _d++)
141{
142 scalar hz = h.z;
143 if (hz[] == nodata)
144 return (coord){nodata, nodata, nodata};
145 int ori = orientation(hz[]);
146 double a = ori ? -1. : 1.;
147 coord n;
148 n.z = a;
150 if (allocated(-1) && hz[-1] != nodata && orientation(hz[-1]) == ori) {
151 if (allocated(1) && hz[1] != nodata && orientation(hz[1]) == ori)
152 n.x = a*(hz[-1] - hz[1])/2.;
153 else
154 n.x = a*(hz[-1] - hz[]);
155 }
156 else if (allocated(1) && hz[1] != nodata && orientation(hz[1]) == ori)
157 n.x = a*(hz[] - hz[1]);
158 else
159 n.x = nodata;
160 }
161 return n;
162}
163
164for (int _d = 0; _d < dimension; _d++)
165static coord normal_z (Point point, vector h) {
166 coord n = normal2_z (point, h);
167 double nn = fabs(n.x) + fabs(n.y) + fabs(n.z);
168 if (nn < nodata) {
169 for (int _d = 0; _d < dimension; _d++)
170 n.x /= nn;
171 return n;
172 }
173 return (coord){nodata, nodata, nodata};
174}
175#endif
176
177/**
178We now need to choose one of the \f$x\f$, \f$y\f$ or \f$z\f$ height functions to
179compute the curvature. This is done by the function below which
180returns the HF curvature given a volume fraction field *c* and a
181height function field *h*. */
182
184{
185
186 /**
187 We first define pairs of normal coordinates *n* (computed by simple
188 differencing of *c*) and corresponding HF curvature function *kappa*
189 (defined above). */
190
191 typedef struct {
192 double n;
193 double (* kappa) (Point, vector);
194 } NormKappa;
195 struct { NormKappa x, y, z; } n;
196 for (int _d = 0; _d < dimension; _d++)
197 n.x.n = c[1] - c[-1], n.x.kappa = kappa_x;
199
200 /**
201 We sort these pairs in decreasing order of \f$|n|\f$. */
202
203 if (fabs(n.x.n) < fabs(n.y.n))
204 swap (NormKappa, n.x, n.y);
205#if dimension == 3
206 if (fabs(n.x.n) < fabs(n.z.n))
207 swap (NormKappa, n.x, n.z);
208 if (fabs(n.y.n) < fabs(n.z.n))
209 swap (NormKappa, n.y, n.z);
210#endif
211
212 /**
213 We try each curvature function in turn. */
214
215 double kappa = nodata;
216 for (int _d = 0; _d < dimension; _d++)
217 if (kappa == nodata) {
218 kappa = n.x.kappa (point, h);
219 if (kappa != nodata) {
220 kappaf = n.x.kappa;
221 if (n.x.n < 0.)
222 kappa = - kappa;
223 }
224 }
225
226 if (kappa != nodata) {
227
228 /**
229 We limit the maximum curvature to \f$1/\Delta\f$. */
230
231 if (fabs(kappa) > 1./Delta)
233
234 /**
235 We add the axisymmetric curvature if necessary. */
236
237#if AXI
238 double nr, r = y, hx;
239 if (kappaf == kappa_x) {
240 hx = (height(h.x[0,1]) - height(h.x[0,-1]))/2.;
241 nr = hx*(orientation(h.x[]) ? 1 : -1);
242 }
243 else {
244 r += height(h.y[])*Delta;
245 hx = (height(h.y[1,0]) - height(h.y[-1,0]))/2.;
246 nr = orientation(h.y[]) ? -1 : 1;
247 }
248 /* limit the minimum radius to half the grid size */
249 kappa += nr/max (sqrt(1. + sq(hx))*r, Delta/2.);
250#endif
251 }
252
253 return kappa;
254}
255
256/**
257The function below works in a similar manner to return the normal
258estimated using height-functions (or a *nodata* vector if this cannot
259be done). */
260
262{
263
264 /**
265 We first define pairs of normal coordinates *n* (computed by simple
266 differencing of *c*) and corresponding normal function *normal*
267 (defined above). */
268
269 typedef struct {
270 double n;
271 coord (* normal) (Point, vector);
272 } NormNormal;
273 struct { NormNormal x, y, z; } n;
274 for (int _d = 0; _d < dimension; _d++)
275 n.x.n = c[1] - c[-1], n.x.normal = normal_x;
276
277 /**
278 We sort these pairs in decreasing order of \f$|n|\f$. */
279
280 if (fabs(n.x.n) < fabs(n.y.n))
281 swap (NormNormal, n.x, n.y);
282#if dimension == 3
283 if (fabs(n.x.n) < fabs(n.z.n))
284 swap (NormNormal, n.x, n.z);
285 if (fabs(n.y.n) < fabs(n.z.n))
286 swap (NormNormal, n.y, n.z);
287#endif
288
289 /**
290 We try each normal function in turn. */
291
293 for (int _d = 0; _d < dimension; _d++)
294 if (normal.x == nodata)
295 normal = n.x.normal (point, h);
296
297 return normal;
298}
299
300/**
301In three dimensions, these functions return the (two) components of
302the normal projected onto the $(x,y)$ plane (respectively). */
303
304#if dimension == 3
305for (int _d = 0; _d < dimension; _d++)
307{
308 coord nx = normal2_x (point, h);
309 coord ny = normal2_y (point, h);
310 if (fabs(nx.y) < fabs(ny.x)) {
311 normalize (&nx);
312 return nx;
313 }
314 else if (ny.x != nodata) {
315 normalize (&ny);
316 return ny;
317 }
318 return (coord){nodata, nodata, nodata};
319}
320#endif
321
322/**
323## Parabolic fit of "mixed" height-functions
324
325When the standard height function curvature calculation is not
326possible (for example because not enough heights are available in any
327given direction), one can try to combine all the available heights
328(thus using "mixed" directions) to obtain points on the
329interface. These point locations can then be fitted with a parabola
330(using least-mean-square optimisation) and the resulting curvature can
331be computed. The fitting functions are defined in the file included
332below. */
333
334#include "parabola.h"
335
336/**
337Given *n* (interface) point coordinates, this function returns the
338number of "independent" points i.e. points which are more than
339half-a-cell distant from all the other points. */
340
341static int independents (coord * p, int n)
342{
343 if (n < 2)
344 return n;
345 int ni = 1;
346 for (int j = 1; j < n; j++) {
347 bool depends = false;
348 for (int i = 0; i < j && !depends; i++) {
349 double d2 = 0.;
350 for (int _d = 0; _d < dimension; _d++)
351 d2 += sq(p[i].x - p[j].x);
352 depends = (d2 < sq(0.5));
353 }
354 ni += !depends;
355 }
356 return ni;
357}
358
359/**
360Given a volume fraction field *c* and a height function field *h*,
361this function returns the "mixed heights" parabola-fitted curvature
362(or *nodata* if the curvature cannot be computed). */
363
365{
366
367 /**
368 The coordinates of the interface points and the number of
369 interface points. */
370
371 coord ip[dimension == 2 ? 6 : 27];
372 int n = 0;
373
374 /**
375 We collect the points along all directions. */
376
377 for (int _d = 0; _d < dimension; _d++) {
378
379 /**
380 We don't want to mix heights with different orientations. We first
381 find the "dominant" orientation *ori*. */
382
383 int n1 = 0, n2 = 0;
384#if dimension == 2
385 for (int i = -1; i <= 1; i++)
386 if (h.y[i] != nodata) {
387 if (orientation(h.y[i])) n1++; else n2++;
388 }
389#else // dimension == 3
390 for (int i = -1; i <= 1; i++)
391 for (int j = -1; j <= 1; j++)
392 if (h.z[i,j] != nodata) {
393 if (orientation(h.z[i,j])) n1++; else n2++;
394 }
395#endif
396 int ori = (n1 > n2);
397
398 /**
399 We look for height-functions with the dominant orientation and
400 store the corresponding interface coordinates (relative to the
401 center of the cell and normalised by the cell size). */
402
403#if dimension == 2
404 for (int i = -1; i <= 1; i++)
405 if (h.y[i] != nodata && orientation(h.y[i]) == ori)
406 ip[n].x = i, ip[n++].y = height(h.y[i]);
407#else // dimension == 3
408 for (int i = -1; i <= 1; i++)
409 for (int j = -1; j <= 1; j++)
410 if (h.z[i,j] != nodata && orientation(h.z[i,j]) == ori)
411 ip[n].x = i, ip[n].y = j, ip[n++].z = height(h.z[i,j]);
412#endif
413 }
414
415 /**
416 If we don't have enough independent points, we cannot do the
417 parabolic fit. */
418
419 if (independents (ip, n) < (dimension == 2 ? 3 : 9))
420 return nodata;
421
422 /**
423 We recover the interface normal and the centroid of the interface
424 fragment and initialize the parabolic fit. */
425
426 coord m = mycs (point, c), fc;
427 double alpha = plane_alpha (c[], m);
428 double area = plane_area_center (m, alpha, &fc);
431#if dimension == 2
434#else // dimension == 3
435 parabola_fit_add (&fit, fc, area*100.);
436#endif
437
438 /**
439 We add the collected interface positions and compute the
440 curvature. */
441
442 for (int i = 0; i < n; i++)
443 parabola_fit_add (&fit, ip[i], 1.);
445 double kappa = parabola_fit_curvature (&fit, 2., NULL)/Delta;
446#if AXI
448#endif
449 return kappa;
450}
451
452/**
453## Parabolic fit of centroids
454
455If all else fails, we try a parabolic fit of interface centroids. */
456
458{
459
460 /**
461 We recover the interface normal and the centroid of the interface
462 fragment and initialize the parabolic fit. */
463
464 coord m = mycs (point, c), fc;
465 double alpha = plane_alpha (c[], m);
469
470 /**
471 We add the interface centroids in a \f$3^d\f$ neighborhood and compute
472 the curvature. */
473
474 coord r = {x,y,z};
475 for (int _n = 0; _n < 1; _n++)
476 if (c[] > 0. && c[] < 1.) {
477 coord m = mycs (point, c), fc;
478 double alpha = plane_alpha (c[], m);
479 double area = plane_area_center (m, alpha, &fc);
480 coord rn = {x,y,z};
481 for (int _d = 0; _d < dimension; _d++)
482 fc.x += (rn.x - r.x)/Delta;
484 }
486 double kappa = parabola_fit_curvature (&fit, 2., NULL)/Delta;
487#if AXI
489#endif
490 return kappa;
491}
492
493#endif // dimension > 1
494
495/**
496## General curvature computation
497
498We first need to define "interfacial cells" i.e. cells which contain
499an interface. A simple test would just be that the volume fraction is
500neither zero nor one. As usual things are more complicated because of
501round-off errors. They can cause the interface to be exactly aligned
502with cell boundaries, so that cells on either side of this interface
503have fractions exactly equal to zero or one. The function below takes
504this into account. */
505
506static inline bool interfacial (Point point, scalar c)
507{
508 if (c[] >= 1.) {
509 for (int i = -1; i <= 1; i += 2)
510 for (int _d = 0; _d < dimension; _d++)
511 if (c[i] <= 0.)
512 return true;
513 }
514 else if (c[] <= 0.) {
515 for (int i = -1; i <= 1; i += 2)
516 for (int _d = 0; _d < dimension; _d++)
517 if (c[i] >= 1.)
518 return true;
519 }
520 else // c[] > 0. && c[] < 1.
521 return true;
522 return false;
523}
524
525/**
526The function below computes the mean curvature *kappa* of the
527interface defined by the volume fraction *c*. It uses a combination of
528the methods above: statistics on the number of curvatures computed
529which each method is returned in a *cstats* data structure.
530
531The curvature is multiplied by *sigma* (default is one).
532
533If *add* is *true*, the curvature is added to field *kappa*. */
534
535typedef struct {
536 int h; // number of standard HF curvatures
537 int f; // number of parabolic fit HF curvatures
538 int a; // number of averaged curvatures
539 int c; // number of centroids fit curvatures
540} cstats;
541
542trace
544 double sigma = 1.[0], bool add = false)
545{
546 int sh = 0, sf = 0, sa = 0, sc = 0;
547
548 /**
549 On trees we set the prolongation and restriction functions for
550 the curvature. */
551
552#if TREE
553 kappa.refine = kappa.prolongation = curvature_prolongation;
554 kappa.restriction = curvature_restriction;
555#endif
556
557#if dimension > 1
558
559 vector ch = c.height, h = automatic (ch);
560 if (!ch.x.i)
561 heights (c, h);
562
563 /**
564 We first compute a temporary curvature *k*: a "clone" of
565 \f$\kappa\f$. */
566
567 scalar k[];
569
570 foreach(reduction(+:sh) reduction(+:sf)) {
571
572 /**
573 If we are not in an interfacial cell, we set \f$\kappa\f$ to *nodata*. */
574
575 if (!interfacial (point, c))
576 k[] = nodata;
577
578 /**
579 Otherwise we try the standard HF curvature calculation first, and
580 the "mixed heights" HF curvature second. */
581
582 else if ((k[] = height_curvature (point, c, h)) != nodata)
583 sh++;
584 else if ((k[] = height_curvature_fit (point, c, h)) != nodata)
585 sf++;
586 }
587
588 foreach (reduction(+:sa) reduction(+:sc)) {
589
590 /**
591 We then construct the final curvature field using either the
592 computed temporary curvature... */
593
594 double kf;
595 if (k[] < nodata)
596 kf = k[];
597 else if (interfacial (point, c)) {
598
599 /**
600 ...or the average of the curvatures in the \f$3^{d}\f$ neighborhood
601 of interfacial cells. */
602
603 double sk = 0., a = 0.;
604 for (int _n = 0; _n < 1; _n++)
605 if (k[] < nodata)
606 sk += k[], a++;
607 if (a > 0.)
608 kf = sk/a, sa++;
609 else
610
611 /**
612 Empty neighborhood: we try centroids as a last resort. */
613
615 }
616 else
617 kf = nodata;
618
619 /**
620 We add or set *kappa*. */
621
622 if (kf == nodata)
623 kappa[] = nodata;
624 else if (add)
625 kappa[] += sigma*kf;
626 else
627 kappa[] = sigma*kf;
628 }
629
630#else // dimension == 1
631 for (int _i = 0; _i < _N; _i++) /* foreach */ {
632 if (!interfacial (point, c))
633 kappa[] = nodata;
634 else {
635 double r = x + sign(c[-1] - c[1])*(clamp(c[],0.,1.) - 0.5)*Delta;
636 double p = r > 0. ? - 2.*sigma/r : 0.;
637 if (add)
638 kappa[] += p;
639 else
640 kappa[] = p;
641 }
642 }
643#endif // dimension == 1
644
645 return (cstats){sh, sf, sa, sc};
646}
647
648#if dimension > 1
649
650/**
651# Position of an interface
652
653This is similar to curvature but this time for the position of the
654interface, defined as
655\f[
656pos = \mathbf{G}\cdot(\mathbf{x} - \mathbf{Z})
657\f]
658with \f$\mathbf{G}\f$ and \f$\mathbf{Z}\f$ two vectors and \f$\mathbf{x}\f$ the
659coordinates of the interface.
660
661This is defined only in interfacial cells. In all the other cells it
662takes the value *nodata*.
663
664We first need a function to compute the position \f$\mathbf{x}\f$ of an
665interface. For accuracy, we first try to use height functions. */
666
667for (int _d = 0; _d < dimension; _d++)
668static double pos_x (Point point, vector h, coord * G, coord * Z)
669{
670 if (fabs(height(h.x[])) > 1.)
671 return nodata;
672 coord o = {x, y, z};
673 o.x += height(h.x[])*Delta;
674 double pos = 0.;
675 for (int _d = 0; _d < dimension; _d++)
676 pos += (o.x - Z->x)*G->x;
677 return pos;
678}
679
680/**
681We now need to choose one of the \f$x\f$, \f$y\f$ or \f$z\f$ height functions to
682compute the position. This is done by the function below which returns
683the HF position given a volume fraction field *f*, a height function
684field *h* and vectors *G* and *Z*. */
685
687 coord * G, coord * Z)
688{
689
690 /**
691 We first define pairs of normal coordinates *n* (computed by simple
692 differencing of *f*) and corresponding HF position function *pos*
693 (defined above). */
694
695 typedef struct {
696 double n;
697 double (* pos) (Point, vector, coord *, coord *);
698 } NormPos;
699 struct { NormPos x, y, z; } n;
700 for (int _d = 0; _d < dimension; _d++)
701 n.x.n = f[1] - f[-1], n.x.pos = pos_x;
702
703 /**
704 We sort these pairs in decreasing order of \f$|n|\f$. */
705
706 if (fabs(n.x.n) < fabs(n.y.n))
707 swap (NormPos, n.x, n.y);
708#if dimension == 3
709 if (fabs(n.x.n) < fabs(n.z.n))
710 swap (NormPos, n.x, n.z);
711 if (fabs(n.y.n) < fabs(n.z.n))
712 swap (NormPos, n.y, n.z);
713#endif
714
715 /**
716 We try each position function in turn. */
717
718 double pos = nodata;
719 for (int _d = 0; _d < dimension; _d++)
720 if (pos == nodata)
721 pos = n.x.pos (point, h, G, Z);
722
723 return pos;
724}
725
726#endif // dimension == 1
727
728/**
729The position() function fills field *pos* with
730\f[
731\mathbf{G}\cdot(\mathbf{x} - \mathbf{Z})
732\f]
733with \f$\mathbf{x}\f$ the position of the interface defined by \f$f\f$.
734
735If *add* is *true*, the position is added to *pos*. */
736
738 coord G = {0}, coord Z = {0}, bool add = false)
739{
740
741 /**
742 On trees we set the prolongation and restriction functions for
743 the position. */
744
745#if TREE
746 pos.refine = pos.prolongation = curvature_prolongation;
747 pos.restriction = curvature_restriction;
748#endif
749
750#if dimension > 1
751 vector fh = f.height, h = automatic (fh);
752 if (!fh.x.i)
753 heights (f, h);
754 for (int _i = 0; _i < _N; _i++) /* foreach */ {
755 if (interfacial (point, f)) {
756 double hp = height_position (point, f, h, &G, &Z);
757 if (hp == nodata) {
758
759 /**
760 If the height function is not defined, we use the centroid of
761 the reconstructed VOF interface. */
762
763 coord n = mycs (point, f), o = {x,y,z}, c;
764 double alpha = plane_alpha (f[], n);
766 hp = 0.;
767 for (int _d = 0; _d < dimension; _d++)
768 hp += (o.x + Delta*c.x - Z.x)*G.x;
769 }
770 if (add)
771 pos[] += hp;
772 else
773 pos[] = hp;
774 }
775 else
776 pos[] = nodata;
777 }
778#else // dimension == 1
779 for (int _i = 0; _i < _N; _i++) /* foreach */ {
780 if (interfacial (point, f)) {
781 double hp = x + sign(f[-1] - f[1])*(clamp(f[],0.,1.) - 0.5)*Delta;
782 hp = (hp - Z.x)*G.x;
783 if (add)
784 pos[] += hp;
785 else
786 pos[] = hp;
787 }
788 else
789 pos[] = nodata;
790 }
791#endif // dimension == 1
792}
const vector alpha
Definition all-mach.h:47
const vector a
Definition all-mach.h:59
#define dimension
Definition bitree.h:3
define k
define m((k)==0 &&(l)==0 &&(m)==0) macro2 foreach_point(double _x=0.
int z
Definition common.h:76
void(* scalar_clone)(scalar, scalar)
Definition common.h:352
#define nodata
Definition common.h:7
void normalize(coord *n)
Definition common.h:98
static number sq(number x)
Definition common.h:11
#define swap(type, a, b)
Definition common.h:19
#define vector(x)
Definition common.h:354
static number clamp(number x, number a, number b)
Definition common.h:15
static int sign(number x)
Definition common.h:13
scalar f[]
The primary fields are:
Definition two-phase.h:56
#define p
Definition tree.h:320
Point point
Definition conserving.h:86
double hx
Definition curvature.h:80
return hxx pow(1.+sq(hx), 3/2.)
trace cstats curvature(scalar c, scalar kappa, double sigma=1.[0], bool add=false)
Definition curvature.h:543
n x
Definition curvature.h:103
double pos
Definition curvature.h:674
static double height_curvature_fit(Point point, scalar c, vector h)
Given a volume fraction field c and a height function field h, this function returns the "mixed heigh...
Definition curvature.h:364
double hxx
Definition curvature.h:81
vector coord * G
Definition curvature.h:668
static double height_position(Point point, scalar f, vector h, coord *G, coord *Z)
We now need to choose one of the , or height functions to compute the position.
Definition curvature.h:686
static bool interfacial(Point point, scalar c)
Definition curvature.h:506
coord height_normal(Point point, scalar c, vector h)
The function below works in a similar manner to return the normal estimated using height-functions (o...
Definition curvature.h:261
vector h
Definition curvature.h:75
vector coord coord * Z
Definition curvature.h:669
static int independents(coord *p, int n)
In three dimensions, these functions return the (two) components of the normal projected onto the $(x...
Definition curvature.h:341
n y
Definition curvature.h:104
int ori
Definition curvature.h:91
static double height_curvature(Point point, scalar c, vector h)
We now need to choose one of the , or height functions to compute the curvature.
Definition curvature.h:183
static void curvature_prolongation(Point point, scalar kappa)
The prolongation function performs a similar averaging, but using the same stencil as that used for b...
Definition curvature.h:29
coord o
Definition curvature.h:672
static double centroids_curvature_fit(Point point, scalar c)
Definition curvature.h:457
else return n
Definition curvature.h:101
static void curvature_restriction(Point point, scalar kappa)
Definition curvature.h:14
double nn
Definition curvature.h:102
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
double filter
Definition filter.h:8
#define plane_alpha
Definition geometry.h:133
#define plane_area_center(m, a, p)
Definition geometry.h:438
trace void heights(scalar c, vector h)
The heights() function implementation is similar to the multigrid case, but the construction of the s...
Definition heights.h:366
static int orientation(double H)
Definition heights.h:35
static double height(double H)
Definition heights.h:31
const scalar sigma[]
static float area(const KdtRect rect)
Definition kdt.c:439
size_t max
Definition mtrace.h:8
size_t nr
Definition mtrace.h:10
coord mycs(Point point, scalar c)
Definition myc.h:18
static double parabola_fit_curvature(ParabolaFit *p, double kappamax, double *kmax)
Definition parabola.h:162
static void parabola_fit_add(ParabolaFit *p, coord m, double w)
Definition parabola.h:74
static void parabola_fit_init(ParabolaFit *p, coord o, coord m)
Definition parabola.h:25
#define PARABOLA_FIT_CENTER_WEIGHT
Definition parabola.h:5
static double parabola_fit_solve(ParabolaFit *p)
Definition parabola.h:114
def _i
Definition stencils.h:405
Definition linear.h:21
Definition common.h:78
double z
Definition common.h:79
double x
Definition common.h:79
The function below computes the mean curvature kappa of the interface defined by the volume fraction ...
Definition curvature.h:535
int f
Definition curvature.h:537
int a
Definition curvature.h:538
int h
Definition curvature.h:536
int c
Definition curvature.h:539
scalar x
Definition common.h:47
scalar y
Definition common.h:49
#define kappa(f)
Definition thermal.h:85
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 sf
We have the option of using some "smearing" of the density/viscosity jump.
Array * normal
Array * position
scalar c
Definition vof.h:57