deal.II version 9.8.0
\(\newcommand{\dealvcentcolon}{\mathrel{\mathop{:}}}\) \(\newcommand{\dealcoloneq}{\dealvcentcolon\mathrel{\mkern-1.2mu}=}\) \(\newcommand{\jump}[1]{\left[\!\left[ #1 \right]\!\right]}\) \(\newcommand{\average}[1]{\left\{\!\left\{ #1 \right\}\!\right\}}\)
Loading...
Searching...
No Matches
repartitioning_policy_tools.cc
Go to the documentation of this file.
1// -----------------------------------------------------------------------------
2//
3// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception OR LGPL-2.1-or-later
4// Copyright (C) 2021 - 2025 by the deal.II authors
5//
6// This file is part of the deal.II library.
7//
8// Detailed license information governing the source code and contributions
9// can be found in LICENSE.md and CONTRIBUTING.md at the top level directory.
10//
11// -----------------------------------------------------------------------------
12
13
14#include <deal.II/base/mpi.h>
15
18
21
23
24
26{
27 namespace
28 {
29 template <int dim, int spacedim>
30 void
31 add_indices_recursively_for_first_child_policy(
32 const TriaIterator<CellAccessor<dim, spacedim>> &cell,
33 const internal::CellIDTranslator<dim> &cell_id_translator,
34 IndexSet &is_fine)
35 {
36 is_fine.add_index(cell_id_translator.translate(cell));
37
38 if (cell->level() > 0 && cell->parent()->child(0) == cell)
39 add_indices_recursively_for_first_child_policy(cell->parent(),
40 cell_id_translator,
41 is_fine);
42 }
43 } // namespace
44
45
46 template <int dim, int spacedim>
50
51 template <int dim, int spacedim>
54 const Triangulation<dim, spacedim> &tria_in) const
55 {
56 if (tighten == false)
57 return {}; // nothing to do
58
59 const auto tria =
61 &tria_in);
62
63 if (tria == nullptr)
64 return {}; // nothing to do, since serial triangulation
65
66#ifndef DEAL_II_WITH_MPI
67 Assert(false, ExcNeedsMPI());
68 return {};
69#else
70
71 const auto comm = tria->get_mpi_communicator();
72
73 const unsigned int process_has_active_locally_owned_cells =
74 tria->n_locally_owned_active_cells() > 0;
75 const unsigned int n_processes_with_active_locally_owned_cells =
76 Utilities::MPI::sum(process_has_active_locally_owned_cells, comm);
77
78 if (n_processes_with_active_locally_owned_cells ==
80 return {}; // nothing to do, since all processes have cells
81
82 unsigned int offset = 0;
83
84 const int ierr =
85 MPI_Exscan(&process_has_active_locally_owned_cells,
86 &offset,
87 1,
89 decltype(process_has_active_locally_owned_cells)>,
90 MPI_SUM,
91 comm);
92 AssertThrowMPI(ierr);
93
95 tria->global_active_cell_index_partitioner().lock());
96
97 partition = offset;
98
99 return partition;
100#endif
101 }
102
103
104
105 template <int dim, int spacedim>
107 const Triangulation<dim, spacedim> &tria_fine)
108 : cell_id_translator(tria_fine)
109 {
110 Assert(
113 "FirstChildPolicy is only working for pure hex meshes at the moment."));
114
116 for (const auto &cell : tria_fine.active_cell_iterators())
117 if (cell->is_locally_owned())
118 add_indices_recursively_for_first_child_policy(cell,
121 }
122
123
124
125 template <int dim, int spacedim>
128 const Triangulation<dim, spacedim> &tria_coarse_in) const
129 {
130 const auto communicator = tria_coarse_in.get_mpi_communicator();
131
132 IndexSet is_coarse(cell_id_translator.size());
133 for (const auto &cell : tria_coarse_in.active_cell_iterators())
134 if (cell->is_locally_owned())
135 is_coarse.add_index(cell_id_translator.translate(cell));
136
137 const std::vector<unsigned int> owning_ranks_of_coarse_cells =
139 is_coarse,
140 communicator);
141
142 const auto tria =
143 dynamic_cast<const parallel::TriangulationBase<dim, spacedim> *>(
144 &tria_coarse_in);
145 Assert(tria, ExcNotImplemented());
146
148 tria->global_active_cell_index_partitioner().lock());
149
150 for (const auto &cell : tria_coarse_in.active_cell_iterators() |
152 partition[cell->global_active_cell_index()] =
153 owning_ranks_of_coarse_cells[is_coarse.index_within_set(
154 cell_id_translator.translate(cell))];
155
156 return partition;
157 }
158
159
160 template <int dim, int spacedim>
165
166
167
168 template <int dim, int spacedim>
171 const Triangulation<dim, spacedim> &tria_in) const
172 {
173 const auto tria =
174 dynamic_cast<const parallel::TriangulationBase<dim, spacedim> *>(
175 &tria_in);
176
177 Assert(tria, ExcNotImplemented());
178
180 tria->global_active_cell_index_partitioner().lock());
181
182 // step 1) check if all processes have enough cells
183
184 const unsigned int n_locally_owned_active_cells =
185 std::count_if(tria_in.begin_active(),
187 tria_in.end()),
188 [](const auto &cell) { return cell.is_locally_owned(); });
189
190 const auto comm = tria_in.get_mpi_communicator();
191
192 if (Utilities::MPI::min(n_locally_owned_active_cells, comm) >= n_min_cells)
193 return {}; // all processes have enough cells
194
195 // step 2) there are processes which do not have enough cells so that
196 // a repartitioning kicks in with the aim that all processes that own
197 // cells have at least the specified number of cells
198
199 const types::global_cell_index n_global_active_cells =
200 tria_in.n_global_active_cells();
201
202 const unsigned int n_partitions =
205 n_global_active_cells / n_min_cells,
207
208 const unsigned int min_cells = n_global_active_cells / n_partitions;
209
210 const auto convert = [&](const unsigned int i) {
211 // determine the owner of a given index: we try to assign each process
212 // the same number of cells; if there is a remainder, we assign the
213 // first processes an additional cell (so that the difference of number of
214 // locally owned cells is never larger than one between processes).
215 const unsigned int n_partitions_with_additional_cell =
216 n_global_active_cells - min_cells * n_partitions;
217
218 const unsigned int rank =
219 (i < (min_cells + 1) * n_partitions_with_additional_cell) ?
220 (i / (min_cells + 1)) :
221 ((i - n_partitions_with_additional_cell) / min_cells);
222
223 AssertIndexRange(rank, n_partitions);
224
225 return rank;
226 };
227
228 for (const auto i : partition.locally_owned_elements())
229 partition[i] = convert(i);
230
231 return partition;
232 }
233
234
235
236 template <int dim, int spacedim>
243
244
245
246 template <int dim, int spacedim>
249 const Triangulation<dim, spacedim> &tria_in) const
250 {
251#ifndef DEAL_II_WITH_MPI
252 (void)tria_in;
253 return {};
254#else
255
256 const auto tria =
257 dynamic_cast<const parallel::TriangulationBase<dim, spacedim> *>(
258 &tria_in);
259
260 Assert(tria, ExcNotImplemented());
261
262 const auto partitioner =
263 tria->global_active_cell_index_partitioner().lock();
264
265 std::vector<unsigned int> weights(partitioner->locally_owned_size());
266
267 const auto mpi_communicator = tria_in.get_mpi_communicator();
268 const auto n_subdomains = Utilities::MPI::n_mpi_processes(mpi_communicator);
269
270 // determine weight of each cell
271 for (const auto &cell :
272 tria->active_cell_iterators() | IteratorFilters::LocallyOwnedCell())
273 weights[partitioner->global_to_local(cell->global_active_cell_index())] =
275
276 // determine weight of all the cells locally owned by this process
277 std::uint64_t process_local_weight = 0;
278 for (const auto &weight : weights)
279 process_local_weight += weight;
280
281 // determine partial sum of weights of this process, as well as the total
282 // weight
283 const auto [process_local_weight_offset, total_weight] =
284 Utilities::MPI::partial_and_total_sum(process_local_weight,
285 tria->get_mpi_communicator());
286
287 // set up partition
289
290 for (std::uint64_t i = 0, weight = process_local_weight_offset;
291 i < partition.locally_owned_size();
292 weight += weights[i], ++i)
293 partition.local_element(i) =
294 static_cast<double>(weight * n_subdomains / total_weight);
295
296 return partition;
297#endif
298 }
299
300
301} // namespace RepartitioningPolicyTools
302
303
304
305/*-------------- Explicit Instantiations -------------------------------*/
306#include "distributed/repartitioning_policy_tools.inst"
307
CellStatus
Definition cell_status.h:29
@ cell_will_persist
Definition cell_status.h:34
size_type index_within_set(const size_type global_index) const
Definition index_set.h:2001
void add_index(const size_type index)
Definition index_set.h:1802
virtual LinearAlgebra::distributed::Vector< double > partition(const Triangulation< dim, spacedim > &tria_in) const override
const std::function< unsigned int(const typename Triangulation< dim, spacedim >::cell_iterator &, const CellStatus)> weighting_function
CellWeightPolicy(const std::function< unsigned int(const typename Triangulation< dim, spacedim >::cell_iterator &, const CellStatus)> &weighting_function)
virtual LinearAlgebra::distributed::Vector< double > partition(const Triangulation< dim, spacedim > &tria_coarse_in) const override
virtual LinearAlgebra::distributed::Vector< double > partition(const Triangulation< dim, spacedim > &tria_coarse_in) const override
FirstChildPolicy(const Triangulation< dim, spacedim > &tria_fine)
virtual LinearAlgebra::distributed::Vector< double > partition(const Triangulation< dim, spacedim > &tria_in) const override
virtual types::global_cell_index n_global_active_cells() const
bool all_reference_cells_are_hyper_cube() const
virtual MPI_Comm get_mpi_communicator() const
cell_iterator end() const
active_cell_iterator begin_active(const unsigned int level=0) const
types::global_cell_index translate(const TriaIterator< Accessor > &cell) const
#define DEAL_II_NAMESPACE_OPEN
Definition config.h:38
#define DEAL_II_NAMESPACE_CLOSE
Definition config.h:39
IteratorRange< active_cell_iterator > active_cell_iterators() const
static ::ExceptionBase & ExcNotImplemented()
static ::ExceptionBase & ExcNeedsMPI()
#define Assert(cond, exc)
#define AssertThrowMPI(error_code)
#define AssertIndexRange(index, range)
static ::ExceptionBase & ExcMessage(std::string arg1)
TriaActiveIterator< CellAccessor< dim, spacedim > > active_cell_iterator
Definition tria.h:1648
TriaIterator< CellAccessor< dim, spacedim > > cell_iterator
Definition tria.h:1624
std::pair< T, T > partial_and_total_sum(const T &value, const MPI_Comm comm)
T sum(const T &t, const MPI_Comm mpi_communicator)
unsigned int n_mpi_processes(const MPI_Comm mpi_communicator)
Definition mpi.cc:103
T min(const T &t, const MPI_Comm mpi_communicator)
std::vector< unsigned int > compute_index_owner(const IndexSet &owned_indices, const IndexSet &indices_to_look_up, const MPI_Comm comm)
Definition mpi.cc:1820
const MPI_Datatype mpi_type_id_for_type
Definition mpi.h:1682
::VectorizedArray< Number, width > min(const ::VectorizedArray< Number, width > &, const ::VectorizedArray< Number, width > &)
::VectorizedArray< Number, width > max(const ::VectorizedArray< Number, width > &, const ::VectorizedArray< Number, width > &)
unsigned int global_cell_index
Definition types.h:136
*braid_SplitCommworld & comm