Assert (cell->coarsen_flag_set() == false, ExcInternalError());
#endif
- // revert change of flags: use
- // coarsen flags again and delete
- // user flags
+ // now loop over all cells which have the
+ // user flag set. their children were
+ // flagged for coarsening. set the coarsen
+ // flag again if we are sure that none of
+ // the neighbors of these children are
+ // refined, or will be refined, since then
+ // we would get a two-level jump in
+ // refinement. on the other hand, if one of
+ // the children's neighbors has their user
+ // flag set, then we know that its children
+ // will go away by coarsening, and we will
+ // be ok.
+ //
+ // note on the other hand that we do allow
+ // level-2 jumps in refinement between
+ // neighbors in 1d, so this whole procedure
+ // is only necessary if we are not in 1d
+ //
+ // since we remove some coarsening/user
+ // flags in the process, we have to work
+ // from the finest level to the coarsest
+ // one, since we occasionally inspect user
+ // flags of cells on finer levels and need
+ // to be sure that these flags are final
for (cell=last(); cell!=endc; --cell)
if (cell->user_flag_set())
{
- cell->clear_user_flag();
-
- // find out whether the
- // children of this cell may
- // be flagged for refinement
bool coarsening_allowed = true;
- for (unsigned int c=0; c<GeometryInfo<dim>::children_per_cell; ++c)
- for (unsigned int n=0; n<GeometryInfo<dim>::faces_per_cell; ++n)
- {
- const cell_iterator child_neighbor = cell->child(c)->neighbor(n);
- if (child_neighbor.state() == IteratorState::valid)
- if (child_neighbor->has_children() ||
- // neighbor has children,
- // then only allow coarsening
- // if this neighbor will be
- // coarsened as well. however,
- // I don't see the consequences
- // of this case, so simply
- // disallow coarsening if
- // any neighbor is more
- // refined. maybe someone
- // else will want to do this
- // some time
- (child_neighbor->refine_flag_set() &&
- (child_neighbor->level()==cell->level()+1)))
- coarsening_allowed = false;
- }
+
+ if (dim > 1)
+ {
+ for (unsigned int c=0;
+ (c<GeometryInfo<dim>::children_per_cell) && (coarsening_allowed==true);
+ ++c)
+ for (unsigned int n=0; n<GeometryInfo<dim>::faces_per_cell; ++n)
+ {
+ const cell_iterator child_neighbor = cell->child(c)->neighbor(n);
+ if ((child_neighbor.state() == IteratorState::valid)
+ &&
+ (child_neighbor->level()==cell->level()+1)
+ &&
+ ((child_neighbor->has_children()
+ &&
+ !child_neighbor->user_flag_set())
+ ||
+ (child_neighbor->has_children()
+ &&
+ child_neighbor->refine_flag_set())))
+ {
+ coarsening_allowed = false;
+ break;
+ }
+ }
+ }
// if allowed: tag the
// children for coarsening
cell->child(c)->set_coarsen_flag();
}
}
+
+ // clear all user flags again, now that we
+ // don't need them any more
+ clear_user_flags ();
}
<h3>deal.II</h3>
<ol>
+ <li> <p>
+ Fixed: The <code class="class">Triangulation</code>::<code
+ class="member">execute_coarsening_and_refinement</code> function has to
+ discard coarsening flags in 2d and 3d if a neighbor of a flagged cell is
+ refined or will be refined, in order to avoid that we end up with
+ neighboring cells that differ in refinement by two levels. The function
+ was overly conservative, however, in that it didn't allow a cell to be
+ coarsened if its neighbor is once refined but is also marked for
+ coarsening. This is now fixed and will lead to a few more cells being
+ coarsened.
+ <br>
+ (Yaqi Wang, WB 2006/12/27)
+ </p>
+
<li> <p>
Fixed: The <code class="class">Triangulation</code>::<code class="member">
MeshSmoothing</code> flag <code>patch_level_1</code> wrongly produced cells
--- /dev/null
+//---------------------------- refine_and_coarsen.cc ---------------------------
+// $Id: refine_and_coarsen.cc 11749 2005-11-09 19:11:20Z wolf $
+// Version: $Name$
+//
+// Copyright (C) 2006 by the deal.II authors
+//
+// This file is subject to QPL and may not be distributed
+// without copyright and license information. Please refer
+// to the file deal.II/doc/license.html for the text and
+// further information on this license.
+//
+//---------------------------- refine_and_coarsen.cc ---------------------------
+
+
+// check that if we take an locally refined mesh, refine it globally once,
+// then coarsen it globally again, that we get the same mesh
+
+#include "../tests.h"
+
+#include <base/logstream.h>
+#include <base/quadrature_lib.h>
+#include <grid/tria.h>
+#include <grid/tria_accessor.h>
+#include <grid/tria_iterator.h>
+#include <grid/grid_generator.h>
+
+#include <fstream>
+
+
+
+template <int dim>
+void check ()
+{
+ Triangulation<dim> tria;
+ GridGenerator::hyper_cube (tria);
+ tria.refine_global (2);
+ tria.begin_active()->set_refine_flag();
+ tria.execute_coarsening_and_refinement ();
+
+ // store which cells we have here
+ std::vector<typename Triangulation<dim>::active_cell_iterator> cells;
+ for (typename Triangulation<dim>::active_cell_iterator cell=tria.begin_active();
+ cell != tria.end(); ++cell)
+ cells.push_back (cell);
+
+ const unsigned int n_cells = tria.n_active_cells();
+ deallog << n_cells << std::endl;
+
+ // refine the mesh globally, then coarsen
+ // it again globally
+ tria.refine_global (1);
+
+ for (typename Triangulation<dim>::active_cell_iterator cell=tria.begin_active();
+ cell != tria.end(); ++cell)
+ cell->set_coarsen_flag ();
+ tria.execute_coarsening_and_refinement ();
+
+
+ // verify that we get the same cells again
+ deallog << n_cells << ' ' << tria.n_active_cells()
+ << std::endl;
+
+ Assert (tria.n_active_cells() == n_cells,
+ ExcInternalError());
+
+ unsigned int index = 0;
+ for (typename Triangulation<dim>::active_cell_iterator cell=tria.begin_active();
+ cell != tria.end(); ++cell, ++index)
+ Assert (cells[index] == cell,
+ ExcInternalError());
+
+}
+
+
+int main ()
+{
+ std::ofstream logfile("refine_and_coarsen/output");
+ deallog.attach(logfile);
+ deallog.depth_console(0);
+ deallog.threshold_double(1.e-10);
+
+ check<1> ();
+ check<2> ();
+ check<3> ();
+}
+
+
+