libMesh
Public Member Functions | Protected Member Functions | List of all members
NodalNeighborsTest Class Reference
Inheritance diagram for NodalNeighborsTest:
[legend]

Public Member Functions

 LIBMESH_CPPUNIT_TEST_SUITE (NodalNeighborsTest)
 The goal of this test is to ensure that MeshTools::find_nodal_neighbors() works in 1D. More...
 
 CPPUNIT_TEST (testEdge2)
 
 CPPUNIT_TEST (testEdge3)
 
 CPPUNIT_TEST (testEdge4)
 
 CPPUNIT_TEST (testOrientation)
 
 CPPUNIT_TEST_SUITE_END ()
 
void setUp ()
 
void tearDown ()
 
void testEdge2 ()
 
void testEdge3 ()
 
void testEdge4 ()
 
void testOrientation ()
 

Protected Member Functions

void do_test (unsigned n_elem, ElemType elem_type, dof_id_type *validation_data)
 

Detailed Description

Definition at line 14 of file nodal_neighbors.C.

Member Function Documentation

◆ CPPUNIT_TEST() [1/4]

NodalNeighborsTest::CPPUNIT_TEST ( testEdge2  )

◆ CPPUNIT_TEST() [2/4]

NodalNeighborsTest::CPPUNIT_TEST ( testEdge3  )

◆ CPPUNIT_TEST() [3/4]

NodalNeighborsTest::CPPUNIT_TEST ( testEdge4  )

◆ CPPUNIT_TEST() [4/4]

NodalNeighborsTest::CPPUNIT_TEST ( testOrientation  )

◆ CPPUNIT_TEST_SUITE_END()

NodalNeighborsTest::CPPUNIT_TEST_SUITE_END ( )

◆ do_test()

void NodalNeighborsTest::do_test ( unsigned  n_elem,
ElemType  elem_type,
dof_id_type validation_data 
)
inlineprotected

Definition at line 46 of file nodal_neighbors.C.

References libMesh::MeshTools::Generation::build_line(), libMesh::MeshTools::build_nodes_to_elem_map(), libMesh::MeshTools::find_nodal_neighbors(), mesh, libMesh::MeshTools::n_elem(), and TestCommWorld.

49  {
50  ReplicatedMesh mesh(*TestCommWorld, /*dim=*/1);
51 
53  n_elem,
54  /*xmin=*/0.,
55  /*xmax=*/1.,
56  elem_type);
57 
58  // find_nodal_neighbors() needs a data structure which is prepared by another function
59  std::vector<std::vector<const Elem *>> nodes_to_elem_map;
60  MeshTools::build_nodes_to_elem_map(mesh, nodes_to_elem_map);
61 
62  // Loop over the nodes and call find_nodal_neighbors()
63  {
64  std::vector<const Node*> neighbor_nodes;
65 
66  unsigned ctr = 0;
67  for (const auto & node : mesh.node_ptr_range())
68  {
69  MeshTools::find_nodal_neighbors(mesh, *node, nodes_to_elem_map, neighbor_nodes);
70 
71  // The entries in neighbor_nodes are just sorted according
72  // to memory address, which is somewhat arbitrary, so create
73  // a vector sorted by IDs for test purposes.
74  std::vector<dof_id_type> neighbor_node_ids(neighbor_nodes.size());
75  for (std::size_t i=0; i<neighbor_nodes.size(); ++i)
76  neighbor_node_ids[i] = neighbor_nodes[i]->id();
77  std::sort(neighbor_node_ids.begin(), neighbor_node_ids.end());
78 
79  // Compare to validation_data
80  for (std::size_t j=0; j<neighbor_node_ids.size(); ++j)
81  {
82  CPPUNIT_ASSERT_EQUAL( validation_data[2*ctr + j], neighbor_node_ids[j] );
83  }
84 
85  ++ctr;
86  }
87  }
88  }
The ReplicatedMesh class is derived from the MeshBase class, and is used to store identical copies of...
dof_id_type n_elem(const MeshBase::const_element_iterator &begin, const MeshBase::const_element_iterator &end)
Count up the number of elements of a specific type (as defined by an iterator range).
Definition: mesh_tools.C:850
libMesh::Parallel::Communicator * TestCommWorld
Definition: driver.C:159
MeshBase & mesh
void find_nodal_neighbors(const MeshBase &mesh, const Node &n, const std::vector< std::vector< const Elem *>> &nodes_to_elem_map, std::vector< const Node *> &neighbors)
Given a mesh and a node in the mesh, the vector will be filled with every node directly attached to t...
Definition: mesh_tools.C:888
void build_nodes_to_elem_map(const MeshBase &mesh, std::vector< std::vector< dof_id_type >> &nodes_to_elem_map)
After calling this function the input vector nodes_to_elem_map will contain the node to element conne...
Definition: mesh_tools.C:448
void build_line(UnstructuredMesh &mesh, const unsigned int nx, const Real xmin=0., const Real xmax=1., const ElemType type=INVALID_ELEM, const bool gauss_lobatto_grid=false)
A specialized build_cube() for 1D meshes.

◆ LIBMESH_CPPUNIT_TEST_SUITE()

NodalNeighborsTest::LIBMESH_CPPUNIT_TEST_SUITE ( NodalNeighborsTest  )

The goal of this test is to ensure that MeshTools::find_nodal_neighbors() works in 1D.

If the numbering of MeshGeneration::build_line() ever changes, this test will break, as it compares hand-checked hard-coded "validation" data with the results of MeshTools::find_nodal_neighbors(). We also use a ReplicatedMesh here to match the hard-coded numbering.

The testOrientation() test is not specifically related to find_nodal_neighbors(), instead it is checking that we can still find_neighbors() correctly in 1D when the mesh is topologically a straight line, but not all elements have the same "orientation" (as defined by their local node numbering). As far as I know, we don't require 2D/3D elements to have the same orientation in order for them to be considered neighbors, so this test ensures the same thing works for 1D elements.

◆ setUp()

void NodalNeighborsTest::setUp ( )
inline

Definition at line 91 of file nodal_neighbors.C.

91 {}

◆ tearDown()

void NodalNeighborsTest::tearDown ( )
inline

Definition at line 93 of file nodal_neighbors.C.

93 {}

◆ testEdge2()

void NodalNeighborsTest::testEdge2 ( )
inline

Definition at line 95 of file nodal_neighbors.C.

References libMesh::EDGE2, and libMesh::DofObject::invalid_id.

96  {
97  LOG_UNIT_TEST;
98 
99  // 11 nodes, 2 neighbor entries per node
100  dof_id_type validation_data[22] =
101  {
102  1, DofObject::invalid_id,
103  0, 2,
104  1, 3,
105  2, 4,
106  3, 5,
107  4, 6,
108  5, 7,
109  6, 8,
110  7, 9,
111  8, 10,
112  9, DofObject::invalid_id
113  };
114 
115  do_test(/*n_elem=*/10, EDGE2, validation_data);
116  }
void do_test(unsigned n_elem, ElemType elem_type, dof_id_type *validation_data)
uint8_t dof_id_type
Definition: id_types.h:67

◆ testEdge3()

void NodalNeighborsTest::testEdge3 ( )
inline

Definition at line 119 of file nodal_neighbors.C.

References libMesh::EDGE3, and libMesh::DofObject::invalid_id.

120  {
121  LOG_UNIT_TEST;
122 
123  // 11 nodes, 2 neighbor entries per node
124  dof_id_type validation_data[22] =
125  {
126  2, DofObject::invalid_id,
127  2, 4,
128  0, 1,
129  4, 6,
130  1, 3,
131  6, 8,
132  3, 5,
133  8, 10,
134  5, 7,
135  10, DofObject::invalid_id,
136  7, 9
137  };
138 
139  do_test(/*n_elem=*/5, EDGE3, validation_data);
140  }
void do_test(unsigned n_elem, ElemType elem_type, dof_id_type *validation_data)
uint8_t dof_id_type
Definition: id_types.h:67

◆ testEdge4()

void NodalNeighborsTest::testEdge4 ( )
inline

Definition at line 143 of file nodal_neighbors.C.

References libMesh::EDGE4, and libMesh::DofObject::invalid_id.

144  {
145  LOG_UNIT_TEST;
146 
147  // 10 nodes, 2 neighbor entries per node
148  dof_id_type validation_data[20] =
149  {
150  2, DofObject::invalid_id,
151  3, 5,
152  0, 3,
153  1, 2,
154  6, 8,
155  1, 6,
156  4, 5,
157  9, DofObject::invalid_id,
158  4, 9,
159  7, 8
160  };
161 
162  do_test(/*n_elem=*/3, EDGE4, validation_data);
163  }
void do_test(unsigned n_elem, ElemType elem_type, dof_id_type *validation_data)
uint8_t dof_id_type
Definition: id_types.h:67

◆ testOrientation()

void NodalNeighborsTest::testOrientation ( )
inline

Definition at line 165 of file nodal_neighbors.C.

References libMesh::MeshBase::add_elem(), libMesh::MeshBase::add_point(), libMesh::Elem::build_with_id(), libMesh::EDGE2, mesh, libMesh::MeshBase::node_ptr(), libMesh::MeshBase::prepare_for_use(), libMesh::Elem::set_node(), and TestCommWorld.

166  {
167  LOG_UNIT_TEST;
168 
170 
171  // The (1-based) node numbering and element orientation (represented
172  // by arrows) for this mesh:
173  // 1 -> 3 -> 4 -> 7 -> 8 <- 6 <- 5 <- 2
174  // So the two elements that meet at node 8 have opposite orientation
175  // and were not detected as neighbors using the original (before the
176  // addition of this test) find_neighbors() algorithm.
177 
178  // These nodes are copied from an exo file where we originally
179  // noticed the problem, but otherwise are not significant to the
180  // test. Note: the actual ids are 0-based but we are using a
181  // 1-based connectivity array below which is copied from the exo
182  // file.
183  mesh.add_point(Point(1.68, -1.695, 8.298), /*id=*/0);
184  mesh.add_point(Point(5.55, -1.695, 8.298), /*id=*/1);
185  mesh.add_point(Point(1.68, -0.175, 8.298), /*id=*/2);
186  mesh.add_point(Point(1.68, -0.175, 9.643), /*id=*/3);
187  mesh.add_point(Point(5.55, -0.175, 8.298), /*id=*/4);
188  mesh.add_point(Point(5.55, -0.175, 9.643), /*id=*/5);
189  mesh.add_point(Point(1.68, -0.075, 9.643), /*id=*/6);
190  mesh.add_point(Point(5.55, -0.075, 9.643), /*id=*/7);
191 
192  // 1-based connectivity array (2 nodes per Elem) copied directly
193  // from exo file. We will convert these to 0-based ids when they
194  // are used.
195  std::vector<unsigned int> conn =
196  {
197  7, 8,
198  1, 3,
199  2, 5,
200  3, 4,
201  5, 6,
202  4, 7,
203  6, 8
204  };
205 
206  // Add 7 EDGE2 elements and assign connectivity
207  for (unsigned int e=0; e<7; ++e)
208  {
209  Elem * elem = mesh.add_elem(Elem::build_with_id(EDGE2, e));
210  elem->set_node(0) = mesh.node_ptr(conn[2*e] - 1); // convert to 0-based index
211  elem->set_node(1) = mesh.node_ptr(conn[2*e + 1] - 1); // convert to 0-based index
212  }
213 
214  // Find neighbors, etc.
216 
217  for (const auto & elem : mesh.element_ptr_range())
218  {
219  auto elem_id = elem->id();
220 
221  // Elems 1, 2 should have no neighbor on side 0
222  if (elem_id == 1 || elem_id == 2)
223  {
224  CPPUNIT_ASSERT(elem->neighbor_ptr(0) == nullptr);
225  CPPUNIT_ASSERT(elem->neighbor_ptr(1) != nullptr);
226  }
227  // Otherwise, elem should have neighbor on both sides
228  else
229  {
230  CPPUNIT_ASSERT(elem->neighbor_ptr(0) != nullptr);
231  CPPUNIT_ASSERT(elem->neighbor_ptr(1) != nullptr);
232  }
233 
234  // Debugging
235  // libMesh::out << "elem " << elem_id << std::endl;
236  // for (auto side_idx : make_range(elem->n_sides()))
237  // {
238  // if (elem->neighbor_ptr(side_idx))
239  // libMesh::out << "Neighbor on side " << side_idx << std::endl;
240  // else
241  // libMesh::out << "No neighbor on side " << side_idx << std::endl;
242  // }
243  }
244  }
The ReplicatedMesh class is derived from the MeshBase class, and is used to store identical copies of...
virtual Node *& set_node(const unsigned int i)
Definition: elem.h:2381
libMesh::Parallel::Communicator * TestCommWorld
Definition: driver.C:159
void prepare_for_use(const bool skip_renumber_nodes_and_elements, const bool skip_find_neighbors)
Prepare a newly ecreated (or read) mesh for use.
Definition: mesh_base.C:710
This is the base class from which all geometric element types are derived.
Definition: elem.h:94
MeshBase & mesh
virtual Node * add_point(const Point &p, const dof_id_type id=DofObject::invalid_id, const processor_id_type proc_id=DofObject::invalid_processor_id)=0
Add a new Node at Point p to the end of the vertex array, with processor_id procid.
dof_id_type id() const
Definition: dof_object.h:823
virtual Elem * add_elem(Elem *e)=0
Add elem e to the end of the element array.
const Elem * neighbor_ptr(unsigned int i) const
Definition: elem.h:2407
virtual const Node * node_ptr(const dof_id_type i) const =0
A Point defines a location in LIBMESH_DIM dimensional Real space.
Definition: point.h:39

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