55 template <
typename SparseMatrixType,
56 typename SparsityPatternType,
57 typename SparseMatrixType2,
58 typename SparsityPatternType2>
61 const SparsityPatternType &sparsity_pattern,
63 SparseMatrixType2 &system_matrix_out,
64 SparsityPatternType2 &sparsity_pattern_out);
78 template <
typename SparseMatrixType,
79 typename SparsityPatternType,
80 typename SparseMatrixType2,
81 typename SparsityPatternType2>
84 const SparsityPatternType &sparsity_pattern,
87 SparseMatrixType2 &system_matrix_out,
88 SparsityPatternType2 &sparsity_pattern_out);
107 typename SparseMatrixType,
108 typename SparsityPatternType,
112 const SparsityPatternType &sparsity_pattern,
129 template <
typename SparseMatrixType,
130 typename SparsityPatternType,
134 const SparseMatrixType &sparse_matrix_in,
135 const SparsityPatternType &sparsity_pattern,
136 const std::vector<std::vector<types::global_dof_index>> &indices,
145 template <
typename T>
146 using get_mpi_communicator_t =
147 decltype(std::declval<const T>().get_mpi_communicator());
149 template <
typename T>
150 constexpr bool has_get_mpi_communicator =
151 ::internal::is_supported_operation<get_mpi_communicator_t, T>;
153 template <
typename T>
154 using local_size_t =
decltype(std::declval<const T>().local_size());
156 template <
typename T>
157 constexpr bool has_local_size =
158 ::internal::is_supported_operation<local_size_t, T>;
160 template <
typename SparseMatrixType,
161 std::enable_if_t<has_get_mpi_communicator<SparseMatrixType>,
162 SparseMatrixType> * =
nullptr>
164 get_mpi_communicator(
const SparseMatrixType &sparse_matrix)
166 return sparse_matrix.get_mpi_communicator();
169 template <
typename SparseMatrixType,
170 std::enable_if_t<!has_get_mpi_communicator<SparseMatrixType>,
171 SparseMatrixType> * =
nullptr>
173 get_mpi_communicator(
const SparseMatrixType &sparse_matrix)
176 return MPI_COMM_SELF;
179 template <
typename SparseMatrixType,
180 std::enable_if_t<has_local_size<SparseMatrixType>,
181 SparseMatrixType> * =
nullptr>
183 get_local_size(
const SparseMatrixType &sparse_matrix)
185 return sparse_matrix.local_size();
188 template <
typename SparseMatrixType,
189 std::enable_if_t<!has_local_size<SparseMatrixType>,
190 SparseMatrixType> * =
nullptr>
192 get_local_size(
const SparseMatrixType &sparse_matrix)
196 return sparse_matrix.m();
201 template <
typename Number,
202 typename SparseMatrixType,
203 typename SparsityPatternType>
204 std::vector<std::vector<std::pair<types::global_dof_index, Number>>>
205 extract_remote_rows(
const SparseMatrixType &system_matrix,
206 const SparsityPatternType &sparsity_pattern,
207 const IndexSet &locally_active_dofs,
210 std::vector<unsigned int> dummy(locally_active_dofs.
n_elements());
212 const auto local_size = get_local_size(system_matrix);
213 const auto [prefix_sum, total_sum] =
215 IndexSet locally_owned_dofs(total_sum);
216 locally_owned_dofs.add_range(prefix_sum, prefix_sum + local_size);
218 using T1 = std::vector<
220 std::vector<std::pair<types::global_dof_index, Number>>>>;
228 std::vector<std::vector<std::pair<types::global_dof_index, Number>>>
229 locally_relevant_matrix_entries(locally_active_dofs.
n_elements());
232 std::vector<unsigned int> ranks;
236 ranks.push_back(i.
first);
238 std::vector<std::vector<unsigned int>> row_to_procs(
239 locally_owned_dofs.n_elements());
243 row_to_procs[locally_owned_dofs.index_within_set(
index)].push_back(
246 std::map<unsigned int, T1>
data;
249 std::vector<std::pair<types::global_dof_index, Number>>>
252 for (
unsigned int i = 0; i < row_to_procs.size(); ++i)
254 if (row_to_procs[i].empty())
257 const auto row = locally_owned_dofs.nth_index_in_set(i);
258 auto entry = system_matrix.begin(row);
260 const unsigned int row_length = sparsity_pattern.row_length(row);
263 buffer.second.resize(row_length);
265 for (
unsigned int j = 0; j < row_length; ++j, ++entry)
266 buffer.second[j] = {entry->column(), entry->value()};
268 for (
const auto &proc : row_to_procs[i])
269 data[proc].emplace_back(buffer);
272 ::Utilities::MPI::ConsensusAlgorithms::selector<T1>(
274 [&](
const unsigned int other_rank) {
return data[other_rank]; },
275 [&](
const unsigned int &,
const T1 &buffer_recv) {
276 for (
const auto &i : buffer_recv)
279 locally_relevant_matrix_entries[locally_active_dofs
282 std::sort(dst.begin(),
284 [](
const auto &a,
const auto &b) {
285 return a.first < b.first;
291 return locally_relevant_matrix_entries;
297 template <
typename SparseMatrixType,
298 typename SparsityPatternType,
299 typename SparseMatrixType2,
300 typename SparsityPatternType2>
303 const SparsityPatternType &sparsity_pattern,
306 SparseMatrixType2 &system_matrix_out,
307 SparsityPatternType2 &sparsity_pattern_out)
312 auto index_set_1_cleared = index_set_1;
313 if (index_set_1.
size() != 0)
316 const auto index_within_set = [&index_set_0,
317 &index_set_1_cleared](
const auto n) {
322 index_set_1_cleared.index_within_set(n);
326 auto index_set_union = index_set_0;
328 if (index_set_1.
size() != 0)
333 const auto locally_relevant_matrix_entries =
334 internal::extract_remote_rows<typename SparseMatrixType2::value_type>(
338 internal::get_mpi_communicator(system_matrix));
342 const unsigned int n_rows = index_set_union.n_elements();
343 const unsigned int n_cols = index_set_union.n_elements();
344 const unsigned int entries_per_row =
345 locally_relevant_matrix_entries.empty() ?
347 std::max_element(locally_relevant_matrix_entries.begin(),
348 locally_relevant_matrix_entries.end(),
349 [](
const auto &a,
const auto &b) {
350 return a.size() < b.size();
354 sparsity_pattern_out.reinit(n_rows, n_cols, entries_per_row);
356 std::vector<types::global_dof_index> temp_indices;
357 std::vector<typename SparseMatrixType2::value_type> temp_values;
359 for (
unsigned int row = 0; row < index_set_union.n_elements(); ++row)
361 const auto &global_row_entries = locally_relevant_matrix_entries[row];
363 temp_indices.clear();
364 temp_indices.reserve(global_row_entries.size());
366 for (
const auto &global_row_entry : global_row_entries)
368 const auto global_index = std::get<0>(global_row_entry);
370 if (index_set_union.is_element(global_index))
371 temp_indices.push_back(index_within_set(global_index));
374 sparsity_pattern_out.add_entries(
375 index_within_set(index_set_union.nth_index_in_set(row)),
376 temp_indices.begin(),
380 sparsity_pattern_out.compress();
383 system_matrix_out.reinit(sparsity_pattern_out);
386 for (
unsigned int row = 0; row < index_set_union.n_elements(); ++row)
388 const auto &global_row_entries = locally_relevant_matrix_entries[row];
390 temp_indices.clear();
393 temp_indices.reserve(global_row_entries.size());
394 temp_values.reserve(global_row_entries.size());
396 for (
const auto &global_row_entry : global_row_entries)
398 const auto global_index = std::get<0>(global_row_entry);
400 if (index_set_union.is_element(global_index))
402 temp_indices.push_back(index_within_set(global_index));
403 temp_values.push_back(std::get<1>(global_row_entry));
407 system_matrix_out.add(index_within_set(
408 index_set_union.nth_index_in_set(row)),
418 template <
typename SparseMatrixType,
419 typename SparsityPatternType,
420 typename SparseMatrixType2,
421 typename SparsityPatternType2>
424 const SparsityPatternType &sparsity_pattern,
426 SparseMatrixType2 &system_matrix_out,
427 SparsityPatternType2 &sparsity_pattern_out)
434 sparsity_pattern_out);
439 template <
typename SparseMatrixType,
440 typename SparsityPatternType,
444 const SparseMatrixType &system_matrix,
445 const SparsityPatternType &sparsity_pattern,
446 const std::vector<std::vector<types::global_dof_index>> &indices,
450 const auto local_size = internal::get_local_size(system_matrix);
452 local_size, internal::get_mpi_communicator(system_matrix));
453 IndexSet locally_owned_dofs(std::get<1>(prefix_sum));
454 locally_owned_dofs.add_range(std::get<0>(prefix_sum),
455 std::get<0>(prefix_sum) + local_size);
457 std::vector<::types::global_dof_index> ghost_indices_vector;
459 for (
const auto &i : indices)
460 ghost_indices_vector.
insert(ghost_indices_vector.
end(),
464 std::sort(ghost_indices_vector.begin(), ghost_indices_vector.end());
466 IndexSet locally_active_dofs(std::get<1>(prefix_sum));
467 locally_active_dofs.
add_indices(ghost_indices_vector.begin(),
468 ghost_indices_vector.end());
473 const auto locally_relevant_matrix_entries =
474 internal::extract_remote_rows<Number>(system_matrix,
477 internal::get_mpi_communicator(
483 blocks.resize(indices.size());
485 for (
unsigned int c = 0; c < indices.size(); ++c)
487 if (indices[c].empty())
490 const auto &local_dof_indices = indices[c];
494 const unsigned int dofs_per_cell = indices[c].size();
501 for (
unsigned int i = 0; i < dofs_per_cell; ++i)
502 for (
unsigned int j = 0; j < dofs_per_cell; ++j)
504 if (locally_owned_dofs.is_element(
505 local_dof_indices[i]))
508 sparsity_pattern.exists(local_dof_indices[i],
509 local_dof_indices[j]) ?
510 system_matrix(local_dof_indices[i],
511 local_dof_indices[j]) :
519 const auto &row_entries =
520 locally_relevant_matrix_entries[locally_active_dofs
522 local_dof_indices[i])];
525 std::lower_bound(row_entries.begin(),
527 std::pair<types::global_dof_index, Number>{
528 local_dof_indices[j], 0.0},
529 [](
const auto a,
const auto b) {
530 return a.first < b.first;
533 if (ptr != row_entries.end() &&
534 local_dof_indices[j] == ptr->first)
547 typename SparseMatrixType,
548 typename SparsityPatternType,
552 const SparsityPatternType &sparsity_pattern,
556 std::vector<std::vector<types::global_dof_index>> all_dof_indices;
559 for (
const auto &cell : dof_handler.active_cell_iterators())
561 if (cell->is_locally_owned() ==
false)
564 auto &local_dof_indices = all_dof_indices[cell->active_cell_index()];
565 local_dof_indices.resize(cell->get_fe().n_dofs_per_cell());
566 cell->get_dof_indices(local_dof_indices);