From: bangerth Date: Mon, 8 Dec 2008 18:45:16 +0000 (+0000) Subject: Work around the problem that gcc4.0 doesn't make member classes (and their respective... X-Git-Url: https://gitweb.dealii.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=0cf6e4bf1891f23e72778c16b418ecf063d8fc0a;p=dealii-svn.git Work around the problem that gcc4.0 doesn't make member classes (and their respective members) friends in the same way as members. The problem is described a bit more in the comment to the Implementation class in tria.cc. git-svn-id: https://svn.dealii.org/trunk@17892 0785d39b-7218-0410-832d-ea1e28bc413d --- diff --git a/deal.II/deal.II/include/dofs/dof_accessor.h b/deal.II/deal.II/include/dofs/dof_accessor.h index 93404e8092..35c039d3bf 100644 --- a/deal.II/deal.II/include/dofs/dof_accessor.h +++ b/deal.II/deal.II/include/dofs/dof_accessor.h @@ -29,6 +29,27 @@ template class Vector; template class TriaRawIterator; +namespace internal +{ + namespace DoFCellAccessor + { + struct Implementation; + } + + namespace DoFHandler + { + struct Implementation; + } + + namespace hp + { + namespace DoFHandler + { + struct Implementation; + } + } +} + // note: the file dof_accessor.templates.h is included at the end of @@ -66,7 +87,7 @@ namespace internal * See the full documentation for * more information. */ - typedef TriaAccessor BaseClass; + typedef dealii::TriaAccessor BaseClass; }; @@ -693,6 +714,9 @@ class DoFAccessor : public internal::DoFAccessor::Inheritance friend class DoFHandler; template friend class hp::DoFHandler; + + friend class internal::DoFHandler::Implementation; + friend class internal::hp::DoFHandler::Implementation; }; @@ -1197,16 +1221,6 @@ class DoFCellAccessor : public DoFAccessor */ private: - /** - * Forward declaration of a class - * into which we put some - * parts of the implementation. - * - * See the .cc file for more - * information. - */ - struct Implementation; - /** * Update the cache in which we * store the dof indices of this @@ -1221,6 +1235,8 @@ class DoFCellAccessor : public DoFAccessor * function */ template friend class DoFHandler; + + friend class internal::DoFCellAccessor::Implementation; }; diff --git a/deal.II/deal.II/include/dofs/dof_accessor.templates.h b/deal.II/deal.II/include/dofs/dof_accessor.templates.h index 2407a84df1..b38f3254c2 100644 --- a/deal.II/deal.II/include/dofs/dof_accessor.templates.h +++ b/deal.II/deal.II/include/dofs/dof_accessor.templates.h @@ -25,7 +25,6 @@ DEAL_II_NAMESPACE_OPEN - /*------------------------- Functions: DoFAccessor ---------------------------*/ @@ -541,338 +540,359 @@ DoFAccessor::quad (const unsigned int i) const /*------------------------- Functions: DoFCellAccessor -----------------------*/ +namespace internal +{ + namespace DoFCellAccessor + { + // make sure we refer to class + // dealii::DoFCellAccessor, not + // namespace + // internal::DoFCellAccessor + using dealii::DoFCellAccessor; + using dealii::DoFHandler; + /** * A class with the same purpose as the similarly named class of the * Triangulation class. See there for more information. */ -template -struct DoFCellAccessor::Implementation -{ - /** - * Implement the updating of the - * cache. Currently not - * implemented for hp::DoFHandler - * objects. - */ - template - static - void - update_cell_dof_indices_cache (const DoFCellAccessor > &accessor) - { - // check as in documentation that - // cell is either active, or dofs - // are only in vertices. otherwise - // simply don't update the cache at - // all. the get_dof_indices - // function will then make sure we - // don't access the invalid data - if (accessor.has_children() - && - (accessor.get_fe().dofs_per_cell != - accessor.get_fe().dofs_per_vertex * GeometryInfo<1>::vertices_per_cell)) - return; + struct Implementation + { + /** + * Implement the updating of the + * cache. Currently not + * implemented for hp::DoFHandler + * objects. + */ + template + static + void + update_cell_dof_indices_cache (const DoFCellAccessor > &accessor) + { + // check as in documentation that + // cell is either active, or dofs + // are only in vertices. otherwise + // simply don't update the cache at + // all. the get_dof_indices + // function will then make sure we + // don't access the invalid data + if (accessor.has_children() + && + (accessor.get_fe().dofs_per_cell != + accessor.get_fe().dofs_per_vertex * GeometryInfo<1>::vertices_per_cell)) + return; - const unsigned int dofs_per_vertex = accessor.get_fe().dofs_per_vertex, - dofs_per_line = accessor.get_fe().dofs_per_line, - dofs_per_cell = accessor.get_fe().dofs_per_cell; + const unsigned int dofs_per_vertex = accessor.get_fe().dofs_per_vertex, + dofs_per_line = accessor.get_fe().dofs_per_line, + dofs_per_cell = accessor.get_fe().dofs_per_cell; - // make sure the cache is at least - // as big as we need it when - // writing to the last element of - // this cell - Assert (accessor.present_index * dofs_per_cell + dofs_per_cell - <= - accessor.dof_handler->levels[accessor.present_level] - ->cell_dof_indices_cache.size(), - ExcInternalError()); + // make sure the cache is at least + // as big as we need it when + // writing to the last element of + // this cell + Assert (accessor.present_index * dofs_per_cell + dofs_per_cell + <= + accessor.dof_handler->levels[accessor.present_level] + ->cell_dof_indices_cache.size(), + ExcInternalError()); - std::vector::iterator next - = (accessor.dof_handler->levels[accessor.present_level] - ->cell_dof_indices_cache.begin() + accessor.present_index * dofs_per_cell); + std::vector::iterator next + = (accessor.dof_handler->levels[accessor.present_level] + ->cell_dof_indices_cache.begin() + accessor.present_index * dofs_per_cell); - for (unsigned int vertex=0; vertex<2; ++vertex) - for (unsigned int d=0; d - static - void - update_cell_dof_indices_cache (const DoFCellAccessor > &accessor) - { - // check as in documentation that - // cell is either active, or dofs - // are only in vertices. otherwise - // simply don't update the cache at - // all. the get_dof_indices - // function will then make sure we - // don't access the invalid data - if (accessor.has_children() - && - (accessor.get_fe().dofs_per_cell != - accessor.get_fe().dofs_per_vertex * GeometryInfo<2>::vertices_per_cell)) - return; + for (unsigned int vertex=0; vertex<2; ++vertex) + for (unsigned int d=0; d + static + void + update_cell_dof_indices_cache (const DoFCellAccessor > &accessor) + { + // check as in documentation that + // cell is either active, or dofs + // are only in vertices. otherwise + // simply don't update the cache at + // all. the get_dof_indices + // function will then make sure we + // don't access the invalid data + if (accessor.has_children() + && + (accessor.get_fe().dofs_per_cell != + accessor.get_fe().dofs_per_vertex * GeometryInfo<2>::vertices_per_cell)) + return; - const unsigned int dofs_per_vertex = accessor.get_fe().dofs_per_vertex, - dofs_per_line = accessor.get_fe().dofs_per_line, - dofs_per_quad = accessor.get_fe().dofs_per_quad, - dofs_per_cell = accessor.get_fe().dofs_per_cell; - - // make sure the cache is at least - // as big as we need it when - // writing to the last element of - // this cell - Assert (accessor.present_index * dofs_per_cell + dofs_per_cell - <= - accessor.dof_handler->levels[accessor.present_level] - ->cell_dof_indices_cache.size(), - ExcInternalError()); - - std::vector::iterator next - = (accessor.dof_handler->levels[accessor.present_level] - ->cell_dof_indices_cache.begin() + accessor.present_index * dofs_per_cell); - - for (unsigned int vertex=0; vertex<4; ++vertex) - for (unsigned int d=0; ddof_index(d); - for (unsigned int d=0; d - static - void - update_cell_dof_indices_cache (const DoFCellAccessor > &accessor) - { - // check as in documentation that - // cell is either active, or dofs - // are only in vertices. otherwise - // simply don't update the cache at - // all. the get_dof_indices - // function will then make sure we - // don't access the invalid data - if (accessor.has_children() - && - (accessor.get_fe().dofs_per_cell != - accessor.get_fe().dofs_per_vertex * GeometryInfo<3>::vertices_per_cell)) - return; + const unsigned int dofs_per_vertex = accessor.get_fe().dofs_per_vertex, + dofs_per_line = accessor.get_fe().dofs_per_line, + dofs_per_quad = accessor.get_fe().dofs_per_quad, + dofs_per_cell = accessor.get_fe().dofs_per_cell; + + // make sure the cache is at least + // as big as we need it when + // writing to the last element of + // this cell + Assert (accessor.present_index * dofs_per_cell + dofs_per_cell + <= + accessor.dof_handler->levels[accessor.present_level] + ->cell_dof_indices_cache.size(), + ExcInternalError()); + + std::vector::iterator next + = (accessor.dof_handler->levels[accessor.present_level] + ->cell_dof_indices_cache.begin() + accessor.present_index * dofs_per_cell); + + for (unsigned int vertex=0; vertex<4; ++vertex) + for (unsigned int d=0; ddof_index(d); + for (unsigned int d=0; d + static + void + update_cell_dof_indices_cache (const DoFCellAccessor > &accessor) + { + // check as in documentation that + // cell is either active, or dofs + // are only in vertices. otherwise + // simply don't update the cache at + // all. the get_dof_indices + // function will then make sure we + // don't access the invalid data + if (accessor.has_children() + && + (accessor.get_fe().dofs_per_cell != + accessor.get_fe().dofs_per_vertex * GeometryInfo<3>::vertices_per_cell)) + return; - const unsigned int dofs_per_vertex = accessor.get_fe().dofs_per_vertex, - dofs_per_line = accessor.get_fe().dofs_per_line, - dofs_per_quad = accessor.get_fe().dofs_per_quad, - dofs_per_hex = accessor.get_fe().dofs_per_hex, - dofs_per_cell = accessor.get_fe().dofs_per_cell; - - // make sure the cache is at least - // as big as we need it when - // writing to the last element of - // this cell - Assert (accessor.present_index * dofs_per_cell + dofs_per_cell - <= - accessor.dof_handler->levels[accessor.present_level] - ->cell_dof_indices_cache.size(), - ExcInternalError()); - - std::vector::iterator next - = (accessor.dof_handler->levels[accessor.present_level] - ->cell_dof_indices_cache.begin() + accessor.present_index * dofs_per_cell); - - for (unsigned int vertex=0; vertex<8; ++vertex) - for (unsigned int d=0; ddof_index(accessor.dof_handler->get_fe(). - adjust_line_dof_index_for_line_orientation(d, - accessor.line_orientation(line))); - // now copy dof numbers from the face. for - // faces with the wrong orientation, we - // have already made sure that we're ok by - // picking the correct lines and vertices - // (this happens automatically in the - // line() and vertex() functions). however, - // if the face is in wrong orientation, we - // look at it in flipped orientation and we - // will have to adjust the shape function - // indices that we see to correspond to the - // correct (cell-local) ordering. The same - // applies, if the face_rotation or - // face_orientation is non-standard - for (unsigned int quad=0; quad<6; ++quad) - for (unsigned int d=0; ddof_index(accessor.dof_handler->get_fe(). - adjust_quad_dof_index_for_face_orientation(d, - accessor.face_orientation(quad), - accessor.face_flip(quad), - accessor.face_rotation(quad))); - for (unsigned int d=0; d - static - void - update_cell_dof_indices_cache (const DoFCellAccessor > &) - { + const unsigned int dofs_per_vertex = accessor.get_fe().dofs_per_vertex, + dofs_per_line = accessor.get_fe().dofs_per_line, + dofs_per_quad = accessor.get_fe().dofs_per_quad, + dofs_per_hex = accessor.get_fe().dofs_per_hex, + dofs_per_cell = accessor.get_fe().dofs_per_cell; + + // make sure the cache is at least + // as big as we need it when + // writing to the last element of + // this cell + Assert (accessor.present_index * dofs_per_cell + dofs_per_cell + <= + accessor.dof_handler->levels[accessor.present_level] + ->cell_dof_indices_cache.size(), + ExcInternalError()); + + std::vector::iterator next + = (accessor.dof_handler->levels[accessor.present_level] + ->cell_dof_indices_cache.begin() + accessor.present_index * dofs_per_cell); + + for (unsigned int vertex=0; vertex<8; ++vertex) + for (unsigned int d=0; ddof_index(accessor.dof_handler->get_fe(). + adjust_line_dof_index_for_line_orientation(d, + accessor.line_orientation(line))); + // now copy dof numbers from the face. for + // faces with the wrong orientation, we + // have already made sure that we're ok by + // picking the correct lines and vertices + // (this happens automatically in the + // line() and vertex() functions). however, + // if the face is in wrong orientation, we + // look at it in flipped orientation and we + // will have to adjust the shape function + // indices that we see to correspond to the + // correct (cell-local) ordering. The same + // applies, if the face_rotation or + // face_orientation is non-standard + for (unsigned int quad=0; quad<6; ++quad) + for (unsigned int d=0; ddof_index(accessor.dof_handler->get_fe(). + adjust_quad_dof_index_for_face_orientation(d, + accessor.face_orientation(quad), + accessor.face_flip(quad), + accessor.face_rotation(quad))); + for (unsigned int d=0; d + static + void + update_cell_dof_indices_cache (const DoFCellAccessor > &) + { //TODO[WB]: should implement a dof indices cache for hp as well - // not implemented, but should also - // not be called - Assert (false, ExcNotImplemented()); - } - - - /** - * A function that collects the - * global indices of degrees of - * freedom. This function works - * for ::DoFHandler and all - * template arguments and copies - * the data out of the cache that - * we hold for each cell. - */ - template - static - void - get_dof_indices (const DoFCellAccessor > &accessor, - std::vector &dof_indices) - { - Assert (dof_indices.size() == accessor.get_fe().dofs_per_cell, - typename BaseClass::ExcVectorDoesNotMatch()); - - // check as in documentation that - // cell is either active, or dofs - // are only in vertices - Assert (!accessor.has_children() - || - (accessor.get_fe().dofs_per_cell == - accessor.get_fe().dofs_per_vertex * GeometryInfo::vertices_per_cell), - ExcMessage ("Cell must either be active, or all DoFs must be in vertices")); + // not implemented, but should also + // not be called + Assert (false, ExcNotImplemented()); + } + + + /** + * A function that collects the + * global indices of degrees of + * freedom. This function works + * for ::DoFHandler and all + * template arguments and copies + * the data out of the cache that + * we hold for each cell. + */ + template + static + void + get_dof_indices (const DoFCellAccessor > &accessor, + std::vector &dof_indices) + { + typedef + dealii::DoFAccessor > + BaseClass; + Assert (dof_indices.size() == accessor.get_fe().dofs_per_cell, + typename BaseClass::ExcVectorDoesNotMatch()); + + // check as in documentation that + // cell is either active, or dofs + // are only in vertices + Assert (!accessor.has_children() + || + (accessor.get_fe().dofs_per_cell == + accessor.get_fe().dofs_per_vertex * GeometryInfo::vertices_per_cell), + ExcMessage ("Cell must either be active, or all DoFs must be in vertices")); - unsigned int *cache = &accessor.dof_handler->levels[accessor.level()] - ->cell_dof_indices_cache[accessor.present_index * accessor.get_fe().dofs_per_cell]; - for (unsigned int i=0; i - static - void - get_dof_indices (const DoFCellAccessor > &accessor, - std::vector &dof_indices) - { - // no caching for hp::DoFHandler implemented - accessor.DoFAccessor >::get_dof_indices (dof_indices, - accessor.active_fe_index()); - } - - - /** - * Do what the active_fe_index - * function in the parent class - * is supposed to do. - */ - template - static - unsigned int - active_fe_index (const DoFCellAccessor > &) - { - // ::DoFHandler only supports a - // single active fe with index - // zero - return 0; - } - - - - template - static - unsigned int - active_fe_index (const DoFCellAccessor > &accessor) - { - Assert (static_cast(accessor.level()) < accessor.dof_handler->levels.size(), - ExcMessage ("DoFHandler not initialized")); - Assert (static_cast::size_type>(accessor.present_index) < - accessor.dof_handler->levels[accessor.level()]->active_fe_indices.size (), - ExcIndexRange (accessor.present_index, 0, - accessor.dof_handler->levels[accessor.level()]->active_fe_indices.size ())); - return accessor.dof_handler->levels[accessor.level()] - ->active_fe_indices[accessor.present_index]; - } - - - - /** - * Do what the - * set_active_fe_index function - * in the parent class is - * supposed to do. - */ - template - static - void - set_active_fe_index (const DoFCellAccessor > &, - const unsigned int i) - { - // ::DoFHandler only supports a - // single active fe with index - // zero - Assert (i == 0, typename BaseClass::ExcInvalidObject()); - } - - - - template - static - void - set_active_fe_index (DoFCellAccessor > &accessor, - const unsigned int i) - { - Assert (accessor.dof_handler != 0, - typename BaseClass::ExcInvalidObject()); - Assert (static_cast(accessor.level()) < - accessor.dof_handler->levels.size(), - ExcMessage ("DoFHandler not initialized")); - Assert (static_cast::size_type>(accessor.present_index) < - accessor.dof_handler->levels[accessor.level()]->active_fe_indices.size (), - ExcIndexRange (accessor.present_index, 0, - accessor.dof_handler->levels[accessor.level()]->active_fe_indices.size ())); - accessor.dof_handler->levels[accessor.level()] - ->active_fe_indices[accessor.present_index] = i; - } -}; + unsigned int *cache = &accessor.dof_handler->levels[accessor.level()] + ->cell_dof_indices_cache[accessor.present_index * accessor.get_fe().dofs_per_cell]; + for (unsigned int i=0; i + static + void + get_dof_indices (const DoFCellAccessor > &accessor, + std::vector &dof_indices) + { + // no caching for hp::DoFHandler implemented + accessor.dealii::DoFAccessor >::get_dof_indices (dof_indices, + accessor.active_fe_index()); + } + + + /** + * Do what the active_fe_index + * function in the parent class + * is supposed to do. + */ + template + static + unsigned int + active_fe_index (const DoFCellAccessor > &) + { + // ::DoFHandler only supports a + // single active fe with index + // zero + return 0; + } + + + + template + static + unsigned int + active_fe_index (const DoFCellAccessor > &accessor) + { + Assert (static_cast(accessor.level()) < accessor.dof_handler->levels.size(), + ExcMessage ("DoFHandler not initialized")); + Assert (static_cast::size_type>(accessor.present_index) < + accessor.dof_handler->levels[accessor.level()]->active_fe_indices.size (), + ExcIndexRange (accessor.present_index, 0, + accessor.dof_handler->levels[accessor.level()]->active_fe_indices.size ())); + return accessor.dof_handler->levels[accessor.level()] + ->active_fe_indices[accessor.present_index]; + } + + + + /** + * Do what the + * set_active_fe_index function + * in the parent class is + * supposed to do. + */ + template + static + void + set_active_fe_index (const DoFCellAccessor > &, + const unsigned int i) + { + // ::DoFHandler only supports a + // single active fe with index + // zero + typedef + dealii::DoFAccessor > + BaseClass; + Assert (i == 0, typename BaseClass::ExcInvalidObject()); + } + + + + template + static + void + set_active_fe_index (DoFCellAccessor > &accessor, + const unsigned int i) + { + typedef + dealii::DoFAccessor > + BaseClass; + Assert (accessor.dof_handler != 0, + typename BaseClass::ExcInvalidObject()); + Assert (static_cast(accessor.level()) < + accessor.dof_handler->levels.size(), + ExcMessage ("DoFHandler not initialized")); + Assert (static_cast::size_type>(accessor.present_index) < + accessor.dof_handler->levels[accessor.level()]->active_fe_indices.size (), + ExcIndexRange (accessor.present_index, 0, + accessor.dof_handler->levels[accessor.level()]->active_fe_indices.size ())); + accessor.dof_handler->levels[accessor.level()] + ->active_fe_indices[accessor.present_index] = i; + } + }; + } +} @@ -969,7 +989,7 @@ void DoFCellAccessor:: get_dof_indices (std::vector &dof_indices) const { - Implementation::get_dof_indices (*this, dof_indices); + internal::DoFCellAccessor::Implementation::get_dof_indices (*this, dof_indices); } @@ -989,7 +1009,7 @@ inline unsigned int DoFCellAccessor::active_fe_index () const { - return Implementation::active_fe_index (*this); + return internal::DoFCellAccessor::Implementation::active_fe_index (*this); } @@ -999,7 +1019,7 @@ inline void DoFCellAccessor::set_active_fe_index (const unsigned int i) { - Implementation::set_active_fe_index (*this, i); + internal::DoFCellAccessor::Implementation::set_active_fe_index (*this, i); } diff --git a/deal.II/deal.II/include/dofs/dof_faces.h b/deal.II/deal.II/include/dofs/dof_faces.h index 33e51963b5..3e4b4f1e88 100644 --- a/deal.II/deal.II/include/dofs/dof_faces.h +++ b/deal.II/deal.II/include/dofs/dof_faces.h @@ -2,7 +2,7 @@ // $Id$ // Version: $Name$ // -// Copyright (C) 2006, 2007 by the deal.II authors +// Copyright (C) 2006, 2007, 2008 by the deal.II authors // // This file is subject to QPL and may not be distributed // without copyright and license information. Please refer @@ -100,29 +100,19 @@ namespace internal template<> class DoFFaces<2> { - private: + public: /** - * The object containing the data of DoFs on lines. + * The object containing the + * data of DoFs on lines. */ internal::DoFHandler::DoFObjects<1> lines; - public: /** * Determine an estimate for the * memory consumption (in bytes) * of this object. */ unsigned int memory_consumption () const; - - /** - * Make the DoFHandler and - * MGDoFHandler classes a - * friend, so that it can - * resize arrays as - * necessary. - */ - template friend class dealii::DoFHandler; - template friend class dealii::MGDoFHandler; }; /** @@ -134,33 +124,25 @@ namespace internal template<> class DoFFaces<3> { - private: + public: /** - * The object containing the data of DoFs on lines. + * The object containing the + * data of DoFs on lines. */ internal::DoFHandler::DoFObjects<1> lines; + /** - * The object containing the data of DoFs on quads. + * The object containing the + * data of DoFs on quads. */ internal::DoFHandler::DoFObjects<2> quads; - public: /** * Determine an estimate for the * memory consumption (in bytes) * of this object. */ unsigned int memory_consumption () const; - - /** - * Make the DoFHandler and - * MGDoFHandler classes a - * friend, so that it can - * resize arrays as - * necessary. - */ - template friend class dealii::DoFHandler; - template friend class dealii::MGDoFHandler; }; } diff --git a/deal.II/deal.II/include/dofs/dof_handler.h b/deal.II/deal.II/include/dofs/dof_handler.h index cab7749455..00ef5ebb07 100644 --- a/deal.II/deal.II/include/dofs/dof_handler.h +++ b/deal.II/deal.II/include/dofs/dof_handler.h @@ -33,6 +33,13 @@ namespace internal { template class DoFLevel; template class DoFFaces; + + struct Implementation; + } + + namespace DoFCellAccessor + { + struct Implementation; } } @@ -1203,28 +1210,14 @@ class DoFHandler : public Subscriptor */ std::vector vertex_dofs; - /** - * Forward declaration of a class - * into which we put significant - * parts of the implementation. - * - * See the .cc file for more - * information. - */ - struct Implementation; - /* * Make accessor objects friends. */ - template friend class DoFAccessor; - - /* - * Same with cell accessor - */ - template friend class DoFCellAccessor; - + template friend class DoFAccessor; + template friend class DoFCellAccessor; + friend class internal::DoFCellAccessor::Implementation; - friend class DoFHandler::Implementation; + friend class internal::DoFHandler::Implementation; }; diff --git a/deal.II/deal.II/include/dofs/dof_levels.h b/deal.II/deal.II/include/dofs/dof_levels.h index 498bee8e4a..05716874af 100644 --- a/deal.II/deal.II/include/dofs/dof_levels.h +++ b/deal.II/deal.II/include/dofs/dof_levels.h @@ -2,7 +2,7 @@ // $Id$ // Version: $Name$ // -// Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006 by the deal.II authors +// Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2008 by the deal.II authors // // This file is subject to QPL and may not be distributed // without copyright and license information. Please refer @@ -130,30 +130,19 @@ namespace internal template <> class DoFLevel<1> : public DoFLevel<0> { - private: + public: /** * The object containing dof-indices * and related access-functions */ DoFObjects<1> lines; - public: /** * Determine an estimate for the * memory consumption (in bytes) * of this object. */ unsigned int memory_consumption () const; - - /** - * Make the DoFHandler and - * MGDoFHandler classes a - * friend, so that it can - * resize arrays as - * necessary. - */ - template friend class dealii::DoFHandler; - template friend class dealii::MGDoFHandler; }; @@ -167,30 +156,19 @@ namespace internal template <> class DoFLevel<2> : public DoFLevel<0> { - private: + public: /** * The object containing dof-indices * and related access-functions */ internal::DoFHandler::DoFObjects<2> quads; - public: /** * Determine an estimate for the * memory consumption (in bytes) * of this object. */ unsigned int memory_consumption () const; - - /** - * Make the DoFHandler and - * MGDoFHandler classes a - * friend, so that it can - * resize arrays as - * necessary. - */ - template friend class dealii::DoFHandler; - template friend class dealii::MGDoFHandler; }; @@ -204,14 +182,12 @@ namespace internal template <> class DoFLevel<3> : public DoFLevel<0> { - private: + public: /** * The object containing dof-indices * and related access-functions */ internal::DoFHandler::DoFObjects<3> hexes; - - public: /** * Determine an estimate for the @@ -219,16 +195,6 @@ namespace internal * of this object. */ unsigned int memory_consumption () const; - - /** - * Make the DoFHandler and - * MGDoFHandler classes a - * friend, so that it can - * resize arrays as - * necessary. - */ - template friend class dealii::DoFHandler; - template friend class dealii::MGDoFHandler; }; } diff --git a/deal.II/deal.II/include/grid/tria.h b/deal.II/deal.II/include/grid/tria.h index 4f9ae16e59..fbcc6209e3 100644 --- a/deal.II/deal.II/include/grid/tria.h +++ b/deal.II/deal.II/include/grid/tria.h @@ -38,8 +38,23 @@ namespace internal { template class TriaLevel; template class TriaFaces; + + /** + * Forward declaration of a class into + * which we put much of the + * implementation of the Triangulation + * class. See the .cc file for more + * information. + */ + struct Implementation; + } + + namespace TriaAccessor + { + struct Implementation; } } + template class DoFHandler; namespace hp { @@ -2907,35 +2922,6 @@ class Triangulation : public Subscriptor int, << "The given level " << arg1 << " is not in the valid range!"); - /** - * 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); - /** - * Trying to re-read a grid, an error occured. - * - * @ingroup Exceptions - */ - DeclException0 (ExcGridReadError); /** * The function raising this * exception can only operate on @@ -2947,92 +2933,16 @@ class Triangulation : public Subscriptor */ DeclException0 (ExcTriangulationNotEmpty); /** - * 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. + * Trying to re-read a grid, an error occured. * * @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); + DeclException0 (ExcGridReadError); /** * Exception * @ingroup Exceptions */ DeclException0 (ExcFacesHaveNoLevel); - /** - * Exception - * @ingroup Exceptions - */ - DeclException2 (ExcMultiplySetLineInfoOfLine, - int, int, - << "In SubCellData the line info of the line with vertex indices " - << arg1 << " and " << arg2 << " is multiply set."); /** * The triangulation level you * accessed is empty. @@ -3236,41 +3146,17 @@ class Triangulation : public Subscriptor */ mutable std::list refinement_listeners; - /** - * Forward declaration of a class - * into which we put significant - * parts of the implementation. - * - * See the .cc file for more - * information. - */ - struct Implementation; - // make a couple of classes // friends template friend class TriaAccessorBase; template friend class TriaAccessor; - - template - friend class TriaAccessor; - friend class CellAccessor; - - friend class TriaRawIterator >; - friend class TriaRawIterator >; - - friend class TriaRawIterator >; - friend class TriaRawIterator >; - friend class TriaRawIterator >; - friend class TriaRawIterator >; - friend class TriaRawIterator >; - friend class TriaRawIterator >; - friend class TriaRawIterator >; + friend class internal::TriaAccessor::Implementation; friend class hp::DoFHandler; - friend class Triangulation::Implementation; + friend class internal::Triangulation::Implementation; }; diff --git a/deal.II/deal.II/include/grid/tria_accessor.h b/deal.II/deal.II/include/grid/tria_accessor.h index f9ec8c6eeb..d749a309de 100644 --- a/deal.II/deal.II/include/grid/tria_accessor.h +++ b/deal.II/deal.II/include/grid/tria_accessor.h @@ -43,6 +43,12 @@ namespace internal { template class TriaObject; template class TriaObjects; + struct Implementation; + } + + namespace TriaAccessor + { + struct Implementation; } } template class TriaAccessor; @@ -1516,20 +1522,10 @@ class TriaAccessor : public TriaAccessorBase */ void operator = (const TriaAccessor &); - /** - * Forward declaration of a class - * into which we put significant - * parts of the implementation. - * - * See the .templates.h file for - * more information. - */ - struct Implementation; - - template friend class Triangulation; - - friend class Implementation; + + friend class internal::Triangulation::Implementation; + friend class internal::TriaAccessor::Implementation; }; diff --git a/deal.II/deal.II/include/grid/tria_accessor.templates.h b/deal.II/deal.II/include/grid/tria_accessor.templates.h index fadf48bb51..19f95e2e4b 100644 --- a/deal.II/deal.II/include/grid/tria_accessor.templates.h +++ b/deal.II/deal.II/include/grid/tria_accessor.templates.h @@ -502,587 +502,600 @@ InvalidAccessor::operator -- () const /*------------------------ Functions: TriaAccessor ---------------------------*/ +namespace internal +{ + namespace TriaAccessor + { + // make sure that if in the following we + // write TriaAccessor + // we mean the *class* + // dealii::TriaAccessor, not the + // enclosing namespace + // internal::TriaAccessor + using dealii::TriaAccessor; + /** * A class with the same purpose as the similarly named class of the * Triangulation class. See there for more information. */ -template -struct TriaAccessor::Implementation -{ - /** - * Implementation of the function - * of some name in the mother - * class. - */ - template - static - unsigned int - line_index (const TriaAccessor<1, dim, spacedim> &, - const unsigned int) - { - Assert (false, - ExcMessage ("You can't ask for the index of a line bounding " - "a one-dimensional cell because it is not " - "bounded by lines.")); - return numbers::invalid_unsigned_int; - } - - - template - static - unsigned int - line_index (const TriaAccessor<2, dim, spacedim> &accessor, - const unsigned int i) - { - return accessor.objects().cells[accessor.present_index].face(i); - } + struct Implementation + { + /** + * Implementation of the function + * of some name in the mother + * class. + */ + template + static + unsigned int + line_index (const TriaAccessor<1, dim, spacedim> &, + const unsigned int) + { + Assert (false, + ExcMessage ("You can't ask for the index of a line bounding " + "a one-dimensional cell because it is not " + "bounded by lines.")); + return numbers::invalid_unsigned_int; + } + + + template + static + unsigned int + line_index (const TriaAccessor<2, dim, spacedim> &accessor, + const unsigned int i) + { + return accessor.objects().cells[accessor.present_index].face(i); + } - template - static - unsigned int - line_index (const TriaAccessor<3, dim, spacedim> &accessor, - const unsigned int i) - { - // get the line index by asking the - // quads. first assume standard orientation - // - // set up a table that for each - // line describes a) from which - // quad to take it, b) which line - // therein it is if the face is - // oriented correctly - static const unsigned int lookup_table[12][2] = - { { 4, 0 }, // take first four lines from bottom face - { 4, 1 }, - { 4, 2 }, - { 4, 3 }, - - { 5, 0 }, // second four lines from top face - { 5, 1 }, - { 5, 2 }, - { 5, 3 }, - - { 0, 0 }, // the rest randomly - { 1, 0 }, - { 0, 1 }, - { 1, 1 }}; - - // respect non-standard faces by calling the - // reordering function from GeometryInfo - - const unsigned int quad_index=lookup_table[i][0]; - const unsigned int std_line_index=lookup_table[i][1]; + template + static + unsigned int + line_index (const TriaAccessor<3, dim, spacedim> &accessor, + const unsigned int i) + { + // get the line index by asking the + // quads. first assume standard orientation + // + // set up a table that for each + // line describes a) from which + // quad to take it, b) which line + // therein it is if the face is + // oriented correctly + static const unsigned int lookup_table[12][2] = + { { 4, 0 }, // take first four lines from bottom face + { 4, 1 }, + { 4, 2 }, + { 4, 3 }, + + { 5, 0 }, // second four lines from top face + { 5, 1 }, + { 5, 2 }, + { 5, 3 }, + + { 0, 0 }, // the rest randomly + { 1, 0 }, + { 0, 1 }, + { 1, 1 }}; + + // respect non-standard faces by calling the + // reordering function from GeometryInfo + + const unsigned int quad_index=lookup_table[i][0]; + const unsigned int std_line_index=lookup_table[i][1]; - const unsigned int line_index=GeometryInfo::standard_to_real_face_line( - std_line_index, - accessor.face_orientation(quad_index), - accessor.face_flip(quad_index), - accessor.face_rotation(quad_index)); - - return (accessor.quad(quad_index)->line_index(line_index)); - } - - - - /** - * Implementation of the function - * of some name in the mother - * class. - */ - template - static - unsigned int - quad_index (const TriaAccessor &, - const unsigned int) - { - Assert (false, - ExcMessage ("You can't ask for the index of a quad bounding " - "a one- or two-dimensional cell because it is not " - "bounded by quads.")); - return numbers::invalid_unsigned_int; - } + const unsigned int line_index=GeometryInfo::standard_to_real_face_line( + std_line_index, + accessor.face_orientation(quad_index), + accessor.face_flip(quad_index), + accessor.face_rotation(quad_index)); + + return (accessor.quad(quad_index)->line_index(line_index)); + } + + + + /** + * Implementation of the function + * of some name in the mother + * class. + */ + template + static + unsigned int + quad_index (const TriaAccessor &, + const unsigned int) + { + Assert (false, + ExcMessage ("You can't ask for the index of a quad bounding " + "a one- or two-dimensional cell because it is not " + "bounded by quads.")); + return numbers::invalid_unsigned_int; + } - template - static - unsigned int - quad_index (const TriaAccessor<3, dim, spacedim> &accessor, - const unsigned int i) - { - Assert (i::quads_per_cell, - ExcIndexRange(i,0,GeometryInfo<3>::quads_per_cell)); - return accessor.tria->levels[accessor.present_level] - ->cells.cells[accessor.present_index].face(i); - } - - - - /** - * Implementation of the function - * of some name in the mother - * class. - */ - template - static - bool - face_orientation (const TriaAccessor &, - const unsigned int) - { - return true; - } + template + static + unsigned int + quad_index (const TriaAccessor<3, dim, spacedim> &accessor, + const unsigned int i) + { + Assert (i::quads_per_cell, + ExcIndexRange(i,0,GeometryInfo<3>::quads_per_cell)); + return accessor.tria->levels[accessor.present_level] + ->cells.cells[accessor.present_index].face(i); + } + + + + /** + * Implementation of the function + * of some name in the mother + * class. + */ + template + static + bool + face_orientation (const TriaAccessor &, + const unsigned int) + { + return true; + } - template - static - bool - face_orientation (const TriaAccessor<3, dim, spacedim> &accessor, - const unsigned int face) - { - return (accessor.tria->levels[accessor.present_level] - ->cells.face_orientation(accessor.present_index, face)); - } - - - - /** - * Implementation of the function - * of some name in the mother - * class. - */ - template - static - bool - face_flip (const TriaAccessor &, - const unsigned int) - { - return true; - } - - - template - static - bool - face_flip (const TriaAccessor<3, dim, spacedim> &accessor, - const unsigned int face) - { - Assert (face::faces_per_cell, - ExcIndexRange (face, 0, GeometryInfo<3>::faces_per_cell)); - Assert (accessor.present_index * GeometryInfo<3>::faces_per_cell + face - < accessor.tria->levels[accessor.present_level] - ->cells.face_flips.size(), - ExcInternalError()); - - return (accessor.tria->levels[accessor.present_level] - ->cells.face_flips[accessor.present_index * - GeometryInfo<3>::faces_per_cell - + face]); - } - - - - /** - * Implementation of the function - * of some name in the mother - * class. - */ - template - static - bool - face_rotation (const TriaAccessor &, + template + static + bool + face_orientation (const TriaAccessor<3, dim, spacedim> &accessor, + const unsigned int face) + { + return (accessor.tria->levels[accessor.present_level] + ->cells.face_orientation(accessor.present_index, face)); + } + + + + /** + * Implementation of the function + * of some name in the mother + * class. + */ + template + static + bool + face_flip (const TriaAccessor &, const unsigned int) - { - return true; - } + { + return true; + } - template - static - bool - face_rotation (const TriaAccessor<3, dim, spacedim> &accessor, - const unsigned int face) - { - Assert (face::faces_per_cell, - ExcIndexRange (face, 0, GeometryInfo<3>::faces_per_cell)); - Assert (accessor.present_index * GeometryInfo<3>::faces_per_cell + face - < accessor.tria->levels[accessor.present_level] - ->cells.face_rotations.size(), - ExcInternalError()); - - return (accessor.tria->levels[accessor.present_level] - ->cells.face_rotations[accessor.present_index * + template + static + bool + face_flip (const TriaAccessor<3, dim, spacedim> &accessor, + const unsigned int face) + { + Assert (face::faces_per_cell, + ExcIndexRange (face, 0, GeometryInfo<3>::faces_per_cell)); + Assert (accessor.present_index * GeometryInfo<3>::faces_per_cell + face + < accessor.tria->levels[accessor.present_level] + ->cells.face_flips.size(), + ExcInternalError()); + + return (accessor.tria->levels[accessor.present_level] + ->cells.face_flips[accessor.present_index * GeometryInfo<3>::faces_per_cell + face]); - } - - /** - * Implementation of the function - * of some name in the mother - * class. - */ - template - static - bool - line_orientation (const TriaAccessor<1, dim, spacedim> &, - const unsigned int) - { - return true; - } + } + + + + /** + * Implementation of the function + * of some name in the mother + * class. + */ + template + static + bool + face_rotation (const TriaAccessor &, + const unsigned int) + { + return true; + } - template - static - bool - line_orientation (const TriaAccessor<2, 2, spacedim> &, - const unsigned int) - { - // quads in 2d have no - // non-standard orientation - return true; - } - + template + static + bool + face_rotation (const TriaAccessor<3, dim, spacedim> &accessor, + const unsigned int face) + { + Assert (face::faces_per_cell, + ExcIndexRange (face, 0, GeometryInfo<3>::faces_per_cell)); + Assert (accessor.present_index * GeometryInfo<3>::faces_per_cell + face + < accessor.tria->levels[accessor.present_level] + ->cells.face_rotations.size(), + ExcInternalError()); + + return (accessor.tria->levels[accessor.present_level] + ->cells.face_rotations[accessor.present_index * + GeometryInfo<3>::faces_per_cell + + face]); + } + + /** + * Implementation of the function + * of some name in the mother + * class. + */ + template + static + bool + line_orientation (const TriaAccessor<1, dim, spacedim> &, + const unsigned int) + { + return true; + } + - template - static - bool - line_orientation (const TriaAccessor<2, 3, spacedim> &accessor, - const unsigned int line) - { - // quads as part of 3d hexes - // can have non-standard - // orientation + template + static + bool + line_orientation (const TriaAccessor<2, 2, spacedim> &, + const unsigned int) + { + // quads in 2d have no + // non-standard orientation + return true; + } + + + template + static + bool + line_orientation (const TriaAccessor<2, 3, spacedim> &accessor, + const unsigned int line) + { + // quads as part of 3d hexes + // can have non-standard + // orientation //TODO: why is this face_orientation, not line_orientation as in the setter function? - return accessor.tria->faces->quads.face_orientation(accessor.present_index, line); - } + return accessor.tria->faces->quads.face_orientation(accessor.present_index, line); + } - template - static - bool - line_orientation (const TriaAccessor<3, dim, spacedim> &accessor, - const unsigned int line) - { - Assert (accessor.used(), TriaAccessorExceptions::ExcCellNotUsed()); - Assert (line::lines_per_cell, - ExcIndexRange (line, 0, GeometryInfo<3>::lines_per_cell)); - - // get the line index by asking the - // quads. first assume standard orientation - // - // set up a table that for each - // line describes a) from which - // quad to take it, b) which line - // therein it is if the face is - // oriented correctly - static const unsigned int lookup_table[12][2] = - { { 4, 0 }, // take first four lines from bottom face - { 4, 1 }, - { 4, 2 }, - { 4, 3 }, - - { 5, 0 }, // second four lines from top face - { 5, 1 }, - { 5, 2 }, - { 5, 3 }, - - { 0, 0 }, // the rest randomly - { 1, 0 }, - { 0, 1 }, - { 1, 1 }}; - - const unsigned int quad_index=lookup_table[line][0]; - const unsigned int std_line_index=lookup_table[line][1]; + template + static + bool + line_orientation (const TriaAccessor<3, dim, spacedim> &accessor, + const unsigned int line) + { + Assert (accessor.used(), TriaAccessorExceptions::ExcCellNotUsed()); + Assert (line::lines_per_cell, + ExcIndexRange (line, 0, GeometryInfo<3>::lines_per_cell)); + + // get the line index by asking the + // quads. first assume standard orientation + // + // set up a table that for each + // line describes a) from which + // quad to take it, b) which line + // therein it is if the face is + // oriented correctly + static const unsigned int lookup_table[12][2] = + { { 4, 0 }, // take first four lines from bottom face + { 4, 1 }, + { 4, 2 }, + { 4, 3 }, + + { 5, 0 }, // second four lines from top face + { 5, 1 }, + { 5, 2 }, + { 5, 3 }, + + { 0, 0 }, // the rest randomly + { 1, 0 }, + { 0, 1 }, + { 1, 1 }}; + + const unsigned int quad_index=lookup_table[line][0]; + const unsigned int std_line_index=lookup_table[line][1]; - const unsigned int line_index=GeometryInfo::standard_to_real_face_line( - std_line_index, - accessor.face_orientation(quad_index), - accessor.face_flip(quad_index), - accessor.face_rotation(quad_index)); + const unsigned int line_index=GeometryInfo::standard_to_real_face_line( + std_line_index, + accessor.face_orientation(quad_index), + accessor.face_flip(quad_index), + accessor.face_rotation(quad_index)); - // now we got to the correct line and ask - // the quad for its line_orientation. however, if - // the face is rotated, it might be possible, - // that a standard orientation of the line - // with respect to the face corrsponds to a - // non-standard orientation for the line with - // respect to the cell. - // - // set up a table indicating if the two - // standard orientations coincide - // - // first index: two pairs of lines 0(lines - // 0/1) and 1(lines 2/3) - // - // second index: face_orientation; 0: - // opposite normal, 1: standard - // - // third index: face_flip; 0: standard, 1: - // face rotated by 180 degrees - // - // forth index: face_rotation: 0: standard, - // 1: face rotated by 90 degrees - - static const bool bool_table[2][2][2][2] = - { { { { true, false }, // lines 0/1, face_orientation=false, face_flip=false, face_rotation=false and true - { false, true }}, // lines 0/1, face_orientation=false, face_flip=true, face_rotation=false and true - { { true, true }, // lines 0/1, face_orientation=true, face_flip=false, face_rotation=false and true - { false, false }}},// linea 0/1, face_orientation=true, face_flip=true, face_rotation=false and true - - { { { true, true }, // lines 2/3 ... - { false, false }}, - { { true, false }, - { false, true }}}}; + // now we got to the correct line and ask + // the quad for its line_orientation. however, if + // the face is rotated, it might be possible, + // that a standard orientation of the line + // with respect to the face corrsponds to a + // non-standard orientation for the line with + // respect to the cell. + // + // set up a table indicating if the two + // standard orientations coincide + // + // first index: two pairs of lines 0(lines + // 0/1) and 1(lines 2/3) + // + // second index: face_orientation; 0: + // opposite normal, 1: standard + // + // third index: face_flip; 0: standard, 1: + // face rotated by 180 degrees + // + // forth index: face_rotation: 0: standard, + // 1: face rotated by 90 degrees + + static const bool bool_table[2][2][2][2] = + { { { { true, false }, // lines 0/1, face_orientation=false, face_flip=false, face_rotation=false and true + { false, true }}, // lines 0/1, face_orientation=false, face_flip=true, face_rotation=false and true + { { true, true }, // lines 0/1, face_orientation=true, face_flip=false, face_rotation=false and true + { false, false }}},// linea 0/1, face_orientation=true, face_flip=true, face_rotation=false and true + + { { { true, true }, // lines 2/3 ... + { false, false }}, + { { true, false }, + { false, true }}}}; - return (accessor.quad(quad_index) - ->line_orientation(line_index) - == bool_table[std_line_index/2] - [accessor.face_orientation(quad_index)] - [accessor.face_flip(quad_index)] - [accessor.face_rotation(quad_index)]); - } - - - - /** - * Implementation of the function - * of some name in the mother - * class. - */ - template - static - void - set_face_orientation (const TriaAccessor &, - const unsigned int, - const bool) - { - Assert (false, ExcInternalError()); - } + return (accessor.quad(quad_index) + ->line_orientation(line_index) + == bool_table[std_line_index/2] + [accessor.face_orientation(quad_index)] + [accessor.face_flip(quad_index)] + [accessor.face_rotation(quad_index)]); + } + + + + /** + * Implementation of the function + * of some name in the mother + * class. + */ + template + static + void + set_face_orientation (const TriaAccessor &, + const unsigned int, + const bool) + { + Assert (false, ExcInternalError()); + } - template - static - void - set_face_orientation (const TriaAccessor<3, dim, spacedim> &accessor, - const unsigned int face, - const bool value) - { - Assert (accessor.used(), TriaAccessorExceptions::ExcCellNotUsed()); - Assert (face::faces_per_cell, - ExcIndexRange (face, 0, GeometryInfo<3>::faces_per_cell)); - Assert (accessor.present_index * GeometryInfo<3>::faces_per_cell + face - < accessor.tria->levels[accessor.present_level] - ->cells.face_orientations.size(), - ExcInternalError()); - accessor.tria->levels[accessor.present_level] - ->cells.face_orientations[accessor.present_index * - GeometryInfo<3>::faces_per_cell - + - face] = value; - } - - - - /** - * Implementation of the function - * of some name in the mother - * class. - */ - template - static - void - set_face_flip (const TriaAccessor &, - const unsigned int, - const bool) - { - Assert (false, ExcInternalError()); - } - - - template - static - void - set_face_flip (const TriaAccessor<3, dim, spacedim> &accessor, - const unsigned int face, - const bool value) - { - Assert (face::faces_per_cell, - ExcIndexRange (face, 0, GeometryInfo<3>::faces_per_cell)); - Assert (accessor.present_index * GeometryInfo<3>::faces_per_cell + face - < accessor.tria->levels[accessor.present_level] - ->cells.face_flips.size(), - ExcInternalError()); - - accessor.tria->levels[accessor.present_level] - ->cells.face_flips[accessor.present_index * - GeometryInfo<3>::faces_per_cell - + face] = value; - } - - - - /** - * Implementation of the function - * of some name in the mother - * class. - */ - template - static - void - set_face_rotation (const TriaAccessor &, + template + static + void + set_face_orientation (const TriaAccessor<3, dim, spacedim> &accessor, + const unsigned int face, + const bool value) + { + Assert (accessor.used(), TriaAccessorExceptions::ExcCellNotUsed()); + Assert (face::faces_per_cell, + ExcIndexRange (face, 0, GeometryInfo<3>::faces_per_cell)); + Assert (accessor.present_index * GeometryInfo<3>::faces_per_cell + face + < accessor.tria->levels[accessor.present_level] + ->cells.face_orientations.size(), + ExcInternalError()); + accessor.tria->levels[accessor.present_level] + ->cells.face_orientations[accessor.present_index * + GeometryInfo<3>::faces_per_cell + + + face] = value; + } + + + + /** + * Implementation of the function + * of some name in the mother + * class. + */ + template + static + void + set_face_flip (const TriaAccessor &, const unsigned int, const bool) - { - Assert (false, ExcInternalError()); - } + { + Assert (false, ExcInternalError()); + } - template - static - void - set_face_rotation (const TriaAccessor<3, dim, spacedim> &accessor, + template + static + void + set_face_flip (const TriaAccessor<3, dim, spacedim> &accessor, const unsigned int face, const bool value) - { - Assert (face::faces_per_cell, - ExcIndexRange (face, 0, GeometryInfo<3>::faces_per_cell)); - Assert (accessor.present_index * GeometryInfo<3>::faces_per_cell + face - < accessor.tria->levels[accessor.present_level] - ->cells.face_rotations.size(), - ExcInternalError()); - - accessor.tria->levels[accessor.present_level] - ->cells.face_rotations[accessor.present_index * + { + Assert (face::faces_per_cell, + ExcIndexRange (face, 0, GeometryInfo<3>::faces_per_cell)); + Assert (accessor.present_index * GeometryInfo<3>::faces_per_cell + face + < accessor.tria->levels[accessor.present_level] + ->cells.face_flips.size(), + ExcInternalError()); + + accessor.tria->levels[accessor.present_level] + ->cells.face_flips[accessor.present_index * GeometryInfo<3>::faces_per_cell + face] = value; - } - - /** - * Implementation of the function - * of some name in the mother - * class. - */ - template - static - void - set_line_orientation (const TriaAccessor<1, dim, spacedim> &, - const unsigned int, - const bool) - { - Assert (false, ExcInternalError()); - } + } + + + + /** + * Implementation of the function + * of some name in the mother + * class. + */ + template + static + void + set_face_rotation (const TriaAccessor &, + const unsigned int, + const bool) + { + Assert (false, ExcInternalError()); + } - template - static - void - set_line_orientation (const TriaAccessor<2, 2, spacedim> &, - const unsigned int, - const bool) - { - // quads in 2d have no - // non-standard orientation - Assert (false, ExcInternalError()); - } - - - template - static - void - set_line_orientation (const TriaAccessor<2, 3, spacedim> &accessor, - const unsigned int line, - const bool value) - { - Assert (accessor.used(), TriaAccessorExceptions::ExcCellNotUsed()); - Assert (line::lines_per_face, - ExcIndexRange (line, 0, GeometryInfo<3>::lines_per_face)); - Assert (accessor.present_index * GeometryInfo<3>::lines_per_face + line - < accessor.tria->faces->quads.line_orientations.size(), - ExcInternalError()); - // quads as part of 3d hexes - // can have non-standard - // orientation - accessor.tria->faces->quads.line_orientations[accessor.present_index * - GeometryInfo<3>::lines_per_face - + line] - = value; - } + template + static + void + set_face_rotation (const TriaAccessor<3, dim, spacedim> &accessor, + const unsigned int face, + const bool value) + { + Assert (face::faces_per_cell, + ExcIndexRange (face, 0, GeometryInfo<3>::faces_per_cell)); + Assert (accessor.present_index * GeometryInfo<3>::faces_per_cell + face + < accessor.tria->levels[accessor.present_level] + ->cells.face_rotations.size(), + ExcInternalError()); + + accessor.tria->levels[accessor.present_level] + ->cells.face_rotations[accessor.present_index * + GeometryInfo<3>::faces_per_cell + + face] = value; + } + + /** + * Implementation of the function + * of some name in the mother + * class. + */ + template + static + void + set_line_orientation (const TriaAccessor<1, dim, spacedim> &, + const unsigned int, + const bool) + { + Assert (false, ExcInternalError()); + } - template - static - void - set_line_orientation (const TriaAccessor<3, dim, spacedim> &, - const unsigned int, - const bool) - { - // it seems like we don't need this - // one - Assert (false, ExcNotImplemented()); - } - - - /** - * Implementation of the function of same - * name in the enclosing class. - */ - template - static - unsigned int - vertex_index (const TriaAccessor<1,dim,spacedim> &accessor, - const unsigned int corner) - { - return accessor.objects().cells[accessor.present_index].face (corner); - } - + template + static + void + set_line_orientation (const TriaAccessor<2, 2, spacedim> &, + const unsigned int, + const bool) + { + // quads in 2d have no + // non-standard orientation + Assert (false, ExcInternalError()); + } + + + template + static + void + set_line_orientation (const TriaAccessor<2, 3, spacedim> &accessor, + const unsigned int line, + const bool value) + { + Assert (accessor.used(), TriaAccessorExceptions::ExcCellNotUsed()); + Assert (line::lines_per_face, + ExcIndexRange (line, 0, GeometryInfo<3>::lines_per_face)); + Assert (accessor.present_index * GeometryInfo<3>::lines_per_face + line + < accessor.tria->faces->quads.line_orientations.size(), + ExcInternalError()); + // quads as part of 3d hexes + // can have non-standard + // orientation + accessor.tria->faces->quads.line_orientations[accessor.present_index * + GeometryInfo<3>::lines_per_face + + line] + = value; + } + - template - static - unsigned int - vertex_index (const TriaAccessor<2,dim,spacedim> &accessor, - const unsigned int corner) - { - // table used to switch the vertices, if the - // line orientation is wrong, - // - // first index: line orientation 0: false or - // 1: true=standard - // - // second index: vertex index to be switched - // (or not) + template + static + void + set_line_orientation (const TriaAccessor<3, dim, spacedim> &, + const unsigned int, + const bool) + { + // it seems like we don't need this + // one + Assert (false, ExcNotImplemented()); + } + + + /** + * Implementation of the function of same + * name in the enclosing class. + */ + template + static + unsigned int + vertex_index (const TriaAccessor<1,dim,spacedim> &accessor, + const unsigned int corner) + { + return accessor.objects().cells[accessor.present_index].face (corner); + } + + + template + static + unsigned int + vertex_index (const TriaAccessor<2,dim,spacedim> &accessor, + const unsigned int corner) + { + // table used to switch the vertices, if the + // line orientation is wrong, + // + // first index: line orientation 0: false or + // 1: true=standard + // + // second index: vertex index to be switched + // (or not) - static const unsigned int switch_table[2][2]={{1,0},{0,1}}; + static const unsigned int switch_table[2][2]={{1,0},{0,1}}; - return accessor.line(corner%2) - ->vertex_index(switch_table[accessor.line_orientation(corner%2)][corner/2]); - } - - - - template - static - unsigned int - vertex_index (const TriaAccessor<3,dim,spacedim> &accessor, - const unsigned int corner) - { - // get the corner indices by asking either - // the bottom or the top face for its - // vertices. handle non-standard faces by - // calling the vertex reordering function - // from GeometryInfo - - // bottom face (4) for first four vertices, - // top face (5) for the rest - const unsigned int face_index=4+corner/4; - - return accessor.quad(face_index) - ->vertex_index(GeometryInfo - ::standard_to_real_face_vertex(corner%4, - accessor.face_orientation(face_index), - accessor.face_flip(face_index), - accessor.face_rotation(face_index))); - } -}; + return accessor.line(corner%2) + ->vertex_index(switch_table[accessor.line_orientation(corner%2)][corner/2]); + } + + + + template + static + unsigned int + vertex_index (const TriaAccessor<3,dim,spacedim> &accessor, + const unsigned int corner) + { + // get the corner indices by asking either + // the bottom or the top face for its + // vertices. handle non-standard faces by + // calling the vertex reordering function + // from GeometryInfo + + // bottom face (4) for first four vertices, + // top face (5) for the rest + const unsigned int face_index=4+corner/4; + + return accessor.quad(face_index) + ->vertex_index(GeometryInfo + ::standard_to_real_face_vertex(corner%4, + accessor.face_orientation(face_index), + accessor.face_flip(face_index), + accessor.face_rotation(face_index))); + } + }; + } +} @@ -1120,7 +1133,7 @@ vertex_index (const unsigned int corner) const Assert (corner::vertices_per_cell, ExcIndexRange(corner,0,GeometryInfo::vertices_per_cell)); - return Implementation::vertex_index (*this, corner); + return internal::TriaAccessor::Implementation::vertex_index (*this, corner); } @@ -1154,7 +1167,7 @@ TriaAccessor::line_index (const unsigned int i) const Assert (i < GeometryInfo::lines_per_cell, ExcIndexRange (i, 0, GeometryInfo::lines_per_cell)); - return Implementation::line_index (*this, i); + return internal::TriaAccessor::Implementation::line_index (*this, i); } @@ -1177,7 +1190,7 @@ inline unsigned int TriaAccessor::quad_index (const unsigned int i) const { - return Implementation::quad_index (*this, i); + return internal::TriaAccessor::Implementation::quad_index (*this, i); } @@ -1189,7 +1202,7 @@ TriaAccessor::face_orientation (const unsigned int face) { Assert (used(), TriaAccessorExceptions::ExcCellNotUsed()); - return Implementation::face_orientation (*this, face); + return internal::TriaAccessor::Implementation::face_orientation (*this, face); } @@ -1201,7 +1214,7 @@ TriaAccessor::face_flip (const unsigned int face) const { Assert (used(), TriaAccessorExceptions::ExcCellNotUsed()); - return Implementation::face_flip (*this, face); + return internal::TriaAccessor::Implementation::face_flip (*this, face); } @@ -1212,7 +1225,7 @@ TriaAccessor::face_rotation (const unsigned int face) co { Assert (used(), TriaAccessorExceptions::ExcCellNotUsed()); - return Implementation::face_rotation (*this, face); + return internal::TriaAccessor::Implementation::face_rotation (*this, face); } @@ -1226,7 +1239,7 @@ TriaAccessor::line_orientation (const unsigned int line) Assert (line::lines_per_cell, ExcIndexRange (line, 0, GeometryInfo::lines_per_cell)); - return Implementation::line_orientation (*this, line); + return internal::TriaAccessor::Implementation::line_orientation (*this, line); } @@ -1239,7 +1252,7 @@ TriaAccessor::set_face_orientation (const unsigned int f { Assert (used(), TriaAccessorExceptions::ExcCellNotUsed()); - Implementation::set_face_orientation (*this, face, value); + internal::TriaAccessor::Implementation::set_face_orientation (*this, face, value); } @@ -1252,7 +1265,7 @@ TriaAccessor::set_face_flip (const unsigned int face, { Assert (used(), TriaAccessorExceptions::ExcCellNotUsed()); - Implementation::set_face_flip (*this, face, value); + internal::TriaAccessor::Implementation::set_face_flip (*this, face, value); } @@ -1264,7 +1277,7 @@ TriaAccessor::set_face_rotation (const unsigned int face { Assert (used(), TriaAccessorExceptions::ExcCellNotUsed()); - Implementation::set_face_rotation (*this, face, value); + internal::TriaAccessor::Implementation::set_face_rotation (*this, face, value); } @@ -1279,7 +1292,7 @@ TriaAccessor::set_line_orientation (const unsigned int l Assert (line::lines_per_cell, ExcIndexRange (line, 0, GeometryInfo::lines_per_cell)); - Implementation::set_line_orientation (*this, line, value); + internal::TriaAccessor::Implementation::set_line_orientation (*this, line, value); } diff --git a/deal.II/deal.II/include/hp/dof_faces.h b/deal.II/deal.II/include/hp/dof_faces.h index be6d12c8af..8835b97f3d 100644 --- a/deal.II/deal.II/include/hp/dof_faces.h +++ b/deal.II/deal.II/include/hp/dof_faces.h @@ -2,7 +2,7 @@ // $Id$ // Version: $Name$ // -// Copyright (C) 2006 by the deal.II authors +// Copyright (C) 2006, 2008 by the deal.II authors // // This file is subject to QPL and may not be distributed // without copyright and license information. Please refer @@ -110,22 +110,20 @@ namespace internal template<> class DoFFaces<2> { - private: + public: internal::hp::DoFObjects<1> lines; - public: /** * Determine an estimate for the * memory consumption (in bytes) * of this object. */ unsigned int memory_consumption () const; - - template friend class dealii::hp::DoFHandler; }; /** - * Store the indices of degrees of freedom on faces in 3D, which are quads, additionaly also on lines. + * Store the indices of degrees of freedom on faces in 3D, which are + * quads, additionally also on lines. * * @ingroup hp * @author Tobias Leicht, 2006 @@ -133,19 +131,16 @@ namespace internal template<> class DoFFaces<3> { - private: + public: internal::hp::DoFObjects<1> lines; internal::hp::DoFObjects<2> quads; - public: /** * Determine an estimate for the * memory consumption (in bytes) * of this object. */ unsigned int memory_consumption () const; - - template friend class dealii::hp::DoFHandler; }; } // namespace hp diff --git a/deal.II/deal.II/include/hp/dof_handler.h b/deal.II/deal.II/include/hp/dof_handler.h index 992fd68a5d..e58a2a488d 100644 --- a/deal.II/deal.II/include/hp/dof_handler.h +++ b/deal.II/deal.II/include/hp/dof_handler.h @@ -36,6 +36,19 @@ namespace internal template class DoFLevel; template class DoFFaces; template class DoFObjects; + + namespace DoFHandler + { + struct Implementation; + } + } +} + +namespace internal +{ + namespace DoFCellAccessor + { + struct Implementation; } } @@ -1253,25 +1266,12 @@ namespace hp */ std::vector *> has_children; - /** - * Forward declaration of a class - * into which we put significant - * parts of the implementation. - * - * See the .cc file for more - * information. - */ - struct Implementation; - - /** - * Make accessor objects friends. - */ - template friend class dealii::DoFAccessor; - /** * Make accessor objects friends. */ - template friend class dealii::DoFCellAccessor; + template friend class dealii::DoFAccessor; + template friend class dealii::DoFCellAccessor; + friend class internal::DoFCellAccessor::Implementation; /** * Likewise for DoFLevel @@ -1283,7 +1283,7 @@ namespace hp template friend class internal::hp::DoFLevel; template friend class internal::hp::DoFObjects; - friend class Triangulation::Implementation; + friend class internal::hp::DoFHandler::Implementation; }; diff --git a/deal.II/deal.II/include/hp/dof_levels.h b/deal.II/deal.II/include/hp/dof_levels.h index 5eff463c14..57f03fc37b 100644 --- a/deal.II/deal.II/include/hp/dof_levels.h +++ b/deal.II/deal.II/include/hp/dof_levels.h @@ -2,7 +2,7 @@ // $Id$ // Version: $Name$ // -// Copyright (C) 2003, 2006 by the deal.II authors +// Copyright (C) 2003, 2006, 2008 by the deal.II authors // // This file is subject to QPL and may not be distributed // without copyright and license information. Please refer @@ -160,27 +160,19 @@ namespace internal template <> class DoFLevel<1> : public DoFLevel<0> { - private: + public: /** * store the dof-indices and related functions of * lines */ internal::hp::DoFObjects<1> lines; - public: /** * Determine an estimate for the * memory consumption (in bytes) * of this object. */ unsigned int memory_consumption () const; - /** - * Make the DoFHandler class - * a friend, so that it can - * resize arrays as - * necessary. - */ - template friend class dealii::hp::DoFHandler; }; @@ -194,27 +186,19 @@ namespace internal template <> class DoFLevel<2> : public DoFLevel<0> { - public: + public: /** * store the dof-indices and related functions of * quads */ internal::hp::DoFObjects<2> quads; - public: /** * Determine an estimate for the * memory consumption (in bytes) * of this object. */ unsigned int memory_consumption () const; - /** - * Make the DoFHandler class - * a friend, so that it can - * resize arrays as - * necessary. - */ - template friend class dealii::hp::DoFHandler; }; @@ -229,27 +213,19 @@ namespace internal template <> class DoFLevel<3> : public DoFLevel<0> { - private: + public: /** * store the dof-indices and related functions of * hexes */ internal::hp::DoFObjects<3> hexes; - public: /** * Determine an estimate for the * memory consumption (in bytes) * of this object. */ unsigned int memory_consumption () const; - /** - * Make the DoFHandler class - * a friend, so that it can - * resize arrays as - * necessary. - */ - template friend class dealii::hp::DoFHandler; }; } // namespace hp diff --git a/deal.II/deal.II/include/hp/dof_objects.h b/deal.II/deal.II/include/hp/dof_objects.h index bdf6106c56..c889d584b3 100644 --- a/deal.II/deal.II/include/hp/dof_objects.h +++ b/deal.II/deal.II/include/hp/dof_objects.h @@ -2,7 +2,7 @@ // $Id$ // Version: $Name$ // -// Copyright (C) 2006 by the deal.II authors +// Copyright (C) 2006, 2008 by the deal.II authors // // This file is subject to QPL and may not be distributed // without copyright and license information. Please refer @@ -96,9 +96,7 @@ namespace internal template class DoFObjects { - - private: - + public: /** * Store the start index for * the degrees of freedom of each @@ -114,8 +112,6 @@ namespace internal */ std::vector dofs; - public: - /** * Set the global index of * the @p local_index-th @@ -240,14 +236,6 @@ namespace internal * of this object. */ unsigned int memory_consumption () const; - - /** - * Make the DoFHandler class - * a friend, so that it can - * resize arrays as - * necessary. - */ - template friend class dealii::hp::DoFHandler; }; diff --git a/deal.II/deal.II/source/dofs/dof_accessor.cc b/deal.II/deal.II/source/dofs/dof_accessor.cc index e7aab2ffd5..94c888ea20 100644 --- a/deal.II/deal.II/source/dofs/dof_accessor.cc +++ b/deal.II/deal.II/source/dofs/dof_accessor.cc @@ -49,7 +49,7 @@ DoFCellAccessor::update_cell_dof_indices_cache () const Assert (this->dof_handler != 0, typename BaseClass::ExcInvalidObject()); Assert (&this->get_fe() != 0, typename BaseClass::ExcInvalidObject()); - Implementation::update_cell_dof_indices_cache (*this); + internal::DoFCellAccessor::Implementation::update_cell_dof_indices_cache (*this); } diff --git a/deal.II/deal.II/source/dofs/dof_handler.cc b/deal.II/deal.II/source/dofs/dof_handler.cc index 2da755351a..3f7f775f6c 100644 --- a/deal.II/deal.II/source/dofs/dof_handler.cc +++ b/deal.II/deal.II/source/dofs/dof_handler.cc @@ -62,803 +62,818 @@ namespace internal +namespace internal +{ + namespace DoFHandler + { + // access class + // dealii::DoFHandler instead of + // namespace internal::DoFHandler + using dealii::DoFHandler; + /** * A class with the same purpose as the similarly named class of the * Triangulation class. See there for more information. */ -template -struct DoFHandler::Implementation -{ - /** - * Distribute dofs on the given cell, - * with new dofs starting with index - * @p next_free_dof. Return the next - * unused index number. The finite - * element used is the one given to - * @p distribute_dofs, which is copied - * to @p selected_fe. - * - * This function is excluded from the - * @p distribute_dofs function since - * it can not be implemented dimension - * independent. - */ - template - static - unsigned int - distribute_dofs_on_cell (const DoFHandler<1,spacedim> &dof_handler, - active_cell_iterator &cell, - unsigned int next_free_dof) - { - - // distribute dofs of vertices - for (unsigned int v=0; v::vertices_per_cell; ++v) + struct Implementation + { + /** + * Distribute dofs on the given cell, + * with new dofs starting with index + * @p next_free_dof. Return the next + * unused index number. The finite + * element used is the one given to + * @p distribute_dofs, which is copied + * to @p selected_fe. + * + * This function is excluded from the + * @p distribute_dofs function since + * it can not be implemented dimension + * independent. + */ + template + static + unsigned int + distribute_dofs_on_cell (const DoFHandler<1,spacedim> &dof_handler, + typename DoFHandler<1,spacedim>::active_cell_iterator &cell, + unsigned int next_free_dof) { - cell_iterator neighbor = cell->neighbor(v); - if (neighbor.state() == IteratorState::valid) + // distribute dofs of vertices + for (unsigned int v=0; v::vertices_per_cell; ++v) { - // find true neighbor; may be its - // a child of @p{neighbor} - while (neighbor->has_children()) - neighbor = neighbor->child(v==0 ? 1 : 0); - - // has neighbor already been processed? - if (neighbor->user_flag_set()) - // copy dofs + typename DoFHandler<1,spacedim>::cell_iterator + neighbor = cell->neighbor(v); + + if (neighbor.state() == IteratorState::valid) { - if (v==0) - for (unsigned int d=0; - ddofs_per_vertex; ++d) - cell->set_vertex_dof_index (0, d, - neighbor->vertex_dof_index (1, d)); - else - for (unsigned int d=0; - ddofs_per_vertex; ++d) - cell->set_vertex_dof_index (1, d, - neighbor->vertex_dof_index (0, d)); - - // next neighbor - continue; + // find true neighbor; may be its + // a child of @p{neighbor} + while (neighbor->has_children()) + neighbor = neighbor->child(v==0 ? 1 : 0); + + // has neighbor already been processed? + if (neighbor->user_flag_set()) + // copy dofs + { + if (v==0) + for (unsigned int d=0; + ddofs_per_vertex; ++d) + cell->set_vertex_dof_index (0, d, + neighbor->vertex_dof_index (1, d)); + else + for (unsigned int d=0; + ddofs_per_vertex; ++d) + cell->set_vertex_dof_index (1, d, + neighbor->vertex_dof_index (0, d)); + + // next neighbor + continue; + } } - } - // otherwise: create dofs newly - for (unsigned int d=0; - ddofs_per_vertex; ++d) - cell->set_vertex_dof_index (v, d, next_free_dof++); - } + // otherwise: create dofs newly + for (unsigned int d=0; + ddofs_per_vertex; ++d) + cell->set_vertex_dof_index (v, d, next_free_dof++); + } - // dofs of line - for (unsigned int d=0; - ddofs_per_line; ++d) - cell->set_dof_index (d, next_free_dof++); - - // note that this cell has been - // processed - cell->set_user_flag (); + // dofs of line + for (unsigned int d=0; + ddofs_per_line; ++d) + cell->set_dof_index (d, next_free_dof++); + + // note that this cell has been + // processed + cell->set_user_flag (); - return next_free_dof; - } + return next_free_dof; + } - template - static - unsigned int - distribute_dofs_on_cell (const DoFHandler<2,spacedim> &dof_handler, - active_cell_iterator &cell, - unsigned int next_free_dof) - { - if (dof_handler.selected_fe->dofs_per_vertex > 0) - // number dofs on vertices - for (unsigned int vertex=0; vertex::vertices_per_cell; ++vertex) - // check whether dofs for this - // vertex have been distributed - // (only check the first dof) - if (cell->vertex_dof_index(vertex, 0) == invalid_dof_index) - for (unsigned int d=0; ddofs_per_vertex; ++d) - cell->set_vertex_dof_index (vertex, d, next_free_dof++); + template + static + unsigned int + distribute_dofs_on_cell (const DoFHandler<2,spacedim> &dof_handler, + typename DoFHandler<2,spacedim>::active_cell_iterator &cell, + unsigned int next_free_dof) + { + if (dof_handler.selected_fe->dofs_per_vertex > 0) + // number dofs on vertices + for (unsigned int vertex=0; vertex::vertices_per_cell; ++vertex) + // check whether dofs for this + // vertex have been distributed + // (only check the first dof) + if (cell->vertex_dof_index(vertex, 0) == DoFHandler<2,spacedim>::invalid_dof_index) + for (unsigned int d=0; ddofs_per_vertex; ++d) + cell->set_vertex_dof_index (vertex, d, next_free_dof++); - // for the four sides - if (dof_handler.selected_fe->dofs_per_line > 0) - for (unsigned int side=0; side::faces_per_cell; ++side) - { - line_iterator line = cell->line(side); + // for the four sides + if (dof_handler.selected_fe->dofs_per_line > 0) + for (unsigned int side=0; side::faces_per_cell; ++side) + { + typename DoFHandler<2,spacedim>::line_iterator + line = cell->line(side); - // distribute dofs if necessary: - // check whether line dof is already - // numbered (check only first dof) - if (line->dof_index(0) == invalid_dof_index) - // if not: distribute dofs - for (unsigned int d=0; ddofs_per_line; ++d) - line->set_dof_index (d, next_free_dof++); - } + // distribute dofs if necessary: + // check whether line dof is already + // numbered (check only first dof) + if (line->dof_index(0) == DoFHandler<2,spacedim>::invalid_dof_index) + // if not: distribute dofs + for (unsigned int d=0; ddofs_per_line; ++d) + line->set_dof_index (d, next_free_dof++); + } - // dofs of quad - if (dof_handler.selected_fe->dofs_per_quad > 0) - for (unsigned int d=0; ddofs_per_quad; ++d) - cell->set_dof_index (d, next_free_dof++); + // dofs of quad + if (dof_handler.selected_fe->dofs_per_quad > 0) + for (unsigned int d=0; ddofs_per_quad; ++d) + cell->set_dof_index (d, next_free_dof++); - // note that this cell has been processed - cell->set_user_flag (); + // note that this cell has been processed + cell->set_user_flag (); - return next_free_dof; - } + return next_free_dof; + } - template - static - unsigned int - distribute_dofs_on_cell (const DoFHandler<3,spacedim> &dof_handler, - active_cell_iterator &cell, - unsigned int next_free_dof) - { - if (dof_handler.selected_fe->dofs_per_vertex > 0) - // number dofs on vertices - for (unsigned int vertex=0; vertex::vertices_per_cell; ++vertex) - // check whether dofs for this - // vertex have been distributed - // (only check the first dof) - if (cell->vertex_dof_index(vertex, 0) == invalid_dof_index) - for (unsigned int d=0; ddofs_per_vertex; ++d) - cell->set_vertex_dof_index (vertex, d, next_free_dof++); + template + static + unsigned int + distribute_dofs_on_cell (const DoFHandler<3,spacedim> &dof_handler, + typename DoFHandler<3,spacedim>::active_cell_iterator &cell, + unsigned int next_free_dof) + { + if (dof_handler.selected_fe->dofs_per_vertex > 0) + // number dofs on vertices + for (unsigned int vertex=0; vertex::vertices_per_cell; ++vertex) + // check whether dofs for this + // vertex have been distributed + // (only check the first dof) + if (cell->vertex_dof_index(vertex, 0) == DoFHandler<3,spacedim>::invalid_dof_index) + for (unsigned int d=0; ddofs_per_vertex; ++d) + cell->set_vertex_dof_index (vertex, d, next_free_dof++); - // for the lines - if (dof_handler.selected_fe->dofs_per_line > 0) - for (unsigned int l=0; l::lines_per_cell; ++l) - { - line_iterator line = cell->line(l); + // for the lines + if (dof_handler.selected_fe->dofs_per_line > 0) + for (unsigned int l=0; l::lines_per_cell; ++l) + { + typename DoFHandler<3,spacedim>::line_iterator + line = cell->line(l); - // distribute dofs if necessary: - // check whether line dof is already - // numbered (check only first dof) - if (line->dof_index(0) == invalid_dof_index) - // if not: distribute dofs - for (unsigned int d=0; ddofs_per_line; ++d) - line->set_dof_index (d, next_free_dof++); - } - - // for the quads - if (dof_handler.selected_fe->dofs_per_quad > 0) - for (unsigned int q=0; q::quads_per_cell; ++q) - { - quad_iterator quad = cell->quad(q); + // distribute dofs if necessary: + // check whether line dof is already + // numbered (check only first dof) + if (line->dof_index(0) == DoFHandler<3,spacedim>::invalid_dof_index) + // if not: distribute dofs + for (unsigned int d=0; ddofs_per_line; ++d) + line->set_dof_index (d, next_free_dof++); + } + + // for the quads + if (dof_handler.selected_fe->dofs_per_quad > 0) + for (unsigned int q=0; q::quads_per_cell; ++q) + { + typename DoFHandler<3,spacedim>::quad_iterator + quad = cell->quad(q); - // distribute dofs if necessary: - // check whether quad dof is already - // numbered (check only first dof) - if (quad->dof_index(0) == invalid_dof_index) - // if not: distribute dofs - for (unsigned int d=0; ddofs_per_quad; ++d) - quad->set_dof_index (d, next_free_dof++); - } + // distribute dofs if necessary: + // check whether quad dof is already + // numbered (check only first dof) + if (quad->dof_index(0) == DoFHandler<3,spacedim>::invalid_dof_index) + // if not: distribute dofs + for (unsigned int d=0; ddofs_per_quad; ++d) + quad->set_dof_index (d, next_free_dof++); + } - // dofs of hex - if (dof_handler.selected_fe->dofs_per_hex > 0) - for (unsigned int d=0; ddofs_per_hex; ++d) - cell->set_dof_index (d, next_free_dof++); + // dofs of hex + if (dof_handler.selected_fe->dofs_per_hex > 0) + for (unsigned int d=0; ddofs_per_hex; ++d) + cell->set_dof_index (d, next_free_dof++); - // note that this cell has been - // processed - cell->set_user_flag (); + // note that this cell has been + // processed + cell->set_user_flag (); - return next_free_dof; - } + return next_free_dof; + } - /** - * Implementation of the general template - * of same name. - */ - template - static - void renumber_dofs (const std::vector &new_numbers, - DoFHandler<1,spacedim> &dof_handler) - { - // note that we can not use cell - // iterators in this function since - // then we would renumber the dofs on - // the interface of two cells more - // than once. Anyway, this way it's - // not only more correct but also - // faster; note, however, that dof - // numbers may be invalid_dof_index, - // namely when the appropriate - // vertex/line/etc is unused - for (std::vector::iterator - i=dof_handler.vertex_dofs.begin(); - i!=dof_handler.vertex_dofs.end(); ++i) - if (*i != invalid_dof_index) - *i = new_numbers[*i]; - else - // if index is invalid_dof_index: - // check if this one really is - // unused - Assert (dof_handler.tria - ->vertex_used((i-dof_handler.vertex_dofs.begin()) / - dof_handler.selected_fe->dofs_per_vertex) - == false, - ExcInternalError ()); + /** + * Implementation of the general template + * of same name. + */ + template + static + void renumber_dofs (const std::vector &new_numbers, + DoFHandler<1,spacedim> &dof_handler) + { + // note that we can not use cell + // iterators in this function since + // then we would renumber the dofs on + // the interface of two cells more + // than once. Anyway, this way it's + // not only more correct but also + // faster; note, however, that dof + // numbers may be invalid_dof_index, + // namely when the appropriate + // vertex/line/etc is unused + for (std::vector::iterator + i=dof_handler.vertex_dofs.begin(); + i!=dof_handler.vertex_dofs.end(); ++i) + if (*i != DoFHandler<1,spacedim>::invalid_dof_index) + *i = new_numbers[*i]; + else + // if index is + // invalid_dof_index: + // check if this one + // really is unused + Assert (dof_handler.tria + ->vertex_used((i-dof_handler.vertex_dofs.begin()) / + dof_handler.selected_fe->dofs_per_vertex) + == false, + ExcInternalError ()); - for (unsigned int level=0; level::iterator - i=dof_handler.levels[level]->lines.dofs.begin(); - i!=dof_handler.levels[level]->lines.dofs.end(); ++i) - if (*i != invalid_dof_index) - *i = new_numbers[*i]; - } + for (unsigned int level=0; level::iterator + i=dof_handler.levels[level]->lines.dofs.begin(); + i!=dof_handler.levels[level]->lines.dofs.end(); ++i) + if (*i != DoFHandler<1,spacedim>::invalid_dof_index) + *i = new_numbers[*i]; + } - template - static - void renumber_dofs (const std::vector &new_numbers, - DoFHandler<2,spacedim> &dof_handler) - { - // note that we can not use cell - // iterators in this function since - // then we would renumber the dofs on - // the interface of two cells more - // than once. Anyway, this way it's - // not only more correct but also - // faster; note, however, that dof - // numbers may be invalid_dof_index, - // namely when the appropriate - // vertex/line/etc is unused - for (std::vector::iterator - i=dof_handler.vertex_dofs.begin(); - i!=dof_handler.vertex_dofs.end(); ++i) - if (*i != invalid_dof_index) - *i = new_numbers[*i]; - else - // if index is invalid_dof_index: - // check if this one really is - // unused - Assert (dof_handler.tria - ->vertex_used((i-dof_handler.vertex_dofs.begin()) / - dof_handler.selected_fe->dofs_per_vertex) - == false, - ExcInternalError ()); - - for (std::vector::iterator - i=dof_handler.faces->lines.dofs.begin(); - i!=dof_handler.faces->lines.dofs.end(); ++i) - if (*i != invalid_dof_index) - *i = new_numbers[*i]; - - for (unsigned int level=0; level + static + void renumber_dofs (const std::vector &new_numbers, + DoFHandler<2,spacedim> &dof_handler) { + // note that we can not use cell + // iterators in this function since + // then we would renumber the dofs on + // the interface of two cells more + // than once. Anyway, this way it's + // not only more correct but also + // faster; note, however, that dof + // numbers may be invalid_dof_index, + // namely when the appropriate + // vertex/line/etc is unused for (std::vector::iterator - i=dof_handler.levels[level]->quads.dofs.begin(); - i!=dof_handler.levels[level]->quads.dofs.end(); ++i) - if (*i != invalid_dof_index) + i=dof_handler.vertex_dofs.begin(); + i!=dof_handler.vertex_dofs.end(); ++i) + if (*i != DoFHandler<2,spacedim>::invalid_dof_index) *i = new_numbers[*i]; + else + // if index is invalid_dof_index: + // check if this one really is + // unused + Assert (dof_handler.tria + ->vertex_used((i-dof_handler.vertex_dofs.begin()) / + dof_handler.selected_fe->dofs_per_vertex) + == false, + ExcInternalError ()); + + for (std::vector::iterator + i=dof_handler.faces->lines.dofs.begin(); + i!=dof_handler.faces->lines.dofs.end(); ++i) + if (*i != DoFHandler<2,spacedim>::invalid_dof_index) + *i = new_numbers[*i]; + + for (unsigned int level=0; level::iterator + i=dof_handler.levels[level]->quads.dofs.begin(); + i!=dof_handler.levels[level]->quads.dofs.end(); ++i) + if (*i != DoFHandler<2,spacedim>::invalid_dof_index) + *i = new_numbers[*i]; + } } - } - template - static - void renumber_dofs (const std::vector &new_numbers, - DoFHandler<3,spacedim> &dof_handler) - { - // note that we can not use cell - // iterators in this function since - // then we would renumber the dofs on - // the interface of two cells more - // than once. Anyway, this way it's - // not only more correct but also - // faster; note, however, that dof - // numbers may be invalid_dof_index, - // namely when the appropriate - // vertex/line/etc is unused - for (std::vector::iterator - i=dof_handler.vertex_dofs.begin(); - i!=dof_handler.vertex_dofs.end(); ++i) - if (*i != invalid_dof_index) - *i = new_numbers[*i]; - else - // if index is invalid_dof_index: - // check if this one really is - // unused - Assert (dof_handler.tria - ->vertex_used((i-dof_handler.vertex_dofs.begin()) / - dof_handler.selected_fe->dofs_per_vertex) - == false, - ExcInternalError ()); - - for (std::vector::iterator - i=dof_handler.faces->lines.dofs.begin(); - i!=dof_handler.faces->lines.dofs.end(); ++i) - if (*i != invalid_dof_index) - *i = new_numbers[*i]; - for (std::vector::iterator - i=dof_handler.faces->quads.dofs.begin(); - i!=dof_handler.faces->quads.dofs.end(); ++i) - if (*i != invalid_dof_index) - *i = new_numbers[*i]; - - for (unsigned int level=0; level + static + void renumber_dofs (const std::vector &new_numbers, + DoFHandler<3,spacedim> &dof_handler) { + // note that we can not use cell + // iterators in this function since + // then we would renumber the dofs on + // the interface of two cells more + // than once. Anyway, this way it's + // not only more correct but also + // faster; note, however, that dof + // numbers may be invalid_dof_index, + // namely when the appropriate + // vertex/line/etc is unused + for (std::vector::iterator + i=dof_handler.vertex_dofs.begin(); + i!=dof_handler.vertex_dofs.end(); ++i) + if (*i != DoFHandler<3,spacedim>::invalid_dof_index) + *i = new_numbers[*i]; + else + // if index is invalid_dof_index: + // check if this one really is + // unused + Assert (dof_handler.tria + ->vertex_used((i-dof_handler.vertex_dofs.begin()) / + dof_handler.selected_fe->dofs_per_vertex) + == false, + ExcInternalError ()); + + for (std::vector::iterator + i=dof_handler.faces->lines.dofs.begin(); + i!=dof_handler.faces->lines.dofs.end(); ++i) + if (*i != DoFHandler<3,spacedim>::invalid_dof_index) + *i = new_numbers[*i]; for (std::vector::iterator - i=dof_handler.levels[level]->hexes.dofs.begin(); - i!=dof_handler.levels[level]->hexes.dofs.end(); ++i) - if (*i != invalid_dof_index) + i=dof_handler.faces->quads.dofs.begin(); + i!=dof_handler.faces->quads.dofs.end(); ++i) + if (*i != DoFHandler<3,spacedim>::invalid_dof_index) *i = new_numbers[*i]; + + for (unsigned int level=0; level::iterator + i=dof_handler.levels[level]->hexes.dofs.begin(); + i!=dof_handler.levels[level]->hexes.dofs.end(); ++i) + if (*i != DoFHandler<3,spacedim>::invalid_dof_index) + *i = new_numbers[*i]; + } } - } - /** - * Implement the function of same name in - * the mother class. - */ - template - static - unsigned int - max_couplings_between_dofs (const DoFHandler<1,spacedim> &dof_handler) - { - return std::min(3*dof_handler.selected_fe->dofs_per_vertex + - 2*dof_handler.selected_fe->dofs_per_line, - dof_handler.n_dofs()); - } + /** + * Implement the function of same name in + * the mother class. + */ + template + static + unsigned int + max_couplings_between_dofs (const DoFHandler<1,spacedim> &dof_handler) + { + return std::min(3*dof_handler.selected_fe->dofs_per_vertex + + 2*dof_handler.selected_fe->dofs_per_line, + dof_handler.n_dofs()); + } - template - static - unsigned int - max_couplings_between_dofs (const DoFHandler<2,spacedim> &dof_handler) - { - - // get these numbers by drawing pictures - // and counting... - // example: - // | | | - // --x-----x--x--X-- - // | | | | - // | x--x--x - // | | | | - // --x--x--*--x--x-- - // | | | | - // x--x--x | - // | | | | - // --X--x--x-----x-- - // | | | - // x = vertices connected with center vertex *; - // = total of 19 - // (the X vertices are connected with * if - // the vertices adjacent to X are hanging - // nodes) - // count lines -> 28 (don't forget to count - // mother and children separately!) - unsigned int max_couplings; - switch (dof_handler.tria->max_adjacent_cells()) + template + static + unsigned int + max_couplings_between_dofs (const DoFHandler<2,spacedim> &dof_handler) { - case 4: - max_couplings=19*dof_handler.selected_fe->dofs_per_vertex + - 28*dof_handler.selected_fe->dofs_per_line + - 8*dof_handler.selected_fe->dofs_per_quad; - break; - case 5: - max_couplings=21*dof_handler.selected_fe->dofs_per_vertex + - 31*dof_handler.selected_fe->dofs_per_line + - 9*dof_handler.selected_fe->dofs_per_quad; - break; - case 6: - max_couplings=28*dof_handler.selected_fe->dofs_per_vertex + - 42*dof_handler.selected_fe->dofs_per_line + - 12*dof_handler.selected_fe->dofs_per_quad; - break; - case 7: - max_couplings=30*dof_handler.selected_fe->dofs_per_vertex + - 45*dof_handler.selected_fe->dofs_per_line + - 13*dof_handler.selected_fe->dofs_per_quad; - break; - case 8: - max_couplings=37*dof_handler.selected_fe->dofs_per_vertex + - 56*dof_handler.selected_fe->dofs_per_line + - 16*dof_handler.selected_fe->dofs_per_quad; - break; - default: - Assert (false, ExcNotImplemented()); - max_couplings=0; + + // get these numbers by drawing pictures + // and counting... + // example: + // | | | + // --x-----x--x--X-- + // | | | | + // | x--x--x + // | | | | + // --x--x--*--x--x-- + // | | | | + // x--x--x | + // | | | | + // --X--x--x-----x-- + // | | | + // x = vertices connected with center vertex *; + // = total of 19 + // (the X vertices are connected with * if + // the vertices adjacent to X are hanging + // nodes) + // count lines -> 28 (don't forget to count + // mother and children separately!) + unsigned int max_couplings; + switch (dof_handler.tria->max_adjacent_cells()) + { + case 4: + max_couplings=19*dof_handler.selected_fe->dofs_per_vertex + + 28*dof_handler.selected_fe->dofs_per_line + + 8*dof_handler.selected_fe->dofs_per_quad; + break; + case 5: + max_couplings=21*dof_handler.selected_fe->dofs_per_vertex + + 31*dof_handler.selected_fe->dofs_per_line + + 9*dof_handler.selected_fe->dofs_per_quad; + break; + case 6: + max_couplings=28*dof_handler.selected_fe->dofs_per_vertex + + 42*dof_handler.selected_fe->dofs_per_line + + 12*dof_handler.selected_fe->dofs_per_quad; + break; + case 7: + max_couplings=30*dof_handler.selected_fe->dofs_per_vertex + + 45*dof_handler.selected_fe->dofs_per_line + + 13*dof_handler.selected_fe->dofs_per_quad; + break; + case 8: + max_couplings=37*dof_handler.selected_fe->dofs_per_vertex + + 56*dof_handler.selected_fe->dofs_per_line + + 16*dof_handler.selected_fe->dofs_per_quad; + break; + default: + Assert (false, ExcNotImplemented()); + max_couplings=0; + } + return std::min(max_couplings,dof_handler.n_dofs()); } - return std::min(max_couplings,dof_handler.n_dofs()); - } - template - static - unsigned int - max_couplings_between_dofs (const DoFHandler<3,spacedim> &dof_handler) - { + template + static + unsigned int + max_couplings_between_dofs (const DoFHandler<3,spacedim> &dof_handler) + { //TODO:[?] Invent significantly better estimates than the ones in this function - // doing the same thing here is a - // rather complicated thing, compared - // to the 2d case, since it is hard - // to draw pictures with several - // refined hexahedra :-) so I - // presently only give a coarse - // estimate for the case that at most - // 8 hexes meet at each vertex - // - // can anyone give better estimate - // here? - const unsigned int max_adjacent_cells - = dof_handler.tria->max_adjacent_cells(); - - unsigned int max_couplings; - if (max_adjacent_cells <= 8) - max_couplings=7*7*7*dof_handler.selected_fe->dofs_per_vertex + - 7*6*7*3*dof_handler.selected_fe->dofs_per_line + - 9*4*7*3*dof_handler.selected_fe->dofs_per_quad + - 27*dof_handler.selected_fe->dofs_per_hex; - else - { - Assert (false, ExcNotImplemented()); - max_couplings=0; - } + // doing the same thing here is a + // rather complicated thing, compared + // to the 2d case, since it is hard + // to draw pictures with several + // refined hexahedra :-) so I + // presently only give a coarse + // estimate for the case that at most + // 8 hexes meet at each vertex + // + // can anyone give better estimate + // here? + const unsigned int max_adjacent_cells + = dof_handler.tria->max_adjacent_cells(); + + unsigned int max_couplings; + if (max_adjacent_cells <= 8) + max_couplings=7*7*7*dof_handler.selected_fe->dofs_per_vertex + + 7*6*7*3*dof_handler.selected_fe->dofs_per_line + + 9*4*7*3*dof_handler.selected_fe->dofs_per_quad + + 27*dof_handler.selected_fe->dofs_per_hex; + else + { + Assert (false, ExcNotImplemented()); + max_couplings=0; + } - return std::min(max_couplings,dof_handler.n_dofs()); - } + return std::min(max_couplings,dof_handler.n_dofs()); + } - /** - * Reserve enough space in the - * levels[] objects to store the - * numbers of the degrees of freedom - * needed for the given element. The - * given element is that one which - * was selected when calling - * @p distribute_dofs the last time. - */ - template - static - void reserve_space (DoFHandler<1,spacedim> &dof_handler) - { - dof_handler.vertex_dofs - .resize(dof_handler.tria->n_vertices() * - dof_handler.selected_fe->dofs_per_vertex, - invalid_dof_index); + /** + * Reserve enough space in the + * levels[] objects to store the + * numbers of the degrees of freedom + * needed for the given element. The + * given element is that one which + * was selected when calling + * @p distribute_dofs the last time. + */ + template + static + void reserve_space (DoFHandler<1,spacedim> &dof_handler) + { + dof_handler.vertex_dofs + .resize(dof_handler.tria->n_vertices() * + dof_handler.selected_fe->dofs_per_vertex, + DoFHandler<1,spacedim>::invalid_dof_index); - for (unsigned int i=0; in_levels(); ++i) - { - dof_handler.levels - .push_back (new internal::DoFHandler::DoFLevel<1>); - - dof_handler.levels.back()->lines.dofs - .resize (dof_handler.tria->n_raw_lines(i) * - dof_handler.selected_fe->dofs_per_line, - invalid_dof_index); - - dof_handler.levels.back()->cell_dof_indices_cache - .resize (dof_handler.tria->n_raw_lines(i) * - dof_handler.selected_fe->dofs_per_cell, - invalid_dof_index); + for (unsigned int i=0; in_levels(); ++i) + { + dof_handler.levels + .push_back (new internal::DoFHandler::DoFLevel<1>); + + dof_handler.levels.back()->lines.dofs + .resize (dof_handler.tria->n_raw_lines(i) * + dof_handler.selected_fe->dofs_per_line, + DoFHandler<1,spacedim>::invalid_dof_index); + + dof_handler.levels.back()->cell_dof_indices_cache + .resize (dof_handler.tria->n_raw_lines(i) * + dof_handler.selected_fe->dofs_per_cell, + DoFHandler<1,spacedim>::invalid_dof_index); + } } - } - template - static - void reserve_space (DoFHandler<2,spacedim> &dof_handler) - { - dof_handler.vertex_dofs - .resize(dof_handler.tria->n_vertices() * - dof_handler.selected_fe->dofs_per_vertex, - invalid_dof_index); - - for (unsigned int i=0; in_levels(); ++i) + template + static + void reserve_space (DoFHandler<2,spacedim> &dof_handler) { - dof_handler.levels.push_back (new internal::DoFHandler::DoFLevel<2>); + dof_handler.vertex_dofs + .resize(dof_handler.tria->n_vertices() * + dof_handler.selected_fe->dofs_per_vertex, + DoFHandler<2,spacedim>::invalid_dof_index); - dof_handler.levels.back()->quads.dofs - .resize (dof_handler.tria->n_raw_quads(i) * - dof_handler.selected_fe->dofs_per_quad, - invalid_dof_index); + for (unsigned int i=0; in_levels(); ++i) + { + dof_handler.levels.push_back (new internal::DoFHandler::DoFLevel<2>); - dof_handler.levels.back()->cell_dof_indices_cache - .resize (dof_handler.tria->n_raw_quads(i) * - dof_handler.selected_fe->dofs_per_cell, - invalid_dof_index); - } + dof_handler.levels.back()->quads.dofs + .resize (dof_handler.tria->n_raw_quads(i) * + dof_handler.selected_fe->dofs_per_quad, + DoFHandler<2,spacedim>::invalid_dof_index); - dof_handler.faces = new internal::DoFHandler::DoFFaces<2>; - dof_handler.faces->lines.dofs - .resize (dof_handler.tria->n_raw_lines() * - dof_handler.selected_fe->dofs_per_line, - invalid_dof_index); - } + dof_handler.levels.back()->cell_dof_indices_cache + .resize (dof_handler.tria->n_raw_quads(i) * + dof_handler.selected_fe->dofs_per_cell, + DoFHandler<2,spacedim>::invalid_dof_index); + } - - template - static - void reserve_space (DoFHandler<3,spacedim> &dof_handler) - { - dof_handler.vertex_dofs - .resize(dof_handler.tria->n_vertices() * - dof_handler.selected_fe->dofs_per_vertex, - invalid_dof_index); + dof_handler.faces = new internal::DoFHandler::DoFFaces<2>; + dof_handler.faces->lines.dofs + .resize (dof_handler.tria->n_raw_lines() * + dof_handler.selected_fe->dofs_per_line, + DoFHandler<2,spacedim>::invalid_dof_index); + } - for (unsigned int i=0; in_levels(); ++i) + + template + static + void reserve_space (DoFHandler<3,spacedim> &dof_handler) { - dof_handler.levels.push_back (new internal::DoFHandler::DoFLevel<3>); + dof_handler.vertex_dofs + .resize(dof_handler.tria->n_vertices() * + dof_handler.selected_fe->dofs_per_vertex, + DoFHandler<3,spacedim>::invalid_dof_index); + + for (unsigned int i=0; in_levels(); ++i) + { + dof_handler.levels.push_back (new internal::DoFHandler::DoFLevel<3>); - dof_handler.levels.back()->hexes.dofs - .resize (dof_handler.tria->n_raw_hexs(i) * - dof_handler.selected_fe->dofs_per_hex, - invalid_dof_index); + dof_handler.levels.back()->hexes.dofs + .resize (dof_handler.tria->n_raw_hexs(i) * + dof_handler.selected_fe->dofs_per_hex, + DoFHandler<3,spacedim>::invalid_dof_index); - dof_handler.levels.back()->cell_dof_indices_cache - .resize (dof_handler.tria->n_raw_hexs(i) * - dof_handler.selected_fe->dofs_per_cell, - invalid_dof_index); - } - dof_handler.faces = new internal::DoFHandler::DoFFaces<3>; + dof_handler.levels.back()->cell_dof_indices_cache + .resize (dof_handler.tria->n_raw_hexs(i) * + dof_handler.selected_fe->dofs_per_cell, + DoFHandler<3,spacedim>::invalid_dof_index); + } + dof_handler.faces = new internal::DoFHandler::DoFFaces<3>; - dof_handler.faces->lines.dofs - .resize (dof_handler.tria->n_raw_lines() * - dof_handler.selected_fe->dofs_per_line, - invalid_dof_index); - dof_handler.faces->quads.dofs - .resize (dof_handler.tria->n_raw_quads() * - dof_handler.selected_fe->dofs_per_quad, - invalid_dof_index); - } + dof_handler.faces->lines.dofs + .resize (dof_handler.tria->n_raw_lines() * + dof_handler.selected_fe->dofs_per_line, + DoFHandler<3,spacedim>::invalid_dof_index); + dof_handler.faces->quads.dofs + .resize (dof_handler.tria->n_raw_quads() * + dof_handler.selected_fe->dofs_per_quad, + DoFHandler<3,spacedim>::invalid_dof_index); + } - /** - * Implementations of the - * get_dof_index/set_dof_index functions. - */ - template - static - unsigned int - get_dof_index (const DoFHandler<1,spacedim> &dof_handler, - const unsigned int obj_level, - const unsigned int obj_index, - const unsigned int fe_index, - const unsigned int local_index, - internal::int2type<1>) - { - return dof_handler.levels[obj_level]->lines. - get_dof_index (dof_handler, - obj_index, - fe_index, - local_index); - } + /** + * Implementations of the + * get_dof_index/set_dof_index functions. + */ + template + static + unsigned int + get_dof_index (const DoFHandler<1,spacedim> &dof_handler, + const unsigned int obj_level, + const unsigned int obj_index, + const unsigned int fe_index, + const unsigned int local_index, + internal::int2type<1>) + { + return dof_handler.levels[obj_level]->lines. + get_dof_index (dof_handler, + obj_index, + fe_index, + local_index); + } - template - static - void - set_dof_index (const DoFHandler<1,spacedim> &dof_handler, - const unsigned int obj_level, - const unsigned int obj_index, - const unsigned int fe_index, - const unsigned int local_index, - internal::int2type<1>, - const unsigned int global_index) - { - dof_handler.levels[obj_level]->lines. - set_dof_index (dof_handler, - obj_index, - fe_index, - local_index, - global_index); - } + template + static + void + set_dof_index (const DoFHandler<1,spacedim> &dof_handler, + const unsigned int obj_level, + const unsigned int obj_index, + const unsigned int fe_index, + const unsigned int local_index, + internal::int2type<1>, + const unsigned int global_index) + { + dof_handler.levels[obj_level]->lines. + set_dof_index (dof_handler, + obj_index, + fe_index, + local_index, + global_index); + } - template - static - unsigned int - get_dof_index (const DoFHandler<2,spacedim> &dof_handler, - const unsigned int obj_level, - const unsigned int obj_index, - const unsigned int fe_index, - const unsigned int local_index, - internal::int2type<1>) - { - // faces have no levels - Assert (obj_level == 0, ExcInternalError()); - return dof_handler.faces->lines. - get_dof_index (dof_handler, - obj_index, - fe_index, - local_index); - } + template + static + unsigned int + get_dof_index (const DoFHandler<2,spacedim> &dof_handler, + const unsigned int obj_level, + const unsigned int obj_index, + const unsigned int fe_index, + const unsigned int local_index, + internal::int2type<1>) + { + // faces have no levels + Assert (obj_level == 0, ExcInternalError()); + return dof_handler.faces->lines. + get_dof_index (dof_handler, + obj_index, + fe_index, + local_index); + } - template - static - void - set_dof_index (const DoFHandler<2,spacedim> &dof_handler, - const unsigned int obj_level, - const unsigned int obj_index, - const unsigned int fe_index, - const unsigned int local_index, - internal::int2type<1>, - const unsigned int global_index) - { - // faces have no levels - Assert (obj_level == 0, ExcInternalError()); - dof_handler.faces->lines. - set_dof_index (dof_handler, - obj_index, - fe_index, - local_index, - global_index); - } + template + static + void + set_dof_index (const DoFHandler<2,spacedim> &dof_handler, + const unsigned int obj_level, + const unsigned int obj_index, + const unsigned int fe_index, + const unsigned int local_index, + internal::int2type<1>, + const unsigned int global_index) + { + // faces have no levels + Assert (obj_level == 0, ExcInternalError()); + dof_handler.faces->lines. + set_dof_index (dof_handler, + obj_index, + fe_index, + local_index, + global_index); + } - template - static - unsigned int - get_dof_index (const DoFHandler<2,spacedim> &dof_handler, - const unsigned int obj_level, - const unsigned int obj_index, - const unsigned int fe_index, - const unsigned int local_index, - internal::int2type<2>) - { - return dof_handler.levels[obj_level]->quads. - get_dof_index (dof_handler, - obj_index, - fe_index, - local_index); - } + template + static + unsigned int + get_dof_index (const DoFHandler<2,spacedim> &dof_handler, + const unsigned int obj_level, + const unsigned int obj_index, + const unsigned int fe_index, + const unsigned int local_index, + internal::int2type<2>) + { + return dof_handler.levels[obj_level]->quads. + get_dof_index (dof_handler, + obj_index, + fe_index, + local_index); + } - template - static - void - set_dof_index (const DoFHandler<2,spacedim> &dof_handler, - const unsigned int obj_level, - const unsigned int obj_index, - const unsigned int fe_index, - const unsigned int local_index, - internal::int2type<2>, - const unsigned int global_index) - { - dof_handler.levels[obj_level]->quads. - set_dof_index (dof_handler, - obj_index, - fe_index, - local_index, - global_index); - } + template + static + void + set_dof_index (const DoFHandler<2,spacedim> &dof_handler, + const unsigned int obj_level, + const unsigned int obj_index, + const unsigned int fe_index, + const unsigned int local_index, + internal::int2type<2>, + const unsigned int global_index) + { + dof_handler.levels[obj_level]->quads. + set_dof_index (dof_handler, + obj_index, + fe_index, + local_index, + global_index); + } - template - static - unsigned int - get_dof_index (const DoFHandler<3,spacedim> &dof_handler, - const unsigned int obj_level, - const unsigned int obj_index, - const unsigned int fe_index, - const unsigned int local_index, - internal::int2type<1>) - { - // faces have no levels - Assert (obj_level == 0, ExcInternalError()); - return dof_handler.faces->lines. - get_dof_index (dof_handler, - obj_index, - fe_index, - local_index); - } + template + static + unsigned int + get_dof_index (const DoFHandler<3,spacedim> &dof_handler, + const unsigned int obj_level, + const unsigned int obj_index, + const unsigned int fe_index, + const unsigned int local_index, + internal::int2type<1>) + { + // faces have no levels + Assert (obj_level == 0, ExcInternalError()); + return dof_handler.faces->lines. + get_dof_index (dof_handler, + obj_index, + fe_index, + local_index); + } - template - static - void - set_dof_index (const DoFHandler<3,spacedim> &dof_handler, - const unsigned int obj_level, - const unsigned int obj_index, - const unsigned int fe_index, - const unsigned int local_index, - internal::int2type<1>, - const unsigned int global_index) - { - // faces have no levels - Assert (obj_level == 0, ExcInternalError()); - dof_handler.faces->lines. - set_dof_index (dof_handler, - obj_index, - fe_index, - local_index, - global_index); - } + template + static + void + set_dof_index (const DoFHandler<3,spacedim> &dof_handler, + const unsigned int obj_level, + const unsigned int obj_index, + const unsigned int fe_index, + const unsigned int local_index, + internal::int2type<1>, + const unsigned int global_index) + { + // faces have no levels + Assert (obj_level == 0, ExcInternalError()); + dof_handler.faces->lines. + set_dof_index (dof_handler, + obj_index, + fe_index, + local_index, + global_index); + } - template - static - unsigned int - get_dof_index (const DoFHandler<3,spacedim> &dof_handler, - const unsigned int obj_level, - const unsigned int obj_index, - const unsigned int fe_index, - const unsigned int local_index, - internal::int2type<2>) - { - // faces have no levels - Assert (obj_level == 0, ExcInternalError()); - return dof_handler.faces->quads. - get_dof_index (dof_handler, - obj_index, - fe_index, - local_index); - } + template + static + unsigned int + get_dof_index (const DoFHandler<3,spacedim> &dof_handler, + const unsigned int obj_level, + const unsigned int obj_index, + const unsigned int fe_index, + const unsigned int local_index, + internal::int2type<2>) + { + // faces have no levels + Assert (obj_level == 0, ExcInternalError()); + return dof_handler.faces->quads. + get_dof_index (dof_handler, + obj_index, + fe_index, + local_index); + } - template - static - void - set_dof_index (const DoFHandler<3,spacedim> &dof_handler, - const unsigned int obj_level, - const unsigned int obj_index, - const unsigned int fe_index, - const unsigned int local_index, - internal::int2type<2>, - const unsigned int global_index) - { - // faces have no levels - Assert (obj_level == 0, ExcInternalError()); - dof_handler.faces->quads. - set_dof_index (dof_handler, - obj_index, - fe_index, - local_index, - global_index); - } + template + static + void + set_dof_index (const DoFHandler<3,spacedim> &dof_handler, + const unsigned int obj_level, + const unsigned int obj_index, + const unsigned int fe_index, + const unsigned int local_index, + internal::int2type<2>, + const unsigned int global_index) + { + // faces have no levels + Assert (obj_level == 0, ExcInternalError()); + dof_handler.faces->quads. + set_dof_index (dof_handler, + obj_index, + fe_index, + local_index, + global_index); + } - template - static - unsigned int - get_dof_index (const DoFHandler<3,spacedim> &dof_handler, - const unsigned int obj_level, - const unsigned int obj_index, - const unsigned int fe_index, - const unsigned int local_index, - internal::int2type<3>) - { - return dof_handler.levels[obj_level]->hexes. - get_dof_index (dof_handler, - obj_index, - fe_index, - local_index); - } + template + static + unsigned int + get_dof_index (const DoFHandler<3,spacedim> &dof_handler, + const unsigned int obj_level, + const unsigned int obj_index, + const unsigned int fe_index, + const unsigned int local_index, + internal::int2type<3>) + { + return dof_handler.levels[obj_level]->hexes. + get_dof_index (dof_handler, + obj_index, + fe_index, + local_index); + } - template - static - void - set_dof_index (const DoFHandler<3,spacedim> &dof_handler, - const unsigned int obj_level, - const unsigned int obj_index, - const unsigned int fe_index, - const unsigned int local_index, - internal::int2type<3>, - const unsigned int global_index) - { - dof_handler.levels[obj_level]->hexes. - set_dof_index (dof_handler, - obj_index, - fe_index, - local_index, - global_index); - } -}; + template + static + void + set_dof_index (const DoFHandler<3,spacedim> &dof_handler, + const unsigned int obj_level, + const unsigned int obj_index, + const unsigned int fe_index, + const unsigned int local_index, + internal::int2type<3>, + const unsigned int global_index) + { + dof_handler.levels[obj_level]->hexes. + set_dof_index (dof_handler, + obj_index, + fe_index, + local_index, + global_index); + } + }; + } +} @@ -1930,7 +1945,7 @@ DoFHandler::get_dof_index (const unsigned int obj_level, const unsigned int local_index) const { return - Implementation::get_dof_index (*this, + internal::DoFHandler::Implementation::get_dof_index (*this, obj_level, obj_index, fe_index, local_index, internal::int2type()); @@ -1947,7 +1962,7 @@ DoFHandler::set_dof_index (const unsigned int obj_level, const unsigned int local_index, const unsigned int global_index) const { - Implementation::set_dof_index (*this, + internal::DoFHandler::Implementation::set_dof_index (*this, obj_level, obj_index, fe_index, local_index, internal::int2type(), @@ -2170,7 +2185,7 @@ void DoFHandler::distribute_dofs (const FiniteElement::distribute_dofs (const FiniteElement &new_numbers) #endif - Implementation::renumber_dofs (new_numbers, *this); + internal::DoFHandler::Implementation::renumber_dofs (new_numbers, *this); // update the cache used for cell dof // indices @@ -2256,7 +2271,7 @@ DoFHandler::max_couplings_between_dofs () const { Assert (selected_fe != 0, ExcNoFESelected()); - return Implementation::max_couplings_between_dofs (*this); + return internal::DoFHandler::Implementation::max_couplings_between_dofs (*this); } diff --git a/deal.II/deal.II/source/grid/tria.cc b/deal.II/deal.II/source/grid/tria.cc index 2af2ef6236..77ec67675c 100644 --- a/deal.II/deal.II/source/grid/tria.cc +++ b/deal.II/deal.II/source/grid/tria.cc @@ -1136,6 +1136,124 @@ namespace }// end of anonymous namespace +namespace internal +{ + namespace Triangulation + { + // make sure that if in the following we + // write Triangulation + // 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 @@ -1173,8 +1291,8 @@ namespace * 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 inner class rather - * than an anonymous namespace, for example. There are threee main reasons: + * 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 @@ -1182,415 +1300,458 @@ namespace * friends of the Triangulation class (there is no such thing as a "friend * namespace XXX" directive). * - * Secondly, by making this class a member class of the - * Triangulation class, our implementation functions + * Ideally, we would make this class a member class of the + * Triangulation 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::active_cell_iterator" but - * can write "active_cell_iterator" right away. + * surrounding Triangulation class. I.e., we do not have to write "typename + * Triangulation::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 * - * Finally, by only forward declaring the class in the .h file and - * declaring it here with member functions inlined, there is no need - * to declare all sorts of helper functions in the .h file: Much of - * what is implementation specific can be done within the .cc file - * without exposing any of the interface to the outside. + * 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... */ -template -struct Triangulation::Implementation -{ - /** - * Create a triangulation from - * given data. This function does - * this work for 1-dimensional - * triangulations independently - * of the actual space dimension. - */ - template - static - void - create_triangulation (const std::vector > &v, - const std::vector > &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; + struct Implementation + { + /** + * Create a triangulation from + * given data. This function does + * this work for 1-dimensional + * triangulations independently + * of the actual space dimension. + */ + template + static + void + create_triangulation (const std::vector > &v, + const std::vector > &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 (v.size(), true); + // copy vertices + triangulation.vertices = v; + triangulation.vertices_used = std::vector (v.size(), true); - // store the indices of the lines - // which are adjacent to a given - // vertex - std::vector > lines_at_vertex (v.size()); - - // reserve enough space - triangulation.levels.push_back (new internal::Triangulation::TriaLevel); - triangulation.levels[0]->reserve_space (cells.size(), dim); - triangulation.levels[0]->cells.reserve_space (0,cells.size()); + // store the indices of the lines + // which are adjacent to a given + // vertex + std::vector > lines_at_vertex (v.size()); + + // reserve enough space + triangulation.levels.push_back (new internal::Triangulation::TriaLevel); + triangulation.levels[0]->reserve_space (cells.size(), dim); + triangulation.levels[0]->cells.reserve_space (0,cells.size()); - // make up cells - raw_line_iterator next_free_line = triangulation.begin_raw_line (); - for (unsigned int cell=0; cellused()) - ++next_free_line; + // make up cells + typename Triangulation::raw_line_iterator + next_free_line = triangulation.begin_raw_line (); + for (unsigned int cell=0; cellused()) + ++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); + 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); - } + // 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 1) && (boundary_nodes <= 2)), - ExcMessage("The Triangulation has too many end points")); - } + // 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) && (boundary_nodes <= 2)), + ExcMessage("The Triangulation has too many end points")); + } - // update neighborship info - 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::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 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 cell_iterator neighbor (&triangulation, - 0, // level - lines_at_vertex[line->vertex_index(vertex)][0]); - line->set_neighbor (vertex, neighbor); - } - } + // update neighborship info + typename Triangulation::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::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::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::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 - static - void - create_triangulation (const std::vector > &v, - const std::vector > &cells, - const SubCellData &subcelldata, - Triangulation<2,spacedim> &triangulation) - { - const unsigned int dim=2; - - // copy vertices - triangulation.vertices = v; - triangulation.vertices_used = std::vector (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,line_iterator> needed_lines; - for (unsigned int cell=0; cell + static + void + create_triangulation (const std::vector > &v, + const std::vector > &cells, + const SubCellData &subcelldata, + Triangulation<2,spacedim> &triangulation) { - 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::faces_per_cell; ++line) + const unsigned int dim=2; + + // copy vertices + triangulation.vertices = v; + triangulation.vertices_used = std::vector (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, + typename Triangulation::line_iterator> needed_lines; + for (unsigned int cell=0; cell line_vertices( - cells[cell].vertices[GeometryInfo::line_to_cell_vertices(line, 0)], - cells[cell].vertices[GeometryInfo::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)); + 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::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 line_vertices( + cells[cell].vertices[GeometryInfo::line_to_cell_vertices(line, 0)], + cells[cell].vertices[GeometryInfo::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(); + // 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 vertex_touch_count (v.size(), 0); - typename std::map,line_iterator>::iterator i; - for (i=needed_lines.begin(); i!=needed_lines.end(); i++) + // check that every vertex has at + // least two adjacent lines { - // touch the vertices of - // this line - ++vertex_touch_count[i->first.first]; - ++vertex_touch_count[i->first.second]; - } + std::vector vertex_touch_count (v.size(), 0); + typename std::map, + typename Triangulation::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()); - } + // 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); - triangulation.faces = new internal::Triangulation::TriaFaces; - 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 - { - raw_line_iterator line = triangulation.begin_raw_line(); - typename std::map,line_iterator>::iterator i; - for (i = needed_lines.begin(); - line!=triangulation.end_line(); ++line, ++i) + // reserve enough space + triangulation.levels.push_back (new internal::Triangulation::TriaLevel); + triangulation.faces = new internal::Triangulation::TriaFaces; + 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 { - 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; + typename Triangulation::raw_line_iterator + line = triangulation.begin_raw_line(); + typename std::map, + typename Triangulation::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 > adjacent_cells; + // store for each line index + // the adjacent cells + std::map::cell_iterator> > + adjacent_cells; - // finally make up cells - { - raw_cell_iterator cell = triangulation.begin_raw_quad(); - for (unsigned int c=0; c::lines_per_cell]; - for (unsigned int line=0; line::lines_per_cell; ++line) - lines[line]=needed_lines[std::make_pair( - cells[c].vertices[GeometryInfo::line_to_cell_vertices(line, 0)], - cells[c].vertices[GeometryInfo::line_to_cell_vertices(line, 1)])]; + typename Triangulation::raw_cell_iterator + cell = triangulation.begin_raw_quad(); + for (unsigned int c=0; c::line_iterator + lines[GeometryInfo::lines_per_cell]; + for (unsigned int line=0; line::lines_per_cell; ++line) + lines[line]=needed_lines[std::make_pair( + cells[c].vertices[GeometryInfo::line_to_cell_vertices(line, 0)], + cells[c].vertices[GeometryInfo::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 (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); + 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::lines_per_cell; ++line) - adjacent_cells[lines[line]->index()].push_back (cell); + // note that this cell is + // adjacent to the four + // lines + for (unsigned int line=0; line::lines_per_cell; ++line) + adjacent_cells[lines[line]->index()].push_back (cell); + } } - } - for (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()); + for (typename Triangulation::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); - } + // 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 >::const_iterator boundary_line - = subcelldata.boundary_lines.begin(); - std::vector >::const_iterator end_boundary_line - = subcelldata.boundary_lines.end(); - for (; boundary_line!=end_boundary_line; ++boundary_line) - { - line_iterator line; - std::pair 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 + // set boundary indicators where + // given + std::vector >::const_iterator boundary_line + = subcelldata.boundary_lines.begin(); + std::vector >::const_iterator end_boundary_line + = subcelldata.boundary_lines.end(); + for (; boundary_line!=end_boundary_line; ++boundary_line) { - // look whether it exists - // in reverse direction - std::swap (line_vertices.first, line_vertices.second); + typename Triangulation::line_iterator line; + std::pair 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 - // line does not exist - AssertThrow (false, ExcLineInexistant(line_vertices.first, - line_vertices.second)); - } + { + // 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 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()); + // Assert that only exterior lines + // are given a boundary indicator + AssertThrow (! (line->boundary_indicator() == 255), + ExcInteriorLineCantBeBoundary()); - line->set_boundary_indicator (boundary_line->material_id); - } + line->set_boundary_indicator (boundary_line->material_id); + } - // finally update neighborship info - for (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 + // finally update neighborship info + for (typename Triangulation::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()][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]); - } + adjacent_cells[cell->line(side)->index()][0]); + } /** @@ -1602,1969 +1763,2008 @@ struct Triangulation::Implementation * 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; - } - }; + 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 - static - void - create_triangulation (const std::vector > &v, - const std::vector > &cells, - const SubCellData &subcelldata, - Triangulation<3,spacedim> &triangulation) - { - const unsigned int dim=3; - - // copy vertices - triangulation.vertices = v; - triangulation.vertices_used = std::vector (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= 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,line_iterator> needed_lines; - for (unsigned int cell=0; cell + static + void + create_triangulation (const std::vector > &v, + const std::vector > &cells, + const SubCellData &subcelldata, + Triangulation<3,spacedim> &triangulation) { - // check whether vertex indices - // are valid ones - for (unsigned int vertex=0; vertex::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::lines_per_cell; ++line) + const unsigned int dim=3; + + // copy vertices + triangulation.vertices = v; + triangulation.vertices_used = std::vector (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= 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, + typename Triangulation::line_iterator> needed_lines; + for (unsigned int cell=0; cell line_vertices( - cells[cell].vertices[GeometryInfo::line_to_cell_vertices(line, 0)], - cells[cell].vertices[GeometryInfo::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())) + // check whether vertex indices + // are valid ones + for (unsigned int vertex=0; vertex::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::lines_per_cell; ++line) { - // insert line, with - // invalid iterator. if line - // already exists, then - // nothing bad happens here - needed_lines[line_vertices] = triangulation.end_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 line_vertices( + cells[cell].vertices[GeometryInfo::line_to_cell_vertices(line, 0)], + cells[cell].vertices[GeometryInfo::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 vertex_touch_count (v.size(), 0); - typename std::map,line_iterator>::iterator i; - for (i=needed_lines.begin(); i!=needed_lines.end(); i++) + ///////////////////////////////// + // now for some sanity-checks: + // + // check that every vertex has at + // least tree adjacent lines { - // touch the vertices of - // this line - ++vertex_touch_count[i->first.first]; - ++vertex_touch_count[i->first.second]; - } + std::vector vertex_touch_count (v.size(), 0); + typename std::map, + typename Triangulation::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()); - } + // 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); - triangulation.faces = new internal::Triangulation::TriaFaces; - triangulation.levels[0]->reserve_space (cells.size(), dim); - triangulation.faces->lines.reserve_space (0,needed_lines.size()); + /////////////////////////////////// + // actually set up data structures + // for the lines + // reserve enough space + triangulation.levels.push_back (new internal::Triangulation::TriaLevel); + triangulation.faces = new internal::Triangulation::TriaFaces; + triangulation.levels[0]->reserve_space (cells.size(), dim); + triangulation.faces->lines.reserve_space (0,needed_lines.size()); - // make up lines - { - raw_line_iterator line = triangulation.begin_raw_line(); - typename std::map,line_iterator>::iterator i; - for (i = needed_lines.begin(); line!=triangulation.end_line(); ++line, ++i) + // make up lines { - 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; - } - } - + typename Triangulation::raw_line_iterator + line = triangulation.begin_raw_line(); + typename std::map, + typename Triangulation::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 (); - /////////////////////////////////////////// - // 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 + // now set the iterator for + // this line + i->second = line; + } + } - // 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,std::pair::lines_per_face> >,QuadComparator> - needed_quads; - for (unsigned int cell=0; cell line_list[GeometryInfo::lines_per_cell], - inverse_line_list[GeometryInfo::lines_per_cell]; - unsigned int face_line_list[GeometryInfo::lines_per_face]; - boost::array::lines_per_face> orientation; - - for (unsigned int line=0; line::lines_per_cell; ++line) - { - line_list[line]=std::pair ( - cells[cell].vertices[GeometryInfo::line_to_cell_vertices(line, 0)], - cells[cell].vertices[GeometryInfo::line_to_cell_vertices(line, 1)]); - inverse_line_list[line]=std::pair ( - cells[cell].vertices[GeometryInfo::line_to_cell_vertices(line, 1)], - cells[cell].vertices[GeometryInfo::line_to_cell_vertices(line, 0)]); - } - - for (unsigned int face=0; face::faces_per_cell; ++face) + // 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, + std::pair::quad_iterator, + boost::array::lines_per_face> >, + QuadComparator> + needed_quads; + for (unsigned int cell=0; cell::lines_per_face; ++l) - if (needed_lines.find (inverse_line_list[GeometryInfo:: - face_to_cell_lines(face,l)]) == needed_lines.end()) - { - face_line_list[l]=needed_lines[line_list[GeometryInfo:: - face_to_cell_lines(face,l)]]->index(); - orientation[l]=true; - } - else - { - face_line_list[l]=needed_lines[inverse_line_list[GeometryInfo:: - face_to_cell_lines(face,l)]]->index(); - orientation[l]=false; - } + // 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 line_list[GeometryInfo::lines_per_cell], + inverse_line_list[GeometryInfo::lines_per_cell]; + unsigned int face_line_list[GeometryInfo::lines_per_face]; + boost::array::lines_per_face> orientation; + + for (unsigned int line=0; line::lines_per_cell; ++line) + { + line_list[line]=std::pair ( + cells[cell].vertices[GeometryInfo::line_to_cell_vertices(line, 0)], + cells[cell].vertices[GeometryInfo::line_to_cell_vertices(line, 1)]); + inverse_line_list[line]=std::pair ( + cells[cell].vertices[GeometryInfo::line_to_cell_vertices(line, 1)], + cells[cell].vertices[GeometryInfo::line_to_cell_vertices(line, 0)]); + } + + for (unsigned int face=0; face::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::lines_per_face; ++l) + if (needed_lines.find (inverse_line_list[GeometryInfo:: + face_to_cell_lines(face,l)]) == needed_lines.end()) + { + face_line_list[l]=needed_lines[line_list[GeometryInfo:: + face_to_cell_lines(face,l)]]->index(); + orientation[l]=true; + } + else + { + face_line_list[l]=needed_lines[inverse_line_list[GeometryInfo:: + 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]); + 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); + // 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()); + ///////////////////////////////// + // enter the resulting quads into + // the arrays of the Triangulation + // + // first reserve enough space + triangulation.faces->quads.reserve_space (0,needed_quads.size()); - { - raw_quad_iterator quad = triangulation.begin_raw_quad(); - typename std::map, - std::pair::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]); + typename Triangulation::raw_quad_iterator + quad = triangulation.begin_raw_quad(); + typename std::map, + std::pair::quad_iterator, + boost::array::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; + // now set the iterator for + // this quad + q->second.first = quad; + } } - } - ///////////////////////////////// - // finally create the cells - triangulation.levels[0]->cells.reserve_space (cells.size()); + ///////////////////////////////// + // finally create the cells + triangulation.levels[0]->cells.reserve_space (cells.size()); - // store for each quad index the - // adjacent cells - std::map > adjacent_cells; + // store for each quad index the + // adjacent cells + std::map::cell_iterator> > + adjacent_cells; - // finally make up cells - { - raw_cell_iterator cell = triangulation.begin_raw_hex(); - for (unsigned int c=0; c line_list[GeometryInfo::lines_per_cell], - inverse_line_list[GeometryInfo::lines_per_cell]; - unsigned int face_line_list[4]; - for (unsigned int line=0; line::lines_per_cell; ++line) - { - line_list[line]=std::make_pair( - cells[c].vertices[GeometryInfo::line_to_cell_vertices(line, 0)], - cells[c].vertices[GeometryInfo::line_to_cell_vertices(line, 1)]); - inverse_line_list[line]=std::pair ( - cells[c].vertices[GeometryInfo::line_to_cell_vertices(line, 1)], - cells[c].vertices[GeometryInfo::line_to_cell_vertices(line, 0)]); - } - - // get the iterators - // corresponding to the - // faces. also store - // whether they are - // reversed or not - quad_iterator face_iterator[GeometryInfo::faces_per_cell]; - bool face_orientation[GeometryInfo::faces_per_cell]; - bool face_flip[GeometryInfo::faces_per_cell]; - bool face_rotation[GeometryInfo::faces_per_cell]; - for (unsigned int face=0; face::faces_per_cell; ++face) + typename Triangulation::raw_cell_iterator + cell = triangulation.begin_raw_hex(); + for (unsigned int c=0; c::lines_per_face; ++l) - if (needed_lines.find (inverse_line_list[GeometryInfo:: - face_to_cell_lines(face,l)]) == needed_lines.end()) - face_line_list[l]=needed_lines[line_list[GeometryInfo:: - face_to_cell_lines(face,l)]]->index(); - else - face_line_list[l]=needed_lines[inverse_line_list[GeometryInfo:: - 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()) + // 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 line_list[GeometryInfo::lines_per_cell], + inverse_line_list[GeometryInfo::lines_per_cell]; + unsigned int face_line_list[4]; + for (unsigned int line=0; line::lines_per_cell; ++line) { - // 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; + line_list[line]=std::make_pair( + cells[c].vertices[GeometryInfo::line_to_cell_vertices(line, 0)], + cells[c].vertices[GeometryInfo::line_to_cell_vertices(line, 1)]); + inverse_line_list[line]=std::pair ( + cells[c].vertices[GeometryInfo::line_to_cell_vertices(line, 1)], + cells[c].vertices[GeometryInfo::line_to_cell_vertices(line, 0)]); } - else + + // get the iterators + // corresponding to the + // faces. also store + // whether they are + // reversed or not + typename Triangulation::quad_iterator + face_iterator[GeometryInfo::faces_per_cell]; + bool face_orientation[GeometryInfo::faces_per_cell]; + bool face_flip[GeometryInfo::faces_per_cell]; + bool face_rotation[GeometryInfo::faces_per_cell]; + for (unsigned int face=0; face::faces_per_cell; ++face) { - // 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()) + for (unsigned int l=0; l::lines_per_face; ++l) + if (needed_lines.find (inverse_line_list[GeometryInfo:: + face_to_cell_lines(face,l)]) == needed_lines.end()) + face_line_list[l]=needed_lines[line_list[GeometryInfo:: + face_to_cell_lines(face,l)]]->index(); + else + face_line_list[l]=needed_lines[inverse_line_list[GeometryInfo:: + 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_iterator[face] = needed_quads[test_quad_5].first; + // 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]=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()) + else { - face_iterator[face] = needed_quads[test_quad_7].first; - face_orientation[face] = true; - face_flip[face]=true; - face_rotation[face]=true; - } + // 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()); + 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())); + } + }// for all faces - 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::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]); - } + // 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::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::faces_per_cell; ++quad) - adjacent_cells[face_iterator[quad]->index()].push_back (cell); + // note that this cell is + // adjacent to the six + // quads + for (unsigned int quad=0; quad::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 > - cell_to_face_lines; - for (unsigned int face=0; face::faces_per_cell; ++face) - for (unsigned int line=0; line::lines_per_face; ++line) - cell_to_face_lines.insert( - std::pair > ( - GeometryInfo::face_to_cell_lines(face,line), - std::pair (face,line))); - std::multimap >::const_iterator - map_iter=cell_to_face_lines.begin(); + // 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 > + cell_to_face_lines; + for (unsigned int face=0; face::faces_per_cell; ++face) + for (unsigned int line=0; line::lines_per_face; ++line) + cell_to_face_lines.insert( + std::pair > ( + GeometryInfo::face_to_cell_lines(face,line), + std::pair (face,line))); + std::multimap >::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::standard_to_real_face_line( - line1, - face_orientation[face1], - face_flip[face1], - face_rotation[face1])) == - face_iterator[face2]->line(GeometryInfo::standard_to_real_face_line( - line2, - face_orientation[face2], - face_flip[face2], - face_rotation[face2])), - ExcInternalErrorOnCell(c)); - } + 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::standard_to_real_face_line( + line1, + face_orientation[face1], + face_flip[face1], + face_rotation[face1])) == + face_iterator[face2]->line(GeometryInfo::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 (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 (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 (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); - - // Check that all cells have - // positive volume. As the input - // CellData already passed this - // test we don't really expect - // negative measures here - for (active_cell_iterator cell=triangulation.begin_active(); cell!=triangulation.end(); ++cell) - Assert(cell->measure()>0, ExcInternalError()); - - /////////////////////////////////////// - // now set boundary indicators - // where given - // - // first do so for lines - std::vector >::const_iterator boundary_line - = subcelldata.boundary_lines.begin(); - std::vector >::const_iterator end_boundary_line - = subcelldata.boundary_lines.end(); - for (; boundary_line!=end_boundary_line; ++boundary_line) - { - line_iterator line; - std::pair 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 + ///////////////////////////////////////// + // find those quads which are at the + // boundary and mark them appropriately + for (typename Triangulation::quad_iterator + quad=triangulation.begin_quad(); quad!=triangulation.end_quad(); ++quad) { - // 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]; + 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 - // line does not exist - AssertThrow (false, ExcLineInexistant(line_vertices.first, - line_vertices.second)); + // interior quad -> 255 + quad->set_boundary_indicator (255); } - // 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); - } + ///////////////////////////////////////// + // 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::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::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 go on with boundary faces - std::vector >::const_iterator boundary_quad - = subcelldata.boundary_quads.begin(); - std::vector >::const_iterator end_boundary_quad - = subcelldata.boundary_quads.end(); - for (; boundary_quad!=end_boundary_quad; ++boundary_quad) - { - quad_iterator quad; - 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) + // Check that all cells have + // positive volume. As the input + // CellData already passed this + // test we don't really expect + // negative measures here + for (typename Triangulation::active_cell_iterator + cell=triangulation.begin_active(); cell!=triangulation.end(); ++cell) + Assert(cell->measure()>0, ExcInternalError()); + + /////////////////////////////////////// + // now set boundary indicators + // where given + // + // first do so for lines + std::vector >::const_iterator boundary_line + = subcelldata.boundary_lines.begin(); + std::vector >::const_iterator end_boundary_line + = subcelldata.boundary_lines.end(); + for (; boundary_line!=end_boundary_line; ++boundary_line) { - std::pair line_vertices( - boundary_quad->vertices[GeometryInfo::line_to_cell_vertices(i,0)], - boundary_quad->vertices[GeometryInfo::line_to_cell_vertices(i,1)]); - - // check whether line - // already exists + typename Triangulation::line_iterator line; + std::pair line_vertices(std::make_pair(boundary_line->vertices[0], + boundary_line->vertices[1])); if (needed_lines.find(line_vertices) != needed_lines.end()) - line[i] = needed_lines[line_vertices]; + // line found in this + // direction + line = needed_lines[line_vertices]; + else - // look wether it exists - // in reverse direction { + // 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]; + line = needed_lines[line_vertices]; else - // line does - // not exist + // 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 >::const_iterator boundary_quad + = subcelldata.boundary_quads.begin(); + std::vector >::const_iterator end_boundary_quad + = subcelldata.boundary_quads.end(); + for (; boundary_quad!=end_boundary_quad; ++boundary_quad) + { + typename Triangulation::quad_iterator quad; + typename Triangulation::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 line_vertices( + boundary_quad->vertices[GeometryInfo::line_to_cell_vertices(i,0)], + boundary_quad->vertices[GeometryInfo::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()); + // 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 - 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 - rotate(line_counterclock, line_counterclock+1, line_counterclock+4); - // update the quads with - // rotated lines (i runs in - // lexicographic ordering) + // 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::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)) { - quad_compare_1.set_face(i, line_counterclock[lex2cclock[i]]->index()); - quad_compare_2.set_face((i+2)%4, line_counterclock[lex2cclock[i]]->index()); - } + // use the rotate defined + // in + 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; - } + ++n_rotations; + } - AssertThrow (n_rotations!=4, - ExcQuadInexistant(line[0]->index(), line[1]->index(), - line[2]->index(), line[3]->index())); + 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.")); + 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); - } + quad->set_boundary_indicator (boundary_quad->material_id); + } - ///////////////////////////////////////// - // finally update neighborship info - for (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 + ///////////////////////////////////////// + // finally update neighborship info + for (typename Triangulation::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()][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]); - } + adjacent_cells[cell->quad(face)->index()][0]); + } - /** - * Distort a 1d triangulation in - * some random way. - */ - template - static - void - distort_random (const double factor, - const bool keep_boundary, - Triangulation<1,spacedim> &triangulation) - { - // 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 + /** + * Distort a 1d triangulation in + * some random way. + */ + template + 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 (cell_iterator cell=triangulation.begin(0); cell!=triangulation.end(0); ++cell) - almost_infinite_length += cell->diameter(); + // 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::cell_iterator + cell=triangulation.begin(0); cell!=triangulation.end(0); ++cell) + almost_infinite_length += cell->diameter(); - std::vector minimal_length (triangulation.vertices.size(), - almost_infinite_length); - // also note if a vertex is at - // the boundary - std::vector at_boundary (triangulation.vertices.size(), false); + std::vector minimal_length (triangulation.vertices.size(), + almost_infinite_length); + // also note if a vertex is at + // the boundary + std::vector at_boundary (triangulation.vertices.size(), false); - for (active_line_iterator line=triangulation.begin_active_line(); - line != triangulation.end_line(); ++line) - { - if (keep_boundary && line->at_boundary()) + for (typename Triangulation::active_line_iterator + line=triangulation.begin_active_line(); + line != triangulation.end_line(); ++line) { - at_boundary[line->vertex_index(0)] = true; - at_boundary[line->vertex_index(1)] = true; - } + 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)]); - } + 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 shift_vector; + const unsigned int n_vertices = triangulation.vertices.size(); + Point shift_vector; - for (unsigned int vertex=0; vertex1. - */ - template - static - void - distort_random (const double factor, - const bool keep_boundary, - Triangulation &triangulation) - { + /** + * Distort a triangulation in + * some random way. This is the + * function taken for the case + * dim>1. + */ + template + static + void + distort_random (const double factor, + const bool keep_boundary, + Triangulation &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 + // 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 (cell_iterator cell=triangulation.begin(0); cell!=triangulation.end(0); ++cell) - almost_infinite_length += cell->diameter(); + // 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::cell_iterator + cell=triangulation.begin(0); cell!=triangulation.end(0); ++cell) + almost_infinite_length += cell->diameter(); - std::vector minimal_length (triangulation.vertices.size(), - almost_infinite_length); + std::vector minimal_length (triangulation.vertices.size(), + almost_infinite_length); - // also note if a vertex is at the - // boundary - std::vector at_boundary (triangulation.vertices.size(), false); + // also note if a vertex is at the + // boundary + std::vector at_boundary (triangulation.vertices.size(), false); - for (active_line_iterator line=triangulation.begin_active_line(); - line != triangulation.end_line(); ++line) - { - if (keep_boundary && line->at_boundary()) + for (typename Triangulation::active_line_iterator + line=triangulation.begin_active_line(); + line != triangulation.end_line(); ++line) { - at_boundary[line->vertex_index(0)] = true; - at_boundary[line->vertex_index(1)] = true; - } + 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)]); - } + 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 shift_vector; + const unsigned int n_vertices = triangulation.vertices.size(); + Point shift_vector; - for (unsigned int vertex=0; vertex::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; - } - } + // finally correct hanging nodes + // again. The following is not + // necessary for 1D + typename Triangulation::active_cell_iterator + cell = triangulation.begin_active(), + endc = triangulation.end(); + for (; cell!=endc; ++cell) + for (unsigned int face=0; face::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 - static - void - delete_children (Triangulation<1,spacedim> &triangulation, - cell_iterator &cell, - std::vector &, - std::vector &) - { - // 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()); + /** + * 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 + static + void + delete_children (Triangulation<1,spacedim> &triangulation, + typename Triangulation<1,spacedim>::cell_iterator &cell, + std::vector &, + std::vector &) + { + 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()) - { - cell_iterator neighbor = cell->neighbor(0); - Assert (neighbor->level() == cell->level(), ExcInternalError()); - - // right child - neighbor = neighbor->child(1); - while (1) + // first do it for the cells to the + // left + if (cell->neighbor(0).state() == IteratorState::valid) + if (cell->neighbor(0)->has_children()) { - Assert (neighbor->neighbor(1) == cell->child(0), - ExcInternalError()); - neighbor->set_neighbor (1, cell); + typename Triangulation::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; + // 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()) - { - cell_iterator neighbor = cell->neighbor(1); - Assert (neighbor->level() == cell->level(), ExcInternalError()); - - // left child - neighbor = neighbor->child(0); - while (1) + // now do it for the cells to the + // left + if (cell->neighbor(1).state() == IteratorState::valid) + if (cell->neighbor(1)->has_children()) { - Assert (neighbor->neighbor(0) == cell->child(1), - ExcInternalError()); - neighbor->set_neighbor (0, cell); + typename Triangulation::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; + // 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; + // 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; childn_children(); ++child) - { - cell->child(child)->clear_user_data(); - cell->child(child)->clear_user_flag(); - cell->child(child)->clear_used_flag(); - } + // invalidate children. clear user + // pointers, to avoid that they may + // appear at unwanted places later + // on... + for (unsigned int child=0; childn_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(); - } + // delete pointer to children + cell->clear_children (); + cell->clear_user_flag(); + } - template - static - void - delete_children (Triangulation<2,spacedim> &triangulation, - cell_iterator &cell, - std::vector &, - std::vector &) - { - const unsigned int dim=2; - const RefinementCase ref_case=cell->refinement_case(); + template + static + void + delete_children (Triangulation<2,spacedim> &triangulation, + typename Triangulation<2,spacedim>::cell_iterator &cell, + std::vector &, + std::vector &) + { + const unsigned int dim=2; + const RefinementCase ref_case=cell->refinement_case(); - for (unsigned int face_no=0; face_no::faces_per_cell; ++face_no) - if (!cell->at_boundary(face_no)) - { - if (GeometryInfo::face_refinement_case(ref_case, face_no) - ==RefinementCase<1>::no_refinement) - cell->set_neighbor(face_no,cell->child(face_no%2)->neighbor(face_no)); + for (unsigned int face_no=0; face_no::faces_per_cell; ++face_no) + if (!cell->at_boundary(face_no)) + { + if (GeometryInfo::face_refinement_case(ref_case, face_no) + ==RefinementCase<1>::no_refinement) + cell->set_neighbor(face_no,cell->child(face_no%2)->neighbor(face_no)); - cell_iterator neighbor=cell->neighbor(face_no); + typename Triangulation::cell_iterator + neighbor=cell->neighbor(face_no); - // it is possible that the neighbor is - // coarser if it has already been - // coarsened earlier in this cycle. for - // anisotropic refinement that can - // happen, even if the neighbor is on a - // higher level. + // it is possible that the neighbor is + // coarser if it has already been + // coarsened earlier in this cycle. for + // anisotropic refinement that can + // happen, even if the neighbor is on a + // higher level. - // it is also possible, that the - // neighbor information of cell was not - // the best information currently - // available. however, the neighbor - // information now set should be - // accurate, as we have taken the - // pointer from one of our children, if - // that could be mor accurate and these - // children can't be further refined. + // it is also possible, that the + // neighbor information of cell was not + // the best information currently + // available. however, the neighbor + // information now set should be + // accurate, as we have taken the + // pointer from one of our children, if + // that could be mor accurate and these + // children can't be further refined. - // if the neighbor is coarser, do - // nothing: we won't have to reset our - // pointer of course and the coarser - // neighbor does not point to this cell - if (cell->neighbor_is_coarser(face_no)) - { - Assert(neighbor->active(), - ExcInternalError()); - continue; - } + // if the neighbor is coarser, do + // nothing: we won't have to reset our + // pointer of course and the coarser + // neighbor does not point to this cell + if (cell->neighbor_is_coarser(face_no)) + { + Assert(neighbor->active(), + ExcInternalError()); + continue; + } - const unsigned int nb_nb=cell->neighbor_of_neighbor(face_no); - neighbor->set_neighbor(nb_nb, cell); - // go down the list of children which - // are not refined along the face (if - // any) - while (neighbor->has_children() && - (GeometryInfo::face_refinement_case(neighbor->refinement_case(), nb_nb) - ==RefinementCase::no_refinement)) - { - neighbor=neighbor->child(GeometryInfo - ::child_cell_on_face(neighbor->refinement_case(), - nb_nb, - 0)); + const unsigned int nb_nb=cell->neighbor_of_neighbor(face_no); neighbor->set_neighbor(nb_nb, cell); - } + // go down the list of children which + // are not refined along the face (if + // any) + while (neighbor->has_children() && + (GeometryInfo::face_refinement_case(neighbor->refinement_case(), nb_nb) + ==RefinementCase::no_refinement)) + { + neighbor=neighbor->child(GeometryInfo + ::child_cell_on_face(neighbor->refinement_case(), + nb_nb, + 0)); + neighbor->set_neighbor(nb_nb, cell); + } - // now we can safely set the cells - // neighbor - cell->set_neighbor(face_no,neighbor); + // now we can safely set the cells + // neighbor + cell->set_neighbor(face_no,neighbor); - // if there are still children, they - // have to be refined along the face - // currently under consideration - if (neighbor->has_children()) - { - unsigned int n_subfaces=GeometryInfo::n_children( - GeometryInfo::face_refinement_case(neighbor->refinement_case(), nb_nb)); - Assert (n_subfaces>0, ExcInternalError()); - - for (unsigned int i=0; ihas_children()) { - cell_iterator neighbor_child=neighbor->child( - GeometryInfo::child_cell_on_face(neighbor->refinement_case(), - nb_nb, i)); - neighbor_child->set_neighbor(nb_nb, cell); - // once again, this - // neighbor_child can be - // refined several times, - // as long as this - // refinement is not along - // the current subface. if - // there are children - // refined along the - // subface they will be - // coarsened away later in - // this process, so we - // don't care about them - // here - while (neighbor_child->has_children() && - (GeometryInfo::face_refinement_case(neighbor_child->refinement_case(), - nb_nb) - == RefinementCase::no_refinement)) + unsigned int n_subfaces=GeometryInfo::n_children( + GeometryInfo::face_refinement_case(neighbor->refinement_case(), nb_nb)); + Assert (n_subfaces>0, ExcInternalError()); + + for (unsigned int i=0; ichild(GeometryInfo - ::child_cell_on_face(neighbor_child->refinement_case(), - nb_nb, - 0)); + typename Triangulation::cell_iterator + neighbor_child=neighbor->child( + GeometryInfo::child_cell_on_face(neighbor->refinement_case(), + nb_nb, i)); neighbor_child->set_neighbor(nb_nb, cell); + // once again, this + // neighbor_child can be + // refined several times, + // as long as this + // refinement is not along + // the current subface. if + // there are children + // refined along the + // subface they will be + // coarsened away later in + // this process, so we + // don't care about them + // here + while (neighbor_child->has_children() && + (GeometryInfo::face_refinement_case(neighbor_child->refinement_case(), + nb_nb) + == RefinementCase::no_refinement)) + { + neighbor_child=neighbor_child + ->child(GeometryInfo + ::child_cell_on_face(neighbor_child->refinement_case(), + nb_nb, + 0)); + neighbor_child->set_neighbor(nb_nb, cell); + } } } } - } - // 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::cut_xy) - { - triangulation.vertices_used[cell->child(0)->line(1)->vertex_index(1)] = false; + // 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::cut_xy) + { + triangulation.vertices_used[cell->child(0)->line(1)->vertex_index(1)] = false; - // clear user pointers, to - // avoid that they may appear - // at unwanted places later - // on... - cell->child(0)->line(1)->clear_user_data(); - cell->child(0)->line(3)->clear_user_data(); - cell->child(3)->line(0)->clear_user_data(); - cell->child(3)->line(2)->clear_user_data(); + // clear user pointers, to + // avoid that they may appear + // at unwanted places later + // on... + cell->child(0)->line(1)->clear_user_data(); + cell->child(0)->line(3)->clear_user_data(); + cell->child(3)->line(0)->clear_user_data(); + cell->child(3)->line(2)->clear_user_data(); - // same for user flags - cell->child(0)->line(1)->clear_user_flag(); - cell->child(0)->line(3)->clear_user_flag(); - cell->child(3)->line(0)->clear_user_flag(); - cell->child(3)->line(2)->clear_user_flag(); + // same for user flags + cell->child(0)->line(1)->clear_user_flag(); + cell->child(0)->line(3)->clear_user_flag(); + cell->child(3)->line(0)->clear_user_flag(); + cell->child(3)->line(2)->clear_user_flag(); - // delete the four interior - // lines - cell->child(0)->line(1)->clear_used_flag(); - cell->child(0)->line(3)->clear_used_flag(); - cell->child(3)->line(0)->clear_used_flag(); - cell->child(3)->line(2)->clear_used_flag(); - } - else - { - unsigned int inner_face_no=ref_case==RefinementCase::cut_x ? 1 : 3; + // delete the four interior + // lines + cell->child(0)->line(1)->clear_used_flag(); + cell->child(0)->line(3)->clear_used_flag(); + cell->child(3)->line(0)->clear_used_flag(); + cell->child(3)->line(2)->clear_used_flag(); + } + else + { + unsigned int inner_face_no=ref_case==RefinementCase::cut_x ? 1 : 3; - // the inner line will not be - // used any more - cell->child(0)->line(inner_face_no)->clear_user_data(); - cell->child(0)->line(inner_face_no)->clear_user_flag(); - cell->child(0)->line(inner_face_no)->clear_used_flag(); - } + // the inner line will not be + // used any more + cell->child(0)->line(inner_face_no)->clear_user_data(); + cell->child(0)->line(inner_face_no)->clear_user_flag(); + cell->child(0)->line(inner_face_no)->clear_used_flag(); + } - // if the neighbor does not need - // the subfaces, delete them. in case of - // anisotropic refinement we can't just - // ask the neighbor's level here to - // assure, that he is not refined along - // the face - for (unsigned int face=0; face::faces_per_cell; ++face) - if (((cell->neighbor(face).state() != IteratorState::valid) || - (!cell->neighbor(face)->has_children())) && - (GeometryInfo::face_refinement_case(ref_case,face) - !=RefinementCase::no_refinement)) - { - line_iterator line=cell->face(face); - // delete middle vertex - triangulation.vertices_used[line->child(0)->vertex_index(1)] = false; - // delete the two subfaces - for (unsigned int subface=0; - subfacen_children(); ++subface) + // if the neighbor does not need + // the subfaces, delete them. in case of + // anisotropic refinement we can't just + // ask the neighbor's level here to + // assure, that he is not refined along + // the face + for (unsigned int face=0; face::faces_per_cell; ++face) + if (((cell->neighbor(face).state() != IteratorState::valid) || + (!cell->neighbor(face)->has_children())) && + (GeometryInfo::face_refinement_case(ref_case,face) + !=RefinementCase::no_refinement)) { - line->child(subface)->clear_user_data (); - line->child(subface)->clear_user_flag (); - line->child(subface)->clear_used_flag (); - } + typename Triangulation::line_iterator + line=cell->face(face); + // delete middle vertex + triangulation.vertices_used[line->child(0)->vertex_index(1)] = false; + // delete the two subfaces + for (unsigned int subface=0; + subfacen_children(); ++subface) + { + line->child(subface)->clear_user_data (); + line->child(subface)->clear_user_flag (); + line->child(subface)->clear_used_flag (); + } - line->clear_children(); - } - // invalidate children - for (unsigned int child=0; childn_children(); ++child) - { - cell->child(child)->clear_user_data(); - cell->child(child)->clear_user_flag(); - cell->child(child)->clear_used_flag(); - } + line->clear_children(); + } + // invalidate children + for (unsigned int child=0; childn_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(); - } + // delete pointer to children + cell->clear_children (); + cell->clear_refinement_case(); + cell->clear_user_flag(); + } - template - static - void - delete_children (Triangulation<3,spacedim> &triangulation, - cell_iterator &cell, - std::vector &line_cell_count, - std::vector &quad_cell_count) - { - const unsigned int dim=3; + template + static + void + delete_children (Triangulation<3,spacedim> &triangulation, + typename Triangulation<3,spacedim>::cell_iterator &cell, + std::vector &line_cell_count, + std::vector &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 ref_case=cell->refinement_case(); - // vectors to hold all lines and quads which - // may be deleted - std::vector lines_to_delete(0); - std::vector quads_to_delete(0); - lines_to_delete.reserve(12*2+6*4+6); - quads_to_delete.reserve(6*4+12); + 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 ref_case=cell->refinement_case(); + // vectors to hold all lines and quads which + // may be deleted + std::vector::line_iterator> + lines_to_delete(0); + std::vector::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; cn_children(); ++c) - { - cell_iterator child=cell->child(c); - for (unsigned int l=0; l::lines_per_cell; ++l) - --line_cell_count[child->line_index(l)]; - for (unsigned int f=0; f::faces_per_cell; ++f) - --quad_cell_count[child->quad_index(f)]; - } + // now we decrease the counters for lines and + // quads contained in the child cells + for (unsigned int c=0; cn_children(); ++c) + { + typename Triangulation::cell_iterator + child=cell->child(c); + for (unsigned int l=0; l::lines_per_cell; ++l) + --line_cell_count[child->line_index(l)]; + for (unsigned int f=0; f::faces_per_cell; ++f) + --quad_cell_count[child->quad_index(f)]; + } - // first we need to reset the neighbor - // pointers of the neighbors from this cell's - // children to this cell. This is done by a - // seperate function. - update_neighbors (cell, false); - - /////////////////////////////////////// - // 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 + // first we need to reset the neighbor + // pointers of the neighbors from this cell's + // children to this cell. This is done by a + // seperate function. + update_neighbors (cell, false); + + /////////////////////////////////////// + // 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::cut_x: - quads_to_delete.push_back(cell->child(0)->face(1)); - break; - case RefinementCase::cut_y: - quads_to_delete.push_back(cell->child(0)->face(3)); - break; - case RefinementCase::cut_z: - quads_to_delete.push_back(cell->child(0)->face(5)); - break; - case RefinementCase::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)); + switch (ref_case) + { + case RefinementCase::cut_x: + quads_to_delete.push_back(cell->child(0)->face(1)); + break; + case RefinementCase::cut_y: + quads_to_delete.push_back(cell->child(0)->face(3)); + break; + case RefinementCase::cut_z: + quads_to_delete.push_back(cell->child(0)->face(5)); + break; + case RefinementCase::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::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(11)); + break; + case RefinementCase::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::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(5)); + break; + case RefinementCase::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::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)); + lines_to_delete.push_back(cell->child(0)->line(7)); + break; + case RefinementCase::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(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)); + 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; - } + 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; childn_children(); ++child) - { - cell->child(child)->clear_user_data(); - cell->child(child)->clear_user_flag(); - - for (unsigned int f=0; f::faces_per_cell; ++f) + // invalidate children + for (unsigned int child=0; childn_children(); ++child) { - // 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_user_data(); + cell->child(child)->clear_user_flag(); + + for (unsigned int f=0; f::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(); - } + cell->child(child)->clear_used_flag(); + } - // delete pointer to children - cell->clear_children (); - cell->clear_refinement_case (); - cell->clear_user_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). + // 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::faces_per_cell; ++quad_no) - { - quad_iterator quad=cell->face(quad_no); + for (unsigned int quad_no=0; quad_no::faces_per_cell; ++quad_no) + { + typename Triangulation::quad_iterator + quad=cell->face(quad_no); - Assert((GeometryInfo::face_refinement_case(ref_case,quad_no) && quad->has_children()) || - GeometryInfo::face_refinement_case(ref_case,quad_no)==RefinementCase::no_refinement, - ExcInternalError()); + Assert((GeometryInfo::face_refinement_case(ref_case,quad_no) && quad->has_children()) || + GeometryInfo::face_refinement_case(ref_case,quad_no)==RefinementCase::no_refinement, + ExcInternalError()); - switch (quad->refinement_case()) - { - case RefinementCase::no_refinement: - // nothing to do as the quad - // is not refined - break; - case RefinementCase::cut_x: - case RefinementCase::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; + switch (quad->refinement_case()) + { + case RefinementCase::no_refinement: + // nothing to do as the quad + // is not refined + break; + case RefinementCase::cut_x: + case RefinementCase::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) + for (unsigned int c=0; c<2; ++c) + if (quad->child(c)->has_children()) { - // Assert, that the two - // anisotropic - // refinements add up to - // isotropic refinement - Assert(quad->refinement_case()+quad->child(c)->refinement_case()==RefinementCase::cut_xy, + ++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()); - // 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 (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::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) - { - 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); + // 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::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(middle_line)] - = false; - middle_line->clear_children(); - } + lines_to_delete.push_back(middle_line->child(0)); + lines_to_delete.push_back(middle_line->child(1)); + triangulation.vertices_used[middle_vertex_index(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 quad_iterator switch_1=quad->child(0)->child(1); - const quad_iterator switch_2=quad->child(1)->child(0); - - Assert(!switch_1->has_children(), ExcInternalError()); - Assert(!switch_2->has_children(), ExcInternalError()); + // 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::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; lcells.cells.size(); ++h) - for (unsigned int q=0; q::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(); + const int switch_1_index=switch_1->index(); + const int switch_2_index=switch_2->index(); + for (unsigned int l=0; lcells.cells.size(); ++h) + for (unsigned int q=0; q::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 - 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(); - } + { + // 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; } - break; - } - case RefinementCase::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) + case RefinementCase::cut_xy: { - // 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; childn_children(); ++child) - quads_to_delete.push_back(quad->child(child)); + // 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; childn_children(); ++child) + quads_to_delete.push_back(quad->child(child)); - triangulation.vertices_used[quad->child(0)->vertex_index(3)] = false; + triangulation.vertices_used[quad->child(0)->vertex_index(3)] = false; - quad->clear_children(); - quad->clear_refinement_case(); + quad->clear_children(); + quad->clear_refinement_case(); + } } - } - break; + break; - default: - Assert(false, ExcInternalError()); - break; - } + default: + Assert(false, ExcInternalError()); + break; + } - } + } - // now we repeat a similar procedure for the - // outer lines of this cell. + // 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::lines_per_cell; ++line_no) - { - line_iterator line=cell->line(line_no); - - Assert((GeometryInfo::line_refinement_case(ref_case,line_no) && line->has_children()) || - GeometryInfo::line_refinement_case(ref_case,line_no)==RefinementCase<1>::no_refinement, - ExcInternalError()); - - if (line->has_children()) + // 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::lines_per_cell; ++line_no) { - // if one of the cell counters is - // zero, the other has to be as well + typename Triangulation::line_iterator + line=cell->line(line_no); - 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), + Assert((GeometryInfo::line_refinement_case(ref_case,line_no) && line->has_children()) || + GeometryInfo::line_refinement_case(ref_case,line_no)==RefinementCase<1>::no_refinement, ExcInternalError()); - if (line_cell_count[line->child_index(0)]==0) + if (line->has_children()) { - for (unsigned int c=0; c<2; ++c) - Assert (!line->child(c)->has_children(), - ExcInternalError()); + // 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; + // 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)); + lines_to_delete.push_back(line->child(0)); + lines_to_delete.push_back(line->child(1)); - line->clear_children(); + line->clear_children(); + } } } - } - // finally, delete unneeded quads and lines + // 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::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(); - } + // 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::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::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(); - } - } + typename std::vector::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 - static - void - create_children (Triangulation<2,spacedim> &triangulation, - unsigned int &next_unused_vertex, - raw_line_iterator &next_unused_line, - raw_cell_iterator &next_unused_cell, - cell_iterator &cell) - { - const unsigned int dim=2; - // clear refinement flag - const RefinementCase ref_case=cell->refine_flag_set(); - cell->clear_refine_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 + 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 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 @@ -3651,5742 +3851,5808 @@ struct Triangulation::Implementation .--.--. */ - // 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); + // 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::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 new_point; - if (dim == spacedim) + if (ref_case==RefinementCase::cut_xy) { - 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); - } + // 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 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; + 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::faces_per_cell; - for (unsigned int face=0; face::faces_per_cell; ++face) - if (cell->face(face)->at_boundary()) - { - if (bound_face == GeometryInfo::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::faces_per_cell+1; - } + // 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::faces_per_cell; + for (unsigned int face=0; face::faces_per_cell; ++face) + if (cell->face(face)->at_boundary()) + { + if (bound_face == GeometryInfo::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::faces_per_cell+1; + } - if (bound_face::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 - ::opposite_face[bound_face]) - ->child(0)->vertex(1)); + if (bound_face::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 + ::opposite_face[bound_face]) + ->child(0)->vertex(1)); + } } - } - // Now the lines: - raw_line_iterator new_lines[12]; - unsigned int lmin=8; - unsigned int lmax=12; - if (ref_case!=RefinementCase::cut_xy) - { - lmin=6; - lmax=7; - } + // Now the lines: + typename Triangulation::raw_line_iterator new_lines[12]; + unsigned int lmin=8; + unsigned int lmax=12; + if (ref_case!=RefinementCase::cut_xy) + { + lmin=6; + lmax=7; + } - for (unsigned int l=lmin; lused() == true) - ++next_unused_line; - new_lines[l] = next_unused_line; - ++next_unused_line; + for (unsigned int l=lmin; lused() == true) + ++next_unused_line; + new_lines[l] = next_unused_line; + ++next_unused_line; - Assert (new_lines[l]->used() == false, - ExcCellShouldBeUnused()); - } + Assert (new_lines[l]->used() == false, + ExcCellShouldBeUnused()); + } - if (ref_case==RefinementCase::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::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::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::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])); - } + if (ref_case==RefinementCase::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::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::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::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; lset_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); - } + for (unsigned int l=lmin; lset_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! - raw_cell_iterator subcells[GeometryInfo::max_children_per_cell]; - while (next_unused_cell->used() == true) - ++next_unused_cell; + // Now add the four (two) + // new cells! + typename Triangulation::raw_cell_iterator + subcells[GeometryInfo::max_children_per_cell]; + while (next_unused_cell->used() == true) + ++next_unused_cell; - const unsigned int n_children= - GeometryInfo::n_children(ref_case); - for (unsigned int i=0; iused() == false, - ExcCellShouldBeUnused()); - subcells[i] = next_unused_cell; - ++next_unused_cell; - if (i%2==1 && iused() == true) + const unsigned int n_children= + GeometryInfo::n_children(ref_case); + for (unsigned int i=0; iused() == false, + ExcCellShouldBeUnused()); + subcells[i] = next_unused_cell; ++next_unused_cell; - } + if (i%2==1 && iused() == true) + ++next_unused_cell; + } - if (ref_case==RefinementCase::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::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::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())); - } + if (ref_case==RefinementCase::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::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::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; iset_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()); - } + for (unsigned int i=0; iset_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()); + } - // now the only thing - // still to be done is - // setting neighborship - // information. - // - // we have to do that for - // all children of our - // current cell. if the - // neighbor is a refined - // one or if we use anisotropic - // refinement and there is only - // one child of the current cell - // adjacent to a certain face, - // we also have to reset the - // neighbors neighbor pointers. - // In earlier versions of the - // library these tasks were done one - // after the other. here we combine - // these steps, as otherwise we - // would have to gather the same - // information on the refinement - // situation along a certain face - // twice. As this is a more - // complicated task for anisotropic - // refinement, we prefer to do it - // only once. - // - // note that in case the - // neighboring cell is - // not refined along the - // common face, the - // neighbor iterators - // point to the common - // mother cell. the same - // applies if there is no - // neighbor: the - // iterators are past the - // end - cell_iterator nb_children[GeometryInfo::max_children_per_face], - nb_child, - children[GeometryInfo::faces_per_cell][GeometryInfo::max_children_per_face]; - - // first, set up an array of our current - // children / subcells. for all faces and - // subfaces store the info, which subcell is - // adjacent to that subface - for (unsigned int face=0; face::faces_per_cell; ++face) - for (unsigned int c=0; c::max_children_per_face; ++c) - children[face][c]=subcells[GeometryInfo::child_cell_on_face(ref_case, - face,c)]; + // now the only thing + // still to be done is + // setting neighborship + // information. + // + // we have to do that for + // all children of our + // current cell. if the + // neighbor is a refined + // one or if we use anisotropic + // refinement and there is only + // one child of the current cell + // adjacent to a certain face, + // we also have to reset the + // neighbors neighbor pointers. + // In earlier versions of the + // library these tasks were done one + // after the other. here we combine + // these steps, as otherwise we + // would have to gather the same + // information on the refinement + // situation along a certain face + // twice. As this is a more + // complicated task for anisotropic + // refinement, we prefer to do it + // only once. + // + // note that in case the + // neighboring cell is + // not refined along the + // common face, the + // neighbor iterators + // point to the common + // mother cell. the same + // applies if there is no + // neighbor: the + // iterators are past the + // end + typename Triangulation::cell_iterator + nb_children[GeometryInfo::max_children_per_face], + nb_child, + children[GeometryInfo::faces_per_cell][GeometryInfo::max_children_per_face]; + + // first, set up an array of our current + // children / subcells. for all faces and + // subfaces store the info, which subcell is + // adjacent to that subface + for (unsigned int face=0; face::faces_per_cell; ++face) + for (unsigned int c=0; c::max_children_per_face; ++c) + children[face][c]=subcells[GeometryInfo::child_cell_on_face(ref_case, + face,c)]; - for (unsigned int face=0; face::faces_per_cell; - ++face) - { - const cell_iterator neighbor=cell->neighbor(face); - const RefinementCase face_ref_case=GeometryInfo::face_refinement_case(ref_case,face); - const unsigned int n_subfaces=std::max(GeometryInfo::n_children(face_ref_case), - static_cast(1)); + for (unsigned int face=0; face::faces_per_cell; + ++face) + { + const typename Triangulation::cell_iterator + neighbor=cell->neighbor(face); + const RefinementCase + face_ref_case=GeometryInfo::face_refinement_case(ref_case,face); + const unsigned int + n_subfaces=std::max(GeometryInfo::n_children(face_ref_case), + static_cast(1)); - // if no neighbor set invalid pointer for - // all children adjacent to that face - if (neighbor.state() != IteratorState::valid) - for (unsigned int c=0; cset_neighbor(face,neighbor); + // if no neighbor set invalid pointer for + // all children adjacent to that face + if (neighbor.state() != IteratorState::valid) + for (unsigned int c=0; cset_neighbor(face,neighbor); - else - // neighbor exists - { - // now there are two possibilities: - // either the neighbor is not refined - // along the common face or it is - // refined along the common face once, - // this must be terminal then - // (otherwise something went wrong in - // prepare_refinement_and_coarsening()). - // however, if at any time the neighbor - // has children, which are not refined - // along the face currently under - // consideration, one of these children - // would have been set as the neighbor - // of our current cell. therefore the - // question wether the neighbor is - // refined along the common face is - // equivalent to the question, wether - // the neighbor has children. if our - // current cell is not refined along - // the face face_no, then we have to - // set the current neighbor as the new - // neighbor, even if the neighbor is - // further refined - if (!neighbor->has_children()) + else + // neighbor exists { - // if the neighbor has no children, - // set the neighbor-pointer of all - // children to this neighbor cell - for (unsigned int c=0; cset_neighbor(face,neighbor); - // if the current cell is not - // refined along the face we have - // to update the neighbors neighbor - // pointer. we have to do this only, - // if the neighbor is not coarser - if (n_subfaces==1 && !cell->neighbor_is_coarser(face)) + // now there are two possibilities: + // either the neighbor is not refined + // along the common face or it is + // refined along the common face once, + // this must be terminal then + // (otherwise something went wrong in + // prepare_refinement_and_coarsening()). + // however, if at any time the neighbor + // has children, which are not refined + // along the face currently under + // consideration, one of these children + // would have been set as the neighbor + // of our current cell. therefore the + // question wether the neighbor is + // refined along the common face is + // equivalent to the question, wether + // the neighbor has children. if our + // current cell is not refined along + // the face face_no, then we have to + // set the current neighbor as the new + // neighbor, even if the neighbor is + // further refined + if (!neighbor->has_children()) { - const unsigned int nb_nb = cell->neighbor_of_neighbor(face); - neighbor->set_neighbor(nb_nb, children[face][0]); + // if the neighbor has no children, + // set the neighbor-pointer of all + // children to this neighbor cell + for (unsigned int c=0; cset_neighbor(face,neighbor); + // if the current cell is not + // refined along the face we have + // to update the neighbors neighbor + // pointer. we have to do this only, + // if the neighbor is not coarser + if (n_subfaces==1 && !cell->neighbor_is_coarser(face)) + { + const unsigned int nb_nb = cell->neighbor_of_neighbor(face); + neighbor->set_neighbor(nb_nb, children[face][0]); + } } - } - else - { - // neighbor has children - const unsigned int nb_nb = cell->neighbor_of_neighbor(face); - const RefinementCase nb_ref_case = neighbor->refinement_case(); - const RefinementCase nb_face_ref_case = GeometryInfo::face_refinement_case(nb_ref_case, - nb_nb); - const unsigned int nb_n_subfaces = std::max(GeometryInfo:: - n_children(nb_face_ref_case), - static_cast(1)); - - for (unsigned int c=0; c::max_children_per_face; ++c) + else { - nb_child=neighbor->child(GeometryInfo:: - child_cell_on_face(nb_ref_case, - nb_nb, - c)); - // there could be an unknown - // number of refinements for - // nb_child that do - // not refine the common - // face. - - // consider for example the - // following case, where the - // lower cell has been refined - // in this step into c1 and c2. - - // --------------- - // | | | - // | | n2.1 | - // | | | - // | n1 ------- - // | | | - // | | n2.2 | - // | | | - // --------------- - // | | | - // | | | - // | | | - // | c1 | c2 | - // | | | - // | | | - // --------------- + // neighbor has children + const unsigned int nb_nb = cell->neighbor_of_neighbor(face); + const RefinementCase nb_ref_case = neighbor->refinement_case(); + const RefinementCase nb_face_ref_case = GeometryInfo::face_refinement_case(nb_ref_case, + nb_nb); + const unsigned int nb_n_subfaces = std::max(GeometryInfo:: + n_children(nb_face_ref_case), + static_cast(1)); + + for (unsigned int c=0; c::max_children_per_face; ++c) + { + nb_child=neighbor->child(GeometryInfo:: + child_cell_on_face(nb_ref_case, + nb_nb, + c)); + // there could be an unknown + // number of refinements for + // nb_child that do + // not refine the common + // face. + + // consider for example the + // following case, where the + // lower cell has been refined + // in this step into c1 and c2. + + // --------------- + // | | | + // | | n2.1 | + // | | | + // | n1 ------- + // | | | + // | | n2.2 | + // | | | + // --------------- + // | | | + // | | | + // | | | + // | c1 | c2 | + // | | | + // | | | + // --------------- - // the neighbor of cell c was - // the whole of cell n. what we - // have done so far is setting - // the right neighbor - // information for cells c1 and - // n1 as well as c2 and n2, - // where n2 is the mother cell - // of n2.1 and n2.2. however, - // n2 is further refined and we - // would have to set n2.2 as - // neighbor of child c2 and - // vice versa. this is specific - // to anisotropic refinement. + // the neighbor of cell c was + // the whole of cell n. what we + // have done so far is setting + // the right neighbor + // information for cells c1 and + // n1 as well as c2 and n2, + // where n2 is the mother cell + // of n2.1 and n2.2. however, + // n2 is further refined and we + // would have to set n2.2 as + // neighbor of child c2 and + // vice versa. this is specific + // to anisotropic refinement. - // note that n2.2 could be - // further refined with cut_y - // (if n1 was also refined with - // cut_y). + // note that n2.2 could be + // further refined with cut_y + // (if n1 was also refined with + // cut_y). - // go down that list to - // the end. note, that nb_nb - // stays constant, for all - // children of a cell have - // their faces in the same - // direction and orientation as - // the mother cell - while(nb_child->has_children() - && (GeometryInfo::face_refinement_case(nb_child->refinement_case(), - nb_nb) - == RefinementCase::no_refinement)) - // nb_child has children - // which are not refined at - // the current (sub)face, - // therefore one of these - // children is the true - // neighbor of our cell - nb_child = nb_child - ->child(GeometryInfo:: - child_cell_on_face(nb_child->refinement_case(), - nb_nb, - 0)); - // there's one more possibility - // here, if the current cell is - // refined along the face: the - // last child found above could - // still be refined once along - // the common face, e.g. n1 or - // n2.2 in the above picture - // could be refined with - // cut_x. this refinement leeds - // to an inreased number of - // hanging nodes. therefore it - // was introduced in this - // refinement cycle and the - // additional hanging nodes - // will be removed now, as the - // current cell is also - // refined. this temporaray - // effect can occur during - // anisotropic refinement, as - // it is possible there, that a - // coarser cell (along the face - // between the cells) is on a - // higher level and therefore - // refined after the already - // refined neighbor. - if (nb_child->has_children()) - { - // This is only valid, if - // the current cell is - // refined along the face - // considered here - Assert(n_subfaces > 1, ExcInternalError()); - for (unsigned int sub=0; - sub::max_children_per_face; ++sub) + // go down that list to + // the end. note, that nb_nb + // stays constant, for all + // children of a cell have + // their faces in the same + // direction and orientation as + // the mother cell + while(nb_child->has_children() + && (GeometryInfo::face_refinement_case(nb_child->refinement_case(), + nb_nb) + == RefinementCase::no_refinement)) + // nb_child has children + // which are not refined at + // the current (sub)face, + // therefore one of these + // children is the true + // neighbor of our cell + nb_child = nb_child + ->child(GeometryInfo:: + child_cell_on_face(nb_child->refinement_case(), + nb_nb, + 0)); + // there's one more possibility + // here, if the current cell is + // refined along the face: the + // last child found above could + // still be refined once along + // the common face, e.g. n1 or + // n2.2 in the above picture + // could be refined with + // cut_x. this refinement leeds + // to an inreased number of + // hanging nodes. therefore it + // was introduced in this + // refinement cycle and the + // additional hanging nodes + // will be removed now, as the + // current cell is also + // refined. this temporaray + // effect can occur during + // anisotropic refinement, as + // it is possible there, that a + // coarser cell (along the face + // between the cells) is on a + // higher level and therefore + // refined after the already + // refined neighbor. + if (nb_child->has_children()) { - // collect all the - // children of nb_child - // and set their - // neighbor - // pointers. we will - // care for our own - // children later on - nb_children[sub]=nb_child-> - child(GeometryInfo:: - child_cell_on_face(nb_child->refinement_case(), - nb_nb, sub)); - nb_children[sub]->set_neighbor(nb_nb, children[face][c]); + // This is only valid, if + // the current cell is + // refined along the face + // considered here + Assert(n_subfaces > 1, ExcInternalError()); + for (unsigned int sub=0; + sub::max_children_per_face; ++sub) + { + // collect all the + // children of nb_child + // and set their + // neighbor + // pointers. we will + // care for our own + // children later on + nb_children[sub]=nb_child-> + child(GeometryInfo:: + child_cell_on_face(nb_child->refinement_case(), + nb_nb, sub)); + nb_children[sub]->set_neighbor(nb_nb, children[face][c]); + } } - } - // now set the neighbor - // pointers of the neighbor's - // children. - nb_child->set_neighbor(nb_nb, children[face][c]); - // if this cell is as refined - // as the neighbor, set the - // neighbor pointers of the - // subcells to the - // corresponting - // neighbor_child. else, set - // the neighbor pointers to the - // common neighbor mother cell - if (nb_n_subfaces==n_subfaces) - children[face][c]->set_neighbor(face,nb_child); - else - children[face][c]->set_neighbor(face,neighbor); + // now set the neighbor + // pointers of the neighbor's + // children. + nb_child->set_neighbor(nb_nb, children[face][c]); + // if this cell is as refined + // as the neighbor, set the + // neighbor pointers of the + // subcells to the + // corresponting + // neighbor_child. else, set + // the neighbor pointers to the + // common neighbor mother cell + if (nb_n_subfaces==n_subfaces) + children[face][c]->set_neighbor(face,nb_child); + else + children[face][c]->set_neighbor(face,neighbor); + } } - } - } - } - // by now, all the outer neighbors have been - // set, the inner neighbors have to be - // considered in the following + } + } + // by now, all the outer neighbors have been + // set, the inner neighbors have to be + // considered in the following - if (ref_case==RefinementCase::cut_xy) - { - // children: - // .--.--. - // |2 . 3| - // .--.--. - // |0 | 1| - // .--.--. - subcells[0]->set_neighbor (1, subcells[1]); - subcells[0]->set_neighbor (3, subcells[2]); + if (ref_case==RefinementCase::cut_xy) + { + // children: + // .--.--. + // |2 . 3| + // .--.--. + // |0 | 1| + // .--.--. + subcells[0]->set_neighbor (1, subcells[1]); + subcells[0]->set_neighbor (3, subcells[2]); - subcells[1]->set_neighbor (0, subcells[0]); - subcells[1]->set_neighbor (3, subcells[3]); + subcells[1]->set_neighbor (0, subcells[0]); + subcells[1]->set_neighbor (3, subcells[3]); - subcells[2]->set_neighbor (1, subcells[3]); - subcells[2]->set_neighbor (2, subcells[0]); + subcells[2]->set_neighbor (1, subcells[3]); + subcells[2]->set_neighbor (2, subcells[0]); - subcells[3]->set_neighbor (0, subcells[2]); - subcells[3]->set_neighbor (2, subcells[1]); - } - else if (ref_case==RefinementCase::cut_x) - { - // children: - // .--.--. - // | . | - // .0 . 1. - // | | | - // .--.--. - subcells[0]->set_neighbor (1, subcells[1]); + subcells[3]->set_neighbor (0, subcells[2]); + subcells[3]->set_neighbor (2, subcells[1]); + } + else if (ref_case==RefinementCase::cut_x) + { + // children: + // .--.--. + // | . | + // .0 . 1. + // | | | + // .--.--. + subcells[0]->set_neighbor (1, subcells[1]); - subcells[1]->set_neighbor (0, subcells[0]); - } - else - { - Assert(ref_case==RefinementCase::cut_y, ExcInternalError()); - // children: - // .-----. - // | 1 | - // .-----. - // | 0 | - // .-----. - subcells[0]->set_neighbor (3, subcells[1]); + subcells[1]->set_neighbor (0, subcells[0]); + } + else + { + Assert(ref_case==RefinementCase::cut_y, ExcInternalError()); + // children: + // .-----. + // | 1 | + // .-----. + // | 0 | + // .-----. + subcells[0]->set_neighbor (3, subcells[1]); - subcells[1]->set_neighbor (2, subcells[0]); - } + subcells[1]->set_neighbor (2, subcells[0]); + } - // set child index for - // even children children - // i=0,2 (0) - for (unsigned int i=0; iset_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 - } + // set child index for + // even children children + // i=0,2 (0) + for (unsigned int i=0; iset_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 - static - void - execute_refinement (Triangulation<1,spacedim> &triangulation) - { - const unsigned int dim = 1; + /** + * A function that performs the + * refinement of a triangulation in 1d. + */ + template + static + void + execute_refinement (Triangulation<1,spacedim> &triangulation) + { + 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) - { - 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); - break; - } - } + // 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::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); + 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; - 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(), 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); + // 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::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(), 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; - } + 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(), - 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()); - triangulation.vertices_used.resize (needed_vertices, false); - } + // 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(), + 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()); + triangulation.vertices_used.resize (needed_vertices, false); + } - // Do REFINEMENT - // on every level; exclude highest - // level as above + // Do REFINEMENT + // on every level; exclude highest + // level as above - // index of next unused vertex - unsigned int next_unused_vertex = 0; + // index of next unused vertex + unsigned int next_unused_vertex = 0; - for (int level=triangulation.levels.size()-2; level>=0; --level) - { - active_cell_iterator - cell = triangulation.begin_active(level), - endc = triangulation.begin_active(level+1); + for (int level=triangulation.levels.size()-2; level>=0; --level) + { + typename Triangulation::active_cell_iterator + cell = triangulation.begin_active(level), + endc = triangulation.begin_active(level+1); - raw_cell_iterator - next_unused_cell = triangulation.begin_raw (level+1); + typename Triangulation::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()); + 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) - 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 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::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()); - // 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()); + // 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 - // 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 - cell_iterator left_neighbor = cell->neighbor(0); - while (left_neighbor->has_children()) + else + if (cell->neighbor(0)->active()) { - left_neighbor = left_neighbor->child(1); - left_neighbor->set_neighbor (1, first_child); + // 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::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()); + // 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 - // right neighbor is - // refined same as - // above - { - second_child->set_neighbor (1, cell->neighbor(1)->child(0)); - - cell_iterator right_neighbor = cell->neighbor(1); - while (right_neighbor->has_children()) + else + if (cell->neighbor(1)->active()) { - right_neighbor = right_neighbor->child(0); - right_neighbor->set_neighbor (0, second_child); + 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::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); + } + } + } + } } - } - /** - * A function that performs the - * refinement of a triangulation in 2d. - */ - template - static - void - execute_refinement (Triangulation<2,spacedim> &triangulation) - { - 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) + /** + * A function that performs the + * refinement of a triangulation in 2d. + */ + template + static + void + execute_refinement (Triangulation<2,spacedim> &triangulation) { - 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); - break; - } - } + 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::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); + break; + } + } - // first clear user flags and - // pointers of lines; we're going - // to use them to flag which lines - // need refinement - for (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; - - 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::cut_xy) + // first clear user flags and + // pointers of lines; we're going + // to use them to flag which lines + // need refinement + for (typename Triangulation::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::active_cell_iterator + cell = triangulation.begin_active(level), + endc = triangulation.begin_active(level+1); + for (; cell!=endc; ++cell) + if (cell->refine_flag_set()) { - needed_cells += 4; + if (cell->refine_flag_set()==RefinementCase::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; + // 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 + needed_cells += 2; + // no vertex at center - // the inner line can - // be stored as - // single - n_single_lines += 1; + // 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::faces_per_cell; - ++line_no) - { - if (GeometryInfo::face_refinement_case( - cell->refine_flag_set(), line_no)==RefinementCase<1>::cut_x) + // 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::faces_per_cell; + ++line_no) { - line_iterator line = cell->line(line_no); - if (line->has_children() == false) { - line->set_user_flag (); + if (GeometryInfo::face_refinement_case( + cell->refine_flag_set(), line_no)==RefinementCase<1>::cut_x) + { + typename Triangulation::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()); - } + 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(), true)); + // 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(), 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 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::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 - // 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 (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); + // 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(), 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()); - triangulation.vertices_used.resize (needed_vertices, false); - } - + // 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(), 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()); + 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; + // Do REFINEMENT + // on every level; exclude highest + // level as above - // first the refinement of lines. - // children are stored pairwise - if (true) - { - // only active objects can be - // refined further - active_line_iterator line = triangulation.begin_active_line(), - endl = triangulation.end_line(); - raw_line_iterator next_unused_line = triangulation.begin_raw_line (); + // index of next unused vertex + unsigned int next_unused_vertex = 0; - 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) + // first the refinement of lines. + // children are stored pairwise + if (true) + { + // only active objects can be + // refined further + typename Triangulation::active_line_iterator + line = triangulation.begin_active_line(), + endl = triangulation.end_line(); + typename Triangulation::raw_line_iterator + next_unused_line = triangulation.begin_raw_line (); + + for (; line!=endl; ++line) + if (line->user_flag_set()) { - // 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); + // 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] - = (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); + = 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()); + // 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 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()); + // set the two new lines + const typename Triangulation::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 (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()); + 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 (); - } - } + // 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); - - // reset next_unused_line, as - // now also single empty places - // in the vector can be used - raw_line_iterator next_unused_line = triangulation.begin_raw_line (); + // 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); + + // reset next_unused_line, as + // now also single empty places + // in the vector can be used + typename Triangulation::raw_line_iterator + next_unused_line = triangulation.begin_raw_line (); - for (int level=0; level(triangulation.levels.size())-1; ++level) - { + for (int level=0; level(triangulation.levels.size())-1; ++level) + { - // Remember: as we don't operate - // on the finest level, begin_*(level+1) - // is allowed - active_cell_iterator cell = triangulation.begin_active(level), - endc = triangulation.begin_active(level+1); + // Remember: as we don't operate + // on the finest level, begin_*(level+1) + // is allowed + typename Triangulation::active_cell_iterator + cell = triangulation.begin_active(level), + endc = triangulation.begin_active(level+1); - raw_cell_iterator next_unused_cell = triangulation.begin_raw (level+1); + typename Triangulation::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 + 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(); + // 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); - } + // actually set up the children and + // update neighbor information + create_children (triangulation, + next_unused_vertex, + next_unused_line, + next_unused_cell, + cell); + } + } } - } - /** - * A function that performs the - * refinement of a triangulation in 3d. - */ - template - static - void - execute_refinement (Triangulation<3,spacedim> &triangulation) - { - 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) + /** + * A function that performs the + * refinement of a triangulation in 3d. + */ + template + static + void + execute_refinement (Triangulation<3,spacedim> &triangulation) { - 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); - break; - } - } + 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::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); + 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(); + // 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 (line_iterator line=triangulation.begin_line(); line!=triangulation.end_line(); ++line) - line->clear_user_flag(); - for (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 face_refinement_cases[4]= - {RefinementCase::no_refinement, - RefinementCase::cut_x, - RefinementCase::cut_y, - RefinementCase::cut_xy}; + for (typename Triangulation::line_iterator + line=triangulation.begin_line(); line!=triangulation.end_line(); ++line) + line->clear_user_flag(); + for (typename Triangulation::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 face_refinement_cases[4]= + {RefinementCase::no_refinement, + RefinementCase::cut_x, + RefinementCase::cut_y, + RefinementCase::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; + // 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; - active_cell_iterator acell = triangulation.begin_active(level), - aendc = triangulation.begin_active(level+1); - for (; acell!=aendc; ++acell) - if (acell->refine_flag_set()) - { - RefinementCase ref_case=acell->refine_flag_set(); - - // now for interior vertices, lines - // and quads, which are needed in - // any case - if (ref_case==RefinementCase::cut_x || - ref_case==RefinementCase::cut_y || - ref_case==RefinementCase::cut_z) - { - ++needed_quads_single; - new_cells+=2; - triangulation.anisotropic_refinement=true; - } - else if (ref_case==RefinementCase::cut_xy || - ref_case==RefinementCase::cut_xz || - ref_case==RefinementCase::cut_yz) - { - ++needed_lines_single; - needed_quads_single += 4; - new_cells+=4; - triangulation.anisotropic_refinement=true; - } - else if (ref_case==RefinementCase::cut_xyz) - { - ++needed_vertices; - needed_lines_single += 6; - needed_quads_single += 12; - new_cells+=8; - } - else + typename Triangulation::active_cell_iterator + acell = triangulation.begin_active(level), + aendc = triangulation.begin_active(level+1); + for (; acell!=aendc; ++acell) + if (acell->refine_flag_set()) { - // we should never get here - Assert(false, ExcInternalError()); - } + RefinementCase ref_case=acell->refine_flag_set(); - // 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::faces_per_cell; - ++face) - { - face_iterator aface = acell->face(face); - // get the RefineCase this - // faces has for the given - // RefineCase of the cell - RefinementCase face_ref_case= - GeometryInfo::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) + // now for interior vertices, lines + // and quads, which are needed in + // any case + if (ref_case==RefinementCase::cut_x || + ref_case==RefinementCase::cut_y || + ref_case==RefinementCase::cut_z) { - if (face_ref_case==RefinementCase::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 + ++needed_quads_single; + new_cells+=2; + triangulation.anisotropic_refinement=true; + } + else if (ref_case==RefinementCase::cut_xy || + ref_case==RefinementCase::cut_xz || + ref_case==RefinementCase::cut_yz) + { + ++needed_lines_single; + needed_quads_single += 4; + new_cells+=4; + triangulation.anisotropic_refinement=true; + } + else if (ref_case==RefinementCase::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::faces_per_cell; + ++face) + { + typename Triangulation::face_iterator + aface = acell->face(face); + // get the RefineCase this + // faces has for the given + // RefineCase of the cell + RefinementCase face_ref_case= + GeometryInfo::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) { - Assert(aface->refinement_case()==RefinementCase::isotropic_refinement || - aface->refinement_case()==RefinementCase::no_refinement, - ExcInternalError()); - aface->set_user_index(face_ref_case); + if (face_ref_case==RefinementCase::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::isotropic_refinement || + aface->refinement_case()==RefinementCase::no_refinement, + ExcInternalError()); + aface->set_user_index(face_ref_case); + } } - } - }// for all faces + }// for all faces - // flag all lines, that have to be - // refined - for (unsigned int line=0; line::lines_per_cell; ++line) - if (GeometryInfo::line_refinement_case(ref_case,line) && - !acell->line(line)->has_children()) - acell->line(line)->set_user_flag(); + // flag all lines, that have to be + // refined + for (unsigned int line=0; line::lines_per_cell; ++line) + if (GeometryInfo::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 + }// 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(), 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 (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()) + // 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(), 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::quad_iterator + quad=triangulation.begin_quad(); quad!=triangulation.end_quad(); ++quad) { - // 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()) + 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()) { - Assert(quad->refinement_case()==RefinementCase::isotropic_refinement, ExcInternalError()); - if ((face_refinement_cases[quad->user_index()]==RefinementCase::cut_x - && (quad->child(0)->line_index(1)+1!=quad->child(2)->line_index(1))) || - (face_refinement_cases[quad->user_index()]==RefinementCase::cut_y - && (quad->child(0)->line_index(3)+1!=quad->child(1)->line_index(3)))) - needed_lines_pair +=2; + // 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::isotropic_refinement, ExcInternalError()); + if ((face_refinement_cases[quad->user_index()]==RefinementCase::cut_x + && (quad->child(0)->line_index(1)+1!=quad->child(2)->line_index(1))) || + (face_refinement_cases[quad->user_index()]==RefinementCase::cut_y + && (quad->child(0)->line_index(3)+1!=quad->child(1)->line_index(3)))) + needed_lines_pair +=2; + } } } - } - for (line_iterator line=triangulation.begin_line(); line!=triangulation.end_line(); ++line) - if (line->user_flag_set()) - { - needed_lines_pair += 2; - needed_vertices += 1; - } + for (typename Triangulation::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(), 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()); - triangulation.vertices_used.resize (needed_vertices, false); - } + // 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(), 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()); + 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 + /////////////////////////////////////////// + // 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 (active_cell_iterator cell=triangulation.begin_active(); cell!=triangulation.end(); ++cell) - if (!cell->refine_flag_set()) - for (unsigned int line=0; line::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()); + for (typename Triangulation::active_cell_iterator + cell=triangulation.begin_active(); cell!=triangulation.end(); ++cell) + if (!cell->refine_flag_set()) + for (unsigned int line=0; line::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 - active_line_iterator line = triangulation.begin_active_line(), - endl = triangulation.end_line(); - raw_line_iterator next_unused_line = triangulation.begin_raw_line (); + /////////////////////////////////////////// + // 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; - 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; + // first for lines + if (true) + { + // only active objects can be + // refined further + typename Triangulation::active_line_iterator + line = triangulation.begin_active_line(), + endl = triangulation.end_line(); + typename Triangulation::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 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()); + // 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 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()); + // set the two new lines + const typename Triangulation::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 (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()); + 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 (); - } - } + // finally clear flag + // indicating the need + // for refinement + line->clear_user_flag (); + } + } - /////////////////////////////////////// - // now refine marked quads - /////////////////////////////////////// + /////////////////////////////////////// + // now refine marked quads + /////////////////////////////////////// - // here we encounter several cases: + // here we encounter several cases: - // a) the quad is unrefined and shall be - // refined isotropically + // a) the quad is unrefined and shall be + // refined isotropically - // b) the quad is unrefined and shall be - // refined anisotropically + // 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) + // 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) + // 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...) + // 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 - quad_iterator quad = triangulation.begin_quad(), - endq = triangulation.end_quad(); - raw_line_iterator next_unused_line = triangulation.begin_raw_line (), - endl = triangulation.end_line(); - raw_quad_iterator next_unused_quad = triangulation.begin_raw_quad (); - - for (; quad!=endq; ++quad) + // 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) { - if (quad->user_index()) + // 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::quad_iterator + quad = triangulation.begin_quad(), + endq = triangulation.end_quad(); + typename Triangulation::raw_line_iterator + next_unused_line = triangulation.begin_raw_line (), + endl = triangulation.end_line(); + typename Triangulation::raw_quad_iterator + next_unused_quad = triangulation.begin_raw_quad (); + + for (; quad!=endq; ++quad) { - RefinementCase 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::cut_xy || - quad->refinement_case()==RefinementCase::no_refinement, - ExcInternalError()); - - // this quad needs to be refined - // anisotropically - Assert(quad->user_index() == RefinementCase::cut_x || - quad->user_index() == RefinementCase::cut_y, - ExcInternalError()); - - // make the new line interior to - // the quad - 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::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 + if (quad->user_index()) { - 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 + RefinementCase 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; - // find some space (consecutive) - // for the two newly to be - // created quads. - raw_quad_iterator new_quads[2]; + Assert(quad->refinement_case()==RefinementCase::cut_xy || + quad->refinement_case()==RefinementCase::no_refinement, + ExcInternalError()); - next_unused_quad=triangulation.faces->quads.next_free_pair_quad(triangulation); - new_quads[0] = next_unused_quad; - Assert (new_quads[0]->used() == false, ExcCellShouldBeUnused()); + // this quad needs to be refined + // anisotropically + Assert(quad->user_index() == RefinementCase::cut_x || + quad->user_index() == RefinementCase::cut_y, + ExcInternalError()); + + // make the new line interior to + // the quad + typename Triangulation::raw_line_iterator new_line; - ++next_unused_quad; - new_quads[1] = next_unused_quad; - Assert (new_quads[1]->used() == false, ExcCellShouldBeUnused()); + 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::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); + } - if (aniso_quad_ref_case==RefinementCase::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))); - } + 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 - 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::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(3)); - if (aniso_quad_ref_case==RefinementCase::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)); - } + // find some space (consecutive) + // for the two newly to be + // created quads. + typename Triangulation::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()); + - // test, whether this face is - // refined isotropically - // already. if so, set the - // correct children pointers. - if (quad->refinement_case()==RefinementCase::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... - line_iterator old_child[2]; if (aniso_quad_ref_case==RefinementCase::cut_x) { - old_child[0]=quad->child(0)->line(1); - old_child[1]=quad->child(2)->line(1); + 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 { - Assert(aniso_quad_ref_case==RefinementCase::cut_y, ExcInternalError()); - - old_child[0]=quad->child(0)->line(3); - old_child[1]=quad->child(1)->line(3); + 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))); } - - if (old_child[0]->index()+1 != old_child[1]->index()) + + for (unsigned int i=0; i<2; ++i) { - // this is exactly the - // ugly case we taked - // about. so, no - // coimplaining, lets get - // two new lines and copy - // all info - raw_line_iterator new_child[2]; - - new_child[0]=new_child[1]=triangulation.faces->lines.next_free_pair_line(triangulation); - ++new_child[1]; + 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::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(3)); + if (aniso_quad_ref_case==RefinementCase::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)); + } - new_child[0]->set_used_flag(); - new_child[1]->set_used_flag(); + // test, whether this face is + // refined isotropically + // already. if so, set the + // correct children pointers. + if (quad->refinement_case()==RefinementCase::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::line_iterator old_child[2]; + if (aniso_quad_ref_case==RefinementCase::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::cut_y, ExcInternalError()); - 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; qquads.cells.size(); ++q) - for (unsigned int l=0; l::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) + 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()) { - Assert(!old_child[i]->has_children(), ExcInternalError()); + // this is exactly the + // ugly case we taked + // about. so, no + // coimplaining, lets get + // two new lines and copy + // all info + typename Triangulation::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; qquads.cells.size(); ++q) + for (unsigned int l=0; l::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]->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(); + 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::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 quad_iterator switch_1=quad->child(1); - const quad_iterator 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; lcells.cells.size(); ++h) - for (unsigned int q=0; q::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); + old_child[i]->clear_user_flag(); + old_child[i]->clear_user_index(); + old_child[i]->clear_used_flag(); } - // 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 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::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::cut_xy) - switch_1->set_children(2, switch_2->child_index(2)); + } + // 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::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::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; lcells.cells.size(); ++h) + for (unsigned int q=0; q::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 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::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::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(); + 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 - 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()); + { + 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(); } - quad->clear_children(); - } - // note these quads as children - // to the present one - quad->set_children (0, new_quads[0]->index()); + // 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); + quad->set_refinement_case(aniso_quad_ref_case); - // finally clear flag - // indicating the need - // for refinement - quad->clear_user_data (); - } // if (anisotropic refinement) + // 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()); + 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 quad_ref_case=quad->refinement_case(); + // 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 quad_ref_case=quad->refinement_case(); - if (quad_ref_case==RefinementCase::cut_x || - quad_ref_case==RefinementCase::cut_y) - { - // set the 'opposite' refine case for children - quad->child(0)->set_user_index(RefinementCase::cut_xy-quad_ref_case); - quad->child(1)->set_user_index(RefinementCase::cut_xy-quad_ref_case); - // refine the inner line - line_iterator middle_line; - if (quad_ref_case==RefinementCase::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()) + if (quad_ref_case==RefinementCase::cut_x || + quad_ref_case==RefinementCase::cut_y) { - // 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; + // set the 'opposite' refine case for children + quad->child(0)->set_user_index(RefinementCase::cut_xy-quad_ref_case); + quad->child(1)->set_user_index(RefinementCase::cut_xy-quad_ref_case); + // refine the inner line + typename Triangulation::line_iterator middle_line; + if (quad_ref_case==RefinementCase::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); + // 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 child + // pointer of the present + // line + middle_line->set_children (0, next_unused_line->index()); - // set the two new lines - const 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()); + // set the two new lines + const typename Triangulation::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 (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_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::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) - raw_line_iterator new_lines[4]; + 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::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; - 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()); - } + 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::raw_line_iterator new_lines[4]; - // 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 | - // *--*--* + 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 - }; + 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])); + 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()); - } + 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 + // 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() - }; + 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. - raw_quad_iterator new_quads[4]; + // find some space (consecutive) + // for the first two newly to be + // created quads. + typename Triangulation::raw_quad_iterator new_quads[4]; - next_unused_quad=triangulation.faces->quads.next_free_pair_quad(triangulation); + 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])); + 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::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)); + 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::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 - /////////////////////////////////// - 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 - active_hex_iterator hex = triangulation.begin_active_hex(level), - endh = triangulation.begin_active_hex(level+1); - raw_line_iterator next_unused_line = triangulation.begin_raw_line (); - raw_quad_iterator next_unused_quad = triangulation.begin_raw_quad (); - 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 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) + // 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 + /////////////////////////////////// + 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::active_hex_iterator + hex = triangulation.begin_active_hex(level), + endh = triangulation.begin_active_hex(level+1); + typename Triangulation::raw_line_iterator + next_unused_line = triangulation.begin_raw_line (); + typename Triangulation::raw_quad_iterator + next_unused_quad = triangulation.begin_raw_quad (); + typename Triangulation::raw_hex_iterator + next_unused_hex = triangulation.begin_raw_hex (level+1); + + for (; hex!=endh; ++hex) + if (hex->refine_flag_set()) { - case RefinementCase::cut_x: - case RefinementCase::cut_y: - case RefinementCase::cut_z: - n_new_lines=0; - n_new_quads=1; - n_new_hexes=2; - break; - case RefinementCase::cut_xy: - case RefinementCase::cut_xz: - case RefinementCase::cut_yz: - n_new_lines=1; - n_new_quads=4; - n_new_hexes=4; - break; - case RefinementCase::cut_xyz: - n_new_lines=6; - n_new_quads=12; - n_new_hexes=8; - break; - default: - Assert(false, ExcInternalError()); - break; - } + // this hex needs to be + // refined - // find some space for the newly to - // be created interior lines and - // initialize them. - std::vector new_lines(n_new_lines); - for (unsigned int i=0; ilines.next_free_single_line(triangulation); + // 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 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::cut_x: + case RefinementCase::cut_y: + case RefinementCase::cut_z: + n_new_lines=0; + n_new_quads=1; + n_new_hexes=2; + break; + case RefinementCase::cut_xy: + case RefinementCase::cut_xz: + case RefinementCase::cut_yz: + n_new_lines=1; + n_new_quads=4; + n_new_hexes=4; + break; + case RefinementCase::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::raw_line_iterator> + new_lines(n_new_lines); + for (unsigned int i=0; ilines.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); - } + 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 new_quads(n_new_quads); - for (unsigned int i=0; iquads.next_free_single_quad(triangulation); + // find some space for the newly to + // be created interior quads and + // initialize them. + std::vector::raw_quad_iterator> + new_quads(n_new_quads); + for (unsigned int i=0; iquads.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::lines_per_face; ++j) - new_quads[i]->set_line_orientation(j,true); - } + 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::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 new_hexes(n_new_hexes); - for (unsigned int i=0; icells.next_free_hex(triangulation,level+1); - else - ++next_unused_hex; + // find some space for the newly to + // be created hexes and initialize + // them. + std::vector::raw_hex_iterator> + new_hexes(n_new_hexes); + for (unsigned int i=0; icells.next_free_hex(triangulation,level+1); + else + ++next_unused_hex; - new_hexes[i]=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()); - // 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::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); + 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()); + // 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::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; iset_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) }; + // note these hexes as + // children to the + // present cell + for (unsigned int i=0; iset_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_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 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::cut_x, face_flip=false, face_rotation=false and true - { 1, 1 }}, // RefinementCase::cut_x, face_flip=true, face_rotation=false and true - { { 0, 1 }, // RefinementCase::cut_y, face_flip=false, face_rotation=false and true - { 1, 0 }}};// RefinementCase::cut_y, face_flip=true, face_rotation=false and true + // 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::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::cut_x, face_flip=false, face_rotation=false and true + { 1, 1 }}, // RefinementCase::cut_x, face_flip=true, face_rotation=false and true + { { 0, 1 }, // RefinementCase::cut_y, face_flip=false, face_rotation=false and true + { 1, 0 }}};// RefinementCase::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::cut_x: - { - ////////////////////////////// - // - // RefinementCase::cut_x - // - // the refined cube will look - // like this: - // - // *----*----* - // / / /| - // / / / | - // / / / | - // *----*----* | - // | | | | - // | | | * - // | | | / - // | | | / - // | | |/ - // *----*----* - // - // again, first - // collect some data - // about the indices of - // the lines, with the - // following numbering: + /////////////////////////////////////// + // + // 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::cut_x: + { + ////////////////////////////// + // + // RefinementCase::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 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 - }; + // 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::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]; + lines=&lines_x[0]; - unsigned int line_indices_x[4]; + 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) + 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; - } + 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]); + 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 + // 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(0)->index(), //1 - hex->face(1)->index(), //2 + 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(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(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(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]]) + 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::cut_y: - { - ////////////////////////////// - // - // RefinementCase::cut_y - // - // the refined cube will look - // like this: - // - // *---------* - // / /| - // *---------* | - // / /| | - // *---------* | | - // | | | | - // | | | * - // | | |/ - // | | * - // | |/ - // *---------* - // - // again, first - // collect some data - // about the indices of - // the lines, with the - // following numbering: + }; + 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::cut_y: + { + ////////////////////////////// + // + // RefinementCase::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 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 - }; + // 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::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]; + lines=&lines_y[0]; - unsigned int line_indices_y[4]; + 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) + 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; - } + 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 + 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(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(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(2)->index(), //5 - hex->face(3)->index(), //6 + 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(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]]) + 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::cut_z: - { - ////////////////////////////// - // - // RefinementCase::cut_z - // - // the refined cube will look - // like this: - // - // *---------* - // / /| - // / / | - // / / * - // *---------* /| - // | | / | - // | |/ * - // *---------* / - // | | / - // | |/ - // *---------* - // - // again, first - // collect some data - // about the indices of - // the lines, with the - // following numbering: + }; + 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::cut_z: + { + ////////////////////////////// + // + // RefinementCase::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 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 - }; + // 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::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]; + lines=&lines_z[0]; - unsigned int line_indices_z[4]; + 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(hex->line(8)), - middle_vertex_index(hex->line(11)) - }; + 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(hex->line(8)), + middle_vertex_index(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; - } + 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])); + 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]); + 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 + // 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(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(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(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(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(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::cut_xy: - { - ////////////////////////////// - // - // RefinementCase::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(hex->face(4)), - middle_vertex_index(hex->face(5)))); - - // again, first - // collect some data - // about the indices of - // the lines, with the - // following numbering: + 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::cut_xy: + { + ////////////////////////////// + // + // RefinementCase::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(hex->face(4)), + middle_vertex_index(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 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::standard_to_real_face_vertex(0,f_or[4],f_fl[4],f_ro[4])) - ->line(GeometryInfo::standard_to_real_face_line(1,f_or[4],f_fl[4],f_ro[4])), //4 - hex->face(4)->isotropic_child(GeometryInfo::standard_to_real_face_vertex(3,f_or[4],f_fl[4],f_ro[4])) - ->line(GeometryInfo::standard_to_real_face_line(0,f_or[4],f_fl[4],f_ro[4])), //5 - hex->face(4)->isotropic_child(GeometryInfo::standard_to_real_face_vertex(0,f_or[4],f_fl[4],f_ro[4])) - ->line(GeometryInfo::standard_to_real_face_line(3,f_or[4],f_fl[4],f_ro[4])), //6 - hex->face(4)->isotropic_child(GeometryInfo::standard_to_real_face_vertex(3,f_or[4],f_fl[4],f_ro[4])) - ->line(GeometryInfo::standard_to_real_face_line(2,f_or[4],f_fl[4],f_ro[4])), //7 + // 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::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::standard_to_real_face_vertex(0,f_or[4],f_fl[4],f_ro[4])) + ->line(GeometryInfo::standard_to_real_face_line(1,f_or[4],f_fl[4],f_ro[4])), //4 + hex->face(4)->isotropic_child(GeometryInfo::standard_to_real_face_vertex(3,f_or[4],f_fl[4],f_ro[4])) + ->line(GeometryInfo::standard_to_real_face_line(0,f_or[4],f_fl[4],f_ro[4])), //5 + hex->face(4)->isotropic_child(GeometryInfo::standard_to_real_face_vertex(0,f_or[4],f_fl[4],f_ro[4])) + ->line(GeometryInfo::standard_to_real_face_line(3,f_or[4],f_fl[4],f_ro[4])), //6 + hex->face(4)->isotropic_child(GeometryInfo::standard_to_real_face_vertex(3,f_or[4],f_fl[4],f_ro[4])) + ->line(GeometryInfo::standard_to_real_face_line(2,f_or[4],f_fl[4],f_ro[4])), //7 - hex->face(5)->isotropic_child(GeometryInfo::standard_to_real_face_vertex(0,f_or[5],f_fl[5],f_ro[5])) - ->line(GeometryInfo::standard_to_real_face_line(1,f_or[5],f_fl[5],f_ro[5])), //8 - hex->face(5)->isotropic_child(GeometryInfo::standard_to_real_face_vertex(3,f_or[5],f_fl[5],f_ro[5])) - ->line(GeometryInfo::standard_to_real_face_line(0,f_or[5],f_fl[5],f_ro[5])), //9 - hex->face(5)->isotropic_child(GeometryInfo::standard_to_real_face_vertex(0,f_or[5],f_fl[5],f_ro[5])) - ->line(GeometryInfo::standard_to_real_face_line(3,f_or[5],f_fl[5],f_ro[5])), //10 - hex->face(5)->isotropic_child(GeometryInfo::standard_to_real_face_vertex(3,f_or[5],f_fl[5],f_ro[5])) - ->line(GeometryInfo::standard_to_real_face_line(2,f_or[5],f_fl[5],f_ro[5])), //11 - - new_lines[0] //12 - }; + hex->face(5)->isotropic_child(GeometryInfo::standard_to_real_face_vertex(0,f_or[5],f_fl[5],f_ro[5])) + ->line(GeometryInfo::standard_to_real_face_line(1,f_or[5],f_fl[5],f_ro[5])), //8 + hex->face(5)->isotropic_child(GeometryInfo::standard_to_real_face_vertex(3,f_or[5],f_fl[5],f_ro[5])) + ->line(GeometryInfo::standard_to_real_face_line(0,f_or[5],f_fl[5],f_ro[5])), //9 + hex->face(5)->isotropic_child(GeometryInfo::standard_to_real_face_vertex(0,f_or[5],f_fl[5],f_ro[5])) + ->line(GeometryInfo::standard_to_real_face_line(3,f_or[5],f_fl[5],f_ro[5])), //10 + hex->face(5)->isotropic_child(GeometryInfo::standard_to_real_face_vertex(3,f_or[5],f_fl[5],f_ro[5])) + ->line(GeometryInfo::standard_to_real_face_line(2,f_or[5],f_fl[5],f_ro[5])), //11 + + new_lines[0] //12 + }; - lines=&lines_xy[0]; + lines=&lines_xy[0]; - unsigned int line_indices_xy[13]; + 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; - } + 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(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(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-* + // 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(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(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[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[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[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]); + 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(), + // 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(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(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(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(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::standard_to_real_face_vertex(0,f_or[4],f_fl[4],f_ro[4])), //12 - hex->face(4)->isotropic_child_index(GeometryInfo::standard_to_real_face_vertex(1,f_or[4],f_fl[4],f_ro[4])), - hex->face(4)->isotropic_child_index(GeometryInfo::standard_to_real_face_vertex(2,f_or[4],f_fl[4],f_ro[4])), - hex->face(4)->isotropic_child_index(GeometryInfo::standard_to_real_face_vertex(3,f_or[4],f_fl[4],f_ro[4])), + hex->face(4)->isotropic_child_index(GeometryInfo::standard_to_real_face_vertex(0,f_or[4],f_fl[4],f_ro[4])), //12 + hex->face(4)->isotropic_child_index(GeometryInfo::standard_to_real_face_vertex(1,f_or[4],f_fl[4],f_ro[4])), + hex->face(4)->isotropic_child_index(GeometryInfo::standard_to_real_face_vertex(2,f_or[4],f_fl[4],f_ro[4])), + hex->face(4)->isotropic_child_index(GeometryInfo::standard_to_real_face_vertex(3,f_or[4],f_fl[4],f_ro[4])), - hex->face(5)->isotropic_child_index(GeometryInfo::standard_to_real_face_vertex(0,f_or[5],f_fl[5],f_ro[5])), //16 - hex->face(5)->isotropic_child_index(GeometryInfo::standard_to_real_face_vertex(1,f_or[5],f_fl[5],f_ro[5])), - hex->face(5)->isotropic_child_index(GeometryInfo::standard_to_real_face_vertex(2,f_or[5],f_fl[5],f_ro[5])), - hex->face(5)->isotropic_child_index(GeometryInfo::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::cut_xz: - { - ////////////////////////////// - // - // RefinementCase::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(hex->face(2)), - middle_vertex_index(hex->face(3)))); - - // again, first - // collect some data - // about the indices of - // the lines, with the - // following numbering: + hex->face(5)->isotropic_child_index(GeometryInfo::standard_to_real_face_vertex(0,f_or[5],f_fl[5],f_ro[5])), //16 + hex->face(5)->isotropic_child_index(GeometryInfo::standard_to_real_face_vertex(1,f_or[5],f_fl[5],f_ro[5])), + hex->face(5)->isotropic_child_index(GeometryInfo::standard_to_real_face_vertex(2,f_or[5],f_fl[5],f_ro[5])), + hex->face(5)->isotropic_child_index(GeometryInfo::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::cut_xz: + { + ////////////////////////////// + // + // RefinementCase::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(hex->face(2)), + middle_vertex_index(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 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::standard_to_real_face_vertex(0,f_or[2],f_fl[2],f_ro[2])) - ->line(GeometryInfo::standard_to_real_face_line(3,f_or[2],f_fl[2],f_ro[2])), //4 - hex->face(2)->isotropic_child(GeometryInfo::standard_to_real_face_vertex(3,f_or[2],f_fl[2],f_ro[2])) - ->line(GeometryInfo::standard_to_real_face_line(2,f_or[2],f_fl[2],f_ro[2])), //5 - hex->face(2)->isotropic_child(GeometryInfo::standard_to_real_face_vertex(0,f_or[2],f_fl[2],f_ro[2])) - ->line(GeometryInfo::standard_to_real_face_line(1,f_or[2],f_fl[2],f_ro[2])), //6 - hex->face(2)->isotropic_child(GeometryInfo::standard_to_real_face_vertex(3,f_or[2],f_fl[2],f_ro[2])) - ->line(GeometryInfo::standard_to_real_face_line(0,f_or[2],f_fl[2],f_ro[2])), //7 + // 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::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::standard_to_real_face_vertex(0,f_or[2],f_fl[2],f_ro[2])) + ->line(GeometryInfo::standard_to_real_face_line(3,f_or[2],f_fl[2],f_ro[2])), //4 + hex->face(2)->isotropic_child(GeometryInfo::standard_to_real_face_vertex(3,f_or[2],f_fl[2],f_ro[2])) + ->line(GeometryInfo::standard_to_real_face_line(2,f_or[2],f_fl[2],f_ro[2])), //5 + hex->face(2)->isotropic_child(GeometryInfo::standard_to_real_face_vertex(0,f_or[2],f_fl[2],f_ro[2])) + ->line(GeometryInfo::standard_to_real_face_line(1,f_or[2],f_fl[2],f_ro[2])), //6 + hex->face(2)->isotropic_child(GeometryInfo::standard_to_real_face_vertex(3,f_or[2],f_fl[2],f_ro[2])) + ->line(GeometryInfo::standard_to_real_face_line(0,f_or[2],f_fl[2],f_ro[2])), //7 - hex->face(3)->isotropic_child(GeometryInfo::standard_to_real_face_vertex(0,f_or[3],f_fl[3],f_ro[3])) - ->line(GeometryInfo::standard_to_real_face_line(3,f_or[3],f_fl[3],f_ro[3])), //8 - hex->face(3)->isotropic_child(GeometryInfo::standard_to_real_face_vertex(3,f_or[3],f_fl[3],f_ro[3])) - ->line(GeometryInfo::standard_to_real_face_line(2,f_or[3],f_fl[3],f_ro[3])), //9 - hex->face(3)->isotropic_child(GeometryInfo::standard_to_real_face_vertex(0,f_or[3],f_fl[3],f_ro[3])) - ->line(GeometryInfo::standard_to_real_face_line(1,f_or[3],f_fl[3],f_ro[3])), //10 - hex->face(3)->isotropic_child(GeometryInfo::standard_to_real_face_vertex(3,f_or[3],f_fl[3],f_ro[3])) - ->line(GeometryInfo::standard_to_real_face_line(0,f_or[3],f_fl[3],f_ro[3])), //11 - - new_lines[0] //12 - }; + hex->face(3)->isotropic_child(GeometryInfo::standard_to_real_face_vertex(0,f_or[3],f_fl[3],f_ro[3])) + ->line(GeometryInfo::standard_to_real_face_line(3,f_or[3],f_fl[3],f_ro[3])), //8 + hex->face(3)->isotropic_child(GeometryInfo::standard_to_real_face_vertex(3,f_or[3],f_fl[3],f_ro[3])) + ->line(GeometryInfo::standard_to_real_face_line(2,f_or[3],f_fl[3],f_ro[3])), //9 + hex->face(3)->isotropic_child(GeometryInfo::standard_to_real_face_vertex(0,f_or[3],f_fl[3],f_ro[3])) + ->line(GeometryInfo::standard_to_real_face_line(1,f_or[3],f_fl[3],f_ro[3])), //10 + hex->face(3)->isotropic_child(GeometryInfo::standard_to_real_face_vertex(3,f_or[3],f_fl[3],f_ro[3])) + ->line(GeometryInfo::standard_to_real_face_line(0,f_or[3],f_fl[3],f_ro[3])), //11 + + new_lines[0] //12 + }; - lines=&lines_xz[0]; + lines=&lines_xz[0]; - unsigned int line_indices_xz[13]; + 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; - } + 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(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(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-* + // 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(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(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[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[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::standard_to_real_face_vertex(0,f_or[2],f_fl[2],f_ro[2])), //8 - hex->face(2)->isotropic_child_index(GeometryInfo::standard_to_real_face_vertex(1,f_or[2],f_fl[2],f_ro[2])), - hex->face(2)->isotropic_child_index(GeometryInfo::standard_to_real_face_vertex(2,f_or[2],f_fl[2],f_ro[2])), - hex->face(2)->isotropic_child_index(GeometryInfo::standard_to_real_face_vertex(3,f_or[2],f_fl[2],f_ro[2])), - - hex->face(3)->isotropic_child_index(GeometryInfo::standard_to_real_face_vertex(0,f_or[3],f_fl[3],f_ro[3])), //12 - hex->face(3)->isotropic_child_index(GeometryInfo::standard_to_real_face_vertex(1,f_or[3],f_fl[3],f_ro[3])), - hex->face(3)->isotropic_child_index(GeometryInfo::standard_to_real_face_vertex(2,f_or[3],f_fl[3],f_ro[3])), - hex->face(3)->isotropic_child_index(GeometryInfo::standard_to_real_face_vertex(3,f_or[3],f_fl[3],f_ro[3])), + 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]); - 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]; + 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]); - // 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::cut_yz: - { - ////////////////////////////// - // - // RefinementCase::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(hex->face(0)), - middle_vertex_index(hex->face(1)))); + // 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]]), - // 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) + 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::standard_to_real_face_vertex(0,f_or[2],f_fl[2],f_ro[2])), //8 + hex->face(2)->isotropic_child_index(GeometryInfo::standard_to_real_face_vertex(1,f_or[2],f_fl[2],f_ro[2])), + hex->face(2)->isotropic_child_index(GeometryInfo::standard_to_real_face_vertex(2,f_or[2],f_fl[2],f_ro[2])), + hex->face(2)->isotropic_child_index(GeometryInfo::standard_to_real_face_vertex(3,f_or[2],f_fl[2],f_ro[2])), + + hex->face(3)->isotropic_child_index(GeometryInfo::standard_to_real_face_vertex(0,f_or[3],f_fl[3],f_ro[3])), //12 + hex->face(3)->isotropic_child_index(GeometryInfo::standard_to_real_face_vertex(1,f_or[3],f_fl[3],f_ro[3])), + hex->face(3)->isotropic_child_index(GeometryInfo::standard_to_real_face_vertex(2,f_or[3],f_fl[3],f_ro[3])), + hex->face(3)->isotropic_child_index(GeometryInfo::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::cut_yz: + { + ////////////////////////////// + // + // RefinementCase::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(hex->face(0)), + middle_vertex_index(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 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::standard_to_real_face_vertex(0,f_or[0],f_fl[0],f_ro[0])) - ->line(GeometryInfo::standard_to_real_face_line(1,f_or[0],f_fl[0],f_ro[0])), //4 - hex->face(0)->isotropic_child(GeometryInfo::standard_to_real_face_vertex(3,f_or[0],f_fl[0],f_ro[0])) - ->line(GeometryInfo::standard_to_real_face_line(0,f_or[0],f_fl[0],f_ro[0])), //5 - hex->face(0)->isotropic_child(GeometryInfo::standard_to_real_face_vertex(0,f_or[0],f_fl[0],f_ro[0])) - ->line(GeometryInfo::standard_to_real_face_line(3,f_or[0],f_fl[0],f_ro[0])), //6 - hex->face(0)->isotropic_child(GeometryInfo::standard_to_real_face_vertex(3,f_or[0],f_fl[0],f_ro[0])) - ->line(GeometryInfo::standard_to_real_face_line(2,f_or[0],f_fl[0],f_ro[0])), //7 + // 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::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::standard_to_real_face_vertex(0,f_or[0],f_fl[0],f_ro[0])) + ->line(GeometryInfo::standard_to_real_face_line(1,f_or[0],f_fl[0],f_ro[0])), //4 + hex->face(0)->isotropic_child(GeometryInfo::standard_to_real_face_vertex(3,f_or[0],f_fl[0],f_ro[0])) + ->line(GeometryInfo::standard_to_real_face_line(0,f_or[0],f_fl[0],f_ro[0])), //5 + hex->face(0)->isotropic_child(GeometryInfo::standard_to_real_face_vertex(0,f_or[0],f_fl[0],f_ro[0])) + ->line(GeometryInfo::standard_to_real_face_line(3,f_or[0],f_fl[0],f_ro[0])), //6 + hex->face(0)->isotropic_child(GeometryInfo::standard_to_real_face_vertex(3,f_or[0],f_fl[0],f_ro[0])) + ->line(GeometryInfo::standard_to_real_face_line(2,f_or[0],f_fl[0],f_ro[0])), //7 - hex->face(1)->isotropic_child(GeometryInfo::standard_to_real_face_vertex(0,f_or[1],f_fl[1],f_ro[1])) - ->line(GeometryInfo::standard_to_real_face_line(1,f_or[1],f_fl[1],f_ro[1])), //8 - hex->face(1)->isotropic_child(GeometryInfo::standard_to_real_face_vertex(3,f_or[1],f_fl[1],f_ro[1])) - ->line(GeometryInfo::standard_to_real_face_line(0,f_or[1],f_fl[1],f_ro[1])), //9 - hex->face(1)->isotropic_child(GeometryInfo::standard_to_real_face_vertex(0,f_or[1],f_fl[1],f_ro[1])) - ->line(GeometryInfo::standard_to_real_face_line(3,f_or[1],f_fl[1],f_ro[1])), //10 - hex->face(1)->isotropic_child(GeometryInfo::standard_to_real_face_vertex(3,f_or[1],f_fl[1],f_ro[1])) - ->line(GeometryInfo::standard_to_real_face_line(2,f_or[1],f_fl[1],f_ro[1])), //11 - - new_lines[0] //12 - }; + hex->face(1)->isotropic_child(GeometryInfo::standard_to_real_face_vertex(0,f_or[1],f_fl[1],f_ro[1])) + ->line(GeometryInfo::standard_to_real_face_line(1,f_or[1],f_fl[1],f_ro[1])), //8 + hex->face(1)->isotropic_child(GeometryInfo::standard_to_real_face_vertex(3,f_or[1],f_fl[1],f_ro[1])) + ->line(GeometryInfo::standard_to_real_face_line(0,f_or[1],f_fl[1],f_ro[1])), //9 + hex->face(1)->isotropic_child(GeometryInfo::standard_to_real_face_vertex(0,f_or[1],f_fl[1],f_ro[1])) + ->line(GeometryInfo::standard_to_real_face_line(3,f_or[1],f_fl[1],f_ro[1])), //10 + hex->face(1)->isotropic_child(GeometryInfo::standard_to_real_face_vertex(3,f_or[1],f_fl[1],f_ro[1])) + ->line(GeometryInfo::standard_to_real_face_line(2,f_or[1],f_fl[1],f_ro[1])), //11 + + new_lines[0] //12 + }; - lines=&lines_yz[0]; + lines=&lines_yz[0]; - unsigned int line_indices_yz[13]; + 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; - } + 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(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(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----* + // 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(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(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[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[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[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]); + 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(), + // 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::standard_to_real_face_vertex(0,f_or[0],f_fl[0],f_ro[0])), //4 - hex->face(0)->isotropic_child_index(GeometryInfo::standard_to_real_face_vertex(1,f_or[0],f_fl[0],f_ro[0])), - hex->face(0)->isotropic_child_index(GeometryInfo::standard_to_real_face_vertex(2,f_or[0],f_fl[0],f_ro[0])), - hex->face(0)->isotropic_child_index(GeometryInfo::standard_to_real_face_vertex(3,f_or[0],f_fl[0],f_ro[0])), + hex->face(0)->isotropic_child_index(GeometryInfo::standard_to_real_face_vertex(0,f_or[0],f_fl[0],f_ro[0])), //4 + hex->face(0)->isotropic_child_index(GeometryInfo::standard_to_real_face_vertex(1,f_or[0],f_fl[0],f_ro[0])), + hex->face(0)->isotropic_child_index(GeometryInfo::standard_to_real_face_vertex(2,f_or[0],f_fl[0],f_ro[0])), + hex->face(0)->isotropic_child_index(GeometryInfo::standard_to_real_face_vertex(3,f_or[0],f_fl[0],f_ro[0])), - hex->face(1)->isotropic_child_index(GeometryInfo::standard_to_real_face_vertex(0,f_or[1],f_fl[1],f_ro[1])), //8 - hex->face(1)->isotropic_child_index(GeometryInfo::standard_to_real_face_vertex(1,f_or[1],f_fl[1],f_ro[1])), - hex->face(1)->isotropic_child_index(GeometryInfo::standard_to_real_face_vertex(2,f_or[1],f_fl[1],f_ro[1])), - hex->face(1)->isotropic_child_index(GeometryInfo::standard_to_real_face_vertex(3,f_or[1],f_fl[1],f_ro[1])), + hex->face(1)->isotropic_child_index(GeometryInfo::standard_to_real_face_vertex(0,f_or[1],f_fl[1],f_ro[1])), //8 + hex->face(1)->isotropic_child_index(GeometryInfo::standard_to_real_face_vertex(1,f_or[1],f_fl[1],f_ro[1])), + hex->face(1)->isotropic_child_index(GeometryInfo::standard_to_real_face_vertex(2,f_or[1],f_fl[1],f_ro[1])), + hex->face(1)->isotropic_child_index(GeometryInfo::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(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(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(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::cut_xyz: - { - ////////////////////////////// - // - // RefinementCase::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; + 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::cut_xyz: + { + ////////////////////////////// + // + // RefinementCase::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(); - // first add corners of hex - for (unsigned int vertex=0; - vertex::vertices_per_cell; ++vertex) - triangulation.vertices[next_unused_vertex] += hex->vertex(vertex) / 128; - // now add center of lines - for (unsigned int line=0; - line::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::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(hex->face(0)), - middle_vertex_index(hex->face(1)), - middle_vertex_index(hex->face(2)), - middle_vertex_index(hex->face(3)), - middle_vertex_index(hex->face(4)), - middle_vertex_index(hex->face(5)), - next_unused_vertex - }; - vertex_indices=&vertex_indices_xyz[0]; + // 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(); + // first add corners of hex + for (unsigned int vertex=0; + vertex::vertices_per_cell; ++vertex) + triangulation.vertices[next_unused_vertex] += hex->vertex(vertex) / 128; + // now add center of lines + for (unsigned int line=0; + line::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::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(hex->face(0)), + middle_vertex_index(hex->face(1)), + middle_vertex_index(hex->face(2)), + middle_vertex_index(hex->face(3)), + middle_vertex_index(hex->face(4)), + middle_vertex_index(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) + 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 | - // *---*---* *---*---* + // 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 raw_line_iterator lines_xyz[30] - = { - hex->face(0)->isotropic_child(GeometryInfo::standard_to_real_face_vertex(0,f_or[0],f_fl[0],f_ro[0])) - ->line(GeometryInfo::standard_to_real_face_line(1,f_or[0],f_fl[0],f_ro[0])), //0 - hex->face(0)->isotropic_child(GeometryInfo::standard_to_real_face_vertex(3,f_or[0],f_fl[0],f_ro[0])) - ->line(GeometryInfo::standard_to_real_face_line(0,f_or[0],f_fl[0],f_ro[0])), //1 - hex->face(0)->isotropic_child(GeometryInfo::standard_to_real_face_vertex(0,f_or[0],f_fl[0],f_ro[0])) - ->line(GeometryInfo::standard_to_real_face_line(3,f_or[0],f_fl[0],f_ro[0])), //2 - hex->face(0)->isotropic_child(GeometryInfo::standard_to_real_face_vertex(3,f_or[0],f_fl[0],f_ro[0])) - ->line(GeometryInfo::standard_to_real_face_line(2,f_or[0],f_fl[0],f_ro[0])), //3 + // set up a list of line iterators + // first. from this, construct + // lists of line_indices and + // line orientations later on + const typename Triangulation::raw_line_iterator + lines_xyz[30] + = { + hex->face(0)->isotropic_child(GeometryInfo::standard_to_real_face_vertex(0,f_or[0],f_fl[0],f_ro[0])) + ->line(GeometryInfo::standard_to_real_face_line(1,f_or[0],f_fl[0],f_ro[0])), //0 + hex->face(0)->isotropic_child(GeometryInfo::standard_to_real_face_vertex(3,f_or[0],f_fl[0],f_ro[0])) + ->line(GeometryInfo::standard_to_real_face_line(0,f_or[0],f_fl[0],f_ro[0])), //1 + hex->face(0)->isotropic_child(GeometryInfo::standard_to_real_face_vertex(0,f_or[0],f_fl[0],f_ro[0])) + ->line(GeometryInfo::standard_to_real_face_line(3,f_or[0],f_fl[0],f_ro[0])), //2 + hex->face(0)->isotropic_child(GeometryInfo::standard_to_real_face_vertex(3,f_or[0],f_fl[0],f_ro[0])) + ->line(GeometryInfo::standard_to_real_face_line(2,f_or[0],f_fl[0],f_ro[0])), //3 - hex->face(1)->isotropic_child(GeometryInfo::standard_to_real_face_vertex(0,f_or[1],f_fl[1],f_ro[1])) - ->line(GeometryInfo::standard_to_real_face_line(1,f_or[1],f_fl[1],f_ro[1])), //4 - hex->face(1)->isotropic_child(GeometryInfo::standard_to_real_face_vertex(3,f_or[1],f_fl[1],f_ro[1])) - ->line(GeometryInfo::standard_to_real_face_line(0,f_or[1],f_fl[1],f_ro[1])), //5 - hex->face(1)->isotropic_child(GeometryInfo::standard_to_real_face_vertex(0,f_or[1],f_fl[1],f_ro[1])) - ->line(GeometryInfo::standard_to_real_face_line(3,f_or[1],f_fl[1],f_ro[1])), //6 - hex->face(1)->isotropic_child(GeometryInfo::standard_to_real_face_vertex(3,f_or[1],f_fl[1],f_ro[1])) - ->line(GeometryInfo::standard_to_real_face_line(2,f_or[1],f_fl[1],f_ro[1])), //7 + hex->face(1)->isotropic_child(GeometryInfo::standard_to_real_face_vertex(0,f_or[1],f_fl[1],f_ro[1])) + ->line(GeometryInfo::standard_to_real_face_line(1,f_or[1],f_fl[1],f_ro[1])), //4 + hex->face(1)->isotropic_child(GeometryInfo::standard_to_real_face_vertex(3,f_or[1],f_fl[1],f_ro[1])) + ->line(GeometryInfo::standard_to_real_face_line(0,f_or[1],f_fl[1],f_ro[1])), //5 + hex->face(1)->isotropic_child(GeometryInfo::standard_to_real_face_vertex(0,f_or[1],f_fl[1],f_ro[1])) + ->line(GeometryInfo::standard_to_real_face_line(3,f_or[1],f_fl[1],f_ro[1])), //6 + hex->face(1)->isotropic_child(GeometryInfo::standard_to_real_face_vertex(3,f_or[1],f_fl[1],f_ro[1])) + ->line(GeometryInfo::standard_to_real_face_line(2,f_or[1],f_fl[1],f_ro[1])), //7 - hex->face(2)->isotropic_child(GeometryInfo::standard_to_real_face_vertex(0,f_or[2],f_fl[2],f_ro[2])) - ->line(GeometryInfo::standard_to_real_face_line(1,f_or[2],f_fl[2],f_ro[2])), //8 - hex->face(2)->isotropic_child(GeometryInfo::standard_to_real_face_vertex(3,f_or[2],f_fl[2],f_ro[2])) - ->line(GeometryInfo::standard_to_real_face_line(0,f_or[2],f_fl[2],f_ro[2])), //9 - hex->face(2)->isotropic_child(GeometryInfo::standard_to_real_face_vertex(0,f_or[2],f_fl[2],f_ro[2])) - ->line(GeometryInfo::standard_to_real_face_line(3,f_or[2],f_fl[2],f_ro[2])), //10 - hex->face(2)->isotropic_child(GeometryInfo::standard_to_real_face_vertex(3,f_or[2],f_fl[2],f_ro[2])) - ->line(GeometryInfo::standard_to_real_face_line(2,f_or[2],f_fl[2],f_ro[2])), //11 + hex->face(2)->isotropic_child(GeometryInfo::standard_to_real_face_vertex(0,f_or[2],f_fl[2],f_ro[2])) + ->line(GeometryInfo::standard_to_real_face_line(1,f_or[2],f_fl[2],f_ro[2])), //8 + hex->face(2)->isotropic_child(GeometryInfo::standard_to_real_face_vertex(3,f_or[2],f_fl[2],f_ro[2])) + ->line(GeometryInfo::standard_to_real_face_line(0,f_or[2],f_fl[2],f_ro[2])), //9 + hex->face(2)->isotropic_child(GeometryInfo::standard_to_real_face_vertex(0,f_or[2],f_fl[2],f_ro[2])) + ->line(GeometryInfo::standard_to_real_face_line(3,f_or[2],f_fl[2],f_ro[2])), //10 + hex->face(2)->isotropic_child(GeometryInfo::standard_to_real_face_vertex(3,f_or[2],f_fl[2],f_ro[2])) + ->line(GeometryInfo::standard_to_real_face_line(2,f_or[2],f_fl[2],f_ro[2])), //11 - hex->face(3)->isotropic_child(GeometryInfo::standard_to_real_face_vertex(0,f_or[3],f_fl[3],f_ro[3])) - ->line(GeometryInfo::standard_to_real_face_line(1,f_or[3],f_fl[3],f_ro[3])), //12 - hex->face(3)->isotropic_child(GeometryInfo::standard_to_real_face_vertex(3,f_or[3],f_fl[3],f_ro[3])) - ->line(GeometryInfo::standard_to_real_face_line(0,f_or[3],f_fl[3],f_ro[3])), //13 - hex->face(3)->isotropic_child(GeometryInfo::standard_to_real_face_vertex(0,f_or[3],f_fl[3],f_ro[3])) - ->line(GeometryInfo::standard_to_real_face_line(3,f_or[3],f_fl[3],f_ro[3])), //14 - hex->face(3)->isotropic_child(GeometryInfo::standard_to_real_face_vertex(3,f_or[3],f_fl[3],f_ro[3])) - ->line(GeometryInfo::standard_to_real_face_line(2,f_or[3],f_fl[3],f_ro[3])), //15 + hex->face(3)->isotropic_child(GeometryInfo::standard_to_real_face_vertex(0,f_or[3],f_fl[3],f_ro[3])) + ->line(GeometryInfo::standard_to_real_face_line(1,f_or[3],f_fl[3],f_ro[3])), //12 + hex->face(3)->isotropic_child(GeometryInfo::standard_to_real_face_vertex(3,f_or[3],f_fl[3],f_ro[3])) + ->line(GeometryInfo::standard_to_real_face_line(0,f_or[3],f_fl[3],f_ro[3])), //13 + hex->face(3)->isotropic_child(GeometryInfo::standard_to_real_face_vertex(0,f_or[3],f_fl[3],f_ro[3])) + ->line(GeometryInfo::standard_to_real_face_line(3,f_or[3],f_fl[3],f_ro[3])), //14 + hex->face(3)->isotropic_child(GeometryInfo::standard_to_real_face_vertex(3,f_or[3],f_fl[3],f_ro[3])) + ->line(GeometryInfo::standard_to_real_face_line(2,f_or[3],f_fl[3],f_ro[3])), //15 - hex->face(4)->isotropic_child(GeometryInfo::standard_to_real_face_vertex(0,f_or[4],f_fl[4],f_ro[4])) - ->line(GeometryInfo::standard_to_real_face_line(1,f_or[4],f_fl[4],f_ro[4])), //16 - hex->face(4)->isotropic_child(GeometryInfo::standard_to_real_face_vertex(3,f_or[4],f_fl[4],f_ro[4])) - ->line(GeometryInfo::standard_to_real_face_line(0,f_or[4],f_fl[4],f_ro[4])), //17 - hex->face(4)->isotropic_child(GeometryInfo::standard_to_real_face_vertex(0,f_or[4],f_fl[4],f_ro[4])) - ->line(GeometryInfo::standard_to_real_face_line(3,f_or[4],f_fl[4],f_ro[4])), //18 - hex->face(4)->isotropic_child(GeometryInfo::standard_to_real_face_vertex(3,f_or[4],f_fl[4],f_ro[4])) - ->line(GeometryInfo::standard_to_real_face_line(2,f_or[4],f_fl[4],f_ro[4])), //19 + hex->face(4)->isotropic_child(GeometryInfo::standard_to_real_face_vertex(0,f_or[4],f_fl[4],f_ro[4])) + ->line(GeometryInfo::standard_to_real_face_line(1,f_or[4],f_fl[4],f_ro[4])), //16 + hex->face(4)->isotropic_child(GeometryInfo::standard_to_real_face_vertex(3,f_or[4],f_fl[4],f_ro[4])) + ->line(GeometryInfo::standard_to_real_face_line(0,f_or[4],f_fl[4],f_ro[4])), //17 + hex->face(4)->isotropic_child(GeometryInfo::standard_to_real_face_vertex(0,f_or[4],f_fl[4],f_ro[4])) + ->line(GeometryInfo::standard_to_real_face_line(3,f_or[4],f_fl[4],f_ro[4])), //18 + hex->face(4)->isotropic_child(GeometryInfo::standard_to_real_face_vertex(3,f_or[4],f_fl[4],f_ro[4])) + ->line(GeometryInfo::standard_to_real_face_line(2,f_or[4],f_fl[4],f_ro[4])), //19 - hex->face(5)->isotropic_child(GeometryInfo::standard_to_real_face_vertex(0,f_or[5],f_fl[5],f_ro[5])) - ->line(GeometryInfo::standard_to_real_face_line(1,f_or[5],f_fl[5],f_ro[5])), //20 - hex->face(5)->isotropic_child(GeometryInfo::standard_to_real_face_vertex(3,f_or[5],f_fl[5],f_ro[5])) - ->line(GeometryInfo::standard_to_real_face_line(0,f_or[5],f_fl[5],f_ro[5])), //21 - hex->face(5)->isotropic_child(GeometryInfo::standard_to_real_face_vertex(0,f_or[5],f_fl[5],f_ro[5])) - ->line(GeometryInfo::standard_to_real_face_line(3,f_or[5],f_fl[5],f_ro[5])), //22 - hex->face(5)->isotropic_child(GeometryInfo::standard_to_real_face_vertex(3,f_or[5],f_fl[5],f_ro[5])) - ->line(GeometryInfo::standard_to_real_face_line(2,f_or[5],f_fl[5],f_ro[5])), //23 + hex->face(5)->isotropic_child(GeometryInfo::standard_to_real_face_vertex(0,f_or[5],f_fl[5],f_ro[5])) + ->line(GeometryInfo::standard_to_real_face_line(1,f_or[5],f_fl[5],f_ro[5])), //20 + hex->face(5)->isotropic_child(GeometryInfo::standard_to_real_face_vertex(3,f_or[5],f_fl[5],f_ro[5])) + ->line(GeometryInfo::standard_to_real_face_line(0,f_or[5],f_fl[5],f_ro[5])), //21 + hex->face(5)->isotropic_child(GeometryInfo::standard_to_real_face_vertex(0,f_or[5],f_fl[5],f_ro[5])) + ->line(GeometryInfo::standard_to_real_face_line(3,f_or[5],f_fl[5],f_ro[5])), //22 + hex->face(5)->isotropic_child(GeometryInfo::standard_to_real_face_vertex(3,f_or[5],f_fl[5],f_ro[5])) + ->line(GeometryInfo::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 - }; + 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]; + 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]; + 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]; + // 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. - // DEBUG - face_iterator face_0=hex->face(0); - face_iterator face_0_child_0=face_0->isotropic_child(GeometryInfo::standard_to_real_face_vertex(0,f_or[0],f_fl[0],f_ro[0])); - line_iterator face_0_child_0_line_1=face_0_child_0 - ->line(GeometryInfo::standard_to_real_face_line(1,f_or[0],f_fl[0],f_ro[0])); - // END DEBUG - 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-* + // 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. + // DEBUG + typename Triangulation::face_iterator + face_0=hex->face(0); + typename Triangulation::face_iterator + face_0_child_0=face_0->isotropic_child(GeometryInfo::standard_to_real_face_vertex(0,f_or[0],f_fl[0],f_ro[0])); + typename Triangulation::line_iterator + face_0_child_0_line_1=face_0_child_0 + ->line(GeometryInfo::standard_to_real_face_line(1,f_or[0],f_fl[0],f_ro[0])); + // END DEBUG + 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])); + 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]); + // 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[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[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[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[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[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[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[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[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[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[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]); + 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. + ///////////////////////////////// + // 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 + // 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::standard_to_real_face_vertex(0,f_or[0],f_fl[0],f_ro[0])), //12 - hex->face(0)->isotropic_child_index(GeometryInfo::standard_to_real_face_vertex(1,f_or[0],f_fl[0],f_ro[0])), - hex->face(0)->isotropic_child_index(GeometryInfo::standard_to_real_face_vertex(2,f_or[0],f_fl[0],f_ro[0])), - hex->face(0)->isotropic_child_index(GeometryInfo::standard_to_real_face_vertex(3,f_or[0],f_fl[0],f_ro[0])), - - hex->face(1)->isotropic_child_index(GeometryInfo::standard_to_real_face_vertex(0,f_or[1],f_fl[1],f_ro[1])), //16 - hex->face(1)->isotropic_child_index(GeometryInfo::standard_to_real_face_vertex(1,f_or[1],f_fl[1],f_ro[1])), - hex->face(1)->isotropic_child_index(GeometryInfo::standard_to_real_face_vertex(2,f_or[1],f_fl[1],f_ro[1])), - hex->face(1)->isotropic_child_index(GeometryInfo::standard_to_real_face_vertex(3,f_or[1],f_fl[1],f_ro[1])), + hex->face(0)->isotropic_child_index(GeometryInfo::standard_to_real_face_vertex(0,f_or[0],f_fl[0],f_ro[0])), //12 + hex->face(0)->isotropic_child_index(GeometryInfo::standard_to_real_face_vertex(1,f_or[0],f_fl[0],f_ro[0])), + hex->face(0)->isotropic_child_index(GeometryInfo::standard_to_real_face_vertex(2,f_or[0],f_fl[0],f_ro[0])), + hex->face(0)->isotropic_child_index(GeometryInfo::standard_to_real_face_vertex(3,f_or[0],f_fl[0],f_ro[0])), + + hex->face(1)->isotropic_child_index(GeometryInfo::standard_to_real_face_vertex(0,f_or[1],f_fl[1],f_ro[1])), //16 + hex->face(1)->isotropic_child_index(GeometryInfo::standard_to_real_face_vertex(1,f_or[1],f_fl[1],f_ro[1])), + hex->face(1)->isotropic_child_index(GeometryInfo::standard_to_real_face_vertex(2,f_or[1],f_fl[1],f_ro[1])), + hex->face(1)->isotropic_child_index(GeometryInfo::standard_to_real_face_vertex(3,f_or[1],f_fl[1],f_ro[1])), - hex->face(2)->isotropic_child_index(GeometryInfo::standard_to_real_face_vertex(0,f_or[2],f_fl[2],f_ro[2])), //20 - hex->face(2)->isotropic_child_index(GeometryInfo::standard_to_real_face_vertex(1,f_or[2],f_fl[2],f_ro[2])), - hex->face(2)->isotropic_child_index(GeometryInfo::standard_to_real_face_vertex(2,f_or[2],f_fl[2],f_ro[2])), - hex->face(2)->isotropic_child_index(GeometryInfo::standard_to_real_face_vertex(3,f_or[2],f_fl[2],f_ro[2])), + hex->face(2)->isotropic_child_index(GeometryInfo::standard_to_real_face_vertex(0,f_or[2],f_fl[2],f_ro[2])), //20 + hex->face(2)->isotropic_child_index(GeometryInfo::standard_to_real_face_vertex(1,f_or[2],f_fl[2],f_ro[2])), + hex->face(2)->isotropic_child_index(GeometryInfo::standard_to_real_face_vertex(2,f_or[2],f_fl[2],f_ro[2])), + hex->face(2)->isotropic_child_index(GeometryInfo::standard_to_real_face_vertex(3,f_or[2],f_fl[2],f_ro[2])), - hex->face(3)->isotropic_child_index(GeometryInfo::standard_to_real_face_vertex(0,f_or[3],f_fl[3],f_ro[3])), //24 - hex->face(3)->isotropic_child_index(GeometryInfo::standard_to_real_face_vertex(1,f_or[3],f_fl[3],f_ro[3])), - hex->face(3)->isotropic_child_index(GeometryInfo::standard_to_real_face_vertex(2,f_or[3],f_fl[3],f_ro[3])), - hex->face(3)->isotropic_child_index(GeometryInfo::standard_to_real_face_vertex(3,f_or[3],f_fl[3],f_ro[3])), + hex->face(3)->isotropic_child_index(GeometryInfo::standard_to_real_face_vertex(0,f_or[3],f_fl[3],f_ro[3])), //24 + hex->face(3)->isotropic_child_index(GeometryInfo::standard_to_real_face_vertex(1,f_or[3],f_fl[3],f_ro[3])), + hex->face(3)->isotropic_child_index(GeometryInfo::standard_to_real_face_vertex(2,f_or[3],f_fl[3],f_ro[3])), + hex->face(3)->isotropic_child_index(GeometryInfo::standard_to_real_face_vertex(3,f_or[3],f_fl[3],f_ro[3])), - hex->face(4)->isotropic_child_index(GeometryInfo::standard_to_real_face_vertex(0,f_or[4],f_fl[4],f_ro[4])), //28 - hex->face(4)->isotropic_child_index(GeometryInfo::standard_to_real_face_vertex(1,f_or[4],f_fl[4],f_ro[4])), - hex->face(4)->isotropic_child_index(GeometryInfo::standard_to_real_face_vertex(2,f_or[4],f_fl[4],f_ro[4])), - hex->face(4)->isotropic_child_index(GeometryInfo::standard_to_real_face_vertex(3,f_or[4],f_fl[4],f_ro[4])), + hex->face(4)->isotropic_child_index(GeometryInfo::standard_to_real_face_vertex(0,f_or[4],f_fl[4],f_ro[4])), //28 + hex->face(4)->isotropic_child_index(GeometryInfo::standard_to_real_face_vertex(1,f_or[4],f_fl[4],f_ro[4])), + hex->face(4)->isotropic_child_index(GeometryInfo::standard_to_real_face_vertex(2,f_or[4],f_fl[4],f_ro[4])), + hex->face(4)->isotropic_child_index(GeometryInfo::standard_to_real_face_vertex(3,f_or[4],f_fl[4],f_ro[4])), - hex->face(5)->isotropic_child_index(GeometryInfo::standard_to_real_face_vertex(0,f_or[5],f_fl[5],f_ro[5])), //32 - hex->face(5)->isotropic_child_index(GeometryInfo::standard_to_real_face_vertex(1,f_or[5],f_fl[5],f_ro[5])), - hex->face(5)->isotropic_child_index(GeometryInfo::standard_to_real_face_vertex(2,f_or[5],f_fl[5],f_ro[5])), - hex->face(5)->isotropic_child_index(GeometryInfo::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])); + hex->face(5)->isotropic_child_index(GeometryInfo::standard_to_real_face_vertex(0,f_or[5],f_fl[5],f_ro[5])), //32 + hex->face(5)->isotropic_child_index(GeometryInfo::standard_to_real_face_vertex(1,f_or[5],f_fl[5],f_ro[5])), + hex->face(5)->isotropic_child_index(GeometryInfo::standard_to_real_face_vertex(2,f_or[5],f_fl[5],f_ro[5])), + hex->face(5)->isotropic_child_index(GeometryInfo::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::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()); + // 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; - }//switch (ref_case) + } + default: + // all refinement cases + // have been treated, + // there only remains + // RefinementCase::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 + // 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::faces_per_cell; ++f) - for (unsigned int s=0; - s::n_children(GeometryInfo::face_refinement_case(ref_case,f)), - 1U); - ++s) - { - const unsigned int current_child - =GeometryInfo::child_cell_on_face(ref_case, - f, - s, - f_or[f], - f_fl[f], - f_ro[f], - GeometryInfo::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]); - } + // 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::faces_per_cell; ++f) + for (unsigned int s=0; + s::n_children(GeometryInfo::face_refinement_case(ref_case,f)), + 1U); + ++s) + { + const unsigned int current_child + =GeometryInfo::child_cell_on_face(ref_case, + f, + s, + f_or[f], + f_fl[f], + f_ro[f], + GeometryInfo::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 the only thing still - // to be done is setting - // neighborship - // information. - // - // the easiest part is setting the - // inner neighbors, i.e. children - // neighboring other children of - // the same mother cube. - switch (ref_case) - { - case RefinementCase::cut_x: - new_hexes[0]->set_neighbor(1, new_hexes[1]); + ///////////////////////////////// + // now the only thing still + // to be done is setting + // neighborship + // information. + // + // the easiest part is setting the + // inner neighbors, i.e. children + // neighboring other children of + // the same mother cube. + switch (ref_case) + { + case RefinementCase::cut_x: + new_hexes[0]->set_neighbor(1, new_hexes[1]); - new_hexes[1]->set_neighbor(0, new_hexes[0]); - break; - case RefinementCase::cut_y: - new_hexes[0]->set_neighbor(3, new_hexes[1]); - - new_hexes[1]->set_neighbor(2, new_hexes[0]); - break; - case RefinementCase::cut_z: - new_hexes[0]->set_neighbor(5, new_hexes[1]); - - new_hexes[1]->set_neighbor(4, new_hexes[0]); - break; - case RefinementCase::cut_xy: - new_hexes[0]->set_neighbor(1, new_hexes[1]); - new_hexes[0]->set_neighbor(3, new_hexes[2]); - - new_hexes[1]->set_neighbor(0, new_hexes[0]); - new_hexes[1]->set_neighbor(3, new_hexes[3]); - - new_hexes[2]->set_neighbor(1, new_hexes[3]); - new_hexes[2]->set_neighbor(2, new_hexes[0]); - - new_hexes[3]->set_neighbor(0, new_hexes[2]); - new_hexes[3]->set_neighbor(2, new_hexes[1]); - break; - case RefinementCase::cut_xz: - new_hexes[0]->set_neighbor(1, new_hexes[2]); - new_hexes[0]->set_neighbor(5, new_hexes[1]); - - new_hexes[1]->set_neighbor(1, new_hexes[3]); - new_hexes[1]->set_neighbor(4, new_hexes[0]); - - new_hexes[2]->set_neighbor(0, new_hexes[0]); - new_hexes[2]->set_neighbor(5, new_hexes[3]); - - new_hexes[3]->set_neighbor(0, new_hexes[1]); - new_hexes[3]->set_neighbor(4, new_hexes[2]); - break; - case RefinementCase::cut_yz: - new_hexes[0]->set_neighbor(3, new_hexes[1]); - new_hexes[0]->set_neighbor(5, new_hexes[2]); - - new_hexes[1]->set_neighbor(2, new_hexes[0]); - new_hexes[1]->set_neighbor(5, new_hexes[3]); - - new_hexes[2]->set_neighbor(3, new_hexes[3]); - new_hexes[2]->set_neighbor(4, new_hexes[0]); - - new_hexes[3]->set_neighbor(2, new_hexes[2]); - new_hexes[3]->set_neighbor(4, new_hexes[1]); - break; - case RefinementCase::cut_xyz: - new_hexes[0]->set_neighbor(1, new_hexes[1]); - new_hexes[0]->set_neighbor(3, new_hexes[2]); - new_hexes[0]->set_neighbor(5, new_hexes[4]); - - new_hexes[1]->set_neighbor(0, new_hexes[0]); - new_hexes[1]->set_neighbor(3, new_hexes[3]); - new_hexes[1]->set_neighbor(5, new_hexes[5]); - - new_hexes[2]->set_neighbor(1, new_hexes[3]); - new_hexes[2]->set_neighbor(2, new_hexes[0]); - new_hexes[2]->set_neighbor(5, new_hexes[6]); - - new_hexes[3]->set_neighbor(0, new_hexes[2]); - new_hexes[3]->set_neighbor(2, new_hexes[1]); - new_hexes[3]->set_neighbor(5, new_hexes[7]); - - new_hexes[4]->set_neighbor(1, new_hexes[5]); - new_hexes[4]->set_neighbor(3, new_hexes[6]); - new_hexes[4]->set_neighbor(4, new_hexes[0]); - - new_hexes[5]->set_neighbor(0, new_hexes[4]); - new_hexes[5]->set_neighbor(3, new_hexes[7]); - new_hexes[5]->set_neighbor(4, new_hexes[1]); - - new_hexes[6]->set_neighbor(1, new_hexes[7]); - new_hexes[6]->set_neighbor(2, new_hexes[4]); - new_hexes[6]->set_neighbor(4, new_hexes[2]); - - new_hexes[7]->set_neighbor(0, new_hexes[6]); - new_hexes[7]->set_neighbor(2, new_hexes[5]); - new_hexes[7]->set_neighbor(4, new_hexes[3]); - break; - default: - Assert (false, ExcInternalError()); - break; - } + new_hexes[1]->set_neighbor(0, new_hexes[0]); + break; + case RefinementCase::cut_y: + new_hexes[0]->set_neighbor(3, new_hexes[1]); + + new_hexes[1]->set_neighbor(2, new_hexes[0]); + break; + case RefinementCase::cut_z: + new_hexes[0]->set_neighbor(5, new_hexes[1]); + + new_hexes[1]->set_neighbor(4, new_hexes[0]); + break; + case RefinementCase::cut_xy: + new_hexes[0]->set_neighbor(1, new_hexes[1]); + new_hexes[0]->set_neighbor(3, new_hexes[2]); + + new_hexes[1]->set_neighbor(0, new_hexes[0]); + new_hexes[1]->set_neighbor(3, new_hexes[3]); + + new_hexes[2]->set_neighbor(1, new_hexes[3]); + new_hexes[2]->set_neighbor(2, new_hexes[0]); + + new_hexes[3]->set_neighbor(0, new_hexes[2]); + new_hexes[3]->set_neighbor(2, new_hexes[1]); + break; + case RefinementCase::cut_xz: + new_hexes[0]->set_neighbor(1, new_hexes[2]); + new_hexes[0]->set_neighbor(5, new_hexes[1]); + + new_hexes[1]->set_neighbor(1, new_hexes[3]); + new_hexes[1]->set_neighbor(4, new_hexes[0]); + + new_hexes[2]->set_neighbor(0, new_hexes[0]); + new_hexes[2]->set_neighbor(5, new_hexes[3]); + + new_hexes[3]->set_neighbor(0, new_hexes[1]); + new_hexes[3]->set_neighbor(4, new_hexes[2]); + break; + case RefinementCase::cut_yz: + new_hexes[0]->set_neighbor(3, new_hexes[1]); + new_hexes[0]->set_neighbor(5, new_hexes[2]); + + new_hexes[1]->set_neighbor(2, new_hexes[0]); + new_hexes[1]->set_neighbor(5, new_hexes[3]); + + new_hexes[2]->set_neighbor(3, new_hexes[3]); + new_hexes[2]->set_neighbor(4, new_hexes[0]); + + new_hexes[3]->set_neighbor(2, new_hexes[2]); + new_hexes[3]->set_neighbor(4, new_hexes[1]); + break; + case RefinementCase::cut_xyz: + new_hexes[0]->set_neighbor(1, new_hexes[1]); + new_hexes[0]->set_neighbor(3, new_hexes[2]); + new_hexes[0]->set_neighbor(5, new_hexes[4]); + + new_hexes[1]->set_neighbor(0, new_hexes[0]); + new_hexes[1]->set_neighbor(3, new_hexes[3]); + new_hexes[1]->set_neighbor(5, new_hexes[5]); + + new_hexes[2]->set_neighbor(1, new_hexes[3]); + new_hexes[2]->set_neighbor(2, new_hexes[0]); + new_hexes[2]->set_neighbor(5, new_hexes[6]); + + new_hexes[3]->set_neighbor(0, new_hexes[2]); + new_hexes[3]->set_neighbor(2, new_hexes[1]); + new_hexes[3]->set_neighbor(5, new_hexes[7]); + + new_hexes[4]->set_neighbor(1, new_hexes[5]); + new_hexes[4]->set_neighbor(3, new_hexes[6]); + new_hexes[4]->set_neighbor(4, new_hexes[0]); + + new_hexes[5]->set_neighbor(0, new_hexes[4]); + new_hexes[5]->set_neighbor(3, new_hexes[7]); + new_hexes[5]->set_neighbor(4, new_hexes[1]); + + new_hexes[6]->set_neighbor(1, new_hexes[7]); + new_hexes[6]->set_neighbor(2, new_hexes[4]); + new_hexes[6]->set_neighbor(4, new_hexes[2]); + + new_hexes[7]->set_neighbor(0, new_hexes[6]); + new_hexes[7]->set_neighbor(2, new_hexes[5]); + new_hexes[7]->set_neighbor(4, new_hexes[3]); + break; + default: + Assert (false, ExcInternalError()); + break; + } - // it's a bit more complicated for - // outer neighbors. Leave this to a - // separate function - update_neighbors (hex, true); - - // note that the - // refinement flag was - // already cleared at the - // beginning of this loop - } - } + // it's a bit more complicated for + // outer neighbors. Leave this to a + // separate function + update_neighbors (hex, true); + + // 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(); - } + // 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(); + } - /** - * 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 - static - void - prevent_distorted_boundary_cells (const Triangulation<1,spacedim> &); - - template - static - void - prevent_distorted_boundary_cells (Triangulation &triangulation) - { - for (cell_iterator cell=triangulation.begin(); cell!=triangulation.end(); ++cell) - if (cell->at_boundary() && - cell->refine_flag_set() && - cell->refine_flag_set()!=RefinementCase::isotropic_refinement) - { - // The cell is at the boundary - // and it is flagged for - // anisotropic - // refinement. Therefore, we have - // a closer look - const RefinementCase ref_case=cell->refine_flag_set(); - for (unsigned int face_no=0; - face_no::faces_per_cell; - ++face_no) - if (cell->face(face_no)->at_boundary()) - { - // this is the critical - // face at the boundary. - if (GeometryInfo::face_refinement_case(ref_case,face_no) - !=RefinementCase::isotropic_refinement) + /** + * 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 + static + void + prevent_distorted_boundary_cells (const Triangulation<1,spacedim> &); + + template + static + void + prevent_distorted_boundary_cells (Triangulation &triangulation) + { + for (typename Triangulation::cell_iterator + cell=triangulation.begin(); cell!=triangulation.end(); ++cell) + if (cell->at_boundary() && + cell->refine_flag_set() && + cell->refine_flag_set()!=RefinementCase::isotropic_refinement) + { + // The cell is at the boundary + // and it is flagged for + // anisotropic + // refinement. Therefore, we have + // a closer look + const RefinementCase ref_case=cell->refine_flag_set(); + for (unsigned int face_no=0; + face_no::faces_per_cell; + ++face_no) + if (cell->face(face_no)->at_boundary()) { - // up to now, we do not - // want to refine this - // cell along the face - // under consideration - // here. - const face_iterator face = cell->face(face_no); - // the new point on the - // boundary would be - // this one. - const Point 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 new_unit - = StaticMappingQ1::mapping. - transform_real_to_unit_cell(cell, - new_bound); + // this is the critical + // face at the boundary. + if (GeometryInfo::face_refinement_case(ref_case,face_no) + !=RefinementCase::isotropic_refinement) + { + // up to now, we do not + // want to refine this + // cell along the face + // under consideration + // here. + const typename Triangulation::face_iterator + face = cell->face(face_no); + // the new point on the + // boundary would be + // this one. + const Point 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 new_unit + = StaticMappingQ1::mapping. + transform_real_to_unit_cell(cell, + new_bound); - // Now, we have to - // calculate the - // distance from the - // face in the unit - // cell. + // 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 = fabs(new_unit[face_no/2] - face_no%2); - // compare this with - // the empirical value - // allowed. if it is - // too big, flag the - // cell for isotropic - // refinement - const double allowed=0.25; + // 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 = fabs(new_unit[face_no/2] - face_no%2); + // compare this with + // the empirical value + // allowed. if it is + // too big, flag the + // cell 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 - } + 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 - static - void - prepare_refinement_dim_dependent (const Triangulation &) - { - Assert (dim < 3, - ExcMessage ("Wrong function called -- there should " - "be a specialization.")); - } + /** + * 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 + static + void + prepare_refinement_dim_dependent (const Triangulation &) + { + Assert (dim < 3, + ExcMessage ("Wrong function called -- there should " + "be a specialization.")); + } - template - 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 + template + static + void + prepare_refinement_dim_dependent (Triangulation<3,spacedim> &triangulation) { - mesh_changed = false; + 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 (); + // 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 (cell_iterator cell=triangulation.begin(); cell!=triangulation.end(); ++cell) - if (cell->refine_flag_set()) - { - for (unsigned int line=0; line::lines_per_cell; ++line) - if (GeometryInfo::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()) - { + // flag those lines that are refined and + // will not be coarsened and those that + // will be refined + for (typename Triangulation::cell_iterator + cell=triangulation.begin(); cell!=triangulation.end(); ++cell) + if (cell->refine_flag_set()) + { + for (unsigned int line=0; line::lines_per_cell; ++line) + if (GeometryInfo::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::lines_per_cell; ++line) + if (GeometryInfo::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::active_cell_iterator + cell=triangulation.last_active(); cell!=triangulation.end(); --cell) for (unsigned int line=0; line::lines_per_cell; ++line) - if (GeometryInfo::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 (active_cell_iterator cell=triangulation.last_active(); cell!=triangulation.end(); --cell) - for (unsigned int line=0; line::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) + if (cell->line(line)->has_children()) { - Assert (cell->line(line)->child(c)->has_children() == false, - ExcInternalError()); - - if (cell->line(line)->child(c)->user_flag_set () && - (GeometryInfo::line_refinement_case(cell->refine_flag_set(), - line) - ==RefinementCase<1>::no_refinement)) + // 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) { - // 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 & allow_anisotropic_smoothing) - cell->flag_for_line_refinement(line); - else - cell->set_refine_flag(); + Assert (cell->line(line)->child(c)->has_children() == false, + ExcInternalError()); + + if (cell->line(line)->child(c)->user_flag_set () && + (GeometryInfo::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::allow_anisotropic_smoothing) + cell->flag_for_line_refinement(line); + else + cell->set_refine_flag(); - for (unsigned int l=0; l::lines_per_cell; ++l) - if (GeometryInfo::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; + for (unsigned int l=0; l::lines_per_cell; ++l) + if (GeometryInfo::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::lines_per_cell; ++line) - if (!cell->line(line)->has_children() && - (GeometryInfo::line_refinement_case(cell->refine_flag_set(), - line) - !=RefinementCase<1>::no_refinement)) - cell->line(line)->set_user_flag(); + // 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::lines_per_cell; ++line) + if (!cell->line(line)->has_children() && + (GeometryInfo::line_refinement_case(cell->refine_flag_set(), + line) + !=RefinementCase<1>::no_refinement)) + cell->line(line)->set_user_flag(); - break; + break; + } } - } - if (offending_line_found) - { - mesh_changed = true; - 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 (cell_iterator cell=triangulation.last(); cell!=triangulation.end(); --cell) - { - if (cell->user_flag_set()) - for (unsigned int line=0; line::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; cn_children(); ++c) - cell->child(c)->clear_coarsen_flag (); - cell->clear_user_flag(); - for (unsigned int l=0; l::lines_per_cell; ++l) - if (GeometryInfo::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; - } + // 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::cell_iterator + cell=triangulation.last(); cell!=triangulation.end(); --cell) + { + if (cell->user_flag_set()) + for (unsigned int line=0; line::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; cn_children(); ++c) + cell->child(c)->clear_coarsen_flag (); + cell->clear_user_flag(); + for (unsigned int l=0; l::lines_per_cell; ++l) + if (GeometryInfo::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); } - 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 - static - bool - coarsening_allowed (const 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 ref_case = cell->refinement_case(); - for (unsigned int n=0; n::faces_per_cell; ++n) + /** + * 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 + static + bool + coarsening_allowed (const typename Triangulation::cell_iterator& cell) { - // 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 face_ref_case = - GeometryInfo::face_refinement_case(cell->refinement_case(), n); + // in 1d, coarsening is + // always allowed since we + // don't enforce the 2:1 + // constraint there + if (dim == 1) + return true; + + const RefinementCase ref_case = cell->refinement_case(); + for (unsigned int n=0; n::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 face_ref_case = + GeometryInfo::face_refinement_case(cell->refinement_case(), n); - const unsigned int n_subfaces - = GeometryInfo::n_children(face_ref_case); + const unsigned int n_subfaces + = GeometryInfo::n_children(face_ref_case); - if (n_subfaces == 0 || cell->at_boundary(n)) - continue; - for (unsigned int c=0; cchild(GeometryInfo:: - child_cell_on_face(ref_case, - n,c)); + if (n_subfaces == 0 || cell->at_boundary(n)) + continue; + for (unsigned int c=0; c::cell_iterator + child = cell->child(GeometryInfo:: + child_cell_on_face(ref_case, + n,c)); - const 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; + const typename Triangulation::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; } - return true; - } -}; + }; + } +} template @@ -9593,7 +9859,7 @@ create_triangulation (const std::vector > &v, // it: try { - Implementation::create_triangulation (v, cells, subcelldata, *this); + internal::Triangulation::Implementation::create_triangulation (v, cells, subcelldata, *this); } catch (...) { @@ -9610,7 +9876,7 @@ template void Triangulation::distort_random (const double factor, const bool keep_boundary) { - Implementation::distort_random (factor, keep_boundary, *this); + internal::Triangulation::Implementation::distort_random (factor, keep_boundary, *this); } @@ -12313,7 +12579,7 @@ template void Triangulation::execute_refinement () { - Implementation::execute_refinement (*this); + internal::Triangulation::Implementation::execute_refinement (*this); @@ -12408,7 +12674,7 @@ void Triangulation::execute_coarsening () // use a separate function, // since this is dimension // specific - Implementation::delete_children (*this, cell, + internal::Triangulation::Implementation::delete_children (*this, cell, line_cell_count, quad_cell_count); // re-compute number of lines and @@ -12660,7 +12926,7 @@ void Triangulation::fix_coarsen_flags () if (cell->user_flag_set()) // if allowed: flag the // children for coarsening - if (Implementation::template coarsening_allowed(cell)) + if (internal::Triangulation::Implementation::template coarsening_allowed(cell)) for (unsigned int c=0; cn_children(); ++c) { Assert (cell->child(c)->refine_flag_set()==false, @@ -13629,7 +13895,7 @@ bool Triangulation::prepare_coarsening_and_refinement () // if the cell is refined // anisotropically. we have to check, // whether that can happen - Implementation::prevent_distorted_boundary_cells(*this); + internal::Triangulation::Implementation::prevent_distorted_boundary_cells(*this); ///////////////////////////////// // STEP 6: @@ -14023,7 +14289,7 @@ bool Triangulation::prepare_coarsening_and_refinement () // take care that no double refinement // is done at each line in 3d or higher // dimensions. - Implementation::prepare_refinement_dim_dependent (*this); + internal::Triangulation::Implementation::prepare_refinement_dim_dependent (*this); ////////////////////////////////////// // STEP 8: diff --git a/deal.II/deal.II/source/hp/dof_handler.cc b/deal.II/deal.II/source/hp/dof_handler.cc index f2e80d4e0c..fd47b71073 100644 --- a/deal.II/deal.II/source/hp/dof_handler.cc +++ b/deal.II/deal.II/source/hp/dof_handler.cc @@ -168,1345 +168,1409 @@ namespace internal -namespace hp +namespace internal { + namespace hp + { + namespace DoFHandler + { + // access class + // dealii::hp::DoFHandler instead of + // namespace internal::hp::DoFHandler, etc + using dealii::hp::DoFHandler; /** * A class with the same purpose as the similarly named class of the * Triangulation class. See there for more information. */ - template - struct DoFHandler::Implementation - { - /** - * Do that part of reserving - * space that pertains to - * vertices, since this is the - * same in all space - * dimensions. - */ - template - static - void - reserve_space_vertices (DoFHandler &dof_handler) - { - // The final step is allocating - // memory is to set up vertex dof - // information. since vertices - // are sequentially numbered, - // what we do first is to set up - // an array in which we record - // whether a vertex is associated - // with any of the given fe's, by - // setting a bit. in a later - // step, we then actually - // allocate memory for the - // required dofs - std::vector > - vertex_fe_association (dof_handler.finite_elements->size(), - std::vector (dof_handler.tria->n_vertices(), false)); + struct Implementation + { + /** + * Do that part of reserving + * space that pertains to + * vertices, since this is the + * same in all space + * dimensions. + */ + template + static + void + reserve_space_vertices (DoFHandler &dof_handler) + { + // The final step is allocating + // memory is to set up vertex dof + // information. since vertices + // are sequentially numbered, + // what we do first is to set up + // an array in which we record + // whether a vertex is associated + // with any of the given fe's, by + // setting a bit. in a later + // step, we then actually + // allocate memory for the + // required dofs + std::vector > + vertex_fe_association (dof_handler.finite_elements->size(), + std::vector (dof_handler.tria->n_vertices(), false)); - for (active_cell_iterator cell=dof_handler.begin_active(); cell!=dof_handler.end(); ++cell) - for (unsigned int v=0; v::vertices_per_cell; ++v) - vertex_fe_association[cell->active_fe_index()][cell->vertex_index(v)] - = true; + for (typename DoFHandler::active_cell_iterator + cell=dof_handler.begin_active(); cell!=dof_handler.end(); ++cell) + for (unsigned int v=0; v::vertices_per_cell; ++v) + vertex_fe_association[cell->active_fe_index()][cell->vertex_index(v)] + = true; - // in debug mode, make sure - // that each vertex is - // associated with at least one - // fe (note that except for - // unused vertices, all - // vertices are actually - // active) + // in debug mode, make sure + // that each vertex is + // associated with at least one + // fe (note that except for + // unused vertices, all + // vertices are actually + // active) #ifdef DEBUG - for (unsigned int v=0; vn_vertices(); ++v) - if (dof_handler.tria->vertex_used(v) == true) - { - unsigned int fe=0; - for (; fesize(); ++fe) - if (vertex_fe_association[fe][v] == true) - break; - Assert (fe != dof_handler.finite_elements->size(), ExcInternalError()); - } + for (unsigned int v=0; vn_vertices(); ++v) + if (dof_handler.tria->vertex_used(v) == true) + { + unsigned int fe=0; + for (; fesize(); ++fe) + if (vertex_fe_association[fe][v] == true) + break; + Assert (fe != dof_handler.finite_elements->size(), ExcInternalError()); + } #endif - // next count how much memory - // we actually need. for each - // vertex, we need one slot per - // fe to store the fe_index, - // plus dofs_per_vertex for - // this fe. in addition, we - // need one slot as the end - // marker for the - // fe_indices. at the same time - // already fill the - // vertex_dofs_offsets field - dof_handler.vertex_dofs_offsets.resize (dof_handler.tria->n_vertices(), - numbers::invalid_unsigned_int); + // next count how much memory + // we actually need. for each + // vertex, we need one slot per + // fe to store the fe_index, + // plus dofs_per_vertex for + // this fe. in addition, we + // need one slot as the end + // marker for the + // fe_indices. at the same time + // already fill the + // vertex_dofs_offsets field + dof_handler.vertex_dofs_offsets.resize (dof_handler.tria->n_vertices(), + numbers::invalid_unsigned_int); - unsigned int vertex_slots_needed = 0; - for (unsigned int v=0; vn_vertices(); ++v) - if (dof_handler.tria->vertex_used(v) == true) - { - dof_handler.vertex_dofs_offsets[v] = vertex_slots_needed; + unsigned int vertex_slots_needed = 0; + for (unsigned int v=0; vn_vertices(); ++v) + if (dof_handler.tria->vertex_used(v) == true) + { + dof_handler.vertex_dofs_offsets[v] = vertex_slots_needed; - for (unsigned int fe=0; fesize(); ++fe) - if (vertex_fe_association[fe][v] == true) - vertex_slots_needed += (*dof_handler.finite_elements)[fe].dofs_per_vertex + 1; - ++vertex_slots_needed; - } + for (unsigned int fe=0; fesize(); ++fe) + if (vertex_fe_association[fe][v] == true) + vertex_slots_needed += (*dof_handler.finite_elements)[fe].dofs_per_vertex + 1; + ++vertex_slots_needed; + } - // now allocate the space we - // have determined we need, and - // set up the linked lists for - // each of the vertices - dof_handler.vertex_dofs.resize (vertex_slots_needed, invalid_dof_index); - for (unsigned int v=0; vn_vertices(); ++v) - if (dof_handler.tria->vertex_used(v) == true) - { - unsigned int pointer = dof_handler.vertex_dofs_offsets[v]; - for (unsigned int fe=0; fesize(); ++fe) - if (vertex_fe_association[fe][v] == true) - { - // if this vertex - // uses this fe, - // then set the - // fe_index and - // move the pointer - // ahead - dof_handler.vertex_dofs[pointer] = fe; - pointer += (*dof_handler.finite_elements)[fe].dofs_per_vertex + 1; - } - // finally place the end - // marker - dof_handler.vertex_dofs[pointer] = numbers::invalid_unsigned_int; - } - } + // now allocate the space we + // have determined we need, and + // set up the linked lists for + // each of the vertices + dof_handler.vertex_dofs.resize (vertex_slots_needed, + DoFHandler::invalid_dof_index); + for (unsigned int v=0; vn_vertices(); ++v) + if (dof_handler.tria->vertex_used(v) == true) + { + unsigned int pointer = dof_handler.vertex_dofs_offsets[v]; + for (unsigned int fe=0; fesize(); ++fe) + if (vertex_fe_association[fe][v] == true) + { + // if this vertex + // uses this fe, + // then set the + // fe_index and + // move the pointer + // ahead + dof_handler.vertex_dofs[pointer] = fe; + pointer += (*dof_handler.finite_elements)[fe].dofs_per_vertex + 1; + } + // finally place the end + // marker + dof_handler.vertex_dofs[pointer] = numbers::invalid_unsigned_int; + } + } - /** - * Distribute dofs on the given cell, - * with new dofs starting with index - * @p next_free_dof. Return the next - * unused index number. The finite - * element used is the one given to - * @p distribute_dofs, which is copied - * to @p selected_fe. - * - * This function is excluded from the - * @p distribute_dofs function since - * it can not be implemented dimension - * independent. - */ - template - static - unsigned int - distribute_dofs_on_cell (const typename DoFHandler<1,spacedim>::active_cell_iterator &cell, - unsigned int next_free_dof) - { - const FiniteElement<1> &fe = cell->get_fe(); - const unsigned int fe_index = cell->active_fe_index (); + /** + * Distribute dofs on the given cell, + * with new dofs starting with index + * @p next_free_dof. Return the next + * unused index number. The finite + * element used is the one given to + * @p distribute_dofs, which is copied + * to @p selected_fe. + * + * This function is excluded from the + * @p distribute_dofs function since + * it can not be implemented dimension + * independent. + */ + template + static + unsigned int + distribute_dofs_on_cell (const typename DoFHandler<1,spacedim>::active_cell_iterator &cell, + unsigned int next_free_dof) + { + const unsigned int dim = 1; + + const FiniteElement<1> &fe = cell->get_fe(); + const unsigned int fe_index = cell->active_fe_index (); - // number dofs on vertices. to do - // so, check whether dofs for - // this vertex have been - // distributed and for the - // present fe (only check the - // first dof), and if this isn't - // the case distribute new ones - // there - if (fe.dofs_per_vertex > 0) - for (unsigned int vertex=0; vertex::vertices_per_cell; ++vertex) - if (cell->vertex_dof_index(vertex, 0, fe_index) == invalid_dof_index) - for (unsigned int d=0; dset_vertex_dof_index (vertex, d, next_free_dof, fe_index); + // number dofs on vertices. to do + // so, check whether dofs for + // this vertex have been + // distributed and for the + // present fe (only check the + // first dof), and if this isn't + // the case distribute new ones + // there + if (fe.dofs_per_vertex > 0) + for (unsigned int vertex=0; vertex::vertices_per_cell; ++vertex) + if (cell->vertex_dof_index(vertex, 0, fe_index) == + DoFHandler::invalid_dof_index) + for (unsigned int d=0; dset_vertex_dof_index (vertex, d, next_free_dof, fe_index); - // finally for the line. this one - // shouldn't be numbered yet - if (fe.dofs_per_line > 0) - { - Assert (cell->dof_index(0, fe_index) == invalid_dof_index, - ExcInternalError()); + // finally for the line. this one + // shouldn't be numbered yet + if (fe.dofs_per_line > 0) + { + Assert ((cell->dof_index(0, fe_index) == + DoFHandler::invalid_dof_index), + ExcInternalError()); - for (unsigned int d=0; dset_dof_index (d, next_free_dof, fe_index); - } + for (unsigned int d=0; dset_dof_index (d, next_free_dof, fe_index); + } - // note that this cell has been processed - cell->set_user_flag (); + // note that this cell has been processed + cell->set_user_flag (); - return next_free_dof; - } + return next_free_dof; + } - template - static - unsigned int - distribute_dofs_on_cell (const typename DoFHandler<2,spacedim>::active_cell_iterator &cell, - unsigned int next_free_dof) - { - const FiniteElement<2> &fe = cell->get_fe(); - const unsigned int fe_index = cell->active_fe_index (); + template + static + unsigned int + distribute_dofs_on_cell (const typename DoFHandler<2,spacedim>::active_cell_iterator &cell, + unsigned int next_free_dof) + { + const unsigned int dim = 2; + + const FiniteElement<2> &fe = cell->get_fe(); + const unsigned int fe_index = cell->active_fe_index (); - // number dofs on vertices. to do - // so, check whether dofs for - // this vertex have been - // distributed and for the - // present fe (only check the - // first dof), and if this isn't - // the case distribute new ones - // there - if (fe.dofs_per_vertex > 0) - for (unsigned int vertex=0; vertex::vertices_per_cell; ++vertex) - if (cell->vertex_dof_index(vertex, 0, fe_index) == invalid_dof_index) - for (unsigned int d=0; dset_vertex_dof_index (vertex, d, next_free_dof, fe_index); + // number dofs on vertices. to do + // so, check whether dofs for + // this vertex have been + // distributed and for the + // present fe (only check the + // first dof), and if this isn't + // the case distribute new ones + // there + if (fe.dofs_per_vertex > 0) + for (unsigned int vertex=0; vertex::vertices_per_cell; ++vertex) + if (cell->vertex_dof_index(vertex, 0, fe_index) == + DoFHandler::invalid_dof_index) + for (unsigned int d=0; dset_vertex_dof_index (vertex, d, next_free_dof, fe_index); - // next the sides. do the - // same as above: check whether - // the line is already numbered - // for the present fe_index, and - // if not do it - if (fe.dofs_per_line > 0) - for (unsigned int l=0; l::lines_per_cell; ++l) - { - line_iterator line = cell->line(l); + // next the sides. do the + // same as above: check whether + // the line is already numbered + // for the present fe_index, and + // if not do it + if (fe.dofs_per_line > 0) + for (unsigned int l=0; l::lines_per_cell; ++l) + { + typename DoFHandler::line_iterator + line = cell->line(l); - if (line->dof_index(0,fe_index) == invalid_dof_index) - for (unsigned int d=0; dset_dof_index (d, next_free_dof, fe_index); - } + if (line->dof_index(0,fe_index) == + DoFHandler::invalid_dof_index) + for (unsigned int d=0; dset_dof_index (d, next_free_dof, fe_index); + } - // finally for the quad. this one - // shouldn't be numbered yet - if (fe.dofs_per_quad > 0) - { - Assert (cell->dof_index(0, fe_index) == invalid_dof_index, - ExcInternalError()); + // finally for the quad. this one + // shouldn't be numbered yet + if (fe.dofs_per_quad > 0) + { + Assert ((cell->dof_index(0, fe_index) == + DoFHandler::invalid_dof_index), + ExcInternalError()); - for (unsigned int d=0; dset_dof_index (d, next_free_dof, fe_index); - } + for (unsigned int d=0; dset_dof_index (d, next_free_dof, fe_index); + } - // note that this cell has been processed - cell->set_user_flag (); + // note that this cell has been processed + cell->set_user_flag (); - return next_free_dof; - } + return next_free_dof; + } - template - static - unsigned int - distribute_dofs_on_cell (const typename DoFHandler<3,spacedim>::active_cell_iterator &cell, - unsigned int next_free_dof) - { - const FiniteElement<3> &fe = cell->get_fe(); - const unsigned int fe_index = cell->active_fe_index (); + template + static + unsigned int + distribute_dofs_on_cell (const typename DoFHandler<3,spacedim>::active_cell_iterator &cell, + unsigned int next_free_dof) + { + const unsigned int dim = 3; + + const FiniteElement<3> &fe = cell->get_fe(); + const unsigned int fe_index = cell->active_fe_index (); - // number dofs on vertices. to do - // so, check whether dofs for - // this vertex have been - // distributed and for the - // present fe (only check the - // first dof), and if this isn't - // the case distribute new ones - // there - if (fe.dofs_per_vertex > 0) - for (unsigned int vertex=0; vertex::vertices_per_cell; ++vertex) - if (cell->vertex_dof_index(vertex, 0, fe_index) == invalid_dof_index) - for (unsigned int d=0; dset_vertex_dof_index (vertex, d, next_free_dof, fe_index); + // number dofs on vertices. to do + // so, check whether dofs for + // this vertex have been + // distributed and for the + // present fe (only check the + // first dof), and if this isn't + // the case distribute new ones + // there + if (fe.dofs_per_vertex > 0) + for (unsigned int vertex=0; vertex::vertices_per_cell; ++vertex) + if (cell->vertex_dof_index(vertex, 0, fe_index) == + DoFHandler::invalid_dof_index) + for (unsigned int d=0; dset_vertex_dof_index (vertex, d, next_free_dof, fe_index); - // next the four lines. do the - // same as above: check whether - // the line is already numbered - // for the present fe_index, and - // if not do it - if (fe.dofs_per_line > 0) - for (unsigned int l=0; l::lines_per_cell; ++l) - { - line_iterator line = cell->line(l); + // next the four lines. do the + // same as above: check whether + // the line is already numbered + // for the present fe_index, and + // if not do it + if (fe.dofs_per_line > 0) + for (unsigned int l=0; l::lines_per_cell; ++l) + { + typename DoFHandler::line_iterator + line = cell->line(l); - if (line->dof_index(0,fe_index) == invalid_dof_index) - for (unsigned int d=0; dset_dof_index (d, next_free_dof, fe_index); - } + if (line->dof_index(0,fe_index) == + DoFHandler::invalid_dof_index) + for (unsigned int d=0; dset_dof_index (d, next_free_dof, fe_index); + } - // same for quads - if (fe.dofs_per_quad > 0) - for (unsigned int q=0; q::quads_per_cell; ++q) - { - quad_iterator quad = cell->quad(q); + // same for quads + if (fe.dofs_per_quad > 0) + for (unsigned int q=0; q::quads_per_cell; ++q) + { + typename DoFHandler::quad_iterator + quad = cell->quad(q); - if (quad->dof_index(0,fe_index) == invalid_dof_index) - for (unsigned int d=0; dset_dof_index (d, next_free_dof, fe_index); - } + if (quad->dof_index(0,fe_index) == + DoFHandler::invalid_dof_index) + for (unsigned int d=0; dset_dof_index (d, next_free_dof, fe_index); + } - // finally for the hex. this one - // shouldn't be numbered yet - if (fe.dofs_per_hex > 0) - { - Assert (cell->dof_index(0, fe_index) == invalid_dof_index, - ExcInternalError()); + // finally for the hex. this one + // shouldn't be numbered yet + if (fe.dofs_per_hex > 0) + { + Assert ((cell->dof_index(0, fe_index) == + DoFHandler::invalid_dof_index), + ExcInternalError()); - for (unsigned int d=0; dset_dof_index (d, next_free_dof, fe_index); - } + for (unsigned int d=0; dset_dof_index (d, next_free_dof, fe_index); + } - // note that this cell has been processed - cell->set_user_flag (); + // note that this cell has been processed + cell->set_user_flag (); - return next_free_dof; - } + return next_free_dof; + } - /** - * Reserve enough space in the - * levels[] objects to store the - * numbers of the degrees of freedom - * needed for the given element. The - * given element is that one which - * was selected when calling - * @p distribute_dofs the last time. - */ - template - static - void - reserve_space (DoFHandler<1,spacedim> &dof_handler) - { - const unsigned int dim = 1; - - Assert (dof_handler.finite_elements != 0, ExcNoFESelected()); - Assert (dof_handler.finite_elements->size() > 0, ExcNoFESelected()); - Assert (dof_handler.tria->n_levels() > 0, ExcInvalidTriangulation()); - Assert (dof_handler.tria->n_levels() == dof_handler.levels.size (), - ExcInternalError ()); - - // Release all space except the - // active_fe_indices field which - // we have to backup before - { - std::vector > - active_fe_backup(dof_handler.levels.size ()); - for (unsigned int level = 0; levelactive_fe_indices, active_fe_backup[level]); - - // delete all levels and set them up - // newly, since vectors are - // troublesome if you want to change - // their size - dof_handler.clear_space (); - - for (unsigned int level=0; leveln_levels(); ++level) + /** + * Reserve enough space in the + * levels[] objects to store the + * numbers of the degrees of freedom + * needed for the given element. The + * given element is that one which + * was selected when calling + * @p distribute_dofs the last time. + */ + template + static + void + reserve_space (DoFHandler<1,spacedim> &dof_handler) + { + const unsigned int dim = 1; + + typedef DoFHandler BaseClass; + + Assert (dof_handler.finite_elements != 0, + typename BaseClass::ExcNoFESelected()); + Assert (dof_handler.finite_elements->size() > 0, + typename BaseClass::ExcNoFESelected()); + Assert (dof_handler.tria->n_levels() > 0, + typename + BaseClass::ExcInvalidTriangulation()); + Assert (dof_handler.tria->n_levels() == dof_handler.levels.size (), + ExcInternalError ()); + + // Release all space except the + // active_fe_indices field which + // we have to backup before { - dof_handler.levels.push_back (new internal::hp::DoFLevel); - std::swap (active_fe_backup[level], - dof_handler.levels[level]->active_fe_indices); + std::vector > + active_fe_backup(dof_handler.levels.size ()); + for (unsigned int level = 0; levelactive_fe_indices, active_fe_backup[level]); + + // delete all levels and set them up + // newly, since vectors are + // troublesome if you want to change + // their size + dof_handler.clear_space (); + + for (unsigned int level=0; leveln_levels(); ++level) + { + dof_handler.levels.push_back (new internal::hp::DoFLevel); + std::swap (active_fe_backup[level], + dof_handler.levels[level]->active_fe_indices); + } } - } - // LINE (CELL) DOFs + // LINE (CELL) DOFs - // count how much space we need - // on each level for the cell - // dofs and set the - // dof_*_offsets - // data. initially set the latter - // to an invalid index, and only - // later set it to something - // reasonable for active dof_handler.cells - // - // note that for dof_handler.cells, the - // situation is simpler than for - // other (lower dimensional) - // objects since exactly one - // finite element is used for it - for (unsigned int level=0; leveln_levels(); ++level) - { - dof_handler.levels[level]->lines.dof_offsets - = std::vector (dof_handler.tria->n_raw_lines(level), - invalid_dof_index); - - unsigned int next_free_dof = 0; - for (active_cell_iterator cell=dof_handler.begin_active(level); - cell!=dof_handler.end_active(level); ++cell) - if (!cell->has_children()) - { - dof_handler.levels[level]->lines.dof_offsets[cell->index()] = next_free_dof; - next_free_dof += cell->get_fe().dofs_per_line; - } + // count how much space we need + // on each level for the cell + // dofs and set the + // dof_*_offsets + // data. initially set the latter + // to an invalid index, and only + // later set it to something + // reasonable for active dof_handler.cells + // + // note that for dof_handler.cells, the + // situation is simpler than for + // other (lower dimensional) + // objects since exactly one + // finite element is used for it + for (unsigned int level=0; leveln_levels(); ++level) + { + dof_handler.levels[level]->lines.dof_offsets + = std::vector (dof_handler.tria->n_raw_lines(level), + DoFHandler::invalid_dof_index); + + unsigned int next_free_dof = 0; + for (typename DoFHandler::active_cell_iterator + cell=dof_handler.begin_active(level); + cell!=dof_handler.end_active(level); ++cell) + if (!cell->has_children()) + { + dof_handler.levels[level]->lines.dof_offsets[cell->index()] = next_free_dof; + next_free_dof += cell->get_fe().dofs_per_line; + } - dof_handler.levels[level]->lines.dofs - = std::vector (next_free_dof, invalid_dof_index); - } + dof_handler.levels[level]->lines.dofs + = std::vector (next_free_dof, + DoFHandler::invalid_dof_index); + } - // safety check: make sure that - // the number of DoFs we - // allocated is actually correct - // (above we have also set the - // dof_*_offsets field, so - // we couldn't use this simpler - // algorithm) + // safety check: make sure that + // the number of DoFs we + // allocated is actually correct + // (above we have also set the + // dof_*_offsets field, so + // we couldn't use this simpler + // algorithm) #ifdef DEBUG - for (unsigned int level=0; leveln_levels(); ++level) - { - unsigned int counter = 0; - for (cell_iterator cell=dof_handler.begin_active(level); - cell!=dof_handler.end_active(level); ++cell) - if (!cell->has_children()) - counter += cell->get_fe().dofs_per_line; + for (unsigned int level=0; leveln_levels(); ++level) + { + unsigned int counter = 0; + for (typename DoFHandler::cell_iterator + cell=dof_handler.begin_active(level); + cell!=dof_handler.end_active(level); ++cell) + if (!cell->has_children()) + counter += cell->get_fe().dofs_per_line; - Assert (dof_handler.levels[level]->lines.dofs.size() == counter, - ExcInternalError()); - Assert (static_cast - (std::count (dof_handler.levels[level]->lines.dof_offsets.begin(), - dof_handler.levels[level]->lines.dof_offsets.end(), - invalid_dof_index)) - == - dof_handler.tria->n_raw_lines(level) - dof_handler.tria->n_active_lines(level), - ExcInternalError()); - } + Assert (dof_handler.levels[level]->lines.dofs.size() == counter, + ExcInternalError()); + Assert (static_cast + (std::count (dof_handler.levels[level]->lines.dof_offsets.begin(), + dof_handler.levels[level]->lines.dof_offsets.end(), + DoFHandler::invalid_dof_index)) + == + dof_handler.tria->n_raw_lines(level) - dof_handler.tria->n_active_lines(level), + ExcInternalError()); + } #endif - // VERTEX DOFS - reserve_space_vertices (dof_handler); - } + // VERTEX DOFS + reserve_space_vertices (dof_handler); + } - template - static - void - reserve_space (DoFHandler<2,spacedim> &dof_handler) - { - const unsigned int dim = 2; - - Assert (dof_handler.finite_elements != 0, ExcNoFESelected()); - Assert (dof_handler.finite_elements->size() > 0, ExcNoFESelected()); - Assert (dof_handler.tria->n_levels() > 0, ExcInvalidTriangulation()); - Assert (dof_handler.tria->n_levels() == dof_handler.levels.size (), - ExcInternalError ()); - - // Release all space except the - // active_fe_indices field which - // we have to backup before - { - std::vector > - active_fe_backup(dof_handler.levels.size ()); - for (unsigned int level = 0; levelactive_fe_indices, - active_fe_backup[level]); - - // delete all levels and set them up - // newly, since vectors are - // troublesome if you want to change - // their size - dof_handler.clear_space (); - - for (unsigned int level=0; leveln_levels(); ++level) + template + static + void + reserve_space (DoFHandler<2,spacedim> &dof_handler) + { + const unsigned int dim = 2; + + typedef DoFHandler BaseClass; + + Assert (dof_handler.finite_elements != 0, + typename BaseClass::ExcNoFESelected()); + Assert (dof_handler.finite_elements->size() > 0, + typename BaseClass::ExcNoFESelected()); + Assert (dof_handler.tria->n_levels() > 0, + typename BaseClass::ExcInvalidTriangulation()); + Assert (dof_handler.tria->n_levels() == dof_handler.levels.size (), + ExcInternalError ()); + + // Release all space except the + // active_fe_indices field which + // we have to backup before { - dof_handler.levels.push_back (new internal::hp::DoFLevel); - std::swap (active_fe_backup[level], - dof_handler.levels[level]->active_fe_indices); + std::vector > + active_fe_backup(dof_handler.levels.size ()); + for (unsigned int level = 0; levelactive_fe_indices, + active_fe_backup[level]); + + // delete all levels and set them up + // newly, since vectors are + // troublesome if you want to change + // their size + dof_handler.clear_space (); + + for (unsigned int level=0; leveln_levels(); ++level) + { + dof_handler.levels.push_back (new internal::hp::DoFLevel); + std::swap (active_fe_backup[level], + dof_handler.levels[level]->active_fe_indices); + } + dof_handler.faces = new internal::hp::DoFFaces<2>; } - dof_handler.faces = new internal::hp::DoFFaces<2>; - } - // QUAD (CELL) DOFs + // QUAD (CELL) DOFs - // count how much space we need - // on each level for the cell - // dofs and set the - // dof_*_offsets - // data. initially set the latter - // to an invalid index, and only - // later set it to something - // reasonable for active dof_handler.cells - // - // note that for dof_handler.cells, the - // situation is simpler than for - // other (lower dimensional) - // objects since exactly one - // finite element is used for it - for (unsigned int level=0; leveln_levels(); ++level) - { - dof_handler.levels[level]->quads.dof_offsets - = std::vector (dof_handler.tria->n_raw_quads(level), - invalid_dof_index); - - unsigned int next_free_dof = 0; - for (active_cell_iterator cell=dof_handler.begin_active(level); - cell!=dof_handler.end_active(level); ++cell) - if (!cell->has_children()) - { - dof_handler.levels[level]->quads.dof_offsets[cell->index()] = next_free_dof; - next_free_dof += cell->get_fe().dofs_per_quad; - } + // count how much space we need + // on each level for the cell + // dofs and set the + // dof_*_offsets + // data. initially set the latter + // to an invalid index, and only + // later set it to something + // reasonable for active dof_handler.cells + // + // note that for dof_handler.cells, the + // situation is simpler than for + // other (lower dimensional) + // objects since exactly one + // finite element is used for it + for (unsigned int level=0; leveln_levels(); ++level) + { + dof_handler.levels[level]->quads.dof_offsets + = std::vector (dof_handler.tria->n_raw_quads(level), + DoFHandler::invalid_dof_index); + + unsigned int next_free_dof = 0; + for (typename DoFHandler::active_cell_iterator + cell=dof_handler.begin_active(level); + cell!=dof_handler.end_active(level); ++cell) + if (!cell->has_children()) + { + dof_handler.levels[level]->quads.dof_offsets[cell->index()] = next_free_dof; + next_free_dof += cell->get_fe().dofs_per_quad; + } - dof_handler.levels[level]->quads.dofs - = std::vector (next_free_dof, invalid_dof_index); - } + dof_handler.levels[level]->quads.dofs + = std::vector (next_free_dof, + DoFHandler::invalid_dof_index); + } - // safety check: make sure that - // the number of DoFs we - // allocated is actually correct - // (above we have also set the - // dof_*_offsets field, so - // we couldn't use this simpler - // algorithm) + // safety check: make sure that + // the number of DoFs we + // allocated is actually correct + // (above we have also set the + // dof_*_offsets field, so + // we couldn't use this simpler + // algorithm) #ifdef DEBUG - for (unsigned int level=0; leveln_levels(); ++level) - { - unsigned int counter = 0; - for (cell_iterator cell=dof_handler.begin_active(level); - cell!=dof_handler.end_active(level); ++cell) - if (!cell->has_children()) - counter += cell->get_fe().dofs_per_quad; + for (unsigned int level=0; leveln_levels(); ++level) + { + unsigned int counter = 0; + for (typename DoFHandler::cell_iterator + cell=dof_handler.begin_active(level); + cell!=dof_handler.end_active(level); ++cell) + if (!cell->has_children()) + counter += cell->get_fe().dofs_per_quad; - Assert (dof_handler.levels[level]->quads.dofs.size() == counter, - ExcInternalError()); - Assert (static_cast - (std::count (dof_handler.levels[level]->quads.dof_offsets.begin(), - dof_handler.levels[level]->quads.dof_offsets.end(), - invalid_dof_index)) - == - dof_handler.tria->n_raw_quads(level) - dof_handler.tria->n_active_quads(level), - ExcInternalError()); - } + Assert (dof_handler.levels[level]->quads.dofs.size() == counter, + ExcInternalError()); + Assert (static_cast + (std::count (dof_handler.levels[level]->quads.dof_offsets.begin(), + dof_handler.levels[level]->quads.dof_offsets.end(), + DoFHandler::invalid_dof_index)) + == + dof_handler.tria->n_raw_quads(level) - dof_handler.tria->n_active_quads(level), + ExcInternalError()); + } #endif - // LINE DOFS - // - // same here: count line dofs, - // then allocate as much space as - // we need and prime the linked - // list for lines (see the - // description in hp::DoFLevels) - // with the indices we will - // need. note that our task is - // more complicated since two - // adjacent dof_handler.cells may have - // different active_fe_indices, - // in which case we need to - // allocate *two* sets of line - // dofs for the same line - // - // the way we do things is that - // we loop over all active dof_handler.cells - // (these are the ones that have - // DoFs only anyway) and all - // their dof_handler.faces. We note in the - // user flags whether we have - // previously visited a face and - // if so skip it (consequently, - // we have to save and later - // restore the line flags) - { - std::vector saved_line_user_flags; - const_cast&>(*dof_handler.tria) - .save_user_flags_line (saved_line_user_flags); - const_cast&>(*dof_handler.tria).clear_user_flags_line (); - - // an array to hold how many - // slots (see the hp::DoFLevel - // class) we will have to store - // on each level - unsigned int n_line_slots = 0; + // LINE DOFS + // + // same here: count line dofs, + // then allocate as much space as + // we need and prime the linked + // list for lines (see the + // description in hp::DoFLevels) + // with the indices we will + // need. note that our task is + // more complicated since two + // adjacent dof_handler.cells may have + // different active_fe_indices, + // in which case we need to + // allocate *two* sets of line + // dofs for the same line + // + // the way we do things is that + // we loop over all active dof_handler.cells + // (these are the ones that have + // DoFs only anyway) and all + // their dof_handler.faces. We note in the + // user flags whether we have + // previously visited a face and + // if so skip it (consequently, + // we have to save and later + // restore the line flags) + { + std::vector saved_line_user_flags; + const_cast&>(*dof_handler.tria) + .save_user_flags_line (saved_line_user_flags); + const_cast&>(*dof_handler.tria) + .clear_user_flags_line (); + + // an array to hold how many + // slots (see the hp::DoFLevel + // class) we will have to store + // on each level + unsigned int n_line_slots = 0; - for (active_cell_iterator cell=dof_handler.begin_active(); cell!=dof_handler.end(); ++cell) - for (unsigned int face=0; face::faces_per_cell; ++face) - if (! cell->face(face)->user_flag_set()) - { - // ok, face has not been - // visited. so we need to - // allocate space for it. let's - // see how much we need: we need - // one set if a) there is no - // neighbor behind this face, or - // b) the neighbor is either - // coarser or finer than we are, - // or c) the neighbor is neither - // coarser nor finer, but has - // happens to have the same - // active_fe_index: - if (cell->at_boundary(face) - || - cell->face(face)->has_children() - || - cell->neighbor_is_coarser(face) - || - (!cell->at_boundary(face) - && - (cell->active_fe_index() == cell->neighbor(face)->active_fe_index()))) - // ok, one set of - // dofs. that makes - // one index, 1 times - // dofs_per_line - // dofs, and one stop - // index - n_line_slots - += (*dof_handler.finite_elements)[cell->active_fe_index()].dofs_per_line + 2; - - // otherwise we do - // indeed need two - // sets, i.e. two - // indices, two sets of - // dofs, and one stop - // index: - else - n_line_slots - += ((*dof_handler.finite_elements)[cell->active_fe_index()].dofs_per_line - + - (*dof_handler.finite_elements)[cell->neighbor(face)->active_fe_index()] - .dofs_per_line - + - 3); + for (typename DoFHandler::active_cell_iterator + cell=dof_handler.begin_active(); cell!=dof_handler.end(); ++cell) + for (unsigned int face=0; face::faces_per_cell; ++face) + if (! cell->face(face)->user_flag_set()) + { + // ok, face has not been + // visited. so we need to + // allocate space for it. let's + // see how much we need: we need + // one set if a) there is no + // neighbor behind this face, or + // b) the neighbor is either + // coarser or finer than we are, + // or c) the neighbor is neither + // coarser nor finer, but has + // happens to have the same + // active_fe_index: + if (cell->at_boundary(face) + || + cell->face(face)->has_children() + || + cell->neighbor_is_coarser(face) + || + (!cell->at_boundary(face) + && + (cell->active_fe_index() == cell->neighbor(face)->active_fe_index()))) + // ok, one set of + // dofs. that makes + // one index, 1 times + // dofs_per_line + // dofs, and one stop + // index + n_line_slots + += (*dof_handler.finite_elements)[cell->active_fe_index()].dofs_per_line + 2; + + // otherwise we do + // indeed need two + // sets, i.e. two + // indices, two sets of + // dofs, and one stop + // index: + else + n_line_slots + += ((*dof_handler.finite_elements)[cell->active_fe_index()].dofs_per_line + + + (*dof_handler.finite_elements)[cell->neighbor(face)->active_fe_index()] + .dofs_per_line + + + 3); - // mark this face as - // visited - cell->face(face)->set_user_flag (); - } + // mark this face as + // visited + cell->face(face)->set_user_flag (); + } - // now that we know how many - // line dofs we will have to - // have on each level, allocate - // the memory. note that we - // allocate offsets for all - // lines, though only the - // active ones will have a - // non-invalid value later on - dof_handler.faces->lines.dof_offsets - = std::vector (dof_handler.tria->n_raw_lines(), - invalid_dof_index); - dof_handler.faces->lines.dofs - = std::vector (n_line_slots, - invalid_dof_index); + // now that we know how many + // line dofs we will have to + // have on each level, allocate + // the memory. note that we + // allocate offsets for all + // lines, though only the + // active ones will have a + // non-invalid value later on + dof_handler.faces->lines.dof_offsets + = std::vector (dof_handler.tria->n_raw_lines(), + DoFHandler::invalid_dof_index); + dof_handler.faces->lines.dofs + = std::vector (n_line_slots, + DoFHandler::invalid_dof_index); - // with the memory now - // allocated, loop over the - // dof_handler.cells again and prime the - // _offset values as well as - // the fe_index fields - const_cast&>(*dof_handler.tria).clear_user_flags_line (); - - unsigned int next_free_line_slot = 0; + // with the memory now + // allocated, loop over the + // dof_handler.cells again and prime the + // _offset values as well as + // the fe_index fields + const_cast&>(*dof_handler.tria) + .clear_user_flags_line (); + + unsigned int next_free_line_slot = 0; - for (active_cell_iterator cell=dof_handler.begin_active(); cell!=dof_handler.end(); ++cell) - for (unsigned int face=0; face::faces_per_cell; ++face) - if (! cell->face(face)->user_flag_set()) - { - // same decision tree - // as before - if (cell->at_boundary(face) - || - cell->face(face)->has_children() - || - cell->neighbor_is_coarser(face) - || - (!cell->at_boundary(face) - && - (cell->active_fe_index() == cell->neighbor(face)->active_fe_index()))) + for (typename DoFHandler::active_cell_iterator + cell=dof_handler.begin_active(); cell!=dof_handler.end(); ++cell) + for (unsigned int face=0; face::faces_per_cell; ++face) + if (! cell->face(face)->user_flag_set()) { - dof_handler.faces - ->lines.dof_offsets[cell->face(face)->index()] - = next_free_line_slot; - - // set first slot - // for this line to - // active_fe_index - // of this face - dof_handler.faces - ->lines.dofs[next_free_line_slot] - = cell->active_fe_index(); - - // the next - // dofs_per_line - // indices remain - // unset for the - // moment (i.e. at - // invalid_dof_index). - // following this - // comes the stop - // index, which - // also is - // invalid_dof_index - // and therefore - // does not have to - // be explicitly - // set + // same decision tree + // as before + if (cell->at_boundary(face) + || + cell->face(face)->has_children() + || + cell->neighbor_is_coarser(face) + || + (!cell->at_boundary(face) + && + (cell->active_fe_index() == cell->neighbor(face)->active_fe_index()))) + { + dof_handler.faces + ->lines.dof_offsets[cell->face(face)->index()] + = next_free_line_slot; + + // set first slot + // for this line to + // active_fe_index + // of this face + dof_handler.faces + ->lines.dofs[next_free_line_slot] + = cell->active_fe_index(); + + // the next + // dofs_per_line + // indices remain + // unset for the + // moment (i.e. at + // invalid_dof_index). + // following this + // comes the stop + // index, which + // also is + // invalid_dof_index + // and therefore + // does not have to + // be explicitly + // set - // finally, mark - // those slots as - // used - next_free_line_slot - += (*dof_handler.finite_elements)[cell->active_fe_index()].dofs_per_line + 2; - } - else - { - dof_handler.faces - ->lines.dof_offsets[cell->face(face)->index()] - = next_free_line_slot; - - // set first slot - // for this line to - // active_fe_index - // of this face - dof_handler.faces - ->lines.dofs[next_free_line_slot] - = cell->active_fe_index(); - - // the next - // dofs_per_line - // indices remain - // unset for the - // moment (i.e. at - // invalid_dof_index). - // - // then comes the - // fe_index for the - // neighboring - // cell: - dof_handler.faces - ->lines.dofs[next_free_line_slot - + - (*dof_handler.finite_elements)[cell->active_fe_index()].dofs_per_line - + - 1] - = cell->neighbor(face)->active_fe_index(); - // then again a set - // of dofs that we - // need not set - // right now - // - // following this - // comes the stop - // index, which - // also is - // invalid_dof_index - // and therefore - // does not have to - // be explicitly - // set + // finally, mark + // those slots as + // used + next_free_line_slot + += (*dof_handler.finite_elements)[cell->active_fe_index()].dofs_per_line + 2; + } + else + { + dof_handler.faces + ->lines.dof_offsets[cell->face(face)->index()] + = next_free_line_slot; + + // set first slot + // for this line to + // active_fe_index + // of this face + dof_handler.faces + ->lines.dofs[next_free_line_slot] + = cell->active_fe_index(); + + // the next + // dofs_per_line + // indices remain + // unset for the + // moment (i.e. at + // invalid_dof_index). + // + // then comes the + // fe_index for the + // neighboring + // cell: + dof_handler.faces + ->lines.dofs[next_free_line_slot + + + (*dof_handler.finite_elements)[cell->active_fe_index()].dofs_per_line + + + 1] + = cell->neighbor(face)->active_fe_index(); + // then again a set + // of dofs that we + // need not set + // right now + // + // following this + // comes the stop + // index, which + // also is + // invalid_dof_index + // and therefore + // does not have to + // be explicitly + // set - // finally, mark - // those slots as - // used - next_free_line_slot - += ((*dof_handler.finite_elements)[cell->active_fe_index()].dofs_per_line - + - (*dof_handler.finite_elements)[cell->neighbor(face)->active_fe_index()] - .dofs_per_line - + - 3); - } + // finally, mark + // those slots as + // used + next_free_line_slot + += ((*dof_handler.finite_elements)[cell->active_fe_index()].dofs_per_line + + + (*dof_handler.finite_elements)[cell->neighbor(face)->active_fe_index()] + .dofs_per_line + + + 3); + } - // mark this face as - // visited - cell->face(face)->set_user_flag (); - } + // mark this face as + // visited + cell->face(face)->set_user_flag (); + } - // we should have moved the - // cursor for each level to the - // total number of dofs on that - // level. check that - Assert (next_free_line_slot == n_line_slots, - ExcInternalError()); + // we should have moved the + // cursor for each level to the + // total number of dofs on that + // level. check that + Assert (next_free_line_slot == n_line_slots, + ExcInternalError()); - // at the end, restore the user - // flags for the lines - const_cast&>(*dof_handler.tria) - .load_user_flags_line (saved_line_user_flags); - } + // at the end, restore the user + // flags for the lines + const_cast&>(*dof_handler.tria) + .load_user_flags_line (saved_line_user_flags); + } - // VERTEX DOFS - reserve_space_vertices (dof_handler); - } + // VERTEX DOFS + reserve_space_vertices (dof_handler); + } - template - static - void - reserve_space (DoFHandler<3,spacedim> &dof_handler) - { - const unsigned int dim = 3; - - Assert (dof_handler.finite_elements != 0, ExcNoFESelected()); - Assert (dof_handler.finite_elements->size() > 0, ExcNoFESelected()); - Assert (dof_handler.tria->n_levels() > 0, ExcInvalidTriangulation()); - Assert (dof_handler.tria->n_levels() == dof_handler.levels.size (), - ExcInternalError ()); - - // Release all space except the - // active_fe_indices field which - // we have to backup before - { - std::vector > - active_fe_backup(dof_handler.levels.size ()); - for (unsigned int level = 0; levelactive_fe_indices, - active_fe_backup[level]); - - // delete all levels and set them up - // newly, since vectors are - // troublesome if you want to change - // their size - dof_handler.clear_space (); - - for (unsigned int level=0; leveln_levels(); ++level) + template + static + void + reserve_space (DoFHandler<3,spacedim> &dof_handler) + { + const unsigned int dim = 3; + + typedef DoFHandler BaseClass; + + Assert (dof_handler.finite_elements != 0, + typename BaseClass::ExcNoFESelected()); + Assert (dof_handler.finite_elements->size() > 0, + typename BaseClass::ExcNoFESelected()); + Assert (dof_handler.tria->n_levels() > 0, + typename BaseClass::ExcInvalidTriangulation()); + Assert (dof_handler.tria->n_levels() == dof_handler.levels.size (), + ExcInternalError ()); + + // Release all space except the + // active_fe_indices field which + // we have to backup before { - dof_handler.levels.push_back (new internal::hp::DoFLevel); - std::swap (active_fe_backup[level], - dof_handler.levels[level]->active_fe_indices); + std::vector > + active_fe_backup(dof_handler.levels.size ()); + for (unsigned int level = 0; levelactive_fe_indices, + active_fe_backup[level]); + + // delete all levels and set them up + // newly, since vectors are + // troublesome if you want to change + // their size + dof_handler.clear_space (); + + for (unsigned int level=0; leveln_levels(); ++level) + { + dof_handler.levels.push_back (new internal::hp::DoFLevel); + std::swap (active_fe_backup[level], + dof_handler.levels[level]->active_fe_indices); + } + dof_handler.faces = new internal::hp::DoFFaces<3>; } - dof_handler.faces = new internal::hp::DoFFaces<3>; - } - // HEX (CELL) DOFs + // HEX (CELL) DOFs - // count how much space we need - // on each level for the cell - // dofs and set the - // dof_*_offsets - // data. initially set the latter - // to an invalid index, and only - // later set it to something - // reasonable for active dof_handler.cells - // - // note that for dof_handler.cells, the - // situation is simpler than for - // other (lower dimensional) - // objects since exactly one - // finite element is used for it - for (unsigned int level=0; leveln_levels(); ++level) - { - dof_handler.levels[level]->hexes.dof_offsets - = std::vector (dof_handler.tria->n_raw_hexs(level), - invalid_dof_index); - - unsigned int next_free_dof = 0; - for (active_cell_iterator cell=dof_handler.begin_active(level); - cell!=dof_handler.end_active(level); ++cell) - if (!cell->has_children()) - { - dof_handler.levels[level]->hexes.dof_offsets[cell->index()] = next_free_dof; - next_free_dof += cell->get_fe().dofs_per_hex; - } + // count how much space we need + // on each level for the cell + // dofs and set the + // dof_*_offsets + // data. initially set the latter + // to an invalid index, and only + // later set it to something + // reasonable for active dof_handler.cells + // + // note that for dof_handler.cells, the + // situation is simpler than for + // other (lower dimensional) + // objects since exactly one + // finite element is used for it + for (unsigned int level=0; leveln_levels(); ++level) + { + dof_handler.levels[level]->hexes.dof_offsets + = std::vector (dof_handler.tria->n_raw_hexs(level), + DoFHandler::invalid_dof_index); + + unsigned int next_free_dof = 0; + for (typename DoFHandler::active_cell_iterator + cell=dof_handler.begin_active(level); + cell!=dof_handler.end_active(level); ++cell) + if (!cell->has_children()) + { + dof_handler.levels[level]->hexes.dof_offsets[cell->index()] = next_free_dof; + next_free_dof += cell->get_fe().dofs_per_hex; + } - dof_handler.levels[level]->hexes.dofs - = std::vector (next_free_dof, invalid_dof_index); - } + dof_handler.levels[level]->hexes.dofs + = std::vector (next_free_dof, + DoFHandler::invalid_dof_index); + } - // safety check: make sure that - // the number of DoFs we - // allocated is actually correct - // (above we have also set the - // dof_*_offsets field, so - // we couldn't use this simpler - // algorithm) + // safety check: make sure that + // the number of DoFs we + // allocated is actually correct + // (above we have also set the + // dof_*_offsets field, so + // we couldn't use this simpler + // algorithm) #ifdef DEBUG - for (unsigned int level=0; leveln_levels(); ++level) - { - unsigned int counter = 0; - for (cell_iterator cell=dof_handler.begin_active(level); - cell!=dof_handler.end_active(level); ++cell) - if (!cell->has_children()) - counter += cell->get_fe().dofs_per_hex; + for (unsigned int level=0; leveln_levels(); ++level) + { + unsigned int counter = 0; + for (typename DoFHandler::cell_iterator + cell=dof_handler.begin_active(level); + cell!=dof_handler.end_active(level); ++cell) + if (!cell->has_children()) + counter += cell->get_fe().dofs_per_hex; - Assert (dof_handler.levels[level]->hexes.dofs.size() == counter, - ExcInternalError()); - Assert (static_cast - (std::count (dof_handler.levels[level]->hexes.dof_offsets.begin(), - dof_handler.levels[level]->hexes.dof_offsets.end(), - invalid_dof_index)) - == - dof_handler.tria->n_raw_hexs(level) - dof_handler.tria->n_active_hexs(level), - ExcInternalError()); - } + Assert (dof_handler.levels[level]->hexes.dofs.size() == counter, + ExcInternalError()); + Assert (static_cast + (std::count (dof_handler.levels[level]->hexes.dof_offsets.begin(), + dof_handler.levels[level]->hexes.dof_offsets.end(), + DoFHandler::invalid_dof_index)) + == + dof_handler.tria->n_raw_hexs(level) - dof_handler.tria->n_active_hexs(level), + ExcInternalError()); + } #endif - // QUAD DOFS - // - // same here: count quad dofs, - // then allocate as much space as - // we need and prime the linked - // list for quad (see the - // description in hp::DoFLevels) - // with the indices we will - // need. note that our task is - // more complicated since two - // adjacent dof_handler.cells may have - // different active_fe_indices, - // in which case we need to - // allocate *two* sets of line - // dofs for the same line - // - // the way we do things is that - // we loop over all active dof_handler.cells - // (these are the ones that have - // DoFs only anyway) and all - // their dof_handler.faces. We note in the - // user flags whether we have - // previously visited a face and - // if so skip it (consequently, - // we have to save and later - // restore the line flags) - { - std::vector saved_quad_user_flags; - const_cast&>(*dof_handler.tria) - .save_user_flags_quad (saved_quad_user_flags); - const_cast&>(*dof_handler.tria).clear_user_flags_quad (); - - // examine, how how many - // slots (see the hp::DoFLevel - // class) we will have to store - unsigned int n_quad_slots = 0; + // QUAD DOFS + // + // same here: count quad dofs, + // then allocate as much space as + // we need and prime the linked + // list for quad (see the + // description in hp::DoFLevels) + // with the indices we will + // need. note that our task is + // more complicated since two + // adjacent dof_handler.cells may have + // different active_fe_indices, + // in which case we need to + // allocate *two* sets of line + // dofs for the same line + // + // the way we do things is that + // we loop over all active dof_handler.cells + // (these are the ones that have + // DoFs only anyway) and all + // their dof_handler.faces. We note in the + // user flags whether we have + // previously visited a face and + // if so skip it (consequently, + // we have to save and later + // restore the line flags) + { + std::vector saved_quad_user_flags; + const_cast&>(*dof_handler.tria) + .save_user_flags_quad (saved_quad_user_flags); + const_cast&>(*dof_handler.tria) + .clear_user_flags_quad (); + + // examine, how how many + // slots (see the hp::DoFLevel + // class) we will have to store + unsigned int n_quad_slots = 0; - for (active_cell_iterator cell=dof_handler.begin_active(); cell!=dof_handler.end(); ++cell) - for (unsigned int face=0; face::faces_per_cell; ++face) - if (! cell->face(face)->user_flag_set()) - { - // ok, face has not been - // visited. so we need to - // allocate space for - // it. let's see how much - // we need: we need one - // set if a) there is no - // neighbor behind this - // face, or b) the - // neighbor is not on the - // same level or further - // refined, or c) the - // neighbor is on the - // same level, but - // happens to have the - // same active_fe_index: - if (cell->at_boundary(face) - || - cell->face(face)->has_children() - || - cell->neighbor_is_coarser(face) - || - (!cell->at_boundary(face) - && - (cell->active_fe_index() == cell->neighbor(face)->active_fe_index()))) - // ok, one set of - // dofs. that makes - // one index, 1 times - // dofs_per_quad - // dofs, and one stop - // index - n_quad_slots - += (*dof_handler.finite_elements)[cell->active_fe_index()].dofs_per_quad + 2; - - // otherwise we do - // indeed need two - // sets, i.e. two - // indices, two sets of - // dofs, and one stop - // index: - else - n_quad_slots - += ((*dof_handler.finite_elements)[cell->active_fe_index()].dofs_per_quad - + - (*dof_handler.finite_elements)[cell->neighbor(face)->active_fe_index()] - .dofs_per_quad - + - 3); + for (typename DoFHandler::active_cell_iterator + cell=dof_handler.begin_active(); cell!=dof_handler.end(); ++cell) + for (unsigned int face=0; face::faces_per_cell; ++face) + if (! cell->face(face)->user_flag_set()) + { + // ok, face has not been + // visited. so we need to + // allocate space for + // it. let's see how much + // we need: we need one + // set if a) there is no + // neighbor behind this + // face, or b) the + // neighbor is not on the + // same level or further + // refined, or c) the + // neighbor is on the + // same level, but + // happens to have the + // same active_fe_index: + if (cell->at_boundary(face) + || + cell->face(face)->has_children() + || + cell->neighbor_is_coarser(face) + || + (!cell->at_boundary(face) + && + (cell->active_fe_index() == cell->neighbor(face)->active_fe_index()))) + // ok, one set of + // dofs. that makes + // one index, 1 times + // dofs_per_quad + // dofs, and one stop + // index + n_quad_slots + += (*dof_handler.finite_elements)[cell->active_fe_index()].dofs_per_quad + 2; + + // otherwise we do + // indeed need two + // sets, i.e. two + // indices, two sets of + // dofs, and one stop + // index: + else + n_quad_slots + += ((*dof_handler.finite_elements)[cell->active_fe_index()].dofs_per_quad + + + (*dof_handler.finite_elements)[cell->neighbor(face)->active_fe_index()] + .dofs_per_quad + + + 3); - // mark this face as - // visited - cell->face(face)->set_user_flag (); - } + // mark this face as + // visited + cell->face(face)->set_user_flag (); + } - // now that we know how many - // quad dofs we will have to - // have, allocate - // the memory. note that we - // allocate offsets for all - // quads, though only the - // active ones will have a - // non-invalid value later on - if (true) - { - dof_handler.faces->quads.dof_offsets - = std::vector (dof_handler.tria->n_raw_quads(), - invalid_dof_index); - dof_handler.faces->quads.dofs - = std::vector (n_quad_slots, - invalid_dof_index); - } + // now that we know how many + // quad dofs we will have to + // have, allocate + // the memory. note that we + // allocate offsets for all + // quads, though only the + // active ones will have a + // non-invalid value later on + if (true) + { + dof_handler.faces->quads.dof_offsets + = std::vector (dof_handler.tria->n_raw_quads(), + DoFHandler::invalid_dof_index); + dof_handler.faces->quads.dofs + = std::vector (n_quad_slots, + DoFHandler::invalid_dof_index); + } - // with the memory now - // allocated, loop over the - // dof_handler.cells again and prime the - // _offset values as well as - // the fe_index fields - const_cast&>(*dof_handler.tria).clear_user_flags_quad (); + // with the memory now + // allocated, loop over the + // dof_handler.cells again and prime the + // _offset values as well as + // the fe_index fields + const_cast&>(*dof_handler.tria) + .clear_user_flags_quad (); - unsigned int next_free_quad_slot = 0; + unsigned int next_free_quad_slot = 0; - for (active_cell_iterator cell=dof_handler.begin_active(); cell!=dof_handler.end(); ++cell) - for (unsigned int face=0; face::faces_per_cell; ++face) - if (! cell->face(face)->user_flag_set()) - { - // same decision tree - // as before - if (cell->at_boundary(face) - || - cell->face(face)->has_children() - || - cell->neighbor_is_coarser(face) - || - (!cell->at_boundary(face) - && - (cell->active_fe_index() == cell->neighbor(face)->active_fe_index()))) + for (typename DoFHandler::active_cell_iterator + cell=dof_handler.begin_active(); cell!=dof_handler.end(); ++cell) + for (unsigned int face=0; face::faces_per_cell; ++face) + if (! cell->face(face)->user_flag_set()) { - dof_handler.faces - ->quads.dof_offsets[cell->face(face)->index()] - = next_free_quad_slot; - - // set first slot - // for this quad to - // active_fe_index - // of this face - dof_handler.faces - ->quads.dofs[next_free_quad_slot] - = cell->active_fe_index(); - - // the next - // dofs_per_quad - // indices remain - // unset for the - // moment (i.e. at - // invalid_dof_index). - // following this - // comes the stop - // index, which - // also is - // invalid_dof_index - // and therefore - // does not have to - // be explicitly - // set + // same decision tree + // as before + if (cell->at_boundary(face) + || + cell->face(face)->has_children() + || + cell->neighbor_is_coarser(face) + || + (!cell->at_boundary(face) + && + (cell->active_fe_index() == cell->neighbor(face)->active_fe_index()))) + { + dof_handler.faces + ->quads.dof_offsets[cell->face(face)->index()] + = next_free_quad_slot; + + // set first slot + // for this quad to + // active_fe_index + // of this face + dof_handler.faces + ->quads.dofs[next_free_quad_slot] + = cell->active_fe_index(); + + // the next + // dofs_per_quad + // indices remain + // unset for the + // moment (i.e. at + // invalid_dof_index). + // following this + // comes the stop + // index, which + // also is + // invalid_dof_index + // and therefore + // does not have to + // be explicitly + // set - // finally, mark - // those slots as - // used - next_free_quad_slot - += (*dof_handler.finite_elements)[cell->active_fe_index()].dofs_per_quad + 2; - } - else - { - dof_handler.faces - ->quads.dof_offsets[cell->face(face)->index()] - = next_free_quad_slot; - - // set first slot - // for this quad to - // active_fe_index - // of this face - dof_handler.faces - ->quads.dofs[next_free_quad_slot] - = cell->active_fe_index(); - - // the next - // dofs_per_quad - // indices remain - // unset for the - // moment (i.e. at - // invalid_dof_index). - // - // then comes the - // fe_index for the - // neighboring - // cell: - dof_handler.faces - ->quads.dofs[next_free_quad_slot - + - (*dof_handler.finite_elements)[cell->active_fe_index()].dofs_per_quad - + - 1] - = cell->neighbor(face)->active_fe_index(); - // then again a set - // of dofs that we - // need not set - // right now - // - // following this - // comes the stop - // index, which - // also is - // invalid_dof_index - // and therefore - // does not have to - // be explicitly - // set + // finally, mark + // those slots as + // used + next_free_quad_slot + += (*dof_handler.finite_elements)[cell->active_fe_index()].dofs_per_quad + 2; + } + else + { + dof_handler.faces + ->quads.dof_offsets[cell->face(face)->index()] + = next_free_quad_slot; + + // set first slot + // for this quad to + // active_fe_index + // of this face + dof_handler.faces + ->quads.dofs[next_free_quad_slot] + = cell->active_fe_index(); + + // the next + // dofs_per_quad + // indices remain + // unset for the + // moment (i.e. at + // invalid_dof_index). + // + // then comes the + // fe_index for the + // neighboring + // cell: + dof_handler.faces + ->quads.dofs[next_free_quad_slot + + + (*dof_handler.finite_elements)[cell->active_fe_index()].dofs_per_quad + + + 1] + = cell->neighbor(face)->active_fe_index(); + // then again a set + // of dofs that we + // need not set + // right now + // + // following this + // comes the stop + // index, which + // also is + // invalid_dof_index + // and therefore + // does not have to + // be explicitly + // set - // finally, mark - // those slots as - // used - next_free_quad_slot - += ((*dof_handler.finite_elements)[cell->active_fe_index()].dofs_per_quad - + - (*dof_handler.finite_elements)[cell->neighbor(face)->active_fe_index()] - .dofs_per_quad - + - 3); - } + // finally, mark + // those slots as + // used + next_free_quad_slot + += ((*dof_handler.finite_elements)[cell->active_fe_index()].dofs_per_quad + + + (*dof_handler.finite_elements)[cell->neighbor(face)->active_fe_index()] + .dofs_per_quad + + + 3); + } - // mark this face as - // visited - cell->face(face)->set_user_flag (); - } + // mark this face as + // visited + cell->face(face)->set_user_flag (); + } - // we should have moved the - // cursor to the total number - // of dofs. check that - Assert (next_free_quad_slot == n_quad_slots, - ExcInternalError()); + // we should have moved the + // cursor to the total number + // of dofs. check that + Assert (next_free_quad_slot == n_quad_slots, + ExcInternalError()); - // at the end, restore the user - // flags for the quads - const_cast&>(*dof_handler.tria) - .load_user_flags_quad (saved_quad_user_flags); - } + // at the end, restore the user + // flags for the quads + const_cast&>(*dof_handler.tria) + .load_user_flags_quad (saved_quad_user_flags); + } - // LINE DOFS + // LINE DOFS - // the situation here is pretty - // much like with vertices: there - // can be an arbitrary number of - // finite elements associated - // with each line. - // - // the algorithm we use is - // somewhat similar to what we do - // in reserve_space_vertices() - if (true) - { - // what we do first is to set up - // an array in which we record - // whether a line is associated - // with any of the given fe's, by - // setting a bit. in a later - // step, we then actually - // allocate memory for the - // required dofs - std::vector > - line_fe_association (dof_handler.finite_elements->size(), - std::vector (dof_handler.tria->n_raw_lines(), - false)); + // the situation here is pretty + // much like with vertices: there + // can be an arbitrary number of + // finite elements associated + // with each line. + // + // the algorithm we use is + // somewhat similar to what we do + // in reserve_space_vertices() + if (true) + { + // what we do first is to set up + // an array in which we record + // whether a line is associated + // with any of the given fe's, by + // setting a bit. in a later + // step, we then actually + // allocate memory for the + // required dofs + std::vector > + line_fe_association (dof_handler.finite_elements->size(), + std::vector (dof_handler.tria->n_raw_lines(), + false)); - for (active_cell_iterator cell=dof_handler.begin_active(); - cell!=dof_handler.end(); ++cell) - for (unsigned int l=0; l::lines_per_cell; ++l) - line_fe_association[cell->active_fe_index()][cell->line_index(l)] - = true; - - // first check which of the - // lines is used at all, - // i.e. is associated with a - // finite element. we do this - // since not all lines may - // actually be used, in which - // case we do not have to - // allocate any memory at - // all - std::vector line_is_used (dof_handler.tria->n_raw_lines(), false); - for (unsigned int line=0; linen_raw_lines(); ++line) - for (unsigned int fe=0; fesize(); ++fe) - if (line_fe_association[fe][line] == true) - { - line_is_used[line] = true; - break; - } - - // next count how much memory - // we actually need. for each - // line, we need one slot per - // fe to store the fe_index, - // plus dofs_per_line for - // this fe. in addition, we - // need one slot as the end - // marker for the - // fe_indices. at the same - // time already fill the - // line_dofs_offsets field - dof_handler.faces->lines.dof_offsets - .resize (dof_handler.tria->n_raw_lines(), - numbers::invalid_unsigned_int); - - unsigned int line_slots_needed = 0; - for (unsigned int line=0; linen_raw_lines(); ++line) - if (line_is_used[line] == true) - { - dof_handler.faces->lines.dof_offsets[line] = line_slots_needed; - - for (unsigned int fe=0; fesize(); ++fe) - if (line_fe_association[fe][line] == true) - line_slots_needed += (*dof_handler.finite_elements)[fe].dofs_per_line + 1; - ++line_slots_needed; - } - - // now allocate the space we - // have determined we need, and - // set up the linked lists for - // each of the lines - dof_handler.faces->lines.dofs.resize (line_slots_needed, invalid_dof_index); - for (unsigned int line=0; linen_raw_lines(); ++line) - if (line_is_used[line] == true) - { - unsigned int pointer = dof_handler.faces->lines.dof_offsets[line]; + for (typename DoFHandler::active_cell_iterator + cell=dof_handler.begin_active(); + cell!=dof_handler.end(); ++cell) + for (unsigned int l=0; l::lines_per_cell; ++l) + line_fe_association[cell->active_fe_index()][cell->line_index(l)] + = true; + + // first check which of the + // lines is used at all, + // i.e. is associated with a + // finite element. we do this + // since not all lines may + // actually be used, in which + // case we do not have to + // allocate any memory at + // all + std::vector line_is_used (dof_handler.tria->n_raw_lines(), false); + for (unsigned int line=0; linen_raw_lines(); ++line) for (unsigned int fe=0; fesize(); ++fe) if (line_fe_association[fe][line] == true) { - // if this line - // uses this fe, - // then set the - // fe_index and - // move the - // pointer ahead - dof_handler.faces->lines.dofs[pointer] = fe; - pointer += (*dof_handler.finite_elements)[fe].dofs_per_line + 1; + line_is_used[line] = true; + break; } - // finally place the end - // marker - dof_handler.faces->lines.dofs[pointer] = numbers::invalid_unsigned_int; - } - } + + // next count how much memory + // we actually need. for each + // line, we need one slot per + // fe to store the fe_index, + // plus dofs_per_line for + // this fe. in addition, we + // need one slot as the end + // marker for the + // fe_indices. at the same + // time already fill the + // line_dofs_offsets field + dof_handler.faces->lines.dof_offsets + .resize (dof_handler.tria->n_raw_lines(), + numbers::invalid_unsigned_int); + + unsigned int line_slots_needed = 0; + for (unsigned int line=0; linen_raw_lines(); ++line) + if (line_is_used[line] == true) + { + dof_handler.faces->lines.dof_offsets[line] = line_slots_needed; + + for (unsigned int fe=0; fesize(); ++fe) + if (line_fe_association[fe][line] == true) + line_slots_needed += (*dof_handler.finite_elements)[fe].dofs_per_line + 1; + ++line_slots_needed; + } + + // now allocate the space we + // have determined we need, and + // set up the linked lists for + // each of the lines + dof_handler.faces->lines.dofs.resize (line_slots_needed, + DoFHandler::invalid_dof_index); + for (unsigned int line=0; linen_raw_lines(); ++line) + if (line_is_used[line] == true) + { + unsigned int pointer = dof_handler.faces->lines.dof_offsets[line]; + for (unsigned int fe=0; fesize(); ++fe) + if (line_fe_association[fe][line] == true) + { + // if this line + // uses this fe, + // then set the + // fe_index and + // move the + // pointer ahead + dof_handler.faces->lines.dofs[pointer] = fe; + pointer += (*dof_handler.finite_elements)[fe].dofs_per_line + 1; + } + // finally place the end + // marker + dof_handler.faces->lines.dofs[pointer] = numbers::invalid_unsigned_int; + } + } - // VERTEX DOFS - reserve_space_vertices (dof_handler); - } + // VERTEX DOFS + reserve_space_vertices (dof_handler); + } - /** - * Implement the function of same name - * in the mother class. - */ - template - static - unsigned int - max_couplings_between_dofs (const DoFHandler<1,spacedim> &dof_handler) - { - return std::min(3*dof_handler.finite_elements->max_dofs_per_vertex() + - 2*dof_handler.finite_elements->max_dofs_per_line(), dof_handler.n_dofs()); - } + /** + * Implement the function of same name + * in the mother class. + */ + template + static + unsigned int + max_couplings_between_dofs (const DoFHandler<1,spacedim> &dof_handler) + { + return std::min(3*dof_handler.finite_elements->max_dofs_per_vertex() + + 2*dof_handler.finite_elements->max_dofs_per_line(), dof_handler.n_dofs()); + } - template - static - unsigned int - max_couplings_between_dofs (const DoFHandler<2,spacedim> &dof_handler) - { - // get these numbers by drawing pictures - // and counting... - // example: - // | | | - // --x-----x--x--X-- - // | | | | - // | x--x--x - // | | | | - // --x--x--*--x--x-- - // | | | | - // x--x--x | - // | | | | - // --X--x--x-----x-- - // | | | - // x = vertices connected with center vertex *; - // = total of 19 - // (the X vertices are connected with * if - // the vertices adjacent to X are hanging - // nodes) - // count lines -> 28 (don't forget to count - // mother and children separately!) - unsigned int max_couplings; - switch (dof_handler.tria->max_adjacent_cells()) + template + static + unsigned int + max_couplings_between_dofs (const DoFHandler<2,spacedim> &dof_handler) { - case 4: - max_couplings=19*dof_handler.finite_elements->max_dofs_per_vertex() + - 28*dof_handler.finite_elements->max_dofs_per_line() + - 8*dof_handler.finite_elements->max_dofs_per_quad(); - break; - case 5: - max_couplings=21*dof_handler.finite_elements->max_dofs_per_vertex() + - 31*dof_handler.finite_elements->max_dofs_per_line() + - 9*dof_handler.finite_elements->max_dofs_per_quad(); - break; - case 6: - max_couplings=28*dof_handler.finite_elements->max_dofs_per_vertex() + - 42*dof_handler.finite_elements->max_dofs_per_line() + - 12*dof_handler.finite_elements->max_dofs_per_quad(); - break; - case 7: - max_couplings=30*dof_handler.finite_elements->max_dofs_per_vertex() + - 45*dof_handler.finite_elements->max_dofs_per_line() + - 13*dof_handler.finite_elements->max_dofs_per_quad(); - break; - case 8: - max_couplings=37*dof_handler.finite_elements->max_dofs_per_vertex() + - 56*dof_handler.finite_elements->max_dofs_per_line() + - 16*dof_handler.finite_elements->max_dofs_per_quad(); - break; - default: - Assert (false, ExcNotImplemented()); - max_couplings=0; - }; - return std::min(max_couplings,dof_handler.n_dofs()); - } + // get these numbers by drawing pictures + // and counting... + // example: + // | | | + // --x-----x--x--X-- + // | | | | + // | x--x--x + // | | | | + // --x--x--*--x--x-- + // | | | | + // x--x--x | + // | | | | + // --X--x--x-----x-- + // | | | + // x = vertices connected with center vertex *; + // = total of 19 + // (the X vertices are connected with * if + // the vertices adjacent to X are hanging + // nodes) + // count lines -> 28 (don't forget to count + // mother and children separately!) + unsigned int max_couplings; + switch (dof_handler.tria->max_adjacent_cells()) + { + case 4: + max_couplings=19*dof_handler.finite_elements->max_dofs_per_vertex() + + 28*dof_handler.finite_elements->max_dofs_per_line() + + 8*dof_handler.finite_elements->max_dofs_per_quad(); + break; + case 5: + max_couplings=21*dof_handler.finite_elements->max_dofs_per_vertex() + + 31*dof_handler.finite_elements->max_dofs_per_line() + + 9*dof_handler.finite_elements->max_dofs_per_quad(); + break; + case 6: + max_couplings=28*dof_handler.finite_elements->max_dofs_per_vertex() + + 42*dof_handler.finite_elements->max_dofs_per_line() + + 12*dof_handler.finite_elements->max_dofs_per_quad(); + break; + case 7: + max_couplings=30*dof_handler.finite_elements->max_dofs_per_vertex() + + 45*dof_handler.finite_elements->max_dofs_per_line() + + 13*dof_handler.finite_elements->max_dofs_per_quad(); + break; + case 8: + max_couplings=37*dof_handler.finite_elements->max_dofs_per_vertex() + + 56*dof_handler.finite_elements->max_dofs_per_line() + + 16*dof_handler.finite_elements->max_dofs_per_quad(); + break; + default: + Assert (false, ExcNotImplemented()); + max_couplings=0; + }; + return std::min(max_couplings,dof_handler.n_dofs()); + } - template - static - unsigned int - max_couplings_between_dofs (const DoFHandler<3,spacedim> &dof_handler) - { -//TODO:[?] Invent significantly better estimates than the ones in this function - // doing the same thing here is a rather - // complicated thing, compared to the 2d - // case, since it is hard to draw pictures - // with several refined hexahedra :-) so I - // presently only give a coarse estimate - // for the case that at most 8 hexes meet - // at each vertex - // - // can anyone give better estimate here? - const unsigned int max_adjacent_cells = dof_handler.tria->max_adjacent_cells(); - - unsigned int max_couplings; - if (max_adjacent_cells <= 8) - max_couplings=7*7*7*dof_handler.finite_elements->max_dofs_per_vertex() + - 7*6*7*3*dof_handler.finite_elements->max_dofs_per_line() + - 9*4*7*3*dof_handler.finite_elements->max_dofs_per_quad() + - 27*dof_handler.finite_elements->max_dofs_per_hex(); - else + template + static + unsigned int + max_couplings_between_dofs (const DoFHandler<3,spacedim> &dof_handler) { - Assert (false, ExcNotImplemented()); - max_couplings=0; - } +//TODO:[?] Invent significantly better estimates than the ones in this function + // doing the same thing here is a rather + // complicated thing, compared to the 2d + // case, since it is hard to draw pictures + // with several refined hexahedra :-) so I + // presently only give a coarse estimate + // for the case that at most 8 hexes meet + // at each vertex + // + // can anyone give better estimate here? + const unsigned int max_adjacent_cells = dof_handler.tria->max_adjacent_cells(); + + unsigned int max_couplings; + if (max_adjacent_cells <= 8) + max_couplings=7*7*7*dof_handler.finite_elements->max_dofs_per_vertex() + + 7*6*7*3*dof_handler.finite_elements->max_dofs_per_line() + + 9*4*7*3*dof_handler.finite_elements->max_dofs_per_quad() + + 27*dof_handler.finite_elements->max_dofs_per_hex(); + else + { + Assert (false, ExcNotImplemented()); + max_couplings=0; + } - return std::min(max_couplings,dof_handler.n_dofs()); - } - -// xxx - }; + return std::min(max_couplings,dof_handler.n_dofs()); + } + }; + } + } +} - +namespace hp +{ template const unsigned int DoFHandler::dimension; @@ -4041,7 +4105,7 @@ namespace hp // then allocate space for all // the other tables - Implementation::reserve_space (*this); + internal::hp::DoFHandler::Implementation::reserve_space (*this); // Clear user flags because we will // need them. But first we save @@ -4067,7 +4131,7 @@ namespace hp for (; cell != endc; ++cell) next_free_dof - = Implementation::template distribute_dofs_on_cell (cell, + = internal::hp::DoFHandler::Implementation::template distribute_dofs_on_cell (cell, next_free_dof); used_dofs = next_free_dof; @@ -4303,7 +4367,7 @@ namespace hp DoFHandler::max_couplings_between_dofs () const { Assert (finite_elements != 0, ExcNoFESelected()); - return Implementation::max_couplings_between_dofs (*this); + return internal::hp::DoFHandler::Implementation::max_couplings_between_dofs (*this); }