16#ifndef dealii_sparse_matrix_tools_h
17#define dealii_sparse_matrix_tools_h
56 template <
typename SparseMatrixType,
57 typename SparsityPatternType,
58 typename SparseMatrixType2,
59 typename SparsityPatternType2>
62 const SparsityPatternType &sparsity_pattern,
64 SparseMatrixType2 & system_matrix_out,
65 SparsityPatternType2 &sparsity_pattern_out);
79 template <
typename SparseMatrixType,
80 typename SparsityPatternType,
81 typename SparseMatrixType2,
82 typename SparsityPatternType2>
85 const SparsityPatternType &sparsity_pattern,
88 SparseMatrixType2 & system_matrix_out,
89 SparsityPatternType2 &sparsity_pattern_out);
108 typename SparseMatrixType,
109 typename SparsityPatternType,
113 const SparsityPatternType & sparsity_pattern,
130 template <
typename SparseMatrixType,
131 typename SparsityPatternType,
135 const SparseMatrixType & sparse_matrix_in,
136 const SparsityPatternType & sparsity_pattern,
137 const std::vector<std::vector<types::global_dof_index>> &indices,
146 template <
typename T>
150# ifndef DEAL_II_WITH_MPI
167 return {prefix,
sum};
171 template <
typename T>
172 using get_mpi_communicator_t =
173 decltype(std::declval<T const>().get_mpi_communicator());
175 template <
typename T>
176 constexpr bool has_get_mpi_communicator =
177 ::internal::is_supported_operation<get_mpi_communicator_t, T>;
179 template <
typename T>
180 using local_size_t =
decltype(std::declval<T const>().local_size());
182 template <
typename T>
183 constexpr bool has_local_size =
184 ::internal::is_supported_operation<local_size_t, T>;
186 template <
typename SparseMatrixType,
187 std::enable_if_t<has_get_mpi_communicator<SparseMatrixType>,
188 SparseMatrixType> * =
nullptr>
190 get_mpi_communicator(
const SparseMatrixType &sparse_matrix)
192 return sparse_matrix.get_mpi_communicator();
195 template <
typename SparseMatrixType,
196 std::enable_if_t<!has_get_mpi_communicator<SparseMatrixType>,
197 SparseMatrixType> * =
nullptr>
199 get_mpi_communicator(
const SparseMatrixType &sparse_matrix)
202 return MPI_COMM_SELF;
205 template <
typename SparseMatrixType,
206 std::enable_if_t<has_local_size<SparseMatrixType>,
207 SparseMatrixType> * =
nullptr>
209 get_local_size(
const SparseMatrixType &sparse_matrix)
211 return sparse_matrix.local_size();
214 template <
typename SparseMatrixType,
215 std::enable_if_t<!has_local_size<SparseMatrixType>,
216 SparseMatrixType> * =
nullptr>
218 get_local_size(
const SparseMatrixType &sparse_matrix)
222 return sparse_matrix.m();
227 template <
typename Number,
228 typename SparseMatrixType,
229 typename SparsityPatternType>
230 std::vector<std::vector<std::pair<types::global_dof_index, Number>>>
231 extract_remote_rows(
const SparseMatrixType & system_matrix,
232 const SparsityPatternType &sparsity_pattern,
233 const IndexSet & locally_active_dofs,
236 std::vector<unsigned int> dummy(locally_active_dofs.
n_elements());
238 const auto local_size = get_local_size(system_matrix);
239 const auto prefix_sum = compute_prefix_sum(local_size,
comm);
240 IndexSet locally_owned_dofs(std::get<1>(prefix_sum));
241 locally_owned_dofs.add_range(std::get<0>(prefix_sum),
242 std::get<0>(prefix_sum) + local_size);
245 process(locally_owned_dofs, locally_active_dofs,
comm, dummy,
true);
249 std::pair<types::global_dof_index, types::global_dof_index>>,
250 std::vector<unsigned int>>
252 consensus_algorithm.
run(process,
comm);
254 using T1 = std::vector<
256 std::vector<std::pair<types::global_dof_index, Number>>>>;
258 auto requesters = process.get_requesters();
260 std::vector<std::vector<std::pair<types::global_dof_index, Number>>>
261 locally_relevant_matrix_entries(locally_active_dofs.
n_elements());
264 std::vector<unsigned int> ranks;
265 ranks.reserve(requesters.size());
267 for (
const auto &i : requesters)
268 ranks.push_back(i.
first);
270 std::vector<std::vector<unsigned int>> row_to_procs(
271 locally_owned_dofs.n_elements());
273 for (
const auto &requester : requesters)
275 row_to_procs[locally_owned_dofs.index_within_set(
index)].push_back(
278 std::map<unsigned int, T1> data;
280 for (
unsigned int i = 0; i < row_to_procs.size(); ++i)
282 if (row_to_procs[i].size() == 0)
285 const auto row = locally_owned_dofs.nth_index_in_set(i);
286 auto entry = system_matrix.begin(row);
288 const unsigned int row_length = sparsity_pattern.row_length(row);
292 std::vector<std::pair<types::global_dof_index, Number>>>
296 for (
unsigned int i = 0; i < row_length; ++i)
298 buffer.second.emplace_back(entry->column(), entry->value());
300 if (i + 1 != row_length)
304 for (
const auto &proc :
305 row_to_procs[locally_owned_dofs.index_within_set(buffer.
first)])
306 data[proc].emplace_back(buffer);
309 ::Utilities::MPI::ConsensusAlgorithms::selector<T1>(
311 [&](
const unsigned int other_rank) {
return data[other_rank]; },
312 [&](
const unsigned int &,
const T1 &buffer_recv) {
313 for (
const auto &i : buffer_recv)
316 locally_relevant_matrix_entries[locally_active_dofs
319 std::sort(dst.begin(),
321 [](
const auto &a,
const auto &b) {
322 return a.first < b.first;
328 return locally_relevant_matrix_entries;
334 template <
typename SparseMatrixType,
335 typename SparsityPatternType,
336 typename SparseMatrixType2,
337 typename SparsityPatternType2>
340 const SparsityPatternType &sparsity_pattern,
343 SparseMatrixType2 & system_matrix_out,
344 SparsityPatternType2 &sparsity_pattern_out)
349 auto index_set_1_cleared = index_set_1;
350 if (index_set_1.
size() != 0)
353 const auto index_within_set = [&index_set_0,
354 &index_set_1_cleared](
const auto n) {
359 index_set_1_cleared.index_within_set(n);
363 auto index_set_union = index_set_0;
365 if (index_set_1.
size() != 0)
370 const auto locally_relevant_matrix_entries =
371 internal::extract_remote_rows<typename SparseMatrixType2::value_type>(
375 internal::get_mpi_communicator(system_matrix));
379 const unsigned int n_rows = index_set_union.n_elements();
380 const unsigned int n_cols = index_set_union.n_elements();
381 const unsigned int entries_per_row =
382 locally_relevant_matrix_entries.size() == 0 ?
384 std::max_element(locally_relevant_matrix_entries.begin(),
385 locally_relevant_matrix_entries.end(),
386 [](
const auto &a,
const auto &b) {
387 return a.size() < b.size();
391 sparsity_pattern_out.reinit(n_rows, n_cols, entries_per_row);
393 std::vector<types::global_dof_index> temp_indices;
394 std::vector<typename SparseMatrixType2::value_type> temp_values;
396 for (
unsigned int row = 0; row < index_set_union.n_elements(); ++row)
398 const auto &global_row_entries = locally_relevant_matrix_entries[row];
400 temp_indices.clear();
401 temp_indices.reserve(global_row_entries.size());
403 for (
const auto &global_row_entry : global_row_entries)
405 const auto global_index = std::get<0>(global_row_entry);
407 if (index_set_union.is_element(global_index))
408 temp_indices.push_back(index_within_set(global_index));
411 sparsity_pattern_out.add_entries(
412 index_within_set(index_set_union.nth_index_in_set(row)),
413 temp_indices.begin(),
417 sparsity_pattern_out.compress();
420 system_matrix_out.reinit(sparsity_pattern_out);
423 for (
unsigned int row = 0; row < index_set_union.n_elements(); ++row)
425 const auto &global_row_entries = locally_relevant_matrix_entries[row];
427 temp_indices.clear();
430 temp_indices.reserve(global_row_entries.size());
431 temp_values.reserve(global_row_entries.size());
433 for (
const auto &global_row_entry : global_row_entries)
435 const auto global_index = std::get<0>(global_row_entry);
437 if (index_set_union.is_element(global_index))
439 temp_indices.push_back(index_within_set(global_index));
440 temp_values.push_back(std::get<1>(global_row_entry));
444 system_matrix_out.add(index_within_set(
445 index_set_union.nth_index_in_set(row)),
455 template <
typename SparseMatrixType,
456 typename SparsityPatternType,
457 typename SparseMatrixType2,
458 typename SparsityPatternType2>
461 const SparsityPatternType &sparsity_pattern,
463 SparseMatrixType2 & system_matrix_out,
464 SparsityPatternType2 &sparsity_pattern_out)
471 sparsity_pattern_out);
476 template <
typename SparseMatrixType,
477 typename SparsityPatternType,
481 const SparseMatrixType & system_matrix,
482 const SparsityPatternType & sparsity_pattern,
483 const std::vector<std::vector<types::global_dof_index>> &indices,
487 const auto local_size = internal::get_local_size(system_matrix);
488 const auto prefix_sum = internal::compute_prefix_sum(
489 local_size, internal::get_mpi_communicator(system_matrix));
490 IndexSet locally_owned_dofs(std::get<1>(prefix_sum));
491 locally_owned_dofs.add_range(std::get<0>(prefix_sum),
492 std::get<0>(prefix_sum) + local_size);
494 std::vector<::types::global_dof_index> ghost_indices_vector;
496 for (
const auto &i : indices)
497 ghost_indices_vector.
insert(ghost_indices_vector.
end(),
501 std::sort(ghost_indices_vector.begin(), ghost_indices_vector.end());
502 ghost_indices_vector.erase(std::unique(ghost_indices_vector.begin(),
503 ghost_indices_vector.end()),
504 ghost_indices_vector.end());
507 IndexSet locally_active_dofs(std::get<1>(prefix_sum));
508 locally_active_dofs.
add_indices(ghost_indices_vector.begin(),
509 ghost_indices_vector.end());
514 const auto locally_relevant_matrix_entries =
515 internal::extract_remote_rows<Number>(system_matrix,
518 internal::get_mpi_communicator(
524 blocks.resize(indices.size());
526 for (
unsigned int c = 0; c < indices.size(); ++c)
528 if (indices[c].size() == 0)
531 const auto &local_dof_indices = indices[c];
535 const unsigned int dofs_per_cell = indices[c].size();
542 for (
unsigned int i = 0; i < dofs_per_cell; ++i)
543 for (
unsigned int j = 0; j < dofs_per_cell; ++j)
545 if (locally_owned_dofs.is_element(
546 local_dof_indices[i]))
549 sparsity_pattern.exists(local_dof_indices[i],
550 local_dof_indices[j]) ?
551 system_matrix(local_dof_indices[i],
552 local_dof_indices[j]) :
560 const auto &row_entries =
561 locally_relevant_matrix_entries[locally_active_dofs
563 local_dof_indices[i])];
566 std::lower_bound(row_entries.begin(),
568 std::pair<types::global_dof_index, Number>{
569 local_dof_indices[j], 0.0},
570 [](
const auto a,
const auto b) {
571 return a.first < b.first;
574 if (ptr != row_entries.end() &&
575 local_dof_indices[j] == ptr->first)
588 typename SparseMatrixType,
589 typename SparsityPatternType,
593 const SparsityPatternType & sparsity_pattern,
597 std::vector<std::vector<types::global_dof_index>> all_dof_indices;
600 for (
const auto &cell : dof_handler.active_cell_iterators())
602 if (cell->is_locally_owned() ==
false)
605 auto &local_dof_indices = all_dof_indices[cell->active_cell_index()];
606 local_dof_indices.resize(cell->get_fe().n_dofs_per_cell());
607 cell->get_dof_indices(local_dof_indices);
const Triangulation< dim, spacedim > & get_triangulation() const
size_type index_within_set(const size_type global_index) const
size_type n_elements() const
bool is_element(const size_type index) const
void subtract_set(const IndexSet &other)
void add_indices(const ForwardIterator &begin, const ForwardIterator &end)
unsigned int n_active_cells() const
virtual std::vector< unsigned int > run(const std::vector< unsigned int > &targets, const std::function< RequestType(const unsigned int)> &create_request, const std::function< AnswerType(const unsigned int, const RequestType &)> &answer_request, const std::function< void(const unsigned int, const AnswerType &)> &process_answer, const MPI_Comm comm) override
#define DEAL_II_NAMESPACE_OPEN
#define DEAL_II_NAMESPACE_CLOSE
#define Assert(cond, exc)
#define AssertDimension(dim1, dim2)
#define AssertThrowMPI(error_code)
static ::ExceptionBase & ExcInternalError()
void cell_matrix(FullMatrix< double > &M, const FEValuesBase< dim > &fe, const FEValuesBase< dim > &fetest, const ArrayView< const std::vector< double > > &velocity, const double factor=1.)
VectorType::value_type * end(VectorType &V)
VectorType::value_type * begin(VectorType &V)
TrilinosWrappers::types::int_type global_index(const Epetra_BlockMap &map, const ::types::global_dof_index i)
T sum(const T &t, const MPI_Comm mpi_communicator)
const MPI_Datatype mpi_type_id_for_type
unsigned int global_dof_index