/home/runner/work/DiFfRG_current/DiFfRG_current/DiFfRG/include/DiFfRG/discretization/common/la_policy.hh Source File#

DiFfRG: /home/runner/work/DiFfRG_current/DiFfRG_current/DiFfRG/include/DiFfRG/discretization/common/la_policy.hh Source File
DiFfRG
Discretization Framework for functional Renormalization Group flows
la_policy.hh
Go to the documentation of this file.
1#pragma once
2
3// external libraries
4#include <deal.II/base/index_set.h>
5#include <deal.II/lac/dynamic_sparsity_pattern.h>
6#include <deal.II/lac/full_matrix.h>
7#include <deal.II/lac/sparsity_tools.h>
8
9// DiFfRG
11#include <DiFfRG/common/mpi.hh>
13
14// std
15#include <vector>
16
17namespace DiFfRG
18{
26 template <typename VectorType>
27 void reinit_la_vector(VectorType &vec, const dealii::IndexSet &locally_owned, MPI_Comm comm)
28 {
29 if constexpr (is_distributed_la<VectorType>) {
30 vec.reinit(locally_owned, comm);
31 } else {
32 (void)comm;
33 vec.reinit(locally_owned.size());
34 }
35 }
36
49 template <typename SparseMatrixType>
50 void finalize_la_sparsity(dealii::DynamicSparsityPattern &dsp, get_type::SparsityPattern<SparseMatrixType> &pattern,
51 const dealii::IndexSet &locally_owned, const dealii::IndexSet &locally_relevant,
52 MPI_Comm comm)
53 {
55 // Guarded, not merely discarded: SparsityTools::distribute_sparsity_pattern only exists in
56 // an MPI-enabled deal.II, and the call's arguments are non-dependent, so an `if constexpr`
57 // alone would still fail name lookup in a serial build.
58#ifdef DEAL_II_WITH_MPI
59 dealii::SparsityTools::distribute_sparsity_pattern(dsp, locally_owned, comm, locally_relevant);
60
61 // Emphatically NOT `pattern = dsp`. DynamicSparsityPattern::operator= is documented to work
62 // "only for empty objects" and enforces that with an Assert -- which is compiled out in
63 // Release. So the obvious assignment silently leaves the pattern 0x0, PETSc then preallocates
64 // from an uninitialised row-start array, and the failure surfaces as
65 // "nnz cannot be greater than row length: value 545352472" from deep inside MatSeqAIJ.
66 // Copy the entries explicitly instead.
67 const auto &rows = dsp.row_index_set();
68 pattern.reinit(dsp.n_rows(), dsp.n_cols(), rows);
69 const auto copy_row = [&](const dealii::types::global_dof_index row) {
70 for (auto it = dsp.begin(row); it != dsp.end(row); ++it)
71 pattern.add(row, it->column());
72 };
73 if (rows.n_elements() > 0)
74 for (const auto row : rows)
75 copy_row(row);
76 else
77 for (dealii::types::global_dof_index row = 0; row < dsp.n_rows(); ++row)
78 copy_row(row);
79#endif
80 } else {
81 (void)locally_owned;
82 (void)locally_relevant;
83 (void)comm;
84 pattern.copy_from(dsp);
85 }
86 }
87
91 template <typename SparseMatrixType>
92 void reinit_la_matrix(SparseMatrixType &matrix, const get_type::SparsityPattern<SparseMatrixType> &pattern,
93 const dealii::IndexSet &locally_owned, MPI_Comm comm)
94 {
96 matrix.reinit(locally_owned, pattern, comm);
97 } else {
98 (void)locally_owned;
99 (void)comm;
100 matrix.reinit(pattern);
101 }
102 }
103
113 template <typename VectorType>
114 dealii::IndexSet restrict_to_owned(const dealii::IndexSet &global_set, const dealii::IndexSet &locally_owned)
115 {
116 if constexpr (is_distributed_la<VectorType>) {
117 return global_set & locally_owned;
118 } else {
119 (void)locally_owned;
120 return global_set;
121 }
122 }
123
131 inline dealii::IndexSet variables_owner_set(const dealii::types::global_dof_index n_vars, MPI_Comm comm)
132 {
133 constexpr unsigned int variable_owner = 0;
134 dealii::IndexSet variables(n_vars);
135 if (MPI::rank(comm) == variable_owner) variables.add_range(0, n_vars);
136 variables.compress();
137 return variables;
138 }
139
146 template <typename VectorType>
147 void reinit_variables_view(SolutionView<VectorType> &view, const dealii::types::global_dof_index n_vars,
148 MPI_Comm comm)
149 {
150 view.reinit(variables_owner_set(n_vars, comm), dealii::complete_index_set(n_vars), comm);
151 }
152
156 template <typename VectorType>
157 void reinit_la_variables_vector(VectorType &vec, const dealii::types::global_dof_index n_vars, MPI_Comm comm)
158 {
159 if constexpr (is_distributed_la<VectorType>) {
160 vec.reinit(variables_owner_set(n_vars, comm), comm);
161 } else {
162 (void)comm;
163 vec.reinit(n_vars);
164 }
165 }
166
182 template <typename BlockVectorType>
183 void reinit_la_block_vector(BlockVectorType &vec, const std::vector<uint> &block_structure,
184 const dealii::IndexSet &locally_owned, MPI_Comm comm)
185 {
187 std::vector<dealii::IndexSet> owned{locally_owned};
188 if (block_structure.size() > 1) owned.push_back(variables_owner_set(block_structure[1], comm));
189 vec.reinit(owned, comm);
190 } else {
191 (void)locally_owned;
192 (void)comm;
193 vec.reinit(block_structure);
194 }
195 }
196
214 template <typename VectorType, typename Fn>
215 void compute_variables_into(VectorType &dst, VectorType &scratch, Fn &&compute)
216 {
217 if constexpr (!is_distributed_la<VectorType>) {
218 (void)scratch;
219 compute(dst);
220 } else {
221 scratch = 0;
222 compute(scratch);
223 // The model wrote through VectorBase::operator(), which stages rather than stores.
224 scratch.compress(dealii::VectorOperation::insert);
225 for (const auto i : dst.locally_owned_elements())
226 dst(i) = scratch(i);
227 dst.compress(dealii::VectorOperation::insert);
228 }
229 }
230
234 template <typename VectorType>
235 void reinit_local_variables_vector(VectorType &vec, const dealii::types::global_dof_index n_vars)
236 {
237 if constexpr (is_distributed_la<VectorType>) {
238 if (n_vars > 0) vec.reinit(dealii::complete_index_set(n_vars), MPI_COMM_SELF);
239 } else {
240 vec.reinit(n_vars);
241 }
242 }
243
260 template <typename VectorType, typename NumberType>
261 void dense_vmult_variables(const dealii::FullMatrix<NumberType> &matrix, VectorType &dst, const VectorType &src,
262 MPI_Comm comm)
263 {
264 if constexpr (!is_distributed_la<VectorType>) {
265 (void)comm;
266 matrix.vmult(dst, src);
267 } else {
268 const auto n = src.size();
269 dealii::Vector<NumberType> local_src(n), local_dst(n);
270
271 const auto owned = src.locally_owned_elements();
272 for (const auto i : owned)
273 local_src[i] = src(i);
274 MPI::bcast(comm, local_src.data(), static_cast<size_t>(n) * sizeof(NumberType), /*root=*/0);
275
276 matrix.vmult(local_dst, local_src);
277
278 for (const auto i : dst.locally_owned_elements())
279 dst(i) = local_dst[i];
280 dst.compress(dealii::VectorOperation::insert);
281 }
282 }
283} // namespace DiFfRG
A read-only, fully-replicated view of the solution.
Definition solution_view.hh:48
void reinit(const dealii::IndexSet &, const dealii::IndexSet &, MPI_Comm)
Establish the layout. No-op for the serial policy.
Definition solution_view.hh:58
All compile-time knowledge about which linear algebra types DiFfRG uses.
uint rank(MPI_Comm comm)
void bcast(MPI_Comm comm, void *data, size_t bytes, uint root=0)
Broadcast raw bytes from root to all ranks.
typename internal::_SparsityPattern< SparseMatrixType >::value SparsityPattern
Definition linear_algebra.hh:155
Definition complex_math.hh:10
constexpr bool is_distributed_la
Whether a linear algebra type distributes its rows across MPI ranks.
Definition linear_algebra.hh:188
void reinit_variables_view(SolutionView< VectorType > &view, const dealii::types::global_dof_index n_vars, MPI_Comm comm)
Establish the layout of a fully-replicated view of the extra-variables block.
Definition la_policy.hh:147
void dense_vmult_variables(const dealii::FullMatrix< NumberType > &matrix, VectorType &dst, const VectorType &src, MPI_Comm comm)
Apply a dense matrix to the extra-variables block.
Definition la_policy.hh:261
void reinit_la_variables_vector(VectorType &vec, const dealii::types::global_dof_index n_vars, MPI_Comm comm)
Size a standalone vector holding only the extra variables.
Definition la_policy.hh:157
void reinit_local_variables_vector(VectorType &vec, const dealii::types::global_dof_index n_vars)
Size a process-local vector holding every extra variable on every rank.
Definition la_policy.hh:235
dealii::IndexSet restrict_to_owned(const dealii::IndexSet &global_set, const dealii::IndexSet &locally_owned)
Restrict a global index set to what this rank may write.
Definition la_policy.hh:114
void compute_variables_into(VectorType &dst, VectorType &scratch, Fn &&compute)
Run a model's variables computation and land the result in the distributed block.
Definition la_policy.hh:215
void reinit_la_matrix(SparseMatrixType &matrix, const get_type::SparsityPattern< SparseMatrixType > &pattern, const dealii::IndexSet &locally_owned, MPI_Comm comm)
Size a matrix from a finalized sparsity pattern.
Definition la_policy.hh:92
dealii::IndexSet variables_owner_set(const dealii::types::global_dof_index n_vars, MPI_Comm comm)
The ownership set for the extra-variables block: everything on rank 0, nothing elsewhere.
Definition la_policy.hh:131
void reinit_la_vector(VectorType &vec, const dealii::IndexSet &locally_owned, MPI_Comm comm)
Size a vector to the rank's share of the rows.
Definition la_policy.hh:27
void finalize_la_sparsity(dealii::DynamicSparsityPattern &dsp, get_type::SparsityPattern< SparseMatrixType > &pattern, const dealii::IndexSet &locally_owned, const dealii::IndexSet &locally_relevant, MPI_Comm comm)
Turn a freshly built DynamicSparsityPattern into the pattern type the matrix wants.
Definition la_policy.hh:50
void reinit_la_block_vector(BlockVectorType &vec, const std::vector< uint > &block_structure, const dealii::IndexSet &locally_owned, MPI_Comm comm)
Size a block vector: block 0 is the FE dofs, block 1 (if present) the extra variables.
Definition la_policy.hh:183