sandbox/Antoonvh/reconstruct.h
Dynamic reconstruction of a geometry defined by GEOM(x,y)
.
A (dis)proof-of-concept in 2D.
#if TREE
The idea is to compute the 2D face fractions fs
and then compute the volume fraction…
static inline void recompute_face_fraction_refine_2D_x (Point point, scalar s) {
vector v = s.v;
if (!is_refined(neighbor(-1)) &&
(is_local(cell) || is_local(neighbor(-1)))) { //lhs
double ll = GEOM (x - Delta/2, y - Delta/2);
double ml = GEOM (x - Delta/2, y);
double ul = GEOM (x - Delta/2, y + Delta/2);
double fl = 0.5, fu = 0.5;
if (ll != ml)
fl = ll / (ll - ml);
if (ml != ul)
fu = ml / (ml - ul);
if (ll * ml < 0)
fine(v.x,0,0,0) = ll < 0 ? 1. - fl : fl ;
else
fine(v.x,0,0,0) = (ll > 0 || ml > 0);
if (ml * ul < 0)
fine(v.x,0,1,0) = ml < 0 ? 1. - fu : fu ;
else
fine(v.x,0,1,0) = (ml > 0 || ul > 0);
}
if (!is_refined(neighbor(1)) && neighbor(1).neighbors &&
(is_local(cell) || is_local(neighbor(1)))) { //rhs
double lr = GEOM (x + Delta/2., y - Delta/2);
double mr = GEOM (x + Delta/2., y);
double ur = GEOM (x + Delta/2., y + Delta/2);
double fl = 0.5, fu = 0.5;
if (lr != mr)
fl = lr / (lr - mr);
if (mr != ur)
fu = mr / (mr - ur);
if (lr * mr <= 0)
fine(v.x,2,0,0) = lr < 0 ? 1 - fl : fl ;
else
fine(v.x,2,0,0) = (lr > 0 || mr > 0);
if (mr * ur <= 0)
fine(v.x,2,1,1) = mr < 0 ? 1. - fu : fu ;
else
fine(v.x,2,1,1) = (mr > 0 || ur > 0);
}
if (is_local(cell)) {
double lm = GEOM (x, y - Delta/2);
double mm = GEOM (x, y);
double um = GEOM (x, y + Delta/2);
double fl = 0.5, fu = 0.5;
if (lm != mm)
fl = lm / (lm - mm);
if (mm != um)
fu = mm / (mm - um);
if (lm * mm < 0)
fine(v.x,1,0,0) = lm < 0 ? 1. - fl : fl ;
else
fine(v.x,1,0,0) = (lm > 0 || mm > 0);
if (mm * um < 0)
fine(v.x,1,1,0) = mm < 0 ? 1. - fu : fu ;
else
fine(v.x,1,1,0) = (mm > 0 || um > 0);
}
}
static inline void recompute_face_fraction_refine_2D_y (Point point, scalar s) {
fflush (stdout);
fflush (stdout);
vector v = s.v;
if (!is_refined(neighbor(0,-1)) &&
(is_local(cell) || is_local(neighbor(0,-1)))) { //lower
double ll = GEOM (x - Delta/2., y - Delta/2.);
double ml = GEOM (x , y - Delta/2.);
double ul = GEOM (x + Delta/2., y - Delta/2.);
double fl = 0.5, fu = 0.5;
if (ll != ml)
fl = ll / (ll - ml);
if (ml != ul)
fu = ml / (ml - ul);
if (ll * ml < 0)
fine(v.y,0,0,0) = ll < 0 ? 1. - fl : fl ;
else
fine(v.y,0,0,0) = (ll > 0 || ml > 0);
if (ml * ul < 0)
fine(v.y,1,0,0) = ml < 0 ? 1. - fu : fu ;
else
fine(v.y,1,0,0) = (ml > 0 || ul > 0);
}
if (!is_refined(neighbor(0,1)) && neighbor(0,1).neighbors &&
(is_local(cell) || is_local(neighbor(0,1)))) { //Upper
double lr = GEOM (x - Delta/2., y + Delta/2.);
double mr = GEOM (x , y + Delta/2.);
double ur = GEOM (x + Delta/2., y + Delta/2.);
double fl = 0.5, fu = 0.5;
if (lr != mr)
fl = lr / (lr - mr);
if (mr != ur)
fu = mr / (mr - ur);
if (lr * mr < 0)
fine(v.y,0,2,0) = lr < 0 ? 1. - fl : fl ;
else
fine(v.y,0,2,0) = (lr > 0 || mr > 0);
if (mr * ur < 0)
fine(v.y,1,2,0) = mr < 0 ? 1. - fu : fu ;
else
fine(v.y,1,2,0) = (mr > 0 || ur > 0);
}
if (is_local(cell)) {
double lm = GEOM (x - Delta/2., y);
double mm = GEOM (x , y);
double um = GEOM (x + Delta/2., y);
double fl = 0.5, fu = 0.5;
if (lm != mm)
fl = lm / (lm - mm);
if (mm != um)
fu = mm / (mm - um);
if (lm * mm < 0)
fine(v.y,0,1,0) = lm < 0 ? 1. - fl : fl ;
else
fine(v.y,0,1,0) = (lm > 0 || mm > 0);
if (mm * um < 0)
fine(v.y,1,1,0) = mm < 0 ? 1. - fu : fu ;
else
fine(v.y,1,1,0) = (mm > 0 || um > 0);
}
}
double intercept (coord n, Point point, face vector fs) {
double alpha = 0;
int ni = 0;
if (fs.x[] > 0. && fs.x[] < 1) {
alpha += sign(GEOM(x - Delta/2., y - Delta/2.))*n.y*(fs.x[] - 0.5) + n.x * -0.5;
ni++;
}
if (fs.x[1] > 0. && fs.x[1] < 1.) {
alpha += sign(GEOM(x + Delta/2., y - Delta/2.))*n.y*(fs.x[1] - 0.5) + n.x * 0.5;
ni++;
}
if (fs.y[] > 0. && fs.y[] < 1.) {
alpha += sign(GEOM(x - Delta/2., y - Delta/2.))*n.x*(fs.y[0] - 0.5) + n.y * -0.5;
ni++;
}
if (fs.y[0,1] > 0. && fs.y[0,1] < 1.) {
alpha += sign(GEOM(x - Delta/2., y + Delta/2.))*n.x*(fs.y[0,1] - 0.5) + n.y * 0.5;
ni++;
}
if (ni != 0)
return (alpha/ni);
else
return (max (fs.x[], 0));
}
static void refine_embed_fraction_recompute (Point point, scalar c) {
foreach_child() {
if (fs.x[] == 0. && fs.x[1] == 0. && fs.y[] == 0. && fs.y[0,1] == 0.) {
c[] = 0.;
} else if (fs.x[] == 1. && fs.x[1] == 1. && fs.y[] == 1. && fs.y[0,1] == 1.) {
c[] = 1.;
} else {
coord n = facet_normal (point, c, fs);
double alpha = intercept (n, point, fs);
c[] = line_area (n.x, n.y, alpha);
}
}
}
#if EMBED
event set_cs_and_fs (i = 0) {
fs
should appear before cs
in lists.
scalar * temp = NULL;
temp = list_append (temp, fs.x);
temp = list_append (temp, fs.y);
temp = list_append (temp, cs);
for (scalar s in all) {
if (s.i != cs.i && !(s.i >= fs.x.i && s.i <= fs.x.i + dimension - 1))
temp = list_append (temp, s);
}
all = temp;
oef…
foreach_dimension() {
fs.x.refine = recompute_face_fraction_refine_2D_x;
fs.x.restriction = restriction_face; // :S
}
cs.refine = refine_embed_fraction_recompute;
}
#endif
refine_embed_linear
is useful but it does not like fraction soups that emerge from degenerate representation of GEOM
etries when they are not consistent between levels. Thus we may simply ignore the assertions and hope for good results.
static inline void refine_embed_linear_not_assert (Point point, scalar s)
{
foreach_child() {
if (!cs[])
s[] = 0.;
else {
//assert (coarse(cs));
int i = (child.x + 1)/2, j = (child.y + 1)/2;
#if dimension == 2
if (coarse(fs.x,i) && coarse(fs.y,0,j) &&
(coarse(cs) == 1. || coarse(cs,child.x) == 1. ||
coarse(cs,0,child.y) == 1. || coarse(cs,child.x,child.y) == 1.)) {
//assert (coarse(cs,child.x) && coarse(cs,0,child.y));
if (coarse(fs.x,i,child.y) && coarse(fs.y,child.x,j)) {
// bilinear interpolation
//assert (coarse(cs,child.x,child.y));
s[] = (9.*coarse(s) +
3.*(coarse(s,child.x) + coarse(s,0,child.y)) +
coarse(s,child.x,child.y))/16.;
}
else
// triangular interpolation
s[] = (2.*coarse(s) + coarse(s,child.x) + coarse(s,0,child.y))/4.;
}
else if (coarse(cs,child.x,child.y) &&
((coarse(fs.x,i) && coarse(fs.y,child.x,j)) ||
(coarse(fs.y,0,j) && coarse(fs.x,i,child.y)))) {
// diagonal interpolation
s[] = (3.*coarse(s) + coarse(s,child.x,child.y))/4.;
}
#else // dimension == 3
int k = (child.z + 1)/2;
if (coarse(fs.x,i) > 0.25 && coarse(fs.y,0,j) > 0.25 &&
coarse(fs.z,0,0,k) > 0.25 &&
(coarse(cs) == 1. || coarse(cs,child.x) == 1. ||
coarse(cs,0,child.y) == 1. || coarse(cs,child.x,child.y) == 1. ||
coarse(cs,0,0,child.z) == 1. || coarse(cs,child.x,0,child.z) == 1. ||
coarse(cs,0,child.y,child.z) == 1. ||
coarse(cs,child.x,child.y,child.z) == 1.)) {
//assert (coarse(cs,child.x) && coarse(cs,0,child.y) &&
coarse(cs,0,0,child.z));
if (coarse(fs.x,i,child.y) && coarse(fs.y,child.x,j) &&
coarse(fs.z,child.x,child.y,k) &&
coarse(fs.z,child.x,0,k) && coarse(fs.z,0,child.y,k)) {
//assert (coarse(cs,child.x,child.y) && coarse(cs,child.x,0,child.z) &&
coarse(cs,0,child.y,child.z) &&
coarse(cs,child.x,child.y,child.z));
// bilinear interpolation
s[] = (27.*coarse(s) +
9.*(coarse(s,child.x) + coarse(s,0,child.y) +
coarse(s,0,0,child.z)) +
3.*(coarse(s,child.x,child.y) + coarse(s,child.x,0,child.z) +
coarse(s,0,child.y,child.z)) +
coarse(s,child.x,child.y,child.z))/64.;
}
else
// tetrahedral interpolation
s[] = (coarse(s) + coarse(s,child.x) + coarse(s,0,child.y) +
coarse(s,0,0,child.z))/4.;
}
else if (coarse(cs,child.x,child.y,child.z) &&
((coarse(fs.z,child.x,child.y,k) &&
((coarse(fs.x,i) && coarse(fs.y,child.x,j)) ||
(coarse(fs.y,0,j) && coarse(fs.x,i,child.y))))
||
(coarse(fs.z,0,0,k) &&
((coarse(fs.x,i,0,child.z) && coarse(fs.y,child.x,j,child.z)) ||
(coarse(fs.y,0,j,child.z) && coarse(fs.x,i,child.y,child.z))))
||
(coarse(fs.z,child.x,0,k) &&
coarse(fs.x,i) && coarse(fs.y,child.x,j,child.z))
||
(coarse(fs.z,0,child.y,k) &&
coarse(fs.y,0,j) && coarse(fs.x,i,child.y,child.z))
))
// diagonal interpolation
s[] = (3.*coarse(s) + coarse(s,child.x,child.y,child.z))/4.;
#endif // dimension == 3
else {
// Pathological cases, use 1D gradients.
s[] = coarse(s);
foreach_dimension() {
if (coarse(fs.x,(child.x + 1)/2) && coarse(cs,child.x))
s[] += (coarse(s,child.x) - coarse(s))/4.;
else if (coarse(fs.x,(- child.x + 1)/2) && coarse(cs,- child.x))
s[] -= (coarse(s,- child.x) - coarse(s))/4.;
}
}
}
}
}
# if EMBED
event properties (i = 0) {
for (scalar s in all) {
if (s.prolongation == refine_embed_linear)
s.prolongation = refine_embed_linear_not_assert;
if (s.refine == refine_embed_linear)
s.refine = refine_embed_linear_not_assert;
}
}
#endif //embed
#endif //tree