$extrastylesheet
elem.h
Go to the documentation of this file.
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