Loading [MathJax]/extensions/tex2jax.js
libMesh
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Pages
elem.C
Go to the documentation of this file.
1 // The libMesh Finite Element Library.
2 // Copyright (C) 2002-2025 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 // Local includes
20 #include "libmesh/elem.h"
21 
22 #include "libmesh/boundary_info.h"
23 #include "libmesh/fe_type.h"
24 #include "libmesh/fe_interface.h"
25 #include "libmesh/node_elem.h"
26 #include "libmesh/edge_edge2.h"
27 #include "libmesh/edge_edge3.h"
28 #include "libmesh/edge_edge4.h"
29 #include "libmesh/edge_inf_edge2.h"
30 #include "libmesh/face_c0polygon.h"
31 #include "libmesh/face_tri3.h"
32 #include "libmesh/face_tri3_subdivision.h"
33 #include "libmesh/face_tri3_shell.h"
34 #include "libmesh/face_tri6.h"
35 #include "libmesh/face_tri7.h"
36 #include "libmesh/face_quad4.h"
37 #include "libmesh/face_quad4_shell.h"
38 #include "libmesh/face_quad8.h"
39 #include "libmesh/face_quad8_shell.h"
40 #include "libmesh/face_quad9.h"
41 #include "libmesh/face_quad9_shell.h"
42 #include "libmesh/face_inf_quad4.h"
43 #include "libmesh/face_inf_quad6.h"
44 #include "libmesh/cell_tet4.h"
45 #include "libmesh/cell_tet10.h"
46 #include "libmesh/cell_tet14.h"
47 #include "libmesh/cell_hex8.h"
48 #include "libmesh/cell_hex20.h"
49 #include "libmesh/cell_hex27.h"
50 #include "libmesh/cell_inf_hex8.h"
51 #include "libmesh/cell_inf_hex16.h"
52 #include "libmesh/cell_inf_hex18.h"
53 #include "libmesh/cell_prism6.h"
54 #include "libmesh/cell_prism15.h"
55 #include "libmesh/cell_prism18.h"
56 #include "libmesh/cell_prism20.h"
57 #include "libmesh/cell_prism21.h"
58 #include "libmesh/cell_inf_prism6.h"
59 #include "libmesh/cell_inf_prism12.h"
60 #include "libmesh/cell_pyramid5.h"
61 #include "libmesh/cell_pyramid13.h"
62 #include "libmesh/cell_pyramid14.h"
63 #include "libmesh/cell_pyramid18.h"
64 #include "libmesh/fe_base.h"
65 #include "libmesh/mesh_base.h"
66 #include "libmesh/quadrature_nodal.h"
67 #include "libmesh/quadrature_gauss.h"
68 #include "libmesh/remote_elem.h"
69 #include "libmesh/reference_elem.h"
70 #include "libmesh/enum_to_string.h"
71 #include "libmesh/threads.h"
72 #include "libmesh/enum_elem_quality.h"
73 #include "libmesh/enum_io_package.h"
74 #include "libmesh/enum_order.h"
75 #include "libmesh/elem_internal.h"
76 
77 #ifdef LIBMESH_ENABLE_PERIODIC
78 #include "libmesh/mesh.h"
79 #include "libmesh/periodic_boundaries.h"
80 #endif
81 
82 
83 // C++ includes
84 #include <algorithm> // for std::sort
85 #include <array>
86 #include <iterator> // for std::ostream_iterator
87 #include <sstream>
88 #include <limits> // for std::numeric_limits<>
89 #include <cmath> // for std::sqrt()
90 #include <memory>
91 #include <regex> // for exceptions in volume()
92 
93 
94 namespace libMesh
95 {
96 
99 
100 const subdomain_id_type Elem::invalid_subdomain_id = std::numeric_limits<subdomain_id_type>::max();
101 
102 // Initialize static member variables
103 const unsigned int Elem::max_n_nodes;
104 
105 const unsigned int Elem::type_to_n_nodes_map [] =
106  {
107  2, // EDGE2
108  3, // EDGE3
109  4, // EDGE4
110 
111  3, // TRI3
112  6, // TRI6
113 
114  4, // QUAD4
115  8, // QUAD8
116  9, // QUAD9
117 
118  4, // TET4
119  10, // TET10
120 
121  8, // HEX8
122  20, // HEX20
123  27, // HEX27
124 
125  6, // PRISM6
126  15, // PRISM15
127  18, // PRISM18
128 
129  5, // PYRAMID5
130  13, // PYRAMID13
131  14, // PYRAMID14
132 
133  2, // INFEDGE2
134 
135  4, // INFQUAD4
136  6, // INFQUAD6
137 
138  8, // INFHEX8
139  16, // INFHEX16
140  18, // INFHEX18
141 
142  6, // INFPRISM6
143  12, // INFPRISM12
144 
145  1, // NODEELEM
146 
147  0, // REMOTEELEM
148 
149  3, // TRI3SUBDIVISION
150  3, // TRISHELL3
151  4, // QUADSHELL4
152  8, // QUADSHELL8
153 
154  7, // TRI7
155  14, // TET14
156  20, // PRISM20
157  21, // PRISM21
158  18, // PYRAMID18
159 
160  9, // QUADSHELL9
161 
162  invalid_uint, // C0POLYGON
163  };
164 
165 const unsigned int Elem::type_to_n_sides_map [] =
166  {
167  2, // EDGE2
168  2, // EDGE3
169  2, // EDGE4
170 
171  3, // TRI3
172  3, // TRI6
173 
174  4, // QUAD4
175  4, // QUAD8
176  4, // QUAD9
177 
178  4, // TET4
179  4, // TET10
180 
181  6, // HEX8
182  6, // HEX20
183  6, // HEX27
184 
185  5, // PRISM6
186  5, // PRISM15
187  5, // PRISM18
188 
189  5, // PYRAMID5
190  5, // PYRAMID13
191  5, // PYRAMID14
192 
193  2, // INFEDGE2
194 
195  3, // INFQUAD4
196  3, // INFQUAD6
197 
198  5, // INFHEX8
199  5, // INFHEX16
200  5, // INFHEX18
201 
202  4, // INFPRISM6
203  4, // INFPRISM12
204 
205  0, // NODEELEM
206 
207  0, // REMOTEELEM
208 
209  3, // TRI3SUBDIVISION
210  3, // TRISHELL3
211  4, // QUADSHELL4
212  4, // QUADSHELL8
213 
214  3, // TRI7
215  4, // TET14
216  5, // PRISM20
217  5, // PRISM21
218  5, // PYRAMID18
219 
220  4, // QUADSHELL9
221 
222  invalid_uint, // C0POLYGON
223  };
224 
225 const unsigned int Elem::type_to_n_edges_map [] =
226  {
227  0, // EDGE2
228  0, // EDGE3
229  0, // EDGE4
230 
231  3, // TRI3
232  3, // TRI6
233 
234  4, // QUAD4
235  4, // QUAD8
236  4, // QUAD9
237 
238  6, // TET4
239  6, // TET10
240 
241  12, // HEX8
242  12, // HEX20
243  12, // HEX27
244 
245  9, // PRISM6
246  9, // PRISM15
247  9, // PRISM18
248 
249  8, // PYRAMID5
250  8, // PYRAMID13
251  8, // PYRAMID14
252 
253  0, // INFEDGE2
254 
255  3, // INFQUAD4
256  3, // INFQUAD6
257 
258  8, // INFHEX8
259  8, // INFHEX16
260  8, // INFHEX18
261 
262  6, // INFPRISM6
263  6, // INFPRISM12
264 
265  0, // NODEELEM
266 
267  0, // REMOTEELEM
268 
269  3, // TRI3SUBDIVISION
270  3, // TRISHELL3
271  4, // QUADSHELL4
272  4, // QUADSHELL8
273 
274  3, // TRI7
275  6, // TET14
276  9, // PRISM20
277  9, // PRISM21
278  8, // PYRAMID18
279 
280  4, // QUADSHELL9
281 
282  invalid_uint, // C0POLYGON
283  };
284 
285 // ------------------------------------------------------------
286 // Elem class member functions
287 std::unique_ptr<Elem> Elem::disconnected_clone() const
288 {
289  std::unique_ptr<Elem> returnval;
290 
291  switch (this->type())
292  {
293  case C0POLYGON:
294  returnval = std::make_unique<C0Polygon>(this->n_sides());
295  break;
296 
297  default:
298  returnval = Elem::build(this->type());
299  }
300 
301  returnval->set_id() = this->id();
302 #ifdef LIBMESH_ENABLE_UNIQUE_ID
303  returnval->set_unique_id(this->unique_id());
304 #endif
305  returnval->subdomain_id() = this->subdomain_id();
306  returnval->processor_id() = this->processor_id();
307 
308  const auto n_elem_ints = this->n_extra_integers();
309  returnval->add_extra_integers(n_elem_ints);
310  for (unsigned int i = 0; i != n_elem_ints; ++i)
311  returnval->set_extra_integer(i, this->get_extra_integer(i));
312 
313  returnval->set_mapping_type(this->mapping_type());
314  returnval->set_mapping_data(this->mapping_data());
315 
316  return returnval;
317 }
318 
319 
320 
321 std::unique_ptr<Elem> Elem::build(const ElemType type,
322  Elem * p)
323 {
324  switch (type)
325  {
326  // 0D elements
327  case NODEELEM:
328  return std::make_unique<NodeElem>(p);
329 
330  // 1D elements
331  case EDGE2:
332  return std::make_unique<Edge2>(p);
333  case EDGE3:
334  return std::make_unique<Edge3>(p);
335  case EDGE4:
336  return std::make_unique<Edge4>(p);
337 
338  // 2D elements
339  case TRI3:
340  return std::make_unique<Tri3>(p);
341  case TRISHELL3:
342  return std::make_unique<TriShell3>(p);
343  case TRI3SUBDIVISION:
344  return std::make_unique<Tri3Subdivision>(p);
345  case TRI6:
346  return std::make_unique<Tri6>(p);
347  case TRI7:
348  return std::make_unique<Tri7>(p);
349  case QUAD4:
350  return std::make_unique<Quad4>(p);
351  case QUADSHELL4:
352  return std::make_unique<QuadShell4>(p);
353  case QUAD8:
354  return std::make_unique<Quad8>(p);
355  case QUADSHELL8:
356  return std::make_unique<QuadShell8>(p);
357  case QUAD9:
358  return std::make_unique<Quad9>(p);
359  case QUADSHELL9:
360  return std::make_unique<QuadShell9>(p);
361 
362  // Well, a hexagon is *a* polygon...
363  case C0POLYGON:
364  return std::make_unique<C0Polygon>(6, p);
365 
366  // 3D elements
367  case TET4:
368  return std::make_unique<Tet4>(p);
369  case TET10:
370  return std::make_unique<Tet10>(p);
371  case TET14:
372  return std::make_unique<Tet14>(p);
373  case HEX8:
374  return std::make_unique<Hex8>(p);
375  case HEX20:
376  return std::make_unique<Hex20>(p);
377  case HEX27:
378  return std::make_unique<Hex27>(p);
379  case PRISM6:
380  return std::make_unique<Prism6>(p);
381  case PRISM15:
382  return std::make_unique<Prism15>(p);
383  case PRISM18:
384  return std::make_unique<Prism18>(p);
385  case PRISM20:
386  return std::make_unique<Prism20>(p);
387  case PRISM21:
388  return std::make_unique<Prism21>(p);
389  case PYRAMID5:
390  return std::make_unique<Pyramid5>(p);
391  case PYRAMID13:
392  return std::make_unique<Pyramid13>(p);
393  case PYRAMID14:
394  return std::make_unique<Pyramid14>(p);
395  case PYRAMID18:
396  return std::make_unique<Pyramid18>(p);
397 
398 #ifdef LIBMESH_ENABLE_INFINITE_ELEMENTS
399  // 1D infinite elements
400  case INFEDGE2:
401  return std::make_unique<InfEdge2>(p);
402 
403  // 2D infinite elements
404  case INFQUAD4:
405  return std::make_unique<InfQuad4>(p);
406  case INFQUAD6:
407  return std::make_unique<InfQuad6>(p);
408 
409  // 3D infinite elements
410  case INFHEX8:
411  return std::make_unique<InfHex8>(p);
412  case INFHEX16:
413  return std::make_unique<InfHex16>(p);
414  case INFHEX18:
415  return std::make_unique<InfHex18>(p);
416  case INFPRISM6:
417  return std::make_unique<InfPrism6>(p);
418  case INFPRISM12:
419  return std::make_unique<InfPrism12>(p);
420 #endif
421 
422  default:
423  libmesh_error_msg("ERROR: Undefined element type == " << Utility::enum_to_string(type));
424  }
425 }
426 
427 
428 
429 std::unique_ptr<Elem> Elem::build_with_id (const ElemType type,
430  dof_id_type id)
431 {
432  // Call the other build() method with nullptr parent, then set the
433  // required id.
434  auto temp = Elem::build(type, nullptr);
435  temp->set_id(id);
436  return temp;
437 }
438 
439 
440 
441 const Elem * Elem::reference_elem () const
442 {
443  return &(ReferenceElem::get(this->type()));
444 }
445 
446 
447 
448 #ifdef LIBMESH_ENABLE_DEPRECATED
450 {
451  libmesh_do_once(libMesh::err
452  << "Elem::centroid() has been deprecated. Replace with either "
453  << "Elem::vertex_average() to maintain existing behavior, or "
454  << "the more expensive Elem::true_centroid() "
455  << "in cases where the true 'geometric' centroid is required."
456  << std::endl);
457  libmesh_deprecated();
458 
459  return Elem::vertex_average();
460 }
461 #endif // LIBMESH_ENABLE_DEPRECATED
462 
463 
464 
466 {
467  // The base class implementation builds a finite element of the correct
468  // order and computes the centroid, c=(cx, cy, cz), where:
469  //
470  // [cx] [\int x dV]
471  // [cy] := (1/V) * [\int y dV]
472  // [cz] [\int z dV]
473  //
474  // using quadrature. Note that we can expand "x" in the FE space as:
475  //
476  // x = \sum_i x_i \phi_i
477  //
478  // where x_i are the nodal positions of the element and \phi_i are the
479  // associated Lagrange shape functions. This allows us to write the
480  // integrals above as e.g.:
481  //
482  // \int x dV = \sum_i x_i \int \phi_i dV
483  //
484  // Defining:
485  //
486  // V_i := \int \phi_i dV
487  //
488  // we then have:
489  //
490  // [cx] [\sum_i x_i V_i]
491  // [cy] = (1/V) * [\sum_i y_i V_i]
492  // [cz] [\sum_i z_i V_i]
493  //
494  // where:
495  // V = \sum_i V_i
496  //
497  // Derived element types can overload this method to compute
498  // the centroid more efficiently when possible.
499 
500  // If this Elem has an elevated p_level, then we need to generate a
501  // barebones copy of it with zero p_level and call true_centroid()
502  // on that instead. This workaround allows us to avoid issues with
503  // calling FE::reinit() with a default_order() FEType, and then
504  // having that order incorrectly boosted by p_level.
505  if (this->p_level())
506  {
507  auto elem_copy = this->disconnected_clone();
508 #ifdef LIBMESH_ENABLE_AMR
509  elem_copy->set_p_level(0);
510 #endif
511 
512  // Set node pointers
513  for (auto n : this->node_index_range())
514  elem_copy->set_node(n) = _nodes[n];
515 
516  return elem_copy->true_centroid();
517  }
518 
519  const FEFamily mapping_family = FEMap::map_fe_type(*this);
520  const FEType fe_type(this->default_order(), mapping_family);
521 
522  // Build FE and attach quadrature rule. The default quadrature rule
523  // integrates the mass matrix exactly, thus it is overkill to
524  // integrate the basis functions, but this is convenient.
525  std::unique_ptr<FEBase> fe = FEBase::build(this->dim(), fe_type);
526  QGauss qrule (this->dim(), fe_type.default_quadrature_order());
527  fe->attach_quadrature_rule(&qrule);
528 
529  // Pre-request required data
530  const auto & JxW = fe->get_JxW();
531  const auto & phi = fe->get_phi();
532 
533  // Re-compute element-specific values
534  fe->reinit(this);
535 
536  // Number of basis functions
537  auto N = phi.size();
538  libmesh_assert_equal_to(N, this->n_nodes());
539 
540  // Compute V_i
541  std::vector<Real> V(N);
542  for (auto qp : index_range(JxW))
543  for (auto i : make_range(N))
544  V[i] += JxW[qp] * phi[i][qp];
545 
546  // Compute centroid
547  Point cp;
548  Real vol = 0.;
549 
550  for (auto i : make_range(N))
551  {
552  cp += this->point(i) * V[i];
553  vol += V[i];
554  }
555 
556  return cp / vol;
557 }
558 
560 {
561  Point cp;
562 
563  const auto n_vertices = this->n_vertices();
564 
565  for (unsigned int n=0; n<n_vertices; n++)
566  cp.add (this->point(n));
567 
568  return (cp /= static_cast<Real>(n_vertices));
569 }
570 
571 
572 
574 {
575  Real h_min=std::numeric_limits<Real>::max();
576 
577  // Avoid calling a virtual a lot of times
578  const auto n_vertices = this->n_vertices();
579 
580  for (unsigned int n_outer=0; n_outer<n_vertices; n_outer++)
581  for (unsigned int n_inner=n_outer+1; n_inner<n_vertices; n_inner++)
582  {
583  const auto diff = (this->point(n_outer) - this->point(n_inner));
584 
585  h_min = std::min(h_min, diff.norm_sq());
586  }
587 
588  return std::sqrt(h_min);
589 }
590 
591 
592 
594 {
595  Real h_max=0;
596 
597  // Avoid calling a virtual a lot of times
598  const auto n_vertices = this->n_vertices();
599 
600  for (unsigned int n_outer=0; n_outer<n_vertices; n_outer++)
601  for (unsigned int n_inner=n_outer+1; n_inner<n_vertices; n_inner++)
602  {
603  const auto diff = (this->point(n_outer) - this->point(n_inner));
604 
605  h_max = std::max(h_max, diff.norm_sq());
606  }
607 
608  return std::sqrt(h_max);
609 }
610 
611 
612 
613 Real Elem::length(const unsigned int n1,
614  const unsigned int n2) const
615 {
616  libmesh_assert_less ( n1, this->n_vertices() );
617  libmesh_assert_less ( n2, this->n_vertices() );
618 
619  return (this->point(n1) - this->point(n2)).norm();
620 }
621 
622 
623 
625 {
626  const unsigned short n_n = this->n_nodes();
627 
628  std::array<dof_id_type, Elem::max_n_nodes> node_ids;
629 
630  for (unsigned short n=0; n != n_n; ++n)
631  node_ids[n] = this->node_id(n);
632 
633  // Always sort, so that different local node numberings hash to the
634  // same value.
635  std::sort (node_ids.begin(), node_ids.begin()+n_n);
636 
637  return Utility::hashword(node_ids.data(), n_n);
638 }
639 
640 
641 
642 bool Elem::operator == (const Elem & rhs) const
643 {
644  // If the elements aren't the same type, they aren't equal
645  if (this->type() != rhs.type())
646  return false;
647 
648  const unsigned short n_n = this->n_nodes();
649  libmesh_assert_equal_to(n_n, rhs.n_nodes());
650 
651  // Make two sorted arrays of global node ids and compare them for
652  // equality.
653  std::array<dof_id_type, Elem::max_n_nodes> this_ids, rhs_ids;
654 
655  for (unsigned short n = 0; n != n_n; n++)
656  {
657  this_ids[n] = this->node_id(n);
658  rhs_ids[n] = rhs.node_id(n);
659  }
660 
661  // Sort the vectors to rule out different local node numberings.
662  std::sort(this_ids.begin(), this_ids.begin()+n_n);
663  std::sort(rhs_ids.begin(), rhs_ids.begin()+n_n);
664 
665  // If the node ids match, the elements are equal!
666  for (unsigned short n = 0; n != n_n; ++n)
667  if (this_ids[n] != rhs_ids[n])
668  return false;
669  return true;
670 }
671 
672 
673 
674 bool Elem::topologically_equal (const Elem & rhs) const
675 {
676  // If the elements aren't the same type, they aren't equal
677  if (this->type() != rhs.type())
678  return false;
679 
680  libmesh_assert_equal_to(this->n_nodes(), rhs.n_nodes());
681 
682  for (auto n : make_range(this->n_nodes()))
683  if (this->node_id(n) != rhs.node_id(n))
684  return false;
685 
686  for (auto neigh : make_range(this->n_neighbors()))
687  {
688  if (!this->neighbor_ptr(neigh))
689  {
690  if (rhs.neighbor_ptr(neigh))
691  return false;
692  continue;
693  }
694  if (!rhs.neighbor_ptr(neigh) ||
695  this->neighbor_ptr(neigh)->id() !=
696  rhs.neighbor_ptr(neigh)->id())
697  return false;
698  }
699 
700  if (this->parent())
701  {
702  if (!rhs.parent())
703  return false;
704  if (this->parent()->id() != rhs.parent()->id())
705  return false;
706  }
707  else if (rhs.parent())
708  return false;
709 
710  if (this->interior_parent())
711  {
712  if (!rhs.interior_parent())
713  return false;
714  if (this->interior_parent()->id() !=
715  rhs.interior_parent()->id())
716  return false;
717  }
718  else if (rhs.interior_parent())
719  return false;
720 
721  return true;
722 }
723 
724 
725 
726 bool Elem::is_semilocal(const processor_id_type my_pid) const
727 {
728  std::set<const Elem *> point_neighbors;
729 
730  this->find_point_neighbors(point_neighbors);
731 
732  for (const auto & elem : point_neighbors)
733  if (elem->processor_id() == my_pid)
734  return true;
735 
736  return false;
737 }
738 
739 
740 
741 unsigned int Elem::which_side_am_i (const Elem * e) const
742 {
743  libmesh_assert(e);
744 
745  const unsigned int ns = this->n_sides();
746  const unsigned int nn = this->n_nodes();
747 
748  const unsigned int en = e->n_nodes();
749 
750  // e might be on any side until proven otherwise
751  std::vector<bool> might_be_side(ns, true);
752 
753  for (unsigned int i=0; i != en; ++i)
754  {
755  Point side_point = e->point(i);
756  unsigned int local_node_id = libMesh::invalid_uint;
757 
758  // Look for a node of this that's contiguous with node i of
759  // e. Note that the exact floating point comparison of Point
760  // positions is intentional, see the class documentation for
761  // this function.
762  for (unsigned int j=0; j != nn; ++j)
763  if (this->point(j) == side_point)
764  local_node_id = j;
765 
766  // If a node of e isn't contiguous with some node of this, then
767  // e isn't a side of this.
768  if (local_node_id == libMesh::invalid_uint)
769  return libMesh::invalid_uint;
770 
771  // If a node of e isn't contiguous with some node on side s of
772  // this, then e isn't on side s.
773  for (unsigned int s=0; s != ns; ++s)
774  if (!this->is_node_on_side(local_node_id, s))
775  might_be_side[s] = false;
776  }
777 
778  for (unsigned int s=0; s != ns; ++s)
779  if (might_be_side[s])
780  {
781 #ifdef DEBUG
782  for (unsigned int s2=s+1; s2 < ns; ++s2)
783  libmesh_assert (!might_be_side[s2]);
784 #endif
785  return s;
786  }
787 
788  // Didn't find any matching side
789  return libMesh::invalid_uint;
790 }
791 
792 
793 
794 #ifdef LIBMESH_ENABLE_DEPRECATED
795 unsigned int Elem::which_node_am_i(unsigned int side,
796  unsigned int side_node) const
797 {
798  libmesh_deprecated();
799  return local_side_node(side, side_node);
800 }
801 #endif // LIBMESH_ENABLE_DEPRECATED
802 
803 
804 
805 bool Elem::contains_vertex_of(const Elem * e, bool mesh_connection) const
806 {
807  // Our vertices are the first numbered nodes
808  const unsigned int nv = e->n_vertices();
809  const unsigned int my_nv = this->n_vertices();
810 
811  // Check for vertex-to-vertex containment first; contains_point() is
812  // expensive
813  for (auto n : make_range(nv))
814  {
815  const Node * vertex = e->node_ptr(n);
816  for (auto my_n : make_range(my_nv))
817  if (&this->node_ref(my_n) == vertex)
818  return true;
819  }
820 
821  // If e is in our mesh, then we might be done testing
822  if (mesh_connection)
823  {
824  const unsigned int l = this->level();
825  const unsigned int el = e->level();
826 
827  if (l >= el)
828  return false;
829 
830  // We could also return false for l==el-1 iff we knew we had no
831  // triangular faces, but we don't have an API to check that.
832  }
833 
834  // Our vertices are the first numbered nodes
835  for (auto n : make_range(nv))
836  if (this->contains_point(e->point(n)))
837  return true;
838  return false;
839 }
840 
841 
842 
843 bool Elem::contains_edge_of(const Elem * e) const
844 {
845  unsigned int num_contained_edges = 0;
846 
847  // Our vertices are the first numbered nodes
848  for (auto n : make_range(e->n_vertices()))
849  {
850  if (this->contains_point(e->point(n)))
851  {
852  num_contained_edges++;
853  if (num_contained_edges>=2)
854  {
855  return true;
856  }
857  }
858  }
859  return false;
860 }
861 
862 
863 
865  std::set<const Elem *> & neighbor_set) const
866 {
867  libmesh_assert(this->contains_point(p));
868  libmesh_assert(this->active());
869 
870  neighbor_set.clear();
871  neighbor_set.insert(this);
872 
873  std::set<const Elem *> untested_set, next_untested_set;
874  untested_set.insert(this);
875 
876 #ifdef LIBMESH_ENABLE_AMR
877  std::vector<const Elem *> active_neighbor_children;
878 #endif // #ifdef LIBMESH_ENABLE_AMR
879 
880  while (!untested_set.empty())
881  {
882  // Loop over all the elements in the patch that haven't already
883  // been tested
884  for (const auto & elem : untested_set)
885  for (auto current_neighbor : elem->neighbor_ptr_range())
886  {
887  if (current_neighbor &&
888  current_neighbor != remote_elem) // we have a real neighbor on this side
889  {
890  if (current_neighbor->active()) // ... if it is active
891  {
892  auto it = neighbor_set.lower_bound(current_neighbor);
893  if ((it == neighbor_set.end() || *it != current_neighbor) &&
894  current_neighbor->contains_point(p)) // ... don't have and touches p
895  {
896  // Add it and test it
897  next_untested_set.insert(current_neighbor);
898  neighbor_set.emplace_hint(it, current_neighbor);
899  }
900  }
901 #ifdef LIBMESH_ENABLE_AMR
902  else // ... the neighbor is *not* active,
903  { // ... so add *all* neighboring
904  // active children that touch p
905  active_neighbor_children.clear();
906  current_neighbor->active_family_tree_by_neighbor
907  (active_neighbor_children, elem);
908 
909  for (const auto & current_child : active_neighbor_children)
910  {
911  auto it = neighbor_set.lower_bound(current_child);
912  if ((it == neighbor_set.end() || *it != current_child) &&
913  current_child->contains_point(p))
914  {
915  // Add it and test it
916  next_untested_set.insert(current_child);
917  neighbor_set.emplace_hint(it, current_child);
918  }
919  }
920  }
921 #endif // #ifdef LIBMESH_ENABLE_AMR
922  }
923  }
924  untested_set.swap(next_untested_set);
925  next_untested_set.clear();
926  }
927 }
928 
929 
930 
931 void Elem::find_point_neighbors(std::set<const Elem *> & neighbor_set) const
932 {
933  this->find_point_neighbors(neighbor_set, this);
934 }
935 
936 
937 
938 void Elem::find_point_neighbors(std::set<const Elem *> & neighbor_set,
939  const Elem * start_elem) const
940 {
941  ElemInternal::find_point_neighbors(this, neighbor_set, start_elem);
942 }
943 
944 
945 
946 void Elem::find_point_neighbors(std::set<Elem *> & neighbor_set,
947  Elem * start_elem)
948 {
949  ElemInternal::find_point_neighbors(this, neighbor_set, start_elem);
950 }
951 
952 
953 
955  const Point & p2,
956  std::set<const Elem *> & neighbor_set) const
957 {
958  // Simple but perhaps suboptimal code: find elements containing the
959  // first point, then winnow this set down by removing elements which
960  // don't also contain the second point
961 
962  libmesh_assert(this->contains_point(p2));
963  this->find_point_neighbors(p1, neighbor_set);
964 
965  std::set<const Elem *>::iterator it = neighbor_set.begin();
966  const std::set<const Elem *>::iterator end = neighbor_set.end();
967 
968  while (it != end)
969  {
970  // As of C++11, set::erase returns an iterator to the element
971  // following the erased element, or end.
972  if (!(*it)->contains_point(p2))
973  it = neighbor_set.erase(it);
974  else
975  ++it;
976  }
977 }
978 
979 
980 
981 void Elem::find_edge_neighbors(std::set<const Elem *> & neighbor_set) const
982 {
983  neighbor_set.clear();
984  neighbor_set.insert(this);
985 
986  std::set<const Elem *> untested_set, next_untested_set;
987  untested_set.insert(this);
988 
989  while (!untested_set.empty())
990  {
991  // Loop over all the elements in the patch that haven't already
992  // been tested
993  for (const auto & elem : untested_set)
994  {
995  for (auto current_neighbor : elem->neighbor_ptr_range())
996  {
997  if (current_neighbor &&
998  current_neighbor != remote_elem) // we have a real neighbor on this side
999  {
1000  if (current_neighbor->active()) // ... if it is active
1001  {
1002  if (this->contains_edge_of(current_neighbor) // ... and touches us
1003  || current_neighbor->contains_edge_of(this))
1004  {
1005  // Make sure we'll test it
1006  if (!neighbor_set.count(current_neighbor))
1007  next_untested_set.insert (current_neighbor);
1008 
1009  // And add it
1010  neighbor_set.insert (current_neighbor);
1011  }
1012  }
1013 #ifdef LIBMESH_ENABLE_AMR
1014  else // ... the neighbor is *not* active,
1015  { // ... so add *all* neighboring
1016  // active children
1017  std::vector<const Elem *> active_neighbor_children;
1018 
1019  current_neighbor->active_family_tree_by_neighbor
1020  (active_neighbor_children, elem);
1021 
1022  for (const auto & current_child : active_neighbor_children)
1023  if (this->contains_edge_of(current_child) || current_child->contains_edge_of(this))
1024  {
1025  // Make sure we'll test it
1026  if (!neighbor_set.count(current_child))
1027  next_untested_set.insert (current_child);
1028 
1029  neighbor_set.insert (current_child);
1030  }
1031  }
1032 #endif // #ifdef LIBMESH_ENABLE_AMR
1033  }
1034  }
1035  }
1036  untested_set.swap(next_untested_set);
1037  next_untested_set.clear();
1038  }
1039 }
1040 
1041 
1042 
1043 void Elem::find_interior_neighbors(std::set<const Elem *> & neighbor_set) const
1044 {
1045  ElemInternal::find_interior_neighbors(this, neighbor_set);
1046 }
1047 
1048 
1049 
1050 void Elem::find_interior_neighbors(std::set<Elem *> & neighbor_set)
1051 {
1052  ElemInternal::find_interior_neighbors(this, neighbor_set);
1053 }
1054 
1055 
1056 
1057 const Elem * Elem::interior_parent () const
1058 {
1059  // interior parents make no sense for full-dimensional elements.
1060  if (this->dim() >= LIBMESH_DIM)
1061  return nullptr;
1062 
1063  // they USED TO BE only good for level-0 elements, but we now
1064  // support keeping interior_parent() valid on refined boundary
1065  // elements.
1066  // if (this->level() != 0)
1067  // return this->parent()->interior_parent();
1068 
1069  // We store the interior_parent pointer after both the parent
1070  // neighbor and neighbor pointers
1071  Elem * interior_p = _elemlinks[1+this->n_sides()];
1072 
1073  // If we have an interior_parent, we USED TO assume it was a
1074  // one-higher-dimensional interior element, but we now allow e.g.
1075  // edge elements to have a 3D interior_parent with no
1076  // intermediate 2D element.
1077  // libmesh_assert (!interior_p ||
1078  // interior_p->dim() == (this->dim()+1));
1079  libmesh_assert (!interior_p ||
1080  (interior_p == remote_elem) ||
1081  (interior_p->dim() > this->dim()));
1082 
1083  // If an element in a multi-dimensional mesh has an interior_parent
1084  // link, it should be at our level or coarser, just like a neighbor
1085  // link. Our collect_families() code relies on this, but it might
1086  // be tempting for users to manually assign something that breaks
1087  // it.
1088  //
1089  // However, we *also* create temporary side elements, and we don't
1090  // bother with creating ancestors for those, so they can be at level
1091  // 0 even when they're sides of non-level-0 elements.
1092  libmesh_assert (!interior_p ||
1093  (interior_p->level() <= this->level()) ||
1094  (this->level() == 0 &&
1095  this->id() == DofObject::invalid_id));
1096 
1097  return interior_p;
1098 }
1099 
1100 
1101 
1103 {
1104  // See the const version for comments
1105  if (this->dim() >= LIBMESH_DIM)
1106  return nullptr;
1107 
1108  Elem * interior_p = _elemlinks[1+this->n_sides()];
1109 
1110  libmesh_assert (!interior_p ||
1111  (interior_p == remote_elem) ||
1112  (interior_p->dim() > this->dim()));
1113 
1114  return interior_p;
1115 }
1116 
1117 
1118 
1120 {
1121  // interior parents make no sense for full-dimensional elements.
1122  libmesh_assert (!p ||
1123  this->dim() < LIBMESH_DIM);
1124 
1125  // If we have an interior_parent, we USED TO assume it was a
1126  // one-higher-dimensional interior element, but we now allow e.g.
1127  // edge elements to have a 3D interior_parent with no
1128  // intermediate 2D element.
1129  // libmesh_assert (!p ||
1130  // p->dim() == (this->dim()+1));
1131  libmesh_assert (!p ||
1132  (p == remote_elem) ||
1133  (p->dim() > this->dim()));
1134 
1135  _elemlinks[1+this->n_sides()] = p;
1136 }
1137 
1138 
1139 
1140 #ifdef LIBMESH_ENABLE_PERIODIC
1141 
1142 Elem * Elem::topological_neighbor (const unsigned int i,
1143  MeshBase & mesh,
1144  const PointLocatorBase & point_locator,
1145  const PeriodicBoundaries * pb)
1146 {
1147  libmesh_assert_less (i, this->n_neighbors());
1148 
1149  Elem * neighbor_i = this->neighbor_ptr(i);
1150  if (neighbor_i != nullptr)
1151  return neighbor_i;
1152 
1153  if (pb)
1154  {
1155  // Since the neighbor is nullptr it must be on a boundary. We need
1156  // see if this is a periodic boundary in which case it will have a
1157  // topological neighbor
1158  std::vector<boundary_id_type> bc_ids;
1159  mesh.get_boundary_info().boundary_ids(this, cast_int<unsigned short>(i), bc_ids);
1160  for (const auto & id : bc_ids)
1161  if (pb->boundary(id))
1162  {
1163  // Since the point locator inside of periodic boundaries
1164  // returns a const pointer we will retrieve the proper
1165  // pointer directly from the mesh object.
1166  const Elem * const cn = pb->neighbor(id, point_locator, this, i);
1167  neighbor_i = const_cast<Elem *>(cn);
1168 
1169  // Since coarse elements do not have more refined
1170  // neighbors we need to make sure that we don't return one
1171  // of these types of neighbors.
1172  if (neighbor_i)
1173  while (level() < neighbor_i->level())
1174  neighbor_i = neighbor_i->parent();
1175  return neighbor_i;
1176  }
1177  }
1178 
1179  return nullptr;
1180 }
1181 
1182 
1183 
1184 const Elem * Elem::topological_neighbor (const unsigned int i,
1185  const MeshBase & mesh,
1186  const PointLocatorBase & point_locator,
1187  const PeriodicBoundaries * pb) const
1188 {
1189  libmesh_assert_less (i, this->n_neighbors());
1190 
1191  const Elem * neighbor_i = this->neighbor_ptr(i);
1192  if (neighbor_i != nullptr)
1193  return neighbor_i;
1194 
1195  if (pb)
1196  {
1197  // Since the neighbor is nullptr it must be on a boundary. We need
1198  // see if this is a periodic boundary in which case it will have a
1199  // topological neighbor
1200  std::vector<boundary_id_type> bc_ids;
1201  mesh.get_boundary_info().boundary_ids(this, cast_int<unsigned short>(i), bc_ids);
1202  for (const auto & id : bc_ids)
1203  if (pb->boundary(id))
1204  {
1205  neighbor_i = pb->neighbor(id, point_locator, this, i);
1206 
1207  // Since coarse elements do not have more refined
1208  // neighbors we need to make sure that we don't return one
1209  // of these types of neighbors.
1210  if (neighbor_i)
1211  while (level() < neighbor_i->level())
1212  neighbor_i = neighbor_i->parent();
1213  return neighbor_i;
1214  }
1215  }
1216 
1217  return nullptr;
1218 }
1219 
1220 
1222  const MeshBase & mesh,
1223  const PointLocatorBase & point_locator,
1224  const PeriodicBoundaries * pb) const
1225 {
1226  // First see if this is a normal "interior" neighbor
1227  if (has_neighbor(elem))
1228  return true;
1229 
1230  for (auto n : this->side_index_range())
1231  if (this->topological_neighbor(n, mesh, point_locator, pb))
1232  return true;
1233 
1234  return false;
1235 }
1236 
1237 
1238 #endif
1239 
1240 #ifndef NDEBUG
1241 
1243 {
1244  libmesh_assert(this->valid_id());
1245  for (auto n : this->node_index_range())
1246  {
1247  libmesh_assert(this->node_ptr(n));
1248  libmesh_assert(this->node_ptr(n)->valid_id());
1249  }
1250 }
1251 
1252 
1253 
1255 {
1256  for (auto n : this->side_index_range())
1257  {
1258  const Elem * neigh = this->neighbor_ptr(n);
1259 
1260  // Any element might have a remote neighbor; checking
1261  // to make sure that's not inaccurate is tough.
1262  if (neigh == remote_elem)
1263  continue;
1264 
1265  if (neigh)
1266  {
1267  // Only subactive elements have subactive neighbors
1268  libmesh_assert (this->subactive() || !neigh->subactive());
1269 
1270  const Elem * elem = this;
1271 
1272  // If we're subactive but our neighbor isn't, its
1273  // return neighbor link will be to our first active
1274  // ancestor OR to our inactive ancestor of the same
1275  // level as neigh,
1276  if (this->subactive() && !neigh->subactive())
1277  {
1278  for (elem = this; !elem->active();
1279  elem = elem->parent())
1280  libmesh_assert(elem);
1281  }
1282  else
1283  {
1284  unsigned int rev = neigh->which_neighbor_am_i(elem);
1285  libmesh_assert_less (rev, neigh->n_neighbors());
1286 
1287  if (this->subactive() && !neigh->subactive())
1288  {
1289  while (neigh->neighbor_ptr(rev) != elem)
1290  {
1291  libmesh_assert(elem->parent());
1292  elem = elem->parent();
1293  }
1294  }
1295  else
1296  {
1297  const Elem * nn = neigh->neighbor_ptr(rev);
1298  libmesh_assert(nn);
1299 
1300  for (; elem != nn; elem = elem->parent())
1301  libmesh_assert(elem);
1302  }
1303  }
1304  }
1305  // If we don't have a neighbor and we're not subactive, our
1306  // ancestors shouldn't have any neighbors in this same
1307  // direction.
1308  else if (!this->subactive())
1309  {
1310  const Elem * my_parent = this->parent();
1311  if (my_parent &&
1312  // A parent with a different dimension isn't really one of
1313  // our ancestors, it means we're on a boundary mesh and this
1314  // is an interior mesh element for which we're on a side.
1315  // Nothing to test for in that case.
1316  (my_parent->dim() == this->dim()))
1317  libmesh_assert (!my_parent->neighbor_ptr(n));
1318  }
1319  }
1320 }
1321 
1322 #endif // !NDEBUG
1323 
1324 
1325 
1326 void Elem::make_links_to_me_local(unsigned int n, unsigned int nn)
1327 {
1328  Elem * neigh = this->neighbor_ptr(n);
1329 
1330  // Don't bother calling this function unless it's necessary
1331  libmesh_assert(neigh);
1332  libmesh_assert(!neigh->is_remote());
1333 
1334  // We never have neighbors more refined than us
1335  libmesh_assert_less_equal (neigh->level(), this->level());
1336 
1337  // We never have subactive neighbors of non subactive elements
1338  libmesh_assert(!neigh->subactive() || this->subactive());
1339 
1340  // If we have a neighbor less refined than us then it must not
1341  // have any more refined descendants we could have pointed to
1342  // instead.
1343  libmesh_assert((neigh->level() == this->level()) ||
1344  (neigh->active() && !this->subactive()) ||
1345  (!neigh->has_children() && this->subactive()));
1346 
1347  // If neigh is at our level, then its family might have
1348  // remote_elem neighbor links which need to point to us
1349  // instead, but if not, then we're done.
1350  if (neigh->level() != this->level())
1351  return;
1352 
1353  // What side of neigh are we on? nn.
1354  //
1355  // We can't use the usual Elem method because we're in the middle of
1356  // restoring topology. We can't compare side_ptr nodes because
1357  // users want to abuse neighbor_ptr to point to
1358  // not-technically-neighbors across mesh slits. We can't compare
1359  // node locations because users want to move those
1360  // not-technically-neighbors until they're
1361  // not-even-geometrically-neighbors.
1362 
1363  // Find any elements that ought to point to elem
1364  std::vector<Elem *> neigh_family;
1365 #ifdef LIBMESH_ENABLE_AMR
1366  if (this->active())
1367  neigh->family_tree_by_side(neigh_family, nn);
1368  else
1369 #endif
1370  neigh_family.push_back(neigh);
1371 
1372  // And point them to elem
1373  for (auto & neigh_family_member : neigh_family)
1374  {
1375  // Only subactive elements point to other subactive elements
1376  if (this->subactive() && !neigh_family_member->subactive())
1377  continue;
1378 
1379  // Ideally, the neighbor link ought to either be correct
1380  // already or ought to be to remote_elem.
1381  //
1382  // However, if we're redistributing a newly created elem,
1383  // after an AMR step but before find_neighbors has fixed up
1384  // neighbor links, we might have an out of date neighbor
1385  // link to elem's parent instead.
1386 #ifdef LIBMESH_ENABLE_AMR
1387  libmesh_assert((neigh_family_member->neighbor_ptr(nn) &&
1388  (neigh_family_member->neighbor_ptr(nn)->active() ||
1389  neigh_family_member->neighbor_ptr(nn)->is_ancestor_of(this))) ||
1390  (neigh_family_member->neighbor_ptr(nn) == remote_elem) ||
1391  ((this->refinement_flag() == JUST_REFINED) &&
1392  (this->parent() != nullptr) &&
1393  (neigh_family_member->neighbor_ptr(nn) == this->parent())));
1394 #else
1395  libmesh_assert((neigh_family_member->neighbor_ptr(nn) == this) ||
1396  (neigh_family_member->neighbor_ptr(nn) == remote_elem));
1397 #endif
1398 
1399  neigh_family_member->set_neighbor(nn, this);
1400  }
1401 }
1402 
1403 
1405 {
1406  libmesh_assert_not_equal_to (this, remote_elem);
1407 
1408  // We need to have handled any children first
1409 #if defined(LIBMESH_ENABLE_AMR) && defined(DEBUG)
1410  if (this->has_children())
1411  for (auto & child : this->child_ref_range())
1412  libmesh_assert_equal_to (&child, remote_elem);
1413 #endif
1414 
1415  // Remotify any neighbor links
1416  for (auto neigh : this->neighbor_ptr_range())
1417  {
1418  if (neigh && neigh != remote_elem)
1419  {
1420  // My neighbor should never be more refined than me; my real
1421  // neighbor would have been its parent in that case.
1422  libmesh_assert_greater_equal (this->level(), neigh->level());
1423 
1424  if (this->level() == neigh->level() &&
1425  neigh->has_neighbor(this))
1426  {
1427 #ifdef LIBMESH_ENABLE_AMR
1428  // My neighbor may have descendants which also consider me a
1429  // neighbor
1430  std::vector<Elem *> family;
1431  neigh->total_family_tree_by_neighbor (family, this);
1432 
1433  // FIXME - There's a lot of ugly const_casts here; we
1434  // may want to make remote_elem non-const
1435  for (auto & n : family)
1436  {
1437  libmesh_assert (n);
1438  if (n == remote_elem)
1439  continue;
1440  unsigned int my_s = n->which_neighbor_am_i(this);
1441  libmesh_assert_less (my_s, n->n_neighbors());
1442  libmesh_assert_equal_to (n->neighbor_ptr(my_s), this);
1443  n->set_neighbor(my_s, const_cast<RemoteElem *>(remote_elem));
1444  }
1445 #else
1446  unsigned int my_s = neigh->which_neighbor_am_i(this);
1447  libmesh_assert_less (my_s, neigh->n_neighbors());
1448  libmesh_assert_equal_to (neigh->neighbor_ptr(my_s), this);
1449  neigh->set_neighbor(my_s, const_cast<RemoteElem *>(remote_elem));
1450 #endif
1451  }
1452 #ifdef LIBMESH_ENABLE_AMR
1453  // Even if my neighbor doesn't link back to me, it might
1454  // have subactive descendants which do
1455  else if (neigh->has_children())
1456  {
1457  // If my neighbor at the same level doesn't have me as a
1458  // neighbor, I must be subactive
1459  libmesh_assert(this->level() > neigh->level() ||
1460  this->subactive());
1461 
1462  // My neighbor must have some ancestor of mine as a
1463  // neighbor
1464  Elem * my_ancestor = this->parent();
1465  libmesh_assert(my_ancestor);
1466  while (!neigh->has_neighbor(my_ancestor))
1467  {
1468  my_ancestor = my_ancestor->parent();
1469  libmesh_assert(my_ancestor);
1470  }
1471 
1472  // My neighbor may have descendants which consider me a
1473  // neighbor
1474  std::vector<Elem *> family;
1475  neigh->total_family_tree_by_subneighbor (family, my_ancestor, this);
1476 
1477  for (auto & n : family)
1478  {
1479  libmesh_assert (n);
1480  if (n->is_remote())
1481  continue;
1482  unsigned int my_s = n->which_neighbor_am_i(this);
1483  libmesh_assert_less (my_s, n->n_neighbors());
1484  libmesh_assert_equal_to (n->neighbor_ptr(my_s), this);
1485  // TODO: we may want to make remote_elem non-const.
1486  n->set_neighbor(my_s, const_cast<RemoteElem *>(remote_elem));
1487  }
1488  }
1489 #endif
1490  }
1491  }
1492 
1493 #ifdef LIBMESH_ENABLE_AMR
1494  // Remotify parent's child link
1495  Elem * my_parent = this->parent();
1496  if (my_parent &&
1497  // As long as it's not already remote
1498  my_parent != remote_elem &&
1499  // And it's a real parent, not an interior parent
1500  this->dim() == my_parent->dim())
1501  {
1502  unsigned int me = my_parent->which_child_am_i(this);
1503  libmesh_assert_equal_to (my_parent->child_ptr(me), this);
1504  my_parent->set_child(me, const_cast<RemoteElem *>(remote_elem));
1505  }
1506 #endif
1507 }
1508 
1509 
1511 {
1512  libmesh_assert_not_equal_to (this, remote_elem);
1513 
1514  // We need to have handled any children first
1515 #ifdef LIBMESH_ENABLE_AMR
1516  libmesh_assert (!this->has_children());
1517 #endif
1518 
1519  // Nullify any neighbor links
1520  for (auto neigh : this->neighbor_ptr_range())
1521  {
1522  if (neigh && neigh != remote_elem)
1523  {
1524  // My neighbor should never be more refined than me; my real
1525  // neighbor would have been its parent in that case.
1526  libmesh_assert_greater_equal (this->level(), neigh->level());
1527 
1528  if (this->level() == neigh->level() &&
1529  neigh->has_neighbor(this))
1530  {
1531 #ifdef LIBMESH_ENABLE_AMR
1532  // My neighbor may have descendants which also consider me a
1533  // neighbor
1534  std::vector<Elem *> family;
1535  neigh->total_family_tree_by_neighbor (family, this);
1536 
1537  for (auto & n : family)
1538  {
1539  libmesh_assert (n);
1540  if (n->is_remote())
1541  continue;
1542  unsigned int my_s = n->which_neighbor_am_i(this);
1543  libmesh_assert_less (my_s, n->n_neighbors());
1544  libmesh_assert_equal_to (n->neighbor_ptr(my_s), this);
1545  n->set_neighbor(my_s, nullptr);
1546  }
1547 #else
1548  unsigned int my_s = neigh->which_neighbor_am_i(this);
1549  libmesh_assert_less (my_s, neigh->n_neighbors());
1550  libmesh_assert_equal_to (neigh->neighbor_ptr(my_s), this);
1551  neigh->set_neighbor(my_s, nullptr);
1552 #endif
1553  }
1554 #ifdef LIBMESH_ENABLE_AMR
1555  // Even if my neighbor doesn't link back to me, it might
1556  // have subactive descendants which do
1557  else if (neigh->has_children())
1558  {
1559  // If my neighbor at the same level doesn't have me as a
1560  // neighbor, I must be subactive
1561  libmesh_assert(this->level() > neigh->level() ||
1562  this->subactive());
1563 
1564  // My neighbor must have some ancestor of mine as a
1565  // neighbor
1566  Elem * my_ancestor = this->parent();
1567  libmesh_assert(my_ancestor);
1568  while (!neigh->has_neighbor(my_ancestor))
1569  {
1570  my_ancestor = my_ancestor->parent();
1571  libmesh_assert(my_ancestor);
1572  }
1573 
1574  // My neighbor may have descendants which consider me a
1575  // neighbor
1576  std::vector<Elem *> family;
1577  neigh->total_family_tree_by_subneighbor (family, my_ancestor, this);
1578 
1579  for (auto & n : family)
1580  {
1581  libmesh_assert (n);
1582  if (n->is_remote())
1583  continue;
1584  unsigned int my_s = n->which_neighbor_am_i(this);
1585  libmesh_assert_less (my_s, n->n_neighbors());
1586  libmesh_assert_equal_to (n->neighbor_ptr(my_s), this);
1587  n->set_neighbor(my_s, nullptr);
1588  }
1589  }
1590 #endif
1591  }
1592  }
1593 
1594 #ifdef LIBMESH_ENABLE_AMR
1595  // We can't currently delete a child with a parent!
1596  libmesh_assert (!this->parent());
1597 #endif
1598 }
1599 
1600 
1601 
1602 void Elem::write_connectivity (std::ostream & out_stream,
1603  const IOPackage iop) const
1604 {
1605  libmesh_assert (out_stream.good());
1607  libmesh_assert_not_equal_to (iop, INVALID_IO_PACKAGE);
1608 
1609  switch (iop)
1610  {
1611  case TECPLOT:
1612  {
1613  // This connectivity vector will be used repeatedly instead
1614  // of being reconstructed inside the loop.
1615  std::vector<dof_id_type> conn;
1616  for (auto sc : make_range(this->n_sub_elem()))
1617  {
1618  this->connectivity(sc, TECPLOT, conn);
1619 
1620  std::copy(conn.begin(),
1621  conn.end(),
1622  std::ostream_iterator<dof_id_type>(out_stream, " "));
1623 
1624  out_stream << '\n';
1625  }
1626  return;
1627  }
1628 
1629  case UCD:
1630  {
1631  for (auto i : this->node_index_range())
1632  out_stream << this->node_id(i)+1 << "\t";
1633 
1634  out_stream << '\n';
1635  return;
1636  }
1637 
1638  default:
1639  libmesh_error_msg("Unsupported IO package " << iop);
1640  }
1641 }
1642 
1643 
1644 
1646 {
1647  switch (q)
1648  {
1649  // Return the maximum ratio of edge lengths, or zero if that
1650  // maximum would otherwise be infinity.
1651  case EDGE_LENGTH_RATIO:
1652  {
1653  if (this->dim() < 2)
1654  return 1;
1655 
1656  std::vector<Real> edge_lengths(this->n_edges());
1657  for (auto e : index_range(edge_lengths))
1658  edge_lengths[e] = (this->point(this->local_edge_node(e,1)) -
1659  this->point(this->local_edge_node(e,0))).norm();
1660 
1661  auto [min, max] =
1662  std::minmax_element(edge_lengths.begin(), edge_lengths.end());
1663 
1664  if (*min == 0.)
1665  return 0.;
1666  else
1667  return *max / *min;
1668  }
1669 
1670  case MIN_ANGLE:
1671  case MAX_ANGLE:
1672  {
1673  // 1D elements don't have interior angles, so just return some
1674  // dummy value in that case.
1675  if (this->dim() < 2)
1676  return 0.;
1677 
1678  // Initialize return values
1679  Real min_angle = std::numeric_limits<Real>::max();
1680  Real max_angle = -std::numeric_limits<Real>::max();
1681 
1682  for (auto n : this->node_index_range())
1683  {
1684  // Get list of edge ids adjacent to this node.
1685  auto adjacent_edge_ids = this->edges_adjacent_to_node(n);
1686 
1687  // Skip any nodes with fewer than 2 adjacent edges. You
1688  // need at least two adjacent edges to form an interior
1689  // element angle.
1690  auto N = adjacent_edge_ids.size();
1691  if (N < 2)
1692  continue;
1693 
1694  // Consider all possible pairs of edges adjacent to node n
1695  for (unsigned int first = 0; first < N-1; ++first)
1696  for (unsigned int second = first+1; second < N; ++second)
1697  {
1698  // Get ids of first and second edges
1699  auto first_edge = adjacent_edge_ids[first];
1700  auto second_edge = adjacent_edge_ids[second];
1701 
1702  // Get node ids of first and second edge
1703  auto first_edge_node_0 = this->local_edge_node(first_edge, 0);
1704  auto first_edge_node_1 = this->local_edge_node(first_edge, 1);
1705  auto second_edge_node_0 = this->local_edge_node(second_edge, 0);
1706  auto second_edge_node_1 = this->local_edge_node(second_edge, 1);
1707 
1708  // Orient both edges so that edge node 0 == n
1709  if (first_edge_node_0 != n)
1710  std::swap(first_edge_node_0, first_edge_node_1);
1711  if (second_edge_node_0 != n)
1712  std::swap(second_edge_node_0, second_edge_node_1);
1713 
1714  libmesh_assert_equal_to(first_edge_node_0, n);
1715  libmesh_assert_equal_to(second_edge_node_0, n);
1716 
1717  // Locally oriented edge vectors
1718  Point
1719  first_ev = this->point(first_edge_node_1) - this->point(first_edge_node_0),
1720  second_ev = this->point(second_edge_node_1) - this->point(second_edge_node_0);
1721 
1722  // Angle between them in the range [0, pi]
1723  Real theta = std::acos(first_ev.unit() * second_ev.unit());
1724 
1725  // Track min and max angles seen
1726  min_angle = std::min(theta, min_angle);
1727  max_angle = std::max(theta, max_angle);
1728  }
1729  }
1730 
1731  // Return requested extreme value (in degrees)
1732  return Real(180)/libMesh::pi * ((q == MIN_ANGLE) ? min_angle : max_angle);
1733  }
1734 
1735  case MIN_DIHEDRAL_ANGLE:
1736  case MAX_DIHEDRAL_ANGLE:
1737  {
1738  // For 1D and 2D elements, just call this function with MIN,MAX_ANGLE instead.
1739  if (this->dim() < 3)
1740  return this->quality((q == MIN_DIHEDRAL_ANGLE) ? MIN_ANGLE : MAX_ANGLE);
1741 
1742  // Initialize return values
1743  Real min_angle = std::numeric_limits<Real>::max();
1744  Real max_angle = -std::numeric_limits<Real>::max();
1745 
1746  // Algorithm for computing dihedral angles:
1747  // .) Loop over the edges, use the edge_sides_map to get the
1748  // two sides adjacent to the edge.
1749  // .) For each adjacent side, use the side_nodes_map to get the
1750  // list of three (or more) node ids on that side.
1751  // .) Use the node ids to compute the (approximate) inward
1752  // normal for the side. Note: this is approximate since 3D
1753  // elements with four-sided faces and quadratic tetrahedra
1754  // do not necessarily have planar faces.
1755  // .) Compute the dihedral angle for the current edge, compare
1756  // it to the current min and max dihedral angles.
1757  for (auto e : this->edge_index_range())
1758  {
1759  // Get list of edge ids adjacent to this node.
1760  auto adjacent_side_ids = this->sides_on_edge(e);
1761 
1762  // All 3D elements should have exactly two sides adjacent to each edge.
1763  libmesh_assert_equal_to(adjacent_side_ids.size(), 2);
1764 
1765  // Get lists of node ids on each side
1766  auto side_0_node_ids = this->nodes_on_side(adjacent_side_ids[0]);
1767  auto side_1_node_ids = this->nodes_on_side(adjacent_side_ids[1]);
1768 
1769  // All 3D elements have at least three nodes on each side
1770  libmesh_assert_greater_equal(side_0_node_ids.size(), 3);
1771  libmesh_assert_greater_equal(side_1_node_ids.size(), 3);
1772 
1773  // Construct (approximate) inward normal on each adjacent side
1774  auto side_0_normal =
1775  (this->point(side_0_node_ids[2]) - this->point(side_0_node_ids[0])).cross
1776  (this->point(side_0_node_ids[1]) - this->point(side_0_node_ids[0])).unit();
1777  auto side_1_normal =
1778  (this->point(side_1_node_ids[2]) - this->point(side_1_node_ids[0])).cross
1779  (this->point(side_1_node_ids[1]) - this->point(side_1_node_ids[0])).unit();
1780 
1781  // Compute dihedral angle between the planes.
1782  // Using the absolute value ensures that we get the same result
1783  // even if the orientation of one of the planes is flipped, i.e.
1784  // it always gives us a value in the range [0, pi/2].
1785  // https://en.wikipedia.org/wiki/Dihedral_angle
1786  Real theta = std::acos(std::abs(side_0_normal * side_1_normal));
1787 
1788  // Track min and max angles seen
1789  min_angle = std::min(theta, min_angle);
1790  max_angle = std::max(theta, max_angle);
1791  }
1792 
1793  // Return requested extreme value (in degrees)
1794  return Real(180)/libMesh::pi * ((q == MIN_DIHEDRAL_ANGLE) ? min_angle : max_angle);
1795  }
1796 
1797  case JACOBIAN:
1798  case SCALED_JACOBIAN:
1799  {
1800  // 1D elements don't have interior corners, so this metric
1801  // does not really apply to them.
1802  const auto N = this->dim();
1803  if (N < 2)
1804  return 1.;
1805 
1806  // Initialize return value
1807  Real min_node_area = std::numeric_limits<Real>::max();
1808 
1809  for (auto n : this->node_index_range())
1810  {
1811  // Get list of edge ids adjacent to this node.
1812  auto adjacent_edge_ids = this->edges_adjacent_to_node(n);
1813 
1814  // Skip any nodes that don't have dim() adjacent edges. In 2D,
1815  // you need at least two adjacent edges to compute the cross
1816  // product, and in 3D, you need at least three adjacent edges
1817  // to compute the scalar triple product. The only element
1818  // type which has an unusual topology in this regard is the
1819  // Pyramid element in 3D, where 4 edges meet at the apex node.
1820  // For now, we just skip this node when computing the JACOBIAN
1821  // metric for Pyramids.
1822  if (adjacent_edge_ids.size() != N)
1823  continue;
1824 
1825  // Construct oriented edges
1826  std::vector<Point> oriented_edges(N);
1827  for (auto i : make_range(N))
1828  {
1829  auto node_0 = this->local_edge_node(adjacent_edge_ids[i], 0);
1830  auto node_1 = this->local_edge_node(adjacent_edge_ids[i], 1);
1831  if (node_0 != n)
1832  std::swap(node_0, node_1);
1833  oriented_edges[i] = this->point(node_1) - this->point(node_0);
1834  }
1835 
1836  // Compute unscaled area (2D) or volume (3D) using the
1837  // cross product (2D) or scalar triple product (3D) of the
1838  // oriented edges. We take the absolute value so that we
1839  // don't have to worry about the sign of the area.
1840  Real node_area = (N == 2) ?
1841  cross_norm(oriented_edges[0], oriented_edges[1]) :
1842  std::abs(triple_product(oriented_edges[0], oriented_edges[1], oriented_edges[2]));
1843 
1844  // Divide by (non-zero) edge lengths if computing scaled Jacobian.
1845  // If any length is zero, then set node_area to zero. This means that
1846  // e.g. degenerate quadrilaterals will have a zero SCALED_JACOBIAN metric.
1847  if (q == SCALED_JACOBIAN)
1848  for (auto i : make_range(N))
1849  {
1850  Real len_i = oriented_edges[i].norm();
1851  node_area = (len_i == 0.) ? 0. : (node_area / len_i);
1852  }
1853 
1854  // Update minimum
1855  min_node_area = std::min(node_area, min_node_area);
1856  }
1857 
1858  return min_node_area;
1859  }
1860 
1861  // Return 1 if we made it here
1862  default:
1863  {
1864  libmesh_do_once( libmesh_here();
1865 
1866  libMesh::err << "ERROR: quality metric "
1868  << " not implemented on element type "
1869  << Utility::enum_to_string(this->type())
1870  << std::endl
1871  << "Returning 1."
1872  << std::endl; );
1873 
1874  return 1.;
1875  }
1876  }
1877 }
1878 
1879 
1880 
1881 bool Elem::ancestor() const
1882 {
1883 #ifdef LIBMESH_ENABLE_AMR
1884 
1885  // Use a fast, DistributedMesh-safe definition
1886  const bool is_ancestor =
1887  !this->active() && !this->subactive();
1888 
1889  // But check for inconsistencies if we have time
1890 #ifdef DEBUG
1891  if (!is_ancestor && this->has_children())
1892  {
1893  for (auto & c : this->child_ref_range())
1894  {
1895  if (&c != remote_elem)
1896  {
1897  libmesh_assert(!c.active());
1898  libmesh_assert(!c.ancestor());
1899  }
1900  }
1901  }
1902 #endif // DEBUG
1903 
1904  return is_ancestor;
1905 
1906 #else
1907  return false;
1908 #endif
1909 }
1910 
1911 
1912 
1913 #ifdef LIBMESH_ENABLE_AMR
1914 
1915 void Elem::add_child (Elem * elem)
1916 {
1917  const unsigned int nc = this->n_children();
1918 
1919  if (!_children)
1920  {
1921  _children = std::make_unique<Elem *[]>(nc);
1922 
1923  for (unsigned int c = 0; c != nc; c++)
1924  this->set_child(c, nullptr);
1925  }
1926 
1927  for (unsigned int c = 0; c != nc; c++)
1928  {
1929  if (this->_children[c] == nullptr || this->_children[c] == remote_elem)
1930  {
1931  libmesh_assert_equal_to (this, elem->parent());
1932  this->set_child(c, elem);
1933  return;
1934  }
1935  }
1936 
1937  libmesh_error_msg("Error: Tried to add a child to an element with full children array");
1938 }
1939 
1940 
1941 
1942 void Elem::add_child (Elem * elem, unsigned int c)
1943 {
1944  if (!this->has_children())
1945  {
1946  const unsigned int nc = this->n_children();
1947  _children = std::make_unique<Elem *[]>(nc);
1948 
1949  for (unsigned int i = 0; i != nc; i++)
1950  this->set_child(i, nullptr);
1951  }
1952 
1953  libmesh_assert (this->_children[c] == nullptr || this->child_ptr(c) == remote_elem);
1954  libmesh_assert (elem == remote_elem || this == elem->parent());
1955 
1956  this->set_child(c, elem);
1957 }
1958 
1959 
1960 
1961 void Elem::replace_child (Elem * elem, unsigned int c)
1962 {
1963  libmesh_assert(this->has_children());
1964 
1965  libmesh_assert(this->child_ptr(c));
1966 
1967  this->set_child(c, elem);
1968 }
1969 
1970 
1971 
1972 void Elem::family_tree (std::vector<const Elem *> & family,
1973  bool reset) const
1974 {
1975  ElemInternal::family_tree(this, family, reset);
1976 }
1977 
1978 
1979 
1980 void Elem::family_tree (std::vector<Elem *> & family,
1981  bool reset)
1982 {
1983  ElemInternal::family_tree(this, family, reset);
1984 }
1985 
1986 
1987 
1988 void Elem::total_family_tree (std::vector<const Elem *> & family,
1989  bool reset) const
1990 {
1991  ElemInternal::total_family_tree(this, family, reset);
1992 }
1993 
1994 
1995 
1996 void Elem::total_family_tree (std::vector<Elem *> & family,
1997  bool reset)
1998 {
1999  ElemInternal::total_family_tree(this, family, reset);
2000 }
2001 
2002 
2003 
2004 void Elem::active_family_tree (std::vector<const Elem *> & active_family,
2005  bool reset) const
2006 {
2007  ElemInternal::active_family_tree(this, active_family, reset);
2008 }
2009 
2010 
2011 
2012 void Elem::active_family_tree (std::vector<Elem *> & active_family,
2013  bool reset)
2014 {
2015  ElemInternal::active_family_tree(this, active_family, reset);
2016 }
2017 
2018 
2019 
2020 void Elem::family_tree_by_side (std::vector<const Elem *> & family,
2021  unsigned int side,
2022  bool reset) const
2023 {
2024  ElemInternal::family_tree_by_side(this, family, side, reset);
2025 }
2026 
2027 
2028 
2029 void Elem:: family_tree_by_side (std::vector<Elem *> & family,
2030  unsigned int side,
2031  bool reset)
2032 {
2033  ElemInternal::family_tree_by_side(this, family, side, reset);
2034 }
2035 
2036 
2037 
2038 void Elem::active_family_tree_by_side (std::vector<const Elem *> & family,
2039  unsigned int side,
2040  bool reset) const
2041 {
2042  ElemInternal::active_family_tree_by_side(this, family, side, reset);
2043 }
2044 
2045 
2046 
2047 void Elem::active_family_tree_by_side (std::vector<Elem *> & family,
2048  unsigned int side,
2049  bool reset)
2050 {
2051  ElemInternal::active_family_tree_by_side(this, family, side, reset);
2052 }
2053 
2054 
2055 
2056 void Elem::family_tree_by_neighbor (std::vector<const Elem *> & family,
2057  const Elem * neighbor,
2058  bool reset) const
2059 {
2060  ElemInternal::family_tree_by_neighbor(this, family, neighbor, reset);
2061 }
2062 
2063 
2064 
2065 void Elem::family_tree_by_neighbor (std::vector<Elem *> & family,
2066  Elem * neighbor,
2067  bool reset)
2068 {
2069  ElemInternal::family_tree_by_neighbor(this, family, neighbor, reset);
2070 }
2071 
2072 
2073 
2074 void Elem::total_family_tree_by_neighbor (std::vector<const Elem *> & family,
2075  const Elem * neighbor,
2076  bool reset) const
2077 {
2078  ElemInternal::total_family_tree_by_neighbor(this, family, neighbor, reset);
2079 }
2080 
2081 
2082 
2083 void Elem::total_family_tree_by_neighbor (std::vector<Elem *> & family,
2084  Elem * neighbor,
2085  bool reset)
2086 {
2087  ElemInternal::total_family_tree_by_neighbor(this, family, neighbor, reset);
2088 }
2089 
2090 
2091 
2092 void Elem::family_tree_by_subneighbor (std::vector<const Elem *> & family,
2093  const Elem * neighbor,
2094  const Elem * subneighbor,
2095  bool reset) const
2096 {
2097  ElemInternal::family_tree_by_subneighbor(this, family, neighbor, subneighbor, reset);
2098 }
2099 
2100 
2101 
2102 void Elem::family_tree_by_subneighbor (std::vector<Elem *> & family,
2103  Elem * neighbor,
2104  Elem * subneighbor,
2105  bool reset)
2106 {
2107  ElemInternal::family_tree_by_subneighbor(this, family, neighbor, subneighbor, reset);
2108 }
2109 
2110 
2111 
2112 void Elem::total_family_tree_by_subneighbor (std::vector<const Elem *> & family,
2113  const Elem * neighbor,
2114  const Elem * subneighbor,
2115  bool reset) const
2116 {
2117  ElemInternal::total_family_tree_by_subneighbor(this, family, neighbor, subneighbor, reset);
2118 }
2119 
2120 
2121 
2122 void Elem::total_family_tree_by_subneighbor (std::vector<Elem *> & family,
2123  Elem * neighbor,
2124  Elem * subneighbor,
2125  bool reset)
2126 {
2127  ElemInternal::total_family_tree_by_subneighbor(this, family, neighbor, subneighbor, reset);
2128 }
2129 
2130 
2131 
2132 void Elem::active_family_tree_by_neighbor (std::vector<const Elem *> & family,
2133  const Elem * neighbor,
2134  bool reset) const
2135 {
2136  ElemInternal::active_family_tree_by_neighbor(this, family, neighbor, reset);
2137 }
2138 
2139 
2140 
2141 void Elem::active_family_tree_by_neighbor (std::vector<Elem *> & family,
2142  Elem * neighbor,
2143  bool reset)
2144 {
2145  ElemInternal::active_family_tree_by_neighbor(this, family, neighbor, reset);
2146 }
2147 
2148 
2149 
2150 void Elem::active_family_tree_by_topological_neighbor (std::vector<const Elem *> & family,
2151  const Elem * neighbor,
2152  const MeshBase & mesh,
2153  const PointLocatorBase & point_locator,
2154  const PeriodicBoundaries * pb,
2155  bool reset) const
2156 {
2158  mesh, point_locator, pb,
2159  reset);
2160 }
2161 
2162 
2163 
2164 void Elem::active_family_tree_by_topological_neighbor (std::vector<Elem *> & family,
2165  Elem * neighbor,
2166  const MeshBase & mesh,
2167  const PointLocatorBase & point_locator,
2168  const PeriodicBoundaries * pb,
2169  bool reset)
2170 {
2172  mesh, point_locator, pb,
2173  reset);
2174 }
2175 
2176 
2177 bool Elem::is_child_on_edge(const unsigned int c,
2178  const unsigned int e) const
2179 {
2180  libmesh_assert_less (c, this->n_children());
2181  libmesh_assert_less (e, this->n_edges());
2182 
2183  std::unique_ptr<const Elem> my_edge = this->build_edge_ptr(e);
2184  std::unique_ptr<const Elem> child_edge = this->child_ptr(c)->build_edge_ptr(e);
2185 
2186  // We're assuming that an overlapping child edge has the same
2187  // number and orientation as its parent
2188  return (child_edge->node_id(0) == my_edge->node_id(0) ||
2189  child_edge->node_id(1) == my_edge->node_id(1));
2190 }
2191 
2192 
2193 
2194 unsigned int Elem::min_p_level_by_neighbor(const Elem * neighbor_in,
2195  unsigned int current_min) const
2196 {
2197  libmesh_assert(!this->subactive());
2198  libmesh_assert(neighbor_in->active());
2199 
2200  // If we're an active element this is simple
2201  if (this->active())
2202  return std::min(current_min, this->p_level());
2203 
2204  libmesh_assert(has_neighbor(neighbor_in));
2205 
2206  // The p_level() of an ancestor element is already the minimum
2207  // p_level() of its children - so if that's high enough, we don't
2208  // need to examine any children.
2209  if (current_min <= this->p_level())
2210  return current_min;
2211 
2212  unsigned int min_p_level = current_min;
2213 
2214  for (auto & c : this->child_ref_range())
2215  if (&c != remote_elem && c.has_neighbor(neighbor_in))
2216  min_p_level =
2217  c.min_p_level_by_neighbor(neighbor_in, min_p_level);
2218 
2219  return min_p_level;
2220 }
2221 
2222 
2223 unsigned int Elem::min_new_p_level_by_neighbor(const Elem * neighbor_in,
2224  unsigned int current_min) const
2225 {
2226  libmesh_assert(!this->subactive());
2227  libmesh_assert(neighbor_in->active());
2228 
2229  // If we're an active element this is simple
2230  if (this->active())
2231  {
2232  unsigned int new_p_level = this->p_level();
2233  if (this->p_refinement_flag() == Elem::REFINE)
2234  new_p_level += 1;
2235  if (this->p_refinement_flag() == Elem::COARSEN)
2236  {
2237  libmesh_assert_greater (new_p_level, 0);
2238  new_p_level -= 1;
2239  }
2240  return std::min(current_min, new_p_level);
2241  }
2242 
2243  libmesh_assert(has_neighbor(neighbor_in));
2244 
2245  unsigned int min_p_level = current_min;
2246 
2247  for (auto & c : this->child_ref_range())
2248  if (&c != remote_elem && c.has_neighbor(neighbor_in))
2249  min_p_level =
2250  c.min_new_p_level_by_neighbor(neighbor_in, min_p_level);
2251 
2252  return min_p_level;
2253 }
2254 
2255 
2256 
2257 unsigned int Elem::as_parent_node (unsigned int child,
2258  unsigned int child_node) const
2259 {
2260  const unsigned int nc = this->n_children();
2261  libmesh_assert_less(child, nc);
2262 
2263  // Cached return values, indexed first by embedding_matrix version,
2264  // then by child number, then by child node number.
2265  std::vector<std::vector<std::vector<signed char>>> &
2266  cached_parent_indices = this->_get_parent_indices_cache();
2267 
2268  unsigned int em_vers = this->embedding_matrix_version();
2269 
2270  // We may be updating the cache on one thread, and while that
2271  // happens we can't safely access the cache from other threads.
2272  Threads::spin_mutex::scoped_lock lock(parent_indices_mutex);
2273 
2274  if (em_vers >= cached_parent_indices.size())
2275  cached_parent_indices.resize(em_vers+1);
2276 
2277  if (child >= cached_parent_indices[em_vers].size())
2278  {
2279  const signed char nn = cast_int<signed char>(this->n_nodes());
2280 
2281  cached_parent_indices[em_vers].resize(nc);
2282 
2283  for (unsigned int c = 0; c != nc; ++c)
2284  {
2285  const unsigned int ncn = this->n_nodes_in_child(c);
2286  cached_parent_indices[em_vers][c].resize(ncn);
2287  for (unsigned int cn = 0; cn != ncn; ++cn)
2288  {
2289  for (signed char n = 0; n != nn; ++n)
2290  {
2291  const Real em_val = this->embedding_matrix
2292  (c, cn, n);
2293  if (em_val == 1)
2294  {
2295  cached_parent_indices[em_vers][c][cn] = n;
2296  break;
2297  }
2298 
2299  if (em_val != 0)
2300  {
2301  cached_parent_indices[em_vers][c][cn] =
2302  -1;
2303  break;
2304  }
2305 
2306  // We should never see an all-zero embedding matrix
2307  // row
2308  libmesh_assert_not_equal_to (n+1, nn);
2309  }
2310  }
2311  }
2312  }
2313 
2314  const signed char cache_val =
2315  cached_parent_indices[em_vers][child][child_node];
2316  if (cache_val == -1)
2317  return libMesh::invalid_uint;
2318 
2319  return cached_parent_indices[em_vers][child][child_node];
2320 }
2321 
2322 
2323 
2324 const std::vector<std::pair<unsigned char, unsigned char>> &
2326  unsigned int child_node) const
2327 {
2328  // Indexed first by embedding matrix type, then by child id, then by
2329  // child node, then by bracketing pair
2330  std::vector<std::vector<std::vector<std::vector<std::pair<unsigned char, unsigned char>>>>> &
2331  cached_bracketing_nodes = this->_get_bracketing_node_cache();
2332 
2333  const unsigned int em_vers = this->embedding_matrix_version();
2334 
2335  // We may be updating the cache on one thread, and while that
2336  // happens we can't safely access the cache from other threads.
2337  Threads::spin_mutex::scoped_lock lock(parent_bracketing_nodes_mutex);
2338 
2339  if (cached_bracketing_nodes.size() <= em_vers)
2340  cached_bracketing_nodes.resize(em_vers+1);
2341 
2342  const unsigned int nc = this->n_children();
2343 
2344  // If we haven't cached the bracketing nodes corresponding to this
2345  // embedding matrix yet, let's do so now.
2346  if (cached_bracketing_nodes[em_vers].size() < nc)
2347  {
2348  // If we're a second-order element but we're not a full-order
2349  // element, then some of our bracketing nodes may not exist
2350  // except on the equivalent full-order element. Let's build an
2351  // equivalent full-order element and make a copy of its cache to
2352  // use.
2353  if (this->default_order() != FIRST &&
2354  second_order_equivalent_type(this->type(), /*full_ordered=*/ true) != this->type())
2355  {
2356  // Check that we really are the non-full-order type
2357  libmesh_assert_equal_to
2358  (second_order_equivalent_type (this->type(), false),
2359  this->type());
2360 
2361  // Build the full-order type
2362  ElemType full_type =
2363  second_order_equivalent_type(this->type(), /*full_ordered=*/ true);
2364  std::unique_ptr<Elem> full_elem = Elem::build(full_type);
2365 
2366  // This won't work for elements with multiple
2367  // embedding_matrix versions, but every such element is full
2368  // order anyways.
2369  libmesh_assert_equal_to(em_vers, 0);
2370 
2371  // Make sure its cache has been built. We temporarily
2372  // release our mutex lock so that the inner call can
2373  // re-acquire it.
2374  lock.release();
2375  full_elem->parent_bracketing_nodes(0,0);
2376 
2377  // And then we need to lock again, so that if someone *else*
2378  // grabbed our lock before we did we don't risk accessing
2379  // cached_bracketing_nodes while they're working on it.
2380  // Threading is hard.
2381  lock.acquire(parent_bracketing_nodes_mutex);
2382 
2383  // Copy its cache
2384  cached_bracketing_nodes =
2385  full_elem->_get_bracketing_node_cache();
2386 
2387  // Now we don't need to build the cache ourselves.
2388  return cached_bracketing_nodes[em_vers][child][child_node];
2389  }
2390 
2391  cached_bracketing_nodes[em_vers].resize(nc);
2392 
2393  const unsigned int nn = this->n_nodes();
2394 
2395  // We have to examine each child
2396  for (unsigned int c = 0; c != nc; ++c)
2397  {
2398  const unsigned int ncn = this->n_nodes_in_child(c);
2399 
2400  cached_bracketing_nodes[em_vers][c].resize(ncn);
2401 
2402  // We have to examine each node in that child
2403  for (unsigned int n = 0; n != ncn; ++n)
2404  {
2405  // If this child node isn't a vertex or an infinite
2406  // child element's mid-infinite-edge node, then we need
2407  // to find bracketing nodes on the child.
2408  if (!this->is_vertex_on_child(c, n)
2409 #ifdef LIBMESH_ENABLE_INFINITE_ELEMENTS
2410  && !this->is_mid_infinite_edge_node(n)
2411 #endif
2412  )
2413  {
2414  // Use the embedding matrix to find the child node
2415  // location in parent master element space
2416  Point bracketed_pt;
2417 
2418  for (unsigned int pn = 0; pn != nn; ++pn)
2419  {
2420  const Real em_val =
2421  this->embedding_matrix(c,n,pn);
2422 
2423  libmesh_assert_not_equal_to (em_val, 1);
2424  if (em_val != 0.)
2425  bracketed_pt.add_scaled(this->master_point(pn), em_val);
2426  }
2427 
2428  // Check each pair of nodes on the child which are
2429  // also both parent nodes
2430  for (unsigned int n1 = 0; n1 != ncn; ++n1)
2431  {
2432  if (n1 == n)
2433  continue;
2434 
2435  unsigned int parent_n1 =
2436  this->as_parent_node(c,n1);
2437 
2438  if (parent_n1 == libMesh::invalid_uint)
2439  continue;
2440 
2441  Point p1 = this->master_point(parent_n1);
2442 
2443  for (unsigned int n2 = n1+1; n2 < nn; ++n2)
2444  {
2445  if (n2 == n)
2446  continue;
2447 
2448  unsigned int parent_n2 =
2449  this->as_parent_node(c,n2);
2450 
2451  if (parent_n2 == libMesh::invalid_uint)
2452  continue;
2453 
2454  Point p2 = this->master_point(parent_n2);
2455 
2456  Point pmid = (p1 + p2)/2;
2457 
2458  if (pmid == bracketed_pt)
2459  {
2460  cached_bracketing_nodes[em_vers][c][n].emplace_back(parent_n1, parent_n2);
2461  break;
2462  }
2463  else
2464  libmesh_assert(!pmid.absolute_fuzzy_equals(bracketed_pt));
2465  }
2466  }
2467  }
2468  // If this child node is a parent node, we need to
2469  // find bracketing nodes on the parent.
2470  else
2471  {
2472  unsigned int parent_node = this->as_parent_node(c,n);
2473 
2474  Point bracketed_pt;
2475 
2476  // If we're not a parent node, use the embedding
2477  // matrix to find the child node location in parent
2478  // master element space
2479  if (parent_node == libMesh::invalid_uint)
2480  {
2481  for (unsigned int pn = 0; pn != nn; ++pn)
2482  {
2483  const Real em_val =
2484  this->embedding_matrix(c,n,pn);
2485 
2486  libmesh_assert_not_equal_to (em_val, 1);
2487  if (em_val != 0.)
2488  bracketed_pt.add_scaled(this->master_point(pn), em_val);
2489  }
2490  }
2491  // If we're a parent node then we need no arithmetic
2492  else
2493  bracketed_pt = this->master_point(parent_node);
2494 
2495  for (unsigned int n1 = 0; n1 != nn; ++n1)
2496  {
2497  if (n1 == parent_node)
2498  continue;
2499 
2500  Point p1 = this->master_point(n1);
2501 
2502  for (unsigned int n2 = n1+1; n2 < nn; ++n2)
2503  {
2504  if (n2 == parent_node)
2505  continue;
2506 
2507  Point pmid = (p1 + this->master_point(n2))/2;
2508 
2509  if (pmid == bracketed_pt)
2510  {
2511  cached_bracketing_nodes[em_vers][c][n].emplace_back(n1, n2);
2512  break;
2513  }
2514  else
2515  libmesh_assert(!pmid.absolute_fuzzy_equals(bracketed_pt));
2516  }
2517  }
2518  }
2519  }
2520  }
2521  }
2522 
2523  return cached_bracketing_nodes[em_vers][child][child_node];
2524 }
2525 
2526 
2527 const std::vector<std::pair<dof_id_type, dof_id_type>>
2528 Elem::bracketing_nodes(unsigned int child,
2529  unsigned int child_node) const
2530 {
2531  std::vector<std::pair<dof_id_type, dof_id_type>> returnval;
2532 
2533  const std::vector<std::pair<unsigned char, unsigned char>> & pbc =
2534  this->parent_bracketing_nodes(child,child_node);
2535 
2536  for (const auto & pb : pbc)
2537  {
2538  const unsigned short n_n = this->n_nodes();
2539  if (pb.first < n_n && pb.second < n_n)
2540  returnval.emplace_back(this->node_id(pb.first), this->node_id(pb.second));
2541  else
2542  {
2543  // We must be on a non-full-order higher order element...
2544  libmesh_assert_not_equal_to(this->default_order(), FIRST);
2545  libmesh_assert_not_equal_to
2546  (second_order_equivalent_type (this->type(), true),
2547  this->type());
2548  libmesh_assert_equal_to
2549  (second_order_equivalent_type (this->type(), false),
2550  this->type());
2551 
2552  // And that's a shame, because this is a nasty search:
2553 
2554  // Build the full-order type
2555  ElemType full_type =
2556  second_order_equivalent_type(this->type(), /*full_ordered=*/ true);
2557  std::unique_ptr<Elem> full_elem = Elem::build(full_type);
2558 
2561 
2562  // Find the bracketing nodes by figuring out what
2563  // already-created children will have them.
2564 
2565  // This only doesn't break horribly because we add children
2566  // and nodes in straightforward + hierarchical orders...
2567  for (unsigned int c=0; c <= child; ++c)
2568  for (auto n : make_range(this->n_nodes_in_child(c)))
2569  {
2570  if (c == child && n == child_node)
2571  break;
2572 
2573  if (pb.first == full_elem->as_parent_node(c,n))
2574  {
2575  // We should be consistent
2576  if (pt1 != DofObject::invalid_id)
2577  libmesh_assert_equal_to(pt1, this->child_ptr(c)->node_id(n));
2578 
2579  pt1 = this->child_ptr(c)->node_id(n);
2580  }
2581 
2582  if (pb.second == full_elem->as_parent_node(c,n))
2583  {
2584  // We should be consistent
2585  if (pt2 != DofObject::invalid_id)
2586  libmesh_assert_equal_to(pt2, this->child_ptr(c)->node_id(n));
2587 
2588  pt2 = this->child_ptr(c)->node_id(n);
2589  }
2590  }
2591 
2592  // We should *usually* find all bracketing nodes by the time
2593  // we query them (again, because of the child & node add
2594  // order)
2595  //
2596  // The exception is if we're a HEX20, in which case we will
2597  // find pairs of vertex nodes and edge nodes bracketing the
2598  // new central node but we *won't* find the pairs of face
2599  // nodes which we would have had on a HEX27. In that case
2600  // we'll still have enough bracketing nodes for a
2601  // topological lookup, but we won't be able to make the
2602  // following assertions.
2603  if (this->type() != HEX20)
2604  {
2605  libmesh_assert_not_equal_to (pt1, DofObject::invalid_id);
2606  libmesh_assert_not_equal_to (pt2, DofObject::invalid_id);
2607  }
2608 
2609  if (pt1 != DofObject::invalid_id &&
2610  pt2 != DofObject::invalid_id)
2611  returnval.emplace_back(pt1, pt2);
2612  }
2613  }
2614 
2615  return returnval;
2616 }
2617 #endif // #ifdef LIBMESH_ENABLE_AMR
2618 
2619 
2620 
2621 
2622 bool Elem::contains_point (const Point & p, Real tol) const
2623 {
2624  // We currently allow the user to enlarge the bounding box by
2625  // providing a tol > TOLERANCE (so this routine is identical to
2626  // Elem::close_to_point()), but print a warning so that the
2627  // user can eventually switch his code over to calling close_to_point()
2628  // instead, which is intended to be used for this purpose.
2629  if (tol > TOLERANCE)
2630  {
2631  libmesh_do_once(libMesh::err
2632  << "WARNING: Resizing bounding box to match user-specified tolerance!\n"
2633  << "In the future, calls to Elem::contains_point() with tol > TOLERANCE\n"
2634  << "will be more optimized, but should not be used\n"
2635  << "to search for points 'close to' elements!\n"
2636  << "Instead, use Elem::close_to_point() for this purpose.\n"
2637  << std::endl;);
2638  return this->point_test(p, tol, tol);
2639  }
2640  else
2641  return this->point_test(p, TOLERANCE, tol);
2642 }
2643 
2644 
2645 
2646 
2647 bool Elem::close_to_point (const Point & p, Real tol) const
2648 {
2649  // This test uses the user's passed-in tolerance for the
2650  // bounding box test as well, thereby allowing the routine to
2651  // find points which are not only "in" the element, but also
2652  // "nearby" to within some tolerance.
2653  return this->point_test(p, tol, tol);
2654 }
2655 
2656 
2657 
2658 
2659 bool Elem::point_test(const Point & p, Real box_tol, Real map_tol) const
2660 {
2661  libmesh_assert_greater (box_tol, 0.);
2662  libmesh_assert_greater (map_tol, 0.);
2663 
2664  // This is a great optimization on first order elements, but it
2665  // could return false negatives on higher orders
2666  if (this->default_order() == FIRST)
2667  {
2668  // Check to make sure the element *could* contain this point, so we
2669  // can avoid an expensive inverse_map call if it doesn't.
2670  bool
2671 #if LIBMESH_DIM > 2
2672  point_above_min_z = false,
2673  point_below_max_z = false,
2674 #endif
2675 #if LIBMESH_DIM > 1
2676  point_above_min_y = false,
2677  point_below_max_y = false,
2678 #endif
2679  point_above_min_x = false,
2680  point_below_max_x = false;
2681 
2682  // For relative bounding box checks in physical space
2683  const Real my_hmax = this->hmax();
2684 
2685  for (auto & n : this->node_ref_range())
2686  {
2687  point_above_min_x = point_above_min_x || (n(0) - my_hmax*box_tol <= p(0));
2688  point_below_max_x = point_below_max_x || (n(0) + my_hmax*box_tol >= p(0));
2689 #if LIBMESH_DIM > 1
2690  point_above_min_y = point_above_min_y || (n(1) - my_hmax*box_tol <= p(1));
2691  point_below_max_y = point_below_max_y || (n(1) + my_hmax*box_tol >= p(1));
2692 #endif
2693 #if LIBMESH_DIM > 2
2694  point_above_min_z = point_above_min_z || (n(2) - my_hmax*box_tol <= p(2));
2695  point_below_max_z = point_below_max_z || (n(2) + my_hmax*box_tol >= p(2));
2696 #endif
2697  }
2698 
2699  if (
2700 #if LIBMESH_DIM > 2
2701  !point_above_min_z ||
2702  !point_below_max_z ||
2703 #endif
2704 #if LIBMESH_DIM > 1
2705  !point_above_min_y ||
2706  !point_below_max_y ||
2707 #endif
2708  !point_above_min_x ||
2709  !point_below_max_x)
2710  return false;
2711  }
2712 
2713  // To be on the safe side, we converge the inverse_map() iteration
2714  // to a slightly tighter tolerance than that requested by the
2715  // user...
2716  const Point mapped_point = FEMap::inverse_map(this->dim(),
2717  this,
2718  p,
2719  0.1*map_tol, // <- this is |dx| tolerance, the Newton residual should be ~ |dx|^2
2720  /*secure=*/ false,
2721  /*extra_checks=*/ false);
2722 
2723  // Check that the refspace point maps back to p! This is only necessary
2724  // for 1D and 2D elements, 3D elements always live in 3D.
2725  //
2726  // TODO: The contains_point() function could most likely be implemented
2727  // more efficiently in the element sub-classes themselves, at least for
2728  // the linear element types.
2729  if (this->dim() < 3)
2730  {
2731  Point xyz = FEMap::map(this->dim(), this, mapped_point);
2732 
2733  // Compute the distance between the original point and the re-mapped point.
2734  // They should be in the same place.
2735  Real dist = (xyz - p).norm();
2736 
2737 
2738  // If dist is larger than some fraction of the tolerance, then return false.
2739  // This can happen when e.g. a 2D element is living in 3D, and
2740  // FEMap::inverse_map() maps p onto the projection of the element,
2741  // effectively "tricking" on_reference_element().
2742  if (dist > this->hmax() * map_tol)
2743  return false;
2744  }
2745 
2746  return this->on_reference_element(mapped_point, map_tol);
2747 }
2748 
2749 
2750 
2751 
2752 bool Elem::has_invertible_map(Real /*tol*/) const
2753 {
2754  QNodal qnodal {this->dim()};
2755  FEMap fe_map;
2756  auto & jac = fe_map.get_jacobian();
2757 
2758  // We have a separate check for is_singular_node() below, so in this
2759  // case its "OK" to do nodal quadrature on pyramids.
2760  qnodal.allow_nodal_pyramid_quadrature = true;
2761  qnodal.init(*this);
2762  auto & qp = qnodal.get_points();
2763  libmesh_assert_equal_to(qp.size(), this->n_nodes());
2764 
2765  std::vector<Point> one_point(1);
2766  std::vector<Real> one_weight(1,1);
2767  for (auto i : index_range(qp))
2768  {
2769  if (this->is_singular_node(i))
2770  continue;
2771 
2772  one_point[0] = qp[i];
2773 
2774  fe_map.init_reference_to_physical_map(this->dim(), one_point, this);
2775  fe_map.compute_map(this->dim(), one_weight, this, false);
2776 
2777  if (jac[0] <= 0)
2778  return false;
2779  }
2780 
2781  return true;
2782 }
2783 
2784 
2785 
2786 void Elem::print_info (std::ostream & os) const
2787 {
2788  os << this->get_info()
2789  << std::endl;
2790 }
2791 
2792 
2793 
2794 std::string Elem::get_info () const
2795 {
2796  std::ostringstream oss;
2797 
2798  oss << " Elem Information" << '\n'
2799  << " id()=";
2800 
2801  if (this->valid_id())
2802  oss << this->id();
2803  else
2804  oss << "invalid";
2805 
2806 #ifdef LIBMESH_ENABLE_UNIQUE_ID
2807  oss << ", unique_id()=";
2808  if (this->valid_unique_id())
2809  oss << this->unique_id();
2810  else
2811  oss << "invalid";
2812 #endif
2813 
2814  oss << ", subdomain_id()=" << this->subdomain_id();
2815  oss << ", processor_id()=" << this->processor_id() << '\n';
2816 
2817  oss << " type()=" << Utility::enum_to_string(this->type()) << '\n'
2818  << " dim()=" << this->dim() << '\n'
2819  << " n_nodes()=" << this->n_nodes() << '\n';
2820 
2821  oss << " mapping=" << Utility::enum_to_string(this->mapping_type()) << '\n';
2822 
2823  for (auto n : this->node_index_range())
2824  {
2825  oss << " " << n << this->node_ref(n);
2826  if (this->mapping_type() == RATIONAL_BERNSTEIN_MAP)
2827  {
2828  const unsigned char datum_index = this->mapping_data();
2829  oss << " weight=" <<
2830  this->node_ref(n).get_extra_datum<Real>(datum_index) << '\n';
2831  }
2832  }
2833 
2834  oss << " n_sides()=" << this->n_sides() << '\n';
2835 
2836  for (auto s : this->side_index_range())
2837  {
2838  oss << " neighbor(" << s << ")=";
2839  if (this->neighbor_ptr(s))
2840  oss << this->neighbor_ptr(s)->id() << '\n';
2841  else
2842  oss << "nullptr\n";
2843  }
2844 
2845  if (!this->infinite())
2846  {
2847  oss << " hmin()=" << this->hmin()
2848  << ", hmax()=" << this->hmax() << '\n'
2849  << " volume()=" << this->volume() << '\n';
2850  }
2851  oss << " active()=" << this->active()
2852  << ", ancestor()=" << this->ancestor()
2853  << ", subactive()=" << this->subactive()
2854  << ", has_children()=" << this->has_children() << '\n'
2855  << " parent()=";
2856  if (this->parent())
2857  oss << this->parent()->id() << '\n';
2858  else
2859  oss << "nullptr\n";
2860  oss << " level()=" << this->level()
2861  << ", p_level()=" << this->p_level() << '\n'
2862 #ifdef LIBMESH_ENABLE_AMR
2863  << " refinement_flag()=" << Utility::enum_to_string(this->refinement_flag()) << '\n'
2864  << " p_refinement_flag()=" << Utility::enum_to_string(this->p_refinement_flag()) << '\n'
2865 #endif
2866 #ifdef LIBMESH_ENABLE_INFINITE_ELEMENTS
2867  << " infinite()=" << this->infinite() << '\n';
2868  if (this->infinite())
2869  oss << " origin()=" << this->origin() << '\n'
2870 #endif
2871  ;
2872 
2873  oss << " DoFs=";
2874  for (auto s : make_range(this->n_systems()))
2875  for (auto v : make_range(this->n_vars(s)))
2876  for (auto c : make_range(this->n_comp(s,v)))
2877  oss << '(' << s << '/' << v << '/' << this->dof_number(s,v,c) << ") ";
2878 
2879 
2880  return oss.str();
2881 }
2882 
2883 
2884 
2886 {
2887  // Tell any of my neighbors about my death...
2888  // Looks strange, huh?
2889  for (auto n : this->side_index_range())
2890  {
2891  Elem * current_neighbor = this->neighbor_ptr(n);
2892  if (current_neighbor && current_neighbor != remote_elem)
2893  {
2894  // Note: it is possible that I see the neighbor
2895  // (which is coarser than me)
2896  // but they don't see me, so avoid that case.
2897  if (current_neighbor->level() == this->level())
2898  {
2899  const unsigned int w_n_a_i = current_neighbor->which_neighbor_am_i(this);
2900  libmesh_assert_less (w_n_a_i, current_neighbor->n_neighbors());
2901  current_neighbor->set_neighbor(w_n_a_i, nullptr);
2902  this->set_neighbor(n, nullptr);
2903  }
2904  }
2905  }
2906 }
2907 
2908 
2909 
2910 
2911 unsigned int Elem::n_second_order_adjacent_vertices (const unsigned int) const
2912 {
2913  // for linear elements, always return 0
2914  return 0;
2915 }
2916 
2917 
2918 
2919 unsigned short int Elem::second_order_adjacent_vertex (const unsigned int,
2920  const unsigned int) const
2921 {
2922  // for linear elements, always return 0
2923  return 0;
2924 }
2925 
2926 
2927 
2928 std::pair<unsigned short int, unsigned short int>
2929 Elem::second_order_child_vertex (const unsigned int) const
2930 {
2931  // for linear elements, always return 0
2932  return std::pair<unsigned short int, unsigned short int>(0,0);
2933 }
2934 
2935 
2936 
2938 {
2939  switch (et)
2940  {
2941  case NODEELEM:
2942  return NODEELEM;
2943  case EDGE2:
2944  case EDGE3:
2945  case EDGE4:
2946  return EDGE2;
2947  case TRI3:
2948  case TRI6:
2949  case TRI7:
2950  return TRI3;
2951  case TRISHELL3:
2952  return TRISHELL3;
2953  case QUAD4:
2954  case QUAD8:
2955  case QUAD9:
2956  return QUAD4;
2957  case QUADSHELL4:
2958  case QUADSHELL8:
2959  case QUADSHELL9:
2960  return QUADSHELL4;
2961  case TET4:
2962  case TET10:
2963  case TET14:
2964  return TET4;
2965  case HEX8:
2966  case HEX27:
2967  case HEX20:
2968  return HEX8;
2969  case PRISM6:
2970  case PRISM15:
2971  case PRISM18:
2972  case PRISM20:
2973  case PRISM21:
2974  return PRISM6;
2975  case PYRAMID5:
2976  case PYRAMID13:
2977  case PYRAMID14:
2978  case PYRAMID18:
2979  return PYRAMID5;
2980 
2981 #ifdef LIBMESH_ENABLE_INFINITE_ELEMENTS
2982 
2983  case INFEDGE2:
2984  return INFEDGE2;
2985  case INFQUAD4:
2986  case INFQUAD6:
2987  return INFQUAD4;
2988  case INFHEX8:
2989  case INFHEX16:
2990  case INFHEX18:
2991  return INFHEX8;
2992  case INFPRISM6:
2993  case INFPRISM12:
2994  return INFPRISM6;
2995 
2996 #endif
2997 
2998  default:
2999  // unknown element
3000  return INVALID_ELEM;
3001  }
3002 }
3003 
3004 
3005 
3007  const bool full_ordered)
3008 {
3009  switch (et)
3010  {
3011  case NODEELEM:
3012  return NODEELEM;
3013  case EDGE2:
3014  case EDGE3:
3015  {
3016  // full_ordered not relevant
3017  return EDGE3;
3018  }
3019 
3020  case EDGE4:
3021  {
3022  // full_ordered not relevant
3023  return EDGE4;
3024  }
3025 
3026  case TRI3:
3027  case TRI6:
3028  {
3029  // full_ordered not relevant
3030  return TRI6;
3031  }
3032 
3033  case TRI7:
3034  return TRI7;
3035 
3036  // Currently there is no TRISHELL6, so similarly to other types
3037  // where this is the case, we just return the input.
3038  case TRISHELL3:
3039  return TRISHELL3;
3040 
3041  case QUAD4:
3042  case QUAD8:
3043  {
3044  if (full_ordered)
3045  return QUAD9;
3046  else
3047  return QUAD8;
3048  }
3049 
3050  case QUADSHELL4:
3051  case QUADSHELL8:
3052  {
3053  if (full_ordered)
3054  return QUADSHELL9;
3055  else
3056  return QUADSHELL8;
3057  }
3058 
3059  case QUAD9:
3060  {
3061  // full_ordered not relevant
3062  return QUAD9;
3063  }
3064 
3065  case QUADSHELL9:
3066  {
3067  // full_ordered not relevant
3068  return QUADSHELL9;
3069  }
3070 
3071  case TET4:
3072  case TET10:
3073  {
3074  // full_ordered not relevant
3075  return TET10;
3076  }
3077 
3078  case TET14:
3079  return TET14;
3080 
3081  case HEX8:
3082  case HEX20:
3083  {
3084  // see below how this correlates with INFHEX8
3085  if (full_ordered)
3086  return HEX27;
3087  else
3088  return HEX20;
3089  }
3090 
3091  case HEX27:
3092  {
3093  // full_ordered not relevant
3094  return HEX27;
3095  }
3096 
3097  case PRISM6:
3098  case PRISM15:
3099  {
3100  if (full_ordered)
3101  return PRISM18;
3102  else
3103  return PRISM15;
3104  }
3105 
3106  // full_ordered not relevant, already fully second order
3107  case PRISM18:
3108  return PRISM18;
3109  case PRISM20:
3110  return PRISM20;
3111  case PRISM21:
3112  return PRISM21;
3113  case PYRAMID18:
3114  return PYRAMID18;
3115 
3116  case PYRAMID5:
3117  case PYRAMID13:
3118  {
3119  if (full_ordered)
3120  return PYRAMID14;
3121  else
3122  return PYRAMID13;
3123  }
3124 
3125  case PYRAMID14:
3126  {
3127  // full_ordered not relevant
3128  return PYRAMID14;
3129  }
3130 
3131 
3132 
3133 #ifdef LIBMESH_ENABLE_INFINITE_ELEMENTS
3134 
3135  // infinite elements
3136  case INFEDGE2:
3137  {
3138  return INFEDGE2;
3139  }
3140 
3141  case INFQUAD4:
3142  case INFQUAD6:
3143  {
3144  // full_ordered not relevant
3145  return INFQUAD6;
3146  }
3147 
3148  case INFHEX8:
3149  case INFHEX16:
3150  {
3151  /*
3152  * Note that this matches with \p Hex8:
3153  * For full-ordered, \p InfHex18 and \p Hex27
3154  * belong together, and for not full-ordered,
3155  * \p InfHex16 and \p Hex20 belong together.
3156  */
3157  if (full_ordered)
3158  return INFHEX18;
3159  else
3160  return INFHEX16;
3161  }
3162 
3163  case INFHEX18:
3164  {
3165  // full_ordered not relevant
3166  return INFHEX18;
3167  }
3168 
3169  case INFPRISM6:
3170  case INFPRISM12:
3171  {
3172  // full_ordered not relevant
3173  return INFPRISM12;
3174  }
3175 
3176 #endif
3177 
3178 
3179  default:
3180  {
3181  // what did we miss?
3182  libmesh_error_msg("No second order equivalent element type for et = "
3183  << Utility::enum_to_string(et));
3184  }
3185  }
3186 }
3187 
3188 
3189 
3191 {
3192  switch (et)
3193  {
3194  case NODEELEM:
3195  return NODEELEM;
3196  case EDGE2:
3197  case EDGE3:
3198  return EDGE3;
3199 
3200  case EDGE4:
3201  return EDGE4;
3202 
3203  case TRI3:
3204  case TRI6:
3205  case TRI7:
3206  return TRI7;
3207 
3208  // Currently there is no TRISHELL6, so similarly to other types
3209  // where this is the case, we just return the input.
3210  case TRISHELL3:
3211  return TRISHELL3;
3212 
3213  case QUAD4:
3214  case QUAD8:
3215  case QUAD9:
3216  return QUAD9;
3217 
3218  case QUADSHELL4:
3219  case QUADSHELL8:
3220  case QUADSHELL9:
3221  return QUADSHELL9;
3222 
3223  case TET4:
3224  case TET10:
3225  case TET14:
3226  return TET14;
3227 
3228  case HEX8:
3229  case HEX20:
3230  case HEX27:
3231  return HEX27;
3232 
3233  // We don't strictly need the 21st node for DoFs, but some code
3234  // depends on it for e.g. refinement patterns
3235  case PRISM6:
3236  case PRISM15:
3237  case PRISM18:
3238  case PRISM20:
3239  case PRISM21:
3240  return PRISM21;
3241 
3242  case PYRAMID5:
3243  case PYRAMID13:
3244  case PYRAMID14:
3245  case PYRAMID18:
3246  return PYRAMID18;
3247 
3248 
3249 
3250 #ifdef LIBMESH_ENABLE_INFINITE_ELEMENTS
3251  case INFEDGE2:
3252  return INFEDGE2;
3253 
3254  case INFQUAD4:
3255  case INFQUAD6:
3256  return INFQUAD6;
3257 
3258  case INFHEX8:
3259  case INFHEX16:
3260  case INFHEX18:
3261  return INFHEX18;
3262 
3263  // Probably ought to implement INFPRISM13 and/or 14; until then
3264  // we'll just return the not-complete-order ElemType, in
3265  // accordance which what seems like bad precedent...
3266  case INFPRISM6:
3267  case INFPRISM12:
3268  return INFPRISM12;
3269 #endif // LIBMESH_ENABLE_INFINITE_ELEMENTS
3270 
3271  default:
3272  {
3273  // what did we miss?
3274  libmesh_error_msg("No complete order equivalent element type for et = "
3275  << Utility::enum_to_string(et));
3276  }
3277  }
3278 }
3279 
3280 
3281 
3283 {
3285  return side_iterator(this->_first_side(), this->_last_side(), bsp);
3286 }
3287 
3288 
3289 
3290 
3292 {
3294  return side_iterator(this->_last_side(), this->_last_side(), bsp);
3295 }
3296 
3297 
3298 
3299 
3301 {
3302  // The default implementation builds a finite element of the correct
3303  // order and sums up the JxW contributions. This can be expensive,
3304  // so the various element types can overload this method and compute
3305  // the volume more efficiently.
3306  const FEFamily mapping_family = FEMap::map_fe_type(*this);
3307  const FEType fe_type(this->default_order(), mapping_family);
3308 
3309  std::unique_ptr<FEBase> fe (FEBase::build(this->dim(),
3310  fe_type));
3311 
3312  // Use a map with a negative Jacobian tolerance, in case we're asked
3313  // for the net volume of a tangled element
3314  fe->get_fe_map().set_jacobian_tolerance(std::numeric_limits<Real>::lowest());
3315 
3316  const std::vector<Real> & JxW = fe->get_JxW();
3317 
3318  // The default quadrature rule should integrate the mass matrix,
3319  // thus it should be plenty to compute the area
3320  QGauss qrule (this->dim(), fe_type.default_quadrature_order());
3321 
3322  fe->attach_quadrature_rule(&qrule);
3323 
3324  fe->reinit(this);
3325 
3326  Real vol=0.;
3327  for (auto jxw : JxW)
3328  vol += jxw;
3329 
3330  return vol;
3331 
3332 }
3333 
3334 
3335 
3337 {
3338  Point pmin = this->point(0);
3339  Point pmax = pmin;
3340 
3341  unsigned int n_points = this->n_nodes();
3342  for (unsigned int p=0; p != n_points; ++p)
3343  for (unsigned d=0; d<LIBMESH_DIM; ++d)
3344  {
3345  const Point & pt = this->point(p);
3346  if (pmin(d) > pt(d))
3347  pmin(d) = pt(d);
3348 
3349  if (pmax(d) < pt(d))
3350  pmax(d) = pt(d);
3351  }
3352 
3353  return BoundingBox(pmin, pmax);
3354 }
3355 
3356 
3357 
3358 bool Elem::is_vertex_on_parent(unsigned int c,
3359  unsigned int n) const
3360 {
3361 #ifdef LIBMESH_ENABLE_AMR
3362 
3363  unsigned int my_n_vertices = this->n_vertices();
3364  for (unsigned int n_parent = 0; n_parent != my_n_vertices;
3365  ++n_parent)
3366  if (this->node_ptr(n_parent) == this->child_ptr(c)->node_ptr(n))
3367  return true;
3368  return false;
3369 
3370 #else
3371 
3372  // No AMR?
3373  libmesh_ignore(c,n);
3374  libmesh_error_msg("ERROR: AMR disabled, how did we get here?");
3375  return true;
3376 
3377 #endif
3378 }
3379 
3380 
3381 
3382 unsigned int Elem::opposite_side(const unsigned int /*s*/) const
3383 {
3384  // If the subclass didn't rederive this, using it is an error
3385  libmesh_not_implemented();
3386 }
3387 
3388 
3389 
3390 unsigned int Elem::opposite_node(const unsigned int /*n*/,
3391  const unsigned int /*s*/) const
3392 {
3393  // If the subclass didn't rederive this, using it is an error
3394  libmesh_not_implemented();
3395 }
3396 
3397 
3398 unsigned int Elem::center_node_on_side(const unsigned short libmesh_dbg_var(side)) const
3399 {
3400  libmesh_assert_less (side, this->n_sides());
3401  return invalid_uint;
3402 }
3403 
3404 
3405 void Elem::swap2boundarysides(unsigned short s1,
3406  unsigned short s2,
3407  BoundaryInfo * boundary_info) const
3408 {
3409  std::vector<boundary_id_type> ids1, ids2;
3410  boundary_info->boundary_ids(this, s1, ids1);
3411  boundary_info->boundary_ids(this, s2, ids2);
3412  boundary_info->remove_side(this, s1);
3413  boundary_info->remove_side(this, s2);
3414  if (!ids1.empty())
3415  boundary_info->add_side(this, s2, ids1);
3416  if (!ids2.empty())
3417  boundary_info->add_side(this, s1, ids2);
3418 }
3419 
3420 
3421 void Elem::swap2boundaryedges(unsigned short e1,
3422  unsigned short e2,
3423  BoundaryInfo * boundary_info) const
3424 {
3425  std::vector<boundary_id_type> ids1, ids2;
3426  boundary_info->edge_boundary_ids(this, e1, ids1);
3427  boundary_info->edge_boundary_ids(this, e2, ids2);
3428  boundary_info->remove_edge(this, e1);
3429  boundary_info->remove_edge(this, e2);
3430  if (!ids1.empty())
3431  boundary_info->add_edge(this, e2, ids1);
3432  if (!ids2.empty())
3433  boundary_info->add_edge(this, e1, ids2);
3434 }
3435 
3436 bool
3437 Elem::is_internal(const unsigned int i) const
3438 {
3439  switch (this->dim())
3440  {
3441  case 0:
3442  return false;
3443 
3444  case 1:
3445  return !this->is_vertex(i);
3446 
3447  case 2:
3448  return !this->is_vertex(i) && !this->is_edge(i);
3449 
3450  case 3:
3451  return !this->is_vertex(i) && !this->is_edge(i) && !this->is_face(i);
3452 
3453  default:
3454  libmesh_error_msg("impossible element dimension " << std::to_string(this->dim()));
3455  return 0;
3456  }
3457 }
3458 
3459 bool
3460 Elem::positive_edge_orientation(const unsigned int i) const
3461 {
3462  libmesh_assert_less (i, this->n_edges());
3463 
3464  return this->point(this->local_edge_node(i, 0)) >
3465  this->point(this->local_edge_node(i, 1));
3466 }
3467 
3468 bool
3469 Elem::positive_face_orientation(const unsigned int i) const
3470 {
3471  libmesh_assert_less (i, this->n_faces());
3472 
3473  // Get the number of vertices N of face i. Note that for 3d elements, i.e.
3474  // elements for which this->n_faces() > 0, the number of vertices on any of
3475  // its sides (or faces) is just the number of that face's sides (or edges).
3476  auto side_i = this->side_ptr(i);
3477  const unsigned int N = side_i->n_sides();
3478 
3479  const std::vector<unsigned int> nodes = this->nodes_on_side(i);
3480  std::vector<Point> vertices(N);
3481  std::transform(nodes.begin(), nodes.begin() + N, vertices.begin(),
3482  [&](unsigned int n) { return this->point(n); });
3483 
3484  for (unsigned int j = 0; j < N - 3; j++)
3485  std::rotate(vertices.begin() + j,
3486  std::min_element(vertices.begin() + j, vertices.end()),
3487  vertices.end());
3488 
3489  unsigned int cnt = 0;
3490  for (unsigned int j = N - 3; j < N; j++)
3491  for (unsigned int k = j + 1; k < N; k++)
3492  if (vertices[j] > vertices[k])
3493  cnt++;
3494 
3495  return cnt % 2;
3496 }
3497 
3498 } // namespace libMesh
virtual Point true_centroid() const
Definition: elem.C:465
void active_family_tree_by_topological_neighbor(std::vector< const Elem *> &family, const Elem *neighbor, const MeshBase &mesh, const PointLocatorBase &point_locator, const PeriodicBoundaries *pb, bool reset=true) const
Same as the active_family_tree_by_neighbor() member, but the neighbor here may be a topological (e...
Definition: elem.C:2150
class FEType hides (possibly multiple) FEFamily and approximation orders, thereby enabling specialize...
Definition: fe_type.h:196
OStreamProxy err
bool has_neighbor(const Elem *elem) const
Definition: elem.h:2550
unsigned char mapping_data() const
Definition: elem.h:3086
virtual bool is_vertex_on_parent(unsigned int c, unsigned int n) const
Definition: elem.C:3358
RefinementState refinement_flag() const
Definition: elem.h:3160
ElemType
Defines an enum for geometric element types.
void swap2boundaryedges(unsigned short e1, unsigned short e2, BoundaryInfo *boundary_info) const
Swaps two edges in boundary_info, if it is non-null.
Definition: elem.C:3421
void total_family_tree(T elem, std::vector< T > &family, bool reset)
Definition: elem_internal.h:67
dof_id_type dof_number(const unsigned int s, const unsigned int var, const unsigned int comp) const
Definition: dof_object.h:1032
void write_connectivity(std::ostream &out, const IOPackage iop) const
Writes the element connectivity for various IO packages to the passed ostream "out".
Definition: elem.C:1602
const Elem * parent() const
Definition: elem.h:2980
void add_scaled(const TypeVector< T2 > &, const T &)
Add a scaled value to this vector without creating a temporary.
Definition: type_vector.h:629
virtual const std::vector< std::pair< dof_id_type, dof_id_type > > bracketing_nodes(unsigned int c, unsigned int n) const
Definition: elem.C:2528
void print_info(std::ostream &os=libMesh::out) const
Prints relevant information about the element.
Definition: elem.C:2786
void active_family_tree_by_side(std::vector< const Elem *> &family, unsigned int side, bool reset=true) const
Same as the active_family_tree() member, but only adds elements which are next to side...
Definition: elem.C:2038
void remove_edge(const Elem *elem, const unsigned short int edge)
Removes all boundary conditions associated with edge edge of element elem, if any exist...
A Node is like a Point, but with more information.
Definition: node.h:52
Node ** _nodes
Pointers to the nodes we are connected to.
Definition: elem.h:2195
virtual std::vector< unsigned int > sides_on_edge(const unsigned int) const =0
static ElemType complete_order_equivalent_type(const ElemType et)
Definition: elem.C:3190
virtual Point origin() const
Definition: elem.h:1863
const unsigned int invalid_uint
A number which is used quite often to represent an invalid or uninitialized value for an unsigned int...
Definition: libmesh.h:293
unsigned int n_comp(const unsigned int s, const unsigned int var) const
Definition: dof_object.h:1002
virtual void compute_map(const unsigned int dim, const std::vector< Real > &qw, const Elem *elem, bool calculate_d2phi)
Compute the jacobian and some other additional data fields.
Definition: fe_map.C:1439
std::string get_info() const
Prints relevant information about the element to a string.
Definition: elem.C:2794
static const unsigned int type_to_n_sides_map[INVALID_ELEM]
This array maps the integer representation of the ElemType enum to the number of sides on the element...
Definition: elem.h:663
void find_interior_neighbors(T this_elem, std::set< T > &neighbor_set)
const Elem * interior_parent() const
Definition: elem.C:1057
const Elem * topological_neighbor(const unsigned int i, const MeshBase &mesh, const PointLocatorBase &point_locator, const PeriodicBoundaries *pb) const
Definition: elem.C:1184
virtual bool is_face(const unsigned int i) const =0
bool is_semilocal(const processor_id_type my_pid) const
Definition: elem.C:726
void total_family_tree_by_neighbor(T elem, std::vector< T > &family, T neighbor_in, bool reset=true)
This class implements nodal quadrature rules for various element types.
IntRange< unsigned short > side_index_range() const
Definition: elem.h:2623
void libmesh_assert_valid_node_pointers() const
Checks for a valid id and pointers to nodes with valid ids on this element.
Definition: elem.C:1242
void active_family_tree_by_neighbor(T elem, std::vector< T > &family, T neighbor_in, bool reset=true)
virtual dof_id_type key() const
Definition: elem.C:624
static constexpr Real TOLERANCE
static Point inverse_map(const unsigned int dim, const Elem *elem, const Point &p, const Real tolerance=TOLERANCE, const bool secure=true, const bool extra_checks=true)
Definition: fe_map.C:1628
void active_family_tree(T elem, std::vector< T > &active_family, bool reset=true)
Definition: elem_internal.h:90
We&#39;re using a class instead of a typedef to allow forward declarations and future flexibility...
virtual unsigned int embedding_matrix_version() const
Definition: elem.h:2000
unsigned int which_side_am_i(const Elem *e) const
This function tells you which side the boundary element e is.
Definition: elem.C:741
T cross_norm(const TypeVector< T > &b, const TypeVector< T > &c)
Calls cross_norm_sq() and takes the square root of the result.
Definition: type_vector.h:1073
RefinementState p_refinement_flag() const
Definition: elem.h:3176
IOPackage
libMesh interfaces with several different software packages for the purposes of creating, reading, and writing mesh files.
void find_interior_neighbors(std::set< const Elem *> &neighbor_set) const
This function finds all active elements (not including this one) in the parent manifold of this eleme...
Definition: elem.C:1043
void family_tree_by_subneighbor(std::vector< const Elem *> &family, const Elem *neighbor, const Elem *subneighbor, bool reset=true) const
Same as the family_tree() member, but only adds elements which are next to subneighbor.
Definition: elem.C:2092
Threads::spin_mutex parent_indices_mutex
Definition: elem.C:97
void active_family_tree_by_side(T elem, std::vector< T > &family, unsigned int side, bool reset=true)
void family_tree(std::vector< const Elem *> &family, bool reset=true) const
Fills the vector family with the children of this element, recursively.
Definition: elem.C:1972
This is the base class from which all geometric element types are derived.
Definition: elem.h:94
MeshBase & mesh
PeriodicBoundaryBase * boundary(boundary_id_type id)
void add_child(Elem *elem)
Adds a child pointer to the array of children of this element.
Definition: elem.C:1915
virtual BoundingBox loose_bounding_box() const
Definition: elem.C:3336
virtual bool on_reference_element(const Point &p, const Real eps=TOLERANCE) const =0
unsigned int min_new_p_level_by_neighbor(const Elem *neighbor, unsigned int current_min) const
Definition: elem.C:2223
virtual bool is_node_on_side(const unsigned int n, const unsigned int s) const =0
void active_family_tree(std::vector< const Elem *> &active_family, bool reset=true) const
Same as the family_tree() member, but only adds the active children.
Definition: elem.C:2004
unique_id_type unique_id() const
Definition: dof_object.h:844
void swap2boundarysides(unsigned short s1, unsigned short s2, BoundaryInfo *boundary_info) const
Swaps two sides in boundary_info, if it is non-null.
Definition: elem.C:3405
Order default_quadrature_order() const
Definition: fe_type.h:371
virtual unsigned int n_children() const =0
unsigned int p_level() const
Definition: elem.h:3058
void find_edge_neighbors(const Point &p1, const Point &p2, std::set< const Elem *> &neighbor_set) const
This function finds all active elements in the same manifold as this element which touch the current ...
Definition: elem.C:954
side_iterator boundary_sides_end()
Definition: elem.C:3291
void boundary_ids(const Node *node, std::vector< boundary_id_type > &vec_to_fill) const
Fills a user-provided std::vector with the boundary ids associated with Node node.
void make_links_to_me_remote()
Resets this element&#39;s neighbors&#39; appropriate neighbor pointers and its parent&#39;s and children&#39;s approp...
Definition: elem.C:1404
The libMesh namespace provides an interface to certain functionality in the library.
virtual Real hmax() const
Definition: elem.C:593
unsigned int min_p_level_by_neighbor(const Elem *neighbor, unsigned int current_min) const
Definition: elem.C:2194
void set_interior_parent(Elem *p)
Sets the pointer to the element&#39;s interior_parent.
Definition: elem.C:1119
static const unsigned int type_to_n_nodes_map[INVALID_ELEM]
This array maps the integer representation of the ElemType enum to the number of nodes in the element...
Definition: elem.h:628
bool contains_vertex_of(const Elem *e, bool mesh_connection=false) const
Definition: elem.C:805
uint8_t processor_id_type
Definition: id_types.h:104
This is the MeshBase class.
Definition: mesh_base.h:75
SimpleRange< ChildRefIter > child_ref_range()
Returns a range with all children of a parent element, usable in range-based for loops.
Definition: elem.h:2296
void add(const TypeVector< T2 > &)
Add to this vector without creating a temporary.
Definition: type_vector.h:605
bool ancestor() const
Definition: elem.C:1881
bool has_topological_neighbor(const Elem *elem, const MeshBase &mesh, const PointLocatorBase &point_locator, const PeriodicBoundaries *pb) const
Definition: elem.C:1221
IntRange< unsigned short > edge_index_range() const
Definition: elem.h:2614
side_iterator boundary_sides_begin()
Iterator accessor functions.
Definition: elem.C:3282
virtual Real embedding_matrix(const unsigned int child_num, const unsigned int child_node_num, const unsigned int parent_node_num) const =0
uint32_t hashword(const uint32_t *k, size_t length, uint32_t initval=0)
The hashword function takes an array of uint32_t&#39;s of length &#39;length&#39; and computes a single key from ...
Definition: hashword.h:158
T triple_product(const TypeVector< T > &a, const TypeVector< T > &b, const TypeVector< T > &c)
Definition: type_vector.h:1029
void family_tree_by_side(std::vector< const Elem *> &family, unsigned int side, bool reset=true) const
Same as the family_tree() member, but only adds elements which are next to side.
Definition: elem.C:2020
void replace_child(Elem *elem, unsigned int c)
Replaces the child pointer at the specified index in the child array.
Definition: elem.C:1961
void total_family_tree_by_subneighbor(std::vector< const Elem *> &family, const Elem *neighbor, const Elem *subneighbor, bool reset=true) const
Same as the family_tree_by_subneighbor() member, but also adds any subactive descendants.
Definition: elem.C:2112
TypeVector< T > unit() const
Definition: type_vector.h:1081
void libmesh_ignore(const Args &...)
static const subdomain_id_type invalid_subdomain_id
A static integral constant representing an invalid subdomain id.
Definition: elem.h:238
void remove_links_to_me()
Resets this element&#39;s neighbors&#39; appropriate neighbor pointers and its parent&#39;s and children&#39;s approp...
Definition: elem.C:1510
virtual std::vector< std::vector< std::vector< signed char > > > & _get_parent_indices_cache() const
Elem subclasses which don&#39;t do their own child-to-parent node calculations will need to supply a stat...
Definition: elem.h:2173
virtual bool contains_point(const Point &p, Real tol=TOLERANCE) const
Definition: elem.C:2622
Real length(const unsigned int n1, const unsigned int n2) const
Definition: elem.C:613
ElemMappingType mapping_type() const
Definition: elem.h:3070
void make_links_to_me_local(unsigned int n, unsigned int neighbor_side)
Resets the neighbor_side pointers of our nth neighbor (and its descendants, if appropriate) to point ...
Definition: elem.C:1326
const Node & node_ref(const unsigned int i) const
Definition: elem.h:2466
void family_tree_by_neighbor(T elem, std::vector< T > &family, T neighbor_in, bool reset=true)
dof_id_type id() const
Definition: dof_object.h:828
virtual Real hmin() const
Definition: elem.C:573
virtual unsigned int n_nodes() const =0
virtual unsigned int local_side_node(unsigned int side, unsigned int side_node) const =0
unsigned int which_node_am_i(unsigned int side, unsigned int side_node) const
This function is deprecated, call local_side_node(side, side_node) instead.
Definition: elem.C:795
static const unsigned int type_to_n_edges_map[INVALID_ELEM]
This array maps the integer representation of the ElemType enum to the number of edges on the element...
Definition: elem.h:721
unsigned int n_vars(const unsigned int s, const unsigned int vg) const
Definition: dof_object.h:967
bool contains_edge_of(const Elem *e) const
Definition: elem.C:843
unsigned int which_neighbor_am_i(const Elem *e) const
This function tells you which neighbor e is.
Definition: elem.h:2869
virtual unsigned int as_parent_node(unsigned int c, unsigned int n) const
Definition: elem.C:2257
virtual std::vector< unsigned int > edges_adjacent_to_node(const unsigned int) const =0
static std::unique_ptr< Elem > build(const ElemType type, Elem *p=nullptr)
Definition: elem.C:321
unsigned int n_systems() const
Definition: dof_object.h:937
virtual unsigned int opposite_node(const unsigned int n, const unsigned int s) const
Definition: elem.C:3390
virtual std::pair< unsigned short int, unsigned short int > second_order_child_vertex(const unsigned int n) const
Definition: elem.C:2929
Elem ** _elemlinks
Pointers to this element&#39;s parent and neighbors, and for lower-dimensional elements&#39; interior_parent...
Definition: elem.h:2201
void find_point_neighbors(const Point &p, std::set< const Elem *> &neighbor_set) const
This function finds all active elements (including this one) which are in the same manifold as this e...
Definition: elem.C:864
virtual unsigned int local_edge_node(unsigned int edge, unsigned int edge_node) const =0
Similar to Elem::local_side_node(), but instead of a side id, takes an edge id and a node id on that ...
The definition of the struct used for iterating over sides.
Definition: elem.h:3425
bool point_test(const Point &p, Real box_tol, Real map_tol) const
Shared private implementation used by the contains_point() and close_to_point() routines.
Definition: elem.C:2659
static std::unique_ptr< FEGenericBase > build(const unsigned int dim, const FEType &type)
Builds a specific finite element type.
The BoundaryInfo class contains information relevant to boundary conditions including storing faces...
Definition: boundary_info.h:57
void family_tree(T elem, std::vector< T > &family, bool reset=true)
Definition: elem_internal.h:41
libmesh_assert(ctx)
static const dof_id_type invalid_id
An invalid id to distinguish an uninitialized DofObject.
Definition: dof_object.h:482
Threads::spin_mutex parent_bracketing_nodes_mutex
Definition: elem.C:98
const Elem * reference_elem() const
Definition: elem.C:441
void libmesh_assert_valid_neighbors() const
Checks for consistent neighbor links on this element.
Definition: elem.C:1254
virtual bool is_remote() const
Definition: elem.h:590
const std::vector< Real > & get_jacobian() const
Definition: fe_map.h:223
bool valid_unique_id() const
Definition: dof_object.h:893
This is the base class for point locators.
virtual unsigned int n_edges() const =0
ElemQuality
Defines an enum for element quality metrics.
virtual std::unique_ptr< Elem > disconnected_clone() const
Definition: elem.C:287
virtual unsigned int n_second_order_adjacent_vertices(const unsigned int n) const
Definition: elem.C:2911
SideIter _last_side()
Definition: elem.h:3414
auto norm(const T &a) -> decltype(std::abs(a))
Definition: tensor_tools.h:74
bool absolute_fuzzy_equals(const TypeVector< T > &rhs, Real tol=TOLERANCE) const
Definition: type_vector.h:972
bool positive_edge_orientation(const unsigned int i) const
Definition: elem.C:3460
void set_neighbor(const unsigned int i, Elem *n)
Assigns n as the neighbor.
Definition: elem.h:2540
static ElemType second_order_equivalent_type(const ElemType et, const bool full_ordered=true)
Definition: elem.C:3006
RealTensorValue rotate(MeshBase &mesh, const Real phi, const Real theta=0., const Real psi=0.)
Rotates the mesh in the xy plane.
unsigned int which_child_am_i(const Elem *e) const
Definition: elem.h:3142
std::string enum_to_string(const T e)
void init_reference_to_physical_map(const std::vector< Point > &qp, const Elem *elem)
Definition: fe_map.C:109
void active_family_tree_by_neighbor(std::vector< const Elem *> &family, const Elem *neighbor, bool reset=true) const
Same as the active_family_tree() member, but only adds elements which are next to neighbor...
Definition: elem.C:2132
void total_family_tree_by_neighbor(std::vector< const Elem *> &family, const Elem *neighbor, bool reset=true) const
Same as the family_tree_by_neighbor() member, but also adds any subactive descendants.
Definition: elem.C:2074
SimpleRange< NodeRefIter > node_ref_range()
Returns a range with all nodes of an element, usable in range-based for loops.
Definition: elem.h:2587
Defines a Cartesian bounding box by the two corner extremum.
Definition: bounding_box.h:40
virtual unsigned int n_sides() const =0
bool topologically_equal(const Elem &rhs) const
Definition: elem.C:674
const Elem * neighbor_ptr(unsigned int i) const
Definition: elem.h:2520
void remove_side(const Elem *elem, const unsigned short int side)
Removes all boundary conditions associated with side side of element elem, if any exist...
void family_tree_by_subneighbor(T elem, std::vector< T > &family, T neighbor_in, T subneighbor, bool reset=true)
virtual bool close_to_point(const Point &p, Real tol) const
Definition: elem.C:2647
unsigned int level() const
Definition: elem.h:3024
virtual unsigned int n_vertices() const =0
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
virtual std::unique_ptr< Elem > side_ptr(unsigned int i)=0
subdomain_id_type subdomain_id() const
Definition: elem.h:2504
bool valid_id() const
Definition: dof_object.h:885
virtual bool is_singular_node(unsigned int) const
Definition: elem.h:1787
virtual unsigned short dim() const =0
const Node * node_ptr(const unsigned int i) const
Definition: elem.h:2444
virtual bool is_vertex(const unsigned int i) const =0
static Point map(const unsigned int dim, const Elem *elem, const Point &reference_point)
Definition: fe_map.C:2069
virtual Point master_point(const unsigned int i) const =0
static std::unique_ptr< Elem > build_with_id(const ElemType type, dof_id_type id)
Calls the build() method above with a nullptr parent, and additionally sets the newly-created Elem&#39;s ...
Definition: elem.C:429
unsigned int n_neighbors() const
Definition: elem.h:692
virtual Real quality(const ElemQuality q) const
Definition: elem.C:1645
void add_side(const dof_id_type elem, const unsigned short int side, const boundary_id_type id)
Add side side of element number elem with boundary id id to the boundary information data structure...
virtual unsigned short int second_order_adjacent_vertex(const unsigned int n, const unsigned int v) const
Definition: elem.C:2919
bool subactive() const
Definition: elem.h:2909
virtual Real volume() const
Definition: elem.C:3300
IntRange< T > make_range(T beg, T end)
The 2-parameter make_range() helper function returns an IntRange<T> when both input parameters are of...
Definition: int_range.h:140
const Elem * neighbor(boundary_id_type boundary_id, const PointLocatorBase &point_locator, const Elem *e, unsigned int side, unsigned int *neigh_side=nullptr) const
This class implements specific orders of Gauss quadrature.
void set_child(unsigned int c, Elem *elem)
Sets the pointer to the child for this element.
Definition: elem.h:3132
virtual void connectivity(const unsigned int sc, const IOPackage iop, std::vector< dof_id_type > &conn) const =0
unsigned int size() const
Alias for n_points() to enable use in index_range.
Definition: quadrature.h:142
virtual bool has_invertible_map(Real tol=TOLERANCE *TOLERANCE) const
Definition: elem.C:2752
IntRange< unsigned short > node_index_range() const
Definition: elem.h:2605
bool positive_face_orientation(const unsigned int i) const
Definition: elem.C:3469
unsigned int n_extra_integers() const
Returns how many extra integers are associated to the DofObject.
Definition: dof_object.h:1170
virtual bool is_vertex_on_child(unsigned int, unsigned int n) const
Definition: elem.h:746
void edge_boundary_ids(const Elem *const elem, const unsigned short int edge, std::vector< boundary_id_type > &vec_to_fill) const
void find_point_neighbors(T this_elem, std::set< T > &neighbor_set, T start_elem)
void nullify_neighbors()
Replaces this element with nullptr for all of its neighbors.
Definition: elem.C:2885
SimpleRange< NeighborPtrIter > neighbor_ptr_range()
Returns a range with all neighbors of an element, usable in range-based for loops.
Definition: elem.h:3439
virtual unsigned int n_faces() const =0
T get_extra_datum(const unsigned int index) const
Gets the value on this object of the extra datum associated with index, which should have been obtain...
Definition: dof_object.h:1146
virtual bool infinite() const =0
FEFamily
defines an enum for finite element families.
virtual unsigned int n_sub_elem() const =0
void total_family_tree(std::vector< const Elem *> &family, bool reset=true) const
Same as the family_tree() member, but also adds any subactive descendants.
Definition: elem.C:1988
void family_tree_by_neighbor(std::vector< const Elem *> &family, const Elem *neighbor, bool reset=true) const
Same as the family_tree() member, but only adds elements which are next to neighbor.
Definition: elem.C:2056
virtual std::unique_ptr< Elem > build_edge_ptr(const unsigned int i)=0
virtual Order default_order() const =0
virtual const std::vector< std::pair< unsigned char, unsigned char > > & parent_bracketing_nodes(unsigned int c, unsigned int n) const
Definition: elem.C:2325
virtual std::vector< std::vector< std::vector< std::vector< std::pair< unsigned char, unsigned char > > > > > & _get_bracketing_node_cache() const
Elem subclasses which don&#39;t do their own bracketing node calculations will need to supply a static ca...
Definition: elem.h:2159
virtual unsigned int opposite_side(const unsigned int s) const
Definition: elem.C:3382
bool active() const
Definition: elem.h:2891
void family_tree_by_side(T elem, std::vector< T > &family, unsigned int s, bool reset)
Class contained in FE that encapsulates mapping (i.e.
Definition: fe_map.h:47
static ElemType first_order_equivalent_type(const ElemType et)
Definition: elem.C:2937
processor_id_type processor_id() const
Definition: dof_object.h:905
virtual ElemType type() const =0
A Point defines a location in LIBMESH_DIM dimensional Real space.
Definition: point.h:39
dof_id_type node_id(const unsigned int i) const
Definition: elem.h:2412
const Point & point(const unsigned int i) const
Definition: elem.h:2390
virtual Point centroid() const
Calls Elem::vertex_average() for backwards compatibility.
Definition: elem.C:449
bool operator==(const Elem &rhs) const
Definition: elem.C:642
bool has_children() const
Definition: elem.h:2929
virtual unsigned int center_node_on_side(const unsigned short side) const
Definition: elem.C:3398
auto index_range(const T &sizable)
Helper function that returns an IntRange<std::size_t> representing all the indices of the passed-in v...
Definition: int_range.h:117
std::unique_ptr< Elem *[]> _children
unique_ptr to array of this element&#39;s children.
Definition: elem.h:2211
virtual bool is_child_on_edge(const unsigned int c, const unsigned int e) const
Definition: elem.C:2177
virtual bool is_edge(const unsigned int i) const =0
const Elem & get(const ElemType type_in)
void total_family_tree_by_subneighbor(T elem, std::vector< T > &family, T neighbor_in, T subneighbor, bool reset=true)
virtual std::vector< unsigned int > nodes_on_side(const unsigned int) const =0
virtual unsigned int n_nodes_in_child(unsigned int) const
Definition: elem.h:652
Point vertex_average() const
Definition: elem.C:559
static const unsigned int max_n_nodes
The maximum number of nodes any element can contain.
Definition: elem.h:639
const Elem * child_ptr(unsigned int i) const
Definition: elem.h:3113
void active_family_tree_by_topological_neighbor(T elem, std::vector< T > &family, T neighbor_in, const MeshBase &mesh, const PointLocatorBase &point_locator, const PeriodicBoundaries *pb, bool reset=true)
uint8_t dof_id_type
Definition: id_types.h:67
void add_edge(const dof_id_type elem, const unsigned short int edge, const boundary_id_type id)
Add edge edge of element number elem with boundary id id to the boundary information data structure...
const Real pi
.
Definition: libmesh.h:281
static FEFamily map_fe_type(const Elem &elem)
Definition: fe_map.C:46
virtual bool is_mid_infinite_edge_node(const unsigned int) const
Definition: elem.h:1854
Used to iterate over the sides of an element which are on the boundary of the Mesh.
bool is_internal(const unsigned int i) const
Definition: elem.C:3437
SideIter _first_side()
Side iterator helper functions.
Definition: elem.h:3406
const RemoteElem * remote_elem
Definition: remote_elem.C:57