29 #include <unordered_map> 30 #include <unordered_set> 39 class FuzzyPointCompare
46 FuzzyPointCompare(
Real tol) : _tol(tol) {}
49 bool operator()(
const Point & lhs,
const Point & rhs)
51 for (
unsigned i=0; i<LIBMESH_DIM; ++i)
74 if (
std::abs(lhs(i) - rhs(i)) / rel_size < _tol)
90 bool operator()(
const std::pair<Point, dof_id_type> & lhs,
91 const std::pair<Point, dof_id_type> & rhs)
93 return (*
this)(lhs.first, rhs.first);
99 bool operator()(
const Point & lhs, std::pair<Point, dof_id_type> & rhs)
101 return (*
this)(lhs, rhs.first);
105 bool operator()(std::pair<Point, dof_id_type> & lhs,
const Point & rhs)
107 return (*
this)(lhs.first, rhs);
123 #ifdef LIBMESH_ENABLE_UNIQUE_ID 147 #ifdef LIBMESH_ENABLE_UNIQUE_ID 171 libmesh_assert_less (i, this->
n_nodes());
172 libmesh_assert(
_nodes[i]);
173 libmesh_assert_equal_to (
_nodes[i]->
id(), i);
183 libmesh_assert_less (i, this->
n_nodes());
184 libmesh_assert(
_nodes[i]);
185 libmesh_assert_equal_to (
_nodes[i]->
id(), i);
197 libmesh_assert (
_nodes[i] ==
nullptr ||
210 libmesh_assert (
_nodes[i] ==
nullptr ||
221 libmesh_assert_less (i, this->
n_elem());
223 libmesh_assert_equal_to (
_elements[i]->
id(), i);
233 libmesh_assert_less (i, this->
n_elem());
235 libmesh_assert_equal_to (
_elements[i]->
id(), i);
247 libmesh_assert (
_elements[i] ==
nullptr ||
260 libmesh_assert (
_elements[i] ==
nullptr ||
281 #ifdef LIBMESH_ENABLE_UNIQUE_ID 307 #ifdef LIBMESH_ENABLE_UNIQUE_ID 313 libmesh_assert_less (eid,
_elements.size());
318 libmesh_assert_equal_to (oldelem->id(), eid);
334 std::vector<Elem *>::iterator pos =
_elements.end();
345 std::advance(pos, e->
id());
407 _nodes.push_back (static_cast<Node *>(
nullptr));
417 cast_int<dof_id_type>(
_nodes.size()-1) :
id).release();
420 #ifdef LIBMESH_ENABLE_UNIQUE_ID 447 #ifdef LIBMESH_ENABLE_UNIQUE_ID 462 libmesh_error_msg(
"Error, attempting to insert nullptr node.");
465 libmesh_error_msg(
"Error, cannot insert node with invalid id.");
476 libmesh_error_msg(
"Error, cannot insert node on top of existing node.");
486 #ifdef LIBMESH_ENABLE_UNIQUE_ID 505 libmesh_assert_less (n->
id(),
_nodes.size());
509 std::vector<Node *>::iterator pos;
517 std::advance(pos, n->
id());
521 pos = std::find (
_nodes.begin(),
527 libmesh_assert (pos !=
_nodes.end());
549 libmesh_assert (!
_nodes[new_id]);
584 #ifdef LIBMESH_ENABLE_UNIQUE_ID 591 #ifdef LIBMESH_ENABLE_UNIQUE_ID 595 parallel_object_only();
607 LOG_SCOPE(
"renumber_nodes_and_elem()",
"Mesh");
614 std::unordered_set<Node *> connected_nodes;
621 std::vector<Elem *>::iterator in =
_elements.begin();
622 std::vector<Elem *>::iterator out_iter =
_elements.begin();
623 const std::vector<Elem *>::iterator
end =
_elements.end();
625 for (; in !=
end; ++in)
634 el->
set_id (next_free_elem++);
640 connected_nodes.insert(&n);
649 if (n.id() == next_free_node)
652 else if (n.id() > next_free_node)
660 libmesh_assert(
_nodes[src_idx]);
667 if (
_nodes[src_idx] !=
nullptr)
668 _nodes[src_idx]->set_id (src_idx);
669 _nodes[dst_idx]->set_id (dst_idx);
688 std::vector<Node *>::iterator in =
_nodes.begin();
689 std::vector<Node *>::iterator out_iter =
_nodes.begin();
690 const std::vector<Node *>::iterator
end =
_nodes.end();
692 for (; in !=
end; ++in)
699 if (connected_nodes.find(nd) != connected_nodes.end())
705 nd->
set_id (next_free_node++);
728 std::vector<Node *>::iterator nd =
_nodes.begin();
729 const std::vector<Node *>::iterator
end =
_nodes.end();
731 std::advance (nd, next_free_node);
753 libmesh_assert_equal_to (next_free_elem,
_elements.size());
754 libmesh_assert_equal_to (next_free_node,
_nodes.size());
764 for (std::size_t n=0; n<this->
_nodes.size(); n++)
765 if (this->
_nodes[n] !=
nullptr)
766 this->
_nodes[n]->set_id() = cast_int<dof_id_type>(n);
769 for (std::size_t e=0; e<this->
_elements.size(); e++)
771 this->
_elements[e]->set_id() = cast_int<dof_id_type>(e);
779 bool clear_stitched_boundary_ids,
781 bool use_binary_search,
782 bool enforce_all_nodes_match_on_boundaries)
784 LOG_SCOPE(
"stitch_meshes()",
"ReplicatedMesh");
786 this_mesh_boundary_id,
787 other_mesh_boundary_id,
789 clear_stitched_boundary_ids,
792 enforce_all_nodes_match_on_boundaries,
799 bool clear_stitched_boundary_ids,
801 bool use_binary_search,
802 bool enforce_all_nodes_match_on_boundaries)
808 clear_stitched_boundary_ids,
811 enforce_all_nodes_match_on_boundaries,
819 bool clear_stitched_boundary_ids,
821 bool use_binary_search,
822 bool enforce_all_nodes_match_on_boundaries,
823 bool skip_find_neighbors)
825 std::map<dof_id_type, dof_id_type> node_to_node_map, other_to_this_node_map;
826 std::map<dof_id_type, std::vector<dof_id_type>> node_to_elems_map;
829 typedef std::pair<Elem *, unsigned char> val_type;
830 typedef std::pair<key_type, val_type> key_val_pair;
831 typedef std::unordered_multimap<key_type, val_type> map_type;
833 map_type side_to_elem_map;
844 LOG_SCOPE(
"stitch_meshes node merging",
"ReplicatedMesh");
850 bool h_min_updated =
false;
853 std::set<dof_id_type> this_boundary_node_ids, other_boundary_node_ids;
856 std::unique_ptr<Elem>
side;
860 boundary_id_type id_array[2] = {this_mesh_boundary_id, other_mesh_boundary_id};
861 std::set<dof_id_type> * set_array[2] = {&this_boundary_node_ids, &other_boundary_node_ids};
864 for (
unsigned i=0; i<2; ++i)
875 if (node_bc_id == id_array[i])
878 set_array[i]->insert( this_node_id );
885 h_min = first_active_elem->
hmin();
886 h_min_updated =
true;
892 std::vector<boundary_id_type> bc_ids;
897 for (
auto side_id : el->side_index_range())
898 if (el->neighbor_ptr(side_id) ==
nullptr)
903 if (std::find(bc_ids.begin(), bc_ids.end(), id_array[i]) != bc_ids.end())
905 el->build_side_ptr(
side, side_id);
906 for (
auto & n :
side->node_ref_range())
907 set_array[i]->insert(n.id());
910 h_min_updated =
true;
913 if (skip_find_neighbors && (i==0))
915 key_type key = el->key(side_id);
918 val.second = cast_int<unsigned char>(side_id);
923 side_to_elem_map.insert (kvp);
930 for (
auto edge_id : el->edge_index_range())
932 if (el->is_edge_on_side(edge_id, side_id))
937 if (std::find(bc_ids.begin(), bc_ids.end(), id_array[i]) != bc_ids.end())
939 std::unique_ptr<Elem> edge (el->build_edge_ptr(edge_id));
940 for (
auto & n : edge->node_ref_range())
941 set_array[i]->insert( n.id() );
943 h_min =
std::min(h_min, edge->hmin());
944 h_min_updated =
true;
956 <<
"This mesh has " << this_boundary_node_ids.size()
957 <<
" nodes on boundary " << this_mesh_boundary_id <<
".\n" 958 <<
"Other mesh has " << other_boundary_node_ids.size()
959 <<
" nodes on boundary " << other_mesh_boundary_id <<
".\n";
963 libMesh::out <<
"Minimum edge length on both surfaces is " << h_min <<
".\n";
967 libMesh::out <<
"No elements on specified surfaces." << std::endl;
972 if (use_binary_search)
976 typedef std::vector<std::pair<Point, dof_id_type>> PointVector;
978 this_sorted_bndry_nodes(this_boundary_node_ids.size()),
979 other_sorted_bndry_nodes(other_boundary_node_ids.size());
987 std::set<dof_id_type> * set_array[2] = {&this_boundary_node_ids, &other_boundary_node_ids};
989 PointVector * vec_array[2] = {&this_sorted_bndry_nodes, &other_sorted_bndry_nodes};
991 for (
unsigned i=0; i<2; ++i)
993 std::set<dof_id_type>::iterator
994 set_it = set_array[i]->begin(),
995 set_it_end = set_array[i]->end();
998 for (
unsigned ctr=0; set_it != set_it_end; ++set_it, ++ctr)
1000 (*vec_array[i])[ctr] = std::make_pair(mesh_array[i]->
point(*set_it),
1005 std::sort(vec_array[i]->begin(), vec_array[i]->
end(), mein_comp);
1010 for (std::size_t i=0; i<this_sorted_bndry_nodes.size(); ++i)
1013 Point this_point = this_sorted_bndry_nodes[i].first;
1018 other_sorted_bndry_nodes.end(),
1024 if (other_iter != other_sorted_bndry_nodes.end())
1030 Point other_point = other_iter->first;
1033 libmesh_error_msg(
"Error: mismatched points: " << this_point <<
" and " << other_point);
1039 this_node_id = this_sorted_bndry_nodes[i].second,
1040 other_node_id = other_iter->second;
1041 node_to_node_map[this_node_id] = other_node_id;
1042 other_to_this_node_map[other_node_id] = this_node_id;
1052 for (
const auto & this_node_id : this_boundary_node_ids)
1056 bool found_matching_nodes =
false;
1058 for (
const auto & other_node_id : other_boundary_node_ids)
1060 const Node & other_node = other_mesh->
node_ref(other_node_id);
1062 Real node_distance = (this_node - other_node).norm();
1064 if (node_distance < tol*h_min)
1067 if (found_matching_nodes)
1068 libmesh_error_msg(
"Error: Found multiple matching nodes in stitch_meshes");
1070 node_to_node_map[this_node_id] = other_node_id;
1071 other_to_this_node_map[other_node_id] = this_node_id;
1073 found_matching_nodes =
true;
1087 for (
auto & n : el->node_ref_range())
1090 std::map<dof_id_type, dof_id_type>::iterator it =
1091 other_to_this_node_map.find(other_node_id);
1093 if (it != other_to_this_node_map.end())
1096 node_to_elems_map[this_node_id].push_back( el->id() );
1104 <<
"Found " << node_to_node_map.size()
1105 <<
" matching nodes.\n" 1109 if (enforce_all_nodes_match_on_boundaries)
1111 std::size_t n_matching_nodes = node_to_node_map.size();
1112 std::size_t this_mesh_n_nodes = this_boundary_node_ids.size();
1113 std::size_t other_mesh_n_nodes = other_boundary_node_ids.size();
1114 if ((n_matching_nodes != this_mesh_n_nodes) || (n_matching_nodes != other_mesh_n_nodes))
1115 libmesh_error_msg(
"Error: We expected the number of nodes to match.");
1122 libMesh::out <<
"Skip node merging in ReplicatedMesh::stitch_meshes:" << std::endl;
1130 #ifdef LIBMESH_ENABLE_UNIQUE_ID 1138 if (
this!=other_mesh)
1140 LOG_SCOPE(
"stitch_meshes copying",
"ReplicatedMesh");
1144 for (
auto & pr : node_to_node_map)
1145 pr.second += node_delta;
1147 for (
auto & pr : node_to_elems_map)
1148 for (
auto & entry : pr.second)
1149 entry += elem_delta;
1154 elem_delta, node_delta,
1163 boundary.
add_node(std::get<0>(t) + node_delta,
1167 boundary.
add_side(std::get<0>(t) + elem_delta,
1172 boundary.
add_edge(std::get<0>(t) + elem_delta,
1191 LOG_SCOPE(
"stitch_meshes node updates",
"ReplicatedMesh");
1194 std::vector<boundary_id_type> bc_ids;
1196 for (
const auto & pr : node_to_elems_map)
1199 dof_id_type other_node_id = node_to_node_map[target_node_id];
1202 std::size_t n_elems = pr.second.size();
1203 for (std::size_t i=0; i<n_elems; i++)
1209 unsigned int local_node_index = el->
local_node(other_node_id);
1215 el->
set_node(local_node_index) = &target_node;
1222 LOG_SCOPE(
"stitch_meshes node deletion",
"ReplicatedMesh");
1223 for (
const auto & pr : node_to_node_map)
1227 if ((
this == other_mesh) && (pr.second == pr.first))
1242 if (skip_find_neighbors)
1244 LOG_SCOPE(
"stitch_meshes neighbor fixes",
"ReplicatedMesh");
1247 std::unique_ptr<Elem> my_side, their_side;
1249 std::set<dof_id_type> fixed_elems;
1250 for (
const auto & pr : node_to_elems_map)
1252 std::size_t n_elems = pr.second.size();
1253 for (std::size_t i=0; i<n_elems; i++)
1256 if (fixed_elems.find(elem_id) == fixed_elems.end())
1259 fixed_elems.insert(elem_id);
1264 key_type key = el->
key(s);
1265 auto bounds = side_to_elem_map.equal_range(key);
1267 if (bounds.first != bounds.second)
1273 while (bounds.first != bounds.second)
1276 Elem * neighbor = bounds.first->second.first;
1279 const unsigned int ns = bounds.first->second.second;
1280 neighbor->
side_ptr(their_side, ns);
1292 if ((*my_side == *their_side) &&
1294 ((el->
dim() != 1) || (ns != s)))
1325 side_to_elem_map.erase (bounds.first);
1343 if (clear_stitched_boundary_ids)
1345 LOG_SCOPE(
"stitch_meshes clear bcids",
"ReplicatedMesh");
1348 std::vector<boundary_id_type> bc_ids;
1351 for (
auto side_id : el->side_index_range())
1352 if (el->neighbor_ptr(side_id) !=
nullptr)
1358 if (std::find(bc_ids.begin(), bc_ids.end(), this_mesh_boundary_id) != bc_ids.end() ||
1359 std::find(bc_ids.begin(), bc_ids.end(), other_mesh_boundary_id) != bc_ids.end())
virtual void copy_nodes_and_elements(const UnstructuredMesh &other_mesh, const bool skip_find_neighbors=false, dof_id_type element_id_offset=0, dof_id_type node_id_offset=0, unique_id_type unique_id_offset=0)
virtual Elem * add_elem(Elem *e) override
unique_id_type & set_unique_id()
virtual element_iterator active_elements_end() override
Mesh data structure replicated on all processors.
bool _skip_renumber_nodes_and_elements
virtual const Elem * elem(const dof_id_type i) const
virtual Node *& set_node(const unsigned int i)
A geometric point in (x,y,z) space associated with a DOF.
const unsigned int invalid_uint
std::vector< Elem * > _elements
IntRange< unsigned short > side_index_range() const
virtual ~ReplicatedMesh()
void stitch_meshes(const ReplicatedMesh &other_mesh, boundary_id_type this_mesh_boundary, boundary_id_type other_mesh_boundary, Real tol=TOLERANCE, bool clear_stitched_boundary_ids=false, bool verbose=true, bool use_binary_search=true, bool enforce_all_nodes_match_on_boundaries=false)
virtual Node * insert_node(Node *n) override
void remove(const Node *node)
virtual dof_id_type n_nodes() const override
virtual dof_id_type n_elem() const override
The base class for all geometric element types.
uint8_t processor_id_type
const Parallel::Communicator & comm() const
static const Real TOLERANCE
virtual dof_id_type n_active_elem() const override
const BoundaryInfo & get_boundary_info() const
long double max(long double a, double b)
virtual dof_id_type max_elem_id() const override
void build_side_list(std::vector< dof_id_type > &element_id_list, std::vector< unsigned short int > &side_list, std::vector< boundary_id_type > &bc_id_list) const
virtual unique_id_type parallel_max_unique_id() const override
std::vector< boundary_id_type > boundary_ids(const Node *node) const
virtual const Elem * query_elem_ptr(const dof_id_type i) const override
unique_id_type _next_unique_id
void build_node_list(std::vector< dof_id_type > &node_id_list, std::vector< boundary_id_type > &bc_id_list) const
void add_node(const Node *node, const boundary_id_type id)
virtual Elem * insert_elem(Elem *e) override
static const boundary_id_type invalid_id
virtual const Elem * elem_ptr(const dof_id_type i) const override
virtual Real hmin() const
virtual void clear() override
Base class for Replicated and Distributed meshes.
virtual dof_id_type key(const unsigned int s) const =0
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) override
std::unique_ptr< Partitioner > _partitioner
Used by the Mesh to keep track of boundary nodes and elements.
SimpleRange< I > as_range(const std::pair< I, I > &p)
static const dof_id_type invalid_id
std::vector< Node * > _nodes
virtual void delete_node(Node *n) override
void prepare_for_use(const bool skip_renumber_nodes_and_elements=false, const bool skip_find_neighbors=false)
bool valid_unique_id() const
bool absolute_fuzzy_equals(const TypeVector< T > &rhs, Real tol=TOLERANCE) const
void set_neighbor(const unsigned int i, Elem *n)
void build_shellface_list(std::vector< dof_id_type > &element_id_list, std::vector< unsigned short int > &shellface_list, std::vector< boundary_id_type > &bc_id_list) const
void regenerate_id_sets()
virtual void renumber_node(dof_id_type old_id, dof_id_type new_id) override
virtual void renumber_nodes_and_elements() override
virtual const Point & point(const dof_id_type i) const override
virtual void renumber_elem(dof_id_type old_id, dof_id_type new_id) override
virtual const Node & node(const dof_id_type i) const
SimpleRange< NodeRefIter > node_ref_range()
virtual Node * add_node(Node *n) override
static std::unique_ptr< Node > build(const Node &n)
const Elem * neighbor_ptr(unsigned int i) const
void remove_side(const Elem *elem, const unsigned short int side)
virtual dof_id_type max_node_id() const override
unsigned int level() const
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
virtual void update_parallel_id_counts() override
virtual std::unique_ptr< Elem > side_ptr(unsigned int i)=0
virtual void fix_broken_node_and_element_numbering() override
virtual unsigned short dim() const =0
const Node * node_ptr(const unsigned int i) const
virtual const Node * query_node_ptr(const dof_id_type i) const override
void build_edge_list(std::vector< dof_id_type > &element_id_list, std::vector< unsigned short int > &edge_list, std::vector< boundary_id_type > &bc_id_list) const
void swap(Iterator &lhs, Iterator &rhs)
void add_side(const dof_id_type elem, const unsigned short int side, const boundary_id_type id)
void add_shellface(const dof_id_type elem, const unsigned short int shellface, const boundary_id_type id)
void stitch_surfaces(boundary_id_type boundary_id_1, boundary_id_type boundary_id_2, Real tol=TOLERANCE, bool clear_stitched_boundary_ids=false, bool verbose=true, bool use_binary_search=true, bool enforce_all_nodes_match_on_boundaries=false)
ForwardIterator binary_find(ForwardIterator first, ForwardIterator last, const T &value)
virtual const Node * node_ptr(const dof_id_type i) const override
void stitching_helper(const ReplicatedMesh *other_mesh, boundary_id_type boundary_id_1, boundary_id_type boundary_id_2, Real tol, bool clear_stitched_boundary_ids, bool verbose, bool use_binary_search, bool enforce_all_nodes_match_on_boundaries, bool skip_find_neighbors)
virtual const Node & node_ref(const dof_id_type i) const
unsigned int local_node(const dof_id_type i) const
ReplicatedMesh(const Parallel::Communicator &comm_in, unsigned char dim=1)
virtual void delete_elem(Elem *e) override
OStreamProxy out(std::cout)
virtual element_iterator active_elements_begin() override
processor_id_type processor_id() const
long double min(long double a, double b)
A geometric point in (x,y,z) space.
void add_edge(const dof_id_type elem, const unsigned short int edge, const boundary_id_type id)
std::vector< boundary_id_type > edge_boundary_ids(const Elem *const elem, const unsigned short int edge) const
virtual SimpleRange< element_iterator > element_ptr_range() override