1#include <libmesh/libmesh.h>
2#include <libmesh/node.h>
3#include <libmesh/mesh_generation.h>
4#include <libmesh/mesh_tools.h>
5#include <libmesh/replicated_mesh.h>
6#include <libmesh/elem.h>
7#include <libmesh/utility.h>
8#include <libmesh/reference_elem.h>
9#include <unordered_map>
75 using Map = std::map<ElemType, std::map<dof_id_type, std::set<dof_id_type>>>;
82 m[
EDGE2][0].insert(1);
83 m[
EDGE2][1].insert(0);
85 m[
EDGE3][0].insert(2);
86 m[
EDGE3][1].insert(2);
87 m[
EDGE3][2].insert({0, 1});
89 m[
EDGE4][0].insert(2);
90 m[
EDGE4][1].insert(3);
91 m[
EDGE4][2].insert({0, 3});
92 m[
EDGE4][3].insert({2, 1});
94 m[
TRI3][0].insert({1, 2});
95 m[
TRI3][1].insert({0, 2});
96 m[
TRI3][2].insert({1, 0});
98 m[
TRI6][0].insert({3, 5});
99 m[
TRI6][1].insert({3, 4});
100 m[
TRI6][2].insert({5, 4});
101 m[
TRI6][3].insert({0, 1});
102 m[
TRI6][4].insert({1, 2});
103 m[
TRI6][5].insert({2, 0});
108 m[
QUAD4][0].insert({1, 3});
109 m[
QUAD4][1].insert({0, 2});
110 m[
QUAD4][2].insert({1, 3});
111 m[
QUAD4][3].insert({0, 2});
113 m[
QUAD8][0].insert({4, 7});
114 m[
QUAD8][1].insert({4, 5});
115 m[
QUAD8][2].insert({5, 6});
116 m[
QUAD8][3].insert({6, 7});
117 m[
QUAD8][4].insert({0, 1});
118 m[
QUAD8][5].insert({1, 2});
119 m[
QUAD8][6].insert({2, 3});
120 m[
QUAD8][7].insert({0, 3});
125 m[
TET4][0].insert({1, 2, 3});
126 m[
TET4][1].insert({0, 2, 3});
127 m[
TET4][2].insert({0, 1, 3});
128 m[
TET4][3].insert({0, 1, 2});
130 m[
TET10][0].insert({4, 6, 7});
131 m[
TET10][1].insert({4, 5, 8});
132 m[
TET10][2].insert({5, 6, 9});
133 m[
TET10][3].insert({7, 8, 9});
134 m[
TET10][4].insert({0, 1});
135 m[
TET10][5].insert({1, 2});
136 m[
TET10][6].insert({0, 2});
137 m[
TET10][7].insert({0, 3});
138 m[
TET10][8].insert({1, 3});
139 m[
TET10][9].insert({2, 3});
148 m[
PYRAMID5][4].insert({0, 1, 2, 3});
170 m[
PRISM6][0].insert({1, 2, 3});
171 m[
PRISM6][1].insert({0, 2, 4});
172 m[
PRISM6][2].insert({0, 1, 5});
173 m[
PRISM6][3].insert({0, 4, 5});
174 m[
PRISM6][4].insert({1, 3, 5});
175 m[
PRISM6][5].insert({2, 3, 4});
177 m[
PRISM18][0].insert({6, 8, 9});
178 m[
PRISM18][1].insert({6, 7, 10});
179 m[
PRISM18][2].insert({7, 8, 11});
180 m[
PRISM18][3].insert({9, 12, 14});
181 m[
PRISM18][4].insert({10, 12, 13});
182 m[
PRISM18][5].insert({11, 13, 14});
200 m[
HEX8][0].insert({1, 3, 4});
201 m[
HEX8][1].insert({0, 2, 5});
202 m[
HEX8][2].insert({1, 3, 6});
203 m[
HEX8][3].insert({0, 2, 7});
204 m[
HEX8][4].insert({0, 5, 7});
205 m[
HEX8][5].insert({1, 4, 6});
206 m[
HEX8][6].insert({2, 5, 7});
207 m[
HEX8][7].insert({3, 4, 6});
209 m[
HEX20][0].insert({8, 11, 12});
210 m[
HEX20][1].insert({8, 9, 13});
211 m[
HEX20][2].insert({9, 10, 14});
212 m[
HEX20][3].insert({10, 11, 15});
213 m[
HEX20][4].insert({12, 16, 19});
214 m[
HEX20][5].insert({13, 16, 17});
215 m[
HEX20][6].insert({14, 17, 18});
216 m[
HEX20][7].insert({15, 18, 19});
217 m[
HEX20][8].insert({0, 1});
218 m[
HEX20][9].insert({1, 2});
219 m[
HEX20][10].insert({2, 3});
220 m[
HEX20][11].insert({0, 3});
221 m[
HEX20][12].insert({0, 4});
222 m[
HEX20][13].insert({1, 5});
223 m[
HEX20][14].insert({2, 6});
224 m[
HEX20][15].insert({3, 7});
225 m[
HEX20][16].insert({4, 5});
226 m[
HEX20][17].insert({5, 6});
227 m[
HEX20][18].insert({6, 7});
228 m[
HEX20][19].insert({4, 7});
244 const auto dim = ref_elem->dim();
257 mesh, n_elems_per_side, n_elems_per_side, 0., 1., 0., 1., elem_type);
275 libmesh_error_msg(
"Unsupported dimension " <<
dim);
281 std::unordered_map<dof_id_type, std::vector<const Elem *>> nodes_to_elem_map;
285 std::vector<const Node*> neighbor_nodes;
287 std::set<dof_id_type> node_ids_checked;
288 for (
const auto * elem :
mesh.element_ptr_range())
290 for (
const auto & node : elem->node_ref_range())
293 if (node_ids_checked.find(node.id()) != node_ids_checked.end())
298 for (
const auto * neigh : neighbor_nodes)
301 const auto & elems_containing_node = libmesh_map_find(nodes_to_elem_map, node.id());
302 const auto & elems_containing_neigh = libmesh_map_find(nodes_to_elem_map, neigh->id());
303 const Elem * common_elem =
nullptr;
304 for (
const auto * neigh_elem : elems_containing_neigh)
306 if ((std::find(elems_containing_node.begin(), elems_containing_node.end(), neigh_elem) !=
307 elems_containing_node.end()))
308 common_elem = neigh_elem;
313 unsigned node_id_local = common_elem->
local_node(node.id());
314 unsigned neigh_id_local = common_elem->
local_node(neigh->id());
320 const auto & correct_neighbor_ids = libmesh_map_find(neighbor_map, node_id_local);
321 CPPUNIT_ASSERT(correct_neighbor_ids.find(neigh_id_local) != correct_neighbor_ids.end());
326 node_ids_checked.insert(node.id());
506 std::vector<unsigned int> conn =
518 for (
unsigned int e=0; e<7; ++e)
528 for (
const auto & elem :
mesh.element_ptr_range())
530 auto elem_id = elem->id();
533 if (elem_id == 1 || elem_id == 2)
535 CPPUNIT_ASSERT(elem->neighbor_ptr(0) ==
nullptr);
536 CPPUNIT_ASSERT(elem->neighbor_ptr(1) !=
nullptr);
541 CPPUNIT_ASSERT(elem->neighbor_ptr(0) !=
nullptr);
542 CPPUNIT_ASSERT(elem->neighbor_ptr(1) !=
nullptr);
CPPUNIT_TEST(testPyramid18)
static Map build_elem_type_to_neighbor_map()
CPPUNIT_TEST(testPrism18)
std::map< ElemType, std::map< dof_id_type, std::set< dof_id_type > > > Map
CPPUNIT_TEST(testOrientation)
CPPUNIT_TEST(testPyramid14)
CPPUNIT_TEST(testPyramid5)
CPPUNIT_TEST(testPyramid13)
CPPUNIT_TEST(testPrism20)
CPPUNIT_TEST(testPrism21)
void do_test(ElemType elem_type)
LIBMESH_CPPUNIT_TEST_SUITE(NodalNeighborsTest)
The goal of this test is to ensure that MeshTools::find_nodal_neighbors() works as expected.
static const Map elem_type_to_neighbor_map
This is the base class from which all geometric element types are derived.
virtual Node *& set_node(const unsigned int i)
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's ...
unsigned int local_node(const dof_id_type i) const
static const Order type_to_default_order_map[INVALID_ELEM]
This array maps the integer representation of the ElemType enum to the default approximation order of...
virtual const Node * node_ptr(const dof_id_type i) const =0
void prepare_for_use(const bool skip_renumber_nodes_and_elements, const bool skip_find_neighbors)
Prepare a newly created (or read) mesh for use.
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.
virtual Elem * add_elem(Elem *e)=0
Add elem e to the end of the element array.
A Point defines a location in LIBMESH_DIM dimensional Real space.
The ReplicatedMesh class is derived from the MeshBase class, and is used to store identical copies of...
Communicator * TestCommWorld
const Elem & get(const ElemType type_in)
The libMesh namespace provides an interface to certain functionality in the library.
ElemType
Defines an enum for geometric element types.
CPPUNIT_TEST_SUITE_REGISTRATION(NodalNeighborsTest)