libMesh
mesh_elem_test.h
Go to the documentation of this file.
1 #ifndef MESH_ELEM_TEST_H
2 #define MESH_ELEM_TEST_H
3 
4 #include "../geom/elem_test.h"
5 
6 #include "libmesh/mesh_serializer.h"
7 
8 using namespace libMesh;
9 
10 template <ElemType elem_type>
11 class MeshPerElemTest : public PerElemTest<elem_type>
12 {
13 protected:
14 
15  bool meshes_equal_enough(Mesh & other_mesh, bool double_precision)
16  {
17  // We'll need to fix up processor_id() and unique_id() values
18  // before we can operator== these meshes. But worse: our gold
19  // meshes might have been numbered differently to our generated
20  // meshes. Some of our generated mesh options practically
21  // *require* renumbering (e.g. after interior HEX20 nodes are
22  // deleted, ExodusII still wants to see a contiguous numbering),
23  // but ReplicatedMesh and DistributedMesh renumber differently.
24  //
25  // So, let's renumber too.
26 
27  MeshSerializer serialthis(*this->_mesh);
28  MeshSerializer serialother(other_mesh);
29 
30  const dof_id_type max_elem_id = this->_mesh->max_elem_id();
31  const dof_id_type max_node_id = this->_mesh->max_node_id();
32 
33  CPPUNIT_ASSERT_EQUAL(max_elem_id, other_mesh.max_elem_id());
34  CPPUNIT_ASSERT_EQUAL(max_node_id, other_mesh.max_node_id());
35 
36  auto locator = other_mesh.sub_point_locator();
37 
38  for (Elem * e1 : this->_mesh->element_ptr_range())
39  {
40  const Elem * e2c = (*locator)(e1->vertex_average());
41  CPPUNIT_ASSERT(e2c);
42  Elem & e2 = other_mesh.elem_ref(e2c->id());
43  e1->processor_id() = 0;
44  e2.processor_id() = 0;
45 
46  const dof_id_type e1_id = e1->id();
47  const dof_id_type e2_id = e2.id();
48  // Do a swap if necessary, using a free temporary id
49  if (e1_id != e2_id)
50  {
51  other_mesh.renumber_elem(e1_id, max_elem_id);
52  other_mesh.renumber_elem(e2_id, e1_id);
53  other_mesh.renumber_elem(max_elem_id, e2_id);
54  }
55 
56 #ifdef LIBMESH_ENABLE_UNIQUE_ID
57  e2.set_unique_id(e1->unique_id());
58 #endif
59  }
60 
61  for (Node * n1 : this->_mesh->node_ptr_range())
62  {
63  const Elem * e1c = (*locator)(*n1);
64  Node * n2 = nullptr;
65  for (const Node & n : e1c->node_ref_range())
66  {
67 #if defined(LIBMESH_DEFAULT_QUADRUPLE_PRECISION) || defined(LIBMESH_DEFAULT_TRIPLE_PRECISION)
68  if (double_precision)
69  {
70  const Point diff = Point(*n1)-Point(n);
71 
72  // We may be testing against ExodusII input, and if
73  // we're in triple or quadruple precision that means our
74  // lovely higher-precision node coordinates got
75  // truncated to double to be written. We need to adjust
76  // ours or they won't satisfy operator== later.
77 
78  // We're *also* testing against gold files that were
79  // calculated at double precision, so just casting a
80  // higher precision calculation to double won't give the
81  // exact same result, we have to account for error.
82  if (diff.norm() < 1e-15)
83  for (auto d : make_range(LIBMESH_DIM))
84  (*n1)(d) = double(n(d));
85  }
86 #else
87  libmesh_ignore(double_precision);
88 #endif
89  if (Point(*n1) == Point(n))
90  n2 = other_mesh.node_ptr(n.id());
91  }
92  CPPUNIT_ASSERT(n2);
93  n1->processor_id() = 0;
94  n2->processor_id() = 0;
95 
96  const dof_id_type n1_id = n1->id();
97  const dof_id_type n2_id = n2->id();
98  // Do a swap if necessary, using a free temporary id
99  if (n1_id != n2_id)
100  {
101  other_mesh.renumber_node(n1_id,max_node_id);
102  other_mesh.renumber_node(n2_id,n1_id);
103  other_mesh.renumber_node(max_node_id, n2_id);
104  }
105 
106 #ifdef LIBMESH_ENABLE_UNIQUE_ID
107  n2->set_unique_id(n1->unique_id());
108 #endif
109  }
110 
111 #ifdef LIBMESH_ENABLE_UNIQUE_ID
112  other_mesh.set_next_unique_id(this->_mesh->parallel_max_unique_id());
113  this->_mesh->set_next_unique_id(this->_mesh->parallel_max_unique_id());
114 #endif
115 
116  return *this->_mesh == other_mesh;
117  }
118 };
119 
120 #endif // MESH_ELEM_TEST_H
A Node is like a Point, but with more information.
Definition: node.h:52
auto norm() const
Definition: type_vector.h:908
std::unique_ptr< PointLocatorBase > sub_point_locator() const
Definition: mesh_base.C:1826
virtual void renumber_elem(dof_id_type old_id, dof_id_type new_id) override final
Changes the id of element old_id, both by changing elem(old_id)->id() and by moving elem(old_id) in t...
bool meshes_equal_enough(Mesh &other_mesh, bool double_precision)
This is the base class from which all geometric element types are derived.
Definition: elem.h:94
The libMesh namespace provides an interface to certain functionality in the library.
void libmesh_ignore(const Args &...)
dof_id_type id() const
Definition: dof_object.h:819
virtual void set_next_unique_id(unique_id_type id) override
Sets the next available unique id to be used.
SimpleRange< NodeRefIter > node_ref_range()
Returns a range with all nodes of an element, usable in range-based for loops.
Definition: elem.h:2679
virtual void renumber_node(dof_id_type old_id, dof_id_type new_id) override final
Changes the id of node old_id, both by changing node(old_id)->id() and by moving node(old_id) in the ...
void set_unique_id(unique_id_type new_id)
Sets the unique_id for this DofObject.
Definition: dof_object.h:848
Temporarily serialize a DistributedMesh for non-distributed-mesh capable code paths.
virtual dof_id_type max_node_id() const override final
virtual const Elem & elem_ref(const dof_id_type i) const
Definition: mesh_base.h:778
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:176
The Mesh class is a thin wrapper, around the ReplicatedMesh class by default.
Definition: mesh.h:50
virtual dof_id_type max_elem_id() const override final
processor_id_type processor_id() const
Definition: dof_object.h:881
A Point defines a location in LIBMESH_DIM dimensional Real space.
Definition: point.h:39
uint8_t dof_id_type
Definition: id_types.h:67
virtual const Node * node_ptr(const dof_id_type i) const override final