21 #include "libmesh/libmesh_config.h"
27 #include <unordered_map>
30 #include "libmesh/boundary_info.h"
31 #include "libmesh/libmesh_logging.h"
32 #include "libmesh/elem.h"
33 #include "libmesh/ghost_point_neighbors.h"
34 #include "libmesh/mesh_base.h"
35 #include "libmesh/mesh_communication.h"
36 #include "libmesh/mesh_tools.h"
37 #include "libmesh/parallel.h"
38 #include "libmesh/partitioner.h"
39 #include "libmesh/point_locator_base.h"
40 #include "libmesh/threads.h"
41 #include "libmesh/enum_elem_type.h"
42 #include "libmesh/enum_point_locator_type.h"
43 #include "libmesh/auto_ptr.h"
58 _default_mapping_data(0),
61 _count_lower_dim_elems_in_point_locator(true),
63 #ifdef LIBMESH_ENABLE_UNIQUE_ID
64 _next_unique_id(
DofObject::invalid_unique_id),
66 _skip_noncritical_partitioning(false),
68 _skip_renumber_nodes_and_elements(false),
69 _allow_remote_element_removal(true),
70 _spatial_dimension(d),
72 _point_locator_close_to_point_tol(0.)
76 libmesh_assert_less_equal (LIBMESH_DIM, 3);
77 libmesh_assert_greater_equal (LIBMESH_DIM, d);
86 _n_parts (other_mesh._n_parts),
87 _default_mapping_type(other_mesh._default_mapping_type),
88 _default_mapping_data(other_mesh._default_mapping_data),
89 _is_prepared (other_mesh._is_prepared),
91 _count_lower_dim_elems_in_point_locator(other_mesh._count_lower_dim_elems_in_point_locator),
93 #ifdef LIBMESH_ENABLE_UNIQUE_ID
94 _next_unique_id(other_mesh._next_unique_id),
96 _skip_noncritical_partitioning(false),
98 _skip_renumber_nodes_and_elements(false),
99 _allow_remote_element_removal(true),
100 _elem_dims(other_mesh._elem_dims),
101 _spatial_dimension(other_mesh._spatial_dimension),
103 _ghosting_functors(other_mesh._ghosting_functors),
104 _point_locator_close_to_point_tol(other_mesh._point_locator_close_to_point_tol)
138 return cast_int<unsigned int>(*
_elem_dims.rbegin());
149 parallel_object_only();
153 "Specified element dimensions does not match true element dimensions!");
194 std::unordered_map<std::string, std::size_t> name_indices;
198 std::vector<unsigned int> returnval(names.size());
200 bool added_an_integer =
false;
203 const std::string &
name = names[i];
204 auto it = name_indices.find(
name);
205 if (it != name_indices.end())
206 returnval[i] = it->second;
210 name_indices[
name] = returnval[i];
212 added_an_integer =
true;
216 if (allocate_data && added_an_integer)
217 this->size_elem_extra_integers();
224 unsigned int MeshBase::get_elem_integer_index(
const std::string &
name)
const
227 if (_elem_integer_names[i] ==
name)
230 libmesh_error_msg(
"Unknown elem integer " <<
name);
236 bool MeshBase::has_elem_integer(
const std::string &
name)
const
238 for (
auto & entry : _elem_integer_names)
247 unsigned int MeshBase::add_node_integer(
const std::string &
name,
251 if (_node_integer_names[i] ==
name)
254 _node_integer_names.push_back(
name);
256 this->size_node_extra_integers();
257 return _node_integer_names.size()-1;
262 std::vector<unsigned int> MeshBase::add_node_integers(
const std::vector<std::string> & names,
265 std::unordered_map<std::string, std::size_t> name_indices;
267 name_indices[_node_integer_names[i]] = i;
269 std::vector<unsigned int> returnval(names.size());
271 bool added_an_integer =
false;
274 const std::string &
name = names[i];
275 auto it = name_indices.find(
name);
276 if (it != name_indices.end())
277 returnval[i] = it->second;
280 returnval[i] = _node_integer_names.size();
281 name_indices[
name] = returnval[i];
282 _node_integer_names.push_back(
name);
283 added_an_integer =
true;
287 if (allocate_data && added_an_integer)
288 this->size_node_extra_integers();
295 unsigned int MeshBase::get_node_integer_index(
const std::string &
name)
const
298 if (_node_integer_names[i] ==
name)
301 libmesh_error_msg(
"Unknown node integer " <<
name);
307 bool MeshBase::has_node_integer(
const std::string &
name)
const
309 for (
auto & entry : _node_integer_names)
318 void MeshBase::prepare_for_use (
const bool skip_renumber_nodes_and_elements,
const bool skip_find_neighbors)
320 LOG_SCOPE(
"prepare_for_use()",
"MeshBase");
322 parallel_object_only();
347 if (skip_renumber_nodes_and_elements)
349 libmesh_deprecated();
350 this->allow_renumbering(
false);
355 if (!_skip_renumber_nodes_and_elements)
356 this->renumber_nodes_and_elements();
358 this->update_parallel_id_counts();
361 if (!skip_find_neighbors)
362 this->find_neighbors();
374 this->cache_elem_dims();
378 this->detect_interior_parents();
386 #if defined(DEBUG) && defined(LIBMESH_ENABLE_UNIQUE_ID)
393 this->clear_point_locator();
398 for (
auto & gf : _ghosting_functors)
407 if (!skip_partitioning())
412 if (this->_allow_remote_element_removal)
413 this->delete_remote_elements();
415 if (!_skip_renumber_nodes_and_elements)
416 this->renumber_nodes_and_elements();
421 #if defined(DEBUG) && defined(LIBMESH_ENABLE_UNIQUE_ID)
429 void MeshBase::clear ()
435 _is_prepared =
false;
439 boundary_info->clear();
445 this->clear_point_locator();
452 _ghosting_functors.erase(&ghosting_functor);
454 auto it = _shared_functors.find(&ghosting_functor);
455 if (it != _shared_functors.end())
456 _shared_functors.erase(it);
461 void MeshBase::subdomain_ids (std::set<subdomain_id_type> & ids)
const
464 parallel_object_only();
468 for (
const auto & elem : this->active_local_element_ptr_range())
469 ids.insert(elem->subdomain_id());
472 this->comm().set_union(ids);
480 parallel_object_only();
482 std::set<subdomain_id_type> ids;
484 this->subdomain_ids (ids);
486 return cast_int<subdomain_id_type>(ids.size());
497 proc_id == DofObject::invalid_processor_id);
499 return static_cast<dof_id_type>(
std::distance (this->pid_nodes_begin(proc_id),
500 this->pid_nodes_end (proc_id)));
510 proc_id == DofObject::invalid_processor_id);
512 return static_cast<dof_id_type>(
std::distance (this->pid_elements_begin(proc_id),
513 this->pid_elements_end (proc_id)));
520 libmesh_assert_less (proc_id, this->n_processors());
521 return static_cast<dof_id_type>(
std::distance (this->active_pid_elements_begin(proc_id),
522 this->active_pid_elements_end (proc_id)));
531 for (
const auto & elem : this->element_ptr_range())
532 ne += elem->n_sub_elem();
543 for (
const auto & elem : this->active_element_ptr_range())
544 ne += elem->n_sub_elem();
551 std::string MeshBase::get_info()
const
553 std::ostringstream oss;
555 oss <<
" Mesh Information:" <<
'\n';
557 if (!_elem_dims.empty())
559 oss <<
" elem_dimensions()={";
560 std::copy(_elem_dims.begin(),
562 std::ostream_iterator<unsigned int>(oss,
", "));
563 oss << cast_int<unsigned int>(*_elem_dims.rbegin());
567 oss <<
" spatial_dimension()=" << this->spatial_dimension() <<
'\n'
568 <<
" n_nodes()=" << this->
n_nodes() <<
'\n'
569 <<
" n_local_nodes()=" << this->n_local_nodes() <<
'\n'
570 <<
" n_elem()=" << this->
n_elem() <<
'\n'
571 <<
" n_local_elem()=" << this->n_local_elem() <<
'\n'
572 #ifdef LIBMESH_ENABLE_AMR
573 <<
" n_active_elem()=" << this->n_active_elem() <<
'\n'
575 <<
" n_subdomains()=" << static_cast<std::size_t>(this->n_subdomains()) <<
'\n'
576 <<
" n_partitions()=" << static_cast<std::size_t>(this->n_partitions()) <<
'\n'
577 <<
" n_processors()=" << static_cast<std::size_t>(this->n_processors()) <<
'\n'
579 <<
" processor_id()=" << static_cast<std::size_t>(this->processor_id()) <<
'\n';
585 void MeshBase::print_info(std::ostream & os)
const
587 os << this->get_info()
599 void MeshBase::partition (
const unsigned int n_parts)
603 if (this->n_unpartitioned_elem() > 0)
607 partitioner()->partition (*
this, n_parts);
612 else if (!skip_noncritical_partitioning())
614 partitioner()->partition (*
this, n_parts);
624 this->recalculate_n_partitions();
627 this->update_post_partitioning();
631 unsigned int MeshBase::recalculate_n_partitions()
634 parallel_object_only();
636 unsigned int max_proc_id=0;
638 for (
const auto & elem : this->active_local_element_ptr_range())
639 max_proc_id = std::max(max_proc_id, static_cast<unsigned int>(elem->processor_id()));
642 _n_parts = max_proc_id+1;
644 this->comm().max(_n_parts);
651 #ifdef LIBMESH_ENABLE_DEPRECATED
654 libmesh_deprecated();
656 if (_point_locator.get() ==
nullptr)
661 _point_locator = PointLocatorBase::build(
TREE_ELEMENTS, *
this);
663 if (_point_locator_close_to_point_tol > 0.)
664 _point_locator->set_close_to_point_tol(_point_locator_close_to_point_tol);
667 return *_point_locator;
672 std::unique_ptr<PointLocatorBase> MeshBase::sub_point_locator ()
const
675 if (_point_locator.get() ==
nullptr)
681 parallel_object_only();
683 _point_locator = PointLocatorBase::build(
TREE_ELEMENTS, *
this);
685 if (_point_locator_close_to_point_tol > 0.)
686 _point_locator->set_close_to_point_tol(_point_locator_close_to_point_tol);
691 return PointLocatorBase::build(
TREE_ELEMENTS, *
this, _point_locator.get());
696 void MeshBase::clear_point_locator ()
698 _point_locator.reset(
nullptr);
703 void MeshBase::set_count_lower_dim_elems_in_point_locator(
bool count_lower_dim_elems)
705 _count_lower_dim_elems_in_point_locator = count_lower_dim_elems;
710 bool MeshBase::get_count_lower_dim_elems_in_point_locator()
const
712 return _count_lower_dim_elems_in_point_locator;
719 return _block_id_to_name[id];
725 static const std::string empty;
727 std::map<subdomain_id_type, std::string>::const_iterator iter = _block_id_to_name.find(
id);
728 if (iter == _block_id_to_name.end())
740 std::map<subdomain_id_type, std::string>::const_iterator
741 iter = _block_id_to_name.begin(),
742 end_iter = _block_id_to_name.end();
744 for ( ; iter != end_iter; ++iter)
745 if (iter->second ==
name)
750 return Elem::invalid_subdomain_id;
753 void MeshBase::cache_elem_dims()
756 parallel_object_only();
762 for (
const auto & elem : this->active_element_ptr_range())
763 _elem_dims.insert(cast_int<unsigned char>(elem->dim()));
766 this->comm().set_union(_elem_dims);
770 unsigned int max_dim = this->mesh_dimension();
771 if (max_dim > _spatial_dimension)
772 _spatial_dimension = cast_int<unsigned char>(max_dim);
781 if (_spatial_dimension < 3)
783 for (
const auto & node : this->node_ptr_range())
787 if ((*node)(1) != 0.)
789 _spatial_dimension = 2;
799 if ((*node)(2) != 0.)
803 _spatial_dimension = 3;
809 #endif // LIBMESH_DIM > 1
812 void MeshBase::detect_interior_parents()
815 parallel_object_only();
818 if (this->elem_dimensions().size() == 1)
822 std::unordered_map<dof_id_type, std::vector<dof_id_type>> node_to_elem;
824 for (
const auto & elem : this->active_element_ptr_range())
829 libmesh_assert_less (elem->id(), this->max_elem_id());
831 node_to_elem[elem->node_id(n)].push_back(elem->id());
836 for (
const auto & element : this->element_ptr_range())
839 if (element->dim()>=LIBMESH_DIM || element->interior_parent())
846 std::vector<std::set<dof_id_type>> neighbors( element->n_vertices() );
848 bool found_interior_parents =
false;
852 std::vector<dof_id_type> & element_ids = node_to_elem[element->node_id(n)];
853 for (
const auto & eid : element_ids)
854 if (this->elem_ref(eid).
dim() == element->dim()+1)
855 neighbors[n].insert(eid);
857 if (neighbors[n].size()>0)
859 found_interior_parents =
true;
866 found_interior_parents =
false;
875 if (found_interior_parents)
877 std::set<dof_id_type> & neighbors_0 = neighbors[0];
878 for (
const auto & interior_parent_id : neighbors_0)
880 found_interior_parents =
false;
883 if (neighbors[n].find(interior_parent_id)!=neighbors[n].end())
885 found_interior_parents=
true;
889 found_interior_parents=
false;
893 if (found_interior_parents)
895 element->set_interior_parent(this->elem_ptr(interior_parent_id));
905 void MeshBase::set_point_locator_close_to_point_tol(
Real val)
907 _point_locator_close_to_point_tol = val;
911 _point_locator->set_close_to_point_tol(val);
913 _point_locator->unset_close_to_point_tol();
919 Real MeshBase::get_point_locator_close_to_point_tol()
const
921 return _point_locator_close_to_point_tol;
926 void MeshBase::size_elem_extra_integers()
928 const std::size_t new_size = _elem_integer_names.size();
929 for (
auto elem : this->element_ptr_range())
930 elem->add_extra_integers(new_size);
935 void MeshBase::size_node_extra_integers()
937 const std::size_t new_size = _node_integer_names.size();
938 for (
auto node : this->node_ptr_range())
939 node->add_extra_integers(new_size);
943 std::pair<std::vector<unsigned int>, std::vector<unsigned int>>
944 MeshBase::merge_extra_integer_names(
const MeshBase & other)
946 std::pair<std::vector<unsigned int>, std::vector<unsigned int>> returnval;