deal.II version GIT relicensing-2289-g1e5549a87a 2024-12-21 21:30:00+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: LGPL-2.1-or-later
4// Copyright (C) 2020 - 2023 by the deal.II authors
5//
6// This file is part of the deal.II library.
7//
8// Part of the source code is dual licensed under Apache-2.0 WITH
9// LLVM-exception OR LGPL-2.1-or-later. Detailed license information
10// governing the source code and code contributions can be found in
11// LICENSE.md and CONTRIBUTING.md at the top level directory of deal.II.
12//
13// ------------------------------------------------------------------------
14
17#include <deal.II/base/mpi_noncontiguous_partitioner.templates.h>
18
20
21#include <boost/serialization/utility.hpp>
22
23
25
26namespace Utilities
27{
28 namespace MPI
29 {
31 const IndexSet &indexset_has,
32 const IndexSet &indexset_want,
33 const MPI_Comm communicator)
34 {
35 this->reinit(indexset_has, indexset_want, communicator);
36 }
37
38
39
41 const std::vector<types::global_dof_index> &indices_has,
42 const std::vector<types::global_dof_index> &indices_want,
43 const MPI_Comm communicator)
44 {
45 this->reinit(indices_has, indices_want, communicator);
46 }
47
48
49
50 std::pair<unsigned int, unsigned int>
52 {
53 return {send_ranks.size(), recv_ranks.size()};
54 }
55
56
57
58 unsigned int
63
64
65
78
79
80
86
87
88
89 void
91 const IndexSet &indexset_want,
92 const MPI_Comm communicator)
93 {
94 this->communicator = communicator;
95
96 // clean up
97 send_ranks.clear();
98 send_ptr.clear();
99 send_indices.clear();
100 recv_ranks.clear();
101 recv_ptr.clear();
102 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<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])] = i;
225
226 for (auto &i : recv_indices)
227 i = temp_map_recv[i];
228 }
229 }
230 } // namespace MPI
231} // namespace Utilities
232
233#include "mpi_noncontiguous_partitioner.inst"
234
size_type index_within_set(const size_type global_index) const
Definition index_set.h:2001
size_type n_elements() const
Definition index_set.h:1934
void add_indices(const ForwardIterator &begin, const ForwardIterator &end)
Definition index_set.h:1831
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:498
#define DEAL_II_NAMESPACE_CLOSE
Definition config.h:499
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:1860
T max(const T &t, const MPI_Comm mpi_communicator)
const types::global_dof_index invalid_dof_index
Definition types.h:252
::VectorizedArray< Number, width > max(const ::VectorizedArray< Number, width > &, const ::VectorizedArray< Number, width > &)