21 #include "libmesh/partitioner.h" 
   24 #include "libmesh/elem.h" 
   25 #include "libmesh/int_range.h" 
   26 #include "libmesh/libmesh_logging.h" 
   27 #include "libmesh/mesh_base.h" 
   28 #include "libmesh/mesh_tools.h" 
   29 #include "libmesh/mesh_communication.h" 
   30 #include "libmesh/parallel_ghost_sync.h" 
   37 #ifdef LIBMESH_HAVE_PETSC 
   38 #include "libmesh/ignore_warnings.h" 
   40 #include "libmesh/restore_warnings.h" 
   67   libmesh_parallel_only(
mesh.comm());
 
   76   const unsigned int n_parts =
 
   77     static_cast<unsigned int>
 
   78     (std::min(
mesh.n_active_elem(), static_cast<dof_id_type>(n)));
 
   81   mesh.set_n_partitions()=n_parts;
 
  107   MeshTools::libmesh_assert_valid_procids<Elem>(
mesh);
 
  114   MeshTools::libmesh_assert_valid_procids<Elem>(
mesh);
 
  119   mesh.update_post_partitioning();
 
  132                                const unsigned int n)
 
  136   const unsigned int n_parts =
 
  137     static_cast<unsigned int>
 
  138     (std::min(
mesh.n_active_elem(), static_cast<dof_id_type>(n)));
 
  141   mesh.set_n_partitions()=n_parts;
 
  169                                mesh.elements_end());
 
  182   LOG_SCOPE(
"single_partition_range()", 
"Partitioner");
 
  186       elem->processor_id() = 0;
 
  189       for (
Node & node : elem->node_ref_range())
 
  190         node.processor_id() = 0;
 
  202                                                     const unsigned int n_subdomains)
 
  211   if (!n_unpartitioned_elements)
 
  215   std::vector<dof_id_type> subdomain_bounds(
mesh.n_processors());
 
  222       if (pid < n_subdomains)
 
  224           tgt_subdomain_size = n_unpartitioned_elements/n_subdomains;
 
  226           if (pid < n_unpartitioned_elements%n_subdomains)
 
  227             tgt_subdomain_size++;
 
  233         subdomain_bounds[0] = tgt_subdomain_size;
 
  235         subdomain_bounds[pid] = subdomain_bounds[pid-1] + tgt_subdomain_size;
 
  238   libmesh_assert_equal_to (subdomain_bounds.back(), n_unpartitioned_elements);
 
  242   std::vector<dof_id_type> global_indices;
 
  253       libmesh_assert_less (cnt, global_indices.size());
 
  255         global_indices[cnt++];
 
  257       libmesh_assert_less (global_index, subdomain_bounds.back());
 
  258       libmesh_assert_less (global_index, n_unpartitioned_elements);
 
  261         cast_int<processor_id_type>
 
  263                        std::upper_bound(subdomain_bounds.begin(),
 
  264                                         subdomain_bounds.end(),
 
  266       libmesh_assert_less (subdomain_id, n_subdomains);
 
  268       elem->processor_id() = subdomain_id;
 
  280   LOG_SCOPE(
"set_parent_processor_ids()", 
"Partitioner");
 
  282 #ifdef LIBMESH_ENABLE_AMR 
  292   if (
mesh.is_serial())
 
  294       for (
auto & elem : 
mesh.active_element_ptr_range())
 
  297           std::vector<Elem *> subactive_family;
 
  298           elem->total_family_tree(subactive_family);
 
  299           for (
const auto & f : subactive_family)
 
  300             f->processor_id() = elem->processor_id();
 
  317                                                     child.processor_id());
 
  319               parent = parent->
parent();
 
  332       for (
auto & child : 
mesh.active_element_ptr_range())
 
  334           std::vector<Elem *> subactive_family;
 
  336           for (
const auto & f : subactive_family)
 
  337             f->processor_id() = child->processor_id();
 
  349       libmesh_parallel_only(
mesh.comm());
 
  351                                        mesh.unpartitioned_elements_end()) == 0);
 
  355       std::vector<processor_id_type>
 
  359       for (
dof_id_type blk=0, last_elem_id=0; last_elem_id<max_elem_id; blk++)
 
  366           std::fill (parent_processor_ids.begin(),
 
  367                      parent_processor_ids.end(),
 
  371           bool have_parent_in_block = 
false;
 
  373           for (
auto & parent : 
as_range(
mesh.ancestor_elements_begin(),
 
  374                                         mesh.ancestor_elements_end()))
 
  377               libmesh_assert_less (parent_idx, max_elem_id);
 
  379               if ((parent_idx >= first_elem_id) &&
 
  380                   (parent_idx <  last_elem_id))
 
  382                   have_parent_in_block = 
true;
 
  385                   std::vector<const Elem *> active_family;
 
  386                   parent->active_family_tree(active_family);
 
  387                   for (
const auto & f : active_family)
 
  388                     parent_pid = std::min (parent_pid, f->processor_id());
 
  390                   const dof_id_type packed_idx = parent_idx - first_elem_id;
 
  391                   libmesh_assert_less (packed_idx, parent_processor_ids.size());
 
  393                   parent_processor_ids[packed_idx] = parent_pid;
 
  398           mesh.comm().min (parent_processor_ids);
 
  401           if (have_parent_in_block)
 
  402             for (
auto & parent : 
as_range(
mesh.ancestor_elements_begin(),
 
  403                                           mesh.ancestor_elements_end()))
 
  407                 if ((parent_idx >= first_elem_id) &&
 
  408                     (parent_idx <  last_elem_id))
 
  410                     const dof_id_type packed_idx = parent_idx - first_elem_id;
 
  411                     libmesh_assert_less (packed_idx, parent_processor_ids.size());
 
  414                       parent_processor_ids[packed_idx];
 
  418                     parent->processor_id() = parent_pid;
 
  424 #endif // LIBMESH_ENABLE_AMR 
  429                                                 std::map<std::pair<processor_id_type, processor_id_type>, std::set<dof_id_type>> & processor_pair_to_nodes)
 
  432   libmesh_parallel_only(
mesh.comm());
 
  434   processor_pair_to_nodes.clear();
 
  436   std::set<dof_id_type> mynodes;
 
  437   std::set<dof_id_type> neighbor_nodes;
 
  438   std::vector<dof_id_type> common_nodes;
 
  441   for (
auto & elem : 
mesh.active_element_ptr_range())
 
  447       auto n_nodes = elem->n_nodes();
 
  451       neighbor_nodes.clear();
 
  452       common_nodes.clear();
 
  454       for (
unsigned int inode = 0; inode < 
n_nodes; inode++)
 
  455         mynodes.insert(elem->node_id(inode));
 
  457       for (
auto i : elem->side_index_range())
 
  459           auto neigh = elem->neighbor_ptr(i);
 
  460           if (neigh && !neigh->is_remote() && neigh->processor_id() != elem->processor_id())
 
  462               neighbor_nodes.clear();
 
  463               common_nodes.clear();
 
  464               auto neigh_n_nodes = neigh->n_nodes();
 
  465               for (
unsigned int inode = 0; inode < neigh_n_nodes; inode++)
 
  466                 neighbor_nodes.insert(neigh->node_id(inode));
 
  468               std::set_intersection(mynodes.begin(), mynodes.end(),
 
  469                                     neighbor_nodes.begin(), neighbor_nodes.end(),
 
  470                                     std::back_inserter(common_nodes));
 
  472               auto & map_set = processor_pair_to_nodes[std::make_pair(std::min(elem->processor_id(), neigh->processor_id()),
 
  473                                                                       std::max(elem->processor_id(), neigh->processor_id()))];
 
  474               for (
auto global_node_id : common_nodes)
 
  475                 map_set.insert(global_node_id);
 
  484   libmesh_parallel_only(
mesh.comm());
 
  486   std::map<std::pair<processor_id_type, processor_id_type>, std::set<dof_id_type>> processor_pair_to_nodes;
 
  490   for (
auto & pmap : processor_pair_to_nodes)
 
  492       std::size_t n_own_nodes = pmap.second.size()/2, i = 0;
 
  496           auto & node = 
mesh.node_ref(
id);
 
  497           if (i <= n_own_nodes)
 
  498             node.processor_id() = pmap.first.first;
 
  500             node.processor_id() = pmap.first.second;
 
  509   libmesh_parallel_only(
mesh.comm());
 
  511   std::map<std::pair<processor_id_type, processor_id_type>, std::set<dof_id_type>> processor_pair_to_nodes;
 
  515   std::unordered_map<dof_id_type, std::vector<const Elem *>> nodes_to_elem_map;
 
  519   std::vector<const Node *>  neighbors;
 
  520   std::set<dof_id_type> neighbors_order;
 
  521   std::vector<dof_id_type> common_nodes;
 
  522   std::queue<dof_id_type> nodes_queue;
 
  523   std::set<dof_id_type> visted_nodes;
 
  525   for (
auto & pmap : processor_pair_to_nodes)
 
  527       std::size_t n_own_nodes = pmap.second.size()/2;
 
  531         mesh.node_ref(
id).processor_id() = pmap.first.second;
 
  533       visted_nodes.clear();
 
  536           mesh.node_ref(
id).processor_id() = pmap.first.second;
 
  538           if (visted_nodes.find(
id) != visted_nodes.end())
 
  542               nodes_queue.push(
id);
 
  543               visted_nodes.insert(
id);
 
  544               if (visted_nodes.size() >= n_own_nodes)
 
  548           while (!nodes_queue.empty())
 
  550               auto & node = 
mesh.node_ref(nodes_queue.front());
 
  555               neighbors_order.clear();
 
  556               for (
auto & neighbor : neighbors)
 
  557                 neighbors_order.insert(neighbor->id());
 
  559               common_nodes.clear();
 
  560               std::set_intersection(pmap.second.begin(), pmap.second.end(),
 
  561                                     neighbors_order.begin(), neighbors_order.end(),
 
  562                                     std::back_inserter(common_nodes));
 
  564               for (
auto c_node : common_nodes)
 
  565                 if (visted_nodes.find(c_node) == visted_nodes.end())
 
  567                     nodes_queue.push(c_node);
 
  568                     visted_nodes.insert(c_node);
 
  569                     if (visted_nodes.size() >= n_own_nodes)
 
  573               if (visted_nodes.size() >= n_own_nodes)
 
  578       for (
auto node : visted_nodes)
 
  579         mesh.node_ref(node).processor_id() = pmap.first.first;
 
  588   libmesh_parallel_only(
mesh.comm());
 
  590 #if LIBMESH_HAVE_PETSC 
  591   std::map<std::pair<processor_id_type, processor_id_type>, std::set<dof_id_type>> processor_pair_to_nodes;
 
  595   std::vector<std::vector<const Elem *>> nodes_to_elem_map;
 
  599   std::vector<const Node *>  neighbors;
 
  600   std::set<dof_id_type> neighbors_order;
 
  601   std::vector<dof_id_type> common_nodes;
 
  603   std::vector<dof_id_type> rows;
 
  604   std::vector<dof_id_type> cols;
 
  606   std::map<dof_id_type, dof_id_type> global_to_local;
 
  608   for (
auto & pmap : processor_pair_to_nodes)
 
  613       rows.resize(pmap.second.size()+1);
 
  616         global_to_local[id] = i++;
 
  619       for (
auto id : pmap.second)
 
  621           auto & node = 
mesh.node_ref(
id);
 
  624           neighbors_order.clear();
 
  625           for (
auto & neighbor : neighbors)
 
  626             neighbors_order.insert(neighbor->id());
 
  628           common_nodes.clear();
 
  629           std::set_intersection(pmap.second.begin(), pmap.second.end(),
 
  630                                 neighbors_order.begin(), neighbors_order.end(),
 
  631                                 std::back_inserter(common_nodes));
 
  633           rows[i+1] = rows[i] + cast_int<dof_id_type>(common_nodes.size());
 
  635           for (
auto c_node : common_nodes)
 
  636             cols.push_back(global_to_local[c_node]);
 
  642       MatPartitioning part;
 
  644       PetscInt local_size, rows_size, cols_size;
 
  645       PetscInt *adj_i, *adj_j;
 
  646       const PetscInt *indices;
 
  647       PetscCalloc1(rows.size(), &adj_i);
 
  648       PetscCalloc1(cols.size(), &adj_j);
 
  649       rows_size = cast_int<PetscInt>(rows.size());
 
  650       for (PetscInt ii=0; ii<rows_size; ii++)
 
  651         adj_i[ii] = rows[ii];
 
  653       cols_size = cast_int<PetscInt>(cols.size());
 
  654       for (PetscInt ii=0; ii<cols_size; ii++)
 
  655         adj_j[ii] = cols[ii];
 
  657       const PetscInt sz = cast_int<PetscInt>(pmap.second.size());
 
  658       MatCreateMPIAdj(PETSC_COMM_SELF, sz, sz, adj_i, adj_j,
nullptr,&adj);
 
  659       MatPartitioningCreate(PETSC_COMM_SELF,&part);
 
  660       MatPartitioningSetAdjacency(part,adj);
 
  661       MatPartitioningSetNParts(part,2);
 
  662       PetscObjectSetOptionsPrefix((PetscObject)part, 
"balance_");
 
  663       MatPartitioningSetFromOptions(part);
 
  664       MatPartitioningApply(part,&
is);
 
  667       MatPartitioningDestroy(&part);
 
  669       ISGetLocalSize(
is, &local_size);
 
  670       ISGetIndices(
is, &indices);
 
  672       for (
auto id : pmap.second)
 
  674           auto & node = 
mesh.node_ref(
id);
 
  676             node.processor_id() = pmap.first.second;
 
  678             node.processor_id() = pmap.first.first;
 
  682       ISRestoreIndices(
is, &indices);
 
  686   libmesh_error_msg(
"PETSc is required");
 
  693   LOG_SCOPE(
"set_node_processor_ids()",
"Partitioner");
 
  696   libmesh_parallel_only(
mesh.comm());
 
  701                                     mesh.unpartitioned_elements_end()) == 0);
 
  718   std::map<processor_id_type, std::vector<dof_id_type>>
 
  722   std::map<processor_id_type, dof_id_type> ghost_nodes_from_proc;
 
  724   for (
auto & node : 
mesh.node_ptr_range())
 
  728       if (current_pid != 
mesh.processor_id() &&
 
  731           libmesh_assert_less (current_pid, 
mesh.n_processors());
 
  732           ghost_nodes_from_proc[current_pid]++;
 
  738   for (
auto pair : ghost_nodes_from_proc)
 
  739     requested_node_ids[pair.first].reserve(pair.second);
 
  743   for (
auto & node : 
mesh.node_ptr_range())
 
  747       if (current_pid != 
mesh.processor_id() &&
 
  750           libmesh_assert_less (requested_node_ids[current_pid].size(),
 
  751                                ghost_nodes_from_proc[current_pid]);
 
  752           requested_node_ids[current_pid].push_back(node->id());
 
  756       node->invalidate_processor_id();
 
  760   for (
auto & elem : 
mesh.active_element_ptr_range())
 
  767       for (
Node & node : elem->node_ref_range())
 
  770           pid = node.choose_processor_id(pid, elem->processor_id());
 
  774   bool load_balanced_nodes_linear =
 
  777   if (load_balanced_nodes_linear)
 
  780   bool load_balanced_nodes_bfs =
 
  783   if (load_balanced_nodes_bfs)
 
  786   bool load_balanced_nodes_petscpartition =
 
  789   if (load_balanced_nodes_petscpartition)
 
  794   for (
auto & elem : 
as_range(
mesh.subactive_elements_begin(),
 
  795                               mesh.subactive_elements_end()))
 
  801       for (
Node & node : elem->node_ref_range())
 
  803           node.processor_id() = elem->processor_id();
 
  810   for (
auto & elem : 
as_range(
mesh.not_active_elements_begin(),
 
  811                               mesh.not_active_elements_end()))
 
  817       for (
Node & node : elem->node_ref_range())
 
  819           node.processor_id() = elem->processor_id();
 
  831   auto gather_functor =
 
  834      std::vector<processor_id_type> & new_pids)
 
  836       const std::size_t ids_size = ids.size();
 
  837       new_pids.resize(ids_size);
 
  840       for (std::size_t i=0; i != ids_size; ++i)
 
  842           Node & node = 
mesh.node_ref(ids[i]);
 
  850           new_pids[i] = new_pid;                                 
 
  854   auto action_functor =
 
  857      const std::vector<dof_id_type> & ids,
 
  858      const std::vector<processor_id_type> & new_pids)
 
  860       const std::size_t ids_size = ids.size();
 
  862       for (std::size_t i=0; i != ids_size; ++i)
 
  864           Node & node = 
mesh.node_ref(ids[i]);
 
  879   Parallel::pull_parallel_vector_data
 
  880     (
mesh.comm(), requested_node_ids, gather_functor, action_functor, ex);
 
  883   MeshTools::libmesh_assert_valid_procids<Node>(
mesh);
 
  894   typedef std::unordered_map<dof_id_type, dof_id_type> 
map_type;
 
  901                     std::vector<datum> & local_ids)
 const 
  903     local_ids.resize(ids.size());
 
  906       local_ids[i] = 
id_map[ids[i]];
 
  910                     const std::vector<datum> & local_ids)
 
  913       id_map[ids[i]] = local_ids[i];
 
  936                                           mesh.active_local_elements_begin(),
 
  937                                           mesh.active_local_elements_end(),
 
  943       (
mesh.comm(), 
mesh.active_elements_begin(), 
mesh.active_elements_end(), sync);
 
  948       for (
const auto & elem : 
as_range(
mesh.active_pid_elements_begin(pid),
 
  949                                         mesh.active_pid_elements_end(pid)))
 
  962   LOG_SCOPE(
"build_graph()", 
"ParmetisPartitioner");
 
  969   typedef std::unordered_multimap<const Elem *, const Elem *> map_type;
 
  970   map_type interior_to_boundary_map;
 
  972   for (
const auto & elem : 
mesh.active_element_ptr_range())
 
  976       if ((elem->dim() >= LIBMESH_DIM) ||
 
  977           !elem->interior_parent())
 
  981       std::set<const Elem *> neighbor_set;
 
  982       elem->find_interior_neighbors(neighbor_set);
 
  984       for (
const auto & neighbor : neighbor_set)
 
  985         interior_to_boundary_map.insert(std::make_pair(neighbor, elem));
 
  988 #ifdef LIBMESH_ENABLE_AMR 
  989   std::vector<const Elem *> neighbors_offspring;
 
 1006   for (
const auto & elem : 
mesh.active_local_element_ptr_range())
 
 1013         global_index_by_pid - first_local_elem;
 
 1014       libmesh_assert_less (local_index, n_active_local_elem);
 
 1016       std::vector<dof_id_type> & graph_row = 
_dual_graph[local_index];
 
 1023       for (
auto neighbor : elem->neighbor_ptr_range())
 
 1025           if (neighbor != 
nullptr)
 
 1029               if (neighbor->active())
 
 1035                   graph_row.push_back(neighbor_global_index_by_pid);
 
 1038 #ifdef LIBMESH_ENABLE_AMR 
 1047                   const unsigned int ns =
 
 1048                     neighbor->which_neighbor_am_i (elem);
 
 1049                   libmesh_assert_less (ns, neighbor->n_neighbors());
 
 1062                   neighbor->active_family_tree (neighbors_offspring);
 
 1067                   for (
const auto & child : neighbors_offspring)
 
 1072                       if (child->neighbor_ptr(ns) == elem)
 
 1079                           graph_row.push_back(child_global_index_by_pid);
 
 1090       if ((elem->dim() < LIBMESH_DIM) &&
 
 1091           elem->interior_parent())
 
 1094           std::set<const Elem *> neighbor_set;
 
 1095           elem->find_interior_neighbors(neighbor_set);
 
 1097           for (
const auto & neighbor : neighbor_set)
 
 1102               graph_row.push_back(neighbor_global_index_by_pid);
 
 1107       for (
const auto & pr : 
as_range(interior_to_boundary_map.equal_range(elem)))
 
 1109           const Elem * neighbor = pr.second;
 
 1114           graph_row.push_back(neighbor_global_index_by_pid);
 
 1122   LOG_SCOPE(
"assign_partitioning()", 
"ParmetisPartitioner");
 
 1125   libmesh_parallel_only(
mesh.comm());
 
 1135   std::map<processor_id_type, std::vector<dof_id_type>>
 
 1140   std::map<processor_id_type, std::vector<processor_id_type>>
 
 1143   for (
auto & elem : 
mesh.active_element_ptr_range())
 
 1148       requested_ids[elem->processor_id()].push_back(elem->id());
 
 1151   auto gather_functor =
 
 1156      n_active_local_elem,
 
 1160      std::vector<processor_id_type> & 
data)
 
 1162       const std::size_t ids_size = ids.size();
 
 1163       data.resize(ids.size());
 
 1165       for (std::size_t i=0; i != ids_size; i++)
 
 1175             global_index_by_pid - first_local_elem;
 
 1177           libmesh_assert_less (local_index, parts.size());
 
 1178           libmesh_assert_less (local_index, n_active_local_elem);
 
 1181             cast_int<processor_id_type>(parts[local_index]);
 
 1183           libmesh_assert_less (elem_procid, 
mesh.n_partitions());
 
 1185           data[i] = elem_procid;
 
 1189   auto action_functor =
 
 1192      const std::vector<dof_id_type> &,
 
 1193      const std::vector<processor_id_type> & new_procids)
 
 1195       filled_request[pid] = new_procids;
 
 1200   Parallel::pull_parallel_vector_data
 
 1201     (
mesh.comm(), requested_ids, gather_functor, action_functor, ex);
 
 1207   std::vector<unsigned int> counters(
mesh.n_processors(), 0);
 
 1208   for (
auto & elem : 
mesh.active_element_ptr_range())
 
 1212       libmesh_assert_less (counters[current_pid], requested_ids[current_pid].size());
 
 1215         filled_request[current_pid][counters[current_pid]++];
 
 1217       libmesh_assert_less (elem_procid, 
mesh.n_partitions());
 
 1218       elem->processor_id() = elem_procid;