deal.II version GIT relicensing-6834-g5b78e6bcdf 2026-10-01 11:20:01+00:00
\(\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
mpi_noncontiguous_partitioner.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) 2020 - 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
15#include <deal.II/base/mpi_noncontiguous_partitioner.templates.h>
16
18
19#include <boost/serialization/utility.hpp>
20
21
23
24namespace Utilities
25{
26 namespace MPI
27 {
29 const IndexSet &indexset_has,
30 const IndexSet &indexset_want,
31 const MPI_Comm communicator)
32 {
33 this->reinit(indexset_has, indexset_want, communicator);
34 }
35
36
37
39 const std::vector<types::global_dof_index> &indices_has,
40 const std::vector<types::global_dof_index> &indices_want,
41 const MPI_Comm communicator)
42 {
43 this->reinit(indices_has, indices_want, communicator);
44 }
45
46
47
48 std::pair<unsigned int, unsigned int>
50 {
51 return {send_ranks.size(), recv_ranks.size()};
52 }
53
54
55
56 unsigned int
61
62
63
76
77
78
84
85
86
87 void
89 const IndexSet &indexset_want,
90 const MPI_Comm communicator)
91 {
92 this->communicator = communicator;
93
94 // clean up
95 send_ranks.clear();
96 send_ptr.clear();
97 send_indices.clear();
98 recv_ranks.clear();
99 recv_ptr.clear();
100 recv_indices.clear();
103 buffers.clear();
104 requests.clear();
105
106 // set up communication pattern
107 const auto [owning_ranks_of_ghosts, targets_with_indexset] =
109 indexset_want,
111
112 // set up map of processes from where this rank will receive values
113 {
114 std::map<unsigned int, std::vector<types::global_dof_index>> recv_map;
115
116 for (const auto &owner : owning_ranks_of_ghosts)
117 recv_map[owner] = std::vector<types::global_dof_index>();
118
119 for (types::global_dof_index i = 0; i < owning_ranks_of_ghosts.size();
120 i++)
121 recv_map[owning_ranks_of_ghosts[i]].push_back(i);
122
123 recv_ptr.push_back(recv_indices.size() /*=0*/);
124 for (const auto &target_with_indexset : recv_map)
125 {
126 recv_ranks.push_back(target_with_indexset.first);
127
128 for (const auto cell_index : target_with_indexset.second)
129 recv_indices.push_back(cell_index);
130
131 recv_ptr.push_back(recv_indices.size());
132 }
133 }
134
135 {
136 send_ptr.push_back(recv_ptr.back());
137 for (const auto &target_with_indexset : targets_with_indexset)
138 {
139 send_ranks.push_back(target_with_indexset.first);
140
141 for (const auto cell_index : target_with_indexset.second)
142 send_indices.push_back(indexset_has.index_within_set(cell_index));
143
144 send_ptr.push_back(send_indices.size() + recv_ptr.back());
145 }
146 }
147 }
148
149
150
151 void
153 const std::vector<types::global_dof_index> &indices_has,
154 const std::vector<types::global_dof_index> &indices_want,
155 const MPI_Comm communicator)
156 {
157 // step 0) clean vectors from numbers::invalid_dof_index (indicating
158 // padding)
159 std::vector<types::global_dof_index> indices_has_clean;
160 indices_has_clean.reserve(indices_has.size());
161
162 for (const auto i : indices_has)
164 indices_has_clean.push_back(i);
165
166 std::vector<types::global_dof_index> indices_want_clean;
167 indices_want_clean.reserve(indices_want.size());
168
169 for (const auto i : indices_want)
171 indices_want_clean.push_back(i);
172
173 // step 0) determine "number of degrees of freedom" needed for IndexSet
174 const types::global_dof_index local_n_dofs_has =
175 indices_has_clean.empty() ?
176 0 :
177 (*std::max_element(indices_has_clean.begin(),
178 indices_has_clean.end()) +
179 1);
180
181 const types::global_dof_index local_n_dofs_want =
182 indices_want_clean.empty() ?
183 0 :
184 (*std::max_element(indices_want_clean.begin(),
185 indices_want_clean.end()) +
186 1);
187
188 const types::global_dof_index n_dofs =
189 Utilities::MPI::max(std::max(local_n_dofs_has, local_n_dofs_want),
191
192 // step 1) convert vectors to indexsets (sorted!)
193 IndexSet index_set_has(n_dofs);
194 index_set_has.add_indices(indices_has_clean.begin(),
195 indices_has_clean.end());
196
197 IndexSet index_set_want(n_dofs);
198 index_set_want.add_indices(indices_want_clean.begin(),
199 indices_want_clean.end());
200
201 // step 2) set up internal data structures with indexset
202 this->reinit(index_set_has, index_set_want, communicator);
203
204 // step 3) fix inner data structures so that it is sorted as
205 // in the original vector
206 {
207 std::vector<types::global_dof_index> temp_map_send(
208 index_set_has.n_elements());
209
210 for (types::global_dof_index i = 0; i < indices_has.size(); ++i)
211 if (indices_has[i] != numbers::invalid_dof_index)
212 temp_map_send[index_set_has.index_within_set(indices_has[i])] = i;
213
214 for (auto &i : send_indices)
215 i = temp_map_send[i];
216 }
217
218 {
219 std::vector<std::vector<types::global_dof_index>> temp_map_recv(
220 index_set_want.n_elements());
221
222 for (types::global_dof_index i = 0; i < indices_want.size(); ++i)
223 if (indices_want[i] != numbers::invalid_dof_index)
224 temp_map_recv[index_set_want.index_within_set(indices_want[i])]
225 .push_back(i);
226
227 const bool use_fast_path =
228 std::all_of(temp_map_recv.begin(),
229 temp_map_recv.end(),
230 [&](const auto &x) { return x.size() == 1; });
231
232 if (use_fast_path)
233 {
234 for (auto &i : recv_indices)
235 i = temp_map_recv[i][0];
236 }
237 else
238 {
240
241 for (const auto &indices : temp_map_recv)
242 {
243 for (const auto &index : indices)
244 recv_indices_duplicates.emplace_back(index);
245
248 }
249 }
250 }
251 }
252 } // namespace MPI
253} // namespace Utilities
254
255#include "base/mpi_noncontiguous_partitioner.inst"
256
***mech_lbc_system increment_interpolation_handlers push_back(scale_z_handler)
size_type index_within_set(const size_type global_index) const
Definition index_set.h:1977
size_type n_elements() const
Definition index_set.h:1917
void add_indices(const ForwardIterator &begin, const ForwardIterator &end)
Definition index_set.h:1814
void reinit(const IndexSet &locally_owned_indices, const IndexSet &ghost_indices, const MPI_Comm communicator) override
std::vector< types::global_dof_index > recv_ptr
std::vector< types::global_dof_index > send_ptr
std::vector< types::global_dof_index > recv_indices
std::pair< unsigned int, unsigned int > n_targets() const
std::vector< types::global_dof_index > send_indices
#define DEAL_II_NAMESPACE_OPEN
Definition config.h:38
#define DEAL_II_NAMESPACE_CLOSE
Definition config.h:39
unsigned int cell_index
std::enable_if_t< std::is_fundamental_v< T >, std::size_t > memory_consumption(const T &t)
std::pair< std::vector< unsigned int >, std::map< unsigned int, IndexSet > > compute_index_owner_and_requesters(const IndexSet &owned_indices, const IndexSet &indices_to_look_up, const MPI_Comm &comm)
Definition mpi.cc:1871
T max(const T &t, const MPI_Comm mpi_communicator)
constexpr types::global_dof_index invalid_dof_index
Definition types.h:259
::VectorizedArray< Number, width > max(const ::VectorizedArray< Number, width > &, const ::VectorizedArray< Number, width > &)