From 83899fd90ba709f4739887aad150b1517abd3791 Mon Sep 17 00:00:00 2001 From: bangerth Date: Wed, 27 Dec 2006 21:57:34 +0000 Subject: [PATCH] Also fix refine_and_coarsen_3d, which required looking around corners a bit. git-svn-id: https://svn.dealii.org/trunk@14278 0785d39b-7218-0410-832d-ea1e28bc413d --- deal.II/deal.II/source/grid/tria.cc | 183 +++++++++++++++---- tests/bits/refine_and_coarsen_1d.cc | 3 + tests/bits/refine_and_coarsen_2d.cc | 3 + tests/bits/refine_and_coarsen_3d.cc | 5 + tests/bits/refine_and_coarsen_3d/cmp/generic | 38 +--- 5 files changed, 162 insertions(+), 70 deletions(-) diff --git a/deal.II/deal.II/source/grid/tria.cc b/deal.II/deal.II/source/grid/tria.cc index 95190e9cde..25e79f7d79 100644 --- a/deal.II/deal.II/source/grid/tria.cc +++ b/deal.II/deal.II/source/grid/tria.cc @@ -7210,10 +7210,9 @@ void Triangulation<3>::prepare_refinement_dim_dependent () // first clear flags on lines, // since we need them to determine // which lines will be refined - for (line_iterator line=begin_line(); line!=end_line(); ++line) - line->clear_user_flag(); + clear_user_flags_line(); - // variables to store whether the + // variable to store whether the // mesh was changed in the present // loop and in the whole process bool mesh_changed = false; @@ -7222,6 +7221,14 @@ void Triangulation<3>::prepare_refinement_dim_dependent () { mesh_changed = false; + // for this following, we need to know + // which cells are going to be + // coarsened, if we had to make a + // decision. the following function + // sets these flags: + fix_coarsen_flags (); + + // flag those lines that will // be refined for (active_cell_iterator cell=begin_active(); cell!=end(); ++cell) @@ -7308,36 +7315,145 @@ void Triangulation<3>::prepare_refinement_dim_dependent () } } - // there is another thing - // here: if any of the - // lines if refined, we - // may not coarsen this - // cell. this also holds - // true if the line is - // not yet refined, but - // will be + // there is another thing here: + // if any of the lines will be + // refined, then we may not + // coarsen the present cell + if (cell->line(line)->user_flag_set() + && + cell->coarsen_flag_set()) + { + cell->clear_coarsen_flag (); + mesh_changed = true; + + break; + } + + // similarly, if any of the lines + // *is* already refined, we may + // not coarsen the current + // cell. however, there's a + // catch: if the line is refined, + // but the cell behind it is + // going to be coarsened, then + // the situation changes. if we + // forget this second condition, + // the refine_and_coarsen_3d test + // will start to fail. note that + // to know which cells are going + // to be coarsened, the call for + // fix_coarsen_flags above is + // necessary // - // this is not totally - // true, since the - // neighbors' children - // may also be all - // coarsened, but we do - // not catch these - // aspects here; in - // effect, we disallow to - // coarsen sharp edges - // where the refinement - // level decreases from - // each cell to the next - if (cell->line(line)->has_children() || - cell->line(line)->user_flag_set()) - if (cell->coarsen_flag_set()) - { - cell->clear_coarsen_flag (); - mesh_changed = true; - - break; - } + // the problem is that finding + // all cells that are behind an + // edge in 3d is somewhat of a + // pain and worst of all + // introduces a quadratic + // behavior in this algorithm. on + // the other hand, not many cells + // have their coarsen flag set + // usually, and fixing + // refine_and_coarsen_3d is a + // somewhat important case + if (cell->line(line)->has_children() && + cell->coarsen_flag_set()) + { + bool cant_be_coarsened = false; + + // loop over all cells of this + // level to find neighbors of + // this cell and edge + for (cell_iterator edge_neighbor=begin(cell->level()); + ((edge_neighbor != end(cell->level())) + && + (cant_be_coarsened == false)); + ++edge_neighbor) + if (edge_neighbor != cell) + for (unsigned int e=0; e::lines_per_cell; ++e) + if (edge_neighbor->line(e) == cell->line(line)) + { + // this is a cell + // that is adjacent + // to the present + // cell across this + // edge. so treat + // it, but only if + // it is actually + // refined or will + // be refined + if (! (cell->has_children() + || + (!cell->has_children() && + cell->refine_flag_set()))) + break; + + // figure out if + // the neighbor is + // going to be + // coarsened. as a + // post-condition + // of the call to + // fix_coarsen_flags(), + // either all + // children of a + // cell must be + // flagged for + // coarsening, or + // none may. above + // we delete some + // coarsen flags, + // and in the next + // call to + // fix_coarsen_flags() + // the flags to all + // siblings will be + // removed. we will + // check here if + // still all + // children have + // that flag set + unsigned int n_children_flagged = 0; + for (unsigned int c=0; c::children_per_cell; ++c) + if ((edge_neighbor->child(c)->has_children() == false) + && + edge_neighbor->child(c)->coarsen_flag_set()) + ++n_children_flagged; + + // now, if not all + // children are + // flagged, then + // the neighboring + // cell isn't going + // to be + // coarsened. that + // means that the + // common edge + // isn't going to + // be coarsened and + // that we can't + // coarsen the + // present cell + if (n_children_flagged != + GeometryInfo::children_per_cell) + cant_be_coarsened = true; + + + // neighbor was + // found. no reason + // to keep looping + // over edges of + // the possible + // edge_neighbor + break; + } + + if (cant_be_coarsened == true) + { + cell->clear_coarsen_flag (); + mesh_changed = true; + } + } } } while (mesh_changed == true); @@ -8230,8 +8346,7 @@ bool Triangulation::prepare_coarsening_and_refinement () && (cell->neighbor(i)->refine_flag_set() == false)) { - if (cell->neighbor(i)->coarsen_flag_set()) - cell->neighbor(i)->clear_coarsen_flag(); + cell->neighbor(i)->clear_coarsen_flag(); cell->neighbor(i)->set_refine_flag(); } else diff --git a/tests/bits/refine_and_coarsen_1d.cc b/tests/bits/refine_and_coarsen_1d.cc index 554729a3ec..9516208750 100644 --- a/tests/bits/refine_and_coarsen_1d.cc +++ b/tests/bits/refine_and_coarsen_1d.cc @@ -14,6 +14,9 @@ // check that if we take an locally refined mesh, refine it globally once, // then coarsen it globally again, that we get the same mesh +// +// Triangulation::fix_coarsen_flags used to be too conservative in allowing +// cells to be coarsened (see today's changes.html entry) #include "../tests.h" diff --git a/tests/bits/refine_and_coarsen_2d.cc b/tests/bits/refine_and_coarsen_2d.cc index ceefe7947a..877134e845 100644 --- a/tests/bits/refine_and_coarsen_2d.cc +++ b/tests/bits/refine_and_coarsen_2d.cc @@ -14,6 +14,9 @@ // check that if we take an locally refined mesh, refine it globally once, // then coarsen it globally again, that we get the same mesh +// +// Triangulation::fix_coarsen_flags used to be too conservative in allowing +// cells to be coarsened (see today's changes.html entry) #include "../tests.h" diff --git a/tests/bits/refine_and_coarsen_3d.cc b/tests/bits/refine_and_coarsen_3d.cc index 744ed26b0b..a4426fcd0a 100644 --- a/tests/bits/refine_and_coarsen_3d.cc +++ b/tests/bits/refine_and_coarsen_3d.cc @@ -14,6 +14,11 @@ // check that if we take an locally refined mesh, refine it globally once, // then coarsen it globally again, that we get the same mesh +// +// Triangulation::fix_coarsen_flags used to be too conservative in allowing +// cells to be coarsened (see today's changes.html entry). in contrast to the +// 1d and 2d cases, the 3d case appears to have an additional problem +// somewhere #include "../tests.h" diff --git a/tests/bits/refine_and_coarsen_3d/cmp/generic b/tests/bits/refine_and_coarsen_3d/cmp/generic index f08e311b42..a3326a6fe9 100644 --- a/tests/bits/refine_and_coarsen_3d/cmp/generic +++ b/tests/bits/refine_and_coarsen_3d/cmp/generic @@ -1,37 +1,3 @@ -DEAL::Initial check -DEAL:: ok. -DEAL::Check 0 -DEAL:: ok. -DEAL::Check 1 -DEAL:: ok. -DEAL::Check 2 -DEAL:: ok. -DEAL::Check 1 -DEAL:: ok. -DEAL::Check 2 -DEAL:: ok. -DEAL::Initial check -DEAL:: ok. -DEAL::Check 0 -DEAL:: ok. -DEAL::Check 1 -DEAL:: ok. -DEAL::Check 2 -DEAL:: ok. -DEAL::Check 1 -DEAL:: ok. -DEAL::Check 2 -DEAL:: ok. -DEAL::Initial check -DEAL:: ok. -DEAL::Check 0 -DEAL:: ok. -DEAL::Check 1 -DEAL:: ok. -DEAL::Check 2 -DEAL:: ok. -DEAL::Check 1 -DEAL:: ok. -DEAL::Check 2 -DEAL:: ok. +DEAL::71 +DEAL::71 71 -- 2.39.5