libMesh
Public Member Functions | Protected Attributes | List of all members
ElemTest< elem_type > Class Template Reference
Inheritance diagram for ElemTest< elem_type >:
[legend]

Public Member Functions

void test_bounding_box ()
 
void test_quality ()
 
void test_maps ()
 
void test_static_data ()
 
void test_contains_point_node ()
 
void test_permute ()
 
void test_flip ()
 
void test_orient ()
 
void test_orient_elements ()
 
void test_center_node_on_side ()
 
void test_side_type ()
 
void test_elem_side_builder ()
 
void test_n_refinements (unsigned int n)
 
void test_refinement ()
 
void test_double_refinement ()
 
void setUp ()
 

Protected Attributes

std::unique_ptr< Mesh_mesh
 
std::string libmesh_suite_name
 

Detailed Description

template<ElemType elem_type>
class ElemTest< elem_type >

Definition at line 13 of file elem_test.C.

Member Function Documentation

◆ setUp()

template<ElemType elem_type>
void PerElemTest< elem_type >::setUp ( )
inlineinherited

Definition at line 22 of file elem_test.h.

References libMesh::Elem::build(), libMesh::MeshTools::Generation::build_cube(), dim, libMesh::INFHEX16, libMesh::INFHEX18, libMesh::INFHEX8, libMesh::INFPRISM12, libMesh::INFPRISM6, libMesh::INFQUAD4, libMesh::INFQUAD6, libMesh::Real, and libMesh::Elem::set_node().

23  {
24  const Real minpos = 1.5, maxpos = 5.5;
25  const unsigned int N = 2;
26 
27  _mesh = std::make_unique<Mesh>(*TestCommWorld);
28 
29  std::unique_ptr<Elem> test_elem = Elem::build(elem_type);
30 
31 #ifdef LIBMESH_ENABLE_INFINITE_ELEMENTS
32 #if LIBMESH_DIM > 1
33  if (test_elem->infinite())
34  {
35  Elem * elem = _mesh->add_elem(std::move(test_elem));
36 
37  const auto add_point =
38  [this, elem](const unsigned int i,
39  const Real x,
40  const Real y,
41  const Real
42 #if LIBMESH_DIM == 3
43  z
44 #endif
45  )
46  {
47 #if LIBMESH_DIM == 2
48  auto node = _mesh->add_point(Point(x, y), i);
49 #else
50  auto node = _mesh->add_point(Point(x, y, z), i);
51 #endif
52  elem->set_node(i) = node;
53  };
54 
55  const Real halfpos = (minpos + maxpos) / 2.;
56 
57  if (elem_type == INFQUAD4 || elem_type == INFQUAD6 ||
58  elem_type == INFHEX8 || elem_type == INFHEX16 || elem_type == INFHEX18)
59  {
60  const bool is_quad = (elem_type == INFQUAD4 || elem_type == INFQUAD6);
61 
62  add_point(0, minpos, minpos, minpos);
63  add_point(1, maxpos, minpos, minpos);
64  add_point(2+is_quad, maxpos, maxpos, minpos);
65  add_point(3-is_quad, minpos, maxpos, minpos);
66 
67  if (elem_type == INFQUAD6)
68  {
69  add_point(4, halfpos, minpos, minpos);
70  add_point(5, halfpos, maxpos, minpos);
71  }
72  }
73  if (elem_type == INFHEX8 || elem_type == INFHEX16 || elem_type == INFHEX18)
74  {
75  add_point(4, minpos, minpos, maxpos);
76  add_point(5, maxpos, minpos, maxpos);
77  add_point(6, maxpos, maxpos, maxpos);
78  add_point(7, minpos, maxpos, maxpos);
79 
80  if (elem_type == INFHEX16 || elem_type == INFHEX18)
81  {
82  add_point(8, halfpos, minpos, minpos);
83  add_point(9, maxpos, halfpos, minpos);
84  add_point(10, halfpos, maxpos, minpos);
85  add_point(11, minpos, halfpos, minpos);
86  add_point(12, halfpos, minpos, maxpos);
87  add_point(13, maxpos, halfpos, maxpos);
88  add_point(14, halfpos, maxpos, maxpos);
89  add_point(15, minpos, halfpos, maxpos);
90  }
91  if (elem_type == INFHEX18)
92  {
93  add_point(16, halfpos, halfpos, minpos);
94  add_point(17, halfpos, halfpos, maxpos);
95  }
96  }
97  if (elem_type == INFPRISM6 || elem_type == INFPRISM12)
98  {
99  add_point(0, minpos, minpos, minpos);
100  add_point(1, maxpos, minpos, minpos);
101  add_point(2, halfpos, maxpos, minpos);
102  add_point(3, minpos, minpos, maxpos);
103  add_point(4, maxpos, minpos, maxpos);
104  add_point(5, halfpos, maxpos, maxpos);
105 
106  if (elem_type == INFPRISM12)
107  {
108  add_point(6, halfpos, minpos, minpos);
109  add_point(7, (halfpos + maxpos) / 2., halfpos, minpos);
110  add_point(8, (halfpos + minpos) / 2., halfpos, minpos);
111  add_point(9, halfpos, minpos, maxpos);
112  add_point(10, (halfpos + maxpos) / 2., halfpos, maxpos);
113  add_point(11, (halfpos + minpos) / 2., halfpos, maxpos);
114  }
115  }
116 
117  _mesh->prepare_for_use();
118  }
119  else
120 #endif
121 #endif
122  {
123  const unsigned int dim = test_elem->dim();
124  const unsigned int use_y = dim > 1;
125  const unsigned int use_z = dim > 2;
126 
128  N, N*use_y, N*use_z,
129  minpos, maxpos,
130  minpos, use_y*maxpos,
131  minpos, use_z*maxpos,
132  elem_type);
133  }
134  }
virtual Node *& set_node(const unsigned int i)
Definition: elem.h:2381
std::unique_ptr< Mesh > _mesh
Definition: elem_test.h:18
unsigned int dim
This is the base class from which all geometric element types are derived.
Definition: elem.h:94
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
A Point defines a location in LIBMESH_DIM dimensional Real space.
Definition: point.h:39
void build_cube(UnstructuredMesh &mesh, const unsigned int nx=0, const unsigned int ny=0, const unsigned int nz=0, const Real xmin=0., const Real xmax=1., const Real ymin=0., const Real ymax=1., const Real zmin=0., const Real zmax=1., const ElemType type=INVALID_ELEM, const bool gauss_lobatto_grid=false)
Builds a (elements) cube.

◆ test_bounding_box()

template<ElemType elem_type>
void ElemTest< elem_type >::test_bounding_box ( )
inline

Definition at line 15 of file elem_test.C.

References libMesh::BoundingBox::contains_point().

16  {
17  LOG_UNIT_TEST;
18 
19  for (const auto & elem :
20  this->_mesh->active_local_element_ptr_range())
21  {
22  const BoundingBox bbox = elem->loose_bounding_box();
23 
24  // The "loose" bounding box should actually be pretty tight
25  // in most of these cases, but for weirdly aligned triangles
26  // (such as occur in pyramid elements) it won't be, so we'll
27  // just test against a widened bounding box.
28  BoundingBox wide_bbox(elem->point(0), elem->point(0));
29 
30  for (unsigned int n = 0; n != elem->n_nodes(); ++n)
31  {
32  const Point & p = elem->point(n);
33 
34  if (!elem->infinite())
35  CPPUNIT_ASSERT(bbox.contains_point(p));
36 
37  wide_bbox.union_with
38  (BoundingBox(elem->point(n), elem->point(n)));
39  }
40 
41  wide_bbox.scale(1. / 3.);
42 
43  if (!elem->infinite())
44  {
45  CPPUNIT_ASSERT(!bbox.contains_point(wide_bbox.min()));
46  CPPUNIT_ASSERT(!bbox.contains_point(wide_bbox.max()));
47  }
48  }
49  }
bool contains_point(const Point &) const
Definition: bounding_box.C:35
std::unique_ptr< Mesh > _mesh
Definition: elem_test.h:18
Defines a Cartesian bounding box by the two corner extremum.
Definition: bounding_box.h:40
A Point defines a location in LIBMESH_DIM dimensional Real space.
Definition: point.h:39

◆ test_center_node_on_side()

template<ElemType elem_type>
void ElemTest< elem_type >::test_center_node_on_side ( )
inline

Definition at line 373 of file elem_test.C.

References libMesh::EDGE2, libMesh::EDGE3, libMesh::EDGE4, libMesh::HEX27, libMesh::invalid_uint, libMesh::PRISM18, libMesh::PRISM20, libMesh::PRISM21, libMesh::PYRAMID14, libMesh::PYRAMID18, libMesh::QUAD8, libMesh::QUAD9, libMesh::QUADSHELL8, libMesh::TRI6, and libMesh::TRI7.

374  {
375  LOG_UNIT_TEST;
376 
377  for (const auto & elem :
378  this->_mesh->active_local_element_ptr_range())
379  for (const auto s : elem->side_index_range())
380  {
381  if (elem->type() == EDGE2 || elem->type() == EDGE3 || elem->type() == EDGE4)
382  CPPUNIT_ASSERT_EQUAL(static_cast<unsigned int>(s), elem->center_node_on_side(s));
383  else if (elem->type() == TRI6 || elem->type() == TRI7)
384  CPPUNIT_ASSERT_EQUAL(static_cast<unsigned int>(s + 3), elem->center_node_on_side(s));
385  else if (elem->type() == QUAD8 || elem->type() == QUAD9 || elem->type() == QUADSHELL8)
386  CPPUNIT_ASSERT_EQUAL(static_cast<unsigned int>(s + 4), elem->center_node_on_side(s));
387  else if (elem->type() == HEX27)
388  CPPUNIT_ASSERT_EQUAL(static_cast<unsigned int>(s + 20), elem->center_node_on_side(s));
389  else if (elem->type() == PRISM18 && s >= 1 && s <= 3)
390  CPPUNIT_ASSERT_EQUAL(static_cast<unsigned int>(s + 14), elem->center_node_on_side(s));
391  else if ((elem->type() == PRISM20 ||
392  elem->type() == PRISM21) && s >= 1 && s <= 3)
393  CPPUNIT_ASSERT_EQUAL(static_cast<unsigned int>(s + 14), elem->center_node_on_side(s));
394  else if (elem->type() == PRISM20 ||
395  elem->type() == PRISM21)
396  CPPUNIT_ASSERT_EQUAL(static_cast<unsigned int>(18 + (s == 4)), elem->center_node_on_side(s));
397  else if (elem->type() == PYRAMID14 && s == 4)
398  CPPUNIT_ASSERT_EQUAL(static_cast<unsigned int>(13), elem->center_node_on_side(s));
399  else if (elem->type() == PYRAMID18)
400  {
401  if (s < 4)
402  CPPUNIT_ASSERT_EQUAL(static_cast<unsigned int>(s + 14), elem->center_node_on_side(s));
403  else
404  CPPUNIT_ASSERT_EQUAL(static_cast<unsigned int>(13), elem->center_node_on_side(s));
405  }
406  else
407  CPPUNIT_ASSERT_EQUAL(invalid_uint, elem->center_node_on_side(s));
408  }
409  }
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:286
std::unique_ptr< Mesh > _mesh
Definition: elem_test.h:18

◆ test_contains_point_node()

template<ElemType elem_type>
void ElemTest< elem_type >::test_contains_point_node ( )
inline

Definition at line 113 of file elem_test.C.

References libMesh::invalid_uint, and libMesh::TOLERANCE.

114  {
115  LOG_UNIT_TEST;
116 
117  for (const auto & elem :
118  this->_mesh->active_local_element_ptr_range())
119  {
120  if (elem->infinite())
121  continue;
122 
123  for (const auto n : elem->node_index_range())
124 #ifndef LIBMESH_ENABLE_EXCEPTIONS
125  // If this node has a singular Jacobian, we need exceptions in order
126  // to catch the failed inverse_map solve and return the singular
127  // master point. Therefore, if we don't have exceptions and we're
128  // at a singular node, we can't test this. As of the writing of
129  // this comment, this issue exists for only Pyramid elements at
130  // the apex.
131  if (elem->local_singular_node(elem->point(n), TOLERANCE*TOLERANCE) == invalid_uint)
132 #endif
133  CPPUNIT_ASSERT(elem->contains_point(elem->point(n)));
134  }
135  }
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:286
static constexpr Real TOLERANCE
std::unique_ptr< Mesh > _mesh
Definition: elem_test.h:18

◆ test_double_refinement()

template<ElemType elem_type>
void ElemTest< elem_type >::test_double_refinement ( )
inline

Definition at line 631 of file elem_test.C.

632  {
633  LOG_UNIT_TEST;
634 
636  }
void test_n_refinements(unsigned int n)
Definition: elem_test.C:443

◆ test_elem_side_builder()

template<ElemType elem_type>
void ElemTest< elem_type >::test_elem_side_builder ( )
inline

Definition at line 421 of file elem_test.C.

422  {
423  LOG_UNIT_TEST;
424 
425  ElemSideBuilder cache;
426  for (auto & elem : this->_mesh->active_local_element_ptr_range())
427  for (const auto s : elem->side_index_range())
428  {
429  const auto side = elem->build_side_ptr(s);
430 
431  auto & cached_side = cache(*elem, s);
432  CPPUNIT_ASSERT_EQUAL(side->type(), cached_side.type());
433  for (const auto n : side->node_index_range())
434  CPPUNIT_ASSERT_EQUAL(side->node_ref(n), cached_side.node_ref(n));
435 
436  const auto & const_cached_side = cache(const_cast<const Elem &>(*elem), s);
437  CPPUNIT_ASSERT_EQUAL(side->type(), const_cached_side.type());
438  for (const auto n : side->node_index_range())
439  CPPUNIT_ASSERT_EQUAL(side->node_ref(n), const_cached_side.node_ref(n));
440  }
441  }
std::unique_ptr< Mesh > _mesh
Definition: elem_test.h:18
Helper for building element sides that minimizes the construction of new elements.

◆ test_flip()

template<ElemType elem_type>
void ElemTest< elem_type >::test_flip ( )
inline

Definition at line 176 of file elem_test.C.

References libMesh::BoundaryInfo::boundary_ids(), libMesh::invalid_uint, libMesh::make_range(), and libMesh::TOLERANCE.

177  {
178  LOG_UNIT_TEST;
179 
180  BoundaryInfo & boundary_info = this->_mesh->get_boundary_info();
181 
182  for (const auto & elem :
183  this->_mesh->active_local_element_ptr_range())
184  {
185  if (elem->infinite())
186  continue;
187 
188  const Point vertex_avg = elem->vertex_average();
189 
190  const unsigned int n_sides = elem->n_sides();
191  std::vector<std::set<Point*>> side_nodes(n_sides);
192  std::vector<Elem*> neighbors(n_sides);
193  std::vector<std::vector<boundary_id_type>> bcids(n_sides);
194  for (auto s : make_range(n_sides))
195  {
196  for (auto n : elem->nodes_on_side(s))
197  side_nodes[s].insert(elem->node_ptr(n));
198  neighbors[s] = elem->neighbor_ptr(s);
199  boundary_info.boundary_ids(elem, s, bcids[s]);
200  }
201 
202  elem->flip(&boundary_info);
203 
204  // We should just be flipped, not twisted, so our map should
205  // still be affine.
206  // ... except for stupid singular pyramid maps
207  if (elem->dim() < 3 ||
208  elem->n_vertices() != 5)
209  CPPUNIT_ASSERT(elem->has_affine_map());
210 
211  // The neighbors and bcids should have flipped in a way
212  // consistently with the nodes.
213  bool something_changed = false;
214  for (auto s : make_range(n_sides))
215  {
216  std::set<Point*> new_side_nodes;
217  for (auto n : elem->nodes_on_side(s))
218  new_side_nodes.insert(elem->node_ptr(n));
219 
220  std::vector<boundary_id_type> new_bcids;
221  boundary_info.boundary_ids(elem, s, new_bcids);
222 
223  unsigned int old_side = libMesh::invalid_uint;
224  for (auto os : make_range(n_sides))
225  if (new_side_nodes == side_nodes[os])
226  old_side = os;
227 
228  if (old_side != s)
229  something_changed = true;
230 
231  CPPUNIT_ASSERT(old_side != libMesh::invalid_uint);
232 
233  CPPUNIT_ASSERT(neighbors[old_side] ==
234  elem->neighbor_ptr(s));
235 
236  CPPUNIT_ASSERT(bcids[old_side] == new_bcids);
237  }
238  CPPUNIT_ASSERT(something_changed);
239 
240  const Point new_vertex_avg = elem->vertex_average();
241  for (const auto d : make_range(LIBMESH_DIM))
242  LIBMESH_ASSERT_FP_EQUAL(vertex_avg(d), new_vertex_avg(d),
244  }
245  }
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:286
static constexpr Real TOLERANCE
std::unique_ptr< Mesh > _mesh
Definition: elem_test.h:18
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.
The BoundaryInfo class contains information relevant to boundary conditions including storing faces...
Definition: boundary_info.h:57
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:134
A Point defines a location in LIBMESH_DIM dimensional Real space.
Definition: point.h:39

◆ test_maps()

template<ElemType elem_type>
void ElemTest< elem_type >::test_maps ( )
inline

Definition at line 73 of file elem_test.C.

74  {
75  LOG_UNIT_TEST;
76 
77  for (const auto & elem :
78  this->_mesh->active_local_element_ptr_range())
79  {
80  for (const auto edge : elem->edge_index_range())
81  for (const auto side_on_edge : elem->sides_on_edge(edge))
82  for (const auto node_on_edge : elem->nodes_on_edge(edge))
83  CPPUNIT_ASSERT(elem->is_node_on_side(node_on_edge, side_on_edge));
84 
85  for (const auto side : elem->side_index_range())
86  for (const auto node_on_side : elem->nodes_on_side(side))
87  CPPUNIT_ASSERT(elem->is_node_on_side(node_on_side, side));
88 
89  for (const auto edge : elem->edge_index_range())
90  for (const auto node_on_edge : elem->nodes_on_edge(edge))
91  CPPUNIT_ASSERT(elem->is_node_on_edge(node_on_edge, edge));
92 
93  for (const auto edge : elem->edge_index_range())
94  for (const auto side_on_edge : elem->sides_on_edge(edge))
95  CPPUNIT_ASSERT(elem->is_edge_on_side(edge, side_on_edge));
96  }
97  }
std::unique_ptr< Mesh > _mesh
Definition: elem_test.h:18

◆ test_n_refinements()

template<ElemType elem_type>
void ElemTest< elem_type >::test_n_refinements ( unsigned int  n)
inline

Definition at line 443 of file elem_test.C.

References libMesh::EDGE4, libMesh::invalid_uint, libMesh::make_range(), libMesh::Elem::parent(), libMesh::Utility::pow(), libMesh::PRISM20, libMesh::PYRAMID13, libMesh::PYRAMID14, libMesh::PYRAMID18, libMesh::PYRAMID5, TIMPI::Communicator::set_union(), TestCommWorld, and libMesh::MeshRefinement::uniformly_refine().

444  {
445 #ifdef LIBMESH_ENABLE_AMR
446  // We don't support refinement of all element types
447  if (elem_type == EDGE4 ||
448  elem_type == PRISM20 ||
449  elem_type == PYRAMID5 ||
450  elem_type == PYRAMID13 ||
451  elem_type == PYRAMID14 ||
452  elem_type == PYRAMID18)
453  return;
454 
455  auto refining_mesh = this->_mesh->clone();
456 
457  MeshRefinement mr(*refining_mesh);
458  mr.uniformly_refine(n);
459 
460  std::set<std::pair<dof_id_type, unsigned int>> parent_node_was_touched;
461  std::set<std::pair<dof_id_type, unsigned int>> parent_child_was_touched;
462 
463  for (const Elem * elem : refining_mesh->active_element_ptr_range())
464  {
465  CPPUNIT_ASSERT_EQUAL(elem->level(), n);
466  CPPUNIT_ASSERT(!elem->ancestor());
467  CPPUNIT_ASSERT(elem->active());
468  CPPUNIT_ASSERT(!elem->subactive());
469  CPPUNIT_ASSERT(!elem->has_children());
470  CPPUNIT_ASSERT(!elem->has_ancestor_children());
471  CPPUNIT_ASSERT(!elem->interior_parent());
472 
473  const Elem * parent = elem->parent();
474  CPPUNIT_ASSERT(parent);
475  CPPUNIT_ASSERT(parent->ancestor());
476  CPPUNIT_ASSERT(!parent->active());
477  CPPUNIT_ASSERT(!parent->subactive());
478  CPPUNIT_ASSERT(parent->has_children());
479  CPPUNIT_ASSERT(!parent->has_ancestor_children());
480  CPPUNIT_ASSERT(!parent->interior_parent());
481  if (n == 1)
482  {
483  CPPUNIT_ASSERT_EQUAL(parent, elem->top_parent());
484  CPPUNIT_ASSERT_EQUAL(parent, parent->top_parent());
485  }
486  else
487  {
488  CPPUNIT_ASSERT(parent != elem->top_parent());
489  CPPUNIT_ASSERT(parent != parent->top_parent());
490  CPPUNIT_ASSERT_EQUAL(elem->top_parent(), parent->top_parent());
491  }
492 
493  CPPUNIT_ASSERT(parent->is_ancestor_of(elem));
494  const unsigned int c = parent->which_child_am_i(elem);
495  CPPUNIT_ASSERT(c < parent->n_children());
496  CPPUNIT_ASSERT_EQUAL(elem, parent->child_ptr(c));
497  parent_child_was_touched.emplace(parent->id(), c);
498 
499  CPPUNIT_ASSERT_EQUAL(parent->n_nodes_in_child(c), elem->n_nodes());
500  for (auto n : make_range(elem->n_nodes()))
501  {
502  CPPUNIT_ASSERT_EQUAL(parent->is_vertex_on_child(c, n), elem->is_vertex(n));
503 
504  auto pn = parent->as_parent_node(c, n);
505  CPPUNIT_ASSERT_EQUAL(pn, parent->get_node_index(elem->node_ptr(n)));
506  if (pn == libMesh::invalid_uint)
507  continue;
508  CPPUNIT_ASSERT_EQUAL(parent->is_vertex_on_parent(c, n), parent->is_vertex(pn));
509  parent_node_was_touched.emplace(parent->id(), pn);
510  }
511 
512  for (auto s : make_range(parent->n_sides()))
513  {
514  if (parent->is_child_on_side(c,s))
515  {
516  auto parent_side = parent->build_side_ptr(s);
517 
518  // Implicitly assuming here that s is the child side
519  // too - we support that now and hopefully won't have
520  // to change it later
521  auto child_side = elem->build_side_ptr(s);
522 
523  // 2D Inf FE inverse_map not yet implemented?
524  if (!parent_side->infinite())
525  for (const Node & node : child_side->node_ref_range())
526  CPPUNIT_ASSERT(parent_side->contains_point(node));
527 
528  if (elem->neighbor_ptr(s) && !elem->neighbor_ptr(s)->is_remote())
529  CPPUNIT_ASSERT_EQUAL(parent->child_neighbor(elem->neighbor_ptr(s)), elem);
530  }
531  }
532 
533  for (auto e : make_range(parent->n_edges()))
534  {
535  if (parent->is_child_on_edge(c,e))
536  {
537  auto parent_edge = parent->build_edge_ptr(e);
538 
539  // Implicitly assuming here that e is the child edge
540  // too - we support that now and hopefully won't have
541  // to change it later
542  auto child_edge = elem->build_edge_ptr(e);
543 
544  // 1D Inf FE inverse_map not yet implemented?
545  if (!parent_edge->infinite())
546  for (const Node & node : child_edge->node_ref_range())
547  CPPUNIT_ASSERT(parent_edge->contains_point(node));
548  }
549  }
550 
551  if (parent->has_affine_map())
552  CPPUNIT_ASSERT(elem->has_affine_map());
553  }
554 
555  // It's possible for a parent element on a distributed mesh to not
556  // have all its children available on any one processor
557  TestCommWorld->set_union(parent_child_was_touched);
558  TestCommWorld->set_union(parent_node_was_touched);
559 
560  for (const Elem * elem : refining_mesh->local_element_ptr_range())
561  {
562  if (elem->active())
563  continue;
564 
565  // With only one layer of refinement the family tree methods
566  // should have the full number of elements, even if some are
567  // remote.
568  if (n == 1)
569  {
570  std::vector<const Elem *> family;
571  elem->family_tree(family);
572  CPPUNIT_ASSERT_EQUAL(family.size(),
573  std::size_t(elem->n_children() + 1));
574 
575  family.clear();
576  elem->total_family_tree(family);
577  CPPUNIT_ASSERT_EQUAL(family.size(),
578  std::size_t(elem->n_children() + 1));
579 
580  family.clear();
581  elem->active_family_tree(family);
582  CPPUNIT_ASSERT_EQUAL(family.size(),
583  std::size_t(elem->n_children()));
584 
585  for (auto s : make_range(elem->n_sides()))
586  {
587  family.clear();
588  elem->active_family_tree_by_side(family,s);
589  if (!elem->build_side_ptr(s)->infinite())
590  CPPUNIT_ASSERT_EQUAL(double(family.size()),
591  std::pow(2.0, int(elem->dim()-1)));
592  else
593  CPPUNIT_ASSERT_EQUAL(double(family.size()),
594  std::pow(2.0, int(elem->dim()-2)));
595  for (const Elem * child : family)
596  {
597  if (child->is_remote())
598  continue;
599 
600  unsigned int c = elem->which_child_am_i(child);
601  CPPUNIT_ASSERT(elem->is_child_on_side(c, s));
602  }
603  }
604  }
605 
606  if (elem->level() + 1 == n)
607  {
608  for (auto c : make_range(elem->n_children()))
609  {
610  auto it = parent_child_was_touched.find(std::make_pair(elem->id(), c));
611  CPPUNIT_ASSERT(it != parent_child_was_touched.end());
612  }
613 
614  for (auto n : make_range(elem->n_nodes()))
615  {
616  auto it = parent_node_was_touched.find(std::make_pair(elem->id(), n));
617  CPPUNIT_ASSERT(it != parent_node_was_touched.end());
618  }
619  }
620  }
621 #endif
622  }
const Elem * parent() const
Definition: elem.h:2867
A Node is like a Point, but with more information.
Definition: node.h:52
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:286
libMesh::Parallel::Communicator * TestCommWorld
Definition: driver.C:159
std::unique_ptr< Mesh > _mesh
Definition: elem_test.h:18
This is the base class from which all geometric element types are derived.
Definition: elem.h:94
T pow(const T &x)
Definition: utility.h:328
Implements (adaptive) mesh refinement algorithms for a MeshBase.
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:134
void set_union(T &data, const unsigned int root_id) const

◆ test_orient()

template<ElemType elem_type>
void ElemTest< elem_type >::test_orient ( )
inline

Definition at line 247 of file elem_test.C.

References libMesh::BoundaryInfo::boundary_ids(), libMesh::make_range(), and libMesh::TOLERANCE.

248  {
249  LOG_UNIT_TEST;
250 
251  BoundaryInfo & boundary_info = this->_mesh->get_boundary_info();
252 
253  for (const auto & elem :
254  this->_mesh->active_local_element_ptr_range())
255  {
256  if (elem->infinite())
257  continue;
258 
259  const Point vertex_avg = elem->vertex_average();
260 
261  const unsigned int n_sides = elem->n_sides();
262  std::vector<std::set<Point*>> side_nodes(n_sides);
263  std::vector<Elem*> neighbors(n_sides);
264  std::vector<std::vector<boundary_id_type>> bcids(n_sides);
265  for (auto s : make_range(n_sides))
266  {
267  for (auto n : elem->nodes_on_side(s))
268  side_nodes[s].insert(elem->node_ptr(n));
269  neighbors[s] = elem->neighbor_ptr(s);
270  boundary_info.boundary_ids(elem, s, bcids[s]);
271  }
272 
273  CPPUNIT_ASSERT(!elem->is_flipped());
274 
275  if (elem->id()%2)
276  {
277  elem->flip(&boundary_info);
278  CPPUNIT_ASSERT(elem->is_flipped());
279  }
280 
281  elem->orient(&boundary_info);
282  CPPUNIT_ASSERT(!elem->is_flipped());
283 
284  // Our map should still be affine.
285  // ... except for stupid singular pyramid maps
286  if (elem->dim() < 3 ||
287  elem->n_vertices() != 5)
288  CPPUNIT_ASSERT(elem->has_affine_map());
289 
290  // The neighbors and bcids should have flipped back to where
291  // they were.
292  for (auto s : make_range(n_sides))
293  {
294  std::set<Point*> new_side_nodes;
295  for (auto n : elem->nodes_on_side(s))
296  new_side_nodes.insert(elem->node_ptr(n));
297 
298  std::vector<boundary_id_type> new_bcids;
299  boundary_info.boundary_ids(elem, s, new_bcids);
300 
301  CPPUNIT_ASSERT(side_nodes[s] ==
302  new_side_nodes);
303 
304  CPPUNIT_ASSERT(neighbors[s] ==
305  elem->neighbor_ptr(s));
306 
307  CPPUNIT_ASSERT(bcids[s] == new_bcids);
308  }
309 
310  const Point new_vertex_avg = elem->vertex_average();
311  for (const auto d : make_range(LIBMESH_DIM))
312  LIBMESH_ASSERT_FP_EQUAL(vertex_avg(d), new_vertex_avg(d),
314  }
315  }
static constexpr Real TOLERANCE
std::unique_ptr< Mesh > _mesh
Definition: elem_test.h:18
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.
The BoundaryInfo class contains information relevant to boundary conditions including storing faces...
Definition: boundary_info.h:57
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:134
A Point defines a location in LIBMESH_DIM dimensional Real space.
Definition: point.h:39

◆ test_orient_elements()

template<ElemType elem_type>
void ElemTest< elem_type >::test_orient_elements ( )
inline

Definition at line 317 of file elem_test.C.

References libMesh::BoundaryInfo::boundary_ids(), libMesh::DofObject::id(), libMesh::make_range(), libMesh::Elem::neighbor_ptr(), and libMesh::MeshTools::Modification::orient_elements().

318  {
319  LOG_UNIT_TEST;
320 
321  const Mesh old_mesh {*this->_mesh};
322 
323  BoundaryInfo & boundary_info = this->_mesh->get_boundary_info();
324  const BoundaryInfo & old_boundary_info = old_mesh.get_boundary_info();
325  CPPUNIT_ASSERT(&boundary_info != &old_boundary_info);
326 
327  for (const auto & elem :
328  this->_mesh->active_local_element_ptr_range())
329  {
330  if (elem->infinite())
331  continue;
332 
333  if (elem->id()%2)
334  {
335  elem->flip(&boundary_info);
336  CPPUNIT_ASSERT(elem->is_flipped());
337  }
338  }
339 
341 
342  // I should really create a MeshBase::operator==()...
343  for (const auto & elem :
344  this->_mesh->active_local_element_ptr_range())
345  {
346  const Elem & old_elem = old_mesh.elem_ref(elem->id());
347 
348  CPPUNIT_ASSERT(!elem->is_flipped());
349 
350  // Elem::operator==() uses node ids to compare
351  CPPUNIT_ASSERT(*elem == old_elem);
352 
353  const unsigned int n_sides = elem->n_sides();
354  for (auto s : make_range(n_sides))
355  {
356  std::vector<boundary_id_type> bcids, old_bcids;
357  boundary_info.boundary_ids(elem, s, bcids);
358  old_boundary_info.boundary_ids(&old_elem, s, old_bcids);
359  CPPUNIT_ASSERT(bcids == old_bcids);
360 
361  if (elem->neighbor_ptr(s))
362  {
363  CPPUNIT_ASSERT(old_elem.neighbor_ptr(s));
364  CPPUNIT_ASSERT_EQUAL(elem->neighbor_ptr(s)->id(),
365  old_elem.neighbor_ptr(s)->id());
366  }
367  else
368  CPPUNIT_ASSERT(!old_elem.neighbor_ptr(s));
369  }
370  }
371  }
std::unique_ptr< Mesh > _mesh
Definition: elem_test.h:18
This is the base class from which all geometric element types are derived.
Definition: elem.h:94
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.
dof_id_type id() const
Definition: dof_object.h:823
The BoundaryInfo class contains information relevant to boundary conditions including storing faces...
Definition: boundary_info.h:57
void orient_elements(MeshBase &mesh)
Redo the nodal ordering of each element as necessary to give the element Jacobian a positive orientat...
const Elem * neighbor_ptr(unsigned int i) const
Definition: elem.h:2407
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:134
The Mesh class is a thin wrapper, around the ReplicatedMesh class by default.
Definition: mesh.h:50

◆ test_permute()

template<ElemType elem_type>
void ElemTest< elem_type >::test_permute ( )
inline

Definition at line 137 of file elem_test.C.

References libMesh::make_range(), std::sqrt(), and libMesh::TOLERANCE.

138  {
139  LOG_UNIT_TEST;
140 
141  for (const auto & elem :
142  this->_mesh->active_local_element_ptr_range())
143  {
144  if (elem->infinite())
145  continue;
146 
147  const Point centroid = elem->true_centroid();
148  const Point vertex_avg = elem->vertex_average();
149  Point quasicc;
150  if (elem->dim() < 3)
151  quasicc = elem->quasicircumcenter();
152 
153  for (const auto p : IntRange<unsigned int>(0, elem->n_permutations()))
154  {
155  elem->permute(p);
156  CPPUNIT_ASSERT(elem->has_invertible_map());
157  const Point new_centroid = elem->true_centroid();
158  const Point new_vertex_avg = elem->vertex_average();
159  Point new_quasicc;
160  if (elem->dim() < 3)
161  new_quasicc = elem->quasicircumcenter();
162  for (const auto d : make_range(LIBMESH_DIM))
163  {
164  // Getting a little FP error from Pyramid18
165  LIBMESH_ASSERT_FP_EQUAL(centroid(d), new_centroid(d),
167  LIBMESH_ASSERT_FP_EQUAL(vertex_avg(d), new_vertex_avg(d),
169  LIBMESH_ASSERT_FP_EQUAL(quasicc(d), new_quasicc(d),
171  }
172  }
173  }
174  }
The IntRange templated class is intended to make it easy to loop over integers which are indices of a...
Definition: int_range.h:53
static constexpr Real TOLERANCE
std::unique_ptr< Mesh > _mesh
Definition: elem_test.h:18
ADRealEigenVector< T, D, asd > sqrt(const ADRealEigenVector< T, D, asd > &)
Definition: type_vector.h:53
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:134
A Point defines a location in LIBMESH_DIM dimensional Real space.
Definition: point.h:39

◆ test_quality()

template<ElemType elem_type>
void ElemTest< elem_type >::test_quality ( )
inline

Definition at line 51 of file elem_test.C.

References libMesh::ASPECT_RATIO, libMesh::Real, and libMesh::TOLERANCE.

52  {
53  LOG_UNIT_TEST;
54 
55  for (const auto & elem : this->_mesh->active_local_element_ptr_range())
56  {
57  // We only have one metric defined on all elements
58  const Real q = elem->quality(ASPECT_RATIO);
59 
60  // We use "0" to mean infinity rather than inf or NaN, and
61  // every quality other than that should be 1 or larger (worse)
62  CPPUNIT_ASSERT_LESSEQUAL(q, Real(1)); // 1 <= q
63 
64  // We're building isotropic meshes, where even elements
65  // dissected from cubes ought to have tolerable quality.
66  //
67  // Worst I see is 2 on tets, but let's add a little tolerance
68  // in case we decide to play with rotated meshes here later
69  CPPUNIT_ASSERT_LESSEQUAL(Real(2+TOLERANCE), q); // q <= 2
70  }
71  }
static constexpr Real TOLERANCE
std::unique_ptr< Mesh > _mesh
Definition: elem_test.h:18
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real

◆ test_refinement()

template<ElemType elem_type>
void ElemTest< elem_type >::test_refinement ( )
inline

Definition at line 624 of file elem_test.C.

625  {
626  LOG_UNIT_TEST;
627 
629  }
void test_n_refinements(unsigned int n)
Definition: elem_test.C:443

◆ test_side_type()

template<ElemType elem_type>
void ElemTest< elem_type >::test_side_type ( )
inline

Definition at line 411 of file elem_test.C.

412  {
413  LOG_UNIT_TEST;
414 
415  for (const auto & elem :
416  this->_mesh->active_local_element_ptr_range())
417  for (const auto s : elem->side_index_range())
418  CPPUNIT_ASSERT_EQUAL(elem->build_side_ptr(s)->type(), elem->side_type(s));
419  }
std::unique_ptr< Mesh > _mesh
Definition: elem_test.h:18

◆ test_static_data()

template<ElemType elem_type>
void ElemTest< elem_type >::test_static_data ( )
inline

Definition at line 99 of file elem_test.C.

References libMesh::Elem::max_n_nodes, libMesh::Elem::type_to_n_edges_map, libMesh::Elem::type_to_n_nodes_map, and libMesh::Elem::type_to_n_sides_map.

100  {
101  LOG_UNIT_TEST;
102 
103  for (const auto & elem :
104  this->_mesh->active_local_element_ptr_range())
105  {
106  CPPUNIT_ASSERT(elem->n_nodes() <= Elem::max_n_nodes);
107  CPPUNIT_ASSERT_EQUAL(elem->n_nodes(), Elem::type_to_n_nodes_map[elem->type()]);
108  CPPUNIT_ASSERT_EQUAL(elem->n_sides(), Elem::type_to_n_sides_map[elem->type()]);
109  CPPUNIT_ASSERT_EQUAL(elem->n_edges(), Elem::type_to_n_edges_map[elem->type()]);
110  }
111  }
std::unique_ptr< Mesh > _mesh
Definition: elem_test.h:18

Member Data Documentation

◆ _mesh

template<ElemType elem_type>
std::unique_ptr<Mesh> PerElemTest< elem_type >::_mesh
protectedinherited

Definition at line 18 of file elem_test.h.

◆ libmesh_suite_name

template<ElemType elem_type>
std::string PerElemTest< elem_type >::libmesh_suite_name
protectedinherited

Definition at line 19 of file elem_test.h.


The documentation for this class was generated from the following file: