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 =
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 =
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);
219 process(locally_owned_dofs, locally_active_dofs,
comm, dummy,
true);
223 std::pair<types::global_dof_index, types::global_dof_index>>,
224 std::vector<unsigned int>>
226 consensus_algorithm.
run(process,
comm);
228 using T1 = std::vector<
230 std::vector<std::pair<types::global_dof_index, Number>>>>;
232 auto requesters = process.get_requesters();
234 std::vector<std::vector<std::pair<types::global_dof_index, Number>>>
235 locally_relevant_matrix_entries(locally_active_dofs.
n_elements());
238 std::vector<unsigned int> ranks;
239 ranks.reserve(requesters.size());
241 for (
const auto &i : requesters)
242 ranks.push_back(i.
first);
244 std::vector<std::vector<unsigned int>> row_to_procs(
245 locally_owned_dofs.n_elements());
247 for (
const auto &requester : requesters)
249 row_to_procs[locally_owned_dofs.index_within_set(
index)].push_back(
252 std::map<unsigned int, T1> data;
255 std::vector<std::pair<types::global_dof_index, Number>>>
258 for (
unsigned int i = 0; i < row_to_procs.size(); ++i)
260 if (row_to_procs[i].empty())
263 const auto row = locally_owned_dofs.nth_index_in_set(i);
264 auto entry = system_matrix.begin(row);
266 const unsigned int row_length = sparsity_pattern.row_length(row);
269 buffer.second.resize(row_length);
271 for (
unsigned int j = 0; j < row_length; ++j, ++entry)
272 buffer.second[j] = {entry->column(), entry->value()};
274 for (
const auto &proc : row_to_procs[i])
275 data[proc].emplace_back(buffer);
280 [&](
const unsigned int other_rank) {
return data[other_rank]; },
281 [&](
const unsigned int &,
const T1 &buffer_recv) {
282 for (
const auto &i : buffer_recv)
285 locally_relevant_matrix_entries[locally_active_dofs
288 std::sort(dst.begin(),
290 [](
const auto &a,
const auto &b) {
291 return a.first < b.first;
297 return locally_relevant_matrix_entries;
303 template <
typename SparseMatrixType,
304 typename SparsityPatternType,
305 typename SparseMatrixType2,
306 typename SparsityPatternType2>
309 const SparsityPatternType &sparsity_pattern,
312 SparseMatrixType2 &system_matrix_out,
313 SparsityPatternType2 &sparsity_pattern_out)
318 auto index_set_1_cleared = index_set_1;
319 if (index_set_1.
size() != 0)
322 const auto index_within_set = [&index_set_0,
323 &index_set_1_cleared](
const auto n) {
328 index_set_1_cleared.index_within_set(n);
332 auto index_set_union = index_set_0;
334 if (index_set_1.
size() != 0)
339 const auto locally_relevant_matrix_entries =
340 internal::extract_remote_rows<typename SparseMatrixType2::value_type>(
344 internal::get_mpi_communicator(system_matrix));
348 const unsigned int n_rows = index_set_union.n_elements();
349 const unsigned int n_cols = index_set_union.n_elements();
350 const unsigned int entries_per_row =
351 locally_relevant_matrix_entries.empty() ?
353 std::max_element(locally_relevant_matrix_entries.begin(),
354 locally_relevant_matrix_entries.end(),
355 [](
const auto &a,
const auto &b) {
356 return a.size() < b.size();
360 sparsity_pattern_out.reinit(n_rows, n_cols, entries_per_row);
362 std::vector<types::global_dof_index> temp_indices;
363 std::vector<typename SparseMatrixType2::value_type> temp_values;
365 for (
unsigned int row = 0; row < index_set_union.n_elements(); ++row)
367 const auto &global_row_entries = locally_relevant_matrix_entries[row];
369 temp_indices.clear();
370 temp_indices.reserve(global_row_entries.size());
372 for (
const auto &global_row_entry : global_row_entries)
374 const auto global_index = std::get<0>(global_row_entry);
376 if (index_set_union.is_element(global_index))
377 temp_indices.push_back(index_within_set(global_index));
380 sparsity_pattern_out.add_entries(
381 index_within_set(index_set_union.nth_index_in_set(row)),
382 temp_indices.begin(),
386 sparsity_pattern_out.compress();
389 system_matrix_out.reinit(sparsity_pattern_out);
392 for (
unsigned int row = 0; row < index_set_union.n_elements(); ++row)
394 const auto &global_row_entries = locally_relevant_matrix_entries[row];
396 temp_indices.clear();
399 temp_indices.reserve(global_row_entries.size());
400 temp_values.reserve(global_row_entries.size());
402 for (
const auto &global_row_entry : global_row_entries)
404 const auto global_index = std::get<0>(global_row_entry);
406 if (index_set_union.is_element(global_index))
408 temp_indices.push_back(index_within_set(global_index));
409 temp_values.push_back(std::get<1>(global_row_entry));
413 system_matrix_out.add(index_within_set(
414 index_set_union.nth_index_in_set(row)),
424 template <
typename SparseMatrixType,
425 typename SparsityPatternType,
426 typename SparseMatrixType2,
427 typename SparsityPatternType2>
430 const SparsityPatternType &sparsity_pattern,
432 SparseMatrixType2 &system_matrix_out,
433 SparsityPatternType2 &sparsity_pattern_out)
440 sparsity_pattern_out);
445 template <
typename SparseMatrixType,
446 typename SparsityPatternType,
450 const SparseMatrixType &system_matrix,
451 const SparsityPatternType &sparsity_pattern,
452 const std::vector<std::vector<types::global_dof_index>> &indices,
456 const auto local_size = internal::get_local_size(system_matrix);
458 local_size, internal::get_mpi_communicator(system_matrix));
459 IndexSet locally_owned_dofs(std::get<1>(prefix_sum));
460 locally_owned_dofs.add_range(std::get<0>(prefix_sum),
461 std::get<0>(prefix_sum) + local_size);
463 std::vector<::types::global_dof_index> ghost_indices_vector;
465 for (
const auto &i : indices)
466 ghost_indices_vector.
insert(ghost_indices_vector.
end(),
470 std::sort(ghost_indices_vector.begin(), ghost_indices_vector.end());
472 IndexSet locally_active_dofs(std::get<1>(prefix_sum));
473 locally_active_dofs.
add_indices(ghost_indices_vector.begin(),
474 ghost_indices_vector.end());
479 const auto locally_relevant_matrix_entries =
480 internal::extract_remote_rows<Number>(system_matrix,
483 internal::get_mpi_communicator(
489 blocks.resize(indices.size());
491 for (
unsigned int c = 0; c < indices.size(); ++c)
493 if (indices[c].empty())
496 const auto &local_dof_indices = indices[c];
500 const unsigned int dofs_per_cell = indices[c].size();
507 for (
unsigned int i = 0; i < dofs_per_cell; ++i)
508 for (
unsigned int j = 0; j < dofs_per_cell; ++j)
510 if (locally_owned_dofs.is_element(
511 local_dof_indices[i]))
514 sparsity_pattern.exists(local_dof_indices[i],
515 local_dof_indices[j]) ?
516 system_matrix(local_dof_indices[i],
517 local_dof_indices[j]) :
525 const auto &row_entries =
526 locally_relevant_matrix_entries[locally_active_dofs
528 local_dof_indices[i])];
531 std::lower_bound(row_entries.begin(),
533 std::pair<types::global_dof_index, Number>{
534 local_dof_indices[j], 0.0},
535 [](
const auto a,
const auto b) {
536 return a.first < b.first;
539 if (ptr != row_entries.end() &&
540 local_dof_indices[j] == ptr->first)
553 typename SparseMatrixType,
554 typename SparsityPatternType,
558 const SparsityPatternType &sparsity_pattern,
562 std::vector<std::vector<types::global_dof_index>> all_dof_indices;
565 for (
const auto &cell : dof_handler.active_cell_iterators())
567 if (cell->is_locally_owned() ==
false)
570 auto &local_dof_indices = all_dof_indices[cell->active_cell_index()];
571 local_dof_indices.resize(cell->get_fe().n_dofs_per_cell());
572 cell->get_dof_indices(local_dof_indices);