Fluid structure interaction suite
inverse_operator.h
Go to the documentation of this file.
1 // ---------------------------------------------------------------------
2 //
3 // Copyright (C) 2022 by Luca Heltai
4 //
5 // This file is part of the FSI-suite platform, based on the deal.II library.
6 //
7 // The FSI-suite platform is free software; you can use it, redistribute it,
8 // and/or modify it under the terms of the GNU Lesser General Public License as
9 // published by the Free Software Foundation; either version 3.0 of the License,
10 // or (at your option) any later version. The full text of the license can be
11 // found in the file LICENSE at the top level of the FSI-suite platform
12 // distribution.
13 //
14 // ---------------------------------------------------------------------
15 
16 #ifndef inverse_opeator_h
17 #define inverse_opeator_h
18 
19 #include <deal.II/base/config.h>
20 
22 
24 
26 #include <deal.II/lac/solver.h>
28 #include <deal.II/lac/solver_cg.h>
34 
35 namespace ParsedLAC
36 {
41  enum class SolverControlType
42  {
43  tolerance = 1 << 0,
44  consecutive_iterations = 1 << 1,
45  iteration_number = 1 << 2,
46  reduction = 1 << 3,
47  };
48 
89  class InverseOperator : public dealii::ParameterAcceptor
90  {
91  public:
115  const std::string &section_name = "",
116  const std::string &default_solver = "cg",
118  const unsigned int max_iterations = 1000,
119  const double tolerance = 1e-12,
120  const double reduction = 1e-6,
121  const unsigned int consecutive_iterations = 2,
122  const bool &log_history = false,
123  const bool &log_result = false);
124 
136  template <typename Domain,
137  typename Payload,
138  typename PreconditionerType,
139  typename Range = Domain>
140  dealii::LinearOperator<Domain, Range, Payload>
141  operator()(const dealii::LinearOperator<Range, Domain, Payload> &op,
142  const PreconditionerType &prec,
143  const double abs_tol = 0.0,
144  const std::string &prefix = "") const;
145 
155  template <typename Range,
156  typename Payload =
157  dealii::internal::LinearOperatorImplementation::EmptyPayload,
158  typename Domain = Range,
159  typename MatrixType,
160  typename PreconditionerType>
161  dealii::LinearOperator<Range, Domain, Payload>
162  solver(const MatrixType &op,
163  const PreconditionerType &prec,
164  const double abs_tol = 0.0,
165  const std::string &prefix = "") const;
166 
167 
174  template <typename MatrixType,
175  typename PreconditionerType,
176  typename VectorType>
177  void
178  solve(const MatrixType &matrix,
179  const PreconditionerType &preconditioner,
180  const VectorType &src,
181  VectorType &dst,
182  const double abs_tol = 0.0) const;
183 
184 
188  std::string
189  get_solver_name() const;
190 
196  std::unique_ptr<dealii::SolverControl>
197  setup_new_solver_control(const double abs_tol = 0.0) const;
198 
204  template <typename Range, typename Payload>
205  std::shared_ptr<dealii::SolverBase<Range>>
206  setup_new_solver(const double abs_tol = 0.0) const;
207 
208  private:
213 
217  mutable std::unique_ptr<dealii::SolverControl> control;
218 
222  std::string solver_name;
223 
228  unsigned int max_iterations;
229 
234 
239  double tolerance;
240 
245  double reduction;
246 
251 
256 
260  mutable dealii::GeneralDataStorage storage;
261  };
262 
263 
264 #ifndef DOXYGEN
265  // ============================================================
266  // Explicit template instantiation
267  // ============================================================
268  template <typename MatrixType,
269  typename PreconditionerType,
270  typename VectorType>
271  void
272  InverseOperator::solve(const MatrixType &matrix,
273  const PreconditionerType &preconditioner,
274  const VectorType &src,
275  VectorType &dst,
276  const double abs_tol) const
277  {
279  if (solver_name == "cg")
280  {
281  dealii::SolverCG<VectorType> solver(*control);
282  solver.solve(matrix, dst, src, preconditioner);
283  }
284  else if (solver_name == "bicgstab")
285  {
286  dealii::SolverBicgstab<VectorType> solver(*control);
287  solver.solve(matrix, dst, src, preconditioner);
288  }
289  else if (solver_name == "gmres")
290  {
291  dealii::SolverGMRES<VectorType> solver(*control);
292  solver.solve(matrix, dst, src, preconditioner);
293  }
294  else if (solver_name == "fgmres")
295  {
296  dealii::SolverFGMRES<VectorType> solver(*control);
297  solver.solve(matrix, dst, src, preconditioner);
298  }
299  else if (solver_name == "minres")
300  {
301  dealii::SolverMinRes<VectorType> solver(*control);
302  solver.solve(matrix, dst, src, preconditioner);
303  }
304  else if (solver_name == "qmrs")
305  {
306  dealii::SolverQMRS<VectorType> solver(*control);
307  solver.solve(matrix, dst, src, preconditioner);
308  }
309  else if (solver_name == "richardson")
310  {
311  dealii::SolverRichardson<VectorType> solver(*control);
312  solver.solve(matrix, dst, src, preconditioner);
313  }
314  else
315  {
316  Assert(false,
317  dealii::ExcInternalError("Solver should not be unknonw."));
318  }
319  }
320 
321 
322  template <typename Range,
323  typename Payload,
324  typename Domain,
325  typename MatrixType,
326  typename PreconditionerType>
327  dealii::LinearOperator<Range, Domain, Payload>
328  InverseOperator::solver(const MatrixType &op,
329  const PreconditionerType &prec,
330  const double abs_tol,
331  const std::string &prefix) const
332  {
334 
335  // Make sure the solver itself is left around until the object is
336  // destroyed we need a general storage class, since we have no
337  // idea what types are used when calling this function.
338  using SolverType = std::shared_ptr<dealii::SolverBase<Range>>;
339  auto &solver = storage.template get_or_add_object_with_name<SolverType>(
340  prefix + "solver");
341 
342  dealii::LinearOperator<Range, Domain, Payload> inverse;
343 
344  auto initialize_solver = [&](auto *s) {
345  solver.reset(s);
346  inverse = dealii::inverse_operator(op, *s, prec);
347  };
348 
349  if (solver_name == "cg")
350  {
351  initialize_solver(new dealii::SolverCG<Range>(*control));
352  }
353  else if (solver_name == "bicgstab")
354  {
355  initialize_solver(new dealii::SolverBicgstab<Range>(*control));
356  }
357  else if (solver_name == "gmres")
358  {
359  initialize_solver(new dealii::SolverGMRES<Range>(*control));
360  }
361  else if (solver_name == "fgmres")
362  {
363  initialize_solver(new dealii::SolverFGMRES<Range>(*control));
364  }
365  else if (solver_name == "minres")
366  {
367  initialize_solver(new dealii::SolverMinRes<Range>(*control));
368  }
369  else if (solver_name == "qmrs")
370  {
371  initialize_solver(new dealii::SolverQMRS<Range>(*control));
372  }
373  else if (solver_name == "richardson")
374  {
375  initialize_solver(new dealii::SolverRichardson<Range>(*control));
376  }
377  else
378  {
379  Assert(false,
380  dealii::ExcInternalError("Solver should not be unknonw."));
381  }
382  return inverse;
383  }
384 
385 
386 
387  template <typename Domain,
388  typename Payload,
389  typename PreconditionerType,
390  typename Range>
391  dealii::LinearOperator<Domain, Range, Payload>
393  const dealii::LinearOperator<Range, Domain, Payload> &op,
394  const PreconditionerType &prec,
395  const double abs_tol,
396  const std::string &prefix) const
397  {
398  return solver<Range, Payload>(op, prec, abs_tol, prefix);
399  }
400 #endif
401 } // namespace ParsedLAC
402 
403 
404 #endif
const std::string section_name
A factory that can generate inverse operators according to parameter files.
bool log_result
Log the final result.
void solve(const MatrixType &matrix, const PreconditionerType &preconditioner, const VectorType &src, VectorType &dst, const double abs_tol=0.0) const
Solve using the specified solver, preconditioner, and tolerance.
double tolerance
Default reduction required to succesfully complete a solution step.
std::string get_solver_name() const
Get the solver name.
InverseOperator(const std::string &section_name="", const std::string &default_solver="cg", const SolverControlType &control_type=SolverControlType::tolerance, const unsigned int max_iterations=1000, const double tolerance=1e-12, const double reduction=1e-6, const unsigned int consecutive_iterations=2, const bool &log_history=false, const bool &log_result=false)
Store and parse the parameters that will be needed to create a linear operator that computes the inve...
std::string solver_name
Solver name.
unsigned int consecutive_iterations
Number of consecutive iterations (used only for ConsecutiveControl).
bool log_history
Log the solver history.
double reduction
Default reduction required to succesfully complete a solution step.
LinearOperator< Domain, Range, Payload > operator()(const LinearOperator< Range, Domain, Payload > &op, const PreconditionerType &prec, const double abs_tol=0.0, const std::string &prefix="") const
Create an inverse operator according to the parameters given in the parameter file.
SolverControlType control_type
Defines the behaviour of the solver control.
LinearOperator< Range, Domain, Payload > solver(const MatrixType &op, const PreconditionerType &prec, const double abs_tol=0.0, const std::string &prefix="") const
Create a solver.
std::unique_ptr< SolverControl > setup_new_solver_control(const double abs_tol=0.0) const
Create a new solver control according to the parameters.
std::shared_ptr< SolverBase< Range > > setup_new_solver(const double abs_tol=0.0) const
Create a new solver according to the parameters.
unsigned int max_iterations
Default number of maximum iterations required to succesfully complete a solution step.
GeneralDataStorage storage
Local storage for the actual solver object.
std::unique_ptr< SolverControl > control
Used internally by the solver.
#define Assert(cond, exc)
static ::ExceptionBase & ExcInternalError()
LinearOperator< Domain, Range, Payload > inverse_operator(const LinearOperator< Range, Domain, Payload > &op, Solver &solver, const Preconditioner &preconditioner)
SymmetricTensor< 2, dim, Number > e(const Tensor< 2, dim, Number > &F)
Definition: amg.h:28
SolverControlType
An enum class used to identify different classes derived from SolverControl.
@ iteration_number
Use IterationNumberControl.
@ tolerance
Use SolverControl.
@ reduction
Use ReductionControl.
@ consecutive_iterations
Use ConsecutiveControl.