libMesh
Loading...
Searching...
No Matches
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
8using namespace libMesh;
9
10template <ElemType elem_type>
11class MeshPerElemTest : public PerElemTest<elem_type>
12{
13protected:
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
bool meshes_equal_enough(Mesh &other_mesh, bool double_precision)
std::unique_ptr< Mesh > _mesh
Definition elem_test.h:26
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...
virtual dof_id_type max_node_id() const override final
virtual void set_next_unique_id(unique_id_type id) override
Sets the next available unique id to be used.
virtual dof_id_type max_elem_id() const override final
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 ...
virtual const Node * node_ptr(const dof_id_type i) const override final
processor_id_type processor_id() const
Definition dof_object.h:881
dof_id_type id() const
Definition dof_object.h:819
void set_unique_id(unique_id_type new_id)
Sets the unique_id for this DofObject.
Definition dof_object.h:848
This is the base class from which all geometric element types are derived.
Definition elem.h:96
SimpleRange< NodeRefIter > node_ref_range()
Returns a range with all nodes of an element, usable in range-based for loops.
Definition elem.h:2682
virtual const Elem & elem_ref(const dof_id_type i) const
Definition mesh_base.h:788
std::unique_ptr< PointLocatorBase > sub_point_locator() const
Definition mesh_base.C:1833
Temporarily serialize a DistributedMesh for non-distributed-mesh capable code paths.
The Mesh class is a thin wrapper, around the ReplicatedMesh class by default.
Definition mesh.h:51
A Node is like a Point, but with more information.
Definition node.h:55
A Point defines a location in LIBMESH_DIM dimensional Real space.
Definition point.h:40
auto norm() const
The libMesh namespace provides an interface to certain functionality in the library.
void libmesh_ignore(const Args &...)
uint8_t dof_id_type
Definition id_types.h:67
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