115 dof_id_type num_edges, num_local_elems, local_elem_id, nj, side;
116 std::vector<dof_id_type> side_weights;
117 std::vector<dof_id_type> elem_weights;
124 std::sort(row.begin(), row.end());
126 elem_weights.clear();
128 elem_weights.resize(num_local_elems);
132 for (dof_id_type k = 0; k < num_local_elems; k++)
139 "Local element id " << k <<
" is not smaller than " <<
_local_id_to_elem.size());
146 side_weights.clear();
149 side_weights.resize(num_edges);
155 bool has_non_face_links = !
mesh.get_constraint_rows().empty();
156 for (
const auto *
const elem :
mesh.active_local_element_ptr_range())
158 if (elem->interior_parent())
159 has_non_face_links =
true;
160 for (
const auto *
const neighbor : elem->neighbor_ptr_range())
161 if (neighbor && !neighbor->active())
162 has_non_face_links =
true;
163 if (has_non_face_links)
166 comm().
max(has_non_face_links);
170 std::map<dof_id_type, dof_id_type> global_index_to_weight;
174 "Local element id " << local_elem_id <<
" is not smaller than "
176 global_index_to_weight.clear();
178 unsigned int n_neighbors = 0;
181 for (
auto neighbor : elem->neighbor_ptr_range())
185 if (neighbor !=
nullptr && neighbor->active())
196 unsigned int n_face_neighbors = 0;
197 for (
const auto global_index : row)
199 const auto it = global_index_to_weight.find(global_index);
200 const bool is_face_neighbor = it != global_index_to_weight.end();
201 if (is_face_neighbor)
206 side_weights[nj++] = is_face_neighbor ? it->second : 1;
208 if (n_face_neighbors != n_neighbors || (!has_non_face_links && row.size() != n_neighbors))
210 "Cannot construct dual graph correctly since the number of neighbors is inconsistent");
231 const std::vector<std::vector<dof_id_type>> & graph,
232 const std::vector<dof_id_type> & elem_weights,
233 const std::vector<dof_id_type> & side_weights,
234 const dof_id_type num_parts,
235 const dof_id_type num_parts_per_compute_node,
236 const std::string & part_package,
237 std::vector<dof_id_type> & partition)
240 PetscInt num_local_elems, num_elems, *xadj =
nullptr, *adjncy =
nullptr, i, *
values =
nullptr,
241 *petsc_elem_weights =
nullptr;
242 const PetscInt * parts;
243 MatPartitioning part;
247 num_elems = num_local_elems = graph.size();
251 LibmeshPetscCallA(
comm.
get(), PetscCalloc1(num_local_elems + 1, &xadj));
255 for (
auto & row : graph)
258 xadj[num_local_elems] = xadj[num_local_elems - 1] + row.size();
261 LibmeshPetscCallA(
comm.
get(), PetscCalloc1(xadj[num_local_elems], &adjncy));
265 for (
auto & row : graph)
266 for (
const auto elem : row)
272 mooseAssert(!side_weights.size(),
273 "No side weights should be provided since there are no neighbors at all");
282 bool use_side_weights = !side_weights.empty();
291 if (use_side_weights)
293 mooseAssert((PetscInt)side_weights.size() == i,
294 "Side weight size " << side_weights.size()
295 <<
" does not match with adjacency matrix size " << i);
297 PetscCalloc1(std::max<std::size_t>(side_weights.size(), 1), &
values));
299 for (
auto weight : side_weights)
305 MatCreateMPIAdj(
comm.
get(), num_local_elems, num_elems, xadj, adjncy,
values, &dual));
307 LibmeshPetscCallA(
comm.
get(), MatPartitioningCreate(
comm.
get(), &part));
308 if (use_side_weights)
311 LibmeshPetscCallA(
comm.
get(), MatPartitioningSetUseEdgeWeights(part, PETSC_TRUE));
312 LibmeshPetscCallA(
comm.
get(), MatPartitioningSetAdjacency(part, dual));
314 if (!num_local_elems)
315 mooseAssert(!elem_weights.size(),
316 "No element weights should be provided since there are no elements at all");
319 bool use_elem_weights = !elem_weights.empty();
323 if (use_elem_weights)
325 mooseAssert((PetscInt)elem_weights.size() == num_local_elems,
326 "Element weight size " << elem_weights.size()
327 <<
" does not match with the number of local elements"
332 PetscCalloc1(std::max<std::size_t>(elem_weights.size(), 1), &petsc_elem_weights));
334 for (
auto weight : elem_weights)
335 petsc_elem_weights[i++] = weight;
337 LibmeshPetscCallA(
comm.
get(), MatPartitioningSetVertexWeights(part, petsc_elem_weights));
340 LibmeshPetscCallA(
comm.
get(), MatPartitioningSetNParts(part, num_parts));
341 mooseAssert(part_package !=
"party",
"PETSc-3.9.3 or higher is required for using party");
342 mooseAssert(part_package !=
"chaco",
"PETSc-3.9.0 or higher is required for using chaco");
343 LibmeshPetscCallA(
comm.
get(), MatPartitioningSetType(part, part_package.c_str()));
344 if (part_package ==
"hierarch")
346 MatPartitioningHierarchicalSetNfineparts(part, num_parts_per_compute_node));
348 LibmeshPetscCallA(
comm.
get(), MatPartitioningSetFromOptions(part));
349 LibmeshPetscCallA(
comm.
get(), MatPartitioningApply(part, &is));
351 LibmeshPetscCallA(
comm.
get(), ISGetIndices(is, &parts));
354 for (i = 0; i < num_local_elems; i++)
357 LibmeshPetscCallA(
comm.
get(), ISRestoreIndices(is, &parts));
358 LibmeshPetscCallA(
comm.
get(), MatPartitioningDestroy(&part));
359 LibmeshPetscCallA(
comm.
get(), MatDestroy(&dual));
360 LibmeshPetscCallA(
comm.
get(), ISDestroy(&is));
static void partitionGraph(const Parallel::Communicator &comm, const std::vector< std::vector< dof_id_type > > &graph, const std::vector< dof_id_type > &elem_weights, const std::vector< dof_id_type > &side_weights, const dof_id_type num_parts, const dof_id_type num_parts_per_compute_node, const std::string &part_package, std::vector< dof_id_type > &partition)