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 <vector>
6 #include "mfem.hpp"
7 
8 namespace smith {
9 
19 using BlockOverride = std::pair<int, std::unique_ptr<const mfem::Operator>>;
20 
31 class BlockDiagonalPreconditioner : public mfem::Solver {
32  public:
40  BlockDiagonalPreconditioner(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, populated by SetOperator().
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  std::unique_ptr<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:
111  BlockTriangularPreconditioner(std::vector<std::unique_ptr<mfem::Solver>> solvers,
113  std::vector<BlockOverride> overrides = {});
114 
121  virtual void Mult(const mfem::Vector& in, mfem::Vector& out) const;
122 
128  virtual void SetOperator(const mfem::Operator& jacobian);
129 
131 
132  private:
133  // Offsets for extracting block vector segments, populated by SetOperator().
134  mfem::Array<int> block_offsets_;
135 
136  // Number of blocks
137  const int num_blocks_;
138 
139  // Jacobian view for block access
140  const mfem::BlockOperator* block_jacobian_;
141 
142  // mfem solvers for each block
143  mutable std::vector<std::unique_ptr<mfem::Solver>> mfem_solvers_;
144 
145  // Block Triangular type
146  BlockTriangularType type_;
147 
154  void LowerSweep(const mfem::Vector& in, mfem::Vector& out) const;
155 
162  void UpperSweep(const mfem::Vector& in, mfem::Vector& out) const;
163 
164  // size num_blocks_, nullptr means "use Jacobian diagonal block"
165  std::vector<std::unique_ptr<const mfem::Operator>> block_op_overrides_;
166 };
167 
172 enum class BlockSchurType
173 {
174  Diagonal,
175  Lower,
176  Upper,
177  Full
178 };
179 
184 enum class SchurApproxType
185 {
186  DiagInv,
187  A22Only,
188  Custom,
189 };
190 
199 class BlockSchurPreconditioner : public mfem::Solver {
200  public:
212  BlockSchurPreconditioner(std::vector<std::unique_ptr<mfem::Solver>> solvers,
215  std::vector<BlockOverride> overrides = {});
216 
223  virtual void Mult(const mfem::Vector& in, mfem::Vector& out) const;
224 
232  virtual void SetOperator(const mfem::Operator& jacobian);
233 
234  virtual ~BlockSchurPreconditioner();
235 
236  private:
237  // Offsets for extracting block vector segments, populated by SetOperator().
238  mfem::Array<int> block_offsets_;
239 
240  // Jacobian view for block access
241  const mfem::BlockOperator* block_jacobian_;
242 
243  // The diagonal part of the preconditioner containing BoomerAMG applications
244  std::unique_ptr<mfem::BlockOperator> solver_diag_;
245 
246  // mfem solvers for each block
247  mutable std::vector<std::unique_ptr<mfem::Solver>> mfem_solvers_;
248 
249  // Views of the linearized Jacobian blocks
250  const mfem::Operator* A_12_ = nullptr;
251  const mfem::Operator* A_21_ = nullptr;
252 
253  // Schur complement approximation operator used by solver for block (1,1).
254  //
255  // For DiagInv and A22Only, the approximation is rebuilt on each SetOperator call and stored in
256  // S_approx_owned_. For Custom, the approximation is provided via block_op_overrides_[1] and referenced
257  // non-owningly via S_approx_view_.
258  mutable std::unique_ptr<const mfem::Operator> S_approx_owned_;
259  const mfem::Operator* S_approx_view_ = nullptr;
260 
261  BlockSchurType type_;
262 
263  SchurApproxType approxType_;
264 
271  void LowerBlock(const mfem::Vector& in, mfem::Vector& out) const;
272 
279  void UpperBlock(const mfem::Vector& in, mfem::Vector& out) const;
280 
281  // size num_blocks_, nullptr means "use Jacobian diagonal block"
282  std::vector<std::unique_ptr<const mfem::Operator>> block_op_overrides_;
283 
284  mfem::HypreParMatrix* BuildSchurDiagApprox_(const mfem::HypreParMatrix& A11, const mfem::HypreParMatrix& A12,
285  const mfem::HypreParMatrix& A21, const mfem::HypreParMatrix& A22) const;
286 };
287 } // namespace smith
Simple block diagonal 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_n)
virtual void SetOperator(const mfem::Operator &jacobian)
Set the preconditioner to use the supplied linearized block Jacobian.
BlockDiagonalPreconditioner(std::vector< std::unique_ptr< mfem::Solver >> solvers, std::vector< BlockOverride > overrides={})
Construct a new N by N block diagonal preconditioner.
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)
virtual void SetOperator(const mfem::Operator &jacobian)
Set the preconditioner to use the supplied linearized block Jacobian.
BlockSchurPreconditioner(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.
Simple block triangular 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_n)
BlockTriangularPreconditioner(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 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.
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.