$extrastylesheet
00001 // The libMesh Finite Element Library. 00002 // Copyright (C) 2002-2014 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 00090 class Elem : public ReferenceCountedObject<Elem>, 00091 public DofObject 00092 { 00093 protected: 00094 00101 Elem (const unsigned int n_nodes, 00102 const unsigned int n_sides, 00103 Elem* parent, 00104 Elem** elemlinkdata, 00105 Node** nodelinkdata); 00106 00107 public: 00108 00112 virtual ~Elem(); 00113 00117 const Point & point (const unsigned int i) const; 00118 00123 Point & point (const unsigned int i); 00124 00128 dof_id_type node (const unsigned int i) const; 00129 00134 unsigned int local_node (const dof_id_type i) const; 00135 00140 unsigned int get_node_index (const Node* node_ptr) const; 00141 00145 const Node* const * get_nodes () const; 00146 00150 Node* get_node (const unsigned int i) const; 00151 00155 virtual Node* & set_node (const unsigned int i); 00156 00160 subdomain_id_type subdomain_id () const; 00161 00166 subdomain_id_type & subdomain_id (); 00167 00182 static const subdomain_id_type invalid_subdomain_id; 00183 00192 const Elem* reference_elem () const; 00193 00199 virtual dof_id_type key (const unsigned int s) const = 0; 00200 00207 bool operator == (const Elem& rhs) const; 00208 00216 Elem* neighbor (const unsigned int i) const; 00217 00218 #ifdef LIBMESH_ENABLE_PERIODIC 00219 00225 const Elem* topological_neighbor (const unsigned int i, 00226 const MeshBase& mesh, 00227 const PointLocatorBase& point_locator, 00228 const PeriodicBoundaries* pb) const; 00229 00236 Elem* topological_neighbor (const unsigned int i, 00237 MeshBase& mesh, 00238 const PointLocatorBase& point_locator, 00239 const PeriodicBoundaries* pb); 00240 00245 bool has_topological_neighbor (const Elem* elem, 00246 const MeshBase& mesh, 00247 const PointLocatorBase& point_locator, 00248 PeriodicBoundaries* pb) const; 00249 #endif 00250 00254 void set_neighbor (const unsigned int i, Elem* n); 00255 00260 bool has_neighbor (const Elem* elem) const; 00261 00267 Elem* child_neighbor (Elem* elem) const; 00268 00274 const Elem* child_neighbor (const Elem* elem) const; 00275 00281 bool on_boundary () const; 00282 00287 bool is_semilocal (const processor_id_type my_pid) const; 00288 00294 unsigned int which_neighbor_am_i(const Elem *e) const; 00295 00303 unsigned int which_side_am_i(const Elem *e) const; 00304 00309 bool contains_vertex_of(const Elem *e) const; 00310 00316 bool contains_edge_of(const Elem *e) const; 00317 00323 void find_point_neighbors(const Point &p, 00324 std::set<const Elem *> &neighbor_set) const; 00325 00330 void find_point_neighbors(std::set<const Elem *> &neighbor_set) const; 00331 00337 void find_edge_neighbors(const Point& p1, 00338 const Point& p2, 00339 std::set<const Elem *> &neighbor_set) const; 00340 00346 void find_edge_neighbors(std::set<const Elem *> &neighbor_set) const; 00347 00355 void make_links_to_me_remote (); 00356 00363 void make_links_to_me_local (unsigned int n); 00364 00375 virtual bool is_remote () const 00376 { return false; } 00377 00384 virtual void connectivity(const unsigned int sc, 00385 const IOPackage iop, 00386 std::vector<dof_id_type>& conn) const = 0; 00387 00395 void write_connectivity (std::ostream& out, 00396 const IOPackage iop) const; 00397 00398 // /** 00399 // * @returns the VTK element type of the sc-th sub-element. 00400 // */ 00401 // virtual unsigned int vtk_element_type (const unsigned int sc) const = 0; 00402 00407 virtual ElemType type () const = 0; 00408 00412 virtual unsigned int dim () const = 0; 00413 00418 static const unsigned int type_to_n_nodes_map[INVALID_ELEM]; 00419 00423 virtual unsigned int n_nodes () const = 0; 00424 00429 static const unsigned int type_to_n_sides_map[INVALID_ELEM]; 00430 00436 virtual unsigned int n_sides () const = 0; 00437 00444 virtual unsigned int n_neighbors () const 00445 { return this->n_sides(); } 00446 00451 virtual unsigned int n_vertices () const = 0; 00452 00457 virtual unsigned int n_edges () const = 0; 00458 00463 static const unsigned int type_to_n_edges_map[INVALID_ELEM]; 00464 00469 virtual unsigned int n_faces () const = 0; 00470 00475 virtual unsigned int n_children () const = 0; 00476 00480 virtual bool is_vertex(const unsigned int i) const = 0; 00481 00485 virtual bool is_edge(const unsigned int i) const = 0; 00486 00490 virtual bool is_face(const unsigned int i) const = 0; 00491 00492 /* 00493 * @returns true iff the specified (local) node number is on the 00494 * specified side 00495 */ 00496 virtual bool is_node_on_side(const unsigned int n, 00497 const unsigned int s) const = 0; 00498 00499 /* 00500 * @returns true iff the specified (local) node number is on the 00501 * specified edge 00502 */ 00503 virtual bool is_node_on_edge(const unsigned int n, 00504 const unsigned int e) const = 0; 00505 00506 /* 00507 * @returns true iff the specified edge is on the specified side 00508 */ 00509 virtual bool is_edge_on_side(const unsigned int e, 00510 const unsigned int s) const = 0; 00511 00512 /* 00513 * @returns the side number opposite to \p s (for a tensor product 00514 * element), or throws an error otherwise. 00515 */ 00516 virtual unsigned int opposite_side(const unsigned int s) const; 00517 00518 /* 00519 * @returns the local node number for the node opposite to node n 00520 * on side \p opposite_side(s) (for a tensor product element), or 00521 * throws an error otherwise. 00522 */ 00523 virtual unsigned int opposite_node(const unsigned int n, 00524 const unsigned int s) const; 00525 00526 // /** 00527 // * @returns the number of children this element has that 00528 // * share side \p s 00529 // */ 00530 // virtual unsigned int n_children_per_side (const unsigned int) const = 0; 00531 00537 virtual unsigned int n_sub_elem () const = 0; 00538 00547 virtual UniquePtr<Elem> side (const unsigned int i) const = 0; 00548 00565 virtual UniquePtr<Elem> build_side (const unsigned int i, 00566 bool proxy=true) const = 0; 00567 00576 virtual UniquePtr<Elem> build_edge (const unsigned int i) const = 0; 00577 00583 virtual Order default_order () const = 0; 00584 00591 virtual Point centroid () const; 00592 00596 virtual Real hmin () const; 00597 00601 virtual Real hmax () const; 00602 00606 virtual Real volume () const; 00607 00612 virtual Real quality (const ElemQuality q) const; 00613 00621 virtual std::pair<Real,Real> qual_bounds (const ElemQuality) const 00622 { libmesh_not_implemented(); return std::make_pair(0.,0.); } 00623 00639 virtual bool contains_point (const Point& p, Real tol=TOLERANCE) const; 00640 00645 virtual bool close_to_point(const Point& p, Real tol) const; 00646 00647 private: 00654 bool point_test(const Point& p, Real box_tol, Real map_tol) const; 00655 00656 public: 00661 virtual bool has_affine_map () const { return false; } 00662 00667 virtual bool is_linear () const { return false; } 00668 00672 void print_info (std::ostream& os=libMesh::out) const; 00673 00677 std::string get_info () const; 00678 00684 bool active () const; 00685 00691 bool ancestor () const; 00692 00698 bool subactive () const; 00699 00704 bool has_children () const; 00705 00711 bool has_ancestor_children () const; 00712 00718 bool is_ancestor_of(const Elem *descendant) const; 00719 00724 const Elem* parent () const; 00725 00730 Elem* parent (); 00731 00736 void set_parent (Elem *p); 00737 00744 const Elem* top_parent () const; 00745 00754 const Elem* interior_parent () const; 00755 00760 void set_interior_parent (Elem *p); 00761 00766 Real length (const unsigned int n1, 00767 const unsigned int n2) const; 00768 00777 virtual unsigned int n_second_order_adjacent_vertices (const unsigned int n) const; 00778 00786 virtual unsigned short int second_order_adjacent_vertex (const unsigned int n, 00787 const unsigned int v) const; 00788 00798 virtual std::pair<unsigned short int, unsigned short int> 00799 second_order_child_vertex (const unsigned int n) const; 00800 00812 static ElemType second_order_equivalent_type (const ElemType et, 00813 const bool full_ordered=true); 00814 00821 static ElemType first_order_equivalent_type (const ElemType et); 00822 00823 00830 unsigned int level () const; 00831 00837 unsigned int p_level () const; 00838 00839 #ifdef LIBMESH_ENABLE_AMR 00840 00845 enum RefinementState { COARSEN = 0, 00846 DO_NOTHING, 00847 REFINE, 00848 JUST_REFINED, 00849 JUST_COARSENED, 00850 INACTIVE, 00851 COARSEN_INACTIVE, 00852 INVALID_REFINEMENTSTATE }; 00853 00858 Elem* child (const unsigned int i) const; 00859 00860 private: 00865 void set_child (unsigned int c, Elem *elem); 00866 00867 public: 00873 unsigned int which_child_am_i(const Elem *e) const; 00874 00879 virtual bool is_child_on_side(const unsigned int c, 00880 const unsigned int s) const = 0; 00881 00886 virtual bool is_child_on_edge(const unsigned int c, 00887 const unsigned int e) const; 00888 00895 void add_child (Elem* elem); 00896 00903 void add_child (Elem* elem, unsigned int c); 00904 00909 void replace_child (Elem* elem, unsigned int c); 00910 00922 void family_tree (std::vector<const Elem*>& family, 00923 const bool reset=true) const; 00924 00929 void total_family_tree (std::vector<const Elem*>& active_family, 00930 const bool reset=true) const; 00931 00938 void active_family_tree (std::vector<const Elem*>& active_family, 00939 const bool reset=true) const; 00940 00945 void family_tree_by_side (std::vector<const Elem*>& family, 00946 const unsigned int side, 00947 const bool reset=true) const; 00948 00953 void active_family_tree_by_side (std::vector<const Elem*>& family, 00954 const unsigned int side, 00955 const bool reset=true) const; 00956 00961 void family_tree_by_neighbor (std::vector<const Elem*>& family, 00962 const Elem *neighbor, 00963 const bool reset=true) const; 00964 00971 void family_tree_by_subneighbor (std::vector<const Elem*>& family, 00972 const Elem *neighbor, 00973 const Elem *subneighbor, 00974 const bool reset=true) const; 00975 00980 void active_family_tree_by_neighbor (std::vector<const Elem*>& family, 00981 const Elem *neighbor, 00982 const bool reset=true) const; 00983 00987 RefinementState refinement_flag () const; 00988 00992 void set_refinement_flag (const RefinementState rflag); 00993 00997 RefinementState p_refinement_flag () const; 00998 01002 void set_p_refinement_flag (const RefinementState pflag); 01003 01008 unsigned int max_descendant_p_level () const; 01009 01015 unsigned int min_p_level_by_neighbor (const Elem* neighbor, 01016 unsigned int current_min) const; 01017 01024 unsigned int min_new_p_level_by_neighbor (const Elem* neighbor, 01025 unsigned int current_min) const; 01026 01031 void set_p_level (const unsigned int p); 01032 01037 void hack_p_level (const unsigned int p); 01038 01042 virtual void refine (MeshRefinement& mesh_refinement); 01043 01049 void coarsen (); 01050 01057 void contract (); 01058 01059 #endif 01060 01061 #ifdef DEBUG 01062 01066 void libmesh_assert_valid_neighbors() const; 01067 01072 void libmesh_assert_valid_node_pointers() const; 01073 #endif // DEBUG 01074 01075 protected: 01076 01087 class SideIter; 01088 01089 public: 01093 typedef Predicates::multi_predicate Predicate; 01094 //typedef variant_filter_iterator<Elem*, Predicate> side_iterator; 01095 01100 struct side_iterator; 01101 01105 side_iterator boundary_sides_begin(); 01106 side_iterator boundary_sides_end(); 01107 01108 private: 01113 SideIter _first_side(); 01114 SideIter _last_side(); 01115 01116 public: 01117 01118 #ifdef LIBMESH_ENABLE_INFINITE_ELEMENTS 01119 01124 virtual bool infinite () const = 0; 01125 01134 virtual Point origin () const { libmesh_not_implemented(); return Point(); } 01135 01136 #endif 01137 01138 01139 01140 01146 static UniquePtr<Elem> build (const ElemType type, 01147 Elem* p=NULL); 01148 01149 #ifdef LIBMESH_ENABLE_AMR 01150 01155 virtual float embedding_matrix (const unsigned int i, 01156 const unsigned int j, 01157 const unsigned int k) const = 0; 01158 01159 #endif 01160 01161 01162 protected: 01163 01164 //------------------------------------------------------- 01165 // These methods compute has keys from the specified 01166 // global node numbers 01167 // 01171 static dof_id_type compute_key (dof_id_type n0); 01172 01176 static dof_id_type compute_key (dof_id_type n0, 01177 dof_id_type n1); 01178 01182 static dof_id_type compute_key (dof_id_type n0, 01183 dof_id_type n1, 01184 dof_id_type n2); 01185 01189 static dof_id_type compute_key (dof_id_type n0, 01190 dof_id_type n1, 01191 dof_id_type n2, 01192 dof_id_type n3); 01193 //------------------------------------------------------- 01194 01195 01196 01197 public: 01198 01204 void nullify_neighbors (); 01205 01206 protected: 01207 01211 Node** _nodes; 01212 01217 Elem** _elemlinks; 01218 01219 #ifdef LIBMESH_ENABLE_AMR 01220 01223 Elem** _children; 01224 #endif 01225 01229 subdomain_id_type _sbd_id; 01230 01231 #ifdef LIBMESH_ENABLE_AMR 01232 01236 unsigned char _rflag; 01237 //RefinementState _rflag; 01238 01243 unsigned char _pflag; 01244 //RefinementState _pflag; 01245 01254 unsigned char _p_level; 01255 #endif 01256 }; 01257 01258 // ------------------------------------------------------------ 01259 // global Elem functions 01260 01261 inline 01262 std::ostream& operator << (std::ostream& os, const Elem& e) 01263 { 01264 e.print_info(os); 01265 return os; 01266 } 01267 01268 01269 // ------------------------------------------------------------ 01270 // Elem class member functions 01271 inline 01272 Elem::Elem(const unsigned int nn, 01273 const unsigned int ns, 01274 Elem* p, 01275 Elem** elemlinkdata, 01276 Node** nodelinkdata) : 01277 _nodes(nodelinkdata), 01278 _elemlinks(elemlinkdata), 01279 #ifdef LIBMESH_ENABLE_AMR 01280 _children(NULL), 01281 #endif 01282 _sbd_id(0) 01283 #ifdef LIBMESH_ENABLE_AMR 01284 , 01285 _rflag(Elem::DO_NOTHING), 01286 _pflag(Elem::DO_NOTHING), 01287 _p_level(0) 01288 #endif 01289 { 01290 this->processor_id() = DofObject::invalid_processor_id; 01291 01292 // Initialize the nodes data structure 01293 if (_nodes) 01294 { 01295 for (unsigned int n=0; n<nn; n++) 01296 _nodes[n] = NULL; 01297 } 01298 01299 // Initialize the neighbors/parent data structure 01300 // _elemlinks = new Elem*[ns+1]; 01301 01302 if (_elemlinks) 01303 { 01304 _elemlinks[0] = p; 01305 01306 for (unsigned int n=1; n<ns+1; n++) 01307 _elemlinks[n] = NULL; 01308 } 01309 01310 // Optionally initialize data from the parent 01311 if (this->parent() != NULL) 01312 { 01313 this->subdomain_id() = this->parent()->subdomain_id(); 01314 this->processor_id() = this->parent()->processor_id(); 01315 } 01316 01317 #ifdef LIBMESH_ENABLE_AMR 01318 if (this->parent()) 01319 this->set_p_level(this->parent()->p_level()); 01320 #endif 01321 } 01322 01323 01324 01325 inline 01326 Elem::~Elem() 01327 { 01328 // Deleting my parent/neighbor/nodes storage isn't necessary since it's 01329 // handled by the subclass 01330 01331 // if (_nodes != NULL) 01332 // delete [] _nodes; 01333 // _nodes = NULL; 01334 01335 // delete [] _elemlinks; 01336 01337 #ifdef LIBMESH_ENABLE_AMR 01338 01339 // Delete my children's storage 01340 if (_children != NULL) 01341 delete [] _children; 01342 _children = NULL; 01343 01344 #endif 01345 } 01346 01347 01348 01349 inline 01350 const Point & Elem::point (const unsigned int i) const 01351 { 01352 libmesh_assert_less (i, this->n_nodes()); 01353 libmesh_assert(_nodes[i]); 01354 libmesh_assert_not_equal_to (_nodes[i]->id(), Node::invalid_id); 01355 01356 return *_nodes[i]; 01357 } 01358 01359 01360 01361 inline 01362 Point & Elem::point (const unsigned int i) 01363 { 01364 libmesh_assert_less (i, this->n_nodes()); 01365 01366 return *_nodes[i]; 01367 } 01368 01369 01370 01371 inline 01372 dof_id_type Elem::node (const unsigned int i) const 01373 { 01374 libmesh_assert_less (i, this->n_nodes()); 01375 libmesh_assert(_nodes[i]); 01376 libmesh_assert_not_equal_to (_nodes[i]->id(), Node::invalid_id); 01377 01378 return _nodes[i]->id(); 01379 } 01380 01381 01382 01383 inline 01384 unsigned int Elem::local_node (const dof_id_type i) const 01385 { 01386 for (unsigned int n=0; n != this->n_nodes(); ++n) 01387 if (this->node(n) == i) 01388 return n; 01389 01390 return libMesh::invalid_uint; 01391 } 01392 01393 01394 01395 inline 01396 const Node * const * Elem::get_nodes () const 01397 { 01398 return _nodes; 01399 } 01400 01401 01402 01403 inline 01404 Node* Elem::get_node (const unsigned int i) const 01405 { 01406 libmesh_assert_less (i, this->n_nodes()); 01407 libmesh_assert(_nodes[i]); 01408 01409 return _nodes[i]; 01410 } 01411 01412 01413 01414 inline 01415 unsigned int Elem::get_node_index (const Node* node_ptr) const 01416 { 01417 for (unsigned int n=0; n != this->n_nodes(); ++n) 01418 if (this->_nodes[n] == node_ptr) 01419 return n; 01420 01421 return libMesh::invalid_uint; 01422 } 01423 01424 01425 01426 inline 01427 Node* & Elem::set_node (const unsigned int i) 01428 { 01429 libmesh_assert_less (i, this->n_nodes()); 01430 01431 return _nodes[i]; 01432 } 01433 01434 01435 01436 inline 01437 subdomain_id_type Elem::subdomain_id () const 01438 { 01439 return _sbd_id; 01440 } 01441 01442 01443 01444 inline 01445 subdomain_id_type & Elem::subdomain_id () 01446 { 01447 return _sbd_id; 01448 } 01449 01450 01451 01452 inline 01453 Elem* Elem::neighbor (const unsigned int i) const 01454 { 01455 libmesh_assert_less (i, this->n_neighbors()); 01456 01457 return _elemlinks[i+1]; 01458 } 01459 01460 01461 01462 inline 01463 void Elem::set_neighbor (const unsigned int i, Elem* n) 01464 { 01465 libmesh_assert_less (i, this->n_neighbors()); 01466 01467 _elemlinks[i+1] = n; 01468 } 01469 01470 01471 01472 inline 01473 bool Elem::has_neighbor (const Elem* elem) const 01474 { 01475 for (unsigned int n=0; n<this->n_neighbors(); n++) 01476 if (this->neighbor(n) == elem) 01477 return true; 01478 01479 return false; 01480 } 01481 01482 01483 01484 inline 01485 Elem* Elem::child_neighbor (Elem* elem) const 01486 { 01487 for (unsigned int n=0; n<elem->n_neighbors(); n++) 01488 if (elem->neighbor(n) && 01489 elem->neighbor(n)->parent() == this) 01490 return elem->neighbor(n); 01491 01492 return NULL; 01493 } 01494 01495 01496 01497 inline 01498 const Elem* Elem::child_neighbor (const Elem* elem) const 01499 { 01500 for (unsigned int n=0; n<elem->n_neighbors(); n++) 01501 if (elem->neighbor(n) && 01502 elem->neighbor(n)->parent() == this) 01503 return elem->neighbor(n); 01504 01505 return NULL; 01506 } 01507 01508 01509 01510 inline 01511 bool Elem::on_boundary () const 01512 { 01513 // By convention, the element is on the boundary 01514 // if it has a NULL neighbor. 01515 return this->has_neighbor(NULL); 01516 } 01517 01518 01519 01520 inline 01521 unsigned int Elem::which_neighbor_am_i (const Elem* e) const 01522 { 01523 libmesh_assert(e); 01524 01525 const Elem* eparent = e; 01526 01527 while (eparent->level() > this->level()) 01528 { 01529 eparent = eparent->parent(); 01530 libmesh_assert(eparent); 01531 } 01532 01533 for (unsigned int s=0; s<this->n_neighbors(); s++) 01534 if (this->neighbor(s) == eparent) 01535 return s; 01536 01537 return libMesh::invalid_uint; 01538 } 01539 01540 01541 01542 inline 01543 unsigned int Elem::which_side_am_i (const Elem* e) const 01544 { 01545 libmesh_assert(e); 01546 01547 const unsigned int ns = this->n_sides(); 01548 const unsigned int nn = this->n_nodes(); 01549 01550 const unsigned int en = e->n_nodes(); 01551 01552 // e might be on any side until proven otherwise 01553 std::vector<bool> might_be_side(ns, true); 01554 01555 for (unsigned int i=0; i != en; ++i) 01556 { 01557 Point side_point = e->point(i); 01558 unsigned int local_node_id = libMesh::invalid_uint; 01559 01560 // Look for a node of this that's contiguous with node i of e 01561 for (unsigned int j=0; j != nn; ++j) 01562 if (this->point(j) == side_point) 01563 local_node_id = j; 01564 01565 // If a node of e isn't contiguous with some node of this, then 01566 // e isn't a side of this. 01567 if (local_node_id == libMesh::invalid_uint) 01568 return libMesh::invalid_uint; 01569 01570 // If a node of e isn't contiguous with some node on side s of 01571 // this, then e isn't on side s. 01572 for (unsigned int s=0; s != ns; ++s) 01573 if (!this->is_node_on_side(local_node_id, s)) 01574 might_be_side[s] = false; 01575 } 01576 01577 for (unsigned int s=0; s != ns; ++s) 01578 if (might_be_side[s]) 01579 { 01580 #ifdef DEBUG 01581 for (unsigned int s2=s+1; s2 < ns; ++s2) 01582 libmesh_assert (!might_be_side[s2]); 01583 #endif 01584 return s; 01585 } 01586 01587 // Didn't find any matching side 01588 return libMesh::invalid_uint; 01589 } 01590 01591 01592 01593 inline 01594 bool Elem::active() const 01595 { 01596 #ifdef LIBMESH_ENABLE_AMR 01597 if ((this->refinement_flag() == INACTIVE) || 01598 (this->refinement_flag() == COARSEN_INACTIVE)) 01599 return false; 01600 else 01601 return true; 01602 #else 01603 return true; 01604 #endif 01605 } 01606 01607 01608 01609 01610 01611 inline 01612 bool Elem::subactive() const 01613 { 01614 #ifdef LIBMESH_ENABLE_AMR 01615 if (this->active()) 01616 return false; 01617 if (!this->has_children()) 01618 return true; 01619 for (const Elem* my_ancestor = this->parent(); 01620 my_ancestor != NULL; 01621 my_ancestor = my_ancestor->parent()) 01622 if (my_ancestor->active()) 01623 return true; 01624 #endif 01625 01626 return false; 01627 } 01628 01629 01630 01631 inline 01632 bool Elem::has_children() const 01633 { 01634 #ifdef LIBMESH_ENABLE_AMR 01635 if (_children == NULL) 01636 return false; 01637 else 01638 return true; 01639 #else 01640 return false; 01641 #endif 01642 } 01643 01644 01645 inline 01646 bool Elem::has_ancestor_children() const 01647 { 01648 #ifdef LIBMESH_ENABLE_AMR 01649 if (_children == NULL) 01650 return false; 01651 else 01652 for (unsigned int c=0; c != this->n_children(); c++) 01653 if (this->child(c)->has_children()) 01654 return true; 01655 #endif 01656 return false; 01657 } 01658 01659 01660 01661 inline 01662 bool Elem::is_ancestor_of(const Elem * 01663 #ifdef LIBMESH_ENABLE_AMR 01664 descendant 01665 #endif 01666 ) const 01667 { 01668 #ifdef LIBMESH_ENABLE_AMR 01669 const Elem *e = descendant; 01670 while (e) 01671 { 01672 if (this == e) 01673 return true; 01674 e = e->parent(); 01675 } 01676 #endif 01677 return false; 01678 } 01679 01680 01681 01682 inline 01683 const Elem* Elem::parent () const 01684 { 01685 return _elemlinks[0]; 01686 } 01687 01688 01689 01690 inline 01691 Elem* Elem::parent () 01692 { 01693 return _elemlinks[0]; 01694 } 01695 01696 01697 01698 inline 01699 void Elem::set_parent (Elem *p) 01700 { 01701 _elemlinks[0] = p; 01702 } 01703 01704 01705 01706 inline 01707 const Elem* Elem::top_parent () const 01708 { 01709 const Elem* tp = this; 01710 01711 // Keep getting the element's parent 01712 // until that parent is at level-0 01713 while (tp->parent() != NULL) 01714 tp = tp->parent(); 01715 01716 libmesh_assert(tp); 01717 libmesh_assert_equal_to (tp->level(), 0); 01718 01719 return tp; 01720 } 01721 01722 01723 01724 inline 01725 const Elem* Elem::interior_parent () const 01726 { 01727 // interior parents make no sense for full-dimensional elements. 01728 libmesh_assert_less (this->dim(), LIBMESH_DIM); 01729 01730 // // and they [USED TO BE] only good for level-0 elements 01731 // if (this->level() != 0) 01732 // return this->parent()->interior_parent(); 01733 01734 // We store the interior_parent pointer after both the parent 01735 // neighbor and neighbor pointers 01736 Elem *interior_p = _elemlinks[1+this->n_sides()]; 01737 01738 // If we have an interior_parent, it had better be the 01739 // one-higher-dimensional interior element we are looking for. 01740 libmesh_assert (!interior_p || 01741 interior_p->dim() == (this->dim()+1)); 01742 01743 return interior_p; 01744 } 01745 01746 01747 01748 inline 01749 void Elem::set_interior_parent (Elem *p) 01750 { 01751 // interior parents make no sense for full-dimensional elements. 01752 libmesh_assert_less (this->dim(), LIBMESH_DIM); 01753 01754 // this had better be a one-higher-dimensional interior element 01755 libmesh_assert (!p || 01756 p->dim() == (this->dim()+1)); 01757 01758 _elemlinks[1+this->n_sides()] = p; 01759 } 01760 01761 01762 01763 inline 01764 unsigned int Elem::level() const 01765 { 01766 #ifdef LIBMESH_ENABLE_AMR 01767 01768 // if I don't have a parent I was 01769 // created directly from file 01770 // or by the user, so I am a 01771 // level-0 element 01772 if (this->parent() == NULL) 01773 return 0; 01774 01775 // if the parent and this element are of different 01776 // dimensionality we are at the same level as 01777 // the parent (e.g. we are the 2D side of a 01778 // 3D element) 01779 if (this->dim() != this->parent()->dim()) 01780 return this->parent()->level(); 01781 01782 // otherwise we are at a level one 01783 // higher than our parent 01784 return (this->parent()->level() + 1); 01785 01786 #else 01787 01788 // Without AMR all elements are 01789 // at level 0. 01790 return 0; 01791 01792 #endif 01793 } 01794 01795 01796 01797 inline 01798 unsigned int Elem::p_level() const 01799 { 01800 #ifdef LIBMESH_ENABLE_AMR 01801 return _p_level; 01802 #else 01803 return 0; 01804 #endif 01805 } 01806 01807 01808 01809 #ifdef LIBMESH_ENABLE_AMR 01810 01811 inline 01812 Elem* Elem::child (const unsigned int i) const 01813 { 01814 libmesh_assert(_children); 01815 libmesh_assert(_children[i]); 01816 01817 return _children[i]; 01818 } 01819 01820 01821 01822 inline 01823 void Elem::set_child (unsigned int c, Elem *elem) 01824 { 01825 libmesh_assert (this->has_children()); 01826 01827 _children[c] = elem; 01828 } 01829 01830 01831 01832 inline 01833 unsigned int Elem::which_child_am_i (const Elem* e) const 01834 { 01835 libmesh_assert(e); 01836 libmesh_assert (this->has_children()); 01837 01838 for (unsigned int c=0; c<this->n_children(); c++) 01839 if (this->child(c) == e) 01840 return c; 01841 01842 libmesh_error_msg("ERROR: which_child_am_i() was called with a non-child!"); 01843 01844 return libMesh::invalid_uint; 01845 } 01846 01847 01848 01849 inline 01850 Elem::RefinementState Elem::refinement_flag () const 01851 { 01852 return static_cast<RefinementState>(_rflag); 01853 } 01854 01855 01856 01857 inline 01858 void Elem::set_refinement_flag(RefinementState rflag) 01859 { 01860 _rflag = cast_int<RefinementState>(rflag); 01861 } 01862 01863 01864 01865 inline 01866 Elem::RefinementState Elem::p_refinement_flag () const 01867 { 01868 return static_cast<RefinementState>(_pflag); 01869 } 01870 01871 01872 01873 inline 01874 void Elem::set_p_refinement_flag(RefinementState pflag) 01875 { 01876 _pflag = cast_int<unsigned char>(pflag); 01877 } 01878 01879 01880 01881 inline 01882 unsigned int Elem::max_descendant_p_level () const 01883 { 01884 // This is undefined for subactive elements, 01885 // which have no active descendants 01886 libmesh_assert (!this->subactive()); 01887 if (this->active()) 01888 return this->p_level(); 01889 01890 unsigned int max_p_level = _p_level; 01891 for (unsigned int c=0; c != this->n_children(); c++) 01892 max_p_level = std::max(max_p_level, 01893 this->child(c)->max_descendant_p_level()); 01894 return max_p_level; 01895 } 01896 01897 01898 01899 inline 01900 void Elem::set_p_level(unsigned int p) 01901 { 01902 // Maintain the parent's p level as the minimum of it's children 01903 if (this->parent() != NULL) 01904 { 01905 unsigned int parent_p_level = this->parent()->p_level(); 01906 01907 // If our new p level is less than our parents, our parents drops 01908 if (parent_p_level > p) 01909 { 01910 this->parent()->set_p_level(p); 01911 } 01912 // If we are the lowest p level and it increases, so might 01913 // our parent's, but we have to check every other child to see 01914 else if (parent_p_level == _p_level && _p_level < p) 01915 { 01916 _p_level = cast_int<unsigned char>(p); 01917 parent_p_level = cast_int<unsigned char>(p); 01918 for (unsigned int c=0; c != this->parent()->n_children(); c++) 01919 parent_p_level = std::min(parent_p_level, 01920 this->parent()->child(c)->p_level()); 01921 01922 if (parent_p_level != this->parent()->p_level()) 01923 this->parent()->set_p_level(parent_p_level); 01924 01925 return; 01926 } 01927 } 01928 01929 _p_level = cast_int<unsigned char>(p); 01930 } 01931 01932 01933 01934 inline 01935 void Elem::hack_p_level(unsigned int p) 01936 { 01937 _p_level = cast_int<unsigned char>(p); 01938 } 01939 01940 01941 01942 #endif /* ifdef LIBMESH_ENABLE_AMR */ 01943 01944 01945 inline 01946 dof_id_type Elem::compute_key (dof_id_type n0) 01947 { 01948 return n0; 01949 } 01950 01951 01952 01953 inline 01954 dof_id_type Elem::compute_key (dof_id_type n0, 01955 dof_id_type n1) 01956 { 01957 // Order the two so that n0 < n1 01958 if (n0 > n1) std::swap (n0, n1); 01959 01960 return Utility::hashword2(n0, n1); 01961 } 01962 01963 01964 01965 inline 01966 dof_id_type Elem::compute_key (dof_id_type n0, 01967 dof_id_type n1, 01968 dof_id_type n2) 01969 { 01970 // Order the numbers such that n0 < n1 < n2. 01971 // We'll do it in 3 steps like this: 01972 // 01973 // n0 n1 n2 01974 // min(n0,n1) max(n0,n1) n2 01975 // min(n0,n1) min(n2,max(n0,n1) max(n2,max(n0,n1) 01976 // |\ /| | 01977 // | \ / | | 01978 // | / | | 01979 // | / \| | 01980 // gb min= min max gb max 01981 01982 // Step 1 01983 if (n0 > n1) std::swap (n0, n1); 01984 01985 // Step 2 01986 if (n1 > n2) std::swap (n1, n2); 01987 01988 // Step 3 01989 if (n0 > n1) std::swap (n0, n1); 01990 01991 libmesh_assert ((n0 < n1) && (n1 < n2)); 01992 01993 dof_id_type array[3] = {n0, n1, n2}; 01994 return Utility::hashword(array, 3); 01995 } 01996 01997 01998 01999 inline 02000 dof_id_type Elem::compute_key (dof_id_type n0, 02001 dof_id_type n1, 02002 dof_id_type n2, 02003 dof_id_type n3) 02004 { 02005 // Sort first 02006 // Step 1 02007 if (n0 > n1) std::swap (n0, n1); 02008 02009 // Step 2 02010 if (n2 > n3) std::swap (n2, n3); 02011 02012 // Step 3 02013 if (n0 > n2) std::swap (n0, n2); 02014 02015 // Step 4 02016 if (n1 > n3) std::swap (n1, n3); 02017 02018 // Finally sort step 5 02019 if (n1 > n2) std::swap (n1, n2); 02020 02021 libmesh_assert ((n0 < n1) && (n1 < n2) && (n2 < n3)); 02022 02023 dof_id_type array[4] = {n0, n1, n2, n3}; 02024 return Utility::hashword(array, 4); 02025 } 02026 02027 02028 02032 class Elem::SideIter 02033 { 02034 public: 02035 // Constructor with arguments. 02036 SideIter(const unsigned int side_number, 02037 Elem* parent) 02038 : _side(), 02039 _side_ptr(NULL), 02040 _parent(parent), 02041 _side_number(side_number) 02042 {} 02043 02044 02045 // Empty constructor. 02046 SideIter() 02047 : _side(), 02048 _side_ptr(NULL), 02049 _parent(NULL), 02050 _side_number(libMesh::invalid_uint) 02051 {} 02052 02053 02054 // Copy constructor 02055 SideIter(const SideIter& other) 02056 : _side(), 02057 _side_ptr(NULL), 02058 _parent(other._parent), 02059 _side_number(other._side_number) 02060 {} 02061 02062 02063 // op= 02064 SideIter& operator=(const SideIter& other) 02065 { 02066 this->_parent = other._parent; 02067 this->_side_number = other._side_number; 02068 return *this; 02069 } 02070 02071 // unary op* 02072 Elem*& operator*() const 02073 { 02074 // Set the UniquePtr 02075 this->_update_side_ptr(); 02076 02077 // Return a reference to _side_ptr 02078 return this->_side_ptr; 02079 } 02080 02081 // op++ 02082 SideIter& operator++() 02083 { 02084 ++_side_number; 02085 return *this; 02086 } 02087 02088 // op== Two side iterators are equal if they have 02089 // the same side number and the same parent element. 02090 bool operator == (const SideIter& other) const 02091 { 02092 return (this->_side_number == other._side_number && 02093 this->_parent == other._parent); 02094 } 02095 02096 02097 // Consults the parent Elem to determine if the side 02098 // is a boundary side. Note: currently side N is a 02099 // boundary side if nieghbor N is NULL. Be careful, 02100 // this could possibly change in the future? 02101 bool side_on_boundary() const 02102 { 02103 return this->_parent->neighbor(_side_number) == NULL; 02104 } 02105 02106 private: 02107 // Update the _side pointer by building the correct side. 02108 // This has to be called before dereferencing. 02109 void _update_side_ptr() const 02110 { 02111 // Construct new side, store in UniquePtr 02112 this->_side = this->_parent->build_side(this->_side_number); 02113 02114 // Also set our internal naked pointer. Memory is still owned 02115 // by the UniquePtr. 02116 this->_side_ptr = _side.get(); 02117 } 02118 02119 // UniquePtr to the actual side, handles memory management for 02120 // the sides which are created during the course of iteration. 02121 mutable UniquePtr<Elem> _side; 02122 02123 // Raw pointer needed to facilitate passing back to the user a 02124 // reference to a non-temporary raw pointer in order to conform to 02125 // the variant_filter_iterator interface. It points to the same 02126 // thing the UniquePtr "_side" above holds. What happens if the user 02127 // calls delete on the pointer passed back? Well, this is an issue 02128 // which is not addressed by the iterators in libMesh. Basically it 02129 // is a bad idea to ever call delete on an iterator from the library. 02130 mutable Elem* _side_ptr; 02131 02132 // Pointer to the parent Elem class which generated this iterator 02133 Elem* _parent; 02134 02135 // A counter variable which keeps track of the side number 02136 unsigned int _side_number; 02137 02138 }; 02139 02140 02141 02142 02143 02144 02145 // Private implementation functions in the Elem class for the side iterators. 02146 // They have to come after the definition of the SideIter class. 02147 inline 02148 Elem::SideIter Elem::_first_side() 02149 { 02150 return SideIter(0, this); 02151 } 02152 02153 02154 02155 inline 02156 Elem::SideIter Elem::_last_side() 02157 { 02158 return SideIter(this->n_neighbors(), this); 02159 } 02160 02161 02162 02163 02167 struct 02168 Elem::side_iterator : 02169 variant_filter_iterator<Elem::Predicate, 02170 Elem*> 02171 { 02172 // Templated forwarding ctor -- forwards to appropriate variant_filter_iterator ctor 02173 template <typename PredType, typename IterType> 02174 side_iterator (const IterType& d, 02175 const IterType& e, 02176 const PredType& p ) : 02177 variant_filter_iterator<Elem::Predicate, 02178 Elem*>(d,e,p) {} 02179 }; 02180 02181 02182 } // namespace libMesh 02183 02184 02185 #endif // LIBMESH_ELEM_H