elem.h
Go to the documentation of this file.
1 // The libMesh Finite Element Library.
2 // Copyright (C) 2002-2014 Benjamin S. Kirk, John W. Peterson, Roy H. Stogner
3 
4 // This library is free software; you can redistribute it and/or
5 // modify it under the terms of the GNU Lesser General Public
6 // License as published by the Free Software Foundation; either
7 // version 2.1 of the License, or (at your option) any later version.
8 
9 // This library is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 // Lesser General Public License for more details.
13 
14 // You should have received a copy of the GNU Lesser General Public
15 // License along with this library; if not, write to the Free Software
16 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 
18 
19 
20 #ifndef LIBMESH_ELEM_H
21 #define LIBMESH_ELEM_H
22 
23 // Local includes
24 #include "libmesh/libmesh_common.h"
25 #include "libmesh/dof_object.h"
26 #include "libmesh/id_types.h"
28 #include "libmesh/node.h"
29 #include "libmesh/enum_elem_type.h"
31 #include "libmesh/enum_order.h"
33 #include "libmesh/auto_ptr.h"
36 #include "libmesh/hashword.h" // Used in compute_key() functions
37 
38 // C++ includes
39 #include <algorithm>
40 #include <cstddef>
41 #include <iostream>
42 #include <limits.h> // CHAR_BIT
43 #include <set>
44 #include <vector>
45 
46 namespace libMesh
47 {
48 
49 // Forward declarations
50 class MeshBase;
51 class MeshRefinement;
52 class Elem;
53 #ifdef LIBMESH_ENABLE_PERIODIC
54 class PeriodicBoundaries;
55 class PointLocatorBase;
56 #endif
57 
91 // ------------------------------------------------------------
92 // Elem class definition
93 class Elem : public ReferenceCountedObject<Elem>,
94  public DofObject
95 {
96  protected:
97 
104  Elem (const unsigned int n_nodes,
105  const unsigned int n_sides,
106  Elem* parent,
107  Elem** elemlinkdata,
108  Node** nodelinkdata);
109 
110  public:
111 
115  virtual ~Elem();
116 
120  virtual const Point & point (const unsigned int i) const;
121 
126  virtual Point & point (const unsigned int i);
127 
131  virtual dof_id_type node (const unsigned int i) const;
132 
137  virtual unsigned int local_node (const dof_id_type i) const;
138 
143  unsigned int get_node_index (const Node* node_ptr) const;
144 
148  virtual Node* get_node (const unsigned int i) const;
149 
153  virtual Node* & set_node (const unsigned int i);
154 
159 
165 
174  const Elem* reference_elem () const;
175 
181  virtual dof_id_type key (const unsigned int s) const = 0;
182 
189  bool operator == (const Elem& rhs) const;
190 
198  Elem* neighbor (const unsigned int i) const;
199 
200 #ifdef LIBMESH_ENABLE_PERIODIC
201 
207  const Elem* topological_neighbor (const unsigned int i,
208  const MeshBase& mesh,
209  const PointLocatorBase& point_locator,
210  const PeriodicBoundaries* pb) const;
211 
218  Elem* topological_neighbor (const unsigned int i,
219  MeshBase& mesh,
220  const PointLocatorBase& point_locator,
221  const PeriodicBoundaries* pb);
222 
227  bool has_topological_neighbor (const Elem* elem,
228  const MeshBase& mesh,
229  const PointLocatorBase& point_locator,
230  PeriodicBoundaries* pb) const;
231 #endif
232 
236  void set_neighbor (const unsigned int i, Elem* n);
237 
242  bool has_neighbor (const Elem* elem) const;
243 
249  Elem* child_neighbor (Elem* elem) const;
250 
256  const Elem* child_neighbor (const Elem* elem) const;
257 
263  bool on_boundary () const;
264 
269  bool is_semilocal (const processor_id_type my_pid) const;
270 
276  unsigned int which_neighbor_am_i(const Elem *e) const;
277 
285  unsigned int which_side_am_i(const Elem *e) const;
286 
291  bool contains_vertex_of(const Elem *e) const;
292 
298  bool contains_edge_of(const Elem *e) const;
299 
305  void find_point_neighbors(const Point &p,
306  std::set<const Elem *> &neighbor_set) const;
307 
312  void find_point_neighbors(std::set<const Elem *> &neighbor_set) const;
313 
319  void find_edge_neighbors(const Point& p1,
320  const Point& p2,
321  std::set<const Elem *> &neighbor_set) const;
322 
328  void find_edge_neighbors(std::set<const Elem *> &neighbor_set) const;
329 
337  void make_links_to_me_remote ();
338 
345  void make_links_to_me_local (unsigned int n);
346 
357  virtual bool is_remote () const
358  { return false; }
359 
366  virtual void connectivity(const unsigned int sc,
367  const IOPackage iop,
368  std::vector<dof_id_type>& conn) const = 0;
369 
377  void write_connectivity (std::ostream& out,
378  const IOPackage iop) const;
379 
380 // /**
381 // * @returns the VTK element type of the sc-th sub-element.
382 // */
383 // virtual unsigned int vtk_element_type (const unsigned int sc) const = 0;
384 
389  virtual ElemType type () const = 0;
390 
394  virtual unsigned int dim () const = 0;
395 
400  static const unsigned int type_to_n_nodes_map[INVALID_ELEM];
401 
405  virtual unsigned int n_nodes () const = 0;
406 
411  static const unsigned int type_to_n_sides_map[INVALID_ELEM];
412 
418  virtual unsigned int n_sides () const = 0;
419 
426  virtual unsigned int n_neighbors () const
427  { return this->n_sides(); }
428 
433  virtual unsigned int n_vertices () const = 0;
434 
439  virtual unsigned int n_edges () const = 0;
440 
445  static const unsigned int type_to_n_edges_map[INVALID_ELEM];
446 
451  virtual unsigned int n_faces () const = 0;
452 
457  virtual unsigned int n_children () const = 0;
458 
462  virtual bool is_vertex(const unsigned int i) const = 0;
463 
467  virtual bool is_edge(const unsigned int i) const = 0;
468 
472  virtual bool is_face(const unsigned int i) const = 0;
473 
474  /*
475  * @returns true iff the specified (local) node number is on the
476  * specified side
477  */
478  virtual bool is_node_on_side(const unsigned int n,
479  const unsigned int s) const = 0;
480 
481  /*
482  * @returns true iff the specified (local) node number is on the
483  * specified edge
484  */
485  virtual bool is_node_on_edge(const unsigned int n,
486  const unsigned int e) const = 0;
487 
488  /*
489  * @returns true iff the specified edge is on the specified side
490  */
491  virtual bool is_edge_on_side(const unsigned int e,
492  const unsigned int s) const = 0;
493 
494  /*
495  * @returns the side number opposite to \p s (for a tensor product
496  * element), or throws an error otherwise.
497  */
498  virtual unsigned int opposite_side(const unsigned int s) const;
499 
500  /*
501  * @returns the local node number for the node opposite to node n
502  * on side \p opposite_side(s) (for a tensor product element), or
503  * throws an error otherwise.
504  */
505  virtual unsigned int opposite_node(const unsigned int n,
506  const unsigned int s) const;
507 
508 // /**
509 // * @returns the number of children this element has that
510 // * share side \p s
511 // */
512 // virtual unsigned int n_children_per_side (const unsigned int) const = 0;
513 
519  virtual unsigned int n_sub_elem () const = 0;
520 
529  virtual AutoPtr<Elem> side (const unsigned int i) const = 0;
530 
547  virtual AutoPtr<Elem> build_side (const unsigned int i,
548  bool proxy=true) const = 0;
549 
558  virtual AutoPtr<Elem> build_edge (const unsigned int i) const = 0;
559 
565  virtual Order default_order () const = 0;
566 
573  virtual Point centroid () const;
574 
578  virtual Real hmin () const;
579 
583  virtual Real hmax () const;
584 
588  virtual Real volume () const;
589 
594  virtual Real quality (const ElemQuality q) const;
595 
603  virtual std::pair<Real,Real> qual_bounds (const ElemQuality) const
604  { libmesh_error(); return std::make_pair(0.,0.); }
605 
621  virtual bool contains_point (const Point& p, Real tol=TOLERANCE) const;
622 
627  virtual bool close_to_point(const Point& p, Real tol) const;
628 
629 private:
636  bool point_test(const Point& p, Real box_tol, Real map_tol) const;
637 
638 public:
643  virtual bool has_affine_map () const { return false; }
644 
649  virtual bool is_linear () const { return false; }
650 
654  void print_info (std::ostream& os=libMesh::out) const;
655 
659  std::string get_info () const;
660 
666  bool active () const;
667 
673  bool ancestor () const;
674 
680  bool subactive () const;
681 
686  bool has_children () const;
687 
693  bool has_ancestor_children () const;
694 
700  bool is_ancestor_of(const Elem *descendant) const;
701 
706  const Elem* parent () const;
707 
712  Elem* parent ();
713 
718  void set_parent (Elem *p);
719 
726  const Elem* top_parent () const;
727 
736  const Elem* interior_parent () const;
737 
742  void set_interior_parent (Elem *p);
743 
748  Real length (const unsigned int n1,
749  const unsigned int n2) const;
750 
759  virtual unsigned int n_second_order_adjacent_vertices (const unsigned int n) const;
760 
768  virtual unsigned short int second_order_adjacent_vertex (const unsigned int n,
769  const unsigned int v) const;
770 
780  virtual std::pair<unsigned short int, unsigned short int>
781  second_order_child_vertex (const unsigned int n) const;
782 
795  const bool full_ordered=true);
796 
804 
805 
812  unsigned int level () const;
813 
819  unsigned int p_level () const;
820 
821 #ifdef LIBMESH_ENABLE_AMR
822 
835 
840  Elem* child (const unsigned int i) const;
841 
842 private:
847  void set_child (unsigned int c, Elem *elem);
848 
849 public:
855  unsigned int which_child_am_i(const Elem *e) const;
856 
861  virtual bool is_child_on_side(const unsigned int c,
862  const unsigned int s) const = 0;
863 
868  virtual bool is_child_on_edge(const unsigned int c,
869  const unsigned int e) const;
870 
877  void add_child (Elem* elem);
878 
885  void add_child (Elem* elem, unsigned int c);
886 
891  void replace_child (Elem* elem, unsigned int c);
892 
904  void family_tree (std::vector<const Elem*>& family,
905  const bool reset=true) const;
906 
911  void total_family_tree (std::vector<const Elem*>& active_family,
912  const bool reset=true) const;
913 
920  void active_family_tree (std::vector<const Elem*>& active_family,
921  const bool reset=true) const;
922 
927  void family_tree_by_side (std::vector<const Elem*>& family,
928  const unsigned int side,
929  const bool reset=true) const;
930 
935  void active_family_tree_by_side (std::vector<const Elem*>& family,
936  const unsigned int side,
937  const bool reset=true) const;
938 
943  void family_tree_by_neighbor (std::vector<const Elem*>& family,
944  const Elem *neighbor,
945  const bool reset=true) const;
946 
953  void family_tree_by_subneighbor (std::vector<const Elem*>& family,
954  const Elem *neighbor,
955  const Elem *subneighbor,
956  const bool reset=true) const;
957 
962  void active_family_tree_by_neighbor (std::vector<const Elem*>& family,
963  const Elem *neighbor,
964  const bool reset=true) const;
965 
970 
974  void set_refinement_flag (const RefinementState rflag);
975 
980 
984  void set_p_refinement_flag (const RefinementState pflag);
985 
990  unsigned int max_descendant_p_level () const;
991 
997  unsigned int min_p_level_by_neighbor (const Elem* neighbor,
998  unsigned int current_min) const;
999 
1006  unsigned int min_new_p_level_by_neighbor (const Elem* neighbor,
1007  unsigned int current_min) const;
1008 
1013  void set_p_level (const unsigned int p);
1014 
1019  void hack_p_level (const unsigned int p);
1020 
1024  virtual void refine (MeshRefinement& mesh_refinement);
1025 
1031  void coarsen ();
1032 
1039  void contract ();
1040 
1041 #endif
1042 
1043 #ifdef DEBUG
1044 
1048  void libmesh_assert_valid_neighbors() const;
1049 
1055 #endif // DEBUG
1056 
1057 protected:
1058 
1069  class SideIter;
1070 
1071 public:
1076  //typedef variant_filter_iterator<Elem*, Predicate> side_iterator;
1077 
1082  struct side_iterator;
1083 
1089 
1090 private:
1096  SideIter _last_side();
1097 
1098 public:
1099 
1100 #ifdef LIBMESH_ENABLE_INFINITE_ELEMENTS
1101 
1106  virtual bool infinite () const = 0;
1107 
1116  virtual Point origin () const { libmesh_error(); return Point(); }
1117 
1118 #endif
1119 
1120 
1121 
1122 
1128  static AutoPtr<Elem> build (const ElemType type,
1129  Elem* p=NULL);
1130 
1131 #ifdef LIBMESH_ENABLE_AMR
1132 
1137  virtual float embedding_matrix (const unsigned int i,
1138  const unsigned int j,
1139  const unsigned int k) const = 0;
1140 
1141 #endif
1142 
1143 
1144  //--------------------------------------------------------
1153  class PackedElem;
1154 
1155  unsigned int packed_size() const;
1156 
1157  protected:
1158 
1159  //-------------------------------------------------------
1160  // These methods compute has keys from the specified
1161  // global node numbers
1162  //
1166  static dof_id_type compute_key (dof_id_type n0);
1167 
1171  static dof_id_type compute_key (dof_id_type n0,
1172  dof_id_type n1);
1173 
1177  static dof_id_type compute_key (dof_id_type n0,
1178  dof_id_type n1,
1179  dof_id_type n2);
1180 
1184  static dof_id_type compute_key (dof_id_type n0,
1185  dof_id_type n1,
1186  dof_id_type n2,
1187  dof_id_type n3);
1188  //-------------------------------------------------------
1189 
1190 
1191 
1197  void nullify_neighbors ();
1198 
1203 
1209 
1210 #ifdef LIBMESH_ENABLE_AMR
1211 
1216 
1221  unsigned char _rflag;
1222  //RefinementState _rflag;
1223 
1228  unsigned char _pflag;
1229  //RefinementState _pflag;
1230 
1239  unsigned char _p_level;
1240 
1241 #endif
1242 
1247 
1259  friend class MeshRefinement; // (Elem::nullify_neighbors)
1260 };
1261 
1262 // ------------------------------------------------------------
1263 // global Elem functions
1264 
1265 inline
1266 std::ostream& operator << (std::ostream& os, const Elem& e)
1267 {
1268  e.print_info(os);
1269  return os;
1270 }
1271 
1272 
1273 // ------------------------------------------------------------
1274 // Elem class member functions
1275 inline
1276 Elem::Elem(const unsigned int nn,
1277  const unsigned int ns,
1278  Elem* p,
1279  Elem** elemlinkdata,
1280  Node** nodelinkdata) :
1281  _nodes(nodelinkdata),
1282  _elemlinks(elemlinkdata),
1283 #ifdef LIBMESH_ENABLE_AMR
1284  _children(NULL),
1285  _rflag(Elem::DO_NOTHING),
1286  _pflag(Elem::DO_NOTHING),
1287  _p_level(0),
1288 #endif
1289  _sbd_id(0)
1290 {
1292 
1293  // Initialize the nodes data structure
1294  if (_nodes)
1295  {
1296  for (unsigned int n=0; n<nn; n++)
1297  _nodes[n] = NULL;
1298  }
1299 
1300  // Initialize the neighbors/parent data structure
1301  // _elemlinks = new Elem*[ns+1];
1302 
1303  if (_elemlinks)
1304  {
1305  _elemlinks[0] = p;
1306 
1307  for (unsigned int n=1; n<ns+1; n++)
1308  _elemlinks[n] = NULL;
1309  }
1310 
1311  // Optionally initialize data from the parent
1312  if (this->parent() != NULL)
1313  {
1314  this->subdomain_id() = this->parent()->subdomain_id();
1315  this->processor_id() = this->parent()->processor_id();
1316  }
1317 
1318 #ifdef LIBMESH_ENABLE_AMR
1319  if (this->parent())
1320  this->set_p_level(this->parent()->p_level());
1321 #endif
1322 }
1323 
1324 
1325 
1326 inline
1328 {
1329  // Deleting my parent/neighbor/nodes storage isn't necessary since it's
1330  // handled by the subclass
1331 
1332  // if (_nodes != NULL)
1333  // delete [] _nodes;
1334  // _nodes = NULL;
1335 
1336  // delete [] _elemlinks;
1337 
1338 #ifdef LIBMESH_ENABLE_AMR
1339 
1340  // Delete my children's storage
1341  if (_children != NULL)
1342  delete [] _children;
1343  _children = NULL;
1344 
1345 #endif
1346 }
1347 
1348 
1349 
1350 inline
1351 const Point & Elem::point (const unsigned int i) const
1352 {
1353  libmesh_assert_less (i, this->n_nodes());
1354  libmesh_assert(_nodes[i]);
1355  libmesh_assert_not_equal_to (_nodes[i]->id(), Node::invalid_id);
1356 
1357  return *_nodes[i];
1358 }
1359 
1360 
1361 
1362 inline
1363 Point & Elem::point (const unsigned int i)
1364 {
1365  libmesh_assert_less (i, this->n_nodes());
1366 
1367  return *_nodes[i];
1368 }
1369 
1370 
1371 
1372 inline
1373 dof_id_type Elem::node (const unsigned int i) const
1374 {
1375  libmesh_assert_less (i, this->n_nodes());
1376  libmesh_assert(_nodes[i]);
1377  libmesh_assert_not_equal_to (_nodes[i]->id(), Node::invalid_id);
1378 
1379  return _nodes[i]->id();
1380 }
1381 
1382 
1383 
1384 inline
1385 unsigned int Elem::local_node (const dof_id_type i) const
1386 {
1387  for (unsigned int n=0; n != this->n_nodes(); ++n)
1388  if (this->node(n) == i)
1389  return n;
1390 
1391  return libMesh::invalid_uint;
1392 }
1393 
1394 
1395 
1396 inline
1397 Node* Elem::get_node (const unsigned int i) const
1398 {
1399  libmesh_assert_less (i, this->n_nodes());
1400  libmesh_assert(_nodes[i]);
1401 
1402  return _nodes[i];
1403 }
1404 
1405 
1406 
1407 inline
1408 unsigned int Elem::get_node_index (const Node* node_ptr) const
1409 {
1410  for (unsigned int n=0; n != this->n_nodes(); ++n)
1411  if (this->_nodes[n] == node_ptr)
1412  return n;
1413 
1414  return libMesh::invalid_uint;
1415 }
1416 
1417 
1418 
1419 inline
1420 Node* & Elem::set_node (const unsigned int i)
1421 {
1422  libmesh_assert_less (i, this->n_nodes());
1423 
1424  return _nodes[i];
1425 }
1426 
1427 
1428 
1429 inline
1431 {
1432  return _sbd_id;
1433 }
1434 
1435 
1436 
1437 inline
1439 {
1440  return _sbd_id;
1441 }
1442 
1443 
1444 
1445 inline
1446 Elem* Elem::neighbor (const unsigned int i) const
1447 {
1448  libmesh_assert_less (i, this->n_neighbors());
1449 
1450  return _elemlinks[i+1];
1451 }
1452 
1453 
1454 
1455 inline
1456 void Elem::set_neighbor (const unsigned int i, Elem* n)
1457 {
1458  libmesh_assert_less (i, this->n_neighbors());
1459 
1460  _elemlinks[i+1] = n;
1461 }
1462 
1463 
1464 
1465 inline
1466 bool Elem::has_neighbor (const Elem* elem) const
1467 {
1468  for (unsigned int n=0; n<this->n_neighbors(); n++)
1469  if (this->neighbor(n) == elem)
1470  return true;
1471 
1472  return false;
1473 }
1474 
1475 
1476 
1477 inline
1479 {
1480  for (unsigned int n=0; n<elem->n_neighbors(); n++)
1481  if (elem->neighbor(n) &&
1482  elem->neighbor(n)->parent() == this)
1483  return elem->neighbor(n);
1484 
1485  return NULL;
1486 }
1487 
1488 
1489 
1490 inline
1491 const Elem* Elem::child_neighbor (const Elem* elem) const
1492 {
1493  for (unsigned int n=0; n<elem->n_neighbors(); n++)
1494  if (elem->neighbor(n) &&
1495  elem->neighbor(n)->parent() == this)
1496  return elem->neighbor(n);
1497 
1498  return NULL;
1499 }
1500 
1501 
1502 
1503 inline
1504 bool Elem::on_boundary () const
1505 {
1506  // By convention, the element is on the boundary
1507  // if it has a NULL neighbor.
1508  return this->has_neighbor(NULL);
1509 }
1510 
1511 
1512 
1513 inline
1514 unsigned int Elem::which_neighbor_am_i (const Elem* e) const
1515 {
1516  libmesh_assert(e);
1517 
1518  const Elem* eparent = e;
1519 
1520  while (eparent->level() > this->level())
1521  {
1522  eparent = eparent->parent();
1523  libmesh_assert(eparent);
1524  }
1525 
1526  for (unsigned int s=0; s<this->n_neighbors(); s++)
1527  if (this->neighbor(s) == eparent)
1528  return s;
1529 
1530  return libMesh::invalid_uint;
1531 }
1532 
1533 
1534 
1535 inline
1536 unsigned int Elem::which_side_am_i (const Elem* e) const
1537 {
1538  libmesh_assert(e);
1539 
1540  const unsigned int ns = this->n_sides();
1541  const unsigned int nn = this->n_nodes();
1542 
1543  const unsigned int en = e->n_nodes();
1544 
1545  // e might be on any side until proven otherwise
1546  std::vector<bool> might_be_side(ns, true);
1547 
1548  for (unsigned int i=0; i != en; ++i)
1549  {
1550  Point side_point = e->point(i);
1551  unsigned int local_node_id = libMesh::invalid_uint;
1552 
1553  // Look for a node of this that's contiguous with node i of e
1554  for (unsigned int j=0; j != nn; ++j)
1555  if (this->point(j) == side_point)
1556  local_node_id = j;
1557 
1558  // If a node of e isn't contiguous with some node of this, then
1559  // e isn't a side of this.
1560  if (local_node_id == libMesh::invalid_uint)
1561  return libMesh::invalid_uint;
1562 
1563  // If a node of e isn't contiguous with some node on side s of
1564  // this, then e isn't on side s.
1565  for (unsigned int s=0; s != ns; ++s)
1566  if (!this->is_node_on_side(local_node_id, s))
1567  might_be_side[s] = false;
1568  }
1569 
1570  for (unsigned int s=0; s != ns; ++s)
1571  if (might_be_side[s])
1572  {
1573 #ifdef DEBUG
1574  for (unsigned int s2=s+1; s2 < ns; ++s2)
1575  libmesh_assert (!might_be_side[s2]);
1576 #endif
1577  return s;
1578  }
1579 
1580  // Didn't find any matching side
1581  return libMesh::invalid_uint;
1582 }
1583 
1584 
1585 
1586 inline
1587 bool Elem::active() const
1588 {
1589 #ifdef LIBMESH_ENABLE_AMR
1590  if ((this->refinement_flag() == INACTIVE) ||
1591  (this->refinement_flag() == COARSEN_INACTIVE))
1592  return false;
1593  else
1594  return true;
1595 #else
1596  return true;
1597 #endif
1598 }
1599 
1600 
1601 
1602 
1603 
1604 inline
1605 bool Elem::subactive() const
1606 {
1607 #ifdef LIBMESH_ENABLE_AMR
1608  if (this->active())
1609  return false;
1610  if (!this->has_children())
1611  return true;
1612  for (const Elem* my_ancestor = this->parent();
1613  my_ancestor != NULL;
1614  my_ancestor = my_ancestor->parent())
1615  if (my_ancestor->active())
1616  return true;
1617 #endif
1618 
1619  return false;
1620 }
1621 
1622 
1623 
1624 inline
1626 {
1627 #ifdef LIBMESH_ENABLE_AMR
1628  if (_children == NULL)
1629  return false;
1630  else
1631  return true;
1632 #else
1633  return false;
1634 #endif
1635 }
1636 
1637 
1638 inline
1640 {
1641 #ifdef LIBMESH_ENABLE_AMR
1642  if (_children == NULL)
1643  return false;
1644  else
1645  for (unsigned int c=0; c != this->n_children(); c++)
1646  if (this->child(c)->has_children())
1647  return true;
1648 #endif
1649  return false;
1650 }
1651 
1652 
1653 
1654 inline
1656 #ifdef LIBMESH_ENABLE_AMR
1657  descendant
1658 #endif
1659  ) const
1660 {
1661 #ifdef LIBMESH_ENABLE_AMR
1662  const Elem *e = descendant;
1663  while (e)
1664  {
1665  if (this == e)
1666  return true;
1667  e = e->parent();
1668  }
1669 #endif
1670  return false;
1671 }
1672 
1673 
1674 
1675 inline
1676 const Elem* Elem::parent () const
1677 {
1678  return _elemlinks[0];
1679 }
1680 
1681 
1682 
1683 inline
1685 {
1686  return _elemlinks[0];
1687 }
1688 
1689 
1690 
1691 inline
1693 {
1694  _elemlinks[0] = p;
1695 }
1696 
1697 
1698 
1699 inline
1700 const Elem* Elem::top_parent () const
1701 {
1702  const Elem* tp = this;
1703 
1704  // Keep getting the element's parent
1705  // until that parent is at level-0
1706  while (tp->parent() != NULL)
1707  tp = tp->parent();
1708 
1709  libmesh_assert(tp);
1710  libmesh_assert_equal_to (tp->level(), 0);
1711 
1712  return tp;
1713 }
1714 
1715 
1716 
1717 inline
1719 {
1720  // interior parents make no sense for full-dimensional elements.
1721  libmesh_assert_less (this->dim(), LIBMESH_DIM);
1722 
1723  // // and they [USED TO BE] only good for level-0 elements
1724  // if (this->level() != 0)
1725  // return this->parent()->interior_parent();
1726 
1727  // We store the interior_parent pointer after both the parent
1728  // neighbor and neighbor pointers
1729  Elem *interior_p = _elemlinks[1+this->n_sides()];
1730 
1731  // If we have an interior_parent, it had better be the
1732  // one-higher-dimensional interior element we are looking for.
1733  libmesh_assert (!interior_p ||
1734  interior_p->dim() == (this->dim()+1));
1735 
1736  return interior_p;
1737 }
1738 
1739 
1740 
1741 inline
1743 {
1744  // interior parents make no sense for full-dimensional elements.
1745  libmesh_assert_less (this->dim(), LIBMESH_DIM);
1746 
1747  // this had better be a one-higher-dimensional interior element
1748  libmesh_assert (!p ||
1749  p->dim() == (this->dim()+1));
1750 
1751  _elemlinks[1+this->n_sides()] = p;
1752 }
1753 
1754 
1755 
1756 inline
1757 unsigned int Elem::level() const
1758 {
1759 #ifdef LIBMESH_ENABLE_AMR
1760 
1761  // if I don't have a parent I was
1762  // created directly from file
1763  // or by the user, so I am a
1764  // level-0 element
1765  if (this->parent() == NULL)
1766  return 0;
1767 
1768  // if the parent and this element are of different
1769  // dimensionality we are at the same level as
1770  // the parent (e.g. we are the 2D side of a
1771  // 3D element)
1772  if (this->dim() != this->parent()->dim())
1773  return this->parent()->level();
1774 
1775  // otherwise we are at a level one
1776  // higher than our parent
1777  return (this->parent()->level() + 1);
1778 
1779 #else
1780 
1781  // Without AMR all elements are
1782  // at level 0.
1783  return 0;
1784 
1785 #endif
1786 }
1787 
1788 
1789 
1790 inline
1791 unsigned int Elem::p_level() const
1792 {
1793 #ifdef LIBMESH_ENABLE_AMR
1794  return _p_level;
1795 #else
1796  return 0;
1797 #endif
1798 }
1799 
1800 
1801 
1802 #ifdef LIBMESH_ENABLE_AMR
1803 
1804 inline
1805 Elem* Elem::child (const unsigned int i) const
1806 {
1809 
1810  return _children[i];
1811 }
1812 
1813 
1814 
1815 inline
1816 void Elem::set_child (unsigned int c, Elem *elem)
1817 {
1818  libmesh_assert (this->has_children());
1819 
1820  _children[c] = elem;
1821 }
1822 
1823 
1824 
1825 inline
1826 unsigned int Elem::which_child_am_i (const Elem* e) const
1827 {
1828  libmesh_assert(e);
1829  libmesh_assert (this->has_children());
1830 
1831  for (unsigned int c=0; c<this->n_children(); c++)
1832  if (this->child(c) == e)
1833  return c;
1834 
1835  libMesh::err << "ERROR: which_child_am_i() was called with a non-child!"
1836  << std::endl;
1837 
1838  libmesh_error();
1839 
1840  return libMesh::invalid_uint;
1841 }
1842 
1843 
1844 
1845 inline
1847 {
1848  return static_cast<RefinementState>(_rflag);
1849 }
1850 
1851 
1852 
1853 inline
1855 {
1856  _rflag = libmesh_cast_int<RefinementState>(rflag);
1857 }
1858 
1859 
1860 
1861 inline
1863 {
1864  return static_cast<RefinementState>(_pflag);
1865 }
1866 
1867 
1868 
1869 inline
1871 {
1872  _pflag = libmesh_cast_int<unsigned char>(pflag);
1873 }
1874 
1875 
1876 
1877 inline
1878 unsigned int Elem::max_descendant_p_level () const
1879 {
1880  // This is undefined for subactive elements,
1881  // which have no active descendants
1882  libmesh_assert (!this->subactive());
1883  if (this->active())
1884  return this->p_level();
1885 
1886  unsigned int max_p_level = _p_level;
1887  for (unsigned int c=0; c != this->n_children(); c++)
1888  max_p_level = std::max(max_p_level,
1889  this->child(c)->max_descendant_p_level());
1890  return max_p_level;
1891 }
1892 
1893 
1894 
1895 inline
1896 void Elem::set_p_level(unsigned int p)
1897 {
1898  // Maintain the parent's p level as the minimum of it's children
1899  if (this->parent() != NULL)
1900  {
1901  unsigned int parent_p_level = this->parent()->p_level();
1902 
1903  // If our new p level is less than our parents, our parents drops
1904  if (parent_p_level > p)
1905  {
1906  this->parent()->set_p_level(p);
1907  }
1908  // If we are the lowest p level and it increases, so might
1909  // our parent's, but we have to check every other child to see
1910  else if (parent_p_level == _p_level && _p_level < p)
1911  {
1912  _p_level = libmesh_cast_int<unsigned char>(p);
1913  parent_p_level = libmesh_cast_int<unsigned char>(p);
1914  for (unsigned int c=0; c != this->parent()->n_children(); c++)
1915  parent_p_level = std::min(parent_p_level,
1916  this->parent()->child(c)->p_level());
1917 
1918  if (parent_p_level != this->parent()->p_level())
1919  this->parent()->set_p_level(parent_p_level);
1920 
1921  return;
1922  }
1923  }
1924 
1925  _p_level = libmesh_cast_int<unsigned char>(p);
1926 }
1927 
1928 
1929 
1930 inline
1931 void Elem::hack_p_level(unsigned int p)
1932 {
1933  _p_level = libmesh_cast_int<unsigned char>(p);
1934 }
1935 
1936 
1937 
1938 #endif /* ifdef LIBMESH_ENABLE_AMR */
1939 
1940 
1941 inline
1943 {
1944  return n0;
1945 }
1946 
1947 
1948 
1949 inline
1951  dof_id_type n1)
1952 {
1953  // Order the two so that n0 < n1
1954  if (n0 > n1) std::swap (n0, n1);
1955 
1956  return Utility::hashword2(n0, n1);
1957 }
1958 
1959 
1960 
1961 inline
1963  dof_id_type n1,
1964  dof_id_type n2)
1965 {
1966  // Order the numbers such that n0 < n1 < n2.
1967  // We'll do it in 3 steps like this:
1968  //
1969  // n0 n1 n2
1970  // min(n0,n1) max(n0,n1) n2
1971  // min(n0,n1) min(n2,max(n0,n1) max(n2,max(n0,n1)
1972  // |\ /| |
1973  // | \ / | |
1974  // | / | |
1975  // | / \| |
1976  // gb min= min max gb max
1977 
1978  // Step 1
1979  if (n0 > n1) std::swap (n0, n1);
1980 
1981  // Step 2
1982  if (n1 > n2) std::swap (n1, n2);
1983 
1984  // Step 3
1985  if (n0 > n1) std::swap (n0, n1);
1986 
1987  libmesh_assert ((n0 < n1) && (n1 < n2));
1988 
1989  dof_id_type array[3] = {n0, n1, n2};
1990  return Utility::hashword(array, 3);
1991 }
1992 
1993 
1994 
1995 inline
1997  dof_id_type n1,
1998  dof_id_type n2,
1999  dof_id_type n3)
2000 {
2001  // Sort first
2002  // Step 1
2003  if (n0 > n1) std::swap (n0, n1);
2004 
2005  // Step 2
2006  if (n2 > n3) std::swap (n2, n3);
2007 
2008  // Step 3
2009  if (n0 > n2) std::swap (n0, n2);
2010 
2011  // Step 4
2012  if (n1 > n3) std::swap (n1, n3);
2013 
2014  // Finally sort step 5
2015  if (n1 > n2) std::swap (n1, n2);
2016 
2017  libmesh_assert ((n0 < n1) && (n1 < n2) && (n2 < n3));
2018 
2019  dof_id_type array[4] = {n0, n1, n2, n3};
2020  return Utility::hashword(array, 4);
2021 }
2022 
2023 
2024 
2025 //-----------------------------------------------------------------
2035 {
2036 private:
2037 
2041  const std::vector<largest_id_type>::const_iterator _buf_begin;
2042 
2043 public:
2044 
2049  PackedElem (const std::vector<largest_id_type>::const_iterator _buf_in) :
2050  _buf_begin(_buf_in)
2051  {}
2052 
2057  static const unsigned int header_size; /* = 10 with AMR, 4 without */
2058 
2066  static void pack (std::vector<largest_id_type> &conn, const Elem* elem);
2067 
2073  Elem * unpack (MeshBase &mesh, Elem *parent = NULL) const;
2074 
2078  unsigned int level () const
2079  {
2080  return static_cast<unsigned int>(*_buf_begin);
2081  }
2082 
2086  unsigned int p_level () const
2087  {
2088  return static_cast<unsigned int>(*(_buf_begin+1));
2089  }
2090 
2091 #ifdef LIBMESH_ENABLE_AMR
2092 
2096  {
2097  // libmesh_assert_greater_equal (*(_buf_begin+2), 0);
2098  libmesh_assert_less (*(_buf_begin+2), INVALID_REFINEMENTSTATE);
2099  return static_cast<Elem::RefinementState>(*(_buf_begin+2));
2100  }
2101 
2106  {
2107  // libmesh_assert_greater_equal (*(_buf_begin+3), 0);
2108  libmesh_assert_less (*(_buf_begin+3), INVALID_REFINEMENTSTATE);
2109  return static_cast<Elem::RefinementState>(*(_buf_begin+3));
2110  }
2111 #endif // LIBMESH_ENABLE_AMR
2112 
2116  ElemType type () const
2117  {
2118  // libmesh_assert_greater_equal (*(_buf_begin+4), 0);
2119  libmesh_assert_less (*(_buf_begin+4), INVALID_ELEM);
2120  return static_cast<ElemType>(*(_buf_begin+4));
2121  }
2122 
2127  {
2128  // libmesh_assert_greater_equal (*(_buf_begin+5), 0);
2129  libmesh_assert_less (static_cast<unsigned int>(*(_buf_begin+5)),
2131  static_cast<processor_id_type>(*(_buf_begin+5)) == DofObject::invalid_processor_id);
2132  return static_cast<processor_id_type>(*(_buf_begin+5));
2133  }
2134 
2139  {
2140  return static_cast<subdomain_id_type>(*(_buf_begin+6));
2141  }
2142 
2146  dof_id_type id () const
2147  {
2148  return static_cast<dof_id_type>(*(_buf_begin+7));
2149  }
2150 
2154  int parent_id () const
2155  {
2156  return *(_buf_begin+8);
2157  }
2158 
2162  unsigned int which_child_am_i () const
2163  {
2164  return static_cast<unsigned int>(*(_buf_begin+9));
2165  }
2166 
2170  unsigned int n_nodes () const
2171  {
2172  return Elem::type_to_n_nodes_map[this->type()];
2173  }
2174 
2178  unsigned int node (const unsigned int n) const
2179  {
2180  return static_cast<unsigned int>(*(_buf_begin+header_size+n));
2181  }
2182 
2186  unsigned int n_neighbors() const
2187  {
2188  return Elem::type_to_n_sides_map[this->type()];
2189  }
2190 
2194  unsigned int neighbor (const unsigned int n) const
2195  {
2196  return static_cast<unsigned int>
2197  (*(_buf_begin + header_size + this->n_nodes() + n));
2198  }
2199 
2200 
2201  std::vector<largest_id_type>::const_iterator indices() const
2202  {
2203  return _buf_begin + header_size + this->n_nodes() +
2204  this->n_neighbors();
2205  }
2206 
2207  unsigned int packed_size() const
2208  {
2209  return this->header_size + this->n_nodes() +
2210  this->n_neighbors() +
2212  }
2213 }; // end class PackedElem
2214 
2219 {
2220 public:
2221  // Constructor with arguments.
2222  SideIter(const unsigned int side_number,
2223  Elem* parent)
2224  : _side(),
2225  _side_ptr(NULL),
2226  _parent(parent),
2227  _side_number(side_number)
2228  {}
2229 
2230 
2231  // Empty constructor.
2233  : _side(),
2234  _side_ptr(NULL),
2235  _parent(NULL),
2236  _side_number(libMesh::invalid_uint)
2237  {}
2238 
2239 
2240  // Copy constructor
2241  SideIter(const SideIter& other)
2242  : _side(),
2243  _side_ptr(NULL),
2244  _parent(other._parent),
2245  _side_number(other._side_number)
2246  {}
2247 
2248 
2249  // op=
2250  SideIter& operator=(const SideIter& other)
2251  {
2252  this->_parent = other._parent;
2253  this->_side_number = other._side_number;
2254  return *this;
2255  }
2256 
2257  // unary op*
2258  Elem*& operator*() const
2259  {
2260  // Set the AutoPtr
2261  this->_update_side_ptr();
2262 
2263  // Return a reference to _side_ptr
2264  return this->_side_ptr;
2265  }
2266 
2267  // op++
2269  {
2270  ++_side_number;
2271  return *this;
2272  }
2273 
2274  // op== Two side iterators are equal if they have
2275  // the same side number and the same parent element.
2276  bool operator == (const SideIter& other) const
2277  {
2278  return (this->_side_number == other._side_number &&
2279  this->_parent == other._parent);
2280  }
2281 
2282 
2283  // Consults the parent Elem to determine if the side
2284  // is a boundary side. Note: currently side N is a
2285  // boundary side if nieghbor N is NULL. Be careful,
2286  // this could possibly change in the future?
2287  bool side_on_boundary() const
2288  {
2289  return this->_parent->neighbor(_side_number) == NULL;
2290  }
2291 
2292 private:
2293  // Update the _side pointer by building the correct side.
2294  // This has to be called before dereferencing.
2295  void _update_side_ptr() const
2296  {
2297  // Construct new side, store in AutoPtr
2298  this->_side = this->_parent->build_side(this->_side_number);
2299 
2300  // Also set our internal naked pointer. Memory is still owned
2301  // by the AutoPtr.
2302  this->_side_ptr = _side.get();
2303  }
2304 
2305  // AutoPtr to the actual side, handles memory management for
2306  // the sides which are created during the course of iteration.
2308 
2309  // Raw pointer needed to facilitate passing back to the user a
2310  // reference to a non-temporary raw pointer in order to conform to
2311  // the variant_filter_iterator interface. It points to the same
2312  // thing the AutoPtr "_side" above holds. What happens if the user
2313  // calls delete on the pointer passed back? Well, this is an issue
2314  // which is not addressed by the iterators in libMesh. Basically it
2315  // is a bad idea to ever call delete on an iterator from the library.
2316  mutable Elem* _side_ptr;
2317 
2318  // Pointer to the parent Elem class which generated this iterator
2320 
2321  // A counter variable which keeps track of the side number
2322  unsigned int _side_number;
2323 
2324 };
2325 
2326 
2327 
2328 
2329 
2330 
2331 // Private implementation functions in the Elem class for the side iterators.
2332 // They have to come after the definition of the SideIter class.
2333 inline
2335 {
2336  return SideIter(0, this);
2337 }
2338 
2339 
2340 
2341 inline
2343 {
2344  return SideIter(this->n_neighbors(), this);
2345 }
2346 
2347 
2348 
2349 
2353 struct
2356  Elem*>
2357 {
2358  // Templated forwarding ctor -- forwards to appropriate variant_filter_iterator ctor
2359  template <typename PredType, typename IterType>
2360  side_iterator (const IterType& d,
2361  const IterType& e,
2362  const PredType& p ) :
2364  Elem*>(d,e,p) {}
2365 };
2366 
2367 
2368 inline
2369 unsigned int
2371 {
2372  return PackedElem::header_size + this->n_nodes() +
2373  this->n_neighbors() + this->packed_indexing_size();
2374 }
2375 
2376 
2377 } // namespace libMesh
2378 
2379 
2380 #endif // LIBMESH_ELEM_H

Site Created By: libMesh Developers
Last modified: February 07 2014 16:57:04 UTC

Hosted By:
SourceForge.net Logo