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;