sandbox/rcaraccio/src/adapt_wavelet_leave_interface.h
This is a copy of Oystein Lande’s function (adapt_wavelet_leave_interface.h)
with some small tweaks. Mainly, MPI seems to cause issue with internal
points, creating value between 0 and 1 during the adaptivity step. The
creation of these artificial interface cells cause problems when
computing interface calculations. A simple workaround is to refine all
the cells within the particle to avoid this issue. This does not add
excessive computational cost as the particle is usually small compared
to the domain size.
Additionally, we use F_ERR macro to identify interface cells, to be
consistent with other parts of this sandbox.
#if TREE
#ifndef F_ERR
# define F_ERR 1.e-10
#endif
astats adapt_wavelet_leave_interface (scalar * slist, // list of scalars
scalar * vol_frac, // the volume fraction scalar
double * max, // tolerance for each scalar
int maxlevel, // maximum level of refinement
int minlevel = 1, // minimum level of refinement (default 1)
int padding = 0, // number of neighbor cells to padd on each side of the interface being preserved
scalar * list = all) // list of fields to update
{
scalar * ilist = list;
if (is_constant(cm)) {
if (list == NULL || list == all)
list = list_copy (all);
boundary (list);
restriction (slist);
}
else {
if (list == NULL || list == all) {
list = list_copy ({cm, fm});
for (scalar s in all)
list = list_add (list, s);
}
boundary (list);
scalar * listr = list_concat (slist, {cm});
restriction (listr);
free (listr);
}
astats st = {0, 0};
scalar * listc = NULL;
for (scalar s in list)
listc = list_add_depend (listc, s);
// refinement
if (minlevel < 1)
minlevel = 1;
tree->refined.n = 0;
static 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) {
cell.flags &= ~too_coarse;
refine_cell (point, listc, refined, &tree->refined);
st.nf++;
}
continue;
}
else { // !is_leaf (cell)
if (cell.flags & refined) {
// cell has already been refined, skip its children
cell.flags &= ~too_coarse;
continue;
}
// check whether the cell or any of its children is local
bool local = is_local(cell);
if (!local)
foreach_child()
if (is_local(cell)) {
local = true; break;
}
if (local) {
int i = 0;
static const int just_fine = 1 << (user + 3);
for (scalar s in slist) {
double emax = max[i++], sc[1 << dimension];
int c = 0;
foreach_child()
sc[c++] = s[];
s.prolongation (point, s);
c = 0;
foreach_child() {
double e = fabs(sc[c] - s[]);
if (e > emax && level < maxlevel) {
cell.flags &= ~too_fine;
cell.flags |= too_coarse;
}
else if ((e <= emax/1.5 || level > maxlevel) &&
!(cell.flags & (too_coarse|just_fine))) {
if (level >= minlevel)
cell.flags |= too_fine;
}
else if (!(cell.flags & too_coarse)) {
cell.flags &= ~too_fine;
cell.flags |= just_fine;
}
// arnbo: always set interface cells to the finest level
for (scalar vf in vol_frac) {MPI seems to cause issue with internal points, creating value between 0 and 1 The creation of these artificial interface cells cause problems when computing interface calculations. Thus, we refine all the cells within the particle to avoid this issue. NOTE: This is just a workaround, ideally one would want to investigate further the origin of this issue
@if _MPI
bool condition = (vf[] > F_ERR && level < maxlevel);
@else
bool condition = (vf[] > F_ERR && vf[] < 1. - F_ERR && level < maxlevel);
@endif
if (condition) {
cell.flags |= too_coarse;
cell.flags &= ~too_fine;
cell.flags &= ~just_fine;
if (padding > 0){
foreach_neighbor(padding){
cell.flags |= too_coarse;
cell.flags &= ~too_fine;
cell.flags &= ~just_fine;
}
}
}
}
s[] = sc[c++];
}
}
foreach_child() {
cell.flags &= ~just_fine;
if (!is_leaf(cell)) {
cell.flags &= ~too_coarse;
if (level >= maxlevel)
cell.flags |= too_fine;
}
else if (!is_active(cell))
cell.flags &= ~too_coarse;
}
}
}
}
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
cell.flags &= ~(refined|too_fine);
else if (cell.flags & too_fine) {
if (is_local(cell) && coarsen_cell (point, listc))
st.nc++;
cell.flags &= ~too_fine; // do not coarsen parent
}
}
if (cell.flags & too_fine)
cell.flags &= ~too_fine;
else if (level > 0 && (aparent(0).flags & too_fine))
aparent(0).flags &= ~too_fine;
continue;
}
else if (is_leaf(cell))
continue;
}
mpi_boundary_coarsen (l, too_fine);
}
free (listc);
mpi_all_reduce (st.nf, MPI_INT, MPI_SUM);
mpi_all_reduce (st.nc, MPI_INT, MPI_SUM);
if (st.nc || st.nf)
mpi_boundary_update (list);
if (list != ilist)
free (list);
return st;
}
#endif