18 #include "libmesh/libmesh_config.h"
20 #ifdef LIBMESH_ENABLE_INFINITE_ELEMENTS
25 #include "libmesh/inf_elem_builder.h"
26 #include "libmesh/libmesh_logging.h"
27 #include "libmesh/mesh_tools.h"
28 #include "libmesh/face_inf_quad4.h"
29 #include "libmesh/face_inf_quad6.h"
30 #include "libmesh/cell_inf_prism6.h"
31 #include "libmesh/cell_inf_prism12.h"
32 #include "libmesh/cell_inf_hex8.h"
33 #include "libmesh/cell_inf_hex16.h"
34 #include "libmesh/cell_inf_hex18.h"
35 #include "libmesh/mesh_base.h"
36 #include "libmesh/remote_elem.h"
46 Point origin = (b_box.first + b_box.second) / 2;
51 libMesh::out <<
" Determined origin for Infinite Elements:"
88 const bool be_verbose,
89 std::vector<const Node *> * inner_boundary_nodes)
91 START_LOG(
"build_inf_elem()",
"InfElemBuilder");
98 Point origin(origin_x.second, origin_y.second, origin_z.second);
102 if ( !origin_x.first || !origin_y.first || !origin_z.first)
106 const Point auto_origin = (b_box.first+b_box.second)/2;
110 origin(0) = auto_origin(0);
113 origin(1) = auto_origin(1);
117 origin(2) = auto_origin(2);
122 libMesh::out <<
" Origin for Infinite Elements:" << std::endl;
125 libMesh::out <<
" determined x-coordinate" << std::endl;
127 libMesh::out <<
" determined y-coordinate" << std::endl;
129 libMesh::out <<
" determined z-coordinate" << std::endl;
140 libMesh::out <<
" Origin for Infinite Elements:" << std::endl;
152 if (inner_boundary_nodes !=
nullptr)
170 unsigned int>> inner_faces;
183 <<
" convert the <int,int> list to a Node * list..."
199 std::vector<dof_id_type> inner_boundary_node_numbers;
200 inner_boundary_node_numbers.reserve(4*inner_faces.size());
204 for (
const auto & p : inner_faces)
210 for (
const Node & node : side->node_ref_range())
211 inner_boundary_node_numbers.push_back(node.id());
222 const std::size_t ibn_size_before = inner_boundary_node_numbers.size();
224 std::sort (inner_boundary_node_numbers.begin(), inner_boundary_node_numbers.end());
226 std::unique (inner_boundary_node_numbers.begin(), inner_boundary_node_numbers.end());
228 std::size_t unique_size =
std::distance(inner_boundary_node_numbers.begin(), unique_end);
229 libmesh_assert_less_equal (unique_size, ibn_size_before);
235 inner_boundary_nodes->reserve (unique_size);
236 inner_boundary_nodes->clear();
238 for (
const auto & dof :
as_range(inner_boundary_node_numbers.begin(), unique_end))
241 inner_boundary_nodes->push_back(node);
246 <<
" target nodes." << std::endl;
257 STOP_LOG(
"build_inf_elem()",
"InfElemBuilder");
280 const bool be_verbose,
282 unsigned int>> * inner_faces)
287 libMesh::out <<
" Building Infinite Elements:" << std::endl;
288 libMesh::out <<
" updating element neighbor tables..." << std::endl;
290 libMesh::out <<
" Verbose mode disabled in non-debug mode." << std::endl;
298 LOG_SCOPE(
"build_inf_elem()",
"InfElemBuilder");
302 std::set<std::pair<dof_id_type,unsigned int>> faces;
303 std::set<std::pair<dof_id_type,unsigned int>> ofaces;
306 std::set<dof_id_type> onodes;
318 if (x_sym || y_sym || z_sym)
319 libMesh::out <<
", skipping sides in symmetry planes..." << std::endl;
329 for (
auto s : elem->side_index_range())
330 if (elem->neighbor_ptr(s) ==
nullptr)
334 std::unique_ptr<Elem> side(elem->build_side_ptr(s));
345 for (
const Node & node : side->node_ref_range())
348 const Point dist_from_origin =
352 if (
std::abs(dist_from_origin(0)) > 1.e-3)
356 if (
std::abs(dist_from_origin(1)) > 1.e-3)
360 if (
std::abs(dist_from_origin(2)) > 1.e-3)
386 sym_side = (x_sym && on_x_sym) || (y_sym && on_y_sym) || (z_sym && on_z_sym);
389 faces.insert( std::make_pair(elem->id(), s) );
409 onodes.insert(max_r_node);
413 auto face_it = faces.begin();
414 auto face_end = faces.end();
415 unsigned int facesfound=0;
416 while (face_it != face_end) {
417 std::pair<dof_id_type, unsigned int> p = *face_it;
424 for (
const Node & node : side->node_ref_range())
425 if (onodes.count(node.id()))
434 for (
const Node & node : side->node_ref_range())
435 onodes.insert(node.id());
438 face_it = faces.erase(face_it);
448 if (facesfound>0 && face_it == faces.end())
451 face_it = faces.begin();
463 <<
" outer boundary faces"
470 if (inner_faces !=
nullptr)
471 *inner_faces = faces;
479 std::map<dof_id_type, Node *> outer_nodes;
486 #ifdef LIBMESH_ENABLE_UNIQUE_ID
492 for (
const auto & dof : onodes)
508 #ifdef LIBMESH_ENABLE_UNIQUE_ID
511 outer_nodes[dof] = new_node;
523 for (
auto & p : ofaces)
532 bool is_higher_order_elem =
false;
545 is_higher_order_elem =
true;
555 is_higher_order_elem =
true;
564 el->
set_node(16) = side->node_ptr(8);
565 el->
set_node(17) = outer_nodes[side->node_id(8)];
566 is_higher_order_elem=
true;
576 el->
set_node(4) = side->node_ptr(2);
581 libMesh::out <<
"InfElemBuilder::build_inf_elem(Point, bool, bool, bool, bool): "
582 <<
"invalid face element "
587 const unsigned int n_base_vertices = side->n_vertices();
596 libmesh_assert_less_equal(el->
n_sides(), 6);
597 el->
set_id (belem.
id() * 6 + p.second + old_max_elem_id);
599 #ifdef LIBMESH_ENABLE_UNIQUE_ID
600 el->
set_unique_id() = old_max_unique_id + old_max_node_id + belem.
id();
620 unsigned int n_shared_vertices = 0;
621 for (
unsigned int i = 0; i != n_base_vertices; ++i)
622 for (
auto & node : remote_side->node_ref_range())
623 if (side->node_ptr(i) == &node &&
627 if (n_shared_vertices + 1 >= belem.
dim())
638 for (
unsigned int i=0; i<n_base_vertices; i++)
640 el->
set_node(i ) = side->node_ptr(i);
641 el->
set_node(i+n_base_vertices) = outer_nodes[side->node_id(i)];
647 if (is_higher_order_elem)
653 const unsigned int n_safe_base_nodes = el->
n_vertices();
655 for (
unsigned int i=n_base_vertices; i<n_safe_base_nodes; i++)
657 el->
set_node(i+n_base_vertices) = side->node_ptr(i);
659 outer_nodes[side->node_id(i)];
675 <<
" infinite elements and "
677 <<
" nodes to the mesh"
689 #endif // LIBMESH_ENABLE_INFINITE_ELEMENTS