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;