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" 48 Point origin = (b_box.first + b_box.second) / 2;
53 libMesh::out <<
" Determined origin for Infinite Elements:" 90 const bool be_verbose,
91 std::vector<const Node *> * inner_boundary_nodes)
93 LOG_SCOPE(
"build_inf_elem()",
"InfElemBuilder");
100 Point origin(origin_x.second, origin_y.second, origin_z.second);
104 if ( !origin_x.first || !origin_y.first || !origin_z.first)
108 const Point auto_origin = (b_box.first+b_box.second)/2;
112 origin(0) = auto_origin(0);
115 origin(1) = auto_origin(1);
119 origin(2) = auto_origin(2);
124 libMesh::out <<
" Origin for Infinite Elements:" << std::endl;
127 libMesh::out <<
" determined x-coordinate" << std::endl;
129 libMesh::out <<
" determined y-coordinate" << std::endl;
131 libMesh::out <<
" determined z-coordinate" << std::endl;
142 libMesh::out <<
" Origin for Infinite Elements:" << std::endl;
154 if (inner_boundary_nodes !=
nullptr)
172 unsigned int>> inner_faces;
185 <<
" convert the <int,int> list to a Node * list..." 201 std::vector<dof_id_type> inner_boundary_node_numbers;
202 inner_boundary_node_numbers.reserve(4*inner_faces.size());
206 for (
const auto & p : inner_faces)
212 for (
const Node & node : side->node_ref_range())
213 inner_boundary_node_numbers.push_back(node.id());
224 const std::size_t ibn_size_before = inner_boundary_node_numbers.size();
226 std::sort (inner_boundary_node_numbers.begin(), inner_boundary_node_numbers.end());
228 std::unique (inner_boundary_node_numbers.begin(), inner_boundary_node_numbers.end());
230 std::size_t unique_size =
std::distance(inner_boundary_node_numbers.begin(), unique_end);
231 libmesh_assert_less_equal (unique_size, ibn_size_before);
237 inner_boundary_nodes->reserve (unique_size);
238 inner_boundary_nodes->clear();
240 for (
const auto & dof :
as_range(inner_boundary_node_numbers.begin(), unique_end))
243 inner_boundary_nodes->push_back(node);
248 <<
" target nodes." << std::endl;
279 const bool be_verbose,
281 unsigned int>> * inner_faces)
286 libMesh::out <<
" Building Infinite Elements:" << std::endl;
287 libMesh::out <<
" updating element neighbor tables..." << std::endl;
289 libMesh::out <<
" Verbose mode disabled in non-debug mode." << std::endl;
297 LOG_SCOPE(
"build_inf_elem()",
"InfElemBuilder");
301 std::set<std::pair<dof_id_type,unsigned int>> faces;
302 std::set<std::pair<dof_id_type,unsigned int>> ofaces;
305 std::set<dof_id_type> onodes;
317 if (x_sym || y_sym || z_sym)
318 libMesh::out <<
", skipping sides in symmetry planes..." << std::endl;
327 for (
const auto & elem :
_mesh.active_element_ptr_range())
328 for (
auto s : elem->side_index_range())
329 if (elem->neighbor_ptr(s) ==
nullptr)
333 std::unique_ptr<Elem> side(elem->build_side_ptr(s));
344 for (
const Node & node : side->node_ref_range())
347 const Point dist_from_origin =
351 if (std::abs(dist_from_origin(0)) > 1.e-3)
355 if (std::abs(dist_from_origin(1)) > 1.e-3)
359 if (std::abs(dist_from_origin(2)) > 1.e-3)
385 sym_side = (x_sym && on_x_sym) || (y_sym && on_y_sym) || (z_sym && on_z_sym);
388 faces.emplace(elem->id(), s);
412 onodes.insert(max_r_node);
416 bool did_parallel_update;
420 did_parallel_update =
false;
422 auto face_it = faces.begin();
423 auto face_end = faces.end();
424 unsigned int facesfound=0;
425 while (face_it != face_end) {
426 std::pair<dof_id_type, unsigned int> p = *face_it;
433 for (
const Node & node : side->node_ref_range())
434 if (onodes.count(node.id()))
443 for (
const Node & node : side->node_ref_range())
444 onodes.insert(node.id());
447 face_it = faces.erase(face_it);
457 if (facesfound>0 && face_it == faces.end())
460 face_it = faces.begin();
466 auto my_onodes_size = onodes.size();
468 did_parallel_update = (onodes.size() > my_onodes_size);
472 while (did_parallel_update);
481 <<
" outer boundary faces" 488 if (inner_faces !=
nullptr)
489 *inner_faces = faces;
497 std::map<dof_id_type, Node *> outer_nodes;
504 #ifdef LIBMESH_ENABLE_UNIQUE_ID 510 for (
const auto & n : onodes)
529 std::unique_ptr<Node> new_node =
Node::build(p, new_id);
531 #ifdef LIBMESH_ENABLE_UNIQUE_ID 532 new_node->set_unique_id(old_max_unique_id + bnode.
id());
548 for (
auto & p : ofaces)
557 bool is_higher_order_elem =
false;
559 std::unique_ptr<Elem> el;
570 is_higher_order_elem =
true;
580 is_higher_order_elem =
true;
589 el->set_node(16, side->node_ptr(8));
590 el->set_node(17, outer_nodes[side->node_id(8)]);
591 is_higher_order_elem=
true;
601 el->set_node(4, side->node_ptr(2));
606 libMesh::out <<
"InfElemBuilder::build_inf_elem(Point, bool, bool, bool, bool): " 607 <<
"invalid face element " 612 const unsigned int n_base_vertices = side->n_vertices();
621 const unsigned int max_sides = 6;
622 libmesh_assert_less_equal(el->n_sides(), max_sides);
623 el->set_id (belem.
id() * max_sides + p.second + old_max_elem_id);
625 #ifdef LIBMESH_ENABLE_UNIQUE_ID 626 el->set_unique_id(old_max_unique_id + old_max_node_id +
627 belem.
id() * max_sides + p.second);
638 for (
auto inf_s : el->side_index_range())
647 unsigned int n_shared_vertices = 0;
648 for (
unsigned int i = 0; i != n_base_vertices; ++i)
649 for (
auto & node : remote_side->node_ref_range())
650 if (side->node_ptr(i) == &node &&
651 el->is_node_on_side(i,inf_s))
654 if (n_shared_vertices + 1 >= belem.
dim())
665 for (
unsigned int i=0; i<n_base_vertices; i++)
667 el->set_node(i , side->node_ptr(i));
668 el->set_node(i+n_base_vertices, outer_nodes[side->node_id(i)]);
674 if (is_higher_order_elem)
680 const unsigned int n_safe_base_nodes = el->n_vertices();
682 for (
unsigned int i=n_base_vertices; i<n_safe_base_nodes; i++)
684 el->set_node(i+n_base_vertices, side->node_ptr(i));
685 el->set_node(i+n_safe_base_nodes,
686 outer_nodes[side->node_id(i)]);
709 for (
auto & p : ofaces)
728 <<
" infinite elements and " 730 <<
" nodes to the mesh" 742 #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
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 created (or read) mesh for use.
virtual void find_neighbors(const bool reset_remote_elements=false, const bool reset_current_list=true, const bool assert_valid=true)=0
Locate element face (edge in 2D) neighbors.
This is the base class from which all geometric element types are derived.
const Parallel::Communicator & comm() const
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
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 const Node * query_node_ptr(const dof_id_type i) const =0
virtual dof_id_type max_elem_id() const =0
void maxloc(T &r, unsigned int &max_id) const
void set_neighbor(const unsigned int i, Elem *n)
Assigns n as the neighbor.
void broadcast(T &data, const unsigned int root_id=0, const bool identical_sizes=false) const
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.
virtual unsigned int n_sides() const =0
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. ...
void max(const T &r, T &o, Request &req) const
virtual unsigned short dim() const =0
virtual const Elem & elem_ref(const dof_id_type i) const
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...
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.
void set_union(T &data, const unsigned int root_id) const
const RemoteElem * remote_elem