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

DiFfRG: /home/runner/work/DiFfRG_current/DiFfRG_current/DiFfRG/include/DiFfRG/common/linear_algebra.hh Source File
DiFfRG
Discretization Framework for functional Renormalization Group flows
linear_algebra.hh
Go to the documentation of this file.
1#pragma once
2
3// external libraries
4#include <deal.II/base/config.h>
5#include <deal.II/lac/block_sparse_matrix.h>
6#include <deal.II/lac/block_sparsity_pattern.h>
7#include <deal.II/lac/block_vector.h>
8#include <deal.II/lac/dynamic_sparsity_pattern.h>
9#include <deal.II/lac/sparse_direct.h>
10#include <deal.II/lac/sparse_matrix.h>
11#include <deal.II/lac/vector.h>
12
13// The distributed linear algebra is PETSc-backed. deal.II ships these headers
14// unconditionally but leaves them empty without PETSc, so guard on the feature
15// macro (defined by deal.II/base/config.h above) rather than on their presence.
16#ifdef DEAL_II_WITH_PETSC
17#include <deal.II/lac/petsc_block_sparse_matrix.h>
18#include <deal.II/lac/petsc_block_vector.h>
19#include <deal.II/lac/petsc_sparse_matrix.h>
20#include <deal.II/lac/petsc_vector.h>
21#endif
22
23#ifdef DEAL_II_WITH_MPI
24#include <deal.II/distributed/shared_tria.h>
25#endif
26#include <deal.II/grid/tria.h>
27
28// std
29#include <type_traits>
30
49namespace DiFfRG
50{
51 namespace get_type
52 {
53 namespace internal
54 {
55 //--------------------------------------------------
56 // Hidden unspecified type helpers
57 //--------------------------------------------------
58
59 template <typename VectorType> struct _NumberType;
60
61 template <typename SparseMatrixType> struct _SparsityPattern;
62
63 template <typename SparseMatrixType> struct _InverseSparseMatrixType;
64
65 template <typename VectorType> struct _BlockVectorType;
66
67 //--------------------------------------------------
68 // Specified type helpers for standard vectors
69 //--------------------------------------------------
70
71 template <typename NT> struct _NumberType<dealii::Vector<NT>> {
72 using value = NT;
73 };
74 template <typename NT> struct _SparsityPattern<dealii::SparseMatrix<NT>> {
75 using value = dealii::SparsityPattern;
76 };
77 template <typename NT> struct _InverseSparseMatrixType<dealii::SparseMatrix<NT>> {
78 using value = dealii::SparseDirectUMFPACK;
79 };
80
81 //--------------------------------------------------
82 // Specified type helpers for block vectors
83 //--------------------------------------------------
84
85 template <typename NT> struct _NumberType<dealii::BlockVector<NT>> {
86 using value = NT;
87 };
88 template <typename NT> struct _SparsityPattern<dealii::BlockSparseMatrix<NT>> {
89 using value = dealii::BlockSparsityPattern;
90 };
91 template <typename NT> struct _InverseSparseMatrixType<dealii::BlockSparseMatrix<NT>> {
92 using value = dealii::SparseDirectUMFPACK;
93 };
94
95 template <typename NT> struct _BlockVectorType<dealii::Vector<NT>> {
96 using value = dealii::BlockVector<NT>;
97 };
98 template <typename NT> struct _BlockVectorType<dealii::BlockVector<NT>> {
99 using value = dealii::BlockVector<NT>;
100 };
101
102 //--------------------------------------------------
103 // Specified type helpers for distributed (PETSc) vectors
104 //--------------------------------------------------
105 //
106 // PETSc's vectors are not templated on the number type -- PetscScalar is fixed
107 // at PETSc configure time -- so these are full specializations and the number
108 // type is read off the vector itself.
109 //
110 // Note what is deliberately NOT specialized here:
111 //
112 // * _InverseSparseMatrixType. It exists only to give the *explicit* steppers
113 // (explicit_euler, boost_rk, boost_abm) a mass-matrix inverse, and those are
114 // not instantiated for PETSc -- they are not viable for these stiff flows and
115 // they route through common/eigen.hh, which assumes contiguous serial storage.
116 // Leaving it unspecialized turns an accidental instantiation into a clear
117 // "incomplete type" error instead of silently selecting a serial UMFPACK.
118 //
119 // * A preconditioner trait for GMRES.hh's `PreconditionJacobi<SparseMatrixType>`
120 // default, which does not exist for PETSc matrices. None is needed: a default
121 // template argument is only instantiated when used, and the PETSc timestepper
122 // instantiations use PETScKrylov/PETScDirect, never GMRES or ScaledGMRES.
123#ifdef DEAL_II_WITH_PETSC
124 template <> struct _NumberType<dealii::PETScWrappers::MPI::Vector> {
125 using value = dealii::PETScWrappers::MPI::Vector::value_type;
126 };
127 template <> struct _NumberType<dealii::PETScWrappers::MPI::BlockVector> {
128 using value = dealii::PETScWrappers::MPI::BlockVector::value_type;
129 };
130
131 // A PETSc matrix owns its sparsity internally and is reinit'ed from a
132 // DynamicSparsityPattern plus IndexSets (petsc_sparse_matrix.h:510), so there is
133 // no persistent SparsityPattern object to hand back. Assemblers therefore keep
134 // the DynamicSparsityPattern they build alive instead of discarding it after
135 // copy_from().
136 template <> struct _SparsityPattern<dealii::PETScWrappers::MPI::SparseMatrix> {
137 using value = dealii::DynamicSparsityPattern;
138 };
139 template <> struct _SparsityPattern<dealii::PETScWrappers::MPI::BlockSparseMatrix> {
140 using value = dealii::BlockDynamicSparsityPattern;
141 };
142
143 template <> struct _BlockVectorType<dealii::PETScWrappers::MPI::Vector> {
144 using value = dealii::PETScWrappers::MPI::BlockVector;
145 };
146 template <> struct _BlockVectorType<dealii::PETScWrappers::MPI::BlockVector> {
147 using value = dealii::PETScWrappers::MPI::BlockVector;
148 };
149#endif
150 } // namespace internal
151
152 template <typename VectorType> using NumberType = typename internal::_NumberType<VectorType>::value;
153
154 template <typename SparseMatrixType>
156
157 template <typename SparseMatrixType>
159
167 template <typename VectorType> using BlockVectorType = typename internal::_BlockVectorType<VectorType>::value;
168 } // namespace get_type
169
178 template <typename VectorType>
179 concept SupportedVectorType = requires { typename get_type::internal::_NumberType<VectorType>::value; };
180
188 template <typename T> inline constexpr bool is_distributed_la = false;
189
190#ifdef DEAL_II_WITH_PETSC
191 template <> inline constexpr bool is_distributed_la<dealii::PETScWrappers::MPI::Vector> = true;
192 template <> inline constexpr bool is_distributed_la<dealii::PETScWrappers::MPI::BlockVector> = true;
193 template <> inline constexpr bool is_distributed_la<dealii::PETScWrappers::MPI::SparseMatrix> = true;
194 template <> inline constexpr bool is_distributed_la<dealii::PETScWrappers::MPI::BlockSparseMatrix> = true;
195#endif
196
197 // ##############################################################################
198 // Build-configuration defaults
199 // ##############################################################################
200 //
201 // An MPI build defaults to distributed linear algebra on a partitioned mesh; a
202 // serial build defaults to what it always did. Both halves of that choice -- the
203 // triangulation and the vector/matrix pair -- must flip together, because a
204 // distributed vector partitions its rows by rank ownership and that only exists
205 // once the mesh has been partitioned.
206 //
207 // The condition is spelled once, here, and reused by rectangular_mesh.hh. Do not
208 // re-derive it from DEAL_II_WITH_MPI alone: PETSc supplies the distributed vectors,
209 // so an MPI-without-PETSc build must stay fully serial. Gating the mesh on MPI and
210 // the vectors on PETSc would give that build a partitioned mesh with serial vectors,
211 // which every static_assert accepts and which then assembles each rank's cells into
212 // a full-size vector that is never summed.
213
214#if defined(DEAL_II_WITH_MPI) && defined(DEAL_II_WITH_PETSC)
215#define DIFFRG_DEFAULT_LA_DISTRIBUTED 1
216#endif
217
218#ifdef DIFFRG_DEFAULT_LA_DISTRIBUTED
219 template <int dim> using DefaultTriangulation = dealii::parallel::shared::Triangulation<dim>;
220#else
221 template <int dim> using DefaultTriangulation = dealii::Triangulation<dim>;
222#endif
223
224 // ##############################################################################
225 // The linear algebra that goes with a mesh
226 // ##############################################################################
227 //
228 // A Discretization takes both a mesh and a vector/matrix pair, and the two must
229 // agree: a distributed vector partitions its rows by rank ownership, which only
230 // exists once the mesh is partitioned. Both directions of disagreement are wrong,
231 // and the Discretizations static_assert against both.
232 //
233 // So derive the pair from the mesh rather than from the build configuration. That
234 // makes the mesh the single dial: naming RectangularMeshSerial<dim> pins serial
235 // linear algebra with it, which is what a test compared against a stored reference
236 // needs in an MPI build tree. Defaulting the pair to the *build* configuration
237 // instead made that pin silently insufficient -- the mesh went serial while the
238 // vectors stayed PETSc, and the mismatch only surfaced as a static_assert naming
239 // the mesh, not the vectors the caller never mentioned.
240 //
241 // A plain RectangularMesh<dim> still follows the build configuration, because its
242 // own default triangulation does; nothing about the defaulted spelling changes.
243
244#ifdef DIFFRG_DEFAULT_LA_DISTRIBUTED
245 template <typename Mesh, typename NumberType>
246 using LAVectorFor =
247 std::conditional_t<Mesh::is_parallel, dealii::PETScWrappers::MPI::Vector, dealii::Vector<NumberType>>;
248 template <typename Mesh, typename NumberType>
249 using LASparseMatrixFor =
250 std::conditional_t<Mesh::is_parallel, dealii::PETScWrappers::MPI::SparseMatrix, dealii::SparseMatrix<NumberType>>;
251#else
252 // Without PETSc there is no distributed vector to select, so the pair is serial
253 // whatever the mesh says. A partitioned mesh is still nameable in an MPI-without-PETSc
254 // build; the Discretization's static_assert rejects that combination rather than
255 // letting it assemble per-rank cells into a full-size vector nothing ever sums.
256 template <typename Mesh, typename NumberType> using LAVectorFor = dealii::Vector<NumberType>;
257 template <typename Mesh, typename NumberType> using LASparseMatrixFor = dealii::SparseMatrix<NumberType>;
258#endif
259} // namespace DiFfRG
A vector type DiFfRG's timesteppers and assemblers can work with.
Definition linear_algebra.hh:179
typename internal::_NumberType< VectorType >::value NumberType
Definition linear_algebra.hh:152
typename internal::_SparsityPattern< SparseMatrixType >::value SparsityPattern
Definition linear_algebra.hh:155
typename internal::_BlockVectorType< VectorType >::value BlockVectorType
The block-vector type belonging to a given vector type.
Definition linear_algebra.hh:167
typename internal::_InverseSparseMatrixType< SparseMatrixType >::value InverseSparseMatrixType
Definition linear_algebra.hh:158
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
dealii::Vector< NumberType > LAVectorFor
Definition linear_algebra.hh:256
dealii::Triangulation< dim > DefaultTriangulation
Definition linear_algebra.hh:221
dealii::SparseMatrix< NumberType > LASparseMatrixFor
Definition linear_algebra.hh:257
dealii::BlockVector< NT > value
Definition linear_algebra.hh:99
dealii::BlockVector< NT > value
Definition linear_algebra.hh:96
Definition linear_algebra.hh:65
dealii::SparseDirectUMFPACK value
Definition linear_algebra.hh:92
dealii::SparseDirectUMFPACK value
Definition linear_algebra.hh:78
Definition linear_algebra.hh:59
dealii::BlockSparsityPattern value
Definition linear_algebra.hh:89
dealii::SparsityPattern value
Definition linear_algebra.hh:75
Definition linear_algebra.hh:61