elem.h
Go to the documentation of this file.00001 // The libMesh Finite Element Library. 00002 // Copyright (C) 2002-2012 Benjamin S. Kirk, John W. Peterson, Roy H. Stogner 00003 00004 // This library is free software; you can redistribute it and/or 00005 // modify it under the terms of the GNU Lesser General Public 00006 // License as published by the Free Software Foundation; either 00007 // version 2.1 of the License, or (at your option) any later version. 00008 00009 // This library is distributed in the hope that it will be useful, 00010 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00012 // Lesser General Public License for more details. 00013 00014 // You should have received a copy of the GNU Lesser General Public 00015 // License along with this library; if not, write to the Free Software 00016 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 00017 00018 00019 00020 #ifndef LIBMESH_ELEM_H 00021 #define LIBMESH_ELEM_H 00022 00023 // Local includes 00024 #include "libmesh/libmesh_common.h" 00025 #include "libmesh/dof_object.h" 00026 #include "libmesh/id_types.h" 00027 #include "libmesh/reference_counted_object.h" 00028 #include "libmesh/node.h" 00029 #include "libmesh/enum_elem_type.h" 00030 #include "libmesh/enum_elem_quality.h" 00031 #include "libmesh/enum_order.h" 00032 #include "libmesh/enum_io_package.h" 00033 #include "libmesh/auto_ptr.h" 00034 #include "libmesh/multi_predicates.h" 00035 #include "libmesh/variant_filter_iterator.h" 00036 #include "libmesh/hashword.h" // Used in compute_key() functions 00037 00038 // C++ includes 00039 #include <algorithm> 00040 #include <cstddef> 00041 #include <iostream> 00042 #include <limits.h> // CHAR_BIT 00043 #include <set> 00044 #include <vector> 00045 00046 namespace libMesh 00047 { 00048 00049 // Forward declarations 00050 class MeshBase; 00051 class MeshRefinement; 00052 class Elem; 00053 #ifdef LIBMESH_ENABLE_PERIODIC 00054 class PeriodicBoundaries; 00055 class PointLocatorBase; 00056 #endif 00057 00091 // ------------------------------------------------------------ 00092 // Elem class definition 00093 class Elem : public ReferenceCountedObject<Elem>, 00094 public DofObject 00095 { 00096 protected: 00097 00104 Elem (const unsigned int n_nodes, 00105 const unsigned int n_sides, 00106 Elem* parent, 00107 Elem** elemlinkdata, 00108 Node** nodelinkdata); 00109 00110 public: 00111 00115 virtual ~Elem(); 00116 00120 virtual const Point & point (const unsigned int i) const; 00121 00126 virtual Point & point (const unsigned int i); 00127 00131 virtual dof_id_type node (const unsigned int i) const; 00132 00137 virtual unsigned int local_node (const dof_id_type i) const; 00138 00143 unsigned int get_node_index (const Node* node_ptr) const; 00144 00148 virtual Node* get_node (const unsigned int i) const; 00149 00153 virtual Node* & set_node (const unsigned int i); 00154 00159 subdomain_id_type subdomain_id () const; 00160 00165 subdomain_id_type & subdomain_id (); 00166 00172 virtual dof_id_type key (const unsigned int s) const = 0; 00173 00180 bool operator == (const Elem& rhs) const; 00181 00189 Elem* neighbor (const unsigned int i) const; 00190 00191 #ifdef LIBMESH_ENABLE_PERIODIC 00192 00198 const Elem* topological_neighbor (const unsigned int i, 00199 const MeshBase& mesh, 00200 const PointLocatorBase& point_locator, 00201 const PeriodicBoundaries* pb) const; 00202 00209 Elem* topological_neighbor (const unsigned int i, 00210 MeshBase& mesh, 00211 const PointLocatorBase& point_locator, 00212 const PeriodicBoundaries* pb); 00213 00218 bool has_topological_neighbor (const Elem* elem, 00219 const MeshBase& mesh, 00220 const PointLocatorBase& point_locator, 00221 PeriodicBoundaries* pb) const; 00222 #endif 00223 00227 void set_neighbor (const unsigned int i, Elem* n); 00228 00233 bool has_neighbor (const Elem* elem) const; 00234 00240 Elem* child_neighbor (Elem* elem) const; 00241 00247 const Elem* child_neighbor (const Elem* elem) const; 00248 00254 bool on_boundary () const; 00255 00260 bool is_semilocal () const; 00261 00267 unsigned int which_neighbor_am_i(const Elem *e) const; 00268 00276 unsigned int which_side_am_i(const Elem *e) const; 00277 00282 bool contains_vertex_of(const Elem *e) const; 00283 00289 bool contains_edge_of(const Elem *e) const; 00290 00296 void find_point_neighbors(const Point &p, 00297 std::set<const Elem *> &neighbor_set) const; 00298 00303 void find_point_neighbors(std::set<const Elem *> &neighbor_set) const; 00304 00310 void find_edge_neighbors(const Point& p1, 00311 const Point& p2, 00312 std::set<const Elem *> &neighbor_set) const; 00313 00319 void find_edge_neighbors(std::set<const Elem *> &neighbor_set) const; 00320 00328 void make_links_to_me_remote (); 00329 00336 void make_links_to_me_local (unsigned int n); 00337 00348 virtual bool is_remote () const 00349 { return false; } 00350 00357 virtual void connectivity(const unsigned int sc, 00358 const IOPackage iop, 00359 std::vector<dof_id_type>& conn) const = 0; 00360 00368 void write_connectivity (std::ostream& out, 00369 const IOPackage iop) const; 00370 00371 // /** 00372 // * @returns the VTK element type of the sc-th sub-element. 00373 // */ 00374 // virtual unsigned int vtk_element_type (const unsigned int sc) const = 0; 00375 00380 virtual ElemType type () const = 0; 00381 00385 virtual unsigned int dim () const = 0; 00386 00391 static const unsigned int type_to_n_nodes_map[INVALID_ELEM]; 00392 00396 virtual unsigned int n_nodes () const = 0; 00397 00402 static const unsigned int type_to_n_sides_map[INVALID_ELEM]; 00403 00409 virtual unsigned int n_sides () const = 0; 00410 00417 virtual unsigned int n_neighbors () const 00418 { return this->n_sides(); } 00419 00424 virtual unsigned int n_vertices () const = 0; 00425 00430 virtual unsigned int n_edges () const = 0; 00431 00436 virtual unsigned int n_faces () const = 0; 00437 00442 virtual unsigned int n_children () const = 0; 00443 00447 virtual bool is_vertex(const unsigned int i) const = 0; 00448 00452 virtual bool is_edge(const unsigned int i) const = 0; 00453 00457 virtual bool is_face(const unsigned int i) const = 0; 00458 00459 /* 00460 * @returns true iff the specified (local) node number is on the 00461 * specified side 00462 */ 00463 virtual bool is_node_on_side(const unsigned int n, 00464 const unsigned int s) const = 0; 00465 00466 /* 00467 * @returns true iff the specified (local) node number is on the 00468 * specified edge 00469 */ 00470 virtual bool is_node_on_edge(const unsigned int n, 00471 const unsigned int e) const = 0; 00472 00473 /* 00474 * @returns true iff the specified edge is on the specified side 00475 */ 00476 virtual bool is_edge_on_side(const unsigned int e, 00477 const unsigned int s) const = 0; 00478 00479 /* 00480 * @returns the side number opposite to \p s (for a tensor product 00481 * element), or throws an error otherwise. 00482 */ 00483 virtual unsigned int opposite_side(const unsigned int s) const; 00484 00485 /* 00486 * @returns the local node number for the node opposite to node n 00487 * on side \p opposite_side(s) (for a tensor product element), or 00488 * throws an error otherwise. 00489 */ 00490 virtual unsigned int opposite_node(const unsigned int n, 00491 const unsigned int s) const; 00492 00493 // /** 00494 // * @returns the number of children this element has that 00495 // * share side \p s 00496 // */ 00497 // virtual unsigned int n_children_per_side (const unsigned int) const = 0; 00498 00504 virtual unsigned int n_sub_elem () const = 0; 00505 00514 virtual AutoPtr<Elem> side (const unsigned int i) const = 0; 00515 00532 virtual AutoPtr<Elem> build_side (const unsigned int i, 00533 bool proxy=true) const = 0; 00534 00543 virtual AutoPtr<Elem> build_edge (const unsigned int i) const = 0; 00544 00550 virtual Order default_order () const = 0; 00551 00558 virtual Point centroid () const; 00559 00563 virtual Real hmin () const; 00564 00568 virtual Real hmax () const; 00569 00573 virtual Real volume () const; 00574 00579 virtual Real quality (const ElemQuality q) const; 00580 00588 virtual std::pair<Real,Real> qual_bounds (const ElemQuality) const 00589 { libmesh_error(); return std::make_pair(0.,0.); } 00590 00606 virtual bool contains_point (const Point& p, Real tol=TOLERANCE) const; 00607 00612 virtual bool close_to_point(const Point& p, Real tol) const; 00613 00614 private: 00621 bool point_test(const Point& p, Real box_tol, Real map_tol) const; 00622 00623 public: 00628 virtual bool has_affine_map () const { return false; } 00629 00634 virtual bool is_linear () const { return false; } 00635 00639 void print_info (std::ostream& os=libMesh::out) const; 00640 00644 std::string get_info () const; 00645 00651 bool active () const; 00652 00658 bool ancestor () const; 00659 00665 bool subactive () const; 00666 00671 bool has_children () const; 00672 00678 bool has_ancestor_children () const; 00679 00685 bool is_ancestor_of(const Elem *descendant) const; 00686 00691 const Elem* parent () const; 00692 00697 Elem* parent (); 00698 00703 void set_parent (Elem *p); 00704 00711 const Elem* top_parent () const; 00712 00721 const Elem* interior_parent () const; 00722 00727 void set_interior_parent (Elem *p); 00728 00733 Real length (const unsigned int n1, 00734 const unsigned int n2) const; 00735 00744 virtual unsigned int n_second_order_adjacent_vertices (const unsigned int n) const; 00745 00753 virtual unsigned short int second_order_adjacent_vertex (const unsigned int n, 00754 const unsigned int v) const; 00755 00765 virtual std::pair<unsigned short int, unsigned short int> 00766 second_order_child_vertex (const unsigned int n) const; 00767 00779 static ElemType second_order_equivalent_type (const ElemType et, 00780 const bool full_ordered=true); 00781 00788 static ElemType first_order_equivalent_type (const ElemType et); 00789 00790 00797 unsigned int level () const; 00798 00804 unsigned int p_level () const; 00805 00806 #ifdef LIBMESH_ENABLE_AMR 00807 00812 enum RefinementState { COARSEN = 0, 00813 DO_NOTHING, 00814 REFINE, 00815 JUST_REFINED, 00816 JUST_COARSENED, 00817 INACTIVE, 00818 COARSEN_INACTIVE, 00819 INVALID_REFINEMENTSTATE }; 00820 00825 Elem* child (const unsigned int i) const; 00826 00827 private: 00832 void set_child (unsigned int c, Elem *elem); 00833 00834 public: 00840 unsigned int which_child_am_i(const Elem *e) const; 00841 00846 virtual bool is_child_on_side(const unsigned int c, 00847 const unsigned int s) const = 0; 00848 00853 virtual bool is_child_on_edge(const unsigned int c, 00854 const unsigned int e) const; 00855 00862 void add_child (Elem* elem); 00863 00870 void add_child (Elem* elem, unsigned int c); 00871 00876 void replace_child (Elem* elem, unsigned int c); 00877 00889 void family_tree (std::vector<const Elem*>& family, 00890 const bool reset=true) const; 00891 00896 void total_family_tree (std::vector<const Elem*>& active_family, 00897 const bool reset=true) const; 00898 00905 void active_family_tree (std::vector<const Elem*>& active_family, 00906 const bool reset=true) const; 00907 00912 void family_tree_by_side (std::vector<const Elem*>& family, 00913 const unsigned int side, 00914 const bool reset=true) const; 00915 00920 void active_family_tree_by_side (std::vector<const Elem*>& family, 00921 const unsigned int side, 00922 const bool reset=true) const; 00923 00928 void family_tree_by_neighbor (std::vector<const Elem*>& family, 00929 const Elem *neighbor, 00930 const bool reset=true) const; 00931 00938 void family_tree_by_subneighbor (std::vector<const Elem*>& family, 00939 const Elem *neighbor, 00940 const Elem *subneighbor, 00941 const bool reset=true) const; 00942 00947 void active_family_tree_by_neighbor (std::vector<const Elem*>& family, 00948 const Elem *neighbor, 00949 const bool reset=true) const; 00950 00954 RefinementState refinement_flag () const; 00955 00959 void set_refinement_flag (const RefinementState rflag); 00960 00964 RefinementState p_refinement_flag () const; 00965 00969 void set_p_refinement_flag (const RefinementState pflag); 00970 00975 unsigned int max_descendant_p_level () const; 00976 00982 unsigned int min_p_level_by_neighbor (const Elem* neighbor, 00983 unsigned int current_min) const; 00984 00991 unsigned int min_new_p_level_by_neighbor (const Elem* neighbor, 00992 unsigned int current_min) const; 00993 00998 void set_p_level (const unsigned int p); 00999 01004 void hack_p_level (const unsigned int p); 01005 01009 virtual void refine (MeshRefinement& mesh_refinement); 01010 01016 void coarsen (); 01017 01024 void contract (); 01025 01026 #endif 01027 01028 #ifdef DEBUG 01029 01033 void libmesh_assert_valid_neighbors() const; 01034 01039 void libmesh_assert_valid_node_pointers() const; 01040 #endif // DEBUG 01041 01042 protected: 01043 01054 class SideIter; 01055 01056 public: 01060 typedef Predicates::multi_predicate Predicate; 01061 //typedef variant_filter_iterator<Elem*, Predicate> side_iterator; 01062 01067 struct side_iterator; 01068 01072 side_iterator boundary_sides_begin(); 01073 side_iterator boundary_sides_end(); 01074 01075 private: 01080 SideIter _first_side(); 01081 SideIter _last_side(); 01082 01083 public: 01084 01085 #ifdef LIBMESH_ENABLE_INFINITE_ELEMENTS 01086 01091 virtual bool infinite () const = 0; 01092 01101 virtual Point origin () const { libmesh_error(); return Point(); } 01102 01103 #endif 01104 01105 01106 01107 01113 static AutoPtr<Elem> build (const ElemType type, 01114 Elem* p=NULL); 01115 01116 #ifdef LIBMESH_ENABLE_AMR 01117 01122 virtual float embedding_matrix (const unsigned int i, 01123 const unsigned int j, 01124 const unsigned int k) const = 0; 01125 01126 #endif 01127 01128 01129 //-------------------------------------------------------- 01138 class PackedElem; 01139 01140 unsigned int packed_size() const; 01141 01142 protected: 01143 01144 //------------------------------------------------------- 01145 // These methods compute has keys from the specified 01146 // global node numbers 01147 // 01151 static dof_id_type compute_key (dof_id_type n0); 01152 01156 static dof_id_type compute_key (dof_id_type n0, 01157 dof_id_type n1); 01158 01162 static dof_id_type compute_key (dof_id_type n0, 01163 dof_id_type n1, 01164 dof_id_type n2); 01165 01169 static dof_id_type compute_key (dof_id_type n0, 01170 dof_id_type n1, 01171 dof_id_type n2, 01172 dof_id_type n3); 01173 //------------------------------------------------------- 01174 01175 01176 01182 void nullify_neighbors (); 01183 01187 Node** _nodes; 01188 01193 Elem** _elemlinks; 01194 01195 #ifdef LIBMESH_ENABLE_AMR 01196 01200 Elem** _children; 01201 01206 unsigned char _rflag; 01207 //RefinementState _rflag; 01208 01213 unsigned char _pflag; 01214 //RefinementState _pflag; 01215 01224 unsigned char _p_level; 01225 01226 #endif 01227 01231 subdomain_id_type _sbd_id; 01232 01244 friend class MeshRefinement; // (Elem::nullify_neighbors) 01245 }; 01246 01247 // ------------------------------------------------------------ 01248 // global Elem functions 01249 01250 inline 01251 std::ostream& operator << (std::ostream& os, const Elem& e) 01252 { 01253 e.print_info(os); 01254 return os; 01255 } 01256 01257 01258 // ------------------------------------------------------------ 01259 // Elem class member functions 01260 inline 01261 Elem::Elem(const unsigned int nn, 01262 const unsigned int ns, 01263 Elem* p, 01264 Elem** elemlinkdata, 01265 Node** nodelinkdata) : 01266 _nodes(nodelinkdata), 01267 _elemlinks(elemlinkdata), 01268 #ifdef LIBMESH_ENABLE_AMR 01269 _children(NULL), 01270 _rflag(Elem::DO_NOTHING), 01271 _pflag(Elem::DO_NOTHING), 01272 _p_level(0), 01273 #endif 01274 _sbd_id(0) 01275 { 01276 this->processor_id() = DofObject::invalid_processor_id; 01277 01278 // Initialize the nodes data structure 01279 if (_nodes) 01280 { 01281 for (unsigned int n=0; n<nn; n++) 01282 _nodes[n] = NULL; 01283 } 01284 01285 // Initialize the neighbors/parent data structure 01286 // _elemlinks = new Elem*[ns+1]; 01287 01288 if (_elemlinks) 01289 { 01290 _elemlinks[0] = p; 01291 01292 for (unsigned int n=1; n<ns+1; n++) 01293 _elemlinks[n] = NULL; 01294 } 01295 01296 // Optionally initialize data from the parent 01297 if (this->parent() != NULL) 01298 { 01299 this->subdomain_id() = this->parent()->subdomain_id(); 01300 this->processor_id() = this->parent()->processor_id(); 01301 } 01302 01303 #ifdef LIBMESH_ENABLE_AMR 01304 if (this->parent()) 01305 this->set_p_level(this->parent()->p_level()); 01306 #endif 01307 } 01308 01309 01310 01311 inline 01312 Elem::~Elem() 01313 { 01314 // Deleting my parent/neighbor/nodes storage isn't necessary since it's 01315 // handled by the subclass 01316 01317 // if (_nodes != NULL) 01318 // delete [] _nodes; 01319 // _nodes = NULL; 01320 01321 // delete [] _elemlinks; 01322 01323 #ifdef LIBMESH_ENABLE_AMR 01324 01325 // Delete my children's storage 01326 if (_children != NULL) 01327 delete [] _children; 01328 _children = NULL; 01329 01330 #endif 01331 } 01332 01333 01334 01335 inline 01336 const Point & Elem::point (const unsigned int i) const 01337 { 01338 libmesh_assert_less (i, this->n_nodes()); 01339 libmesh_assert(_nodes[i]); 01340 libmesh_assert_not_equal_to (_nodes[i]->id(), Node::invalid_id); 01341 01342 return *_nodes[i]; 01343 } 01344 01345 01346 01347 inline 01348 Point & Elem::point (const unsigned int i) 01349 { 01350 libmesh_assert_less (i, this->n_nodes()); 01351 01352 return *_nodes[i]; 01353 } 01354 01355 01356 01357 inline 01358 dof_id_type Elem::node (const unsigned int i) const 01359 { 01360 libmesh_assert_less (i, this->n_nodes()); 01361 libmesh_assert(_nodes[i]); 01362 libmesh_assert_not_equal_to (_nodes[i]->id(), Node::invalid_id); 01363 01364 return _nodes[i]->id(); 01365 } 01366 01367 01368 01369 inline 01370 unsigned int Elem::local_node (const dof_id_type i) const 01371 { 01372 for (unsigned int n=0; n != this->n_nodes(); ++n) 01373 if (this->node(n) == i) 01374 return n; 01375 01376 return libMesh::invalid_uint; 01377 } 01378 01379 01380 01381 inline 01382 Node* Elem::get_node (const unsigned int i) const 01383 { 01384 libmesh_assert_less (i, this->n_nodes()); 01385 libmesh_assert(_nodes[i]); 01386 01387 return _nodes[i]; 01388 } 01389 01390 01391 01392 inline 01393 unsigned int Elem::get_node_index (const Node* node_ptr) const 01394 { 01395 for (unsigned int n=0; n != this->n_nodes(); ++n) 01396 if (this->_nodes[n] == node_ptr) 01397 return n; 01398 01399 return libMesh::invalid_uint; 01400 } 01401 01402 01403 01404 inline 01405 Node* & Elem::set_node (const unsigned int i) 01406 { 01407 libmesh_assert_less (i, this->n_nodes()); 01408 01409 return _nodes[i]; 01410 } 01411 01412 01413 01414 inline 01415 subdomain_id_type Elem::subdomain_id () const 01416 { 01417 return _sbd_id; 01418 } 01419 01420 01421 01422 inline 01423 subdomain_id_type & Elem::subdomain_id () 01424 { 01425 return _sbd_id; 01426 } 01427 01428 01429 01430 inline 01431 Elem* Elem::neighbor (const unsigned int i) const 01432 { 01433 libmesh_assert_less (i, this->n_neighbors()); 01434 01435 return _elemlinks[i+1]; 01436 } 01437 01438 01439 01440 inline 01441 void Elem::set_neighbor (const unsigned int i, Elem* n) 01442 { 01443 libmesh_assert_less (i, this->n_neighbors()); 01444 01445 _elemlinks[i+1] = n; 01446 } 01447 01448 01449 01450 inline 01451 bool Elem::has_neighbor (const Elem* elem) const 01452 { 01453 for (unsigned int n=0; n<this->n_neighbors(); n++) 01454 if (this->neighbor(n) == elem) 01455 return true; 01456 01457 return false; 01458 } 01459 01460 01461 01462 inline 01463 Elem* Elem::child_neighbor (Elem* elem) const 01464 { 01465 for (unsigned int n=0; n<elem->n_neighbors(); n++) 01466 if (elem->neighbor(n) && 01467 elem->neighbor(n)->parent() == this) 01468 return elem->neighbor(n); 01469 01470 return NULL; 01471 } 01472 01473 01474 01475 inline 01476 const Elem* Elem::child_neighbor (const Elem* elem) const 01477 { 01478 for (unsigned int n=0; n<elem->n_neighbors(); n++) 01479 if (elem->neighbor(n) && 01480 elem->neighbor(n)->parent() == this) 01481 return elem->neighbor(n); 01482 01483 return NULL; 01484 } 01485 01486 01487 01488 inline 01489 bool Elem::on_boundary () const 01490 { 01491 // By convention, the element is on the boundary 01492 // if it has a NULL neighbor. 01493 return this->has_neighbor(NULL); 01494 } 01495 01496 01497 01498 inline 01499 unsigned int Elem::which_neighbor_am_i (const Elem* e) const 01500 { 01501 libmesh_assert(e); 01502 01503 const Elem* eparent = e; 01504 01505 while (eparent->level() > this->level()) 01506 { 01507 eparent = eparent->parent(); 01508 libmesh_assert(eparent); 01509 } 01510 01511 for (unsigned int s=0; s<this->n_neighbors(); s++) 01512 if (this->neighbor(s) == eparent) 01513 return s; 01514 01515 return libMesh::invalid_uint; 01516 } 01517 01518 01519 01520 inline 01521 unsigned int Elem::which_side_am_i (const Elem* e) const 01522 { 01523 libmesh_assert(e); 01524 01525 const unsigned int ns = this->n_sides(); 01526 const unsigned int nn = this->n_nodes(); 01527 01528 const unsigned int en = e->n_nodes(); 01529 01530 // e might be on any side until proven otherwise 01531 std::vector<bool> might_be_side(ns, true); 01532 01533 for (unsigned int i=0; i != en; ++i) 01534 { 01535 Point side_point = e->point(i); 01536 unsigned int local_node_id = libMesh::invalid_uint; 01537 01538 // Look for a node of this that's contiguous with node i of e 01539 for (unsigned int j=0; j != nn; ++j) 01540 if (this->point(j) == side_point) 01541 local_node_id = j; 01542 01543 // If a node of e isn't contiguous with some node of this, then 01544 // e isn't a side of this. 01545 if (local_node_id == libMesh::invalid_uint) 01546 return libMesh::invalid_uint; 01547 01548 // If a node of e isn't contiguous with some node on side s of 01549 // this, then e isn't on side s. 01550 for (unsigned int s=0; s != ns; ++s) 01551 if (!this->is_node_on_side(local_node_id, s)) 01552 might_be_side[s] = false; 01553 } 01554 01555 for (unsigned int s=0; s != ns; ++s) 01556 if (might_be_side[s]) 01557 { 01558 #ifdef DEBUG 01559 for (unsigned int s2=s+1; s2 < ns; ++s2) 01560 libmesh_assert (!might_be_side[s2]); 01561 #endif 01562 return s; 01563 } 01564 01565 // Didn't find any matching side 01566 return libMesh::invalid_uint; 01567 } 01568 01569 01570 01571 inline 01572 bool Elem::active() const 01573 { 01574 #ifdef LIBMESH_ENABLE_AMR 01575 if ((this->refinement_flag() == INACTIVE) || 01576 (this->refinement_flag() == COARSEN_INACTIVE)) 01577 return false; 01578 else 01579 return true; 01580 #else 01581 return true; 01582 #endif 01583 } 01584 01585 01586 01587 01588 01589 inline 01590 bool Elem::subactive() const 01591 { 01592 #ifdef LIBMESH_ENABLE_AMR 01593 if (this->active()) 01594 return false; 01595 if (!this->has_children()) 01596 return true; 01597 for (const Elem* my_ancestor = this->parent(); 01598 my_ancestor != NULL; 01599 my_ancestor = my_ancestor->parent()) 01600 if (my_ancestor->active()) 01601 return true; 01602 #endif 01603 01604 return false; 01605 } 01606 01607 01608 01609 inline 01610 bool Elem::has_children() const 01611 { 01612 #ifdef LIBMESH_ENABLE_AMR 01613 if (_children == NULL) 01614 return false; 01615 else 01616 return true; 01617 #else 01618 return false; 01619 #endif 01620 } 01621 01622 01623 inline 01624 bool Elem::has_ancestor_children() const 01625 { 01626 #ifdef LIBMESH_ENABLE_AMR 01627 if (_children == NULL) 01628 return false; 01629 else 01630 for (unsigned int c=0; c != this->n_children(); c++) 01631 if (this->child(c)->has_children()) 01632 return true; 01633 #endif 01634 return false; 01635 } 01636 01637 01638 01639 inline 01640 bool Elem::is_ancestor_of(const Elem * 01641 #ifdef LIBMESH_ENABLE_AMR 01642 descendant 01643 #endif 01644 ) const 01645 { 01646 #ifdef LIBMESH_ENABLE_AMR 01647 const Elem *e = descendant; 01648 while (e) 01649 { 01650 if (this == e) 01651 return true; 01652 e = e->parent(); 01653 } 01654 #endif 01655 return false; 01656 } 01657 01658 01659 01660 inline 01661 const Elem* Elem::parent () const 01662 { 01663 return _elemlinks[0]; 01664 } 01665 01666 01667 01668 inline 01669 Elem* Elem::parent () 01670 { 01671 return _elemlinks[0]; 01672 } 01673 01674 01675 01676 inline 01677 void Elem::set_parent (Elem *p) 01678 { 01679 _elemlinks[0] = p; 01680 } 01681 01682 01683 01684 inline 01685 const Elem* Elem::top_parent () const 01686 { 01687 const Elem* tp = this; 01688 01689 // Keep getting the element's parent 01690 // until that parent is at level-0 01691 while (tp->parent() != NULL) 01692 tp = tp->parent(); 01693 01694 libmesh_assert(tp); 01695 libmesh_assert_equal_to (tp->level(), 0); 01696 01697 return tp; 01698 } 01699 01700 01701 01702 inline 01703 const Elem* Elem::interior_parent () const 01704 { 01705 // interior parents make no sense for full-dimensional elements. 01706 libmesh_assert_less (this->dim(), LIBMESH_DIM); 01707 01708 // // and they [USED TO BE] only good for level-0 elements 01709 // if (this->level() != 0) 01710 // return this->parent()->interior_parent(); 01711 01712 // We store the interior_parent pointer after both the parent 01713 // neighbor and neighbor pointers 01714 Elem *interior_p = _elemlinks[1+this->n_sides()]; 01715 01716 // If we have an interior_parent, it had better be the 01717 // one-higher-dimensional interior element we are looking for. 01718 libmesh_assert (!interior_p || 01719 interior_p->dim() == (this->dim()+1)); 01720 01721 return interior_p; 01722 } 01723 01724 01725 01726 inline 01727 void Elem::set_interior_parent (Elem *p) 01728 { 01729 // interior parents make no sense for full-dimensional elements. 01730 libmesh_assert_less (this->dim(), LIBMESH_DIM); 01731 01732 // this had better be a one-higher-dimensional interior element 01733 libmesh_assert (!p || 01734 p->dim() == (this->dim()+1)); 01735 01736 _elemlinks[1+this->n_sides()] = p; 01737 } 01738 01739 01740 01741 inline 01742 unsigned int Elem::level() const 01743 { 01744 #ifdef LIBMESH_ENABLE_AMR 01745 01746 // if I don't have a parent I was 01747 // created directly from file 01748 // or by the user, so I am a 01749 // level-0 element 01750 if (this->parent() == NULL) 01751 return 0; 01752 01753 // if the parent and this element are of different 01754 // dimensionality we are at the same level as 01755 // the parent (e.g. we are the 2D side of a 01756 // 3D element) 01757 if (this->dim() != this->parent()->dim()) 01758 return this->parent()->level(); 01759 01760 // otherwise we are at a level one 01761 // higher than our parent 01762 return (this->parent()->level() + 1); 01763 01764 #else 01765 01766 // Without AMR all elements are 01767 // at level 0. 01768 return 0; 01769 01770 #endif 01771 } 01772 01773 01774 01775 inline 01776 unsigned int Elem::p_level() const 01777 { 01778 #ifdef LIBMESH_ENABLE_AMR 01779 return _p_level; 01780 #else 01781 return 0; 01782 #endif 01783 } 01784 01785 01786 01787 #ifdef LIBMESH_ENABLE_AMR 01788 01789 inline 01790 Elem* Elem::child (const unsigned int i) const 01791 { 01792 libmesh_assert(_children); 01793 libmesh_assert(_children[i]); 01794 01795 return _children[i]; 01796 } 01797 01798 01799 01800 inline 01801 void Elem::set_child (unsigned int c, Elem *elem) 01802 { 01803 libmesh_assert (this->has_children()); 01804 01805 _children[c] = elem; 01806 } 01807 01808 01809 01810 inline 01811 unsigned int Elem::which_child_am_i (const Elem* e) const 01812 { 01813 libmesh_assert(e); 01814 libmesh_assert (this->has_children()); 01815 01816 for (unsigned int c=0; c<this->n_children(); c++) 01817 if (this->child(c) == e) 01818 return c; 01819 01820 libMesh::err << "ERROR: which_child_am_i() was called with a non-child!" 01821 << std::endl; 01822 01823 libmesh_error(); 01824 01825 return libMesh::invalid_uint; 01826 } 01827 01828 01829 01830 inline 01831 Elem::RefinementState Elem::refinement_flag () const 01832 { 01833 return static_cast<RefinementState>(_rflag); 01834 } 01835 01836 01837 01838 inline 01839 void Elem::set_refinement_flag(RefinementState rflag) 01840 { 01841 _rflag = libmesh_cast_int<RefinementState>(rflag); 01842 } 01843 01844 01845 01846 inline 01847 Elem::RefinementState Elem::p_refinement_flag () const 01848 { 01849 return static_cast<RefinementState>(_pflag); 01850 } 01851 01852 01853 01854 inline 01855 void Elem::set_p_refinement_flag(RefinementState pflag) 01856 { 01857 _pflag = libmesh_cast_int<unsigned char>(pflag); 01858 } 01859 01860 01861 01862 inline 01863 unsigned int Elem::max_descendant_p_level () const 01864 { 01865 // This is undefined for subactive elements, 01866 // which have no active descendants 01867 libmesh_assert (!this->subactive()); 01868 if (this->active()) 01869 return this->p_level(); 01870 01871 unsigned int max_p_level = _p_level; 01872 for (unsigned int c=0; c != this->n_children(); c++) 01873 max_p_level = std::max(max_p_level, 01874 this->child(c)->max_descendant_p_level()); 01875 return max_p_level; 01876 } 01877 01878 01879 01880 inline 01881 void Elem::set_p_level(unsigned int p) 01882 { 01883 // Maintain the parent's p level as the minimum of it's children 01884 if (this->parent() != NULL) 01885 { 01886 unsigned int parent_p_level = this->parent()->p_level(); 01887 01888 // If our new p level is less than our parents, our parents drops 01889 if (parent_p_level > p) 01890 { 01891 this->parent()->set_p_level(p); 01892 } 01893 // If we are the lowest p level and it increases, so might 01894 // our parent's, but we have to check every other child to see 01895 else if (parent_p_level == _p_level && _p_level < p) 01896 { 01897 _p_level = libmesh_cast_int<unsigned char>(p); 01898 parent_p_level = libmesh_cast_int<unsigned char>(p); 01899 for (unsigned int c=0; c != this->parent()->n_children(); c++) 01900 parent_p_level = std::min(parent_p_level, 01901 this->parent()->child(c)->p_level()); 01902 01903 if (parent_p_level != this->parent()->p_level()) 01904 this->parent()->set_p_level(parent_p_level); 01905 01906 return; 01907 } 01908 } 01909 01910 _p_level = libmesh_cast_int<unsigned char>(p); 01911 } 01912 01913 01914 01915 inline 01916 void Elem::hack_p_level(unsigned int p) 01917 { 01918 _p_level = libmesh_cast_int<unsigned char>(p); 01919 } 01920 01921 01922 01923 #endif /* ifdef LIBMESH_ENABLE_AMR */ 01924 01925 01926 inline 01927 dof_id_type Elem::compute_key (dof_id_type n0) 01928 { 01929 return n0; 01930 } 01931 01932 01933 01934 inline 01935 dof_id_type Elem::compute_key (dof_id_type n0, 01936 dof_id_type n1) 01937 { 01938 // Order the two so that n0 < n1 01939 if (n0 > n1) std::swap (n0, n1); 01940 01941 return Utility::hashword2(n0, n1); 01942 } 01943 01944 01945 01946 inline 01947 dof_id_type Elem::compute_key (dof_id_type n0, 01948 dof_id_type n1, 01949 dof_id_type n2) 01950 { 01951 // Order the numbers such that n0 < n1 < n2. 01952 // We'll do it in 3 steps like this: 01953 // 01954 // n0 n1 n2 01955 // min(n0,n1) max(n0,n1) n2 01956 // min(n0,n1) min(n2,max(n0,n1) max(n2,max(n0,n1) 01957 // |\ /| | 01958 // | \ / | | 01959 // | / | | 01960 // | / \| | 01961 // gb min= min max gb max 01962 01963 // Step 1 01964 if (n0 > n1) std::swap (n0, n1); 01965 01966 // Step 2 01967 if (n1 > n2) std::swap (n1, n2); 01968 01969 // Step 3 01970 if (n0 > n1) std::swap (n0, n1); 01971 01972 libmesh_assert ((n0 < n1) && (n1 < n2)); 01973 01974 dof_id_type array[3] = {n0, n1, n2}; 01975 return Utility::hashword(array, 3); 01976 } 01977 01978 01979 01980 inline 01981 dof_id_type Elem::compute_key (dof_id_type n0, 01982 dof_id_type n1, 01983 dof_id_type n2, 01984 dof_id_type n3) 01985 { 01986 // Sort first 01987 // Step 1 01988 if (n0 > n1) std::swap (n0, n1); 01989 01990 // Step 2 01991 if (n2 > n3) std::swap (n2, n3); 01992 01993 // Step 3 01994 if (n0 > n2) std::swap (n0, n2); 01995 01996 // Step 4 01997 if (n1 > n3) std::swap (n1, n3); 01998 01999 // Finally sort step 5 02000 if (n1 > n2) std::swap (n1, n2); 02001 02002 libmesh_assert ((n0 < n1) && (n1 < n2) && (n2 < n3)); 02003 02004 dof_id_type array[4] = {n0, n1, n2, n3}; 02005 return Utility::hashword(array, 4); 02006 } 02007 02008 02009 02010 //----------------------------------------------------------------- 02019 class Elem::PackedElem 02020 { 02021 private: 02022 02026 const std::vector<int>::const_iterator _buf_begin; 02027 02028 public: 02029 02034 PackedElem (const std::vector<int>::const_iterator _buf_in) : 02035 _buf_begin(_buf_in) 02036 {} 02037 02042 static const unsigned int header_size; /* = 10 with AMR, 4 without */ 02043 02051 static void pack (std::vector<int> &conn, const Elem* elem); 02052 02058 Elem * unpack (MeshBase &mesh, Elem *parent = NULL) const; 02059 02063 unsigned int level () const 02064 { 02065 return static_cast<unsigned int>(*_buf_begin); 02066 } 02067 02071 unsigned int p_level () const 02072 { 02073 return static_cast<unsigned int>(*(_buf_begin+1)); 02074 } 02075 02076 #ifdef LIBMESH_ENABLE_AMR 02077 02080 Elem::RefinementState refinement_flag () const 02081 { 02082 libmesh_assert_greater_equal (*(_buf_begin+2), 0); 02083 libmesh_assert_less (*(_buf_begin+2), INVALID_REFINEMENTSTATE); 02084 return static_cast<Elem::RefinementState>(*(_buf_begin+2)); 02085 } 02086 02090 Elem::RefinementState p_refinement_flag () const 02091 { 02092 libmesh_assert_greater_equal (*(_buf_begin+3), 0); 02093 libmesh_assert_less (*(_buf_begin+3), INVALID_REFINEMENTSTATE); 02094 return static_cast<Elem::RefinementState>(*(_buf_begin+3)); 02095 } 02096 #endif // LIBMESH_ENABLE_AMR 02097 02101 ElemType type () const 02102 { 02103 libmesh_assert_greater_equal (*(_buf_begin+4), 0); 02104 libmesh_assert_less (*(_buf_begin+4), INVALID_ELEM); 02105 return static_cast<ElemType>(*(_buf_begin+4)); 02106 } 02107 02111 processor_id_type processor_id () const 02112 { 02113 libmesh_assert_greater_equal (*(_buf_begin+5), 0); 02114 libmesh_assert_less (static_cast<unsigned int>(*(_buf_begin+5)), 02115 libMesh::n_processors() || 02116 static_cast<processor_id_type>(*(_buf_begin+5)) == DofObject::invalid_processor_id); 02117 return static_cast<processor_id_type>(*(_buf_begin+5)); 02118 } 02119 02123 subdomain_id_type subdomain_id () const 02124 { 02125 return static_cast<subdomain_id_type>(*(_buf_begin+6)); 02126 } 02127 02131 dof_id_type id () const 02132 { 02133 return static_cast<dof_id_type>(*(_buf_begin+7)); 02134 } 02135 02139 int parent_id () const 02140 { 02141 return *(_buf_begin+8); 02142 } 02143 02147 unsigned int which_child_am_i () const 02148 { 02149 return static_cast<unsigned int>(*(_buf_begin+9)); 02150 } 02151 02155 unsigned int n_nodes () const 02156 { 02157 return Elem::type_to_n_nodes_map[this->type()]; 02158 } 02159 02163 unsigned int node (const unsigned int n) const 02164 { 02165 return static_cast<unsigned int>(*(_buf_begin+header_size+n)); 02166 } 02167 02171 unsigned int n_neighbors() const 02172 { 02173 return Elem::type_to_n_sides_map[this->type()]; 02174 } 02175 02179 unsigned int neighbor (const unsigned int n) const 02180 { 02181 return static_cast<unsigned int> 02182 (*(_buf_begin + header_size + this->n_nodes() + n)); 02183 } 02184 02185 02186 std::vector<int>::const_iterator indices() const 02187 { 02188 return _buf_begin + header_size + this->n_nodes() + 02189 this->n_neighbors(); 02190 } 02191 02192 unsigned int packed_size() const 02193 { 02194 return this->header_size + this->n_nodes() + 02195 this->n_neighbors() + 02196 DofObject::unpackable_indexing_size(this->indices()); 02197 } 02198 }; // end class PackedElem 02199 02203 class Elem::SideIter 02204 { 02205 public: 02206 // Constructor with arguments. 02207 SideIter(const unsigned int side_number, 02208 Elem* parent) 02209 : _side(), 02210 _side_ptr(NULL), 02211 _parent(parent), 02212 _side_number(side_number) 02213 {} 02214 02215 02216 // Empty constructor. 02217 SideIter() 02218 : _side(), 02219 _side_ptr(NULL), 02220 _parent(NULL), 02221 _side_number(libMesh::invalid_uint) 02222 {} 02223 02224 02225 // Copy constructor 02226 SideIter(const SideIter& other) 02227 : _side(), 02228 _side_ptr(NULL), 02229 _parent(other._parent), 02230 _side_number(other._side_number) 02231 {} 02232 02233 02234 // op= 02235 SideIter& operator=(const SideIter& other) 02236 { 02237 this->_parent = other._parent; 02238 this->_side_number = other._side_number; 02239 return *this; 02240 } 02241 02242 // unary op* 02243 Elem*& operator*() const 02244 { 02245 // Set the AutoPtr 02246 this->_update_side_ptr(); 02247 02248 // Return a reference to _side_ptr 02249 return this->_side_ptr; 02250 } 02251 02252 // op++ 02253 SideIter& operator++() 02254 { 02255 ++_side_number; 02256 return *this; 02257 } 02258 02259 // op== Two side iterators are equal if they have 02260 // the same side number and the same parent element. 02261 bool operator == (const SideIter& other) const 02262 { 02263 return (this->_side_number == other._side_number && 02264 this->_parent == other._parent); 02265 } 02266 02267 02268 // Consults the parent Elem to determine if the side 02269 // is a boundary side. Note: currently side N is a 02270 // boundary side if nieghbor N is NULL. Be careful, 02271 // this could possibly change in the future? 02272 bool side_on_boundary() const 02273 { 02274 return this->_parent->neighbor(_side_number) == NULL; 02275 } 02276 02277 private: 02278 // Update the _side pointer by building the correct side. 02279 // This has to be called before dereferencing. 02280 void _update_side_ptr() const 02281 { 02282 // Construct new side, store in AutoPtr 02283 this->_side = this->_parent->build_side(this->_side_number); 02284 02285 // Also set our internal naked pointer. Memory is still owned 02286 // by the AutoPtr. 02287 this->_side_ptr = _side.get(); 02288 } 02289 02290 // AutoPtr to the actual side, handles memory management for 02291 // the sides which are created during the course of iteration. 02292 mutable AutoPtr<Elem> _side; 02293 02294 // Raw pointer needed to facilitate passing back to the user a 02295 // reference to a non-temporary raw pointer in order to conform to 02296 // the variant_filter_iterator interface. It points to the same 02297 // thing the AutoPtr "_side" above holds. What happens if the user 02298 // calls delete on the pointer passed back? Well, this is an issue 02299 // which is not addressed by the iterators in libMesh. Basically it 02300 // is a bad idea to ever call delete on an iterator from the library. 02301 mutable Elem* _side_ptr; 02302 02303 // Pointer to the parent Elem class which generated this iterator 02304 Elem* _parent; 02305 02306 // A counter variable which keeps track of the side number 02307 unsigned int _side_number; 02308 02309 }; 02310 02311 02312 02313 02314 02315 02316 // Private implementation functions in the Elem class for the side iterators. 02317 // They have to come after the definition of the SideIter class. 02318 inline 02319 Elem::SideIter Elem::_first_side() 02320 { 02321 return SideIter(0, this); 02322 } 02323 02324 02325 02326 inline 02327 Elem::SideIter Elem::_last_side() 02328 { 02329 return SideIter(this->n_neighbors(), this); 02330 } 02331 02332 02333 02334 02338 struct 02339 Elem::side_iterator : 02340 variant_filter_iterator<Elem::Predicate, 02341 Elem*> 02342 { 02343 // Templated forwarding ctor -- forwards to appropriate variant_filter_iterator ctor 02344 template <typename PredType, typename IterType> 02345 side_iterator (const IterType& d, 02346 const IterType& e, 02347 const PredType& p ) : 02348 variant_filter_iterator<Elem::Predicate, 02349 Elem*>(d,e,p) {} 02350 }; 02351 02352 02353 inline 02354 unsigned int 02355 Elem::packed_size() const 02356 { 02357 return PackedElem::header_size + this->n_nodes() + 02358 this->n_neighbors() + this->packed_indexing_size(); 02359 } 02360 02361 02362 } // namespace libMesh 02363 02364 02365 #endif // LIBMESH_ELEM_H
Site Created By: libMesh Developers
Last modified: February 05 2013 19:54:46 UTC
Hosted By: