sandbox/Antoonvh/adapt_field.h
A flexible adaptation algorithm
A special purpose adaptation algorithm. consider using
adapt_wavelet()
instead.
struct Adapt_Field {
scalar f; // The field with leaf-filled values
double max; // refinement criterion
double min; // coarseing criterion
int maxlevel; // maximum level of refinement
int minlevel; // minimum level of refinement (default 1)
scalar * list; // list of fields to update (default all)
};
astats adapt_field (struct Adapt_Field p);
extern vector u;
struct Adapt_Flow {
double ue;
int maxlevel;
double p;
double cfac;
};
attribute {
void (* interpolant) (Point, scalar);
}
void wavelet_interpolant (scalar s, scalar w)
{
({s});
restriction for (int l = grid->maxdepth - 1; l >= 0; l--) {
foreach_coarse_level (l) {
foreach_child()
[] = s[];
w.interpolant (point, s);
sforeach_child() {
double sp = s[];
[] = w[];
s/* difference between fine value and its prolongation */
[] -= sp;
w}
}
({w}, l + 1);
boundary_level }
/* root cell */
(0)
foreach_level[] = s[];
w({w}, 0);
boundary_level }
astats adapt_flow (struct Adapt_Flow pa) {
double ue = pa.ue;
int maxlevel = pa.maxlevel;
double p = pa.p;
double uec = ue/1.5;
if (pa.cfac)
= ue/pa.cfac;
uec scalar w[];
vector wv[];
foreach_dimension()
wavelet_interpolant (u.x, wv.x);
for (int l = 1; l < grid->maxdepth; l++)
foreach_coarse_level (l) {
double maxw = 0.;
foreach_child() {
double a = 0;
foreach_dimension()
+= fabs(wv.x[]);
a = max(maxw, a);
maxw }
[] = maxw;
w}
#if _MPI
.restriction = no_restriction;
w.prolongation = no_restriction;
wboundary ({w});
#endif
for (int l = grid->maxdepth; l > 1; l--)
(l) {// 3x3(x3) Gaussian kernel
foreach_level#if (dimension == 2)
[] = pow(Delta, p)*(1. * coarse(w,0,0,0) +
w.5 *(coarse(w,1,0,0) + coarse(w,0,1,0) +
(w,-1,0,0) + coarse(w,0,-1,0)) +
coarse0.25*(coarse(w,1,1,0) + coarse(w,1,-1,0) +
(w,-1,-1,0) + coarse(w,-1,1,0)))/4.;
coarse#else //(dimension == 3)
[] = pow(Delta, p)*(1. * coarse(w,0,0,0) +
w.5 *(coarse(w,1,0,0) + coarse(w,-1,0,0) +
(w,0,1,0) + coarse(w,0,-1,0) +
coarse(w,0,0,1) + coarse(w,0,0,-1)) +
coarse0.25 *(coarse(w,1,1,0) + coarse(w,1,-1,0) +
(w,-1,-1,0) + coarse(w,-1,1,0) +
coarse(w,0,1,1) + coarse(w,0,-1,1) +
coarse(w,0,-1,-1) + coarse(w,0,1,-1) +
coarse(w,1,0,1) + coarse(w,1,0,-1) +
coarse(w,-1,0,-1) + coarse(w,-1,0,1)) +
coarse0.125*(coarse(w,1,1,1) + coarse(w,-1,1,1) +
(w,1,-1,1) + coarse(w,1,1,-1) +
coarse(w,-1,-1,1) + coarse(w,-1,1,-1) +
coarse(w,1,-1,-1) + coarse(w,-1,-1,-1)))/8.;
coarse#endif
}
return adapt_field (w, ue, uec, maxlevel);
}
struct Adapt_List {
scalar * list;
double * ues;
int maxlevel;
double p;
double fac;
};
astats adapt_list (struct Adapt_List pa) {
scalar * list = pa.list;
double * ues = pa.ues;
int maxlevel = pa.maxlevel;
double p = pa.p;
if (!pa.fac)
.fac = 1.5;
pascalar w[], * wl = list_clone (list);
scalar s, ws;
for (s,ws in list,wl)
wavelet (s, ws);
for (int l = 1; l < depth() - 1; l++)
foreach_coarse_level (l) {
double maxw = 0.;
foreach_child() {
double a = 0;
scalar s, ws;
(s);
NOT_UNUSEDint is = 0;
for (s, ws in list, wl) {
+= fabs(ws[])/ues[is]; //scale w with ue
a ++;
is}
= max(maxw, a);
maxw }
[] = maxw;
w}
#if _MPI
.restriction = no_restriction;
w.prolongation = no_restriction;
wboundary ({w});
#endif
for (int l = depth(); l > 1; l--)
(l) {// 3x3(x3) Gaussian kernel
foreach_level#if (dimension == 2)
[] = pow(Delta, p)*(1. * coarse(w,0,0,0) +
w.5 *(coarse(w,1,0,0) + coarse(w,0,1,0) +
(w,-1,0,0) + coarse(w,0,-1,0)) +
coarse0.25*(coarse(w,1,1,0) + coarse(w,1,-1,0) +
(w,-1,-1,0) + coarse(w,-1,1,0)))/4.;
coarse#else //(dimension == 3)
[] = pow(Delta, p)*(1. * coarse(w,0,0,0) +
w.5 *(coarse(w,1,0,0) + coarse(w,-1,0,0) +
(w,0,1,0) + coarse(w,0,-1,0) +
coarse(w,0,0,1) + coarse(w,0,0,-1)) +
coarse0.25 *(coarse(w,1,1,0) + coarse(w,1,-1,0) +
(w,-1,-1,0) + coarse(w,-1,1,0) +
coarse(w,0,1,1) + coarse(w,0,-1,1) +
coarse(w,0,-1,-1) + coarse(w,0,1,-1) +
coarse(w,1,0,1) + coarse(w,1,0,-1) +
coarse(w,-1,0,-1) + coarse(w,-1,0,1)) +
coarse0.125*(coarse(w,1,1,1) + coarse(w,-1,1,1) +
(w,1,-1,1) + coarse(w,1,1,-1) +
coarse(w,-1,-1,1) + coarse(w,-1,1,-1) +
coarse(w,1,-1,-1) + coarse(w,-1,-1,-1)))/8.;
coarse#endif
}
return adapt_field (w, 1., 1./pa.fac, maxlevel); //w is already scaled
}
trace
astats adapt_field (struct Adapt_Field p) {
scalar f = p.f;
if (p.list == NULL)
.list = all;
pscalar * listc = NULL;
for (scalar s in p.list)
if (!is_constant(s) && s.restriction != no_restriction)
= list_add (listc, s);
listc astats st = {0, 0};
// refinement
if (p.minlevel < 1)
.minlevel = 1;
p->refined.n = 0;
treestatic const int refined = 1 << user, too_fine = 1 << (user + 1);
foreach_cell() {
if (is_active(cell)) {
static const int too_coarse = 1 << (user + 2);
if (is_leaf (cell)) {
if (cell.flags & too_coarse) {
.flags &= ~too_coarse;
cellrefine_cell (point, listc, refined, &tree->refined);
.nf++;
st}
continue;
}
else { // !is_leaf (cell)
if (cell.flags & refined) {
// cell has already been refined, skip its children
.flags &= ~too_coarse;
cellcontinue;
}
// check whether the cell or any of its children is local
bool local = is_local(cell);
if (!local)
foreach_child()
if (is_local(cell)) {
= true;
local break;
}
if (local) {
static const int just_fine = 1 << (user + 3);
double max = p.max, min = p.min;
foreach_child() {
double e = fabs(f[]);
if (e > max && level < p.maxlevel) {
.flags &= ~too_fine;
cell.flags |= too_coarse;
cell}
else if ((e <= min || level > p.maxlevel) &&
!(cell.flags & (too_coarse|just_fine))) {
if (level >= p.minlevel)
.flags |= too_fine;
cell}
else if (!(cell.flags & too_coarse)) {
.flags &= ~too_fine;
cell.flags |= just_fine;
cell}
}
foreach_child() {
.flags &= ~just_fine;
cellif (!is_leaf(cell)) {
.flags &= ~too_coarse;
cellif (level >= p.maxlevel)
.flags |= too_fine;
cell}
else if (!is_active(cell))
.flags &= ~too_coarse;
cell}
}
}
}
else // inactive cell
continue;
}
mpi_boundary_refine (listc);
// coarsening
// the loop below is only necessary to ensure symmetry of 2:1 constraint
for (int l = depth(); l >= 0; l--) {
foreach_cell()
if (!is_boundary(cell)) {
if (level == l) {
if (!is_leaf(cell)) {
if (cell.flags & refined)
// cell was refined previously, unset the flag
.flags &= ~(refined|too_fine);
cellelse if (cell.flags & too_fine) {
if (is_local(cell) && coarsen_cell (point, listc))
.nc++;
st.flags &= ~too_fine; // do not coarsen parent
cell}
}
if (cell.flags & too_fine)
.flags &= ~too_fine;
cellelse if (level > 0 && (aparent(0).flags & too_fine))
(0).flags &= ~too_fine;
aparentcontinue;
}
else if (is_leaf(cell))
continue;
}
mpi_boundary_coarsen (l, too_fine);
}
free (listc);
(st.nf, MPI_INT, MPI_SUM);
mpi_all_reduce (st.nc, MPI_INT, MPI_SUM);
mpi_all_reduce if (st.nc || st.nf)
mpi_boundary_update (p.list);
return st;
}