Smith  0.1
Smith is an implicit thermal structural mechanics simulation code.
block_preconditioner.hpp
1 #pragma once
2 
3 #include <memory>
4 #include <functional>
5 #include "mfem.hpp"
6 
7 namespace smith {
8 
18 using BlockOverride = std::pair<int, std::unique_ptr<const mfem::Operator>>;
19 
30 class BlockDiagonalPreconditioner : public mfem::Solver {
31  public:
40  BlockDiagonalPreconditioner(mfem::Array<int>& offsets, std::vector<std::unique_ptr<mfem::Solver>> solvers,
41  std::vector<BlockOverride> overrides = {});
42 
49  virtual void Mult(const mfem::Vector& in, mfem::Vector& out) const;
50 
56  virtual void SetOperator(const mfem::Operator& jacobian);
57 
58  virtual ~BlockDiagonalPreconditioner();
59 
60  private:
61  // Offsets for extracting block vector segments
62  mfem::Array<int>& block_offsets_;
63 
64  // Number of blocks
65  const int num_blocks_;
66 
67  // Jacobian view for block access
68  const mfem::BlockOperator* block_jacobian_;
69 
70  // The diagonal part of the preconditioner containing BoomerAMG applications
71  mfem::BlockOperator solver_diag_;
72 
73  // mfem solvers for each block
74  mutable std::vector<std::unique_ptr<mfem::Solver>> mfem_solvers_;
75 
76  // size num_blocks_, nullptr means "use Jacobian diagonal block"
77  std::vector<std::unique_ptr<const mfem::Operator>> block_op_overrides_;
78 };
79 
85 {
86  Lower,
87  Upper,
88  Symmetric
89 };
90 
101 class BlockTriangularPreconditioner : public mfem::Solver {
102  public:
112  BlockTriangularPreconditioner(mfem::Array<int>& offsets, std::vector<std::unique_ptr<mfem::Solver>> solvers,
114  std::vector<BlockOverride> overrides = {});
115 
122  virtual void Mult(const mfem::Vector& in, mfem::Vector& out) const;
123 
129  virtual void SetOperator(const mfem::Operator& jacobian);
130 
132 
133  private:
134  // Offsets for extracting block vector segments
135  mfem::Array<int>& block_offsets_;
136 
137  // Number of blocks
138  const int num_blocks_;
139 
140  // Jacobian view for block access
141  const mfem::BlockOperator* block_jacobian_;
142 
143  // mfem solvers for each block
144  mutable std::vector<std::unique_ptr<mfem::Solver>> mfem_solvers_;
145 
146  // Block Triangular type
147  BlockTriangularType type_;
148 
155  void LowerSweep(const mfem::Vector& in, mfem::Vector& out) const;
156 
163  void UpperSweep(const mfem::Vector& in, mfem::Vector& out) const;
164 
165  // size num_blocks_, nullptr means "use Jacobian diagonal block"
166  std::vector<std::unique_ptr<const mfem::Operator>> block_op_overrides_;
167 };
168 
173 enum class BlockSchurType
174 {
175  Diagonal,
176  Lower,
177  Upper,
178  Full
179 };
180 
185 enum class SchurApproxType
186 {
187  DiagInv,
188  A22Only,
189  Custom,
190 };
191 
200 class BlockSchurPreconditioner : public mfem::Solver {
201  public:
214  BlockSchurPreconditioner(mfem::Array<int>& offsets, std::vector<std::unique_ptr<mfem::Solver>> solvers,
217  std::vector<BlockOverride> overrides = {});
218 
225  virtual void Mult(const mfem::Vector& in, mfem::Vector& out) const;
226 
234  virtual void SetOperator(const mfem::Operator& jacobian);
235 
236  virtual ~BlockSchurPreconditioner();
237 
238  private:
239  // Offsets for extracting block vector segments
240  mfem::Array<int>& block_offsets_;
241 
242  // Jacobian view for block access
243  const mfem::BlockOperator* block_jacobian_;
244 
245  // The diagonal part of the preconditioner containing BoomerAMG applications
246  mfem::BlockOperator solver_diag_;
247 
248  // mfem solvers for each block
249  mutable std::vector<std::unique_ptr<mfem::Solver>> mfem_solvers_;
250 
251  // Views of the linearized Jacobian blocks
252  const mfem::Operator* A_12_ = nullptr;
253  const mfem::Operator* A_21_ = nullptr;
254 
255  // Schur complement approximation operator used by solver for block (1,1).
256  //
257  // For DiagInv and A22Only, the approximation is rebuilt on each SetOperator call and stored in
258  // S_approx_owned_. For Custom, the approximation is provided via block_op_overrides_[1] and referenced
259  // non-owningly via S_approx_view_.
260  mutable std::unique_ptr<const mfem::Operator> S_approx_owned_;
261  const mfem::Operator* S_approx_view_ = nullptr;
262 
263  BlockSchurType type_;
264 
265  SchurApproxType approxType_;
266 
273  void LowerBlock(const mfem::Vector& in, mfem::Vector& out) const;
274 
281  void UpperBlock(const mfem::Vector& in, mfem::Vector& out) const;
282 
283  // size num_blocks_, nullptr means "use Jacobian diagonal block"
284  std::vector<std::unique_ptr<const mfem::Operator>> block_op_overrides_;
285 
286  mfem::HypreParMatrix* BuildSchurDiagApprox_(const mfem::HypreParMatrix& A11, const mfem::HypreParMatrix& A12,
287  const mfem::HypreParMatrix& A21, const mfem::HypreParMatrix& A22) const;
288 };
289 } // namespace smith
Simple block diagonal preconditioner for block systems.
BlockDiagonalPreconditioner(mfem::Array< int > &offsets, std::vector< std::unique_ptr< mfem::Solver >> solvers, std::vector< BlockOverride > overrides={})
Construct a new N by N block diagonal preconditioner.
virtual void Mult(const mfem::Vector &in, mfem::Vector &out) const
The action of the precondition on the block vector (b_1, ..., b_n)
virtual void SetOperator(const mfem::Operator &jacobian)
Set the preconditioner to use the supplied linearized block Jacobian.
Simple 2x2 block Schur complement preconditioner for block systems.
virtual void Mult(const mfem::Vector &in, mfem::Vector &out) const
The action of the precondition on the block vector (b_1, b_2)
BlockSchurPreconditioner(mfem::Array< int > &offsets, std::vector< std::unique_ptr< mfem::Solver >> solvers, BlockSchurType type=BlockSchurType::Diagonal, SchurApproxType approxType=SchurApproxType::DiagInv, std::vector< BlockOverride > overrides={})
Construct a new 2x2 block Schur complement preconditioner.
virtual void SetOperator(const mfem::Operator &jacobian)
Set the preconditioner to use the supplied linearized block Jacobian.
Simple block triangular preconditioner for block systems.
BlockTriangularPreconditioner(mfem::Array< int > &offsets, std::vector< std::unique_ptr< mfem::Solver >> solvers, BlockTriangularType type=BlockTriangularType::Lower, std::vector< BlockOverride > overrides={})
Construct a new nxn block triangular preconditioner.
virtual void Mult(const mfem::Vector &in, mfem::Vector &out) const
The action of the precondition on the block vector (b_1, ..., b_n)
virtual void SetOperator(const mfem::Operator &jacobian)
Set the preconditioner to use the supplied linearized block Jacobian.
Accelerator functionality.
Definition: smith.cpp:36
SchurApproxType
Selects how the (1,1) Schur operator is approximated.
constexpr SMITH_HOST_DEVICE auto type(const tuple< T... > &values)
a function intended to be used for extracting the ith type from a tuple.
Definition: tuple.hpp:376
BlockTriangularType
Selects the block triangular sweep used by BlockTriangularPreconditioner.
BlockSchurType
Selects the block Schur preconditioner variant.
std::pair< int, std::unique_ptr< const mfem::Operator > > BlockOverride
Optional override for a diagonal block operator.