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 & )
175 return MPI_COMM_SELF;
178 template <
typename SparseMatrixType,
179 std::enable_if_t<has_local_size<SparseMatrixType>,
180 SparseMatrixType> * =
nullptr>
182 get_local_size(
const SparseMatrixType &sparse_matrix)
184 return sparse_matrix.local_size();
187 template <
typename SparseMatrixType,
188 std::enable_if_t<!has_local_size<SparseMatrixType>,
189 SparseMatrixType> * =
nullptr>
191 get_local_size(
const SparseMatrixType &sparse_matrix)
195 return sparse_matrix.m();
200 template <
typename Number,
201 typename SparseMatrixType,
202 typename SparsityPatternType>
203 std::vector<std::vector<std::pair<types::global_dof_index, Number>>>
204 extract_remote_rows(
const SparseMatrixType &system_matrix,
205 const SparsityPatternType &sparsity_pattern,
206 const IndexSet &locally_active_dofs,
209 std::vector<unsigned int> dummy(locally_active_dofs.
n_elements());
211 const auto local_size = get_local_size(system_matrix);
212 const auto [prefix_sum, total_sum] =
214 IndexSet locally_owned_dofs(total_sum);
215 locally_owned_dofs.add_range(prefix_sum, prefix_sum + local_size);
217 using T1 = std::vector<
219 std::vector<std::pair<types::global_dof_index, Number>>>>;
221 std::map<unsigned int, IndexSet> requesters;
222 std::tie(std::ignore, requesters) =
227 std::vector<std::vector<std::pair<types::global_dof_index, Number>>>
228 locally_relevant_matrix_entries(locally_active_dofs.
n_elements());
231 std::vector<unsigned int> ranks;
232 ranks.reserve(requesters.size());
234 for (
const auto &i : requesters)
235 ranks.push_back(i.first);
237 std::vector<std::vector<unsigned int>> row_to_procs(
238 locally_owned_dofs.n_elements());
240 for (
const auto &requester : requesters)
241 for (
const auto &index : requester.second)
242 row_to_procs[locally_owned_dofs.index_within_set(index)].push_back(
245 std::map<unsigned int, T1> data;
248 std::vector<std::pair<types::global_dof_index, Number>>>
251 for (
unsigned int i = 0; i < row_to_procs.size(); ++i)
253 if (row_to_procs[i].empty())
256 const auto row = locally_owned_dofs.nth_index_in_set(i);
257 auto entry = system_matrix.begin(row);
259 const unsigned int row_length = sparsity_pattern.row_length(row);
262 buffer.second.resize(row_length);
264 for (
unsigned int j = 0; j < row_length; ++j, ++entry)
265 buffer.second[j] = {entry->column(), entry->value()};
267 for (
const auto &proc : row_to_procs[i])
268 data[proc].emplace_back(buffer);
273 [&](
const unsigned int other_rank) {
return data[other_rank]; },
274 [&](
const unsigned int &,
const T1 &buffer_recv) {
275 for (
const auto &i : buffer_recv)
278 locally_relevant_matrix_entries[locally_active_dofs
281 std::sort(dst.begin(),
283 [](
const auto &a,
const auto &b) {
284 return a.first < b.first;
290 return locally_relevant_matrix_entries;
296 template <
typename SparseMatrixType,
297 typename SparsityPatternType,
298 typename SparseMatrixType2,
299 typename SparsityPatternType2>
302 const SparsityPatternType &sparsity_pattern,
305 SparseMatrixType2 &system_matrix_out,
306 SparsityPatternType2 &sparsity_pattern_out)
311 auto index_set_1_cleared = index_set_1;
312 if (index_set_1.
size() != 0)
315 const auto index_within_set = [&index_set_0,
316 &index_set_1_cleared](
const auto n) {
321 index_set_1_cleared.index_within_set(n);
325 auto index_set_union = index_set_0;
327 if (index_set_1.
size() != 0)
332 const auto locally_relevant_matrix_entries =
333 internal::extract_remote_rows<typename SparseMatrixType2::value_type>(
337 internal::get_mpi_communicator(system_matrix));
341 const unsigned int n_rows = index_set_union.n_elements();
342 const unsigned int n_cols = index_set_union.n_elements();
343 const unsigned int entries_per_row =
344 locally_relevant_matrix_entries.empty() ?
346 std::max_element(locally_relevant_matrix_entries.begin(),
347 locally_relevant_matrix_entries.end(),
348 [](
const auto &a,
const auto &b) {
349 return a.size() < b.size();
353 sparsity_pattern_out.reinit(n_rows, n_cols, entries_per_row);
355 std::vector<types::global_dof_index> temp_indices;
356 std::vector<typename SparseMatrixType2::value_type> temp_values;
358 for (
unsigned int row = 0; row < index_set_union.n_elements(); ++row)
360 const auto &global_row_entries = locally_relevant_matrix_entries[row];
362 temp_indices.clear();
363 temp_indices.reserve(global_row_entries.size());
365 for (
const auto &global_row_entry : global_row_entries)
367 const auto global_index = std::get<0>(global_row_entry);
369 if (index_set_union.is_element(global_index))
370 temp_indices.push_back(index_within_set(global_index));
373 sparsity_pattern_out.add_entries(
374 index_within_set(index_set_union.nth_index_in_set(row)),
375 temp_indices.begin(),
379 sparsity_pattern_out.compress();
382 system_matrix_out.reinit(sparsity_pattern_out);
385 for (
unsigned int row = 0; row < index_set_union.n_elements(); ++row)
387 const auto &global_row_entries = locally_relevant_matrix_entries[row];
389 temp_indices.clear();
392 temp_indices.reserve(global_row_entries.size());
393 temp_values.reserve(global_row_entries.size());
395 for (
const auto &global_row_entry : global_row_entries)
397 const auto global_index = std::get<0>(global_row_entry);
399 if (index_set_union.is_element(global_index))
401 temp_indices.push_back(index_within_set(global_index));
402 temp_values.push_back(std::get<1>(global_row_entry));
406 system_matrix_out.add(index_within_set(
407 index_set_union.nth_index_in_set(row)),
417 template <
typename SparseMatrixType,
418 typename SparsityPatternType,
419 typename SparseMatrixType2,
420 typename SparsityPatternType2>
423 const SparsityPatternType &sparsity_pattern,
425 SparseMatrixType2 &system_matrix_out,
426 SparsityPatternType2 &sparsity_pattern_out)
433 sparsity_pattern_out);
438 template <
typename SparseMatrixType,
439 typename SparsityPatternType,
443 const SparseMatrixType &system_matrix,
444 const SparsityPatternType &sparsity_pattern,
445 const std::vector<std::vector<types::global_dof_index>> &indices,
449 const auto local_size = internal::get_local_size(system_matrix);
451 local_size, internal::get_mpi_communicator(system_matrix));
452 IndexSet locally_owned_dofs(std::get<1>(prefix_sum));
453 locally_owned_dofs.add_range(std::get<0>(prefix_sum),
454 std::get<0>(prefix_sum) + local_size);
456 std::vector<::types::global_dof_index> ghost_indices_vector;
458 for (
const auto &i : indices)
459 ghost_indices_vector.insert(ghost_indices_vector.end(),
463 std::sort(ghost_indices_vector.begin(), ghost_indices_vector.end());
465 IndexSet locally_active_dofs(std::get<1>(prefix_sum));
466 locally_active_dofs.
add_indices(ghost_indices_vector.begin(),
467 ghost_indices_vector.end());
472 const auto locally_relevant_matrix_entries =
473 internal::extract_remote_rows<Number>(system_matrix,
476 internal::get_mpi_communicator(
482 blocks.resize(indices.size());
484 for (
unsigned int c = 0; c < indices.size(); ++c)
486 if (indices[c].empty())
489 const auto &local_dof_indices = indices[c];
493 const unsigned int dofs_per_cell = indices[c].size();
500 for (
unsigned int i = 0; i < dofs_per_cell; ++i)
501 for (
unsigned int j = 0; j < dofs_per_cell; ++j)
503 if (locally_owned_dofs.is_element(
504 local_dof_indices[i]))
506 if constexpr (std::is_same_v<SparseMatrixType,
510 system_matrix.get_sparsity_pattern()(
511 local_dof_indices[i], local_dof_indices[j]);
521 accessor(&system_matrix, ind);
529 sparsity_pattern.exists(local_dof_indices[i],
530 local_dof_indices[j]) ?
531 system_matrix(local_dof_indices[i],
532 local_dof_indices[j]) :
540 const auto &row_entries =
541 locally_relevant_matrix_entries[locally_active_dofs
543 local_dof_indices[i])];
546 std::lower_bound(row_entries.begin(),
548 std::pair<types::global_dof_index, Number>{
549 local_dof_indices[j], 0.0},
550 [](
const auto a,
const auto b) {
551 return a.first < b.first;
554 if (ptr != row_entries.end() &&
555 local_dof_indices[j] == ptr->first)
568 typename SparseMatrixType,
569 typename SparsityPatternType,
573 const SparsityPatternType &sparsity_pattern,
577 std::vector<std::vector<types::global_dof_index>> all_dof_indices;
582 if (cell->is_locally_owned() ==
false)
585 auto &local_dof_indices = all_dof_indices[cell->active_cell_index()];
586 local_dof_indices.resize(cell->get_fe().n_dofs_per_cell());
587 cell->get_dof_indices(local_dof_indices);