// $Id$
// Version: $Name$
//
-// Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2009 by the deal.II authors
+// Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 by the deal.II authors
//
// This file is subject to QPL and may not be distributed
// without copyright and license information. Please refer
//
//---------------------------------------------------------------------------
-
-/*
- * Single out some functions which are needed by all dimensions, but
- * which are not template. They thus have the same name and when we
- * try to link with the libraries for different dimensions at the same
- * time, we get linker errors for functions defined more than once. By
- * putting these functions in a single file, the linker is allowed to
- * use it only once and throw away all other versions of this file in
- * the other libraries.
- */
-
-
#include <base/memory_consumption.h>
#include <grid/tria.h>
#include <grid/tria_levels.h>
+#include <grid/tria_faces.h>
#include <grid/tria_boundary.h>
+#include <grid/tria_accessor.h>
+#include <grid/tria_iterator.h>
+#include <base/geometry_info.h>
+#include <grid/grid_tools.h>
+#include <grid/magic_numbers.h>
+#include <fe/mapping_q1.h>
+#include <lac/vector.h>
+#include <algorithm>
#include <numeric>
+#include <map>
+#include <cmath>
+#include <functional>
-DEAL_II_NAMESPACE_OPEN
-
+#include <base/std_cxx1x/array.h>
+DEAL_II_NAMESPACE_OPEN
bool
SubCellData::check_consistency (const unsigned int dim) const
}
}
+// anonymous namespace for internal helper functions
+namespace
+{
+ // return whether the given cell is
+ // patch_level_1, i.e. determine
+ // whether either all or none of
+ // its children are further
+ // refined. this function can only
+ // be called for non-active cells.
+ template <int dim, int spacedim>
+ bool cell_is_patch_level_1 (const TriaIterator<dealii::CellAccessor<dim, spacedim> > &cell)
+ {
+ Assert (cell->active() == false, ExcInternalError());
+
+ unsigned int n_active_children = 0;
+ for (unsigned int i=0; i<cell->n_children(); ++i)
+ if (cell->child(i)->active())
+ ++n_active_children;
+
+ return (n_active_children == 0) || (n_active_children == cell->n_children());
+ }
+
+
+
+ // return, wheter a given @p cell will be
+ // coarsened, which is the case if all
+ // children are active and have their coarsen
+ // flag set. In case only part of the coarsen
+ // flags are set, remove them.
+ template <int dim, int spacedim>
+ bool cell_will_be_coarsened (const TriaIterator<dealii::CellAccessor<dim,spacedim> > &cell)
+ {
+ // only cells with children should be
+ // considered for coarsening
+
+ if (cell->has_children())
+ {
+ unsigned int children_to_coarsen=0;
+ const unsigned int n_children=cell->n_children();
+
+ for (unsigned int c=0; c<n_children; ++c)
+ if (cell->child(c)->active() &&
+ cell->child(c)->coarsen_flag_set())
+ ++children_to_coarsen;
+ if (children_to_coarsen==n_children)
+ return true;
+ else
+ for (unsigned int c=0; c<n_children; ++c)
+ if (cell->child(c)->active())
+ cell->child(c)->clear_coarsen_flag();
+ }
+ // no children, so no coarsening
+ // possible. however, no children also
+ // means that this cell will be in the same
+ // state as if it had children and was
+ // coarsened. So, what should we return -
+ // false or true?
+ // make sure we do not have to do this at
+ // all...
+ Assert(cell->has_children(), ExcInternalError());
+ // ... and then simply return false
+ return false;
+ }
+
+
+ // return, whether the face @p face_no of the
+ // given @p cell will be refined after the
+ // current refinement step, considering
+ // refine and coarsen flags and considering
+ // only those refinemnts that will be caused
+ // by the neighboring cell.
+
+ // this function is used on both active cells
+ // and cells with children. on cells with
+ // children it also of interest to know 'how'
+ // the face will be refined. thus there is an
+ // additional third argument @p
+ // expected_face_ref_case returning just
+ // that. be aware, that this vriable will
+ // only contain useful information if this
+ // function is called for an active cell.
+ //
+ // thus, this is an internal function, users
+ // should call one of the two alternatives
+ // following below.
+ template <int dim, int spacedim>
+ bool
+ face_will_be_refined_by_neighbor_internal(const TriaIterator<dealii::CellAccessor<dim,spacedim> > &cell,
+ const unsigned int face_no,
+ RefinementCase<dim-1> &expected_face_ref_case)
+ {
+ // first of all: set the default value for
+ // expected_face_ref_case, which is no
+ // refinement at all
+ expected_face_ref_case=RefinementCase<dim-1>::no_refinement;
+
+ const typename Triangulation<dim,spacedim>::cell_iterator neighbor=cell->neighbor(face_no);
+
+ // If we are at the boundary, there is no
+ // neighbor which could refine the face
+ if (neighbor.state()!=IteratorState::valid)
+ return false;
+
+ if (neighbor->has_children())
+ {
+ // if the neighbor is refined, it may be
+ // coarsened. if so, then it won't refine
+ // the face, no matter what else happens
+ if (cell_will_be_coarsened(neighbor))
+ return false;
+ else
+ // if the neighor is refined, then he
+ // is also refined at our current
+ // face. He will stay so without
+ // coarsening, so return true in that
+ // case.
+ {
+ expected_face_ref_case=cell->face(face_no)->refinement_case();
+ return true;
+ }
+ }
+
+ // now, the neighbor is not refined, but
+ // perhaps he will be
+ const RefinementCase<dim> nb_ref_flag=neighbor->refine_flag_set();
+ if (nb_ref_flag != RefinementCase<dim>::no_refinement)
+ {
+ // now we need to know, which of the
+ // neighbors faces points towards us
+ const unsigned int neighbor_neighbor=cell->neighbor_face_no(face_no);
+ // check, whether the cell will be
+ // refined in a way that refines our
+ // face
+ const RefinementCase<dim-1> face_ref_case=
+ GeometryInfo<dim>::face_refinement_case(nb_ref_flag,
+ neighbor_neighbor,
+ neighbor->face_orientation(neighbor_neighbor),
+ neighbor->face_flip(neighbor_neighbor),
+ neighbor->face_rotation(neighbor_neighbor));
+ if (face_ref_case != RefinementCase<dim-1>::no_refinement)
+ {
+ const typename Triangulation<dim,spacedim>::face_iterator neighbor_face=neighbor->face(neighbor_neighbor);
+ const int this_face_index=cell->face_index(face_no);
+
+ // there are still two basic
+ // possibilities here: the neighbor
+ // might be coarser or as coarse
+ // as we are
+ if (neighbor_face->index()==this_face_index)
+ // the neighbor is as coarse as
+ // we are and will be refined at
+ // the face of consideration, so
+ // return true
+ {
+ expected_face_ref_case = face_ref_case;
+ return true;
+ }
+ else
+ {
+
+ // the neighbor is coarser.
+ // this is the most complicated
+ // case. It might be, that the
+ // neighbor's face will be
+ // refined, but that we will
+ // not see this, as we are
+ // refined in a similar way.
+
+ // so, the neighbor's face must
+ // have children. check, if our
+ // cell's face is one of these
+ // (it could also be a
+ // grand_child)
+ for (unsigned int c=0; c<neighbor_face->n_children(); ++c)
+ if (neighbor_face->child_index(c)==this_face_index)
+ {
+ // if the flagged refine
+ // case of the face is a
+ // subset or the same as
+ // the current refine case,
+ // then the face, as seen
+ // from our cell, won't be
+ // refined by the neighbor
+ if ((neighbor_face->refinement_case() | face_ref_case)
+ == neighbor_face->refinement_case())
+ return false;
+ else
+ {
+ // if we are active, we
+ // must be an
+ // anisotropic child
+ // and the coming
+ // face_ref_case is
+ // isotropic. Thus,
+ // from our cell we
+ // will see exactly the
+ // opposite refine case
+ // that the face has
+ // now...
+ Assert(face_ref_case==RefinementCase<dim-1>::isotropic_refinement, ExcInternalError());
+ expected_face_ref_case = ~neighbor_face->refinement_case();
+ return true;
+ }
+ }
+
+ // so, obviously we were not
+ // one of the children, but a
+ // grandchild. This is only
+ // possible in 3d.
+ Assert(dim==3, ExcInternalError());
+ // In that case, however, no
+ // matter what the neighbor
+ // does, he won't be finer
+ // after the next refinement
+ // step.
+ return false;
+ }
+ }// if face will be refined
+ }// if neighbor is flagged for refinement
+
+ // no cases left, so the neighbor will not
+ // refine the face
+ return false;
+ }
+
+ // version of above function for both active
+ // and non-active cells
+ template <int dim, int spacedim>
+ bool
+ face_will_be_refined_by_neighbor(const TriaIterator<dealii::CellAccessor<dim, spacedim> > &cell,
+ const unsigned int face_no)
+ {
+ RefinementCase<dim-1> dummy = RefinementCase<dim-1>::no_refinement;
+ return face_will_be_refined_by_neighbor_internal(cell, face_no, dummy);
+ }
+
+ // version of above function for active cells
+ // only. Additionally returning the refine
+ // case (to come) of the face under
+ // consideration
+ template <int dim, int spacedim>
+ bool
+ face_will_be_refined_by_neighbor(const TriaActiveIterator<dealii::CellAccessor<dim,spacedim> > &cell,
+ const unsigned int face_no,
+ RefinementCase<dim-1> &expected_face_ref_case)
+ {
+ return face_will_be_refined_by_neighbor_internal(cell, face_no,
+ expected_face_ref_case);
+ }
+
+
+
+ template <int dim, int spacedim>
+ bool
+ satisfies_level1_at_vertex_rule (const Triangulation<dim,spacedim> &triangulation)
+ {
+ std::vector<unsigned int> min_adjacent_cell_level (triangulation.n_vertices(),
+ triangulation.n_levels());
+ std::vector<unsigned int> max_adjacent_cell_level (triangulation.n_vertices(),
+ 0);
+
+ for (typename Triangulation<dim,spacedim>::active_cell_iterator
+ cell = triangulation.begin_active();
+ cell != triangulation.end(); ++cell)
+ for (unsigned int v=0; v<GeometryInfo<dim>::vertices_per_cell; ++v)
+ {
+ min_adjacent_cell_level[cell->vertex_index(v)]
+ = std::min<unsigned int>
+ (min_adjacent_cell_level[cell->vertex_index(v)],
+ cell->level());
+ max_adjacent_cell_level[cell->vertex_index(v)]
+ = std::max<unsigned int> (min_adjacent_cell_level[cell->vertex_index(v)],
+ cell->level());
+ }
+
+ for (unsigned int k=0; k<triangulation.n_vertices(); ++k)
+ if (triangulation.vertex_used(k))
+ if (max_adjacent_cell_level[k] -
+ min_adjacent_cell_level[k] > 1)
+ return false;
+ return true;
+ }
+
+
+
+ /**
+ * Fill the vector @p line_cell_count
+ * needed by @p delete_children with the
+ * number of cells bounded by a given
+ * line.
+ */
+ template <int dim, int spacedim>
+ std::vector<unsigned int>
+ count_cells_bounded_by_line (const Triangulation<dim,spacedim> &triangulation)
+ {
+ if (dim >= 2)
+ {
+ std::vector<unsigned int> line_cell_count(triangulation.n_raw_lines(),0);
+ typename Triangulation<dim,spacedim>::cell_iterator
+ cell=triangulation.begin(),
+ endc=triangulation.end();
+ for (; cell!=endc; ++cell)
+ for (unsigned int l=0; l<GeometryInfo<dim>::lines_per_cell; ++l)
+ ++line_cell_count[cell->line_index(l)];
+ return line_cell_count;
+ }
+ else
+ return std::vector<unsigned int>();
+ }
+
+
+
+
+ /**
+ * Fill the vector @p quad_cell_count
+ * needed by @p delete_children with the
+ * number of cells bounded by a given
+ * quad.
+ */
+ template <int dim, int spacedim>
+ std::vector<unsigned int>
+ count_cells_bounded_by_quad (const Triangulation<dim,spacedim> &triangulation)
+ {
+ if (dim >= 3)
+ {
+ std::vector<unsigned int> quad_cell_count (triangulation.n_raw_quads(),0);
+ typename Triangulation<dim,spacedim>::cell_iterator
+ cell=triangulation.begin(),
+ endc=triangulation.end();
+ for (; cell!=endc; ++cell)
+ for (unsigned int q=0; q<GeometryInfo<dim>::faces_per_cell; ++q)
+ ++quad_cell_count[cell->quad_index(q)];
+ return quad_cell_count;
+ }
+ else
+ return std::vector<unsigned int>();
+ }
+
+
+ /**
+ * For a given Triangulation, update the
+ * number cache for lines. For 1d, we have
+ * to deal with the fact that lines have
+ * levels, whereas for higher dimensions
+ * they do not.
+ *
+ * The second argument indicates
+ * for how many levels the
+ * Triangulation has objects,
+ * though the highest levels need
+ * not contain active cells if they
+ * have previously all been
+ * coarsened away.
+ */
+ template <int dim, int spacedim>
+ void compute_number_cache (const Triangulation<dim,spacedim> &triangulation,
+ const unsigned int level_objects,
+ internal::Triangulation::NumberCache<1> &number_cache)
+ {
+ typedef
+ typename Triangulation<dim,spacedim>::line_iterator line_iterator;
+ typedef
+ typename Triangulation<dim,spacedim>::active_line_iterator active_line_iterator;
+
+ number_cache.n_levels = 0;
+ if (level_objects > 0)
+ {
+ // check whether there are
+ // cells on the highest
+ // levels (there need not be,
+ // since they might all have
+ // been coarsened away)
+ typename Triangulation<dim,spacedim>::raw_cell_iterator
+ cell = triangulation.last_raw (level_objects-1),
+ endc = triangulation.end();
+ for (; cell!=endc; --cell)
+ if (cell->used())
+ {
+ // return level of most
+ // refined existing cell
+ // (+1 because of
+ // counting conventions)
+ number_cache.n_levels = cell->level()+1;
+ break;
+ }
+
+ // no cells at all?
+ Assert (number_cache.n_levels > 0, ExcInternalError());
+ }
+
+ ///////////////////////////////////
+ // update the number of lines
+ // on the different levels in
+ // the cache
+ number_cache.n_lines_level.resize (number_cache.n_levels);
+ number_cache.n_lines = 0;
+
+ number_cache.n_active_lines_level.resize (number_cache.n_levels);
+ number_cache.n_active_lines = 0;
+
+ // for 1d, lines have levels so take
+ // count the objects per level and
+ // globally
+ if (dim == 1)
+ {
+ for (unsigned int level=0; level<number_cache.n_levels; ++level)
+ {
+ // count lines on this level
+ number_cache.n_lines_level[level] = 0;
+
+ line_iterator line = triangulation.begin_line (level),
+ endc = (level == number_cache.n_levels-1 ?
+ line_iterator(triangulation.end_line()) :
+ triangulation.begin_line (level+1));
+ for (; line!=endc; ++line)
+ ++number_cache.n_lines_level[level];
+
+ // update total number of lines
+ number_cache.n_lines += number_cache.n_lines_level[level];
+ }
+
+ // do the update for the number of
+ // active lines as well
+ for (unsigned int level=0; level<number_cache.n_levels; ++level)
+ {
+ // count lines on this level
+ number_cache.n_active_lines_level[level] = 0;
+
+ active_line_iterator line = triangulation.begin_active_line (level),
+ endc = triangulation.end_active_line (level);
+ for (; line!=endc; ++line)
+ ++number_cache.n_active_lines_level[level];
+
+ // update total number of lines
+ number_cache.n_active_lines += number_cache.n_active_lines_level[level];
+ }
+ }
+ else
+ {
+ // for dim>1, there are no
+ // levels for lines
+ {
+ line_iterator line = triangulation.begin_line (),
+ endc = triangulation.end_line();
+ for (; line!=endc; ++line)
+ ++number_cache.n_lines;
+ }
+
+ {
+ active_line_iterator line = triangulation.begin_active_line (),
+ endc = triangulation.end_line();
+ for (; line!=endc; ++line)
+ ++number_cache.n_active_lines;
+ }
+ }
+ }
+
+ /**
+ * For a given Triangulation, update the
+ * number cache for quads. For 2d, we have
+ * to deal with the fact that quads have
+ * levels, whereas for higher dimensions
+ * they do not.
+ *
+ * The second argument indicates
+ * for how many levels the
+ * Triangulation has objects,
+ * though the highest levels need
+ * not contain active cells if they
+ * have previously all been
+ * coarsened away.
+ *
+ * At the beginning of the function, we call the
+ * respective function to update the number
+ * cache for lines.
+ */
+ template <int dim, int spacedim>
+ void compute_number_cache (const Triangulation<dim,spacedim> &triangulation,
+ const unsigned int level_objects,
+ internal::Triangulation::NumberCache<2> &number_cache)
+ {
+ // update lines and n_levels
+ compute_number_cache (triangulation,
+ level_objects,
+ static_cast<internal::Triangulation::NumberCache<1>&>
+ (number_cache));
+
+ typedef
+ typename Triangulation<dim,spacedim>::quad_iterator quad_iterator;
+ typedef
+ typename Triangulation<dim,spacedim>::active_quad_iterator active_quad_iterator;
+
+ ///////////////////////////////////
+ // update the number of quads
+ // on the different levels in
+ // the cache
+ number_cache.n_quads_level.resize (number_cache.n_levels);
+ number_cache.n_quads = 0;
+
+ number_cache.n_active_quads_level.resize (number_cache.n_levels);
+ number_cache.n_active_quads = 0;
+
+ // for 2d, quads have levels so take
+ // count the objects per level and
+ // globally
+ if (dim == 2)
+ {
+ for (unsigned int level=0; level<number_cache.n_levels; ++level)
+ {
+ // count quads on this level
+ number_cache.n_quads_level[level] = 0;
+
+ quad_iterator quad = triangulation.begin_quad (level),
+ endc = (level == number_cache.n_levels-1 ?
+ quad_iterator(triangulation.end_quad()) :
+ triangulation.begin_quad (level+1));
+ for (; quad!=endc; ++quad)
+ ++number_cache.n_quads_level[level];
+
+ // update total number of quads
+ number_cache.n_quads += number_cache.n_quads_level[level];
+ }
+
+ // do the update for the number of
+ // active quads as well
+ for (unsigned int level=0; level<number_cache.n_levels; ++level)
+ {
+ // count quads on this level
+ number_cache.n_active_quads_level[level] = 0;
+
+ active_quad_iterator quad = triangulation.begin_active_quad (level),
+ endc = triangulation.end_active_quad (level);
+ for (; quad!=endc; ++quad)
+ ++number_cache.n_active_quads_level[level];
+
+ // update total number of quads
+ number_cache.n_active_quads += number_cache.n_active_quads_level[level];
+ }
+ }
+ else
+ {
+ // for dim>2, there are no
+ // levels for quads
+ {
+ quad_iterator quad = triangulation.begin_quad (),
+ endc = triangulation.end_quad();
+ for (; quad!=endc; ++quad)
+ ++number_cache.n_quads;
+ }
+
+ {
+ active_quad_iterator quad = triangulation.begin_active_quad (),
+ endc = triangulation.end_quad();
+ for (; quad!=endc; ++quad)
+ ++number_cache.n_active_quads;
+ }
+ }
+ }
+
+ /**
+ * For a given Triangulation, update the
+ * number cache for hexes. For 3d, we have
+ * to deal with the fact that hexes have
+ * levels, whereas for higher dimensions
+ * they do not.
+ *
+ * The second argument indicates
+ * for how many levels the
+ * Triangulation has objects,
+ * though the highest levels need
+ * not contain active cells if they
+ * have previously all been
+ * coarsened away.
+ *
+ * At the end of the function, we call the
+ * respective function to update the number
+ * cache for quads, which will in turn call
+ * the respective function for lines.
+ */
+ template <int dim, int spacedim>
+ void compute_number_cache (const Triangulation<dim,spacedim> &triangulation,
+ const unsigned int level_objects,
+ internal::Triangulation::NumberCache<3> &number_cache)
+ {
+ // update quads, lines and n_levels
+ compute_number_cache (triangulation,
+ level_objects,
+ static_cast<internal::Triangulation::NumberCache<2>&>
+ (number_cache));
+
+ typedef
+ typename Triangulation<dim,spacedim>::hex_iterator hex_iterator;
+ typedef
+ typename Triangulation<dim,spacedim>::active_hex_iterator active_hex_iterator;
+
+ ///////////////////////////////////
+ // update the number of hexes
+ // on the different levels in
+ // the cache
+ number_cache.n_hexes_level.resize (number_cache.n_levels);
+ number_cache.n_hexes = 0;
+
+ number_cache.n_active_hexes_level.resize (number_cache.n_levels);
+ number_cache.n_active_hexes = 0;
+
+ // for 3d, hexes have levels so take
+ // count the objects per level and
+ // globally
+ if (dim == 3)
+ {
+ for (unsigned int level=0; level<number_cache.n_levels; ++level)
+ {
+ // count hexes on this level
+ number_cache.n_hexes_level[level] = 0;
+
+ hex_iterator hex = triangulation.begin_hex (level),
+ endc = (level == number_cache.n_levels-1 ?
+ hex_iterator(triangulation.end_hex()) :
+ triangulation.begin_hex (level+1));
+ for (; hex!=endc; ++hex)
+ ++number_cache.n_hexes_level[level];
+
+ // update total number of hexes
+ number_cache.n_hexes += number_cache.n_hexes_level[level];
+ }
+
+ // do the update for the number of
+ // active hexes as well
+ for (unsigned int level=0; level<number_cache.n_levels; ++level)
+ {
+ // count hexes on this level
+ number_cache.n_active_hexes_level[level] = 0;
+
+ active_hex_iterator hex = triangulation.begin_active_hex (level),
+ endc = triangulation.end_active_hex (level);
+ for (; hex!=endc; ++hex)
+ ++number_cache.n_active_hexes_level[level];
+
+ // update total number of hexes
+ number_cache.n_active_hexes += number_cache.n_active_hexes_level[level];
+ }
+ }
+ else
+ {
+ // for dim>3, there are no
+ // levels for hexs
+ {
+ hex_iterator hex = triangulation.begin_hex (),
+ endc = triangulation.end_hex();
+ for (; hex!=endc; ++hex)
+ ++number_cache.n_hexes;
+ }
+
+ {
+ active_hex_iterator hex = triangulation.begin_active_hex (),
+ endc = triangulation.end_hex();
+ for (; hex!=endc; ++hex)
+ ++number_cache.n_active_hexes;
+ }
+ }
+ }
+
+
+
+ /**
+ * A set of three functions that
+ * reorder the data given to
+ * create_triangulation_compatibility
+ * from the "classic" to the
+ * "current" format of vertex
+ * numbering of cells and
+ * faces. These functions do the
+ * reordering of their arguments
+ * in-place.
+ */
+ void
+ reorder_compatibility (const std::vector<CellData<1> > &,
+ const SubCellData &)
+ {
+ // nothing to do here: the format
+ // hasn't changed for 1d
+ }
+
+
+ void
+ reorder_compatibility (std::vector<CellData<2> > &cells,
+ const SubCellData &)
+ {
+ for (unsigned int cell=0; cell<cells.size(); ++cell)
+ std::swap(cells[cell].vertices[2],cells[cell].vertices[3]);
+ }
+
+
+ void
+ reorder_compatibility (std::vector<CellData<3> > &cells,
+ SubCellData &subcelldata)
+ {
+ unsigned int tmp[GeometryInfo<3>::vertices_per_cell];
+ for (unsigned int cell=0; cell<cells.size(); ++cell)
+ {
+ for (unsigned int i=0; i<GeometryInfo<3>::vertices_per_cell; ++i)
+ tmp[i] = cells[cell].vertices[i];
+ for (unsigned int i=0; i<GeometryInfo<3>::vertices_per_cell; ++i)
+ cells[cell].vertices[GeometryInfo<3>::ucd_to_deal[i]] = tmp[i];
+ }
+
+ // now points in boundary quads
+ std::vector<CellData<2> >::iterator boundary_quad
+ = subcelldata.boundary_quads.begin();
+ std::vector<CellData<2> >::iterator end_quad
+ = subcelldata.boundary_quads.end();
+ for (unsigned int quad_no=0; boundary_quad!=end_quad; ++boundary_quad, ++quad_no)
+ std::swap(boundary_quad->vertices[2], boundary_quad->vertices[3]);
+ }
+
+
+
+ /**
+ * Return the index of the vertex
+ * in the middle of this object,
+ * if it exists. In order to
+ * exist, the object needs to be
+ * refined - for 2D and 3D it
+ * needs to be refined
+ * isotropically or else the
+ * anisotropic children have to
+ * be refined again. If the
+ * middle vertex does not exist,
+ * return
+ * <tt>numbers::invalid_unsigned_int</tt>.
+ *
+ * This function should not really be
+ * used in application programs.
+ */
+ template <int dim, int spacedim>
+ unsigned int
+ middle_vertex_index(const typename Triangulation<dim,spacedim>::line_iterator &line)
+ {
+ if (line->has_children())
+ return line->child(0)->vertex_index(1);
+ return numbers::invalid_unsigned_int;
+ }
+
+
+ template <int dim, int spacedim>
+ unsigned int
+ middle_vertex_index(const typename Triangulation<dim,spacedim>::quad_iterator &quad)
+ {
+ switch (static_cast<unsigned char> (quad->refinement_case()))
+ {
+ case RefinementCase<2>::cut_x:
+ return middle_vertex_index<dim,spacedim>(quad->child(0)->line(1));
+ break;
+ case RefinementCase<2>::cut_y:
+ return middle_vertex_index<dim,spacedim>(quad->child(0)->line(3));
+ break;
+ case RefinementCase<2>::cut_xy:
+ return quad->child(0)->vertex_index(3);
+ break;
+ default:
+ break;
+ }
+ return numbers::invalid_unsigned_int;
+ }
+
+
+ template <int dim, int spacedim>
+ unsigned int
+ middle_vertex_index(const typename Triangulation<dim,spacedim>::hex_iterator &hex)
+ {
+ switch (static_cast<unsigned char> (hex->refinement_case()))
+ {
+ case RefinementCase<3>::cut_x:
+ return middle_vertex_index<dim,spacedim>(hex->child(0)->quad(1));
+ break;
+ case RefinementCase<3>::cut_y:
+ return middle_vertex_index<dim,spacedim>(hex->child(0)->quad(3));
+ break;
+ case RefinementCase<3>::cut_z:
+ return middle_vertex_index<dim,spacedim>(hex->child(0)->quad(5));
+ break;
+ case RefinementCase<3>::cut_xy:
+ return middle_vertex_index<dim,spacedim>(hex->child(0)->line(11));
+ break;
+ case RefinementCase<3>::cut_xz:
+ return middle_vertex_index<dim,spacedim>(hex->child(0)->line(5));
+ break;
+ case RefinementCase<3>::cut_yz:
+ return middle_vertex_index<dim,spacedim>(hex->child(0)->line(7));
+ break;
+ case RefinementCase<3>::cut_xyz:
+ return hex->child(0)->vertex_index(7);
+ break;
+ default:
+ break;
+ }
+ return numbers::invalid_unsigned_int;
+ }
+
+
+ /**
+ * Collect all coarse mesh cells
+ * with at least one vertex at
+ * which the determinant of the
+ * Jacobian is zero or
+ * negative. This is the function
+ * for the case dim==spacedim.
+ */
+ template <int dim>
+ typename Triangulation<dim,dim>::DistortedCellList
+ collect_distorted_coarse_cells (const Triangulation<dim,dim> &triangulation)
+ {
+ typename Triangulation<dim,dim>::DistortedCellList distorted_cells;
+ for (typename Triangulation<dim,dim>::cell_iterator
+ cell = triangulation.begin(0); cell != triangulation.end(0); ++cell)
+ {
+ Point<dim> vertices[GeometryInfo<dim>::vertices_per_cell];
+ for (unsigned int i=0; i<GeometryInfo<dim>::vertices_per_cell; ++i)
+ vertices[i] = cell->vertex(i);
+
+ Tensor<0,dim> determinants[GeometryInfo<dim>::vertices_per_cell];
+ GeometryInfo<dim>::alternating_form_at_vertices (vertices,
+ determinants);
+
+ for (unsigned int i=0; i<GeometryInfo<dim>::vertices_per_cell; ++i)
+ if (determinants[i] <= 1e-9 * std::pow (cell->diameter(),
+ 1.*dim))
+ {
+ distorted_cells.distorted_cells.push_back (cell);
+ break;
+ }
+ }
+
+ return distorted_cells;
+ }
+
+
+ /**
+ * Collect all coarse mesh cells
+ * with at least one vertex at
+ * which the determinant of the
+ * Jacobian is zero or
+ * negative. This is the function
+ * for the case dim!=spacedim,
+ * where we can not determine
+ * whether a cell is twisted as it
+ * may, for example, discretize a
+ * manifold with a twist.
+ */
+ template <int dim, int spacedim>
+ typename Triangulation<dim,spacedim>::DistortedCellList
+ collect_distorted_coarse_cells (const Triangulation<dim,spacedim> &)
+ {
+ return typename Triangulation<dim,spacedim>::DistortedCellList();
+ }
+
+
+
+ /**
+ * Return whether any of the
+ * children of the given cell is
+ * distorted or not. This is the
+ * function for dim==spacedim.
+ */
+ template <int dim>
+ bool
+ has_distorted_children (const typename Triangulation<dim,dim>::cell_iterator &cell,
+ internal::int2type<dim>,
+ internal::int2type<dim>)
+ {
+ Assert (cell->has_children(), ExcInternalError());
+
+ for (unsigned int c=0; c<cell->n_children(); ++c)
+ {
+ Point<dim> vertices[GeometryInfo<dim>::vertices_per_cell];
+ for (unsigned int i=0; i<GeometryInfo<dim>::vertices_per_cell; ++i)
+ vertices[i] = cell->child(c)->vertex(i);
+
+ Tensor<0,dim> determinants[GeometryInfo<dim>::vertices_per_cell];
+ GeometryInfo<dim>::alternating_form_at_vertices (vertices,
+ determinants);
+
+ for (unsigned int i=0; i<GeometryInfo<dim>::vertices_per_cell; ++i)
+ if (determinants[i] <= 1e-9 * std::pow (cell->child(c)->diameter(),
+ 1.*dim))
+ return true;
+ }
+
+ return false;
+ }
+
+
+ /**
+ * Function for dim!=spacedim. As
+ * for
+ * collect_distorted_coarse_cells,
+ * there is nothing that we can do
+ * in this case.
+ */
+ template <int dim, int spacedim>
+ bool
+ has_distorted_children (const typename Triangulation<dim,spacedim>::cell_iterator &,
+ internal::int2type<dim>,
+ internal::int2type<spacedim>)
+ {
+ return false;
+ }
+
+
+
+ /**
+ * For a given triangulation: set up the
+ * neighbor information on all cells.
+ */
+ template <int spacedim>
+ void
+ update_neighbors (Triangulation<1,spacedim> &/*triangulation*/)
+ {}
+
+
+ template <int dim, int spacedim>
+ void
+ update_neighbors (Triangulation<dim,spacedim> &triangulation)
+ {
+ // each face can be neighbored on two sides
+ // by cells. according to the face's
+ // intrinsic normal we define the left
+ // neighbor as the one for which the face
+ // normal points outward, and store that
+ // one first, with an offset of one we
+ // store the right neighbor for which the
+ // face normal points inward. This
+ // information depends on the type of cell
+ // and local number of face for the
+ // 'standard ordering and orientation' of
+ // faces and then on the face_orientation
+ // information for the real mesh. Set up a
+ // table to have fast access to those
+ // offsets (0 for left and 1 for
+ // right). Some of the values are invalid
+ // as they reference too large face
+ // numbers, but we just leave them at a
+ // zero value.
+ //
+ // Note, that in 2d for lines as faces the
+ // normal direction given in the
+ // GeometryInfo class is not consistent. We
+ // thus define here that the normal for a
+ // line points to the right if the line
+ // points upwards.
+ //
+ // first index: dimension (minus 2)
+ // second index: local face index
+ // third index: face_orientation (false and true)
+ static const unsigned int left_right_offset[2][6][2] =
+ {
+ // quadrilateral
+ {{0,1}, // face 0, face_orientation = false and true
+ {1,0}, // face 1, face_orientation = false and true
+ {1,0}, // face 2, face_orientation = false and true
+ {0,1}, // face 3, face_orientation = false and true
+ {0,0}, // face 4, invalid face
+ {0,0}},// face 5, invalid face
+ // hexahedron
+ {{0,1},
+ {1,0},
+ {0,1},
+ {1,0},
+ {0,1},
+ {1,0}}};
+
+ // now create a vector of the two active
+ // neighbors (left and right) for each face
+ // and fill it by looping over all cells. For
+ // cases with anisotropic refinement and more
+ // then one cell neighboring at a given side
+ // of the face we will automatically get the
+ // active one on the highest level as we loop
+ // over cells from lower levels first.
+ const typename Triangulation<dim,spacedim>::cell_iterator dummy;
+ std::vector<typename Triangulation<dim,spacedim>::cell_iterator>
+ adjacent_cells(2*triangulation.n_raw_faces(), dummy);
+
+ typename Triangulation<dim,spacedim>::cell_iterator
+ cell = triangulation.begin(),
+ endc = triangulation.end();
+ for (; cell != endc; ++cell)
+ for (unsigned int f=0; f<GeometryInfo<dim>::faces_per_cell; ++f)
+ {
+ const typename Triangulation<dim,spacedim>::face_iterator face=cell->face(f);
+ const unsigned int offset=left_right_offset[dim-2][f][cell->face_orientation(f)];
+ adjacent_cells[2*face->index() + offset] = cell;
+ // if this cell is not refined, but the
+ // face is, then we'll have to set our
+ // cell as neighbor for the cild faces
+ // as well. Fortunately the normal
+ // orientation of children will be just
+ // the same.
+ if (dim==2)
+ {
+ if (cell->active() && face->has_children())
+ {
+ adjacent_cells[2*face->child(0)->index() + offset] = cell;
+ adjacent_cells[2*face->child(1)->index() + offset] = cell;
+ }
+ }
+ else // -> dim == 3
+ {
+ // We need the same as in 2d
+ // here. Furthermore, if the face is
+ // refined with cut_x or cut_y then
+ // those children again in the other
+ // direction, and if this cell is
+ // refined isotropically (along the
+ // face) then the neighbor will
+ // (probably) be refined as cut_x or
+ // cut_y along the face. For those
+ // neighboring children cells, their
+ // neighbor will be the current,
+ // inactive cell, as our children are
+ // too fine to be neighbors. Catch that
+ // case by also acting on inactive
+ // cells with isotropic refinement
+ // along the face. If the situation
+ // described is not present, the data
+ // will be overwritten later on when we
+ // visit cells on finer levels, so no
+ // harm will be done.
+ if (face->has_children() &&
+ (cell->active() ||
+ GeometryInfo<dim>::face_refinement_case(cell->refinement_case(),f) == RefinementCase<dim-1>::isotropic_refinement))
+ {
+
+ for (unsigned int c=0; c<face->n_children(); ++c)
+ adjacent_cells[2*face->child(c)->index() + offset] = cell;
+ if (face->child(0)->has_children())
+ {
+ adjacent_cells[2*face->child(0)->child(0)->index() + offset] = cell;
+ adjacent_cells[2*face->child(0)->child(1)->index() + offset] = cell;
+ }
+ if (face->child(1)->has_children())
+ {
+ adjacent_cells[2*face->child(1)->child(0)->index() + offset] = cell;
+ adjacent_cells[2*face->child(1)->child(1)->index() + offset] = cell;
+ }
+ } // if cell active and face refined
+ } // else -> dim==3
+ } // for all faces of all cells
+
+ // now loop again over all cells and set the
+ // corresponding neighbor cell. Note, that we
+ // have to use the opposite of the
+ // left_right_offset in this case as we want
+ // the offset of the neighbor, not our own.
+ for (cell=triangulation.begin(); cell != endc; ++cell)
+ for (unsigned int f=0; f<GeometryInfo<dim>::faces_per_cell; ++f)
+ cell->set_neighbor(f,
+ adjacent_cells[2*cell->face(f)->index() + 1
+ - left_right_offset[dim-2][f][cell->face_orientation(f)]]);
+ }
+
+}// end of anonymous namespace
+
+
+namespace internal
+{
+ namespace Triangulation
+ {
+ // make sure that if in the following we
+ // write Triangulation<dim,spacedim>
+ // we mean the *class*
+ // dealii::Triangulation, not the
+ // enclosing namespace
+ // internal::Triangulation
+ using dealii::Triangulation;
+
+ /**
+ * Exception
+ * @ingroup Exceptions
+ */
+ DeclException0 (ExcCellShouldBeUnused);
+ /**
+ * Exception
+ * @ingroup Exceptions
+ */
+ DeclException0 (ExcTooFewVerticesAllocated);
+ /**
+ * Exception
+ * @ingroup Exceptions
+ */
+ DeclException0 (ExcUncaughtState);
+ /**
+ * Exception
+ * @ingroup Exceptions
+ */
+ DeclException2 (ExcGridsDoNotMatch,
+ int, int,
+ << "The present grid has " << arg1 << " active cells, "
+ << "but the one in the file had " << arg2);
+ /**
+ * Exception
+ * @ingroup Exceptions
+ */
+ DeclException1 (ExcGridHasInvalidCell,
+ int,
+ << "Something went wrong when making cell " << arg1
+ << ". Read the docs and the source code "
+ << "for more information.");
+ /**
+ * Exception
+ * @ingroup Exceptions
+ */
+ DeclException0 (ExcGridHasInvalidVertices);
+ /**
+ * Exception
+ * @ingroup Exceptions
+ */
+ DeclException1 (ExcInternalErrorOnCell,
+ int,
+ << "Something went wrong upon construction of cell "
+ << arg1);
+ /**
+ * A cell was entered which has
+ * negative measure. In most
+ * cases, this is due to a wrong
+ * order of the vertices of the
+ * cell.
+ *
+ * @ingroup Exceptions
+ */
+ DeclException1 (ExcCellHasNegativeMeasure,
+ int,
+ << "Cell " << arg1 << " has negative measure.");
+ /**
+ * A cell is created with a
+ * vertex number exceeding the
+ * vertex array.
+ *
+ * @ingroup Exceptions
+ */
+ DeclException3 (ExcInvalidVertexIndex,
+ int, int, int,
+ << "Error while creating cell " << arg1
+ << ": the vertex index " << arg2 << " must be between 0 and "
+ << arg3 << ".");
+ /**
+ * Exception
+ * @ingroup Exceptions
+ */
+ DeclException2 (ExcLineInexistant,
+ int, int,
+ << "When trying to give a boundary indicator to a line: "
+ << "the line with end vertices " << arg1 << " and "
+ << arg2 << " does not exist.");
+ /**
+ * Exception
+ * @ingroup Exceptions
+ */
+ DeclException4 (ExcQuadInexistant,
+ int, int, int, int,
+ << "When trying to give a boundary indicator to a quad: "
+ << "the quad with bounding lines " << arg1 << ", " << arg2
+ << ", " << arg3 << ", " << arg4 << " does not exist.");
+ /**
+ * Exception
+ * @ingroup Exceptions
+ */
+ DeclException0 (ExcInteriorLineCantBeBoundary);
+ /**
+ * Exception
+ * @ingroup Exceptions
+ */
+ DeclException0 (ExcInteriorQuadCantBeBoundary);
+ /**
+ * Exception
+ * @ingroup Exceptions
+ */
+ DeclException2 (ExcMultiplySetLineInfoOfLine,
+ int, int,
+ << "In SubCellData the line info of the line with vertex indices "
+ << arg1 << " and " << arg2 << " is multiply set.");
+
+
+/**
+ * A class into which we put many of the functions that implement
+ * functionality of the Triangulation class. The main reason for this
+ * class is as follows: the majority of the functions in Triangulation
+ * need to be implemented differently for dim==1, dim==2, and
+ * dim==3. However, their implementation is largly independent of the
+ * spacedim template parameter. So we would like to write things like
+ *
+ * template <int spacedim>
+ * void Triangulation<1,spacedim>::create_triangulation (...) {...}
+ *
+ * Unfortunately, C++ doesn't allow this: member functions of class
+ * templates have to be either not specialized at all, or fully
+ * specialized. No partial specialization is allowed. One possible
+ * solution would be to just duplicate the bodies of the functions and
+ * have equally implemented functions
+ *
+ * template <>
+ * void Triangulation<1,1>::create_triangulation (...) {...}
+ *
+ * template <>
+ * void Triangulation<1,2>::create_triangulation (...) {...}
+ *
+ * but that is clearly an unsatisfactory solution. Rather, what we do
+ * is introduce the current Implementation class in which we can write
+ * these functions as member templates over spacedim, i.e. we can have
+ *
+ * template <int dim_, int spacedim_>
+ * template <int spacedim>
+ * void Triangulation<dim_,spacedim_>::Implementation::
+ * create_triangulation (...,
+ * Triangulation<1,spacedim> &tria ) {...}
+ *
+ * The outer template parameters are here unused, only the inner
+ * ones are of real interest.
+ *
+ * One may ask why we put these functions into an class rather
+ * than an anonymous namespace, for example?
+ *
+ * First, these implementation functions need to be friends of the
+ * Triangulation class. It is simpler to make the entire class a friend
+ * rather than listing all members of an implementation namespace as
+ * friends of the Triangulation class (there is no such thing as a "friend
+ * namespace XXX" directive).
+ *
+ * Ideally, we would make this class a member class of the
+ * Triangulation<dim,spacedim> class, since then our implementation functions
+ * have immediate access to the typedefs and static functions of the
+ * surrounding Triangulation class. I.e., we do not have to write "typename
+ * Triangulation<dim,spacedim>::active_cell_iterator" but can write
+ * "active_cell_iterator" right away. This is, in fact, the way it was
+ * implemented first, but we ran into a bug in gcc4.0:
+ * @code
+ * class Triangulation {
+ * struct Implementation;
+ * friend class TriaAccessor;
+ * };
+ *
+ * class TriaAccessor {
+ * struct Implementation;
+ * friend class Triangulation;
+ * };
+ * @endcode
+ *
+ * Here, friendship (per C++ standard) is supposed to extend to all members of
+ * the befriended class, including its 'Implementation' member class. But gcc4.0
+ * gets this wrong: the members of Triangulation::Implementation are not friends
+ * of TriaAccessor and the other way around. Ideally, one would fix this by
+ * saying
+ * @code
+ * class Triangulation {
+ * struct Implementation;
+ * friend class TriaAccessor;
+ * friend class TriaAccessor::Implementation; // **
+ * };
+ *
+ * class TriaAccessor {
+ * struct Implementation;
+ * friend class Triangulation;
+ * friend class Triangulation::Implementation;
+ * };
+ * @endcode
+ * but that's not legal because in ** we don't know yet that TriaAccessor has
+ * a member class Implementation and so we can't make it a friend. The only
+ * way forward at this point was to make Implementation a class in the
+ * internal namespace so that we can forward declare it and make it a friend
+ * of the respective other outer class -- not quite what we wanted but the
+ * only way I could see to make it work...
+ */
+ struct Implementation
+ {
+ /**
+ * Create a triangulation from
+ * given data. This function does
+ * this work for 1-dimensional
+ * triangulations independently
+ * of the actual space dimension.
+ */
+ template <int spacedim>
+ static
+ void
+ create_triangulation (const std::vector<Point<spacedim> > &v,
+ const std::vector<CellData<1> > &cells,
+ const SubCellData &/*subcelldata*/,
+ Triangulation<1,spacedim> &triangulation)
+ {
+ // note: since no boundary
+ // information can be given in one
+ // dimension, the @p{subcelldata}
+ // field is ignored. (only used for
+ // error checking, which is a good
+ // idea in any case)
+ const unsigned int dim=1;
+
+ // copy vertices
+ triangulation.vertices = v;
+ triangulation.vertices_used = std::vector<bool> (v.size(), true);
+
+ // store the indices of the lines
+ // which are adjacent to a given
+ // vertex
+ std::vector<std::vector<int> > lines_at_vertex (v.size());
+
+ // reserve enough space
+ triangulation.levels.push_back (new internal::Triangulation::TriaLevel<dim>);
+ triangulation.levels[0]->reserve_space (cells.size(), dim);
+ triangulation.levels[0]->cells.reserve_space (0,cells.size());
+
+ // make up cells
+ typename Triangulation<dim,spacedim>::raw_line_iterator
+ next_free_line = triangulation.begin_raw_line ();
+ for (unsigned int cell=0; cell<cells.size(); ++cell)
+ {
+ while (next_free_line->used())
+ ++next_free_line;
+
+ next_free_line->set (internal::Triangulation
+ ::TriaObject<1> (cells[cell].vertices[0],
+ cells[cell].vertices[1]));
+ next_free_line->set_used_flag ();
+ next_free_line->set_material_id (cells[cell].material_id);
+ next_free_line->clear_user_data ();
+ next_free_line->set_subdomain_id (0);
+
+ // note that this cell is
+ // adjacent to these vertices
+ lines_at_vertex[cells[cell].vertices[0]].push_back (cell);
+ lines_at_vertex[cells[cell].vertices[1]].push_back (cell);
+ }
+
+
+ // some security tests
+ {
+ unsigned int boundary_nodes = 0;
+ for (unsigned int i=0; i<lines_at_vertex.size(); ++i)
+ switch (lines_at_vertex[i].size())
+ {
+ case 1:
+ // this vertex has only
+ // one adjacent line
+ ++boundary_nodes;
+ break;
+ case 2:
+ break;
+ default:
+ // a node must have one
+ // or two adjacent
+ // lines
+ AssertThrow (false, ExcInternalError());
+ }
+
+ // assert there are no more
+ // than two boundary
+ // nodes. note that if the
+ // space dimension is
+ // bigger than 1, then we
+ // can have fewer than 2
+ // nodes (for example a
+ // ring of cells -- no end
+ // points at all)
+ AssertThrow (((spacedim == 1) && (boundary_nodes == 2))
+ ||
+ (spacedim > 1),
+ ExcMessage("The Triangulation has too many end points"));
+ }
+
+
+
+ // update neighborship info
+ typename Triangulation<dim,spacedim>::active_line_iterator
+ line = triangulation.begin_active_line ();
+ // for all lines
+ for (; line!=triangulation.end(); ++line)
+ // for each of the two vertices
+ for (unsigned int vertex=0; vertex<GeometryInfo<dim>::vertices_per_cell; ++vertex)
+ // if first cell adjacent to
+ // this vertex is the present
+ // one, then the neighbor is
+ // the second adjacent cell and
+ // vice versa
+ if (lines_at_vertex[line->vertex_index(vertex)][0] == line->index())
+ if (lines_at_vertex[line->vertex_index(vertex)].size() == 2)
+ {
+ const typename Triangulation<dim,spacedim>::cell_iterator
+ neighbor (&triangulation,
+ 0, // level
+ lines_at_vertex[line->vertex_index(vertex)][1]);
+ line->set_neighbor (vertex, neighbor);
+ }
+ else
+ // no second adjacent cell
+ // entered -> cell at
+ // boundary
+ line->set_neighbor (vertex, triangulation.end());
+ else
+ // present line is not first
+ // adjacent one -> first
+ // adjacent one is neighbor
+ {
+ const typename Triangulation<dim,spacedim>::cell_iterator
+ neighbor (&triangulation,
+ 0, // level
+ lines_at_vertex[line->vertex_index(vertex)][0]);
+ line->set_neighbor (vertex, neighbor);
+ }
+ }
+
+
+ /**
+ * Create a triangulation from
+ * given data. This function does
+ * this work for 2-dimensional
+ * triangulations independently
+ * of the actual space dimension.
+ */
+ template <int spacedim>
+ static
+ void
+ create_triangulation (const std::vector<Point<spacedim> > &v,
+ const std::vector<CellData<2> > &cells,
+ const SubCellData &subcelldata,
+ Triangulation<2,spacedim> &triangulation)
+ {
+ const unsigned int dim=2;
+
+ // copy vertices
+ triangulation.vertices = v;
+ triangulation.vertices_used = std::vector<bool> (v.size(), true);
+
+ // make up a list of the needed
+ // lines each line is a pair of
+ // vertices. The list is kept
+ // sorted and it is guaranteed that
+ // each line is inserted only once.
+ // While the key of such an entry
+ // is the pair of vertices, the
+ // thing it points to is an
+ // iterator pointing to the line
+ // object itself. In the first run,
+ // these iterators are all invalid
+ // ones, but they are filled
+ // afterwards
+ std::map<std::pair<int,int>,
+ typename Triangulation<dim,spacedim>::line_iterator> needed_lines;
+ for (unsigned int cell=0; cell<cells.size(); ++cell)
+ {
+ for (unsigned int vertex=0; vertex<4; ++vertex)
+ AssertThrow (cells[cell].vertices[vertex] < triangulation.vertices.size(),
+ ExcInvalidVertexIndex (cell, cells[cell].vertices[vertex],
+ triangulation.vertices.size()));
+
+ for (unsigned int line=0; line<GeometryInfo<dim>::faces_per_cell; ++line)
+ {
+ // given a line vertex number
+ // (0,1) on a specific line we
+ // get the cell vertex number
+ // (0-4) through the
+ // line_to_cell_vertices
+ // function
+ std::pair<int,int> line_vertices(
+ cells[cell].vertices[GeometryInfo<dim>::line_to_cell_vertices(line, 0)],
+ cells[cell].vertices[GeometryInfo<dim>::line_to_cell_vertices(line, 1)]);
+
+ // assert that the line was
+ // not already inserted in
+ // reverse order. This
+ // happens in spite of the
+ // vertex rotation above,
+ // if the sense of the cell
+ // was incorrect.
+ //
+ // Here is what usually
+ // happened when this
+ // exception is thrown:
+ // consider these two cells
+ // and the vertices
+ // 3---4---5
+ // | | |
+ // 0---1---2
+ // If in the input vector
+ // the two cells are given
+ // with vertices <0 1 4 3>
+ // and <4 1 2 5>, in the
+ // first cell the middle
+ // line would have
+ // direction 1->4, while in
+ // the second it would be
+ // 4->1. This will cause
+ // the exception.
+ AssertThrow (needed_lines.find(std::make_pair(line_vertices.second,
+ line_vertices.first))
+ ==
+ needed_lines.end(),
+ ExcGridHasInvalidCell(cell));
+
+ // insert line, with
+ // invalid iterator if line
+ // already exists, then
+ // nothing bad happens here
+ needed_lines[line_vertices] = triangulation.end_line();
+ }
+ }
+
+
+ // check that every vertex has at
+ // least two adjacent lines
+ {
+ std::vector<unsigned short int> vertex_touch_count (v.size(), 0);
+ typename std::map<std::pair<int,int>,
+ typename Triangulation<dim,spacedim>::line_iterator>::iterator i;
+ for (i=needed_lines.begin(); i!=needed_lines.end(); i++)
+ {
+ // touch the vertices of
+ // this line
+ ++vertex_touch_count[i->first.first];
+ ++vertex_touch_count[i->first.second];
+ }
+
+ // assert minimum touch count
+ // is at least two. if not so,
+ // then clean triangulation and
+ // exit with an exception
+ AssertThrow (* (std::min_element(vertex_touch_count.begin(),
+ vertex_touch_count.end())) >= 2,
+ ExcGridHasInvalidVertices());
+ }
+
+ // reserve enough space
+ triangulation.levels.push_back (new internal::Triangulation::TriaLevel<dim>);
+ triangulation.faces = new internal::Triangulation::TriaFaces<dim>;
+ triangulation.levels[0]->reserve_space (cells.size(), dim);
+ triangulation.faces->lines.reserve_space (0,needed_lines.size());
+ triangulation.levels[0]->cells.reserve_space (0,cells.size());
+
+ // make up lines
+ {
+ typename Triangulation<dim,spacedim>::raw_line_iterator
+ line = triangulation.begin_raw_line();
+ typename std::map<std::pair<int,int>,
+ typename Triangulation<dim,spacedim>::line_iterator>::iterator i;
+ for (i = needed_lines.begin();
+ line!=triangulation.end_line(); ++line, ++i)
+ {
+ line->set (internal::Triangulation::TriaObject<1>(i->first.first,
+ i->first.second));
+ line->set_used_flag ();
+ line->clear_user_flag ();
+ line->clear_user_data ();
+ i->second = line;
+ }
+ }
+
+
+ // store for each line index
+ // the adjacent cells
+ std::map<int,std::vector<typename Triangulation<dim,spacedim>::cell_iterator> >
+ adjacent_cells;
+
+ // finally make up cells
+ {
+ typename Triangulation<dim,spacedim>::raw_cell_iterator
+ cell = triangulation.begin_raw_quad();
+ for (unsigned int c=0; c<cells.size(); ++c, ++cell)
+ {
+ typename Triangulation<dim,spacedim>::line_iterator
+ lines[GeometryInfo<dim>::lines_per_cell];
+ for (unsigned int line=0; line<GeometryInfo<dim>::lines_per_cell; ++line)
+ lines[line]=needed_lines[std::make_pair(
+ cells[c].vertices[GeometryInfo<dim>::line_to_cell_vertices(line, 0)],
+ cells[c].vertices[GeometryInfo<dim>::line_to_cell_vertices(line, 1)])];
+
+ cell->set (internal::Triangulation::TriaObject<2> (lines[0]->index(),
+ lines[1]->index(),
+ lines[2]->index(),
+ lines[3]->index()));
+
+ cell->set_used_flag ();
+ cell->set_material_id (cells[c].material_id);
+ cell->clear_user_data ();
+ cell->set_subdomain_id (0);
+
+ // note that this cell is
+ // adjacent to the four
+ // lines
+ for (unsigned int line=0; line<GeometryInfo<dim>::lines_per_cell; ++line)
+ adjacent_cells[lines[line]->index()].push_back (cell);
+ }
+ }
+
+
+ for (typename Triangulation<dim,spacedim>::line_iterator
+ line=triangulation.begin_line();
+ line!=triangulation.end_line(); ++line)
+ {
+ const unsigned int n_adj_cells = adjacent_cells[line->index()].size();
+ // assert that every line has
+ // one or two adjacent cells
+ AssertThrow ((n_adj_cells >= 1) &&
+ (n_adj_cells <= 2),
+ ExcInternalError());
+
+ // if only one cell: line is at
+ // boundary -> give it the
+ // boundary indicator zero by
+ // default
+ if (n_adj_cells == 1)
+ line->set_boundary_indicator (0);
+ else
+ // interior line -> 255
+ line->set_boundary_indicator (255);
+ }
+
+ // set boundary indicators where
+ // given
+ std::vector<CellData<1> >::const_iterator boundary_line
+ = subcelldata.boundary_lines.begin();
+ std::vector<CellData<1> >::const_iterator end_boundary_line
+ = subcelldata.boundary_lines.end();
+ for (; boundary_line!=end_boundary_line; ++boundary_line)
+ {
+ typename Triangulation<dim,spacedim>::line_iterator line;
+ std::pair<int,int> line_vertices(std::make_pair(boundary_line->vertices[0],
+ boundary_line->vertices[1]));
+ if (needed_lines.find(line_vertices) != needed_lines.end())
+ // line found in this
+ // direction
+ line = needed_lines[line_vertices];
+ else
+ {
+ // look whether it exists
+ // in reverse direction
+ std::swap (line_vertices.first, line_vertices.second);
+ if (needed_lines.find(line_vertices) != needed_lines.end())
+ line = needed_lines[line_vertices];
+ else
+ // line does not exist
+ AssertThrow (false, ExcLineInexistant(line_vertices.first,
+ line_vertices.second));
+ }
+
+ // assert that we only set
+ // boundary info once
+ AssertThrow (! (line->boundary_indicator() != 0 &&
+ line->boundary_indicator() != 255),
+ ExcMultiplySetLineInfoOfLine(line_vertices.first,
+ line_vertices.second));
+
+ // Assert that only exterior lines
+ // are given a boundary indicator
+ AssertThrow (! (line->boundary_indicator() == 255),
+ ExcInteriorLineCantBeBoundary());
+
+ line->set_boundary_indicator (boundary_line->material_id);
+ }
+
+
+ // finally update neighborship info
+ for (typename Triangulation<dim,spacedim>::cell_iterator
+ cell=triangulation.begin(); cell!=triangulation.end(); ++cell)
+ for (unsigned int side=0; side<4; ++side)
+ if (adjacent_cells[cell->line(side)->index()][0] == cell)
+ // first adjacent cell is
+ // this one
+ {
+ if (adjacent_cells[cell->line(side)->index()].size() == 2)
+ // there is another
+ // adjacent cell
+ cell->set_neighbor (side,
+ adjacent_cells[cell->line(side)->index()][1]);
+ }
+ // first adjacent cell is not this
+ // one, -> it must be the neighbor
+ // we are looking for
+ else
+ cell->set_neighbor (side,
+ adjacent_cells[cell->line(side)->index()][0]);
+ }
+
+
+/**
+ * Invent an object which compares two internal::Triangulation::TriaObject<2>
+ * against each other. This comparison is needed in order to establish a map
+ * of TriaObject<2> to iterators in the Triangulation<3,3>::create_triangulation
+ * function.
+ *
+ * Since this comparison is not canonical, we do not include it into the
+ * general internal::Triangulation::TriaObject<2> class.
+ */
+ struct QuadComparator
+ {
+ inline bool operator () (const internal::Triangulation::TriaObject<2> &q1,
+ const internal::Triangulation::TriaObject<2> &q2) const
+ {
+ // here is room to
+ // optimize the repeated
+ // equality test of the
+ // previous lines; the
+ // compiler will probably
+ // take care of most of
+ // it anyway
+ if ((q1.face(0) < q2.face(0)) ||
+ ((q1.face(0) == q2.face(0)) &&
+ (q1.face(1) < q2.face(1))) ||
+ ((q1.face(0) == q2.face(0)) &&
+ (q1.face(1) == q2.face(1)) &&
+ (q1.face(2) < q2.face(2))) ||
+ ((q1.face(0) == q2.face(0)) &&
+ (q1.face(1) == q2.face(1)) &&
+ (q1.face(2) == q2.face(2)) &&
+ (q1.face(3) < q2.face(3))))
+ return true;
+ else
+ return false;
+ }
+ };
+
+
+
+ template <int spacedim>
+ static
+ void
+ create_triangulation (const std::vector<Point<spacedim> > &v,
+ const std::vector<CellData<3> > &cells,
+ const SubCellData &subcelldata,
+ Triangulation<3,spacedim> &triangulation)
+ {
+ const unsigned int dim=3;
+
+ // copy vertices
+ triangulation.vertices = v;
+ triangulation.vertices_used = std::vector<bool> (v.size(), true);
+
+ // check that all cells have
+ // positive volume. if not call the
+ // invert_all_cells_of_negative_grid
+ // and reorder_cells function of
+ // GridReordering before creating
+ // the triangulation
+ for (unsigned int cell_no=0; cell_no<cells.size(); ++cell_no)
+ AssertThrow (dealii::GridTools::cell_measure(triangulation.vertices,
+ cells[cell_no].vertices) >= 0,
+ ExcGridHasInvalidCell(cell_no));
+
+ ///////////////////////////////////////
+ // first set up some collections of data
+ //
+ // make up a list of the needed
+ // lines
+ //
+ // each line is a pair of
+ // vertices. The list is kept
+ // sorted and it is guaranteed that
+ // each line is inserted only once.
+ // While the key of such an entry
+ // is the pair of vertices, the
+ // thing it points to is an
+ // iterator pointing to the line
+ // object itself. In the first run,
+ // these iterators are all invalid
+ // ones, but they are filled
+ // afterwards same applies for the
+ // quads
+ typename std::map<std::pair<int,int>,
+ typename Triangulation<dim,spacedim>::line_iterator> needed_lines;
+ for (unsigned int cell=0; cell<cells.size(); ++cell)
+ {
+ // check whether vertex indices
+ // are valid ones
+ for (unsigned int vertex=0; vertex<GeometryInfo<dim>::vertices_per_cell; ++vertex)
+ AssertThrow (cells[cell].vertices[vertex] < triangulation.vertices.size(),
+ ExcInvalidVertexIndex (cell, cells[cell].vertices[vertex],
+ triangulation.vertices.size()));
+
+ for (unsigned int line=0; line<GeometryInfo<dim>::lines_per_cell; ++line)
+ {
+ // given a line vertex number
+ // (0,1) on a specific line we
+ // get the cell vertex number
+ // (0-7) through the
+ // line_to_cell_vertices
+ // function
+ std::pair<int,int> line_vertices(
+ cells[cell].vertices[GeometryInfo<dim>::line_to_cell_vertices(line, 0)],
+ cells[cell].vertices[GeometryInfo<dim>::line_to_cell_vertices(line, 1)]);
+
+ // if that line was already inserted
+ // in reverse order do nothing, else
+ // insert the line
+ if ( (needed_lines.find(std::make_pair(line_vertices.second,
+ line_vertices.first))
+ ==
+ needed_lines.end()))
+ {
+ // insert line, with
+ // invalid iterator. if line
+ // already exists, then
+ // nothing bad happens here
+ needed_lines[line_vertices] = triangulation.end_line();
+ }
+ }
+ }
+
+
+ /////////////////////////////////
+ // now for some sanity-checks:
+ //
+ // check that every vertex has at
+ // least tree adjacent lines
+ {
+ std::vector<unsigned short int> vertex_touch_count (v.size(), 0);
+ typename std::map<std::pair<int,int>,
+ typename Triangulation<dim,spacedim>::line_iterator>::iterator i;
+ for (i=needed_lines.begin(); i!=needed_lines.end(); i++)
+ {
+ // touch the vertices of
+ // this line
+ ++vertex_touch_count[i->first.first];
+ ++vertex_touch_count[i->first.second];
+ }
+
+ // assert minimum touch count
+ // is at least three. if not so,
+ // then clean triangulation and
+ // exit with an exception
+ AssertThrow (* (std::min_element(vertex_touch_count.begin(),
+ vertex_touch_count.end())) >= 3,
+ ExcGridHasInvalidVertices());
+ }
+
+
+ ///////////////////////////////////
+ // actually set up data structures
+ // for the lines
+ // reserve enough space
+ triangulation.levels.push_back (new internal::Triangulation::TriaLevel<dim>);
+ triangulation.faces = new internal::Triangulation::TriaFaces<dim>;
+ triangulation.levels[0]->reserve_space (cells.size(), dim);
+ triangulation.faces->lines.reserve_space (0,needed_lines.size());
+
+ // make up lines
+ {
+ typename Triangulation<dim,spacedim>::raw_line_iterator
+ line = triangulation.begin_raw_line();
+ typename std::map<std::pair<int,int>,
+ typename Triangulation<dim,spacedim>::line_iterator>::iterator i;
+ for (i = needed_lines.begin(); line!=triangulation.end_line(); ++line, ++i)
+ {
+ line->set (internal::Triangulation::TriaObject<1>(i->first.first,
+ i->first.second));
+ line->set_used_flag ();
+ line->clear_user_flag ();
+ line->clear_user_data ();
+
+ // now set the iterator for
+ // this line
+ i->second = line;
+ }
+ }
+
+
+ ///////////////////////////////////////////
+ // make up the quads of this triangulation
+ //
+ // same thing: the iterators are
+ // set to the invalid value at
+ // first, we only collect the data
+ // now
+
+ // the bool array stores, wether the lines
+ // are in the standard orientation or not
+
+ // note that QuadComparator is a
+ // class declared and defined in
+ // this file
+ std::map<internal::Triangulation::TriaObject<2>,
+ std::pair<typename Triangulation<dim,spacedim>::quad_iterator,
+ std_cxx1x::array<bool,GeometryInfo<dim>::lines_per_face> >,
+ QuadComparator>
+ needed_quads;
+ for (unsigned int cell=0; cell<cells.size(); ++cell)
+ {
+ // the faces are quads which
+ // consist of four numbers
+ // denoting the index of the
+ // four lines bounding the
+ // quad. we can get this index
+ // by asking @p{needed_lines}
+ // for an iterator to this
+ // line, dereferencing it and
+ // thus return an iterator into
+ // the @p{lines} array of the
+ // triangulation, which is
+ // already set up. we can then
+ // ask this iterator for its
+ // index within the present
+ // level (the level is zero, of
+ // course)
+ //
+ // to make things easier, we
+ // don't create the lines
+ // (pairs of their vertex
+ // indices) in place, but
+ // before they are really
+ // needed.
+ std::pair<int,int> line_list[GeometryInfo<dim>::lines_per_cell],
+ inverse_line_list[GeometryInfo<dim>::lines_per_cell];
+ unsigned int face_line_list[GeometryInfo<dim>::lines_per_face];
+ std_cxx1x::array<bool,GeometryInfo<dim>::lines_per_face> orientation;
+
+ for (unsigned int line=0; line<GeometryInfo<dim>::lines_per_cell; ++line)
+ {
+ line_list[line]=std::pair<int,int> (
+ cells[cell].vertices[GeometryInfo<dim>::line_to_cell_vertices(line, 0)],
+ cells[cell].vertices[GeometryInfo<dim>::line_to_cell_vertices(line, 1)]);
+ inverse_line_list[line]=std::pair<int,int> (
+ cells[cell].vertices[GeometryInfo<dim>::line_to_cell_vertices(line, 1)],
+ cells[cell].vertices[GeometryInfo<dim>::line_to_cell_vertices(line, 0)]);
+ }
+
+ for (unsigned int face=0; face<GeometryInfo<dim>::faces_per_cell; ++face)
+ {
+ // set up a list of the lines to be
+ // used for this face. check the
+ // direction for each line
+ //
+ // given a face line number (0-3) on
+ // a specific face we get the cell
+ // line number (0-11) through the
+ // face_to_cell_lines function
+ for (unsigned int l=0; l<GeometryInfo<dim>::lines_per_face; ++l)
+ if (needed_lines.find (inverse_line_list[GeometryInfo<dim>::
+ face_to_cell_lines(face,l)]) == needed_lines.end())
+ {
+ face_line_list[l]=needed_lines[line_list[GeometryInfo<dim>::
+ face_to_cell_lines(face,l)]]->index();
+ orientation[l]=true;
+ }
+ else
+ {
+ face_line_list[l]=needed_lines[inverse_line_list[GeometryInfo<dim>::
+ face_to_cell_lines(face,l)]]->index();
+ orientation[l]=false;
+ }
+
+
+ internal::Triangulation::TriaObject<2>
+ quad(face_line_list[0],
+ face_line_list[1],
+ face_line_list[2],
+ face_line_list[3]);
+
+ // insert quad, with
+ // invalid iterator
+ //
+ // if quad already exists,
+ // then nothing bad happens
+ // here, as this will then
+ // simply become an
+ // interior face of the
+ // triangulation. however,
+ // we will run into major
+ // trouble if the face was
+ // already inserted in the
+ // opposite
+ // direction. there are
+ // really only two
+ // orientations for a face
+ // to be in, since the edge
+ // directions are already
+ // set. thus, vertex 0 is
+ // the one from which two
+ // edges originate, and
+ // vertex 3 is the one to
+ // which they converge. we
+ // are then left with
+ // orientations 0-1-2-3 and
+ // 2-3-0-1 for the order of
+ // lines. the
+ // corresponding quad can
+ // be easily constructed by
+ // exchanging lines. we do
+ // so here, just to check
+ // that that flipped quad
+ // isn't already in the
+ // triangulation. if it is,
+ // then don't insert the
+ // new one and instead
+ // later set the
+ // face_orientation flag
+ const internal::Triangulation::TriaObject<2>
+ test_quad_1(quad.face(2), quad.face(3),
+ quad.face(0), quad.face(1)),//face_orientation=false, face_flip=false, face_rotation=false
+ test_quad_2(quad.face(0), quad.face(1),
+ quad.face(3), quad.face(2)),//face_orientation=false, face_flip=false, face_rotation=true
+ test_quad_3(quad.face(3), quad.face(2),
+ quad.face(1), quad.face(0)),//face_orientation=false, face_flip=true, face_rotation=false
+ test_quad_4(quad.face(1), quad.face(0),
+ quad.face(2), quad.face(3)),//face_orientation=false, face_flip=true, face_rotation=true
+ test_quad_5(quad.face(2), quad.face(3),
+ quad.face(1), quad.face(0)),//face_orientation=true, face_flip=false, face_rotation=true
+ test_quad_6(quad.face(1), quad.face(0),
+ quad.face(3), quad.face(2)),//face_orientation=true, face_flip=true, face_rotation=false
+ test_quad_7(quad.face(3), quad.face(2),
+ quad.face(0), quad.face(1));//face_orientation=true, face_flip=true, face_rotation=true
+ if (needed_quads.find (test_quad_1) == needed_quads.end() &&
+ needed_quads.find (test_quad_2) == needed_quads.end() &&
+ needed_quads.find (test_quad_3) == needed_quads.end() &&
+ needed_quads.find (test_quad_4) == needed_quads.end() &&
+ needed_quads.find (test_quad_5) == needed_quads.end() &&
+ needed_quads.find (test_quad_6) == needed_quads.end() &&
+ needed_quads.find (test_quad_7) == needed_quads.end())
+ needed_quads[quad] = std::make_pair(triangulation.end_quad(),orientation);
+ }
+ }
+
+
+ /////////////////////////////////
+ // enter the resulting quads into
+ // the arrays of the Triangulation
+ //
+ // first reserve enough space
+ triangulation.faces->quads.reserve_space (0,needed_quads.size());
+
+ {
+ typename Triangulation<dim,spacedim>::raw_quad_iterator
+ quad = triangulation.begin_raw_quad();
+ typename std::map<internal::Triangulation::TriaObject<2>,
+ std::pair<typename Triangulation<dim,spacedim>::quad_iterator,
+ std_cxx1x::array<bool,GeometryInfo<dim>::lines_per_face> >,
+ QuadComparator>
+ ::iterator q;
+ for (q = needed_quads.begin(); quad!=triangulation.end_quad(); ++quad, ++q)
+ {
+ quad->set (q->first);
+ quad->set_used_flag ();
+ quad->clear_user_flag ();
+ quad->clear_user_data ();
+ // set the line orientation
+ quad->set_line_orientation(0,q->second.second[0]);
+ quad->set_line_orientation(1,q->second.second[1]);
+ quad->set_line_orientation(2,q->second.second[2]);
+ quad->set_line_orientation(3,q->second.second[3]);
+
+
+ // now set the iterator for
+ // this quad
+ q->second.first = quad;
+ }
+ }
+
+ /////////////////////////////////
+ // finally create the cells
+ triangulation.levels[0]->cells.reserve_space (cells.size());
+
+ // store for each quad index the
+ // adjacent cells
+ std::map<int,std::vector<typename Triangulation<dim,spacedim>::cell_iterator> >
+ adjacent_cells;
+
+ // finally make up cells
+ {
+ typename Triangulation<dim,spacedim>::raw_cell_iterator
+ cell = triangulation.begin_raw_hex();
+ for (unsigned int c=0; c<cells.size(); ++c, ++cell)
+ {
+ // first find for each of
+ // the cells the quad
+ // iterator of the
+ // respective faces.
+ //
+ // to this end, set up the
+ // lines of this cell and
+ // find the quads that are
+ // bounded by these lines;
+ // these are then the faces
+ // of the present cell
+ std::pair<int,int> line_list[GeometryInfo<dim>::lines_per_cell],
+ inverse_line_list[GeometryInfo<dim>::lines_per_cell];
+ unsigned int face_line_list[4];
+ for (unsigned int line=0; line<GeometryInfo<dim>::lines_per_cell; ++line)
+ {
+ line_list[line]=std::make_pair(
+ cells[c].vertices[GeometryInfo<dim>::line_to_cell_vertices(line, 0)],
+ cells[c].vertices[GeometryInfo<dim>::line_to_cell_vertices(line, 1)]);
+ inverse_line_list[line]=std::pair<int,int> (
+ cells[c].vertices[GeometryInfo<dim>::line_to_cell_vertices(line, 1)],
+ cells[c].vertices[GeometryInfo<dim>::line_to_cell_vertices(line, 0)]);
+ }
+
+ // get the iterators
+ // corresponding to the
+ // faces. also store
+ // whether they are
+ // reversed or not
+ typename Triangulation<dim,spacedim>::quad_iterator
+ face_iterator[GeometryInfo<dim>::faces_per_cell];
+ bool face_orientation[GeometryInfo<dim>::faces_per_cell];
+ bool face_flip[GeometryInfo<dim>::faces_per_cell];
+ bool face_rotation[GeometryInfo<dim>::faces_per_cell];
+ for (unsigned int face=0; face<GeometryInfo<dim>::faces_per_cell; ++face)
+ {
+ for (unsigned int l=0; l<GeometryInfo<dim>::lines_per_face; ++l)
+ if (needed_lines.find (inverse_line_list[GeometryInfo<dim>::
+ face_to_cell_lines(face,l)]) == needed_lines.end())
+ face_line_list[l]=needed_lines[line_list[GeometryInfo<dim>::
+ face_to_cell_lines(face,l)]]->index();
+ else
+ face_line_list[l]=needed_lines[inverse_line_list[GeometryInfo<dim>::
+ face_to_cell_lines(face,l)]]->index();
+
+ internal::Triangulation::TriaObject<2>
+ quad(face_line_list[0],
+ face_line_list[1],
+ face_line_list[2],
+ face_line_list[3]);
+
+ if (needed_quads.find (quad) != needed_quads.end())
+ {
+ // face is in standard
+ // orientation (and not
+ // flipped or rotated). this
+ // must be true for at least
+ // one of the two cells
+ // containing this face
+ // (i.e. for the cell which
+ // originally inserted the
+ // face)
+ face_iterator[face] = needed_quads[quad].first;
+ face_orientation[face] = true;
+ face_flip[face]=false;
+ face_rotation[face]=false;
+ }
+ else
+ {
+ // face must be available in
+ // reverse order
+ // then. construct all
+ // possibilities and check
+ // them one after the other
+ const internal::Triangulation::TriaObject<2>
+ test_quad_1(quad.face(2), quad.face(3),
+ quad.face(0), quad.face(1)),//face_orientation=false, face_flip=false, face_rotation=false
+ test_quad_2(quad.face(0), quad.face(1),
+ quad.face(3), quad.face(2)),//face_orientation=false, face_flip=false, face_rotation=true
+ test_quad_3(quad.face(3), quad.face(2),
+ quad.face(1), quad.face(0)),//face_orientation=false, face_flip=true, face_rotation=false
+ test_quad_4(quad.face(1), quad.face(0),
+ quad.face(2), quad.face(3)),//face_orientation=false, face_flip=true, face_rotation=true
+ test_quad_5(quad.face(2), quad.face(3),
+ quad.face(1), quad.face(0)),//face_orientation=true, face_flip=false, face_rotation=true
+ test_quad_6(quad.face(1), quad.face(0),
+ quad.face(3), quad.face(2)),//face_orientation=true, face_flip=true, face_rotation=false
+ test_quad_7(quad.face(3), quad.face(2),
+ quad.face(0), quad.face(1));//face_orientation=true, face_flip=true, face_rotation=true
+ if (needed_quads.find (test_quad_1) != needed_quads.end())
+ {
+ face_iterator[face] = needed_quads[test_quad_1].first;
+ face_orientation[face] = false;
+ face_flip[face]=false;
+ face_rotation[face]=false;
+ }
+ else if (needed_quads.find (test_quad_2) != needed_quads.end())
+ {
+ face_iterator[face] = needed_quads[test_quad_2].first;
+ face_orientation[face] = false;
+ face_flip[face]=false;
+ face_rotation[face]=true;
+ }
+ else if (needed_quads.find (test_quad_3) != needed_quads.end())
+ {
+ face_iterator[face] = needed_quads[test_quad_3].first;
+ face_orientation[face] = false;
+ face_flip[face]=true;
+ face_rotation[face]=false;
+ }
+ else if (needed_quads.find (test_quad_4) != needed_quads.end())
+ {
+ face_iterator[face] = needed_quads[test_quad_4].first;
+ face_orientation[face] = false;
+ face_flip[face]=true;
+ face_rotation[face]=true;
+ }
+ else if (needed_quads.find (test_quad_5) != needed_quads.end())
+ {
+ face_iterator[face] = needed_quads[test_quad_5].first;
+ face_orientation[face] = true;
+ face_flip[face]=false;
+ face_rotation[face]=true;
+ }
+ else if (needed_quads.find (test_quad_6) != needed_quads.end())
+ {
+ face_iterator[face] = needed_quads[test_quad_6].first;
+ face_orientation[face] = true;
+ face_flip[face]=true;
+ face_rotation[face]=false;
+ }
+ else if (needed_quads.find (test_quad_7) != needed_quads.end())
+ {
+ face_iterator[face] = needed_quads[test_quad_7].first;
+ face_orientation[face] = true;
+ face_flip[face]=true;
+ face_rotation[face]=true;
+ }
+
+ else
+ // we didn't find the
+ // face in any direction,
+ // so something went
+ // wrong above
+ Assert(false,ExcInternalError());
+
+ }
+ }// for all faces
+
+ // make the cell out of
+ // these iterators
+ cell->set (internal::Triangulation
+ ::TriaObject<3> (face_iterator[0]->index(),
+ face_iterator[1]->index(),
+ face_iterator[2]->index(),
+ face_iterator[3]->index(),
+ face_iterator[4]->index(),
+ face_iterator[5]->index()));
+
+ cell->set_used_flag ();
+ cell->set_material_id (cells[c].material_id);
+ cell->clear_user_flag ();
+ cell->clear_user_data ();
+ cell->set_subdomain_id (0);
+
+ // set orientation flag for
+ // each of the faces
+ for (unsigned int quad=0; quad<GeometryInfo<dim>::faces_per_cell; ++quad)
+ {
+ cell->set_face_orientation (quad, face_orientation[quad]);
+ cell->set_face_flip (quad, face_flip[quad]);
+ cell->set_face_rotation (quad, face_rotation[quad]);
+ }
+
+
+ // note that this cell is
+ // adjacent to the six
+ // quads
+ for (unsigned int quad=0; quad<GeometryInfo<dim>::faces_per_cell; ++quad)
+ adjacent_cells[face_iterator[quad]->index()].push_back (cell);
+
+#ifdef DEBUG
+ // make some checks on the
+ // lines and their
+ // ordering
+
+ // first map all cell lines
+ // to the two face lines
+ // which should
+ // coincide. all face lines
+ // are included with a cell
+ // line number (0-11)
+ // key. At the end all keys
+ // will be included twice
+ // (for each of the two
+ // coinciding lines once)
+ std::multimap<unsigned int, std::pair<unsigned int, unsigned int> >
+ cell_to_face_lines;
+ for (unsigned int face=0; face<GeometryInfo<dim>::faces_per_cell; ++face)
+ for (unsigned int line=0; line<GeometryInfo<dim>::lines_per_face; ++line)
+ cell_to_face_lines.insert(
+ std::pair<unsigned int, std::pair<unsigned int, unsigned int> > (
+ GeometryInfo<dim>::face_to_cell_lines(face,line),
+ std::pair<unsigned int, unsigned int> (face,line)));
+ std::multimap<unsigned int, std::pair<unsigned int, unsigned int> >::const_iterator
+ map_iter=cell_to_face_lines.begin();
+
+ for (; map_iter!=cell_to_face_lines.end(); ++map_iter)
+ {
+ const unsigned int cell_line=map_iter->first;
+ const unsigned int face1=map_iter->second.first;
+ const unsigned int line1=map_iter->second.second;
+ ++map_iter;
+ Assert(map_iter!=cell_to_face_lines.end(), ExcInternalErrorOnCell(c));
+ Assert(map_iter->first==cell_line, ExcInternalErrorOnCell(c));
+ const unsigned int face2=map_iter->second.first;
+ const unsigned int line2=map_iter->second.second;
+
+ // check that the pair
+ // of lines really
+ // coincide. Take care
+ // about the face
+ // orientation;
+ Assert (face_iterator[face1]->line(GeometryInfo<dim>::standard_to_real_face_line(
+ line1,
+ face_orientation[face1],
+ face_flip[face1],
+ face_rotation[face1])) ==
+ face_iterator[face2]->line(GeometryInfo<dim>::standard_to_real_face_line(
+ line2,
+ face_orientation[face2],
+ face_flip[face2],
+ face_rotation[face2])),
+ ExcInternalErrorOnCell(c));
+ }
+#endif
+ }
+ }
+
+
+ /////////////////////////////////////////
+ // find those quads which are at the
+ // boundary and mark them appropriately
+ for (typename Triangulation<dim,spacedim>::quad_iterator
+ quad=triangulation.begin_quad(); quad!=triangulation.end_quad(); ++quad)
+ {
+ const unsigned int n_adj_cells = adjacent_cells[quad->index()].size();
+ // assert that every quad has
+ // one or two adjacent cells
+ AssertThrow ((n_adj_cells >= 1) &&
+ (n_adj_cells <= 2),
+ ExcInternalError());
+
+ // if only one cell: quad is at
+ // boundary -> give it the
+ // boundary indicator zero by
+ // default
+ if (n_adj_cells == 1)
+ quad->set_boundary_indicator (0);
+ else
+ // interior quad -> 255
+ quad->set_boundary_indicator (255);
+ }
+
+ /////////////////////////////////////////
+ // next find those lines which are at
+ // the boundary and mark all others as
+ // interior ones
+ //
+ // for this: first mark all lines
+ // as interior
+ for (typename Triangulation<dim,spacedim>::line_iterator
+ line=triangulation.begin_line(); line!=triangulation.end_line(); ++line)
+ line->set_boundary_indicator (255);
+ // next reset all lines bounding
+ // boundary quads as on the
+ // boundary also. note that since
+ // we are in 3d, there are cases
+ // where one or more lines of a
+ // quad that is not on the
+ // boundary, are actually boundary
+ // lines. they will not be marked
+ // when visiting this
+ // face. however, since we do not
+ // support dim-2 dimensional
+ // boundaries (i.e. internal lines
+ // constituting boundaries), every
+ // such line is also part of a face
+ // that is actually on the
+ // boundary, so sooner or later we
+ // get to mark that line for being
+ // on the boundary
+ for (typename Triangulation<dim,spacedim>::quad_iterator
+ quad=triangulation.begin_quad(); quad!=triangulation.end_quad(); ++quad)
+ if (quad->at_boundary())
+ for (unsigned int l=0; l<4; ++l)
+ quad->line(l)->set_boundary_indicator (0);
+
+ ///////////////////////////////////////
+ // now set boundary indicators
+ // where given
+ //
+ // first do so for lines
+ std::vector<CellData<1> >::const_iterator boundary_line
+ = subcelldata.boundary_lines.begin();
+ std::vector<CellData<1> >::const_iterator end_boundary_line
+ = subcelldata.boundary_lines.end();
+ for (; boundary_line!=end_boundary_line; ++boundary_line)
+ {
+ typename Triangulation<dim,spacedim>::line_iterator line;
+ std::pair <int, int> line_vertices(std::make_pair(boundary_line->vertices[0],
+ boundary_line->vertices[1]));
+ if (needed_lines.find(line_vertices) != needed_lines.end())
+ // line found in this
+ // direction
+ line = needed_lines[line_vertices];
+
+ else
+ {
+ // look wether it exists in
+ // reverse direction
+ std::swap (line_vertices.first, line_vertices.second);
+ if (needed_lines.find(line_vertices) != needed_lines.end())
+ line = needed_lines[line_vertices];
+ else
+ // line does not exist
+ AssertThrow (false, ExcLineInexistant(line_vertices.first,
+ line_vertices.second));
+ }
+ // Assert that only exterior
+ // lines are given a boundary
+ // indicator
+ AssertThrow (line->at_boundary(),
+ ExcInteriorLineCantBeBoundary());
+
+ // and make sure that we don't
+ // attempt to reset the
+ // boundary indicator to a
+ // different than the
+ // previously set value
+ if (line->boundary_indicator() != 0)
+ AssertThrow (line->boundary_indicator() == boundary_line->material_id,
+ ExcMessage ("Duplicate boundary lines are only allowed "
+ "if they carry the same boundary indicator."));
+
+ line->set_boundary_indicator (boundary_line->material_id);
+ }
+
+
+ // now go on with boundary faces
+ std::vector<CellData<2> >::const_iterator boundary_quad
+ = subcelldata.boundary_quads.begin();
+ std::vector<CellData<2> >::const_iterator end_boundary_quad
+ = subcelldata.boundary_quads.end();
+ for (; boundary_quad!=end_boundary_quad; ++boundary_quad)
+ {
+ typename Triangulation<dim,spacedim>::quad_iterator quad;
+ typename Triangulation<dim,spacedim>::line_iterator line[4];
+
+ // first find the lines that
+ // are made up of the given
+ // vertices, then build up a
+ // quad from these lines
+ // finally use the find
+ // function of the map template
+ // to find the quad
+ for (unsigned int i=0; i<4; ++i)
+ {
+ std::pair<int, int> line_vertices(
+ boundary_quad->vertices[GeometryInfo<dim-1>::line_to_cell_vertices(i,0)],
+ boundary_quad->vertices[GeometryInfo<dim-1>::line_to_cell_vertices(i,1)]);
+
+ // check whether line
+ // already exists
+ if (needed_lines.find(line_vertices) != needed_lines.end())
+ line[i] = needed_lines[line_vertices];
+ else
+ // look wether it exists
+ // in reverse direction
+ {
+ std::swap (line_vertices.first, line_vertices.second);
+ if (needed_lines.find(line_vertices) != needed_lines.end())
+ line[i] = needed_lines[line_vertices];
+ else
+ // line does
+ // not exist
+ AssertThrow (false, ExcLineInexistant(line_vertices.first,
+ line_vertices.second));
+ }
+ }
+
+
+ // Set up 2 quads that are
+ // built up from the lines for
+ // reasons of comparison to
+ // needed_quads. The second
+ // quad is the reversed version
+ // of the first quad in order
+ // find the quad regardless of
+ // its orientation. This is
+ // introduced for convenience
+ // and because boundary quad
+ // orientation does not carry
+ // any information.
+ internal::Triangulation::TriaObject<2>
+ quad_compare_1(line[0]->index(), line[1]->index(),
+ line[2]->index(), line[3]->index());
+ internal::Triangulation::TriaObject<2>
+ quad_compare_2(line[2]->index(), line[3]->index(),
+ line[0]->index(), line[1]->index());
+
+ // try to find the quad with
+ // lines situated as
+ // constructed above. if it
+ // could not be found, rotate
+ // the boundary lines 3 times
+ // until it is found or it does
+ // not exist.
+
+ // mapping from counterclock to
+ // lexicographic ordering of
+ // quad lines
+ static const unsigned int lex2cclock[4]={3,1,0,2};
+ // copy lines from
+ // lexicographic to
+ // counterclock ordering, as
+ // rotation is much simpler in
+ // counterclock ordering
+ typename Triangulation<dim,spacedim>::line_iterator
+ line_counterclock[4];
+ for (unsigned int i=0; i<4; ++i)
+ line_counterclock[lex2cclock[i]]=line[i];
+ unsigned int n_rotations=0;
+ bool not_found_quad_1;
+ while ( (not_found_quad_1=(needed_quads.find(quad_compare_1) == needed_quads.end())) &&
+ ( needed_quads.find(quad_compare_2) == needed_quads.end()) &&
+ (n_rotations<4))
+ {
+ // use the rotate defined
+ // in <algorithms>
+ rotate(line_counterclock, line_counterclock+1, line_counterclock+4);
+ // update the quads with
+ // rotated lines (i runs in
+ // lexicographic ordering)
+ for (unsigned int i=0; i<4; ++i)
+ {
+ quad_compare_1.set_face(i, line_counterclock[lex2cclock[i]]->index());
+ quad_compare_2.set_face((i+2)%4, line_counterclock[lex2cclock[i]]->index());
+ }
+
+ ++n_rotations;
+ }
+
+ AssertThrow (n_rotations!=4,
+ ExcQuadInexistant(line[0]->index(), line[1]->index(),
+ line[2]->index(), line[3]->index()));
+
+ if (not_found_quad_1)
+ quad = needed_quads[quad_compare_2].first;
+ else
+ quad = needed_quads[quad_compare_1].first;
+
+ // check whether this face is
+ // really an exterior one
+ AssertThrow (quad->at_boundary(),
+ ExcInteriorQuadCantBeBoundary());
+
+ // and make sure that we don't
+ // attempt to reset the
+ // boundary indicator to a
+ // different than the
+ // previously set value
+ if (quad->boundary_indicator() != 0)
+ AssertThrow (quad->boundary_indicator() == boundary_quad->material_id,
+ ExcMessage ("Duplicate boundary quads are only allowed "
+ "if they carry the same boundary indicator."));
+
+ quad->set_boundary_indicator (boundary_quad->material_id);
+ }
+
+
+ /////////////////////////////////////////
+ // finally update neighborship info
+ for (typename Triangulation<dim,spacedim>::cell_iterator
+ cell=triangulation.begin(); cell!=triangulation.end(); ++cell)
+ for (unsigned int face=0; face<6; ++face)
+ if (adjacent_cells[cell->quad(face)->index()][0] == cell)
+ // first adjacent cell is
+ // this one
+ {
+ if (adjacent_cells[cell->quad(face)->index()].size() == 2)
+ // there is another
+ // adjacent cell
+ cell->set_neighbor (face,
+ adjacent_cells[cell->quad(face)->index()][1]);
+ }
+ // first adjacent cell is not this
+ // one, -> it must be the neighbor
+ // we are looking for
+ else
+ cell->set_neighbor (face,
+ adjacent_cells[cell->quad(face)->index()][0]);
+ }
+
+
+ /**
+ * Distort a 1d triangulation in
+ * some random way.
+ */
+ template <int spacedim>
+ static
+ void
+ distort_random (const double factor,
+ const bool keep_boundary,
+ Triangulation<1,spacedim> &triangulation)
+ {
+ const unsigned int dim = 1;
+
+ // if spacedim>1 we need to
+ // make sure that we perturb
+ // points but keep them on
+ // the manifold
+ Assert (spacedim == 1,
+ ExcNotImplemented());
+
+ // this function is mostly
+ // equivalent to that for the
+ // general dimensional case the
+ // only difference being the
+ // correction for split faces which
+ // is not necessary in 1D
+
+ // find the smallest length of the
+ // lines adjacent to the
+ // vertex. take the initial value
+ // to be larger than anything that
+ // might be found: the diameter of
+ // the triangulation, here computed
+ // by adding up the diameters of
+ // the coarse grid cells.
+ double almost_infinite_length = 0;
+ for (typename Triangulation<dim,spacedim>::cell_iterator
+ cell=triangulation.begin(0); cell!=triangulation.end(0); ++cell)
+ almost_infinite_length += cell->diameter();
+
+ std::vector<double> minimal_length (triangulation.vertices.size(),
+ almost_infinite_length);
+ // also note if a vertex is at
+ // the boundary
+ std::vector<bool> at_boundary (triangulation.vertices.size(), false);
+
+ for (typename Triangulation<dim,spacedim>::active_line_iterator
+ line=triangulation.begin_active_line();
+ line != triangulation.end_line(); ++line)
+ {
+ if (keep_boundary && line->at_boundary())
+ {
+ at_boundary[line->vertex_index(0)] = true;
+ at_boundary[line->vertex_index(1)] = true;
+ }
+
+ minimal_length[line->vertex_index(0)]
+ = std::min(line->diameter(),
+ minimal_length[line->vertex_index(0)]);
+ minimal_length[line->vertex_index(1)]
+ = std::min(line->diameter(),
+ minimal_length[line->vertex_index(1)]);
+ }
+
+
+ const unsigned int n_vertices = triangulation.vertices.size();
+ Point<spacedim> shift_vector;
+
+ for (unsigned int vertex=0; vertex<n_vertices; ++vertex)
+ {
+ // ignore this vertex if we
+ // whall keep the boundary and
+ // this vertex *is* at the
+ // boundary
+ if (keep_boundary && at_boundary[vertex])
+ continue;
+
+ // first compute a random shift
+ // vector
+ for (unsigned int d=0; d<spacedim; ++d)
+ shift_vector(d) = std::rand()*1.0/RAND_MAX;
+
+ shift_vector *= factor * minimal_length[vertex] /
+ std::sqrt(shift_vector.square());
+
+ // finally move the vertex
+ triangulation.vertices[vertex] += shift_vector;
+ }
+ }
+
+
+ /**
+ * Distort a triangulation in
+ * some random way. This is the
+ * function taken for the case
+ * dim>1.
+ */
+ template <int dim, int spacedim>
+ static
+ void
+ distort_random (const double factor,
+ const bool keep_boundary,
+ Triangulation<dim,spacedim> &triangulation)
+ {
+//TODO:[?]Implement the random distortion in Triangulation for hanging nodes as well
+// Hanging nodes need to be reset to the correct mean value
+// at the end, which is simple for 2D but difficult for 3D. Maybe take
+// a look at how we get to the original location of the point in the
+// execute_refinement function and copy the relevant lines.
+
+ // this function is mostly
+ // equivalent to that for the
+ // general dimensional case the
+ // only difference being the
+ // correction for split faces which
+ // is not necessary in 1D
+ //
+ // if you change something here,
+ // don't forget to do so there as
+ // well
+
+ // find the smallest length of the
+ // lines adjacent to the
+ // vertex. take the initial value
+ // to be larger than anything that
+ // might be found: the diameter of
+ // the triangulation, here
+ // estimated by adding up the
+ // diameters of the coarse grid
+ // cells.
+ double almost_infinite_length = 0;
+ for (typename Triangulation<dim,spacedim>::cell_iterator
+ cell=triangulation.begin(0); cell!=triangulation.end(0); ++cell)
+ almost_infinite_length += cell->diameter();
+
+ std::vector<double> minimal_length (triangulation.vertices.size(),
+ almost_infinite_length);
+
+ // also note if a vertex is at the
+ // boundary
+ std::vector<bool> at_boundary (triangulation.vertices.size(), false);
+
+ for (typename Triangulation<dim,spacedim>::active_line_iterator
+ line=triangulation.begin_active_line();
+ line != triangulation.end_line(); ++line)
+ {
+ if (keep_boundary && line->at_boundary())
+ {
+ at_boundary[line->vertex_index(0)] = true;
+ at_boundary[line->vertex_index(1)] = true;
+ }
+
+ minimal_length[line->vertex_index(0)]
+ = std::min(line->diameter(),
+ minimal_length[line->vertex_index(0)]);
+ minimal_length[line->vertex_index(1)]
+ = std::min(line->diameter(),
+ minimal_length[line->vertex_index(1)]);
+ }
+
+
+ const unsigned int n_vertices = triangulation.vertices.size();
+ Point<spacedim> shift_vector;
+
+ for (unsigned int vertex=0; vertex<n_vertices; ++vertex)
+ {
+ // ignore this vertex if we
+ // whall keep the boundary and
+ // this vertex *is* at the
+ // boundary
+ if (keep_boundary && at_boundary[vertex])
+ continue;
+
+ // first compute a random shift
+ // vector
+ for (unsigned int d=0; d<spacedim; ++d)
+ shift_vector(d) = std::rand()*1.0/RAND_MAX;
+
+ shift_vector *= factor * minimal_length[vertex] /
+ std::sqrt(shift_vector.square());
+
+ // finally move the vertex
+ triangulation.vertices[vertex] += shift_vector;
+ }
+
+
+ // finally correct hanging nodes
+ // again. The following is not
+ // necessary for 1D
+ typename Triangulation<dim,spacedim>::active_cell_iterator
+ cell = triangulation.begin_active(),
+ endc = triangulation.end();
+ for (; cell!=endc; ++cell)
+ for (unsigned int face=0; face<GeometryInfo<dim>::faces_per_cell; ++face)
+ if (cell->face(face)->has_children() &&
+ !cell->face(face)->at_boundary())
+ // this lines has children,
+ // thus there are restricted
+ // nodes
+ {
+ // not implemented at
+ // present for dim=3 or
+ // higher
+ Assert (dim<=2, ExcNotImplemented());
+
+ // compute where the common
+ // point of the two child
+ // lines will lie and reset
+ // it to the correct value
+ triangulation.vertices[cell->face(face)->child(0)->vertex_index(1)]
+ = (cell->face(face)->vertex(0) +
+ cell->face(face)->vertex(1)) / 2;
+ }
+ }
+
+
+ /**
+ * Actually delete a cell, or rather all
+ * its children, which is the main step for
+ * the coarsening process. This is the
+ * dimension dependent part of @p
+ * execute_coarsening. The second argument
+ * is a vector which gives for each line
+ * index the number of cells containing
+ * this line. This information is needed to
+ * decide whether a refined line may be
+ * coarsened or not in 3D. In 1D and 2D
+ * this argument is not needed and thus
+ * ignored. The same applies for the last
+ * argument and quads instead of lines.
+ */
+ template <int spacedim>
+ static
+ void
+ delete_children (Triangulation<1,spacedim> &triangulation,
+ typename Triangulation<1,spacedim>::cell_iterator &cell,
+ std::vector<unsigned int> &,
+ std::vector<unsigned int> &)
+ {
+ const unsigned int dim = 1;
+
+ // first we need to reset the
+ // neighbor pointers of the
+ // neighbors of this cell's
+ // children to this cell. This is
+ // different for one dimension,
+ // since there neighbors can have a
+ // refinement level differing from
+ // that of this cell's children by
+ // more than one level.
+
+ Assert (!cell->child(0)->has_children() && !cell->child(1)->has_children(),
+ ExcInternalError());
+
+ // first do it for the cells to the
+ // left
+ if (cell->neighbor(0).state() == IteratorState::valid)
+ if (cell->neighbor(0)->has_children())
+ {
+ typename Triangulation<dim,spacedim>::cell_iterator
+ neighbor = cell->neighbor(0);
+ Assert (neighbor->level() == cell->level(), ExcInternalError());
+
+ // right child
+ neighbor = neighbor->child(1);
+ while (1)
+ {
+ Assert (neighbor->neighbor(1) == cell->child(0),
+ ExcInternalError());
+ neighbor->set_neighbor (1, cell);
+
+ // move on to further
+ // children on the
+ // boundary between this
+ // cell and its neighbor
+ if (neighbor->has_children())
+ neighbor = neighbor->child(1);
+ else
+ break;
+ }
+ }
+
+ // now do it for the cells to the
+ // left
+ if (cell->neighbor(1).state() == IteratorState::valid)
+ if (cell->neighbor(1)->has_children())
+ {
+ typename Triangulation<dim,spacedim>::cell_iterator
+ neighbor = cell->neighbor(1);
+ Assert (neighbor->level() == cell->level(), ExcInternalError());
+
+ // left child
+ neighbor = neighbor->child(0);
+ while (1)
+ {
+ Assert (neighbor->neighbor(0) == cell->child(1),
+ ExcInternalError());
+ neighbor->set_neighbor (0, cell);
+
+ // move on to further
+ // children on the
+ // boundary between this
+ // cell and its neighbor
+ if (neighbor->has_children())
+ neighbor = neighbor->child(0);
+ else
+ break;
+ }
+ }
+
+
+ // delete the vertex which will not
+ // be needed anymore. This vertex
+ // is the second of the first child
+ triangulation.vertices_used[cell->child(0)->vertex_index(1)] = false;
+
+ // invalidate children. clear user
+ // pointers, to avoid that they may
+ // appear at unwanted places later
+ // on...
+ for (unsigned int child=0; child<cell->n_children(); ++child)
+ {
+ cell->child(child)->clear_user_data();
+ cell->child(child)->clear_user_flag();
+ cell->child(child)->clear_used_flag();
+ }
+
+
+ // delete pointer to children
+ cell->clear_children ();
+ cell->clear_user_flag();
+ }
+
+
+
+ template <int spacedim>
+ static
+ void
+ delete_children (Triangulation<2,spacedim> &triangulation,
+ typename Triangulation<2,spacedim>::cell_iterator &cell,
+ std::vector<unsigned int> &line_cell_count,
+ std::vector<unsigned int> &)
+ {
+ const unsigned int dim=2;
+ const RefinementCase<dim> ref_case=cell->refinement_case();
+
+ Assert(line_cell_count.size()==triangulation.n_raw_lines(), ExcInternalError());
+
+ // vectors to hold all lines which
+ // may be deleted
+ std::vector<typename Triangulation<dim,spacedim>::line_iterator>
+ lines_to_delete(0);
+
+ lines_to_delete.reserve(4*2+4);
+
+ // now we decrease the counters for
+ // lines contained in the child
+ // cells
+ for (unsigned int c=0; c<cell->n_children(); ++c)
+ {
+ typename Triangulation<dim,spacedim>::cell_iterator
+ child=cell->child(c);
+ for (unsigned int l=0; l<GeometryInfo<dim>::lines_per_cell; ++l)
+ --line_cell_count[child->line_index(l)];
+ }
+
+
+ // delete the vertex which will not
+ // be needed anymore. This vertex
+ // is the second of the second line
+ // of the first child, if the cell
+ // is refined with cut_xy, else there
+ // is no inner vertex.
+ // additionally delete unneeded inner
+ // lines
+ if (ref_case==RefinementCase<dim>::cut_xy)
+ {
+ triangulation.vertices_used[cell->child(0)->line(1)->vertex_index(1)] = false;
+
+ lines_to_delete.push_back(cell->child(0)->line(1));
+ lines_to_delete.push_back(cell->child(0)->line(3));
+ lines_to_delete.push_back(cell->child(3)->line(0));
+ lines_to_delete.push_back(cell->child(3)->line(2));
+ }
+ else
+ {
+ unsigned int inner_face_no=ref_case==RefinementCase<dim>::cut_x ? 1 : 3;
+
+ // the inner line will not be
+ // used any more
+ lines_to_delete.push_back(cell->child(0)->line(inner_face_no));
+ }
+
+ // invalidate children
+ for (unsigned int child=0; child<cell->n_children(); ++child)
+ {
+ cell->child(child)->clear_user_data();
+ cell->child(child)->clear_user_flag();
+ cell->child(child)->clear_used_flag();
+ }
+
+
+ // delete pointer to children
+ cell->clear_children ();
+ cell->clear_refinement_case();
+ cell->clear_user_flag();
+
+ // look at the refinement of outer
+ // lines. if nobody needs those
+ // anymore we can add them to the
+ // list of lines to be deleted.
+ for (unsigned int line_no=0; line_no<GeometryInfo<dim>::lines_per_cell; ++line_no)
+ {
+ typename Triangulation<dim,spacedim>::line_iterator
+ line=cell->line(line_no);
+
+ if (line->has_children())
+ {
+ // if one of the cell counters is
+ // zero, the other has to be as well
+
+ Assert((line_cell_count[line->child_index(0)] == 0 &&
+ line_cell_count[line->child_index(1)] == 0) ||
+ (line_cell_count[line->child_index(0)] > 0 &&
+ line_cell_count[line->child_index(1)] > 0),
+ ExcInternalError());
+
+ if (line_cell_count[line->child_index(0)]==0)
+ {
+ for (unsigned int c=0; c<2; ++c)
+ Assert (!line->child(c)->has_children(),
+ ExcInternalError());
+
+ // we may delete the line's
+ // children and the middle vertex
+ // as no cell references them
+ // anymore
+ triangulation.vertices_used[line->child(0)->vertex_index(1)] = false;
+
+ lines_to_delete.push_back(line->child(0));
+ lines_to_delete.push_back(line->child(1));
+
+ line->clear_children();
+ }
+ }
+ }
+
+ // finally, delete unneeded lines
+
+ // clear user pointers, to avoid that
+ // they may appear at unwanted places
+ // later on...
+ // same for user flags, then finally
+ // delete the lines
+ typename std::vector<typename Triangulation<dim,spacedim>::line_iterator>::iterator
+ line=lines_to_delete.begin(),
+ endline=lines_to_delete.end();
+ for (; line!=endline; ++line)
+ {
+ (*line)->clear_user_data();
+ (*line)->clear_user_flag();
+ (*line)->clear_used_flag();
+ }
+ }
+
+
+
+ template <int spacedim>
+ static
+ void
+ delete_children (Triangulation<3,spacedim> &triangulation,
+ typename Triangulation<3,spacedim>::cell_iterator &cell,
+ std::vector<unsigned int> &line_cell_count,
+ std::vector<unsigned int> &quad_cell_count)
+ {
+ const unsigned int dim=3;
+
+ Assert(line_cell_count.size()==triangulation.n_raw_lines(), ExcInternalError());
+ Assert(quad_cell_count.size()==triangulation.n_raw_quads(), ExcInternalError());
+
+ // first of all, we store the RefineCase of
+ // this cell
+ const RefinementCase<dim> ref_case=cell->refinement_case();
+ // vectors to hold all lines and quads which
+ // may be deleted
+ std::vector<typename Triangulation<dim,spacedim>::line_iterator>
+ lines_to_delete(0);
+ std::vector<typename Triangulation<dim,spacedim>::quad_iterator>
+ quads_to_delete(0);
+
+ lines_to_delete.reserve(12*2+6*4+6);
+ quads_to_delete.reserve(6*4+12);
+
+ // now we decrease the counters for lines and
+ // quads contained in the child cells
+ for (unsigned int c=0; c<cell->n_children(); ++c)
+ {
+ typename Triangulation<dim,spacedim>::cell_iterator
+ child=cell->child(c);
+ for (unsigned int l=0; l<GeometryInfo<dim>::lines_per_cell; ++l)
+ --line_cell_count[child->line_index(l)];
+ for (unsigned int f=0; f<GeometryInfo<dim>::faces_per_cell; ++f)
+ --quad_cell_count[child->quad_index(f)];
+ }
+
+ ///////////////////////////////////////
+ // delete interior quads and lines and the
+ // interior vertex, depending on the
+ // refinement case of the cell
+ //
+ // for append quads and lines: only append
+ // them to the list of objects to be deleted
+
+ switch (ref_case)
+ {
+ case RefinementCase<dim>::cut_x:
+ quads_to_delete.push_back(cell->child(0)->face(1));
+ break;
+ case RefinementCase<dim>::cut_y:
+ quads_to_delete.push_back(cell->child(0)->face(3));
+ break;
+ case RefinementCase<dim>::cut_z:
+ quads_to_delete.push_back(cell->child(0)->face(5));
+ break;
+ case RefinementCase<dim>::cut_xy:
+ quads_to_delete.push_back(cell->child(0)->face(1));
+ quads_to_delete.push_back(cell->child(0)->face(3));
+ quads_to_delete.push_back(cell->child(3)->face(0));
+ quads_to_delete.push_back(cell->child(3)->face(2));
+
+ lines_to_delete.push_back(cell->child(0)->line(11));
+ break;
+ case RefinementCase<dim>::cut_xz:
+ quads_to_delete.push_back(cell->child(0)->face(1));
+ quads_to_delete.push_back(cell->child(0)->face(5));
+ quads_to_delete.push_back(cell->child(3)->face(0));
+ quads_to_delete.push_back(cell->child(3)->face(4));
+
+ lines_to_delete.push_back(cell->child(0)->line(5));
+ break;
+ case RefinementCase<dim>::cut_yz:
+ quads_to_delete.push_back(cell->child(0)->face(3));
+ quads_to_delete.push_back(cell->child(0)->face(5));
+ quads_to_delete.push_back(cell->child(3)->face(2));
+ quads_to_delete.push_back(cell->child(3)->face(4));
+
+ lines_to_delete.push_back(cell->child(0)->line(7));
+ break;
+ case RefinementCase<dim>::cut_xyz:
+ quads_to_delete.push_back(cell->child(0)->face(1));
+ quads_to_delete.push_back(cell->child(2)->face(1));
+ quads_to_delete.push_back(cell->child(4)->face(1));
+ quads_to_delete.push_back(cell->child(6)->face(1));
+
+ quads_to_delete.push_back(cell->child(0)->face(3));
+ quads_to_delete.push_back(cell->child(1)->face(3));
+ quads_to_delete.push_back(cell->child(4)->face(3));
+ quads_to_delete.push_back(cell->child(5)->face(3));
+
+ quads_to_delete.push_back(cell->child(0)->face(5));
+ quads_to_delete.push_back(cell->child(1)->face(5));
+ quads_to_delete.push_back(cell->child(2)->face(5));
+ quads_to_delete.push_back(cell->child(3)->face(5));
+
+ lines_to_delete.push_back(cell->child(0)->line(5));
+ lines_to_delete.push_back(cell->child(0)->line(7));
+ lines_to_delete.push_back(cell->child(0)->line(11));
+ lines_to_delete.push_back(cell->child(7)->line(0));
+ lines_to_delete.push_back(cell->child(7)->line(2));
+ lines_to_delete.push_back(cell->child(7)->line(8));
+ // delete the vertex which will not
+ // be needed anymore. This vertex
+ // is the vertex at the heart of
+ // this cell, which is the sixth of
+ // the first child
+ triangulation.vertices_used[cell->child(0)->vertex_index(7)] = false;
+ break;
+ default:
+ // only remaining case is
+ // no_refinement, thus an error
+ Assert(false, ExcInternalError());
+ break;
+ }
+
+
+ // invalidate children
+ for (unsigned int child=0; child<cell->n_children(); ++child)
+ {
+ cell->child(child)->clear_user_data();
+ cell->child(child)->clear_user_flag();
+
+ for (unsigned int f=0; f<GeometryInfo<dim>::faces_per_cell; ++f)
+ {
+ // set flags denoting deviations from
+ // standard orientation of faces back
+ // to initialization values
+ cell->child(child)->set_face_orientation (f, true);
+ cell->child(child)->set_face_flip(f,false);
+ cell->child(child)->set_face_rotation(f,false);
+ }
+
+ cell->child(child)->clear_used_flag();
+ }
+
+
+ // delete pointer to children
+ cell->clear_children ();
+ cell->clear_refinement_case ();
+ cell->clear_user_flag();
+
+ // so far we only looked at inner quads,
+ // lines and vertices. Now we have to
+ // consider outer ones as well. here, we have
+ // to check, whether there are other cells
+ // still needing these objects. oherwise we
+ // can delete them. first for quads (and
+ // their inner lines).
+
+ for (unsigned int quad_no=0; quad_no<GeometryInfo<dim>::faces_per_cell; ++quad_no)
+ {
+ typename Triangulation<dim,spacedim>::quad_iterator
+ quad=cell->face(quad_no);
+
+ Assert((GeometryInfo<dim>::face_refinement_case(ref_case,quad_no) && quad->has_children()) ||
+ GeometryInfo<dim>::face_refinement_case(ref_case,quad_no)==RefinementCase<dim-1>::no_refinement,
+ ExcInternalError());
+
+ switch (quad->refinement_case())
+ {
+ case RefinementCase<dim-1>::no_refinement:
+ // nothing to do as the quad
+ // is not refined
+ break;
+ case RefinementCase<dim-1>::cut_x:
+ case RefinementCase<dim-1>::cut_y:
+ {
+ // if one of the cell counters is
+ // zero, the other has to be as
+ // well
+ Assert((quad_cell_count[quad->child_index(0)] == 0 &&
+ quad_cell_count[quad->child_index(1)] == 0) ||
+ (quad_cell_count[quad->child_index(0)] > 0 &&
+ quad_cell_count[quad->child_index(1)] > 0),
+ ExcInternalError());
+ // it might be, that the quad is
+ // refined twice anisotropically,
+ // first check, whether we may
+ // delete possible grand_children
+ unsigned int deleted_grandchildren=0;
+ unsigned int number_of_child_refinements=0;
+
+ for (unsigned int c=0; c<2; ++c)
+ if (quad->child(c)->has_children())
+ {
+ ++number_of_child_refinements;
+ // if one of the cell counters is
+ // zero, the other has to be as
+ // well
+ Assert((quad_cell_count[quad->child(c)->child_index(0)] == 0 &&
+ quad_cell_count[quad->child(c)->child_index(1)] == 0) ||
+ (quad_cell_count[quad->child(c)->child_index(0)] > 0 &&
+ quad_cell_count[quad->child(c)->child_index(1)] > 0),
+ ExcInternalError());
+ if (quad_cell_count[quad->child(c)->child_index(0)]==0)
+ {
+ // Assert, that the two
+ // anisotropic
+ // refinements add up to
+ // isotropic refinement
+ Assert(quad->refinement_case()+quad->child(c)->refinement_case()==RefinementCase<dim>::cut_xy,
+ ExcInternalError());
+ // we may delete the
+ // quad's children and
+ // the inner line as no
+ // cell references them
+ // anymore
+ quads_to_delete.push_back(quad->child(c)->child(0));
+ quads_to_delete.push_back(quad->child(c)->child(1));
+ if (quad->child(c)->refinement_case()==RefinementCase<2>::cut_x)
+ lines_to_delete.push_back(quad->child(c)->child(0)->line(1));
+ else
+ lines_to_delete.push_back(quad->child(c)->child(0)->line(3));
+ quad->child(c)->clear_children();
+ quad->child(c)->clear_refinement_case();
+ ++deleted_grandchildren;
+ }
+ }
+ // if no grandchildren are left, we
+ // may as well delete the
+ // refinement of the inner line
+ // between our children and the
+ // corresponding vertex
+ if (number_of_child_refinements>0 &&
+ deleted_grandchildren==number_of_child_refinements)
+ {
+ typename Triangulation<dim,spacedim>::line_iterator
+ middle_line;
+ if (quad->refinement_case()==RefinementCase<2>::cut_x)
+ middle_line=quad->child(0)->line(1);
+ else
+ middle_line=quad->child(0)->line(3);
+
+ lines_to_delete.push_back(middle_line->child(0));
+ lines_to_delete.push_back(middle_line->child(1));
+ triangulation.vertices_used[middle_vertex_index<dim,spacedim>(middle_line)]
+ = false;
+ middle_line->clear_children();
+ }
+
+ // now consider the direct children
+ // of the given quad
+ if (quad_cell_count[quad->child_index(0)]==0)
+ {
+ // we may delete the quad's
+ // children and the inner line
+ // as no cell references them
+ // anymore
+ quads_to_delete.push_back(quad->child(0));
+ quads_to_delete.push_back(quad->child(1));
+ if (quad->refinement_case()==RefinementCase<2>::cut_x)
+ lines_to_delete.push_back(quad->child(0)->line(1));
+ else
+ lines_to_delete.push_back(quad->child(0)->line(3));
+
+ // if the counters just dropped
+ // to zero, otherwise the
+ // children would have been
+ // deleted earlier, then this
+ // cell's children must have
+ // contained the anisotropic
+ // quad children. thus, if
+ // those have again anisotropic
+ // children, which are in
+ // effect isotropic children of
+ // the original quad, those are
+ // still needed by a
+ // neighboring cell and we
+ // cannot delete them. instead,
+ // we have to reset this quad's
+ // refine case to isotropic and
+ // set the children
+ // accordingly.
+ if (quad->child(0)->has_children())
+ if (quad->refinement_case()==RefinementCase<2>::cut_x)
+ {
+ // now evereything is
+ // quite complicated. we
+ // have the children
+ // numbered according to
+ //
+ // *---*---*
+ // |n+1|m+1|
+ // *---*---*
+ // | n | m |
+ // *---*---*
+ //
+ // from the original
+ // anisotropic
+ // refinement. we have to
+ // reorder them as
+ //
+ // *---*---*
+ // | m |m+1|
+ // *---*---*
+ // | n |n+1|
+ // *---*---*
+ //
+ // for isotropic refinement.
+ //
+ // this is a bit ugly, of
+ // course: loop over all
+ // cells on all levels
+ // and look for faces n+1
+ // (switch_1) and m
+ // (switch_2).
+ const typename Triangulation<dim,spacedim>::quad_iterator
+ switch_1=quad->child(0)->child(1),
+ switch_2=quad->child(1)->child(0);
+
+ Assert(!switch_1->has_children(), ExcInternalError());
+ Assert(!switch_2->has_children(), ExcInternalError());
+
+ const int switch_1_index=switch_1->index();
+ const int switch_2_index=switch_2->index();
+ for (unsigned int l=0; l<triangulation.levels.size(); ++l)
+ for (unsigned int h=0; h<triangulation.levels[l]->cells.cells.size(); ++h)
+ for (unsigned int q=0; q<GeometryInfo<dim>::faces_per_cell; ++q)
+ {
+ const int index=triangulation.levels[l]->cells.cells[h].face(q);
+ if (index==switch_1_index)
+ triangulation.levels[l]->cells.cells[h].set_face(q,switch_2_index);
+ else if (index==switch_2_index)
+ triangulation.levels[l]->cells.cells[h].set_face(q,switch_1_index);
+ }
+ // now we have to copy
+ // all information of the
+ // two quads
+ const int switch_1_lines[4]=
+ {switch_1->line_index(0),
+ switch_1->line_index(1),
+ switch_1->line_index(2),
+ switch_1->line_index(3)};
+ const bool switch_1_line_orientations[4]=
+ {switch_1->line_orientation(0),
+ switch_1->line_orientation(1),
+ switch_1->line_orientation(2),
+ switch_1->line_orientation(3)};
+ const unsigned char switch_1_boundary_indicator=switch_1->boundary_indicator();
+ const unsigned int switch_1_user_index=switch_1->user_index();
+ const bool switch_1_user_flag=switch_1->user_flag_set();
+
+ switch_1->set(internal::Triangulation::TriaObject<2>(switch_2->line_index(0),
+ switch_2->line_index(1),
+ switch_2->line_index(2),
+ switch_2->line_index(3)));
+ switch_1->set_line_orientation(0, switch_2->line_orientation(0));
+ switch_1->set_line_orientation(1, switch_2->line_orientation(1));
+ switch_1->set_line_orientation(2, switch_2->line_orientation(2));
+ switch_1->set_line_orientation(3, switch_2->line_orientation(3));
+ switch_1->set_boundary_indicator(switch_2->boundary_indicator());
+ switch_1->set_user_index(switch_2->user_index());
+ if (switch_2->user_flag_set())
+ switch_1->set_user_flag();
+ else
+ switch_1->clear_user_flag();
+
+ switch_2->set(internal::Triangulation::TriaObject<2>(switch_1_lines[0],
+ switch_1_lines[1],
+ switch_1_lines[2],
+ switch_1_lines[3]));
+ switch_2->set_line_orientation(0, switch_1_line_orientations[0]);
+ switch_2->set_line_orientation(1, switch_1_line_orientations[1]);
+ switch_2->set_line_orientation(2, switch_1_line_orientations[2]);
+ switch_2->set_line_orientation(3, switch_1_line_orientations[3]);
+ switch_2->set_boundary_indicator(switch_1_boundary_indicator);
+ switch_2->set_user_index(switch_1_user_index);
+ if (switch_1_user_flag)
+ switch_2->set_user_flag();
+ else
+ switch_2->clear_user_flag();
+
+ const unsigned int child_0=quad->child(0)->child_index(0);
+ const unsigned int child_2=quad->child(1)->child_index(0);
+ quad->clear_children();
+ quad->clear_refinement_case();
+ quad->set_refinement_case(RefinementCase<2>::cut_xy);
+ quad->set_children(0,child_0);
+ quad->set_children(2,child_2);
+ std::swap(quad_cell_count[child_0+1],quad_cell_count[child_2]);
+ }
+ else
+ {
+ // the face was refined
+ // with cut_y, thus the
+ // children are already
+ // in correct order. we
+ // only have to set them
+ // correctly, deleting
+ // the indirection of two
+ // anisotropic refinement
+ // and going directly
+ // from the quad to
+ // isotropic children
+ const unsigned int child_0=quad->child(0)->child_index(0);
+ const unsigned int child_2=quad->child(1)->child_index(0);
+ quad->clear_children();
+ quad->clear_refinement_case();
+ quad->set_refinement_case(RefinementCase<2>::cut_xy);
+ quad->set_children(0,child_0);
+ quad->set_children(2,child_2);
+ }
+ else
+ {
+ quad->clear_children();
+ quad->clear_refinement_case();
+ }
+
+
+ }
+ break;
+ }
+ case RefinementCase<dim-1>::cut_xy:
+ {
+ // if one of the cell counters is
+ // zero, the others have to be as
+ // well
+
+ Assert((quad_cell_count[quad->child_index(0)] == 0 &&
+ quad_cell_count[quad->child_index(1)] == 0 &&
+ quad_cell_count[quad->child_index(2)] == 0 &&
+ quad_cell_count[quad->child_index(3)] == 0) ||
+ (quad_cell_count[quad->child_index(0)] > 0 &&
+ quad_cell_count[quad->child_index(1)] > 0 &&
+ quad_cell_count[quad->child_index(2)] > 0 &&
+ quad_cell_count[quad->child_index(3)] > 0),
+ ExcInternalError());
+
+ if (quad_cell_count[quad->child_index(0)]==0)
+ {
+ // we may delete the quad's
+ // children, the inner lines
+ // and the middle vertex as no
+ // cell references them anymore
+ lines_to_delete.push_back(quad->child(0)->line(1));
+ lines_to_delete.push_back(quad->child(3)->line(0));
+ lines_to_delete.push_back(quad->child(0)->line(3));
+ lines_to_delete.push_back(quad->child(3)->line(2));
+
+ for (unsigned int child=0; child<quad->n_children(); ++child)
+ quads_to_delete.push_back(quad->child(child));
+
+ triangulation.vertices_used[quad->child(0)->vertex_index(3)] = false;
+
+ quad->clear_children();
+ quad->clear_refinement_case();
+ }
+ }
+ break;
+
+ default:
+ Assert(false, ExcInternalError());
+ break;
+ }
+
+ }
+
+ // now we repeat a similar procedure
+ // for the outer lines of this cell.
+
+ // if in debug mode: check that each
+ // of the lines for which we consider
+ // deleting the children in fact has
+ // children (the bits/coarsening_3d
+ // test tripped over this initially)
+ for (unsigned int line_no=0; line_no<GeometryInfo<dim>::lines_per_cell; ++line_no)
+ {
+ typename Triangulation<dim,spacedim>::line_iterator
+ line=cell->line(line_no);
+
+ Assert((GeometryInfo<dim>::line_refinement_case(ref_case,line_no) && line->has_children()) ||
+ GeometryInfo<dim>::line_refinement_case(ref_case,line_no)==RefinementCase<1>::no_refinement,
+ ExcInternalError());
+
+ if (line->has_children())
+ {
+ // if one of the cell counters is
+ // zero, the other has to be as well
+
+ Assert((line_cell_count[line->child_index(0)] == 0 &&
+ line_cell_count[line->child_index(1)] == 0) ||
+ (line_cell_count[line->child_index(0)] > 0 &&
+ line_cell_count[line->child_index(1)] > 0),
+ ExcInternalError());
+
+ if (line_cell_count[line->child_index(0)]==0)
+ {
+ for (unsigned int c=0; c<2; ++c)
+ Assert (!line->child(c)->has_children(),
+ ExcInternalError());
+
+ // we may delete the line's
+ // children and the middle vertex
+ // as no cell references them
+ // anymore
+ triangulation.vertices_used[line->child(0)->vertex_index(1)] = false;
+
+ lines_to_delete.push_back(line->child(0));
+ lines_to_delete.push_back(line->child(1));
+
+ line->clear_children();
+ }
+ }
+ }
+
+ // finally, delete unneeded quads and lines
+
+ // clear user pointers, to avoid that
+ // they may appear at unwanted places
+ // later on...
+ // same for user flags, then finally
+ // delete the quads and lines
+ typename std::vector<typename Triangulation<dim,spacedim>::line_iterator>::iterator
+ line=lines_to_delete.begin(),
+ endline=lines_to_delete.end();
+ for (; line!=endline; ++line)
+ {
+ (*line)->clear_user_data();
+ (*line)->clear_user_flag();
+ (*line)->clear_used_flag();
+ }
+
+ typename std::vector<typename Triangulation<dim,spacedim>::quad_iterator>::iterator
+ quad=quads_to_delete.begin(),
+ endquad=quads_to_delete.end();
+ for (; quad!=endquad; ++quad)
+ {
+ (*quad)->clear_user_data();
+ (*quad)->clear_children();
+ (*quad)->clear_refinement_case();
+ (*quad)->clear_user_flag();
+ (*quad)->clear_used_flag();
+ }
+ }
+
+
+ /**
+ * Create the children of a 2d
+ * cell. The arguments indicate
+ * the next free spots in the
+ * vertices, lines, and cells
+ * arrays.
+ *
+ * The faces of the cell have to
+ * be refined already, whereas
+ * the inner lines in 2D will be
+ * created in this
+ * function. Therefore iterator
+ * pointers into the vectors of
+ * lines, quads and cells have to
+ * be passed, which point at (or
+ * "before") the reserved space.
+ */
+ template <int spacedim>
+ static
+ void
+ create_children (Triangulation<2,spacedim> &triangulation,
+ unsigned int &next_unused_vertex,
+ typename Triangulation<2,spacedim>::raw_line_iterator &next_unused_line,
+ typename Triangulation<2,spacedim>::raw_cell_iterator &next_unused_cell,
+ typename Triangulation<2,spacedim>::cell_iterator &cell)
+ {
+ const unsigned int dim=2;
+ // clear refinement flag
+ const RefinementCase<dim> ref_case=cell->refine_flag_set();
+ cell->clear_refine_flag ();
+
+/* For the refinement process: since we go the levels up from the lowest, there
+ are (unlike above) only two possibilities: a neighbor cell is on the same
+ level or one level up (in both cases, it may or may not be refined later on,
+ but we don't care here).
+
+ First:
+ Set up an array of the 3x3 vertices, which are distributed on the cell
+ (the array consists of indices into the @p{vertices} std::vector
+
+ 2--7--3
+ | | |
+ 4--8--5
+ | | |
+ 0--6--1
+
+ note: in case of cut_x or cut_y not all these vertices are needed for the new
+ cells
+
+ Second:
+ Set up an array of the new lines (the array consists of iterator pointers
+ into the lines arrays)
+
+ .-6-.-7-. The directions are: .->-.->-.
+ 1 9 3 ^ ^ ^
+ .-10.11-. .->-.->-.
+ 0 8 2 ^ ^ ^
+ .-4-.-5-. .->-.->-.
+
+ cut_x:
+ .-4-.-5-.
+ | | |
+ 0 6 1
+ | | |
+ .-2-.-3-.
+
+ cut_y:
+ .---5---.
+ 1 3
+ .---6---.
+ 0 2
+ .---4---.
+
+
+ Third:
+ Set up an array of neighbors:
+
+ 6 7
+ .--.--.
+ 1| | |3
+ .--.--.
+ 0| | |2
+ .--.--.
+ 4 5
+
+ We need this array for two reasons: first to get the lines which will
+ bound the four subcells (if the neighboring cell is refined, these
+ lines already exist), and second to update neighborship information.
+ Since if a neighbor is not refined, its neighborship record only
+ points to the present, unrefined, cell rather than the children we
+ are presently creating, we only need the neighborship information
+ if the neighbor cells are refined. In all other cases, we store
+ the unrefined neighbor address
+
+ We also need for every neighbor (if refined) which number among its
+ neighbors the present (unrefined) cell has, since that number is to
+ be replaced and because that also is the number of the subline which
+ will be the interface between that neighbor and the to be created cell.
+ We will store this number (between 0 and 3) in the field
+ @p{neighbors_neighbor}.
+
+ It would be sufficient to use the children of the common line to the
+ neighbor, if we only wanted to get the new sublines and the new vertex,
+ but because we need to update the neighborship information of the
+ two refined subcells of the neighbor, we need to search these anyway.
+
+ Convention:
+ The created children are numbered like this:
+
+ .--.--.
+ |2 . 3|
+ .--.--.
+ |0 | 1|
+ .--.--.
+*/
+
+ // collect the indices
+ // all vertices
+ // 2--7--3
+ // | | |
+ // 4--8--5
+ // | | |
+ // 0--6--1
+ int new_vertices[9];
+ for (unsigned int vertex_no=0; vertex_no<4; ++vertex_no)
+ new_vertices[vertex_no]=cell->vertex_index(vertex_no);
+ for (unsigned int line_no=0; line_no<4; ++line_no)
+ if (cell->line(line_no)->has_children())
+ new_vertices[4+line_no]=cell->line(line_no)->child(0)->vertex_index(1);
+
+ if (ref_case==RefinementCase<dim>::cut_xy)
+ {
+ // find the next
+ // unused vertex and
+ // set it
+ // appropriately
+ while (triangulation.vertices_used[next_unused_vertex] == true)
+ ++next_unused_vertex;
+ Assert (next_unused_vertex < triangulation.vertices.size(),
+ ExcTooFewVerticesAllocated());
+ triangulation.vertices_used[next_unused_vertex] = true;
+
+ new_vertices[8]=next_unused_vertex;
+
+ Point<spacedim> new_point;
+ if (dim == spacedim)
+ {
+ for (unsigned int i=0; i<8; ++i)
+ new_point += triangulation.vertices[new_vertices[i]];
+ new_point /= 8.0;
+ }
+ else
+ {
+ // new vertex is
+ // placed on the
+ // surface according
+ // to the information
+ // stored in the
+ // boundary class
+ new_point =
+ triangulation.boundary[cell->material_id()]
+ ->get_new_point_on_quad (cell);
+ }
+
+ triangulation.vertices[new_vertices[8]] = new_point;
+
+
+ // if the user_flag is set, i.e. if the
+ // cell is at the boundary, use a
+ // different calculation of the middle
+ // vertex here. this is of advantage, if
+ // the boundary is strongly curved and
+ // the cell has a high aspect ratio. this
+ // can happen for example, if it was
+ // refined anisotropically before.
+ if (cell->user_flag_set())
+ {
+ // first reset the user_flag
+ cell->clear_user_flag();
+ // the user flag indicates: at least
+ // one face is at the boundary. if it
+ // is only one, set the new middle
+ // vertex in a different way to avoid
+ // some mis-shaped elements if the
+ // new point on the boundary is not
+ // where we expect it, especially if
+ // it is to far inside the current
+ // cell
+ unsigned int bound_face=GeometryInfo<dim>::faces_per_cell;
+ for (unsigned int face=0; face<GeometryInfo<dim>::faces_per_cell; ++face)
+ if (cell->face(face)->at_boundary())
+ {
+ if (bound_face == GeometryInfo<dim>::faces_per_cell)
+ // no boundary face found so
+ // far, so set it now
+ bound_face=face;
+ else
+ // there is another boundary
+ // face, so reset bound_face to
+ // invalid value as a flag to
+ // do nothing in the following
+ bound_face=GeometryInfo<dim>::faces_per_cell+1;
+ }
+
+ if (bound_face<GeometryInfo<dim>::faces_per_cell)
+ // reset the cell's middle vertex
+ // to the middle of the straight
+ // connection between the new
+ // points on this face and on the
+ // opposite face
+ triangulation.vertices[new_vertices[8]]
+ = 0.5*(cell->face(bound_face)
+ ->child(0)->vertex(1)+
+ cell->face(GeometryInfo<dim>
+ ::opposite_face[bound_face])
+ ->child(0)->vertex(1));
+ }
+ }
+
+
+ // Now the lines:
+ typename Triangulation<dim,spacedim>::raw_line_iterator new_lines[12];
+ unsigned int lmin=8;
+ unsigned int lmax=12;
+ if (ref_case!=RefinementCase<dim>::cut_xy)
+ {
+ lmin=6;
+ lmax=7;
+ }
+
+ for (unsigned int l=lmin; l<lmax; ++l)
+ {
+ while (next_unused_line->used() == true)
+ ++next_unused_line;
+ new_lines[l] = next_unused_line;
+ ++next_unused_line;
+
+ Assert (new_lines[l]->used() == false,
+ ExcCellShouldBeUnused());
+ }
+
+ if (ref_case==RefinementCase<dim>::cut_xy)
+ {
+ // .-6-.-7-.
+ // 1 9 3
+ // .-10.11-.
+ // 0 8 2
+ // .-4-.-5-.
+
+ // lines 0-7 already
+ // exist, create only
+ // the four interior
+ // lines 8-11
+ unsigned int l=0;
+ for (unsigned int face_no=0; face_no<GeometryInfo<dim>::faces_per_cell; ++face_no)
+ for (unsigned int c=0; c<2; ++c, ++l)
+ new_lines[l]=cell->line(face_no)->child(c);
+ Assert(l==8, ExcInternalError());
+
+ new_lines[8] ->set (internal::Triangulation::
+ TriaObject<1>(new_vertices[6], new_vertices[8]));
+ new_lines[9] ->set (internal::Triangulation::
+ TriaObject<1>(new_vertices[8], new_vertices[7]));
+ new_lines[10]->set (internal::Triangulation::
+ TriaObject<1>(new_vertices[4], new_vertices[8]));
+ new_lines[11]->set (internal::Triangulation::
+ TriaObject<1>(new_vertices[8], new_vertices[5]));
+ }
+ else if (ref_case==RefinementCase<dim>::cut_x)
+ {
+ // .-4-.-5-.
+ // | | |
+ // 0 6 1
+ // | | |
+ // .-2-.-3-.
+ new_lines[0]=cell->line(0);
+ new_lines[1]=cell->line(1);
+ new_lines[2]=cell->line(2)->child(0);
+ new_lines[3]=cell->line(2)->child(1);
+ new_lines[4]=cell->line(3)->child(0);
+ new_lines[5]=cell->line(3)->child(1);
+ new_lines[6]->set (internal::Triangulation::
+ TriaObject<1>(new_vertices[6], new_vertices[7]));
+ }
+ else
+ {
+ Assert(ref_case==RefinementCase<dim>::cut_y, ExcInternalError());
+ // .---5---.
+ // 1 3
+ // .---6---.
+ // 0 2
+ // .---4---.
+ new_lines[0]=cell->line(0)->child(0);
+ new_lines[1]=cell->line(0)->child(1);
+ new_lines[2]=cell->line(1)->child(0);
+ new_lines[3]=cell->line(1)->child(1);
+ new_lines[4]=cell->line(2);
+ new_lines[5]=cell->line(3);
+ new_lines[6]->set (internal::Triangulation::
+ TriaObject<1>(new_vertices[4], new_vertices[5]));
+ }
+
+ for (unsigned int l=lmin; l<lmax; ++l)
+ {
+ new_lines[l]->set_used_flag();
+ new_lines[l]->clear_user_flag();
+ new_lines[l]->clear_user_data();
+ new_lines[l]->clear_children();
+ // interior line
+ new_lines[l]->set_boundary_indicator(255);
+ }
+
+ // Now add the four (two)
+ // new cells!
+ typename Triangulation<dim,spacedim>::raw_cell_iterator
+ subcells[GeometryInfo<dim>::max_children_per_cell];
+ while (next_unused_cell->used() == true)
+ ++next_unused_cell;
+
+ const unsigned int n_children=
+ GeometryInfo<dim>::n_children(ref_case);
+ for (unsigned int i=0; i<n_children; ++i)
+ {
+ Assert (next_unused_cell->used() == false,
+ ExcCellShouldBeUnused());
+ subcells[i] = next_unused_cell;
+ ++next_unused_cell;
+ if (i%2==1 && i<n_children-1)
+ while (next_unused_cell->used() == true)
+ ++next_unused_cell;
+ }
+
+ if (ref_case==RefinementCase<dim>::cut_xy)
+ {
+ // children:
+ // .--.--.
+ // |2 . 3|
+ // .--.--.
+ // |0 | 1|
+ // .--.--.
+ // lines:
+ // .-6-.-7-.
+ // 1 9 3
+ // .-10.11-.
+ // 0 8 2
+ // .-4-.-5-.
+ subcells[0]->set (internal::Triangulation::
+ TriaObject<2>(new_lines[0]->index(),
+ new_lines[8]->index(),
+ new_lines[4]->index(),
+ new_lines[10]->index()));
+ subcells[1]->set (internal::Triangulation::
+ TriaObject<2>(new_lines[8]->index(),
+ new_lines[2]->index(),
+ new_lines[5]->index(),
+ new_lines[11]->index()));
+ subcells[2]->set (internal::Triangulation::
+ TriaObject<2>(new_lines[1]->index(),
+ new_lines[9]->index(),
+ new_lines[10]->index(),
+ new_lines[6]->index()));
+ subcells[3]->set (internal::Triangulation::
+ TriaObject<2>(new_lines[9]->index(),
+ new_lines[3]->index(),
+ new_lines[11]->index(),
+ new_lines[7]->index()));
+ }
+ else if (ref_case==RefinementCase<dim>::cut_x)
+ {
+ // children:
+ // .--.--.
+ // | . |
+ // .0 . 1.
+ // | | |
+ // .--.--.
+ // lines:
+ // .-4-.-5-.
+ // | | |
+ // 0 6 1
+ // | | |
+ // .-2-.-3-.
+ subcells[0]->set (internal::Triangulation::
+ TriaObject<2>(new_lines[0]->index(),
+ new_lines[6]->index(),
+ new_lines[2]->index(),
+ new_lines[4]->index()));
+ subcells[1]->set (internal::Triangulation::
+ TriaObject<2>(new_lines[6]->index(),
+ new_lines[1]->index(),
+ new_lines[3]->index(),
+ new_lines[5]->index()));
+ }
+ else
+ {
+ Assert(ref_case==RefinementCase<dim>::cut_y, ExcInternalError());
+ // children:
+ // .-----.
+ // | 1 |
+ // .-----.
+ // | 0 |
+ // .-----.
+ // lines:
+ // .---5---.
+ // 1 3
+ // .---6---.
+ // 0 2
+ // .---4---.
+ subcells[0]->set (internal::Triangulation::
+ TriaObject<2>(new_lines[0]->index(),
+ new_lines[2]->index(),
+ new_lines[4]->index(),
+ new_lines[6]->index()));
+ subcells[1]->set (internal::Triangulation::
+ TriaObject<2>(new_lines[1]->index(),
+ new_lines[3]->index(),
+ new_lines[6]->index(),
+ new_lines[5]->index()));
+ }
+
+
+ for (unsigned int i=0; i<n_children; ++i)
+ {
+ subcells[i]->set_used_flag();
+ subcells[i]->clear_refine_flag();
+ subcells[i]->clear_user_flag();
+ subcells[i]->clear_user_data();
+ subcells[i]->clear_children();
+ // inherit material
+ // properties
+ subcells[i]->set_material_id (cell->material_id());
+ subcells[i]->set_subdomain_id (cell->subdomain_id());
+
+ if (i%2==0)
+ subcells[i]->set_parent (cell->index ());
+ }
+
+
+
+ // set child index for
+ // even children children
+ // i=0,2 (0)
+ for (unsigned int i=0; i<n_children/2; ++i)
+ cell->set_children (2*i, subcells[2*i]->index());
+ // set the refine case
+ cell->set_refinement_case(ref_case);
+
+ // note that the
+ // refinement flag was
+ // already cleared at the
+ // beginning of this function
+ }
+
+
+
+ /**
+ * A function that performs the
+ * refinement of a triangulation in 1d.
+ */
+ template <int spacedim>
+ static
+ typename Triangulation<1,spacedim>::DistortedCellList
+ execute_refinement (Triangulation<1,spacedim> &triangulation,
+ const bool /*check_for_distorted_cells*/)
+ {
+ const unsigned int dim = 1;
+
+ // check whether a new level is
+ // needed we have to check for this
+ // on the highest level only (on
+ // this, all used cells are also
+ // active, so we only have to check
+ // for this)
+ {
+ typename Triangulation<dim,spacedim>::raw_cell_iterator
+ cell = triangulation.begin_active (triangulation.levels.size()-1),
+ endc = triangulation.end();
+ for (; cell != endc; ++cell)
+ if (cell->used())
+ if (cell->refine_flag_set())
+ {
+ triangulation.levels
+ .push_back (new internal::Triangulation::TriaLevel<dim>);
+ break;
+ }
+ }
+
+
+ // check how much space is needed
+ // on every level we need not check
+ // the highest level since either -
+ // on the highest level no cells
+ // are flagged for refinement -
+ // there are, but
+ // prepare_refinement added another
+ // empty level
+ unsigned int needed_vertices = 0;
+ for (int level=triangulation.levels.size()-2; level>=0; --level)
+ {
+ // count number of flagged
+ // cells on this level
+ unsigned int flagged_cells = 0;
+ typename Triangulation<dim,spacedim>::active_cell_iterator
+ acell = triangulation.begin_active(level),
+ aendc = triangulation.begin_active(level+1);
+ for (; acell!=aendc; ++acell)
+ if (acell->refine_flag_set())
+ ++flagged_cells;
+
+ // count number of used cells
+ // on the next higher level
+ const unsigned int used_cells
+ = std::count_if (triangulation.levels[level+1]->cells.used.begin(),
+ triangulation.levels[level+1]->cells.used.end(),
+ std::bind2nd (std::equal_to<bool>(), true));
+
+ // reserve space for the
+ // used_cells cells already
+ // existing on the next higher
+ // level as well as for the
+ // 2*flagged_cells that will be
+ // created on that level
+ triangulation.levels[level+1]
+ ->reserve_space(used_cells+
+ GeometryInfo<1>::max_children_per_cell *
+ flagged_cells,
+ 1);
+ // reserve space for
+ // 2*flagged_cells new lines on
+ // the next higher level
+ triangulation.levels[level+1]->cells
+ .reserve_space (GeometryInfo<1>::max_children_per_cell *
+ flagged_cells,
+ 0);
+
+ needed_vertices += flagged_cells;
+ }
+
+ // add to needed vertices how many
+ // vertices are already in use
+ needed_vertices += std::count_if (triangulation.vertices_used.begin(),
+ triangulation.vertices_used.end(),
+ std::bind2nd (std::equal_to<bool>(),
+ true));
+ // if we need more vertices: create
+ // them, if not: leave the array as
+ // is, since shrinking is not
+ // really possible because some of
+ // the vertices at the end may be
+ // in use
+ if (needed_vertices > triangulation.vertices.size())
+ {
+ triangulation.vertices.resize (needed_vertices,
+ Point<spacedim>());
+ triangulation.vertices_used.resize (needed_vertices, false);
+ }
+
+
+ // Do REFINEMENT
+ // on every level; exclude highest
+ // level as above
+
+ // index of next unused vertex
+ unsigned int next_unused_vertex = 0;
+
+ for (int level=triangulation.levels.size()-2; level>=0; --level)
+ {
+ typename Triangulation<dim,spacedim>::active_cell_iterator
+ cell = triangulation.begin_active(level),
+ endc = triangulation.begin_active(level+1);
+
+ typename Triangulation<dim,spacedim>::raw_cell_iterator
+ next_unused_cell = triangulation.begin_raw (level+1);
+
+ for (; (cell!=endc) && (cell->level()==level); ++cell)
+ if (cell->refine_flag_set())
+ {
+ // clear refinement flag
+ cell->clear_refine_flag ();
+
+ // search for next unused
+ // vertex
+ while (triangulation.vertices_used[next_unused_vertex] == true)
+ ++next_unused_vertex;
+ Assert (next_unused_vertex < triangulation.vertices.size(),
+ ExcTooFewVerticesAllocated());
+
+ // first insert new
+ // vertex. if dim==spacedim
+ // then simply use the
+ // midpoint; otherwise we
+ // have to ask the manifold
+ // object
+ if (dim == spacedim)
+ triangulation.vertices[next_unused_vertex] =
+ (cell->vertex(0) + cell->vertex(1)) / 2;
+ else
+ triangulation.vertices[next_unused_vertex] =
+ triangulation.boundary[cell->material_id()]
+ ->get_new_point_on_line(cell);
+ triangulation.vertices_used[next_unused_vertex] = true;
+
+ // search for next two
+ // unused cell (++ takes
+ // care of the end of the
+ // vector)
+ typename Triangulation<dim,spacedim>::raw_cell_iterator
+ first_child,
+ second_child;
+ while (next_unused_cell->used() == true)
+ ++next_unused_cell;
+ first_child = next_unused_cell;
+ first_child->set_used_flag ();
+ first_child->clear_user_data ();
+ ++next_unused_cell;
+ Assert (next_unused_cell->used() == false,
+ ExcCellShouldBeUnused());
+ second_child = next_unused_cell;
+ second_child->set_used_flag ();
+ second_child->clear_user_data ();
+
+ // insert first child
+ cell->set_children (0, first_child->index());
+ first_child->clear_children ();
+ first_child->set (internal::Triangulation
+ ::TriaObject<1> (cell->vertex_index(0),
+ next_unused_vertex));
+ first_child->set_material_id (cell->material_id());
+ first_child->set_subdomain_id (cell->subdomain_id());
+ first_child->set_parent (cell->index ());
+
+ // reset neighborship info (refer
+ // to
+ // internal::Triangulation::TriaLevel<0>
+ // for details)
+ first_child->set_neighbor (1, second_child);
+ if (cell->neighbor(0).state() != IteratorState::valid)
+ first_child->set_neighbor (0, cell->neighbor(0));
+ else
+ if (cell->neighbor(0)->active())
+ {
+ // since the
+ // neighbors level
+ // is always
+ // <=level, if the
+ // cell is active,
+ // then there are
+ // no cells to the
+ // left which may
+ // want to know
+ // about this new
+ // child cell.
+ Assert (cell->neighbor(0)->level() <= cell->level(),
+ ExcInternalError());
+ first_child->set_neighbor (0, cell->neighbor(0));
+ }
+ else
+ // left neighbor is
+ // refined
+ {
+ // set neighbor to
+ // cell on same
+ // level
+ first_child->set_neighbor (0, cell->neighbor(0)->child(1));
+
+ // reset neighbor
+ // info of all
+ // right descendant
+ // of the left
+ // neighbor of cell
+ typename Triangulation<dim,spacedim>::cell_iterator
+ left_neighbor = cell->neighbor(0);
+ while (left_neighbor->has_children())
+ {
+ left_neighbor = left_neighbor->child(1);
+ left_neighbor->set_neighbor (1, first_child);
+ }
+ }
+
+ // insert second child
+ second_child->clear_children ();
+ second_child->set (internal::Triangulation
+ ::TriaObject<1>(next_unused_vertex,
+ cell->vertex_index(1)));
+ second_child->set_neighbor (0, first_child);
+ second_child->set_material_id (cell->material_id());
+ second_child->set_subdomain_id (cell->subdomain_id());
+ if (cell->neighbor(1).state() != IteratorState::valid)
+ second_child->set_neighbor (1, cell->neighbor(1));
+ else
+ if (cell->neighbor(1)->active())
+ {
+ Assert (cell->neighbor(1)->level() <= cell->level(),
+ ExcInternalError());
+ second_child->set_neighbor (1, cell->neighbor(1));
+ }
+ else
+ // right neighbor is
+ // refined same as
+ // above
+ {
+ second_child->set_neighbor (1, cell->neighbor(1)->child(0));
+
+ typename Triangulation<dim,spacedim>::cell_iterator
+ right_neighbor = cell->neighbor(1);
+ while (right_neighbor->has_children())
+ {
+ right_neighbor = right_neighbor->child(0);
+ right_neighbor->set_neighbor (0, second_child);
+ }
+ }
+ }
+ }
+
+ // in 1d, we can not have
+ // distorted children
+ // unless the parent was
+ // already distorted
+ // (that is because we
+ // don't use boundary
+ // information for 1d
+ // triangulations). so
+ // return an empty list
+ return typename Triangulation<1,spacedim>::DistortedCellList();
+ }
+
+
+ /**
+ * A function that performs the
+ * refinement of a triangulation in 2d.
+ */
+ template <int spacedim>
+ static
+ typename Triangulation<2,spacedim>::DistortedCellList
+ execute_refinement (Triangulation<2,spacedim> &triangulation,
+ const bool check_for_distorted_cells)
+ {
+ const unsigned int dim = 2;
+
+ // check whether a new level is
+ // needed we have to check for this
+ // on the highest level only (on
+ // this, all used cells are also
+ // active, so we only have to check
+ // for this)
+ if (true)
+ {
+ typename Triangulation<dim,spacedim>::raw_cell_iterator
+ cell = triangulation.begin_active (triangulation.levels.size()-1),
+ endc = triangulation.end();
+ for (; cell != endc; ++cell)
+ if (cell->used())
+ if (cell->refine_flag_set())
+ {
+ triangulation.levels.push_back (new internal::Triangulation::TriaLevel<dim>);
+ break;
+ }
+ }
+
+
+ // first clear user flags and
+ // pointers of lines; we're going
+ // to use them to flag which lines
+ // need refinement
+ for (typename Triangulation<dim,spacedim>::line_iterator
+ line=triangulation.begin_line(); line!=triangulation.end_line(); ++line)
+ {
+ line->clear_user_flag();
+ line->clear_user_data();
+ }
+ // running over all cells and lines
+ // count the number
+ // n_single_lines of lines
+ // which can be stored as
+ // single lines, e.g. inner lines
+ unsigned int n_single_lines=0;
+ // New lines to be created:
+ // number lines which are
+ // stored in pairs (the
+ // children of lines must be
+ // stored in pairs)
+ unsigned int n_lines_in_pairs = 0;
+
+ // check how much space is needed
+ // on every level we need not check
+ // the highest level since either
+ // - on the highest level no cells
+ // are flagged for refinement
+ // - there are, but prepare_refinement
+ // added another empty level
+ unsigned int needed_vertices = 0;
+ for (int level=triangulation.levels.size()-2; level>=0; --level)
+ {
+ // count number of flagged
+ // cells on this level and
+ // compute how many new
+ // vertices and new lines will
+ // be needed
+ unsigned int needed_cells = 0;
+
+ typename Triangulation<dim,spacedim>::active_cell_iterator
+ cell = triangulation.begin_active(level),
+ endc = triangulation.begin_active(level+1);
+ for (; cell!=endc; ++cell)
+ if (cell->refine_flag_set())
+ {
+ if (cell->refine_flag_set()==RefinementCase<dim>::cut_xy)
+ {
+ needed_cells += 4;
+
+ // new vertex at
+ // center of cell is
+ // needed in any case
+ ++needed_vertices;
+ // the four inner
+ // lines can be
+ // stored as singles
+ n_single_lines += 4;
+ }
+ else // cut_x || cut_y
+ {
+ // set the flag showing that
+ // anisotropic refinement is
+ // used for at least one cell
+ triangulation.anisotropic_refinement = true;
+
+ needed_cells += 2;
+ // no vertex at center
+
+ // the inner line can
+ // be stored as
+ // single
+ n_single_lines += 1;
+
+ }
+
+ // mark all faces
+ // (lines) for
+ // refinement;
+ // checking locally
+ // whether the
+ // neighbor would
+ // also like to
+ // refine them is
+ // rather difficult
+ // for lines so we
+ // only flag them and
+ // after visiting all
+ // cells, we decide
+ // which lines need
+ // refinement;
+ for (unsigned int line_no=0; line_no<GeometryInfo<dim>::faces_per_cell;
+ ++line_no)
+ {
+ if (GeometryInfo<dim>::face_refinement_case(
+ cell->refine_flag_set(), line_no)==RefinementCase<1>::cut_x)
+ {
+ typename Triangulation<dim,spacedim>::line_iterator
+ line = cell->line(line_no);
+ if (line->has_children() == false)
+ {
+ line->set_user_flag ();
+//TODO[WB]: we overwrite the user_index here because we later on need to find
+// out which boundary object we have to ask to refine this line. find a better
+// way to do that
+ if (spacedim > dim)
+ line->set_user_index(cell->material_id());
+ }
+ }
+ }
+ }
+
+
+ // count number of used cells
+ // on the next higher level
+ const unsigned int used_cells
+ = std::count_if (triangulation.levels[level+1]->cells.used.begin(),
+ triangulation.levels[level+1]->cells.used.end(),
+ std::bind2nd (std::equal_to<bool>(), true));
+
+
+ // reserve space for the
+ // used_cells cells already
+ // existing on the next higher
+ // level as well as for the
+ // needed_cells that will be
+ // created on that level
+ triangulation.levels[level+1]->reserve_space (used_cells+needed_cells, 2);
+
+ // reserve space for
+ // needed_cells
+ // new quads on the next higher
+ // level
+ triangulation.levels[level+1]->cells.
+ reserve_space (needed_cells,0);
+ }
+
+ // now count the lines which
+ // were flagged for refinement
+ for (typename Triangulation<dim,spacedim>::line_iterator
+ line=triangulation.begin_line(); line!=triangulation.end_line(); ++line)
+ if (line->user_flag_set())
+ {
+ Assert (line->has_children() == false, ExcInternalError());
+ n_lines_in_pairs += 2;
+ needed_vertices += 1;
+ }
+ // reserve space for
+ // n_lines_in_pairs new lines.
+ // note, that we can't reserve space
+ // for the single lines here as well,
+ // as all the space reserved for lines
+ // in pairs would be counted as unused
+ // and we would end up with too little
+ // space to store all lines. memory
+ // reservation for n_single_lines can
+ // only be done AFTER we refined the lines
+ // of the current cells
+ triangulation.faces->lines.
+ reserve_space (n_lines_in_pairs, 0);
+
+ // add to needed vertices how many
+ // vertices are already in use
+ needed_vertices += std::count_if (triangulation.vertices_used.begin(), triangulation.vertices_used.end(),
+ std::bind2nd (std::equal_to<bool>(), true));
+ // if we need more vertices: create
+ // them, if not: leave the array as
+ // is, since shrinking is not
+ // really possible because some of
+ // the vertices at the end may be
+ // in use
+ if (needed_vertices > triangulation.vertices.size())
+ {
+ triangulation.vertices.resize (needed_vertices, Point<spacedim>());
+ triangulation.vertices_used.resize (needed_vertices, false);
+ }
+
+
+ // Do REFINEMENT
+ // on every level; exclude highest
+ // level as above
+
+ // index of next unused vertex
+ unsigned int next_unused_vertex = 0;
+
+ // first the refinement of lines.
+ // children are stored pairwise
+ if (true)
+ {
+ // only active objects can be
+ // refined further
+ typename Triangulation<dim,spacedim>::active_line_iterator
+ line = triangulation.begin_active_line(),
+ endl = triangulation.end_line();
+ typename Triangulation<dim,spacedim>::raw_line_iterator
+ next_unused_line = triangulation.begin_raw_line ();
+
+ for (; line!=endl; ++line)
+ if (line->user_flag_set())
+ {
+ // this line needs to be
+ // refined
+
+ // find the next unused
+ // vertex and set it
+ // appropriately
+ while (triangulation.vertices_used[next_unused_vertex] == true)
+ ++next_unused_vertex;
+ Assert (next_unused_vertex < triangulation.vertices.size(),
+ ExcTooFewVerticesAllocated());
+ triangulation.vertices_used[next_unused_vertex] = true;
+
+ if (spacedim == dim)
+ {
+ // for the case of a domain
+ // in an equal-dimensional
+ // space we only have to
+ // treat boundary lines
+ // differently; for interior
+ // lines we can compute the
+ // midpoint as the mean of
+ // the two vertices:
+ if (line->at_boundary())
+ triangulation.vertices[next_unused_vertex]
+ = triangulation.boundary[line->boundary_indicator()]
+ ->get_new_point_on_line (line);
+ else
+ triangulation.vertices[next_unused_vertex]
+ = (line->vertex(0) + line->vertex(1)) / 2;
+ }
+ else
+ // however, if spacedim>dim, we
+ // always have to ask the
+ // boundary object for its
+ // answer
+ triangulation.vertices[next_unused_vertex]
+ = triangulation.boundary[line->user_index()]->get_new_point_on_line (line);
+
+ // now that we created
+ // the right point, make
+ // up the two child
+ // lines. To this end,
+ // find a pair of unused
+ // lines
+ bool pair_found=false;
+ for (; next_unused_line!=endl; ++next_unused_line)
+ if (!next_unused_line->used() &&
+ !(++next_unused_line)->used())
+ {
+ // go back to the
+ // first of the two
+ // unused lines
+ --next_unused_line;
+ pair_found=true;
+ break;
+ }
+ Assert (pair_found, ExcInternalError());
+
+ // there are now two
+ // consecutive unused
+ // lines, such that the
+ // children of a line
+ // will be consecutive.
+ // then set the child
+ // pointer of the present
+ // line
+ line->set_children (0, next_unused_line->index());
+
+ // set the two new lines
+ const typename Triangulation<dim,spacedim>::raw_line_iterator
+ children[2] = { next_unused_line,
+ ++next_unused_line };
+ // some tests; if any of
+ // the iterators should
+ // be invalid, then
+ // already dereferencing
+ // will fail
+ Assert (children[0]->used() == false, ExcCellShouldBeUnused());
+ Assert (children[1]->used() == false, ExcCellShouldBeUnused());
+
+ children[0]->set (internal::Triangulation
+ ::TriaObject<1>(line->vertex_index(0),
+ next_unused_vertex));
+ children[1]->set (internal::Triangulation
+ ::TriaObject<1>(next_unused_vertex,
+ line->vertex_index(1)));
+
+ children[0]->set_used_flag();
+ children[1]->set_used_flag();
+ children[0]->clear_children();
+ children[1]->clear_children();
+ children[0]->clear_user_data();
+ children[1]->clear_user_data();
+ children[0]->clear_user_flag();
+ children[1]->clear_user_flag();
+
+ children[0]->set_boundary_indicator (line->boundary_indicator());
+ children[1]->set_boundary_indicator (line->boundary_indicator());
+
+ // finally clear flag
+ // indicating the need
+ // for refinement
+ line->clear_user_flag ();
+ }
+ }
+
+
+ // Now set up the new cells
+
+ // reserve space for inner
+ // lines (can be stored as
+ // single lines)
+ triangulation.faces->lines.
+ reserve_space (0,n_single_lines);
+
+ typename Triangulation<2,spacedim>::DistortedCellList
+ cells_with_distorted_children;
+
+ // reset next_unused_line, as
+ // now also single empty places
+ // in the vector can be used
+ typename Triangulation<dim,spacedim>::raw_line_iterator
+ next_unused_line = triangulation.begin_raw_line ();
+
+ for (int level=0; level<static_cast<int>(triangulation.levels.size())-1; ++level)
+ {
+
+ // Remember: as we don't operate
+ // on the finest level, begin_*(level+1)
+ // is allowed
+ typename Triangulation<dim,spacedim>::active_cell_iterator
+ cell = triangulation.begin_active(level),
+ endc = triangulation.begin_active(level+1);
+
+ typename Triangulation<dim,spacedim>::raw_cell_iterator
+ next_unused_cell = triangulation.begin_raw (level+1);
+
+ for (; cell!=endc; ++cell)
+ if (cell->refine_flag_set())
+ {
+ // set the user flag to
+ // indicate, that at least one
+ // line is at the boundary
+
+ // TODO[Tobias Leicht] find a
+ // better place to set this flag,
+ // so that we do not need so much
+ // time to check each cell here
+ if (cell->at_boundary())
+ cell->set_user_flag();
+
+ // actually set up the children and
+ // update neighbor information
+ create_children (triangulation,
+ next_unused_vertex,
+ next_unused_line,
+ next_unused_cell,
+ cell);
+
+ if ((check_for_distorted_cells == true)
+ &&
+ has_distorted_children (cell,
+ internal::int2type<dim>(),
+ internal::int2type<spacedim>()))
+ cells_with_distorted_children.distorted_cells.push_back (cell);
+ }
+ }
+
+ return cells_with_distorted_children;
+ }
+
+
+ /**
+ * A function that performs the
+ * refinement of a triangulation in 3d.
+ */
+ template <int spacedim>
+ static
+ typename Triangulation<3,spacedim>::DistortedCellList
+ execute_refinement (Triangulation<3,spacedim> &triangulation,
+ const bool check_for_distorted_cells)
+ {
+ const unsigned int dim = 3;
+
+ // this function probably
+ // also works for spacedim>3
+ // but it isn't tested. it
+ // will probably be necessary
+ // to pull new vertices onto
+ // the manifold just as we do
+ // for the other functions
+ // above.
+ Assert (spacedim == 3, ExcNotImplemented());
+
+ // check whether a new level is
+ // needed we have to check for this
+ // on the highest level only (on
+ // this, all used cells are also
+ // active, so we only have to check
+ // for this)
+ if (true)
+ {
+ typename Triangulation<dim,spacedim>::raw_cell_iterator
+ cell = triangulation.begin_active (triangulation.levels.size()-1),
+ endc = triangulation.end();
+ for (; cell != endc; ++cell)
+ if (cell->used())
+ if (cell->refine_flag_set())
+ {
+ triangulation.levels.push_back (new internal::Triangulation::TriaLevel<dim>);
+ break;
+ }
+ }
+
+
+ // first clear user flags for quads
+ // and lines; we're going to use them
+ // to flag which lines and quads
+ // need refinement
+ triangulation.faces->quads.clear_user_data();
+
+ for (typename Triangulation<dim,spacedim>::line_iterator
+ line=triangulation.begin_line(); line!=triangulation.end_line(); ++line)
+ line->clear_user_flag();
+ for (typename Triangulation<dim,spacedim>::quad_iterator
+ quad=triangulation.begin_quad(); quad!=triangulation.end_quad(); ++quad)
+ quad->clear_user_flag();
+
+ // create an array of face refine cases. User
+ // indices of faces will be set to values
+ // corresponding with indices in this array.
+ const RefinementCase<dim-1> face_refinement_cases[4]=
+ {RefinementCase<dim-1>::no_refinement,
+ RefinementCase<dim-1>::cut_x,
+ RefinementCase<dim-1>::cut_y,
+ RefinementCase<dim-1>::cut_xy};
+
+ // check how much space is needed
+ // on every level
+ // we need not check the highest
+ // level since either
+ // - on the highest level no cells
+ // are flagged for refinement
+ // - there are, but prepare_refinement
+ // added another empty level which
+ // then is the highest level
+
+ // variables to hold the number of newly to
+ // be created vertices, lines and quads. as
+ // these are stored globally, declare them
+ // outside the loop over al levels. we need
+ // lines and quads in pairs for refinement of
+ // old ones and lines and quads, that can be
+ // stored as single ones, as they are newly
+ // created in the inside of an existing cell
+ unsigned int needed_vertices = 0;
+ unsigned int needed_lines_single = 0;
+ unsigned int needed_quads_single = 0;
+ unsigned int needed_lines_pair = 0;
+ unsigned int needed_quads_pair = 0;
+ for (int level=triangulation.levels.size()-2; level>=0; --level)
+ {
+ // count number of flagged
+ // cells on this level and
+ // compute how many new
+ // vertices and new lines will
+ // be needed
+ unsigned int new_cells = 0;
+
+ typename Triangulation<dim,spacedim>::active_cell_iterator
+ acell = triangulation.begin_active(level),
+ aendc = triangulation.begin_active(level+1);
+ for (; acell!=aendc; ++acell)
+ if (acell->refine_flag_set())
+ {
+ RefinementCase<dim> ref_case=acell->refine_flag_set();
+
+ // now for interior vertices, lines
+ // and quads, which are needed in
+ // any case
+ if (ref_case==RefinementCase<dim>::cut_x ||
+ ref_case==RefinementCase<dim>::cut_y ||
+ ref_case==RefinementCase<dim>::cut_z)
+ {
+ ++needed_quads_single;
+ new_cells+=2;
+ triangulation.anisotropic_refinement=true;
+ }
+ else if (ref_case==RefinementCase<dim>::cut_xy ||
+ ref_case==RefinementCase<dim>::cut_xz ||
+ ref_case==RefinementCase<dim>::cut_yz)
+ {
+ ++needed_lines_single;
+ needed_quads_single += 4;
+ new_cells+=4;
+ triangulation.anisotropic_refinement=true;
+ }
+ else if (ref_case==RefinementCase<dim>::cut_xyz)
+ {
+ ++needed_vertices;
+ needed_lines_single += 6;
+ needed_quads_single += 12;
+ new_cells+=8;
+ }
+ else
+ {
+ // we should never get here
+ Assert(false, ExcInternalError());
+ }
+
+ // mark all faces for refinement;
+ // checking locally
+ // if and how the neighbor
+ // would like to
+ // refine these is
+ // difficult so
+ // we only flag them and
+ // after visiting all
+ // cells, we decide which
+ // faces need which refinement;
+ for (unsigned int face=0; face<GeometryInfo<dim>::faces_per_cell;
+ ++face)
+ {
+ typename Triangulation<dim,spacedim>::face_iterator
+ aface = acell->face(face);
+ // get the RefineCase this
+ // faces has for the given
+ // RefineCase of the cell
+ RefinementCase<dim-1> face_ref_case=
+ GeometryInfo<dim>::face_refinement_case(ref_case,
+ face,
+ acell->face_orientation(face),
+ acell->face_flip(face),
+ acell->face_rotation(face));
+ // only do something, if this
+ // face has to be refined
+ if (face_ref_case)
+ {
+ if (face_ref_case==RefinementCase<dim-1>::isotropic_refinement)
+ {
+ if (aface->number_of_children()<4)
+ // we use user_flags to
+ // denote needed isotropic
+ // refinement
+ aface->set_user_flag();
+ }
+ else if (aface->refinement_case()!=face_ref_case)
+ // we use user_indices
+ // to denote needed
+ // anisotropic
+ // refinement. note, that
+ // we can have at most
+ // one anisotropic
+ // refinement case for
+ // this face, as
+ // otherwise
+ // prepare_refinement()
+ // would have changed one
+ // of the cells to yield
+ // isotropic refinement
+ // at this
+ // face. therefore we set
+ // the user_index
+ // uniquely
+ {
+ Assert(aface->refinement_case()==RefinementCase<dim-1>::isotropic_refinement ||
+ aface->refinement_case()==RefinementCase<dim-1>::no_refinement,
+ ExcInternalError());
+ aface->set_user_index(face_ref_case);
+ }
+ }
+ }// for all faces
+
+ // flag all lines, that have to be
+ // refined
+ for (unsigned int line=0; line<GeometryInfo<dim>::lines_per_cell; ++line)
+ if (GeometryInfo<dim>::line_refinement_case(ref_case,line) &&
+ !acell->line(line)->has_children())
+ acell->line(line)->set_user_flag();
+
+ }// if refine_flag set and for all cells on this level
+
+
+ // count number of used cells on
+ // the next higher level
+ const unsigned int used_cells
+ = std::count_if (triangulation.levels[level+1]->cells.used.begin(),
+ triangulation.levels[level+1]->cells.used.end(),
+ std::bind2nd (std::equal_to<bool>(), true));
+
+
+ // reserve space for the
+ // used_cells cells already
+ // existing on the next higher
+ // level as well as for the
+ // 8*flagged_cells that will be
+ // created on that level
+ triangulation.levels[level+1]->reserve_space (used_cells+new_cells, 3);
+ // reserve space for
+ // 8*flagged_cells
+ // new hexes on the next higher
+ // level
+ triangulation.levels[level+1]->cells.reserve_space (new_cells);
+ }// for all levels
+ // now count the quads and
+ // lines which were flagged for
+ // refinement
+ for (typename Triangulation<dim,spacedim>::quad_iterator
+ quad=triangulation.begin_quad(); quad!=triangulation.end_quad(); ++quad)
+ {
+ if (quad->user_flag_set())
+ {
+ // isotropic refinement: 1 interior
+ // vertex, 4 quads and 4 interior
+ // lines. we store the interior lines
+ // in pairs in case the face is
+ // already or will be refined
+ // anisotropically
+ needed_quads_pair += 4;
+ needed_lines_pair += 4;
+ needed_vertices += 1;
+ }
+ if (quad->user_index())
+ {
+ // anisotropic refinement: 1 interior
+ // line and two quads
+ needed_quads_pair += 2;
+ needed_lines_single += 1;
+ // there is a kind of complicated
+ // situation here which requires our
+ // attention. if the quad is refined
+ // isotropcally, two of the interior
+ // lines will get a new mother line -
+ // the interior line of our
+ // anisotropically refined quad. if
+ // those two lines are not
+ // consecutive, we cannot do so and
+ // have to replace them by two lines
+ // that are consecutive. we try to
+ // avoid that situation, but it may
+ // happen nevertheless throug
+ // repeated refinement and
+ // coarsening. thus we have to check
+ // here, as we will need some
+ // additional space to store those
+ // new lines in case we need them...
+ if (quad->has_children())
+ {
+ Assert(quad->refinement_case()==RefinementCase<dim-1>::isotropic_refinement, ExcInternalError());
+ if ((face_refinement_cases[quad->user_index()]==RefinementCase<dim-1>::cut_x
+ && (quad->child(0)->line_index(1)+1!=quad->child(2)->line_index(1))) ||
+ (face_refinement_cases[quad->user_index()]==RefinementCase<dim-1>::cut_y
+ && (quad->child(0)->line_index(3)+1!=quad->child(1)->line_index(3))))
+ needed_lines_pair +=2;
+ }
+ }
+ }
+
+ for (typename Triangulation<dim,spacedim>::line_iterator
+ line=triangulation.begin_line(); line!=triangulation.end_line(); ++line)
+ if (line->user_flag_set())
+ {
+ needed_lines_pair += 2;
+ needed_vertices += 1;
+ }
+
+ // reserve space for
+ // needed_lines new lines
+ // stored in pairs
+ triangulation.faces->lines.
+ reserve_space (needed_lines_pair,needed_lines_single);
+ // reserve space for
+ // needed_quads new quads
+ // stored in pairs
+ triangulation.faces->quads.
+ reserve_space (needed_quads_pair,needed_quads_single);
+
+
+ // add to needed vertices how many
+ // vertices are already in use
+ needed_vertices += std::count_if (triangulation.vertices_used.begin(), triangulation.vertices_used.end(),
+ std::bind2nd (std::equal_to<bool>(), true));
+ // if we need more vertices: create
+ // them, if not: leave the array as
+ // is, since shrinking is not
+ // really possible because some of
+ // the vertices at the end may be
+ // in use
+ if (needed_vertices > triangulation.vertices.size())
+ {
+ triangulation.vertices.resize (needed_vertices, Point<spacedim>());
+ triangulation.vertices_used.resize (needed_vertices, false);
+ }
+
+
+ ///////////////////////////////////////////
+ // Before we start with the actual
+ // refinement, we do some sanity
+ // checks if in debug
+ // mode. especially, we try to
+ // catch the notorious problem with
+ // lines being twice refined,
+ // i.e. there are cells adjacent at
+ // one line ("around the edge", but
+ // not at a face), with two cells
+ // differing by more than one
+ // refinement level
+ //
+ // this check is very simple to
+ // implement here, since we have
+ // all lines flagged if they shall
+ // be refined
+#ifdef DEBUG
+ for (typename Triangulation<dim,spacedim>::active_cell_iterator
+ cell=triangulation.begin_active(); cell!=triangulation.end(); ++cell)
+ if (!cell->refine_flag_set())
+ for (unsigned int line=0; line<GeometryInfo<dim>::lines_per_cell; ++line)
+ if (cell->line(line)->has_children())
+ for (unsigned int c=0; c<2; ++c)
+ Assert (cell->line(line)->child(c)->user_flag_set() == false,
+ ExcInternalError());
+#endif
+
+ ///////////////////////////////////////////
+ // Do refinement on every level
+ //
+ // To make life a bit easier, we
+ // first refine those lines and
+ // quads that were flagged for
+ // refinement and then compose the
+ // newly to be created cells.
+ //
+ // index of next unused vertex
+ unsigned int next_unused_vertex = 0;
+
+ // first for lines
+ if (true)
+ {
+ // only active objects can be
+ // refined further
+ typename Triangulation<dim,spacedim>::active_line_iterator
+ line = triangulation.begin_active_line(),
+ endl = triangulation.end_line();
+ typename Triangulation<dim,spacedim>::raw_line_iterator
+ next_unused_line = triangulation.begin_raw_line ();
+
+ for (; line!=endl; ++line)
+ if (line->user_flag_set())
+ {
+ // this line needs to be
+ // refined
+
+ // find the next unused
+ // vertex and set it
+ // appropriately
+ while (triangulation.vertices_used[next_unused_vertex] == true)
+ ++next_unused_vertex;
+ Assert (next_unused_vertex < triangulation.vertices.size(),
+ ExcTooFewVerticesAllocated());
+ triangulation.vertices_used[next_unused_vertex] = true;
+
+ if (line->at_boundary())
+ triangulation.vertices[next_unused_vertex]
+ = triangulation.boundary[line->boundary_indicator()]->get_new_point_on_line (line);
+ else
+ triangulation.vertices[next_unused_vertex]
+ = (line->vertex(0) + line->vertex(1)) / 2;
+
+ // now that we created
+ // the right point, make
+ // up the two child lines
+ // (++ takes care of the
+ // end of the vector)
+ next_unused_line=triangulation.faces->lines.next_free_pair_line(triangulation);
+ Assert(next_unused_line.state() == IteratorState::valid,
+ ExcInternalError());
+
+ // now we found
+ // two consecutive unused
+ // lines, such that the
+ // children of a line
+ // will be consecutive.
+ // then set the child
+ // pointer of the present
+ // line
+ line->set_children (0, next_unused_line->index());
+
+ // set the two new lines
+ const typename Triangulation<dim,spacedim>::raw_line_iterator
+ children[2] = { next_unused_line,
+ ++next_unused_line };
+
+ // some tests; if any of
+ // the iterators should
+ // be invalid, then
+ // already dereferencing
+ // will fail
+ Assert (children[0]->used() == false, ExcCellShouldBeUnused());
+ Assert (children[1]->used() == false, ExcCellShouldBeUnused());
+
+ children[0]->set (internal::Triangulation
+ ::TriaObject<1>(line->vertex_index(0),
+ next_unused_vertex));
+ children[1]->set (internal::Triangulation
+ ::TriaObject<1>(next_unused_vertex,
+ line->vertex_index(1)));
+
+ children[0]->set_used_flag();
+ children[1]->set_used_flag();
+ children[0]->clear_children();
+ children[1]->clear_children();
+ children[0]->clear_user_data();
+ children[1]->clear_user_data();
+ children[0]->clear_user_flag();
+ children[1]->clear_user_flag();
+
+ children[0]->set_boundary_indicator (line->boundary_indicator());
+ children[1]->set_boundary_indicator (line->boundary_indicator());
+
+ // finally clear flag
+ // indicating the need
+ // for refinement
+ line->clear_user_flag ();
+ }
+ }
+
+
+ ///////////////////////////////////////
+ // now refine marked quads
+ ///////////////////////////////////////
+
+ // here we encounter several cases:
+
+ // a) the quad is unrefined and shall be
+ // refined isotropically
+
+ // b) the quad is unrefined and shall be
+ // refined anisotropically
+
+ // c) the quad is unrefined and shall be
+ // refined both anisotropically and
+ // isotropically (this is reduced to case b)
+ // and then case b) for the children again)
+
+ // d) the quad is refined anisotropically and
+ // shall be refined isotropically (this is
+ // reduced to case b) for the anisotropic
+ // children)
+
+ // e) the quad is refined isotropically and
+ // shall be refined anisotropically (this is
+ // transformed to case c), however we might
+ // have to renumber/rename children...)
+
+ // we need a loop in cases c) and d), as the
+ // anisotropic children migt have a lower
+ // index than the mother quad
+ for (unsigned int loop=0; loop<2; ++loop)
+ {
+ // usually, only active objects can be
+ // refined further. however, in cases d)
+ // and e) that is not true, so we have to
+ // use 'normal' iterators here
+ typename Triangulation<dim,spacedim>::quad_iterator
+ quad = triangulation.begin_quad(),
+ endq = triangulation.end_quad();
+ typename Triangulation<dim,spacedim>::raw_line_iterator
+ next_unused_line = triangulation.begin_raw_line ();
+ typename Triangulation<dim,spacedim>::raw_quad_iterator
+ next_unused_quad = triangulation.begin_raw_quad ();
+
+ for (; quad!=endq; ++quad)
+ {
+ if (quad->user_index())
+ {
+ RefinementCase<dim-1> aniso_quad_ref_case=face_refinement_cases[quad->user_index()];
+ // there is one unlikely event
+ // here, where we already have
+ // refind the face: if the face
+ // was refined anisotropically
+ // and we want to refine it
+ // isotropically, both children
+ // are flagged for anisotropic
+ // refinement. however, if those
+ // children were already flagged
+ // for anisotropic refinement,
+ // they might already be
+ // processed and refined.
+ if (aniso_quad_ref_case == quad->refinement_case())
+ continue;
+
+ Assert(quad->refinement_case()==RefinementCase<dim-1>::cut_xy ||
+ quad->refinement_case()==RefinementCase<dim-1>::no_refinement,
+ ExcInternalError());
+
+ // this quad needs to be refined
+ // anisotropically
+ Assert(quad->user_index() == RefinementCase<dim-1>::cut_x ||
+ quad->user_index() == RefinementCase<dim-1>::cut_y,
+ ExcInternalError());
+
+ // make the new line interior to
+ // the quad
+ typename Triangulation<dim,spacedim>::raw_line_iterator new_line;
+
+ new_line=triangulation.faces->lines.next_free_single_line(triangulation);
+ Assert (new_line->used() == false,
+ ExcCellShouldBeUnused());
+
+ // first collect the
+ // indices of the vertices:
+ // *--1--*
+ // | | |
+ // | | | cut_x
+ // | | |
+ // *--0--*
+ //
+ // *-----*
+ // | |
+ // 0-----1 cut_y
+ // | |
+ // *-----*
+ unsigned int vertex_indices[2];
+ if (aniso_quad_ref_case==RefinementCase<dim-1>::cut_x)
+ {
+ vertex_indices[0]=quad->line(2)->child(0)->vertex_index(1);
+ vertex_indices[1]=quad->line(3)->child(0)->vertex_index(1);
+ }
+ else
+ {
+ vertex_indices[0]=quad->line(0)->child(0)->vertex_index(1);
+ vertex_indices[1]=quad->line(1)->child(0)->vertex_index(1);
+ }
+
+ new_line->set (internal::Triangulation::
+ TriaObject<1>(vertex_indices[0], vertex_indices[1]));
+ new_line->set_used_flag();
+ new_line->clear_user_flag();
+ new_line->clear_user_data();
+ new_line->clear_children();
+ new_line->set_boundary_indicator(quad->boundary_indicator());
+
+ // child 0 and 1 of a line are
+ // switched if the line
+ // orientation is false. set up a
+ // miniature table, indicating
+ // which child to take for line
+ // orientations false and
+ // true. first index: child index
+ // in standard orientation,
+ // second index: line orientation
+ const unsigned int index[2][2]=
+ {{1,0}, // child 0, line_orientation=false and true
+ {0,1}}; // child 1, line_orientation=false and true
+
+ // find some space (consecutive)
+ // for the two newly to be
+ // created quads.
+ typename Triangulation<dim,spacedim>::raw_quad_iterator new_quads[2];
+
+ next_unused_quad=triangulation.faces->quads.next_free_pair_quad(triangulation);
+ new_quads[0] = next_unused_quad;
+ Assert (new_quads[0]->used() == false, ExcCellShouldBeUnused());
+
+ ++next_unused_quad;
+ new_quads[1] = next_unused_quad;
+ Assert (new_quads[1]->used() == false, ExcCellShouldBeUnused());
+
+
+ if (aniso_quad_ref_case==RefinementCase<dim-1>::cut_x)
+ {
+ new_quads[0]->set (internal::Triangulation
+ ::TriaObject<2>(quad->line_index(0),
+ new_line->index(),
+ quad->line(2)->child(index[0][quad->line_orientation(2)])->index(),
+ quad->line(3)->child(index[0][quad->line_orientation(3)])->index()));
+ new_quads[1]->set (internal::Triangulation
+ ::TriaObject<2>(new_line->index(),
+ quad->line_index(1),
+ quad->line(2)->child(index[1][quad->line_orientation(2)])->index(),
+ quad->line(3)->child(index[1][quad->line_orientation(3)])->index()));
+ }
+ else
+ {
+ new_quads[0]->set (internal::Triangulation
+ ::TriaObject<2>(quad->line(0)->child(index[0][quad->line_orientation(0)])->index(),
+ quad->line(1)->child(index[0][quad->line_orientation(1)])->index(),
+ quad->line_index(2),
+ new_line->index()));
+ new_quads[1]->set (internal::Triangulation
+ ::TriaObject<2>(quad->line(0)->child(index[1][quad->line_orientation(0)])->index(),
+ quad->line(1)->child(index[1][quad->line_orientation(1)])->index(),
+ new_line->index(),
+ quad->line_index(3)));
+ }
+
+ for (unsigned int i=0; i<2; ++i)
+ {
+ new_quads[i]->set_used_flag();
+ new_quads[i]->clear_user_flag();
+ new_quads[i]->clear_user_data();
+ new_quads[i]->clear_children();
+ new_quads[i]->set_boundary_indicator (quad->boundary_indicator());
+ // set all line orientations to
+ // true, change this after the
+ // loop, as we have to consider
+ // different lines for each
+ // child
+ for (unsigned int j=0; j<GeometryInfo<dim>::lines_per_face; ++j)
+ new_quads[i]->set_line_orientation(j,true);
+ }
+ // now set the line orientation of
+ // children of outer lines
+ // correctly, the lines in the
+ // interior of the refined quad are
+ // automatically oriented
+ // conforming to the standard
+ new_quads[0]->set_line_orientation(0,quad->line_orientation(0));
+ new_quads[0]->set_line_orientation(2,quad->line_orientation(2));
+ new_quads[1]->set_line_orientation(1,quad->line_orientation(1));
+ new_quads[1]->set_line_orientation(3,quad->line_orientation(3));
+ if (aniso_quad_ref_case==RefinementCase<dim-1>::cut_x)
+ {
+ new_quads[0]->set_line_orientation(3,quad->line_orientation(3));
+ new_quads[1]->set_line_orientation(2,quad->line_orientation(2));
+ }
+ else
+ {
+ new_quads[0]->set_line_orientation(1,quad->line_orientation(1));
+ new_quads[1]->set_line_orientation(0,quad->line_orientation(0));
+ }
+
+ // test, whether this face is
+ // refined isotropically
+ // already. if so, set the
+ // correct children pointers.
+ if (quad->refinement_case()==RefinementCase<dim-1>::cut_xy)
+ {
+ // we will put a new
+ // refinemnt level of
+ // anisotropic refinement
+ // between the unrefined and
+ // isotropically refined quad
+ // ending up with the same
+ // fine quads but introducing
+ // anisotropically refined
+ // ones as children of the
+ // unrefined quad and mother
+ // cells of the original fine
+ // ones.
+
+ // this process includes the
+ // creation of a new middle
+ // line which we will assign
+ // as the mother line of two
+ // of the existing inner
+ // lines. If those inner
+ // lines are not consecutive
+ // in memory, we won't find
+ // them later on, so we have
+ // to create new ones instead
+ // and replace all occurances
+ // of the old ones with those
+ // new ones. As this is kind
+ // of ugly, we hope we don't
+ // have to do it often...
+ typename Triangulation<dim,spacedim>::line_iterator old_child[2];
+ if (aniso_quad_ref_case==RefinementCase<dim-1>::cut_x)
+ {
+ old_child[0]=quad->child(0)->line(1);
+ old_child[1]=quad->child(2)->line(1);
+ }
+ else
+ {
+ Assert(aniso_quad_ref_case==RefinementCase<dim-1>::cut_y, ExcInternalError());
+
+ old_child[0]=quad->child(0)->line(3);
+ old_child[1]=quad->child(1)->line(3);
+ }
+
+ if (old_child[0]->index()+1 != old_child[1]->index())
+ {
+ // this is exactly the
+ // ugly case we taked
+ // about. so, no
+ // coimplaining, lets get
+ // two new lines and copy
+ // all info
+ typename Triangulation<dim,spacedim>::raw_line_iterator new_child[2];
+
+ new_child[0]=new_child[1]=triangulation.faces->lines.next_free_pair_line(triangulation);
+ ++new_child[1];
+
+ new_child[0]->set_used_flag();
+ new_child[1]->set_used_flag();
+
+ const int old_index_0=old_child[0]->index(),
+ old_index_1=old_child[1]->index(),
+ new_index_0=new_child[0]->index(),
+ new_index_1=new_child[1]->index();
+
+ // loop over all quads
+ // and replace the old
+ // lines
+ for (unsigned int q=0; q<triangulation.faces->quads.cells.size(); ++q)
+ for (unsigned int l=0; l<GeometryInfo<dim>::lines_per_face; ++l)
+ {
+ const int index=triangulation.faces->quads.cells[q].face(l);
+ if (index==old_index_0)
+ triangulation.faces->quads.cells[q].set_face(l,new_index_0);
+ else if (index==old_index_1)
+ triangulation.faces->quads.cells[q].set_face(l,new_index_1);
+ }
+ // now we have to copy
+ // all information of the
+ // two lines
+ for (unsigned int i=0; i<2; ++i)
+ {
+ Assert(!old_child[i]->has_children(), ExcInternalError());
+
+ new_child[i]->set(internal::Triangulation::TriaObject<1>(old_child[i]->vertex_index(0),
+ old_child[i]->vertex_index(1)));
+ new_child[i]->set_boundary_indicator(old_child[i]->boundary_indicator());
+ new_child[i]->set_user_index(old_child[i]->user_index());
+ if (old_child[i]->user_flag_set())
+ new_child[i]->set_user_flag();
+ else
+ new_child[i]->clear_user_flag();
+
+ new_child[i]->clear_children();
+
+ old_child[i]->clear_user_flag();
+ old_child[i]->clear_user_index();
+ old_child[i]->clear_used_flag();
+ }
+ }
+ // now that we cared
+ // about the lines, go on
+ // with the quads
+ // themselves, where we
+ // might encounter
+ // similar situations...
+ if (aniso_quad_ref_case==RefinementCase<dim-1>::cut_x)
+ {
+ new_line->set_children(0, quad->child(0)->line_index(1));
+ Assert(new_line->child(1)==quad->child(2)->line(1),
+ ExcInternalError());
+ // now evereything is
+ // quite complicated. we
+ // have the children
+ // numbered according to
+ //
+ // *---*---*
+ // |n+2|n+3|
+ // *---*---*
+ // | n |n+1|
+ // *---*---*
+ //
+ // from the original
+ // isotropic
+ // refinement. we have to
+ // reorder them as
+ //
+ // *---*---*
+ // |n+1|n+3|
+ // *---*---*
+ // | n |n+2|
+ // *---*---*
+ //
+ // such that n and n+1
+ // are consecutive
+ // children of m and n+2
+ // and n+3 are
+ // consecutive children
+ // of m+1, where m and
+ // m+1 are given as in
+ //
+ // *---*---*
+ // | | |
+ // | m |m+1|
+ // | | |
+ // *---*---*
+ //
+ // this is a bit ugly, of
+ // course: loop over all
+ // cells on all levels
+ // and look for faces n+1
+ // (switch_1) and n+2
+ // (switch_2).
+ const typename Triangulation<dim,spacedim>::quad_iterator
+ switch_1=quad->child(1),
+ switch_2=quad->child(2);
+ const int switch_1_index=switch_1->index();
+ const int switch_2_index=switch_2->index();
+ for (unsigned int l=0; l<triangulation.levels.size(); ++l)
+ for (unsigned int h=0; h<triangulation.levels[l]->cells.cells.size(); ++h)
+ for (unsigned int q=0; q<GeometryInfo<dim>::faces_per_cell; ++q)
+ {
+ const int index=triangulation.levels[l]->cells.cells[h].face(q);
+ if (index==switch_1_index)
+ triangulation.levels[l]->cells.cells[h].set_face(q,switch_2_index);
+ else if (index==switch_2_index)
+ triangulation.levels[l]->cells.cells[h].set_face(q,switch_1_index);
+ }
+ // now we have to copy
+ // all information of the
+ // two quads
+ const int switch_1_lines[4]=
+ {switch_1->line_index(0),
+ switch_1->line_index(1),
+ switch_1->line_index(2),
+ switch_1->line_index(3)};
+ const bool switch_1_line_orientations[4]=
+ {switch_1->line_orientation(0),
+ switch_1->line_orientation(1),
+ switch_1->line_orientation(2),
+ switch_1->line_orientation(3)};
+ const unsigned char switch_1_boundary_indicator=switch_1->boundary_indicator();
+ const unsigned int switch_1_user_index=switch_1->user_index();
+ const bool switch_1_user_flag=switch_1->user_flag_set();
+ const RefinementCase<dim-1> switch_1_refinement_case=switch_1->refinement_case();
+ const int switch_1_first_child_pair=(switch_1_refinement_case ? switch_1->child_index(0) : -1);
+ const int switch_1_second_child_pair=(switch_1_refinement_case==RefinementCase<dim-1>::cut_xy ? switch_1->child_index(2) : -1);
+
+ switch_1->set(internal::Triangulation::TriaObject<2>(switch_2->line_index(0),
+ switch_2->line_index(1),
+ switch_2->line_index(2),
+ switch_2->line_index(3)));
+ switch_1->set_line_orientation(0, switch_2->line_orientation(0));
+ switch_1->set_line_orientation(1, switch_2->line_orientation(1));
+ switch_1->set_line_orientation(2, switch_2->line_orientation(2));
+ switch_1->set_line_orientation(3, switch_2->line_orientation(3));
+ switch_1->set_boundary_indicator(switch_2->boundary_indicator());
+ switch_1->set_user_index(switch_2->user_index());
+ if (switch_2->user_flag_set())
+ switch_1->set_user_flag();
+ else
+ switch_1->clear_user_flag();
+ switch_1->clear_refinement_case();
+ switch_1->set_refinement_case(switch_2->refinement_case());
+ switch_1->clear_children();
+ if (switch_2->refinement_case())
+ switch_1->set_children(0, switch_2->child_index(0));
+ if (switch_2->refinement_case()==RefinementCase<dim-1>::cut_xy)
+ switch_1->set_children(2, switch_2->child_index(2));
+
+ switch_2->set(internal::Triangulation::TriaObject<2>(switch_1_lines[0],
+ switch_1_lines[1],
+ switch_1_lines[2],
+ switch_1_lines[3]));
+ switch_2->set_line_orientation(0, switch_1_line_orientations[0]);
+ switch_2->set_line_orientation(1, switch_1_line_orientations[1]);
+ switch_2->set_line_orientation(2, switch_1_line_orientations[2]);
+ switch_2->set_line_orientation(3, switch_1_line_orientations[3]);
+ switch_2->set_boundary_indicator(switch_1_boundary_indicator);
+ switch_2->set_user_index(switch_1_user_index);
+ if (switch_1_user_flag)
+ switch_2->set_user_flag();
+ else
+ switch_2->clear_user_flag();
+ switch_2->clear_refinement_case();
+ switch_2->set_refinement_case(switch_1_refinement_case);
+ switch_2->clear_children();
+ switch_2->set_children(0, switch_1_first_child_pair);
+ switch_2->set_children(2, switch_1_second_child_pair);
+
+ new_quads[0]->set_refinement_case(RefinementCase<2>::cut_y);
+ new_quads[0]->set_children(0, quad->child_index(0));
+ new_quads[1]->set_refinement_case(RefinementCase<2>::cut_y);
+ new_quads[1]->set_children(0, quad->child_index(2));
+ }
+ else
+ {
+ new_quads[0]->set_refinement_case(RefinementCase<2>::cut_x);
+ new_quads[0]->set_children(0, quad->child_index(0));
+ new_quads[1]->set_refinement_case(RefinementCase<2>::cut_x);
+ new_quads[1]->set_children(0, quad->child_index(2));
+ new_line->set_children(0, quad->child(0)->line_index(3));
+ Assert(new_line->child(1)==quad->child(1)->line(3),
+ ExcInternalError());
+ }
+ quad->clear_children();
+ }
+
+ // note these quads as children
+ // to the present one
+ quad->set_children (0, new_quads[0]->index());
+
+ quad->set_refinement_case(aniso_quad_ref_case);
+
+ // finally clear flag
+ // indicating the need
+ // for refinement
+ quad->clear_user_data ();
+ } // if (anisotropic refinement)
+
+ if (quad->user_flag_set())
+ {
+ // this quad needs to be
+ // refined isotropically
+
+ // first of all: we only get here
+ // in the first run of the loop
+ Assert(loop==0,ExcInternalError());
+
+ // find the next unused
+ // vertex. we'll need this in any
+ // case
+ while (triangulation.vertices_used[next_unused_vertex] == true)
+ ++next_unused_vertex;
+ Assert (next_unused_vertex < triangulation.vertices.size(),
+ ExcTooFewVerticesAllocated());
+
+ // now: if the quad is refined
+ // anisotropically already, set
+ // the anisotropic refinement
+ // flag for both
+ // children. Additionally, we
+ // have to refine the inner line,
+ // as it is an outer line of the
+ // two (anisotropic) children
+ const RefinementCase<dim-1> quad_ref_case=quad->refinement_case();
+
+ if (quad_ref_case==RefinementCase<dim-1>::cut_x ||
+ quad_ref_case==RefinementCase<dim-1>::cut_y)
+ {
+ // set the 'opposite' refine case for children
+ quad->child(0)->set_user_index(RefinementCase<dim-1>::cut_xy-quad_ref_case);
+ quad->child(1)->set_user_index(RefinementCase<dim-1>::cut_xy-quad_ref_case);
+ // refine the inner line
+ typename Triangulation<dim,spacedim>::line_iterator middle_line;
+ if (quad_ref_case==RefinementCase<dim-1>::cut_x)
+ middle_line=quad->child(0)->line(1);
+ else
+ middle_line=quad->child(0)->line(3);
+
+ // if the face has been
+ // refined anisotropically in
+ // the last refinement step
+ // it might be, that it is
+ // flagged already and that
+ // the middle line is thus
+ // refined already. if not
+ // create children.
+ if (!middle_line->has_children())
+ {
+ // set the middle vertex
+ // appropriately. double
+ // refinement of quads can only
+ // happen in the interior of
+ // the domain, so we need not
+ // care about boundary quads
+ // here
+ triangulation.vertices[next_unused_vertex]
+ = (middle_line->vertex(0) + middle_line->vertex(1)) / 2;
+ triangulation.vertices_used[next_unused_vertex] = true;
+
+ // now search a slot for the two
+ // child lines
+ next_unused_line=triangulation.faces->lines.next_free_pair_line(triangulation);
+
+ // set the child
+ // pointer of the present
+ // line
+ middle_line->set_children (0, next_unused_line->index());
+
+ // set the two new lines
+ const typename Triangulation<dim,spacedim>::raw_line_iterator
+ children[2] = { next_unused_line,
+ ++next_unused_line };
+
+ // some tests; if any of
+ // the iterators should
+ // be invalid, then
+ // already dereferencing
+ // will fail
+ Assert (children[0]->used() == false, ExcCellShouldBeUnused());
+ Assert (children[1]->used() == false, ExcCellShouldBeUnused());
+
+ children[0]->set (internal::Triangulation::
+ TriaObject<1>(middle_line->vertex_index(0),
+ next_unused_vertex));
+ children[1]->set (internal::Triangulation::
+ TriaObject<1>(next_unused_vertex,
+ middle_line->vertex_index(1)));
+
+ children[0]->set_used_flag();
+ children[1]->set_used_flag();
+ children[0]->clear_children();
+ children[1]->clear_children();
+ children[0]->clear_user_data();
+ children[1]->clear_user_data();
+ children[0]->clear_user_flag();
+ children[1]->clear_user_flag();
+
+ children[0]->set_boundary_indicator (middle_line->boundary_indicator());
+ children[1]->set_boundary_indicator (middle_line->boundary_indicator());
+ }
+ // now remove the flag from the
+ // quad and go to the next
+ // quad, the actual refinement
+ // of the quad takes place
+ // later on in this pass of the
+ // loop or in the next one
+ quad->clear_user_flag();
+ continue;
+ } // if (several refinement cases)
+
+ // if we got here, we have an
+ // unrefined quad and have to do
+ // the usual work like in an purely
+ // isotropic refinement
+ Assert(quad_ref_case==RefinementCase<dim-1>::no_refinement, ExcInternalError());
+
+ // set the middle vertex
+ // appropriately
+ if (quad->at_boundary())
+ triangulation.vertices[next_unused_vertex]
+ = triangulation.boundary[quad->boundary_indicator()]->get_new_point_on_quad (quad);
+ else
+ // it might be that the
+ // quad itself is not
+ // at the boundary, but
+ // that one of its lines
+ // actually is. in this
+ // case, the newly
+ // created vertices at
+ // the centers of the
+ // lines are not
+ // necessarily the mean
+ // values of the
+ // adjacent vertices,
+ // so do not compute
+ // the new vertex as
+ // the mean value of
+ // the 4 vertices of
+ // the face, but rather
+ // as a weighted mean
+ // value of the 8
+ // vertices which we
+ // already have (the
+ // four old ones, and
+ // the four ones
+ // inserted as middle
+ // points for the four
+ // lines). summing up
+ // some more points is
+ // generally cheaper
+ // than first asking
+ // whether one of the
+ // lines is at the
+ // boundary
+ //
+ // note that the exact
+ // weights are chosen
+ // such as to minimize
+ // the distortion of
+ // the four new quads
+ // from the optimal
+ // shape; their
+ // derivation and
+ // values is copied
+ // over from the
+ // @p{MappingQ::set_laplace_on_vector}
+ // function
+ triangulation.vertices[next_unused_vertex]
+ = (quad->vertex(0) + quad->vertex(1) +
+ quad->vertex(2) + quad->vertex(3) +
+ 3*(quad->line(0)->child(0)->vertex(1) +
+ quad->line(1)->child(0)->vertex(1) +
+ quad->line(2)->child(0)->vertex(1) +
+ quad->line(3)->child(0)->vertex(1)) ) / 16;
+
+ triangulation.vertices_used[next_unused_vertex] = true;
+
+ // now that we created
+ // the right point, make
+ // up the four lines
+ // interior to the quad
+ // (++ takes care of the
+ // end of the vector)
+ typename Triangulation<dim,spacedim>::raw_line_iterator new_lines[4];
+
+ for (unsigned int i=0; i<4; ++i)
+ {
+ if (i%2==0)
+ // search a free pair of
+ // lines for 0. and 2. line,
+ // so that two of them end up
+ // together, which is
+ // necessary if later on we
+ // want to refine the quad
+ // anisotropically and the
+ // two lines end up as
+ // children of new line
+ next_unused_line=triangulation.faces->lines.next_free_pair_line(triangulation);
+
+ new_lines[i] = next_unused_line;
+ ++next_unused_line;
+
+ Assert (new_lines[i]->used() == false,
+ ExcCellShouldBeUnused());
+ }
+
+ // set the data of the
+ // four lines.
+ // first collect the
+ // indices of the five
+ // vertices:
+ // *--3--*
+ // | | |
+ // 0--4--1
+ // | | |
+ // *--2--*
+ // the lines are numbered
+ // as follows:
+ // *--*--*
+ // | 1 |
+ // *2-*-3*
+ // | 0 |
+ // *--*--*
+
+ const unsigned int vertex_indices[5]
+ = { quad->line(0)->child(0)->vertex_index(1),
+ quad->line(1)->child(0)->vertex_index(1),
+ quad->line(2)->child(0)->vertex_index(1),
+ quad->line(3)->child(0)->vertex_index(1),
+ next_unused_vertex
+ };
+
+ new_lines[0]->set (internal::Triangulation::
+ TriaObject<1>(vertex_indices[2], vertex_indices[4]));
+ new_lines[1]->set (internal::Triangulation::
+ TriaObject<1>(vertex_indices[4], vertex_indices[3]));
+ new_lines[2]->set (internal::Triangulation::
+ TriaObject<1>(vertex_indices[0], vertex_indices[4]));
+ new_lines[3]->set (internal::Triangulation::
+ TriaObject<1>(vertex_indices[4], vertex_indices[1]));
+
+ for (unsigned int i=0; i<4; ++i)
+ {
+ new_lines[i]->set_used_flag();
+ new_lines[i]->clear_user_flag();
+ new_lines[i]->clear_user_data();
+ new_lines[i]->clear_children();
+ new_lines[i]->set_boundary_indicator(quad->boundary_indicator());
+ }
+
+ // now for the
+ // quads. again, first
+ // collect some data
+ // about the indices of
+ // the lines, with the
+ // following numbering:
+ // .-6-.-7-.
+ // 1 9 3
+ // .-10.11-.
+ // 0 8 2
+ // .-4-.-5-.
+
+ // child 0 and 1 of a line are
+ // switched if the line orientation
+ // is false. set up a miniature
+ // table, indicating which child to
+ // take for line orientations false
+ // and true. first index: child
+ // index in standard orientation,
+ // second index: line orientation
+ const unsigned int index[2][2]=
+ {{1,0}, // child 0, line_orientation=false and true
+ {0,1}}; // child 1, line_orientation=false and true
+
+ const unsigned int line_indices[12]
+ = { quad->line(0)->child(index[0][quad->line_orientation(0)])->index(),
+ quad->line(0)->child(index[1][quad->line_orientation(0)])->index(),
+ quad->line(1)->child(index[0][quad->line_orientation(1)])->index(),
+ quad->line(1)->child(index[1][quad->line_orientation(1)])->index(),
+ quad->line(2)->child(index[0][quad->line_orientation(2)])->index(),
+ quad->line(2)->child(index[1][quad->line_orientation(2)])->index(),
+ quad->line(3)->child(index[0][quad->line_orientation(3)])->index(),
+ quad->line(3)->child(index[1][quad->line_orientation(3)])->index(),
+ new_lines[0]->index(),
+ new_lines[1]->index(),
+ new_lines[2]->index(),
+ new_lines[3]->index()
+ };
+
+ // find some space (consecutive)
+ // for the first two newly to be
+ // created quads.
+ typename Triangulation<dim,spacedim>::raw_quad_iterator new_quads[4];
+
+ next_unused_quad=triangulation.faces->quads.next_free_pair_quad(triangulation);
+
+ new_quads[0] = next_unused_quad;
+ Assert (new_quads[0]->used() == false, ExcCellShouldBeUnused());
+
+ ++next_unused_quad;
+ new_quads[1] = next_unused_quad;
+ Assert (new_quads[1]->used() == false, ExcCellShouldBeUnused());
+
+ next_unused_quad=triangulation.faces->quads.next_free_pair_quad(triangulation);
+ new_quads[2] = next_unused_quad;
+ Assert (new_quads[2]->used() == false, ExcCellShouldBeUnused());
+
+ ++next_unused_quad;
+ new_quads[3] = next_unused_quad;
+ Assert (new_quads[3]->used() == false, ExcCellShouldBeUnused());
+
+ // note these quads as
+ // children to the
+ // present one
+ quad->set_children (0, new_quads[0]->index());
+ quad->set_children (2, new_quads[2]->index());
+ new_quads[0]->set (internal::Triangulation
+ ::TriaObject<2>(line_indices[0],
+ line_indices[8],
+ line_indices[4],
+ line_indices[10]));
+
+ quad->set_refinement_case(RefinementCase<2>::cut_xy);
+
+ new_quads[0]->set (internal::Triangulation
+ ::TriaObject<2>(line_indices[0],
+ line_indices[8],
+ line_indices[4],
+ line_indices[10]));
+ new_quads[1]->set (internal::Triangulation
+ ::TriaObject<2>(line_indices[8],
+ line_indices[2],
+ line_indices[5],
+ line_indices[11]));
+ new_quads[2]->set (internal::Triangulation
+ ::TriaObject<2>(line_indices[1],
+ line_indices[9],
+ line_indices[10],
+ line_indices[6]));
+ new_quads[3]->set (internal::Triangulation
+ ::TriaObject<2>(line_indices[9],
+ line_indices[3],
+ line_indices[11],
+ line_indices[7]));
+ for (unsigned int i=0; i<4; ++i)
+ {
+ new_quads[i]->set_used_flag();
+ new_quads[i]->clear_user_flag();
+ new_quads[i]->clear_user_data();
+ new_quads[i]->clear_children();
+ new_quads[i]->set_boundary_indicator (quad->boundary_indicator());
+ // set all line orientations to
+ // true, change this after the
+ // loop, as we have to consider
+ // different lines for each
+ // child
+ for (unsigned int j=0; j<GeometryInfo<dim>::lines_per_face; ++j)
+ new_quads[i]->set_line_orientation(j,true);
+ }
+ // now set the line orientation of
+ // children of outer lines
+ // correctly, the lines in the
+ // interior of the refined quad are
+ // automatically oriented
+ // conforming to the standard
+ new_quads[0]->set_line_orientation(0,quad->line_orientation(0));
+ new_quads[0]->set_line_orientation(2,quad->line_orientation(2));
+ new_quads[1]->set_line_orientation(1,quad->line_orientation(1));
+ new_quads[1]->set_line_orientation(2,quad->line_orientation(2));
+ new_quads[2]->set_line_orientation(0,quad->line_orientation(0));
+ new_quads[2]->set_line_orientation(3,quad->line_orientation(3));
+ new_quads[3]->set_line_orientation(1,quad->line_orientation(1));
+ new_quads[3]->set_line_orientation(3,quad->line_orientation(3));
+
+ // finally clear flag
+ // indicating the need
+ // for refinement
+ quad->clear_user_flag ();
+ } // if (isotropic refinement)
+ } // for all quads
+ } // looped two times over all quads, all quads refined now
+
+ ///////////////////////////////////
+ // Now, finally, set up the new
+ // cells
+ ///////////////////////////////////
+
+ typename Triangulation<3,spacedim>::DistortedCellList
+ cells_with_distorted_children;
+
+ for (unsigned int level=0; level!=triangulation.levels.size()-1; ++level)
+ {
+ // only active objects can be
+ // refined further; remember
+ // that we won't operate on the
+ // finest level, so
+ // triangulation.begin_*(level+1) is allowed
+ typename Triangulation<dim,spacedim>::active_hex_iterator
+ hex = triangulation.begin_active_hex(level),
+ endh = triangulation.begin_active_hex(level+1);
+ typename Triangulation<dim,spacedim>::raw_hex_iterator
+ next_unused_hex = triangulation.begin_raw_hex (level+1);
+
+ for (; hex!=endh; ++hex)
+ if (hex->refine_flag_set())
+ {
+ // this hex needs to be
+ // refined
+
+ // clear flag indicating
+ // the need for
+ // refinement. do it here
+ // already, since we
+ // can't do it anymore
+ // once the cell has
+ // children
+ const RefinementCase<dim> ref_case=hex->refine_flag_set();
+ hex->clear_refine_flag ();
+ hex->set_refinement_case(ref_case);
+
+ // depending on the refine case we
+ // might have to create additional
+ // vertices, lines and quads
+ // interior of the hex before the
+ // actual children can be set up.
+
+ // in a first step: reserve the
+ // needed space for lines, quads
+ // and hexes and initialize them
+ // correctly
+
+ unsigned int n_new_lines=0;
+ unsigned int n_new_quads=0;
+ unsigned int n_new_hexes=0;
+ switch (ref_case)
+ {
+ case RefinementCase<dim>::cut_x:
+ case RefinementCase<dim>::cut_y:
+ case RefinementCase<dim>::cut_z:
+ n_new_lines=0;
+ n_new_quads=1;
+ n_new_hexes=2;
+ break;
+ case RefinementCase<dim>::cut_xy:
+ case RefinementCase<dim>::cut_xz:
+ case RefinementCase<dim>::cut_yz:
+ n_new_lines=1;
+ n_new_quads=4;
+ n_new_hexes=4;
+ break;
+ case RefinementCase<dim>::cut_xyz:
+ n_new_lines=6;
+ n_new_quads=12;
+ n_new_hexes=8;
+ break;
+ default:
+ Assert(false, ExcInternalError());
+ break;
+ }
+
+ // find some space for the newly to
+ // be created interior lines and
+ // initialize them.
+ std::vector<typename Triangulation<dim,spacedim>::raw_line_iterator>
+ new_lines(n_new_lines);
+ for (unsigned int i=0; i<n_new_lines; ++i)
+ {
+ new_lines[i] = triangulation.faces->lines.next_free_single_line(triangulation);
+
+ Assert (new_lines[i]->used() == false,
+ ExcCellShouldBeUnused());
+ new_lines[i]->set_used_flag();
+ new_lines[i]->clear_user_flag();
+ new_lines[i]->clear_user_data();
+ new_lines[i]->clear_children();
+ // interior line
+ new_lines[i]->set_boundary_indicator(255);
+ }
+
+ // find some space for the newly to
+ // be created interior quads and
+ // initialize them.
+ std::vector<typename Triangulation<dim,spacedim>::raw_quad_iterator>
+ new_quads(n_new_quads);
+ for (unsigned int i=0; i<n_new_quads; ++i)
+ {
+ new_quads[i] = triangulation.faces->quads.next_free_single_quad(triangulation);
+
+ Assert (new_quads[i]->used() == false,
+ ExcCellShouldBeUnused());
+ new_quads[i]->set_used_flag();
+ new_quads[i]->clear_user_flag();
+ new_quads[i]->clear_user_data();
+ new_quads[i]->clear_children();
+ // interior quad
+ new_quads[i]->set_boundary_indicator (255);
+ // set all line orientation
+ // flags to true by default,
+ // change this afterwards, if
+ // necessary
+ for (unsigned int j=0; j<GeometryInfo<dim>::lines_per_face; ++j)
+ new_quads[i]->set_line_orientation(j,true);
+ }
+
+ // find some space for the newly to
+ // be created hexes and initialize
+ // them.
+ std::vector<typename Triangulation<dim,spacedim>::raw_hex_iterator>
+ new_hexes(n_new_hexes);
+ for (unsigned int i=0; i<n_new_hexes; ++i)
+ {
+ if (i%2==0)
+ next_unused_hex=triangulation.levels[level+1]->cells.next_free_hex(triangulation,level+1);
+
+ else
+ ++next_unused_hex;
+
+ new_hexes[i]=next_unused_hex;
+
+ Assert (new_hexes[i]->used() == false,
+ ExcCellShouldBeUnused());
+ new_hexes[i]->set_used_flag();
+ new_hexes[i]->clear_user_flag();
+ new_hexes[i]->clear_user_data();
+ new_hexes[i]->clear_children();
+ // inherit material
+ // properties
+ new_hexes[i]->set_material_id (hex->material_id());
+ new_hexes[i]->set_subdomain_id (hex->subdomain_id());
+
+ if (i%2)
+ new_hexes[i]->set_parent (hex->index ());
+ // set the face_orientation
+ // flag to true for all faces
+ // initially, as this is the
+ // default value which is true
+ // for all faces interior to
+ // the hex. later on go the
+ // other way round and reset
+ // faces that are at the
+ // boundary of the mother cube
+ //
+ // the same is true for the
+ // face_flip and face_rotation
+ // flags. however, the latter
+ // two are set to false by
+ // default as this is the
+ // standard value
+ for (unsigned int f=0; f<GeometryInfo<dim>::faces_per_cell; ++f)
+ {
+ new_hexes[i]->set_face_orientation(f, true);
+ new_hexes[i]->set_face_flip(f, false);
+ new_hexes[i]->set_face_rotation(f, false);
+ }
+ }
+ // note these hexes as
+ // children to the
+ // present cell
+ for (unsigned int i=0; i<n_new_hexes/2; ++i)
+ hex->set_children (2*i, new_hexes[2*i]->index());
+
+ // we have to take into account
+ // whether the different faces are
+ // oriented correctly or in the
+ // opposite direction, so store
+ // that up front
+
+ // face_orientation
+ const bool f_or[6]
+ = { hex->face_orientation (0),
+ hex->face_orientation (1),
+ hex->face_orientation (2),
+ hex->face_orientation (3),
+ hex->face_orientation (4),
+ hex->face_orientation (5) };
+
+ // face_flip
+ const bool f_fl[6]
+ = { hex->face_flip (0),
+ hex->face_flip (1),
+ hex->face_flip (2),
+ hex->face_flip (3),
+ hex->face_flip (4),
+ hex->face_flip (5) };
+
+ // face_rotation
+ const bool f_ro[6]
+ = { hex->face_rotation (0),
+ hex->face_rotation (1),
+ hex->face_rotation (2),
+ hex->face_rotation (3),
+ hex->face_rotation (4),
+ hex->face_rotation (5) };
+
+ // some commonly used fields which
+ // have varying size
+ const unsigned int *vertex_indices=0;
+ const typename Triangulation<dim,spacedim>::raw_line_iterator
+ *lines=0;
+ const unsigned int *line_indices=0;
+ const bool *line_orientation=0;
+ const unsigned int *quad_indices=0;
+
+ // little helper table, indicating,
+ // whether the child with index 0
+ // or with index 1 can be found at
+ // the standard origin of an
+ // anisotropically refined quads in
+ // real orientation
+ // index 1: (RefineCase - 1)
+ // index 2: face_flip
+
+ // index 3: face rotation
+ // note: face orientation has no influence
+ const unsigned int child_at_origin[2][2][2]=
+ { { { 0, 0 }, // RefinementCase<dim>::cut_x, face_flip=false, face_rotation=false and true
+ { 1, 1 }}, // RefinementCase<dim>::cut_x, face_flip=true, face_rotation=false and true
+ { { 0, 1 }, // RefinementCase<dim>::cut_y, face_flip=false, face_rotation=false and true
+ { 1, 0 }}};// RefinementCase<dim>::cut_y, face_flip=true, face_rotation=false and true
+
+ ///////////////////////////////////////
+ //
+ // in the following we will do the
+ // same thing for each refinement
+ // case: create a new vertex (if
+ // needed), create new interior
+ // lines (if needed), create new
+ // interior quads and afterwards
+ // build the children hexes out of
+ // these and the existing subfaces
+ // of the outer quads (which have
+ // been created above). However,
+ // even if the steps are quite
+ // similar, the actual work
+ // strongly depends on the actual
+ // refinement case. therefore, we
+ // use seperate blocks of code for
+ // each of these cases, which
+ // hopefully increases the
+ // readability to some extend.
+
+ switch (ref_case)
+ {
+ case RefinementCase<dim>::cut_x:
+ {
+ //////////////////////////////
+ //
+ // RefinementCase<dim>::cut_x
+ //
+ // the refined cube will look
+ // like this:
+ //
+ // *----*----*
+ // / / /|
+ // / / / |
+ // / / / |
+ // *----*----* |
+ // | | | |
+ // | | | *
+ // | | | /
+ // | | | /
+ // | | |/
+ // *----*----*
+ //
+ // again, first
+ // collect some data
+ // about the indices of
+ // the lines, with the
+ // following numbering:
+
+ // face 2: front plane
+ // (note: x,y exchanged)
+ // *---*---*
+ // | | |
+ // | 0 |
+ // | | |
+ // *---*---*
+ // m0
+ // face 3: back plane
+ // (note: x,y exchanged)
+ // m1
+ // *---*---*
+ // | | |
+ // | 1 |
+ // | | |
+ // *---*---*
+ // face 4: bottom plane
+ // *---*---*
+ // / / /
+ // / 2 /
+ // / / /
+ // *---*---*
+ // m0
+ // face 5: top plane
+ // m1
+ // *---*---*
+ // / / /
+ // / 3 /
+ // / / /
+ // *---*---*
+
+ // set up a list of line iterators
+ // first. from this, construct
+ // lists of line_indices and
+ // line orientations later on
+ const typename Triangulation<dim,spacedim>::raw_line_iterator
+ lines_x[4]
+ = {
+ hex->face(2)->child(0)
+ ->line((hex->face(2)->refinement_case() == RefinementCase<2>::cut_x) ? 1 : 3), //0
+ hex->face(3)->child(0)
+ ->line((hex->face(3)->refinement_case() == RefinementCase<2>::cut_x) ? 1 : 3), //1
+ hex->face(4)->child(0)
+ ->line((hex->face(4)->refinement_case() == RefinementCase<2>::cut_x) ? 1 : 3), //2
+ hex->face(5)->child(0)
+ ->line((hex->face(5)->refinement_case() == RefinementCase<2>::cut_x) ? 1 : 3) //3
+ };
+
+ lines=&lines_x[0];
+
+ unsigned int line_indices_x[4];
+
+ for (unsigned int i=0; i<4; ++i)
+ line_indices_x[i]=lines[i]->index();
+ line_indices=&line_indices_x[0];
+
+ // the orientation of lines for the
+ // inner quads is quite tricky. as
+ // these lines are newly created
+ // ones and thus have no parents,
+ // they cannot inherit this
+ // property. set up an array and
+ // fill it with the respective
+ // values
+ bool line_orientation_x[4];
+
+ // the middle vertice marked
+ // as m0 above is the start
+ // vertex for lines 0 and 2
+ // in standard orientation,
+ // whereas m1 is the end
+ // vertex of lines 1 and 3 in
+ // standard orientation
+ const unsigned int middle_vertices[2]=
+ {
+ hex->line(2)->child(0)->vertex_index(1),
+ hex->line(7)->child(0)->vertex_index(1)
+ };
+
+ for (unsigned int i=0; i<4; ++i)
+ if (lines[i]->vertex_index(i%2)==middle_vertices[i%2])
+ line_orientation_x[i]=true;
+ else
+ {
+ // it must be the other
+ // way round then
+ Assert(lines[i]->vertex_index((i+1)%2)==middle_vertices[i%2],
+ ExcInternalError());
+ line_orientation_x[i]=false;
+ }
+
+ line_orientation=&line_orientation_x[0];
+
+ // set up the new quad, line
+ // numbering is as indicated
+ // above
+ new_quads[0]->set (internal::Triangulation
+ ::TriaObject<2>(line_indices[0],
+ line_indices[1],
+ line_indices[2],
+ line_indices[3]));
+
+ new_quads[0]->set_line_orientation(0,line_orientation[0]);
+ new_quads[0]->set_line_orientation(1,line_orientation[1]);
+ new_quads[0]->set_line_orientation(2,line_orientation[2]);
+ new_quads[0]->set_line_orientation(3,line_orientation[3]);
+
+ // the quads are
+ // numbered as follows:
+ //
+ // planes in the interior
+ // of the old hex:
+ // *
+ // /|
+ // / | x
+ // / | *-------* *---------*
+ // * | | | / /
+ // | 0 | | | / /
+ // | * | | / /
+ // | / *-------*y *---------*x
+ // | /
+ // |/
+ // *
+ //
+ // children of the faces
+ // of the old hex
+ // *---*---* *---*---*
+ // /| | | / / /|
+ // / | | | / 9 / 10/ |
+ // / | 5 | 6 | / / / |
+ // * | | | *---*---* |
+ // | 1 *---*---* | | | 2 *
+ // | / / / | | | /
+ // | / 7 / 8 / | 3 | 4 | /
+ // |/ / / | | |/
+ // *---*---* *---*---*
+ //
+ // note that we have to
+ // take care of the
+ // orientation of
+ // faces.
+ const unsigned int quad_indices_x[11]
+ = {
+ new_quads[0]->index(), //0
+
+ hex->face(0)->index(), //1
+
+ hex->face(1)->index(), //2
+
+ hex->face(2)->child_index( child_at_origin[hex->face(2)->refinement_case()-1][f_fl[2]][f_ro[2]]), //3
+ hex->face(2)->child_index(1-child_at_origin[hex->face(2)->refinement_case()-1][f_fl[2]][f_ro[2]]),
+
+ hex->face(3)->child_index( child_at_origin[hex->face(3)->refinement_case()-1][f_fl[3]][f_ro[3]]), //5
+ hex->face(3)->child_index(1-child_at_origin[hex->face(3)->refinement_case()-1][f_fl[3]][f_ro[3]]),
+
+ hex->face(4)->child_index( child_at_origin[hex->face(4)->refinement_case()-1][f_fl[4]][f_ro[4]]), //7
+ hex->face(4)->child_index(1-child_at_origin[hex->face(4)->refinement_case()-1][f_fl[4]][f_ro[4]]),
+
+ hex->face(5)->child_index( child_at_origin[hex->face(5)->refinement_case()-1][f_fl[5]][f_ro[5]]), //9
+ hex->face(5)->child_index(1-child_at_origin[hex->face(5)->refinement_case()-1][f_fl[5]][f_ro[5]])
+
+ };
+ quad_indices=&quad_indices_x[0];
+
+ new_hexes[0]->set (internal::Triangulation
+ ::TriaObject<3>(quad_indices[1],
+ quad_indices[0],
+ quad_indices[3],
+ quad_indices[5],
+ quad_indices[7],
+ quad_indices[9]));
+ new_hexes[1]->set (internal::Triangulation
+ ::TriaObject<3>(quad_indices[0],
+ quad_indices[2],
+ quad_indices[4],
+ quad_indices[6],
+ quad_indices[8],
+ quad_indices[10]));
+ break;
+ }
+ case RefinementCase<dim>::cut_y:
+ {
+ //////////////////////////////
+ //
+ // RefinementCase<dim>::cut_y
+ //
+ // the refined cube will look
+ // like this:
+ //
+ // *---------*
+ // / /|
+ // *---------* |
+ // / /| |
+ // *---------* | |
+ // | | | |
+ // | | | *
+ // | | |/
+ // | | *
+ // | |/
+ // *---------*
+ //
+ // again, first
+ // collect some data
+ // about the indices of
+ // the lines, with the
+ // following numbering:
+
+ // face 0: left plane
+ // *
+ // /|
+ // * |
+ // /| |
+ // * | |
+ // | 0 |
+ // | | *
+ // | |/
+ // | *m0
+ // |/
+ // *
+ // face 1: right plane
+ // *
+ // /|
+ // m1* |
+ // /| |
+ // * | |
+ // | 1 |
+ // | | *
+ // | |/
+ // | *
+ // |/
+ // *
+ // face 4: bottom plane
+ // *-------*
+ // / /
+ // m0*---2---*
+ // / /
+ // *-------*
+ // face 5: top plane
+ // *-------*
+ // / /
+ // *---3---*m1
+ // / /
+ // *-------*
+
+ // set up a list of line iterators
+ // first. from this, construct
+ // lists of line_indices and
+ // line orientations later on
+ const typename Triangulation<dim,spacedim>::raw_line_iterator
+ lines_y[4]
+ = {
+ hex->face(0)->child(0)
+ ->line((hex->face(0)->refinement_case() == RefinementCase<2>::cut_x) ? 1 : 3), //0
+ hex->face(1)->child(0)
+ ->line((hex->face(1)->refinement_case() == RefinementCase<2>::cut_x) ? 1 : 3), //1
+ hex->face(4)->child(0)
+ ->line((hex->face(4)->refinement_case() == RefinementCase<2>::cut_x) ? 1 : 3), //2
+ hex->face(5)->child(0)
+ ->line((hex->face(5)->refinement_case() == RefinementCase<2>::cut_x) ? 1 : 3) //3
+ };
+
+ lines=&lines_y[0];
+
+ unsigned int line_indices_y[4];
+
+ for (unsigned int i=0; i<4; ++i)
+ line_indices_y[i]=lines[i]->index();
+ line_indices=&line_indices_y[0];
+
+ // the orientation of lines for the
+ // inner quads is quite tricky. as
+ // these lines are newly created
+ // ones and thus have no parents,
+ // they cannot inherit this
+ // property. set up an array and
+ // fill it with the respective
+ // values
+ bool line_orientation_y[4];
+
+ // the middle vertice marked
+ // as m0 above is the start
+ // vertex for lines 0 and 2
+ // in standard orientation,
+ // whereas m1 is the end
+ // vertex of lines 1 and 3 in
+ // standard orientation
+ const unsigned int middle_vertices[2]=
+ {
+ hex->line(0)->child(0)->vertex_index(1),
+ hex->line(5)->child(0)->vertex_index(1)
+ };
+
+ for (unsigned int i=0; i<4; ++i)
+ if (lines[i]->vertex_index(i%2)==middle_vertices[i%2])
+ line_orientation_y[i]=true;
+ else
+ {
+ // it must be the other way round then
+ Assert(lines[i]->vertex_index((i+1)%2)==middle_vertices[i%2],
+ ExcInternalError());
+ line_orientation_y[i]=false;
+ }
+
+ line_orientation=&line_orientation_y[0];
+
+ // set up the new quad, line
+ // numbering is as indicated
+ // above
+ new_quads[0]->set (internal::Triangulation
+ ::TriaObject<2>(line_indices[2],
+ line_indices[3],
+ line_indices[0],
+ line_indices[1]));
+
+ new_quads[0]->set_line_orientation(0,line_orientation[2]);
+ new_quads[0]->set_line_orientation(1,line_orientation[3]);
+ new_quads[0]->set_line_orientation(2,line_orientation[0]);
+ new_quads[0]->set_line_orientation(3,line_orientation[1]);
+
+ // the quads are
+ // numbered as follows:
+ //
+ // planes in the interior
+ // of the old hex:
+ // *
+ // /|
+ // / | x
+ // / | *-------* *---------*
+ // * | | | / /
+ // | | | 0 | / /
+ // | * | | / /
+ // | / *-------*y *---------*x
+ // | /
+ // |/
+ // *
+ //
+ // children of the faces
+ // of the old hex
+ // *-------* *-------*
+ // /| | / 10 /|
+ // * | | *-------* |
+ // /| | 6 | / 9 /| |
+ // * |2| | *-------* |4|
+ // | | *-------* | | | *
+ // |1|/ 8 / | |3|/
+ // | *-------* | 5 | *
+ // |/ 7 / | |/
+ // *-------* *-------*
+ //
+ // note that we have to
+ // take care of the
+ // orientation of
+ // faces.
+ const unsigned int quad_indices_y[11]
+ = {
+ new_quads[0]->index(), //0
+
+ hex->face(0)->child_index( child_at_origin[hex->face(0)->refinement_case()-1][f_fl[0]][f_ro[0]]), //1
+ hex->face(0)->child_index(1-child_at_origin[hex->face(0)->refinement_case()-1][f_fl[0]][f_ro[0]]),
+
+ hex->face(1)->child_index( child_at_origin[hex->face(1)->refinement_case()-1][f_fl[1]][f_ro[1]]), //3
+ hex->face(1)->child_index(1-child_at_origin[hex->face(1)->refinement_case()-1][f_fl[1]][f_ro[1]]),
+
+ hex->face(2)->index(), //5
+
+ hex->face(3)->index(), //6
+
+ hex->face(4)->child_index( child_at_origin[hex->face(4)->refinement_case()-1][f_fl[4]][f_ro[4]]), //7
+ hex->face(4)->child_index(1-child_at_origin[hex->face(4)->refinement_case()-1][f_fl[4]][f_ro[4]]),
+
+ hex->face(5)->child_index( child_at_origin[hex->face(5)->refinement_case()-1][f_fl[5]][f_ro[5]]), //9
+ hex->face(5)->child_index(1-child_at_origin[hex->face(5)->refinement_case()-1][f_fl[5]][f_ro[5]])
+
+ };
+ quad_indices=&quad_indices_y[0];
+
+ new_hexes[0]->set (internal::Triangulation
+ ::TriaObject<3>(quad_indices[1],
+ quad_indices[3],
+ quad_indices[5],
+ quad_indices[0],
+ quad_indices[7],
+ quad_indices[9]));
+ new_hexes[1]->set (internal::Triangulation
+ ::TriaObject<3>(quad_indices[2],
+ quad_indices[4],
+ quad_indices[0],
+ quad_indices[6],
+ quad_indices[8],
+ quad_indices[10]));
+ break;
+ }
+ case RefinementCase<dim>::cut_z:
+ {
+ //////////////////////////////
+ //
+ // RefinementCase<dim>::cut_z
+ //
+ // the refined cube will look
+ // like this:
+ //
+ // *---------*
+ // / /|
+ // / / |
+ // / / *
+ // *---------* /|
+ // | | / |
+ // | |/ *
+ // *---------* /
+ // | | /
+ // | |/
+ // *---------*
+ //
+ // again, first
+ // collect some data
+ // about the indices of
+ // the lines, with the
+ // following numbering:
+
+ // face 0: left plane
+ // *
+ // /|
+ // / |
+ // / *
+ // * /|
+ // | 0 |
+ // |/ *
+ // m0* /
+ // | /
+ // |/
+ // *
+ // face 1: right plane
+ // *
+ // /|
+ // / |
+ // / *m1
+ // * /|
+ // | 1 |
+ // |/ *
+ // * /
+ // | /
+ // |/
+ // *
+ // face 2: front plane
+ // (note: x,y exchanged)
+ // *-------*
+ // | |
+ // m0*---2---*
+ // | |
+ // *-------*
+ // face 3: back plane
+ // (note: x,y exchanged)
+ // *-------*
+ // | |
+ // *---3---*m1
+ // | |
+ // *-------*
+
+ // set up a list of line iterators
+ // first. from this, construct
+ // lists of line_indices and
+ // line orientations later on
+ const typename Triangulation<dim,spacedim>::raw_line_iterator
+ lines_z[4]
+ = {
+ hex->face(0)->child(0)
+ ->line((hex->face(0)->refinement_case() == RefinementCase<2>::cut_x) ? 1 : 3), //0
+ hex->face(1)->child(0)
+ ->line((hex->face(1)->refinement_case() == RefinementCase<2>::cut_x) ? 1 : 3), //1
+ hex->face(2)->child(0)
+ ->line((hex->face(2)->refinement_case() == RefinementCase<2>::cut_x) ? 1 : 3), //2
+ hex->face(3)->child(0)
+ ->line((hex->face(3)->refinement_case() == RefinementCase<2>::cut_x) ? 1 : 3) //3
+ };
+
+ lines=&lines_z[0];
+
+ unsigned int line_indices_z[4];
+
+ for (unsigned int i=0; i<4; ++i)
+ line_indices_z[i]=lines[i]->index();
+ line_indices=&line_indices_z[0];
+
+ // the orientation of lines for the
+ // inner quads is quite tricky. as
+ // these lines are newly created
+ // ones and thus have no parents,
+ // they cannot inherit this
+ // property. set up an array and
+ // fill it with the respective
+ // values
+ bool line_orientation_z[4];
+
+ // the middle vertex marked
+ // as m0 above is the start
+ // vertex for lines 0 and 2
+ // in standard orientation,
+ // whereas m1 is the end
+ // vertex of lines 1 and 3 in
+ // standard orientation
+ const unsigned int middle_vertices[2]=
+ {
+ middle_vertex_index<dim,spacedim>(hex->line(8)),
+ middle_vertex_index<dim,spacedim>(hex->line(11))
+ };
+
+ for (unsigned int i=0; i<4; ++i)
+ if (lines[i]->vertex_index(i%2)==middle_vertices[i%2])
+ line_orientation_z[i]=true;
+ else
+ {
+ // it must be the other way round then
+ Assert(lines[i]->vertex_index((i+1)%2)==middle_vertices[i%2],
+ ExcInternalError());
+ line_orientation_z[i]=false;
+ }
+
+ line_orientation=&line_orientation_z[0];
+
+ // set up the new quad, line
+ // numbering is as indicated
+ // above
+ new_quads[0]->set (internal::Triangulation
+ ::TriaObject<2>(line_indices[0],
+ line_indices[1],
+ line_indices[2],
+ line_indices[3]));
+
+ new_quads[0]->set_line_orientation(0,line_orientation[0]);
+ new_quads[0]->set_line_orientation(1,line_orientation[1]);
+ new_quads[0]->set_line_orientation(2,line_orientation[2]);
+ new_quads[0]->set_line_orientation(3,line_orientation[3]);
+
+ // the quads are
+ // numbered as follows:
+ //
+ // planes in the interior
+ // of the old hex:
+ // *
+ // /|
+ // / | x
+ // / | *-------* *---------*
+ // * | | | / /
+ // | | | | / 0 /
+ // | * | | / /
+ // | / *-------*y *---------*x
+ // | /
+ // |/
+ // *
+ //
+ // children of the faces
+ // of the old hex
+ // *---*---* *-------*
+ // /| 8 | / /|
+ // / | | / 10 / |
+ // / *-------* / / *
+ // * 2/| | *-------* 4/|
+ // | / | 7 | | 6 | / |
+ // |/1 *-------* | |/3 *
+ // * / / *-------* /
+ // | / 9 / | | /
+ // |/ / | 5 |/
+ // *-------* *---*---*
+ //
+ // note that we have to
+ // take care of the
+ // orientation of
+ // faces.
+ const unsigned int quad_indices_z[11]
+ = {
+ new_quads[0]->index(), //0
+
+ hex->face(0)->child_index( child_at_origin[hex->face(0)->refinement_case()-1][f_fl[0]][f_ro[0]]), //1
+ hex->face(0)->child_index(1-child_at_origin[hex->face(0)->refinement_case()-1][f_fl[0]][f_ro[0]]),
+
+ hex->face(1)->child_index( child_at_origin[hex->face(1)->refinement_case()-1][f_fl[1]][f_ro[1]]), //3
+ hex->face(1)->child_index(1-child_at_origin[hex->face(1)->refinement_case()-1][f_fl[1]][f_ro[1]]),
+
+ hex->face(2)->child_index( child_at_origin[hex->face(2)->refinement_case()-1][f_fl[2]][f_ro[2]]), //5
+ hex->face(2)->child_index(1-child_at_origin[hex->face(2)->refinement_case()-1][f_fl[2]][f_ro[2]]),
+
+ hex->face(3)->child_index( child_at_origin[hex->face(3)->refinement_case()-1][f_fl[3]][f_ro[3]]), //7
+ hex->face(3)->child_index(1-child_at_origin[hex->face(3)->refinement_case()-1][f_fl[3]][f_ro[3]]),
+
+ hex->face(4)->index(), //9
+
+ hex->face(5)->index() //10
+ };
+ quad_indices=&quad_indices_z[0];
+
+ new_hexes[0]->set (internal::Triangulation
+ ::TriaObject<3>(quad_indices[1],
+ quad_indices[3],
+ quad_indices[5],
+ quad_indices[7],
+ quad_indices[9],
+ quad_indices[0]));
+ new_hexes[1]->set (internal::Triangulation
+ ::TriaObject<3>(quad_indices[2],
+ quad_indices[4],
+ quad_indices[6],
+ quad_indices[8],
+ quad_indices[0],
+ quad_indices[10]));
+ break;
+ }
+ case RefinementCase<dim>::cut_xy:
+ {
+ //////////////////////////////
+ //
+ // RefinementCase<dim>::cut_xy
+ //
+ // the refined cube will look
+ // like this:
+ //
+ // *----*----*
+ // / / /|
+ // *----*----* |
+ // / / /| |
+ // *----*----* | |
+ // | | | | |
+ // | | | | *
+ // | | | |/
+ // | | | *
+ // | | |/
+ // *----*----*
+ //
+
+ // first, create the new
+ // internal line
+ new_lines[0]->set (internal::Triangulation::
+ TriaObject<1>(middle_vertex_index<dim,spacedim>(hex->face(4)),
+ middle_vertex_index<dim,spacedim>(hex->face(5))));
+
+ // again, first
+ // collect some data
+ // about the indices of
+ // the lines, with the
+ // following numbering:
+
+ // face 0: left plane
+ // *
+ // /|
+ // * |
+ // /| |
+ // * | |
+ // | 0 |
+ // | | *
+ // | |/
+ // | *
+ // |/
+ // *
+ // face 1: right plane
+ // *
+ // /|
+ // * |
+ // /| |
+ // * | |
+ // | 1 |
+ // | | *
+ // | |/
+ // | *
+ // |/
+ // *
+ // face 2: front plane
+ // (note: x,y exchanged)
+ // *---*---*
+ // | | |
+ // | 2 |
+ // | | |
+ // *-------*
+ // face 3: back plane
+ // (note: x,y exchanged)
+ // *---*---*
+ // | | |
+ // | 3 |
+ // | | |
+ // *---*---*
+ // face 4: bottom plane
+ // *---*---*
+ // / 5 /
+ // *-6-*-7-*
+ // / 4 /
+ // *---*---*
+ // face 5: top plane
+ // *---*---*
+ // / 9 /
+ // *10-*-11*
+ // / 8 /
+ // *---*---*
+ // middle planes
+ // *-------* *---*---*
+ // / / | | |
+ // / / | 12 |
+ // / / | | |
+ // *-------* *---*---*
+
+ // set up a list of line iterators
+ // first. from this, construct
+ // lists of line_indices and
+ // line orientations later on
+ const typename Triangulation<dim,spacedim>::raw_line_iterator
+ lines_xy[13]
+ = {
+ hex->face(0)->child(0)
+ ->line((hex->face(0)->refinement_case() == RefinementCase<2>::cut_x) ? 1 : 3), //0
+ hex->face(1)->child(0)
+ ->line((hex->face(1)->refinement_case() == RefinementCase<2>::cut_x) ? 1 : 3), //1
+ hex->face(2)->child(0)
+ ->line((hex->face(2)->refinement_case() == RefinementCase<2>::cut_x) ? 1 : 3), //2
+ hex->face(3)->child(0)
+ ->line((hex->face(3)->refinement_case() == RefinementCase<2>::cut_x) ? 1 : 3), //3
+
+ hex->face(4)->isotropic_child(GeometryInfo<dim>::standard_to_real_face_vertex(0,f_or[4],f_fl[4],f_ro[4]))
+ ->line(GeometryInfo<dim>::standard_to_real_face_line(1,f_or[4],f_fl[4],f_ro[4])), //4
+ hex->face(4)->isotropic_child(GeometryInfo<dim>::standard_to_real_face_vertex(3,f_or[4],f_fl[4],f_ro[4]))
+ ->line(GeometryInfo<dim>::standard_to_real_face_line(0,f_or[4],f_fl[4],f_ro[4])), //5
+ hex->face(4)->isotropic_child(GeometryInfo<dim>::standard_to_real_face_vertex(0,f_or[4],f_fl[4],f_ro[4]))
+ ->line(GeometryInfo<dim>::standard_to_real_face_line(3,f_or[4],f_fl[4],f_ro[4])), //6
+ hex->face(4)->isotropic_child(GeometryInfo<dim>::standard_to_real_face_vertex(3,f_or[4],f_fl[4],f_ro[4]))
+ ->line(GeometryInfo<dim>::standard_to_real_face_line(2,f_or[4],f_fl[4],f_ro[4])), //7
+
+ hex->face(5)->isotropic_child(GeometryInfo<dim>::standard_to_real_face_vertex(0,f_or[5],f_fl[5],f_ro[5]))
+ ->line(GeometryInfo<dim>::standard_to_real_face_line(1,f_or[5],f_fl[5],f_ro[5])), //8
+ hex->face(5)->isotropic_child(GeometryInfo<dim>::standard_to_real_face_vertex(3,f_or[5],f_fl[5],f_ro[5]))
+ ->line(GeometryInfo<dim>::standard_to_real_face_line(0,f_or[5],f_fl[5],f_ro[5])), //9
+ hex->face(5)->isotropic_child(GeometryInfo<dim>::standard_to_real_face_vertex(0,f_or[5],f_fl[5],f_ro[5]))
+ ->line(GeometryInfo<dim>::standard_to_real_face_line(3,f_or[5],f_fl[5],f_ro[5])), //10
+ hex->face(5)->isotropic_child(GeometryInfo<dim>::standard_to_real_face_vertex(3,f_or[5],f_fl[5],f_ro[5]))
+ ->line(GeometryInfo<dim>::standard_to_real_face_line(2,f_or[5],f_fl[5],f_ro[5])), //11
+
+ new_lines[0] //12
+ };
+
+ lines=&lines_xy[0];
+
+ unsigned int line_indices_xy[13];
+
+ for (unsigned int i=0; i<13; ++i)
+ line_indices_xy[i]=lines[i]->index();
+ line_indices=&line_indices_xy[0];
+
+ // the orientation of lines for the
+ // inner quads is quite tricky. as
+ // these lines are newly created
+ // ones and thus have no parents,
+ // they cannot inherit this
+ // property. set up an array and
+ // fill it with the respective
+ // values
+ bool line_orientation_xy[13];
+
+ // the middle vertices of the
+ // lines of our bottom face
+ const unsigned int middle_vertices[4]=
+ {
+ hex->line(0)->child(0)->vertex_index(1),
+ hex->line(1)->child(0)->vertex_index(1),
+ hex->line(2)->child(0)->vertex_index(1),
+ hex->line(3)->child(0)->vertex_index(1),
+ };
+
+ // note: for lines 0 to 3 the
+ // orientation of the line
+ // is 'true', if vertex 0 is
+ // on the bottom face
+ for (unsigned int i=0; i<4; ++i)
+ if (lines[i]->vertex_index(0)==middle_vertices[i])
+ line_orientation_xy[i]=true;
+ else
+ {
+ // it must be the other way round then
+ Assert(lines[i]->vertex_index(1)==middle_vertices[i],
+ ExcInternalError());
+ line_orientation_xy[i]=false;
+ }
+
+ // note: for lines 4 to 11
+ // (inner lines of the outer quads)
+ // the following holds: the second
+ // vertex of the even lines in
+ // standard orientation is the
+ // vertex in the middle of the
+ // quad, whereas for odd lines the
+ // first vertex is the same middle
+ // vertex.
+ for (unsigned int i=4; i<12; ++i)
+ if (lines[i]->vertex_index((i+1)%2) ==
+ middle_vertex_index<dim,spacedim>(hex->face(3+i/4)))
+ line_orientation_xy[i]=true;
+ else
+ {
+ // it must be the other way
+ // round then
+ Assert(lines[i]->vertex_index(i%2) ==
+ (middle_vertex_index<dim,spacedim>(hex->face(3+i/4))),
+ ExcInternalError());
+ line_orientation_xy[i]=false;
+ }
+ // for the last line the line
+ // orientation is always true,
+ // since it was just constructed
+ // that way
+
+ line_orientation_xy[12]=true;
+ line_orientation=&line_orientation_xy[0];
+
+ // set up the 4 quads,
+ // numbered as follows
+ // (left quad numbering,
+ // right line numbering
+ // extracted from above)
+ //
+ // * *
+ // /| 9|
+ // * | * |
+ // y/| | 8| 3
+ // * |1| * | |
+ // | | |x | 12|
+ // |0| * | | *
+ // | |/ 2 |5
+ // | * | *
+ // |/ |4
+ // * *
+ //
+ // x
+ // *---*---* *10-*-11*
+ // | | | | | |
+ // | 2 | 3 | 0 12 1
+ // | | | | | |
+ // *---*---*y *-6-*-7-*
+
+ new_quads[0]->set (internal::Triangulation
+ ::TriaObject<2>(line_indices[2],
+ line_indices[12],
+ line_indices[4],
+ line_indices[8]));
+ new_quads[1]->set (internal::Triangulation
+ ::TriaObject<2>(line_indices[12],
+ line_indices[3],
+ line_indices[5],
+ line_indices[9]));
+ new_quads[2]->set (internal::Triangulation
+ ::TriaObject<2>(line_indices[6],
+ line_indices[10],
+ line_indices[0],
+ line_indices[12]));
+ new_quads[3]->set (internal::Triangulation
+ ::TriaObject<2>(line_indices[7],
+ line_indices[11],
+ line_indices[12],
+ line_indices[1]));
+
+ new_quads[0]->set_line_orientation(0,line_orientation[2]);
+ new_quads[0]->set_line_orientation(2,line_orientation[4]);
+ new_quads[0]->set_line_orientation(3,line_orientation[8]);
+
+ new_quads[1]->set_line_orientation(1,line_orientation[3]);
+ new_quads[1]->set_line_orientation(2,line_orientation[5]);
+ new_quads[1]->set_line_orientation(3,line_orientation[9]);
+
+ new_quads[2]->set_line_orientation(0,line_orientation[6]);
+ new_quads[2]->set_line_orientation(1,line_orientation[10]);
+ new_quads[2]->set_line_orientation(2,line_orientation[0]);
+
+ new_quads[3]->set_line_orientation(0,line_orientation[7]);
+ new_quads[3]->set_line_orientation(1,line_orientation[11]);
+ new_quads[3]->set_line_orientation(3,line_orientation[1]);
+
+ // the quads are
+ // numbered as follows:
+ //
+ // planes in the interior
+ // of the old hex:
+ // *
+ // /|
+ // * | x
+ // /| | *---*---* *---------*
+ // * |1| | | | / /
+ // | | | | 2 | 3 | / /
+ // |0| * | | | / /
+ // | |/ *---*---*y *---------*x
+ // | *
+ // |/
+ // *
+ //
+ // children of the faces
+ // of the old hex
+ // *---*---* *---*---*
+ // /| | | /18 / 19/|
+ // * |10 | 11| /---/---* |
+ // /| | | | /16 / 17/| |
+ // * |5| | | *---*---* |7|
+ // | | *---*---* | | | | *
+ // |4|/14 / 15/ | | |6|/
+ // | *---/---/ | 8 | 9 | *
+ // |/12 / 13/ | | |/
+ // *---*---* *---*---*
+ //
+ // note that we have to
+ // take care of the
+ // orientation of
+ // faces.
+ const unsigned int quad_indices_xy[20]
+ = {
+ new_quads[0]->index(), //0
+ new_quads[1]->index(),
+ new_quads[2]->index(),
+ new_quads[3]->index(),
+
+ hex->face(0)->child_index( child_at_origin[hex->face(0)->refinement_case()-1][f_fl[0]][f_ro[0]]), //4
+ hex->face(0)->child_index(1-child_at_origin[hex->face(0)->refinement_case()-1][f_fl[0]][f_ro[0]]),
+
+ hex->face(1)->child_index( child_at_origin[hex->face(1)->refinement_case()-1][f_fl[1]][f_ro[1]]), //6
+ hex->face(1)->child_index(1-child_at_origin[hex->face(1)->refinement_case()-1][f_fl[1]][f_ro[1]]),
+
+ hex->face(2)->child_index( child_at_origin[hex->face(2)->refinement_case()-1][f_fl[2]][f_ro[2]]), //8
+ hex->face(2)->child_index(1-child_at_origin[hex->face(2)->refinement_case()-1][f_fl[2]][f_ro[2]]),
+
+ hex->face(3)->child_index( child_at_origin[hex->face(3)->refinement_case()-1][f_fl[3]][f_ro[3]]), //10
+ hex->face(3)->child_index(1-child_at_origin[hex->face(3)->refinement_case()-1][f_fl[3]][f_ro[3]]),
+
+ hex->face(4)->isotropic_child_index(GeometryInfo<dim>::standard_to_real_face_vertex(0,f_or[4],f_fl[4],f_ro[4])), //12
+ hex->face(4)->isotropic_child_index(GeometryInfo<dim>::standard_to_real_face_vertex(1,f_or[4],f_fl[4],f_ro[4])),
+ hex->face(4)->isotropic_child_index(GeometryInfo<dim>::standard_to_real_face_vertex(2,f_or[4],f_fl[4],f_ro[4])),
+ hex->face(4)->isotropic_child_index(GeometryInfo<dim>::standard_to_real_face_vertex(3,f_or[4],f_fl[4],f_ro[4])),
+
+ hex->face(5)->isotropic_child_index(GeometryInfo<dim>::standard_to_real_face_vertex(0,f_or[5],f_fl[5],f_ro[5])), //16
+ hex->face(5)->isotropic_child_index(GeometryInfo<dim>::standard_to_real_face_vertex(1,f_or[5],f_fl[5],f_ro[5])),
+ hex->face(5)->isotropic_child_index(GeometryInfo<dim>::standard_to_real_face_vertex(2,f_or[5],f_fl[5],f_ro[5])),
+ hex->face(5)->isotropic_child_index(GeometryInfo<dim>::standard_to_real_face_vertex(3,f_or[5],f_fl[5],f_ro[5]))
+ };
+ quad_indices=&quad_indices_xy[0];
+
+ new_hexes[0]->set (internal::Triangulation
+ ::TriaObject<3>(quad_indices[4],
+ quad_indices[0],
+ quad_indices[8],
+ quad_indices[2],
+ quad_indices[12],
+ quad_indices[16]));
+ new_hexes[1]->set (internal::Triangulation
+ ::TriaObject<3>(quad_indices[0],
+ quad_indices[6],
+ quad_indices[9],
+ quad_indices[3],
+ quad_indices[13],
+ quad_indices[17]));
+ new_hexes[2]->set (internal::Triangulation
+ ::TriaObject<3>(quad_indices[5],
+ quad_indices[1],
+ quad_indices[2],
+ quad_indices[10],
+ quad_indices[14],
+ quad_indices[18]));
+ new_hexes[3]->set (internal::Triangulation
+ ::TriaObject<3>(quad_indices[1],
+ quad_indices[7],
+ quad_indices[3],
+ quad_indices[11],
+ quad_indices[15],
+ quad_indices[19]));
+ break;
+ }
+ case RefinementCase<dim>::cut_xz:
+ {
+ //////////////////////////////
+ //
+ // RefinementCase<dim>::cut_xz
+ //
+ // the refined cube will look
+ // like this:
+ //
+ // *----*----*
+ // / / /|
+ // / / / |
+ // / / / *
+ // *----*----* /|
+ // | | | / |
+ // | | |/ *
+ // *----*----* /
+ // | | | /
+ // | | |/
+ // *----*----*
+ //
+
+ // first, create the new
+ // internal line
+ new_lines[0]->set (internal::Triangulation::
+ TriaObject<1>(middle_vertex_index<dim,spacedim>(hex->face(2)),
+ middle_vertex_index<dim,spacedim>(hex->face(3))));
+
+ // again, first
+ // collect some data
+ // about the indices of
+ // the lines, with the
+ // following numbering:
+
+ // face 0: left plane
+ // *
+ // /|
+ // / |
+ // / *
+ // * /|
+ // | 0 |
+ // |/ *
+ // * /
+ // | /
+ // |/
+ // *
+ // face 1: right plane
+ // *
+ // /|
+ // / |
+ // / *
+ // * /|
+ // | 1 |
+ // |/ *
+ // * /
+ // | /
+ // |/
+ // *
+ // face 2: front plane
+ // (note: x,y exchanged)
+ // *---*---*
+ // | 5 |
+ // *-6-*-7-*
+ // | 4 |
+ // *---*---*
+ // face 3: back plane
+ // (note: x,y exchanged)
+ // *---*---*
+ // | 9 |
+ // *10-*-11*
+ // | 8 |
+ // *---*---*
+ // face 4: bottom plane
+ // *---*---*
+ // / / /
+ // / 2 /
+ // / / /
+ // *---*---*
+ // face 5: top plane
+ // *---*---*
+ // / / /
+ // / 3 /
+ // / / /
+ // *---*---*
+ // middle planes
+ // *---*---* *-------*
+ // / / / | |
+ // / 12 / | |
+ // / / / | |
+ // *---*---* *-------*
+
+ // set up a list of line iterators
+ // first. from this, construct
+ // lists of line_indices and
+ // line orientations later on
+ const typename Triangulation<dim,spacedim>::raw_line_iterator
+ lines_xz[13]
+ = {
+ hex->face(0)->child(0)
+ ->line((hex->face(0)->refinement_case() == RefinementCase<2>::cut_x) ? 1 : 3), //0
+ hex->face(1)->child(0)
+ ->line((hex->face(1)->refinement_case() == RefinementCase<2>::cut_x) ? 1 : 3), //1
+ hex->face(4)->child(0)
+ ->line((hex->face(4)->refinement_case() == RefinementCase<2>::cut_x) ? 1 : 3), //2
+ hex->face(5)->child(0)
+ ->line((hex->face(5)->refinement_case() == RefinementCase<2>::cut_x) ? 1 : 3), //3
+
+ hex->face(2)->isotropic_child(GeometryInfo<dim>::standard_to_real_face_vertex(0,f_or[2],f_fl[2],f_ro[2]))
+ ->line(GeometryInfo<dim>::standard_to_real_face_line(3,f_or[2],f_fl[2],f_ro[2])), //4
+ hex->face(2)->isotropic_child(GeometryInfo<dim>::standard_to_real_face_vertex(3,f_or[2],f_fl[2],f_ro[2]))
+ ->line(GeometryInfo<dim>::standard_to_real_face_line(2,f_or[2],f_fl[2],f_ro[2])), //5
+ hex->face(2)->isotropic_child(GeometryInfo<dim>::standard_to_real_face_vertex(0,f_or[2],f_fl[2],f_ro[2]))
+ ->line(GeometryInfo<dim>::standard_to_real_face_line(1,f_or[2],f_fl[2],f_ro[2])), //6
+ hex->face(2)->isotropic_child(GeometryInfo<dim>::standard_to_real_face_vertex(3,f_or[2],f_fl[2],f_ro[2]))
+ ->line(GeometryInfo<dim>::standard_to_real_face_line(0,f_or[2],f_fl[2],f_ro[2])), //7
+
+ hex->face(3)->isotropic_child(GeometryInfo<dim>::standard_to_real_face_vertex(0,f_or[3],f_fl[3],f_ro[3]))
+ ->line(GeometryInfo<dim>::standard_to_real_face_line(3,f_or[3],f_fl[3],f_ro[3])), //8
+ hex->face(3)->isotropic_child(GeometryInfo<dim>::standard_to_real_face_vertex(3,f_or[3],f_fl[3],f_ro[3]))
+ ->line(GeometryInfo<dim>::standard_to_real_face_line(2,f_or[3],f_fl[3],f_ro[3])), //9
+ hex->face(3)->isotropic_child(GeometryInfo<dim>::standard_to_real_face_vertex(0,f_or[3],f_fl[3],f_ro[3]))
+ ->line(GeometryInfo<dim>::standard_to_real_face_line(1,f_or[3],f_fl[3],f_ro[3])), //10
+ hex->face(3)->isotropic_child(GeometryInfo<dim>::standard_to_real_face_vertex(3,f_or[3],f_fl[3],f_ro[3]))
+ ->line(GeometryInfo<dim>::standard_to_real_face_line(0,f_or[3],f_fl[3],f_ro[3])), //11
+
+ new_lines[0] //12
+ };
+
+ lines=&lines_xz[0];
+
+ unsigned int line_indices_xz[13];
+
+ for (unsigned int i=0; i<13; ++i)
+ line_indices_xz[i]=lines[i]->index();
+ line_indices=&line_indices_xz[0];
+
+ // the orientation of lines for the
+ // inner quads is quite tricky. as
+ // these lines are newly created
+ // ones and thus have no parents,
+ // they cannot inherit this
+ // property. set up an array and
+ // fill it with the respective
+ // values
+ bool line_orientation_xz[13];
+
+ // the middle vertices of the
+ // lines of our front face
+ const unsigned int middle_vertices[4]=
+ {
+ hex->line(8)->child(0)->vertex_index(1),
+ hex->line(9)->child(0)->vertex_index(1),
+ hex->line(2)->child(0)->vertex_index(1),
+ hex->line(6)->child(0)->vertex_index(1),
+ };
+
+ // note: for lines 0 to 3 the
+ // orientation of the line
+ // is 'true', if vertex 0 is
+ // on the front
+ for (unsigned int i=0; i<4; ++i)
+ if (lines[i]->vertex_index(0)==middle_vertices[i])
+ line_orientation_xz[i]=true;
+ else
+ {
+ // it must be the other way round then
+ Assert(lines[i]->vertex_index(1)==middle_vertices[i],
+ ExcInternalError());
+ line_orientation_xz[i]=false;
+ }
+
+ // note: for lines 4 to 11
+ // (inner lines of the outer quads)
+ // the following holds: the second
+ // vertex of the even lines in
+ // standard orientation is the
+ // vertex in the middle of the
+ // quad, whereas for odd lines the
+ // first vertex is the same middle
+ // vertex.
+ for (unsigned int i=4; i<12; ++i)
+ if (lines[i]->vertex_index((i+1)%2) ==
+ middle_vertex_index<dim,spacedim>(hex->face(1+i/4)))
+ line_orientation_xz[i]=true;
+ else
+ {
+ // it must be the other way
+ // round then
+ Assert(lines[i]->vertex_index(i%2) ==
+ (middle_vertex_index<dim,spacedim>(hex->face(1+i/4))),
+ ExcInternalError());
+ line_orientation_xz[i]=false;
+ }
+ // for the last line the line
+ // orientation is always true,
+ // since it was just constructed
+ // that way
+
+ line_orientation_xz[12]=true;
+ line_orientation=&line_orientation_xz[0];
+
+ // set up the 4 quads,
+ // numbered as follows
+ // (left quad numbering,
+ // right line numbering
+ // extracted from above),
+ // the drawings denote
+ // middle planes
+ //
+ // * *
+ // /| /|
+ // / | 3 9
+ // y/ * / *
+ // * 3/| * /|
+ // | / |x 5 12|8
+ // |/ * |/ *
+ // * 2/ * /
+ // | / 4 2
+ // |/ |/
+ // * *
+ //
+ // y
+ // *----*----* *-10-*-11-*
+ // / / / / / /
+ // / 0 / 1 / 0 12 1
+ // / / / / / /
+ // *----*----*x *--6-*--7-*
+
+ new_quads[0]->set (internal::Triangulation
+ ::TriaObject<2>(line_indices[0],
+ line_indices[12],
+ line_indices[6],
+ line_indices[10]));
+ new_quads[1]->set (internal::Triangulation
+ ::TriaObject<2>(line_indices[12],
+ line_indices[1],
+ line_indices[7],
+ line_indices[11]));
+ new_quads[2]->set (internal::Triangulation
+ ::TriaObject<2>(line_indices[4],
+ line_indices[8],
+ line_indices[2],
+ line_indices[12]));
+ new_quads[3]->set (internal::Triangulation
+ ::TriaObject<2>(line_indices[5],
+ line_indices[9],
+ line_indices[12],
+ line_indices[3]));
+
+ new_quads[0]->set_line_orientation(0,line_orientation[0]);
+ new_quads[0]->set_line_orientation(2,line_orientation[6]);
+ new_quads[0]->set_line_orientation(3,line_orientation[10]);
+
+ new_quads[1]->set_line_orientation(1,line_orientation[1]);
+ new_quads[1]->set_line_orientation(2,line_orientation[7]);
+ new_quads[1]->set_line_orientation(3,line_orientation[11]);
+
+ new_quads[2]->set_line_orientation(0,line_orientation[4]);
+ new_quads[2]->set_line_orientation(1,line_orientation[8]);
+ new_quads[2]->set_line_orientation(2,line_orientation[2]);
+
+ new_quads[3]->set_line_orientation(0,line_orientation[5]);
+ new_quads[3]->set_line_orientation(1,line_orientation[9]);
+ new_quads[3]->set_line_orientation(3,line_orientation[3]);
+
+ // the quads are
+ // numbered as follows:
+ //
+ // planes in the interior
+ // of the old hex:
+ // *
+ // /|
+ // / | x
+ // /3 * *-------* *----*----*
+ // * /| | | / / /
+ // | / | | | / 0 / 1 /
+ // |/ * | | / / /
+ // * 2/ *-------*y *----*----*x
+ // | /
+ // |/
+ // *
+ //
+ // children of the faces
+ // of the old hex
+ // *---*---* *---*---*
+ // /|13 | 15| / / /|
+ // / | | | /18 / 19/ |
+ // / *---*---* / / / *
+ // * 5/| | | *---*---* 7/|
+ // | / |12 | 14| | 9 | 11| / |
+ // |/4 *---*---* | | |/6 *
+ // * / / / *---*---* /
+ // | /16 / 17/ | | | /
+ // |/ / / | 8 | 10|/
+ // *---*---* *---*---*
+ //
+ // note that we have to
+ // take care of the
+ // orientation of
+ // faces.
+ const unsigned int quad_indices_xz[20]
+ = {
+ new_quads[0]->index(), //0
+ new_quads[1]->index(),
+ new_quads[2]->index(),
+ new_quads[3]->index(),
+
+ hex->face(0)->child_index( child_at_origin[hex->face(0)->refinement_case()-1][f_fl[0]][f_ro[0]]), //4
+ hex->face(0)->child_index(1-child_at_origin[hex->face(0)->refinement_case()-1][f_fl[0]][f_ro[0]]),
+
+ hex->face(1)->child_index( child_at_origin[hex->face(1)->refinement_case()-1][f_fl[1]][f_ro[1]]), //6
+ hex->face(1)->child_index(1-child_at_origin[hex->face(1)->refinement_case()-1][f_fl[1]][f_ro[1]]),
+
+ hex->face(2)->isotropic_child_index(GeometryInfo<dim>::standard_to_real_face_vertex(0,f_or[2],f_fl[2],f_ro[2])), //8
+ hex->face(2)->isotropic_child_index(GeometryInfo<dim>::standard_to_real_face_vertex(1,f_or[2],f_fl[2],f_ro[2])),
+ hex->face(2)->isotropic_child_index(GeometryInfo<dim>::standard_to_real_face_vertex(2,f_or[2],f_fl[2],f_ro[2])),
+ hex->face(2)->isotropic_child_index(GeometryInfo<dim>::standard_to_real_face_vertex(3,f_or[2],f_fl[2],f_ro[2])),
+
+ hex->face(3)->isotropic_child_index(GeometryInfo<dim>::standard_to_real_face_vertex(0,f_or[3],f_fl[3],f_ro[3])), //12
+ hex->face(3)->isotropic_child_index(GeometryInfo<dim>::standard_to_real_face_vertex(1,f_or[3],f_fl[3],f_ro[3])),
+ hex->face(3)->isotropic_child_index(GeometryInfo<dim>::standard_to_real_face_vertex(2,f_or[3],f_fl[3],f_ro[3])),
+ hex->face(3)->isotropic_child_index(GeometryInfo<dim>::standard_to_real_face_vertex(3,f_or[3],f_fl[3],f_ro[3])),
+
+ hex->face(4)->child_index( child_at_origin[hex->face(4)->refinement_case()-1][f_fl[4]][f_ro[4]]), //16
+ hex->face(4)->child_index(1-child_at_origin[hex->face(4)->refinement_case()-1][f_fl[4]][f_ro[4]]),
+
+ hex->face(5)->child_index( child_at_origin[hex->face(5)->refinement_case()-1][f_fl[5]][f_ro[5]]), //18
+ hex->face(5)->child_index(1-child_at_origin[hex->face(5)->refinement_case()-1][f_fl[5]][f_ro[5]])
+ };
+ quad_indices=&quad_indices_xz[0];
+
+ // due to the exchange of x
+ // and y for the front and
+ // back face, we order the
+ // children according to
+ //
+ // *---*---*
+ // | 1 | 3 |
+ // *---*---*
+ // | 0 | 2 |
+ // *---*---*
+ new_hexes[0]->set (internal::Triangulation
+ ::TriaObject<3>(quad_indices[4],
+ quad_indices[2],
+ quad_indices[8],
+ quad_indices[12],
+ quad_indices[16],
+ quad_indices[0]));
+ new_hexes[1]->set (internal::Triangulation
+ ::TriaObject<3>(quad_indices[5],
+ quad_indices[3],
+ quad_indices[9],
+ quad_indices[13],
+ quad_indices[0],
+ quad_indices[18]));
+ new_hexes[2]->set (internal::Triangulation
+ ::TriaObject<3>(quad_indices[2],
+ quad_indices[6],
+ quad_indices[10],
+ quad_indices[14],
+ quad_indices[17],
+ quad_indices[1]));
+ new_hexes[3]->set (internal::Triangulation
+ ::TriaObject<3>(quad_indices[3],
+ quad_indices[7],
+ quad_indices[11],
+ quad_indices[15],
+ quad_indices[1],
+ quad_indices[19]));
+ break;
+ }
+ case RefinementCase<dim>::cut_yz:
+ {
+ //////////////////////////////
+ //
+ // RefinementCase<dim>::cut_yz
+ //
+ // the refined cube will look
+ // like this:
+ //
+ // *---------*
+ // / /|
+ // *---------* |
+ // / /| |
+ // *---------* |/|
+ // | | * |
+ // | |/| *
+ // *---------* |/
+ // | | *
+ // | |/
+ // *---------*
+ //
+
+ // first, create the new
+ // internal line
+ new_lines[0]->set (internal::Triangulation::
+ TriaObject<1>(middle_vertex_index<dim,spacedim>(hex->face(0)),
+ middle_vertex_index<dim,spacedim>(hex->face(1))));
+
+ // again, first
+ // collect some data
+ // about the indices of
+ // the lines, with the
+ // following numbering:
+ // (note that face 0 and
+ // 1 each are shown twice
+ // for better
+ // readability)
+
+ // face 0: left plane
+ // * *
+ // /| /|
+ // * | * |
+ // /| * /| *
+ // * 5/| * |7|
+ // | * | | * |
+ // |/| * |6| *
+ // * 4/ * |/
+ // | * | *
+ // |/ |/
+ // * *
+ // face 1: right plane
+ // * *
+ // /| /|
+ // * | * |
+ // /| * /| *
+ // * 9/| * |11
+ // | * | | * |
+ // |/| * |10 *
+ // * 8/ * |/
+ // | * | *
+ // |/ |/
+ // * *
+ // face 2: front plane
+ // (note: x,y exchanged)
+ // *-------*
+ // | |
+ // *---0---*
+ // | |
+ // *-------*
+ // face 3: back plane
+ // (note: x,y exchanged)
+ // *-------*
+ // | |
+ // *---1---*
+ // | |
+ // *-------*
+ // face 4: bottom plane
+ // *-------*
+ // / /
+ // *---2---*
+ // / /
+ // *-------*
+ // face 5: top plane
+ // *-------*
+ // / /
+ // *---3---*
+ // / /
+ // *-------*
+ // middle planes
+ // *-------* *-------*
+ // / / | |
+ // *---12--* | |
+ // / / | |
+ // *-------* *-------*
+
+ // set up a list of line iterators
+ // first. from this, construct
+ // lists of line_indices and
+ // line orientations later on
+ const typename Triangulation<dim,spacedim>::raw_line_iterator
+ lines_yz[13]
+ = {
+ hex->face(2)->child(0)
+ ->line((hex->face(2)->refinement_case() == RefinementCase<2>::cut_x) ? 1 : 3), //0
+ hex->face(3)->child(0)
+ ->line((hex->face(3)->refinement_case() == RefinementCase<2>::cut_x) ? 1 : 3), //1
+ hex->face(4)->child(0)
+ ->line((hex->face(4)->refinement_case() == RefinementCase<2>::cut_x) ? 1 : 3), //2
+ hex->face(5)->child(0)
+ ->line((hex->face(5)->refinement_case() == RefinementCase<2>::cut_x) ? 1 : 3), //3
+
+ hex->face(0)->isotropic_child(GeometryInfo<dim>::standard_to_real_face_vertex(0,f_or[0],f_fl[0],f_ro[0]))
+ ->line(GeometryInfo<dim>::standard_to_real_face_line(1,f_or[0],f_fl[0],f_ro[0])), //4
+ hex->face(0)->isotropic_child(GeometryInfo<dim>::standard_to_real_face_vertex(3,f_or[0],f_fl[0],f_ro[0]))
+ ->line(GeometryInfo<dim>::standard_to_real_face_line(0,f_or[0],f_fl[0],f_ro[0])), //5
+ hex->face(0)->isotropic_child(GeometryInfo<dim>::standard_to_real_face_vertex(0,f_or[0],f_fl[0],f_ro[0]))
+ ->line(GeometryInfo<dim>::standard_to_real_face_line(3,f_or[0],f_fl[0],f_ro[0])), //6
+ hex->face(0)->isotropic_child(GeometryInfo<dim>::standard_to_real_face_vertex(3,f_or[0],f_fl[0],f_ro[0]))
+ ->line(GeometryInfo<dim>::standard_to_real_face_line(2,f_or[0],f_fl[0],f_ro[0])), //7
+
+ hex->face(1)->isotropic_child(GeometryInfo<dim>::standard_to_real_face_vertex(0,f_or[1],f_fl[1],f_ro[1]))
+ ->line(GeometryInfo<dim>::standard_to_real_face_line(1,f_or[1],f_fl[1],f_ro[1])), //8
+ hex->face(1)->isotropic_child(GeometryInfo<dim>::standard_to_real_face_vertex(3,f_or[1],f_fl[1],f_ro[1]))
+ ->line(GeometryInfo<dim>::standard_to_real_face_line(0,f_or[1],f_fl[1],f_ro[1])), //9
+ hex->face(1)->isotropic_child(GeometryInfo<dim>::standard_to_real_face_vertex(0,f_or[1],f_fl[1],f_ro[1]))
+ ->line(GeometryInfo<dim>::standard_to_real_face_line(3,f_or[1],f_fl[1],f_ro[1])), //10
+ hex->face(1)->isotropic_child(GeometryInfo<dim>::standard_to_real_face_vertex(3,f_or[1],f_fl[1],f_ro[1]))
+ ->line(GeometryInfo<dim>::standard_to_real_face_line(2,f_or[1],f_fl[1],f_ro[1])), //11
+
+ new_lines[0] //12
+ };
+
+ lines=&lines_yz[0];
+
+ unsigned int line_indices_yz[13];
+
+ for (unsigned int i=0; i<13; ++i)
+ line_indices_yz[i]=lines[i]->index();
+ line_indices=&line_indices_yz[0];
+
+ // the orientation of lines for the
+ // inner quads is quite tricky. as
+ // these lines are newly created
+ // ones and thus have no parents,
+ // they cannot inherit this
+ // property. set up an array and
+ // fill it with the respective
+ // values
+ bool line_orientation_yz[13];
+
+ // the middle vertices of the
+ // lines of our front face
+ const unsigned int middle_vertices[4]=
+ {
+ hex->line(8)->child(0)->vertex_index(1),
+ hex->line(10)->child(0)->vertex_index(1),
+ hex->line(0)->child(0)->vertex_index(1),
+ hex->line(4)->child(0)->vertex_index(1),
+ };
+
+ // note: for lines 0 to 3 the
+ // orientation of the line
+ // is 'true', if vertex 0 is
+ // on the front
+ for (unsigned int i=0; i<4; ++i)
+ if (lines[i]->vertex_index(0)==middle_vertices[i])
+ line_orientation_yz[i]=true;
+ else
+ {
+ // it must be the other way round then
+ Assert(lines[i]->vertex_index(1)==middle_vertices[i],
+ ExcInternalError());
+ line_orientation_yz[i]=false;
+ }
+
+ // note: for lines 4 to 11
+ // (inner lines of the outer quads)
+ // the following holds: the second
+ // vertex of the even lines in
+ // standard orientation is the
+ // vertex in the middle of the
+ // quad, whereas for odd lines the
+ // first vertex is the same middle
+ // vertex.
+ for (unsigned int i=4; i<12; ++i)
+ if (lines[i]->vertex_index((i+1)%2) ==
+ middle_vertex_index<dim,spacedim>(hex->face(i/4-1)))
+ line_orientation_yz[i]=true;
+ else
+ {
+ // it must be the other way
+ // round then
+ Assert(lines[i]->vertex_index(i%2) ==
+ (middle_vertex_index<dim,spacedim>(hex->face(i/4-1))),
+ ExcInternalError());
+ line_orientation_yz[i]=false;
+ }
+ // for the last line the line
+ // orientation is always true,
+ // since it was just constructed
+ // that way
+
+ line_orientation_yz[12]=true;
+ line_orientation=&line_orientation_yz[0];
+
+ // set up the 4 quads,
+ // numbered as follows (left
+ // quad numbering, right line
+ // numbering extracted from
+ // above)
+ //
+ // x
+ // *-------* *---3---*
+ // | 3 | 5 9
+ // *-------* *---12--*
+ // | 2 | 4 8
+ // *-------*y *---2---*
+ //
+ // y
+ // *---------* *----1----*
+ // / 1 / 7 11
+ // *---------* *----12---*
+ // / 0 / 6 10
+ // *---------*x *----0----*
+
+ new_quads[0]->set (internal::Triangulation
+ ::TriaObject<2>(line_indices[6],
+ line_indices[10],
+ line_indices[0],
+ line_indices[12]));
+ new_quads[1]->set (internal::Triangulation
+ ::TriaObject<2>(line_indices[7],
+ line_indices[11],
+ line_indices[12],
+ line_indices[1]));
+ new_quads[2]->set (internal::Triangulation
+ ::TriaObject<2>(line_indices[2],
+ line_indices[12],
+ line_indices[4],
+ line_indices[8]));
+ new_quads[3]->set (internal::Triangulation
+ ::TriaObject<2>(line_indices[12],
+ line_indices[3],
+ line_indices[5],
+ line_indices[9]));
+
+ new_quads[0]->set_line_orientation(0,line_orientation[6]);
+ new_quads[0]->set_line_orientation(1,line_orientation[10]);
+ new_quads[0]->set_line_orientation(2,line_orientation[0]);
+
+ new_quads[1]->set_line_orientation(0,line_orientation[7]);
+ new_quads[1]->set_line_orientation(1,line_orientation[11]);
+ new_quads[1]->set_line_orientation(3,line_orientation[1]);
+
+ new_quads[2]->set_line_orientation(0,line_orientation[2]);
+ new_quads[2]->set_line_orientation(2,line_orientation[4]);
+ new_quads[2]->set_line_orientation(3,line_orientation[8]);
+
+ new_quads[3]->set_line_orientation(1,line_orientation[3]);
+ new_quads[3]->set_line_orientation(2,line_orientation[5]);
+ new_quads[3]->set_line_orientation(3,line_orientation[9]);
+
+ // the quads are
+ // numbered as follows:
+ //
+ // planes in the interior
+ // of the old hex:
+ // *
+ // /|
+ // / | x
+ // / | *-------* *---------*
+ // * | | 3 | / 1 /
+ // | | *-------* *---------*
+ // | * | 2 | / 0 /
+ // | / *-------*y *---------*x
+ // | /
+ // |/
+ // *
+ //
+ // children of the faces
+ // of the old hex
+ // *-------* *-------*
+ // /| | / 19 /|
+ // * | 15 | *-------* |
+ // /|7*-------* / 18 /|11
+ // * |/| | *-------* |/|
+ // |6* | 14 | | 10* |
+ // |/|5*-------* | 13 |/|9*
+ // * |/ 17 / *-------* |/
+ // |4*-------* | |8*
+ // |/ 16 / | 12 |/
+ // *-------* *-------*
+ //
+ // note that we have to
+ // take care of the
+ // orientation of
+ // faces.
+ const unsigned int quad_indices_yz[20]
+ = {
+ new_quads[0]->index(), //0
+ new_quads[1]->index(),
+ new_quads[2]->index(),
+ new_quads[3]->index(),
+
+ hex->face(0)->isotropic_child_index(GeometryInfo<dim>::standard_to_real_face_vertex(0,f_or[0],f_fl[0],f_ro[0])), //4
+ hex->face(0)->isotropic_child_index(GeometryInfo<dim>::standard_to_real_face_vertex(1,f_or[0],f_fl[0],f_ro[0])),
+ hex->face(0)->isotropic_child_index(GeometryInfo<dim>::standard_to_real_face_vertex(2,f_or[0],f_fl[0],f_ro[0])),
+ hex->face(0)->isotropic_child_index(GeometryInfo<dim>::standard_to_real_face_vertex(3,f_or[0],f_fl[0],f_ro[0])),
+
+ hex->face(1)->isotropic_child_index(GeometryInfo<dim>::standard_to_real_face_vertex(0,f_or[1],f_fl[1],f_ro[1])), //8
+ hex->face(1)->isotropic_child_index(GeometryInfo<dim>::standard_to_real_face_vertex(1,f_or[1],f_fl[1],f_ro[1])),
+ hex->face(1)->isotropic_child_index(GeometryInfo<dim>::standard_to_real_face_vertex(2,f_or[1],f_fl[1],f_ro[1])),
+ hex->face(1)->isotropic_child_index(GeometryInfo<dim>::standard_to_real_face_vertex(3,f_or[1],f_fl[1],f_ro[1])),
+
+ hex->face(2)->child_index( child_at_origin[hex->face(2)->refinement_case()-1][f_fl[2]][f_ro[2]]), //12
+ hex->face(2)->child_index(1-child_at_origin[hex->face(2)->refinement_case()-1][f_fl[2]][f_ro[2]]),
+
+ hex->face(3)->child_index( child_at_origin[hex->face(3)->refinement_case()-1][f_fl[3]][f_ro[3]]), //14
+ hex->face(3)->child_index(1-child_at_origin[hex->face(3)->refinement_case()-1][f_fl[3]][f_ro[3]]),
+
+ hex->face(4)->child_index( child_at_origin[hex->face(4)->refinement_case()-1][f_fl[4]][f_ro[4]]), //16
+ hex->face(4)->child_index(1-child_at_origin[hex->face(4)->refinement_case()-1][f_fl[4]][f_ro[4]]),
+
+ hex->face(5)->child_index( child_at_origin[hex->face(5)->refinement_case()-1][f_fl[5]][f_ro[5]]), //18
+ hex->face(5)->child_index(1-child_at_origin[hex->face(5)->refinement_case()-1][f_fl[5]][f_ro[5]])
+ };
+ quad_indices=&quad_indices_yz[0];
+
+ new_hexes[0]->set (internal::Triangulation
+ ::TriaObject<3>(quad_indices[4],
+ quad_indices[8],
+ quad_indices[12],
+ quad_indices[2],
+ quad_indices[16],
+ quad_indices[0]));
+ new_hexes[1]->set (internal::Triangulation
+ ::TriaObject<3>(quad_indices[5],
+ quad_indices[9],
+ quad_indices[2],
+ quad_indices[14],
+ quad_indices[17],
+ quad_indices[1]));
+ new_hexes[2]->set (internal::Triangulation
+ ::TriaObject<3>(quad_indices[6],
+ quad_indices[10],
+ quad_indices[13],
+ quad_indices[3],
+ quad_indices[0],
+ quad_indices[18]));
+ new_hexes[3]->set (internal::Triangulation
+ ::TriaObject<3>(quad_indices[7],
+ quad_indices[11],
+ quad_indices[3],
+ quad_indices[15],
+ quad_indices[1],
+ quad_indices[19]));
+ break;
+ }
+ case RefinementCase<dim>::cut_xyz:
+ {
+ //////////////////////////////
+ //
+ // RefinementCase<dim>::cut_xyz
+ // isotropic refinement
+ //
+ // the refined cube will look
+ // like this:
+ //
+ // *----*----*
+ // / / /|
+ // *----*----* |
+ // / / /| *
+ // *----*----* |/|
+ // | | | * |
+ // | | |/| *
+ // *----*----* |/
+ // | | | *
+ // | | |/
+ // *----*----*
+ //
+
+ // find the next unused
+ // vertex and set it
+ // appropriately
+ while (triangulation.vertices_used[next_unused_vertex] == true)
+ ++next_unused_vertex;
+ Assert (next_unused_vertex < triangulation.vertices.size(),
+ ExcTooFewVerticesAllocated());
+ triangulation.vertices_used[next_unused_vertex] = true;
+
+ // the new vertex is
+ // definitely in the
+ // interior, so we need not
+ // worry about the boundary.
+ // let it be the average of
+ // the 26 vertices
+ // surrounding it. weight
+ // these vertices in the same
+ // way as they are weighted
+ // in the
+ // @p{MappingQ::set_laplace_on_hex_vector}
+ // function, and like the new
+ // vertex at the center of
+ // the quad is weighted (see
+ // above)
+ triangulation.vertices[next_unused_vertex] = Point<dim>();
+ // first add corners of hex
+ for (unsigned int vertex=0;
+ vertex<GeometryInfo<dim>::vertices_per_cell; ++vertex)
+ triangulation.vertices[next_unused_vertex] += hex->vertex(vertex) / 128;
+ // now add center of lines
+ for (unsigned int line=0;
+ line<GeometryInfo<dim>::lines_per_cell; ++line)
+ triangulation.vertices[next_unused_vertex] += hex->line(line)->child(0)->vertex(1) *
+ 7./192.;
+ // finally add centers of
+ // faces. note that vertex 3
+ // of child 0 is an invariant
+ // with respect to the face
+ // orientation, flip and
+ // rotation
+ for (unsigned int face=0;
+ face<GeometryInfo<dim>::faces_per_cell; ++face)
+ triangulation.vertices[next_unused_vertex] += hex->face(face)->isotropic_child(0)->vertex(3) *
+ 1./12.;
+
+ // set the data of the
+ // six lines. first
+ // collect the indices of
+ // the seven vertices
+ // (consider the two
+ // planes to be crossed
+ // to form the planes
+ // cutting the hex in two
+ // vertically and
+ // horizontally)
+ // *--3--* *--5--*
+ // / / / | | |
+ // 0--6--1 0--6--1
+ // / / / | | |
+ // *--2--* *--4--*
+ // the lines are numbered
+ // as follows:
+ // *--*--* *--*--*
+ // / 1 / | 5 |
+ // *2-*-3* *2-*-3*
+ // / 0 / | 4 |
+ // *--*--* *--*--*
+ //
+ const unsigned int vertex_indices_xyz[7]
+ = { middle_vertex_index<dim,spacedim>(hex->face(0)),
+ middle_vertex_index<dim,spacedim>(hex->face(1)),
+ middle_vertex_index<dim,spacedim>(hex->face(2)),
+ middle_vertex_index<dim,spacedim>(hex->face(3)),
+ middle_vertex_index<dim,spacedim>(hex->face(4)),
+ middle_vertex_index<dim,spacedim>(hex->face(5)),
+ next_unused_vertex
+ };
+ vertex_indices=&vertex_indices_xyz[0];
+
+ new_lines[0]->set (internal::Triangulation::
+ TriaObject<1>(vertex_indices[2], vertex_indices[6]));
+ new_lines[1]->set (internal::Triangulation::
+ TriaObject<1>(vertex_indices[6], vertex_indices[3]));
+ new_lines[2]->set (internal::Triangulation::
+ TriaObject<1>(vertex_indices[0], vertex_indices[6]));
+ new_lines[3]->set (internal::Triangulation::
+ TriaObject<1>(vertex_indices[6], vertex_indices[1]));
+ new_lines[4]->set (internal::Triangulation::
+ TriaObject<1>(vertex_indices[4], vertex_indices[6]));
+ new_lines[5]->set (internal::Triangulation::
+ TriaObject<1>(vertex_indices[6], vertex_indices[5]));
+
+ // again, first
+ // collect some data
+ // about the indices of
+ // the lines, with the
+ // following numbering:
+ // (note that face 0 and
+ // 1 each are shown twice
+ // for better
+ // readability)
+
+ // face 0: left plane
+ // * *
+ // /| /|
+ // * | * |
+ // /| * /| *
+ // * 1/| * |3|
+ // | * | | * |
+ // |/| * |2| *
+ // * 0/ * |/
+ // | * | *
+ // |/ |/
+ // * *
+ // face 1: right plane
+ // * *
+ // /| /|
+ // * | * |
+ // /| * /| *
+ // * 5/| * |7|
+ // | * | | * |
+ // |/| * |6| *
+ // * 4/ * |/
+ // | * | *
+ // |/ |/
+ // * *
+ // face 2: front plane
+ // (note: x,y exchanged)
+ // *---*---*
+ // | 11 |
+ // *-8-*-9-*
+ // | 10 |
+ // *---*---*
+ // face 3: back plane
+ // (note: x,y exchanged)
+ // *---*---*
+ // | 15 |
+ // *12-*-13*
+ // | 14 |
+ // *---*---*
+ // face 4: bottom plane
+ // *---*---*
+ // / 17 /
+ // *18-*-19*
+ // / 16 /
+ // *---*---*
+ // face 5: top plane
+ // *---*---*
+ // / 21 /
+ // *22-*-23*
+ // / 20 /
+ // *---*---*
+ // middle planes
+ // *---*---* *---*---*
+ // / 25 / | 29 |
+ // *26-*-27* *26-*-27*
+ // / 24 / | 28 |
+ // *---*---* *---*---*
+
+ // set up a list of line iterators
+ // first. from this, construct
+ // lists of line_indices and
+ // line orientations later on
+ const typename Triangulation<dim,spacedim>::raw_line_iterator
+ lines_xyz[30]
+ = {
+ hex->face(0)->isotropic_child(GeometryInfo<dim>::standard_to_real_face_vertex(0,f_or[0],f_fl[0],f_ro[0]))
+ ->line(GeometryInfo<dim>::standard_to_real_face_line(1,f_or[0],f_fl[0],f_ro[0])), //0
+ hex->face(0)->isotropic_child(GeometryInfo<dim>::standard_to_real_face_vertex(3,f_or[0],f_fl[0],f_ro[0]))
+ ->line(GeometryInfo<dim>::standard_to_real_face_line(0,f_or[0],f_fl[0],f_ro[0])), //1
+ hex->face(0)->isotropic_child(GeometryInfo<dim>::standard_to_real_face_vertex(0,f_or[0],f_fl[0],f_ro[0]))
+ ->line(GeometryInfo<dim>::standard_to_real_face_line(3,f_or[0],f_fl[0],f_ro[0])), //2
+ hex->face(0)->isotropic_child(GeometryInfo<dim>::standard_to_real_face_vertex(3,f_or[0],f_fl[0],f_ro[0]))
+ ->line(GeometryInfo<dim>::standard_to_real_face_line(2,f_or[0],f_fl[0],f_ro[0])), //3
+
+ hex->face(1)->isotropic_child(GeometryInfo<dim>::standard_to_real_face_vertex(0,f_or[1],f_fl[1],f_ro[1]))
+ ->line(GeometryInfo<dim>::standard_to_real_face_line(1,f_or[1],f_fl[1],f_ro[1])), //4
+ hex->face(1)->isotropic_child(GeometryInfo<dim>::standard_to_real_face_vertex(3,f_or[1],f_fl[1],f_ro[1]))
+ ->line(GeometryInfo<dim>::standard_to_real_face_line(0,f_or[1],f_fl[1],f_ro[1])), //5
+ hex->face(1)->isotropic_child(GeometryInfo<dim>::standard_to_real_face_vertex(0,f_or[1],f_fl[1],f_ro[1]))
+ ->line(GeometryInfo<dim>::standard_to_real_face_line(3,f_or[1],f_fl[1],f_ro[1])), //6
+ hex->face(1)->isotropic_child(GeometryInfo<dim>::standard_to_real_face_vertex(3,f_or[1],f_fl[1],f_ro[1]))
+ ->line(GeometryInfo<dim>::standard_to_real_face_line(2,f_or[1],f_fl[1],f_ro[1])), //7
+
+ hex->face(2)->isotropic_child(GeometryInfo<dim>::standard_to_real_face_vertex(0,f_or[2],f_fl[2],f_ro[2]))
+ ->line(GeometryInfo<dim>::standard_to_real_face_line(1,f_or[2],f_fl[2],f_ro[2])), //8
+ hex->face(2)->isotropic_child(GeometryInfo<dim>::standard_to_real_face_vertex(3,f_or[2],f_fl[2],f_ro[2]))
+ ->line(GeometryInfo<dim>::standard_to_real_face_line(0,f_or[2],f_fl[2],f_ro[2])), //9
+ hex->face(2)->isotropic_child(GeometryInfo<dim>::standard_to_real_face_vertex(0,f_or[2],f_fl[2],f_ro[2]))
+ ->line(GeometryInfo<dim>::standard_to_real_face_line(3,f_or[2],f_fl[2],f_ro[2])), //10
+ hex->face(2)->isotropic_child(GeometryInfo<dim>::standard_to_real_face_vertex(3,f_or[2],f_fl[2],f_ro[2]))
+ ->line(GeometryInfo<dim>::standard_to_real_face_line(2,f_or[2],f_fl[2],f_ro[2])), //11
+
+ hex->face(3)->isotropic_child(GeometryInfo<dim>::standard_to_real_face_vertex(0,f_or[3],f_fl[3],f_ro[3]))
+ ->line(GeometryInfo<dim>::standard_to_real_face_line(1,f_or[3],f_fl[3],f_ro[3])), //12
+ hex->face(3)->isotropic_child(GeometryInfo<dim>::standard_to_real_face_vertex(3,f_or[3],f_fl[3],f_ro[3]))
+ ->line(GeometryInfo<dim>::standard_to_real_face_line(0,f_or[3],f_fl[3],f_ro[3])), //13
+ hex->face(3)->isotropic_child(GeometryInfo<dim>::standard_to_real_face_vertex(0,f_or[3],f_fl[3],f_ro[3]))
+ ->line(GeometryInfo<dim>::standard_to_real_face_line(3,f_or[3],f_fl[3],f_ro[3])), //14
+ hex->face(3)->isotropic_child(GeometryInfo<dim>::standard_to_real_face_vertex(3,f_or[3],f_fl[3],f_ro[3]))
+ ->line(GeometryInfo<dim>::standard_to_real_face_line(2,f_or[3],f_fl[3],f_ro[3])), //15
+
+ hex->face(4)->isotropic_child(GeometryInfo<dim>::standard_to_real_face_vertex(0,f_or[4],f_fl[4],f_ro[4]))
+ ->line(GeometryInfo<dim>::standard_to_real_face_line(1,f_or[4],f_fl[4],f_ro[4])), //16
+ hex->face(4)->isotropic_child(GeometryInfo<dim>::standard_to_real_face_vertex(3,f_or[4],f_fl[4],f_ro[4]))
+ ->line(GeometryInfo<dim>::standard_to_real_face_line(0,f_or[4],f_fl[4],f_ro[4])), //17
+ hex->face(4)->isotropic_child(GeometryInfo<dim>::standard_to_real_face_vertex(0,f_or[4],f_fl[4],f_ro[4]))
+ ->line(GeometryInfo<dim>::standard_to_real_face_line(3,f_or[4],f_fl[4],f_ro[4])), //18
+ hex->face(4)->isotropic_child(GeometryInfo<dim>::standard_to_real_face_vertex(3,f_or[4],f_fl[4],f_ro[4]))
+ ->line(GeometryInfo<dim>::standard_to_real_face_line(2,f_or[4],f_fl[4],f_ro[4])), //19
+
+ hex->face(5)->isotropic_child(GeometryInfo<dim>::standard_to_real_face_vertex(0,f_or[5],f_fl[5],f_ro[5]))
+ ->line(GeometryInfo<dim>::standard_to_real_face_line(1,f_or[5],f_fl[5],f_ro[5])), //20
+ hex->face(5)->isotropic_child(GeometryInfo<dim>::standard_to_real_face_vertex(3,f_or[5],f_fl[5],f_ro[5]))
+ ->line(GeometryInfo<dim>::standard_to_real_face_line(0,f_or[5],f_fl[5],f_ro[5])), //21
+ hex->face(5)->isotropic_child(GeometryInfo<dim>::standard_to_real_face_vertex(0,f_or[5],f_fl[5],f_ro[5]))
+ ->line(GeometryInfo<dim>::standard_to_real_face_line(3,f_or[5],f_fl[5],f_ro[5])), //22
+ hex->face(5)->isotropic_child(GeometryInfo<dim>::standard_to_real_face_vertex(3,f_or[5],f_fl[5],f_ro[5]))
+ ->line(GeometryInfo<dim>::standard_to_real_face_line(2,f_or[5],f_fl[5],f_ro[5])), //23
+
+ new_lines[0], //24
+ new_lines[1], //25
+ new_lines[2], //26
+ new_lines[3], //27
+ new_lines[4], //28
+ new_lines[5] //29
+ };
+
+ lines=&lines_xyz[0];
+
+ unsigned int line_indices_xyz[30];
+ for (unsigned int i=0; i<30; ++i)
+ line_indices_xyz[i]=lines[i]->index();
+ line_indices=&line_indices_xyz[0];
+
+ // the orientation of lines for the
+ // inner quads is quite tricky. as
+ // these lines are newly created
+ // ones and thus have no parents,
+ // they cannot inherit this
+ // property. set up an array and
+ // fill it with the respective
+ // values
+ bool line_orientation_xyz[30];
+
+ // note: for the first 24 lines
+ // (inner lines of the outer quads)
+ // the following holds: the second
+ // vertex of the even lines in
+ // standard orientation is the
+ // vertex in the middle of the
+ // quad, whereas for odd lines the
+ // first vertex is the same middle
+ // vertex.
+ for (unsigned int i=0; i<24; ++i)
+ if (lines[i]->vertex_index((i+1)%2)==vertex_indices[i/4])
+ line_orientation_xyz[i]=true;
+ else
+ {
+ // it must be the other way
+ // round then
+ Assert(lines[i]->vertex_index(i%2)==vertex_indices[i/4],
+ ExcInternalError());
+ line_orientation_xyz[i]=false;
+ }
+ // for the last 6 lines the line
+ // orientation is always true,
+ // since they were just constructed
+ // that way
+ for (unsigned int i=24; i<30; ++i)
+ line_orientation_xyz[i]=true;
+ line_orientation=&line_orientation_xyz[0];
+
+ // set up the 12 quads,
+ // numbered as follows
+ // (left quad numbering,
+ // right line numbering
+ // extracted from above)
+ //
+ // * *
+ // /| 21|
+ // * | * 15
+ // y/|3* 20| *
+ // * |/| * |/|
+ // |2* |x 11 * 14
+ // |/|1* |/| *
+ // * |/ * |17
+ // |0* 10 *
+ // |/ |16
+ // * *
+ //
+ // x
+ // *---*---* *22-*-23*
+ // | 5 | 7 | 1 29 5
+ // *---*---* *26-*-27*
+ // | 4 | 6 | 0 28 4
+ // *---*---*y *18-*-19*
+ //
+ // y
+ // *----*----* *-12-*-13-*
+ // / 10 / 11 / 3 25 7
+ // *----*----* *-26-*-27-*
+ // / 8 / 9 / 2 24 6
+ // *----*----*x *--8-*--9-*
+
+ new_quads[0]->set (internal::Triangulation
+ ::TriaObject<2>(line_indices[10],
+ line_indices[28],
+ line_indices[16],
+ line_indices[24]));
+ new_quads[1]->set (internal::Triangulation
+ ::TriaObject<2>(line_indices[28],
+ line_indices[14],
+ line_indices[17],
+ line_indices[25]));
+ new_quads[2]->set (internal::Triangulation
+ ::TriaObject<2>(line_indices[11],
+ line_indices[29],
+ line_indices[24],
+ line_indices[20]));
+ new_quads[3]->set (internal::Triangulation
+ ::TriaObject<2>(line_indices[29],
+ line_indices[15],
+ line_indices[25],
+ line_indices[21]));
+ new_quads[4]->set (internal::Triangulation
+ ::TriaObject<2>(line_indices[18],
+ line_indices[26],
+ line_indices[0],
+ line_indices[28]));
+ new_quads[5]->set (internal::Triangulation
+ ::TriaObject<2>(line_indices[26],
+ line_indices[22],
+ line_indices[1],
+ line_indices[29]));
+ new_quads[6]->set (internal::Triangulation
+ ::TriaObject<2>(line_indices[19],
+ line_indices[27],
+ line_indices[28],
+ line_indices[4]));
+ new_quads[7]->set (internal::Triangulation
+ ::TriaObject<2>(line_indices[27],
+ line_indices[23],
+ line_indices[29],
+ line_indices[5]));
+ new_quads[8]->set (internal::Triangulation
+ ::TriaObject<2>(line_indices[2],
+ line_indices[24],
+ line_indices[8],
+ line_indices[26]));
+ new_quads[9]->set (internal::Triangulation
+ ::TriaObject<2>(line_indices[24],
+ line_indices[6],
+ line_indices[9],
+ line_indices[27]));
+ new_quads[10]->set (internal::Triangulation
+ ::TriaObject<2>(line_indices[3],
+ line_indices[25],
+ line_indices[26],
+ line_indices[12]));
+ new_quads[11]->set (internal::Triangulation
+ ::TriaObject<2>(line_indices[25],
+ line_indices[7],
+ line_indices[27],
+ line_indices[13]));
+
+ // now reset the line_orientation
+ // flags of outer lines as they
+ // cannot be set in a loop (at
+ // least not easily)
+ new_quads[0]->set_line_orientation(0,line_orientation[10]);
+ new_quads[0]->set_line_orientation(2,line_orientation[16]);
+
+ new_quads[1]->set_line_orientation(1,line_orientation[14]);
+ new_quads[1]->set_line_orientation(2,line_orientation[17]);
+
+ new_quads[2]->set_line_orientation(0,line_orientation[11]);
+ new_quads[2]->set_line_orientation(3,line_orientation[20]);
+
+ new_quads[3]->set_line_orientation(1,line_orientation[15]);
+ new_quads[3]->set_line_orientation(3,line_orientation[21]);
+
+ new_quads[4]->set_line_orientation(0,line_orientation[18]);
+ new_quads[4]->set_line_orientation(2,line_orientation[0]);
+
+ new_quads[5]->set_line_orientation(1,line_orientation[22]);
+ new_quads[5]->set_line_orientation(2,line_orientation[1]);
+
+ new_quads[6]->set_line_orientation(0,line_orientation[19]);
+ new_quads[6]->set_line_orientation(3,line_orientation[4]);
+
+ new_quads[7]->set_line_orientation(1,line_orientation[23]);
+ new_quads[7]->set_line_orientation(3,line_orientation[5]);
+
+ new_quads[8]->set_line_orientation(0,line_orientation[2]);
+ new_quads[8]->set_line_orientation(2,line_orientation[8]);
+
+ new_quads[9]->set_line_orientation(1,line_orientation[6]);
+ new_quads[9]->set_line_orientation(2,line_orientation[9]);
+
+ new_quads[10]->set_line_orientation(0,line_orientation[3]);
+ new_quads[10]->set_line_orientation(3,line_orientation[12]);
+
+ new_quads[11]->set_line_orientation(1,line_orientation[7]);
+ new_quads[11]->set_line_orientation(3,line_orientation[13]);
+
+ /////////////////////////////////
+ // create the eight new hexes
+ //
+ // again first collect
+ // some data. here, we
+ // need the indices of a
+ // whole lotta
+ // quads.
+
+ // the quads are
+ // numbered as follows:
+ //
+ // planes in the interior
+ // of the old hex:
+ // *
+ // /|
+ // * |
+ // /|3* *---*---* *----*----*
+ // * |/| | 5 | 7 | / 10 / 11 /
+ // |2* | *---*---* *----*----*
+ // |/|1* | 4 | 6 | / 8 / 9 /
+ // * |/ *---*---*y *----*----*x
+ // |0*
+ // |/
+ // *
+ //
+ // children of the faces
+ // of the old hex
+ // *-------* *-------*
+ // /|25 27| /34 35/|
+ // 15| | / /19
+ // / | | /32 33/ |
+ // * |24 26| *-------*18 |
+ // 1413*-------* |21 23| 17*
+ // | /30 31/ | | /
+ // 12/ / | |16
+ // |/28 29/ |20 22|/
+ // *-------* *-------*
+ //
+ // note that we have to
+ // take care of the
+ // orientation of
+ // faces.
+ const unsigned int quad_indices_xyz[36]
+ = {
+ new_quads[0]->index(), //0
+ new_quads[1]->index(),
+ new_quads[2]->index(),
+ new_quads[3]->index(),
+ new_quads[4]->index(),
+ new_quads[5]->index(),
+ new_quads[6]->index(),
+ new_quads[7]->index(),
+ new_quads[8]->index(),
+ new_quads[9]->index(),
+ new_quads[10]->index(),
+ new_quads[11]->index(), //11
+
+ hex->face(0)->isotropic_child_index(GeometryInfo<dim>::standard_to_real_face_vertex(0,f_or[0],f_fl[0],f_ro[0])), //12
+ hex->face(0)->isotropic_child_index(GeometryInfo<dim>::standard_to_real_face_vertex(1,f_or[0],f_fl[0],f_ro[0])),
+ hex->face(0)->isotropic_child_index(GeometryInfo<dim>::standard_to_real_face_vertex(2,f_or[0],f_fl[0],f_ro[0])),
+ hex->face(0)->isotropic_child_index(GeometryInfo<dim>::standard_to_real_face_vertex(3,f_or[0],f_fl[0],f_ro[0])),
+
+ hex->face(1)->isotropic_child_index(GeometryInfo<dim>::standard_to_real_face_vertex(0,f_or[1],f_fl[1],f_ro[1])), //16
+ hex->face(1)->isotropic_child_index(GeometryInfo<dim>::standard_to_real_face_vertex(1,f_or[1],f_fl[1],f_ro[1])),
+ hex->face(1)->isotropic_child_index(GeometryInfo<dim>::standard_to_real_face_vertex(2,f_or[1],f_fl[1],f_ro[1])),
+ hex->face(1)->isotropic_child_index(GeometryInfo<dim>::standard_to_real_face_vertex(3,f_or[1],f_fl[1],f_ro[1])),
+
+ hex->face(2)->isotropic_child_index(GeometryInfo<dim>::standard_to_real_face_vertex(0,f_or[2],f_fl[2],f_ro[2])), //20
+ hex->face(2)->isotropic_child_index(GeometryInfo<dim>::standard_to_real_face_vertex(1,f_or[2],f_fl[2],f_ro[2])),
+ hex->face(2)->isotropic_child_index(GeometryInfo<dim>::standard_to_real_face_vertex(2,f_or[2],f_fl[2],f_ro[2])),
+ hex->face(2)->isotropic_child_index(GeometryInfo<dim>::standard_to_real_face_vertex(3,f_or[2],f_fl[2],f_ro[2])),
+
+ hex->face(3)->isotropic_child_index(GeometryInfo<dim>::standard_to_real_face_vertex(0,f_or[3],f_fl[3],f_ro[3])), //24
+ hex->face(3)->isotropic_child_index(GeometryInfo<dim>::standard_to_real_face_vertex(1,f_or[3],f_fl[3],f_ro[3])),
+ hex->face(3)->isotropic_child_index(GeometryInfo<dim>::standard_to_real_face_vertex(2,f_or[3],f_fl[3],f_ro[3])),
+ hex->face(3)->isotropic_child_index(GeometryInfo<dim>::standard_to_real_face_vertex(3,f_or[3],f_fl[3],f_ro[3])),
+
+ hex->face(4)->isotropic_child_index(GeometryInfo<dim>::standard_to_real_face_vertex(0,f_or[4],f_fl[4],f_ro[4])), //28
+ hex->face(4)->isotropic_child_index(GeometryInfo<dim>::standard_to_real_face_vertex(1,f_or[4],f_fl[4],f_ro[4])),
+ hex->face(4)->isotropic_child_index(GeometryInfo<dim>::standard_to_real_face_vertex(2,f_or[4],f_fl[4],f_ro[4])),
+ hex->face(4)->isotropic_child_index(GeometryInfo<dim>::standard_to_real_face_vertex(3,f_or[4],f_fl[4],f_ro[4])),
+
+ hex->face(5)->isotropic_child_index(GeometryInfo<dim>::standard_to_real_face_vertex(0,f_or[5],f_fl[5],f_ro[5])), //32
+ hex->face(5)->isotropic_child_index(GeometryInfo<dim>::standard_to_real_face_vertex(1,f_or[5],f_fl[5],f_ro[5])),
+ hex->face(5)->isotropic_child_index(GeometryInfo<dim>::standard_to_real_face_vertex(2,f_or[5],f_fl[5],f_ro[5])),
+ hex->face(5)->isotropic_child_index(GeometryInfo<dim>::standard_to_real_face_vertex(3,f_or[5],f_fl[5],f_ro[5]))
+ };
+ quad_indices=&quad_indices_xyz[0];
+
+ // bottom children
+ new_hexes[0]->set (internal::Triangulation
+ ::TriaObject<3>(quad_indices[12],
+ quad_indices[0],
+ quad_indices[20],
+ quad_indices[4],
+ quad_indices[28],
+ quad_indices[8]));
+ new_hexes[1]->set (internal::Triangulation
+ ::TriaObject<3>(quad_indices[0],
+ quad_indices[16],
+ quad_indices[22],
+ quad_indices[6],
+ quad_indices[29],
+ quad_indices[9]));
+ new_hexes[2]->set (internal::Triangulation
+ ::TriaObject<3>(quad_indices[13],
+ quad_indices[1],
+ quad_indices[4],
+ quad_indices[24],
+ quad_indices[30],
+ quad_indices[10]));
+ new_hexes[3]->set (internal::Triangulation
+ ::TriaObject<3>(quad_indices[1],
+ quad_indices[17],
+ quad_indices[6],
+ quad_indices[26],
+ quad_indices[31],
+ quad_indices[11]));
+
+ // top children
+ new_hexes[4]->set (internal::Triangulation
+ ::TriaObject<3>(quad_indices[14],
+ quad_indices[2],
+ quad_indices[21],
+ quad_indices[5],
+ quad_indices[8],
+ quad_indices[32]));
+ new_hexes[5]->set (internal::Triangulation
+ ::TriaObject<3>(quad_indices[2],
+ quad_indices[18],
+ quad_indices[23],
+ quad_indices[7],
+ quad_indices[9],
+ quad_indices[33]));
+ new_hexes[6]->set (internal::Triangulation
+ ::TriaObject<3>(quad_indices[15],
+ quad_indices[3],
+ quad_indices[5],
+ quad_indices[25],
+ quad_indices[10],
+ quad_indices[34]));
+ new_hexes[7]->set (internal::Triangulation
+ ::TriaObject<3>(quad_indices[3],
+ quad_indices[19],
+ quad_indices[7],
+ quad_indices[27],
+ quad_indices[11],
+ quad_indices[35]));
+ break;
+ }
+ default:
+ // all refinement cases
+ // have been treated,
+ // there only remains
+ // RefinementCase<dim>::no_refinement
+ // as untreated
+ // enumeration
+ // value. However, in
+ // that case we should
+ // have aborted much
+ // earlier. thus we
+ // should never get here
+ Assert(false, ExcInternalError());
+ break;
+ }//switch (ref_case)
+
+ // and set face orientation
+ // flags. note that new faces in
+ // the interior of the mother cell
+ // always have a correctly oriented
+ // face, but the ones on the outer
+ // faces will inherit this flag
+ //
+ // the flag have been set to true
+ // for all faces initially, now go
+ // the other way round and reset
+ // faces that are at the boundary
+ // of the mother cube
+ //
+ // the same is true for the
+ // face_flip and face_rotation
+ // flags. however, the latter two
+ // are set to false by default as
+ // this is the standard value
+
+ // loop over all faces and all
+ // (relevant) subfaces of that in
+ // order to set the correct values
+ // for face_orientation, face_flip
+ // and face_rotation, which are
+ // inherited from the corresponding
+ // face of the mother cube
+ for (unsigned int f=0; f<GeometryInfo<dim>::faces_per_cell; ++f)
+ for (unsigned int s=0;
+ s<std::max(GeometryInfo<dim-1>::n_children(GeometryInfo<dim>::face_refinement_case(ref_case,f)),
+ 1U);
+ ++s)
+ {
+ const unsigned int current_child
+ =GeometryInfo<dim>::child_cell_on_face(ref_case,
+ f,
+ s,
+ f_or[f],
+ f_fl[f],
+ f_ro[f],
+ GeometryInfo<dim>::face_refinement_case(ref_case,
+ f,
+ f_or[f],
+ f_fl[f],
+ f_ro[f]));
+ new_hexes[current_child]->set_face_orientation (f, f_or[f]);
+ new_hexes[current_child]->set_face_flip (f, f_fl[f]);
+ new_hexes[current_child]->set_face_rotation (f, f_ro[f]);
+ }
+
+ // now see if
+ // we have
+ // created
+ // cells that
+ // are
+ // distorted
+ // and if so
+ // add them to
+ // our list
+ if ((check_for_distorted_cells == true)
+ &&
+ has_distorted_children (hex,
+ internal::int2type<dim>(),
+ internal::int2type<spacedim>()))
+ cells_with_distorted_children.distorted_cells.push_back (hex);
+
+ // note that the
+ // refinement flag was
+ // already cleared at the
+ // beginning of this loop
+ }
+ }
+
+ // clear user data on quads. we used some of
+ // this data to indicate anisotropic
+ // refinemnt cases on faces. all data should
+ // be cleared by now, but the information
+ // whether we used indices or pointers is
+ // still present. reset it now to enable the
+ // user to use whichever he likes later on.
+ triangulation.faces->quads.clear_user_data();
+
+ // return the list with distorted children
+ return cells_with_distorted_children;
+ }
+
+
+ /**
+ * At the boundary of the domain, the new
+ * point on the face may be far inside the
+ * current cell, if the boundary has a
+ * strong curvature. If we allow anisotropic
+ * refinement here, the resulting cell may
+ * be strongly distorted. To prevent this,
+ * this function flags such cells for
+ * isotropic refinement. It is called
+ * automatically from
+ * prepare_coarsening_and_refinement().
+ *
+ * This function does nothing in
+ * 1d (therefore the
+ * specialization).
+ */
+ template <int spacedim>
+ static
+ void
+ prevent_distorted_boundary_cells (const Triangulation<1,spacedim> &);
+
+ template <int dim, int spacedim>
+ static
+ void
+ prevent_distorted_boundary_cells (Triangulation<dim,spacedim> &triangulation)
+ {
+ for (typename Triangulation<dim,spacedim>::cell_iterator
+ cell=triangulation.begin(); cell!=triangulation.end(); ++cell)
+ if (cell->at_boundary() &&
+ cell->refine_flag_set() &&
+ cell->refine_flag_set()!=RefinementCase<dim>::isotropic_refinement)
+ {
+ // The cell is at the boundary
+ // and it is flagged for
+ // anisotropic
+ // refinement. Therefore, we have
+ // a closer look
+ const RefinementCase<dim> ref_case=cell->refine_flag_set();
+ for (unsigned int face_no=0;
+ face_no<GeometryInfo<dim>::faces_per_cell;
+ ++face_no)
+ if (cell->face(face_no)->at_boundary())
+ {
+ // this is the critical
+ // face at the boundary.
+ if (GeometryInfo<dim>::face_refinement_case(ref_case,face_no)
+ !=RefinementCase<dim-1>::isotropic_refinement)
+ {
+ // up to now, we do not
+ // want to refine this
+ // cell along the face
+ // under consideration
+ // here.
+ const typename Triangulation<dim,spacedim>::face_iterator
+ face = cell->face(face_no);
+ // the new point on the
+ // boundary would be
+ // this one.
+ const Point<spacedim> new_bound
+ = triangulation.boundary[face->boundary_indicator()]
+ ->get_new_point_on_face (face);
+ // to check it,
+ // transform to the
+ // unit cell with
+ // Q1Mapping
+ const Point<dim> new_unit
+ = StaticMappingQ1<dim,spacedim>::mapping.
+ transform_real_to_unit_cell(cell,
+ new_bound);
+
+ // Now, we have to
+ // calculate the
+ // distance from the
+ // face in the unit
+ // cell.
+
+ // take the correct
+ // coordinate direction (0
+ // for faces 0 and 1, 1 for
+ // faces 2 and 3, 2 for faces
+ // 4 and 5) and substract the
+ // correct boundary value of
+ // the face (0 for faces 0,
+ // 2, and 4; 1 for faces 1, 3
+ // and 5)
+ const double dist = std::fabs(new_unit[face_no/2] - face_no%2);
+ // compare this with
+ // the empirical value
+ // allowed. if it is
+ // too big, flag the
+ // face for isotropic
+ // refinement
+ const double allowed=0.25;
+
+ if (dist>allowed)
+ cell->flag_for_face_refinement(face_no);
+ }//if flagged for anistropic refinement
+ }//if (cell->face(face)->at_boundary())
+ }//for all cells
+ }
+
+
+ /**
+ * Some dimension dependent stuff for
+ * mesh smoothing.
+ *
+ * At present, this function does nothing
+ * in 1d and 2D, but makes sure no two
+ * cells with a level difference greater
+ * than one share one line in 3D. This
+ * is a requirement needed for the
+ * interpolation of hanging nodes, since
+ * otherwise to steps of interpolation
+ * would be necessary. This would make
+ * the processes implemented in the
+ * @p ConstraintMatrix class much more
+ * complex, since these two steps of
+ * interpolation do not commute.
+ */
+ template <int dim, int spacedim>
+ static
+ void
+ prepare_refinement_dim_dependent (const Triangulation<dim,spacedim> &)
+ {
+ Assert (dim < 3,
+ ExcMessage ("Wrong function called -- there should "
+ "be a specialization."));
+ }
+
+
+ template <int spacedim>
+ static
+ void
+ prepare_refinement_dim_dependent (Triangulation<3,spacedim> &triangulation)
+ {
+ const unsigned int dim = 3;
+
+ // first clear flags on lines,
+ // since we need them to determine
+ // which lines will be refined
+ triangulation.clear_user_flags_line();
+
+ // also clear flags on hexes, since we need
+ // them to mark those cells which are to be
+ // coarsened
+ triangulation.clear_user_flags_hex();
+
+ // variable to store whether the
+ // mesh was changed in the present
+ // loop and in the whole process
+ bool mesh_changed = false;
+
+ do
+ {
+ 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:
+ triangulation.fix_coarsen_flags ();
+
+
+ // flag those lines that are refined and
+ // will not be coarsened and those that
+ // will be refined
+ for (typename Triangulation<dim,spacedim>::cell_iterator
+ cell=triangulation.begin(); cell!=triangulation.end(); ++cell)
+ if (cell->refine_flag_set())
+ {
+ for (unsigned int line=0; line<GeometryInfo<dim>::lines_per_cell; ++line)
+ if (GeometryInfo<dim>::line_refinement_case(cell->refine_flag_set(), line)
+ ==RefinementCase<1>::cut_x)
+ // flag a line, that will be
+ // refined
+ cell->line(line)->set_user_flag();
+ }
+ else if(cell->has_children() && !cell->child(0)->coarsen_flag_set())
+ {
+ for (unsigned int line=0; line<GeometryInfo<dim>::lines_per_cell; ++line)
+ if (GeometryInfo<dim>::line_refinement_case(cell->refinement_case(), line)
+ ==RefinementCase<1>::cut_x)
+ // flag a line, that is refined
+ // and will stay so
+ cell->line(line)->set_user_flag();
+ }
+ else if(cell->has_children() && cell->child(0)->coarsen_flag_set())
+ cell->set_user_flag();
+
+
+ // now check whether there are
+ // cells with lines that are
+ // more than once refined or
+ // that will be more than once
+ // refined. The first thing
+ // should never be the case, in
+ // the second case we flag the
+ // cell for refinement
+ for (typename Triangulation<dim,spacedim>::active_cell_iterator
+ cell=triangulation.last_active(); cell!=triangulation.end(); --cell)
+ for (unsigned int line=0; line<GeometryInfo<dim>::lines_per_cell; ++line)
+ {
+ if (cell->line(line)->has_children())
+ {
+ // if this line is
+ // refined, its
+ // children should
+ // not have further
+ // children
+ //
+ // however, if any of
+ // the children is
+ // flagged for
+ // further
+ // refinement, we
+ // need to refine
+ // this cell also (at
+ // least, if the cell
+ // is not already
+ // flagged)
+ bool offending_line_found = false;
+
+ for (unsigned int c=0; c<2; ++c)
+ {
+ Assert (cell->line(line)->child(c)->has_children() == false,
+ ExcInternalError());
+
+ if (cell->line(line)->child(c)->user_flag_set () &&
+ (GeometryInfo<dim>::line_refinement_case(cell->refine_flag_set(),
+ line)
+ ==RefinementCase<1>::no_refinement))
+ {
+ // tag this
+ // cell for
+ // refinement
+ cell->clear_coarsen_flag ();
+ // if anisotropic
+ // coarsening is
+ // allowed: extend the
+ // refine_flag in the
+ // needed direction,
+ // else set refine_flag
+ // (isotropic)
+ if (triangulation.smooth_grid &
+ Triangulation<dim,spacedim>::allow_anisotropic_smoothing)
+ cell->flag_for_line_refinement(line);
+ else
+ cell->set_refine_flag();
+
+ for (unsigned int l=0; l<GeometryInfo<dim>::lines_per_cell; ++l)
+ if (GeometryInfo<dim>::line_refinement_case(cell->refine_flag_set(), line)
+ ==RefinementCase<1>::cut_x)
+ // flag a line,
+ // that will be
+ // refined
+ cell->line(l)->set_user_flag();
+ // note that
+ // we have
+ // changed
+ // the grid
+ offending_line_found = true;
+
+ // it may save us several
+ // loop iterations if we
+ // flag all lines of
+ // this cell now (and not
+ // at the outset of the
+ // next iteration) for
+ // refinement
+ for (unsigned int line=0;
+ line<GeometryInfo<dim>::lines_per_cell; ++line)
+ if (!cell->line(line)->has_children() &&
+ (GeometryInfo<dim>::line_refinement_case(cell->refine_flag_set(),
+ line)
+ !=RefinementCase<1>::no_refinement))
+ cell->line(line)->set_user_flag();
+
+ break;
+ }
+ }
+
+ if (offending_line_found)
+ {
+ mesh_changed = true;
+ break;
+ }
+ }
+ }
+
+
+ // there is another thing here:
+ // if any of the lines will be
+ // refined, then we may not
+ // coarsen the present cell
+ // 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
+ for (typename Triangulation<dim,spacedim>::cell_iterator
+ cell=triangulation.last(); cell!=triangulation.end(); --cell)
+ {
+ if (cell->user_flag_set())
+ for (unsigned int line=0; line<GeometryInfo<dim>::lines_per_cell; ++line)
+ if (cell->line(line)->has_children() &&
+ (cell->line(line)->child(0)->user_flag_set() ||
+ cell->line(line)->child(1)->user_flag_set()))
+ {
+ for (unsigned int c=0; c<cell->n_children(); ++c)
+ cell->child(c)->clear_coarsen_flag ();
+ cell->clear_user_flag();
+ for (unsigned int l=0; l<GeometryInfo<dim>::lines_per_cell; ++l)
+ if (GeometryInfo<dim>::line_refinement_case(cell->refinement_case(), l)
+ ==RefinementCase<1>::cut_x)
+ // flag a line, that is refined
+ // and will stay so
+ cell->line(l)->set_user_flag();
+ mesh_changed = true;
+ break;
+ }
+ }
+ }
+ while (mesh_changed == true);
+ }
+
+
+
+ /**
+ * Helper function for
+ * @p fix_coarsen_flags. Return wether
+ * coarsening of this cell is allowed.
+ * Coarsening can be forbidden if the
+ * neighboring cells are or will be
+ * refined twice along the common face.
+ */
+ template <int dim, int spacedim>
+ static
+ bool
+ coarsening_allowed (const typename Triangulation<dim,spacedim>::cell_iterator& cell)
+ {
+ // in 1d, coarsening is
+ // always allowed since we
+ // don't enforce the 2:1
+ // constraint there
+ if (dim == 1)
+ return true;
+
+ const RefinementCase<dim> ref_case = cell->refinement_case();
+ for (unsigned int n=0; n<GeometryInfo<dim>::faces_per_cell; ++n)
+ {
+ // if the cell is not refined
+ // along that face, coarsening
+ // will not change anything, so
+ // do nothing. the same applies,
+ // if the face is at the boandary
+ const RefinementCase<dim-1> face_ref_case =
+ GeometryInfo<dim>::face_refinement_case(cell->refinement_case(), n);
+
+ const unsigned int n_subfaces
+ = GeometryInfo<dim-1>::n_children(face_ref_case);
+
+ if (n_subfaces == 0 || cell->at_boundary(n))
+ continue;
+ for (unsigned int c=0; c<n_subfaces; ++c)
+ {
+ const typename Triangulation<dim,spacedim>::cell_iterator
+ child = cell->child(GeometryInfo<dim>::
+ child_cell_on_face(ref_case,
+ n,c));
+
+ const typename Triangulation<dim,spacedim>::cell_iterator
+ child_neighbor = child->neighbor(n);
+ if (!child->neighbor_is_coarser(n))
+ // in 2d, if the child's neighbor
+ // is coarser, then it has no
+ // children. however, in 3d it
+ // might be otherwise. consider
+ // for example, that our face
+ // might be refined with cut_x,
+ // but the neighbor is refined
+ // with cut_xy at that face. then
+ // the neighbor pointers of the
+ // children of our cell will point
+ // to the common neighbor cell,
+ // not to its children. what we
+ // really want to know in the
+ // following is, wether the
+ // neighbor cell is refined twice
+ // with reference to our cell.
+ // that only has to be asked, if
+ // the child's neighbor is not a
+ // coarser one.
+ if ((child_neighbor->has_children() &&
+ !child_neighbor->user_flag_set())||
+ // neighbor has children, which
+ // are further refined along
+ // the face, otherwise
+ // something went wrong in the
+ // contruction of neighbor
+ // pointers. then only allow
+ // coarsening if this neighbor
+ // will be coarsened as well
+ // (user_pointer is set). the
+ // same applies, if the
+ // neighbors children are not
+ // refined but will be after
+ // refinement
+ child_neighbor->refine_flag_set())
+ return false;
+ }
+ }
+ return true;
+ }
+ };
+ }
+}
+
+
+template <int dim, int spacedim>
+const StraightBoundary<dim,spacedim>
+Triangulation<dim, spacedim>::straight_boundary = StraightBoundary<dim,spacedim>();
+
+
+
+template <int dim, int spacedim>
+const unsigned int
+Triangulation<dim, spacedim>::dimension;
+
+
+
+template <int dim, int spacedim>
+Triangulation<dim, spacedim>::
+Triangulation (const MeshSmoothing smooth_grid,
+ const bool check_for_distorted_cells)
+ :
+ smooth_grid(smooth_grid),
+ faces(NULL),
+ anisotropic_refinement(false),
+ check_for_distorted_cells(check_for_distorted_cells)
+{
+ // set default boundary for all
+ // possible components
+ for (unsigned int i=0;i<255;++i)
+ boundary[i] = &straight_boundary;
+}
+
+
+template <int dim, int spacedim>
+Triangulation<dim, spacedim>::
+Triangulation (const Triangulation<dim, spacedim> &)
+ // do not set any subscriptors;
+ // anyway, calling this constructor
+ // is an error!
+ :
+ Subscriptor(),
+ check_for_distorted_cells(check_for_distorted_cells)
+{
+ Assert (false, ExcInternalError());
+}
+
+
+
+template <int dim, int spacedim>
+Triangulation<dim, spacedim>::~Triangulation ()
+{
+ for (unsigned int i=0; i<levels.size(); ++i)
+ delete levels[i];
+ levels.clear ();
+ delete faces;
+}
+
+
+
+template <int dim, int spacedim>
+void Triangulation<dim, spacedim>::clear ()
+{
+ clear_despite_subscriptions();
+}
+
+
+
+template <int dim, int spacedim>
+void
+Triangulation<dim, spacedim>::set_mesh_smoothing(const MeshSmoothing mesh_smoothing)
+{
+ Assert (n_levels() == 0, ExcTriangulationNotEmpty ());
+ smooth_grid=mesh_smoothing;
+}
+
+
+
+template <int dim, int spacedim>
+void
+Triangulation<dim, spacedim>::set_boundary (const unsigned int number,
+ const Boundary<dim, spacedim>& boundary_object)
+{
+ Assert(number<255, ExcIndexRange(number,0,255));
+
+ boundary[number] = &boundary_object;
+}
+
+
+
+template <int dim, int spacedim>
+void
+Triangulation<dim, spacedim>::set_boundary (const unsigned int number)
+{
+ set_boundary (number, straight_boundary);
+}
+
+
+
+template <int dim, int spacedim>
+const Boundary<dim, spacedim> &
+Triangulation<dim, spacedim>::get_boundary (const unsigned int number) const
+{
+ Assert(number<255, ExcIndexRange(number,0,255));
+
+ return *(boundary[number]);
+}
+
+
+template <int dim, int spacedim>
+std::vector<unsigned char>
+Triangulation<dim, spacedim>::get_boundary_indicators () const
+{
+ // in 1d, the situation is simpler:
+ if (dim == 1)
+ return std::vector<unsigned char> (0);;
+
+ std::vector<bool> bi_exists(255, false);
+ active_cell_iterator cell=begin_active();
+ for (; cell!=end(); ++cell)
+ for (unsigned int face=0; face<GeometryInfo<dim>::faces_per_cell; ++face)
+ if (cell->at_boundary(face))
+ bi_exists[cell->face(face)->boundary_indicator()]=true;
+
+ const unsigned int n_bi=
+ std::count(bi_exists.begin(), bi_exists.end(), true);
+
+ std::vector<unsigned char> boundary_indicators(n_bi);
+ unsigned int bi_counter=0;
+ for (unsigned int i=0; i<bi_exists.size(); ++i)
+ if (bi_exists[i]==true)
+ boundary_indicators[bi_counter++]=i;
+
+ return boundary_indicators;
+}
+
+
+
+/*-----------------------------------------------------------------*/
+
+
+template <int dim, int spacedim>
+void Triangulation<dim, spacedim>::copy_triangulation (const Triangulation<dim, spacedim> &old_tria)
+{
+ Assert (vertices.size() == 0, ExcTriangulationNotEmpty());
+ Assert (levels.size () == 0, ExcTriangulationNotEmpty());
+ Assert (faces == NULL, ExcTriangulationNotEmpty());
+
+ Assert (old_tria.levels.size() != 0, ExcInternalError());
+ Assert (old_tria.vertices.size() != 0, ExcInternalError());
+ Assert (dim == 1 || old_tria.faces != NULL, ExcInternalError());
+
+
+ // copy normal elements
+ vertices = old_tria.vertices;
+ vertices_used = old_tria.vertices_used;
+ anisotropic_refinement = old_tria.anisotropic_refinement;
+ smooth_grid = old_tria.smooth_grid;
+
+ faces = new internal::Triangulation::TriaFaces<dim>(*old_tria.faces);
+
+ for (unsigned i=0;i<255;++i)
+ boundary[i] = old_tria.boundary[i];
+
+ levels.reserve (old_tria.levels.size());
+ for (unsigned int level=0; level<old_tria.levels.size(); ++level)
+ levels.push_back (new internal::Triangulation::TriaLevel<dim>(*old_tria.levels[level]));
+
+ number_cache = old_tria.number_cache;
+
+ // inform RefinementListeners of old_tria of
+ // the copy operation
+ typename std::list<RefinementListener *>::iterator ref_listener =
+ old_tria.refinement_listeners.begin (),
+ end_listener = old_tria.refinement_listeners.end ();
+ for (; ref_listener != end_listener; ++ref_listener)
+ (*ref_listener)->copy_notification (old_tria, *this);
+
+ // note that we need not copy the
+ // subscriptor!
+}
+
+
+
+template <int dim, int spacedim>
+void
+Triangulation<dim,spacedim>::
+create_triangulation_compatibility (const std::vector<Point<spacedim> > &v,
+ const std::vector<CellData<dim> > &cells,
+ const SubCellData &subcelldata)
+{
+ std::vector<CellData<dim> > reordered_cells (cells);
+ SubCellData reordered_subcelldata (subcelldata);
+
+ // in-place reordering of data
+ reorder_compatibility (reordered_cells, reordered_subcelldata);
+
+ // now create triangulation from
+ // reordered data
+ create_triangulation(v, reordered_cells, reordered_subcelldata);
+}
+
+
+template <int dim, int spacedim>
+void
+Triangulation<dim,spacedim>::
+create_triangulation (const std::vector<Point<spacedim> > &v,
+ const std::vector<CellData<dim> > &cells,
+ const SubCellData &subcelldata)
+{
+ Assert (vertices.size() == 0, ExcTriangulationNotEmpty());
+ Assert (levels.size() == 0, ExcTriangulationNotEmpty());
+ Assert (faces == NULL, ExcTriangulationNotEmpty());
+ // check that no forbidden arrays
+ // are used
+ Assert (subcelldata.check_consistency(dim), ExcInternalError());
+
+ // try to create a triangulation;
+ // if this fails, we still want to
+ // throw an exception but if we
+ // just do so we'll get into
+ // trouble because sometimes other
+ // objects are already attached to
+ // it:
+ try
+ {
+ internal::Triangulation::Implementation::create_triangulation (v, cells, subcelldata, *this);
+ }
+ catch (...)
+ {
+ clear_despite_subscriptions();
+ throw;
+ }
+
+ compute_number_cache (*this, levels.size(), number_cache);
+
+ // now verify that there are indeed
+ // no distorted cells. as per the
+ // documentation of this class, we
+ // first collect all distorted
+ // cells and then throw an
+ // exception if there are any
+ if (check_for_distorted_cells == true)
+ {
+ DistortedCellList distorted_cells = collect_distorted_coarse_cells (*this);
+ // throw the array (and fill the
+ // various location fields) if
+ // there are distorted
+ // cells. otherwise, just fall off
+ // the end of the function
+ AssertThrow (distorted_cells.distorted_cells.size() == 0,
+ distorted_cells);
+ }
+}
+
+
+
+template <int dim, int spacedim>
+void Triangulation<dim, spacedim>::distort_random (const double factor,
+ const bool keep_boundary)
+{
+ internal::Triangulation::Implementation::distort_random (factor, keep_boundary, *this);
+}
+
+
+
+template <int dim, int spacedim>
+void Triangulation<dim, spacedim>::set_all_refine_flags ()
+{
+ active_cell_iterator cell = begin_active(),
+ endc = end();
+
+ for (; cell != endc; ++cell)
+ {
+ cell->clear_coarsen_flag();
+ cell->set_refine_flag ();
+ }
+}
+
+
+
+template <int dim, int spacedim>
+void Triangulation<dim, spacedim>::refine_global (const unsigned int times)
+{
+ for (unsigned int i=0; i<times; ++i)
+ {
+ set_all_refine_flags();
+ execute_coarsening_and_refinement ();
+ }
+}
+
+
+
+/*-------------------- refine/coarsen flags -------------------------*/
+
+
+
+template <int dim, int spacedim>
+void Triangulation<dim, spacedim>::save_refine_flags (std::vector<bool> &v) const
+{
+ v.resize (dim*n_active_cells(), false);
+ std::vector<bool>::iterator i = v.begin();
+ active_cell_iterator cell = begin_active(),
+ endc = end();
+ for (; cell!=endc; ++cell)
+ for (unsigned int j=0; j<dim; ++j,++i)
+ if (cell->refine_flag_set() & (1<<j) )
+ *i = true;
+
+ Assert (i == v.end(), ExcInternalError());
+}
+
+
+
+template <int dim, int spacedim>
+void Triangulation<dim, spacedim>::save_refine_flags (std::ostream &out) const
+{
+ std::vector<bool> v;
+ save_refine_flags (v);
+ write_bool_vector (mn_tria_refine_flags_begin, v, mn_tria_refine_flags_end,
+ out);
+}
+
+
+
+template <int dim, int spacedim>
+void Triangulation<dim, spacedim>::load_refine_flags (std::istream &in)
+{
+ std::vector<bool> v;
+ read_bool_vector (mn_tria_refine_flags_begin, v, mn_tria_refine_flags_end,
+ in);
+ load_refine_flags (v);
+}
+
+
+
+template <int dim, int spacedim>
+void Triangulation<dim, spacedim>::load_refine_flags (const std::vector<bool> &v)
+{
+ AssertThrow (v.size() == dim*n_active_cells(), ExcGridReadError());
+
+ active_cell_iterator cell = begin_active(),
+ endc = end();
+ std::vector<bool>::const_iterator i = v.begin();
+ for (; cell!=endc; ++cell)
+ {
+ unsigned int ref_case=0;
+
+ for(unsigned int j=0; j<dim; ++j, ++i)
+ if (*i == true)
+ ref_case+=1<<j;
+ Assert(ref_case<RefinementCase<dim>::isotropic_refinement+1,
+ ExcGridReadError());
+ if (ref_case>0)
+ cell->set_refine_flag(RefinementCase<dim>(ref_case));
+ else
+ cell->clear_refine_flag();
+ }
+
+ Assert (i == v.end(), ExcInternalError());
+}
+
+
+
+template <int dim, int spacedim>
+void Triangulation<dim, spacedim>::save_coarsen_flags (std::vector<bool> &v) const
+{
+ v.resize (n_active_cells(), false);
+ std::vector<bool>::iterator i = v.begin();
+ active_cell_iterator cell = begin_active(),
+ endc = end();
+ for (; cell!=endc; ++cell, ++i)
+ *i = cell->coarsen_flag_set();
+
+ Assert (i == v.end(), ExcInternalError());
+}
+
+
+
+template <int dim, int spacedim>
+void Triangulation<dim, spacedim>::save_coarsen_flags (std::ostream &out) const
+{
+ std::vector<bool> v;
+ save_coarsen_flags (v);
+ write_bool_vector (mn_tria_coarsen_flags_begin, v, mn_tria_coarsen_flags_end,
+ out);
+}
+
+
+
+template <int dim, int spacedim>
+void Triangulation<dim, spacedim>::load_coarsen_flags (std::istream &in)
+{
+ std::vector<bool> v;
+ read_bool_vector (mn_tria_coarsen_flags_begin, v, mn_tria_coarsen_flags_end,
+ in);
+ load_coarsen_flags (v);
+}
+
+
+
+template <int dim, int spacedim>
+void Triangulation<dim, spacedim>::load_coarsen_flags (const std::vector<bool> &v)
+{
+ Assert (v.size() == n_active_cells(), ExcGridReadError());
+
+ active_cell_iterator cell = begin_active(),
+ endc = end();
+ std::vector<bool>::const_iterator i = v.begin();
+ for (; cell!=endc; ++cell, ++i)
+ if (*i == true)
+ cell->set_coarsen_flag();
+ else
+ cell->clear_coarsen_flag();
+
+ Assert (i == v.end(), ExcInternalError());
+}
+
+
+template <int dim, int spacedim>
+bool Triangulation<dim,spacedim>::get_anisotropic_refinement_flag() const
+{
+ return anisotropic_refinement;
+}
+
+
+
+/*-------------------- user data/flags -------------------------*/
+
+
+namespace
+{
+ // clear user data of cells
+ template <int dim>
+ void clear_user_data (std::vector<internal::Triangulation::TriaLevel<dim>*> &levels)
+ {
+ for (unsigned int level=0;level<levels.size();++level)
+ levels[level]->cells.clear_user_data();
+ }
+
+
+ // clear user data of faces
+ void clear_user_data (internal::Triangulation::TriaFaces<1> *)
+ {
+ // nothing to do in 1d
+ }
+
+
+ void clear_user_data (internal::Triangulation::TriaFaces<2> *faces)
+ {
+ faces->lines.clear_user_data();
+ }
+
+
+ void clear_user_data (internal::Triangulation::TriaFaces<3> *faces)
+ {
+ faces->lines.clear_user_data();
+ faces->quads.clear_user_data();
+ }
+}
+
+
+template <int dim, int spacedim>
+void Triangulation<dim,spacedim>::clear_user_data ()
+{
+ // let functions in anonymous namespace do their work
+ dealii::clear_user_data (levels);
+ dealii::clear_user_data (faces);
+}
+
+
+
+namespace
+{
+ void clear_user_flags_line (std::vector<internal::Triangulation::TriaLevel<1>*> &levels,
+ internal::Triangulation::TriaFaces<1> *)
+ {
+ for (unsigned int level=0; level<levels.size(); ++level)
+ levels[level]->cells.clear_user_flags();
+ }
+
+ template <int dim>
+ void clear_user_flags_line (std::vector<internal::Triangulation::TriaLevel<dim>*> &,
+ internal::Triangulation::TriaFaces<dim> *faces)
+ {
+ faces->lines.clear_user_flags();
+ }
+}
+
+
+template <int dim, int spacedim>
+void Triangulation<dim,spacedim>::clear_user_flags_line ()
+{
+ dealii::clear_user_flags_line (levels, faces);
+}
+
+
+
+namespace
+{
+ void clear_user_flags_quad (std::vector<internal::Triangulation::TriaLevel<1>*> &,
+ internal::Triangulation::TriaFaces<1> *)
+ {
+ // nothing to do in 1d
+ }
+
+ void clear_user_flags_quad (std::vector<internal::Triangulation::TriaLevel<2>*> &levels,
+ internal::Triangulation::TriaFaces<2> *)
+ {
+ for (unsigned int level=0; level<levels.size(); ++level)
+ levels[level]->cells.clear_user_flags();
+ }
+
+ template <int dim>
+ void clear_user_flags_quad (std::vector<internal::Triangulation::TriaLevel<dim>*> &,
+ internal::Triangulation::TriaFaces<dim> *faces)
+ {
+ faces->quads.clear_user_flags();
+ }
+}
+
+
+template <int dim, int spacedim>
+void Triangulation<dim,spacedim>::clear_user_flags_quad ()
+{
+ dealii::clear_user_flags_quad (levels, faces);
+}
+
+
+
+namespace
+{
+ void clear_user_flags_hex (std::vector<internal::Triangulation::TriaLevel<1>*> &,
+ internal::Triangulation::TriaFaces<1> *)
+ {
+ // nothing to do in 1d
+ }
+
+
+ void clear_user_flags_hex (std::vector<internal::Triangulation::TriaLevel<2>*> &,
+ internal::Triangulation::TriaFaces<2> *)
+ {
+ // nothing to do in 2d
+ }
+
+ void clear_user_flags_hex (std::vector<internal::Triangulation::TriaLevel<3>*> &levels,
+ internal::Triangulation::TriaFaces<3> *)
+ {
+ for (unsigned int level=0; level<levels.size(); ++level)
+ levels[level]->cells.clear_user_flags();
+ }
+}
+
+
+template <int dim, int spacedim>
+void Triangulation<dim,spacedim>::clear_user_flags_hex ()
+{
+ dealii::clear_user_flags_hex (levels, faces);
+}
+
+
+
+template <int dim, int spacedim>
+void Triangulation<dim,spacedim>::clear_user_flags ()
+{
+ clear_user_flags_line ();
+ clear_user_flags_quad ();
+ clear_user_flags_hex ();
+}
+
+
+
+template <int dim, int spacedim>
+void Triangulation<dim,spacedim>::clear_user_pointers ()
+{
+ clear_user_data();
+}
+
+
+
+
+template <int dim, int spacedim>
+void Triangulation<dim, spacedim>::save_user_flags (std::ostream &out) const
+{
+ save_user_flags_line (out);
+
+ if (dim>=2)
+ save_user_flags_quad (out);
+
+ if (dim>=3)
+ save_user_flags_hex (out);
+
+ if (dim >= 4)
+ Assert (false, ExcNotImplemented());
+}
+
+
+
+template <int dim, int spacedim>
+void Triangulation<dim, spacedim>::save_user_flags (std::vector<bool> &v) const
+{
+ // clear vector and append
+ // all the stuff later on
+ v.clear ();
+
+ std::vector<bool> tmp;
+
+ save_user_flags_line (tmp);
+ v.insert (v.end(), tmp.begin(), tmp.end());
+
+ if (dim >= 2)
+ {
+ save_user_flags_quad (tmp);
+ v.insert (v.end(), tmp.begin(), tmp.end());
+ }
+
+ if (dim >= 3)
+ {
+ save_user_flags_hex (tmp);
+ v.insert (v.end(), tmp.begin(), tmp.end());
+ }
+
+ if (dim >= 4)
+ Assert (false, ExcNotImplemented());
+}
+
+
+
+template <int dim, int spacedim>
+void Triangulation<dim, spacedim>::load_user_flags (std::istream &in)
+{
+ load_user_flags_line (in);
+
+ if (dim>=2)
+ load_user_flags_quad (in);
+
+ if (dim>=3)
+ load_user_flags_hex (in);
+
+ if (dim >= 4)
+ Assert (false, ExcNotImplemented());
+}
+
+
+
+template <int dim, int spacedim>
+void Triangulation<dim, spacedim>::load_user_flags (const std::vector<bool> &v)
+{
+ Assert (v.size() == n_lines()+n_quads()+n_hexs(), ExcInternalError());
+ std::vector<bool> tmp;
+
+ // first extract the flags
+ // belonging to lines
+ tmp.insert (tmp.end(),
+ v.begin(), v.begin()+n_lines());
+ // and set the lines
+ load_user_flags_line (tmp);
+
+ if (dim >= 2)
+ {
+ tmp.clear ();
+ tmp.insert (tmp.end(),
+ v.begin()+n_lines(), v.begin()+n_lines()+n_quads());
+ load_user_flags_quad (tmp);
+ }
+
+ if (dim >= 3)
+ {
+ tmp.clear();
+ tmp.insert (tmp.end(),
+ v.begin()+n_lines()+n_quads(), v.begin()+n_lines()+n_quads()+n_hexs());
+ load_user_flags_hex (tmp);
+ }
+
+ if (dim >= 4)
+ Assert (false, ExcNotImplemented());
+}
+
+
+
+template <int dim, int spacedim>
+void Triangulation<dim, spacedim>::save_user_flags_line (std::vector<bool> &v) const
+{
+ v.resize (n_lines(), false);
+ std::vector<bool>::iterator i = v.begin();
+ line_iterator line = begin_line(),
+ endl = end_line();
+ for (; line!=endl; ++line, ++i)
+ *i = line->user_flag_set();
+
+ Assert (i == v.end(), ExcInternalError());
+}
+
+
+
+template <int dim, int spacedim>
+void Triangulation<dim, spacedim>::save_user_flags_line (std::ostream &out) const
+{
+ std::vector<bool> v;
+ save_user_flags_line (v);
+ write_bool_vector (mn_tria_line_user_flags_begin, v, mn_tria_line_user_flags_end,
+ out);
+}
+
+
+
+template <int dim, int spacedim>
+void Triangulation<dim, spacedim>::load_user_flags_line (std::istream &in)
+{
+ std::vector<bool> v;
+ read_bool_vector (mn_tria_line_user_flags_begin, v, mn_tria_line_user_flags_end,
+ in);
+ load_user_flags_line (v);
+}
+
+
+
+template <int dim, int spacedim>
+void Triangulation<dim, spacedim>::load_user_flags_line (const std::vector<bool> &v)
+{
+ Assert (v.size() == n_lines(), ExcGridReadError());
+
+ line_iterator line = begin_line(),
+ endl = end_line();
+ std::vector<bool>::const_iterator i = v.begin();
+ for (; line!=endl; ++line, ++i)
+ if (*i == true)
+ line->set_user_flag();
+ else
+ line->clear_user_flag();
+
+ Assert (i == v.end(), ExcInternalError());
+}
+
+
+namespace
+{
+ template <typename Iterator>
+ bool get_user_flag (const Iterator &i)
+ {
+ return i->user_flag_set();
+ }
+
+
+
+ template <int structdim, int dim, int spacedim>
+ bool get_user_flag (const TriaIterator<InvalidAccessor<structdim,dim,spacedim> > &)
+ {
+ Assert (false, ExcInternalError());
+ return false;
+ }
+
+
+
+ template <typename Iterator>
+ void set_user_flag (const Iterator &i)
+ {
+ i->set_user_flag();
+ }
+
+
+
+ template <int structdim, int dim, int spacedim>
+ void set_user_flag (const TriaIterator<InvalidAccessor<structdim,dim,spacedim> > &)
+ {
+ Assert (false, ExcInternalError());
+ }
+
+
+
+ template <typename Iterator>
+ void clear_user_flag (const Iterator &i)
+ {
+ i->clear_user_flag();
+ }
+
+
+
+ template <int structdim, int dim, int spacedim>
+ void clear_user_flag (const TriaIterator<InvalidAccessor<structdim,dim,spacedim> > &)
+ {
+ Assert (false, ExcInternalError());
+ }
+}
+
+
+template <int dim, int spacedim>
+void Triangulation<dim, spacedim>::save_user_flags_quad (std::vector<bool> &v) const
+{
+ v.resize (n_quads(), false);
+
+ if (dim >= 2)
+ {
+ std::vector<bool>::iterator i = v.begin();
+ quad_iterator quad = begin_quad(),
+ endq = end_quad();
+ for (; quad!=endq; ++quad, ++i)
+ *i = get_user_flag (quad);
+
+ Assert (i == v.end(), ExcInternalError());
+ }
+}
+
+
+
+template <int dim, int spacedim>
+void Triangulation<dim, spacedim>::save_user_flags_quad (std::ostream &out) const
+{
+ std::vector<bool> v;
+ save_user_flags_quad (v);
+ write_bool_vector (mn_tria_quad_user_flags_begin, v, mn_tria_quad_user_flags_end,
+ out);
+}
+
+
+
+template <int dim, int spacedim>
+void Triangulation<dim, spacedim>::load_user_flags_quad (std::istream &in)
+{
+ std::vector<bool> v;
+ read_bool_vector (mn_tria_quad_user_flags_begin, v, mn_tria_quad_user_flags_end,
+ in);
+ load_user_flags_quad (v);
+}
+
+
+
+template <int dim, int spacedim>
+void Triangulation<dim, spacedim>::load_user_flags_quad (const std::vector<bool> &v)
+{
+ Assert (v.size() == n_quads(), ExcGridReadError());
+
+ if (dim >= 2)
+ {
+ quad_iterator quad = begin_quad(),
+ endq = end_quad();
+ std::vector<bool>::const_iterator i = v.begin();
+ for (; quad!=endq; ++quad, ++i)
+ if (*i == true)
+ set_user_flag(quad);
+ else
+ clear_user_flag(quad);
+
+ Assert (i == v.end(), ExcInternalError());
+ }
+}
+
+
+
+template <int dim, int spacedim>
+void Triangulation<dim, spacedim>::save_user_flags_hex (std::vector<bool> &v) const
+{
+ v.resize (n_hexs(), false);
+
+ if (dim >= 3)
+ {
+ std::vector<bool>::iterator i = v.begin();
+ hex_iterator hex = begin_hex(),
+ endh = end_hex();
+ for (; hex!=endh; ++hex, ++i)
+ *i = get_user_flag (hex);
+
+ Assert (i == v.end(), ExcInternalError());
+ }
+}
+
+
+
+template <int dim, int spacedim>
+void Triangulation<dim, spacedim>::save_user_flags_hex (std::ostream &out) const
+{
+ std::vector<bool> v;
+ save_user_flags_hex (v);
+ write_bool_vector (mn_tria_hex_user_flags_begin, v, mn_tria_hex_user_flags_end,
+ out);
+}
+
+
+
+template <int dim, int spacedim>
+void Triangulation<dim, spacedim>::load_user_flags_hex (std::istream &in)
+{
+ std::vector<bool> v;
+ read_bool_vector (mn_tria_hex_user_flags_begin, v, mn_tria_hex_user_flags_end,
+ in);
+ load_user_flags_hex (v);
+}
+
+
+
+template <int dim, int spacedim>
+void Triangulation<dim, spacedim>::load_user_flags_hex (const std::vector<bool> &v)
+{
+ Assert (v.size() == n_hexs(), ExcGridReadError());
+
+ if (dim >= 3)
+ {
+ hex_iterator hex = begin_hex(),
+ endh = end_hex();
+ std::vector<bool>::const_iterator i = v.begin();
+ for (; hex!=endh; ++hex, ++i)
+ if (*i == true)
+ set_user_flag(hex);
+ else
+ clear_user_flag(hex);
+
+ Assert (i == v.end(), ExcInternalError());
+ }
+}
+
+
+
+template <int dim, int spacedim>
+void Triangulation<dim, spacedim>::save_user_indices (std::vector<unsigned int> &v) const
+{
+ // clear vector and append all the
+ // stuff later on
+ v.clear ();
+
+ std::vector<unsigned int> tmp;
+
+ save_user_indices_line (tmp);
+ v.insert (v.end(), tmp.begin(), tmp.end());
+
+ if (dim >= 2)
+ {
+ save_user_indices_quad (tmp);
+ v.insert (v.end(), tmp.begin(), tmp.end());
+ }
+
+ if (dim >= 3)
+ {
+ save_user_indices_hex (tmp);
+ v.insert (v.end(), tmp.begin(), tmp.end());
+ }
+
+ if (dim >= 4)
+ Assert (false, ExcNotImplemented());
+}
+
+
+
+template <int dim, int spacedim>
+void Triangulation<dim, spacedim>::load_user_indices (const std::vector<unsigned int> &v)
+{
+ Assert (v.size() == n_lines()+n_quads()+n_hexs(), ExcInternalError());
+ std::vector<unsigned int> tmp;
+
+ // first extract the indices
+ // belonging to lines
+ tmp.insert (tmp.end(),
+ v.begin(), v.begin()+n_lines());
+ // and set the lines
+ load_user_indices_line (tmp);
+
+ if (dim >= 2)
+ {
+ tmp.clear ();
+ tmp.insert (tmp.end(),
+ v.begin()+n_lines(), v.begin()+n_lines()+n_quads());
+ load_user_indices_quad (tmp);
+ }
+
+ if (dim >= 3)
+ {
+ tmp.clear ();
+ tmp.insert (tmp.end(),
+ v.begin()+n_lines()+n_quads(), v.begin()+n_lines()+n_quads()+n_hexs());
+ load_user_indices_hex (tmp);
+ }
+
+ if (dim >= 4)
+ Assert (false, ExcNotImplemented());
+}
+
+
+
+namespace
+{
+ template <typename Iterator>
+ unsigned int get_user_index (const Iterator &i)
+ {
+ return i->user_index();
+ }
+
+
+
+ template <int structdim, int dim, int spacedim>
+ unsigned int get_user_index (const TriaIterator<InvalidAccessor<structdim,dim,spacedim> > &)
+ {
+ Assert (false, ExcInternalError());
+ return numbers::invalid_unsigned_int;
+ }
+
+
+
+ template <typename Iterator>
+ void set_user_index (const Iterator &i,
+ const unsigned int x)
+ {
+ i->set_user_index(x);
+ }
+
+
+
+ template <int structdim, int dim, int spacedim>
+ void set_user_index (const TriaIterator<InvalidAccessor<structdim,dim,spacedim> > &,
+ const unsigned int)
+ {
+ Assert (false, ExcInternalError());
+ }
+}
+
+
+template <int dim, int spacedim>
+void Triangulation<dim, spacedim>::save_user_indices_line (std::vector<unsigned int> &v) const
+{
+ v.resize (n_lines(), 0);
+ std::vector<unsigned int>::iterator i = v.begin();
+ line_iterator line = begin_line(),
+ endl = end_line();
+ for (; line!=endl; ++line, ++i)
+ *i = line->user_index();
+}
+
+
+
+template <int dim, int spacedim>
+void Triangulation<dim, spacedim>::load_user_indices_line (const std::vector<unsigned int> &v)
+{
+ Assert (v.size() == n_lines(), ExcGridReadError());
+
+ line_iterator line = begin_line(),
+ endl = end_line();
+ std::vector<unsigned int>::const_iterator i = v.begin();
+ for (; line!=endl; ++line, ++i)
+ line->set_user_index(*i);
+}
+
+
+template <int dim, int spacedim>
+void Triangulation<dim, spacedim>::save_user_indices_quad (std::vector<unsigned int> &v) const
+{
+ v.resize (n_quads(), 0);
+
+ if (dim >= 2)
+ {
+ std::vector<unsigned int>::iterator i = v.begin();
+ quad_iterator quad = begin_quad(),
+ endq = end_quad();
+ for (; quad!=endq; ++quad, ++i)
+ *i = get_user_index(quad);
+ }
+}
+
+
+
+template <int dim, int spacedim>
+void Triangulation<dim, spacedim>::load_user_indices_quad (const std::vector<unsigned int> &v)
+{
+ Assert (v.size() == n_quads(), ExcGridReadError());
+
+ if (dim >= 2)
+ {
+ quad_iterator quad = begin_quad(),
+ endq = end_quad();
+ std::vector<unsigned int>::const_iterator i = v.begin();
+ for (; quad!=endq; ++quad, ++i)
+ set_user_index(quad, *i);
+ }
+}
+
+
+template <int dim, int spacedim>
+void Triangulation<dim, spacedim>::save_user_indices_hex (std::vector<unsigned int> &v) const
+{
+ v.resize (n_hexs(), 0);
+
+ if (dim >= 3)
+ {
+ std::vector<unsigned int>::iterator i = v.begin();
+ hex_iterator hex = begin_hex(),
+ endh = end_hex();
+ for (; hex!=endh; ++hex, ++i)
+ *i = get_user_index(hex);
+ }
+}
+
+
+
+template <int dim, int spacedim>
+void Triangulation<dim, spacedim>::load_user_indices_hex (const std::vector<unsigned int> &v)
+{
+ Assert (v.size() == n_hexs(), ExcGridReadError());
+
+ if (dim >= 3)
+ {
+ hex_iterator hex = begin_hex(),
+ endh = end_hex();
+ std::vector<unsigned int>::const_iterator i = v.begin();
+ for (; hex!=endh; ++hex, ++i)
+ set_user_index(hex, *i);
+ }
+}
+
+
+
+//---------------- user pointers ----------------------------------------//
+
+
+namespace
+{
+ template <typename Iterator>
+ void * get_user_pointer (const Iterator &i)
+ {
+ return i->user_pointer();
+ }
+
+
+
+ template <int structdim, int dim, int spacedim>
+ void * get_user_pointer (const TriaIterator<InvalidAccessor<structdim,dim,spacedim> > &)
+ {
+ Assert (false, ExcInternalError());
+ return 0;
+ }
+
+
+
+ template <typename Iterator>
+ void set_user_pointer (const Iterator &i,
+ void * x)
+ {
+ i->set_user_pointer(x);
+ }
+
+
+
+ template <int structdim, int dim, int spacedim>
+ void set_user_pointer (const TriaIterator<InvalidAccessor<structdim,dim,spacedim> > &,
+ void *)
+ {
+ Assert (false, ExcInternalError());
+ }
+}
+
+
+template <int dim, int spacedim>
+void Triangulation<dim, spacedim>::save_user_pointers (std::vector<void *> &v) const
+{
+ // clear vector and append all the
+ // stuff later on
+ v.clear ();
+
+ std::vector<void *> tmp;
+
+ save_user_pointers_line (tmp);
+ v.insert (v.end(), tmp.begin(), tmp.end());
+
+ if (dim >= 2)
+ {
+ save_user_pointers_quad (tmp);
+ v.insert (v.end(), tmp.begin(), tmp.end());
+ }
+
+ if (dim >= 3)
+ {
+ save_user_pointers_hex (tmp);
+ v.insert (v.end(), tmp.begin(), tmp.end());
+ }
+
+ if (dim >= 4)
+ Assert (false, ExcNotImplemented());
+}
+
+
+
+template <int dim, int spacedim>
+void Triangulation<dim, spacedim>::load_user_pointers (const std::vector<void *> &v)
+{
+ Assert (v.size() == n_lines()+n_quads()+n_hexs(), ExcInternalError());
+ std::vector<void *> tmp;
+
+ // first extract the pointers
+ // belonging to lines
+ tmp.insert (tmp.end(),
+ v.begin(), v.begin()+n_lines());
+ // and set the lines
+ load_user_pointers_line (tmp);
+
+ if (dim >= 2)
+ {
+ tmp.clear ();
+ tmp.insert (tmp.end(),
+ v.begin()+n_lines(), v.begin()+n_lines()+n_quads());
+ load_user_pointers_quad (tmp);
+ }
+
+ if (dim >= 3)
+ {
+ tmp.clear ();
+ tmp.insert (tmp.end(),
+ v.begin()+n_lines()+n_quads(), v.begin()+n_lines()+n_quads()+n_hexs());
+ load_user_pointers_hex (tmp);
+ }
+
+ if (dim >= 4)
+ Assert (false, ExcNotImplemented());
+}
+
+
+
+template <int dim, int spacedim>
+void Triangulation<dim, spacedim>::save_user_pointers_line (std::vector<void *> &v) const
+{
+ v.resize (n_lines(), 0);
+ std::vector<void *>::iterator i = v.begin();
+ line_iterator line = begin_line(),
+ endl = end_line();
+ for (; line!=endl; ++line, ++i)
+ *i = line->user_pointer();
+}
+
+
+
+template <int dim, int spacedim>
+void Triangulation<dim, spacedim>::load_user_pointers_line (const std::vector<void *> &v)
+{
+ Assert (v.size() == n_lines(), ExcGridReadError());
+
+ line_iterator line = begin_line(),
+ endl = end_line();
+ std::vector<void *>::const_iterator i = v.begin();
+ for (; line!=endl; ++line, ++i)
+ line->set_user_pointer(*i);
+}
+
+
+
+template <int dim, int spacedim>
+void Triangulation<dim, spacedim>::save_user_pointers_quad (std::vector<void *> &v) const
+{
+ v.resize (n_quads(), 0);
+
+ if (dim >= 2)
+ {
+ std::vector<void *>::iterator i = v.begin();
+ quad_iterator quad = begin_quad(),
+ endq = end_quad();
+ for (; quad!=endq; ++quad, ++i)
+ *i = get_user_pointer(quad);
+ }
+}
+
+
+
+template <int dim, int spacedim>
+void Triangulation<dim, spacedim>::load_user_pointers_quad (const std::vector<void *> &v)
+{
+ Assert (v.size() == n_quads(), ExcGridReadError());
+
+ if (dim >= 2)
+ {
+ quad_iterator quad = begin_quad(),
+ endq = end_quad();
+ std::vector<void *>::const_iterator i = v.begin();
+ for (; quad!=endq; ++quad, ++i)
+ set_user_pointer(quad, *i);
+ }
+}
+
+
+template <int dim, int spacedim>
+void Triangulation<dim, spacedim>::save_user_pointers_hex (std::vector<void *> &v) const
+{
+ v.resize (n_hexs(), 0);
+
+ if (dim >= 3)
+ {
+ std::vector<void *>::iterator i = v.begin();
+ hex_iterator hex = begin_hex(),
+ endh = end_hex();
+ for (; hex!=endh; ++hex, ++i)
+ *i = get_user_pointer(hex);
+ }
+}
+
+
+
+template <int dim, int spacedim>
+void Triangulation<dim, spacedim>::load_user_pointers_hex (const std::vector<void *> &v)
+{
+ Assert (v.size() == n_hexs(), ExcGridReadError());
+
+ if (dim >= 3)
+ {
+ hex_iterator hex = begin_hex(),
+ endh = end_hex();
+ std::vector<void *>::const_iterator i = v.begin();
+ for (; hex!=endh; ++hex, ++i)
+ set_user_pointer(hex, *i);
+ }
+}
+
+
+
+/*------------------------ Cell iterator functions ------------------------*/
+
+
+template <int dim, int spacedim>
+typename Triangulation<dim,spacedim>::raw_cell_iterator
+Triangulation<dim,spacedim>::begin_raw (const unsigned int level) const
+{
+ switch (dim)
+ {
+ case 1:
+ return begin_raw_line (level);
+ case 2:
+ return begin_raw_quad (level);
+ case 3:
+ return begin_raw_hex (level);
+ default:
+ Assert (false, ExcNotImplemented());
+ return raw_cell_iterator();
+ }
+}
+
+
+
+template <int dim, int spacedim>
+typename Triangulation<dim,spacedim>::cell_iterator
+Triangulation<dim,spacedim>::begin (const unsigned int level) const
+{
+ switch (dim)
+ {
+ case 1:
+ return begin_line (level);
+ case 2:
+ return begin_quad (level);
+ case 3:
+ return begin_hex (level);
+ default:
+ Assert (false, ExcImpossibleInDim(dim));
+ return cell_iterator();
+ }
+}
+
+
+
+template <int dim, int spacedim>
+typename Triangulation<dim,spacedim>::active_cell_iterator
+Triangulation<dim,spacedim>::begin_active (const unsigned int level) const
+{
+ switch (dim)
+ {
+ case 1:
+ return begin_active_line (level);
+ case 2:
+ return begin_active_quad (level);
+ case 3:
+ return begin_active_hex (level);
+ default:
+ Assert (false, ExcNotImplemented());
+ return active_cell_iterator();
+ }
+}
+
+
+
+template <int dim, int spacedim>
+typename Triangulation<dim,spacedim>::raw_cell_iterator
+Triangulation<dim,spacedim>::last_raw () const
+{
+ switch (dim)
+ {
+ case 1:
+ return last_raw_line ();
+ case 2:
+ return last_raw_quad ();
+ case 3:
+ return last_raw_hex ();
+ default:
+ Assert (false, ExcNotImplemented());
+ return raw_cell_iterator();
+ }
+}
+
+
+
+template <int dim, int spacedim>
+typename Triangulation<dim,spacedim>::raw_cell_iterator
+Triangulation<dim,spacedim>::last_raw (const unsigned int level) const
+{
+ switch (dim)
+ {
+ case 1:
+ return last_raw_line (level);
+ case 2:
+ return last_raw_quad (level);
+ case 3:
+ return last_raw_hex (level);
+ default:
+ Assert (false, ExcNotImplemented());
+ return raw_cell_iterator();
+ }
+}
+
+
+
+template <int dim, int spacedim>
+typename Triangulation<dim,spacedim>::cell_iterator
+Triangulation<dim,spacedim>::last () const
+{
+ switch (dim)
+ {
+ case 1:
+ return last_line ();
+ case 2:
+ return last_quad ();
+ case 3:
+ return last_hex ();
+ default:
+ Assert (false, ExcNotImplemented());
+ return cell_iterator();
+ }
+}
+
+
+
+template <int dim, int spacedim>
+typename Triangulation<dim,spacedim>::cell_iterator
+Triangulation<dim,spacedim>::last (const unsigned int level) const
+{
+ switch (dim)
+ {
+ case 1:
+ return last_line (level);
+ case 2:
+ return last_quad (level);
+ case 3:
+ return last_hex (level);
+ default:
+ Assert (false, ExcNotImplemented());
+ return cell_iterator();
+ }
+}
+
+
+
+template <int dim, int spacedim>
+typename Triangulation<dim,spacedim>::active_cell_iterator
+Triangulation<dim,spacedim>::last_active () const
+{
+ switch (dim)
+ {
+ case 1:
+ return last_active_line ();
+ case 2:
+ return last_active_quad ();
+ case 3:
+ return last_active_hex ();
+ default:
+ Assert (false, ExcNotImplemented());
+ return active_cell_iterator();
+ }
+}
+
+
+
+template <int dim, int spacedim>
+typename Triangulation<dim,spacedim>::active_cell_iterator
+Triangulation<dim,spacedim>::last_active (const unsigned int level) const
+{
+ switch (dim)
+ {
+ case 1:
+ return last_active_line (level);
+ case 2:
+ return last_active_quad (level);
+ case 3:
+ return last_active_hex (level);
+ default:
+ Assert (false, ExcNotImplemented());
+ return active_cell_iterator();
+ }
+}
+
+
+template <int dim, int spacedim>
+typename Triangulation<dim,spacedim>::raw_cell_iterator
+Triangulation<dim,spacedim>::end () const
+{
+ switch (dim)
+ {
+ case 1:
+ return end_line();
+ case 2:
+ return end_quad();
+ case 3:
+ return end_hex();
+ default:
+ Assert (false, ExcImpossibleInDim(dim));
+ return raw_cell_iterator();
+ }
+}
+
+
+
+template <int dim, int spacedim>
+typename Triangulation<dim, spacedim>::raw_cell_iterator
+Triangulation<dim, spacedim>::end_raw (const unsigned int level) const
+{
+ return (level == levels.size()-1 ?
+ end() :
+ begin_raw (level+1));
+}
+
+
+template <int dim, int spacedim>
+typename Triangulation<dim, spacedim>::cell_iterator
+Triangulation<dim, spacedim>::end (const unsigned int level) const
+{
+ return (level == levels.size()-1 ?
+ cell_iterator(end()) :
+ begin (level+1));
+}
+
+
+template <int dim, int spacedim>
+typename Triangulation<dim, spacedim>::active_cell_iterator
+Triangulation<dim, spacedim>::end_active (const unsigned int level) const
+{
+ return (level == levels.size()-1 ?
+ active_cell_iterator(end()) :
+ begin_active (level+1));
+}
+
+
+/*------------------------ Face iterator functions ------------------------*/
+
+
+template <int dim, int spacedim>
+typename Triangulation<dim,spacedim>::raw_face_iterator
+Triangulation<dim,spacedim>::begin_raw_face () const
+{
+ switch (dim)
+ {
+ case 1:
+ Assert (false, ExcImpossibleInDim(1));
+ return raw_face_iterator();
+ case 2:
+ return begin_raw_line ();
+ case 3:
+ return begin_raw_quad ();
+ default:
+ Assert (false, ExcNotImplemented());
+ return raw_face_iterator ();
+ }
+}
+
+
+
+template <int dim, int spacedim>
+typename Triangulation<dim,spacedim>::face_iterator
+Triangulation<dim,spacedim>::begin_face () const
+{
+ switch (dim)
+ {
+ case 1:
+ Assert (false, ExcImpossibleInDim(1));
+ return raw_face_iterator();
+ case 2:
+ return begin_line ();
+ case 3:
+ return begin_quad ();
+ default:
+ Assert (false, ExcNotImplemented());
+ return face_iterator ();
+ }
+}
+
+
+
+template <int dim, int spacedim>
+typename Triangulation<dim,spacedim>::active_face_iterator
+Triangulation<dim,spacedim>::begin_active_face () const
+{
+ switch (dim)
+ {
+ case 1:
+ Assert (false, ExcImpossibleInDim(1));
+ return raw_face_iterator();
+ case 2:
+ return begin_active_line ();
+ case 3:
+ return begin_active_quad ();
+ default:
+ Assert (false, ExcNotImplemented());
+ return active_face_iterator ();
+ }
+}
+
+
+
+template <int dim, int spacedim>
+typename Triangulation<dim, spacedim>::raw_face_iterator
+Triangulation<dim, spacedim>::end_raw_face () const
+{
+ return end_face();
+}
+
+
+
+template <int dim, int spacedim>
+typename Triangulation<dim,spacedim>::raw_face_iterator
+Triangulation<dim,spacedim>::end_face () const
+{
+ switch (dim)
+ {
+ case 1:
+ Assert (false, ExcImpossibleInDim(1));
+ return raw_face_iterator();
+ case 2:
+ return end_line ();
+ case 3:
+ return end_quad ();
+ default:
+ Assert (false, ExcNotImplemented());
+ return raw_face_iterator ();
+ }
+}
+
+
+
+template <int dim, int spacedim>
+typename Triangulation<dim, spacedim>::active_face_iterator
+Triangulation<dim, spacedim>::end_active_face () const
+{
+ return active_face_iterator(end_face());
+}
+
+
+
+
+
+template <int dim, int spacedim>
+typename Triangulation<dim,spacedim>::raw_face_iterator
+Triangulation<dim,spacedim>::last_raw_face () const
+{
+ switch (dim)
+ {
+ case 1:
+ Assert (false, ExcImpossibleInDim(1));
+ return raw_face_iterator();
+ case 2:
+ return last_raw_line ();
+ case 3:
+ return last_raw_quad ();
+ default:
+ Assert (false, ExcNotImplemented());
+ return raw_face_iterator ();
+ }
+}
+
+
+
+template <int dim, int spacedim>
+typename Triangulation<dim,spacedim>::face_iterator
+Triangulation<dim,spacedim>::last_face () const
+{
+ switch (dim)
+ {
+ case 1:
+ Assert (false, ExcImpossibleInDim(1));
+ return raw_face_iterator();
+ case 2:
+ return last_line ();
+ case 3:
+ return last_quad ();
+ default:
+ Assert (false, ExcNotImplemented());
+ return raw_face_iterator ();
+ }
+}
+
+
+
+template <int dim, int spacedim>
+typename Triangulation<dim,spacedim>::active_face_iterator
+Triangulation<dim,spacedim>::last_active_face () const
+{
+ switch (dim)
+ {
+ case 1:
+ Assert (false, ExcImpossibleInDim(1));
+ return raw_face_iterator();
+ case 2:
+ return last_active_line ();
+ case 3:
+ return last_active_quad ();
+ default:
+ Assert (false, ExcNotImplemented());
+ return raw_face_iterator ();
+ }
+}
+
+
+/*------------------------ Line iterator functions ------------------------*/
+
+
+
+template <int dim, int spacedim>
+typename Triangulation<dim, spacedim>::raw_line_iterator
+Triangulation<dim, spacedim>::begin_raw_line (const unsigned int level) const
+{
+ switch (dim)
+ {
+ case 1:
+ Assert (level<levels.size(), ExcInvalidLevel(level));
+
+ if (levels[level]->cells.cells.size() == 0)
+ return end_line ();
+
+ return raw_line_iterator (const_cast<Triangulation<dim,spacedim>*>(this),
+ level,
+ 0);
+
+ default:
+ Assert (level == 0, ExcFacesHaveNoLevel());
+ return raw_line_iterator (const_cast<Triangulation<dim, spacedim>*>(this),
+ 0,
+ 0);
+ }
+}
+
+
+template <int dim, int spacedim>
+typename Triangulation<dim, spacedim>::line_iterator
+Triangulation<dim, spacedim>::begin_line (const unsigned int level) const
+{
+ // level is checked in begin_raw
+ raw_line_iterator ri = begin_raw_line (level);
+ if (ri.state() != IteratorState::valid)
+ return ri;
+ while (ri->used() == false)
+ if ((++ri).state() != IteratorState::valid)
+ return ri;
+ return ri;
+}
+
+
+
+template <int dim, int spacedim>
+typename Triangulation<dim, spacedim>::active_line_iterator
+Triangulation<dim, spacedim>::begin_active_line (const unsigned int level) const
+{
+ // level is checked in begin_raw
+ line_iterator i = begin_line (level);
+ if (i.state() != IteratorState::valid)
+ return i;
+ while (i->has_children())
+ if ((++i).state() != IteratorState::valid)
+ return i;
+ return i;
+}
+
+
+
+template <int dim, int spacedim>
+typename Triangulation<dim, spacedim>::raw_line_iterator
+Triangulation<dim, spacedim>::end_line () const
+{
+ return raw_line_iterator (const_cast<Triangulation<dim, spacedim>*>(this),
+ -1,
+ -1);
+}
+
+
+
+template <int dim, int spacedim>
+typename Triangulation<dim, spacedim>::raw_line_iterator
+Triangulation<dim, spacedim>::last_raw_line (const unsigned int level) const
+{
+ switch (dim)
+ {
+ case 1:
+ Assert (level<levels.size(), ExcInvalidLevel(level));
+ Assert (levels[level]->cells.cells.size() != 0,
+ ExcEmptyLevel (level));
+
+ return raw_line_iterator (const_cast<Triangulation<dim,spacedim>*>(this),
+ level,
+ levels[level]->cells.cells.size()-1);
+
+ default:
+ Assert (level == 0, ExcFacesHaveNoLevel());
+ return raw_line_iterator (const_cast<Triangulation<dim, spacedim>*>(this),
+ 0,
+ n_raw_lines()-1);
+ }
+}
+
+
+
+template <int dim, int spacedim>
+typename Triangulation<dim, spacedim>::raw_line_iterator
+Triangulation<dim, spacedim>::last_raw_line () const
+{
+ if (dim == 1)
+ return last_raw_line (levels.size()-1);
+ else
+ return last_raw_line (0);
+}
+
+
+template <int dim, int spacedim>
+typename Triangulation<dim, spacedim>::line_iterator
+Triangulation<dim, spacedim>::last_line (const unsigned int level) const
+{
+ // level is checked in last_raw
+ raw_line_iterator ri = last_raw_line(level);
+ if (ri->used()==true)
+ return ri;
+ while ((--ri).state() == IteratorState::valid)
+ if (ri->used()==true)
+ return ri;
+ return ri;
+}
+
+
+template <int dim, int spacedim>
+typename Triangulation<dim, spacedim>::line_iterator
+Triangulation<dim, spacedim>::last_line () const
+{
+ if (dim == 1)
+ return last_line (levels.size()-1);
+ else
+ return last_line (0);
+}
+
+
+template <int dim, int spacedim>
+typename Triangulation<dim, spacedim>::active_line_iterator
+Triangulation<dim, spacedim>::last_active_line (const unsigned int level) const
+{
+ // level is checked in last_raw
+ line_iterator i = last_line(level);
+ if (i->has_children()==false)
+ return i;
+ while ((--i).state() == IteratorState::valid)
+ if (i->has_children()==false)
+ return i;
+ return i;
+}
+
+
+template <int dim, int spacedim>
+typename Triangulation<dim, spacedim>::active_line_iterator
+Triangulation<dim, spacedim>::last_active_line () const
+{
+ if (dim == 1)
+ return last_active_line (levels.size()-1);
+ else
+ return last_active_line (0);
+}
+
+
+template <int dim, int spacedim>
+typename Triangulation<dim, spacedim>::raw_line_iterator
+Triangulation<dim, spacedim>::end_raw_line (const unsigned int level) const
+{
+ Assert (dim == 1 || level == 0, ExcFacesHaveNoLevel());
+ if (dim == 1)
+ return (level == levels.size()-1 ?
+ end_line() :
+ begin_raw_line (level+1));
+ else
+ return end_line();
+}
+
+
+template <int dim, int spacedim>
+typename Triangulation<dim, spacedim>::line_iterator
+Triangulation<dim, spacedim>::end_line (const unsigned int level) const
+{
+ Assert (dim == 1 || level == 0, ExcFacesHaveNoLevel());
+ if (dim == 1)
+ return (level == levels.size()-1 ?
+ line_iterator(end_line()) :
+ begin_line (level+1));
+ else
+ return line_iterator(end_line());
+}
+
+
+template <int dim, int spacedim>
+typename Triangulation<dim, spacedim>::active_line_iterator
+Triangulation<dim, spacedim>::end_active_line (const unsigned int level) const
+{
+ Assert (dim == 1 || level == 0, ExcFacesHaveNoLevel());
+ if (dim == 1)
+ return (level == levels.size()-1 ?
+ active_line_iterator(end_line()) :
+ begin_active_line (level+1));
+ else
+ return active_line_iterator(end_line());
+}
+
+
+
+/*------------------------ Quad iterator functions ------------------------*/
+
+
+template <int dim, int spacedim>
+typename Triangulation<dim,spacedim>::raw_quad_iterator
+Triangulation<dim,spacedim>::begin_raw_quad (const unsigned int level) const
+{
+ switch (dim)
+ {
+ case 1:
+ Assert (false, ExcImpossibleInDim(1));
+ return raw_hex_iterator();
+ case 2:
+ {
+ Assert (level<levels.size(), ExcInvalidLevel(level));
+
+ if (levels[level]->cells.cells.size() == 0)
+ return end_quad();
+
+ return raw_quad_iterator (const_cast<Triangulation<dim,spacedim>*>(this),
+ level,
+ 0);
+ }
+
+ case 3:
+ {
+ Assert (level == 0, ExcFacesHaveNoLevel());
+
+ return raw_quad_iterator (const_cast<Triangulation<dim,spacedim>*>(this),
+ 0,
+ 0);
+ }
+
+
+ default:
+ Assert (false, ExcNotImplemented());
+ return raw_hex_iterator();
+ }
+}
+
+
+
+template <int dim, int spacedim>
+typename Triangulation<dim,spacedim>::quad_iterator
+Triangulation<dim,spacedim>::begin_quad (const unsigned int level) const
+{
+ // level is checked in begin_raw
+ raw_quad_iterator ri = begin_raw_quad (level);
+ if (ri.state() != IteratorState::valid)
+ return ri;
+ while (ri->used() == false)
+ if ((++ri).state() != IteratorState::valid)
+ return ri;
+ return ri;
+}
+
+
+
+template <int dim, int spacedim>
+typename Triangulation<dim,spacedim>::active_quad_iterator
+Triangulation<dim,spacedim>::begin_active_quad (const unsigned int level) const
+{
+ // level is checked in begin_raw
+ quad_iterator i = begin_quad (level);
+ if (i.state() != IteratorState::valid)
+ return i;
+ while (i->has_children())
+ if ((++i).state() != IteratorState::valid)
+ return i;
+ return i;
+}
+
+
+
+template <int dim, int spacedim>
+typename Triangulation<dim, spacedim>::raw_quad_iterator
+Triangulation<dim, spacedim>::end_raw_quad (const unsigned int level) const
+{
+ Assert (dim == 2 || level == 0, ExcFacesHaveNoLevel());
+ if (dim == 2)
+ return (level == levels.size()-1 ?
+ end_quad() :
+ begin_raw_quad (level+1));
+ else
+ return end_quad();
+}
+
+
+
+template <int dim, int spacedim>
+typename Triangulation<dim, spacedim>::quad_iterator
+Triangulation<dim, spacedim>::end_quad (const unsigned int level) const
+{
+ Assert (dim == 2 || level == 0, ExcFacesHaveNoLevel());
+ if (dim == 2)
+ return (level == levels.size()-1 ?
+ quad_iterator(end_quad()) :
+ begin_quad (level+1));
+ else
+ return quad_iterator(end_quad());
+}
+
+
+template <int dim, int spacedim>
+typename Triangulation<dim, spacedim>::active_quad_iterator
+Triangulation<dim, spacedim>::end_active_quad (const unsigned int level) const
+{
+ Assert(dim == 2 || level == 0, ExcFacesHaveNoLevel());
+ if (dim == 2)
+ return (level == levels.size()-1 ?
+ active_quad_iterator(end_quad()) :
+ begin_active_quad (level+1));
+ else
+ return active_quad_iterator(end_quad());
+}
+
+
+
+template <int dim, int spacedim>
+typename Triangulation<dim,spacedim>::raw_quad_iterator
+Triangulation<dim,spacedim>::end_quad () const
+{
+ return raw_quad_iterator (const_cast<Triangulation<dim, spacedim>*>(this),
+ -1,
+ -1);
+}
+
+
+
+template <int dim, int spacedim>
+typename Triangulation<dim,spacedim>::raw_quad_iterator
+Triangulation<dim,spacedim>::last_raw_quad (const unsigned int level) const
+{
+ switch (dim)
+ {
+ case 1:
+ Assert (false, ExcImpossibleInDim(1));
+ return raw_quad_iterator();
+ case 2:
+ Assert (level<levels.size(),
+ ExcInvalidLevel(level));
+ Assert (levels[level]->cells.cells.size() != 0,
+ ExcEmptyLevel (level));
+ return raw_quad_iterator (const_cast<Triangulation<dim,spacedim>*>(this),
+ level,
+ levels[level]->cells.cells.size()-1);
+ case 3:
+ Assert (level == 0, ExcFacesHaveNoLevel());
+ return raw_quad_iterator (const_cast<Triangulation<dim,spacedim>*>(this),
+ 0,
+ n_raw_quads()-1);
+ default:
+ Assert (false, ExcNotImplemented());
+ return raw_quad_iterator();
+ }
+}
+
+
+
+template <int dim, int spacedim>
+typename Triangulation<dim,spacedim>::raw_quad_iterator
+Triangulation<dim,spacedim>::last_raw_quad () const
+{
+ if (dim == 2)
+ return last_raw_quad (levels.size()-1);
+ else
+ return last_raw_quad (0);
+}
+
+
+
+template <int dim, int spacedim>
+typename Triangulation<dim,spacedim>::quad_iterator
+Triangulation<dim,spacedim>::last_quad (const unsigned int level) const
+{
+ // level is checked in last_raw
+ raw_quad_iterator ri = last_raw_quad(level);
+ if (ri->used()==true)
+ return ri;
+ while ((--ri).state() == IteratorState::valid)
+ if (ri->used()==true)
+ return ri;
+ return ri;
+}
+
+
+
+template <int dim, int spacedim>
+typename Triangulation<dim,spacedim>::quad_iterator
+Triangulation<dim,spacedim>::last_quad () const
+{
+ if (dim == 2)
+ return last_quad (levels.size()-1);
+ else
+ return last_quad (0);
+}
+
+
+
+template <int dim, int spacedim>
+typename Triangulation<dim,spacedim>::active_quad_iterator
+Triangulation<dim,spacedim>::last_active_quad (const unsigned int level) const
+{
+ // level is checked in last_raw
+ quad_iterator i = last_quad(level);
+ if (i->has_children()==false)
+ return i;
+ while ((--i).state() == IteratorState::valid)
+ if (i->has_children()==false)
+ return i;
+ return i;
+}
+
+
+
+template <int dim, int spacedim>
+typename Triangulation<dim,spacedim>::active_quad_iterator
+Triangulation<dim,spacedim>::last_active_quad () const
+{
+ if (dim == 2)
+ return last_active_quad (levels.size()-1);
+ else
+ return last_active_quad (0);
+}
+
+
+/*------------------------ Hex iterator functions ------------------------*/
+
+
+template <int dim, int spacedim>
+typename Triangulation<dim,spacedim>::raw_hex_iterator
+Triangulation<dim,spacedim>::begin_raw_hex (const unsigned int level) const
+{
+ switch (dim)
+ {
+ case 1:
+ case 2:
+ Assert (false, ExcImpossibleInDim(1));
+ return raw_hex_iterator();
+ case 3:
+ {
+ Assert (level<levels.size(), ExcInvalidLevel(level));
+
+ if (levels[level]->cells.cells.size() == 0)
+ return end_hex();
+
+ return raw_hex_iterator (const_cast<Triangulation<dim,spacedim>*>(this),
+ level,
+ 0);
+ }
+
+ default:
+ Assert (false, ExcNotImplemented());
+ return raw_hex_iterator();
+ }
+}
+
+
+
+template <int dim, int spacedim>
+typename Triangulation<dim,spacedim>::hex_iterator
+Triangulation<dim,spacedim>::begin_hex (const unsigned int level) const
+{
+ // level is checked in begin_raw
+ raw_hex_iterator ri = begin_raw_hex (level);
+ if (ri.state() != IteratorState::valid)
+ return ri;
+ while (ri->used() == false)
+ if ((++ri).state() != IteratorState::valid)
+ return ri;
+ return ri;
+}
+
+
+
+template <int dim, int spacedim>
+typename Triangulation<dim, spacedim>::active_hex_iterator
+Triangulation<dim, spacedim>::begin_active_hex (const unsigned int level) const
+{
+ // level is checked in begin_raw
+ hex_iterator i = begin_hex (level);
+ if (i.state() != IteratorState::valid)
+ return i;
+ while (i->has_children())
+ if ((++i).state() != IteratorState::valid)
+ return i;
+ return i;
+}
+
+
+
+template <int dim, int spacedim>
+typename Triangulation<dim, spacedim>::raw_hex_iterator
+Triangulation<dim, spacedim>::end_raw_hex (const unsigned int level) const
+{
+ return (level == levels.size()-1 ?
+ end_hex() :
+ begin_raw_hex (level+1));
+}
+
+
+template <int dim, int spacedim>
+typename Triangulation<dim, spacedim>::hex_iterator
+Triangulation<dim, spacedim>::end_hex (const unsigned int level) const
+{
+ return (level == levels.size()-1 ?
+ hex_iterator(end_hex()) :
+ begin_hex (level+1));
+}
+
+
+template <int dim, int spacedim>
+typename Triangulation<dim, spacedim>::active_hex_iterator
+Triangulation<dim, spacedim>::end_active_hex (const unsigned int level) const
+{
+ return (level == levels.size()-1 ?
+ active_hex_iterator(end_hex()) :
+ begin_active_hex (level+1));
+}
+
+
+
+template <int dim, int spacedim>
+typename Triangulation<dim, spacedim>::raw_hex_iterator
+Triangulation<dim, spacedim>::end_hex () const
+{
+ return raw_hex_iterator (const_cast<Triangulation<dim,spacedim>*>(this),
+ -1,
+ -1);
+}
+
+
+
+template <int dim, int spacedim>
+typename Triangulation<dim, spacedim>::raw_hex_iterator
+Triangulation<dim, spacedim>::last_raw_hex (const unsigned int level) const
+{
+ switch (dim)
+ {
+ case 1:
+ case 2:
+ Assert (false, ExcImpossibleInDim(dim));
+ return raw_hex_iterator();
+
+ case 3:
+ Assert (level<levels.size(),
+ ExcInvalidLevel(level));
+ Assert (levels[level]->cells.cells.size() != 0,
+ ExcEmptyLevel (level));
+
+ return raw_hex_iterator (const_cast<Triangulation<dim,spacedim>*>(this),
+ level,
+ levels[level]->cells.cells.size()-1);
+ default:
+ Assert (false, ExcNotImplemented());
+ return raw_hex_iterator();
+ }
+}
+
+
+
+template <int dim, int spacedim>
+typename Triangulation<dim, spacedim>::raw_hex_iterator
+Triangulation<dim, spacedim>::last_raw_hex () const
+{
+ return last_raw_hex (levels.size()-1);
+}
+
+
+
+template <int dim, int spacedim>
+typename Triangulation<dim, spacedim>::hex_iterator
+Triangulation<dim, spacedim>::last_hex (const unsigned int level) const
+{
+ // level is checked in last_raw
+ raw_hex_iterator ri = last_raw_hex(level);
+ if (ri->used()==true)
+ return ri;
+ while ((--ri).state() == IteratorState::valid)
+ if (ri->used()==true)
+ return ri;
+ return ri;
+}
+
+
+
+template <int dim, int spacedim>
+typename Triangulation<dim, spacedim>::hex_iterator
+Triangulation<dim, spacedim>::last_hex () const
+{
+ return last_hex (levels.size()-1);
+}
+
+
+
+template <int dim, int spacedim>
+typename Triangulation<dim, spacedim>::active_hex_iterator
+Triangulation<dim, spacedim>::last_active_hex (const unsigned int level) const
+{
+ // level is checked in last_raw
+ hex_iterator i = last_hex(level);
+ if (i->has_children()==false)
+ return i;
+ while ((--i).state() == IteratorState::valid)
+ if (i->has_children()==false)
+ return i;
+ return i;
+}
+
+
+
+template <int dim, int spacedim>
+typename Triangulation<dim, spacedim>::active_hex_iterator
+Triangulation<dim, spacedim>::last_active_hex () const
+{
+ return last_active_hex (levels.size()-1);
+}
+
+
+
+// -------------------------------- number of cells etc ---------------
+
+
+namespace internal
+{
+ namespace Triangulation
+ {
+ inline
+ unsigned int
+ n_cells (const internal::Triangulation::NumberCache<1> &c)
+ {
+ return c.n_lines;
+ }
+
+
+ inline
+ unsigned int
+ n_active_cells (const internal::Triangulation::NumberCache<1> &c)
+ {
+ return c.n_active_lines;
+ }
+
+
+ inline
+ unsigned int
+ n_cells (const internal::Triangulation::NumberCache<2> &c)
+ {
+ return c.n_quads;
+ }
+
+
+ inline
+ unsigned int
+ n_active_cells (const internal::Triangulation::NumberCache<2> &c)
+ {
+ return c.n_active_quads;
+ }
+
+
+ inline
+ unsigned int
+ n_cells (const internal::Triangulation::NumberCache<3> &c)
+ {
+ return c.n_hexes;
+ }
+
+
+ inline
+ unsigned int
+ n_active_cells (const internal::Triangulation::NumberCache<3> &c)
+ {
+ return c.n_active_hexes;
+ }
+ }
+}
+
+
+
+template <int dim, int spacedim>
+unsigned int Triangulation<dim, spacedim>::n_cells () const
+{
+ return internal::Triangulation::n_cells (number_cache);
+}
+
+
+template <int dim, int spacedim>
+unsigned int Triangulation<dim, spacedim>::n_active_cells () const
+{
+ return internal::Triangulation::n_active_cells (number_cache);
+}
+
+
+template <int dim, int spacedim>
+unsigned int Triangulation<dim, spacedim>::n_faces () const
+{
+ switch (dim)
+ {
+ case 1:
+ return 0;
+ case 2:
+ return n_lines();
+ case 3:
+ return n_quads();
+ default:
+ Assert (false, ExcNotImplemented());
+ }
+ return 0;
+}
+
+
+template <int dim, int spacedim>
+unsigned int Triangulation<dim, spacedim>::n_raw_faces () const
+{
+ switch (dim)
+ {
+ case 2:
+ return n_raw_lines();
+ case 3:
+ return n_raw_quads();
+ default:
+ Assert (false, ExcNotImplemented());
+ }
+ return 0;
+}
+
+
+template <int dim, int spacedim>
+unsigned int Triangulation<dim, spacedim>::n_active_faces () const
+{
+ switch (dim)
+ {
+ case 1:
+ return 0;
+ case 2:
+ return n_active_lines();
+ case 3:
+ return n_active_quads();
+ default:
+ Assert (false, ExcNotImplemented());
+ }
+ return 0;
+}
+
+
+template <int dim, int spacedim>
+unsigned int Triangulation<dim, spacedim>::n_raw_cells (const unsigned int level) const
+{
+ switch (dim)
+ {
+ case 1:
+ return n_raw_lines(level);
+ case 2:
+ return n_raw_quads(level);
+ case 3:
+ return n_raw_hexs(level);
+ default:
+ Assert (false, ExcNotImplemented());
+ }
+ return 0;
+}
+
+
+
+template <int dim, int spacedim>
+unsigned int Triangulation<dim, spacedim>::n_cells (const unsigned int level) const
+{
+ switch (dim)
+ {
+ case 1:
+ return n_lines(level);
+ case 2:
+ return n_quads(level);
+ case 3:
+ return n_hexs(level);
+ default:
+ Assert (false, ExcNotImplemented());
+ }
+ return 0;
+}
+
+
+
+template <int dim, int spacedim>
+unsigned int Triangulation<dim, spacedim>::n_active_cells (const unsigned int level) const
+{
+ switch (dim)
+ {
+ case 1:
+ return n_active_lines(level);
+ case 2:
+ return n_active_quads(level);
+ case 3:
+ return n_active_hexs(level);
+ default:
+ Assert (false, ExcNotImplemented());
+ }
+ return 0;
+}
+
+
+
+template <int dim, int spacedim>
+unsigned int Triangulation<dim, spacedim>::n_lines () const
+{
+ return number_cache.n_lines;
+}
+
+
+
+template <>
+unsigned int Triangulation<1,1>::n_raw_lines (const unsigned int level) const
+{
+ Assert(level < n_levels(), ExcIndexRange(level,0,n_levels()));
+ return levels[level]->cells.cells.size();
+}
+
+
+template <>
+unsigned int Triangulation<1,1>::n_raw_lines () const
+{
+ Assert(false, ExcNotImplemented());
+ return 0;
+}
+
+
+
+template <>
+unsigned int Triangulation<1,2>::n_raw_lines (const unsigned int level) const
+{
+ Assert(level < n_levels(), ExcIndexRange(level,0,n_levels()));
+ return levels[level]->cells.cells.size();
+}
+
+
+template <>
+unsigned int Triangulation<1,2>::n_raw_lines () const
+{
+ Assert(false, ExcNotImplemented());
+ return 0;
+}
+
+
+
+template <int dim, int spacedim>
+unsigned int Triangulation<dim, spacedim>::n_raw_lines (const unsigned int) const
+{
+ Assert(false, ExcFacesHaveNoLevel());
+ return 0;
+}
+
+
+template <int dim, int spacedim>
+unsigned int Triangulation<dim, spacedim>::n_raw_lines () const
+{
+ return faces->lines.cells.size();
+}
+
+
+template <int dim, int spacedim>
+unsigned int Triangulation<dim, spacedim>::n_lines (const unsigned int level) const
+{
+ Assert (level < number_cache.n_lines_level.size(),
+ ExcIndexRange (level, 0, number_cache.n_lines_level.size()));
+ Assert (dim == 1, ExcFacesHaveNoLevel());
+ return number_cache.n_lines_level[level];
+}
+
+
+template <int dim, int spacedim>
+unsigned int Triangulation<dim, spacedim>::n_active_lines () const
+{
+ return number_cache.n_active_lines;
+}
+
+
+template <int dim, int spacedim>
+unsigned int Triangulation<dim, spacedim>::n_active_lines (const unsigned int level) const
+{
+ Assert (level < number_cache.n_lines_level.size(),
+ ExcIndexRange (level, 0, number_cache.n_lines_level.size()));
+ Assert (dim == 1, ExcFacesHaveNoLevel());
+
+ return number_cache.n_active_lines_level[level];
+}
+
+
+template <>
+unsigned int Triangulation<1,1>::n_quads () const
+{
+ return 0;
+}
+
+
+template <>
+unsigned int Triangulation<1,1>::n_quads (const unsigned int) const
+{
+ return 0;
+}
+
+
+template <>
+unsigned int Triangulation<1,1>::n_raw_quads (const unsigned int) const
+{
+ return 0;
+}
+
+
+template <>
+unsigned int Triangulation<1,1>::n_raw_hexs (const unsigned int) const
+{
+ return 0;
+}
+
+
+template <>
+unsigned int Triangulation<1,1>::n_active_quads (const unsigned int) const
+{
+ return 0;
+}
+
+
+template <>
+unsigned int Triangulation<1,1>::n_active_quads () const
+{
+ return 0;
+}
+
+
+template <>
+unsigned int Triangulation<1,2>::n_quads () const
+{
+ return 0;
+}
+
+
+template <>
+unsigned int Triangulation<1,2>::n_quads (const unsigned int) const
+{
+ return 0;
+}
+
+
+template <>
+unsigned int Triangulation<1,2>::n_raw_quads (const unsigned int) const
+{
+ return 0;
+}
+
+
+template <>
+unsigned int Triangulation<1,2>::n_raw_hexs (const unsigned int) const
+{
+ return 0;
+}
+
+
+template <>
+unsigned int Triangulation<1,2>::n_active_quads (const unsigned int) const
+{
+ return 0;
+}
+
+
+template <>
+unsigned int Triangulation<1,2>::n_active_quads () const
+{
+ return 0;
+}
+
+
+template <int dim, int spacedim>
+unsigned int Triangulation<dim, spacedim>::n_quads () const
+{
+ return number_cache.n_quads;
+}
+
+
+template <int dim, int spacedim>
+unsigned int Triangulation<dim, spacedim>::n_quads (const unsigned int level) const
+{
+ Assert (dim == 2, ExcFacesHaveNoLevel());
+ Assert (level < number_cache.n_quads_level.size(),
+ ExcIndexRange (level, 0, number_cache.n_quads_level.size()));
+ return number_cache.n_quads_level[level];
+}
+
+
+
+template <>
+unsigned int Triangulation<2,2>::n_raw_quads (const unsigned int level) const
+{
+ Assert(level < n_levels(), ExcIndexRange(level,0,n_levels()));
+ return levels[level]->cells.cells.size();
+}
+
+
+
+template <>
+unsigned int Triangulation<2,3>::n_raw_quads (const unsigned int level) const
+{
+ Assert(level < n_levels(), ExcIndexRange(level,0,n_levels()));
+ return levels[level]->cells.cells.size();
+}
+
+
+template <>
+unsigned int Triangulation<3,3>::n_raw_quads (const unsigned int) const
+{
+ Assert(false, ExcFacesHaveNoLevel());
+ return 0;
+}
+
+
+
+
+
+template <int dim, int spacedim>
+unsigned int Triangulation<dim, spacedim>::n_raw_quads () const
+{
+ Assert (false, ExcNotImplemented());
+ return 0;
+}
+
+
+
+template <>
+unsigned int Triangulation<3,3>::n_raw_quads () const
+{
+ return faces->quads.cells.size();
+}
+
+
+
+template <int dim, int spacedim>
+unsigned int Triangulation<dim, spacedim>::n_active_quads () const
+{
+ return number_cache.n_active_quads;
+}
+
+
+template <int dim, int spacedim>
+unsigned int Triangulation<dim, spacedim>::n_active_quads (const unsigned int level) const
+{
+ Assert (level < number_cache.n_quads_level.size(),
+ ExcIndexRange (level, 0, number_cache.n_quads_level.size()));
+ Assert (dim == 2, ExcFacesHaveNoLevel());
+
+ return number_cache.n_active_quads_level[level];
+}
+
+
+template <int dim, int spacedim>
+unsigned int Triangulation<dim, spacedim>::n_hexs () const
+{
+ return 0;
+}
+
+
+
+template <int dim, int spacedim>
+unsigned int Triangulation<dim, spacedim>::n_hexs (const unsigned int) const
+{
+ return 0;
+}
+
+
+
+template <int dim, int spacedim>
+unsigned int Triangulation<dim, spacedim>::n_raw_hexs (const unsigned int) const
+{
+ return 0;
+}
+
+
+template <int dim, int spacedim>
+unsigned int Triangulation<dim, spacedim>::n_active_hexs () const
+{
+ return 0;
+}
+
+
+
+template <int dim, int spacedim>
+unsigned int Triangulation<dim, spacedim>::n_active_hexs (const unsigned int) const
+{
+ return 0;
+}
+
+
+template <>
+unsigned int Triangulation<3,3>::n_hexs () const
+{
+ return number_cache.n_hexes;
+}
+
+
+
+template <>
+unsigned int Triangulation<3,3>::n_hexs (const unsigned int level) const
+{
+ Assert (level < number_cache.n_hexes_level.size(),
+ ExcIndexRange (level, 0, number_cache.n_hexes_level.size()));
+
+ return number_cache.n_hexes_level[level];
+}
+
+
+
+template <>
+unsigned int Triangulation<3,3>::n_raw_hexs (const unsigned int level) const
+{
+ Assert(level < n_levels(), ExcIndexRange(level,0,n_levels()));
+ return levels[level]->cells.cells.size();
+}
+
+
+template <>
+unsigned int Triangulation<3,3>::n_active_hexs () const
+{
+ return number_cache.n_active_hexes;
+}
+
+
+
+template <>
+unsigned int Triangulation<3,3>::n_active_hexs (const unsigned int level) const
+{
+ Assert (level < number_cache.n_hexes_level.size(),
+ ExcIndexRange (level, 0, number_cache.n_hexes_level.size()));
+
+ return number_cache.n_active_hexes_level[level];
+}
+
+
+
+template <int dim, int spacedim>
+unsigned int
+Triangulation<dim, spacedim>::n_used_vertices () const
+{
+ return std::count_if (vertices_used.begin(), vertices_used.end(),
+ std::bind2nd (std::equal_to<bool>(), true));
+}
+
+
+
+template <int dim, int spacedim>
+const std::vector<bool> &
+Triangulation<dim, spacedim>::get_used_vertices () const
+{
+ return vertices_used;
+}
+
+
+
+
+template <>
+unsigned int Triangulation<1,1>::max_adjacent_cells () const
+{
+ return 2;
+}
+
+
+
+template <>
+unsigned int Triangulation<1,2>::max_adjacent_cells () const
+{
+ return 2;
+}
+
+
+
+template <int dim, int spacedim>
+unsigned int Triangulation<dim, spacedim>::max_adjacent_cells () const
+{
+ cell_iterator cell = begin(0),
+ endc = (n_levels() > 1 ? begin(1) : cell_iterator(end()));
+ // store the largest index of the
+ // vertices used on level 0
+ unsigned int max_vertex_index = 0;
+ for (; cell!=endc; ++cell)
+ for (unsigned vertex=0; vertex<GeometryInfo<dim>::vertices_per_cell; ++vertex)
+ if (cell->vertex_index(vertex) > max_vertex_index)
+ max_vertex_index = cell->vertex_index(vertex);
+
+ // store the number of times a cell
+ // touches a vertex. An unsigned
+ // int should suffice, even for
+ // larger dimensions
+ std::vector<unsigned short int> usage_count (max_vertex_index+1, 0);
+ // touch a vertex's usage count
+ // everytime we find an adjacent
+ // element
+ for (cell=begin(); cell!=endc; ++cell)
+ for (unsigned vertex=0; vertex<GeometryInfo<dim>::vertices_per_cell; ++vertex)
+ ++usage_count[cell->vertex_index(vertex)];
+
+ return std::max (GeometryInfo<dim>::vertices_per_cell,
+ static_cast<unsigned int>(*std::max_element (usage_count.begin(),
+ usage_count.end())));
+}
+
+
+
+template <int dim, int spacedim>
+void
+Triangulation<dim, spacedim>::execute_coarsening_and_refinement ()
+{
+ prepare_coarsening_and_refinement ();
+
+ // verify a case with which we have had
+ // some difficulty in the past (see the
+ // deal.II/coarsening_* tests)
+ if (smooth_grid & limit_level_difference_at_vertices)
+ Assert (satisfies_level1_at_vertex_rule (*this) == true,
+ ExcInternalError());
+
+ // Inform RefinementListeners
+ // about beginning of refinement.
+ typename std::list<RefinementListener *>::iterator ref_listener =
+ refinement_listeners.begin (),
+ end_listener = refinement_listeners.end ();
+ for (; ref_listener != end_listener; ++ref_listener)
+ (*ref_listener)->pre_refinement_notification (*this);
+
+ execute_coarsening();
+
+ const DistortedCellList
+ cells_with_distorted_children = execute_refinement();
+
+ // verify a case with which we have had
+ // some difficulty in the past (see the
+ // deal.II/coarsening_* tests)
+ if (smooth_grid & limit_level_difference_at_vertices)
+ Assert (satisfies_level1_at_vertex_rule (*this) == true,
+ ExcInternalError());
+
+ // finally build up neighbor connectivity
+ // information
+ update_neighbors(*this);
+
+ // Inform RefinementListeners
+ // about end of refinement.
+ for (ref_listener = refinement_listeners.begin ();
+ ref_listener != end_listener; ++ref_listener)
+ (*ref_listener)->post_refinement_notification (*this);
+
+ AssertThrow (cells_with_distorted_children.distorted_cells.size() == 0,
+ cells_with_distorted_children);
+}
+
+
+template<int dim, int spacedim>
+void
+Triangulation<dim, spacedim>::clear_despite_subscriptions()
+{
+ // This is the former function
+ // clear without the assertion in
+ // the beginning.
+ for (unsigned int i=0; i<levels.size(); ++i)
+ delete levels[i];
+ levels.clear ();
+
+ delete faces;
+ faces = NULL;
+
+ vertices.clear ();
+ vertices_used.clear ();
+
+ for (unsigned int i=0; i<255; ++i)
+ boundary[i] = &straight_boundary;
+
+ number_cache = internal::Triangulation::NumberCache<dim>();
+}
+
+
+template <int dim, int spacedim>
+typename Triangulation<dim,spacedim>::DistortedCellList
+Triangulation<dim,spacedim>::execute_refinement ()
+{
+ const DistortedCellList
+ cells_with_distorted_children
+ =
+ internal::Triangulation::Implementation::
+ execute_refinement (*this,check_for_distorted_cells);
+
+
+
+ // re-compute number of lines
+ compute_number_cache (*this, levels.size(), number_cache);
+
+#ifdef DEBUG
+ for (unsigned int level=0; level<levels.size(); ++level)
+ levels[level]->cells.monitor_memory (dim);
+
+ // check whether really all
+ // refinement flags are reset (also
+ // of previously non-active cells
+ // which we may not have
+ // touched. If the refinement flag
+ // of a non-active cell is set,
+ // something went wrong since the
+ // cell-accessors should have
+ // caught this)
+ cell_iterator cell = begin(),
+ endc = end();
+ while (cell != endc)
+ Assert (!(cell++)->refine_flag_set(), ExcInternalError ());
+#endif
+
+ return cells_with_distorted_children;
+}
+
+
+
+template <int dim, int spacedim>
+void Triangulation<dim, spacedim>::execute_coarsening ()
+{
+ // create a vector counting for each line how
+ // many cells contain this line. in 3D, this
+ // is used later on to decide which lines can
+ // be deleted after coarsening a cell. in
+ // other dimensions it will be ignored
+ std::vector<unsigned int> line_cell_count = count_cells_bounded_by_line (*this);
+ std::vector<unsigned int> quad_cell_count = count_cells_bounded_by_quad (*this);
+
+ // loop over all cells. Flag all
+ // cells of which all children are
+ // flagged for
+ // coarsening and delete the childrens'
+ // flags. In effect, only those
+ // cells are flagged of which originally
+ // all children were flagged and for which
+ // all children are on the same refinement
+ // level. For flagging, the user flags are
+ // used, to avoid confusion and because
+ // non-active cells can't be flagged for
+ // coarsening. Note that because of the
+ // effects of @p{fix_coarsen_flags}, of a
+ // cell either all or no children must
+ // be flagged for coarsening, so it is
+ // ok to only check the first child
+ clear_user_flags ();
+
+ cell_iterator cell = begin(),
+ endc = end();
+ for (; cell!=endc; ++cell)
+ if (!cell->active())
+ if (cell->child(0)->coarsen_flag_set())
+ {
+ cell->set_user_flag();
+ for (unsigned int child=0; child<cell->n_children(); ++child)
+ {
+ Assert (cell->child(child)->coarsen_flag_set(),
+ ExcInternalError());
+ cell->child(child)->clear_coarsen_flag();
+ }
+ }
+
+
+ // now do the actual coarsening
+ // step. Since the loop goes over
+ // used cells we only need not
+ // worry about deleting some cells
+ // since the ++operator will then
+ // just hop over them if we should
+ // hit one. Do the loop in the
+ // reverse way since we may only
+ // delete some cells if their
+ // neighbors have already been
+ // deleted (if the latter are on a
+ // higher level for example)
+ //
+ // if there is only one level,
+ // there can not be anything to do
+ if (levels.size() >= 2)
+ for (cell = last(levels.size()-2); cell!=endc; --cell)
+ if (cell->user_flag_set())
+ // use a separate function,
+ // since this is dimension
+ // specific
+ internal::Triangulation::Implementation::delete_children (*this, cell,
+ line_cell_count, quad_cell_count);
+
+ // re-compute number of lines and
+ // quads
+ compute_number_cache (*this, levels.size(), number_cache);
+
+ // in principle no user flags
+ // should be
+ // set any more at this point
+#if DEBUG
+ for (cell=begin(); cell!=endc; ++cell)
+ Assert (cell->user_flag_set() == false, ExcInternalError());
+#endif
+}
+
+
+
+template <int dim, int spacedim>
+void Triangulation<dim, spacedim>::fix_coarsen_flags ()
+{
+ // copy a piece of code from
+ // prepare_coarsening_and_refinement that
+ // ensures that the level difference at
+ // vertices is limited if so desired. we
+ // need this code here since at least in 1d
+ // we don't call the dimension-independent
+ // version of
+ // prepare_coarsening_and_refinement
+ // function. in 2d and 3d, having this hunk
+ // here makes our lives a bit easier as
+ // well as it takes care of these cases
+ // earlier than it would otherwise happen.
+ //
+ // the main difference to the code
+ // in p_c_and_r is that here we
+ // absolutely have to make sure
+ // that we get things right,
+ // i.e. that in particular we set
+ // flags right if
+ // limit_level_difference_at_vertices
+ // is set. to do so we iterate
+ // until the flags don't change any
+ // more
+ std::vector<bool> previous_coarsen_flags (n_active_cells());
+ save_coarsen_flags (previous_coarsen_flags);
+
+ std::vector<int> vertex_level (vertices.size(), 0);
+
+ bool continue_iterating = true;
+
+ do
+ {
+ if (smooth_grid & limit_level_difference_at_vertices)
+ {
+ Assert(!anisotropic_refinement,
+ ExcMessage("In case of anisotropic refinement the "
+ "limit_level_difference_at_vertices flag for "
+ "mesh smoothing must not be set!"));
+
+ // store highest level one
+ // of the cells adjacent to
+ // a vertex belongs to
+ std::fill (vertex_level.begin(), vertex_level.end(), 0);
+ active_cell_iterator cell = begin_active(),
+ endc = end();
+ for (; cell!=endc; ++cell)
+ {
+ if (cell->refine_flag_set())
+ for (unsigned int vertex=0; vertex<GeometryInfo<dim>::vertices_per_cell;
+ ++vertex)
+ vertex_level[cell->vertex_index(vertex)]
+ = std::max (vertex_level[cell->vertex_index(vertex)],
+ cell->level()+1);
+ else if (!cell->coarsen_flag_set())
+ for (unsigned int vertex=0; vertex<GeometryInfo<dim>::vertices_per_cell;
+ ++vertex)
+ vertex_level[cell->vertex_index(vertex)]
+ = std::max (vertex_level[cell->vertex_index(vertex)],
+ cell->level());
+ else
+ {
+ // if coarsen flag is
+ // set then tentatively
+ // assume that the cell
+ // will be
+ // coarsened. this
+ // isn't always true
+ // (the coarsen flag
+ // could be removed
+ // again) and so we may
+ // make an error
+ // here. we try to
+ // correct this by
+ // iterating over the
+ // entire process until
+ // we are converged
+ Assert (cell->coarsen_flag_set(), ExcInternalError());
+ for (unsigned int vertex=0; vertex<GeometryInfo<dim>::vertices_per_cell;
+ ++vertex)
+ vertex_level[cell->vertex_index(vertex)]
+ = std::max (vertex_level[cell->vertex_index(vertex)],
+ cell->level()-1);
+ }
+ }
+
+
+ // loop over all cells in reverse
+ // order. do so because we can then
+ // update the vertex levels on the
+ // adjacent vertices and maybe
+ // already flag additional cells in
+ // this loop
+ //
+ // note that not only may we have
+ // to add additional refinement
+ // flags, but we will also have to
+ // remove coarsening flags on cells
+ // adjacent to vertices that will
+ // see refinement
+ for (cell=last_active(); cell != endc; --cell)
+ if (cell->refine_flag_set() == false)
+ {
+ for (unsigned int vertex=0;
+ vertex<GeometryInfo<dim>::vertices_per_cell; ++vertex)
+ if (vertex_level[cell->vertex_index(vertex)] >=
+ cell->level()+1)
+ {
+ // remove coarsen flag...
+ cell->clear_coarsen_flag();
+
+ // ...and if necessary also
+ // refine the current cell,
+ // at the same time
+ // updating the level
+ // information about
+ // vertices
+ if (vertex_level[cell->vertex_index(vertex)] >
+ cell->level()+1)
+ {
+ cell->set_refine_flag();
+
+ for (unsigned int v=0; v<GeometryInfo<dim>::vertices_per_cell;
+ ++v)
+ vertex_level[cell->vertex_index(v)]
+ = std::max (vertex_level[cell->vertex_index(v)],
+ cell->level()+1);
+ }
+
+ // continue and see whether
+ // we may, for example, go
+ // into the inner 'if'
+ // above based on a
+ // different vertex
+ }
+ }
+ }
+
+ // loop over all cells. Flag all
+ // cells of which all children are
+ // flagged for coarsening and
+ // delete the childrens'
+ // flags. Also delete all flags of
+ // cells for which not all children
+ // of a cell are flagged. In
+ // effect, only those cells are
+ // flagged of which originally all
+ // children were flagged and for
+ // which all children are on the
+ // same refinement level. For
+ // flagging, the user flags are
+ // used, to avoid confusion and
+ // because non-active cells can't
+ // be flagged for coarsening
+ //
+ // In effect, all coarsen flags are
+ // turned into user flags of the
+ // mother cell if coarsening is
+ // possible or deleted
+ // otherwise.
+ clear_user_flags ();
+ // Coarsen flags of
+ // cells with no mother cell,
+ // i.e. on the coarsest level are
+ // deleted explicitly.
+ active_cell_iterator acell = begin_active(0),
+ end_ac = end_active(0);
+ for (; acell!=end_ac; ++acell)
+ acell->clear_coarsen_flag();
+
+ cell_iterator cell = begin(),
+ endc = end();
+ for (; cell!=endc; ++cell)
+ {
+ // nothing to do if we are
+ // already on the finest level
+ if (cell->active())
+ continue;
+
+ const unsigned int n_children=cell->n_children();
+ unsigned int flagged_children=0;
+ for (unsigned int child=0; child<n_children; ++child)
+ if (cell->child(child)->active() &&
+ cell->child(child)->coarsen_flag_set())
+ {
+ ++flagged_children;
+ // clear flag since we
+ // don't need it anymore
+ cell->child(child)->clear_coarsen_flag();
+ }
+
+ // flag this cell for
+ // coarsening if all children
+ // were flagged
+ if (flagged_children == n_children)
+ cell->set_user_flag();
+ }
+
+ // in principle no coarsen flags
+ // should be set any more at this
+ // point
+#if DEBUG
+ for (cell=begin(); cell!=endc; ++cell)
+ Assert (cell->coarsen_flag_set() == false, ExcInternalError());
+#endif
+
+ // 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())
+ // if allowed: flag the
+ // children for coarsening
+ if (internal::Triangulation::Implementation::template coarsening_allowed<dim,spacedim>(cell))
+ for (unsigned int c=0; c<cell->n_children(); ++c)
+ {
+ Assert (cell->child(c)->refine_flag_set()==false,
+ ExcInternalError());
+
+ cell->child(c)->set_coarsen_flag();
+ }
+
+ // clear all user flags again, now that we
+ // don't need them any more
+ clear_user_flags ();
+
+
+ // now see if anything has
+ // changed in the last
+ // iteration of this function
+ std::vector<bool> current_coarsen_flags (n_active_cells());
+ save_coarsen_flags (current_coarsen_flags);
+
+ continue_iterating = (current_coarsen_flags != previous_coarsen_flags);
+ previous_coarsen_flags = current_coarsen_flags;
+ }
+ while (continue_iterating == true);
+}
+
+
+
+template <>
+bool Triangulation<1,1>::prepare_coarsening_and_refinement ()
+{
+ // save the flags to determine
+ // whether something was changed in
+ // the course of this function
+ std::vector<bool> flags_before;
+ save_coarsen_flags (flags_before);
+
+ // do nothing in 1d, except setting
+ // the coarsening flags correctly
+ fix_coarsen_flags ();
+
+ std::vector<bool> flags_after;
+ save_coarsen_flags (flags_after);
+
+ return (flags_before != flags_after);
+}
+
+
+template <>
+bool Triangulation<1,2>::prepare_coarsening_and_refinement ()
+{
+ // save the flags to determine
+ // whether something was changed in
+ // the course of this function
+ std::vector<bool> flags_before;
+ save_coarsen_flags (flags_before);
+
+ // do nothing in 1d, except setting
+ // the coarsening flags correctly
+ fix_coarsen_flags ();
+
+ std::vector<bool> flags_after;
+ save_coarsen_flags (flags_after);
+
+ return (flags_before != flags_after);
+}
+
+
+
+namespace
+{
+
+ // check if the given @param cell marked
+ // for coarsening would produce an
+ // unrefined island. To break up long
+ // chains of these cells we recursively
+ // check our neighbors in case we change
+ // this cell. This reduces the number of
+ // outer iterations dramatically.
+ template <int dim, int spacedim>
+ void
+ possibly_do_not_produce_unrefined_islands(
+ const typename Triangulation<dim,spacedim>::cell_iterator &cell)
+ {
+ Assert (cell->has_children(), ExcInternalError());
+
+ unsigned int n_neighbors=0;
+ // count all neighbors
+ // that will be refined
+ // along the face of our
+ // cell after the next
+ // step
+ unsigned int count=0;
+ for (unsigned int n=0; n<GeometryInfo<dim>::faces_per_cell; ++n)
+ {
+ const typename Triangulation<dim,spacedim>::cell_iterator neighbor = cell->neighbor(n);
+ if (neighbor.state() == IteratorState::valid)
+ {
+ ++n_neighbors;
+ if (face_will_be_refined_by_neighbor(cell,n))
+ ++count;
+ }
+ }
+ // clear coarsen flags if
+ // either all existing
+ // neighbors will be
+ // refined or all but one
+ // will be and the cell
+ // is in the interior of
+ // the domain
+ if (count==n_neighbors ||
+ (count>=n_neighbors-1 &&
+ n_neighbors == GeometryInfo<dim>::faces_per_cell) )
+ {
+ for (unsigned int c=0; c<cell->n_children(); ++c)
+ cell->child(c)->clear_coarsen_flag();
+
+ for (unsigned int face=0; face<GeometryInfo<dim>::faces_per_cell; ++face)
+ if (!cell->at_boundary(face)
+ &&
+ ( !cell->neighbor(face)->active() )
+ && (cell_will_be_coarsened(cell->neighbor(face))) )
+ possibly_do_not_produce_unrefined_islands<dim,spacedim>( cell->neighbor(face) );
+ }
+ }
+
+
+ // see if the current cell needs to
+ // be refined to avoid unrefined
+ // islands.
+ //
+ // there are sometimes chains of
+ // cells that induce refinement of
+ // each other. to avoid running the
+ // loop in
+ // prepare_coarsening_and_refinement
+ // over and over again for each one
+ // of them, at least for the
+ // isotropic refinement case we
+ // seek to flag neighboring
+ // elements as well as
+ // necessary. this takes care of
+ // (slightly pathological) cases
+ // like deal.II/mesh_smoothing_03
+ template <int dim, int spacedim>
+ void
+ possibly_refine_unrefined_island
+ (const typename Triangulation<dim,spacedim>::cell_iterator &cell,
+ const bool allow_anisotropic_smoothing)
+ {
+ Assert (cell->has_children() == false, ExcInternalError());
+ Assert (cell->refine_flag_set() == false, ExcInternalError());
+
+
+ // now we provide two
+ // algorithms. the first one is
+ // the standard one, coming from
+ // the time, where only isotropic
+ // refinement was possible. it
+ // simply counts the neighbors
+ // that are or will be refined
+ // and compares to the number of
+ // other ones. the second one
+ // does this check independently
+ // for each direction: if all
+ // neighbors in one direction
+ // (normally two, at the boundary
+ // only one) are refined, the
+ // current cell is flagged to be
+ // refined in an according
+ // direction.
+
+ if (allow_anisotropic_smoothing == false)
+ {
+ // use first algorithm
+ unsigned int refined_neighbors = 0,
+ unrefined_neighbors = 0;
+ for (unsigned int face=0; face<GeometryInfo<dim>::faces_per_cell; ++face)
+ if (!cell->at_boundary(face))
+ {
+ if (face_will_be_refined_by_neighbor(cell,face))
+ ++refined_neighbors;
+ else
+ ++unrefined_neighbors;
+ }
+
+ if (unrefined_neighbors < refined_neighbors)
+ {
+ cell->clear_coarsen_flag();
+ cell->set_refine_flag ();
+
+ // ok, so now we have
+ // flagged this cell. if
+ // we know that there
+ // were any unrefined
+ // neighbors at all, see
+ // if any of those will
+ // have to be refined as
+ // well
+ if (unrefined_neighbors > 0)
+ for (unsigned int face=0; face<GeometryInfo<dim>::faces_per_cell; ++face)
+ if (!cell->at_boundary(face)
+ &&
+ (face_will_be_refined_by_neighbor(cell,face) == false)
+ &&
+ (cell->neighbor(face)->has_children() == false)
+ &&
+ (cell->neighbor(face)->refine_flag_set() == false))
+ possibly_refine_unrefined_island<dim,spacedim>
+ (cell->neighbor(face),
+ allow_anisotropic_smoothing);
+ }
+ }
+ else
+ {
+ // variable to store the cell
+ // refine case needed to
+ // fulfill all smoothing
+ // requirements
+ RefinementCase<dim> smoothing_cell_refinement_case
+ = RefinementCase<dim>::no_refinement;
+
+ // use second algorithm, do
+ // the check individually for
+ // each direction
+ for (unsigned int face_pair=0;
+ face_pair<GeometryInfo<dim>::faces_per_cell/2; ++face_pair)
+ {
+ // variable to store the
+ // cell refine case
+ // needed to refine at
+ // the current face pair
+ // in the same way as the
+ // neighbors do...
+ RefinementCase<dim> directional_cell_refinement_case
+ = RefinementCase<dim>::isotropic_refinement;
+
+ for (unsigned int face_index=0; face_index<2; ++face_index)
+ {
+ unsigned int face=2*face_pair+face_index;
+ // variable to store
+ // the refine case
+ // (to come) of the
+ // face under
+ // consideration
+ RefinementCase<dim-1> expected_face_ref_case
+ = RefinementCase<dim-1>::no_refinement;
+
+ if (cell->neighbor(face).state() == IteratorState::valid)
+ face_will_be_refined_by_neighbor<dim,spacedim>(cell,face,expected_face_ref_case);
+ // now extract which
+ // refine case would
+ // be necessary to
+ // achive the same
+ // face
+ // refinement. set
+ // the intersection
+ // with other
+ // requirements for
+ // the same
+ // direction.
+
+ // note: using the
+ // intersection is
+ // not an obvious
+ // decision, we could
+ // also argue that it
+ // is more natural to
+ // use the
+ // union. however,
+ // intersection is
+ // the less
+ // aggressive tactic
+ // and favours a
+ // smaller number of
+ // refined cells over
+ // an intensive
+ // smoothing. this
+ // way we try not to
+ // loose too much of
+ // the effort we put
+ // in anisotropic
+ // refinement
+ // indicators due to
+ // overly aggressive
+ // smoothing...
+ directional_cell_refinement_case
+ = (directional_cell_refinement_case &
+ GeometryInfo<dim>::min_cell_refinement_case_for_face_refinement(
+ expected_face_ref_case,
+ face,
+ cell->face_orientation(face),
+ cell->face_flip(face),
+ cell->face_rotation(face)));
+ }//for both face indices
+ // if both requirements
+ // sum up to something
+ // useful, add this to
+ // the refine case for
+ // smoothing. note: if
+ // directional_cell_refinement_case
+ // is isotropic still,
+ // then something went
+ // wrong...
+ Assert(directional_cell_refinement_case <
+ RefinementCase<dim>::isotropic_refinement,
+ ExcInternalError());
+ smoothing_cell_refinement_case = smoothing_cell_refinement_case |
+ directional_cell_refinement_case;
+ }//for all face_pairs
+ // no we collected
+ // contributions from all
+ // directions. combine the
+ // new flags with the
+ // existing refine case, but
+ // only if smoothing is
+ // required
+ if (smoothing_cell_refinement_case)
+ {
+ cell->clear_coarsen_flag();
+ cell->set_refine_flag(cell->refine_flag_set() |
+ smoothing_cell_refinement_case);
+ }
+ }
+ }
+}
+
+
+template <int dim, int spacedim>
+bool Triangulation<dim,spacedim>::prepare_coarsening_and_refinement ()
+{
+ // save the flags to determine
+ // whether something was changed in
+ // the course of this function
+ std::vector<bool> flags_before[2];
+ save_coarsen_flags (flags_before[0]);
+ save_refine_flags (flags_before[1]);
+
+ // save the flags at the outset of
+ // each loop. we do so in order to
+ // find out whether something was
+ // changed in the present loop, in
+ // which case we would have to
+ // re-run the loop. the other
+ // possibility to find this out
+ // would be to set a flag
+ // @p{something_changed} to true
+ // each time we change something.
+ // however, sometimes one change in
+ // one of the parts of the loop is
+ // undone by another one, so we
+ // might end up in an endless
+ // loop. we could be tempted to
+ // break this loop at an arbitrary
+ // number of runs, but that would
+ // not be a clean solution, since
+ // we would either have to
+ // 1/ break the loop too early, in which
+ // case the promise that a second
+ // call to this function immediately
+ // after the first one does not
+ // change anything, would be broken,
+ // or
+ // 2/ we do as many loops as there are
+ // levels. we know that information
+ // is transported over one level
+ // in each run of the loop, so this
+ // is enough. Unfortunately, each
+ // loop is rather expensive, so
+ // we chose the way presented here
+ std::vector<bool> flags_before_loop[2] = {flags_before[0],
+ flags_before[1]};
+
+ // now for what is done in each
+ // loop: we have to fulfill several
+ // tasks at the same time, namely
+ // several mesh smoothing
+ // algorithms and mesh
+ // regularisation, by which we mean
+ // that the next mesh fulfills
+ // several requirements such as no
+ // double refinement at each face
+ // or line, etc.
+ //
+ // since doing these things at once
+ // seems almost impossible (in the
+ // first year of this library, they
+ // were done in two functions, one
+ // for refinement and one for
+ // coarsening, and most things
+ // within these were done at once,
+ // so the code was rather
+ // impossible to join into this,
+ // only, function), we do them one
+ // after each other. the order in
+ // which we do them is such that
+ // the important tasks, namely
+ // regularisation, are done last
+ // and the least important things
+ // are done the first. the
+ // following order is chosen:
+ //
+ // 0/ Only if coarsest_level_1 or
+ // patch_level_1 is set:
+ // clear all coarsen flags on level 1
+ // to avoid level 0 cells being
+ // created by coarsening.
+ // As coarsen flags will never be added,
+ // this can be done once and for all
+ // before the actual loop starts.
+ // 1/ do not coarsen a cell if
+ // 'most of the neighbors' will be
+ // refined after the step. This is
+ // to prevent occurence of
+ // unrefined islands.
+ // 2/ eliminate refined islands in the
+ // interior and at the boundary. since
+ // they don't do much harm besides
+ // increasing the number of degrees
+ // of freedom, doing this has a
+ // rather low priority.
+ // 3/ limit the level difference of
+ // neighboring cells at each vertex.
+ // 4/ eliminate unrefined islands. this
+ // has higher priority since this
+ // diminishes the approximation
+ // properties not only of the unrefined
+ // island, but also of the surrounding
+ // patch.
+ // 5/ ensure patch level 1. Then the
+ // triangulation consists of patches,
+ // i.e. of cells that are
+ // refined once. It follows that if at
+ // least one of the children of a cell
+ // is or will be refined than all children
+ // need to be refined. This step
+ // only sets refinement flags and does
+ // not set coarsening flags.
+ // If the patch_level_1 flag is set, then
+ // eliminate_unrefined_islands,
+ // eliminate_refined_inner_islands and
+ // eliminate_refined_boundary_islands will
+ // be fulfilled automatically and do not
+ // need to be enforced separately.
+ // 6/ take care of the requirement that no
+ // double refinement is done at each face
+ // 7/ take care that no double refinement
+ // is done at each line in 3d or higher
+ // dimensions.
+ // 8/ make sure that all children of each
+ // cell are either flagged for coarsening
+ // or none of the children is
+ //
+ // For some of these steps, it is
+ // known that they
+ // interact. Namely, it is not
+ // possible to guarantee that after
+ // step 6 another step 5 would have
+ // no effect; the same holds for
+ // the opposite order and also when
+ // taking into account step
+ // 7. however, it is important to
+ // guarantee that step five or six
+ // do not undo something that step
+ // 5 did, and step 7 not something
+ // of step 6, otherwise the
+ // requirements will not be
+ // satisfied even if the loop
+ // terminates. this is accomplished
+ // by the fact that steps 5 and 6
+ // only *add* refinement flags and
+ // delete coarsening flags
+ // (therefore, step 6 can't undo
+ // something that step 4 already
+ // did), and step 7 only deletes
+ // coarsening flags, never adds
+ // some. step 7 needs also take
+ // care that it won't tag cells for
+ // refinement for which some
+ // neighbors are more refined or
+ // will be refined.
+
+ //////////////////////////////////////
+ // STEP 0:
+ // Only if coarsest_level_1 or
+ // patch_level_1 is set:
+ // clear all coarsen flags on level 1
+ // to avoid level 0 cells being
+ // created by coarsening.
+ if (((smooth_grid & coarsest_level_1) ||
+ (smooth_grid & patch_level_1)) && n_levels()>=2)
+ {
+ active_cell_iterator
+ cell=begin_active(1),
+ endc=end_active(1);
+
+ for (; cell!=endc; ++cell)
+ cell->clear_coarsen_flag();
+ }
+
+ bool mesh_changed_in_this_loop = false;
+ do
+ {
+ //////////////////////////////////////
+ // STEP 1:
+ // do not coarsen a cell if 'most of
+ // the neighbors' will be refined after
+ // the step. This is to prevent the
+ // occurence of unrefined islands.
+ // If patch_level_1 is set, this will
+ // be automatically fulfilled.
+ if (smooth_grid & do_not_produce_unrefined_islands &&
+ !(smooth_grid & patch_level_1))
+ {
+ cell_iterator cell;
+ const cell_iterator endc = end();
+
+ for (cell=begin(); cell!=endc; ++cell)
+ {
+ // only do something if this
+ // cell will be coarsened
+ if (!cell->active() && cell_will_be_coarsened(cell))
+ possibly_do_not_produce_unrefined_islands<dim,spacedim>(cell);
+ }
+ }
+
+
+ //////////////////////////////////////
+ // STEP 2:
+ // eliminate refined islands in the
+ // interior and at the boundary. since
+ // they don't do much harm besides
+ // increasing the number of degrees of
+ // freedom, doing this has a rather low
+ // priority.
+ // If patch_level_1 is set, this will
+ // be automatically fulfilled.
+ //
+ // there is one corner case
+ // to consider: if this is a
+ // distributed
+ // triangulation, there may
+ // be refined islands on the
+ // boundary of which we own
+ // only part (e.g. a single
+ // cell in the corner of a
+ // domain). the rest of the
+ // island is ghost cells and
+ // it *looks* like the area
+ // around it (artificial
+ // cells) are coarser but
+ // this is only because they
+ // may actually be equally
+ // fine on other
+ // processors. it's hard to
+ // detect this case but we
+ // can do the following:
+ // only set coarsen flags to
+ // remove this refined
+ // island if all cells we
+ // want to set flags on are
+ // locally owned
+ if (smooth_grid & (eliminate_refined_inner_islands |
+ eliminate_refined_boundary_islands) &&
+ !(smooth_grid & patch_level_1))
+ {
+ cell_iterator cell;
+ const cell_iterator endc = end();
+
+ for (cell=begin(); cell!=endc; ++cell)
+ if (!cell->active() ||
+ (cell->active() &&
+ cell->refine_flag_set() &&
+ !cell->is_ghost() &&
+ !cell->is_artificial()))
+ {
+ // check whether all
+ // children are
+ // active, i.e. not
+ // refined
+ // themselves. This
+ // is a precondition
+ // that the children
+ // may be coarsened
+ // away. If the cell
+ // is only flagged
+ // for refinement,
+ // then all future
+ // children will be
+ // active
+ bool all_children_active = true;
+ if (!cell->active())
+ for (unsigned int c=0; c<cell->n_children(); ++c)
+ if (!cell->child(c)->active() ||
+ cell->child(c)->is_ghost() ||
+ cell->child(c)->is_artificial())
+ {
+ all_children_active = false;
+ break;
+ }
+
+ if (all_children_active)
+ {
+ // count number
+ // of refined and
+ // unrefined
+ // neighbors of
+ // cell.
+ // neighbors on
+ // lower levels
+ // are counted as
+ // unrefined
+ // since they can
+ // only get to
+ // the same level
+ // as this cell
+ // by the next
+ // refinement
+ // cycle
+ unsigned int unrefined_neighbors = 0,
+ total_neighbors = 0;
+
+ for (unsigned int n=0; n<GeometryInfo<dim>::faces_per_cell; ++n)
+ {
+ const cell_iterator neighbor = cell->neighbor(n);
+ if (neighbor.state() == IteratorState::valid)
+ {
+ ++total_neighbors;
+
+ if (!face_will_be_refined_by_neighbor(cell,n))
+ ++unrefined_neighbors;
+ }
+
+ }
+
+ // if all
+ // neighbors
+ // unrefined:
+ // mark this cell
+ // for coarsening
+ // or don't
+ // refine if
+ // marked for
+ // that
+ //
+ // also do the
+ // distinction
+ // between the
+ // two versions
+ // of the
+ // eliminate_refined_*_islands
+ // flag
+ //
+ // the last check
+ // is whether
+ // there are any
+ // neighbors at
+ // all. if not
+ // so, then we
+ // are (e.g.) on
+ // the coarsest
+ // grid with one
+ // cell, for
+ // which, of
+ // course, we do
+ // not remove the
+ // refine flag.
+ if ((unrefined_neighbors == total_neighbors)
+ &&
+ (((unrefined_neighbors==GeometryInfo<dim>::faces_per_cell) &&
+ (smooth_grid & eliminate_refined_inner_islands)) ||
+ ((unrefined_neighbors<GeometryInfo<dim>::faces_per_cell) &&
+ (smooth_grid & eliminate_refined_boundary_islands)) )
+ &&
+ (total_neighbors != 0))
+ {
+ if (!cell->active())
+ for (unsigned int c=0; c<cell->n_children(); ++c)
+ {
+ cell->child(c)->clear_refine_flag ();
+ cell->child(c)->set_coarsen_flag ();
+ }
+ else
+ cell->clear_refine_flag();
+ }
+ }
+ }
+ }
+
+ //////////////////////////////////////
+ // STEP 3:
+ // limit the level difference of
+ // neighboring cells at each vertex.
+ //
+ // in case of anisotropic refinement
+ // this does not make sense. as soon
+ // as one cell is anisotropically
+ // refined, an Assertion is
+ // thrown. therefore we can ignore
+ // this problem later on
+ if (smooth_grid & limit_level_difference_at_vertices)
+ {
+ Assert(!anisotropic_refinement,
+ ExcMessage("In case of anisotropic refinement the "
+ "limit_level_difference_at_vertices flag for "
+ "mesh smoothing must not be set!"));
+
+ // store highest level one
+ // of the cells adjacent to
+ // a vertex belongs to
+ std::vector<int> vertex_level (vertices.size(), 0);
+ active_cell_iterator cell = begin_active(),
+ endc = end();
+ for (; cell!=endc; ++cell)
+ {
+ if (cell->refine_flag_set())
+ for (unsigned int vertex=0; vertex<GeometryInfo<dim>::vertices_per_cell;
+ ++vertex)
+ vertex_level[cell->vertex_index(vertex)]
+ = std::max (vertex_level[cell->vertex_index(vertex)],
+ cell->level()+1);
+ else if (!cell->coarsen_flag_set())
+ for (unsigned int vertex=0; vertex<GeometryInfo<dim>::vertices_per_cell;
+ ++vertex)
+ vertex_level[cell->vertex_index(vertex)]
+ = std::max (vertex_level[cell->vertex_index(vertex)],
+ cell->level());
+ else
+ {
+ // if coarsen flag is set then
+ // tentatively assume that the
+ // cell will be coarsened. this
+ // isn't always true (the
+ // coarsen flag could be
+ // removed again) and so we may
+ // make an error here
+ Assert (cell->coarsen_flag_set(), ExcInternalError());
+ for (unsigned int vertex=0; vertex<GeometryInfo<dim>::vertices_per_cell;
+ ++vertex)
+ vertex_level[cell->vertex_index(vertex)]
+ = std::max (vertex_level[cell->vertex_index(vertex)],
+ cell->level()-1);
+ }
+ }
+
+
+ // loop over all cells in reverse
+ // order. do so because we can then
+ // update the vertex levels on the
+ // adjacent vertices and maybe
+ // already flag additional cells in
+ // this loop
+ //
+ // note that not only may we have
+ // to add additional refinement
+ // flags, but we will also have to
+ // remove coarsening flags on cells
+ // adjacent to vertices that will
+ // see refinement
+ for (cell=last_active(); cell != endc; --cell)
+ if (cell->refine_flag_set() == false)
+ {
+ for (unsigned int vertex=0;
+ vertex<GeometryInfo<dim>::vertices_per_cell; ++vertex)
+ if (vertex_level[cell->vertex_index(vertex)] >=
+ cell->level()+1)
+ {
+ // remove coarsen flag...
+ cell->clear_coarsen_flag();
+
+ // ...and if necessary also
+ // refine the current cell,
+ // at the same time
+ // updating the level
+ // information about
+ // vertices
+ if (vertex_level[cell->vertex_index(vertex)] >
+ cell->level()+1)
+ {
+ cell->set_refine_flag();
+
+ for (unsigned int v=0; v<GeometryInfo<dim>::vertices_per_cell;
+ ++v)
+ vertex_level[cell->vertex_index(v)]
+ = std::max (vertex_level[cell->vertex_index(v)],
+ cell->level()+1);
+ }
+
+ // continue and see whether
+ // we may, for example, go
+ // into the inner 'if'
+ // above based on a
+ // different vertex
+ }
+ }
+ }
+
+ /////////////////////////////////////
+ // STEP 4:
+ // eliminate unrefined
+ // islands. this has higher
+ // priority since this
+ // diminishes the
+ // approximation properties
+ // not only of the unrefined
+ // island, but also of the
+ // surrounding patch.
+ //
+ // do the loop from finest
+ // to coarsest cells since
+ // we may trigger a cascade
+ // by marking cells for
+ // refinement which may
+ // trigger more cells
+ // further down below
+ if (smooth_grid & eliminate_unrefined_islands)
+ {
+ active_cell_iterator cell=last_active(),
+ endc=end();
+
+ for (; cell != endc; --cell)
+ // only do something if
+ // cell is not already
+ // flagged for
+ // (isotropic) refinement
+ if (cell->refine_flag_set() != RefinementCase<dim>::isotropic_refinement)
+ possibly_refine_unrefined_island<dim,spacedim>
+ (cell,
+ (smooth_grid & allow_anisotropic_smoothing) != 0);
+ }
+
+ /////////////////////////////////
+ // STEP 5:
+ // ensure patch level 1.
+ //
+ // Introduce some terminology:
+ // - a cell that is refined
+ // once is a patch of
+ // level 1 simply called patch.
+ // - a cell that is globally
+ // refined twice is called
+ // a patch of level 2.
+ // - patch level n says that
+ // the triangulation consists
+ // of patches of level n.
+ // This makes sense only
+ // if the grid is already at
+ // least n times globally
+ // refined.
+ //
+ // E.g. from patch level 1
+ // follows: if at least one
+ // of the children of a cell
+ // is or will be refined
+ // than enforce all
+ // children to be
+ // refined.
+
+ // This step 4 only
+ // sets refinement flags and
+ // does not set coarsening
+ // flags.
+ if (smooth_grid & patch_level_1)
+ {
+ // An important assumption
+ // (A) is that before
+ // calling this function
+ // the grid was already of
+ // patch level 1.
+
+ // loop over all cells
+ // whose children are all
+ // active. (By assumption
+ // (A) either all or none
+ // of the children are
+ // active). If the refine
+ // flag of at least one of
+ // the children is set then
+ // set_refine_flag and
+ // clear_coarsen_flag of
+ // all children.
+ for (cell_iterator cell = begin(); cell != end(); ++cell)
+ if (!cell->active())
+ {
+ // ensure the
+ // invariant. we can
+ // then check whether
+ // all of its
+ // children are
+ // further refined or
+ // not by simply
+ // looking at the
+ // first child
+ Assert (cell_is_patch_level_1(cell),
+ ExcInternalError());
+ if (cell->child(0)->has_children() == true)
+ continue;
+
+ // cell is found to
+ // be a patch.
+ // combine the refine
+ // cases of all
+ // children
+ RefinementCase<dim> combined_ref_case = RefinementCase<dim>::no_refinement;
+ for (unsigned int i=0; i<cell->n_children(); ++i)
+ combined_ref_case = combined_ref_case |
+ cell->child(i)->refine_flag_set();
+ if (combined_ref_case != RefinementCase<dim>::no_refinement)
+ for (unsigned int i=0; i<cell->n_children(); ++i)
+ {
+ cell_iterator child = cell->child(i);
+
+ child->clear_coarsen_flag();
+ child->set_refine_flag(combined_ref_case);
+ }
+ }
+
+ // The code above dealt
+ // with the case where we
+ // may get a
+ // non-patch_level_1 mesh
+ // from refinement. Now
+ // also deal with the case
+ // where we could get such
+ // a mesh by coarsening.
+ // Coarsen the children
+ // (and remove the
+ // grandchildren) only if
+ // all cell->grandchild(i)
+ // ->coarsen_flag_set()
+ // are set.
+ //
+ // for a case where this is
+ // a bit tricky, take a
+ // look at the
+ // mesh_smoothing_0[12]
+ // testcases
+ for (cell_iterator cell = begin(); cell != end(); ++cell)
+ {
+ // check if this cell
+ // has active
+ // grandchildren. note
+ // that we know that it
+ // is patch_level_1,
+ // i.e. if one of its
+ // children is active
+ // then so are all, and
+ // it isn't going to
+ // have any
+ // grandchildren at
+ // all:
+ if (cell->active()
+ ||
+ cell->child(0)->active())
+ continue;
+
+ // cell is not active,
+ // and so are none of
+ // its children. check
+ // the
+ // grandchildren. note
+ // that the children
+ // are also
+ // patch_level_1, and
+ // so we only ever need
+ // to check their first
+ // child
+ const unsigned int n_children=cell->n_children();
+ bool has_active_grandchildren = false;
+
+ for (unsigned int i=0; i<n_children; ++i)
+ if (cell->child(i)->child(0)->active())
+ {
+ has_active_grandchildren = true;
+ break;
+ }
+
+ if (has_active_grandchildren == false)
+ continue;
+
+
+ // ok, there are active
+ // grandchildren. see
+ // if either all or
+ // none of them are
+ // flagged for
+ // coarsening
+ unsigned int n_grandchildren=0;
+ // count all coarsen
+ // flags of the
+ // grandchildren.
+ unsigned int n_coarsen_flags=0;
+ // cell is not a
+ // patch (of level 1)
+ // as it has a
+ // grandchild. Is
+ // cell a patch of
+ // level 2??
+ // Therefore: find
+ // out whether all
+ // cell->child(i) are
+ // patches
+ for (unsigned int c=0; c<n_children; ++c)
+ {
+ // get at the
+ // child. by
+ // assumption
+ // (A), and the
+ // check by which
+ // we got here,
+ // the child is
+ // not active
+ cell_iterator child=cell->child(c);
+
+ const unsigned int nn_children=child->n_children();
+ n_grandchildren += nn_children;
+
+ // if child is
+ // found to be a
+ // patch of
+ // active cells
+ // itself, then
+ // add up how
+ // many of its
+ // children are
+ // supposed to be
+ // coarsened
+ if (child->child(0)->active())
+ for (unsigned int cc=0; cc<nn_children; ++cc)
+ if (child->child(cc)->coarsen_flag_set())
+ ++n_coarsen_flags;
+ }
+
+ // if not all
+ // grandchildren are
+ // supposed to be
+ // coarsened
+ // (e.g. because some
+ // simply don't have
+ // the flag set, or
+ // because they are not
+ // active and therefore
+ // cannot carry the
+ // flag), then remove
+ // the coarsen flag
+ // from all of the
+ // active
+ // grandchildren. note
+ // that there may be
+ // coarsen flags on the
+ // grandgrandchildren
+ // -- we don't clear
+ // them here, but we'll
+ // get to them in later
+ // iterations if
+ // necessary
+ //
+ // there is nothing
+ // we have to do if
+ // no coarsen flags
+ // have been set at
+ // all
+ if ((n_coarsen_flags != n_grandchildren)
+ &&
+ (n_coarsen_flags > 0))
+ for (unsigned int c=0; c<n_children; ++c)
+ {
+ const cell_iterator child = cell->child(c);
+ if (child->child(0)->active())
+ for (unsigned int cc=0; cc<child->n_children(); ++cc)
+ child->child(cc)->clear_coarsen_flag();
+ }
+ }
+ }
+
+ //////////////////////////////////
+ //
+ // at the boundary we could end up with
+ // cells with negative volume or at
+ // least with a part, that is negative,
+ // if the cell is refined
+ // anisotropically. we have to check,
+ // whether that can happen
+ internal::Triangulation::Implementation::prevent_distorted_boundary_cells(*this);
+
+ /////////////////////////////////
+ // STEP 6:
+ // take care of the requirement that no
+ // double refinement is done at each face
+ //
+ // in case of anisotropic refinement
+ // it is only likely, but not sure,
+ // that the cells, which are more
+ // refined along a certain face common
+ // to two cells are on a higher
+ // level. therefore we cannot be sure,
+ // that the requirement of no double
+ // refinement is fulfilled after a
+ // single pass of the following
+ // actions. We could just wait for the
+ // next global loop. when this
+ // function terminates, the
+ // requirement will be
+ // fullfilled. However, it might be
+ // faster to insert an inner loop
+ // here.
+ bool changed = true;
+ while (changed)
+ {
+ changed=false;
+ active_cell_iterator cell=last_active(),
+ endc=end();
+
+ for (; cell != endc; --cell)
+ if (cell->refine_flag_set())
+ {
+ // loop over neighbors of cell
+ for (unsigned int i=0; i<GeometryInfo<dim>::faces_per_cell; ++i)
+ {
+ // only do something if the
+ // face is not at the boundary
+ // and if the face will be
+ // refined with the RefineCase
+ // currently flagged for
+ if (cell->neighbor(i).state() == IteratorState::valid &&
+ (GeometryInfo<dim>::face_refinement_case(cell->refine_flag_set(),
+ i)
+ != RefinementCase<dim-1>::no_refinement))
+ {
+ // 1) if the neighbor has
+ // children: nothing to
+ // worry about.
+ // 2) if the neighbor is
+ // active and a coarser
+ // one, ensure, that its
+ // refine_flag is set
+ // 3) if the neighbor is
+ // active and as
+ // refined along the face
+ // as our current cell,
+ // make sure, that no
+ // coarsen_flag is set. if
+ // we remove the coarsen
+ // flag of our neighbor,
+ // fix_coarsen_flags() makes
+ // sure, that the mother
+ // cell will not be
+ // coarsened
+ if (cell->neighbor(i)->active())
+ {
+ if (cell->neighbor_is_coarser(i))
+ {
+ if (cell->neighbor(i)->coarsen_flag_set())
+ cell->neighbor(i)->clear_coarsen_flag();
+ // we'll set the
+ // refine flag
+ // for this
+ // neighbor
+ // below. we
+ // note, that we
+ // have changed
+ // something by
+ // setting the
+ // changed flag
+ // to true. We do
+ // not need to do
+ // so, if we just
+ // removed the
+ // coarsen flag,
+ // as the changed
+ // flag only
+ // indicates the
+ // need to re-run
+ // the inner
+ // loop. however,
+ // we only loop
+ // over cells
+ // flagged for
+ // refinement
+ // here, so
+ // nothing to
+ // worry about if
+ // we remove
+ // coarsen flags
+
+ if (dim==2)
+ {
+ if (smooth_grid & allow_anisotropic_smoothing)
+ changed=cell->neighbor(i)->flag_for_face_refinement(cell->neighbor_of_coarser_neighbor(i).first,
+ RefinementCase<dim-1>::cut_x);
+ else
+ {
+ if (!cell->neighbor(i)->refine_flag_set())
+ changed=true;
+ cell->neighbor(i)->set_refine_flag();
+ }
+ }
+ else //i.e. if (dim==3)
+ {
+// ugly situations might arise here, consider the following situation, which
+// shows neighboring cells at the common face, where the upper right element is
+// coarser at the given face. Now the upper child element of the lower left
+// wants to refine according to cut_z, such that there is a 'horizontal'
+// refinement of the face marked with #####
+//
+// / /
+// / /
+// *---------------*
+// | |
+// | |
+// | |
+// | |
+// | |
+// | | /
+// | |/
+// *---------------*
+//
+//
+// *---------------*
+// /| /|
+// / | ##### / |
+// | |
+// *---------------*
+// /| /|
+// / | / |
+// | |
+// *---------------*
+// / /
+// / /
+//
+// this introduces too many hanging nodes and the neighboring (coarser) cell
+// (upper right) has to be refined. If it is only refined according to cut_z,
+// then everything is ok:
+//
+// / /
+// / /
+// *---------------*
+// | |
+// | | /
+// | |/
+// *---------------*
+// | |
+// | | /
+// | |/
+// *---------------*
+//
+//
+// *---------------*
+// /| /|
+// / *---------------*
+// /| /|
+// *---------------*
+// /| /|
+// / | / |
+// | |
+// *---------------*
+// / /
+// / /
+//
+// if however the cell wants to refine itself in an other way, or if we disallow
+// anisotropic smoothing, then simply refining the neighbor isotropically is not
+// going to work, since this introduces a refinement of face ##### with both
+// cut_x and cut_y, which is not possible:
+//
+// / / /
+// / / /
+// *-------*-------*
+// | | |
+// | | | /
+// | | |/
+// *-------*-------*
+// | | |
+// | | | /
+// | | |/
+// *-------*-------*
+//
+//
+// *---------------*
+// /| /|
+// / *---------------*
+// /| /|
+// *---------------*
+// /| /|
+// / | / |
+// | |
+// *---------------*
+// / /
+// / /
+//
+// thus, in this case we also need to refine our current cell in the new
+// direction:
+//
+// / / /
+// / / /
+// *-------*-------*
+// | | |
+// | | | /
+// | | |/
+// *-------*-------*
+// | | |
+// | | | /
+// | | |/
+// *-------*-------*
+//
+//
+// *-------*-------*
+// /| /| /|
+// / *-------*-------*
+// /| /| /|
+// *-------*-------*
+// /| / /|
+// / | / |
+// | |
+// *---------------*
+// / /
+// / /
+
+ std::pair<unsigned int, unsigned int> nb_indices
+ =cell->neighbor_of_coarser_neighbor(i);
+ unsigned int refined_along_x=0,
+ refined_along_y=0,
+ to_be_refined_along_x=0,
+ to_be_refined_along_y=0;
+
+ const int this_face_index=cell->face_index(i);
+
+// step 1: detect, along which axis the face is currently refined
+ if ((this_face_index
+ == cell->neighbor(i)->face(nb_indices.first)->child_index(0)) ||
+ (this_face_index
+ == cell->neighbor(i)->face(nb_indices.first)->child_index(1)))
+ {
+ // this
+ // might
+ // be an
+ // anisotropic
+ // child. get
+ // the
+ // face
+ // refine
+ // case
+ // of the
+ // neighbors
+ // face
+ // and
+ // count
+ // refinements
+ // in x
+ // and y
+ // direction.
+ RefinementCase<dim-1> frc=cell->neighbor(i)->face(nb_indices.first)->refinement_case();
+ if (frc & RefinementCase<dim>::cut_x)
+ ++refined_along_x;
+ if (frc & RefinementCase<dim>::cut_y)
+ ++refined_along_y;
+ }
+ else
+ // this has
+ // to be an
+ // isotropic
+ // child
+ {
+ ++refined_along_x;
+ ++refined_along_y;
+ }
+// step 2: detect, along which axis the face has to be refined given the current
+// refine flag
+ RefinementCase<dim-1> flagged_frc=
+ GeometryInfo<dim>::face_refinement_case(cell->refine_flag_set(),
+ i,
+ cell->face_orientation(i),
+ cell->face_flip(i),
+ cell->face_rotation(i));
+ if (flagged_frc & RefinementCase<dim>::cut_x)
+ ++to_be_refined_along_x;
+ if (flagged_frc & RefinementCase<dim>::cut_y)
+ ++to_be_refined_along_y;
+
+// step 3: set the refine flag of the (coarser and active) neighbor.
+ if ((smooth_grid & allow_anisotropic_smoothing) ||
+ cell->neighbor(i)->refine_flag_set())
+ {
+ if (refined_along_x + to_be_refined_along_x > 1)
+ changed |= cell->neighbor(i)->flag_for_face_refinement(nb_indices.first,
+ RefinementCase<dim-1>::cut_axis(0));
+ if (refined_along_y + to_be_refined_along_y > 1)
+ changed |= cell->neighbor(i)->flag_for_face_refinement(nb_indices.first,
+ RefinementCase<dim-1>::cut_axis(1));
+ }
+ else
+ {
+ if (cell->neighbor(i)->refine_flag_set()!=RefinementCase<dim>::isotropic_refinement)
+ changed=true;
+ cell->neighbor(i)->set_refine_flag();
+ }
+
+// step 4: if necessary (see above) add to the refine flag of the current cell
+ cell_iterator nb=cell->neighbor(i);
+ RefinementCase<dim-1> nb_frc
+ = GeometryInfo<dim>::face_refinement_case(nb->refine_flag_set(),
+ nb_indices.first,
+ nb->face_orientation(nb_indices.first),
+ nb->face_flip(nb_indices.first),
+ nb->face_rotation(nb_indices.first));
+ if ((nb_frc & RefinementCase<dim>::cut_x) &&
+ !(refined_along_x || to_be_refined_along_x))
+ changed |= cell->flag_for_face_refinement(i,RefinementCase<dim-1>::cut_axis(0));
+ if ((nb_frc & RefinementCase<dim>::cut_y) &&
+ !(refined_along_y || to_be_refined_along_y))
+ changed |= cell->flag_for_face_refinement(i,RefinementCase<dim-1>::cut_axis(1));
+ }
+ }// if neighbor is coarser
+ else // -> now the neighbor is not coarser
+ {
+ cell->neighbor(i)->clear_coarsen_flag();
+ const unsigned int nb_nb=cell->neighbor_of_neighbor(i);
+ const cell_iterator neighbor=cell->neighbor(i);
+ RefinementCase<dim-1> face_ref_case=
+ GeometryInfo<dim>::face_refinement_case(neighbor->refine_flag_set(),
+ nb_nb,
+ neighbor->face_orientation(nb_nb),
+ neighbor->face_flip(nb_nb),
+ neighbor->face_rotation(nb_nb));
+ RefinementCase<dim-1> needed_face_ref_case
+ =GeometryInfo<dim>::face_refinement_case(cell->refine_flag_set(),
+ i,
+ cell->face_orientation(i),
+ cell->face_flip(i),
+ cell->face_rotation(i));
+ // if the
+ // neighbor wants
+ // to refine the
+ // face with
+ // cut_x and we
+ // want cut_y or
+ // vice versa, we
+ // have to refine
+ // isotropically
+ // at the given
+ // face
+ if ((face_ref_case==RefinementCase<dim>::cut_x && needed_face_ref_case==RefinementCase<dim>::cut_y) ||
+ (face_ref_case==RefinementCase<dim>::cut_y && needed_face_ref_case==RefinementCase<dim>::cut_x))
+ {
+ changed=cell->flag_for_face_refinement(i, face_ref_case);
+ neighbor->flag_for_face_refinement(nb_nb, needed_face_ref_case);
+ }
+ }
+ }
+ else //-> the neighbor is not active
+ {
+ RefinementCase<dim-1> face_ref_case = cell->face(i)->refinement_case(),
+ needed_face_ref_case = GeometryInfo<dim>::face_refinement_case(cell->refine_flag_set(),
+ i,
+ cell->face_orientation(i),
+ cell->face_flip(i),
+ cell->face_rotation(i));
+ // if the face is
+ // refined with cut_x
+ // and we want cut_y
+ // or vice versa, we
+ // have to refine
+ // isotropically at
+ // the given face
+ if ((face_ref_case==RefinementCase<dim>::cut_x && needed_face_ref_case==RefinementCase<dim>::cut_y) ||
+ (face_ref_case==RefinementCase<dim>::cut_y && needed_face_ref_case==RefinementCase<dim>::cut_x))
+ changed=cell->flag_for_face_refinement(i, face_ref_case);
+ }
+ }
+ }
+ }
+ }
+
+ //////////////////////////////////////
+ // STEP 7:
+ // take care that no double refinement
+ // is done at each line in 3d or higher
+ // dimensions.
+ internal::Triangulation::Implementation::prepare_refinement_dim_dependent (*this);
+
+ //////////////////////////////////////
+ // STEP 8:
+ // make sure that all children of each
+ // cell are either flagged for coarsening
+ // or none of the children is
+ fix_coarsen_flags ();
+ // get the refinement and coarsening
+ // flags
+ std::vector<bool> flags_after_loop[2];
+ save_coarsen_flags (flags_after_loop[0]);
+ save_refine_flags (flags_after_loop[1]);
+
+ // find out whether something was
+ // changed in this loop
+ mesh_changed_in_this_loop
+ = ((flags_before_loop[0] != flags_after_loop[0]) ||
+ (flags_before_loop[1] != flags_after_loop[1]));
+
+ // set the flags for the next loop
+ // already
+ flags_before_loop[0].swap(flags_after_loop[0]);
+ flags_before_loop[1].swap(flags_after_loop[1]);
+ }
+ while (mesh_changed_in_this_loop);
+
+
+ // find out whether something was really
+ // changed in this function. Note that
+ // @p{flags_before_loop} represents the
+ // state after the last loop, i.e.
+ // the present state
+ return ((flags_before[0] != flags_before_loop[0]) ||
+ (flags_before[1] != flags_before_loop[1]));
+}
+
+
+
+
+template <int dim, int spacedim>
+void Triangulation<dim, spacedim>::write_bool_vector (const unsigned int magic_number1,
+ const std::vector<bool> &v,
+ const unsigned int magic_number2,
+ std::ostream &out)
+{
+ const unsigned int N = v.size();
+ unsigned char *flags = new unsigned char[N/8+1];
+ for (unsigned int i=0; i<N/8+1; ++i) flags[i]=0;
+
+ for (unsigned int position=0; position<N; ++position)
+ flags[position/8] |= (v[position] ? (1<<(position%8)) : 0);
+
+ AssertThrow (out, ExcIO());
+
+ // format:
+ // 0. magic number
+ // 1. number of flags
+ // 2. the flags
+ // 3. magic number
+ out << magic_number1 << ' ' << N << std::endl;
+ for (unsigned int i=0; i<N/8+1; ++i)
+ out << static_cast<unsigned int>(flags[i]) << ' ';
+
+ out << std::endl << magic_number2 << std::endl;
+
+ delete[] flags;
+
+ AssertThrow (out, ExcIO());
+}
+
+
+template <int dim, int spacedim>
+void Triangulation<dim, spacedim>::read_bool_vector (const unsigned int magic_number1,
+ std::vector<bool> &v,
+ const unsigned int magic_number2,
+ std::istream &in)
+{
+ AssertThrow (in, ExcIO());
+
+ unsigned int magic_number;
+ in >> magic_number;
+ AssertThrow (magic_number==magic_number1, ExcGridReadError());
+
+ unsigned int N;
+ in >> N;
+ v.resize (N);
+
+ unsigned char *flags = new unsigned char[N/8+1];
+ unsigned short int tmp;
+ for (unsigned int i=0; i<N/8+1; ++i)
+ {
+ in >> tmp;
+ flags[i] = tmp;
+ }
+
+ for (unsigned int position=0; position!=N; ++position)
+ v[position] = (flags[position/8] & (1<<(position%8)));
+
+ in >> magic_number;
+ AssertThrow (magic_number==magic_number2, ExcGridReadError());
+
+ delete[] flags;
+
+ AssertThrow (in, ExcIO());
+}
+
+
+
+template <int dim, int spacedim>
+unsigned int
+Triangulation<dim, spacedim>::memory_consumption () const
+{
+ unsigned int mem = 0;
+ mem += MemoryConsumption::memory_consumption(levels);
+ for (unsigned int i=0; i<levels.size(); ++i)
+ mem += MemoryConsumption::memory_consumption (*levels[i]);
+ mem += MemoryConsumption::memory_consumption (vertices);
+ mem += MemoryConsumption::memory_consumption (vertices_used);
+ mem += sizeof(boundary);
+ mem += sizeof(smooth_grid);
+ mem += MemoryConsumption::memory_consumption (number_cache);
+ mem += sizeof (faces);
+ mem += MemoryConsumption::memory_consumption (*faces);
+
+ return mem;
+}
+
+
+
+
+template<int dim, int spacedim>
+Triangulation<dim, spacedim>::RefinementListener::~RefinementListener ()
+{}
+
+
+
+template<int dim, int spacedim>
+Triangulation<dim, spacedim>::DistortedCellList::~DistortedCellList () throw ()
+{
+ // don't do anything here. the compiler
+ // will automatically convert any
+ // exceptions created by the destructors of
+ // the member variables into abort() in
+ // order to satisfy the throw()
+ // specification
+}
+
+
+
+
+template<int dim, int spacedim>
+void Triangulation<dim, spacedim>::
+RefinementListener::pre_refinement_notification (const Triangulation<dim, spacedim> &)
+{}
+
+
+
+template<int dim, int spacedim>
+void Triangulation<dim, spacedim>::
+RefinementListener::post_refinement_notification (const Triangulation<dim, spacedim> &)
+{}
+
+
+
+template<int dim, int spacedim>
+void Triangulation<dim, spacedim>::
+RefinementListener::copy_notification (const Triangulation<dim, spacedim> &,
+ const Triangulation<dim, spacedim> &)
+{}
+
+
+
+template<int dim, int spacedim>
+void
+Triangulation<dim, spacedim>::add_refinement_listener (RefinementListener &listener) const
+{
+ refinement_listeners.push_back (&listener);
+}
+
+
+
+template<int dim, int spacedim>
+void
+Triangulation<dim, spacedim>::remove_refinement_listener (RefinementListener &listener) const
+{
+ typename std::list<RefinementListener *>::iterator p =
+ std::find (refinement_listeners.begin (),
+ refinement_listeners.end (),
+ &listener);
+ Assert (p != refinement_listeners.end (), ExcInternalError ());
+ refinement_listeners.erase (p);
+}
+
+
+
+// explicit instantiations
+#include "tria.inst"
+
+// this is a hack: we need to instantiate this one function because
+// TriaAccessor<1,1,3> uses it. We could instead instantiate
+// Triangulation<1,3>, but that requires a lot more specializations of
+// functions that currently only exist for <1,1> and <1,2>
+template
+const Boundary<1,3> &
+Triangulation<1,3>::get_boundary (const unsigned int number) const;
+
DEAL_II_NAMESPACE_CLOSE
+++ /dev/null
-//---------------------------------------------------------------------------
-// $Id$
-// Version: $Name$
-//
-// Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 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.
-//
-//---------------------------------------------------------------------------
-
-#include <base/memory_consumption.h>
-#include <grid/tria.h>
-#include <grid/tria_levels.h>
-#include <grid/tria_faces.h>
-#include <grid/tria_boundary.h>
-#include <grid/tria_accessor.h>
-#include <grid/tria_iterator.h>
-#include <base/geometry_info.h>
-#include <grid/grid_tools.h>
-#include <grid/magic_numbers.h>
-#include <fe/mapping_q1.h>
-#include <lac/vector.h>
-
-#include <algorithm>
-#include <numeric>
-#include <map>
-#include <cmath>
-#include <functional>
-
-#include <base/std_cxx1x/array.h>
-
-DEAL_II_NAMESPACE_OPEN
-
-// anonymous namespace for internal helper functions
-namespace
-{
- // return whether the given cell is
- // patch_level_1, i.e. determine
- // whether either all or none of
- // its children are further
- // refined. this function can only
- // be called for non-active cells.
- template <int dim, int spacedim>
- bool cell_is_patch_level_1 (const TriaIterator<dealii::CellAccessor<dim, spacedim> > &cell)
- {
- Assert (cell->active() == false, ExcInternalError());
-
- unsigned int n_active_children = 0;
- for (unsigned int i=0; i<cell->n_children(); ++i)
- if (cell->child(i)->active())
- ++n_active_children;
-
- return (n_active_children == 0) || (n_active_children == cell->n_children());
- }
-
-
-
- // return, wheter a given @p cell will be
- // coarsened, which is the case if all
- // children are active and have their coarsen
- // flag set. In case only part of the coarsen
- // flags are set, remove them.
- template <int dim, int spacedim>
- bool cell_will_be_coarsened (const TriaIterator<dealii::CellAccessor<dim,spacedim> > &cell)
- {
- // only cells with children should be
- // considered for coarsening
-
- if (cell->has_children())
- {
- unsigned int children_to_coarsen=0;
- const unsigned int n_children=cell->n_children();
-
- for (unsigned int c=0; c<n_children; ++c)
- if (cell->child(c)->active() &&
- cell->child(c)->coarsen_flag_set())
- ++children_to_coarsen;
- if (children_to_coarsen==n_children)
- return true;
- else
- for (unsigned int c=0; c<n_children; ++c)
- if (cell->child(c)->active())
- cell->child(c)->clear_coarsen_flag();
- }
- // no children, so no coarsening
- // possible. however, no children also
- // means that this cell will be in the same
- // state as if it had children and was
- // coarsened. So, what should we return -
- // false or true?
- // make sure we do not have to do this at
- // all...
- Assert(cell->has_children(), ExcInternalError());
- // ... and then simply return false
- return false;
- }
-
-
- // return, whether the face @p face_no of the
- // given @p cell will be refined after the
- // current refinement step, considering
- // refine and coarsen flags and considering
- // only those refinemnts that will be caused
- // by the neighboring cell.
-
- // this function is used on both active cells
- // and cells with children. on cells with
- // children it also of interest to know 'how'
- // the face will be refined. thus there is an
- // additional third argument @p
- // expected_face_ref_case returning just
- // that. be aware, that this vriable will
- // only contain useful information if this
- // function is called for an active cell.
- //
- // thus, this is an internal function, users
- // should call one of the two alternatives
- // following below.
- template <int dim, int spacedim>
- bool
- face_will_be_refined_by_neighbor_internal(const TriaIterator<dealii::CellAccessor<dim,spacedim> > &cell,
- const unsigned int face_no,
- RefinementCase<dim-1> &expected_face_ref_case)
- {
- // first of all: set the default value for
- // expected_face_ref_case, which is no
- // refinement at all
- expected_face_ref_case=RefinementCase<dim-1>::no_refinement;
-
- const typename Triangulation<dim,spacedim>::cell_iterator neighbor=cell->neighbor(face_no);
-
- // If we are at the boundary, there is no
- // neighbor which could refine the face
- if (neighbor.state()!=IteratorState::valid)
- return false;
-
- if (neighbor->has_children())
- {
- // if the neighbor is refined, it may be
- // coarsened. if so, then it won't refine
- // the face, no matter what else happens
- if (cell_will_be_coarsened(neighbor))
- return false;
- else
- // if the neighor is refined, then he
- // is also refined at our current
- // face. He will stay so without
- // coarsening, so return true in that
- // case.
- {
- expected_face_ref_case=cell->face(face_no)->refinement_case();
- return true;
- }
- }
-
- // now, the neighbor is not refined, but
- // perhaps he will be
- const RefinementCase<dim> nb_ref_flag=neighbor->refine_flag_set();
- if (nb_ref_flag != RefinementCase<dim>::no_refinement)
- {
- // now we need to know, which of the
- // neighbors faces points towards us
- const unsigned int neighbor_neighbor=cell->neighbor_face_no(face_no);
- // check, whether the cell will be
- // refined in a way that refines our
- // face
- const RefinementCase<dim-1> face_ref_case=
- GeometryInfo<dim>::face_refinement_case(nb_ref_flag,
- neighbor_neighbor,
- neighbor->face_orientation(neighbor_neighbor),
- neighbor->face_flip(neighbor_neighbor),
- neighbor->face_rotation(neighbor_neighbor));
- if (face_ref_case != RefinementCase<dim-1>::no_refinement)
- {
- const typename Triangulation<dim,spacedim>::face_iterator neighbor_face=neighbor->face(neighbor_neighbor);
- const int this_face_index=cell->face_index(face_no);
-
- // there are still two basic
- // possibilities here: the neighbor
- // might be coarser or as coarse
- // as we are
- if (neighbor_face->index()==this_face_index)
- // the neighbor is as coarse as
- // we are and will be refined at
- // the face of consideration, so
- // return true
- {
- expected_face_ref_case = face_ref_case;
- return true;
- }
- else
- {
-
- // the neighbor is coarser.
- // this is the most complicated
- // case. It might be, that the
- // neighbor's face will be
- // refined, but that we will
- // not see this, as we are
- // refined in a similar way.
-
- // so, the neighbor's face must
- // have children. check, if our
- // cell's face is one of these
- // (it could also be a
- // grand_child)
- for (unsigned int c=0; c<neighbor_face->n_children(); ++c)
- if (neighbor_face->child_index(c)==this_face_index)
- {
- // if the flagged refine
- // case of the face is a
- // subset or the same as
- // the current refine case,
- // then the face, as seen
- // from our cell, won't be
- // refined by the neighbor
- if ((neighbor_face->refinement_case() | face_ref_case)
- == neighbor_face->refinement_case())
- return false;
- else
- {
- // if we are active, we
- // must be an
- // anisotropic child
- // and the coming
- // face_ref_case is
- // isotropic. Thus,
- // from our cell we
- // will see exactly the
- // opposite refine case
- // that the face has
- // now...
- Assert(face_ref_case==RefinementCase<dim-1>::isotropic_refinement, ExcInternalError());
- expected_face_ref_case = ~neighbor_face->refinement_case();
- return true;
- }
- }
-
- // so, obviously we were not
- // one of the children, but a
- // grandchild. This is only
- // possible in 3d.
- Assert(dim==3, ExcInternalError());
- // In that case, however, no
- // matter what the neighbor
- // does, he won't be finer
- // after the next refinement
- // step.
- return false;
- }
- }// if face will be refined
- }// if neighbor is flagged for refinement
-
- // no cases left, so the neighbor will not
- // refine the face
- return false;
- }
-
- // version of above function for both active
- // and non-active cells
- template <int dim, int spacedim>
- bool
- face_will_be_refined_by_neighbor(const TriaIterator<dealii::CellAccessor<dim, spacedim> > &cell,
- const unsigned int face_no)
- {
- RefinementCase<dim-1> dummy = RefinementCase<dim-1>::no_refinement;
- return face_will_be_refined_by_neighbor_internal(cell, face_no, dummy);
- }
-
- // version of above function for active cells
- // only. Additionally returning the refine
- // case (to come) of the face under
- // consideration
- template <int dim, int spacedim>
- bool
- face_will_be_refined_by_neighbor(const TriaActiveIterator<dealii::CellAccessor<dim,spacedim> > &cell,
- const unsigned int face_no,
- RefinementCase<dim-1> &expected_face_ref_case)
- {
- return face_will_be_refined_by_neighbor_internal(cell, face_no,
- expected_face_ref_case);
- }
-
-
-
- template <int dim, int spacedim>
- bool
- satisfies_level1_at_vertex_rule (const Triangulation<dim,spacedim> &triangulation)
- {
- std::vector<unsigned int> min_adjacent_cell_level (triangulation.n_vertices(),
- triangulation.n_levels());
- std::vector<unsigned int> max_adjacent_cell_level (triangulation.n_vertices(),
- 0);
-
- for (typename Triangulation<dim,spacedim>::active_cell_iterator
- cell = triangulation.begin_active();
- cell != triangulation.end(); ++cell)
- for (unsigned int v=0; v<GeometryInfo<dim>::vertices_per_cell; ++v)
- {
- min_adjacent_cell_level[cell->vertex_index(v)]
- = std::min<unsigned int>
- (min_adjacent_cell_level[cell->vertex_index(v)],
- cell->level());
- max_adjacent_cell_level[cell->vertex_index(v)]
- = std::max<unsigned int> (min_adjacent_cell_level[cell->vertex_index(v)],
- cell->level());
- }
-
- for (unsigned int k=0; k<triangulation.n_vertices(); ++k)
- if (triangulation.vertex_used(k))
- if (max_adjacent_cell_level[k] -
- min_adjacent_cell_level[k] > 1)
- return false;
- return true;
- }
-
-
-
- /**
- * Fill the vector @p line_cell_count
- * needed by @p delete_children with the
- * number of cells bounded by a given
- * line.
- */
- template <int dim, int spacedim>
- std::vector<unsigned int>
- count_cells_bounded_by_line (const Triangulation<dim,spacedim> &triangulation)
- {
- if (dim >= 2)
- {
- std::vector<unsigned int> line_cell_count(triangulation.n_raw_lines(),0);
- typename Triangulation<dim,spacedim>::cell_iterator
- cell=triangulation.begin(),
- endc=triangulation.end();
- for (; cell!=endc; ++cell)
- for (unsigned int l=0; l<GeometryInfo<dim>::lines_per_cell; ++l)
- ++line_cell_count[cell->line_index(l)];
- return line_cell_count;
- }
- else
- return std::vector<unsigned int>();
- }
-
-
-
-
- /**
- * Fill the vector @p quad_cell_count
- * needed by @p delete_children with the
- * number of cells bounded by a given
- * quad.
- */
- template <int dim, int spacedim>
- std::vector<unsigned int>
- count_cells_bounded_by_quad (const Triangulation<dim,spacedim> &triangulation)
- {
- if (dim >= 3)
- {
- std::vector<unsigned int> quad_cell_count (triangulation.n_raw_quads(),0);
- typename Triangulation<dim,spacedim>::cell_iterator
- cell=triangulation.begin(),
- endc=triangulation.end();
- for (; cell!=endc; ++cell)
- for (unsigned int q=0; q<GeometryInfo<dim>::faces_per_cell; ++q)
- ++quad_cell_count[cell->quad_index(q)];
- return quad_cell_count;
- }
- else
- return std::vector<unsigned int>();
- }
-
-
- /**
- * For a given Triangulation, update the
- * number cache for lines. For 1d, we have
- * to deal with the fact that lines have
- * levels, whereas for higher dimensions
- * they do not.
- *
- * The second argument indicates
- * for how many levels the
- * Triangulation has objects,
- * though the highest levels need
- * not contain active cells if they
- * have previously all been
- * coarsened away.
- */
- template <int dim, int spacedim>
- void compute_number_cache (const Triangulation<dim,spacedim> &triangulation,
- const unsigned int level_objects,
- internal::Triangulation::NumberCache<1> &number_cache)
- {
- typedef
- typename Triangulation<dim,spacedim>::line_iterator line_iterator;
- typedef
- typename Triangulation<dim,spacedim>::active_line_iterator active_line_iterator;
-
- number_cache.n_levels = 0;
- if (level_objects > 0)
- {
- // check whether there are
- // cells on the highest
- // levels (there need not be,
- // since they might all have
- // been coarsened away)
- typename Triangulation<dim,spacedim>::raw_cell_iterator
- cell = triangulation.last_raw (level_objects-1),
- endc = triangulation.end();
- for (; cell!=endc; --cell)
- if (cell->used())
- {
- // return level of most
- // refined existing cell
- // (+1 because of
- // counting conventions)
- number_cache.n_levels = cell->level()+1;
- break;
- }
-
- // no cells at all?
- Assert (number_cache.n_levels > 0, ExcInternalError());
- }
-
- ///////////////////////////////////
- // update the number of lines
- // on the different levels in
- // the cache
- number_cache.n_lines_level.resize (number_cache.n_levels);
- number_cache.n_lines = 0;
-
- number_cache.n_active_lines_level.resize (number_cache.n_levels);
- number_cache.n_active_lines = 0;
-
- // for 1d, lines have levels so take
- // count the objects per level and
- // globally
- if (dim == 1)
- {
- for (unsigned int level=0; level<number_cache.n_levels; ++level)
- {
- // count lines on this level
- number_cache.n_lines_level[level] = 0;
-
- line_iterator line = triangulation.begin_line (level),
- endc = (level == number_cache.n_levels-1 ?
- line_iterator(triangulation.end_line()) :
- triangulation.begin_line (level+1));
- for (; line!=endc; ++line)
- ++number_cache.n_lines_level[level];
-
- // update total number of lines
- number_cache.n_lines += number_cache.n_lines_level[level];
- }
-
- // do the update for the number of
- // active lines as well
- for (unsigned int level=0; level<number_cache.n_levels; ++level)
- {
- // count lines on this level
- number_cache.n_active_lines_level[level] = 0;
-
- active_line_iterator line = triangulation.begin_active_line (level),
- endc = triangulation.end_active_line (level);
- for (; line!=endc; ++line)
- ++number_cache.n_active_lines_level[level];
-
- // update total number of lines
- number_cache.n_active_lines += number_cache.n_active_lines_level[level];
- }
- }
- else
- {
- // for dim>1, there are no
- // levels for lines
- {
- line_iterator line = triangulation.begin_line (),
- endc = triangulation.end_line();
- for (; line!=endc; ++line)
- ++number_cache.n_lines;
- }
-
- {
- active_line_iterator line = triangulation.begin_active_line (),
- endc = triangulation.end_line();
- for (; line!=endc; ++line)
- ++number_cache.n_active_lines;
- }
- }
- }
-
- /**
- * For a given Triangulation, update the
- * number cache for quads. For 2d, we have
- * to deal with the fact that quads have
- * levels, whereas for higher dimensions
- * they do not.
- *
- * The second argument indicates
- * for how many levels the
- * Triangulation has objects,
- * though the highest levels need
- * not contain active cells if they
- * have previously all been
- * coarsened away.
- *
- * At the beginning of the function, we call the
- * respective function to update the number
- * cache for lines.
- */
- template <int dim, int spacedim>
- void compute_number_cache (const Triangulation<dim,spacedim> &triangulation,
- const unsigned int level_objects,
- internal::Triangulation::NumberCache<2> &number_cache)
- {
- // update lines and n_levels
- compute_number_cache (triangulation,
- level_objects,
- static_cast<internal::Triangulation::NumberCache<1>&>
- (number_cache));
-
- typedef
- typename Triangulation<dim,spacedim>::quad_iterator quad_iterator;
- typedef
- typename Triangulation<dim,spacedim>::active_quad_iterator active_quad_iterator;
-
- ///////////////////////////////////
- // update the number of quads
- // on the different levels in
- // the cache
- number_cache.n_quads_level.resize (number_cache.n_levels);
- number_cache.n_quads = 0;
-
- number_cache.n_active_quads_level.resize (number_cache.n_levels);
- number_cache.n_active_quads = 0;
-
- // for 2d, quads have levels so take
- // count the objects per level and
- // globally
- if (dim == 2)
- {
- for (unsigned int level=0; level<number_cache.n_levels; ++level)
- {
- // count quads on this level
- number_cache.n_quads_level[level] = 0;
-
- quad_iterator quad = triangulation.begin_quad (level),
- endc = (level == number_cache.n_levels-1 ?
- quad_iterator(triangulation.end_quad()) :
- triangulation.begin_quad (level+1));
- for (; quad!=endc; ++quad)
- ++number_cache.n_quads_level[level];
-
- // update total number of quads
- number_cache.n_quads += number_cache.n_quads_level[level];
- }
-
- // do the update for the number of
- // active quads as well
- for (unsigned int level=0; level<number_cache.n_levels; ++level)
- {
- // count quads on this level
- number_cache.n_active_quads_level[level] = 0;
-
- active_quad_iterator quad = triangulation.begin_active_quad (level),
- endc = triangulation.end_active_quad (level);
- for (; quad!=endc; ++quad)
- ++number_cache.n_active_quads_level[level];
-
- // update total number of quads
- number_cache.n_active_quads += number_cache.n_active_quads_level[level];
- }
- }
- else
- {
- // for dim>2, there are no
- // levels for quads
- {
- quad_iterator quad = triangulation.begin_quad (),
- endc = triangulation.end_quad();
- for (; quad!=endc; ++quad)
- ++number_cache.n_quads;
- }
-
- {
- active_quad_iterator quad = triangulation.begin_active_quad (),
- endc = triangulation.end_quad();
- for (; quad!=endc; ++quad)
- ++number_cache.n_active_quads;
- }
- }
- }
-
- /**
- * For a given Triangulation, update the
- * number cache for hexes. For 3d, we have
- * to deal with the fact that hexes have
- * levels, whereas for higher dimensions
- * they do not.
- *
- * The second argument indicates
- * for how many levels the
- * Triangulation has objects,
- * though the highest levels need
- * not contain active cells if they
- * have previously all been
- * coarsened away.
- *
- * At the end of the function, we call the
- * respective function to update the number
- * cache for quads, which will in turn call
- * the respective function for lines.
- */
- template <int dim, int spacedim>
- void compute_number_cache (const Triangulation<dim,spacedim> &triangulation,
- const unsigned int level_objects,
- internal::Triangulation::NumberCache<3> &number_cache)
- {
- // update quads, lines and n_levels
- compute_number_cache (triangulation,
- level_objects,
- static_cast<internal::Triangulation::NumberCache<2>&>
- (number_cache));
-
- typedef
- typename Triangulation<dim,spacedim>::hex_iterator hex_iterator;
- typedef
- typename Triangulation<dim,spacedim>::active_hex_iterator active_hex_iterator;
-
- ///////////////////////////////////
- // update the number of hexes
- // on the different levels in
- // the cache
- number_cache.n_hexes_level.resize (number_cache.n_levels);
- number_cache.n_hexes = 0;
-
- number_cache.n_active_hexes_level.resize (number_cache.n_levels);
- number_cache.n_active_hexes = 0;
-
- // for 3d, hexes have levels so take
- // count the objects per level and
- // globally
- if (dim == 3)
- {
- for (unsigned int level=0; level<number_cache.n_levels; ++level)
- {
- // count hexes on this level
- number_cache.n_hexes_level[level] = 0;
-
- hex_iterator hex = triangulation.begin_hex (level),
- endc = (level == number_cache.n_levels-1 ?
- hex_iterator(triangulation.end_hex()) :
- triangulation.begin_hex (level+1));
- for (; hex!=endc; ++hex)
- ++number_cache.n_hexes_level[level];
-
- // update total number of hexes
- number_cache.n_hexes += number_cache.n_hexes_level[level];
- }
-
- // do the update for the number of
- // active hexes as well
- for (unsigned int level=0; level<number_cache.n_levels; ++level)
- {
- // count hexes on this level
- number_cache.n_active_hexes_level[level] = 0;
-
- active_hex_iterator hex = triangulation.begin_active_hex (level),
- endc = triangulation.end_active_hex (level);
- for (; hex!=endc; ++hex)
- ++number_cache.n_active_hexes_level[level];
-
- // update total number of hexes
- number_cache.n_active_hexes += number_cache.n_active_hexes_level[level];
- }
- }
- else
- {
- // for dim>3, there are no
- // levels for hexs
- {
- hex_iterator hex = triangulation.begin_hex (),
- endc = triangulation.end_hex();
- for (; hex!=endc; ++hex)
- ++number_cache.n_hexes;
- }
-
- {
- active_hex_iterator hex = triangulation.begin_active_hex (),
- endc = triangulation.end_hex();
- for (; hex!=endc; ++hex)
- ++number_cache.n_active_hexes;
- }
- }
- }
-
-
-
- /**
- * A set of three functions that
- * reorder the data given to
- * create_triangulation_compatibility
- * from the "classic" to the
- * "current" format of vertex
- * numbering of cells and
- * faces. These functions do the
- * reordering of their arguments
- * in-place.
- */
- void
- reorder_compatibility (const std::vector<CellData<1> > &,
- const SubCellData &)
- {
- // nothing to do here: the format
- // hasn't changed for 1d
- }
-
-
- void
- reorder_compatibility (std::vector<CellData<2> > &cells,
- const SubCellData &)
- {
- for (unsigned int cell=0; cell<cells.size(); ++cell)
- std::swap(cells[cell].vertices[2],cells[cell].vertices[3]);
- }
-
-
- void
- reorder_compatibility (std::vector<CellData<3> > &cells,
- SubCellData &subcelldata)
- {
- unsigned int tmp[GeometryInfo<3>::vertices_per_cell];
- for (unsigned int cell=0; cell<cells.size(); ++cell)
- {
- for (unsigned int i=0; i<GeometryInfo<3>::vertices_per_cell; ++i)
- tmp[i] = cells[cell].vertices[i];
- for (unsigned int i=0; i<GeometryInfo<3>::vertices_per_cell; ++i)
- cells[cell].vertices[GeometryInfo<3>::ucd_to_deal[i]] = tmp[i];
- }
-
- // now points in boundary quads
- std::vector<CellData<2> >::iterator boundary_quad
- = subcelldata.boundary_quads.begin();
- std::vector<CellData<2> >::iterator end_quad
- = subcelldata.boundary_quads.end();
- for (unsigned int quad_no=0; boundary_quad!=end_quad; ++boundary_quad, ++quad_no)
- std::swap(boundary_quad->vertices[2], boundary_quad->vertices[3]);
- }
-
-
-
- /**
- * Return the index of the vertex
- * in the middle of this object,
- * if it exists. In order to
- * exist, the object needs to be
- * refined - for 2D and 3D it
- * needs to be refined
- * isotropically or else the
- * anisotropic children have to
- * be refined again. If the
- * middle vertex does not exist,
- * return
- * <tt>numbers::invalid_unsigned_int</tt>.
- *
- * This function should not really be
- * used in application programs.
- */
- template <int dim, int spacedim>
- unsigned int
- middle_vertex_index(const typename Triangulation<dim,spacedim>::line_iterator &line)
- {
- if (line->has_children())
- return line->child(0)->vertex_index(1);
- return numbers::invalid_unsigned_int;
- }
-
-
- template <int dim, int spacedim>
- unsigned int
- middle_vertex_index(const typename Triangulation<dim,spacedim>::quad_iterator &quad)
- {
- switch (static_cast<unsigned char> (quad->refinement_case()))
- {
- case RefinementCase<2>::cut_x:
- return middle_vertex_index<dim,spacedim>(quad->child(0)->line(1));
- break;
- case RefinementCase<2>::cut_y:
- return middle_vertex_index<dim,spacedim>(quad->child(0)->line(3));
- break;
- case RefinementCase<2>::cut_xy:
- return quad->child(0)->vertex_index(3);
- break;
- default:
- break;
- }
- return numbers::invalid_unsigned_int;
- }
-
-
- template <int dim, int spacedim>
- unsigned int
- middle_vertex_index(const typename Triangulation<dim,spacedim>::hex_iterator &hex)
- {
- switch (static_cast<unsigned char> (hex->refinement_case()))
- {
- case RefinementCase<3>::cut_x:
- return middle_vertex_index<dim,spacedim>(hex->child(0)->quad(1));
- break;
- case RefinementCase<3>::cut_y:
- return middle_vertex_index<dim,spacedim>(hex->child(0)->quad(3));
- break;
- case RefinementCase<3>::cut_z:
- return middle_vertex_index<dim,spacedim>(hex->child(0)->quad(5));
- break;
- case RefinementCase<3>::cut_xy:
- return middle_vertex_index<dim,spacedim>(hex->child(0)->line(11));
- break;
- case RefinementCase<3>::cut_xz:
- return middle_vertex_index<dim,spacedim>(hex->child(0)->line(5));
- break;
- case RefinementCase<3>::cut_yz:
- return middle_vertex_index<dim,spacedim>(hex->child(0)->line(7));
- break;
- case RefinementCase<3>::cut_xyz:
- return hex->child(0)->vertex_index(7);
- break;
- default:
- break;
- }
- return numbers::invalid_unsigned_int;
- }
-
-
- /**
- * Collect all coarse mesh cells
- * with at least one vertex at
- * which the determinant of the
- * Jacobian is zero or
- * negative. This is the function
- * for the case dim==spacedim.
- */
- template <int dim>
- typename Triangulation<dim,dim>::DistortedCellList
- collect_distorted_coarse_cells (const Triangulation<dim,dim> &triangulation)
- {
- typename Triangulation<dim,dim>::DistortedCellList distorted_cells;
- for (typename Triangulation<dim,dim>::cell_iterator
- cell = triangulation.begin(0); cell != triangulation.end(0); ++cell)
- {
- Point<dim> vertices[GeometryInfo<dim>::vertices_per_cell];
- for (unsigned int i=0; i<GeometryInfo<dim>::vertices_per_cell; ++i)
- vertices[i] = cell->vertex(i);
-
- Tensor<0,dim> determinants[GeometryInfo<dim>::vertices_per_cell];
- GeometryInfo<dim>::alternating_form_at_vertices (vertices,
- determinants);
-
- for (unsigned int i=0; i<GeometryInfo<dim>::vertices_per_cell; ++i)
- if (determinants[i] <= 1e-9 * std::pow (cell->diameter(),
- 1.*dim))
- {
- distorted_cells.distorted_cells.push_back (cell);
- break;
- }
- }
-
- return distorted_cells;
- }
-
-
- /**
- * Collect all coarse mesh cells
- * with at least one vertex at
- * which the determinant of the
- * Jacobian is zero or
- * negative. This is the function
- * for the case dim!=spacedim,
- * where we can not determine
- * whether a cell is twisted as it
- * may, for example, discretize a
- * manifold with a twist.
- */
- template <int dim, int spacedim>
- typename Triangulation<dim,spacedim>::DistortedCellList
- collect_distorted_coarse_cells (const Triangulation<dim,spacedim> &)
- {
- return typename Triangulation<dim,spacedim>::DistortedCellList();
- }
-
-
-
- /**
- * Return whether any of the
- * children of the given cell is
- * distorted or not. This is the
- * function for dim==spacedim.
- */
- template <int dim>
- bool
- has_distorted_children (const typename Triangulation<dim,dim>::cell_iterator &cell,
- internal::int2type<dim>,
- internal::int2type<dim>)
- {
- Assert (cell->has_children(), ExcInternalError());
-
- for (unsigned int c=0; c<cell->n_children(); ++c)
- {
- Point<dim> vertices[GeometryInfo<dim>::vertices_per_cell];
- for (unsigned int i=0; i<GeometryInfo<dim>::vertices_per_cell; ++i)
- vertices[i] = cell->child(c)->vertex(i);
-
- Tensor<0,dim> determinants[GeometryInfo<dim>::vertices_per_cell];
- GeometryInfo<dim>::alternating_form_at_vertices (vertices,
- determinants);
-
- for (unsigned int i=0; i<GeometryInfo<dim>::vertices_per_cell; ++i)
- if (determinants[i] <= 1e-9 * std::pow (cell->child(c)->diameter(),
- 1.*dim))
- return true;
- }
-
- return false;
- }
-
-
- /**
- * Function for dim!=spacedim. As
- * for
- * collect_distorted_coarse_cells,
- * there is nothing that we can do
- * in this case.
- */
- template <int dim, int spacedim>
- bool
- has_distorted_children (const typename Triangulation<dim,spacedim>::cell_iterator &,
- internal::int2type<dim>,
- internal::int2type<spacedim>)
- {
- return false;
- }
-
-
-
- /**
- * For a given triangulation: set up the
- * neighbor information on all cells.
- */
- template <int dim, int spacedim>
- void
- update_neighbors (Triangulation<dim,spacedim> &triangulation)
- {
- // each face can be neighbored on two sides
- // by cells. according to the face's
- // intrinsic normal we define the left
- // neighbor as the one for which the face
- // normal points outward, and store that
- // one first, with an offset of one we
- // store the right neighbor for which the
- // face normal points inward. This
- // information depends on the type of cell
- // and local number of face for the
- // 'standard ordering and orientation' of
- // faces and then on the face_orientation
- // information for the real mesh. Set up a
- // table to have fast access to those
- // offsets (0 for left and 1 for
- // right). Some of the values are invalid
- // as they reference too large face
- // numbers, but we just leave them at a
- // zero value.
- //
- // Note, that in 2d for lines as faces the
- // normal direction given in the
- // GeometryInfo class is not consistent. We
- // thus define here that the normal for a
- // line points to the right if the line
- // points upwards.
- //
- // first index: dimension (minus 2)
- // second index: local face index
- // third index: face_orientation (false and true)
- static const unsigned int left_right_offset[2][6][2] =
- {
- // quadrilateral
- {{0,1}, // face 0, face_orientation = false and true
- {1,0}, // face 1, face_orientation = false and true
- {1,0}, // face 2, face_orientation = false and true
- {0,1}, // face 3, face_orientation = false and true
- {0,0}, // face 4, invalid face
- {0,0}},// face 5, invalid face
- // hexahedron
- {{0,1},
- {1,0},
- {0,1},
- {1,0},
- {0,1},
- {1,0}}};
-
- // now create a vector of the two active
- // neighbors (left and right) for each face
- // and fill it by looping over all cells. For
- // cases with anisotropic refinement and more
- // then one cell neighboring at a given side
- // of the face we will automatically get the
- // active one on the highest level as we loop
- // over cells from lower levels first.
- const typename Triangulation<dim,spacedim>::cell_iterator dummy;
- std::vector<typename Triangulation<dim,spacedim>::cell_iterator>
- adjacent_cells(2*triangulation.n_raw_faces(), dummy);
-
- typename Triangulation<dim,spacedim>::cell_iterator
- cell = triangulation.begin(),
- endc = triangulation.end();
- for (; cell != endc; ++cell)
- for (unsigned int f=0; f<GeometryInfo<dim>::faces_per_cell; ++f)
- {
- const typename Triangulation<dim,spacedim>::face_iterator face=cell->face(f);
- const unsigned int offset=left_right_offset[dim-2][f][cell->face_orientation(f)];
- adjacent_cells[2*face->index() + offset] = cell;
- // if this cell is not refined, but the
- // face is, then we'll have to set our
- // cell as neighbor for the cild faces
- // as well. Fortunately the normal
- // orientation of children will be just
- // the same.
- if (dim==2)
- {
- if (cell->active() && face->has_children())
- {
- adjacent_cells[2*face->child(0)->index() + offset] = cell;
- adjacent_cells[2*face->child(1)->index() + offset] = cell;
- }
- }
- else // -> dim == 3
- {
- // We need the same as in 2d
- // here. Furthermore, if the face is
- // refined with cut_x or cut_y then
- // those children again in the other
- // direction, and if this cell is
- // refined isotropically (along the
- // face) then the neighbor will
- // (probably) be refined as cut_x or
- // cut_y along the face. For those
- // neighboring children cells, their
- // neighbor will be the current,
- // inactive cell, as our children are
- // too fine to be neighbors. Catch that
- // case by also acting on inactive
- // cells with isotropic refinement
- // along the face. If the situation
- // described is not present, the data
- // will be overwritten later on when we
- // visit cells on finer levels, so no
- // harm will be done.
- if (face->has_children() &&
- (cell->active() ||
- GeometryInfo<dim>::face_refinement_case(cell->refinement_case(),f) == RefinementCase<dim-1>::isotropic_refinement))
- {
-
- for (unsigned int c=0; c<face->n_children(); ++c)
- adjacent_cells[2*face->child(c)->index() + offset] = cell;
- if (face->child(0)->has_children())
- {
- adjacent_cells[2*face->child(0)->child(0)->index() + offset] = cell;
- adjacent_cells[2*face->child(0)->child(1)->index() + offset] = cell;
- }
- if (face->child(1)->has_children())
- {
- adjacent_cells[2*face->child(1)->child(0)->index() + offset] = cell;
- adjacent_cells[2*face->child(1)->child(1)->index() + offset] = cell;
- }
- } // if cell active and face refined
- } // else -> dim==3
- } // for all faces of all cells
-
- // now loop again over all cells and set the
- // corresponding neighbor cell. Note, that we
- // have to use the opposite of the
- // left_right_offset in this case as we want
- // the offset of the neighbor, not our own.
- for (cell=triangulation.begin(); cell != endc; ++cell)
- for (unsigned int f=0; f<GeometryInfo<dim>::faces_per_cell; ++f)
- cell->set_neighbor(f,
- adjacent_cells[2*cell->face(f)->index() + 1
- - left_right_offset[dim-2][f][cell->face_orientation(f)]]);
- }
-
-}// end of anonymous namespace
-
-
-namespace internal
-{
- namespace Triangulation
- {
- // make sure that if in the following we
- // write Triangulation<dim,spacedim>
- // we mean the *class*
- // dealii::Triangulation, not the
- // enclosing namespace
- // internal::Triangulation
- using dealii::Triangulation;
-
- /**
- * Exception
- * @ingroup Exceptions
- */
- DeclException0 (ExcCellShouldBeUnused);
- /**
- * Exception
- * @ingroup Exceptions
- */
- DeclException0 (ExcTooFewVerticesAllocated);
- /**
- * Exception
- * @ingroup Exceptions
- */
- DeclException0 (ExcUncaughtState);
- /**
- * Exception
- * @ingroup Exceptions
- */
- DeclException2 (ExcGridsDoNotMatch,
- int, int,
- << "The present grid has " << arg1 << " active cells, "
- << "but the one in the file had " << arg2);
- /**
- * Exception
- * @ingroup Exceptions
- */
- DeclException1 (ExcGridHasInvalidCell,
- int,
- << "Something went wrong when making cell " << arg1
- << ". Read the docs and the source code "
- << "for more information.");
- /**
- * Exception
- * @ingroup Exceptions
- */
- DeclException0 (ExcGridHasInvalidVertices);
- /**
- * Exception
- * @ingroup Exceptions
- */
- DeclException1 (ExcInternalErrorOnCell,
- int,
- << "Something went wrong upon construction of cell "
- << arg1);
- /**
- * A cell was entered which has
- * negative measure. In most
- * cases, this is due to a wrong
- * order of the vertices of the
- * cell.
- *
- * @ingroup Exceptions
- */
- DeclException1 (ExcCellHasNegativeMeasure,
- int,
- << "Cell " << arg1 << " has negative measure.");
- /**
- * A cell is created with a
- * vertex number exceeding the
- * vertex array.
- *
- * @ingroup Exceptions
- */
- DeclException3 (ExcInvalidVertexIndex,
- int, int, int,
- << "Error while creating cell " << arg1
- << ": the vertex index " << arg2 << " must be between 0 and "
- << arg3 << ".");
- /**
- * Exception
- * @ingroup Exceptions
- */
- DeclException2 (ExcLineInexistant,
- int, int,
- << "When trying to give a boundary indicator to a line: "
- << "the line with end vertices " << arg1 << " and "
- << arg2 << " does not exist.");
- /**
- * Exception
- * @ingroup Exceptions
- */
- DeclException4 (ExcQuadInexistant,
- int, int, int, int,
- << "When trying to give a boundary indicator to a quad: "
- << "the quad with bounding lines " << arg1 << ", " << arg2
- << ", " << arg3 << ", " << arg4 << " does not exist.");
- /**
- * Exception
- * @ingroup Exceptions
- */
- DeclException0 (ExcInteriorLineCantBeBoundary);
- /**
- * Exception
- * @ingroup Exceptions
- */
- DeclException0 (ExcInteriorQuadCantBeBoundary);
- /**
- * Exception
- * @ingroup Exceptions
- */
- DeclException2 (ExcMultiplySetLineInfoOfLine,
- int, int,
- << "In SubCellData the line info of the line with vertex indices "
- << arg1 << " and " << arg2 << " is multiply set.");
-
-
-/**
- * A class into which we put many of the functions that implement
- * functionality of the Triangulation class. The main reason for this
- * class is as follows: the majority of the functions in Triangulation
- * need to be implemented differently for dim==1, dim==2, and
- * dim==3. However, their implementation is largly independent of the
- * spacedim template parameter. So we would like to write things like
- *
- * template <int spacedim>
- * void Triangulation<1,spacedim>::create_triangulation (...) {...}
- *
- * Unfortunately, C++ doesn't allow this: member functions of class
- * templates have to be either not specialized at all, or fully
- * specialized. No partial specialization is allowed. One possible
- * solution would be to just duplicate the bodies of the functions and
- * have equally implemented functions
- *
- * template <>
- * void Triangulation<1,1>::create_triangulation (...) {...}
- *
- * template <>
- * void Triangulation<1,2>::create_triangulation (...) {...}
- *
- * but that is clearly an unsatisfactory solution. Rather, what we do
- * is introduce the current Implementation class in which we can write
- * these functions as member templates over spacedim, i.e. we can have
- *
- * template <int dim_, int spacedim_>
- * template <int spacedim>
- * void Triangulation<dim_,spacedim_>::Implementation::
- * create_triangulation (...,
- * Triangulation<1,spacedim> &tria ) {...}
- *
- * The outer template parameters are here unused, only the inner
- * ones are of real interest.
- *
- * One may ask why we put these functions into an class rather
- * than an anonymous namespace, for example?
- *
- * First, these implementation functions need to be friends of the
- * Triangulation class. It is simpler to make the entire class a friend
- * rather than listing all members of an implementation namespace as
- * friends of the Triangulation class (there is no such thing as a "friend
- * namespace XXX" directive).
- *
- * Ideally, we would make this class a member class of the
- * Triangulation<dim,spacedim> class, since then our implementation functions
- * have immediate access to the typedefs and static functions of the
- * surrounding Triangulation class. I.e., we do not have to write "typename
- * Triangulation<dim,spacedim>::active_cell_iterator" but can write
- * "active_cell_iterator" right away. This is, in fact, the way it was
- * implemented first, but we ran into a bug in gcc4.0:
- * @code
- * class Triangulation {
- * struct Implementation;
- * friend class TriaAccessor;
- * };
- *
- * class TriaAccessor {
- * struct Implementation;
- * friend class Triangulation;
- * };
- * @endcode
- *
- * Here, friendship (per C++ standard) is supposed to extend to all members of
- * the befriended class, including its 'Implementation' member class. But gcc4.0
- * gets this wrong: the members of Triangulation::Implementation are not friends
- * of TriaAccessor and the other way around. Ideally, one would fix this by
- * saying
- * @code
- * class Triangulation {
- * struct Implementation;
- * friend class TriaAccessor;
- * friend class TriaAccessor::Implementation; // **
- * };
- *
- * class TriaAccessor {
- * struct Implementation;
- * friend class Triangulation;
- * friend class Triangulation::Implementation;
- * };
- * @endcode
- * but that's not legal because in ** we don't know yet that TriaAccessor has
- * a member class Implementation and so we can't make it a friend. The only
- * way forward at this point was to make Implementation a class in the
- * internal namespace so that we can forward declare it and make it a friend
- * of the respective other outer class -- not quite what we wanted but the
- * only way I could see to make it work...
- */
- struct Implementation
- {
- /**
- * Create a triangulation from
- * given data. This function does
- * this work for 1-dimensional
- * triangulations independently
- * of the actual space dimension.
- */
- template <int spacedim>
- static
- void
- create_triangulation (const std::vector<Point<spacedim> > &v,
- const std::vector<CellData<1> > &cells,
- const SubCellData &/*subcelldata*/,
- Triangulation<1,spacedim> &triangulation)
- {
- // note: since no boundary
- // information can be given in one
- // dimension, the @p{subcelldata}
- // field is ignored. (only used for
- // error checking, which is a good
- // idea in any case)
- const unsigned int dim=1;
-
- // copy vertices
- triangulation.vertices = v;
- triangulation.vertices_used = std::vector<bool> (v.size(), true);
-
- // store the indices of the lines
- // which are adjacent to a given
- // vertex
- std::vector<std::vector<int> > lines_at_vertex (v.size());
-
- // reserve enough space
- triangulation.levels.push_back (new internal::Triangulation::TriaLevel<dim>);
- triangulation.levels[0]->reserve_space (cells.size(), dim);
- triangulation.levels[0]->cells.reserve_space (0,cells.size());
-
- // make up cells
- typename Triangulation<dim,spacedim>::raw_line_iterator
- next_free_line = triangulation.begin_raw_line ();
- for (unsigned int cell=0; cell<cells.size(); ++cell)
- {
- while (next_free_line->used())
- ++next_free_line;
-
- next_free_line->set (internal::Triangulation
- ::TriaObject<1> (cells[cell].vertices[0],
- cells[cell].vertices[1]));
- next_free_line->set_used_flag ();
- next_free_line->set_material_id (cells[cell].material_id);
- next_free_line->clear_user_data ();
- next_free_line->set_subdomain_id (0);
-
- // note that this cell is
- // adjacent to these vertices
- lines_at_vertex[cells[cell].vertices[0]].push_back (cell);
- lines_at_vertex[cells[cell].vertices[1]].push_back (cell);
- }
-
-
- // some security tests
- {
- unsigned int boundary_nodes = 0;
- for (unsigned int i=0; i<lines_at_vertex.size(); ++i)
- switch (lines_at_vertex[i].size())
- {
- case 1:
- // this vertex has only
- // one adjacent line
- ++boundary_nodes;
- break;
- case 2:
- break;
- default:
- // a node must have one
- // or two adjacent
- // lines
- AssertThrow (false, ExcInternalError());
- }
-
- // assert there are no more
- // than two boundary
- // nodes. note that if the
- // space dimension is
- // bigger than 1, then we
- // can have fewer than 2
- // nodes (for example a
- // ring of cells -- no end
- // points at all)
- AssertThrow (((spacedim == 1) && (boundary_nodes == 2))
- ||
- (spacedim > 1),
- ExcMessage("The Triangulation has too many end points"));
- }
-
-
-
- // update neighborship info
- typename Triangulation<dim,spacedim>::active_line_iterator
- line = triangulation.begin_active_line ();
- // for all lines
- for (; line!=triangulation.end(); ++line)
- // for each of the two vertices
- for (unsigned int vertex=0; vertex<GeometryInfo<dim>::vertices_per_cell; ++vertex)
- // if first cell adjacent to
- // this vertex is the present
- // one, then the neighbor is
- // the second adjacent cell and
- // vice versa
- if (lines_at_vertex[line->vertex_index(vertex)][0] == line->index())
- if (lines_at_vertex[line->vertex_index(vertex)].size() == 2)
- {
- const typename Triangulation<dim,spacedim>::cell_iterator
- neighbor (&triangulation,
- 0, // level
- lines_at_vertex[line->vertex_index(vertex)][1]);
- line->set_neighbor (vertex, neighbor);
- }
- else
- // no second adjacent cell
- // entered -> cell at
- // boundary
- line->set_neighbor (vertex, triangulation.end());
- else
- // present line is not first
- // adjacent one -> first
- // adjacent one is neighbor
- {
- const typename Triangulation<dim,spacedim>::cell_iterator
- neighbor (&triangulation,
- 0, // level
- lines_at_vertex[line->vertex_index(vertex)][0]);
- line->set_neighbor (vertex, neighbor);
- }
- }
-
-
- /**
- * Create a triangulation from
- * given data. This function does
- * this work for 2-dimensional
- * triangulations independently
- * of the actual space dimension.
- */
- template <int spacedim>
- static
- void
- create_triangulation (const std::vector<Point<spacedim> > &v,
- const std::vector<CellData<2> > &cells,
- const SubCellData &subcelldata,
- Triangulation<2,spacedim> &triangulation)
- {
- const unsigned int dim=2;
-
- // copy vertices
- triangulation.vertices = v;
- triangulation.vertices_used = std::vector<bool> (v.size(), true);
-
- // make up a list of the needed
- // lines each line is a pair of
- // vertices. The list is kept
- // sorted and it is guaranteed that
- // each line is inserted only once.
- // While the key of such an entry
- // is the pair of vertices, the
- // thing it points to is an
- // iterator pointing to the line
- // object itself. In the first run,
- // these iterators are all invalid
- // ones, but they are filled
- // afterwards
- std::map<std::pair<int,int>,
- typename Triangulation<dim,spacedim>::line_iterator> needed_lines;
- for (unsigned int cell=0; cell<cells.size(); ++cell)
- {
- for (unsigned int vertex=0; vertex<4; ++vertex)
- AssertThrow (cells[cell].vertices[vertex] < triangulation.vertices.size(),
- ExcInvalidVertexIndex (cell, cells[cell].vertices[vertex],
- triangulation.vertices.size()));
-
- for (unsigned int line=0; line<GeometryInfo<dim>::faces_per_cell; ++line)
- {
- // given a line vertex number
- // (0,1) on a specific line we
- // get the cell vertex number
- // (0-4) through the
- // line_to_cell_vertices
- // function
- std::pair<int,int> line_vertices(
- cells[cell].vertices[GeometryInfo<dim>::line_to_cell_vertices(line, 0)],
- cells[cell].vertices[GeometryInfo<dim>::line_to_cell_vertices(line, 1)]);
-
- // assert that the line was
- // not already inserted in
- // reverse order. This
- // happens in spite of the
- // vertex rotation above,
- // if the sense of the cell
- // was incorrect.
- //
- // Here is what usually
- // happened when this
- // exception is thrown:
- // consider these two cells
- // and the vertices
- // 3---4---5
- // | | |
- // 0---1---2
- // If in the input vector
- // the two cells are given
- // with vertices <0 1 4 3>
- // and <4 1 2 5>, in the
- // first cell the middle
- // line would have
- // direction 1->4, while in
- // the second it would be
- // 4->1. This will cause
- // the exception.
- AssertThrow (needed_lines.find(std::make_pair(line_vertices.second,
- line_vertices.first))
- ==
- needed_lines.end(),
- ExcGridHasInvalidCell(cell));
-
- // insert line, with
- // invalid iterator if line
- // already exists, then
- // nothing bad happens here
- needed_lines[line_vertices] = triangulation.end_line();
- }
- }
-
-
- // check that every vertex has at
- // least two adjacent lines
- {
- std::vector<unsigned short int> vertex_touch_count (v.size(), 0);
- typename std::map<std::pair<int,int>,
- typename Triangulation<dim,spacedim>::line_iterator>::iterator i;
- for (i=needed_lines.begin(); i!=needed_lines.end(); i++)
- {
- // touch the vertices of
- // this line
- ++vertex_touch_count[i->first.first];
- ++vertex_touch_count[i->first.second];
- }
-
- // assert minimum touch count
- // is at least two. if not so,
- // then clean triangulation and
- // exit with an exception
- AssertThrow (* (std::min_element(vertex_touch_count.begin(),
- vertex_touch_count.end())) >= 2,
- ExcGridHasInvalidVertices());
- }
-
- // reserve enough space
- triangulation.levels.push_back (new internal::Triangulation::TriaLevel<dim>);
- triangulation.faces = new internal::Triangulation::TriaFaces<dim>;
- triangulation.levels[0]->reserve_space (cells.size(), dim);
- triangulation.faces->lines.reserve_space (0,needed_lines.size());
- triangulation.levels[0]->cells.reserve_space (0,cells.size());
-
- // make up lines
- {
- typename Triangulation<dim,spacedim>::raw_line_iterator
- line = triangulation.begin_raw_line();
- typename std::map<std::pair<int,int>,
- typename Triangulation<dim,spacedim>::line_iterator>::iterator i;
- for (i = needed_lines.begin();
- line!=triangulation.end_line(); ++line, ++i)
- {
- line->set (internal::Triangulation::TriaObject<1>(i->first.first,
- i->first.second));
- line->set_used_flag ();
- line->clear_user_flag ();
- line->clear_user_data ();
- i->second = line;
- }
- }
-
-
- // store for each line index
- // the adjacent cells
- std::map<int,std::vector<typename Triangulation<dim,spacedim>::cell_iterator> >
- adjacent_cells;
-
- // finally make up cells
- {
- typename Triangulation<dim,spacedim>::raw_cell_iterator
- cell = triangulation.begin_raw_quad();
- for (unsigned int c=0; c<cells.size(); ++c, ++cell)
- {
- typename Triangulation<dim,spacedim>::line_iterator
- lines[GeometryInfo<dim>::lines_per_cell];
- for (unsigned int line=0; line<GeometryInfo<dim>::lines_per_cell; ++line)
- lines[line]=needed_lines[std::make_pair(
- cells[c].vertices[GeometryInfo<dim>::line_to_cell_vertices(line, 0)],
- cells[c].vertices[GeometryInfo<dim>::line_to_cell_vertices(line, 1)])];
-
- cell->set (internal::Triangulation::TriaObject<2> (lines[0]->index(),
- lines[1]->index(),
- lines[2]->index(),
- lines[3]->index()));
-
- cell->set_used_flag ();
- cell->set_material_id (cells[c].material_id);
- cell->clear_user_data ();
- cell->set_subdomain_id (0);
-
- // note that this cell is
- // adjacent to the four
- // lines
- for (unsigned int line=0; line<GeometryInfo<dim>::lines_per_cell; ++line)
- adjacent_cells[lines[line]->index()].push_back (cell);
- }
- }
-
-
- for (typename Triangulation<dim,spacedim>::line_iterator
- line=triangulation.begin_line();
- line!=triangulation.end_line(); ++line)
- {
- const unsigned int n_adj_cells = adjacent_cells[line->index()].size();
- // assert that every line has
- // one or two adjacent cells
- AssertThrow ((n_adj_cells >= 1) &&
- (n_adj_cells <= 2),
- ExcInternalError());
-
- // if only one cell: line is at
- // boundary -> give it the
- // boundary indicator zero by
- // default
- if (n_adj_cells == 1)
- line->set_boundary_indicator (0);
- else
- // interior line -> 255
- line->set_boundary_indicator (255);
- }
-
- // set boundary indicators where
- // given
- std::vector<CellData<1> >::const_iterator boundary_line
- = subcelldata.boundary_lines.begin();
- std::vector<CellData<1> >::const_iterator end_boundary_line
- = subcelldata.boundary_lines.end();
- for (; boundary_line!=end_boundary_line; ++boundary_line)
- {
- typename Triangulation<dim,spacedim>::line_iterator line;
- std::pair<int,int> line_vertices(std::make_pair(boundary_line->vertices[0],
- boundary_line->vertices[1]));
- if (needed_lines.find(line_vertices) != needed_lines.end())
- // line found in this
- // direction
- line = needed_lines[line_vertices];
- else
- {
- // look whether it exists
- // in reverse direction
- std::swap (line_vertices.first, line_vertices.second);
- if (needed_lines.find(line_vertices) != needed_lines.end())
- line = needed_lines[line_vertices];
- else
- // line does not exist
- AssertThrow (false, ExcLineInexistant(line_vertices.first,
- line_vertices.second));
- }
-
- // assert that we only set
- // boundary info once
- AssertThrow (! (line->boundary_indicator() != 0 &&
- line->boundary_indicator() != 255),
- ExcMultiplySetLineInfoOfLine(line_vertices.first,
- line_vertices.second));
-
- // Assert that only exterior lines
- // are given a boundary indicator
- AssertThrow (! (line->boundary_indicator() == 255),
- ExcInteriorLineCantBeBoundary());
-
- line->set_boundary_indicator (boundary_line->material_id);
- }
-
-
- // finally update neighborship info
- for (typename Triangulation<dim,spacedim>::cell_iterator
- cell=triangulation.begin(); cell!=triangulation.end(); ++cell)
- for (unsigned int side=0; side<4; ++side)
- if (adjacent_cells[cell->line(side)->index()][0] == cell)
- // first adjacent cell is
- // this one
- {
- if (adjacent_cells[cell->line(side)->index()].size() == 2)
- // there is another
- // adjacent cell
- cell->set_neighbor (side,
- adjacent_cells[cell->line(side)->index()][1]);
- }
- // first adjacent cell is not this
- // one, -> it must be the neighbor
- // we are looking for
- else
- cell->set_neighbor (side,
- adjacent_cells[cell->line(side)->index()][0]);
- }
-
-
-/**
- * Invent an object which compares two internal::Triangulation::TriaObject<2>
- * against each other. This comparison is needed in order to establish a map
- * of TriaObject<2> to iterators in the Triangulation<3,3>::create_triangulation
- * function.
- *
- * Since this comparison is not canonical, we do not include it into the
- * general internal::Triangulation::TriaObject<2> class.
- */
- struct QuadComparator
- {
- inline bool operator () (const internal::Triangulation::TriaObject<2> &q1,
- const internal::Triangulation::TriaObject<2> &q2) const
- {
- // here is room to
- // optimize the repeated
- // equality test of the
- // previous lines; the
- // compiler will probably
- // take care of most of
- // it anyway
- if ((q1.face(0) < q2.face(0)) ||
- ((q1.face(0) == q2.face(0)) &&
- (q1.face(1) < q2.face(1))) ||
- ((q1.face(0) == q2.face(0)) &&
- (q1.face(1) == q2.face(1)) &&
- (q1.face(2) < q2.face(2))) ||
- ((q1.face(0) == q2.face(0)) &&
- (q1.face(1) == q2.face(1)) &&
- (q1.face(2) == q2.face(2)) &&
- (q1.face(3) < q2.face(3))))
- return true;
- else
- return false;
- }
- };
-
-
-
- template <int spacedim>
- static
- void
- create_triangulation (const std::vector<Point<spacedim> > &v,
- const std::vector<CellData<3> > &cells,
- const SubCellData &subcelldata,
- Triangulation<3,spacedim> &triangulation)
- {
- const unsigned int dim=3;
-
- // copy vertices
- triangulation.vertices = v;
- triangulation.vertices_used = std::vector<bool> (v.size(), true);
-
- // check that all cells have
- // positive volume. if not call the
- // invert_all_cells_of_negative_grid
- // and reorder_cells function of
- // GridReordering before creating
- // the triangulation
- for (unsigned int cell_no=0; cell_no<cells.size(); ++cell_no)
- AssertThrow (dealii::GridTools::cell_measure(triangulation.vertices,
- cells[cell_no].vertices) >= 0,
- ExcGridHasInvalidCell(cell_no));
-
- ///////////////////////////////////////
- // first set up some collections of data
- //
- // make up a list of the needed
- // lines
- //
- // each line is a pair of
- // vertices. The list is kept
- // sorted and it is guaranteed that
- // each line is inserted only once.
- // While the key of such an entry
- // is the pair of vertices, the
- // thing it points to is an
- // iterator pointing to the line
- // object itself. In the first run,
- // these iterators are all invalid
- // ones, but they are filled
- // afterwards same applies for the
- // quads
- typename std::map<std::pair<int,int>,
- typename Triangulation<dim,spacedim>::line_iterator> needed_lines;
- for (unsigned int cell=0; cell<cells.size(); ++cell)
- {
- // check whether vertex indices
- // are valid ones
- for (unsigned int vertex=0; vertex<GeometryInfo<dim>::vertices_per_cell; ++vertex)
- AssertThrow (cells[cell].vertices[vertex] < triangulation.vertices.size(),
- ExcInvalidVertexIndex (cell, cells[cell].vertices[vertex],
- triangulation.vertices.size()));
-
- for (unsigned int line=0; line<GeometryInfo<dim>::lines_per_cell; ++line)
- {
- // given a line vertex number
- // (0,1) on a specific line we
- // get the cell vertex number
- // (0-7) through the
- // line_to_cell_vertices
- // function
- std::pair<int,int> line_vertices(
- cells[cell].vertices[GeometryInfo<dim>::line_to_cell_vertices(line, 0)],
- cells[cell].vertices[GeometryInfo<dim>::line_to_cell_vertices(line, 1)]);
-
- // if that line was already inserted
- // in reverse order do nothing, else
- // insert the line
- if ( (needed_lines.find(std::make_pair(line_vertices.second,
- line_vertices.first))
- ==
- needed_lines.end()))
- {
- // insert line, with
- // invalid iterator. if line
- // already exists, then
- // nothing bad happens here
- needed_lines[line_vertices] = triangulation.end_line();
- }
- }
- }
-
-
- /////////////////////////////////
- // now for some sanity-checks:
- //
- // check that every vertex has at
- // least tree adjacent lines
- {
- std::vector<unsigned short int> vertex_touch_count (v.size(), 0);
- typename std::map<std::pair<int,int>,
- typename Triangulation<dim,spacedim>::line_iterator>::iterator i;
- for (i=needed_lines.begin(); i!=needed_lines.end(); i++)
- {
- // touch the vertices of
- // this line
- ++vertex_touch_count[i->first.first];
- ++vertex_touch_count[i->first.second];
- }
-
- // assert minimum touch count
- // is at least three. if not so,
- // then clean triangulation and
- // exit with an exception
- AssertThrow (* (std::min_element(vertex_touch_count.begin(),
- vertex_touch_count.end())) >= 3,
- ExcGridHasInvalidVertices());
- }
-
-
- ///////////////////////////////////
- // actually set up data structures
- // for the lines
- // reserve enough space
- triangulation.levels.push_back (new internal::Triangulation::TriaLevel<dim>);
- triangulation.faces = new internal::Triangulation::TriaFaces<dim>;
- triangulation.levels[0]->reserve_space (cells.size(), dim);
- triangulation.faces->lines.reserve_space (0,needed_lines.size());
-
- // make up lines
- {
- typename Triangulation<dim,spacedim>::raw_line_iterator
- line = triangulation.begin_raw_line();
- typename std::map<std::pair<int,int>,
- typename Triangulation<dim,spacedim>::line_iterator>::iterator i;
- for (i = needed_lines.begin(); line!=triangulation.end_line(); ++line, ++i)
- {
- line->set (internal::Triangulation::TriaObject<1>(i->first.first,
- i->first.second));
- line->set_used_flag ();
- line->clear_user_flag ();
- line->clear_user_data ();
-
- // now set the iterator for
- // this line
- i->second = line;
- }
- }
-
-
- ///////////////////////////////////////////
- // make up the quads of this triangulation
- //
- // same thing: the iterators are
- // set to the invalid value at
- // first, we only collect the data
- // now
-
- // the bool array stores, wether the lines
- // are in the standard orientation or not
-
- // note that QuadComparator is a
- // class declared and defined in
- // this file
- std::map<internal::Triangulation::TriaObject<2>,
- std::pair<typename Triangulation<dim,spacedim>::quad_iterator,
- std_cxx1x::array<bool,GeometryInfo<dim>::lines_per_face> >,
- QuadComparator>
- needed_quads;
- for (unsigned int cell=0; cell<cells.size(); ++cell)
- {
- // the faces are quads which
- // consist of four numbers
- // denoting the index of the
- // four lines bounding the
- // quad. we can get this index
- // by asking @p{needed_lines}
- // for an iterator to this
- // line, dereferencing it and
- // thus return an iterator into
- // the @p{lines} array of the
- // triangulation, which is
- // already set up. we can then
- // ask this iterator for its
- // index within the present
- // level (the level is zero, of
- // course)
- //
- // to make things easier, we
- // don't create the lines
- // (pairs of their vertex
- // indices) in place, but
- // before they are really
- // needed.
- std::pair<int,int> line_list[GeometryInfo<dim>::lines_per_cell],
- inverse_line_list[GeometryInfo<dim>::lines_per_cell];
- unsigned int face_line_list[GeometryInfo<dim>::lines_per_face];
- std_cxx1x::array<bool,GeometryInfo<dim>::lines_per_face> orientation;
-
- for (unsigned int line=0; line<GeometryInfo<dim>::lines_per_cell; ++line)
- {
- line_list[line]=std::pair<int,int> (
- cells[cell].vertices[GeometryInfo<dim>::line_to_cell_vertices(line, 0)],
- cells[cell].vertices[GeometryInfo<dim>::line_to_cell_vertices(line, 1)]);
- inverse_line_list[line]=std::pair<int,int> (
- cells[cell].vertices[GeometryInfo<dim>::line_to_cell_vertices(line, 1)],
- cells[cell].vertices[GeometryInfo<dim>::line_to_cell_vertices(line, 0)]);
- }
-
- for (unsigned int face=0; face<GeometryInfo<dim>::faces_per_cell; ++face)
- {
- // set up a list of the lines to be
- // used for this face. check the
- // direction for each line
- //
- // given a face line number (0-3) on
- // a specific face we get the cell
- // line number (0-11) through the
- // face_to_cell_lines function
- for (unsigned int l=0; l<GeometryInfo<dim>::lines_per_face; ++l)
- if (needed_lines.find (inverse_line_list[GeometryInfo<dim>::
- face_to_cell_lines(face,l)]) == needed_lines.end())
- {
- face_line_list[l]=needed_lines[line_list[GeometryInfo<dim>::
- face_to_cell_lines(face,l)]]->index();
- orientation[l]=true;
- }
- else
- {
- face_line_list[l]=needed_lines[inverse_line_list[GeometryInfo<dim>::
- face_to_cell_lines(face,l)]]->index();
- orientation[l]=false;
- }
-
-
- internal::Triangulation::TriaObject<2>
- quad(face_line_list[0],
- face_line_list[1],
- face_line_list[2],
- face_line_list[3]);
-
- // insert quad, with
- // invalid iterator
- //
- // if quad already exists,
- // then nothing bad happens
- // here, as this will then
- // simply become an
- // interior face of the
- // triangulation. however,
- // we will run into major
- // trouble if the face was
- // already inserted in the
- // opposite
- // direction. there are
- // really only two
- // orientations for a face
- // to be in, since the edge
- // directions are already
- // set. thus, vertex 0 is
- // the one from which two
- // edges originate, and
- // vertex 3 is the one to
- // which they converge. we
- // are then left with
- // orientations 0-1-2-3 and
- // 2-3-0-1 for the order of
- // lines. the
- // corresponding quad can
- // be easily constructed by
- // exchanging lines. we do
- // so here, just to check
- // that that flipped quad
- // isn't already in the
- // triangulation. if it is,
- // then don't insert the
- // new one and instead
- // later set the
- // face_orientation flag
- const internal::Triangulation::TriaObject<2>
- test_quad_1(quad.face(2), quad.face(3),
- quad.face(0), quad.face(1)),//face_orientation=false, face_flip=false, face_rotation=false
- test_quad_2(quad.face(0), quad.face(1),
- quad.face(3), quad.face(2)),//face_orientation=false, face_flip=false, face_rotation=true
- test_quad_3(quad.face(3), quad.face(2),
- quad.face(1), quad.face(0)),//face_orientation=false, face_flip=true, face_rotation=false
- test_quad_4(quad.face(1), quad.face(0),
- quad.face(2), quad.face(3)),//face_orientation=false, face_flip=true, face_rotation=true
- test_quad_5(quad.face(2), quad.face(3),
- quad.face(1), quad.face(0)),//face_orientation=true, face_flip=false, face_rotation=true
- test_quad_6(quad.face(1), quad.face(0),
- quad.face(3), quad.face(2)),//face_orientation=true, face_flip=true, face_rotation=false
- test_quad_7(quad.face(3), quad.face(2),
- quad.face(0), quad.face(1));//face_orientation=true, face_flip=true, face_rotation=true
- if (needed_quads.find (test_quad_1) == needed_quads.end() &&
- needed_quads.find (test_quad_2) == needed_quads.end() &&
- needed_quads.find (test_quad_3) == needed_quads.end() &&
- needed_quads.find (test_quad_4) == needed_quads.end() &&
- needed_quads.find (test_quad_5) == needed_quads.end() &&
- needed_quads.find (test_quad_6) == needed_quads.end() &&
- needed_quads.find (test_quad_7) == needed_quads.end())
- needed_quads[quad] = std::make_pair(triangulation.end_quad(),orientation);
- }
- }
-
-
- /////////////////////////////////
- // enter the resulting quads into
- // the arrays of the Triangulation
- //
- // first reserve enough space
- triangulation.faces->quads.reserve_space (0,needed_quads.size());
-
- {
- typename Triangulation<dim,spacedim>::raw_quad_iterator
- quad = triangulation.begin_raw_quad();
- typename std::map<internal::Triangulation::TriaObject<2>,
- std::pair<typename Triangulation<dim,spacedim>::quad_iterator,
- std_cxx1x::array<bool,GeometryInfo<dim>::lines_per_face> >,
- QuadComparator>
- ::iterator q;
- for (q = needed_quads.begin(); quad!=triangulation.end_quad(); ++quad, ++q)
- {
- quad->set (q->first);
- quad->set_used_flag ();
- quad->clear_user_flag ();
- quad->clear_user_data ();
- // set the line orientation
- quad->set_line_orientation(0,q->second.second[0]);
- quad->set_line_orientation(1,q->second.second[1]);
- quad->set_line_orientation(2,q->second.second[2]);
- quad->set_line_orientation(3,q->second.second[3]);
-
-
- // now set the iterator for
- // this quad
- q->second.first = quad;
- }
- }
-
- /////////////////////////////////
- // finally create the cells
- triangulation.levels[0]->cells.reserve_space (cells.size());
-
- // store for each quad index the
- // adjacent cells
- std::map<int,std::vector<typename Triangulation<dim,spacedim>::cell_iterator> >
- adjacent_cells;
-
- // finally make up cells
- {
- typename Triangulation<dim,spacedim>::raw_cell_iterator
- cell = triangulation.begin_raw_hex();
- for (unsigned int c=0; c<cells.size(); ++c, ++cell)
- {
- // first find for each of
- // the cells the quad
- // iterator of the
- // respective faces.
- //
- // to this end, set up the
- // lines of this cell and
- // find the quads that are
- // bounded by these lines;
- // these are then the faces
- // of the present cell
- std::pair<int,int> line_list[GeometryInfo<dim>::lines_per_cell],
- inverse_line_list[GeometryInfo<dim>::lines_per_cell];
- unsigned int face_line_list[4];
- for (unsigned int line=0; line<GeometryInfo<dim>::lines_per_cell; ++line)
- {
- line_list[line]=std::make_pair(
- cells[c].vertices[GeometryInfo<dim>::line_to_cell_vertices(line, 0)],
- cells[c].vertices[GeometryInfo<dim>::line_to_cell_vertices(line, 1)]);
- inverse_line_list[line]=std::pair<int,int> (
- cells[c].vertices[GeometryInfo<dim>::line_to_cell_vertices(line, 1)],
- cells[c].vertices[GeometryInfo<dim>::line_to_cell_vertices(line, 0)]);
- }
-
- // get the iterators
- // corresponding to the
- // faces. also store
- // whether they are
- // reversed or not
- typename Triangulation<dim,spacedim>::quad_iterator
- face_iterator[GeometryInfo<dim>::faces_per_cell];
- bool face_orientation[GeometryInfo<dim>::faces_per_cell];
- bool face_flip[GeometryInfo<dim>::faces_per_cell];
- bool face_rotation[GeometryInfo<dim>::faces_per_cell];
- for (unsigned int face=0; face<GeometryInfo<dim>::faces_per_cell; ++face)
- {
- for (unsigned int l=0; l<GeometryInfo<dim>::lines_per_face; ++l)
- if (needed_lines.find (inverse_line_list[GeometryInfo<dim>::
- face_to_cell_lines(face,l)]) == needed_lines.end())
- face_line_list[l]=needed_lines[line_list[GeometryInfo<dim>::
- face_to_cell_lines(face,l)]]->index();
- else
- face_line_list[l]=needed_lines[inverse_line_list[GeometryInfo<dim>::
- face_to_cell_lines(face,l)]]->index();
-
- internal::Triangulation::TriaObject<2>
- quad(face_line_list[0],
- face_line_list[1],
- face_line_list[2],
- face_line_list[3]);
-
- if (needed_quads.find (quad) != needed_quads.end())
- {
- // face is in standard
- // orientation (and not
- // flipped or rotated). this
- // must be true for at least
- // one of the two cells
- // containing this face
- // (i.e. for the cell which
- // originally inserted the
- // face)
- face_iterator[face] = needed_quads[quad].first;
- face_orientation[face] = true;
- face_flip[face]=false;
- face_rotation[face]=false;
- }
- else
- {
- // face must be available in
- // reverse order
- // then. construct all
- // possibilities and check
- // them one after the other
- const internal::Triangulation::TriaObject<2>
- test_quad_1(quad.face(2), quad.face(3),
- quad.face(0), quad.face(1)),//face_orientation=false, face_flip=false, face_rotation=false
- test_quad_2(quad.face(0), quad.face(1),
- quad.face(3), quad.face(2)),//face_orientation=false, face_flip=false, face_rotation=true
- test_quad_3(quad.face(3), quad.face(2),
- quad.face(1), quad.face(0)),//face_orientation=false, face_flip=true, face_rotation=false
- test_quad_4(quad.face(1), quad.face(0),
- quad.face(2), quad.face(3)),//face_orientation=false, face_flip=true, face_rotation=true
- test_quad_5(quad.face(2), quad.face(3),
- quad.face(1), quad.face(0)),//face_orientation=true, face_flip=false, face_rotation=true
- test_quad_6(quad.face(1), quad.face(0),
- quad.face(3), quad.face(2)),//face_orientation=true, face_flip=true, face_rotation=false
- test_quad_7(quad.face(3), quad.face(2),
- quad.face(0), quad.face(1));//face_orientation=true, face_flip=true, face_rotation=true
- if (needed_quads.find (test_quad_1) != needed_quads.end())
- {
- face_iterator[face] = needed_quads[test_quad_1].first;
- face_orientation[face] = false;
- face_flip[face]=false;
- face_rotation[face]=false;
- }
- else if (needed_quads.find (test_quad_2) != needed_quads.end())
- {
- face_iterator[face] = needed_quads[test_quad_2].first;
- face_orientation[face] = false;
- face_flip[face]=false;
- face_rotation[face]=true;
- }
- else if (needed_quads.find (test_quad_3) != needed_quads.end())
- {
- face_iterator[face] = needed_quads[test_quad_3].first;
- face_orientation[face] = false;
- face_flip[face]=true;
- face_rotation[face]=false;
- }
- else if (needed_quads.find (test_quad_4) != needed_quads.end())
- {
- face_iterator[face] = needed_quads[test_quad_4].first;
- face_orientation[face] = false;
- face_flip[face]=true;
- face_rotation[face]=true;
- }
- else if (needed_quads.find (test_quad_5) != needed_quads.end())
- {
- face_iterator[face] = needed_quads[test_quad_5].first;
- face_orientation[face] = true;
- face_flip[face]=false;
- face_rotation[face]=true;
- }
- else if (needed_quads.find (test_quad_6) != needed_quads.end())
- {
- face_iterator[face] = needed_quads[test_quad_6].first;
- face_orientation[face] = true;
- face_flip[face]=true;
- face_rotation[face]=false;
- }
- else if (needed_quads.find (test_quad_7) != needed_quads.end())
- {
- face_iterator[face] = needed_quads[test_quad_7].first;
- face_orientation[face] = true;
- face_flip[face]=true;
- face_rotation[face]=true;
- }
-
- else
- // we didn't find the
- // face in any direction,
- // so something went
- // wrong above
- Assert(false,ExcInternalError());
-
- }
- }// for all faces
-
- // make the cell out of
- // these iterators
- cell->set (internal::Triangulation
- ::TriaObject<3> (face_iterator[0]->index(),
- face_iterator[1]->index(),
- face_iterator[2]->index(),
- face_iterator[3]->index(),
- face_iterator[4]->index(),
- face_iterator[5]->index()));
-
- cell->set_used_flag ();
- cell->set_material_id (cells[c].material_id);
- cell->clear_user_flag ();
- cell->clear_user_data ();
- cell->set_subdomain_id (0);
-
- // set orientation flag for
- // each of the faces
- for (unsigned int quad=0; quad<GeometryInfo<dim>::faces_per_cell; ++quad)
- {
- cell->set_face_orientation (quad, face_orientation[quad]);
- cell->set_face_flip (quad, face_flip[quad]);
- cell->set_face_rotation (quad, face_rotation[quad]);
- }
-
-
- // note that this cell is
- // adjacent to the six
- // quads
- for (unsigned int quad=0; quad<GeometryInfo<dim>::faces_per_cell; ++quad)
- adjacent_cells[face_iterator[quad]->index()].push_back (cell);
-
-#ifdef DEBUG
- // make some checks on the
- // lines and their
- // ordering
-
- // first map all cell lines
- // to the two face lines
- // which should
- // coincide. all face lines
- // are included with a cell
- // line number (0-11)
- // key. At the end all keys
- // will be included twice
- // (for each of the two
- // coinciding lines once)
- std::multimap<unsigned int, std::pair<unsigned int, unsigned int> >
- cell_to_face_lines;
- for (unsigned int face=0; face<GeometryInfo<dim>::faces_per_cell; ++face)
- for (unsigned int line=0; line<GeometryInfo<dim>::lines_per_face; ++line)
- cell_to_face_lines.insert(
- std::pair<unsigned int, std::pair<unsigned int, unsigned int> > (
- GeometryInfo<dim>::face_to_cell_lines(face,line),
- std::pair<unsigned int, unsigned int> (face,line)));
- std::multimap<unsigned int, std::pair<unsigned int, unsigned int> >::const_iterator
- map_iter=cell_to_face_lines.begin();
-
- for (; map_iter!=cell_to_face_lines.end(); ++map_iter)
- {
- const unsigned int cell_line=map_iter->first;
- const unsigned int face1=map_iter->second.first;
- const unsigned int line1=map_iter->second.second;
- ++map_iter;
- Assert(map_iter!=cell_to_face_lines.end(), ExcInternalErrorOnCell(c));
- Assert(map_iter->first==cell_line, ExcInternalErrorOnCell(c));
- const unsigned int face2=map_iter->second.first;
- const unsigned int line2=map_iter->second.second;
-
- // check that the pair
- // of lines really
- // coincide. Take care
- // about the face
- // orientation;
- Assert (face_iterator[face1]->line(GeometryInfo<dim>::standard_to_real_face_line(
- line1,
- face_orientation[face1],
- face_flip[face1],
- face_rotation[face1])) ==
- face_iterator[face2]->line(GeometryInfo<dim>::standard_to_real_face_line(
- line2,
- face_orientation[face2],
- face_flip[face2],
- face_rotation[face2])),
- ExcInternalErrorOnCell(c));
- }
-#endif
- }
- }
-
-
- /////////////////////////////////////////
- // find those quads which are at the
- // boundary and mark them appropriately
- for (typename Triangulation<dim,spacedim>::quad_iterator
- quad=triangulation.begin_quad(); quad!=triangulation.end_quad(); ++quad)
- {
- const unsigned int n_adj_cells = adjacent_cells[quad->index()].size();
- // assert that every quad has
- // one or two adjacent cells
- AssertThrow ((n_adj_cells >= 1) &&
- (n_adj_cells <= 2),
- ExcInternalError());
-
- // if only one cell: quad is at
- // boundary -> give it the
- // boundary indicator zero by
- // default
- if (n_adj_cells == 1)
- quad->set_boundary_indicator (0);
- else
- // interior quad -> 255
- quad->set_boundary_indicator (255);
- }
-
- /////////////////////////////////////////
- // next find those lines which are at
- // the boundary and mark all others as
- // interior ones
- //
- // for this: first mark all lines
- // as interior
- for (typename Triangulation<dim,spacedim>::line_iterator
- line=triangulation.begin_line(); line!=triangulation.end_line(); ++line)
- line->set_boundary_indicator (255);
- // next reset all lines bounding
- // boundary quads as on the
- // boundary also. note that since
- // we are in 3d, there are cases
- // where one or more lines of a
- // quad that is not on the
- // boundary, are actually boundary
- // lines. they will not be marked
- // when visiting this
- // face. however, since we do not
- // support dim-2 dimensional
- // boundaries (i.e. internal lines
- // constituting boundaries), every
- // such line is also part of a face
- // that is actually on the
- // boundary, so sooner or later we
- // get to mark that line for being
- // on the boundary
- for (typename Triangulation<dim,spacedim>::quad_iterator
- quad=triangulation.begin_quad(); quad!=triangulation.end_quad(); ++quad)
- if (quad->at_boundary())
- for (unsigned int l=0; l<4; ++l)
- quad->line(l)->set_boundary_indicator (0);
-
- ///////////////////////////////////////
- // now set boundary indicators
- // where given
- //
- // first do so for lines
- std::vector<CellData<1> >::const_iterator boundary_line
- = subcelldata.boundary_lines.begin();
- std::vector<CellData<1> >::const_iterator end_boundary_line
- = subcelldata.boundary_lines.end();
- for (; boundary_line!=end_boundary_line; ++boundary_line)
- {
- typename Triangulation<dim,spacedim>::line_iterator line;
- std::pair <int, int> line_vertices(std::make_pair(boundary_line->vertices[0],
- boundary_line->vertices[1]));
- if (needed_lines.find(line_vertices) != needed_lines.end())
- // line found in this
- // direction
- line = needed_lines[line_vertices];
-
- else
- {
- // look wether it exists in
- // reverse direction
- std::swap (line_vertices.first, line_vertices.second);
- if (needed_lines.find(line_vertices) != needed_lines.end())
- line = needed_lines[line_vertices];
- else
- // line does not exist
- AssertThrow (false, ExcLineInexistant(line_vertices.first,
- line_vertices.second));
- }
- // Assert that only exterior
- // lines are given a boundary
- // indicator
- AssertThrow (line->at_boundary(),
- ExcInteriorLineCantBeBoundary());
-
- // and make sure that we don't
- // attempt to reset the
- // boundary indicator to a
- // different than the
- // previously set value
- if (line->boundary_indicator() != 0)
- AssertThrow (line->boundary_indicator() == boundary_line->material_id,
- ExcMessage ("Duplicate boundary lines are only allowed "
- "if they carry the same boundary indicator."));
-
- line->set_boundary_indicator (boundary_line->material_id);
- }
-
-
- // now go on with boundary faces
- std::vector<CellData<2> >::const_iterator boundary_quad
- = subcelldata.boundary_quads.begin();
- std::vector<CellData<2> >::const_iterator end_boundary_quad
- = subcelldata.boundary_quads.end();
- for (; boundary_quad!=end_boundary_quad; ++boundary_quad)
- {
- typename Triangulation<dim,spacedim>::quad_iterator quad;
- typename Triangulation<dim,spacedim>::line_iterator line[4];
-
- // first find the lines that
- // are made up of the given
- // vertices, then build up a
- // quad from these lines
- // finally use the find
- // function of the map template
- // to find the quad
- for (unsigned int i=0; i<4; ++i)
- {
- std::pair<int, int> line_vertices(
- boundary_quad->vertices[GeometryInfo<dim-1>::line_to_cell_vertices(i,0)],
- boundary_quad->vertices[GeometryInfo<dim-1>::line_to_cell_vertices(i,1)]);
-
- // check whether line
- // already exists
- if (needed_lines.find(line_vertices) != needed_lines.end())
- line[i] = needed_lines[line_vertices];
- else
- // look wether it exists
- // in reverse direction
- {
- std::swap (line_vertices.first, line_vertices.second);
- if (needed_lines.find(line_vertices) != needed_lines.end())
- line[i] = needed_lines[line_vertices];
- else
- // line does
- // not exist
- AssertThrow (false, ExcLineInexistant(line_vertices.first,
- line_vertices.second));
- }
- }
-
-
- // Set up 2 quads that are
- // built up from the lines for
- // reasons of comparison to
- // needed_quads. The second
- // quad is the reversed version
- // of the first quad in order
- // find the quad regardless of
- // its orientation. This is
- // introduced for convenience
- // and because boundary quad
- // orientation does not carry
- // any information.
- internal::Triangulation::TriaObject<2>
- quad_compare_1(line[0]->index(), line[1]->index(),
- line[2]->index(), line[3]->index());
- internal::Triangulation::TriaObject<2>
- quad_compare_2(line[2]->index(), line[3]->index(),
- line[0]->index(), line[1]->index());
-
- // try to find the quad with
- // lines situated as
- // constructed above. if it
- // could not be found, rotate
- // the boundary lines 3 times
- // until it is found or it does
- // not exist.
-
- // mapping from counterclock to
- // lexicographic ordering of
- // quad lines
- static const unsigned int lex2cclock[4]={3,1,0,2};
- // copy lines from
- // lexicographic to
- // counterclock ordering, as
- // rotation is much simpler in
- // counterclock ordering
- typename Triangulation<dim,spacedim>::line_iterator
- line_counterclock[4];
- for (unsigned int i=0; i<4; ++i)
- line_counterclock[lex2cclock[i]]=line[i];
- unsigned int n_rotations=0;
- bool not_found_quad_1;
- while ( (not_found_quad_1=(needed_quads.find(quad_compare_1) == needed_quads.end())) &&
- ( needed_quads.find(quad_compare_2) == needed_quads.end()) &&
- (n_rotations<4))
- {
- // use the rotate defined
- // in <algorithms>
- rotate(line_counterclock, line_counterclock+1, line_counterclock+4);
- // update the quads with
- // rotated lines (i runs in
- // lexicographic ordering)
- for (unsigned int i=0; i<4; ++i)
- {
- quad_compare_1.set_face(i, line_counterclock[lex2cclock[i]]->index());
- quad_compare_2.set_face((i+2)%4, line_counterclock[lex2cclock[i]]->index());
- }
-
- ++n_rotations;
- }
-
- AssertThrow (n_rotations!=4,
- ExcQuadInexistant(line[0]->index(), line[1]->index(),
- line[2]->index(), line[3]->index()));
-
- if (not_found_quad_1)
- quad = needed_quads[quad_compare_2].first;
- else
- quad = needed_quads[quad_compare_1].first;
-
- // check whether this face is
- // really an exterior one
- AssertThrow (quad->at_boundary(),
- ExcInteriorQuadCantBeBoundary());
-
- // and make sure that we don't
- // attempt to reset the
- // boundary indicator to a
- // different than the
- // previously set value
- if (quad->boundary_indicator() != 0)
- AssertThrow (quad->boundary_indicator() == boundary_quad->material_id,
- ExcMessage ("Duplicate boundary quads are only allowed "
- "if they carry the same boundary indicator."));
-
- quad->set_boundary_indicator (boundary_quad->material_id);
- }
-
-
- /////////////////////////////////////////
- // finally update neighborship info
- for (typename Triangulation<dim,spacedim>::cell_iterator
- cell=triangulation.begin(); cell!=triangulation.end(); ++cell)
- for (unsigned int face=0; face<6; ++face)
- if (adjacent_cells[cell->quad(face)->index()][0] == cell)
- // first adjacent cell is
- // this one
- {
- if (adjacent_cells[cell->quad(face)->index()].size() == 2)
- // there is another
- // adjacent cell
- cell->set_neighbor (face,
- adjacent_cells[cell->quad(face)->index()][1]);
- }
- // first adjacent cell is not this
- // one, -> it must be the neighbor
- // we are looking for
- else
- cell->set_neighbor (face,
- adjacent_cells[cell->quad(face)->index()][0]);
- }
-
-
- /**
- * Distort a 1d triangulation in
- * some random way.
- */
- template <int spacedim>
- static
- void
- distort_random (const double factor,
- const bool keep_boundary,
- Triangulation<1,spacedim> &triangulation)
- {
- const unsigned int dim = 1;
-
- // if spacedim>1 we need to
- // make sure that we perturb
- // points but keep them on
- // the manifold
- Assert (spacedim == 1,
- ExcNotImplemented());
-
- // this function is mostly
- // equivalent to that for the
- // general dimensional case the
- // only difference being the
- // correction for split faces which
- // is not necessary in 1D
-
- // find the smallest length of the
- // lines adjacent to the
- // vertex. take the initial value
- // to be larger than anything that
- // might be found: the diameter of
- // the triangulation, here computed
- // by adding up the diameters of
- // the coarse grid cells.
- double almost_infinite_length = 0;
- for (typename Triangulation<dim,spacedim>::cell_iterator
- cell=triangulation.begin(0); cell!=triangulation.end(0); ++cell)
- almost_infinite_length += cell->diameter();
-
- std::vector<double> minimal_length (triangulation.vertices.size(),
- almost_infinite_length);
- // also note if a vertex is at
- // the boundary
- std::vector<bool> at_boundary (triangulation.vertices.size(), false);
-
- for (typename Triangulation<dim,spacedim>::active_line_iterator
- line=triangulation.begin_active_line();
- line != triangulation.end_line(); ++line)
- {
- if (keep_boundary && line->at_boundary())
- {
- at_boundary[line->vertex_index(0)] = true;
- at_boundary[line->vertex_index(1)] = true;
- }
-
- minimal_length[line->vertex_index(0)]
- = std::min(line->diameter(),
- minimal_length[line->vertex_index(0)]);
- minimal_length[line->vertex_index(1)]
- = std::min(line->diameter(),
- minimal_length[line->vertex_index(1)]);
- }
-
-
- const unsigned int n_vertices = triangulation.vertices.size();
- Point<spacedim> shift_vector;
-
- for (unsigned int vertex=0; vertex<n_vertices; ++vertex)
- {
- // ignore this vertex if we
- // whall keep the boundary and
- // this vertex *is* at the
- // boundary
- if (keep_boundary && at_boundary[vertex])
- continue;
-
- // first compute a random shift
- // vector
- for (unsigned int d=0; d<spacedim; ++d)
- shift_vector(d) = std::rand()*1.0/RAND_MAX;
-
- shift_vector *= factor * minimal_length[vertex] /
- std::sqrt(shift_vector.square());
-
- // finally move the vertex
- triangulation.vertices[vertex] += shift_vector;
- }
- }
-
-
- /**
- * Distort a triangulation in
- * some random way. This is the
- * function taken for the case
- * dim>1.
- */
- template <int dim, int spacedim>
- static
- void
- distort_random (const double factor,
- const bool keep_boundary,
- Triangulation<dim,spacedim> &triangulation)
- {
-//TODO:[?]Implement the random distortion in Triangulation for hanging nodes as well
-// Hanging nodes need to be reset to the correct mean value
-// at the end, which is simple for 2D but difficult for 3D. Maybe take
-// a look at how we get to the original location of the point in the
-// execute_refinement function and copy the relevant lines.
-
- // this function is mostly
- // equivalent to that for the
- // general dimensional case the
- // only difference being the
- // correction for split faces which
- // is not necessary in 1D
- //
- // if you change something here,
- // don't forget to do so there as
- // well
-
- // find the smallest length of the
- // lines adjacent to the
- // vertex. take the initial value
- // to be larger than anything that
- // might be found: the diameter of
- // the triangulation, here
- // estimated by adding up the
- // diameters of the coarse grid
- // cells.
- double almost_infinite_length = 0;
- for (typename Triangulation<dim,spacedim>::cell_iterator
- cell=triangulation.begin(0); cell!=triangulation.end(0); ++cell)
- almost_infinite_length += cell->diameter();
-
- std::vector<double> minimal_length (triangulation.vertices.size(),
- almost_infinite_length);
-
- // also note if a vertex is at the
- // boundary
- std::vector<bool> at_boundary (triangulation.vertices.size(), false);
-
- for (typename Triangulation<dim,spacedim>::active_line_iterator
- line=triangulation.begin_active_line();
- line != triangulation.end_line(); ++line)
- {
- if (keep_boundary && line->at_boundary())
- {
- at_boundary[line->vertex_index(0)] = true;
- at_boundary[line->vertex_index(1)] = true;
- }
-
- minimal_length[line->vertex_index(0)]
- = std::min(line->diameter(),
- minimal_length[line->vertex_index(0)]);
- minimal_length[line->vertex_index(1)]
- = std::min(line->diameter(),
- minimal_length[line->vertex_index(1)]);
- }
-
-
- const unsigned int n_vertices = triangulation.vertices.size();
- Point<spacedim> shift_vector;
-
- for (unsigned int vertex=0; vertex<n_vertices; ++vertex)
- {
- // ignore this vertex if we
- // whall keep the boundary and
- // this vertex *is* at the
- // boundary
- if (keep_boundary && at_boundary[vertex])
- continue;
-
- // first compute a random shift
- // vector
- for (unsigned int d=0; d<spacedim; ++d)
- shift_vector(d) = std::rand()*1.0/RAND_MAX;
-
- shift_vector *= factor * minimal_length[vertex] /
- std::sqrt(shift_vector.square());
-
- // finally move the vertex
- triangulation.vertices[vertex] += shift_vector;
- }
-
-
- // finally correct hanging nodes
- // again. The following is not
- // necessary for 1D
- typename Triangulation<dim,spacedim>::active_cell_iterator
- cell = triangulation.begin_active(),
- endc = triangulation.end();
- for (; cell!=endc; ++cell)
- for (unsigned int face=0; face<GeometryInfo<dim>::faces_per_cell; ++face)
- if (cell->face(face)->has_children() &&
- !cell->face(face)->at_boundary())
- // this lines has children,
- // thus there are restricted
- // nodes
- {
- // not implemented at
- // present for dim=3 or
- // higher
- Assert (dim<=2, ExcNotImplemented());
-
- // compute where the common
- // point of the two child
- // lines will lie and reset
- // it to the correct value
- triangulation.vertices[cell->face(face)->child(0)->vertex_index(1)]
- = (cell->face(face)->vertex(0) +
- cell->face(face)->vertex(1)) / 2;
- }
- }
-
-
- /**
- * Actually delete a cell, or rather all
- * its children, which is the main step for
- * the coarsening process. This is the
- * dimension dependent part of @p
- * execute_coarsening. The second argument
- * is a vector which gives for each line
- * index the number of cells containing
- * this line. This information is needed to
- * decide whether a refined line may be
- * coarsened or not in 3D. In 1D and 2D
- * this argument is not needed and thus
- * ignored. The same applies for the last
- * argument and quads instead of lines.
- */
- template <int spacedim>
- static
- void
- delete_children (Triangulation<1,spacedim> &triangulation,
- typename Triangulation<1,spacedim>::cell_iterator &cell,
- std::vector<unsigned int> &,
- std::vector<unsigned int> &)
- {
- const unsigned int dim = 1;
-
- // first we need to reset the
- // neighbor pointers of the
- // neighbors of this cell's
- // children to this cell. This is
- // different for one dimension,
- // since there neighbors can have a
- // refinement level differing from
- // that of this cell's children by
- // more than one level.
-
- Assert (!cell->child(0)->has_children() && !cell->child(1)->has_children(),
- ExcInternalError());
-
- // first do it for the cells to the
- // left
- if (cell->neighbor(0).state() == IteratorState::valid)
- if (cell->neighbor(0)->has_children())
- {
- typename Triangulation<dim,spacedim>::cell_iterator
- neighbor = cell->neighbor(0);
- Assert (neighbor->level() == cell->level(), ExcInternalError());
-
- // right child
- neighbor = neighbor->child(1);
- while (1)
- {
- Assert (neighbor->neighbor(1) == cell->child(0),
- ExcInternalError());
- neighbor->set_neighbor (1, cell);
-
- // move on to further
- // children on the
- // boundary between this
- // cell and its neighbor
- if (neighbor->has_children())
- neighbor = neighbor->child(1);
- else
- break;
- }
- }
-
- // now do it for the cells to the
- // left
- if (cell->neighbor(1).state() == IteratorState::valid)
- if (cell->neighbor(1)->has_children())
- {
- typename Triangulation<dim,spacedim>::cell_iterator
- neighbor = cell->neighbor(1);
- Assert (neighbor->level() == cell->level(), ExcInternalError());
-
- // left child
- neighbor = neighbor->child(0);
- while (1)
- {
- Assert (neighbor->neighbor(0) == cell->child(1),
- ExcInternalError());
- neighbor->set_neighbor (0, cell);
-
- // move on to further
- // children on the
- // boundary between this
- // cell and its neighbor
- if (neighbor->has_children())
- neighbor = neighbor->child(0);
- else
- break;
- }
- }
-
-
- // delete the vertex which will not
- // be needed anymore. This vertex
- // is the second of the first child
- triangulation.vertices_used[cell->child(0)->vertex_index(1)] = false;
-
- // invalidate children. clear user
- // pointers, to avoid that they may
- // appear at unwanted places later
- // on...
- for (unsigned int child=0; child<cell->n_children(); ++child)
- {
- cell->child(child)->clear_user_data();
- cell->child(child)->clear_user_flag();
- cell->child(child)->clear_used_flag();
- }
-
-
- // delete pointer to children
- cell->clear_children ();
- cell->clear_user_flag();
- }
-
-
-
- template <int spacedim>
- static
- void
- delete_children (Triangulation<2,spacedim> &triangulation,
- typename Triangulation<2,spacedim>::cell_iterator &cell,
- std::vector<unsigned int> &line_cell_count,
- std::vector<unsigned int> &)
- {
- const unsigned int dim=2;
- const RefinementCase<dim> ref_case=cell->refinement_case();
-
- Assert(line_cell_count.size()==triangulation.n_raw_lines(), ExcInternalError());
-
- // vectors to hold all lines which
- // may be deleted
- std::vector<typename Triangulation<dim,spacedim>::line_iterator>
- lines_to_delete(0);
-
- lines_to_delete.reserve(4*2+4);
-
- // now we decrease the counters for
- // lines contained in the child
- // cells
- for (unsigned int c=0; c<cell->n_children(); ++c)
- {
- typename Triangulation<dim,spacedim>::cell_iterator
- child=cell->child(c);
- for (unsigned int l=0; l<GeometryInfo<dim>::lines_per_cell; ++l)
- --line_cell_count[child->line_index(l)];
- }
-
-
- // delete the vertex which will not
- // be needed anymore. This vertex
- // is the second of the second line
- // of the first child, if the cell
- // is refined with cut_xy, else there
- // is no inner vertex.
- // additionally delete unneeded inner
- // lines
- if (ref_case==RefinementCase<dim>::cut_xy)
- {
- triangulation.vertices_used[cell->child(0)->line(1)->vertex_index(1)] = false;
-
- lines_to_delete.push_back(cell->child(0)->line(1));
- lines_to_delete.push_back(cell->child(0)->line(3));
- lines_to_delete.push_back(cell->child(3)->line(0));
- lines_to_delete.push_back(cell->child(3)->line(2));
- }
- else
- {
- unsigned int inner_face_no=ref_case==RefinementCase<dim>::cut_x ? 1 : 3;
-
- // the inner line will not be
- // used any more
- lines_to_delete.push_back(cell->child(0)->line(inner_face_no));
- }
-
- // invalidate children
- for (unsigned int child=0; child<cell->n_children(); ++child)
- {
- cell->child(child)->clear_user_data();
- cell->child(child)->clear_user_flag();
- cell->child(child)->clear_used_flag();
- }
-
-
- // delete pointer to children
- cell->clear_children ();
- cell->clear_refinement_case();
- cell->clear_user_flag();
-
- // look at the refinement of outer
- // lines. if nobody needs those
- // anymore we can add them to the
- // list of lines to be deleted.
- for (unsigned int line_no=0; line_no<GeometryInfo<dim>::lines_per_cell; ++line_no)
- {
- typename Triangulation<dim,spacedim>::line_iterator
- line=cell->line(line_no);
-
- if (line->has_children())
- {
- // if one of the cell counters is
- // zero, the other has to be as well
-
- Assert((line_cell_count[line->child_index(0)] == 0 &&
- line_cell_count[line->child_index(1)] == 0) ||
- (line_cell_count[line->child_index(0)] > 0 &&
- line_cell_count[line->child_index(1)] > 0),
- ExcInternalError());
-
- if (line_cell_count[line->child_index(0)]==0)
- {
- for (unsigned int c=0; c<2; ++c)
- Assert (!line->child(c)->has_children(),
- ExcInternalError());
-
- // we may delete the line's
- // children and the middle vertex
- // as no cell references them
- // anymore
- triangulation.vertices_used[line->child(0)->vertex_index(1)] = false;
-
- lines_to_delete.push_back(line->child(0));
- lines_to_delete.push_back(line->child(1));
-
- line->clear_children();
- }
- }
- }
-
- // finally, delete unneeded lines
-
- // clear user pointers, to avoid that
- // they may appear at unwanted places
- // later on...
- // same for user flags, then finally
- // delete the lines
- typename std::vector<typename Triangulation<dim,spacedim>::line_iterator>::iterator
- line=lines_to_delete.begin(),
- endline=lines_to_delete.end();
- for (; line!=endline; ++line)
- {
- (*line)->clear_user_data();
- (*line)->clear_user_flag();
- (*line)->clear_used_flag();
- }
- }
-
-
-
- template <int spacedim>
- static
- void
- delete_children (Triangulation<3,spacedim> &triangulation,
- typename Triangulation<3,spacedim>::cell_iterator &cell,
- std::vector<unsigned int> &line_cell_count,
- std::vector<unsigned int> &quad_cell_count)
- {
- const unsigned int dim=3;
-
- Assert(line_cell_count.size()==triangulation.n_raw_lines(), ExcInternalError());
- Assert(quad_cell_count.size()==triangulation.n_raw_quads(), ExcInternalError());
-
- // first of all, we store the RefineCase of
- // this cell
- const RefinementCase<dim> ref_case=cell->refinement_case();
- // vectors to hold all lines and quads which
- // may be deleted
- std::vector<typename Triangulation<dim,spacedim>::line_iterator>
- lines_to_delete(0);
- std::vector<typename Triangulation<dim,spacedim>::quad_iterator>
- quads_to_delete(0);
-
- lines_to_delete.reserve(12*2+6*4+6);
- quads_to_delete.reserve(6*4+12);
-
- // now we decrease the counters for lines and
- // quads contained in the child cells
- for (unsigned int c=0; c<cell->n_children(); ++c)
- {
- typename Triangulation<dim,spacedim>::cell_iterator
- child=cell->child(c);
- for (unsigned int l=0; l<GeometryInfo<dim>::lines_per_cell; ++l)
- --line_cell_count[child->line_index(l)];
- for (unsigned int f=0; f<GeometryInfo<dim>::faces_per_cell; ++f)
- --quad_cell_count[child->quad_index(f)];
- }
-
- ///////////////////////////////////////
- // delete interior quads and lines and the
- // interior vertex, depending on the
- // refinement case of the cell
- //
- // for append quads and lines: only append
- // them to the list of objects to be deleted
-
- switch (ref_case)
- {
- case RefinementCase<dim>::cut_x:
- quads_to_delete.push_back(cell->child(0)->face(1));
- break;
- case RefinementCase<dim>::cut_y:
- quads_to_delete.push_back(cell->child(0)->face(3));
- break;
- case RefinementCase<dim>::cut_z:
- quads_to_delete.push_back(cell->child(0)->face(5));
- break;
- case RefinementCase<dim>::cut_xy:
- quads_to_delete.push_back(cell->child(0)->face(1));
- quads_to_delete.push_back(cell->child(0)->face(3));
- quads_to_delete.push_back(cell->child(3)->face(0));
- quads_to_delete.push_back(cell->child(3)->face(2));
-
- lines_to_delete.push_back(cell->child(0)->line(11));
- break;
- case RefinementCase<dim>::cut_xz:
- quads_to_delete.push_back(cell->child(0)->face(1));
- quads_to_delete.push_back(cell->child(0)->face(5));
- quads_to_delete.push_back(cell->child(3)->face(0));
- quads_to_delete.push_back(cell->child(3)->face(4));
-
- lines_to_delete.push_back(cell->child(0)->line(5));
- break;
- case RefinementCase<dim>::cut_yz:
- quads_to_delete.push_back(cell->child(0)->face(3));
- quads_to_delete.push_back(cell->child(0)->face(5));
- quads_to_delete.push_back(cell->child(3)->face(2));
- quads_to_delete.push_back(cell->child(3)->face(4));
-
- lines_to_delete.push_back(cell->child(0)->line(7));
- break;
- case RefinementCase<dim>::cut_xyz:
- quads_to_delete.push_back(cell->child(0)->face(1));
- quads_to_delete.push_back(cell->child(2)->face(1));
- quads_to_delete.push_back(cell->child(4)->face(1));
- quads_to_delete.push_back(cell->child(6)->face(1));
-
- quads_to_delete.push_back(cell->child(0)->face(3));
- quads_to_delete.push_back(cell->child(1)->face(3));
- quads_to_delete.push_back(cell->child(4)->face(3));
- quads_to_delete.push_back(cell->child(5)->face(3));
-
- quads_to_delete.push_back(cell->child(0)->face(5));
- quads_to_delete.push_back(cell->child(1)->face(5));
- quads_to_delete.push_back(cell->child(2)->face(5));
- quads_to_delete.push_back(cell->child(3)->face(5));
-
- lines_to_delete.push_back(cell->child(0)->line(5));
- lines_to_delete.push_back(cell->child(0)->line(7));
- lines_to_delete.push_back(cell->child(0)->line(11));
- lines_to_delete.push_back(cell->child(7)->line(0));
- lines_to_delete.push_back(cell->child(7)->line(2));
- lines_to_delete.push_back(cell->child(7)->line(8));
- // delete the vertex which will not
- // be needed anymore. This vertex
- // is the vertex at the heart of
- // this cell, which is the sixth of
- // the first child
- triangulation.vertices_used[cell->child(0)->vertex_index(7)] = false;
- break;
- default:
- // only remaining case is
- // no_refinement, thus an error
- Assert(false, ExcInternalError());
- break;
- }
-
-
- // invalidate children
- for (unsigned int child=0; child<cell->n_children(); ++child)
- {
- cell->child(child)->clear_user_data();
- cell->child(child)->clear_user_flag();
-
- for (unsigned int f=0; f<GeometryInfo<dim>::faces_per_cell; ++f)
- {
- // set flags denoting deviations from
- // standard orientation of faces back
- // to initialization values
- cell->child(child)->set_face_orientation (f, true);
- cell->child(child)->set_face_flip(f,false);
- cell->child(child)->set_face_rotation(f,false);
- }
-
- cell->child(child)->clear_used_flag();
- }
-
-
- // delete pointer to children
- cell->clear_children ();
- cell->clear_refinement_case ();
- cell->clear_user_flag();
-
- // so far we only looked at inner quads,
- // lines and vertices. Now we have to
- // consider outer ones as well. here, we have
- // to check, whether there are other cells
- // still needing these objects. oherwise we
- // can delete them. first for quads (and
- // their inner lines).
-
- for (unsigned int quad_no=0; quad_no<GeometryInfo<dim>::faces_per_cell; ++quad_no)
- {
- typename Triangulation<dim,spacedim>::quad_iterator
- quad=cell->face(quad_no);
-
- Assert((GeometryInfo<dim>::face_refinement_case(ref_case,quad_no) && quad->has_children()) ||
- GeometryInfo<dim>::face_refinement_case(ref_case,quad_no)==RefinementCase<dim-1>::no_refinement,
- ExcInternalError());
-
- switch (quad->refinement_case())
- {
- case RefinementCase<dim-1>::no_refinement:
- // nothing to do as the quad
- // is not refined
- break;
- case RefinementCase<dim-1>::cut_x:
- case RefinementCase<dim-1>::cut_y:
- {
- // if one of the cell counters is
- // zero, the other has to be as
- // well
- Assert((quad_cell_count[quad->child_index(0)] == 0 &&
- quad_cell_count[quad->child_index(1)] == 0) ||
- (quad_cell_count[quad->child_index(0)] > 0 &&
- quad_cell_count[quad->child_index(1)] > 0),
- ExcInternalError());
- // it might be, that the quad is
- // refined twice anisotropically,
- // first check, whether we may
- // delete possible grand_children
- unsigned int deleted_grandchildren=0;
- unsigned int number_of_child_refinements=0;
-
- for (unsigned int c=0; c<2; ++c)
- if (quad->child(c)->has_children())
- {
- ++number_of_child_refinements;
- // if one of the cell counters is
- // zero, the other has to be as
- // well
- Assert((quad_cell_count[quad->child(c)->child_index(0)] == 0 &&
- quad_cell_count[quad->child(c)->child_index(1)] == 0) ||
- (quad_cell_count[quad->child(c)->child_index(0)] > 0 &&
- quad_cell_count[quad->child(c)->child_index(1)] > 0),
- ExcInternalError());
- if (quad_cell_count[quad->child(c)->child_index(0)]==0)
- {
- // Assert, that the two
- // anisotropic
- // refinements add up to
- // isotropic refinement
- Assert(quad->refinement_case()+quad->child(c)->refinement_case()==RefinementCase<dim>::cut_xy,
- ExcInternalError());
- // we may delete the
- // quad's children and
- // the inner line as no
- // cell references them
- // anymore
- quads_to_delete.push_back(quad->child(c)->child(0));
- quads_to_delete.push_back(quad->child(c)->child(1));
- if (quad->child(c)->refinement_case()==RefinementCase<2>::cut_x)
- lines_to_delete.push_back(quad->child(c)->child(0)->line(1));
- else
- lines_to_delete.push_back(quad->child(c)->child(0)->line(3));
- quad->child(c)->clear_children();
- quad->child(c)->clear_refinement_case();
- ++deleted_grandchildren;
- }
- }
- // if no grandchildren are left, we
- // may as well delete the
- // refinement of the inner line
- // between our children and the
- // corresponding vertex
- if (number_of_child_refinements>0 &&
- deleted_grandchildren==number_of_child_refinements)
- {
- typename Triangulation<dim,spacedim>::line_iterator
- middle_line;
- if (quad->refinement_case()==RefinementCase<2>::cut_x)
- middle_line=quad->child(0)->line(1);
- else
- middle_line=quad->child(0)->line(3);
-
- lines_to_delete.push_back(middle_line->child(0));
- lines_to_delete.push_back(middle_line->child(1));
- triangulation.vertices_used[middle_vertex_index<dim,spacedim>(middle_line)]
- = false;
- middle_line->clear_children();
- }
-
- // now consider the direct children
- // of the given quad
- if (quad_cell_count[quad->child_index(0)]==0)
- {
- // we may delete the quad's
- // children and the inner line
- // as no cell references them
- // anymore
- quads_to_delete.push_back(quad->child(0));
- quads_to_delete.push_back(quad->child(1));
- if (quad->refinement_case()==RefinementCase<2>::cut_x)
- lines_to_delete.push_back(quad->child(0)->line(1));
- else
- lines_to_delete.push_back(quad->child(0)->line(3));
-
- // if the counters just dropped
- // to zero, otherwise the
- // children would have been
- // deleted earlier, then this
- // cell's children must have
- // contained the anisotropic
- // quad children. thus, if
- // those have again anisotropic
- // children, which are in
- // effect isotropic children of
- // the original quad, those are
- // still needed by a
- // neighboring cell and we
- // cannot delete them. instead,
- // we have to reset this quad's
- // refine case to isotropic and
- // set the children
- // accordingly.
- if (quad->child(0)->has_children())
- if (quad->refinement_case()==RefinementCase<2>::cut_x)
- {
- // now evereything is
- // quite complicated. we
- // have the children
- // numbered according to
- //
- // *---*---*
- // |n+1|m+1|
- // *---*---*
- // | n | m |
- // *---*---*
- //
- // from the original
- // anisotropic
- // refinement. we have to
- // reorder them as
- //
- // *---*---*
- // | m |m+1|
- // *---*---*
- // | n |n+1|
- // *---*---*
- //
- // for isotropic refinement.
- //
- // this is a bit ugly, of
- // course: loop over all
- // cells on all levels
- // and look for faces n+1
- // (switch_1) and m
- // (switch_2).
- const typename Triangulation<dim,spacedim>::quad_iterator
- switch_1=quad->child(0)->child(1),
- switch_2=quad->child(1)->child(0);
-
- Assert(!switch_1->has_children(), ExcInternalError());
- Assert(!switch_2->has_children(), ExcInternalError());
-
- const int switch_1_index=switch_1->index();
- const int switch_2_index=switch_2->index();
- for (unsigned int l=0; l<triangulation.levels.size(); ++l)
- for (unsigned int h=0; h<triangulation.levels[l]->cells.cells.size(); ++h)
- for (unsigned int q=0; q<GeometryInfo<dim>::faces_per_cell; ++q)
- {
- const int index=triangulation.levels[l]->cells.cells[h].face(q);
- if (index==switch_1_index)
- triangulation.levels[l]->cells.cells[h].set_face(q,switch_2_index);
- else if (index==switch_2_index)
- triangulation.levels[l]->cells.cells[h].set_face(q,switch_1_index);
- }
- // now we have to copy
- // all information of the
- // two quads
- const int switch_1_lines[4]=
- {switch_1->line_index(0),
- switch_1->line_index(1),
- switch_1->line_index(2),
- switch_1->line_index(3)};
- const bool switch_1_line_orientations[4]=
- {switch_1->line_orientation(0),
- switch_1->line_orientation(1),
- switch_1->line_orientation(2),
- switch_1->line_orientation(3)};
- const unsigned char switch_1_boundary_indicator=switch_1->boundary_indicator();
- const unsigned int switch_1_user_index=switch_1->user_index();
- const bool switch_1_user_flag=switch_1->user_flag_set();
-
- switch_1->set(internal::Triangulation::TriaObject<2>(switch_2->line_index(0),
- switch_2->line_index(1),
- switch_2->line_index(2),
- switch_2->line_index(3)));
- switch_1->set_line_orientation(0, switch_2->line_orientation(0));
- switch_1->set_line_orientation(1, switch_2->line_orientation(1));
- switch_1->set_line_orientation(2, switch_2->line_orientation(2));
- switch_1->set_line_orientation(3, switch_2->line_orientation(3));
- switch_1->set_boundary_indicator(switch_2->boundary_indicator());
- switch_1->set_user_index(switch_2->user_index());
- if (switch_2->user_flag_set())
- switch_1->set_user_flag();
- else
- switch_1->clear_user_flag();
-
- switch_2->set(internal::Triangulation::TriaObject<2>(switch_1_lines[0],
- switch_1_lines[1],
- switch_1_lines[2],
- switch_1_lines[3]));
- switch_2->set_line_orientation(0, switch_1_line_orientations[0]);
- switch_2->set_line_orientation(1, switch_1_line_orientations[1]);
- switch_2->set_line_orientation(2, switch_1_line_orientations[2]);
- switch_2->set_line_orientation(3, switch_1_line_orientations[3]);
- switch_2->set_boundary_indicator(switch_1_boundary_indicator);
- switch_2->set_user_index(switch_1_user_index);
- if (switch_1_user_flag)
- switch_2->set_user_flag();
- else
- switch_2->clear_user_flag();
-
- const unsigned int child_0=quad->child(0)->child_index(0);
- const unsigned int child_2=quad->child(1)->child_index(0);
- quad->clear_children();
- quad->clear_refinement_case();
- quad->set_refinement_case(RefinementCase<2>::cut_xy);
- quad->set_children(0,child_0);
- quad->set_children(2,child_2);
- std::swap(quad_cell_count[child_0+1],quad_cell_count[child_2]);
- }
- else
- {
- // the face was refined
- // with cut_y, thus the
- // children are already
- // in correct order. we
- // only have to set them
- // correctly, deleting
- // the indirection of two
- // anisotropic refinement
- // and going directly
- // from the quad to
- // isotropic children
- const unsigned int child_0=quad->child(0)->child_index(0);
- const unsigned int child_2=quad->child(1)->child_index(0);
- quad->clear_children();
- quad->clear_refinement_case();
- quad->set_refinement_case(RefinementCase<2>::cut_xy);
- quad->set_children(0,child_0);
- quad->set_children(2,child_2);
- }
- else
- {
- quad->clear_children();
- quad->clear_refinement_case();
- }
-
-
- }
- break;
- }
- case RefinementCase<dim-1>::cut_xy:
- {
- // if one of the cell counters is
- // zero, the others have to be as
- // well
-
- Assert((quad_cell_count[quad->child_index(0)] == 0 &&
- quad_cell_count[quad->child_index(1)] == 0 &&
- quad_cell_count[quad->child_index(2)] == 0 &&
- quad_cell_count[quad->child_index(3)] == 0) ||
- (quad_cell_count[quad->child_index(0)] > 0 &&
- quad_cell_count[quad->child_index(1)] > 0 &&
- quad_cell_count[quad->child_index(2)] > 0 &&
- quad_cell_count[quad->child_index(3)] > 0),
- ExcInternalError());
-
- if (quad_cell_count[quad->child_index(0)]==0)
- {
- // we may delete the quad's
- // children, the inner lines
- // and the middle vertex as no
- // cell references them anymore
- lines_to_delete.push_back(quad->child(0)->line(1));
- lines_to_delete.push_back(quad->child(3)->line(0));
- lines_to_delete.push_back(quad->child(0)->line(3));
- lines_to_delete.push_back(quad->child(3)->line(2));
-
- for (unsigned int child=0; child<quad->n_children(); ++child)
- quads_to_delete.push_back(quad->child(child));
-
- triangulation.vertices_used[quad->child(0)->vertex_index(3)] = false;
-
- quad->clear_children();
- quad->clear_refinement_case();
- }
- }
- break;
-
- default:
- Assert(false, ExcInternalError());
- break;
- }
-
- }
-
- // now we repeat a similar procedure
- // for the outer lines of this cell.
-
- // if in debug mode: check that each
- // of the lines for which we consider
- // deleting the children in fact has
- // children (the bits/coarsening_3d
- // test tripped over this initially)
- for (unsigned int line_no=0; line_no<GeometryInfo<dim>::lines_per_cell; ++line_no)
- {
- typename Triangulation<dim,spacedim>::line_iterator
- line=cell->line(line_no);
-
- Assert((GeometryInfo<dim>::line_refinement_case(ref_case,line_no) && line->has_children()) ||
- GeometryInfo<dim>::line_refinement_case(ref_case,line_no)==RefinementCase<1>::no_refinement,
- ExcInternalError());
-
- if (line->has_children())
- {
- // if one of the cell counters is
- // zero, the other has to be as well
-
- Assert((line_cell_count[line->child_index(0)] == 0 &&
- line_cell_count[line->child_index(1)] == 0) ||
- (line_cell_count[line->child_index(0)] > 0 &&
- line_cell_count[line->child_index(1)] > 0),
- ExcInternalError());
-
- if (line_cell_count[line->child_index(0)]==0)
- {
- for (unsigned int c=0; c<2; ++c)
- Assert (!line->child(c)->has_children(),
- ExcInternalError());
-
- // we may delete the line's
- // children and the middle vertex
- // as no cell references them
- // anymore
- triangulation.vertices_used[line->child(0)->vertex_index(1)] = false;
-
- lines_to_delete.push_back(line->child(0));
- lines_to_delete.push_back(line->child(1));
-
- line->clear_children();
- }
- }
- }
-
- // finally, delete unneeded quads and lines
-
- // clear user pointers, to avoid that
- // they may appear at unwanted places
- // later on...
- // same for user flags, then finally
- // delete the quads and lines
- typename std::vector<typename Triangulation<dim,spacedim>::line_iterator>::iterator
- line=lines_to_delete.begin(),
- endline=lines_to_delete.end();
- for (; line!=endline; ++line)
- {
- (*line)->clear_user_data();
- (*line)->clear_user_flag();
- (*line)->clear_used_flag();
- }
-
- typename std::vector<typename Triangulation<dim,spacedim>::quad_iterator>::iterator
- quad=quads_to_delete.begin(),
- endquad=quads_to_delete.end();
- for (; quad!=endquad; ++quad)
- {
- (*quad)->clear_user_data();
- (*quad)->clear_children();
- (*quad)->clear_refinement_case();
- (*quad)->clear_user_flag();
- (*quad)->clear_used_flag();
- }
- }
-
-
- /**
- * Create the children of a 2d
- * cell. The arguments indicate
- * the next free spots in the
- * vertices, lines, and cells
- * arrays.
- *
- * The faces of the cell have to
- * be refined already, whereas
- * the inner lines in 2D will be
- * created in this
- * function. Therefore iterator
- * pointers into the vectors of
- * lines, quads and cells have to
- * be passed, which point at (or
- * "before") the reserved space.
- */
- template <int spacedim>
- static
- void
- create_children (Triangulation<2,spacedim> &triangulation,
- unsigned int &next_unused_vertex,
- typename Triangulation<2,spacedim>::raw_line_iterator &next_unused_line,
- typename Triangulation<2,spacedim>::raw_cell_iterator &next_unused_cell,
- typename Triangulation<2,spacedim>::cell_iterator &cell)
- {
- const unsigned int dim=2;
- // clear refinement flag
- const RefinementCase<dim> ref_case=cell->refine_flag_set();
- cell->clear_refine_flag ();
-
-/* For the refinement process: since we go the levels up from the lowest, there
- are (unlike above) only two possibilities: a neighbor cell is on the same
- level or one level up (in both cases, it may or may not be refined later on,
- but we don't care here).
-
- First:
- Set up an array of the 3x3 vertices, which are distributed on the cell
- (the array consists of indices into the @p{vertices} std::vector
-
- 2--7--3
- | | |
- 4--8--5
- | | |
- 0--6--1
-
- note: in case of cut_x or cut_y not all these vertices are needed for the new
- cells
-
- Second:
- Set up an array of the new lines (the array consists of iterator pointers
- into the lines arrays)
-
- .-6-.-7-. The directions are: .->-.->-.
- 1 9 3 ^ ^ ^
- .-10.11-. .->-.->-.
- 0 8 2 ^ ^ ^
- .-4-.-5-. .->-.->-.
-
- cut_x:
- .-4-.-5-.
- | | |
- 0 6 1
- | | |
- .-2-.-3-.
-
- cut_y:
- .---5---.
- 1 3
- .---6---.
- 0 2
- .---4---.
-
-
- Third:
- Set up an array of neighbors:
-
- 6 7
- .--.--.
- 1| | |3
- .--.--.
- 0| | |2
- .--.--.
- 4 5
-
- We need this array for two reasons: first to get the lines which will
- bound the four subcells (if the neighboring cell is refined, these
- lines already exist), and second to update neighborship information.
- Since if a neighbor is not refined, its neighborship record only
- points to the present, unrefined, cell rather than the children we
- are presently creating, we only need the neighborship information
- if the neighbor cells are refined. In all other cases, we store
- the unrefined neighbor address
-
- We also need for every neighbor (if refined) which number among its
- neighbors the present (unrefined) cell has, since that number is to
- be replaced and because that also is the number of the subline which
- will be the interface between that neighbor and the to be created cell.
- We will store this number (between 0 and 3) in the field
- @p{neighbors_neighbor}.
-
- It would be sufficient to use the children of the common line to the
- neighbor, if we only wanted to get the new sublines and the new vertex,
- but because we need to update the neighborship information of the
- two refined subcells of the neighbor, we need to search these anyway.
-
- Convention:
- The created children are numbered like this:
-
- .--.--.
- |2 . 3|
- .--.--.
- |0 | 1|
- .--.--.
-*/
-
- // collect the indices
- // all vertices
- // 2--7--3
- // | | |
- // 4--8--5
- // | | |
- // 0--6--1
- int new_vertices[9];
- for (unsigned int vertex_no=0; vertex_no<4; ++vertex_no)
- new_vertices[vertex_no]=cell->vertex_index(vertex_no);
- for (unsigned int line_no=0; line_no<4; ++line_no)
- if (cell->line(line_no)->has_children())
- new_vertices[4+line_no]=cell->line(line_no)->child(0)->vertex_index(1);
-
- if (ref_case==RefinementCase<dim>::cut_xy)
- {
- // find the next
- // unused vertex and
- // set it
- // appropriately
- while (triangulation.vertices_used[next_unused_vertex] == true)
- ++next_unused_vertex;
- Assert (next_unused_vertex < triangulation.vertices.size(),
- ExcTooFewVerticesAllocated());
- triangulation.vertices_used[next_unused_vertex] = true;
-
- new_vertices[8]=next_unused_vertex;
-
- Point<spacedim> new_point;
- if (dim == spacedim)
- {
- for (unsigned int i=0; i<8; ++i)
- new_point += triangulation.vertices[new_vertices[i]];
- new_point /= 8.0;
- }
- else
- {
- // new vertex is
- // placed on the
- // surface according
- // to the information
- // stored in the
- // boundary class
- new_point =
- triangulation.boundary[cell->material_id()]
- ->get_new_point_on_quad (cell);
- }
-
- triangulation.vertices[new_vertices[8]] = new_point;
-
-
- // if the user_flag is set, i.e. if the
- // cell is at the boundary, use a
- // different calculation of the middle
- // vertex here. this is of advantage, if
- // the boundary is strongly curved and
- // the cell has a high aspect ratio. this
- // can happen for example, if it was
- // refined anisotropically before.
- if (cell->user_flag_set())
- {
- // first reset the user_flag
- cell->clear_user_flag();
- // the user flag indicates: at least
- // one face is at the boundary. if it
- // is only one, set the new middle
- // vertex in a different way to avoid
- // some mis-shaped elements if the
- // new point on the boundary is not
- // where we expect it, especially if
- // it is to far inside the current
- // cell
- unsigned int bound_face=GeometryInfo<dim>::faces_per_cell;
- for (unsigned int face=0; face<GeometryInfo<dim>::faces_per_cell; ++face)
- if (cell->face(face)->at_boundary())
- {
- if (bound_face == GeometryInfo<dim>::faces_per_cell)
- // no boundary face found so
- // far, so set it now
- bound_face=face;
- else
- // there is another boundary
- // face, so reset bound_face to
- // invalid value as a flag to
- // do nothing in the following
- bound_face=GeometryInfo<dim>::faces_per_cell+1;
- }
-
- if (bound_face<GeometryInfo<dim>::faces_per_cell)
- // reset the cell's middle vertex
- // to the middle of the straight
- // connection between the new
- // points on this face and on the
- // opposite face
- triangulation.vertices[new_vertices[8]]
- = 0.5*(cell->face(bound_face)
- ->child(0)->vertex(1)+
- cell->face(GeometryInfo<dim>
- ::opposite_face[bound_face])
- ->child(0)->vertex(1));
- }
- }
-
-
- // Now the lines:
- typename Triangulation<dim,spacedim>::raw_line_iterator new_lines[12];
- unsigned int lmin=8;
- unsigned int lmax=12;
- if (ref_case!=RefinementCase<dim>::cut_xy)
- {
- lmin=6;
- lmax=7;
- }
-
- for (unsigned int l=lmin; l<lmax; ++l)
- {
- while (next_unused_line->used() == true)
- ++next_unused_line;
- new_lines[l] = next_unused_line;
- ++next_unused_line;
-
- Assert (new_lines[l]->used() == false,
- ExcCellShouldBeUnused());
- }
-
- if (ref_case==RefinementCase<dim>::cut_xy)
- {
- // .-6-.-7-.
- // 1 9 3
- // .-10.11-.
- // 0 8 2
- // .-4-.-5-.
-
- // lines 0-7 already
- // exist, create only
- // the four interior
- // lines 8-11
- unsigned int l=0;
- for (unsigned int face_no=0; face_no<GeometryInfo<dim>::faces_per_cell; ++face_no)
- for (unsigned int c=0; c<2; ++c, ++l)
- new_lines[l]=cell->line(face_no)->child(c);
- Assert(l==8, ExcInternalError());
-
- new_lines[8] ->set (internal::Triangulation::
- TriaObject<1>(new_vertices[6], new_vertices[8]));
- new_lines[9] ->set (internal::Triangulation::
- TriaObject<1>(new_vertices[8], new_vertices[7]));
- new_lines[10]->set (internal::Triangulation::
- TriaObject<1>(new_vertices[4], new_vertices[8]));
- new_lines[11]->set (internal::Triangulation::
- TriaObject<1>(new_vertices[8], new_vertices[5]));
- }
- else if (ref_case==RefinementCase<dim>::cut_x)
- {
- // .-4-.-5-.
- // | | |
- // 0 6 1
- // | | |
- // .-2-.-3-.
- new_lines[0]=cell->line(0);
- new_lines[1]=cell->line(1);
- new_lines[2]=cell->line(2)->child(0);
- new_lines[3]=cell->line(2)->child(1);
- new_lines[4]=cell->line(3)->child(0);
- new_lines[5]=cell->line(3)->child(1);
- new_lines[6]->set (internal::Triangulation::
- TriaObject<1>(new_vertices[6], new_vertices[7]));
- }
- else
- {
- Assert(ref_case==RefinementCase<dim>::cut_y, ExcInternalError());
- // .---5---.
- // 1 3
- // .---6---.
- // 0 2
- // .---4---.
- new_lines[0]=cell->line(0)->child(0);
- new_lines[1]=cell->line(0)->child(1);
- new_lines[2]=cell->line(1)->child(0);
- new_lines[3]=cell->line(1)->child(1);
- new_lines[4]=cell->line(2);
- new_lines[5]=cell->line(3);
- new_lines[6]->set (internal::Triangulation::
- TriaObject<1>(new_vertices[4], new_vertices[5]));
- }
-
- for (unsigned int l=lmin; l<lmax; ++l)
- {
- new_lines[l]->set_used_flag();
- new_lines[l]->clear_user_flag();
- new_lines[l]->clear_user_data();
- new_lines[l]->clear_children();
- // interior line
- new_lines[l]->set_boundary_indicator(255);
- }
-
- // Now add the four (two)
- // new cells!
- typename Triangulation<dim,spacedim>::raw_cell_iterator
- subcells[GeometryInfo<dim>::max_children_per_cell];
- while (next_unused_cell->used() == true)
- ++next_unused_cell;
-
- const unsigned int n_children=
- GeometryInfo<dim>::n_children(ref_case);
- for (unsigned int i=0; i<n_children; ++i)
- {
- Assert (next_unused_cell->used() == false,
- ExcCellShouldBeUnused());
- subcells[i] = next_unused_cell;
- ++next_unused_cell;
- if (i%2==1 && i<n_children-1)
- while (next_unused_cell->used() == true)
- ++next_unused_cell;
- }
-
- if (ref_case==RefinementCase<dim>::cut_xy)
- {
- // children:
- // .--.--.
- // |2 . 3|
- // .--.--.
- // |0 | 1|
- // .--.--.
- // lines:
- // .-6-.-7-.
- // 1 9 3
- // .-10.11-.
- // 0 8 2
- // .-4-.-5-.
- subcells[0]->set (internal::Triangulation::
- TriaObject<2>(new_lines[0]->index(),
- new_lines[8]->index(),
- new_lines[4]->index(),
- new_lines[10]->index()));
- subcells[1]->set (internal::Triangulation::
- TriaObject<2>(new_lines[8]->index(),
- new_lines[2]->index(),
- new_lines[5]->index(),
- new_lines[11]->index()));
- subcells[2]->set (internal::Triangulation::
- TriaObject<2>(new_lines[1]->index(),
- new_lines[9]->index(),
- new_lines[10]->index(),
- new_lines[6]->index()));
- subcells[3]->set (internal::Triangulation::
- TriaObject<2>(new_lines[9]->index(),
- new_lines[3]->index(),
- new_lines[11]->index(),
- new_lines[7]->index()));
- }
- else if (ref_case==RefinementCase<dim>::cut_x)
- {
- // children:
- // .--.--.
- // | . |
- // .0 . 1.
- // | | |
- // .--.--.
- // lines:
- // .-4-.-5-.
- // | | |
- // 0 6 1
- // | | |
- // .-2-.-3-.
- subcells[0]->set (internal::Triangulation::
- TriaObject<2>(new_lines[0]->index(),
- new_lines[6]->index(),
- new_lines[2]->index(),
- new_lines[4]->index()));
- subcells[1]->set (internal::Triangulation::
- TriaObject<2>(new_lines[6]->index(),
- new_lines[1]->index(),
- new_lines[3]->index(),
- new_lines[5]->index()));
- }
- else
- {
- Assert(ref_case==RefinementCase<dim>::cut_y, ExcInternalError());
- // children:
- // .-----.
- // | 1 |
- // .-----.
- // | 0 |
- // .-----.
- // lines:
- // .---5---.
- // 1 3
- // .---6---.
- // 0 2
- // .---4---.
- subcells[0]->set (internal::Triangulation::
- TriaObject<2>(new_lines[0]->index(),
- new_lines[2]->index(),
- new_lines[4]->index(),
- new_lines[6]->index()));
- subcells[1]->set (internal::Triangulation::
- TriaObject<2>(new_lines[1]->index(),
- new_lines[3]->index(),
- new_lines[6]->index(),
- new_lines[5]->index()));
- }
-
-
- for (unsigned int i=0; i<n_children; ++i)
- {
- subcells[i]->set_used_flag();
- subcells[i]->clear_refine_flag();
- subcells[i]->clear_user_flag();
- subcells[i]->clear_user_data();
- subcells[i]->clear_children();
- // inherit material
- // properties
- subcells[i]->set_material_id (cell->material_id());
- subcells[i]->set_subdomain_id (cell->subdomain_id());
-
- if (i%2==0)
- subcells[i]->set_parent (cell->index ());
- }
-
-
-
- // set child index for
- // even children children
- // i=0,2 (0)
- for (unsigned int i=0; i<n_children/2; ++i)
- cell->set_children (2*i, subcells[2*i]->index());
- // set the refine case
- cell->set_refinement_case(ref_case);
-
- // note that the
- // refinement flag was
- // already cleared at the
- // beginning of this function
- }
-
-
-
- /**
- * A function that performs the
- * refinement of a triangulation in 1d.
- */
- template <int spacedim>
- static
- typename Triangulation<1,spacedim>::DistortedCellList
- execute_refinement (Triangulation<1,spacedim> &triangulation,
- const bool /*check_for_distorted_cells*/)
- {
- const unsigned int dim = 1;
-
- // check whether a new level is
- // needed we have to check for this
- // on the highest level only (on
- // this, all used cells are also
- // active, so we only have to check
- // for this)
- {
- typename Triangulation<dim,spacedim>::raw_cell_iterator
- cell = triangulation.begin_active (triangulation.levels.size()-1),
- endc = triangulation.end();
- for (; cell != endc; ++cell)
- if (cell->used())
- if (cell->refine_flag_set())
- {
- triangulation.levels
- .push_back (new internal::Triangulation::TriaLevel<dim>);
- break;
- }
- }
-
-
- // check how much space is needed
- // on every level we need not check
- // the highest level since either -
- // on the highest level no cells
- // are flagged for refinement -
- // there are, but
- // prepare_refinement added another
- // empty level
- unsigned int needed_vertices = 0;
- for (int level=triangulation.levels.size()-2; level>=0; --level)
- {
- // count number of flagged
- // cells on this level
- unsigned int flagged_cells = 0;
- typename Triangulation<dim,spacedim>::active_cell_iterator
- acell = triangulation.begin_active(level),
- aendc = triangulation.begin_active(level+1);
- for (; acell!=aendc; ++acell)
- if (acell->refine_flag_set())
- ++flagged_cells;
-
- // count number of used cells
- // on the next higher level
- const unsigned int used_cells
- = std::count_if (triangulation.levels[level+1]->cells.used.begin(),
- triangulation.levels[level+1]->cells.used.end(),
- std::bind2nd (std::equal_to<bool>(), true));
-
- // reserve space for the
- // used_cells cells already
- // existing on the next higher
- // level as well as for the
- // 2*flagged_cells that will be
- // created on that level
- triangulation.levels[level+1]
- ->reserve_space(used_cells+
- GeometryInfo<1>::max_children_per_cell *
- flagged_cells,
- 1);
- // reserve space for
- // 2*flagged_cells new lines on
- // the next higher level
- triangulation.levels[level+1]->cells
- .reserve_space (GeometryInfo<1>::max_children_per_cell *
- flagged_cells,
- 0);
-
- needed_vertices += flagged_cells;
- }
-
- // add to needed vertices how many
- // vertices are already in use
- needed_vertices += std::count_if (triangulation.vertices_used.begin(),
- triangulation.vertices_used.end(),
- std::bind2nd (std::equal_to<bool>(),
- true));
- // if we need more vertices: create
- // them, if not: leave the array as
- // is, since shrinking is not
- // really possible because some of
- // the vertices at the end may be
- // in use
- if (needed_vertices > triangulation.vertices.size())
- {
- triangulation.vertices.resize (needed_vertices,
- Point<spacedim>());
- triangulation.vertices_used.resize (needed_vertices, false);
- }
-
-
- // Do REFINEMENT
- // on every level; exclude highest
- // level as above
-
- // index of next unused vertex
- unsigned int next_unused_vertex = 0;
-
- for (int level=triangulation.levels.size()-2; level>=0; --level)
- {
- typename Triangulation<dim,spacedim>::active_cell_iterator
- cell = triangulation.begin_active(level),
- endc = triangulation.begin_active(level+1);
-
- typename Triangulation<dim,spacedim>::raw_cell_iterator
- next_unused_cell = triangulation.begin_raw (level+1);
-
- for (; (cell!=endc) && (cell->level()==level); ++cell)
- if (cell->refine_flag_set())
- {
- // clear refinement flag
- cell->clear_refine_flag ();
-
- // search for next unused
- // vertex
- while (triangulation.vertices_used[next_unused_vertex] == true)
- ++next_unused_vertex;
- Assert (next_unused_vertex < triangulation.vertices.size(),
- ExcTooFewVerticesAllocated());
-
- // first insert new
- // vertex. if dim==spacedim
- // then simply use the
- // midpoint; otherwise we
- // have to ask the manifold
- // object
- if (dim == spacedim)
- triangulation.vertices[next_unused_vertex] =
- (cell->vertex(0) + cell->vertex(1)) / 2;
- else
- triangulation.vertices[next_unused_vertex] =
- triangulation.boundary[cell->material_id()]
- ->get_new_point_on_line(cell);
- triangulation.vertices_used[next_unused_vertex] = true;
-
- // search for next two
- // unused cell (++ takes
- // care of the end of the
- // vector)
- typename Triangulation<dim,spacedim>::raw_cell_iterator
- first_child,
- second_child;
- while (next_unused_cell->used() == true)
- ++next_unused_cell;
- first_child = next_unused_cell;
- first_child->set_used_flag ();
- first_child->clear_user_data ();
- ++next_unused_cell;
- Assert (next_unused_cell->used() == false,
- ExcCellShouldBeUnused());
- second_child = next_unused_cell;
- second_child->set_used_flag ();
- second_child->clear_user_data ();
-
- // insert first child
- cell->set_children (0, first_child->index());
- first_child->clear_children ();
- first_child->set (internal::Triangulation
- ::TriaObject<1> (cell->vertex_index(0),
- next_unused_vertex));
- first_child->set_material_id (cell->material_id());
- first_child->set_subdomain_id (cell->subdomain_id());
- first_child->set_parent (cell->index ());
-
- // reset neighborship info (refer
- // to
- // internal::Triangulation::TriaLevel<0>
- // for details)
- first_child->set_neighbor (1, second_child);
- if (cell->neighbor(0).state() != IteratorState::valid)
- first_child->set_neighbor (0, cell->neighbor(0));
- else
- if (cell->neighbor(0)->active())
- {
- // since the
- // neighbors level
- // is always
- // <=level, if the
- // cell is active,
- // then there are
- // no cells to the
- // left which may
- // want to know
- // about this new
- // child cell.
- Assert (cell->neighbor(0)->level() <= cell->level(),
- ExcInternalError());
- first_child->set_neighbor (0, cell->neighbor(0));
- }
- else
- // left neighbor is
- // refined
- {
- // set neighbor to
- // cell on same
- // level
- first_child->set_neighbor (0, cell->neighbor(0)->child(1));
-
- // reset neighbor
- // info of all
- // right descendant
- // of the left
- // neighbor of cell
- typename Triangulation<dim,spacedim>::cell_iterator
- left_neighbor = cell->neighbor(0);
- while (left_neighbor->has_children())
- {
- left_neighbor = left_neighbor->child(1);
- left_neighbor->set_neighbor (1, first_child);
- }
- }
-
- // insert second child
- second_child->clear_children ();
- second_child->set (internal::Triangulation
- ::TriaObject<1>(next_unused_vertex,
- cell->vertex_index(1)));
- second_child->set_neighbor (0, first_child);
- second_child->set_material_id (cell->material_id());
- second_child->set_subdomain_id (cell->subdomain_id());
- if (cell->neighbor(1).state() != IteratorState::valid)
- second_child->set_neighbor (1, cell->neighbor(1));
- else
- if (cell->neighbor(1)->active())
- {
- Assert (cell->neighbor(1)->level() <= cell->level(),
- ExcInternalError());
- second_child->set_neighbor (1, cell->neighbor(1));
- }
- else
- // right neighbor is
- // refined same as
- // above
- {
- second_child->set_neighbor (1, cell->neighbor(1)->child(0));
-
- typename Triangulation<dim,spacedim>::cell_iterator
- right_neighbor = cell->neighbor(1);
- while (right_neighbor->has_children())
- {
- right_neighbor = right_neighbor->child(0);
- right_neighbor->set_neighbor (0, second_child);
- }
- }
- }
- }
-
- // in 1d, we can not have
- // distorted children
- // unless the parent was
- // already distorted
- // (that is because we
- // don't use boundary
- // information for 1d
- // triangulations). so
- // return an empty list
- return typename Triangulation<1,spacedim>::DistortedCellList();
- }
-
-
- /**
- * A function that performs the
- * refinement of a triangulation in 2d.
- */
- template <int spacedim>
- static
- typename Triangulation<2,spacedim>::DistortedCellList
- execute_refinement (Triangulation<2,spacedim> &triangulation,
- const bool check_for_distorted_cells)
- {
- const unsigned int dim = 2;
-
- // check whether a new level is
- // needed we have to check for this
- // on the highest level only (on
- // this, all used cells are also
- // active, so we only have to check
- // for this)
- if (true)
- {
- typename Triangulation<dim,spacedim>::raw_cell_iterator
- cell = triangulation.begin_active (triangulation.levels.size()-1),
- endc = triangulation.end();
- for (; cell != endc; ++cell)
- if (cell->used())
- if (cell->refine_flag_set())
- {
- triangulation.levels.push_back (new internal::Triangulation::TriaLevel<dim>);
- break;
- }
- }
-
-
- // first clear user flags and
- // pointers of lines; we're going
- // to use them to flag which lines
- // need refinement
- for (typename Triangulation<dim,spacedim>::line_iterator
- line=triangulation.begin_line(); line!=triangulation.end_line(); ++line)
- {
- line->clear_user_flag();
- line->clear_user_data();
- }
- // running over all cells and lines
- // count the number
- // n_single_lines of lines
- // which can be stored as
- // single lines, e.g. inner lines
- unsigned int n_single_lines=0;
- // New lines to be created:
- // number lines which are
- // stored in pairs (the
- // children of lines must be
- // stored in pairs)
- unsigned int n_lines_in_pairs = 0;
-
- // check how much space is needed
- // on every level we need not check
- // the highest level since either
- // - on the highest level no cells
- // are flagged for refinement
- // - there are, but prepare_refinement
- // added another empty level
- unsigned int needed_vertices = 0;
- for (int level=triangulation.levels.size()-2; level>=0; --level)
- {
- // count number of flagged
- // cells on this level and
- // compute how many new
- // vertices and new lines will
- // be needed
- unsigned int needed_cells = 0;
-
- typename Triangulation<dim,spacedim>::active_cell_iterator
- cell = triangulation.begin_active(level),
- endc = triangulation.begin_active(level+1);
- for (; cell!=endc; ++cell)
- if (cell->refine_flag_set())
- {
- if (cell->refine_flag_set()==RefinementCase<dim>::cut_xy)
- {
- needed_cells += 4;
-
- // new vertex at
- // center of cell is
- // needed in any case
- ++needed_vertices;
- // the four inner
- // lines can be
- // stored as singles
- n_single_lines += 4;
- }
- else // cut_x || cut_y
- {
- // set the flag showing that
- // anisotropic refinement is
- // used for at least one cell
- triangulation.anisotropic_refinement = true;
-
- needed_cells += 2;
- // no vertex at center
-
- // the inner line can
- // be stored as
- // single
- n_single_lines += 1;
-
- }
-
- // mark all faces
- // (lines) for
- // refinement;
- // checking locally
- // whether the
- // neighbor would
- // also like to
- // refine them is
- // rather difficult
- // for lines so we
- // only flag them and
- // after visiting all
- // cells, we decide
- // which lines need
- // refinement;
- for (unsigned int line_no=0; line_no<GeometryInfo<dim>::faces_per_cell;
- ++line_no)
- {
- if (GeometryInfo<dim>::face_refinement_case(
- cell->refine_flag_set(), line_no)==RefinementCase<1>::cut_x)
- {
- typename Triangulation<dim,spacedim>::line_iterator
- line = cell->line(line_no);
- if (line->has_children() == false)
- {
- line->set_user_flag ();
-//TODO[WB]: we overwrite the user_index here because we later on need to find
-// out which boundary object we have to ask to refine this line. find a better
-// way to do that
- if (spacedim > dim)
- line->set_user_index(cell->material_id());
- }
- }
- }
- }
-
-
- // count number of used cells
- // on the next higher level
- const unsigned int used_cells
- = std::count_if (triangulation.levels[level+1]->cells.used.begin(),
- triangulation.levels[level+1]->cells.used.end(),
- std::bind2nd (std::equal_to<bool>(), true));
-
-
- // reserve space for the
- // used_cells cells already
- // existing on the next higher
- // level as well as for the
- // needed_cells that will be
- // created on that level
- triangulation.levels[level+1]->reserve_space (used_cells+needed_cells, 2);
-
- // reserve space for
- // needed_cells
- // new quads on the next higher
- // level
- triangulation.levels[level+1]->cells.
- reserve_space (needed_cells,0);
- }
-
- // now count the lines which
- // were flagged for refinement
- for (typename Triangulation<dim,spacedim>::line_iterator
- line=triangulation.begin_line(); line!=triangulation.end_line(); ++line)
- if (line->user_flag_set())
- {
- Assert (line->has_children() == false, ExcInternalError());
- n_lines_in_pairs += 2;
- needed_vertices += 1;
- }
- // reserve space for
- // n_lines_in_pairs new lines.
- // note, that we can't reserve space
- // for the single lines here as well,
- // as all the space reserved for lines
- // in pairs would be counted as unused
- // and we would end up with too little
- // space to store all lines. memory
- // reservation for n_single_lines can
- // only be done AFTER we refined the lines
- // of the current cells
- triangulation.faces->lines.
- reserve_space (n_lines_in_pairs, 0);
-
- // add to needed vertices how many
- // vertices are already in use
- needed_vertices += std::count_if (triangulation.vertices_used.begin(), triangulation.vertices_used.end(),
- std::bind2nd (std::equal_to<bool>(), true));
- // if we need more vertices: create
- // them, if not: leave the array as
- // is, since shrinking is not
- // really possible because some of
- // the vertices at the end may be
- // in use
- if (needed_vertices > triangulation.vertices.size())
- {
- triangulation.vertices.resize (needed_vertices, Point<spacedim>());
- triangulation.vertices_used.resize (needed_vertices, false);
- }
-
-
- // Do REFINEMENT
- // on every level; exclude highest
- // level as above
-
- // index of next unused vertex
- unsigned int next_unused_vertex = 0;
-
- // first the refinement of lines.
- // children are stored pairwise
- if (true)
- {
- // only active objects can be
- // refined further
- typename Triangulation<dim,spacedim>::active_line_iterator
- line = triangulation.begin_active_line(),
- endl = triangulation.end_line();
- typename Triangulation<dim,spacedim>::raw_line_iterator
- next_unused_line = triangulation.begin_raw_line ();
-
- for (; line!=endl; ++line)
- if (line->user_flag_set())
- {
- // this line needs to be
- // refined
-
- // find the next unused
- // vertex and set it
- // appropriately
- while (triangulation.vertices_used[next_unused_vertex] == true)
- ++next_unused_vertex;
- Assert (next_unused_vertex < triangulation.vertices.size(),
- ExcTooFewVerticesAllocated());
- triangulation.vertices_used[next_unused_vertex] = true;
-
- if (spacedim == dim)
- {
- // for the case of a domain
- // in an equal-dimensional
- // space we only have to
- // treat boundary lines
- // differently; for interior
- // lines we can compute the
- // midpoint as the mean of
- // the two vertices:
- if (line->at_boundary())
- triangulation.vertices[next_unused_vertex]
- = triangulation.boundary[line->boundary_indicator()]
- ->get_new_point_on_line (line);
- else
- triangulation.vertices[next_unused_vertex]
- = (line->vertex(0) + line->vertex(1)) / 2;
- }
- else
- // however, if spacedim>dim, we
- // always have to ask the
- // boundary object for its
- // answer
- triangulation.vertices[next_unused_vertex]
- = triangulation.boundary[line->user_index()]->get_new_point_on_line (line);
-
- // now that we created
- // the right point, make
- // up the two child
- // lines. To this end,
- // find a pair of unused
- // lines
- bool pair_found=false;
- for (; next_unused_line!=endl; ++next_unused_line)
- if (!next_unused_line->used() &&
- !(++next_unused_line)->used())
- {
- // go back to the
- // first of the two
- // unused lines
- --next_unused_line;
- pair_found=true;
- break;
- }
- Assert (pair_found, ExcInternalError());
-
- // there are now two
- // consecutive unused
- // lines, such that the
- // children of a line
- // will be consecutive.
- // then set the child
- // pointer of the present
- // line
- line->set_children (0, next_unused_line->index());
-
- // set the two new lines
- const typename Triangulation<dim,spacedim>::raw_line_iterator
- children[2] = { next_unused_line,
- ++next_unused_line };
- // some tests; if any of
- // the iterators should
- // be invalid, then
- // already dereferencing
- // will fail
- Assert (children[0]->used() == false, ExcCellShouldBeUnused());
- Assert (children[1]->used() == false, ExcCellShouldBeUnused());
-
- children[0]->set (internal::Triangulation
- ::TriaObject<1>(line->vertex_index(0),
- next_unused_vertex));
- children[1]->set (internal::Triangulation
- ::TriaObject<1>(next_unused_vertex,
- line->vertex_index(1)));
-
- children[0]->set_used_flag();
- children[1]->set_used_flag();
- children[0]->clear_children();
- children[1]->clear_children();
- children[0]->clear_user_data();
- children[1]->clear_user_data();
- children[0]->clear_user_flag();
- children[1]->clear_user_flag();
-
- children[0]->set_boundary_indicator (line->boundary_indicator());
- children[1]->set_boundary_indicator (line->boundary_indicator());
-
- // finally clear flag
- // indicating the need
- // for refinement
- line->clear_user_flag ();
- }
- }
-
-
- // Now set up the new cells
-
- // reserve space for inner
- // lines (can be stored as
- // single lines)
- triangulation.faces->lines.
- reserve_space (0,n_single_lines);
-
- typename Triangulation<2,spacedim>::DistortedCellList
- cells_with_distorted_children;
-
- // reset next_unused_line, as
- // now also single empty places
- // in the vector can be used
- typename Triangulation<dim,spacedim>::raw_line_iterator
- next_unused_line = triangulation.begin_raw_line ();
-
- for (int level=0; level<static_cast<int>(triangulation.levels.size())-1; ++level)
- {
-
- // Remember: as we don't operate
- // on the finest level, begin_*(level+1)
- // is allowed
- typename Triangulation<dim,spacedim>::active_cell_iterator
- cell = triangulation.begin_active(level),
- endc = triangulation.begin_active(level+1);
-
- typename Triangulation<dim,spacedim>::raw_cell_iterator
- next_unused_cell = triangulation.begin_raw (level+1);
-
- for (; cell!=endc; ++cell)
- if (cell->refine_flag_set())
- {
- // set the user flag to
- // indicate, that at least one
- // line is at the boundary
-
- // TODO[Tobias Leicht] find a
- // better place to set this flag,
- // so that we do not need so much
- // time to check each cell here
- if (cell->at_boundary())
- cell->set_user_flag();
-
- // actually set up the children and
- // update neighbor information
- create_children (triangulation,
- next_unused_vertex,
- next_unused_line,
- next_unused_cell,
- cell);
-
- if ((check_for_distorted_cells == true)
- &&
- has_distorted_children (cell,
- internal::int2type<dim>(),
- internal::int2type<spacedim>()))
- cells_with_distorted_children.distorted_cells.push_back (cell);
- }
- }
-
- return cells_with_distorted_children;
- }
-
-
- /**
- * A function that performs the
- * refinement of a triangulation in 3d.
- */
- template <int spacedim>
- static
- typename Triangulation<3,spacedim>::DistortedCellList
- execute_refinement (Triangulation<3,spacedim> &triangulation,
- const bool check_for_distorted_cells)
- {
- const unsigned int dim = 3;
-
- // this function probably
- // also works for spacedim>3
- // but it isn't tested. it
- // will probably be necessary
- // to pull new vertices onto
- // the manifold just as we do
- // for the other functions
- // above.
- Assert (spacedim == 3, ExcNotImplemented());
-
- // check whether a new level is
- // needed we have to check for this
- // on the highest level only (on
- // this, all used cells are also
- // active, so we only have to check
- // for this)
- if (true)
- {
- typename Triangulation<dim,spacedim>::raw_cell_iterator
- cell = triangulation.begin_active (triangulation.levels.size()-1),
- endc = triangulation.end();
- for (; cell != endc; ++cell)
- if (cell->used())
- if (cell->refine_flag_set())
- {
- triangulation.levels.push_back (new internal::Triangulation::TriaLevel<dim>);
- break;
- }
- }
-
-
- // first clear user flags for quads
- // and lines; we're going to use them
- // to flag which lines and quads
- // need refinement
- triangulation.faces->quads.clear_user_data();
-
- for (typename Triangulation<dim,spacedim>::line_iterator
- line=triangulation.begin_line(); line!=triangulation.end_line(); ++line)
- line->clear_user_flag();
- for (typename Triangulation<dim,spacedim>::quad_iterator
- quad=triangulation.begin_quad(); quad!=triangulation.end_quad(); ++quad)
- quad->clear_user_flag();
-
- // create an array of face refine cases. User
- // indices of faces will be set to values
- // corresponding with indices in this array.
- const RefinementCase<dim-1> face_refinement_cases[4]=
- {RefinementCase<dim-1>::no_refinement,
- RefinementCase<dim-1>::cut_x,
- RefinementCase<dim-1>::cut_y,
- RefinementCase<dim-1>::cut_xy};
-
- // check how much space is needed
- // on every level
- // we need not check the highest
- // level since either
- // - on the highest level no cells
- // are flagged for refinement
- // - there are, but prepare_refinement
- // added another empty level which
- // then is the highest level
-
- // variables to hold the number of newly to
- // be created vertices, lines and quads. as
- // these are stored globally, declare them
- // outside the loop over al levels. we need
- // lines and quads in pairs for refinement of
- // old ones and lines and quads, that can be
- // stored as single ones, as they are newly
- // created in the inside of an existing cell
- unsigned int needed_vertices = 0;
- unsigned int needed_lines_single = 0;
- unsigned int needed_quads_single = 0;
- unsigned int needed_lines_pair = 0;
- unsigned int needed_quads_pair = 0;
- for (int level=triangulation.levels.size()-2; level>=0; --level)
- {
- // count number of flagged
- // cells on this level and
- // compute how many new
- // vertices and new lines will
- // be needed
- unsigned int new_cells = 0;
-
- typename Triangulation<dim,spacedim>::active_cell_iterator
- acell = triangulation.begin_active(level),
- aendc = triangulation.begin_active(level+1);
- for (; acell!=aendc; ++acell)
- if (acell->refine_flag_set())
- {
- RefinementCase<dim> ref_case=acell->refine_flag_set();
-
- // now for interior vertices, lines
- // and quads, which are needed in
- // any case
- if (ref_case==RefinementCase<dim>::cut_x ||
- ref_case==RefinementCase<dim>::cut_y ||
- ref_case==RefinementCase<dim>::cut_z)
- {
- ++needed_quads_single;
- new_cells+=2;
- triangulation.anisotropic_refinement=true;
- }
- else if (ref_case==RefinementCase<dim>::cut_xy ||
- ref_case==RefinementCase<dim>::cut_xz ||
- ref_case==RefinementCase<dim>::cut_yz)
- {
- ++needed_lines_single;
- needed_quads_single += 4;
- new_cells+=4;
- triangulation.anisotropic_refinement=true;
- }
- else if (ref_case==RefinementCase<dim>::cut_xyz)
- {
- ++needed_vertices;
- needed_lines_single += 6;
- needed_quads_single += 12;
- new_cells+=8;
- }
- else
- {
- // we should never get here
- Assert(false, ExcInternalError());
- }
-
- // mark all faces for refinement;
- // checking locally
- // if and how the neighbor
- // would like to
- // refine these is
- // difficult so
- // we only flag them and
- // after visiting all
- // cells, we decide which
- // faces need which refinement;
- for (unsigned int face=0; face<GeometryInfo<dim>::faces_per_cell;
- ++face)
- {
- typename Triangulation<dim,spacedim>::face_iterator
- aface = acell->face(face);
- // get the RefineCase this
- // faces has for the given
- // RefineCase of the cell
- RefinementCase<dim-1> face_ref_case=
- GeometryInfo<dim>::face_refinement_case(ref_case,
- face,
- acell->face_orientation(face),
- acell->face_flip(face),
- acell->face_rotation(face));
- // only do something, if this
- // face has to be refined
- if (face_ref_case)
- {
- if (face_ref_case==RefinementCase<dim-1>::isotropic_refinement)
- {
- if (aface->number_of_children()<4)
- // we use user_flags to
- // denote needed isotropic
- // refinement
- aface->set_user_flag();
- }
- else if (aface->refinement_case()!=face_ref_case)
- // we use user_indices
- // to denote needed
- // anisotropic
- // refinement. note, that
- // we can have at most
- // one anisotropic
- // refinement case for
- // this face, as
- // otherwise
- // prepare_refinement()
- // would have changed one
- // of the cells to yield
- // isotropic refinement
- // at this
- // face. therefore we set
- // the user_index
- // uniquely
- {
- Assert(aface->refinement_case()==RefinementCase<dim-1>::isotropic_refinement ||
- aface->refinement_case()==RefinementCase<dim-1>::no_refinement,
- ExcInternalError());
- aface->set_user_index(face_ref_case);
- }
- }
- }// for all faces
-
- // flag all lines, that have to be
- // refined
- for (unsigned int line=0; line<GeometryInfo<dim>::lines_per_cell; ++line)
- if (GeometryInfo<dim>::line_refinement_case(ref_case,line) &&
- !acell->line(line)->has_children())
- acell->line(line)->set_user_flag();
-
- }// if refine_flag set and for all cells on this level
-
-
- // count number of used cells on
- // the next higher level
- const unsigned int used_cells
- = std::count_if (triangulation.levels[level+1]->cells.used.begin(),
- triangulation.levels[level+1]->cells.used.end(),
- std::bind2nd (std::equal_to<bool>(), true));
-
-
- // reserve space for the
- // used_cells cells already
- // existing on the next higher
- // level as well as for the
- // 8*flagged_cells that will be
- // created on that level
- triangulation.levels[level+1]->reserve_space (used_cells+new_cells, 3);
- // reserve space for
- // 8*flagged_cells
- // new hexes on the next higher
- // level
- triangulation.levels[level+1]->cells.reserve_space (new_cells);
- }// for all levels
- // now count the quads and
- // lines which were flagged for
- // refinement
- for (typename Triangulation<dim,spacedim>::quad_iterator
- quad=triangulation.begin_quad(); quad!=triangulation.end_quad(); ++quad)
- {
- if (quad->user_flag_set())
- {
- // isotropic refinement: 1 interior
- // vertex, 4 quads and 4 interior
- // lines. we store the interior lines
- // in pairs in case the face is
- // already or will be refined
- // anisotropically
- needed_quads_pair += 4;
- needed_lines_pair += 4;
- needed_vertices += 1;
- }
- if (quad->user_index())
- {
- // anisotropic refinement: 1 interior
- // line and two quads
- needed_quads_pair += 2;
- needed_lines_single += 1;
- // there is a kind of complicated
- // situation here which requires our
- // attention. if the quad is refined
- // isotropcally, two of the interior
- // lines will get a new mother line -
- // the interior line of our
- // anisotropically refined quad. if
- // those two lines are not
- // consecutive, we cannot do so and
- // have to replace them by two lines
- // that are consecutive. we try to
- // avoid that situation, but it may
- // happen nevertheless throug
- // repeated refinement and
- // coarsening. thus we have to check
- // here, as we will need some
- // additional space to store those
- // new lines in case we need them...
- if (quad->has_children())
- {
- Assert(quad->refinement_case()==RefinementCase<dim-1>::isotropic_refinement, ExcInternalError());
- if ((face_refinement_cases[quad->user_index()]==RefinementCase<dim-1>::cut_x
- && (quad->child(0)->line_index(1)+1!=quad->child(2)->line_index(1))) ||
- (face_refinement_cases[quad->user_index()]==RefinementCase<dim-1>::cut_y
- && (quad->child(0)->line_index(3)+1!=quad->child(1)->line_index(3))))
- needed_lines_pair +=2;
- }
- }
- }
-
- for (typename Triangulation<dim,spacedim>::line_iterator
- line=triangulation.begin_line(); line!=triangulation.end_line(); ++line)
- if (line->user_flag_set())
- {
- needed_lines_pair += 2;
- needed_vertices += 1;
- }
-
- // reserve space for
- // needed_lines new lines
- // stored in pairs
- triangulation.faces->lines.
- reserve_space (needed_lines_pair,needed_lines_single);
- // reserve space for
- // needed_quads new quads
- // stored in pairs
- triangulation.faces->quads.
- reserve_space (needed_quads_pair,needed_quads_single);
-
-
- // add to needed vertices how many
- // vertices are already in use
- needed_vertices += std::count_if (triangulation.vertices_used.begin(), triangulation.vertices_used.end(),
- std::bind2nd (std::equal_to<bool>(), true));
- // if we need more vertices: create
- // them, if not: leave the array as
- // is, since shrinking is not
- // really possible because some of
- // the vertices at the end may be
- // in use
- if (needed_vertices > triangulation.vertices.size())
- {
- triangulation.vertices.resize (needed_vertices, Point<spacedim>());
- triangulation.vertices_used.resize (needed_vertices, false);
- }
-
-
- ///////////////////////////////////////////
- // Before we start with the actual
- // refinement, we do some sanity
- // checks if in debug
- // mode. especially, we try to
- // catch the notorious problem with
- // lines being twice refined,
- // i.e. there are cells adjacent at
- // one line ("around the edge", but
- // not at a face), with two cells
- // differing by more than one
- // refinement level
- //
- // this check is very simple to
- // implement here, since we have
- // all lines flagged if they shall
- // be refined
-#ifdef DEBUG
- for (typename Triangulation<dim,spacedim>::active_cell_iterator
- cell=triangulation.begin_active(); cell!=triangulation.end(); ++cell)
- if (!cell->refine_flag_set())
- for (unsigned int line=0; line<GeometryInfo<dim>::lines_per_cell; ++line)
- if (cell->line(line)->has_children())
- for (unsigned int c=0; c<2; ++c)
- Assert (cell->line(line)->child(c)->user_flag_set() == false,
- ExcInternalError());
-#endif
-
- ///////////////////////////////////////////
- // Do refinement on every level
- //
- // To make life a bit easier, we
- // first refine those lines and
- // quads that were flagged for
- // refinement and then compose the
- // newly to be created cells.
- //
- // index of next unused vertex
- unsigned int next_unused_vertex = 0;
-
- // first for lines
- if (true)
- {
- // only active objects can be
- // refined further
- typename Triangulation<dim,spacedim>::active_line_iterator
- line = triangulation.begin_active_line(),
- endl = triangulation.end_line();
- typename Triangulation<dim,spacedim>::raw_line_iterator
- next_unused_line = triangulation.begin_raw_line ();
-
- for (; line!=endl; ++line)
- if (line->user_flag_set())
- {
- // this line needs to be
- // refined
-
- // find the next unused
- // vertex and set it
- // appropriately
- while (triangulation.vertices_used[next_unused_vertex] == true)
- ++next_unused_vertex;
- Assert (next_unused_vertex < triangulation.vertices.size(),
- ExcTooFewVerticesAllocated());
- triangulation.vertices_used[next_unused_vertex] = true;
-
- if (line->at_boundary())
- triangulation.vertices[next_unused_vertex]
- = triangulation.boundary[line->boundary_indicator()]->get_new_point_on_line (line);
- else
- triangulation.vertices[next_unused_vertex]
- = (line->vertex(0) + line->vertex(1)) / 2;
-
- // now that we created
- // the right point, make
- // up the two child lines
- // (++ takes care of the
- // end of the vector)
- next_unused_line=triangulation.faces->lines.next_free_pair_line(triangulation);
- Assert(next_unused_line.state() == IteratorState::valid,
- ExcInternalError());
-
- // now we found
- // two consecutive unused
- // lines, such that the
- // children of a line
- // will be consecutive.
- // then set the child
- // pointer of the present
- // line
- line->set_children (0, next_unused_line->index());
-
- // set the two new lines
- const typename Triangulation<dim,spacedim>::raw_line_iterator
- children[2] = { next_unused_line,
- ++next_unused_line };
-
- // some tests; if any of
- // the iterators should
- // be invalid, then
- // already dereferencing
- // will fail
- Assert (children[0]->used() == false, ExcCellShouldBeUnused());
- Assert (children[1]->used() == false, ExcCellShouldBeUnused());
-
- children[0]->set (internal::Triangulation
- ::TriaObject<1>(line->vertex_index(0),
- next_unused_vertex));
- children[1]->set (internal::Triangulation
- ::TriaObject<1>(next_unused_vertex,
- line->vertex_index(1)));
-
- children[0]->set_used_flag();
- children[1]->set_used_flag();
- children[0]->clear_children();
- children[1]->clear_children();
- children[0]->clear_user_data();
- children[1]->clear_user_data();
- children[0]->clear_user_flag();
- children[1]->clear_user_flag();
-
- children[0]->set_boundary_indicator (line->boundary_indicator());
- children[1]->set_boundary_indicator (line->boundary_indicator());
-
- // finally clear flag
- // indicating the need
- // for refinement
- line->clear_user_flag ();
- }
- }
-
-
- ///////////////////////////////////////
- // now refine marked quads
- ///////////////////////////////////////
-
- // here we encounter several cases:
-
- // a) the quad is unrefined and shall be
- // refined isotropically
-
- // b) the quad is unrefined and shall be
- // refined anisotropically
-
- // c) the quad is unrefined and shall be
- // refined both anisotropically and
- // isotropically (this is reduced to case b)
- // and then case b) for the children again)
-
- // d) the quad is refined anisotropically and
- // shall be refined isotropically (this is
- // reduced to case b) for the anisotropic
- // children)
-
- // e) the quad is refined isotropically and
- // shall be refined anisotropically (this is
- // transformed to case c), however we might
- // have to renumber/rename children...)
-
- // we need a loop in cases c) and d), as the
- // anisotropic children migt have a lower
- // index than the mother quad
- for (unsigned int loop=0; loop<2; ++loop)
- {
- // usually, only active objects can be
- // refined further. however, in cases d)
- // and e) that is not true, so we have to
- // use 'normal' iterators here
- typename Triangulation<dim,spacedim>::quad_iterator
- quad = triangulation.begin_quad(),
- endq = triangulation.end_quad();
- typename Triangulation<dim,spacedim>::raw_line_iterator
- next_unused_line = triangulation.begin_raw_line ();
- typename Triangulation<dim,spacedim>::raw_quad_iterator
- next_unused_quad = triangulation.begin_raw_quad ();
-
- for (; quad!=endq; ++quad)
- {
- if (quad->user_index())
- {
- RefinementCase<dim-1> aniso_quad_ref_case=face_refinement_cases[quad->user_index()];
- // there is one unlikely event
- // here, where we already have
- // refind the face: if the face
- // was refined anisotropically
- // and we want to refine it
- // isotropically, both children
- // are flagged for anisotropic
- // refinement. however, if those
- // children were already flagged
- // for anisotropic refinement,
- // they might already be
- // processed and refined.
- if (aniso_quad_ref_case == quad->refinement_case())
- continue;
-
- Assert(quad->refinement_case()==RefinementCase<dim-1>::cut_xy ||
- quad->refinement_case()==RefinementCase<dim-1>::no_refinement,
- ExcInternalError());
-
- // this quad needs to be refined
- // anisotropically
- Assert(quad->user_index() == RefinementCase<dim-1>::cut_x ||
- quad->user_index() == RefinementCase<dim-1>::cut_y,
- ExcInternalError());
-
- // make the new line interior to
- // the quad
- typename Triangulation<dim,spacedim>::raw_line_iterator new_line;
-
- new_line=triangulation.faces->lines.next_free_single_line(triangulation);
- Assert (new_line->used() == false,
- ExcCellShouldBeUnused());
-
- // first collect the
- // indices of the vertices:
- // *--1--*
- // | | |
- // | | | cut_x
- // | | |
- // *--0--*
- //
- // *-----*
- // | |
- // 0-----1 cut_y
- // | |
- // *-----*
- unsigned int vertex_indices[2];
- if (aniso_quad_ref_case==RefinementCase<dim-1>::cut_x)
- {
- vertex_indices[0]=quad->line(2)->child(0)->vertex_index(1);
- vertex_indices[1]=quad->line(3)->child(0)->vertex_index(1);
- }
- else
- {
- vertex_indices[0]=quad->line(0)->child(0)->vertex_index(1);
- vertex_indices[1]=quad->line(1)->child(0)->vertex_index(1);
- }
-
- new_line->set (internal::Triangulation::
- TriaObject<1>(vertex_indices[0], vertex_indices[1]));
- new_line->set_used_flag();
- new_line->clear_user_flag();
- new_line->clear_user_data();
- new_line->clear_children();
- new_line->set_boundary_indicator(quad->boundary_indicator());
-
- // child 0 and 1 of a line are
- // switched if the line
- // orientation is false. set up a
- // miniature table, indicating
- // which child to take for line
- // orientations false and
- // true. first index: child index
- // in standard orientation,
- // second index: line orientation
- const unsigned int index[2][2]=
- {{1,0}, // child 0, line_orientation=false and true
- {0,1}}; // child 1, line_orientation=false and true
-
- // find some space (consecutive)
- // for the two newly to be
- // created quads.
- typename Triangulation<dim,spacedim>::raw_quad_iterator new_quads[2];
-
- next_unused_quad=triangulation.faces->quads.next_free_pair_quad(triangulation);
- new_quads[0] = next_unused_quad;
- Assert (new_quads[0]->used() == false, ExcCellShouldBeUnused());
-
- ++next_unused_quad;
- new_quads[1] = next_unused_quad;
- Assert (new_quads[1]->used() == false, ExcCellShouldBeUnused());
-
-
- if (aniso_quad_ref_case==RefinementCase<dim-1>::cut_x)
- {
- new_quads[0]->set (internal::Triangulation
- ::TriaObject<2>(quad->line_index(0),
- new_line->index(),
- quad->line(2)->child(index[0][quad->line_orientation(2)])->index(),
- quad->line(3)->child(index[0][quad->line_orientation(3)])->index()));
- new_quads[1]->set (internal::Triangulation
- ::TriaObject<2>(new_line->index(),
- quad->line_index(1),
- quad->line(2)->child(index[1][quad->line_orientation(2)])->index(),
- quad->line(3)->child(index[1][quad->line_orientation(3)])->index()));
- }
- else
- {
- new_quads[0]->set (internal::Triangulation
- ::TriaObject<2>(quad->line(0)->child(index[0][quad->line_orientation(0)])->index(),
- quad->line(1)->child(index[0][quad->line_orientation(1)])->index(),
- quad->line_index(2),
- new_line->index()));
- new_quads[1]->set (internal::Triangulation
- ::TriaObject<2>(quad->line(0)->child(index[1][quad->line_orientation(0)])->index(),
- quad->line(1)->child(index[1][quad->line_orientation(1)])->index(),
- new_line->index(),
- quad->line_index(3)));
- }
-
- for (unsigned int i=0; i<2; ++i)
- {
- new_quads[i]->set_used_flag();
- new_quads[i]->clear_user_flag();
- new_quads[i]->clear_user_data();
- new_quads[i]->clear_children();
- new_quads[i]->set_boundary_indicator (quad->boundary_indicator());
- // set all line orientations to
- // true, change this after the
- // loop, as we have to consider
- // different lines for each
- // child
- for (unsigned int j=0; j<GeometryInfo<dim>::lines_per_face; ++j)
- new_quads[i]->set_line_orientation(j,true);
- }
- // now set the line orientation of
- // children of outer lines
- // correctly, the lines in the
- // interior of the refined quad are
- // automatically oriented
- // conforming to the standard
- new_quads[0]->set_line_orientation(0,quad->line_orientation(0));
- new_quads[0]->set_line_orientation(2,quad->line_orientation(2));
- new_quads[1]->set_line_orientation(1,quad->line_orientation(1));
- new_quads[1]->set_line_orientation(3,quad->line_orientation(3));
- if (aniso_quad_ref_case==RefinementCase<dim-1>::cut_x)
- {
- new_quads[0]->set_line_orientation(3,quad->line_orientation(3));
- new_quads[1]->set_line_orientation(2,quad->line_orientation(2));
- }
- else
- {
- new_quads[0]->set_line_orientation(1,quad->line_orientation(1));
- new_quads[1]->set_line_orientation(0,quad->line_orientation(0));
- }
-
- // test, whether this face is
- // refined isotropically
- // already. if so, set the
- // correct children pointers.
- if (quad->refinement_case()==RefinementCase<dim-1>::cut_xy)
- {
- // we will put a new
- // refinemnt level of
- // anisotropic refinement
- // between the unrefined and
- // isotropically refined quad
- // ending up with the same
- // fine quads but introducing
- // anisotropically refined
- // ones as children of the
- // unrefined quad and mother
- // cells of the original fine
- // ones.
-
- // this process includes the
- // creation of a new middle
- // line which we will assign
- // as the mother line of two
- // of the existing inner
- // lines. If those inner
- // lines are not consecutive
- // in memory, we won't find
- // them later on, so we have
- // to create new ones instead
- // and replace all occurances
- // of the old ones with those
- // new ones. As this is kind
- // of ugly, we hope we don't
- // have to do it often...
- typename Triangulation<dim,spacedim>::line_iterator old_child[2];
- if (aniso_quad_ref_case==RefinementCase<dim-1>::cut_x)
- {
- old_child[0]=quad->child(0)->line(1);
- old_child[1]=quad->child(2)->line(1);
- }
- else
- {
- Assert(aniso_quad_ref_case==RefinementCase<dim-1>::cut_y, ExcInternalError());
-
- old_child[0]=quad->child(0)->line(3);
- old_child[1]=quad->child(1)->line(3);
- }
-
- if (old_child[0]->index()+1 != old_child[1]->index())
- {
- // this is exactly the
- // ugly case we taked
- // about. so, no
- // coimplaining, lets get
- // two new lines and copy
- // all info
- typename Triangulation<dim,spacedim>::raw_line_iterator new_child[2];
-
- new_child[0]=new_child[1]=triangulation.faces->lines.next_free_pair_line(triangulation);
- ++new_child[1];
-
- new_child[0]->set_used_flag();
- new_child[1]->set_used_flag();
-
- const int old_index_0=old_child[0]->index(),
- old_index_1=old_child[1]->index(),
- new_index_0=new_child[0]->index(),
- new_index_1=new_child[1]->index();
-
- // loop over all quads
- // and replace the old
- // lines
- for (unsigned int q=0; q<triangulation.faces->quads.cells.size(); ++q)
- for (unsigned int l=0; l<GeometryInfo<dim>::lines_per_face; ++l)
- {
- const int index=triangulation.faces->quads.cells[q].face(l);
- if (index==old_index_0)
- triangulation.faces->quads.cells[q].set_face(l,new_index_0);
- else if (index==old_index_1)
- triangulation.faces->quads.cells[q].set_face(l,new_index_1);
- }
- // now we have to copy
- // all information of the
- // two lines
- for (unsigned int i=0; i<2; ++i)
- {
- Assert(!old_child[i]->has_children(), ExcInternalError());
-
- new_child[i]->set(internal::Triangulation::TriaObject<1>(old_child[i]->vertex_index(0),
- old_child[i]->vertex_index(1)));
- new_child[i]->set_boundary_indicator(old_child[i]->boundary_indicator());
- new_child[i]->set_user_index(old_child[i]->user_index());
- if (old_child[i]->user_flag_set())
- new_child[i]->set_user_flag();
- else
- new_child[i]->clear_user_flag();
-
- new_child[i]->clear_children();
-
- old_child[i]->clear_user_flag();
- old_child[i]->clear_user_index();
- old_child[i]->clear_used_flag();
- }
- }
- // now that we cared
- // about the lines, go on
- // with the quads
- // themselves, where we
- // might encounter
- // similar situations...
- if (aniso_quad_ref_case==RefinementCase<dim-1>::cut_x)
- {
- new_line->set_children(0, quad->child(0)->line_index(1));
- Assert(new_line->child(1)==quad->child(2)->line(1),
- ExcInternalError());
- // now evereything is
- // quite complicated. we
- // have the children
- // numbered according to
- //
- // *---*---*
- // |n+2|n+3|
- // *---*---*
- // | n |n+1|
- // *---*---*
- //
- // from the original
- // isotropic
- // refinement. we have to
- // reorder them as
- //
- // *---*---*
- // |n+1|n+3|
- // *---*---*
- // | n |n+2|
- // *---*---*
- //
- // such that n and n+1
- // are consecutive
- // children of m and n+2
- // and n+3 are
- // consecutive children
- // of m+1, where m and
- // m+1 are given as in
- //
- // *---*---*
- // | | |
- // | m |m+1|
- // | | |
- // *---*---*
- //
- // this is a bit ugly, of
- // course: loop over all
- // cells on all levels
- // and look for faces n+1
- // (switch_1) and n+2
- // (switch_2).
- const typename Triangulation<dim,spacedim>::quad_iterator
- switch_1=quad->child(1),
- switch_2=quad->child(2);
- const int switch_1_index=switch_1->index();
- const int switch_2_index=switch_2->index();
- for (unsigned int l=0; l<triangulation.levels.size(); ++l)
- for (unsigned int h=0; h<triangulation.levels[l]->cells.cells.size(); ++h)
- for (unsigned int q=0; q<GeometryInfo<dim>::faces_per_cell; ++q)
- {
- const int index=triangulation.levels[l]->cells.cells[h].face(q);
- if (index==switch_1_index)
- triangulation.levels[l]->cells.cells[h].set_face(q,switch_2_index);
- else if (index==switch_2_index)
- triangulation.levels[l]->cells.cells[h].set_face(q,switch_1_index);
- }
- // now we have to copy
- // all information of the
- // two quads
- const int switch_1_lines[4]=
- {switch_1->line_index(0),
- switch_1->line_index(1),
- switch_1->line_index(2),
- switch_1->line_index(3)};
- const bool switch_1_line_orientations[4]=
- {switch_1->line_orientation(0),
- switch_1->line_orientation(1),
- switch_1->line_orientation(2),
- switch_1->line_orientation(3)};
- const unsigned char switch_1_boundary_indicator=switch_1->boundary_indicator();
- const unsigned int switch_1_user_index=switch_1->user_index();
- const bool switch_1_user_flag=switch_1->user_flag_set();
- const RefinementCase<dim-1> switch_1_refinement_case=switch_1->refinement_case();
- const int switch_1_first_child_pair=(switch_1_refinement_case ? switch_1->child_index(0) : -1);
- const int switch_1_second_child_pair=(switch_1_refinement_case==RefinementCase<dim-1>::cut_xy ? switch_1->child_index(2) : -1);
-
- switch_1->set(internal::Triangulation::TriaObject<2>(switch_2->line_index(0),
- switch_2->line_index(1),
- switch_2->line_index(2),
- switch_2->line_index(3)));
- switch_1->set_line_orientation(0, switch_2->line_orientation(0));
- switch_1->set_line_orientation(1, switch_2->line_orientation(1));
- switch_1->set_line_orientation(2, switch_2->line_orientation(2));
- switch_1->set_line_orientation(3, switch_2->line_orientation(3));
- switch_1->set_boundary_indicator(switch_2->boundary_indicator());
- switch_1->set_user_index(switch_2->user_index());
- if (switch_2->user_flag_set())
- switch_1->set_user_flag();
- else
- switch_1->clear_user_flag();
- switch_1->clear_refinement_case();
- switch_1->set_refinement_case(switch_2->refinement_case());
- switch_1->clear_children();
- if (switch_2->refinement_case())
- switch_1->set_children(0, switch_2->child_index(0));
- if (switch_2->refinement_case()==RefinementCase<dim-1>::cut_xy)
- switch_1->set_children(2, switch_2->child_index(2));
-
- switch_2->set(internal::Triangulation::TriaObject<2>(switch_1_lines[0],
- switch_1_lines[1],
- switch_1_lines[2],
- switch_1_lines[3]));
- switch_2->set_line_orientation(0, switch_1_line_orientations[0]);
- switch_2->set_line_orientation(1, switch_1_line_orientations[1]);
- switch_2->set_line_orientation(2, switch_1_line_orientations[2]);
- switch_2->set_line_orientation(3, switch_1_line_orientations[3]);
- switch_2->set_boundary_indicator(switch_1_boundary_indicator);
- switch_2->set_user_index(switch_1_user_index);
- if (switch_1_user_flag)
- switch_2->set_user_flag();
- else
- switch_2->clear_user_flag();
- switch_2->clear_refinement_case();
- switch_2->set_refinement_case(switch_1_refinement_case);
- switch_2->clear_children();
- switch_2->set_children(0, switch_1_first_child_pair);
- switch_2->set_children(2, switch_1_second_child_pair);
-
- new_quads[0]->set_refinement_case(RefinementCase<2>::cut_y);
- new_quads[0]->set_children(0, quad->child_index(0));
- new_quads[1]->set_refinement_case(RefinementCase<2>::cut_y);
- new_quads[1]->set_children(0, quad->child_index(2));
- }
- else
- {
- new_quads[0]->set_refinement_case(RefinementCase<2>::cut_x);
- new_quads[0]->set_children(0, quad->child_index(0));
- new_quads[1]->set_refinement_case(RefinementCase<2>::cut_x);
- new_quads[1]->set_children(0, quad->child_index(2));
- new_line->set_children(0, quad->child(0)->line_index(3));
- Assert(new_line->child(1)==quad->child(1)->line(3),
- ExcInternalError());
- }
- quad->clear_children();
- }
-
- // note these quads as children
- // to the present one
- quad->set_children (0, new_quads[0]->index());
-
- quad->set_refinement_case(aniso_quad_ref_case);
-
- // finally clear flag
- // indicating the need
- // for refinement
- quad->clear_user_data ();
- } // if (anisotropic refinement)
-
- if (quad->user_flag_set())
- {
- // this quad needs to be
- // refined isotropically
-
- // first of all: we only get here
- // in the first run of the loop
- Assert(loop==0,ExcInternalError());
-
- // find the next unused
- // vertex. we'll need this in any
- // case
- while (triangulation.vertices_used[next_unused_vertex] == true)
- ++next_unused_vertex;
- Assert (next_unused_vertex < triangulation.vertices.size(),
- ExcTooFewVerticesAllocated());
-
- // now: if the quad is refined
- // anisotropically already, set
- // the anisotropic refinement
- // flag for both
- // children. Additionally, we
- // have to refine the inner line,
- // as it is an outer line of the
- // two (anisotropic) children
- const RefinementCase<dim-1> quad_ref_case=quad->refinement_case();
-
- if (quad_ref_case==RefinementCase<dim-1>::cut_x ||
- quad_ref_case==RefinementCase<dim-1>::cut_y)
- {
- // set the 'opposite' refine case for children
- quad->child(0)->set_user_index(RefinementCase<dim-1>::cut_xy-quad_ref_case);
- quad->child(1)->set_user_index(RefinementCase<dim-1>::cut_xy-quad_ref_case);
- // refine the inner line
- typename Triangulation<dim,spacedim>::line_iterator middle_line;
- if (quad_ref_case==RefinementCase<dim-1>::cut_x)
- middle_line=quad->child(0)->line(1);
- else
- middle_line=quad->child(0)->line(3);
-
- // if the face has been
- // refined anisotropically in
- // the last refinement step
- // it might be, that it is
- // flagged already and that
- // the middle line is thus
- // refined already. if not
- // create children.
- if (!middle_line->has_children())
- {
- // set the middle vertex
- // appropriately. double
- // refinement of quads can only
- // happen in the interior of
- // the domain, so we need not
- // care about boundary quads
- // here
- triangulation.vertices[next_unused_vertex]
- = (middle_line->vertex(0) + middle_line->vertex(1)) / 2;
- triangulation.vertices_used[next_unused_vertex] = true;
-
- // now search a slot for the two
- // child lines
- next_unused_line=triangulation.faces->lines.next_free_pair_line(triangulation);
-
- // set the child
- // pointer of the present
- // line
- middle_line->set_children (0, next_unused_line->index());
-
- // set the two new lines
- const typename Triangulation<dim,spacedim>::raw_line_iterator
- children[2] = { next_unused_line,
- ++next_unused_line };
-
- // some tests; if any of
- // the iterators should
- // be invalid, then
- // already dereferencing
- // will fail
- Assert (children[0]->used() == false, ExcCellShouldBeUnused());
- Assert (children[1]->used() == false, ExcCellShouldBeUnused());
-
- children[0]->set (internal::Triangulation::
- TriaObject<1>(middle_line->vertex_index(0),
- next_unused_vertex));
- children[1]->set (internal::Triangulation::
- TriaObject<1>(next_unused_vertex,
- middle_line->vertex_index(1)));
-
- children[0]->set_used_flag();
- children[1]->set_used_flag();
- children[0]->clear_children();
- children[1]->clear_children();
- children[0]->clear_user_data();
- children[1]->clear_user_data();
- children[0]->clear_user_flag();
- children[1]->clear_user_flag();
-
- children[0]->set_boundary_indicator (middle_line->boundary_indicator());
- children[1]->set_boundary_indicator (middle_line->boundary_indicator());
- }
- // now remove the flag from the
- // quad and go to the next
- // quad, the actual refinement
- // of the quad takes place
- // later on in this pass of the
- // loop or in the next one
- quad->clear_user_flag();
- continue;
- } // if (several refinement cases)
-
- // if we got here, we have an
- // unrefined quad and have to do
- // the usual work like in an purely
- // isotropic refinement
- Assert(quad_ref_case==RefinementCase<dim-1>::no_refinement, ExcInternalError());
-
- // set the middle vertex
- // appropriately
- if (quad->at_boundary())
- triangulation.vertices[next_unused_vertex]
- = triangulation.boundary[quad->boundary_indicator()]->get_new_point_on_quad (quad);
- else
- // it might be that the
- // quad itself is not
- // at the boundary, but
- // that one of its lines
- // actually is. in this
- // case, the newly
- // created vertices at
- // the centers of the
- // lines are not
- // necessarily the mean
- // values of the
- // adjacent vertices,
- // so do not compute
- // the new vertex as
- // the mean value of
- // the 4 vertices of
- // the face, but rather
- // as a weighted mean
- // value of the 8
- // vertices which we
- // already have (the
- // four old ones, and
- // the four ones
- // inserted as middle
- // points for the four
- // lines). summing up
- // some more points is
- // generally cheaper
- // than first asking
- // whether one of the
- // lines is at the
- // boundary
- //
- // note that the exact
- // weights are chosen
- // such as to minimize
- // the distortion of
- // the four new quads
- // from the optimal
- // shape; their
- // derivation and
- // values is copied
- // over from the
- // @p{MappingQ::set_laplace_on_vector}
- // function
- triangulation.vertices[next_unused_vertex]
- = (quad->vertex(0) + quad->vertex(1) +
- quad->vertex(2) + quad->vertex(3) +
- 3*(quad->line(0)->child(0)->vertex(1) +
- quad->line(1)->child(0)->vertex(1) +
- quad->line(2)->child(0)->vertex(1) +
- quad->line(3)->child(0)->vertex(1)) ) / 16;
-
- triangulation.vertices_used[next_unused_vertex] = true;
-
- // now that we created
- // the right point, make
- // up the four lines
- // interior to the quad
- // (++ takes care of the
- // end of the vector)
- typename Triangulation<dim,spacedim>::raw_line_iterator new_lines[4];
-
- for (unsigned int i=0; i<4; ++i)
- {
- if (i%2==0)
- // search a free pair of
- // lines for 0. and 2. line,
- // so that two of them end up
- // together, which is
- // necessary if later on we
- // want to refine the quad
- // anisotropically and the
- // two lines end up as
- // children of new line
- next_unused_line=triangulation.faces->lines.next_free_pair_line(triangulation);
-
- new_lines[i] = next_unused_line;
- ++next_unused_line;
-
- Assert (new_lines[i]->used() == false,
- ExcCellShouldBeUnused());
- }
-
- // set the data of the
- // four lines.
- // first collect the
- // indices of the five
- // vertices:
- // *--3--*
- // | | |
- // 0--4--1
- // | | |
- // *--2--*
- // the lines are numbered
- // as follows:
- // *--*--*
- // | 1 |
- // *2-*-3*
- // | 0 |
- // *--*--*
-
- const unsigned int vertex_indices[5]
- = { quad->line(0)->child(0)->vertex_index(1),
- quad->line(1)->child(0)->vertex_index(1),
- quad->line(2)->child(0)->vertex_index(1),
- quad->line(3)->child(0)->vertex_index(1),
- next_unused_vertex
- };
-
- new_lines[0]->set (internal::Triangulation::
- TriaObject<1>(vertex_indices[2], vertex_indices[4]));
- new_lines[1]->set (internal::Triangulation::
- TriaObject<1>(vertex_indices[4], vertex_indices[3]));
- new_lines[2]->set (internal::Triangulation::
- TriaObject<1>(vertex_indices[0], vertex_indices[4]));
- new_lines[3]->set (internal::Triangulation::
- TriaObject<1>(vertex_indices[4], vertex_indices[1]));
-
- for (unsigned int i=0; i<4; ++i)
- {
- new_lines[i]->set_used_flag();
- new_lines[i]->clear_user_flag();
- new_lines[i]->clear_user_data();
- new_lines[i]->clear_children();
- new_lines[i]->set_boundary_indicator(quad->boundary_indicator());
- }
-
- // now for the
- // quads. again, first
- // collect some data
- // about the indices of
- // the lines, with the
- // following numbering:
- // .-6-.-7-.
- // 1 9 3
- // .-10.11-.
- // 0 8 2
- // .-4-.-5-.
-
- // child 0 and 1 of a line are
- // switched if the line orientation
- // is false. set up a miniature
- // table, indicating which child to
- // take for line orientations false
- // and true. first index: child
- // index in standard orientation,
- // second index: line orientation
- const unsigned int index[2][2]=
- {{1,0}, // child 0, line_orientation=false and true
- {0,1}}; // child 1, line_orientation=false and true
-
- const unsigned int line_indices[12]
- = { quad->line(0)->child(index[0][quad->line_orientation(0)])->index(),
- quad->line(0)->child(index[1][quad->line_orientation(0)])->index(),
- quad->line(1)->child(index[0][quad->line_orientation(1)])->index(),
- quad->line(1)->child(index[1][quad->line_orientation(1)])->index(),
- quad->line(2)->child(index[0][quad->line_orientation(2)])->index(),
- quad->line(2)->child(index[1][quad->line_orientation(2)])->index(),
- quad->line(3)->child(index[0][quad->line_orientation(3)])->index(),
- quad->line(3)->child(index[1][quad->line_orientation(3)])->index(),
- new_lines[0]->index(),
- new_lines[1]->index(),
- new_lines[2]->index(),
- new_lines[3]->index()
- };
-
- // find some space (consecutive)
- // for the first two newly to be
- // created quads.
- typename Triangulation<dim,spacedim>::raw_quad_iterator new_quads[4];
-
- next_unused_quad=triangulation.faces->quads.next_free_pair_quad(triangulation);
-
- new_quads[0] = next_unused_quad;
- Assert (new_quads[0]->used() == false, ExcCellShouldBeUnused());
-
- ++next_unused_quad;
- new_quads[1] = next_unused_quad;
- Assert (new_quads[1]->used() == false, ExcCellShouldBeUnused());
-
- next_unused_quad=triangulation.faces->quads.next_free_pair_quad(triangulation);
- new_quads[2] = next_unused_quad;
- Assert (new_quads[2]->used() == false, ExcCellShouldBeUnused());
-
- ++next_unused_quad;
- new_quads[3] = next_unused_quad;
- Assert (new_quads[3]->used() == false, ExcCellShouldBeUnused());
-
- // note these quads as
- // children to the
- // present one
- quad->set_children (0, new_quads[0]->index());
- quad->set_children (2, new_quads[2]->index());
- new_quads[0]->set (internal::Triangulation
- ::TriaObject<2>(line_indices[0],
- line_indices[8],
- line_indices[4],
- line_indices[10]));
-
- quad->set_refinement_case(RefinementCase<2>::cut_xy);
-
- new_quads[0]->set (internal::Triangulation
- ::TriaObject<2>(line_indices[0],
- line_indices[8],
- line_indices[4],
- line_indices[10]));
- new_quads[1]->set (internal::Triangulation
- ::TriaObject<2>(line_indices[8],
- line_indices[2],
- line_indices[5],
- line_indices[11]));
- new_quads[2]->set (internal::Triangulation
- ::TriaObject<2>(line_indices[1],
- line_indices[9],
- line_indices[10],
- line_indices[6]));
- new_quads[3]->set (internal::Triangulation
- ::TriaObject<2>(line_indices[9],
- line_indices[3],
- line_indices[11],
- line_indices[7]));
- for (unsigned int i=0; i<4; ++i)
- {
- new_quads[i]->set_used_flag();
- new_quads[i]->clear_user_flag();
- new_quads[i]->clear_user_data();
- new_quads[i]->clear_children();
- new_quads[i]->set_boundary_indicator (quad->boundary_indicator());
- // set all line orientations to
- // true, change this after the
- // loop, as we have to consider
- // different lines for each
- // child
- for (unsigned int j=0; j<GeometryInfo<dim>::lines_per_face; ++j)
- new_quads[i]->set_line_orientation(j,true);
- }
- // now set the line orientation of
- // children of outer lines
- // correctly, the lines in the
- // interior of the refined quad are
- // automatically oriented
- // conforming to the standard
- new_quads[0]->set_line_orientation(0,quad->line_orientation(0));
- new_quads[0]->set_line_orientation(2,quad->line_orientation(2));
- new_quads[1]->set_line_orientation(1,quad->line_orientation(1));
- new_quads[1]->set_line_orientation(2,quad->line_orientation(2));
- new_quads[2]->set_line_orientation(0,quad->line_orientation(0));
- new_quads[2]->set_line_orientation(3,quad->line_orientation(3));
- new_quads[3]->set_line_orientation(1,quad->line_orientation(1));
- new_quads[3]->set_line_orientation(3,quad->line_orientation(3));
-
- // finally clear flag
- // indicating the need
- // for refinement
- quad->clear_user_flag ();
- } // if (isotropic refinement)
- } // for all quads
- } // looped two times over all quads, all quads refined now
-
- ///////////////////////////////////
- // Now, finally, set up the new
- // cells
- ///////////////////////////////////
-
- typename Triangulation<3,spacedim>::DistortedCellList
- cells_with_distorted_children;
-
- for (unsigned int level=0; level!=triangulation.levels.size()-1; ++level)
- {
- // only active objects can be
- // refined further; remember
- // that we won't operate on the
- // finest level, so
- // triangulation.begin_*(level+1) is allowed
- typename Triangulation<dim,spacedim>::active_hex_iterator
- hex = triangulation.begin_active_hex(level),
- endh = triangulation.begin_active_hex(level+1);
- typename Triangulation<dim,spacedim>::raw_hex_iterator
- next_unused_hex = triangulation.begin_raw_hex (level+1);
-
- for (; hex!=endh; ++hex)
- if (hex->refine_flag_set())
- {
- // this hex needs to be
- // refined
-
- // clear flag indicating
- // the need for
- // refinement. do it here
- // already, since we
- // can't do it anymore
- // once the cell has
- // children
- const RefinementCase<dim> ref_case=hex->refine_flag_set();
- hex->clear_refine_flag ();
- hex->set_refinement_case(ref_case);
-
- // depending on the refine case we
- // might have to create additional
- // vertices, lines and quads
- // interior of the hex before the
- // actual children can be set up.
-
- // in a first step: reserve the
- // needed space for lines, quads
- // and hexes and initialize them
- // correctly
-
- unsigned int n_new_lines=0;
- unsigned int n_new_quads=0;
- unsigned int n_new_hexes=0;
- switch (ref_case)
- {
- case RefinementCase<dim>::cut_x:
- case RefinementCase<dim>::cut_y:
- case RefinementCase<dim>::cut_z:
- n_new_lines=0;
- n_new_quads=1;
- n_new_hexes=2;
- break;
- case RefinementCase<dim>::cut_xy:
- case RefinementCase<dim>::cut_xz:
- case RefinementCase<dim>::cut_yz:
- n_new_lines=1;
- n_new_quads=4;
- n_new_hexes=4;
- break;
- case RefinementCase<dim>::cut_xyz:
- n_new_lines=6;
- n_new_quads=12;
- n_new_hexes=8;
- break;
- default:
- Assert(false, ExcInternalError());
- break;
- }
-
- // find some space for the newly to
- // be created interior lines and
- // initialize them.
- std::vector<typename Triangulation<dim,spacedim>::raw_line_iterator>
- new_lines(n_new_lines);
- for (unsigned int i=0; i<n_new_lines; ++i)
- {
- new_lines[i] = triangulation.faces->lines.next_free_single_line(triangulation);
-
- Assert (new_lines[i]->used() == false,
- ExcCellShouldBeUnused());
- new_lines[i]->set_used_flag();
- new_lines[i]->clear_user_flag();
- new_lines[i]->clear_user_data();
- new_lines[i]->clear_children();
- // interior line
- new_lines[i]->set_boundary_indicator(255);
- }
-
- // find some space for the newly to
- // be created interior quads and
- // initialize them.
- std::vector<typename Triangulation<dim,spacedim>::raw_quad_iterator>
- new_quads(n_new_quads);
- for (unsigned int i=0; i<n_new_quads; ++i)
- {
- new_quads[i] = triangulation.faces->quads.next_free_single_quad(triangulation);
-
- Assert (new_quads[i]->used() == false,
- ExcCellShouldBeUnused());
- new_quads[i]->set_used_flag();
- new_quads[i]->clear_user_flag();
- new_quads[i]->clear_user_data();
- new_quads[i]->clear_children();
- // interior quad
- new_quads[i]->set_boundary_indicator (255);
- // set all line orientation
- // flags to true by default,
- // change this afterwards, if
- // necessary
- for (unsigned int j=0; j<GeometryInfo<dim>::lines_per_face; ++j)
- new_quads[i]->set_line_orientation(j,true);
- }
-
- // find some space for the newly to
- // be created hexes and initialize
- // them.
- std::vector<typename Triangulation<dim,spacedim>::raw_hex_iterator>
- new_hexes(n_new_hexes);
- for (unsigned int i=0; i<n_new_hexes; ++i)
- {
- if (i%2==0)
- next_unused_hex=triangulation.levels[level+1]->cells.next_free_hex(triangulation,level+1);
-
- else
- ++next_unused_hex;
-
- new_hexes[i]=next_unused_hex;
-
- Assert (new_hexes[i]->used() == false,
- ExcCellShouldBeUnused());
- new_hexes[i]->set_used_flag();
- new_hexes[i]->clear_user_flag();
- new_hexes[i]->clear_user_data();
- new_hexes[i]->clear_children();
- // inherit material
- // properties
- new_hexes[i]->set_material_id (hex->material_id());
- new_hexes[i]->set_subdomain_id (hex->subdomain_id());
-
- if (i%2)
- new_hexes[i]->set_parent (hex->index ());
- // set the face_orientation
- // flag to true for all faces
- // initially, as this is the
- // default value which is true
- // for all faces interior to
- // the hex. later on go the
- // other way round and reset
- // faces that are at the
- // boundary of the mother cube
- //
- // the same is true for the
- // face_flip and face_rotation
- // flags. however, the latter
- // two are set to false by
- // default as this is the
- // standard value
- for (unsigned int f=0; f<GeometryInfo<dim>::faces_per_cell; ++f)
- {
- new_hexes[i]->set_face_orientation(f, true);
- new_hexes[i]->set_face_flip(f, false);
- new_hexes[i]->set_face_rotation(f, false);
- }
- }
- // note these hexes as
- // children to the
- // present cell
- for (unsigned int i=0; i<n_new_hexes/2; ++i)
- hex->set_children (2*i, new_hexes[2*i]->index());
-
- // we have to take into account
- // whether the different faces are
- // oriented correctly or in the
- // opposite direction, so store
- // that up front
-
- // face_orientation
- const bool f_or[6]
- = { hex->face_orientation (0),
- hex->face_orientation (1),
- hex->face_orientation (2),
- hex->face_orientation (3),
- hex->face_orientation (4),
- hex->face_orientation (5) };
-
- // face_flip
- const bool f_fl[6]
- = { hex->face_flip (0),
- hex->face_flip (1),
- hex->face_flip (2),
- hex->face_flip (3),
- hex->face_flip (4),
- hex->face_flip (5) };
-
- // face_rotation
- const bool f_ro[6]
- = { hex->face_rotation (0),
- hex->face_rotation (1),
- hex->face_rotation (2),
- hex->face_rotation (3),
- hex->face_rotation (4),
- hex->face_rotation (5) };
-
- // some commonly used fields which
- // have varying size
- const unsigned int *vertex_indices=0;
- const typename Triangulation<dim,spacedim>::raw_line_iterator
- *lines=0;
- const unsigned int *line_indices=0;
- const bool *line_orientation=0;
- const unsigned int *quad_indices=0;
-
- // little helper table, indicating,
- // whether the child with index 0
- // or with index 1 can be found at
- // the standard origin of an
- // anisotropically refined quads in
- // real orientation
- // index 1: (RefineCase - 1)
- // index 2: face_flip
-
- // index 3: face rotation
- // note: face orientation has no influence
- const unsigned int child_at_origin[2][2][2]=
- { { { 0, 0 }, // RefinementCase<dim>::cut_x, face_flip=false, face_rotation=false and true
- { 1, 1 }}, // RefinementCase<dim>::cut_x, face_flip=true, face_rotation=false and true
- { { 0, 1 }, // RefinementCase<dim>::cut_y, face_flip=false, face_rotation=false and true
- { 1, 0 }}};// RefinementCase<dim>::cut_y, face_flip=true, face_rotation=false and true
-
- ///////////////////////////////////////
- //
- // in the following we will do the
- // same thing for each refinement
- // case: create a new vertex (if
- // needed), create new interior
- // lines (if needed), create new
- // interior quads and afterwards
- // build the children hexes out of
- // these and the existing subfaces
- // of the outer quads (which have
- // been created above). However,
- // even if the steps are quite
- // similar, the actual work
- // strongly depends on the actual
- // refinement case. therefore, we
- // use seperate blocks of code for
- // each of these cases, which
- // hopefully increases the
- // readability to some extend.
-
- switch (ref_case)
- {
- case RefinementCase<dim>::cut_x:
- {
- //////////////////////////////
- //
- // RefinementCase<dim>::cut_x
- //
- // the refined cube will look
- // like this:
- //
- // *----*----*
- // / / /|
- // / / / |
- // / / / |
- // *----*----* |
- // | | | |
- // | | | *
- // | | | /
- // | | | /
- // | | |/
- // *----*----*
- //
- // again, first
- // collect some data
- // about the indices of
- // the lines, with the
- // following numbering:
-
- // face 2: front plane
- // (note: x,y exchanged)
- // *---*---*
- // | | |
- // | 0 |
- // | | |
- // *---*---*
- // m0
- // face 3: back plane
- // (note: x,y exchanged)
- // m1
- // *---*---*
- // | | |
- // | 1 |
- // | | |
- // *---*---*
- // face 4: bottom plane
- // *---*---*
- // / / /
- // / 2 /
- // / / /
- // *---*---*
- // m0
- // face 5: top plane
- // m1
- // *---*---*
- // / / /
- // / 3 /
- // / / /
- // *---*---*
-
- // set up a list of line iterators
- // first. from this, construct
- // lists of line_indices and
- // line orientations later on
- const typename Triangulation<dim,spacedim>::raw_line_iterator
- lines_x[4]
- = {
- hex->face(2)->child(0)
- ->line((hex->face(2)->refinement_case() == RefinementCase<2>::cut_x) ? 1 : 3), //0
- hex->face(3)->child(0)
- ->line((hex->face(3)->refinement_case() == RefinementCase<2>::cut_x) ? 1 : 3), //1
- hex->face(4)->child(0)
- ->line((hex->face(4)->refinement_case() == RefinementCase<2>::cut_x) ? 1 : 3), //2
- hex->face(5)->child(0)
- ->line((hex->face(5)->refinement_case() == RefinementCase<2>::cut_x) ? 1 : 3) //3
- };
-
- lines=&lines_x[0];
-
- unsigned int line_indices_x[4];
-
- for (unsigned int i=0; i<4; ++i)
- line_indices_x[i]=lines[i]->index();
- line_indices=&line_indices_x[0];
-
- // the orientation of lines for the
- // inner quads is quite tricky. as
- // these lines are newly created
- // ones and thus have no parents,
- // they cannot inherit this
- // property. set up an array and
- // fill it with the respective
- // values
- bool line_orientation_x[4];
-
- // the middle vertice marked
- // as m0 above is the start
- // vertex for lines 0 and 2
- // in standard orientation,
- // whereas m1 is the end
- // vertex of lines 1 and 3 in
- // standard orientation
- const unsigned int middle_vertices[2]=
- {
- hex->line(2)->child(0)->vertex_index(1),
- hex->line(7)->child(0)->vertex_index(1)
- };
-
- for (unsigned int i=0; i<4; ++i)
- if (lines[i]->vertex_index(i%2)==middle_vertices[i%2])
- line_orientation_x[i]=true;
- else
- {
- // it must be the other
- // way round then
- Assert(lines[i]->vertex_index((i+1)%2)==middle_vertices[i%2],
- ExcInternalError());
- line_orientation_x[i]=false;
- }
-
- line_orientation=&line_orientation_x[0];
-
- // set up the new quad, line
- // numbering is as indicated
- // above
- new_quads[0]->set (internal::Triangulation
- ::TriaObject<2>(line_indices[0],
- line_indices[1],
- line_indices[2],
- line_indices[3]));
-
- new_quads[0]->set_line_orientation(0,line_orientation[0]);
- new_quads[0]->set_line_orientation(1,line_orientation[1]);
- new_quads[0]->set_line_orientation(2,line_orientation[2]);
- new_quads[0]->set_line_orientation(3,line_orientation[3]);
-
- // the quads are
- // numbered as follows:
- //
- // planes in the interior
- // of the old hex:
- // *
- // /|
- // / | x
- // / | *-------* *---------*
- // * | | | / /
- // | 0 | | | / /
- // | * | | / /
- // | / *-------*y *---------*x
- // | /
- // |/
- // *
- //
- // children of the faces
- // of the old hex
- // *---*---* *---*---*
- // /| | | / / /|
- // / | | | / 9 / 10/ |
- // / | 5 | 6 | / / / |
- // * | | | *---*---* |
- // | 1 *---*---* | | | 2 *
- // | / / / | | | /
- // | / 7 / 8 / | 3 | 4 | /
- // |/ / / | | |/
- // *---*---* *---*---*
- //
- // note that we have to
- // take care of the
- // orientation of
- // faces.
- const unsigned int quad_indices_x[11]
- = {
- new_quads[0]->index(), //0
-
- hex->face(0)->index(), //1
-
- hex->face(1)->index(), //2
-
- hex->face(2)->child_index( child_at_origin[hex->face(2)->refinement_case()-1][f_fl[2]][f_ro[2]]), //3
- hex->face(2)->child_index(1-child_at_origin[hex->face(2)->refinement_case()-1][f_fl[2]][f_ro[2]]),
-
- hex->face(3)->child_index( child_at_origin[hex->face(3)->refinement_case()-1][f_fl[3]][f_ro[3]]), //5
- hex->face(3)->child_index(1-child_at_origin[hex->face(3)->refinement_case()-1][f_fl[3]][f_ro[3]]),
-
- hex->face(4)->child_index( child_at_origin[hex->face(4)->refinement_case()-1][f_fl[4]][f_ro[4]]), //7
- hex->face(4)->child_index(1-child_at_origin[hex->face(4)->refinement_case()-1][f_fl[4]][f_ro[4]]),
-
- hex->face(5)->child_index( child_at_origin[hex->face(5)->refinement_case()-1][f_fl[5]][f_ro[5]]), //9
- hex->face(5)->child_index(1-child_at_origin[hex->face(5)->refinement_case()-1][f_fl[5]][f_ro[5]])
-
- };
- quad_indices=&quad_indices_x[0];
-
- new_hexes[0]->set (internal::Triangulation
- ::TriaObject<3>(quad_indices[1],
- quad_indices[0],
- quad_indices[3],
- quad_indices[5],
- quad_indices[7],
- quad_indices[9]));
- new_hexes[1]->set (internal::Triangulation
- ::TriaObject<3>(quad_indices[0],
- quad_indices[2],
- quad_indices[4],
- quad_indices[6],
- quad_indices[8],
- quad_indices[10]));
- break;
- }
- case RefinementCase<dim>::cut_y:
- {
- //////////////////////////////
- //
- // RefinementCase<dim>::cut_y
- //
- // the refined cube will look
- // like this:
- //
- // *---------*
- // / /|
- // *---------* |
- // / /| |
- // *---------* | |
- // | | | |
- // | | | *
- // | | |/
- // | | *
- // | |/
- // *---------*
- //
- // again, first
- // collect some data
- // about the indices of
- // the lines, with the
- // following numbering:
-
- // face 0: left plane
- // *
- // /|
- // * |
- // /| |
- // * | |
- // | 0 |
- // | | *
- // | |/
- // | *m0
- // |/
- // *
- // face 1: right plane
- // *
- // /|
- // m1* |
- // /| |
- // * | |
- // | 1 |
- // | | *
- // | |/
- // | *
- // |/
- // *
- // face 4: bottom plane
- // *-------*
- // / /
- // m0*---2---*
- // / /
- // *-------*
- // face 5: top plane
- // *-------*
- // / /
- // *---3---*m1
- // / /
- // *-------*
-
- // set up a list of line iterators
- // first. from this, construct
- // lists of line_indices and
- // line orientations later on
- const typename Triangulation<dim,spacedim>::raw_line_iterator
- lines_y[4]
- = {
- hex->face(0)->child(0)
- ->line((hex->face(0)->refinement_case() == RefinementCase<2>::cut_x) ? 1 : 3), //0
- hex->face(1)->child(0)
- ->line((hex->face(1)->refinement_case() == RefinementCase<2>::cut_x) ? 1 : 3), //1
- hex->face(4)->child(0)
- ->line((hex->face(4)->refinement_case() == RefinementCase<2>::cut_x) ? 1 : 3), //2
- hex->face(5)->child(0)
- ->line((hex->face(5)->refinement_case() == RefinementCase<2>::cut_x) ? 1 : 3) //3
- };
-
- lines=&lines_y[0];
-
- unsigned int line_indices_y[4];
-
- for (unsigned int i=0; i<4; ++i)
- line_indices_y[i]=lines[i]->index();
- line_indices=&line_indices_y[0];
-
- // the orientation of lines for the
- // inner quads is quite tricky. as
- // these lines are newly created
- // ones and thus have no parents,
- // they cannot inherit this
- // property. set up an array and
- // fill it with the respective
- // values
- bool line_orientation_y[4];
-
- // the middle vertice marked
- // as m0 above is the start
- // vertex for lines 0 and 2
- // in standard orientation,
- // whereas m1 is the end
- // vertex of lines 1 and 3 in
- // standard orientation
- const unsigned int middle_vertices[2]=
- {
- hex->line(0)->child(0)->vertex_index(1),
- hex->line(5)->child(0)->vertex_index(1)
- };
-
- for (unsigned int i=0; i<4; ++i)
- if (lines[i]->vertex_index(i%2)==middle_vertices[i%2])
- line_orientation_y[i]=true;
- else
- {
- // it must be the other way round then
- Assert(lines[i]->vertex_index((i+1)%2)==middle_vertices[i%2],
- ExcInternalError());
- line_orientation_y[i]=false;
- }
-
- line_orientation=&line_orientation_y[0];
-
- // set up the new quad, line
- // numbering is as indicated
- // above
- new_quads[0]->set (internal::Triangulation
- ::TriaObject<2>(line_indices[2],
- line_indices[3],
- line_indices[0],
- line_indices[1]));
-
- new_quads[0]->set_line_orientation(0,line_orientation[2]);
- new_quads[0]->set_line_orientation(1,line_orientation[3]);
- new_quads[0]->set_line_orientation(2,line_orientation[0]);
- new_quads[0]->set_line_orientation(3,line_orientation[1]);
-
- // the quads are
- // numbered as follows:
- //
- // planes in the interior
- // of the old hex:
- // *
- // /|
- // / | x
- // / | *-------* *---------*
- // * | | | / /
- // | | | 0 | / /
- // | * | | / /
- // | / *-------*y *---------*x
- // | /
- // |/
- // *
- //
- // children of the faces
- // of the old hex
- // *-------* *-------*
- // /| | / 10 /|
- // * | | *-------* |
- // /| | 6 | / 9 /| |
- // * |2| | *-------* |4|
- // | | *-------* | | | *
- // |1|/ 8 / | |3|/
- // | *-------* | 5 | *
- // |/ 7 / | |/
- // *-------* *-------*
- //
- // note that we have to
- // take care of the
- // orientation of
- // faces.
- const unsigned int quad_indices_y[11]
- = {
- new_quads[0]->index(), //0
-
- hex->face(0)->child_index( child_at_origin[hex->face(0)->refinement_case()-1][f_fl[0]][f_ro[0]]), //1
- hex->face(0)->child_index(1-child_at_origin[hex->face(0)->refinement_case()-1][f_fl[0]][f_ro[0]]),
-
- hex->face(1)->child_index( child_at_origin[hex->face(1)->refinement_case()-1][f_fl[1]][f_ro[1]]), //3
- hex->face(1)->child_index(1-child_at_origin[hex->face(1)->refinement_case()-1][f_fl[1]][f_ro[1]]),
-
- hex->face(2)->index(), //5
-
- hex->face(3)->index(), //6
-
- hex->face(4)->child_index( child_at_origin[hex->face(4)->refinement_case()-1][f_fl[4]][f_ro[4]]), //7
- hex->face(4)->child_index(1-child_at_origin[hex->face(4)->refinement_case()-1][f_fl[4]][f_ro[4]]),
-
- hex->face(5)->child_index( child_at_origin[hex->face(5)->refinement_case()-1][f_fl[5]][f_ro[5]]), //9
- hex->face(5)->child_index(1-child_at_origin[hex->face(5)->refinement_case()-1][f_fl[5]][f_ro[5]])
-
- };
- quad_indices=&quad_indices_y[0];
-
- new_hexes[0]->set (internal::Triangulation
- ::TriaObject<3>(quad_indices[1],
- quad_indices[3],
- quad_indices[5],
- quad_indices[0],
- quad_indices[7],
- quad_indices[9]));
- new_hexes[1]->set (internal::Triangulation
- ::TriaObject<3>(quad_indices[2],
- quad_indices[4],
- quad_indices[0],
- quad_indices[6],
- quad_indices[8],
- quad_indices[10]));
- break;
- }
- case RefinementCase<dim>::cut_z:
- {
- //////////////////////////////
- //
- // RefinementCase<dim>::cut_z
- //
- // the refined cube will look
- // like this:
- //
- // *---------*
- // / /|
- // / / |
- // / / *
- // *---------* /|
- // | | / |
- // | |/ *
- // *---------* /
- // | | /
- // | |/
- // *---------*
- //
- // again, first
- // collect some data
- // about the indices of
- // the lines, with the
- // following numbering:
-
- // face 0: left plane
- // *
- // /|
- // / |
- // / *
- // * /|
- // | 0 |
- // |/ *
- // m0* /
- // | /
- // |/
- // *
- // face 1: right plane
- // *
- // /|
- // / |
- // / *m1
- // * /|
- // | 1 |
- // |/ *
- // * /
- // | /
- // |/
- // *
- // face 2: front plane
- // (note: x,y exchanged)
- // *-------*
- // | |
- // m0*---2---*
- // | |
- // *-------*
- // face 3: back plane
- // (note: x,y exchanged)
- // *-------*
- // | |
- // *---3---*m1
- // | |
- // *-------*
-
- // set up a list of line iterators
- // first. from this, construct
- // lists of line_indices and
- // line orientations later on
- const typename Triangulation<dim,spacedim>::raw_line_iterator
- lines_z[4]
- = {
- hex->face(0)->child(0)
- ->line((hex->face(0)->refinement_case() == RefinementCase<2>::cut_x) ? 1 : 3), //0
- hex->face(1)->child(0)
- ->line((hex->face(1)->refinement_case() == RefinementCase<2>::cut_x) ? 1 : 3), //1
- hex->face(2)->child(0)
- ->line((hex->face(2)->refinement_case() == RefinementCase<2>::cut_x) ? 1 : 3), //2
- hex->face(3)->child(0)
- ->line((hex->face(3)->refinement_case() == RefinementCase<2>::cut_x) ? 1 : 3) //3
- };
-
- lines=&lines_z[0];
-
- unsigned int line_indices_z[4];
-
- for (unsigned int i=0; i<4; ++i)
- line_indices_z[i]=lines[i]->index();
- line_indices=&line_indices_z[0];
-
- // the orientation of lines for the
- // inner quads is quite tricky. as
- // these lines are newly created
- // ones and thus have no parents,
- // they cannot inherit this
- // property. set up an array and
- // fill it with the respective
- // values
- bool line_orientation_z[4];
-
- // the middle vertex marked
- // as m0 above is the start
- // vertex for lines 0 and 2
- // in standard orientation,
- // whereas m1 is the end
- // vertex of lines 1 and 3 in
- // standard orientation
- const unsigned int middle_vertices[2]=
- {
- middle_vertex_index<dim,spacedim>(hex->line(8)),
- middle_vertex_index<dim,spacedim>(hex->line(11))
- };
-
- for (unsigned int i=0; i<4; ++i)
- if (lines[i]->vertex_index(i%2)==middle_vertices[i%2])
- line_orientation_z[i]=true;
- else
- {
- // it must be the other way round then
- Assert(lines[i]->vertex_index((i+1)%2)==middle_vertices[i%2],
- ExcInternalError());
- line_orientation_z[i]=false;
- }
-
- line_orientation=&line_orientation_z[0];
-
- // set up the new quad, line
- // numbering is as indicated
- // above
- new_quads[0]->set (internal::Triangulation
- ::TriaObject<2>(line_indices[0],
- line_indices[1],
- line_indices[2],
- line_indices[3]));
-
- new_quads[0]->set_line_orientation(0,line_orientation[0]);
- new_quads[0]->set_line_orientation(1,line_orientation[1]);
- new_quads[0]->set_line_orientation(2,line_orientation[2]);
- new_quads[0]->set_line_orientation(3,line_orientation[3]);
-
- // the quads are
- // numbered as follows:
- //
- // planes in the interior
- // of the old hex:
- // *
- // /|
- // / | x
- // / | *-------* *---------*
- // * | | | / /
- // | | | | / 0 /
- // | * | | / /
- // | / *-------*y *---------*x
- // | /
- // |/
- // *
- //
- // children of the faces
- // of the old hex
- // *---*---* *-------*
- // /| 8 | / /|
- // / | | / 10 / |
- // / *-------* / / *
- // * 2/| | *-------* 4/|
- // | / | 7 | | 6 | / |
- // |/1 *-------* | |/3 *
- // * / / *-------* /
- // | / 9 / | | /
- // |/ / | 5 |/
- // *-------* *---*---*
- //
- // note that we have to
- // take care of the
- // orientation of
- // faces.
- const unsigned int quad_indices_z[11]
- = {
- new_quads[0]->index(), //0
-
- hex->face(0)->child_index( child_at_origin[hex->face(0)->refinement_case()-1][f_fl[0]][f_ro[0]]), //1
- hex->face(0)->child_index(1-child_at_origin[hex->face(0)->refinement_case()-1][f_fl[0]][f_ro[0]]),
-
- hex->face(1)->child_index( child_at_origin[hex->face(1)->refinement_case()-1][f_fl[1]][f_ro[1]]), //3
- hex->face(1)->child_index(1-child_at_origin[hex->face(1)->refinement_case()-1][f_fl[1]][f_ro[1]]),
-
- hex->face(2)->child_index( child_at_origin[hex->face(2)->refinement_case()-1][f_fl[2]][f_ro[2]]), //5
- hex->face(2)->child_index(1-child_at_origin[hex->face(2)->refinement_case()-1][f_fl[2]][f_ro[2]]),
-
- hex->face(3)->child_index( child_at_origin[hex->face(3)->refinement_case()-1][f_fl[3]][f_ro[3]]), //7
- hex->face(3)->child_index(1-child_at_origin[hex->face(3)->refinement_case()-1][f_fl[3]][f_ro[3]]),
-
- hex->face(4)->index(), //9
-
- hex->face(5)->index() //10
- };
- quad_indices=&quad_indices_z[0];
-
- new_hexes[0]->set (internal::Triangulation
- ::TriaObject<3>(quad_indices[1],
- quad_indices[3],
- quad_indices[5],
- quad_indices[7],
- quad_indices[9],
- quad_indices[0]));
- new_hexes[1]->set (internal::Triangulation
- ::TriaObject<3>(quad_indices[2],
- quad_indices[4],
- quad_indices[6],
- quad_indices[8],
- quad_indices[0],
- quad_indices[10]));
- break;
- }
- case RefinementCase<dim>::cut_xy:
- {
- //////////////////////////////
- //
- // RefinementCase<dim>::cut_xy
- //
- // the refined cube will look
- // like this:
- //
- // *----*----*
- // / / /|
- // *----*----* |
- // / / /| |
- // *----*----* | |
- // | | | | |
- // | | | | *
- // | | | |/
- // | | | *
- // | | |/
- // *----*----*
- //
-
- // first, create the new
- // internal line
- new_lines[0]->set (internal::Triangulation::
- TriaObject<1>(middle_vertex_index<dim,spacedim>(hex->face(4)),
- middle_vertex_index<dim,spacedim>(hex->face(5))));
-
- // again, first
- // collect some data
- // about the indices of
- // the lines, with the
- // following numbering:
-
- // face 0: left plane
- // *
- // /|
- // * |
- // /| |
- // * | |
- // | 0 |
- // | | *
- // | |/
- // | *
- // |/
- // *
- // face 1: right plane
- // *
- // /|
- // * |
- // /| |
- // * | |
- // | 1 |
- // | | *
- // | |/
- // | *
- // |/
- // *
- // face 2: front plane
- // (note: x,y exchanged)
- // *---*---*
- // | | |
- // | 2 |
- // | | |
- // *-------*
- // face 3: back plane
- // (note: x,y exchanged)
- // *---*---*
- // | | |
- // | 3 |
- // | | |
- // *---*---*
- // face 4: bottom plane
- // *---*---*
- // / 5 /
- // *-6-*-7-*
- // / 4 /
- // *---*---*
- // face 5: top plane
- // *---*---*
- // / 9 /
- // *10-*-11*
- // / 8 /
- // *---*---*
- // middle planes
- // *-------* *---*---*
- // / / | | |
- // / / | 12 |
- // / / | | |
- // *-------* *---*---*
-
- // set up a list of line iterators
- // first. from this, construct
- // lists of line_indices and
- // line orientations later on
- const typename Triangulation<dim,spacedim>::raw_line_iterator
- lines_xy[13]
- = {
- hex->face(0)->child(0)
- ->line((hex->face(0)->refinement_case() == RefinementCase<2>::cut_x) ? 1 : 3), //0
- hex->face(1)->child(0)
- ->line((hex->face(1)->refinement_case() == RefinementCase<2>::cut_x) ? 1 : 3), //1
- hex->face(2)->child(0)
- ->line((hex->face(2)->refinement_case() == RefinementCase<2>::cut_x) ? 1 : 3), //2
- hex->face(3)->child(0)
- ->line((hex->face(3)->refinement_case() == RefinementCase<2>::cut_x) ? 1 : 3), //3
-
- hex->face(4)->isotropic_child(GeometryInfo<dim>::standard_to_real_face_vertex(0,f_or[4],f_fl[4],f_ro[4]))
- ->line(GeometryInfo<dim>::standard_to_real_face_line(1,f_or[4],f_fl[4],f_ro[4])), //4
- hex->face(4)->isotropic_child(GeometryInfo<dim>::standard_to_real_face_vertex(3,f_or[4],f_fl[4],f_ro[4]))
- ->line(GeometryInfo<dim>::standard_to_real_face_line(0,f_or[4],f_fl[4],f_ro[4])), //5
- hex->face(4)->isotropic_child(GeometryInfo<dim>::standard_to_real_face_vertex(0,f_or[4],f_fl[4],f_ro[4]))
- ->line(GeometryInfo<dim>::standard_to_real_face_line(3,f_or[4],f_fl[4],f_ro[4])), //6
- hex->face(4)->isotropic_child(GeometryInfo<dim>::standard_to_real_face_vertex(3,f_or[4],f_fl[4],f_ro[4]))
- ->line(GeometryInfo<dim>::standard_to_real_face_line(2,f_or[4],f_fl[4],f_ro[4])), //7
-
- hex->face(5)->isotropic_child(GeometryInfo<dim>::standard_to_real_face_vertex(0,f_or[5],f_fl[5],f_ro[5]))
- ->line(GeometryInfo<dim>::standard_to_real_face_line(1,f_or[5],f_fl[5],f_ro[5])), //8
- hex->face(5)->isotropic_child(GeometryInfo<dim>::standard_to_real_face_vertex(3,f_or[5],f_fl[5],f_ro[5]))
- ->line(GeometryInfo<dim>::standard_to_real_face_line(0,f_or[5],f_fl[5],f_ro[5])), //9
- hex->face(5)->isotropic_child(GeometryInfo<dim>::standard_to_real_face_vertex(0,f_or[5],f_fl[5],f_ro[5]))
- ->line(GeometryInfo<dim>::standard_to_real_face_line(3,f_or[5],f_fl[5],f_ro[5])), //10
- hex->face(5)->isotropic_child(GeometryInfo<dim>::standard_to_real_face_vertex(3,f_or[5],f_fl[5],f_ro[5]))
- ->line(GeometryInfo<dim>::standard_to_real_face_line(2,f_or[5],f_fl[5],f_ro[5])), //11
-
- new_lines[0] //12
- };
-
- lines=&lines_xy[0];
-
- unsigned int line_indices_xy[13];
-
- for (unsigned int i=0; i<13; ++i)
- line_indices_xy[i]=lines[i]->index();
- line_indices=&line_indices_xy[0];
-
- // the orientation of lines for the
- // inner quads is quite tricky. as
- // these lines are newly created
- // ones and thus have no parents,
- // they cannot inherit this
- // property. set up an array and
- // fill it with the respective
- // values
- bool line_orientation_xy[13];
-
- // the middle vertices of the
- // lines of our bottom face
- const unsigned int middle_vertices[4]=
- {
- hex->line(0)->child(0)->vertex_index(1),
- hex->line(1)->child(0)->vertex_index(1),
- hex->line(2)->child(0)->vertex_index(1),
- hex->line(3)->child(0)->vertex_index(1),
- };
-
- // note: for lines 0 to 3 the
- // orientation of the line
- // is 'true', if vertex 0 is
- // on the bottom face
- for (unsigned int i=0; i<4; ++i)
- if (lines[i]->vertex_index(0)==middle_vertices[i])
- line_orientation_xy[i]=true;
- else
- {
- // it must be the other way round then
- Assert(lines[i]->vertex_index(1)==middle_vertices[i],
- ExcInternalError());
- line_orientation_xy[i]=false;
- }
-
- // note: for lines 4 to 11
- // (inner lines of the outer quads)
- // the following holds: the second
- // vertex of the even lines in
- // standard orientation is the
- // vertex in the middle of the
- // quad, whereas for odd lines the
- // first vertex is the same middle
- // vertex.
- for (unsigned int i=4; i<12; ++i)
- if (lines[i]->vertex_index((i+1)%2) ==
- middle_vertex_index<dim,spacedim>(hex->face(3+i/4)))
- line_orientation_xy[i]=true;
- else
- {
- // it must be the other way
- // round then
- Assert(lines[i]->vertex_index(i%2) ==
- (middle_vertex_index<dim,spacedim>(hex->face(3+i/4))),
- ExcInternalError());
- line_orientation_xy[i]=false;
- }
- // for the last line the line
- // orientation is always true,
- // since it was just constructed
- // that way
-
- line_orientation_xy[12]=true;
- line_orientation=&line_orientation_xy[0];
-
- // set up the 4 quads,
- // numbered as follows
- // (left quad numbering,
- // right line numbering
- // extracted from above)
- //
- // * *
- // /| 9|
- // * | * |
- // y/| | 8| 3
- // * |1| * | |
- // | | |x | 12|
- // |0| * | | *
- // | |/ 2 |5
- // | * | *
- // |/ |4
- // * *
- //
- // x
- // *---*---* *10-*-11*
- // | | | | | |
- // | 2 | 3 | 0 12 1
- // | | | | | |
- // *---*---*y *-6-*-7-*
-
- new_quads[0]->set (internal::Triangulation
- ::TriaObject<2>(line_indices[2],
- line_indices[12],
- line_indices[4],
- line_indices[8]));
- new_quads[1]->set (internal::Triangulation
- ::TriaObject<2>(line_indices[12],
- line_indices[3],
- line_indices[5],
- line_indices[9]));
- new_quads[2]->set (internal::Triangulation
- ::TriaObject<2>(line_indices[6],
- line_indices[10],
- line_indices[0],
- line_indices[12]));
- new_quads[3]->set (internal::Triangulation
- ::TriaObject<2>(line_indices[7],
- line_indices[11],
- line_indices[12],
- line_indices[1]));
-
- new_quads[0]->set_line_orientation(0,line_orientation[2]);
- new_quads[0]->set_line_orientation(2,line_orientation[4]);
- new_quads[0]->set_line_orientation(3,line_orientation[8]);
-
- new_quads[1]->set_line_orientation(1,line_orientation[3]);
- new_quads[1]->set_line_orientation(2,line_orientation[5]);
- new_quads[1]->set_line_orientation(3,line_orientation[9]);
-
- new_quads[2]->set_line_orientation(0,line_orientation[6]);
- new_quads[2]->set_line_orientation(1,line_orientation[10]);
- new_quads[2]->set_line_orientation(2,line_orientation[0]);
-
- new_quads[3]->set_line_orientation(0,line_orientation[7]);
- new_quads[3]->set_line_orientation(1,line_orientation[11]);
- new_quads[3]->set_line_orientation(3,line_orientation[1]);
-
- // the quads are
- // numbered as follows:
- //
- // planes in the interior
- // of the old hex:
- // *
- // /|
- // * | x
- // /| | *---*---* *---------*
- // * |1| | | | / /
- // | | | | 2 | 3 | / /
- // |0| * | | | / /
- // | |/ *---*---*y *---------*x
- // | *
- // |/
- // *
- //
- // children of the faces
- // of the old hex
- // *---*---* *---*---*
- // /| | | /18 / 19/|
- // * |10 | 11| /---/---* |
- // /| | | | /16 / 17/| |
- // * |5| | | *---*---* |7|
- // | | *---*---* | | | | *
- // |4|/14 / 15/ | | |6|/
- // | *---/---/ | 8 | 9 | *
- // |/12 / 13/ | | |/
- // *---*---* *---*---*
- //
- // note that we have to
- // take care of the
- // orientation of
- // faces.
- const unsigned int quad_indices_xy[20]
- = {
- new_quads[0]->index(), //0
- new_quads[1]->index(),
- new_quads[2]->index(),
- new_quads[3]->index(),
-
- hex->face(0)->child_index( child_at_origin[hex->face(0)->refinement_case()-1][f_fl[0]][f_ro[0]]), //4
- hex->face(0)->child_index(1-child_at_origin[hex->face(0)->refinement_case()-1][f_fl[0]][f_ro[0]]),
-
- hex->face(1)->child_index( child_at_origin[hex->face(1)->refinement_case()-1][f_fl[1]][f_ro[1]]), //6
- hex->face(1)->child_index(1-child_at_origin[hex->face(1)->refinement_case()-1][f_fl[1]][f_ro[1]]),
-
- hex->face(2)->child_index( child_at_origin[hex->face(2)->refinement_case()-1][f_fl[2]][f_ro[2]]), //8
- hex->face(2)->child_index(1-child_at_origin[hex->face(2)->refinement_case()-1][f_fl[2]][f_ro[2]]),
-
- hex->face(3)->child_index( child_at_origin[hex->face(3)->refinement_case()-1][f_fl[3]][f_ro[3]]), //10
- hex->face(3)->child_index(1-child_at_origin[hex->face(3)->refinement_case()-1][f_fl[3]][f_ro[3]]),
-
- hex->face(4)->isotropic_child_index(GeometryInfo<dim>::standard_to_real_face_vertex(0,f_or[4],f_fl[4],f_ro[4])), //12
- hex->face(4)->isotropic_child_index(GeometryInfo<dim>::standard_to_real_face_vertex(1,f_or[4],f_fl[4],f_ro[4])),
- hex->face(4)->isotropic_child_index(GeometryInfo<dim>::standard_to_real_face_vertex(2,f_or[4],f_fl[4],f_ro[4])),
- hex->face(4)->isotropic_child_index(GeometryInfo<dim>::standard_to_real_face_vertex(3,f_or[4],f_fl[4],f_ro[4])),
-
- hex->face(5)->isotropic_child_index(GeometryInfo<dim>::standard_to_real_face_vertex(0,f_or[5],f_fl[5],f_ro[5])), //16
- hex->face(5)->isotropic_child_index(GeometryInfo<dim>::standard_to_real_face_vertex(1,f_or[5],f_fl[5],f_ro[5])),
- hex->face(5)->isotropic_child_index(GeometryInfo<dim>::standard_to_real_face_vertex(2,f_or[5],f_fl[5],f_ro[5])),
- hex->face(5)->isotropic_child_index(GeometryInfo<dim>::standard_to_real_face_vertex(3,f_or[5],f_fl[5],f_ro[5]))
- };
- quad_indices=&quad_indices_xy[0];
-
- new_hexes[0]->set (internal::Triangulation
- ::TriaObject<3>(quad_indices[4],
- quad_indices[0],
- quad_indices[8],
- quad_indices[2],
- quad_indices[12],
- quad_indices[16]));
- new_hexes[1]->set (internal::Triangulation
- ::TriaObject<3>(quad_indices[0],
- quad_indices[6],
- quad_indices[9],
- quad_indices[3],
- quad_indices[13],
- quad_indices[17]));
- new_hexes[2]->set (internal::Triangulation
- ::TriaObject<3>(quad_indices[5],
- quad_indices[1],
- quad_indices[2],
- quad_indices[10],
- quad_indices[14],
- quad_indices[18]));
- new_hexes[3]->set (internal::Triangulation
- ::TriaObject<3>(quad_indices[1],
- quad_indices[7],
- quad_indices[3],
- quad_indices[11],
- quad_indices[15],
- quad_indices[19]));
- break;
- }
- case RefinementCase<dim>::cut_xz:
- {
- //////////////////////////////
- //
- // RefinementCase<dim>::cut_xz
- //
- // the refined cube will look
- // like this:
- //
- // *----*----*
- // / / /|
- // / / / |
- // / / / *
- // *----*----* /|
- // | | | / |
- // | | |/ *
- // *----*----* /
- // | | | /
- // | | |/
- // *----*----*
- //
-
- // first, create the new
- // internal line
- new_lines[0]->set (internal::Triangulation::
- TriaObject<1>(middle_vertex_index<dim,spacedim>(hex->face(2)),
- middle_vertex_index<dim,spacedim>(hex->face(3))));
-
- // again, first
- // collect some data
- // about the indices of
- // the lines, with the
- // following numbering:
-
- // face 0: left plane
- // *
- // /|
- // / |
- // / *
- // * /|
- // | 0 |
- // |/ *
- // * /
- // | /
- // |/
- // *
- // face 1: right plane
- // *
- // /|
- // / |
- // / *
- // * /|
- // | 1 |
- // |/ *
- // * /
- // | /
- // |/
- // *
- // face 2: front plane
- // (note: x,y exchanged)
- // *---*---*
- // | 5 |
- // *-6-*-7-*
- // | 4 |
- // *---*---*
- // face 3: back plane
- // (note: x,y exchanged)
- // *---*---*
- // | 9 |
- // *10-*-11*
- // | 8 |
- // *---*---*
- // face 4: bottom plane
- // *---*---*
- // / / /
- // / 2 /
- // / / /
- // *---*---*
- // face 5: top plane
- // *---*---*
- // / / /
- // / 3 /
- // / / /
- // *---*---*
- // middle planes
- // *---*---* *-------*
- // / / / | |
- // / 12 / | |
- // / / / | |
- // *---*---* *-------*
-
- // set up a list of line iterators
- // first. from this, construct
- // lists of line_indices and
- // line orientations later on
- const typename Triangulation<dim,spacedim>::raw_line_iterator
- lines_xz[13]
- = {
- hex->face(0)->child(0)
- ->line((hex->face(0)->refinement_case() == RefinementCase<2>::cut_x) ? 1 : 3), //0
- hex->face(1)->child(0)
- ->line((hex->face(1)->refinement_case() == RefinementCase<2>::cut_x) ? 1 : 3), //1
- hex->face(4)->child(0)
- ->line((hex->face(4)->refinement_case() == RefinementCase<2>::cut_x) ? 1 : 3), //2
- hex->face(5)->child(0)
- ->line((hex->face(5)->refinement_case() == RefinementCase<2>::cut_x) ? 1 : 3), //3
-
- hex->face(2)->isotropic_child(GeometryInfo<dim>::standard_to_real_face_vertex(0,f_or[2],f_fl[2],f_ro[2]))
- ->line(GeometryInfo<dim>::standard_to_real_face_line(3,f_or[2],f_fl[2],f_ro[2])), //4
- hex->face(2)->isotropic_child(GeometryInfo<dim>::standard_to_real_face_vertex(3,f_or[2],f_fl[2],f_ro[2]))
- ->line(GeometryInfo<dim>::standard_to_real_face_line(2,f_or[2],f_fl[2],f_ro[2])), //5
- hex->face(2)->isotropic_child(GeometryInfo<dim>::standard_to_real_face_vertex(0,f_or[2],f_fl[2],f_ro[2]))
- ->line(GeometryInfo<dim>::standard_to_real_face_line(1,f_or[2],f_fl[2],f_ro[2])), //6
- hex->face(2)->isotropic_child(GeometryInfo<dim>::standard_to_real_face_vertex(3,f_or[2],f_fl[2],f_ro[2]))
- ->line(GeometryInfo<dim>::standard_to_real_face_line(0,f_or[2],f_fl[2],f_ro[2])), //7
-
- hex->face(3)->isotropic_child(GeometryInfo<dim>::standard_to_real_face_vertex(0,f_or[3],f_fl[3],f_ro[3]))
- ->line(GeometryInfo<dim>::standard_to_real_face_line(3,f_or[3],f_fl[3],f_ro[3])), //8
- hex->face(3)->isotropic_child(GeometryInfo<dim>::standard_to_real_face_vertex(3,f_or[3],f_fl[3],f_ro[3]))
- ->line(GeometryInfo<dim>::standard_to_real_face_line(2,f_or[3],f_fl[3],f_ro[3])), //9
- hex->face(3)->isotropic_child(GeometryInfo<dim>::standard_to_real_face_vertex(0,f_or[3],f_fl[3],f_ro[3]))
- ->line(GeometryInfo<dim>::standard_to_real_face_line(1,f_or[3],f_fl[3],f_ro[3])), //10
- hex->face(3)->isotropic_child(GeometryInfo<dim>::standard_to_real_face_vertex(3,f_or[3],f_fl[3],f_ro[3]))
- ->line(GeometryInfo<dim>::standard_to_real_face_line(0,f_or[3],f_fl[3],f_ro[3])), //11
-
- new_lines[0] //12
- };
-
- lines=&lines_xz[0];
-
- unsigned int line_indices_xz[13];
-
- for (unsigned int i=0; i<13; ++i)
- line_indices_xz[i]=lines[i]->index();
- line_indices=&line_indices_xz[0];
-
- // the orientation of lines for the
- // inner quads is quite tricky. as
- // these lines are newly created
- // ones and thus have no parents,
- // they cannot inherit this
- // property. set up an array and
- // fill it with the respective
- // values
- bool line_orientation_xz[13];
-
- // the middle vertices of the
- // lines of our front face
- const unsigned int middle_vertices[4]=
- {
- hex->line(8)->child(0)->vertex_index(1),
- hex->line(9)->child(0)->vertex_index(1),
- hex->line(2)->child(0)->vertex_index(1),
- hex->line(6)->child(0)->vertex_index(1),
- };
-
- // note: for lines 0 to 3 the
- // orientation of the line
- // is 'true', if vertex 0 is
- // on the front
- for (unsigned int i=0; i<4; ++i)
- if (lines[i]->vertex_index(0)==middle_vertices[i])
- line_orientation_xz[i]=true;
- else
- {
- // it must be the other way round then
- Assert(lines[i]->vertex_index(1)==middle_vertices[i],
- ExcInternalError());
- line_orientation_xz[i]=false;
- }
-
- // note: for lines 4 to 11
- // (inner lines of the outer quads)
- // the following holds: the second
- // vertex of the even lines in
- // standard orientation is the
- // vertex in the middle of the
- // quad, whereas for odd lines the
- // first vertex is the same middle
- // vertex.
- for (unsigned int i=4; i<12; ++i)
- if (lines[i]->vertex_index((i+1)%2) ==
- middle_vertex_index<dim,spacedim>(hex->face(1+i/4)))
- line_orientation_xz[i]=true;
- else
- {
- // it must be the other way
- // round then
- Assert(lines[i]->vertex_index(i%2) ==
- (middle_vertex_index<dim,spacedim>(hex->face(1+i/4))),
- ExcInternalError());
- line_orientation_xz[i]=false;
- }
- // for the last line the line
- // orientation is always true,
- // since it was just constructed
- // that way
-
- line_orientation_xz[12]=true;
- line_orientation=&line_orientation_xz[0];
-
- // set up the 4 quads,
- // numbered as follows
- // (left quad numbering,
- // right line numbering
- // extracted from above),
- // the drawings denote
- // middle planes
- //
- // * *
- // /| /|
- // / | 3 9
- // y/ * / *
- // * 3/| * /|
- // | / |x 5 12|8
- // |/ * |/ *
- // * 2/ * /
- // | / 4 2
- // |/ |/
- // * *
- //
- // y
- // *----*----* *-10-*-11-*
- // / / / / / /
- // / 0 / 1 / 0 12 1
- // / / / / / /
- // *----*----*x *--6-*--7-*
-
- new_quads[0]->set (internal::Triangulation
- ::TriaObject<2>(line_indices[0],
- line_indices[12],
- line_indices[6],
- line_indices[10]));
- new_quads[1]->set (internal::Triangulation
- ::TriaObject<2>(line_indices[12],
- line_indices[1],
- line_indices[7],
- line_indices[11]));
- new_quads[2]->set (internal::Triangulation
- ::TriaObject<2>(line_indices[4],
- line_indices[8],
- line_indices[2],
- line_indices[12]));
- new_quads[3]->set (internal::Triangulation
- ::TriaObject<2>(line_indices[5],
- line_indices[9],
- line_indices[12],
- line_indices[3]));
-
- new_quads[0]->set_line_orientation(0,line_orientation[0]);
- new_quads[0]->set_line_orientation(2,line_orientation[6]);
- new_quads[0]->set_line_orientation(3,line_orientation[10]);
-
- new_quads[1]->set_line_orientation(1,line_orientation[1]);
- new_quads[1]->set_line_orientation(2,line_orientation[7]);
- new_quads[1]->set_line_orientation(3,line_orientation[11]);
-
- new_quads[2]->set_line_orientation(0,line_orientation[4]);
- new_quads[2]->set_line_orientation(1,line_orientation[8]);
- new_quads[2]->set_line_orientation(2,line_orientation[2]);
-
- new_quads[3]->set_line_orientation(0,line_orientation[5]);
- new_quads[3]->set_line_orientation(1,line_orientation[9]);
- new_quads[3]->set_line_orientation(3,line_orientation[3]);
-
- // the quads are
- // numbered as follows:
- //
- // planes in the interior
- // of the old hex:
- // *
- // /|
- // / | x
- // /3 * *-------* *----*----*
- // * /| | | / / /
- // | / | | | / 0 / 1 /
- // |/ * | | / / /
- // * 2/ *-------*y *----*----*x
- // | /
- // |/
- // *
- //
- // children of the faces
- // of the old hex
- // *---*---* *---*---*
- // /|13 | 15| / / /|
- // / | | | /18 / 19/ |
- // / *---*---* / / / *
- // * 5/| | | *---*---* 7/|
- // | / |12 | 14| | 9 | 11| / |
- // |/4 *---*---* | | |/6 *
- // * / / / *---*---* /
- // | /16 / 17/ | | | /
- // |/ / / | 8 | 10|/
- // *---*---* *---*---*
- //
- // note that we have to
- // take care of the
- // orientation of
- // faces.
- const unsigned int quad_indices_xz[20]
- = {
- new_quads[0]->index(), //0
- new_quads[1]->index(),
- new_quads[2]->index(),
- new_quads[3]->index(),
-
- hex->face(0)->child_index( child_at_origin[hex->face(0)->refinement_case()-1][f_fl[0]][f_ro[0]]), //4
- hex->face(0)->child_index(1-child_at_origin[hex->face(0)->refinement_case()-1][f_fl[0]][f_ro[0]]),
-
- hex->face(1)->child_index( child_at_origin[hex->face(1)->refinement_case()-1][f_fl[1]][f_ro[1]]), //6
- hex->face(1)->child_index(1-child_at_origin[hex->face(1)->refinement_case()-1][f_fl[1]][f_ro[1]]),
-
- hex->face(2)->isotropic_child_index(GeometryInfo<dim>::standard_to_real_face_vertex(0,f_or[2],f_fl[2],f_ro[2])), //8
- hex->face(2)->isotropic_child_index(GeometryInfo<dim>::standard_to_real_face_vertex(1,f_or[2],f_fl[2],f_ro[2])),
- hex->face(2)->isotropic_child_index(GeometryInfo<dim>::standard_to_real_face_vertex(2,f_or[2],f_fl[2],f_ro[2])),
- hex->face(2)->isotropic_child_index(GeometryInfo<dim>::standard_to_real_face_vertex(3,f_or[2],f_fl[2],f_ro[2])),
-
- hex->face(3)->isotropic_child_index(GeometryInfo<dim>::standard_to_real_face_vertex(0,f_or[3],f_fl[3],f_ro[3])), //12
- hex->face(3)->isotropic_child_index(GeometryInfo<dim>::standard_to_real_face_vertex(1,f_or[3],f_fl[3],f_ro[3])),
- hex->face(3)->isotropic_child_index(GeometryInfo<dim>::standard_to_real_face_vertex(2,f_or[3],f_fl[3],f_ro[3])),
- hex->face(3)->isotropic_child_index(GeometryInfo<dim>::standard_to_real_face_vertex(3,f_or[3],f_fl[3],f_ro[3])),
-
- hex->face(4)->child_index( child_at_origin[hex->face(4)->refinement_case()-1][f_fl[4]][f_ro[4]]), //16
- hex->face(4)->child_index(1-child_at_origin[hex->face(4)->refinement_case()-1][f_fl[4]][f_ro[4]]),
-
- hex->face(5)->child_index( child_at_origin[hex->face(5)->refinement_case()-1][f_fl[5]][f_ro[5]]), //18
- hex->face(5)->child_index(1-child_at_origin[hex->face(5)->refinement_case()-1][f_fl[5]][f_ro[5]])
- };
- quad_indices=&quad_indices_xz[0];
-
- // due to the exchange of x
- // and y for the front and
- // back face, we order the
- // children according to
- //
- // *---*---*
- // | 1 | 3 |
- // *---*---*
- // | 0 | 2 |
- // *---*---*
- new_hexes[0]->set (internal::Triangulation
- ::TriaObject<3>(quad_indices[4],
- quad_indices[2],
- quad_indices[8],
- quad_indices[12],
- quad_indices[16],
- quad_indices[0]));
- new_hexes[1]->set (internal::Triangulation
- ::TriaObject<3>(quad_indices[5],
- quad_indices[3],
- quad_indices[9],
- quad_indices[13],
- quad_indices[0],
- quad_indices[18]));
- new_hexes[2]->set (internal::Triangulation
- ::TriaObject<3>(quad_indices[2],
- quad_indices[6],
- quad_indices[10],
- quad_indices[14],
- quad_indices[17],
- quad_indices[1]));
- new_hexes[3]->set (internal::Triangulation
- ::TriaObject<3>(quad_indices[3],
- quad_indices[7],
- quad_indices[11],
- quad_indices[15],
- quad_indices[1],
- quad_indices[19]));
- break;
- }
- case RefinementCase<dim>::cut_yz:
- {
- //////////////////////////////
- //
- // RefinementCase<dim>::cut_yz
- //
- // the refined cube will look
- // like this:
- //
- // *---------*
- // / /|
- // *---------* |
- // / /| |
- // *---------* |/|
- // | | * |
- // | |/| *
- // *---------* |/
- // | | *
- // | |/
- // *---------*
- //
-
- // first, create the new
- // internal line
- new_lines[0]->set (internal::Triangulation::
- TriaObject<1>(middle_vertex_index<dim,spacedim>(hex->face(0)),
- middle_vertex_index<dim,spacedim>(hex->face(1))));
-
- // again, first
- // collect some data
- // about the indices of
- // the lines, with the
- // following numbering:
- // (note that face 0 and
- // 1 each are shown twice
- // for better
- // readability)
-
- // face 0: left plane
- // * *
- // /| /|
- // * | * |
- // /| * /| *
- // * 5/| * |7|
- // | * | | * |
- // |/| * |6| *
- // * 4/ * |/
- // | * | *
- // |/ |/
- // * *
- // face 1: right plane
- // * *
- // /| /|
- // * | * |
- // /| * /| *
- // * 9/| * |11
- // | * | | * |
- // |/| * |10 *
- // * 8/ * |/
- // | * | *
- // |/ |/
- // * *
- // face 2: front plane
- // (note: x,y exchanged)
- // *-------*
- // | |
- // *---0---*
- // | |
- // *-------*
- // face 3: back plane
- // (note: x,y exchanged)
- // *-------*
- // | |
- // *---1---*
- // | |
- // *-------*
- // face 4: bottom plane
- // *-------*
- // / /
- // *---2---*
- // / /
- // *-------*
- // face 5: top plane
- // *-------*
- // / /
- // *---3---*
- // / /
- // *-------*
- // middle planes
- // *-------* *-------*
- // / / | |
- // *---12--* | |
- // / / | |
- // *-------* *-------*
-
- // set up a list of line iterators
- // first. from this, construct
- // lists of line_indices and
- // line orientations later on
- const typename Triangulation<dim,spacedim>::raw_line_iterator
- lines_yz[13]
- = {
- hex->face(2)->child(0)
- ->line((hex->face(2)->refinement_case() == RefinementCase<2>::cut_x) ? 1 : 3), //0
- hex->face(3)->child(0)
- ->line((hex->face(3)->refinement_case() == RefinementCase<2>::cut_x) ? 1 : 3), //1
- hex->face(4)->child(0)
- ->line((hex->face(4)->refinement_case() == RefinementCase<2>::cut_x) ? 1 : 3), //2
- hex->face(5)->child(0)
- ->line((hex->face(5)->refinement_case() == RefinementCase<2>::cut_x) ? 1 : 3), //3
-
- hex->face(0)->isotropic_child(GeometryInfo<dim>::standard_to_real_face_vertex(0,f_or[0],f_fl[0],f_ro[0]))
- ->line(GeometryInfo<dim>::standard_to_real_face_line(1,f_or[0],f_fl[0],f_ro[0])), //4
- hex->face(0)->isotropic_child(GeometryInfo<dim>::standard_to_real_face_vertex(3,f_or[0],f_fl[0],f_ro[0]))
- ->line(GeometryInfo<dim>::standard_to_real_face_line(0,f_or[0],f_fl[0],f_ro[0])), //5
- hex->face(0)->isotropic_child(GeometryInfo<dim>::standard_to_real_face_vertex(0,f_or[0],f_fl[0],f_ro[0]))
- ->line(GeometryInfo<dim>::standard_to_real_face_line(3,f_or[0],f_fl[0],f_ro[0])), //6
- hex->face(0)->isotropic_child(GeometryInfo<dim>::standard_to_real_face_vertex(3,f_or[0],f_fl[0],f_ro[0]))
- ->line(GeometryInfo<dim>::standard_to_real_face_line(2,f_or[0],f_fl[0],f_ro[0])), //7
-
- hex->face(1)->isotropic_child(GeometryInfo<dim>::standard_to_real_face_vertex(0,f_or[1],f_fl[1],f_ro[1]))
- ->line(GeometryInfo<dim>::standard_to_real_face_line(1,f_or[1],f_fl[1],f_ro[1])), //8
- hex->face(1)->isotropic_child(GeometryInfo<dim>::standard_to_real_face_vertex(3,f_or[1],f_fl[1],f_ro[1]))
- ->line(GeometryInfo<dim>::standard_to_real_face_line(0,f_or[1],f_fl[1],f_ro[1])), //9
- hex->face(1)->isotropic_child(GeometryInfo<dim>::standard_to_real_face_vertex(0,f_or[1],f_fl[1],f_ro[1]))
- ->line(GeometryInfo<dim>::standard_to_real_face_line(3,f_or[1],f_fl[1],f_ro[1])), //10
- hex->face(1)->isotropic_child(GeometryInfo<dim>::standard_to_real_face_vertex(3,f_or[1],f_fl[1],f_ro[1]))
- ->line(GeometryInfo<dim>::standard_to_real_face_line(2,f_or[1],f_fl[1],f_ro[1])), //11
-
- new_lines[0] //12
- };
-
- lines=&lines_yz[0];
-
- unsigned int line_indices_yz[13];
-
- for (unsigned int i=0; i<13; ++i)
- line_indices_yz[i]=lines[i]->index();
- line_indices=&line_indices_yz[0];
-
- // the orientation of lines for the
- // inner quads is quite tricky. as
- // these lines are newly created
- // ones and thus have no parents,
- // they cannot inherit this
- // property. set up an array and
- // fill it with the respective
- // values
- bool line_orientation_yz[13];
-
- // the middle vertices of the
- // lines of our front face
- const unsigned int middle_vertices[4]=
- {
- hex->line(8)->child(0)->vertex_index(1),
- hex->line(10)->child(0)->vertex_index(1),
- hex->line(0)->child(0)->vertex_index(1),
- hex->line(4)->child(0)->vertex_index(1),
- };
-
- // note: for lines 0 to 3 the
- // orientation of the line
- // is 'true', if vertex 0 is
- // on the front
- for (unsigned int i=0; i<4; ++i)
- if (lines[i]->vertex_index(0)==middle_vertices[i])
- line_orientation_yz[i]=true;
- else
- {
- // it must be the other way round then
- Assert(lines[i]->vertex_index(1)==middle_vertices[i],
- ExcInternalError());
- line_orientation_yz[i]=false;
- }
-
- // note: for lines 4 to 11
- // (inner lines of the outer quads)
- // the following holds: the second
- // vertex of the even lines in
- // standard orientation is the
- // vertex in the middle of the
- // quad, whereas for odd lines the
- // first vertex is the same middle
- // vertex.
- for (unsigned int i=4; i<12; ++i)
- if (lines[i]->vertex_index((i+1)%2) ==
- middle_vertex_index<dim,spacedim>(hex->face(i/4-1)))
- line_orientation_yz[i]=true;
- else
- {
- // it must be the other way
- // round then
- Assert(lines[i]->vertex_index(i%2) ==
- (middle_vertex_index<dim,spacedim>(hex->face(i/4-1))),
- ExcInternalError());
- line_orientation_yz[i]=false;
- }
- // for the last line the line
- // orientation is always true,
- // since it was just constructed
- // that way
-
- line_orientation_yz[12]=true;
- line_orientation=&line_orientation_yz[0];
-
- // set up the 4 quads,
- // numbered as follows (left
- // quad numbering, right line
- // numbering extracted from
- // above)
- //
- // x
- // *-------* *---3---*
- // | 3 | 5 9
- // *-------* *---12--*
- // | 2 | 4 8
- // *-------*y *---2---*
- //
- // y
- // *---------* *----1----*
- // / 1 / 7 11
- // *---------* *----12---*
- // / 0 / 6 10
- // *---------*x *----0----*
-
- new_quads[0]->set (internal::Triangulation
- ::TriaObject<2>(line_indices[6],
- line_indices[10],
- line_indices[0],
- line_indices[12]));
- new_quads[1]->set (internal::Triangulation
- ::TriaObject<2>(line_indices[7],
- line_indices[11],
- line_indices[12],
- line_indices[1]));
- new_quads[2]->set (internal::Triangulation
- ::TriaObject<2>(line_indices[2],
- line_indices[12],
- line_indices[4],
- line_indices[8]));
- new_quads[3]->set (internal::Triangulation
- ::TriaObject<2>(line_indices[12],
- line_indices[3],
- line_indices[5],
- line_indices[9]));
-
- new_quads[0]->set_line_orientation(0,line_orientation[6]);
- new_quads[0]->set_line_orientation(1,line_orientation[10]);
- new_quads[0]->set_line_orientation(2,line_orientation[0]);
-
- new_quads[1]->set_line_orientation(0,line_orientation[7]);
- new_quads[1]->set_line_orientation(1,line_orientation[11]);
- new_quads[1]->set_line_orientation(3,line_orientation[1]);
-
- new_quads[2]->set_line_orientation(0,line_orientation[2]);
- new_quads[2]->set_line_orientation(2,line_orientation[4]);
- new_quads[2]->set_line_orientation(3,line_orientation[8]);
-
- new_quads[3]->set_line_orientation(1,line_orientation[3]);
- new_quads[3]->set_line_orientation(2,line_orientation[5]);
- new_quads[3]->set_line_orientation(3,line_orientation[9]);
-
- // the quads are
- // numbered as follows:
- //
- // planes in the interior
- // of the old hex:
- // *
- // /|
- // / | x
- // / | *-------* *---------*
- // * | | 3 | / 1 /
- // | | *-------* *---------*
- // | * | 2 | / 0 /
- // | / *-------*y *---------*x
- // | /
- // |/
- // *
- //
- // children of the faces
- // of the old hex
- // *-------* *-------*
- // /| | / 19 /|
- // * | 15 | *-------* |
- // /|7*-------* / 18 /|11
- // * |/| | *-------* |/|
- // |6* | 14 | | 10* |
- // |/|5*-------* | 13 |/|9*
- // * |/ 17 / *-------* |/
- // |4*-------* | |8*
- // |/ 16 / | 12 |/
- // *-------* *-------*
- //
- // note that we have to
- // take care of the
- // orientation of
- // faces.
- const unsigned int quad_indices_yz[20]
- = {
- new_quads[0]->index(), //0
- new_quads[1]->index(),
- new_quads[2]->index(),
- new_quads[3]->index(),
-
- hex->face(0)->isotropic_child_index(GeometryInfo<dim>::standard_to_real_face_vertex(0,f_or[0],f_fl[0],f_ro[0])), //4
- hex->face(0)->isotropic_child_index(GeometryInfo<dim>::standard_to_real_face_vertex(1,f_or[0],f_fl[0],f_ro[0])),
- hex->face(0)->isotropic_child_index(GeometryInfo<dim>::standard_to_real_face_vertex(2,f_or[0],f_fl[0],f_ro[0])),
- hex->face(0)->isotropic_child_index(GeometryInfo<dim>::standard_to_real_face_vertex(3,f_or[0],f_fl[0],f_ro[0])),
-
- hex->face(1)->isotropic_child_index(GeometryInfo<dim>::standard_to_real_face_vertex(0,f_or[1],f_fl[1],f_ro[1])), //8
- hex->face(1)->isotropic_child_index(GeometryInfo<dim>::standard_to_real_face_vertex(1,f_or[1],f_fl[1],f_ro[1])),
- hex->face(1)->isotropic_child_index(GeometryInfo<dim>::standard_to_real_face_vertex(2,f_or[1],f_fl[1],f_ro[1])),
- hex->face(1)->isotropic_child_index(GeometryInfo<dim>::standard_to_real_face_vertex(3,f_or[1],f_fl[1],f_ro[1])),
-
- hex->face(2)->child_index( child_at_origin[hex->face(2)->refinement_case()-1][f_fl[2]][f_ro[2]]), //12
- hex->face(2)->child_index(1-child_at_origin[hex->face(2)->refinement_case()-1][f_fl[2]][f_ro[2]]),
-
- hex->face(3)->child_index( child_at_origin[hex->face(3)->refinement_case()-1][f_fl[3]][f_ro[3]]), //14
- hex->face(3)->child_index(1-child_at_origin[hex->face(3)->refinement_case()-1][f_fl[3]][f_ro[3]]),
-
- hex->face(4)->child_index( child_at_origin[hex->face(4)->refinement_case()-1][f_fl[4]][f_ro[4]]), //16
- hex->face(4)->child_index(1-child_at_origin[hex->face(4)->refinement_case()-1][f_fl[4]][f_ro[4]]),
-
- hex->face(5)->child_index( child_at_origin[hex->face(5)->refinement_case()-1][f_fl[5]][f_ro[5]]), //18
- hex->face(5)->child_index(1-child_at_origin[hex->face(5)->refinement_case()-1][f_fl[5]][f_ro[5]])
- };
- quad_indices=&quad_indices_yz[0];
-
- new_hexes[0]->set (internal::Triangulation
- ::TriaObject<3>(quad_indices[4],
- quad_indices[8],
- quad_indices[12],
- quad_indices[2],
- quad_indices[16],
- quad_indices[0]));
- new_hexes[1]->set (internal::Triangulation
- ::TriaObject<3>(quad_indices[5],
- quad_indices[9],
- quad_indices[2],
- quad_indices[14],
- quad_indices[17],
- quad_indices[1]));
- new_hexes[2]->set (internal::Triangulation
- ::TriaObject<3>(quad_indices[6],
- quad_indices[10],
- quad_indices[13],
- quad_indices[3],
- quad_indices[0],
- quad_indices[18]));
- new_hexes[3]->set (internal::Triangulation
- ::TriaObject<3>(quad_indices[7],
- quad_indices[11],
- quad_indices[3],
- quad_indices[15],
- quad_indices[1],
- quad_indices[19]));
- break;
- }
- case RefinementCase<dim>::cut_xyz:
- {
- //////////////////////////////
- //
- // RefinementCase<dim>::cut_xyz
- // isotropic refinement
- //
- // the refined cube will look
- // like this:
- //
- // *----*----*
- // / / /|
- // *----*----* |
- // / / /| *
- // *----*----* |/|
- // | | | * |
- // | | |/| *
- // *----*----* |/
- // | | | *
- // | | |/
- // *----*----*
- //
-
- // find the next unused
- // vertex and set it
- // appropriately
- while (triangulation.vertices_used[next_unused_vertex] == true)
- ++next_unused_vertex;
- Assert (next_unused_vertex < triangulation.vertices.size(),
- ExcTooFewVerticesAllocated());
- triangulation.vertices_used[next_unused_vertex] = true;
-
- // the new vertex is
- // definitely in the
- // interior, so we need not
- // worry about the boundary.
- // let it be the average of
- // the 26 vertices
- // surrounding it. weight
- // these vertices in the same
- // way as they are weighted
- // in the
- // @p{MappingQ::set_laplace_on_hex_vector}
- // function, and like the new
- // vertex at the center of
- // the quad is weighted (see
- // above)
- triangulation.vertices[next_unused_vertex] = Point<dim>();
- // first add corners of hex
- for (unsigned int vertex=0;
- vertex<GeometryInfo<dim>::vertices_per_cell; ++vertex)
- triangulation.vertices[next_unused_vertex] += hex->vertex(vertex) / 128;
- // now add center of lines
- for (unsigned int line=0;
- line<GeometryInfo<dim>::lines_per_cell; ++line)
- triangulation.vertices[next_unused_vertex] += hex->line(line)->child(0)->vertex(1) *
- 7./192.;
- // finally add centers of
- // faces. note that vertex 3
- // of child 0 is an invariant
- // with respect to the face
- // orientation, flip and
- // rotation
- for (unsigned int face=0;
- face<GeometryInfo<dim>::faces_per_cell; ++face)
- triangulation.vertices[next_unused_vertex] += hex->face(face)->isotropic_child(0)->vertex(3) *
- 1./12.;
-
- // set the data of the
- // six lines. first
- // collect the indices of
- // the seven vertices
- // (consider the two
- // planes to be crossed
- // to form the planes
- // cutting the hex in two
- // vertically and
- // horizontally)
- // *--3--* *--5--*
- // / / / | | |
- // 0--6--1 0--6--1
- // / / / | | |
- // *--2--* *--4--*
- // the lines are numbered
- // as follows:
- // *--*--* *--*--*
- // / 1 / | 5 |
- // *2-*-3* *2-*-3*
- // / 0 / | 4 |
- // *--*--* *--*--*
- //
- const unsigned int vertex_indices_xyz[7]
- = { middle_vertex_index<dim,spacedim>(hex->face(0)),
- middle_vertex_index<dim,spacedim>(hex->face(1)),
- middle_vertex_index<dim,spacedim>(hex->face(2)),
- middle_vertex_index<dim,spacedim>(hex->face(3)),
- middle_vertex_index<dim,spacedim>(hex->face(4)),
- middle_vertex_index<dim,spacedim>(hex->face(5)),
- next_unused_vertex
- };
- vertex_indices=&vertex_indices_xyz[0];
-
- new_lines[0]->set (internal::Triangulation::
- TriaObject<1>(vertex_indices[2], vertex_indices[6]));
- new_lines[1]->set (internal::Triangulation::
- TriaObject<1>(vertex_indices[6], vertex_indices[3]));
- new_lines[2]->set (internal::Triangulation::
- TriaObject<1>(vertex_indices[0], vertex_indices[6]));
- new_lines[3]->set (internal::Triangulation::
- TriaObject<1>(vertex_indices[6], vertex_indices[1]));
- new_lines[4]->set (internal::Triangulation::
- TriaObject<1>(vertex_indices[4], vertex_indices[6]));
- new_lines[5]->set (internal::Triangulation::
- TriaObject<1>(vertex_indices[6], vertex_indices[5]));
-
- // again, first
- // collect some data
- // about the indices of
- // the lines, with the
- // following numbering:
- // (note that face 0 and
- // 1 each are shown twice
- // for better
- // readability)
-
- // face 0: left plane
- // * *
- // /| /|
- // * | * |
- // /| * /| *
- // * 1/| * |3|
- // | * | | * |
- // |/| * |2| *
- // * 0/ * |/
- // | * | *
- // |/ |/
- // * *
- // face 1: right plane
- // * *
- // /| /|
- // * | * |
- // /| * /| *
- // * 5/| * |7|
- // | * | | * |
- // |/| * |6| *
- // * 4/ * |/
- // | * | *
- // |/ |/
- // * *
- // face 2: front plane
- // (note: x,y exchanged)
- // *---*---*
- // | 11 |
- // *-8-*-9-*
- // | 10 |
- // *---*---*
- // face 3: back plane
- // (note: x,y exchanged)
- // *---*---*
- // | 15 |
- // *12-*-13*
- // | 14 |
- // *---*---*
- // face 4: bottom plane
- // *---*---*
- // / 17 /
- // *18-*-19*
- // / 16 /
- // *---*---*
- // face 5: top plane
- // *---*---*
- // / 21 /
- // *22-*-23*
- // / 20 /
- // *---*---*
- // middle planes
- // *---*---* *---*---*
- // / 25 / | 29 |
- // *26-*-27* *26-*-27*
- // / 24 / | 28 |
- // *---*---* *---*---*
-
- // set up a list of line iterators
- // first. from this, construct
- // lists of line_indices and
- // line orientations later on
- const typename Triangulation<dim,spacedim>::raw_line_iterator
- lines_xyz[30]
- = {
- hex->face(0)->isotropic_child(GeometryInfo<dim>::standard_to_real_face_vertex(0,f_or[0],f_fl[0],f_ro[0]))
- ->line(GeometryInfo<dim>::standard_to_real_face_line(1,f_or[0],f_fl[0],f_ro[0])), //0
- hex->face(0)->isotropic_child(GeometryInfo<dim>::standard_to_real_face_vertex(3,f_or[0],f_fl[0],f_ro[0]))
- ->line(GeometryInfo<dim>::standard_to_real_face_line(0,f_or[0],f_fl[0],f_ro[0])), //1
- hex->face(0)->isotropic_child(GeometryInfo<dim>::standard_to_real_face_vertex(0,f_or[0],f_fl[0],f_ro[0]))
- ->line(GeometryInfo<dim>::standard_to_real_face_line(3,f_or[0],f_fl[0],f_ro[0])), //2
- hex->face(0)->isotropic_child(GeometryInfo<dim>::standard_to_real_face_vertex(3,f_or[0],f_fl[0],f_ro[0]))
- ->line(GeometryInfo<dim>::standard_to_real_face_line(2,f_or[0],f_fl[0],f_ro[0])), //3
-
- hex->face(1)->isotropic_child(GeometryInfo<dim>::standard_to_real_face_vertex(0,f_or[1],f_fl[1],f_ro[1]))
- ->line(GeometryInfo<dim>::standard_to_real_face_line(1,f_or[1],f_fl[1],f_ro[1])), //4
- hex->face(1)->isotropic_child(GeometryInfo<dim>::standard_to_real_face_vertex(3,f_or[1],f_fl[1],f_ro[1]))
- ->line(GeometryInfo<dim>::standard_to_real_face_line(0,f_or[1],f_fl[1],f_ro[1])), //5
- hex->face(1)->isotropic_child(GeometryInfo<dim>::standard_to_real_face_vertex(0,f_or[1],f_fl[1],f_ro[1]))
- ->line(GeometryInfo<dim>::standard_to_real_face_line(3,f_or[1],f_fl[1],f_ro[1])), //6
- hex->face(1)->isotropic_child(GeometryInfo<dim>::standard_to_real_face_vertex(3,f_or[1],f_fl[1],f_ro[1]))
- ->line(GeometryInfo<dim>::standard_to_real_face_line(2,f_or[1],f_fl[1],f_ro[1])), //7
-
- hex->face(2)->isotropic_child(GeometryInfo<dim>::standard_to_real_face_vertex(0,f_or[2],f_fl[2],f_ro[2]))
- ->line(GeometryInfo<dim>::standard_to_real_face_line(1,f_or[2],f_fl[2],f_ro[2])), //8
- hex->face(2)->isotropic_child(GeometryInfo<dim>::standard_to_real_face_vertex(3,f_or[2],f_fl[2],f_ro[2]))
- ->line(GeometryInfo<dim>::standard_to_real_face_line(0,f_or[2],f_fl[2],f_ro[2])), //9
- hex->face(2)->isotropic_child(GeometryInfo<dim>::standard_to_real_face_vertex(0,f_or[2],f_fl[2],f_ro[2]))
- ->line(GeometryInfo<dim>::standard_to_real_face_line(3,f_or[2],f_fl[2],f_ro[2])), //10
- hex->face(2)->isotropic_child(GeometryInfo<dim>::standard_to_real_face_vertex(3,f_or[2],f_fl[2],f_ro[2]))
- ->line(GeometryInfo<dim>::standard_to_real_face_line(2,f_or[2],f_fl[2],f_ro[2])), //11
-
- hex->face(3)->isotropic_child(GeometryInfo<dim>::standard_to_real_face_vertex(0,f_or[3],f_fl[3],f_ro[3]))
- ->line(GeometryInfo<dim>::standard_to_real_face_line(1,f_or[3],f_fl[3],f_ro[3])), //12
- hex->face(3)->isotropic_child(GeometryInfo<dim>::standard_to_real_face_vertex(3,f_or[3],f_fl[3],f_ro[3]))
- ->line(GeometryInfo<dim>::standard_to_real_face_line(0,f_or[3],f_fl[3],f_ro[3])), //13
- hex->face(3)->isotropic_child(GeometryInfo<dim>::standard_to_real_face_vertex(0,f_or[3],f_fl[3],f_ro[3]))
- ->line(GeometryInfo<dim>::standard_to_real_face_line(3,f_or[3],f_fl[3],f_ro[3])), //14
- hex->face(3)->isotropic_child(GeometryInfo<dim>::standard_to_real_face_vertex(3,f_or[3],f_fl[3],f_ro[3]))
- ->line(GeometryInfo<dim>::standard_to_real_face_line(2,f_or[3],f_fl[3],f_ro[3])), //15
-
- hex->face(4)->isotropic_child(GeometryInfo<dim>::standard_to_real_face_vertex(0,f_or[4],f_fl[4],f_ro[4]))
- ->line(GeometryInfo<dim>::standard_to_real_face_line(1,f_or[4],f_fl[4],f_ro[4])), //16
- hex->face(4)->isotropic_child(GeometryInfo<dim>::standard_to_real_face_vertex(3,f_or[4],f_fl[4],f_ro[4]))
- ->line(GeometryInfo<dim>::standard_to_real_face_line(0,f_or[4],f_fl[4],f_ro[4])), //17
- hex->face(4)->isotropic_child(GeometryInfo<dim>::standard_to_real_face_vertex(0,f_or[4],f_fl[4],f_ro[4]))
- ->line(GeometryInfo<dim>::standard_to_real_face_line(3,f_or[4],f_fl[4],f_ro[4])), //18
- hex->face(4)->isotropic_child(GeometryInfo<dim>::standard_to_real_face_vertex(3,f_or[4],f_fl[4],f_ro[4]))
- ->line(GeometryInfo<dim>::standard_to_real_face_line(2,f_or[4],f_fl[4],f_ro[4])), //19
-
- hex->face(5)->isotropic_child(GeometryInfo<dim>::standard_to_real_face_vertex(0,f_or[5],f_fl[5],f_ro[5]))
- ->line(GeometryInfo<dim>::standard_to_real_face_line(1,f_or[5],f_fl[5],f_ro[5])), //20
- hex->face(5)->isotropic_child(GeometryInfo<dim>::standard_to_real_face_vertex(3,f_or[5],f_fl[5],f_ro[5]))
- ->line(GeometryInfo<dim>::standard_to_real_face_line(0,f_or[5],f_fl[5],f_ro[5])), //21
- hex->face(5)->isotropic_child(GeometryInfo<dim>::standard_to_real_face_vertex(0,f_or[5],f_fl[5],f_ro[5]))
- ->line(GeometryInfo<dim>::standard_to_real_face_line(3,f_or[5],f_fl[5],f_ro[5])), //22
- hex->face(5)->isotropic_child(GeometryInfo<dim>::standard_to_real_face_vertex(3,f_or[5],f_fl[5],f_ro[5]))
- ->line(GeometryInfo<dim>::standard_to_real_face_line(2,f_or[5],f_fl[5],f_ro[5])), //23
-
- new_lines[0], //24
- new_lines[1], //25
- new_lines[2], //26
- new_lines[3], //27
- new_lines[4], //28
- new_lines[5] //29
- };
-
- lines=&lines_xyz[0];
-
- unsigned int line_indices_xyz[30];
- for (unsigned int i=0; i<30; ++i)
- line_indices_xyz[i]=lines[i]->index();
- line_indices=&line_indices_xyz[0];
-
- // the orientation of lines for the
- // inner quads is quite tricky. as
- // these lines are newly created
- // ones and thus have no parents,
- // they cannot inherit this
- // property. set up an array and
- // fill it with the respective
- // values
- bool line_orientation_xyz[30];
-
- // note: for the first 24 lines
- // (inner lines of the outer quads)
- // the following holds: the second
- // vertex of the even lines in
- // standard orientation is the
- // vertex in the middle of the
- // quad, whereas for odd lines the
- // first vertex is the same middle
- // vertex.
- for (unsigned int i=0; i<24; ++i)
- if (lines[i]->vertex_index((i+1)%2)==vertex_indices[i/4])
- line_orientation_xyz[i]=true;
- else
- {
- // it must be the other way
- // round then
- Assert(lines[i]->vertex_index(i%2)==vertex_indices[i/4],
- ExcInternalError());
- line_orientation_xyz[i]=false;
- }
- // for the last 6 lines the line
- // orientation is always true,
- // since they were just constructed
- // that way
- for (unsigned int i=24; i<30; ++i)
- line_orientation_xyz[i]=true;
- line_orientation=&line_orientation_xyz[0];
-
- // set up the 12 quads,
- // numbered as follows
- // (left quad numbering,
- // right line numbering
- // extracted from above)
- //
- // * *
- // /| 21|
- // * | * 15
- // y/|3* 20| *
- // * |/| * |/|
- // |2* |x 11 * 14
- // |/|1* |/| *
- // * |/ * |17
- // |0* 10 *
- // |/ |16
- // * *
- //
- // x
- // *---*---* *22-*-23*
- // | 5 | 7 | 1 29 5
- // *---*---* *26-*-27*
- // | 4 | 6 | 0 28 4
- // *---*---*y *18-*-19*
- //
- // y
- // *----*----* *-12-*-13-*
- // / 10 / 11 / 3 25 7
- // *----*----* *-26-*-27-*
- // / 8 / 9 / 2 24 6
- // *----*----*x *--8-*--9-*
-
- new_quads[0]->set (internal::Triangulation
- ::TriaObject<2>(line_indices[10],
- line_indices[28],
- line_indices[16],
- line_indices[24]));
- new_quads[1]->set (internal::Triangulation
- ::TriaObject<2>(line_indices[28],
- line_indices[14],
- line_indices[17],
- line_indices[25]));
- new_quads[2]->set (internal::Triangulation
- ::TriaObject<2>(line_indices[11],
- line_indices[29],
- line_indices[24],
- line_indices[20]));
- new_quads[3]->set (internal::Triangulation
- ::TriaObject<2>(line_indices[29],
- line_indices[15],
- line_indices[25],
- line_indices[21]));
- new_quads[4]->set (internal::Triangulation
- ::TriaObject<2>(line_indices[18],
- line_indices[26],
- line_indices[0],
- line_indices[28]));
- new_quads[5]->set (internal::Triangulation
- ::TriaObject<2>(line_indices[26],
- line_indices[22],
- line_indices[1],
- line_indices[29]));
- new_quads[6]->set (internal::Triangulation
- ::TriaObject<2>(line_indices[19],
- line_indices[27],
- line_indices[28],
- line_indices[4]));
- new_quads[7]->set (internal::Triangulation
- ::TriaObject<2>(line_indices[27],
- line_indices[23],
- line_indices[29],
- line_indices[5]));
- new_quads[8]->set (internal::Triangulation
- ::TriaObject<2>(line_indices[2],
- line_indices[24],
- line_indices[8],
- line_indices[26]));
- new_quads[9]->set (internal::Triangulation
- ::TriaObject<2>(line_indices[24],
- line_indices[6],
- line_indices[9],
- line_indices[27]));
- new_quads[10]->set (internal::Triangulation
- ::TriaObject<2>(line_indices[3],
- line_indices[25],
- line_indices[26],
- line_indices[12]));
- new_quads[11]->set (internal::Triangulation
- ::TriaObject<2>(line_indices[25],
- line_indices[7],
- line_indices[27],
- line_indices[13]));
-
- // now reset the line_orientation
- // flags of outer lines as they
- // cannot be set in a loop (at
- // least not easily)
- new_quads[0]->set_line_orientation(0,line_orientation[10]);
- new_quads[0]->set_line_orientation(2,line_orientation[16]);
-
- new_quads[1]->set_line_orientation(1,line_orientation[14]);
- new_quads[1]->set_line_orientation(2,line_orientation[17]);
-
- new_quads[2]->set_line_orientation(0,line_orientation[11]);
- new_quads[2]->set_line_orientation(3,line_orientation[20]);
-
- new_quads[3]->set_line_orientation(1,line_orientation[15]);
- new_quads[3]->set_line_orientation(3,line_orientation[21]);
-
- new_quads[4]->set_line_orientation(0,line_orientation[18]);
- new_quads[4]->set_line_orientation(2,line_orientation[0]);
-
- new_quads[5]->set_line_orientation(1,line_orientation[22]);
- new_quads[5]->set_line_orientation(2,line_orientation[1]);
-
- new_quads[6]->set_line_orientation(0,line_orientation[19]);
- new_quads[6]->set_line_orientation(3,line_orientation[4]);
-
- new_quads[7]->set_line_orientation(1,line_orientation[23]);
- new_quads[7]->set_line_orientation(3,line_orientation[5]);
-
- new_quads[8]->set_line_orientation(0,line_orientation[2]);
- new_quads[8]->set_line_orientation(2,line_orientation[8]);
-
- new_quads[9]->set_line_orientation(1,line_orientation[6]);
- new_quads[9]->set_line_orientation(2,line_orientation[9]);
-
- new_quads[10]->set_line_orientation(0,line_orientation[3]);
- new_quads[10]->set_line_orientation(3,line_orientation[12]);
-
- new_quads[11]->set_line_orientation(1,line_orientation[7]);
- new_quads[11]->set_line_orientation(3,line_orientation[13]);
-
- /////////////////////////////////
- // create the eight new hexes
- //
- // again first collect
- // some data. here, we
- // need the indices of a
- // whole lotta
- // quads.
-
- // the quads are
- // numbered as follows:
- //
- // planes in the interior
- // of the old hex:
- // *
- // /|
- // * |
- // /|3* *---*---* *----*----*
- // * |/| | 5 | 7 | / 10 / 11 /
- // |2* | *---*---* *----*----*
- // |/|1* | 4 | 6 | / 8 / 9 /
- // * |/ *---*---*y *----*----*x
- // |0*
- // |/
- // *
- //
- // children of the faces
- // of the old hex
- // *-------* *-------*
- // /|25 27| /34 35/|
- // 15| | / /19
- // / | | /32 33/ |
- // * |24 26| *-------*18 |
- // 1413*-------* |21 23| 17*
- // | /30 31/ | | /
- // 12/ / | |16
- // |/28 29/ |20 22|/
- // *-------* *-------*
- //
- // note that we have to
- // take care of the
- // orientation of
- // faces.
- const unsigned int quad_indices_xyz[36]
- = {
- new_quads[0]->index(), //0
- new_quads[1]->index(),
- new_quads[2]->index(),
- new_quads[3]->index(),
- new_quads[4]->index(),
- new_quads[5]->index(),
- new_quads[6]->index(),
- new_quads[7]->index(),
- new_quads[8]->index(),
- new_quads[9]->index(),
- new_quads[10]->index(),
- new_quads[11]->index(), //11
-
- hex->face(0)->isotropic_child_index(GeometryInfo<dim>::standard_to_real_face_vertex(0,f_or[0],f_fl[0],f_ro[0])), //12
- hex->face(0)->isotropic_child_index(GeometryInfo<dim>::standard_to_real_face_vertex(1,f_or[0],f_fl[0],f_ro[0])),
- hex->face(0)->isotropic_child_index(GeometryInfo<dim>::standard_to_real_face_vertex(2,f_or[0],f_fl[0],f_ro[0])),
- hex->face(0)->isotropic_child_index(GeometryInfo<dim>::standard_to_real_face_vertex(3,f_or[0],f_fl[0],f_ro[0])),
-
- hex->face(1)->isotropic_child_index(GeometryInfo<dim>::standard_to_real_face_vertex(0,f_or[1],f_fl[1],f_ro[1])), //16
- hex->face(1)->isotropic_child_index(GeometryInfo<dim>::standard_to_real_face_vertex(1,f_or[1],f_fl[1],f_ro[1])),
- hex->face(1)->isotropic_child_index(GeometryInfo<dim>::standard_to_real_face_vertex(2,f_or[1],f_fl[1],f_ro[1])),
- hex->face(1)->isotropic_child_index(GeometryInfo<dim>::standard_to_real_face_vertex(3,f_or[1],f_fl[1],f_ro[1])),
-
- hex->face(2)->isotropic_child_index(GeometryInfo<dim>::standard_to_real_face_vertex(0,f_or[2],f_fl[2],f_ro[2])), //20
- hex->face(2)->isotropic_child_index(GeometryInfo<dim>::standard_to_real_face_vertex(1,f_or[2],f_fl[2],f_ro[2])),
- hex->face(2)->isotropic_child_index(GeometryInfo<dim>::standard_to_real_face_vertex(2,f_or[2],f_fl[2],f_ro[2])),
- hex->face(2)->isotropic_child_index(GeometryInfo<dim>::standard_to_real_face_vertex(3,f_or[2],f_fl[2],f_ro[2])),
-
- hex->face(3)->isotropic_child_index(GeometryInfo<dim>::standard_to_real_face_vertex(0,f_or[3],f_fl[3],f_ro[3])), //24
- hex->face(3)->isotropic_child_index(GeometryInfo<dim>::standard_to_real_face_vertex(1,f_or[3],f_fl[3],f_ro[3])),
- hex->face(3)->isotropic_child_index(GeometryInfo<dim>::standard_to_real_face_vertex(2,f_or[3],f_fl[3],f_ro[3])),
- hex->face(3)->isotropic_child_index(GeometryInfo<dim>::standard_to_real_face_vertex(3,f_or[3],f_fl[3],f_ro[3])),
-
- hex->face(4)->isotropic_child_index(GeometryInfo<dim>::standard_to_real_face_vertex(0,f_or[4],f_fl[4],f_ro[4])), //28
- hex->face(4)->isotropic_child_index(GeometryInfo<dim>::standard_to_real_face_vertex(1,f_or[4],f_fl[4],f_ro[4])),
- hex->face(4)->isotropic_child_index(GeometryInfo<dim>::standard_to_real_face_vertex(2,f_or[4],f_fl[4],f_ro[4])),
- hex->face(4)->isotropic_child_index(GeometryInfo<dim>::standard_to_real_face_vertex(3,f_or[4],f_fl[4],f_ro[4])),
-
- hex->face(5)->isotropic_child_index(GeometryInfo<dim>::standard_to_real_face_vertex(0,f_or[5],f_fl[5],f_ro[5])), //32
- hex->face(5)->isotropic_child_index(GeometryInfo<dim>::standard_to_real_face_vertex(1,f_or[5],f_fl[5],f_ro[5])),
- hex->face(5)->isotropic_child_index(GeometryInfo<dim>::standard_to_real_face_vertex(2,f_or[5],f_fl[5],f_ro[5])),
- hex->face(5)->isotropic_child_index(GeometryInfo<dim>::standard_to_real_face_vertex(3,f_or[5],f_fl[5],f_ro[5]))
- };
- quad_indices=&quad_indices_xyz[0];
-
- // bottom children
- new_hexes[0]->set (internal::Triangulation
- ::TriaObject<3>(quad_indices[12],
- quad_indices[0],
- quad_indices[20],
- quad_indices[4],
- quad_indices[28],
- quad_indices[8]));
- new_hexes[1]->set (internal::Triangulation
- ::TriaObject<3>(quad_indices[0],
- quad_indices[16],
- quad_indices[22],
- quad_indices[6],
- quad_indices[29],
- quad_indices[9]));
- new_hexes[2]->set (internal::Triangulation
- ::TriaObject<3>(quad_indices[13],
- quad_indices[1],
- quad_indices[4],
- quad_indices[24],
- quad_indices[30],
- quad_indices[10]));
- new_hexes[3]->set (internal::Triangulation
- ::TriaObject<3>(quad_indices[1],
- quad_indices[17],
- quad_indices[6],
- quad_indices[26],
- quad_indices[31],
- quad_indices[11]));
-
- // top children
- new_hexes[4]->set (internal::Triangulation
- ::TriaObject<3>(quad_indices[14],
- quad_indices[2],
- quad_indices[21],
- quad_indices[5],
- quad_indices[8],
- quad_indices[32]));
- new_hexes[5]->set (internal::Triangulation
- ::TriaObject<3>(quad_indices[2],
- quad_indices[18],
- quad_indices[23],
- quad_indices[7],
- quad_indices[9],
- quad_indices[33]));
- new_hexes[6]->set (internal::Triangulation
- ::TriaObject<3>(quad_indices[15],
- quad_indices[3],
- quad_indices[5],
- quad_indices[25],
- quad_indices[10],
- quad_indices[34]));
- new_hexes[7]->set (internal::Triangulation
- ::TriaObject<3>(quad_indices[3],
- quad_indices[19],
- quad_indices[7],
- quad_indices[27],
- quad_indices[11],
- quad_indices[35]));
- break;
- }
- default:
- // all refinement cases
- // have been treated,
- // there only remains
- // RefinementCase<dim>::no_refinement
- // as untreated
- // enumeration
- // value. However, in
- // that case we should
- // have aborted much
- // earlier. thus we
- // should never get here
- Assert(false, ExcInternalError());
- break;
- }//switch (ref_case)
-
- // and set face orientation
- // flags. note that new faces in
- // the interior of the mother cell
- // always have a correctly oriented
- // face, but the ones on the outer
- // faces will inherit this flag
- //
- // the flag have been set to true
- // for all faces initially, now go
- // the other way round and reset
- // faces that are at the boundary
- // of the mother cube
- //
- // the same is true for the
- // face_flip and face_rotation
- // flags. however, the latter two
- // are set to false by default as
- // this is the standard value
-
- // loop over all faces and all
- // (relevant) subfaces of that in
- // order to set the correct values
- // for face_orientation, face_flip
- // and face_rotation, which are
- // inherited from the corresponding
- // face of the mother cube
- for (unsigned int f=0; f<GeometryInfo<dim>::faces_per_cell; ++f)
- for (unsigned int s=0;
- s<std::max(GeometryInfo<dim-1>::n_children(GeometryInfo<dim>::face_refinement_case(ref_case,f)),
- 1U);
- ++s)
- {
- const unsigned int current_child
- =GeometryInfo<dim>::child_cell_on_face(ref_case,
- f,
- s,
- f_or[f],
- f_fl[f],
- f_ro[f],
- GeometryInfo<dim>::face_refinement_case(ref_case,
- f,
- f_or[f],
- f_fl[f],
- f_ro[f]));
- new_hexes[current_child]->set_face_orientation (f, f_or[f]);
- new_hexes[current_child]->set_face_flip (f, f_fl[f]);
- new_hexes[current_child]->set_face_rotation (f, f_ro[f]);
- }
-
- // now see if
- // we have
- // created
- // cells that
- // are
- // distorted
- // and if so
- // add them to
- // our list
- if ((check_for_distorted_cells == true)
- &&
- has_distorted_children (hex,
- internal::int2type<dim>(),
- internal::int2type<spacedim>()))
- cells_with_distorted_children.distorted_cells.push_back (hex);
-
- // note that the
- // refinement flag was
- // already cleared at the
- // beginning of this loop
- }
- }
-
- // clear user data on quads. we used some of
- // this data to indicate anisotropic
- // refinemnt cases on faces. all data should
- // be cleared by now, but the information
- // whether we used indices or pointers is
- // still present. reset it now to enable the
- // user to use whichever he likes later on.
- triangulation.faces->quads.clear_user_data();
-
- // return the list with distorted children
- return cells_with_distorted_children;
- }
-
-
- /**
- * At the boundary of the domain, the new
- * point on the face may be far inside the
- * current cell, if the boundary has a
- * strong curvature. If we allow anisotropic
- * refinement here, the resulting cell may
- * be strongly distorted. To prevent this,
- * this function flags such cells for
- * isotropic refinement. It is called
- * automatically from
- * prepare_coarsening_and_refinement().
- *
- * This function does nothing in
- * 1d (therefore the
- * specialization).
- */
- template <int spacedim>
- static
- void
- prevent_distorted_boundary_cells (const Triangulation<1,spacedim> &);
-
- template <int dim, int spacedim>
- static
- void
- prevent_distorted_boundary_cells (Triangulation<dim,spacedim> &triangulation)
- {
- for (typename Triangulation<dim,spacedim>::cell_iterator
- cell=triangulation.begin(); cell!=triangulation.end(); ++cell)
- if (cell->at_boundary() &&
- cell->refine_flag_set() &&
- cell->refine_flag_set()!=RefinementCase<dim>::isotropic_refinement)
- {
- // The cell is at the boundary
- // and it is flagged for
- // anisotropic
- // refinement. Therefore, we have
- // a closer look
- const RefinementCase<dim> ref_case=cell->refine_flag_set();
- for (unsigned int face_no=0;
- face_no<GeometryInfo<dim>::faces_per_cell;
- ++face_no)
- if (cell->face(face_no)->at_boundary())
- {
- // this is the critical
- // face at the boundary.
- if (GeometryInfo<dim>::face_refinement_case(ref_case,face_no)
- !=RefinementCase<dim-1>::isotropic_refinement)
- {
- // up to now, we do not
- // want to refine this
- // cell along the face
- // under consideration
- // here.
- const typename Triangulation<dim,spacedim>::face_iterator
- face = cell->face(face_no);
- // the new point on the
- // boundary would be
- // this one.
- const Point<spacedim> new_bound
- = triangulation.boundary[face->boundary_indicator()]
- ->get_new_point_on_face (face);
- // to check it,
- // transform to the
- // unit cell with
- // Q1Mapping
- const Point<dim> new_unit
- = StaticMappingQ1<dim,spacedim>::mapping.
- transform_real_to_unit_cell(cell,
- new_bound);
-
- // Now, we have to
- // calculate the
- // distance from the
- // face in the unit
- // cell.
-
- // take the correct
- // coordinate direction (0
- // for faces 0 and 1, 1 for
- // faces 2 and 3, 2 for faces
- // 4 and 5) and substract the
- // correct boundary value of
- // the face (0 for faces 0,
- // 2, and 4; 1 for faces 1, 3
- // and 5)
- const double dist = std::fabs(new_unit[face_no/2] - face_no%2);
- // compare this with
- // the empirical value
- // allowed. if it is
- // too big, flag the
- // face for isotropic
- // refinement
- const double allowed=0.25;
-
- if (dist>allowed)
- cell->flag_for_face_refinement(face_no);
- }//if flagged for anistropic refinement
- }//if (cell->face(face)->at_boundary())
- }//for all cells
- }
-
-
- /**
- * Some dimension dependent stuff for
- * mesh smoothing.
- *
- * At present, this function does nothing
- * in 1d and 2D, but makes sure no two
- * cells with a level difference greater
- * than one share one line in 3D. This
- * is a requirement needed for the
- * interpolation of hanging nodes, since
- * otherwise to steps of interpolation
- * would be necessary. This would make
- * the processes implemented in the
- * @p ConstraintMatrix class much more
- * complex, since these two steps of
- * interpolation do not commute.
- */
- template <int dim, int spacedim>
- static
- void
- prepare_refinement_dim_dependent (const Triangulation<dim,spacedim> &)
- {
- Assert (dim < 3,
- ExcMessage ("Wrong function called -- there should "
- "be a specialization."));
- }
-
-
- template <int spacedim>
- static
- void
- prepare_refinement_dim_dependent (Triangulation<3,spacedim> &triangulation)
- {
- const unsigned int dim = 3;
-
- // first clear flags on lines,
- // since we need them to determine
- // which lines will be refined
- triangulation.clear_user_flags_line();
-
- // also clear flags on hexes, since we need
- // them to mark those cells which are to be
- // coarsened
- triangulation.clear_user_flags_hex();
-
- // variable to store whether the
- // mesh was changed in the present
- // loop and in the whole process
- bool mesh_changed = false;
-
- do
- {
- 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:
- triangulation.fix_coarsen_flags ();
-
-
- // flag those lines that are refined and
- // will not be coarsened and those that
- // will be refined
- for (typename Triangulation<dim,spacedim>::cell_iterator
- cell=triangulation.begin(); cell!=triangulation.end(); ++cell)
- if (cell->refine_flag_set())
- {
- for (unsigned int line=0; line<GeometryInfo<dim>::lines_per_cell; ++line)
- if (GeometryInfo<dim>::line_refinement_case(cell->refine_flag_set(), line)
- ==RefinementCase<1>::cut_x)
- // flag a line, that will be
- // refined
- cell->line(line)->set_user_flag();
- }
- else if(cell->has_children() && !cell->child(0)->coarsen_flag_set())
- {
- for (unsigned int line=0; line<GeometryInfo<dim>::lines_per_cell; ++line)
- if (GeometryInfo<dim>::line_refinement_case(cell->refinement_case(), line)
- ==RefinementCase<1>::cut_x)
- // flag a line, that is refined
- // and will stay so
- cell->line(line)->set_user_flag();
- }
- else if(cell->has_children() && cell->child(0)->coarsen_flag_set())
- cell->set_user_flag();
-
-
- // now check whether there are
- // cells with lines that are
- // more than once refined or
- // that will be more than once
- // refined. The first thing
- // should never be the case, in
- // the second case we flag the
- // cell for refinement
- for (typename Triangulation<dim,spacedim>::active_cell_iterator
- cell=triangulation.last_active(); cell!=triangulation.end(); --cell)
- for (unsigned int line=0; line<GeometryInfo<dim>::lines_per_cell; ++line)
- {
- if (cell->line(line)->has_children())
- {
- // if this line is
- // refined, its
- // children should
- // not have further
- // children
- //
- // however, if any of
- // the children is
- // flagged for
- // further
- // refinement, we
- // need to refine
- // this cell also (at
- // least, if the cell
- // is not already
- // flagged)
- bool offending_line_found = false;
-
- for (unsigned int c=0; c<2; ++c)
- {
- Assert (cell->line(line)->child(c)->has_children() == false,
- ExcInternalError());
-
- if (cell->line(line)->child(c)->user_flag_set () &&
- (GeometryInfo<dim>::line_refinement_case(cell->refine_flag_set(),
- line)
- ==RefinementCase<1>::no_refinement))
- {
- // tag this
- // cell for
- // refinement
- cell->clear_coarsen_flag ();
- // if anisotropic
- // coarsening is
- // allowed: extend the
- // refine_flag in the
- // needed direction,
- // else set refine_flag
- // (isotropic)
- if (triangulation.smooth_grid &
- Triangulation<dim,spacedim>::allow_anisotropic_smoothing)
- cell->flag_for_line_refinement(line);
- else
- cell->set_refine_flag();
-
- for (unsigned int l=0; l<GeometryInfo<dim>::lines_per_cell; ++l)
- if (GeometryInfo<dim>::line_refinement_case(cell->refine_flag_set(), line)
- ==RefinementCase<1>::cut_x)
- // flag a line,
- // that will be
- // refined
- cell->line(l)->set_user_flag();
- // note that
- // we have
- // changed
- // the grid
- offending_line_found = true;
-
- // it may save us several
- // loop iterations if we
- // flag all lines of
- // this cell now (and not
- // at the outset of the
- // next iteration) for
- // refinement
- for (unsigned int line=0;
- line<GeometryInfo<dim>::lines_per_cell; ++line)
- if (!cell->line(line)->has_children() &&
- (GeometryInfo<dim>::line_refinement_case(cell->refine_flag_set(),
- line)
- !=RefinementCase<1>::no_refinement))
- cell->line(line)->set_user_flag();
-
- break;
- }
- }
-
- if (offending_line_found)
- {
- mesh_changed = true;
- break;
- }
- }
- }
-
-
- // there is another thing here:
- // if any of the lines will be
- // refined, then we may not
- // coarsen the present cell
- // 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
- for (typename Triangulation<dim,spacedim>::cell_iterator
- cell=triangulation.last(); cell!=triangulation.end(); --cell)
- {
- if (cell->user_flag_set())
- for (unsigned int line=0; line<GeometryInfo<dim>::lines_per_cell; ++line)
- if (cell->line(line)->has_children() &&
- (cell->line(line)->child(0)->user_flag_set() ||
- cell->line(line)->child(1)->user_flag_set()))
- {
- for (unsigned int c=0; c<cell->n_children(); ++c)
- cell->child(c)->clear_coarsen_flag ();
- cell->clear_user_flag();
- for (unsigned int l=0; l<GeometryInfo<dim>::lines_per_cell; ++l)
- if (GeometryInfo<dim>::line_refinement_case(cell->refinement_case(), l)
- ==RefinementCase<1>::cut_x)
- // flag a line, that is refined
- // and will stay so
- cell->line(l)->set_user_flag();
- mesh_changed = true;
- break;
- }
- }
- }
- while (mesh_changed == true);
- }
-
-
-
- /**
- * Helper function for
- * @p fix_coarsen_flags. Return wether
- * coarsening of this cell is allowed.
- * Coarsening can be forbidden if the
- * neighboring cells are or will be
- * refined twice along the common face.
- */
- template <int dim, int spacedim>
- static
- bool
- coarsening_allowed (const typename Triangulation<dim,spacedim>::cell_iterator& cell)
- {
- // in 1d, coarsening is
- // always allowed since we
- // don't enforce the 2:1
- // constraint there
- if (dim == 1)
- return true;
-
- const RefinementCase<dim> ref_case = cell->refinement_case();
- for (unsigned int n=0; n<GeometryInfo<dim>::faces_per_cell; ++n)
- {
- // if the cell is not refined
- // along that face, coarsening
- // will not change anything, so
- // do nothing. the same applies,
- // if the face is at the boandary
- const RefinementCase<dim-1> face_ref_case =
- GeometryInfo<dim>::face_refinement_case(cell->refinement_case(), n);
-
- const unsigned int n_subfaces
- = GeometryInfo<dim-1>::n_children(face_ref_case);
-
- if (n_subfaces == 0 || cell->at_boundary(n))
- continue;
- for (unsigned int c=0; c<n_subfaces; ++c)
- {
- const typename Triangulation<dim,spacedim>::cell_iterator
- child = cell->child(GeometryInfo<dim>::
- child_cell_on_face(ref_case,
- n,c));
-
- const typename Triangulation<dim,spacedim>::cell_iterator
- child_neighbor = child->neighbor(n);
- if (!child->neighbor_is_coarser(n))
- // in 2d, if the child's neighbor
- // is coarser, then it has no
- // children. however, in 3d it
- // might be otherwise. consider
- // for example, that our face
- // might be refined with cut_x,
- // but the neighbor is refined
- // with cut_xy at that face. then
- // the neighbor pointers of the
- // children of our cell will point
- // to the common neighbor cell,
- // not to its children. what we
- // really want to know in the
- // following is, wether the
- // neighbor cell is refined twice
- // with reference to our cell.
- // that only has to be asked, if
- // the child's neighbor is not a
- // coarser one.
- if ((child_neighbor->has_children() &&
- !child_neighbor->user_flag_set())||
- // neighbor has children, which
- // are further refined along
- // the face, otherwise
- // something went wrong in the
- // contruction of neighbor
- // pointers. then only allow
- // coarsening if this neighbor
- // will be coarsened as well
- // (user_pointer is set). the
- // same applies, if the
- // neighbors children are not
- // refined but will be after
- // refinement
- child_neighbor->refine_flag_set())
- return false;
- }
- }
- return true;
- }
- };
- }
-}
-
-
-template <int dim, int spacedim>
-const StraightBoundary<dim,spacedim>
-Triangulation<dim, spacedim>::straight_boundary = StraightBoundary<dim,spacedim>();
-
-
-
-template <int dim, int spacedim>
-const unsigned int
-Triangulation<dim, spacedim>::dimension;
-
-
-
-template <int dim, int spacedim>
-Triangulation<dim, spacedim>::
-Triangulation (const MeshSmoothing smooth_grid,
- const bool check_for_distorted_cells)
- :
- smooth_grid(smooth_grid),
- faces(NULL),
- anisotropic_refinement(false),
- check_for_distorted_cells(check_for_distorted_cells)
-{
- // set default boundary for all
- // possible components
- for (unsigned int i=0;i<255;++i)
- boundary[i] = &straight_boundary;
-}
-
-
-template <int dim, int spacedim>
-Triangulation<dim, spacedim>::
-Triangulation (const Triangulation<dim, spacedim> &)
- // do not set any subscriptors;
- // anyway, calling this constructor
- // is an error!
- :
- Subscriptor(),
- check_for_distorted_cells(check_for_distorted_cells)
-{
- Assert (false, ExcInternalError());
-}
-
-
-
-template <int dim, int spacedim>
-Triangulation<dim, spacedim>::~Triangulation ()
-{
- for (unsigned int i=0; i<levels.size(); ++i)
- delete levels[i];
- levels.clear ();
- delete faces;
-}
-
-
-
-template <int dim, int spacedim>
-void Triangulation<dim, spacedim>::clear ()
-{
- clear_despite_subscriptions();
-}
-
-
-
-template <int dim, int spacedim>
-void
-Triangulation<dim, spacedim>::set_mesh_smoothing(const MeshSmoothing mesh_smoothing)
-{
- Assert (n_levels() == 0, ExcTriangulationNotEmpty ());
- smooth_grid=mesh_smoothing;
-}
-
-
-
-template <int dim, int spacedim>
-void
-Triangulation<dim, spacedim>::set_boundary (const unsigned int number,
- const Boundary<dim, spacedim>& boundary_object)
-{
- Assert(number<255, ExcIndexRange(number,0,255));
-
- boundary[number] = &boundary_object;
-}
-
-
-
-template <int dim, int spacedim>
-void
-Triangulation<dim, spacedim>::set_boundary (const unsigned int number)
-{
- set_boundary (number, straight_boundary);
-}
-
-
-
-template <int dim, int spacedim>
-const Boundary<dim, spacedim> &
-Triangulation<dim, spacedim>::get_boundary (const unsigned int number) const
-{
- Assert(number<255, ExcIndexRange(number,0,255));
-
- return *(boundary[number]);
-}
-
-
-template <int dim, int spacedim>
-std::vector<unsigned char>
-Triangulation<dim, spacedim>::get_boundary_indicators () const
-{
- // in 1d, the situation is simpler:
- if (dim == 1)
- return std::vector<unsigned char> (0);;
-
- std::vector<bool> bi_exists(255, false);
- active_cell_iterator cell=begin_active();
- for (; cell!=end(); ++cell)
- for (unsigned int face=0; face<GeometryInfo<dim>::faces_per_cell; ++face)
- if (cell->at_boundary(face))
- bi_exists[cell->face(face)->boundary_indicator()]=true;
-
- const unsigned int n_bi=
- std::count(bi_exists.begin(), bi_exists.end(), true);
-
- std::vector<unsigned char> boundary_indicators(n_bi);
- unsigned int bi_counter=0;
- for (unsigned int i=0; i<bi_exists.size(); ++i)
- if (bi_exists[i]==true)
- boundary_indicators[bi_counter++]=i;
-
- return boundary_indicators;
-}
-
-
-
-/*-----------------------------------------------------------------*/
-
-
-template <int dim, int spacedim>
-void Triangulation<dim, spacedim>::copy_triangulation (const Triangulation<dim, spacedim> &old_tria)
-{
- Assert (vertices.size() == 0, ExcTriangulationNotEmpty());
- Assert (levels.size () == 0, ExcTriangulationNotEmpty());
- Assert (faces == NULL, ExcTriangulationNotEmpty());
-
- Assert (old_tria.levels.size() != 0, ExcInternalError());
- Assert (old_tria.vertices.size() != 0, ExcInternalError());
- Assert (dim == 1 || old_tria.faces != NULL, ExcInternalError());
-
-
- // copy normal elements
- vertices = old_tria.vertices;
- vertices_used = old_tria.vertices_used;
- anisotropic_refinement = old_tria.anisotropic_refinement;
- smooth_grid = old_tria.smooth_grid;
-
- faces = new internal::Triangulation::TriaFaces<dim>(*old_tria.faces);
-
- for (unsigned i=0;i<255;++i)
- boundary[i] = old_tria.boundary[i];
-
- levels.reserve (old_tria.levels.size());
- for (unsigned int level=0; level<old_tria.levels.size(); ++level)
- levels.push_back (new internal::Triangulation::TriaLevel<dim>(*old_tria.levels[level]));
-
- number_cache = old_tria.number_cache;
-
- // inform RefinementListeners of old_tria of
- // the copy operation
- typename std::list<RefinementListener *>::iterator ref_listener =
- old_tria.refinement_listeners.begin (),
- end_listener = old_tria.refinement_listeners.end ();
- for (; ref_listener != end_listener; ++ref_listener)
- (*ref_listener)->copy_notification (old_tria, *this);
-
- // note that we need not copy the
- // subscriptor!
-}
-
-
-
-template <int dim, int spacedim>
-void
-Triangulation<dim,spacedim>::
-create_triangulation_compatibility (const std::vector<Point<spacedim> > &v,
- const std::vector<CellData<dim> > &cells,
- const SubCellData &subcelldata)
-{
- std::vector<CellData<dim> > reordered_cells (cells);
- SubCellData reordered_subcelldata (subcelldata);
-
- // in-place reordering of data
- reorder_compatibility (reordered_cells, reordered_subcelldata);
-
- // now create triangulation from
- // reordered data
- create_triangulation(v, reordered_cells, reordered_subcelldata);
-}
-
-
-template <int dim, int spacedim>
-void
-Triangulation<dim,spacedim>::
-create_triangulation (const std::vector<Point<spacedim> > &v,
- const std::vector<CellData<dim> > &cells,
- const SubCellData &subcelldata)
-{
- Assert (vertices.size() == 0, ExcTriangulationNotEmpty());
- Assert (levels.size() == 0, ExcTriangulationNotEmpty());
- Assert (faces == NULL, ExcTriangulationNotEmpty());
- // check that no forbidden arrays
- // are used
- Assert (subcelldata.check_consistency(dim), ExcInternalError());
-
- // try to create a triangulation;
- // if this fails, we still want to
- // throw an exception but if we
- // just do so we'll get into
- // trouble because sometimes other
- // objects are already attached to
- // it:
- try
- {
- internal::Triangulation::Implementation::create_triangulation (v, cells, subcelldata, *this);
- }
- catch (...)
- {
- clear_despite_subscriptions();
- throw;
- }
-
- compute_number_cache (*this, levels.size(), number_cache);
-
- // now verify that there are indeed
- // no distorted cells. as per the
- // documentation of this class, we
- // first collect all distorted
- // cells and then throw an
- // exception if there are any
- if (check_for_distorted_cells == true)
- {
- DistortedCellList distorted_cells = collect_distorted_coarse_cells (*this);
- // throw the array (and fill the
- // various location fields) if
- // there are distorted
- // cells. otherwise, just fall off
- // the end of the function
- AssertThrow (distorted_cells.distorted_cells.size() == 0,
- distorted_cells);
- }
-}
-
-
-
-template <int dim, int spacedim>
-void Triangulation<dim, spacedim>::distort_random (const double factor,
- const bool keep_boundary)
-{
- internal::Triangulation::Implementation::distort_random (factor, keep_boundary, *this);
-}
-
-
-
-template <int dim, int spacedim>
-void Triangulation<dim, spacedim>::set_all_refine_flags ()
-{
- active_cell_iterator cell = begin_active(),
- endc = end();
-
- for (; cell != endc; ++cell)
- {
- cell->clear_coarsen_flag();
- cell->set_refine_flag ();
- }
-}
-
-
-
-template <int dim, int spacedim>
-void Triangulation<dim, spacedim>::refine_global (const unsigned int times)
-{
- for (unsigned int i=0; i<times; ++i)
- {
- set_all_refine_flags();
- execute_coarsening_and_refinement ();
- }
-}
-
-
-
-/*-------------------- refine/coarsen flags -------------------------*/
-
-
-
-template <int dim, int spacedim>
-void Triangulation<dim, spacedim>::save_refine_flags (std::vector<bool> &v) const
-{
- v.resize (dim*n_active_cells(), false);
- std::vector<bool>::iterator i = v.begin();
- active_cell_iterator cell = begin_active(),
- endc = end();
- for (; cell!=endc; ++cell)
- for (unsigned int j=0; j<dim; ++j,++i)
- if (cell->refine_flag_set() & (1<<j) )
- *i = true;
-
- Assert (i == v.end(), ExcInternalError());
-}
-
-
-
-template <int dim, int spacedim>
-void Triangulation<dim, spacedim>::save_refine_flags (std::ostream &out) const
-{
- std::vector<bool> v;
- save_refine_flags (v);
- write_bool_vector (mn_tria_refine_flags_begin, v, mn_tria_refine_flags_end,
- out);
-}
-
-
-
-template <int dim, int spacedim>
-void Triangulation<dim, spacedim>::load_refine_flags (std::istream &in)
-{
- std::vector<bool> v;
- read_bool_vector (mn_tria_refine_flags_begin, v, mn_tria_refine_flags_end,
- in);
- load_refine_flags (v);
-}
-
-
-
-template <int dim, int spacedim>
-void Triangulation<dim, spacedim>::load_refine_flags (const std::vector<bool> &v)
-{
- AssertThrow (v.size() == dim*n_active_cells(), ExcGridReadError());
-
- active_cell_iterator cell = begin_active(),
- endc = end();
- std::vector<bool>::const_iterator i = v.begin();
- for (; cell!=endc; ++cell)
- {
- unsigned int ref_case=0;
-
- for(unsigned int j=0; j<dim; ++j, ++i)
- if (*i == true)
- ref_case+=1<<j;
- Assert(ref_case<RefinementCase<dim>::isotropic_refinement+1,
- ExcGridReadError());
- if (ref_case>0)
- cell->set_refine_flag(RefinementCase<dim>(ref_case));
- else
- cell->clear_refine_flag();
- }
-
- Assert (i == v.end(), ExcInternalError());
-}
-
-
-
-template <int dim, int spacedim>
-void Triangulation<dim, spacedim>::save_coarsen_flags (std::vector<bool> &v) const
-{
- v.resize (n_active_cells(), false);
- std::vector<bool>::iterator i = v.begin();
- active_cell_iterator cell = begin_active(),
- endc = end();
- for (; cell!=endc; ++cell, ++i)
- *i = cell->coarsen_flag_set();
-
- Assert (i == v.end(), ExcInternalError());
-}
-
-
-
-template <int dim, int spacedim>
-void Triangulation<dim, spacedim>::save_coarsen_flags (std::ostream &out) const
-{
- std::vector<bool> v;
- save_coarsen_flags (v);
- write_bool_vector (mn_tria_coarsen_flags_begin, v, mn_tria_coarsen_flags_end,
- out);
-}
-
-
-
-template <int dim, int spacedim>
-void Triangulation<dim, spacedim>::load_coarsen_flags (std::istream &in)
-{
- std::vector<bool> v;
- read_bool_vector (mn_tria_coarsen_flags_begin, v, mn_tria_coarsen_flags_end,
- in);
- load_coarsen_flags (v);
-}
-
-
-
-template <int dim, int spacedim>
-void Triangulation<dim, spacedim>::load_coarsen_flags (const std::vector<bool> &v)
-{
- Assert (v.size() == n_active_cells(), ExcGridReadError());
-
- active_cell_iterator cell = begin_active(),
- endc = end();
- std::vector<bool>::const_iterator i = v.begin();
- for (; cell!=endc; ++cell, ++i)
- if (*i == true)
- cell->set_coarsen_flag();
- else
- cell->clear_coarsen_flag();
-
- Assert (i == v.end(), ExcInternalError());
-}
-
-
-template <int dim, int spacedim>
-bool Triangulation<dim,spacedim>::get_anisotropic_refinement_flag() const
-{
- return anisotropic_refinement;
-}
-
-
-
-/*-------------------- user data/flags -------------------------*/
-
-
-namespace
-{
- // clear user data of cells
- template <int dim>
- void clear_user_data (std::vector<internal::Triangulation::TriaLevel<dim>*> &levels)
- {
- for (unsigned int level=0;level<levels.size();++level)
- levels[level]->cells.clear_user_data();
- }
-
-
- // clear user data of faces
- void clear_user_data (internal::Triangulation::TriaFaces<1> *)
- {
- // nothing to do in 1d
- }
-
-
- void clear_user_data (internal::Triangulation::TriaFaces<2> *faces)
- {
- faces->lines.clear_user_data();
- }
-
-
- void clear_user_data (internal::Triangulation::TriaFaces<3> *faces)
- {
- faces->lines.clear_user_data();
- faces->quads.clear_user_data();
- }
-}
-
-
-template <int dim, int spacedim>
-void Triangulation<dim,spacedim>::clear_user_data ()
-{
- // let functions in anonymous namespace do their work
- dealii::clear_user_data (levels);
- dealii::clear_user_data (faces);
-}
-
-
-
-namespace
-{
- void clear_user_flags_line (std::vector<internal::Triangulation::TriaLevel<1>*> &levels,
- internal::Triangulation::TriaFaces<1> *)
- {
- for (unsigned int level=0; level<levels.size(); ++level)
- levels[level]->cells.clear_user_flags();
- }
-
- template <int dim>
- void clear_user_flags_line (std::vector<internal::Triangulation::TriaLevel<dim>*> &,
- internal::Triangulation::TriaFaces<dim> *faces)
- {
- faces->lines.clear_user_flags();
- }
-}
-
-
-template <int dim, int spacedim>
-void Triangulation<dim,spacedim>::clear_user_flags_line ()
-{
- dealii::clear_user_flags_line (levels, faces);
-}
-
-
-
-namespace
-{
- void clear_user_flags_quad (std::vector<internal::Triangulation::TriaLevel<1>*> &,
- internal::Triangulation::TriaFaces<1> *)
- {
- // nothing to do in 1d
- }
-
- void clear_user_flags_quad (std::vector<internal::Triangulation::TriaLevel<2>*> &levels,
- internal::Triangulation::TriaFaces<2> *)
- {
- for (unsigned int level=0; level<levels.size(); ++level)
- levels[level]->cells.clear_user_flags();
- }
-
- template <int dim>
- void clear_user_flags_quad (std::vector<internal::Triangulation::TriaLevel<dim>*> &,
- internal::Triangulation::TriaFaces<dim> *faces)
- {
- faces->quads.clear_user_flags();
- }
-}
-
-
-template <int dim, int spacedim>
-void Triangulation<dim,spacedim>::clear_user_flags_quad ()
-{
- dealii::clear_user_flags_quad (levels, faces);
-}
-
-
-
-namespace
-{
- void clear_user_flags_hex (std::vector<internal::Triangulation::TriaLevel<1>*> &,
- internal::Triangulation::TriaFaces<1> *)
- {
- // nothing to do in 1d
- }
-
-
- void clear_user_flags_hex (std::vector<internal::Triangulation::TriaLevel<2>*> &,
- internal::Triangulation::TriaFaces<2> *)
- {
- // nothing to do in 2d
- }
-
- void clear_user_flags_hex (std::vector<internal::Triangulation::TriaLevel<3>*> &levels,
- internal::Triangulation::TriaFaces<3> *)
- {
- for (unsigned int level=0; level<levels.size(); ++level)
- levels[level]->cells.clear_user_flags();
- }
-}
-
-
-template <int dim, int spacedim>
-void Triangulation<dim,spacedim>::clear_user_flags_hex ()
-{
- dealii::clear_user_flags_hex (levels, faces);
-}
-
-
-
-template <int dim, int spacedim>
-void Triangulation<dim,spacedim>::clear_user_flags ()
-{
- clear_user_flags_line ();
- clear_user_flags_quad ();
- clear_user_flags_hex ();
-}
-
-
-
-template <int dim, int spacedim>
-void Triangulation<dim,spacedim>::clear_user_pointers ()
-{
- clear_user_data();
-}
-
-
-
-
-template <int dim, int spacedim>
-void Triangulation<dim, spacedim>::save_user_flags (std::ostream &out) const
-{
- save_user_flags_line (out);
-
- if (dim>=2)
- save_user_flags_quad (out);
-
- if (dim>=3)
- save_user_flags_hex (out);
-
- if (dim >= 4)
- Assert (false, ExcNotImplemented());
-}
-
-
-
-template <int dim, int spacedim>
-void Triangulation<dim, spacedim>::save_user_flags (std::vector<bool> &v) const
-{
- // clear vector and append
- // all the stuff later on
- v.clear ();
-
- std::vector<bool> tmp;
-
- save_user_flags_line (tmp);
- v.insert (v.end(), tmp.begin(), tmp.end());
-
- if (dim >= 2)
- {
- save_user_flags_quad (tmp);
- v.insert (v.end(), tmp.begin(), tmp.end());
- }
-
- if (dim >= 3)
- {
- save_user_flags_hex (tmp);
- v.insert (v.end(), tmp.begin(), tmp.end());
- }
-
- if (dim >= 4)
- Assert (false, ExcNotImplemented());
-}
-
-
-
-template <int dim, int spacedim>
-void Triangulation<dim, spacedim>::load_user_flags (std::istream &in)
-{
- load_user_flags_line (in);
-
- if (dim>=2)
- load_user_flags_quad (in);
-
- if (dim>=3)
- load_user_flags_hex (in);
-
- if (dim >= 4)
- Assert (false, ExcNotImplemented());
-}
-
-
-
-template <int dim, int spacedim>
-void Triangulation<dim, spacedim>::load_user_flags (const std::vector<bool> &v)
-{
- Assert (v.size() == n_lines()+n_quads()+n_hexs(), ExcInternalError());
- std::vector<bool> tmp;
-
- // first extract the flags
- // belonging to lines
- tmp.insert (tmp.end(),
- v.begin(), v.begin()+n_lines());
- // and set the lines
- load_user_flags_line (tmp);
-
- if (dim >= 2)
- {
- tmp.clear ();
- tmp.insert (tmp.end(),
- v.begin()+n_lines(), v.begin()+n_lines()+n_quads());
- load_user_flags_quad (tmp);
- }
-
- if (dim >= 3)
- {
- tmp.clear();
- tmp.insert (tmp.end(),
- v.begin()+n_lines()+n_quads(), v.begin()+n_lines()+n_quads()+n_hexs());
- load_user_flags_hex (tmp);
- }
-
- if (dim >= 4)
- Assert (false, ExcNotImplemented());
-}
-
-
-
-template <int dim, int spacedim>
-void Triangulation<dim, spacedim>::save_user_flags_line (std::vector<bool> &v) const
-{
- v.resize (n_lines(), false);
- std::vector<bool>::iterator i = v.begin();
- line_iterator line = begin_line(),
- endl = end_line();
- for (; line!=endl; ++line, ++i)
- *i = line->user_flag_set();
-
- Assert (i == v.end(), ExcInternalError());
-}
-
-
-
-template <int dim, int spacedim>
-void Triangulation<dim, spacedim>::save_user_flags_line (std::ostream &out) const
-{
- std::vector<bool> v;
- save_user_flags_line (v);
- write_bool_vector (mn_tria_line_user_flags_begin, v, mn_tria_line_user_flags_end,
- out);
-}
-
-
-
-template <int dim, int spacedim>
-void Triangulation<dim, spacedim>::load_user_flags_line (std::istream &in)
-{
- std::vector<bool> v;
- read_bool_vector (mn_tria_line_user_flags_begin, v, mn_tria_line_user_flags_end,
- in);
- load_user_flags_line (v);
-}
-
-
-
-template <int dim, int spacedim>
-void Triangulation<dim, spacedim>::load_user_flags_line (const std::vector<bool> &v)
-{
- Assert (v.size() == n_lines(), ExcGridReadError());
-
- line_iterator line = begin_line(),
- endl = end_line();
- std::vector<bool>::const_iterator i = v.begin();
- for (; line!=endl; ++line, ++i)
- if (*i == true)
- line->set_user_flag();
- else
- line->clear_user_flag();
-
- Assert (i == v.end(), ExcInternalError());
-}
-
-
-namespace
-{
- template <typename Iterator>
- bool get_user_flag (const Iterator &i)
- {
- return i->user_flag_set();
- }
-
-
-
- template <int structdim, int dim, int spacedim>
- bool get_user_flag (const TriaIterator<InvalidAccessor<structdim,dim,spacedim> > &)
- {
- Assert (false, ExcInternalError());
- return false;
- }
-
-
-
- template <typename Iterator>
- void set_user_flag (const Iterator &i)
- {
- i->set_user_flag();
- }
-
-
-
- template <int structdim, int dim, int spacedim>
- void set_user_flag (const TriaIterator<InvalidAccessor<structdim,dim,spacedim> > &)
- {
- Assert (false, ExcInternalError());
- }
-
-
-
- template <typename Iterator>
- void clear_user_flag (const Iterator &i)
- {
- i->clear_user_flag();
- }
-
-
-
- template <int structdim, int dim, int spacedim>
- void clear_user_flag (const TriaIterator<InvalidAccessor<structdim,dim,spacedim> > &)
- {
- Assert (false, ExcInternalError());
- }
-}
-
-
-template <int dim, int spacedim>
-void Triangulation<dim, spacedim>::save_user_flags_quad (std::vector<bool> &v) const
-{
- v.resize (n_quads(), false);
-
- if (dim >= 2)
- {
- std::vector<bool>::iterator i = v.begin();
- quad_iterator quad = begin_quad(),
- endq = end_quad();
- for (; quad!=endq; ++quad, ++i)
- *i = get_user_flag (quad);
-
- Assert (i == v.end(), ExcInternalError());
- }
-}
-
-
-
-template <int dim, int spacedim>
-void Triangulation<dim, spacedim>::save_user_flags_quad (std::ostream &out) const
-{
- std::vector<bool> v;
- save_user_flags_quad (v);
- write_bool_vector (mn_tria_quad_user_flags_begin, v, mn_tria_quad_user_flags_end,
- out);
-}
-
-
-
-template <int dim, int spacedim>
-void Triangulation<dim, spacedim>::load_user_flags_quad (std::istream &in)
-{
- std::vector<bool> v;
- read_bool_vector (mn_tria_quad_user_flags_begin, v, mn_tria_quad_user_flags_end,
- in);
- load_user_flags_quad (v);
-}
-
-
-
-template <int dim, int spacedim>
-void Triangulation<dim, spacedim>::load_user_flags_quad (const std::vector<bool> &v)
-{
- Assert (v.size() == n_quads(), ExcGridReadError());
-
- if (dim >= 2)
- {
- quad_iterator quad = begin_quad(),
- endq = end_quad();
- std::vector<bool>::const_iterator i = v.begin();
- for (; quad!=endq; ++quad, ++i)
- if (*i == true)
- set_user_flag(quad);
- else
- clear_user_flag(quad);
-
- Assert (i == v.end(), ExcInternalError());
- }
-}
-
-
-
-template <int dim, int spacedim>
-void Triangulation<dim, spacedim>::save_user_flags_hex (std::vector<bool> &v) const
-{
- v.resize (n_hexs(), false);
-
- if (dim >= 3)
- {
- std::vector<bool>::iterator i = v.begin();
- hex_iterator hex = begin_hex(),
- endh = end_hex();
- for (; hex!=endh; ++hex, ++i)
- *i = get_user_flag (hex);
-
- Assert (i == v.end(), ExcInternalError());
- }
-}
-
-
-
-template <int dim, int spacedim>
-void Triangulation<dim, spacedim>::save_user_flags_hex (std::ostream &out) const
-{
- std::vector<bool> v;
- save_user_flags_hex (v);
- write_bool_vector (mn_tria_hex_user_flags_begin, v, mn_tria_hex_user_flags_end,
- out);
-}
-
-
-
-template <int dim, int spacedim>
-void Triangulation<dim, spacedim>::load_user_flags_hex (std::istream &in)
-{
- std::vector<bool> v;
- read_bool_vector (mn_tria_hex_user_flags_begin, v, mn_tria_hex_user_flags_end,
- in);
- load_user_flags_hex (v);
-}
-
-
-
-template <int dim, int spacedim>
-void Triangulation<dim, spacedim>::load_user_flags_hex (const std::vector<bool> &v)
-{
- Assert (v.size() == n_hexs(), ExcGridReadError());
-
- if (dim >= 3)
- {
- hex_iterator hex = begin_hex(),
- endh = end_hex();
- std::vector<bool>::const_iterator i = v.begin();
- for (; hex!=endh; ++hex, ++i)
- if (*i == true)
- set_user_flag(hex);
- else
- clear_user_flag(hex);
-
- Assert (i == v.end(), ExcInternalError());
- }
-}
-
-
-
-template <int dim, int spacedim>
-void Triangulation<dim, spacedim>::save_user_indices (std::vector<unsigned int> &v) const
-{
- // clear vector and append all the
- // stuff later on
- v.clear ();
-
- std::vector<unsigned int> tmp;
-
- save_user_indices_line (tmp);
- v.insert (v.end(), tmp.begin(), tmp.end());
-
- if (dim >= 2)
- {
- save_user_indices_quad (tmp);
- v.insert (v.end(), tmp.begin(), tmp.end());
- }
-
- if (dim >= 3)
- {
- save_user_indices_hex (tmp);
- v.insert (v.end(), tmp.begin(), tmp.end());
- }
-
- if (dim >= 4)
- Assert (false, ExcNotImplemented());
-}
-
-
-
-template <int dim, int spacedim>
-void Triangulation<dim, spacedim>::load_user_indices (const std::vector<unsigned int> &v)
-{
- Assert (v.size() == n_lines()+n_quads()+n_hexs(), ExcInternalError());
- std::vector<unsigned int> tmp;
-
- // first extract the indices
- // belonging to lines
- tmp.insert (tmp.end(),
- v.begin(), v.begin()+n_lines());
- // and set the lines
- load_user_indices_line (tmp);
-
- if (dim >= 2)
- {
- tmp.clear ();
- tmp.insert (tmp.end(),
- v.begin()+n_lines(), v.begin()+n_lines()+n_quads());
- load_user_indices_quad (tmp);
- }
-
- if (dim >= 3)
- {
- tmp.clear ();
- tmp.insert (tmp.end(),
- v.begin()+n_lines()+n_quads(), v.begin()+n_lines()+n_quads()+n_hexs());
- load_user_indices_hex (tmp);
- }
-
- if (dim >= 4)
- Assert (false, ExcNotImplemented());
-}
-
-
-
-namespace
-{
- template <typename Iterator>
- unsigned int get_user_index (const Iterator &i)
- {
- return i->user_index();
- }
-
-
-
- template <int structdim, int dim, int spacedim>
- unsigned int get_user_index (const TriaIterator<InvalidAccessor<structdim,dim,spacedim> > &)
- {
- Assert (false, ExcInternalError());
- return numbers::invalid_unsigned_int;
- }
-
-
-
- template <typename Iterator>
- void set_user_index (const Iterator &i,
- const unsigned int x)
- {
- i->set_user_index(x);
- }
-
-
-
- template <int structdim, int dim, int spacedim>
- void set_user_index (const TriaIterator<InvalidAccessor<structdim,dim,spacedim> > &,
- const unsigned int)
- {
- Assert (false, ExcInternalError());
- }
-}
-
-
-template <int dim, int spacedim>
-void Triangulation<dim, spacedim>::save_user_indices_line (std::vector<unsigned int> &v) const
-{
- v.resize (n_lines(), 0);
- std::vector<unsigned int>::iterator i = v.begin();
- line_iterator line = begin_line(),
- endl = end_line();
- for (; line!=endl; ++line, ++i)
- *i = line->user_index();
-}
-
-
-
-template <int dim, int spacedim>
-void Triangulation<dim, spacedim>::load_user_indices_line (const std::vector<unsigned int> &v)
-{
- Assert (v.size() == n_lines(), ExcGridReadError());
-
- line_iterator line = begin_line(),
- endl = end_line();
- std::vector<unsigned int>::const_iterator i = v.begin();
- for (; line!=endl; ++line, ++i)
- line->set_user_index(*i);
-}
-
-
-template <int dim, int spacedim>
-void Triangulation<dim, spacedim>::save_user_indices_quad (std::vector<unsigned int> &v) const
-{
- v.resize (n_quads(), 0);
-
- if (dim >= 2)
- {
- std::vector<unsigned int>::iterator i = v.begin();
- quad_iterator quad = begin_quad(),
- endq = end_quad();
- for (; quad!=endq; ++quad, ++i)
- *i = get_user_index(quad);
- }
-}
-
-
-
-template <int dim, int spacedim>
-void Triangulation<dim, spacedim>::load_user_indices_quad (const std::vector<unsigned int> &v)
-{
- Assert (v.size() == n_quads(), ExcGridReadError());
-
- if (dim >= 2)
- {
- quad_iterator quad = begin_quad(),
- endq = end_quad();
- std::vector<unsigned int>::const_iterator i = v.begin();
- for (; quad!=endq; ++quad, ++i)
- set_user_index(quad, *i);
- }
-}
-
-
-template <int dim, int spacedim>
-void Triangulation<dim, spacedim>::save_user_indices_hex (std::vector<unsigned int> &v) const
-{
- v.resize (n_hexs(), 0);
-
- if (dim >= 3)
- {
- std::vector<unsigned int>::iterator i = v.begin();
- hex_iterator hex = begin_hex(),
- endh = end_hex();
- for (; hex!=endh; ++hex, ++i)
- *i = get_user_index(hex);
- }
-}
-
-
-
-template <int dim, int spacedim>
-void Triangulation<dim, spacedim>::load_user_indices_hex (const std::vector<unsigned int> &v)
-{
- Assert (v.size() == n_hexs(), ExcGridReadError());
-
- if (dim >= 3)
- {
- hex_iterator hex = begin_hex(),
- endh = end_hex();
- std::vector<unsigned int>::const_iterator i = v.begin();
- for (; hex!=endh; ++hex, ++i)
- set_user_index(hex, *i);
- }
-}
-
-
-
-//---------------- user pointers ----------------------------------------//
-
-
-namespace
-{
- template <typename Iterator>
- void * get_user_pointer (const Iterator &i)
- {
- return i->user_pointer();
- }
-
-
-
- template <int structdim, int dim, int spacedim>
- void * get_user_pointer (const TriaIterator<InvalidAccessor<structdim,dim,spacedim> > &)
- {
- Assert (false, ExcInternalError());
- return 0;
- }
-
-
-
- template <typename Iterator>
- void set_user_pointer (const Iterator &i,
- void * x)
- {
- i->set_user_pointer(x);
- }
-
-
-
- template <int structdim, int dim, int spacedim>
- void set_user_pointer (const TriaIterator<InvalidAccessor<structdim,dim,spacedim> > &,
- void *)
- {
- Assert (false, ExcInternalError());
- }
-}
-
-
-template <int dim, int spacedim>
-void Triangulation<dim, spacedim>::save_user_pointers (std::vector<void *> &v) const
-{
- // clear vector and append all the
- // stuff later on
- v.clear ();
-
- std::vector<void *> tmp;
-
- save_user_pointers_line (tmp);
- v.insert (v.end(), tmp.begin(), tmp.end());
-
- if (dim >= 2)
- {
- save_user_pointers_quad (tmp);
- v.insert (v.end(), tmp.begin(), tmp.end());
- }
-
- if (dim >= 3)
- {
- save_user_pointers_hex (tmp);
- v.insert (v.end(), tmp.begin(), tmp.end());
- }
-
- if (dim >= 4)
- Assert (false, ExcNotImplemented());
-}
-
-
-
-template <int dim, int spacedim>
-void Triangulation<dim, spacedim>::load_user_pointers (const std::vector<void *> &v)
-{
- Assert (v.size() == n_lines()+n_quads()+n_hexs(), ExcInternalError());
- std::vector<void *> tmp;
-
- // first extract the pointers
- // belonging to lines
- tmp.insert (tmp.end(),
- v.begin(), v.begin()+n_lines());
- // and set the lines
- load_user_pointers_line (tmp);
-
- if (dim >= 2)
- {
- tmp.clear ();
- tmp.insert (tmp.end(),
- v.begin()+n_lines(), v.begin()+n_lines()+n_quads());
- load_user_pointers_quad (tmp);
- }
-
- if (dim >= 3)
- {
- tmp.clear ();
- tmp.insert (tmp.end(),
- v.begin()+n_lines()+n_quads(), v.begin()+n_lines()+n_quads()+n_hexs());
- load_user_pointers_hex (tmp);
- }
-
- if (dim >= 4)
- Assert (false, ExcNotImplemented());
-}
-
-
-
-template <int dim, int spacedim>
-void Triangulation<dim, spacedim>::save_user_pointers_line (std::vector<void *> &v) const
-{
- v.resize (n_lines(), 0);
- std::vector<void *>::iterator i = v.begin();
- line_iterator line = begin_line(),
- endl = end_line();
- for (; line!=endl; ++line, ++i)
- *i = line->user_pointer();
-}
-
-
-
-template <int dim, int spacedim>
-void Triangulation<dim, spacedim>::load_user_pointers_line (const std::vector<void *> &v)
-{
- Assert (v.size() == n_lines(), ExcGridReadError());
-
- line_iterator line = begin_line(),
- endl = end_line();
- std::vector<void *>::const_iterator i = v.begin();
- for (; line!=endl; ++line, ++i)
- line->set_user_pointer(*i);
-}
-
-
-
-template <int dim, int spacedim>
-void Triangulation<dim, spacedim>::save_user_pointers_quad (std::vector<void *> &v) const
-{
- v.resize (n_quads(), 0);
-
- if (dim >= 2)
- {
- std::vector<void *>::iterator i = v.begin();
- quad_iterator quad = begin_quad(),
- endq = end_quad();
- for (; quad!=endq; ++quad, ++i)
- *i = get_user_pointer(quad);
- }
-}
-
-
-
-template <int dim, int spacedim>
-void Triangulation<dim, spacedim>::load_user_pointers_quad (const std::vector<void *> &v)
-{
- Assert (v.size() == n_quads(), ExcGridReadError());
-
- if (dim >= 2)
- {
- quad_iterator quad = begin_quad(),
- endq = end_quad();
- std::vector<void *>::const_iterator i = v.begin();
- for (; quad!=endq; ++quad, ++i)
- set_user_pointer(quad, *i);
- }
-}
-
-
-template <int dim, int spacedim>
-void Triangulation<dim, spacedim>::save_user_pointers_hex (std::vector<void *> &v) const
-{
- v.resize (n_hexs(), 0);
-
- if (dim >= 3)
- {
- std::vector<void *>::iterator i = v.begin();
- hex_iterator hex = begin_hex(),
- endh = end_hex();
- for (; hex!=endh; ++hex, ++i)
- *i = get_user_pointer(hex);
- }
-}
-
-
-
-template <int dim, int spacedim>
-void Triangulation<dim, spacedim>::load_user_pointers_hex (const std::vector<void *> &v)
-{
- Assert (v.size() == n_hexs(), ExcGridReadError());
-
- if (dim >= 3)
- {
- hex_iterator hex = begin_hex(),
- endh = end_hex();
- std::vector<void *>::const_iterator i = v.begin();
- for (; hex!=endh; ++hex, ++i)
- set_user_pointer(hex, *i);
- }
-}
-
-
-
-/*------------------------ Cell iterator functions ------------------------*/
-
-
-template <int dim, int spacedim>
-typename Triangulation<dim,spacedim>::raw_cell_iterator
-Triangulation<dim,spacedim>::begin_raw (const unsigned int level) const
-{
- switch (dim)
- {
- case 1:
- return begin_raw_line (level);
- case 2:
- return begin_raw_quad (level);
- case 3:
- return begin_raw_hex (level);
- default:
- Assert (false, ExcNotImplemented());
- return raw_cell_iterator();
- }
-}
-
-
-
-template <int dim, int spacedim>
-typename Triangulation<dim,spacedim>::cell_iterator
-Triangulation<dim,spacedim>::begin (const unsigned int level) const
-{
- switch (dim)
- {
- case 1:
- return begin_line (level);
- case 2:
- return begin_quad (level);
- case 3:
- return begin_hex (level);
- default:
- Assert (false, ExcImpossibleInDim(dim));
- return cell_iterator();
- }
-}
-
-
-
-template <int dim, int spacedim>
-typename Triangulation<dim,spacedim>::active_cell_iterator
-Triangulation<dim,spacedim>::begin_active (const unsigned int level) const
-{
- switch (dim)
- {
- case 1:
- return begin_active_line (level);
- case 2:
- return begin_active_quad (level);
- case 3:
- return begin_active_hex (level);
- default:
- Assert (false, ExcNotImplemented());
- return active_cell_iterator();
- }
-}
-
-
-
-template <int dim, int spacedim>
-typename Triangulation<dim,spacedim>::raw_cell_iterator
-Triangulation<dim,spacedim>::last_raw () const
-{
- switch (dim)
- {
- case 1:
- return last_raw_line ();
- case 2:
- return last_raw_quad ();
- case 3:
- return last_raw_hex ();
- default:
- Assert (false, ExcNotImplemented());
- return raw_cell_iterator();
- }
-}
-
-
-
-template <int dim, int spacedim>
-typename Triangulation<dim,spacedim>::raw_cell_iterator
-Triangulation<dim,spacedim>::last_raw (const unsigned int level) const
-{
- switch (dim)
- {
- case 1:
- return last_raw_line (level);
- case 2:
- return last_raw_quad (level);
- case 3:
- return last_raw_hex (level);
- default:
- Assert (false, ExcNotImplemented());
- return raw_cell_iterator();
- }
-}
-
-
-
-template <int dim, int spacedim>
-typename Triangulation<dim,spacedim>::cell_iterator
-Triangulation<dim,spacedim>::last () const
-{
- switch (dim)
- {
- case 1:
- return last_line ();
- case 2:
- return last_quad ();
- case 3:
- return last_hex ();
- default:
- Assert (false, ExcNotImplemented());
- return cell_iterator();
- }
-}
-
-
-
-template <int dim, int spacedim>
-typename Triangulation<dim,spacedim>::cell_iterator
-Triangulation<dim,spacedim>::last (const unsigned int level) const
-{
- switch (dim)
- {
- case 1:
- return last_line (level);
- case 2:
- return last_quad (level);
- case 3:
- return last_hex (level);
- default:
- Assert (false, ExcNotImplemented());
- return cell_iterator();
- }
-}
-
-
-
-template <int dim, int spacedim>
-typename Triangulation<dim,spacedim>::active_cell_iterator
-Triangulation<dim,spacedim>::last_active () const
-{
- switch (dim)
- {
- case 1:
- return last_active_line ();
- case 2:
- return last_active_quad ();
- case 3:
- return last_active_hex ();
- default:
- Assert (false, ExcNotImplemented());
- return active_cell_iterator();
- }
-}
-
-
-
-template <int dim, int spacedim>
-typename Triangulation<dim,spacedim>::active_cell_iterator
-Triangulation<dim,spacedim>::last_active (const unsigned int level) const
-{
- switch (dim)
- {
- case 1:
- return last_active_line (level);
- case 2:
- return last_active_quad (level);
- case 3:
- return last_active_hex (level);
- default:
- Assert (false, ExcNotImplemented());
- return active_cell_iterator();
- }
-}
-
-
-template <int dim, int spacedim>
-typename Triangulation<dim,spacedim>::raw_cell_iterator
-Triangulation<dim,spacedim>::end () const
-{
- switch (dim)
- {
- case 1:
- return end_line();
- case 2:
- return end_quad();
- case 3:
- return end_hex();
- default:
- Assert (false, ExcImpossibleInDim(dim));
- return raw_cell_iterator();
- }
-}
-
-
-
-template <int dim, int spacedim>
-typename Triangulation<dim, spacedim>::raw_cell_iterator
-Triangulation<dim, spacedim>::end_raw (const unsigned int level) const
-{
- return (level == levels.size()-1 ?
- end() :
- begin_raw (level+1));
-}
-
-
-template <int dim, int spacedim>
-typename Triangulation<dim, spacedim>::cell_iterator
-Triangulation<dim, spacedim>::end (const unsigned int level) const
-{
- return (level == levels.size()-1 ?
- cell_iterator(end()) :
- begin (level+1));
-}
-
-
-template <int dim, int spacedim>
-typename Triangulation<dim, spacedim>::active_cell_iterator
-Triangulation<dim, spacedim>::end_active (const unsigned int level) const
-{
- return (level == levels.size()-1 ?
- active_cell_iterator(end()) :
- begin_active (level+1));
-}
-
-
-/*------------------------ Face iterator functions ------------------------*/
-
-
-template <int dim, int spacedim>
-typename Triangulation<dim,spacedim>::raw_face_iterator
-Triangulation<dim,spacedim>::begin_raw_face () const
-{
- switch (dim)
- {
- case 1:
- Assert (false, ExcImpossibleInDim(1));
- return raw_face_iterator();
- case 2:
- return begin_raw_line ();
- case 3:
- return begin_raw_quad ();
- default:
- Assert (false, ExcNotImplemented());
- return raw_face_iterator ();
- }
-}
-
-
-
-template <int dim, int spacedim>
-typename Triangulation<dim,spacedim>::face_iterator
-Triangulation<dim,spacedim>::begin_face () const
-{
- switch (dim)
- {
- case 1:
- Assert (false, ExcImpossibleInDim(1));
- return raw_face_iterator();
- case 2:
- return begin_line ();
- case 3:
- return begin_quad ();
- default:
- Assert (false, ExcNotImplemented());
- return face_iterator ();
- }
-}
-
-
-
-template <int dim, int spacedim>
-typename Triangulation<dim,spacedim>::active_face_iterator
-Triangulation<dim,spacedim>::begin_active_face () const
-{
- switch (dim)
- {
- case 1:
- Assert (false, ExcImpossibleInDim(1));
- return raw_face_iterator();
- case 2:
- return begin_active_line ();
- case 3:
- return begin_active_quad ();
- default:
- Assert (false, ExcNotImplemented());
- return active_face_iterator ();
- }
-}
-
-
-
-template <int dim, int spacedim>
-typename Triangulation<dim, spacedim>::raw_face_iterator
-Triangulation<dim, spacedim>::end_raw_face () const
-{
- return end_face();
-}
-
-
-
-template <int dim, int spacedim>
-typename Triangulation<dim,spacedim>::raw_face_iterator
-Triangulation<dim,spacedim>::end_face () const
-{
- switch (dim)
- {
- case 1:
- Assert (false, ExcImpossibleInDim(1));
- return raw_face_iterator();
- case 2:
- return end_line ();
- case 3:
- return end_quad ();
- default:
- Assert (false, ExcNotImplemented());
- return raw_face_iterator ();
- }
-}
-
-
-
-template <int dim, int spacedim>
-typename Triangulation<dim, spacedim>::active_face_iterator
-Triangulation<dim, spacedim>::end_active_face () const
-{
- return active_face_iterator(end_face());
-}
-
-
-
-
-
-template <int dim, int spacedim>
-typename Triangulation<dim,spacedim>::raw_face_iterator
-Triangulation<dim,spacedim>::last_raw_face () const
-{
- switch (dim)
- {
- case 1:
- Assert (false, ExcImpossibleInDim(1));
- return raw_face_iterator();
- case 2:
- return last_raw_line ();
- case 3:
- return last_raw_quad ();
- default:
- Assert (false, ExcNotImplemented());
- return raw_face_iterator ();
- }
-}
-
-
-
-template <int dim, int spacedim>
-typename Triangulation<dim,spacedim>::face_iterator
-Triangulation<dim,spacedim>::last_face () const
-{
- switch (dim)
- {
- case 1:
- Assert (false, ExcImpossibleInDim(1));
- return raw_face_iterator();
- case 2:
- return last_line ();
- case 3:
- return last_quad ();
- default:
- Assert (false, ExcNotImplemented());
- return raw_face_iterator ();
- }
-}
-
-
-
-template <int dim, int spacedim>
-typename Triangulation<dim,spacedim>::active_face_iterator
-Triangulation<dim,spacedim>::last_active_face () const
-{
- switch (dim)
- {
- case 1:
- Assert (false, ExcImpossibleInDim(1));
- return raw_face_iterator();
- case 2:
- return last_active_line ();
- case 3:
- return last_active_quad ();
- default:
- Assert (false, ExcNotImplemented());
- return raw_face_iterator ();
- }
-}
-
-
-/*------------------------ Line iterator functions ------------------------*/
-
-
-
-template <int dim, int spacedim>
-typename Triangulation<dim, spacedim>::raw_line_iterator
-Triangulation<dim, spacedim>::begin_raw_line (const unsigned int level) const
-{
- switch (dim)
- {
- case 1:
- Assert (level<levels.size(), ExcInvalidLevel(level));
-
- if (levels[level]->cells.cells.size() == 0)
- return end_line ();
-
- return raw_line_iterator (const_cast<Triangulation<dim,spacedim>*>(this),
- level,
- 0);
-
- default:
- Assert (level == 0, ExcFacesHaveNoLevel());
- return raw_line_iterator (const_cast<Triangulation<dim, spacedim>*>(this),
- 0,
- 0);
- }
-}
-
-
-template <int dim, int spacedim>
-typename Triangulation<dim, spacedim>::line_iterator
-Triangulation<dim, spacedim>::begin_line (const unsigned int level) const
-{
- // level is checked in begin_raw
- raw_line_iterator ri = begin_raw_line (level);
- if (ri.state() != IteratorState::valid)
- return ri;
- while (ri->used() == false)
- if ((++ri).state() != IteratorState::valid)
- return ri;
- return ri;
-}
-
-
-
-template <int dim, int spacedim>
-typename Triangulation<dim, spacedim>::active_line_iterator
-Triangulation<dim, spacedim>::begin_active_line (const unsigned int level) const
-{
- // level is checked in begin_raw
- line_iterator i = begin_line (level);
- if (i.state() != IteratorState::valid)
- return i;
- while (i->has_children())
- if ((++i).state() != IteratorState::valid)
- return i;
- return i;
-}
-
-
-
-template <int dim, int spacedim>
-typename Triangulation<dim, spacedim>::raw_line_iterator
-Triangulation<dim, spacedim>::end_line () const
-{
- return raw_line_iterator (const_cast<Triangulation<dim, spacedim>*>(this),
- -1,
- -1);
-}
-
-
-
-template <int dim, int spacedim>
-typename Triangulation<dim, spacedim>::raw_line_iterator
-Triangulation<dim, spacedim>::last_raw_line (const unsigned int level) const
-{
- switch (dim)
- {
- case 1:
- Assert (level<levels.size(), ExcInvalidLevel(level));
- Assert (levels[level]->cells.cells.size() != 0,
- ExcEmptyLevel (level));
-
- return raw_line_iterator (const_cast<Triangulation<dim,spacedim>*>(this),
- level,
- levels[level]->cells.cells.size()-1);
-
- default:
- Assert (level == 0, ExcFacesHaveNoLevel());
- return raw_line_iterator (const_cast<Triangulation<dim, spacedim>*>(this),
- 0,
- n_raw_lines()-1);
- }
-}
-
-
-
-template <int dim, int spacedim>
-typename Triangulation<dim, spacedim>::raw_line_iterator
-Triangulation<dim, spacedim>::last_raw_line () const
-{
- if (dim == 1)
- return last_raw_line (levels.size()-1);
- else
- return last_raw_line (0);
-}
-
-
-template <int dim, int spacedim>
-typename Triangulation<dim, spacedim>::line_iterator
-Triangulation<dim, spacedim>::last_line (const unsigned int level) const
-{
- // level is checked in last_raw
- raw_line_iterator ri = last_raw_line(level);
- if (ri->used()==true)
- return ri;
- while ((--ri).state() == IteratorState::valid)
- if (ri->used()==true)
- return ri;
- return ri;
-}
-
-
-template <int dim, int spacedim>
-typename Triangulation<dim, spacedim>::line_iterator
-Triangulation<dim, spacedim>::last_line () const
-{
- if (dim == 1)
- return last_line (levels.size()-1);
- else
- return last_line (0);
-}
-
-
-template <int dim, int spacedim>
-typename Triangulation<dim, spacedim>::active_line_iterator
-Triangulation<dim, spacedim>::last_active_line (const unsigned int level) const
-{
- // level is checked in last_raw
- line_iterator i = last_line(level);
- if (i->has_children()==false)
- return i;
- while ((--i).state() == IteratorState::valid)
- if (i->has_children()==false)
- return i;
- return i;
-}
-
-
-template <int dim, int spacedim>
-typename Triangulation<dim, spacedim>::active_line_iterator
-Triangulation<dim, spacedim>::last_active_line () const
-{
- if (dim == 1)
- return last_active_line (levels.size()-1);
- else
- return last_active_line (0);
-}
-
-
-template <int dim, int spacedim>
-typename Triangulation<dim, spacedim>::raw_line_iterator
-Triangulation<dim, spacedim>::end_raw_line (const unsigned int level) const
-{
- Assert (dim == 1 || level == 0, ExcFacesHaveNoLevel());
- if (dim == 1)
- return (level == levels.size()-1 ?
- end_line() :
- begin_raw_line (level+1));
- else
- return end_line();
-}
-
-
-template <int dim, int spacedim>
-typename Triangulation<dim, spacedim>::line_iterator
-Triangulation<dim, spacedim>::end_line (const unsigned int level) const
-{
- Assert (dim == 1 || level == 0, ExcFacesHaveNoLevel());
- if (dim == 1)
- return (level == levels.size()-1 ?
- line_iterator(end_line()) :
- begin_line (level+1));
- else
- return line_iterator(end_line());
-}
-
-
-template <int dim, int spacedim>
-typename Triangulation<dim, spacedim>::active_line_iterator
-Triangulation<dim, spacedim>::end_active_line (const unsigned int level) const
-{
- Assert (dim == 1 || level == 0, ExcFacesHaveNoLevel());
- if (dim == 1)
- return (level == levels.size()-1 ?
- active_line_iterator(end_line()) :
- begin_active_line (level+1));
- else
- return active_line_iterator(end_line());
-}
-
-
-
-/*------------------------ Quad iterator functions ------------------------*/
-
-
-template <int dim, int spacedim>
-typename Triangulation<dim,spacedim>::raw_quad_iterator
-Triangulation<dim,spacedim>::begin_raw_quad (const unsigned int level) const
-{
- switch (dim)
- {
- case 1:
- Assert (false, ExcImpossibleInDim(1));
- return raw_hex_iterator();
- case 2:
- {
- Assert (level<levels.size(), ExcInvalidLevel(level));
-
- if (levels[level]->cells.cells.size() == 0)
- return end_quad();
-
- return raw_quad_iterator (const_cast<Triangulation<dim,spacedim>*>(this),
- level,
- 0);
- }
-
- case 3:
- {
- Assert (level == 0, ExcFacesHaveNoLevel());
-
- return raw_quad_iterator (const_cast<Triangulation<dim,spacedim>*>(this),
- 0,
- 0);
- }
-
-
- default:
- Assert (false, ExcNotImplemented());
- return raw_hex_iterator();
- }
-}
-
-
-
-template <int dim, int spacedim>
-typename Triangulation<dim,spacedim>::quad_iterator
-Triangulation<dim,spacedim>::begin_quad (const unsigned int level) const
-{
- // level is checked in begin_raw
- raw_quad_iterator ri = begin_raw_quad (level);
- if (ri.state() != IteratorState::valid)
- return ri;
- while (ri->used() == false)
- if ((++ri).state() != IteratorState::valid)
- return ri;
- return ri;
-}
-
-
-
-template <int dim, int spacedim>
-typename Triangulation<dim,spacedim>::active_quad_iterator
-Triangulation<dim,spacedim>::begin_active_quad (const unsigned int level) const
-{
- // level is checked in begin_raw
- quad_iterator i = begin_quad (level);
- if (i.state() != IteratorState::valid)
- return i;
- while (i->has_children())
- if ((++i).state() != IteratorState::valid)
- return i;
- return i;
-}
-
-
-
-template <int dim, int spacedim>
-typename Triangulation<dim, spacedim>::raw_quad_iterator
-Triangulation<dim, spacedim>::end_raw_quad (const unsigned int level) const
-{
- Assert (dim == 2 || level == 0, ExcFacesHaveNoLevel());
- if (dim == 2)
- return (level == levels.size()-1 ?
- end_quad() :
- begin_raw_quad (level+1));
- else
- return end_quad();
-}
-
-
-
-template <int dim, int spacedim>
-typename Triangulation<dim, spacedim>::quad_iterator
-Triangulation<dim, spacedim>::end_quad (const unsigned int level) const
-{
- Assert (dim == 2 || level == 0, ExcFacesHaveNoLevel());
- if (dim == 2)
- return (level == levels.size()-1 ?
- quad_iterator(end_quad()) :
- begin_quad (level+1));
- else
- return quad_iterator(end_quad());
-}
-
-
-template <int dim, int spacedim>
-typename Triangulation<dim, spacedim>::active_quad_iterator
-Triangulation<dim, spacedim>::end_active_quad (const unsigned int level) const
-{
- Assert(dim == 2 || level == 0, ExcFacesHaveNoLevel());
- if (dim == 2)
- return (level == levels.size()-1 ?
- active_quad_iterator(end_quad()) :
- begin_active_quad (level+1));
- else
- return active_quad_iterator(end_quad());
-}
-
-
-
-template <int dim, int spacedim>
-typename Triangulation<dim,spacedim>::raw_quad_iterator
-Triangulation<dim,spacedim>::end_quad () const
-{
- return raw_quad_iterator (const_cast<Triangulation<dim, spacedim>*>(this),
- -1,
- -1);
-}
-
-
-
-template <int dim, int spacedim>
-typename Triangulation<dim,spacedim>::raw_quad_iterator
-Triangulation<dim,spacedim>::last_raw_quad (const unsigned int level) const
-{
- switch (dim)
- {
- case 1:
- Assert (false, ExcImpossibleInDim(1));
- return raw_quad_iterator();
- case 2:
- Assert (level<levels.size(),
- ExcInvalidLevel(level));
- Assert (levels[level]->cells.cells.size() != 0,
- ExcEmptyLevel (level));
- return raw_quad_iterator (const_cast<Triangulation<dim,spacedim>*>(this),
- level,
- levels[level]->cells.cells.size()-1);
- case 3:
- Assert (level == 0, ExcFacesHaveNoLevel());
- return raw_quad_iterator (const_cast<Triangulation<dim,spacedim>*>(this),
- 0,
- n_raw_quads()-1);
- default:
- Assert (false, ExcNotImplemented());
- return raw_quad_iterator();
- }
-}
-
-
-
-template <int dim, int spacedim>
-typename Triangulation<dim,spacedim>::raw_quad_iterator
-Triangulation<dim,spacedim>::last_raw_quad () const
-{
- if (dim == 2)
- return last_raw_quad (levels.size()-1);
- else
- return last_raw_quad (0);
-}
-
-
-
-template <int dim, int spacedim>
-typename Triangulation<dim,spacedim>::quad_iterator
-Triangulation<dim,spacedim>::last_quad (const unsigned int level) const
-{
- // level is checked in last_raw
- raw_quad_iterator ri = last_raw_quad(level);
- if (ri->used()==true)
- return ri;
- while ((--ri).state() == IteratorState::valid)
- if (ri->used()==true)
- return ri;
- return ri;
-}
-
-
-
-template <int dim, int spacedim>
-typename Triangulation<dim,spacedim>::quad_iterator
-Triangulation<dim,spacedim>::last_quad () const
-{
- if (dim == 2)
- return last_quad (levels.size()-1);
- else
- return last_quad (0);
-}
-
-
-
-template <int dim, int spacedim>
-typename Triangulation<dim,spacedim>::active_quad_iterator
-Triangulation<dim,spacedim>::last_active_quad (const unsigned int level) const
-{
- // level is checked in last_raw
- quad_iterator i = last_quad(level);
- if (i->has_children()==false)
- return i;
- while ((--i).state() == IteratorState::valid)
- if (i->has_children()==false)
- return i;
- return i;
-}
-
-
-
-template <int dim, int spacedim>
-typename Triangulation<dim,spacedim>::active_quad_iterator
-Triangulation<dim,spacedim>::last_active_quad () const
-{
- if (dim == 2)
- return last_active_quad (levels.size()-1);
- else
- return last_active_quad (0);
-}
-
-
-/*------------------------ Hex iterator functions ------------------------*/
-
-
-template <int dim, int spacedim>
-typename Triangulation<dim,spacedim>::raw_hex_iterator
-Triangulation<dim,spacedim>::begin_raw_hex (const unsigned int level) const
-{
- switch (dim)
- {
- case 1:
- case 2:
- Assert (false, ExcImpossibleInDim(1));
- return raw_hex_iterator();
- case 3:
- {
- Assert (level<levels.size(), ExcInvalidLevel(level));
-
- if (levels[level]->cells.cells.size() == 0)
- return end_hex();
-
- return raw_hex_iterator (const_cast<Triangulation<dim,spacedim>*>(this),
- level,
- 0);
- }
-
- default:
- Assert (false, ExcNotImplemented());
- return raw_hex_iterator();
- }
-}
-
-
-
-template <int dim, int spacedim>
-typename Triangulation<dim,spacedim>::hex_iterator
-Triangulation<dim,spacedim>::begin_hex (const unsigned int level) const
-{
- // level is checked in begin_raw
- raw_hex_iterator ri = begin_raw_hex (level);
- if (ri.state() != IteratorState::valid)
- return ri;
- while (ri->used() == false)
- if ((++ri).state() != IteratorState::valid)
- return ri;
- return ri;
-}
-
-
-
-template <int dim, int spacedim>
-typename Triangulation<dim, spacedim>::active_hex_iterator
-Triangulation<dim, spacedim>::begin_active_hex (const unsigned int level) const
-{
- // level is checked in begin_raw
- hex_iterator i = begin_hex (level);
- if (i.state() != IteratorState::valid)
- return i;
- while (i->has_children())
- if ((++i).state() != IteratorState::valid)
- return i;
- return i;
-}
-
-
-
-template <int dim, int spacedim>
-typename Triangulation<dim, spacedim>::raw_hex_iterator
-Triangulation<dim, spacedim>::end_raw_hex (const unsigned int level) const
-{
- return (level == levels.size()-1 ?
- end_hex() :
- begin_raw_hex (level+1));
-}
-
-
-template <int dim, int spacedim>
-typename Triangulation<dim, spacedim>::hex_iterator
-Triangulation<dim, spacedim>::end_hex (const unsigned int level) const
-{
- return (level == levels.size()-1 ?
- hex_iterator(end_hex()) :
- begin_hex (level+1));
-}
-
-
-template <int dim, int spacedim>
-typename Triangulation<dim, spacedim>::active_hex_iterator
-Triangulation<dim, spacedim>::end_active_hex (const unsigned int level) const
-{
- return (level == levels.size()-1 ?
- active_hex_iterator(end_hex()) :
- begin_active_hex (level+1));
-}
-
-
-
-template <int dim, int spacedim>
-typename Triangulation<dim, spacedim>::raw_hex_iterator
-Triangulation<dim, spacedim>::end_hex () const
-{
- return raw_hex_iterator (const_cast<Triangulation<dim,spacedim>*>(this),
- -1,
- -1);
-}
-
-
-
-template <int dim, int spacedim>
-typename Triangulation<dim, spacedim>::raw_hex_iterator
-Triangulation<dim, spacedim>::last_raw_hex (const unsigned int level) const
-{
- switch (dim)
- {
- case 1:
- case 2:
- Assert (false, ExcImpossibleInDim(dim));
- return raw_hex_iterator();
-
- case 3:
- Assert (level<levels.size(),
- ExcInvalidLevel(level));
- Assert (levels[level]->cells.cells.size() != 0,
- ExcEmptyLevel (level));
-
- return raw_hex_iterator (const_cast<Triangulation<dim,spacedim>*>(this),
- level,
- levels[level]->cells.cells.size()-1);
- default:
- Assert (false, ExcNotImplemented());
- return raw_hex_iterator();
- }
-}
-
-
-
-template <int dim, int spacedim>
-typename Triangulation<dim, spacedim>::raw_hex_iterator
-Triangulation<dim, spacedim>::last_raw_hex () const
-{
- return last_raw_hex (levels.size()-1);
-}
-
-
-
-template <int dim, int spacedim>
-typename Triangulation<dim, spacedim>::hex_iterator
-Triangulation<dim, spacedim>::last_hex (const unsigned int level) const
-{
- // level is checked in last_raw
- raw_hex_iterator ri = last_raw_hex(level);
- if (ri->used()==true)
- return ri;
- while ((--ri).state() == IteratorState::valid)
- if (ri->used()==true)
- return ri;
- return ri;
-}
-
-
-
-template <int dim, int spacedim>
-typename Triangulation<dim, spacedim>::hex_iterator
-Triangulation<dim, spacedim>::last_hex () const
-{
- return last_hex (levels.size()-1);
-}
-
-
-
-template <int dim, int spacedim>
-typename Triangulation<dim, spacedim>::active_hex_iterator
-Triangulation<dim, spacedim>::last_active_hex (const unsigned int level) const
-{
- // level is checked in last_raw
- hex_iterator i = last_hex(level);
- if (i->has_children()==false)
- return i;
- while ((--i).state() == IteratorState::valid)
- if (i->has_children()==false)
- return i;
- return i;
-}
-
-
-
-template <int dim, int spacedim>
-typename Triangulation<dim, spacedim>::active_hex_iterator
-Triangulation<dim, spacedim>::last_active_hex () const
-{
- return last_active_hex (levels.size()-1);
-}
-
-
-
-// -------------------------------- number of cells etc ---------------
-
-
-namespace internal
-{
- namespace Triangulation
- {
- inline
- unsigned int
- n_cells (const internal::Triangulation::NumberCache<1> &c)
- {
- return c.n_lines;
- }
-
-
- inline
- unsigned int
- n_active_cells (const internal::Triangulation::NumberCache<1> &c)
- {
- return c.n_active_lines;
- }
-
-
- inline
- unsigned int
- n_cells (const internal::Triangulation::NumberCache<2> &c)
- {
- return c.n_quads;
- }
-
-
- inline
- unsigned int
- n_active_cells (const internal::Triangulation::NumberCache<2> &c)
- {
- return c.n_active_quads;
- }
-
-
- inline
- unsigned int
- n_cells (const internal::Triangulation::NumberCache<3> &c)
- {
- return c.n_hexes;
- }
-
-
- inline
- unsigned int
- n_active_cells (const internal::Triangulation::NumberCache<3> &c)
- {
- return c.n_active_hexes;
- }
- }
-}
-
-
-
-template <int dim, int spacedim>
-unsigned int Triangulation<dim, spacedim>::n_cells () const
-{
- return internal::Triangulation::n_cells (number_cache);
-}
-
-
-template <int dim, int spacedim>
-unsigned int Triangulation<dim, spacedim>::n_active_cells () const
-{
- return internal::Triangulation::n_active_cells (number_cache);
-}
-
-
-template <int dim, int spacedim>
-unsigned int Triangulation<dim, spacedim>::n_faces () const
-{
- switch (dim)
- {
- case 1:
- return 0;
- case 2:
- return n_lines();
- case 3:
- return n_quads();
- default:
- Assert (false, ExcNotImplemented());
- }
- return 0;
-}
-
-
-template <int dim, int spacedim>
-unsigned int Triangulation<dim, spacedim>::n_raw_faces () const
-{
- switch (dim)
- {
- case 2:
- return n_raw_lines();
- case 3:
- return n_raw_quads();
- default:
- Assert (false, ExcNotImplemented());
- }
- return 0;
-}
-
-
-template <int dim, int spacedim>
-unsigned int Triangulation<dim, spacedim>::n_active_faces () const
-{
- switch (dim)
- {
- case 1:
- return 0;
- case 2:
- return n_active_lines();
- case 3:
- return n_active_quads();
- default:
- Assert (false, ExcNotImplemented());
- }
- return 0;
-}
-
-
-template <int dim, int spacedim>
-unsigned int Triangulation<dim, spacedim>::n_raw_cells (const unsigned int level) const
-{
- switch (dim)
- {
- case 1:
- return n_raw_lines(level);
- case 2:
- return n_raw_quads(level);
- case 3:
- return n_raw_hexs(level);
- default:
- Assert (false, ExcNotImplemented());
- }
- return 0;
-}
-
-
-
-template <int dim, int spacedim>
-unsigned int Triangulation<dim, spacedim>::n_cells (const unsigned int level) const
-{
- switch (dim)
- {
- case 1:
- return n_lines(level);
- case 2:
- return n_quads(level);
- case 3:
- return n_hexs(level);
- default:
- Assert (false, ExcNotImplemented());
- }
- return 0;
-}
-
-
-
-template <int dim, int spacedim>
-unsigned int Triangulation<dim, spacedim>::n_active_cells (const unsigned int level) const
-{
- switch (dim)
- {
- case 1:
- return n_active_lines(level);
- case 2:
- return n_active_quads(level);
- case 3:
- return n_active_hexs(level);
- default:
- Assert (false, ExcNotImplemented());
- }
- return 0;
-}
-
-
-
-template <int dim, int spacedim>
-unsigned int Triangulation<dim, spacedim>::n_lines () const
-{
- return number_cache.n_lines;
-}
-
-
-#if deal_II_dimension == 1
-
-
-
-template <>
-unsigned int Triangulation<1,1>::n_raw_lines (const unsigned int level) const
-{
- Assert(level < n_levels(), ExcIndexRange(level,0,n_levels()));
- return levels[level]->cells.cells.size();
-}
-
-
-template <>
-unsigned int Triangulation<1,1>::n_raw_lines () const
-{
- Assert(false, ExcNotImplemented());
- return 0;
-}
-
-
-
-template <>
-unsigned int Triangulation<1,2>::n_raw_lines (const unsigned int level) const
-{
- Assert(level < n_levels(), ExcIndexRange(level,0,n_levels()));
- return levels[level]->cells.cells.size();
-}
-
-
-template <>
-unsigned int Triangulation<1,2>::n_raw_lines () const
-{
- Assert(false, ExcNotImplemented());
- return 0;
-}
-
-#endif
-
-
-template <int dim, int spacedim>
-unsigned int Triangulation<dim, spacedim>::n_raw_lines (const unsigned int) const
-{
- Assert(false, ExcFacesHaveNoLevel());
- return 0;
-}
-
-
-template <int dim, int spacedim>
-unsigned int Triangulation<dim, spacedim>::n_raw_lines () const
-{
- return faces->lines.cells.size();
-}
-
-
-template <int dim, int spacedim>
-unsigned int Triangulation<dim, spacedim>::n_lines (const unsigned int level) const
-{
- Assert (level < number_cache.n_lines_level.size(),
- ExcIndexRange (level, 0, number_cache.n_lines_level.size()));
- Assert (dim == 1, ExcFacesHaveNoLevel());
- return number_cache.n_lines_level[level];
-}
-
-
-template <int dim, int spacedim>
-unsigned int Triangulation<dim, spacedim>::n_active_lines () const
-{
- return number_cache.n_active_lines;
-}
-
-
-template <int dim, int spacedim>
-unsigned int Triangulation<dim, spacedim>::n_active_lines (const unsigned int level) const
-{
- Assert (level < number_cache.n_lines_level.size(),
- ExcIndexRange (level, 0, number_cache.n_lines_level.size()));
- Assert (dim == 1, ExcFacesHaveNoLevel());
-
- return number_cache.n_active_lines_level[level];
-}
-
-
-#if deal_II_dimension == 1
-
-template <>
-unsigned int Triangulation<1,1>::n_quads () const
-{
- return 0;
-}
-
-
-template <>
-unsigned int Triangulation<1,1>::n_quads (const unsigned int) const
-{
- return 0;
-}
-
-
-template <>
-unsigned int Triangulation<1,1>::n_raw_quads (const unsigned int) const
-{
- return 0;
-}
-
-
-template <>
-unsigned int Triangulation<1,1>::n_raw_hexs (const unsigned int) const
-{
- return 0;
-}
-
-
-template <>
-unsigned int Triangulation<1,1>::n_active_quads (const unsigned int) const
-{
- return 0;
-}
-
-
-template <>
-unsigned int Triangulation<1,1>::n_active_quads () const
-{
- return 0;
-}
-
-
-template <>
-unsigned int Triangulation<1,2>::n_quads () const
-{
- return 0;
-}
-
-
-template <>
-unsigned int Triangulation<1,2>::n_quads (const unsigned int) const
-{
- return 0;
-}
-
-
-template <>
-unsigned int Triangulation<1,2>::n_raw_quads (const unsigned int) const
-{
- return 0;
-}
-
-
-template <>
-unsigned int Triangulation<1,2>::n_raw_hexs (const unsigned int) const
-{
- return 0;
-}
-
-
-template <>
-unsigned int Triangulation<1,2>::n_active_quads (const unsigned int) const
-{
- return 0;
-}
-
-
-template <>
-unsigned int Triangulation<1,2>::n_active_quads () const
-{
- return 0;
-}
-
-
-#endif
-
-
-template <int dim, int spacedim>
-unsigned int Triangulation<dim, spacedim>::n_quads () const
-{
- return number_cache.n_quads;
-}
-
-
-template <int dim, int spacedim>
-unsigned int Triangulation<dim, spacedim>::n_quads (const unsigned int level) const
-{
- Assert (dim == 2, ExcFacesHaveNoLevel());
- Assert (level < number_cache.n_quads_level.size(),
- ExcIndexRange (level, 0, number_cache.n_quads_level.size()));
- return number_cache.n_quads_level[level];
-}
-
-#if deal_II_dimension == 2
-
-
-template <>
-unsigned int Triangulation<2,2>::n_raw_quads (const unsigned int level) const
-{
- Assert(level < n_levels(), ExcIndexRange(level,0,n_levels()));
- return levels[level]->cells.cells.size();
-}
-
-
-
-template <>
-unsigned int Triangulation<2,3>::n_raw_quads (const unsigned int level) const
-{
- Assert(level < n_levels(), ExcIndexRange(level,0,n_levels()));
- return levels[level]->cells.cells.size();
-}
-
-#endif
-
-#if deal_II_dimension == 3
-
-template <>
-unsigned int Triangulation<3,3>::n_raw_quads (const unsigned int) const
-{
- Assert(false, ExcFacesHaveNoLevel());
- return 0;
-}
-
-#endif
-
-
-
-
-template <int dim, int spacedim>
-unsigned int Triangulation<dim, spacedim>::n_raw_quads () const
-{
- Assert (false, ExcNotImplemented());
- return 0;
-}
-
-
-#if deal_II_dimension == 3
-
-template <>
-unsigned int Triangulation<3,3>::n_raw_quads () const
-{
- return faces->quads.cells.size();
-}
-
-#endif
-
-template <int dim, int spacedim>
-unsigned int Triangulation<dim, spacedim>::n_active_quads () const
-{
- return number_cache.n_active_quads;
-}
-
-
-template <int dim, int spacedim>
-unsigned int Triangulation<dim, spacedim>::n_active_quads (const unsigned int level) const
-{
- Assert (level < number_cache.n_quads_level.size(),
- ExcIndexRange (level, 0, number_cache.n_quads_level.size()));
- Assert (dim == 2, ExcFacesHaveNoLevel());
-
- return number_cache.n_active_quads_level[level];
-}
-
-
-#if deal_II_dimension < 3
-
-template <int dim, int spacedim>
-unsigned int Triangulation<dim, spacedim>::n_hexs () const
-{
- return 0;
-}
-
-
-
-template <int dim, int spacedim>
-unsigned int Triangulation<dim, spacedim>::n_hexs (const unsigned int) const
-{
- return 0;
-}
-
-
-
-template <int dim, int spacedim>
-unsigned int Triangulation<dim, spacedim>::n_raw_hexs (const unsigned int) const
-{
- return 0;
-}
-
-
-template <int dim, int spacedim>
-unsigned int Triangulation<dim, spacedim>::n_active_hexs () const
-{
- return 0;
-}
-
-
-
-template <int dim, int spacedim>
-unsigned int Triangulation<dim, spacedim>::n_active_hexs (const unsigned int) const
-{
- return 0;
-}
-
-
-#else
-
-
-template <int dim, int spacedim>
-unsigned int Triangulation<dim, spacedim>::n_hexs () const
-{
- return number_cache.n_hexes;
-}
-
-
-
-template <int dim, int spacedim>
-unsigned int Triangulation<dim, spacedim>::n_hexs (const unsigned int level) const
-{
- Assert (level < number_cache.n_hexes_level.size(),
- ExcIndexRange (level, 0, number_cache.n_hexes_level.size()));
-
- return number_cache.n_hexes_level[level];
-}
-
-
-
-template <int dim, int spacedim>
-unsigned int Triangulation<dim, spacedim>::n_raw_hexs (const unsigned int level) const
-{
- Assert(level < n_levels(), ExcIndexRange(level,0,n_levels()));
- return levels[level]->cells.cells.size();
-}
-
-
-template <int dim, int spacedim>
-unsigned int Triangulation<dim, spacedim>::n_active_hexs () const
-{
- return number_cache.n_active_hexes;
-}
-
-
-
-template <int dim, int spacedim>
-unsigned int Triangulation<dim, spacedim>::n_active_hexs (const unsigned int level) const
-{
- Assert (level < number_cache.n_hexes_level.size(),
- ExcIndexRange (level, 0, number_cache.n_hexes_level.size()));
-
- return number_cache.n_active_hexes_level[level];
-}
-
-
-#endif
-
-
-template <int dim, int spacedim>
-unsigned int
-Triangulation<dim, spacedim>::n_used_vertices () const
-{
- return std::count_if (vertices_used.begin(), vertices_used.end(),
- std::bind2nd (std::equal_to<bool>(), true));
-}
-
-
-
-template <int dim, int spacedim>
-const std::vector<bool> &
-Triangulation<dim, spacedim>::get_used_vertices () const
-{
- return vertices_used;
-}
-
-
-#if deal_II_dimension == 1
-
-
-template <>
-unsigned int Triangulation<1,1>::max_adjacent_cells () const
-{
- return 2;
-}
-
-#endif
-
-
-template <int dim, int spacedim>
-unsigned int Triangulation<dim, spacedim>::max_adjacent_cells () const
-{
- cell_iterator cell = begin(0),
- endc = (n_levels() > 1 ? begin(1) : cell_iterator(end()));
- // store the largest index of the
- // vertices used on level 0
- unsigned int max_vertex_index = 0;
- for (; cell!=endc; ++cell)
- for (unsigned vertex=0; vertex<GeometryInfo<dim>::vertices_per_cell; ++vertex)
- if (cell->vertex_index(vertex) > max_vertex_index)
- max_vertex_index = cell->vertex_index(vertex);
-
- // store the number of times a cell
- // touches a vertex. An unsigned
- // int should suffice, even for
- // larger dimensions
- std::vector<unsigned short int> usage_count (max_vertex_index+1, 0);
- // touch a vertex's usage count
- // everytime we find an adjacent
- // element
- for (cell=begin(); cell!=endc; ++cell)
- for (unsigned vertex=0; vertex<GeometryInfo<dim>::vertices_per_cell; ++vertex)
- ++usage_count[cell->vertex_index(vertex)];
-
- return std::max (GeometryInfo<dim>::vertices_per_cell,
- static_cast<unsigned int>(*std::max_element (usage_count.begin(),
- usage_count.end())));
-}
-
-
-
-template <int dim, int spacedim>
-void
-Triangulation<dim, spacedim>::execute_coarsening_and_refinement ()
-{
- prepare_coarsening_and_refinement ();
-
- // verify a case with which we have had
- // some difficulty in the past (see the
- // deal.II/coarsening_* tests)
- if (smooth_grid & limit_level_difference_at_vertices)
- Assert (satisfies_level1_at_vertex_rule (*this) == true,
- ExcInternalError());
-
- // Inform RefinementListeners
- // about beginning of refinement.
- typename std::list<RefinementListener *>::iterator ref_listener =
- refinement_listeners.begin (),
- end_listener = refinement_listeners.end ();
- for (; ref_listener != end_listener; ++ref_listener)
- (*ref_listener)->pre_refinement_notification (*this);
-
- execute_coarsening();
-
- const DistortedCellList
- cells_with_distorted_children = execute_refinement();
-
- // verify a case with which we have had
- // some difficulty in the past (see the
- // deal.II/coarsening_* tests)
- if (smooth_grid & limit_level_difference_at_vertices)
- Assert (satisfies_level1_at_vertex_rule (*this) == true,
- ExcInternalError());
-
-#if deal_II_dimension > 1
- // finally build up neighbor connectivity
- // information
- update_neighbors(*this);
-#endif
-
- // Inform RefinementListeners
- // about end of refinement.
- for (ref_listener = refinement_listeners.begin ();
- ref_listener != end_listener; ++ref_listener)
- (*ref_listener)->post_refinement_notification (*this);
-
- AssertThrow (cells_with_distorted_children.distorted_cells.size() == 0,
- cells_with_distorted_children);
-}
-
-
-template<int dim, int spacedim>
-void
-Triangulation<dim, spacedim>::clear_despite_subscriptions()
-{
- // This is the former function
- // clear without the assertion in
- // the beginning.
- for (unsigned int i=0; i<levels.size(); ++i)
- delete levels[i];
- levels.clear ();
-
- delete faces;
- faces = NULL;
-
- vertices.clear ();
- vertices_used.clear ();
-
- for (unsigned int i=0; i<255; ++i)
- boundary[i] = &straight_boundary;
-
- number_cache = internal::Triangulation::NumberCache<dim>();
-}
-
-
-template <int dim, int spacedim>
-typename Triangulation<dim,spacedim>::DistortedCellList
-Triangulation<dim,spacedim>::execute_refinement ()
-{
- const DistortedCellList
- cells_with_distorted_children
- =
- internal::Triangulation::Implementation::
- execute_refinement (*this,check_for_distorted_cells);
-
-
-
- // re-compute number of lines
- compute_number_cache (*this, levels.size(), number_cache);
-
-#ifdef DEBUG
- for (unsigned int level=0; level<levels.size(); ++level)
- levels[level]->cells.monitor_memory (dim);
-
- // check whether really all
- // refinement flags are reset (also
- // of previously non-active cells
- // which we may not have
- // touched. If the refinement flag
- // of a non-active cell is set,
- // something went wrong since the
- // cell-accessors should have
- // caught this)
- cell_iterator cell = begin(),
- endc = end();
- while (cell != endc)
- Assert (!(cell++)->refine_flag_set(), ExcInternalError ());
-#endif
-
- return cells_with_distorted_children;
-}
-
-
-
-template <int dim, int spacedim>
-void Triangulation<dim, spacedim>::execute_coarsening ()
-{
- // create a vector counting for each line how
- // many cells contain this line. in 3D, this
- // is used later on to decide which lines can
- // be deleted after coarsening a cell. in
- // other dimensions it will be ignored
- std::vector<unsigned int> line_cell_count = count_cells_bounded_by_line (*this);
- std::vector<unsigned int> quad_cell_count = count_cells_bounded_by_quad (*this);
-
- // loop over all cells. Flag all
- // cells of which all children are
- // flagged for
- // coarsening and delete the childrens'
- // flags. In effect, only those
- // cells are flagged of which originally
- // all children were flagged and for which
- // all children are on the same refinement
- // level. For flagging, the user flags are
- // used, to avoid confusion and because
- // non-active cells can't be flagged for
- // coarsening. Note that because of the
- // effects of @p{fix_coarsen_flags}, of a
- // cell either all or no children must
- // be flagged for coarsening, so it is
- // ok to only check the first child
- clear_user_flags ();
-
- cell_iterator cell = begin(),
- endc = end();
- for (; cell!=endc; ++cell)
- if (!cell->active())
- if (cell->child(0)->coarsen_flag_set())
- {
- cell->set_user_flag();
- for (unsigned int child=0; child<cell->n_children(); ++child)
- {
- Assert (cell->child(child)->coarsen_flag_set(),
- ExcInternalError());
- cell->child(child)->clear_coarsen_flag();
- }
- }
-
-
- // now do the actual coarsening
- // step. Since the loop goes over
- // used cells we only need not
- // worry about deleting some cells
- // since the ++operator will then
- // just hop over them if we should
- // hit one. Do the loop in the
- // reverse way since we may only
- // delete some cells if their
- // neighbors have already been
- // deleted (if the latter are on a
- // higher level for example)
- //
- // if there is only one level,
- // there can not be anything to do
- if (levels.size() >= 2)
- for (cell = last(levels.size()-2); cell!=endc; --cell)
- if (cell->user_flag_set())
- // use a separate function,
- // since this is dimension
- // specific
- internal::Triangulation::Implementation::delete_children (*this, cell,
- line_cell_count, quad_cell_count);
-
- // re-compute number of lines and
- // quads
- compute_number_cache (*this, levels.size(), number_cache);
-
- // in principle no user flags
- // should be
- // set any more at this point
-#if DEBUG
- for (cell=begin(); cell!=endc; ++cell)
- Assert (cell->user_flag_set() == false, ExcInternalError());
-#endif
-}
-
-
-
-template <int dim, int spacedim>
-void Triangulation<dim, spacedim>::fix_coarsen_flags ()
-{
- // copy a piece of code from
- // prepare_coarsening_and_refinement that
- // ensures that the level difference at
- // vertices is limited if so desired. we
- // need this code here since at least in 1d
- // we don't call the dimension-independent
- // version of
- // prepare_coarsening_and_refinement
- // function. in 2d and 3d, having this hunk
- // here makes our lives a bit easier as
- // well as it takes care of these cases
- // earlier than it would otherwise happen.
- //
- // the main difference to the code
- // in p_c_and_r is that here we
- // absolutely have to make sure
- // that we get things right,
- // i.e. that in particular we set
- // flags right if
- // limit_level_difference_at_vertices
- // is set. to do so we iterate
- // until the flags don't change any
- // more
- std::vector<bool> previous_coarsen_flags (n_active_cells());
- save_coarsen_flags (previous_coarsen_flags);
-
- std::vector<int> vertex_level (vertices.size(), 0);
-
- bool continue_iterating = true;
-
- do
- {
- if (smooth_grid & limit_level_difference_at_vertices)
- {
- Assert(!anisotropic_refinement,
- ExcMessage("In case of anisotropic refinement the "
- "limit_level_difference_at_vertices flag for "
- "mesh smoothing must not be set!"));
-
- // store highest level one
- // of the cells adjacent to
- // a vertex belongs to
- std::fill (vertex_level.begin(), vertex_level.end(), 0);
- active_cell_iterator cell = begin_active(),
- endc = end();
- for (; cell!=endc; ++cell)
- {
- if (cell->refine_flag_set())
- for (unsigned int vertex=0; vertex<GeometryInfo<dim>::vertices_per_cell;
- ++vertex)
- vertex_level[cell->vertex_index(vertex)]
- = std::max (vertex_level[cell->vertex_index(vertex)],
- cell->level()+1);
- else if (!cell->coarsen_flag_set())
- for (unsigned int vertex=0; vertex<GeometryInfo<dim>::vertices_per_cell;
- ++vertex)
- vertex_level[cell->vertex_index(vertex)]
- = std::max (vertex_level[cell->vertex_index(vertex)],
- cell->level());
- else
- {
- // if coarsen flag is
- // set then tentatively
- // assume that the cell
- // will be
- // coarsened. this
- // isn't always true
- // (the coarsen flag
- // could be removed
- // again) and so we may
- // make an error
- // here. we try to
- // correct this by
- // iterating over the
- // entire process until
- // we are converged
- Assert (cell->coarsen_flag_set(), ExcInternalError());
- for (unsigned int vertex=0; vertex<GeometryInfo<dim>::vertices_per_cell;
- ++vertex)
- vertex_level[cell->vertex_index(vertex)]
- = std::max (vertex_level[cell->vertex_index(vertex)],
- cell->level()-1);
- }
- }
-
-
- // loop over all cells in reverse
- // order. do so because we can then
- // update the vertex levels on the
- // adjacent vertices and maybe
- // already flag additional cells in
- // this loop
- //
- // note that not only may we have
- // to add additional refinement
- // flags, but we will also have to
- // remove coarsening flags on cells
- // adjacent to vertices that will
- // see refinement
- for (cell=last_active(); cell != endc; --cell)
- if (cell->refine_flag_set() == false)
- {
- for (unsigned int vertex=0;
- vertex<GeometryInfo<dim>::vertices_per_cell; ++vertex)
- if (vertex_level[cell->vertex_index(vertex)] >=
- cell->level()+1)
- {
- // remove coarsen flag...
- cell->clear_coarsen_flag();
-
- // ...and if necessary also
- // refine the current cell,
- // at the same time
- // updating the level
- // information about
- // vertices
- if (vertex_level[cell->vertex_index(vertex)] >
- cell->level()+1)
- {
- cell->set_refine_flag();
-
- for (unsigned int v=0; v<GeometryInfo<dim>::vertices_per_cell;
- ++v)
- vertex_level[cell->vertex_index(v)]
- = std::max (vertex_level[cell->vertex_index(v)],
- cell->level()+1);
- }
-
- // continue and see whether
- // we may, for example, go
- // into the inner 'if'
- // above based on a
- // different vertex
- }
- }
- }
-
- // loop over all cells. Flag all
- // cells of which all children are
- // flagged for coarsening and
- // delete the childrens'
- // flags. Also delete all flags of
- // cells for which not all children
- // of a cell are flagged. In
- // effect, only those cells are
- // flagged of which originally all
- // children were flagged and for
- // which all children are on the
- // same refinement level. For
- // flagging, the user flags are
- // used, to avoid confusion and
- // because non-active cells can't
- // be flagged for coarsening
- //
- // In effect, all coarsen flags are
- // turned into user flags of the
- // mother cell if coarsening is
- // possible or deleted
- // otherwise.
- clear_user_flags ();
- // Coarsen flags of
- // cells with no mother cell,
- // i.e. on the coarsest level are
- // deleted explicitly.
- active_cell_iterator acell = begin_active(0),
- end_ac = end_active(0);
- for (; acell!=end_ac; ++acell)
- acell->clear_coarsen_flag();
-
- cell_iterator cell = begin(),
- endc = end();
- for (; cell!=endc; ++cell)
- {
- // nothing to do if we are
- // already on the finest level
- if (cell->active())
- continue;
-
- const unsigned int n_children=cell->n_children();
- unsigned int flagged_children=0;
- for (unsigned int child=0; child<n_children; ++child)
- if (cell->child(child)->active() &&
- cell->child(child)->coarsen_flag_set())
- {
- ++flagged_children;
- // clear flag since we
- // don't need it anymore
- cell->child(child)->clear_coarsen_flag();
- }
-
- // flag this cell for
- // coarsening if all children
- // were flagged
- if (flagged_children == n_children)
- cell->set_user_flag();
- }
-
- // in principle no coarsen flags
- // should be set any more at this
- // point
-#if DEBUG
- for (cell=begin(); cell!=endc; ++cell)
- Assert (cell->coarsen_flag_set() == false, ExcInternalError());
-#endif
-
- // 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())
- // if allowed: flag the
- // children for coarsening
- if (internal::Triangulation::Implementation::template coarsening_allowed<dim,spacedim>(cell))
- for (unsigned int c=0; c<cell->n_children(); ++c)
- {
- Assert (cell->child(c)->refine_flag_set()==false,
- ExcInternalError());
-
- cell->child(c)->set_coarsen_flag();
- }
-
- // clear all user flags again, now that we
- // don't need them any more
- clear_user_flags ();
-
-
- // now see if anything has
- // changed in the last
- // iteration of this function
- std::vector<bool> current_coarsen_flags (n_active_cells());
- save_coarsen_flags (current_coarsen_flags);
-
- continue_iterating = (current_coarsen_flags != previous_coarsen_flags);
- previous_coarsen_flags = current_coarsen_flags;
- }
- while (continue_iterating == true);
-}
-
-
-#if deal_II_dimension == 1
-
-template <>
-bool Triangulation<1,1>::prepare_coarsening_and_refinement ()
-{
- // save the flags to determine
- // whether something was changed in
- // the course of this function
- std::vector<bool> flags_before;
- save_coarsen_flags (flags_before);
-
- // do nothing in 1d, except setting
- // the coarsening flags correctly
- fix_coarsen_flags ();
-
- std::vector<bool> flags_after;
- save_coarsen_flags (flags_after);
-
- return (flags_before != flags_after);
-}
-
-
-template <>
-bool Triangulation<1,2>::prepare_coarsening_and_refinement ()
-{
- // save the flags to determine
- // whether something was changed in
- // the course of this function
- std::vector<bool> flags_before;
- save_coarsen_flags (flags_before);
-
- // do nothing in 1d, except setting
- // the coarsening flags correctly
- fix_coarsen_flags ();
-
- std::vector<bool> flags_after;
- save_coarsen_flags (flags_after);
-
- return (flags_before != flags_after);
-}
-
-
-#endif
-
-
-namespace
-{
-
- // check if the given @param cell marked
- // for coarsening would produce an
- // unrefined island. To break up long
- // chains of these cells we recursively
- // check our neighbors in case we change
- // this cell. This reduces the number of
- // outer iterations dramatically.
- template <int dim, int spacedim>
- void
- possibly_do_not_produce_unrefined_islands(
- const typename Triangulation<dim,spacedim>::cell_iterator &cell)
- {
- Assert (cell->has_children(), ExcInternalError());
-
- unsigned int n_neighbors=0;
- // count all neighbors
- // that will be refined
- // along the face of our
- // cell after the next
- // step
- unsigned int count=0;
- for (unsigned int n=0; n<GeometryInfo<dim>::faces_per_cell; ++n)
- {
- const typename Triangulation<dim,spacedim>::cell_iterator neighbor = cell->neighbor(n);
- if (neighbor.state() == IteratorState::valid)
- {
- ++n_neighbors;
- if (face_will_be_refined_by_neighbor(cell,n))
- ++count;
- }
- }
- // clear coarsen flags if
- // either all existing
- // neighbors will be
- // refined or all but one
- // will be and the cell
- // is in the interior of
- // the domain
- if (count==n_neighbors ||
- (count>=n_neighbors-1 &&
- n_neighbors == GeometryInfo<dim>::faces_per_cell) )
- {
- for (unsigned int c=0; c<cell->n_children(); ++c)
- cell->child(c)->clear_coarsen_flag();
-
- for (unsigned int face=0; face<GeometryInfo<dim>::faces_per_cell; ++face)
- if (!cell->at_boundary(face)
- &&
- ( !cell->neighbor(face)->active() )
- && (cell_will_be_coarsened(cell->neighbor(face))) )
- possibly_do_not_produce_unrefined_islands<dim,spacedim>( cell->neighbor(face) );
- }
- }
-
-
- // see if the current cell needs to
- // be refined to avoid unrefined
- // islands.
- //
- // there are sometimes chains of
- // cells that induce refinement of
- // each other. to avoid running the
- // loop in
- // prepare_coarsening_and_refinement
- // over and over again for each one
- // of them, at least for the
- // isotropic refinement case we
- // seek to flag neighboring
- // elements as well as
- // necessary. this takes care of
- // (slightly pathological) cases
- // like deal.II/mesh_smoothing_03
- template <int dim, int spacedim>
- void
- possibly_refine_unrefined_island
- (const typename Triangulation<dim,spacedim>::cell_iterator &cell,
- const bool allow_anisotropic_smoothing)
- {
- Assert (cell->has_children() == false, ExcInternalError());
- Assert (cell->refine_flag_set() == false, ExcInternalError());
-
-
- // now we provide two
- // algorithms. the first one is
- // the standard one, coming from
- // the time, where only isotropic
- // refinement was possible. it
- // simply counts the neighbors
- // that are or will be refined
- // and compares to the number of
- // other ones. the second one
- // does this check independently
- // for each direction: if all
- // neighbors in one direction
- // (normally two, at the boundary
- // only one) are refined, the
- // current cell is flagged to be
- // refined in an according
- // direction.
-
- if (allow_anisotropic_smoothing == false)
- {
- // use first algorithm
- unsigned int refined_neighbors = 0,
- unrefined_neighbors = 0;
- for (unsigned int face=0; face<GeometryInfo<dim>::faces_per_cell; ++face)
- if (!cell->at_boundary(face))
- {
- if (face_will_be_refined_by_neighbor(cell,face))
- ++refined_neighbors;
- else
- ++unrefined_neighbors;
- }
-
- if (unrefined_neighbors < refined_neighbors)
- {
- cell->clear_coarsen_flag();
- cell->set_refine_flag ();
-
- // ok, so now we have
- // flagged this cell. if
- // we know that there
- // were any unrefined
- // neighbors at all, see
- // if any of those will
- // have to be refined as
- // well
- if (unrefined_neighbors > 0)
- for (unsigned int face=0; face<GeometryInfo<dim>::faces_per_cell; ++face)
- if (!cell->at_boundary(face)
- &&
- (face_will_be_refined_by_neighbor(cell,face) == false)
- &&
- (cell->neighbor(face)->has_children() == false)
- &&
- (cell->neighbor(face)->refine_flag_set() == false))
- possibly_refine_unrefined_island<dim,spacedim>
- (cell->neighbor(face),
- allow_anisotropic_smoothing);
- }
- }
- else
- {
- // variable to store the cell
- // refine case needed to
- // fulfill all smoothing
- // requirements
- RefinementCase<dim> smoothing_cell_refinement_case
- = RefinementCase<dim>::no_refinement;
-
- // use second algorithm, do
- // the check individually for
- // each direction
- for (unsigned int face_pair=0;
- face_pair<GeometryInfo<dim>::faces_per_cell/2; ++face_pair)
- {
- // variable to store the
- // cell refine case
- // needed to refine at
- // the current face pair
- // in the same way as the
- // neighbors do...
- RefinementCase<dim> directional_cell_refinement_case
- = RefinementCase<dim>::isotropic_refinement;
-
- for (unsigned int face_index=0; face_index<2; ++face_index)
- {
- unsigned int face=2*face_pair+face_index;
- // variable to store
- // the refine case
- // (to come) of the
- // face under
- // consideration
- RefinementCase<dim-1> expected_face_ref_case
- = RefinementCase<dim-1>::no_refinement;
-
- if (cell->neighbor(face).state() == IteratorState::valid)
- face_will_be_refined_by_neighbor<dim,spacedim>(cell,face,expected_face_ref_case);
- // now extract which
- // refine case would
- // be necessary to
- // achive the same
- // face
- // refinement. set
- // the intersection
- // with other
- // requirements for
- // the same
- // direction.
-
- // note: using the
- // intersection is
- // not an obvious
- // decision, we could
- // also argue that it
- // is more natural to
- // use the
- // union. however,
- // intersection is
- // the less
- // aggressive tactic
- // and favours a
- // smaller number of
- // refined cells over
- // an intensive
- // smoothing. this
- // way we try not to
- // loose too much of
- // the effort we put
- // in anisotropic
- // refinement
- // indicators due to
- // overly aggressive
- // smoothing...
- directional_cell_refinement_case
- = (directional_cell_refinement_case &
- GeometryInfo<dim>::min_cell_refinement_case_for_face_refinement(
- expected_face_ref_case,
- face,
- cell->face_orientation(face),
- cell->face_flip(face),
- cell->face_rotation(face)));
- }//for both face indices
- // if both requirements
- // sum up to something
- // useful, add this to
- // the refine case for
- // smoothing. note: if
- // directional_cell_refinement_case
- // is isotropic still,
- // then something went
- // wrong...
- Assert(directional_cell_refinement_case <
- RefinementCase<dim>::isotropic_refinement,
- ExcInternalError());
- smoothing_cell_refinement_case = smoothing_cell_refinement_case |
- directional_cell_refinement_case;
- }//for all face_pairs
- // no we collected
- // contributions from all
- // directions. combine the
- // new flags with the
- // existing refine case, but
- // only if smoothing is
- // required
- if (smoothing_cell_refinement_case)
- {
- cell->clear_coarsen_flag();
- cell->set_refine_flag(cell->refine_flag_set() |
- smoothing_cell_refinement_case);
- }
- }
- }
-}
-
-
-template <int dim, int spacedim>
-bool Triangulation<dim,spacedim>::prepare_coarsening_and_refinement ()
-{
- // save the flags to determine
- // whether something was changed in
- // the course of this function
- std::vector<bool> flags_before[2];
- save_coarsen_flags (flags_before[0]);
- save_refine_flags (flags_before[1]);
-
- // save the flags at the outset of
- // each loop. we do so in order to
- // find out whether something was
- // changed in the present loop, in
- // which case we would have to
- // re-run the loop. the other
- // possibility to find this out
- // would be to set a flag
- // @p{something_changed} to true
- // each time we change something.
- // however, sometimes one change in
- // one of the parts of the loop is
- // undone by another one, so we
- // might end up in an endless
- // loop. we could be tempted to
- // break this loop at an arbitrary
- // number of runs, but that would
- // not be a clean solution, since
- // we would either have to
- // 1/ break the loop too early, in which
- // case the promise that a second
- // call to this function immediately
- // after the first one does not
- // change anything, would be broken,
- // or
- // 2/ we do as many loops as there are
- // levels. we know that information
- // is transported over one level
- // in each run of the loop, so this
- // is enough. Unfortunately, each
- // loop is rather expensive, so
- // we chose the way presented here
- std::vector<bool> flags_before_loop[2] = {flags_before[0],
- flags_before[1]};
-
- // now for what is done in each
- // loop: we have to fulfill several
- // tasks at the same time, namely
- // several mesh smoothing
- // algorithms and mesh
- // regularisation, by which we mean
- // that the next mesh fulfills
- // several requirements such as no
- // double refinement at each face
- // or line, etc.
- //
- // since doing these things at once
- // seems almost impossible (in the
- // first year of this library, they
- // were done in two functions, one
- // for refinement and one for
- // coarsening, and most things
- // within these were done at once,
- // so the code was rather
- // impossible to join into this,
- // only, function), we do them one
- // after each other. the order in
- // which we do them is such that
- // the important tasks, namely
- // regularisation, are done last
- // and the least important things
- // are done the first. the
- // following order is chosen:
- //
- // 0/ Only if coarsest_level_1 or
- // patch_level_1 is set:
- // clear all coarsen flags on level 1
- // to avoid level 0 cells being
- // created by coarsening.
- // As coarsen flags will never be added,
- // this can be done once and for all
- // before the actual loop starts.
- // 1/ do not coarsen a cell if
- // 'most of the neighbors' will be
- // refined after the step. This is
- // to prevent occurence of
- // unrefined islands.
- // 2/ eliminate refined islands in the
- // interior and at the boundary. since
- // they don't do much harm besides
- // increasing the number of degrees
- // of freedom, doing this has a
- // rather low priority.
- // 3/ limit the level difference of
- // neighboring cells at each vertex.
- // 4/ eliminate unrefined islands. this
- // has higher priority since this
- // diminishes the approximation
- // properties not only of the unrefined
- // island, but also of the surrounding
- // patch.
- // 5/ ensure patch level 1. Then the
- // triangulation consists of patches,
- // i.e. of cells that are
- // refined once. It follows that if at
- // least one of the children of a cell
- // is or will be refined than all children
- // need to be refined. This step
- // only sets refinement flags and does
- // not set coarsening flags.
- // If the patch_level_1 flag is set, then
- // eliminate_unrefined_islands,
- // eliminate_refined_inner_islands and
- // eliminate_refined_boundary_islands will
- // be fulfilled automatically and do not
- // need to be enforced separately.
- // 6/ take care of the requirement that no
- // double refinement is done at each face
- // 7/ take care that no double refinement
- // is done at each line in 3d or higher
- // dimensions.
- // 8/ make sure that all children of each
- // cell are either flagged for coarsening
- // or none of the children is
- //
- // For some of these steps, it is
- // known that they
- // interact. Namely, it is not
- // possible to guarantee that after
- // step 6 another step 5 would have
- // no effect; the same holds for
- // the opposite order and also when
- // taking into account step
- // 7. however, it is important to
- // guarantee that step five or six
- // do not undo something that step
- // 5 did, and step 7 not something
- // of step 6, otherwise the
- // requirements will not be
- // satisfied even if the loop
- // terminates. this is accomplished
- // by the fact that steps 5 and 6
- // only *add* refinement flags and
- // delete coarsening flags
- // (therefore, step 6 can't undo
- // something that step 4 already
- // did), and step 7 only deletes
- // coarsening flags, never adds
- // some. step 7 needs also take
- // care that it won't tag cells for
- // refinement for which some
- // neighbors are more refined or
- // will be refined.
-
- //////////////////////////////////////
- // STEP 0:
- // Only if coarsest_level_1 or
- // patch_level_1 is set:
- // clear all coarsen flags on level 1
- // to avoid level 0 cells being
- // created by coarsening.
- if (((smooth_grid & coarsest_level_1) ||
- (smooth_grid & patch_level_1)) && n_levels()>=2)
- {
- active_cell_iterator
- cell=begin_active(1),
- endc=end_active(1);
-
- for (; cell!=endc; ++cell)
- cell->clear_coarsen_flag();
- }
-
- bool mesh_changed_in_this_loop = false;
- do
- {
- //////////////////////////////////////
- // STEP 1:
- // do not coarsen a cell if 'most of
- // the neighbors' will be refined after
- // the step. This is to prevent the
- // occurence of unrefined islands.
- // If patch_level_1 is set, this will
- // be automatically fulfilled.
- if (smooth_grid & do_not_produce_unrefined_islands &&
- !(smooth_grid & patch_level_1))
- {
- cell_iterator cell;
- const cell_iterator endc = end();
-
- for (cell=begin(); cell!=endc; ++cell)
- {
- // only do something if this
- // cell will be coarsened
- if (!cell->active() && cell_will_be_coarsened(cell))
- possibly_do_not_produce_unrefined_islands<dim,spacedim>(cell);
- }
- }
-
-
- //////////////////////////////////////
- // STEP 2:
- // eliminate refined islands in the
- // interior and at the boundary. since
- // they don't do much harm besides
- // increasing the number of degrees of
- // freedom, doing this has a rather low
- // priority.
- // If patch_level_1 is set, this will
- // be automatically fulfilled.
- //
- // there is one corner case
- // to consider: if this is a
- // distributed
- // triangulation, there may
- // be refined islands on the
- // boundary of which we own
- // only part (e.g. a single
- // cell in the corner of a
- // domain). the rest of the
- // island is ghost cells and
- // it *looks* like the area
- // around it (artificial
- // cells) are coarser but
- // this is only because they
- // may actually be equally
- // fine on other
- // processors. it's hard to
- // detect this case but we
- // can do the following:
- // only set coarsen flags to
- // remove this refined
- // island if all cells we
- // want to set flags on are
- // locally owned
- if (smooth_grid & (eliminate_refined_inner_islands |
- eliminate_refined_boundary_islands) &&
- !(smooth_grid & patch_level_1))
- {
- cell_iterator cell;
- const cell_iterator endc = end();
-
- for (cell=begin(); cell!=endc; ++cell)
- if (!cell->active() ||
- (cell->active() &&
- cell->refine_flag_set() &&
- !cell->is_ghost() &&
- !cell->is_artificial()))
- {
- // check whether all
- // children are
- // active, i.e. not
- // refined
- // themselves. This
- // is a precondition
- // that the children
- // may be coarsened
- // away. If the cell
- // is only flagged
- // for refinement,
- // then all future
- // children will be
- // active
- bool all_children_active = true;
- if (!cell->active())
- for (unsigned int c=0; c<cell->n_children(); ++c)
- if (!cell->child(c)->active() ||
- cell->child(c)->is_ghost() ||
- cell->child(c)->is_artificial())
- {
- all_children_active = false;
- break;
- }
-
- if (all_children_active)
- {
- // count number
- // of refined and
- // unrefined
- // neighbors of
- // cell.
- // neighbors on
- // lower levels
- // are counted as
- // unrefined
- // since they can
- // only get to
- // the same level
- // as this cell
- // by the next
- // refinement
- // cycle
- unsigned int unrefined_neighbors = 0,
- total_neighbors = 0;
-
- for (unsigned int n=0; n<GeometryInfo<dim>::faces_per_cell; ++n)
- {
- const cell_iterator neighbor = cell->neighbor(n);
- if (neighbor.state() == IteratorState::valid)
- {
- ++total_neighbors;
-
- if (!face_will_be_refined_by_neighbor(cell,n))
- ++unrefined_neighbors;
- }
-
- }
-
- // if all
- // neighbors
- // unrefined:
- // mark this cell
- // for coarsening
- // or don't
- // refine if
- // marked for
- // that
- //
- // also do the
- // distinction
- // between the
- // two versions
- // of the
- // eliminate_refined_*_islands
- // flag
- //
- // the last check
- // is whether
- // there are any
- // neighbors at
- // all. if not
- // so, then we
- // are (e.g.) on
- // the coarsest
- // grid with one
- // cell, for
- // which, of
- // course, we do
- // not remove the
- // refine flag.
- if ((unrefined_neighbors == total_neighbors)
- &&
- (((unrefined_neighbors==GeometryInfo<dim>::faces_per_cell) &&
- (smooth_grid & eliminate_refined_inner_islands)) ||
- ((unrefined_neighbors<GeometryInfo<dim>::faces_per_cell) &&
- (smooth_grid & eliminate_refined_boundary_islands)) )
- &&
- (total_neighbors != 0))
- {
- if (!cell->active())
- for (unsigned int c=0; c<cell->n_children(); ++c)
- {
- cell->child(c)->clear_refine_flag ();
- cell->child(c)->set_coarsen_flag ();
- }
- else
- cell->clear_refine_flag();
- }
- }
- }
- }
-
- //////////////////////////////////////
- // STEP 3:
- // limit the level difference of
- // neighboring cells at each vertex.
- //
- // in case of anisotropic refinement
- // this does not make sense. as soon
- // as one cell is anisotropically
- // refined, an Assertion is
- // thrown. therefore we can ignore
- // this problem later on
- if (smooth_grid & limit_level_difference_at_vertices)
- {
- Assert(!anisotropic_refinement,
- ExcMessage("In case of anisotropic refinement the "
- "limit_level_difference_at_vertices flag for "
- "mesh smoothing must not be set!"));
-
- // store highest level one
- // of the cells adjacent to
- // a vertex belongs to
- std::vector<int> vertex_level (vertices.size(), 0);
- active_cell_iterator cell = begin_active(),
- endc = end();
- for (; cell!=endc; ++cell)
- {
- if (cell->refine_flag_set())
- for (unsigned int vertex=0; vertex<GeometryInfo<dim>::vertices_per_cell;
- ++vertex)
- vertex_level[cell->vertex_index(vertex)]
- = std::max (vertex_level[cell->vertex_index(vertex)],
- cell->level()+1);
- else if (!cell->coarsen_flag_set())
- for (unsigned int vertex=0; vertex<GeometryInfo<dim>::vertices_per_cell;
- ++vertex)
- vertex_level[cell->vertex_index(vertex)]
- = std::max (vertex_level[cell->vertex_index(vertex)],
- cell->level());
- else
- {
- // if coarsen flag is set then
- // tentatively assume that the
- // cell will be coarsened. this
- // isn't always true (the
- // coarsen flag could be
- // removed again) and so we may
- // make an error here
- Assert (cell->coarsen_flag_set(), ExcInternalError());
- for (unsigned int vertex=0; vertex<GeometryInfo<dim>::vertices_per_cell;
- ++vertex)
- vertex_level[cell->vertex_index(vertex)]
- = std::max (vertex_level[cell->vertex_index(vertex)],
- cell->level()-1);
- }
- }
-
-
- // loop over all cells in reverse
- // order. do so because we can then
- // update the vertex levels on the
- // adjacent vertices and maybe
- // already flag additional cells in
- // this loop
- //
- // note that not only may we have
- // to add additional refinement
- // flags, but we will also have to
- // remove coarsening flags on cells
- // adjacent to vertices that will
- // see refinement
- for (cell=last_active(); cell != endc; --cell)
- if (cell->refine_flag_set() == false)
- {
- for (unsigned int vertex=0;
- vertex<GeometryInfo<dim>::vertices_per_cell; ++vertex)
- if (vertex_level[cell->vertex_index(vertex)] >=
- cell->level()+1)
- {
- // remove coarsen flag...
- cell->clear_coarsen_flag();
-
- // ...and if necessary also
- // refine the current cell,
- // at the same time
- // updating the level
- // information about
- // vertices
- if (vertex_level[cell->vertex_index(vertex)] >
- cell->level()+1)
- {
- cell->set_refine_flag();
-
- for (unsigned int v=0; v<GeometryInfo<dim>::vertices_per_cell;
- ++v)
- vertex_level[cell->vertex_index(v)]
- = std::max (vertex_level[cell->vertex_index(v)],
- cell->level()+1);
- }
-
- // continue and see whether
- // we may, for example, go
- // into the inner 'if'
- // above based on a
- // different vertex
- }
- }
- }
-
- /////////////////////////////////////
- // STEP 4:
- // eliminate unrefined
- // islands. this has higher
- // priority since this
- // diminishes the
- // approximation properties
- // not only of the unrefined
- // island, but also of the
- // surrounding patch.
- //
- // do the loop from finest
- // to coarsest cells since
- // we may trigger a cascade
- // by marking cells for
- // refinement which may
- // trigger more cells
- // further down below
- if (smooth_grid & eliminate_unrefined_islands)
- {
- active_cell_iterator cell=last_active(),
- endc=end();
-
- for (; cell != endc; --cell)
- // only do something if
- // cell is not already
- // flagged for
- // (isotropic) refinement
- if (cell->refine_flag_set() != RefinementCase<dim>::isotropic_refinement)
- possibly_refine_unrefined_island<dim,spacedim>
- (cell,
- (smooth_grid & allow_anisotropic_smoothing) != 0);
- }
-
- /////////////////////////////////
- // STEP 5:
- // ensure patch level 1.
- //
- // Introduce some terminology:
- // - a cell that is refined
- // once is a patch of
- // level 1 simply called patch.
- // - a cell that is globally
- // refined twice is called
- // a patch of level 2.
- // - patch level n says that
- // the triangulation consists
- // of patches of level n.
- // This makes sense only
- // if the grid is already at
- // least n times globally
- // refined.
- //
- // E.g. from patch level 1
- // follows: if at least one
- // of the children of a cell
- // is or will be refined
- // than enforce all
- // children to be
- // refined.
-
- // This step 4 only
- // sets refinement flags and
- // does not set coarsening
- // flags.
- if (smooth_grid & patch_level_1)
- {
- // An important assumption
- // (A) is that before
- // calling this function
- // the grid was already of
- // patch level 1.
-
- // loop over all cells
- // whose children are all
- // active. (By assumption
- // (A) either all or none
- // of the children are
- // active). If the refine
- // flag of at least one of
- // the children is set then
- // set_refine_flag and
- // clear_coarsen_flag of
- // all children.
- for (cell_iterator cell = begin(); cell != end(); ++cell)
- if (!cell->active())
- {
- // ensure the
- // invariant. we can
- // then check whether
- // all of its
- // children are
- // further refined or
- // not by simply
- // looking at the
- // first child
- Assert (cell_is_patch_level_1(cell),
- ExcInternalError());
- if (cell->child(0)->has_children() == true)
- continue;
-
- // cell is found to
- // be a patch.
- // combine the refine
- // cases of all
- // children
- RefinementCase<dim> combined_ref_case = RefinementCase<dim>::no_refinement;
- for (unsigned int i=0; i<cell->n_children(); ++i)
- combined_ref_case = combined_ref_case |
- cell->child(i)->refine_flag_set();
- if (combined_ref_case != RefinementCase<dim>::no_refinement)
- for (unsigned int i=0; i<cell->n_children(); ++i)
- {
- cell_iterator child = cell->child(i);
-
- child->clear_coarsen_flag();
- child->set_refine_flag(combined_ref_case);
- }
- }
-
- // The code above dealt
- // with the case where we
- // may get a
- // non-patch_level_1 mesh
- // from refinement. Now
- // also deal with the case
- // where we could get such
- // a mesh by coarsening.
- // Coarsen the children
- // (and remove the
- // grandchildren) only if
- // all cell->grandchild(i)
- // ->coarsen_flag_set()
- // are set.
- //
- // for a case where this is
- // a bit tricky, take a
- // look at the
- // mesh_smoothing_0[12]
- // testcases
- for (cell_iterator cell = begin(); cell != end(); ++cell)
- {
- // check if this cell
- // has active
- // grandchildren. note
- // that we know that it
- // is patch_level_1,
- // i.e. if one of its
- // children is active
- // then so are all, and
- // it isn't going to
- // have any
- // grandchildren at
- // all:
- if (cell->active()
- ||
- cell->child(0)->active())
- continue;
-
- // cell is not active,
- // and so are none of
- // its children. check
- // the
- // grandchildren. note
- // that the children
- // are also
- // patch_level_1, and
- // so we only ever need
- // to check their first
- // child
- const unsigned int n_children=cell->n_children();
- bool has_active_grandchildren = false;
-
- for (unsigned int i=0; i<n_children; ++i)
- if (cell->child(i)->child(0)->active())
- {
- has_active_grandchildren = true;
- break;
- }
-
- if (has_active_grandchildren == false)
- continue;
-
-
- // ok, there are active
- // grandchildren. see
- // if either all or
- // none of them are
- // flagged for
- // coarsening
- unsigned int n_grandchildren=0;
- // count all coarsen
- // flags of the
- // grandchildren.
- unsigned int n_coarsen_flags=0;
- // cell is not a
- // patch (of level 1)
- // as it has a
- // grandchild. Is
- // cell a patch of
- // level 2??
- // Therefore: find
- // out whether all
- // cell->child(i) are
- // patches
- for (unsigned int c=0; c<n_children; ++c)
- {
- // get at the
- // child. by
- // assumption
- // (A), and the
- // check by which
- // we got here,
- // the child is
- // not active
- cell_iterator child=cell->child(c);
-
- const unsigned int nn_children=child->n_children();
- n_grandchildren += nn_children;
-
- // if child is
- // found to be a
- // patch of
- // active cells
- // itself, then
- // add up how
- // many of its
- // children are
- // supposed to be
- // coarsened
- if (child->child(0)->active())
- for (unsigned int cc=0; cc<nn_children; ++cc)
- if (child->child(cc)->coarsen_flag_set())
- ++n_coarsen_flags;
- }
-
- // if not all
- // grandchildren are
- // supposed to be
- // coarsened
- // (e.g. because some
- // simply don't have
- // the flag set, or
- // because they are not
- // active and therefore
- // cannot carry the
- // flag), then remove
- // the coarsen flag
- // from all of the
- // active
- // grandchildren. note
- // that there may be
- // coarsen flags on the
- // grandgrandchildren
- // -- we don't clear
- // them here, but we'll
- // get to them in later
- // iterations if
- // necessary
- //
- // there is nothing
- // we have to do if
- // no coarsen flags
- // have been set at
- // all
- if ((n_coarsen_flags != n_grandchildren)
- &&
- (n_coarsen_flags > 0))
- for (unsigned int c=0; c<n_children; ++c)
- {
- const cell_iterator child = cell->child(c);
- if (child->child(0)->active())
- for (unsigned int cc=0; cc<child->n_children(); ++cc)
- child->child(cc)->clear_coarsen_flag();
- }
- }
- }
-
- //////////////////////////////////
- //
- // at the boundary we could end up with
- // cells with negative volume or at
- // least with a part, that is negative,
- // if the cell is refined
- // anisotropically. we have to check,
- // whether that can happen
- internal::Triangulation::Implementation::prevent_distorted_boundary_cells(*this);
-
- /////////////////////////////////
- // STEP 6:
- // take care of the requirement that no
- // double refinement is done at each face
- //
- // in case of anisotropic refinement
- // it is only likely, but not sure,
- // that the cells, which are more
- // refined along a certain face common
- // to two cells are on a higher
- // level. therefore we cannot be sure,
- // that the requirement of no double
- // refinement is fulfilled after a
- // single pass of the following
- // actions. We could just wait for the
- // next global loop. when this
- // function terminates, the
- // requirement will be
- // fullfilled. However, it might be
- // faster to insert an inner loop
- // here.
- bool changed = true;
- while (changed)
- {
- changed=false;
- active_cell_iterator cell=last_active(),
- endc=end();
-
- for (; cell != endc; --cell)
- if (cell->refine_flag_set())
- {
- // loop over neighbors of cell
- for (unsigned int i=0; i<GeometryInfo<dim>::faces_per_cell; ++i)
- {
- // only do something if the
- // face is not at the boundary
- // and if the face will be
- // refined with the RefineCase
- // currently flagged for
- if (cell->neighbor(i).state() == IteratorState::valid &&
- (GeometryInfo<dim>::face_refinement_case(cell->refine_flag_set(),
- i)
- != RefinementCase<dim-1>::no_refinement))
- {
- // 1) if the neighbor has
- // children: nothing to
- // worry about.
- // 2) if the neighbor is
- // active and a coarser
- // one, ensure, that its
- // refine_flag is set
- // 3) if the neighbor is
- // active and as
- // refined along the face
- // as our current cell,
- // make sure, that no
- // coarsen_flag is set. if
- // we remove the coarsen
- // flag of our neighbor,
- // fix_coarsen_flags() makes
- // sure, that the mother
- // cell will not be
- // coarsened
- if (cell->neighbor(i)->active())
- {
- if (cell->neighbor_is_coarser(i))
- {
- if (cell->neighbor(i)->coarsen_flag_set())
- cell->neighbor(i)->clear_coarsen_flag();
- // we'll set the
- // refine flag
- // for this
- // neighbor
- // below. we
- // note, that we
- // have changed
- // something by
- // setting the
- // changed flag
- // to true. We do
- // not need to do
- // so, if we just
- // removed the
- // coarsen flag,
- // as the changed
- // flag only
- // indicates the
- // need to re-run
- // the inner
- // loop. however,
- // we only loop
- // over cells
- // flagged for
- // refinement
- // here, so
- // nothing to
- // worry about if
- // we remove
- // coarsen flags
-
- if (dim==2)
- {
- if (smooth_grid & allow_anisotropic_smoothing)
- changed=cell->neighbor(i)->flag_for_face_refinement(cell->neighbor_of_coarser_neighbor(i).first,
- RefinementCase<dim-1>::cut_x);
- else
- {
- if (!cell->neighbor(i)->refine_flag_set())
- changed=true;
- cell->neighbor(i)->set_refine_flag();
- }
- }
- else //i.e. if (dim==3)
- {
-// ugly situations might arise here, consider the following situation, which
-// shows neighboring cells at the common face, where the upper right element is
-// coarser at the given face. Now the upper child element of the lower left
-// wants to refine according to cut_z, such that there is a 'horizontal'
-// refinement of the face marked with #####
-//
-// / /
-// / /
-// *---------------*
-// | |
-// | |
-// | |
-// | |
-// | |
-// | | /
-// | |/
-// *---------------*
-//
-//
-// *---------------*
-// /| /|
-// / | ##### / |
-// | |
-// *---------------*
-// /| /|
-// / | / |
-// | |
-// *---------------*
-// / /
-// / /
-//
-// this introduces too many hanging nodes and the neighboring (coarser) cell
-// (upper right) has to be refined. If it is only refined according to cut_z,
-// then everything is ok:
-//
-// / /
-// / /
-// *---------------*
-// | |
-// | | /
-// | |/
-// *---------------*
-// | |
-// | | /
-// | |/
-// *---------------*
-//
-//
-// *---------------*
-// /| /|
-// / *---------------*
-// /| /|
-// *---------------*
-// /| /|
-// / | / |
-// | |
-// *---------------*
-// / /
-// / /
-//
-// if however the cell wants to refine itself in an other way, or if we disallow
-// anisotropic smoothing, then simply refining the neighbor isotropically is not
-// going to work, since this introduces a refinement of face ##### with both
-// cut_x and cut_y, which is not possible:
-//
-// / / /
-// / / /
-// *-------*-------*
-// | | |
-// | | | /
-// | | |/
-// *-------*-------*
-// | | |
-// | | | /
-// | | |/
-// *-------*-------*
-//
-//
-// *---------------*
-// /| /|
-// / *---------------*
-// /| /|
-// *---------------*
-// /| /|
-// / | / |
-// | |
-// *---------------*
-// / /
-// / /
-//
-// thus, in this case we also need to refine our current cell in the new
-// direction:
-//
-// / / /
-// / / /
-// *-------*-------*
-// | | |
-// | | | /
-// | | |/
-// *-------*-------*
-// | | |
-// | | | /
-// | | |/
-// *-------*-------*
-//
-//
-// *-------*-------*
-// /| /| /|
-// / *-------*-------*
-// /| /| /|
-// *-------*-------*
-// /| / /|
-// / | / |
-// | |
-// *---------------*
-// / /
-// / /
-
- std::pair<unsigned int, unsigned int> nb_indices
- =cell->neighbor_of_coarser_neighbor(i);
- unsigned int refined_along_x=0,
- refined_along_y=0,
- to_be_refined_along_x=0,
- to_be_refined_along_y=0;
-
- const int this_face_index=cell->face_index(i);
-
-// step 1: detect, along which axis the face is currently refined
- if ((this_face_index
- == cell->neighbor(i)->face(nb_indices.first)->child_index(0)) ||
- (this_face_index
- == cell->neighbor(i)->face(nb_indices.first)->child_index(1)))
- {
- // this
- // might
- // be an
- // anisotropic
- // child. get
- // the
- // face
- // refine
- // case
- // of the
- // neighbors
- // face
- // and
- // count
- // refinements
- // in x
- // and y
- // direction.
- RefinementCase<dim-1> frc=cell->neighbor(i)->face(nb_indices.first)->refinement_case();
- if (frc & RefinementCase<dim>::cut_x)
- ++refined_along_x;
- if (frc & RefinementCase<dim>::cut_y)
- ++refined_along_y;
- }
- else
- // this has
- // to be an
- // isotropic
- // child
- {
- ++refined_along_x;
- ++refined_along_y;
- }
-// step 2: detect, along which axis the face has to be refined given the current
-// refine flag
- RefinementCase<dim-1> flagged_frc=
- GeometryInfo<dim>::face_refinement_case(cell->refine_flag_set(),
- i,
- cell->face_orientation(i),
- cell->face_flip(i),
- cell->face_rotation(i));
- if (flagged_frc & RefinementCase<dim>::cut_x)
- ++to_be_refined_along_x;
- if (flagged_frc & RefinementCase<dim>::cut_y)
- ++to_be_refined_along_y;
-
-// step 3: set the refine flag of the (coarser and active) neighbor.
- if ((smooth_grid & allow_anisotropic_smoothing) ||
- cell->neighbor(i)->refine_flag_set())
- {
- if (refined_along_x + to_be_refined_along_x > 1)
- changed |= cell->neighbor(i)->flag_for_face_refinement(nb_indices.first,
- RefinementCase<dim-1>::cut_axis(0));
- if (refined_along_y + to_be_refined_along_y > 1)
- changed |= cell->neighbor(i)->flag_for_face_refinement(nb_indices.first,
- RefinementCase<dim-1>::cut_axis(1));
- }
- else
- {
- if (cell->neighbor(i)->refine_flag_set()!=RefinementCase<dim>::isotropic_refinement)
- changed=true;
- cell->neighbor(i)->set_refine_flag();
- }
-
-// step 4: if necessary (see above) add to the refine flag of the current cell
- cell_iterator nb=cell->neighbor(i);
- RefinementCase<dim-1> nb_frc
- = GeometryInfo<dim>::face_refinement_case(nb->refine_flag_set(),
- nb_indices.first,
- nb->face_orientation(nb_indices.first),
- nb->face_flip(nb_indices.first),
- nb->face_rotation(nb_indices.first));
- if ((nb_frc & RefinementCase<dim>::cut_x) &&
- !(refined_along_x || to_be_refined_along_x))
- changed |= cell->flag_for_face_refinement(i,RefinementCase<dim-1>::cut_axis(0));
- if ((nb_frc & RefinementCase<dim>::cut_y) &&
- !(refined_along_y || to_be_refined_along_y))
- changed |= cell->flag_for_face_refinement(i,RefinementCase<dim-1>::cut_axis(1));
- }
- }// if neighbor is coarser
- else // -> now the neighbor is not coarser
- {
- cell->neighbor(i)->clear_coarsen_flag();
- const unsigned int nb_nb=cell->neighbor_of_neighbor(i);
- const cell_iterator neighbor=cell->neighbor(i);
- RefinementCase<dim-1> face_ref_case=
- GeometryInfo<dim>::face_refinement_case(neighbor->refine_flag_set(),
- nb_nb,
- neighbor->face_orientation(nb_nb),
- neighbor->face_flip(nb_nb),
- neighbor->face_rotation(nb_nb));
- RefinementCase<dim-1> needed_face_ref_case
- =GeometryInfo<dim>::face_refinement_case(cell->refine_flag_set(),
- i,
- cell->face_orientation(i),
- cell->face_flip(i),
- cell->face_rotation(i));
- // if the
- // neighbor wants
- // to refine the
- // face with
- // cut_x and we
- // want cut_y or
- // vice versa, we
- // have to refine
- // isotropically
- // at the given
- // face
- if ((face_ref_case==RefinementCase<dim>::cut_x && needed_face_ref_case==RefinementCase<dim>::cut_y) ||
- (face_ref_case==RefinementCase<dim>::cut_y && needed_face_ref_case==RefinementCase<dim>::cut_x))
- {
- changed=cell->flag_for_face_refinement(i, face_ref_case);
- neighbor->flag_for_face_refinement(nb_nb, needed_face_ref_case);
- }
- }
- }
- else //-> the neighbor is not active
- {
- RefinementCase<dim-1> face_ref_case = cell->face(i)->refinement_case(),
- needed_face_ref_case = GeometryInfo<dim>::face_refinement_case(cell->refine_flag_set(),
- i,
- cell->face_orientation(i),
- cell->face_flip(i),
- cell->face_rotation(i));
- // if the face is
- // refined with cut_x
- // and we want cut_y
- // or vice versa, we
- // have to refine
- // isotropically at
- // the given face
- if ((face_ref_case==RefinementCase<dim>::cut_x && needed_face_ref_case==RefinementCase<dim>::cut_y) ||
- (face_ref_case==RefinementCase<dim>::cut_y && needed_face_ref_case==RefinementCase<dim>::cut_x))
- changed=cell->flag_for_face_refinement(i, face_ref_case);
- }
- }
- }
- }
- }
-
- //////////////////////////////////////
- // STEP 7:
- // take care that no double refinement
- // is done at each line in 3d or higher
- // dimensions.
- internal::Triangulation::Implementation::prepare_refinement_dim_dependent (*this);
-
- //////////////////////////////////////
- // STEP 8:
- // make sure that all children of each
- // cell are either flagged for coarsening
- // or none of the children is
- fix_coarsen_flags ();
- // get the refinement and coarsening
- // flags
- std::vector<bool> flags_after_loop[2];
- save_coarsen_flags (flags_after_loop[0]);
- save_refine_flags (flags_after_loop[1]);
-
- // find out whether something was
- // changed in this loop
- mesh_changed_in_this_loop
- = ((flags_before_loop[0] != flags_after_loop[0]) ||
- (flags_before_loop[1] != flags_after_loop[1]));
-
- // set the flags for the next loop
- // already
- flags_before_loop[0].swap(flags_after_loop[0]);
- flags_before_loop[1].swap(flags_after_loop[1]);
- }
- while (mesh_changed_in_this_loop);
-
-
- // find out whether something was really
- // changed in this function. Note that
- // @p{flags_before_loop} represents the
- // state after the last loop, i.e.
- // the present state
- return ((flags_before[0] != flags_before_loop[0]) ||
- (flags_before[1] != flags_before_loop[1]));
-}
-
-
-
-
-template <int dim, int spacedim>
-void Triangulation<dim, spacedim>::write_bool_vector (const unsigned int magic_number1,
- const std::vector<bool> &v,
- const unsigned int magic_number2,
- std::ostream &out)
-{
- const unsigned int N = v.size();
- unsigned char *flags = new unsigned char[N/8+1];
- for (unsigned int i=0; i<N/8+1; ++i) flags[i]=0;
-
- for (unsigned int position=0; position<N; ++position)
- flags[position/8] |= (v[position] ? (1<<(position%8)) : 0);
-
- AssertThrow (out, ExcIO());
-
- // format:
- // 0. magic number
- // 1. number of flags
- // 2. the flags
- // 3. magic number
- out << magic_number1 << ' ' << N << std::endl;
- for (unsigned int i=0; i<N/8+1; ++i)
- out << static_cast<unsigned int>(flags[i]) << ' ';
-
- out << std::endl << magic_number2 << std::endl;
-
- delete[] flags;
-
- AssertThrow (out, ExcIO());
-}
-
-
-template <int dim, int spacedim>
-void Triangulation<dim, spacedim>::read_bool_vector (const unsigned int magic_number1,
- std::vector<bool> &v,
- const unsigned int magic_number2,
- std::istream &in)
-{
- AssertThrow (in, ExcIO());
-
- unsigned int magic_number;
- in >> magic_number;
- AssertThrow (magic_number==magic_number1, ExcGridReadError());
-
- unsigned int N;
- in >> N;
- v.resize (N);
-
- unsigned char *flags = new unsigned char[N/8+1];
- unsigned short int tmp;
- for (unsigned int i=0; i<N/8+1; ++i)
- {
- in >> tmp;
- flags[i] = tmp;
- }
-
- for (unsigned int position=0; position!=N; ++position)
- v[position] = (flags[position/8] & (1<<(position%8)));
-
- in >> magic_number;
- AssertThrow (magic_number==magic_number2, ExcGridReadError());
-
- delete[] flags;
-
- AssertThrow (in, ExcIO());
-}
-
-
-
-template <int dim, int spacedim>
-unsigned int
-Triangulation<dim, spacedim>::memory_consumption () const
-{
- unsigned int mem = 0;
- mem += MemoryConsumption::memory_consumption(levels);
- for (unsigned int i=0; i<levels.size(); ++i)
- mem += MemoryConsumption::memory_consumption (*levels[i]);
- mem += MemoryConsumption::memory_consumption (vertices);
- mem += MemoryConsumption::memory_consumption (vertices_used);
- mem += sizeof(boundary);
- mem += sizeof(smooth_grid);
- mem += MemoryConsumption::memory_consumption (number_cache);
- mem += sizeof (faces);
- mem += MemoryConsumption::memory_consumption (*faces);
-
- return mem;
-}
-
-
-
-
-template<int dim, int spacedim>
-Triangulation<dim, spacedim>::RefinementListener::~RefinementListener ()
-{}
-
-
-
-template<int dim, int spacedim>
-Triangulation<dim, spacedim>::DistortedCellList::~DistortedCellList () throw ()
-{
- // don't do anything here. the compiler
- // will automatically convert any
- // exceptions created by the destructors of
- // the member variables into abort() in
- // order to satisfy the throw()
- // specification
-}
-
-
-
-
-template<int dim, int spacedim>
-void Triangulation<dim, spacedim>::
-RefinementListener::pre_refinement_notification (const Triangulation<dim, spacedim> &)
-{}
-
-
-
-template<int dim, int spacedim>
-void Triangulation<dim, spacedim>::
-RefinementListener::post_refinement_notification (const Triangulation<dim, spacedim> &)
-{}
-
-
-
-template<int dim, int spacedim>
-void Triangulation<dim, spacedim>::
-RefinementListener::copy_notification (const Triangulation<dim, spacedim> &,
- const Triangulation<dim, spacedim> &)
-{}
-
-
-
-template<int dim, int spacedim>
-void
-Triangulation<dim, spacedim>::add_refinement_listener (RefinementListener &listener) const
-{
- refinement_listeners.push_back (&listener);
-}
-
-
-
-template<int dim, int spacedim>
-void
-Triangulation<dim, spacedim>::remove_refinement_listener (RefinementListener &listener) const
-{
- typename std::list<RefinementListener *>::iterator p =
- std::find (refinement_listeners.begin (),
- refinement_listeners.end (),
- &listener);
- Assert (p != refinement_listeners.end (), ExcInternalError ());
- refinement_listeners.erase (p);
-}
-
-
-
-// explicit instantiations
-template class Triangulation<deal_II_dimension>;
-
-#if deal_II_dimension == 1
-template class Triangulation<1,2>;
-
-// this is a hack: we need to instantiate this one function because
-// TriaAccessor<1,1,3> uses it. We could instead instantiate
-// Triangulation<1,3>, but that requires a lot more specializations of
-// functions that currently only exist for <1,1> and <1,2>
-template
-const Boundary<1,3> &
-Triangulation<1,3>::get_boundary (const unsigned int number) const;
-
-#else
-# if deal_II_dimension == 2
-template class Triangulation<2,3>;
-# endif
-#endif
-
-DEAL_II_NAMESPACE_CLOSE
-
--- /dev/null
+//---------------------------------------------------------------------------
+// $Id$
+// Version: $Name$
+//
+// Copyright (C) 2010 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.
+//
+//---------------------------------------------------------------------------
+
+
+
+for (deal_II_dimension : DIMENSIONS)
+{
+ template class Triangulation<deal_II_dimension>;
+
+#if deal_II_dimension < 3
+ template class Triangulation<deal_II_dimension,deal_II_dimension+1>;
+#endif
+}