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 LOG_SCOPE(
"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;
277 const bool be_verbose,
279 unsigned int>> * inner_faces)
284 libMesh::out <<
" Building Infinite Elements:" << std::endl;
285 libMesh::out <<
" updating element neighbor tables..." << std::endl;
287 libMesh::out <<
" Verbose mode disabled in non-debug mode." << std::endl;
295 LOG_SCOPE(
"build_inf_elem()",
"InfElemBuilder");
299 std::set<std::pair<dof_id_type,unsigned int>> faces;
300 std::set<std::pair<dof_id_type,unsigned int>> ofaces;
303 std::set<dof_id_type> onodes;
315 if (x_sym || y_sym || z_sym)
316 libMesh::out <<
", skipping sides in symmetry planes..." << std::endl;
325 for (
const auto & elem :
_mesh.active_element_ptr_range())
326 for (
auto s : elem->side_index_range())
327 if (elem->neighbor_ptr(s) ==
nullptr)
331 std::unique_ptr<Elem> side(elem->build_side_ptr(s));
342 for (
const Node & node : side->node_ref_range())
345 const Point dist_from_origin =
349 if (std::abs(dist_from_origin(0)) > 1.e-3)
353 if (std::abs(dist_from_origin(1)) > 1.e-3)
357 if (std::abs(dist_from_origin(2)) > 1.e-3)
383 sym_side = (x_sym && on_x_sym) || (y_sym && on_y_sym) || (z_sym && on_z_sym);
386 faces.emplace(elem->id(), s);
406 onodes.insert(max_r_node);
410 auto face_it = faces.begin();
411 auto face_end = faces.end();
412 unsigned int facesfound=0;
413 while (face_it != face_end) {
414 std::pair<dof_id_type, unsigned int> p = *face_it;
421 for (
const Node & node : side->node_ref_range())
422 if (onodes.count(node.id()))
431 for (
const Node & node : side->node_ref_range())
432 onodes.insert(node.id());
435 face_it = faces.erase(face_it);
445 if (facesfound>0 && face_it == faces.end())
448 face_it = faces.begin();
460 <<
" outer boundary faces" 467 if (inner_faces !=
nullptr)
468 *inner_faces = faces;
476 std::map<dof_id_type, Node *> outer_nodes;
483 #ifdef LIBMESH_ENABLE_UNIQUE_ID 489 for (
const auto & dof : onodes)
502 std::unique_ptr<Node> new_node =
Node::build(p, new_id);
504 #ifdef LIBMESH_ENABLE_UNIQUE_ID 505 new_node->set_unique_id(old_max_unique_id + bnode.
id());
521 for (
auto & p : ofaces)
530 bool is_higher_order_elem =
false;
532 std::unique_ptr<Elem> el;
543 is_higher_order_elem =
true;
553 is_higher_order_elem =
true;
562 el->set_node(16, side->node_ptr(8));
563 el->set_node(17, outer_nodes[side->node_id(8)]);
564 is_higher_order_elem=
true;
574 el->set_node(4, side->node_ptr(2));
579 libMesh::out <<
"InfElemBuilder::build_inf_elem(Point, bool, bool, bool, bool): " 580 <<
"invalid face element " 585 const unsigned int n_base_vertices = side->n_vertices();
594 const unsigned int max_sides = 6;
595 libmesh_assert_less_equal(el->n_sides(), max_sides);
596 el->set_id (belem.
id() * max_sides + p.second + old_max_elem_id);
598 #ifdef LIBMESH_ENABLE_UNIQUE_ID 599 el->set_unique_id(old_max_unique_id + old_max_node_id +
600 belem.
id() * max_sides + p.second);
611 for (
auto inf_s : el->side_index_range())
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 &&
624 el->is_node_on_side(i,inf_s))
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));
658 el->set_node(i+n_safe_base_nodes,
659 outer_nodes[side->node_id(i)]);
675 <<
" infinite elements and " 677 <<
" nodes to the mesh" 689 #endif // LIBMESH_ENABLE_INFINITE_ELEMENTS A Node is like a Point, but with more information.
virtual unique_id_type parallel_max_unique_id() const =0
auto norm() const -> decltype(std::norm(T()))
IntRange< unsigned short > side_index_range() const
virtual std::unique_ptr< Elem > build_side_ptr(const unsigned int i)=0
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.
This is the base class from which all geometric element types are derived.
The libMesh namespace provides an interface to certain functionality in the library.
Real distance(const Point &p)
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 bool is_serial() const
virtual void find_neighbors(const bool reset_remote_elements=false, const bool reset_current_list=true)=0
Locate element face (edge in 2D) neighbors.
std::pair< bool, double > InfElemOriginValue
Useful typedef.
virtual Elem * add_elem(Elem *e)=0
Add elem e to the end of the element array.
static std::unique_ptr< Elem > build(const ElemType type, Elem *p=nullptr)
void print_info(std::ostream &os=libMesh::out, const unsigned int verbosity=0, const bool global=true) const
Prints relevant information about the mesh.
SimpleRange< IndexType > as_range(const std::pair< IndexType, IndexType > &p)
Helper function that allows us to treat a homogenous pair as a range.
virtual dof_id_type max_elem_id() const =0
virtual Node * add_node(Node *n)=0
Add Node n to the end of the vertex array.
Defines a Cartesian bounding box by the two corner extremum.
static std::unique_ptr< Node > build(const Node &n)
const Elem * neighbor_ptr(unsigned int i) const
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
const Point build_inf_elem(const bool be_verbose=false)
Build infinite elements atop a volume-based mesh, determine origin automatically. ...
virtual unsigned short dim() const =0
virtual const Elem & elem_ref(const dof_id_type i) const
virtual void libmesh_assert_valid_parallel_ids() const
Verify id and processor_id consistency of our elements and nodes containers.
virtual const Node & node_ref(const dof_id_type i) const
virtual const Point & point(const dof_id_type i) const =0
void write_unformatted(std::ostream &out_stream, const bool newline=true) const
Unformatted print to the stream out.
virtual dof_id_type max_node_id() const =0
virtual dof_id_type n_elem() const =0
virtual const Node * node_ptr(const dof_id_type i) const =0
processor_id_type processor_id() const
MeshBase & _mesh
Reference to the mesh we're building infinite elements for.
processor_id_type processor_id() const
A Point defines a location in LIBMESH_DIM dimensional Real space.
const RemoteElem * remote_elem