53 template <
typename SparseMatrixType,
54 typename SparsityPatternType,
55 typename SparseMatrixType2,
56 typename SparsityPatternType2>
59 const SparsityPatternType &sparsity_pattern,
61 SparseMatrixType2 &system_matrix_out,
62 SparsityPatternType2 &sparsity_pattern_out);
76 template <
typename SparseMatrixType,
77 typename SparsityPatternType,
78 typename SparseMatrixType2,
79 typename SparsityPatternType2>
82 const SparsityPatternType &sparsity_pattern,
85 SparseMatrixType2 &system_matrix_out,
86 SparsityPatternType2 &sparsity_pattern_out);
105 typename SparseMatrixType,
106 typename SparsityPatternType,
110 const SparsityPatternType &sparsity_pattern,
127 template <
typename SparseMatrixType,
128 typename SparsityPatternType,
132 const SparseMatrixType &sparse_matrix_in,
133 const SparsityPatternType &sparsity_pattern,
134 const std::vector<std::vector<types::global_dof_index>> &indices,
143 template <
typename T>
144 using get_mpi_communicator_t =
145 decltype(std::declval<const T>().get_mpi_communicator());
147 template <
typename T>
148 constexpr bool has_get_mpi_communicator =
149 ::internal::is_supported_operation<get_mpi_communicator_t, T>;
151 template <
typename T>
152 using local_size_t =
decltype(std::declval<const T>().local_size());
154 template <
typename T>
155 constexpr bool has_local_size =
156 ::internal::is_supported_operation<local_size_t, T>;
158 template <
typename SparseMatrixType,
159 std::enable_if_t<has_get_mpi_communicator<SparseMatrixType>,
160 SparseMatrixType> * =
nullptr>
162 get_mpi_communicator(
const SparseMatrixType &sparse_matrix)
164 return sparse_matrix.get_mpi_communicator();
167 template <
typename SparseMatrixType,
168 std::enable_if_t<!has_get_mpi_communicator<SparseMatrixType>,
169 SparseMatrixType> * =
nullptr>
171 get_mpi_communicator(
const SparseMatrixType & )
173 return MPI_COMM_SELF;
176 template <
typename SparseMatrixType,
177 std::enable_if_t<has_local_size<SparseMatrixType>,
178 SparseMatrixType> * =
nullptr>
180 get_local_size(
const SparseMatrixType &sparse_matrix)
182 return sparse_matrix.local_size();
185 template <
typename SparseMatrixType,
186 std::enable_if_t<!has_local_size<SparseMatrixType>,
187 SparseMatrixType> * =
nullptr>
189 get_local_size(
const SparseMatrixType &sparse_matrix)
193 return sparse_matrix.m();
198 template <
typename Number,
199 typename SparseMatrixType,
200 typename SparsityPatternType>
201 std::vector<std::vector<std::pair<types::global_dof_index, Number>>>
202 extract_remote_rows(
const SparseMatrixType &system_matrix,
203 const SparsityPatternType &sparsity_pattern,
204 const IndexSet &locally_active_dofs,
207 std::vector<unsigned int> dummy(locally_active_dofs.
n_elements());
209 const auto local_size = get_local_size(system_matrix);
210 const auto [prefix_sum, total_sum] =
212 IndexSet locally_owned_dofs(total_sum);
213 locally_owned_dofs.add_range(prefix_sum, prefix_sum + local_size);
215 using T1 = std::vector<
217 std::vector<std::pair<types::global_dof_index, Number>>>>;
225 std::vector<std::vector<std::pair<types::global_dof_index, Number>>>
226 locally_relevant_matrix_entries(locally_active_dofs.
n_elements());
229 std::vector<unsigned int> ranks;
235 std::vector<std::vector<unsigned int>> row_to_procs(
236 locally_owned_dofs.n_elements());
240 row_to_procs[locally_owned_dofs.index_within_set(
index)].
push_back(
243 std::map<unsigned int, T1>
data;
246 std::vector<std::pair<types::global_dof_index, Number>>>
249 for (
unsigned int i = 0; i < row_to_procs.size(); ++i)
251 if (row_to_procs[i].empty())
254 const auto row = locally_owned_dofs.nth_index_in_set(i);
255 auto entry = system_matrix.begin(row);
257 const unsigned int row_length = sparsity_pattern.row_length(row);
260 buffer.second.resize(row_length);
262 for (
unsigned int j = 0; j < row_length; ++j, ++entry)
263 buffer.second[j] = {entry->column(), entry->value()};
265 for (
const auto &proc : row_to_procs[i])
266 data[proc].emplace_back(buffer);
269 ::Utilities::MPI::ConsensusAlgorithms::selector<T1>(
271 [&](
const unsigned int other_rank) {
return data[other_rank]; },
272 [&](
const unsigned int &,
const T1 &buffer_recv) {
273 for (
const auto &i : buffer_recv)
276 locally_relevant_matrix_entries[locally_active_dofs
279 std::sort(dst.begin(),
281 [](
const auto &a,
const auto &b) {
282 return a.first < b.first;
288 return locally_relevant_matrix_entries;
294 template <
typename SparseMatrixType,
295 typename SparsityPatternType,
296 typename SparseMatrixType2,
297 typename SparsityPatternType2>
300 const SparsityPatternType &sparsity_pattern,
303 SparseMatrixType2 &system_matrix_out,
304 SparsityPatternType2 &sparsity_pattern_out)
309 auto index_set_1_cleared = index_set_1;
310 if (index_set_1.
size() != 0)
313 const auto index_within_set = [&index_set_0,
314 &index_set_1_cleared](
const auto n) {
319 index_set_1_cleared.index_within_set(n);
323 auto index_set_union = index_set_0;
325 if (index_set_1.
size() != 0)
330 const auto locally_relevant_matrix_entries =
331 internal::extract_remote_rows<typename SparseMatrixType2::value_type>(
335 internal::get_mpi_communicator(system_matrix));
339 const unsigned int n_rows = index_set_union.n_elements();
340 const unsigned int n_cols = index_set_union.n_elements();
341 const unsigned int entries_per_row =
342 locally_relevant_matrix_entries.empty() ?
344 std::max_element(locally_relevant_matrix_entries.begin(),
345 locally_relevant_matrix_entries.end(),
346 [](
const auto &a,
const auto &b) {
347 return a.size() < b.size();
351 sparsity_pattern_out.reinit(n_rows, n_cols, entries_per_row);
353 std::vector<types::global_dof_index> temp_indices;
354 std::vector<typename SparseMatrixType2::value_type> temp_values;
356 for (
unsigned int row = 0; row < index_set_union.n_elements(); ++row)
358 const auto &global_row_entries = locally_relevant_matrix_entries[row];
360 temp_indices.clear();
361 temp_indices.reserve(global_row_entries.size());
363 for (
const auto &global_row_entry : global_row_entries)
365 const auto global_index = std::get<0>(global_row_entry);
367 if (index_set_union.is_element(global_index))
368 temp_indices.push_back(index_within_set(global_index));
371 sparsity_pattern_out.add_entries(
372 index_within_set(index_set_union.nth_index_in_set(row)),
373 temp_indices.begin(),
377 sparsity_pattern_out.compress();
380 system_matrix_out.reinit(sparsity_pattern_out);
383 for (
unsigned int row = 0; row < index_set_union.n_elements(); ++row)
385 const auto &global_row_entries = locally_relevant_matrix_entries[row];
387 temp_indices.clear();
390 temp_indices.reserve(global_row_entries.size());
391 temp_values.reserve(global_row_entries.size());
393 for (
const auto &global_row_entry : global_row_entries)
395 const auto global_index = std::get<0>(global_row_entry);
397 if (index_set_union.is_element(global_index))
399 temp_indices.push_back(index_within_set(global_index));
400 temp_values.push_back(std::get<1>(global_row_entry));
404 system_matrix_out.add(index_within_set(
405 index_set_union.nth_index_in_set(row)),
415 template <
typename SparseMatrixType,
416 typename SparsityPatternType,
417 typename SparseMatrixType2,
418 typename SparsityPatternType2>
421 const SparsityPatternType &sparsity_pattern,
423 SparseMatrixType2 &system_matrix_out,
424 SparsityPatternType2 &sparsity_pattern_out)
431 sparsity_pattern_out);
436 template <
typename SparseMatrixType,
437 typename SparsityPatternType,
441 const SparseMatrixType &system_matrix,
442 const SparsityPatternType &sparsity_pattern,
443 const std::vector<std::vector<types::global_dof_index>> &indices,
447 const auto local_size = internal::get_local_size(system_matrix);
449 local_size, internal::get_mpi_communicator(system_matrix));
450 IndexSet locally_owned_dofs(std::get<1>(prefix_sum));
451 locally_owned_dofs.add_range(std::get<0>(prefix_sum),
452 std::get<0>(prefix_sum) + local_size);
454 std::vector<::types::global_dof_index> ghost_indices_vector;
456 for (
const auto &i : indices)
457 ghost_indices_vector.
insert(ghost_indices_vector.
end(),
461 std::sort(ghost_indices_vector.begin(), ghost_indices_vector.end());
463 IndexSet locally_active_dofs(std::get<1>(prefix_sum));
464 locally_active_dofs.
add_indices(ghost_indices_vector.begin(),
465 ghost_indices_vector.end());
470 const auto locally_relevant_matrix_entries =
471 internal::extract_remote_rows<Number>(system_matrix,
474 internal::get_mpi_communicator(
480 blocks.resize(indices.size());
482 for (
unsigned int c = 0; c < indices.size(); ++c)
484 if (indices[c].empty())
487 const auto &local_dof_indices = indices[c];
491 const unsigned int dofs_per_cell = indices[c].size();
498 for (
unsigned int i = 0; i < dofs_per_cell; ++i)
499 for (
unsigned int j = 0; j < dofs_per_cell; ++j)
501 if (locally_owned_dofs.is_element(
502 local_dof_indices[i]))
504 if constexpr (std::is_same_v<SparseMatrixType,
508 system_matrix.get_sparsity_pattern()(
509 local_dof_indices[i], local_dof_indices[j]);
519 accessor(&system_matrix, ind);
527 sparsity_pattern.exists(local_dof_indices[i],
528 local_dof_indices[j]) ?
529 system_matrix(local_dof_indices[i],
530 local_dof_indices[j]) :
538 const auto &row_entries =
539 locally_relevant_matrix_entries[locally_active_dofs
541 local_dof_indices[i])];
544 std::lower_bound(row_entries.begin(),
546 std::pair<types::global_dof_index, Number>{
547 local_dof_indices[j], 0.0},
548 [](
const auto a,
const auto b) {
549 return a.first < b.first;
552 if (ptr != row_entries.end() &&
553 local_dof_indices[j] == ptr->first)
566 typename SparseMatrixType,
567 typename SparsityPatternType,
571 const SparsityPatternType &sparsity_pattern,
575 std::vector<std::vector<types::global_dof_index>> all_dof_indices;
578 for (
const auto &cell : dof_handler.active_cell_iterators())
580 if (cell->is_locally_owned() ==
false)
583 auto &local_dof_indices = all_dof_indices[cell->active_cell_index()];
584 local_dof_indices.resize(cell->get_fe().n_dofs_per_cell());
585 cell->get_dof_indices(local_dof_indices);