21 #include "libmesh/libmesh_config.h" 
   22 #include "libmesh/mesh_base.h" 
   23 #include "libmesh/metis_partitioner.h" 
   24 #include "libmesh/libmesh_logging.h" 
   25 #include "libmesh/elem.h" 
   26 #include "libmesh/mesh_communication.h" 
   27 #include "libmesh/error_vector.h" 
   28 #include "libmesh/vectormap.h" 
   29 #include "libmesh/metis_csr_graph.h" 
   30 #include "libmesh/parallel.h" 
   31 #include "libmesh/utility.h" 
   33 #ifdef LIBMESH_HAVE_METIS 
   40 #     include "libmesh/ignore_warnings.h" 
   42 #     include "libmesh/restore_warnings.h" 
   46 #  include "libmesh/sfc_partitioner.h" 
   51 #include <unordered_map> 
   61                                        unsigned int n_pieces)
 
   73   libmesh_assert_greater (n_pieces, 0);
 
   76   if (!
mesh.is_serial())
 
   78       libMesh::out << 
"WARNING: Forced to gather a distributed mesh for METIS" << std::endl;
 
   83 #ifndef LIBMESH_HAVE_METIS 
   86   libMesh::out << 
"ERROR: The library has been built without"    << std::endl
 
   87                << 
"Metis support.  Using a space-filling curve"  << std::endl
 
   88                << 
"partitioner instead!"                         << std::endl;);
 
   96   LOG_SCOPE(
"partition_range()", 
"MetisPartitioner");
 
  107   global_index_map.reserve (n_range_elem);
 
  110     std::vector<dof_id_type> global_index;
 
  114                                              beg, 
end, global_index);
 
  116     libmesh_assert_equal_to (global_index.size(), n_range_elem);
 
  120       global_index_map.
insert (std::make_pair(elem->id(), global_index[cnt++]));
 
  122     libmesh_assert_equal_to (global_index_map.size(), n_range_elem);
 
  129   typedef std::unordered_multimap<const Elem *, const Elem *> map_type;
 
  130   map_type interior_to_boundary_map;
 
  136       if ((elem->dim() >= LIBMESH_DIM) ||
 
  137           !elem->interior_parent())
 
  141       std::set<Elem *> neighbor_set;
 
  142       elem->find_interior_neighbors(neighbor_set);
 
  144       for (
auto & neighbor : neighbor_set)
 
  145         interior_to_boundary_map.insert(std::make_pair(neighbor, elem));
 
  149   std::vector<Metis::idx_t> part(n_range_elem);
 
  153   if (
mesh.processor_id() == 0)
 
  157       std::vector<Metis::idx_t> vwgt(n_range_elem);
 
  160         n = static_cast<Metis::idx_t>(n_range_elem),   
 
  163         nparts  = static_cast<Metis::idx_t>(n_pieces), 
 
  172       csr_graph.
offsets.resize(n_range_elem + 1, 0);
 
  180 #ifdef LIBMESH_ENABLE_AMR 
  181         std::vector<const Elem *> neighbors_offspring;
 
  185         std::size_t graph_size=0;
 
  193               global_index_map[elem->id()];
 
  195             libmesh_assert_less (elem_global_index, vwgt.size());
 
  200               vwgt[elem_global_index] = elem->n_nodes();
 
  202               vwgt[elem_global_index] = static_cast<Metis::idx_t>((*
_weights)[elem->id()]);
 
  204             unsigned int num_neighbors = 0;
 
  208             for (
auto neighbor : elem->neighbor_ptr_range())
 
  210                 if (neighbor != 
nullptr)
 
  215                     if (neighbor->active() && !global_index_map.
count(neighbor->id()))
 
  220                     if (neighbor->active())
 
  223 #ifdef LIBMESH_ENABLE_AMR 
  232                         const unsigned int ns =
 
  233                           neighbor->which_neighbor_am_i (elem);
 
  234                         libmesh_assert_less (ns, neighbor->n_neighbors());
 
  246                         neighbor->active_family_tree (neighbors_offspring);
 
  251                         for (
const auto & child : neighbors_offspring)
 
  254                             if (!global_index_map.
count(child->id()))
 
  260                             if (child->neighbor_ptr(ns) == elem)
 
  274             if ((elem->dim() < LIBMESH_DIM) && elem->interior_parent())
 
  277                 std::set<const Elem *> neighbor_set;
 
  278                 elem->find_interior_neighbors(neighbor_set);
 
  280                 num_neighbors += cast_int<unsigned int>(neighbor_set.size());
 
  284             typedef map_type::iterator map_it_type;
 
  285             std::pair<map_it_type, map_it_type>
 
  286               bounds = interior_to_boundary_map.equal_range(elem);
 
  287             num_neighbors += cast_int<unsigned int>
 
  292             graph_size += num_neighbors;
 
  302               global_index_map[elem->id()];
 
  304             unsigned int connection=0;
 
  308             for (
auto neighbor : elem->neighbor_ptr_range())
 
  310                 if (neighbor != 
nullptr)
 
  315                     if (neighbor->active() && !global_index_map.
count(neighbor->id()))
 
  320                     if (neighbor->active())
 
  321                       csr_graph(elem_global_index, connection++) = global_index_map[neighbor->id()];
 
  323 #ifdef LIBMESH_ENABLE_AMR 
  332                         const unsigned int ns =
 
  333                           neighbor->which_neighbor_am_i (elem);
 
  334                         libmesh_assert_less (ns, neighbor->n_neighbors());
 
  338                         neighbor->active_family_tree (neighbors_offspring);
 
  343                         for (
const auto & child : neighbors_offspring)
 
  346                             if (!global_index_map.
count(child->id()))
 
  352                             if (child->neighbor_ptr(ns) == elem)
 
  356                                 csr_graph(elem_global_index, connection++) = global_index_map[child->id()];
 
  366             if ((elem->dim() < LIBMESH_DIM) &&
 
  367                 elem->interior_parent())
 
  370                 std::set<const Elem *> neighbor_set;
 
  371                 elem->find_interior_neighbors(neighbor_set);
 
  373                 for (
const Elem * neighbor : neighbor_set)
 
  381                     const Elem * queried_elem = 
mesh.query_elem_ptr(neighbor->id());
 
  385                     if (queried_elem && queried_elem == neighbor)
 
  386                       csr_graph(elem_global_index, connection++) =
 
  387                         libmesh_map_find(global_index_map, neighbor->id());
 
  392             for (
const auto & pr : 
as_range(interior_to_boundary_map.equal_range(elem)))
 
  394                 const Elem * neighbor = pr.second;
 
  395                 csr_graph(elem_global_index, connection++) =
 
  396                   global_index_map[neighbor->
id()];
 
  402         libmesh_assert_equal_to (csr_graph.
vals.size(),
 
  403                                  std::max(graph_size, std::size_t(1)));
 
  406       Metis::idx_t ncon = 1;
 
  412         Metis::METIS_PartGraphRecursive(&n,
 
  415                                         csr_graph.
vals.data(),
 
  428         Metis::METIS_PartGraphKway(&n,
 
  431                                    csr_graph.
vals.data(),
 
  445   mesh.comm().broadcast(part);
 
  455         global_index_map[elem->id()];
 
  457       libmesh_assert_less (elem_global_index, part.size());
 
  459         static_cast<processor_id_type>(part[elem_global_index]);
 
  461       elem->processor_id() = elem_procid;
 
  469                                       const unsigned int n_pieces)
 
  472                         mesh.active_elements_begin(),
 
  473                         mesh.active_elements_end(),