Commit cba97849 authored by Praetorius, Simon's avatar Praetorius, Simon
Browse files

solver interface compiles and heat runs correctly

parent aa8f19fc
Pipeline #104 skipped
#pragma once #pragma once
#include "linear_algebra/LinearSolverInterface.hpp"
#include "linear_algebra/SolverInfo.hpp"
#if defined(AMDIS_BACKEND_ISTL) #if defined(AMDIS_BACKEND_ISTL)
#include "linear_algebra/istl/SystemVector.hpp" #include "linear_algebra/istl/SystemVector.hpp"
...@@ -11,6 +14,8 @@ ...@@ -11,6 +14,8 @@
#include "linear_algebra/mtl/SystemVector.hpp" #include "linear_algebra/mtl/SystemVector.hpp"
#include "linear_algebra/mtl/SystemMatrix.hpp" #include "linear_algebra/mtl/SystemMatrix.hpp"
#include "linear_algebra/mtl/LinearSolver.hpp" #include "linear_algebra/mtl/LinearSolver.hpp"
#include "linear_algebra/mtl/ITL_Solver.hpp"
#include "linear_algebra/mtl/BITL_Solver.hpp"
#elif defined(AMDIS_BACKEND_PETSC) #elif defined(AMDIS_BACKEND_PETSC)
......
...@@ -61,8 +61,8 @@ namespace AMDiS ...@@ -61,8 +61,8 @@ namespace AMDiS
using SystemMatrixType = SystemMatrix<FeSpaces>; using SystemMatrixType = SystemMatrix<FeSpaces>;
using OperatorType = Operator<MeshView>; using OperatorType = Operator<MeshView>;
using LinearSolverType = LinearSolver<typename SystemMatrixType::MultiMatrix, using LinearSolverType = LinearSolverInterface<typename SystemMatrixType::MultiMatrix,
typename SystemVectorType::MultiVector>; typename SystemVectorType::MultiVector>;
public: public:
/// \brief Constructor. Takes the name of the problem that is used to /// \brief Constructor. Takes the name of the problem that is used to
...@@ -213,7 +213,12 @@ namespace AMDiS ...@@ -213,7 +213,12 @@ namespace AMDiS
// //
void createSolver() void createSolver()
{ {
linearSolver = std::make_shared<LinearSolverType>(name + "->solver"); using Creator = SolverCreator<typename SystemMatrixType::MultiMatrix,
typename SystemVectorType::MultiVector>;
std::string solverName = "cg";
Parameters::get(name + "->solver->name", solverName);
linearSolver = Creator::create(solverName, name + "->solver");
} }
// //
......
...@@ -161,14 +161,39 @@ namespace AMDiS ...@@ -161,14 +161,39 @@ namespace AMDiS
bool storeMatrixData) bool storeMatrixData)
{ {
Timer t; Timer t;
SolverInfo solverInfo(name + "->solver");
solverInfo.setCreateMatrixData(createMatrixData);
solverInfo.setStoreMatrixData(storeMatrixData);
solution->compress(); solution->compress();
linearSolver->solve(adaptInfo, systemMatrix->getMatrix(), linearSolver->solve(systemMatrix->getMatrix(),
solution->getVector(), rhs->getVector()); solution->getVector(), rhs->getVector(),
solverInfo);
AMDIS_MSG("solution of discrete system needed " << t.elapsed() << " seconds"); AMDIS_MSG("solution of discrete system needed " << t.elapsed() << " seconds");
// adaptInfo.setSolverIterations(statistics.iterations); if (solverInfo.getInfo() > 0) {
// adaptInfo.setSolverResidual(statistics.reduction); if (solverInfo.getAbsResidual() >= 0.0) {
if (solverInfo.getRelResidual() >= 0.0)
AMDIS_MSG("Residual norm: ||b-Ax|| = " << solverInfo.getAbsResidual()
<< ", ||b-Ax||/||b|| = " << solverInfo.getRelResidual());
else
AMDIS_MSG("Residual norm: ||b-Ax|| = " << solverInfo.getAbsResidual());
}
}
if (solverInfo.doBreak()) {
std::stringstream tol_str;
if (solverInfo.getAbsTolerance() > 0
&& solverInfo.getAbsResidual() > solverInfo.getAbsTolerance())
tol_str << "absTol = " << solverInfo.getAbsTolerance() << " ";
if (solverInfo.getRelTolerance() > 0
&& solverInfo.getRelResidual() > solverInfo.getRelTolerance())
tol_str << "relTol = " << solverInfo.getRelTolerance() << " ";
AMDIS_ERROR_EXIT("Tolerance " << tol_str.str() << " could not be reached!");
}
} }
......
#pragma once
namespace AMDiS
{
namespace Impl
{
// Type-Trait needs to be specialized by linear algebra libraries
template <class Vector>
struct BaseVector { using type = Vector; };
}
template <class Vector>
using BaseVector = typename Impl::BaseVector<Vector>::type;
} // end namespace AMDiS
...@@ -11,8 +11,11 @@ ...@@ -11,8 +11,11 @@
* systems. * systems.
*/ */
#include <dune/amdis/linear_algebra/Preconditioner.hpp> #include <dune/amdis/linear_algebra/LinearAlgebraBase.hpp>
#include <dune/amdis/linear_algebra/SolverStatistics.hpp>
#include <dune/amdis/linear_algebra/PreconditionerInterface.hpp>
#include <dune/amdis/linear_algebra/RunnerInterface.hpp>
#include <dune/amdis/linear_algebra/SolverInfo.hpp>
namespace AMDiS namespace AMDiS
{ {
...@@ -20,6 +23,11 @@ namespace AMDiS ...@@ -20,6 +23,11 @@ namespace AMDiS
template <class Matrix, class VectorX, class VectorB = VectorX> template <class Matrix, class VectorX, class VectorB = VectorX>
class LinearSolverInterface class LinearSolverInterface
{ {
protected:
using RunnerBase = RunnerInterface<Matrix, BaseVector<VectorX>,
BaseVector<VectorB>>;
public:
/// Destructor. /// Destructor.
virtual ~LinearSolverInterface() {} virtual ~LinearSolverInterface() {}
...@@ -29,21 +37,23 @@ namespace AMDiS ...@@ -29,21 +37,23 @@ namespace AMDiS
* and error estimations at the end. * and error estimations at the end.
* *
* The parameters correspond to * The parameters correspond to
* \p A A block-matrix that represents the system-matrix. * \p A A [block-]matrix that represents the system-matrix.
* \p x A block-vector for the unknown components. * \p x A [block-]vector for the unknown components.
* \p b A block-vector for the right-hand side of the linear system. * \p b A [block-]vector for the right-hand side of the linear system.
**/ **/
void solve(Matrix const& A, VectorX& x, VectorB const& b, void solve(Matrix const& A, VectorX& x, VectorB const& b,
SolverStatistics& statistics) SolverInfo& solverInfo)
{ {
solveImpl(A, x, b, statistics); solveImpl(A, x, b, solverInfo);
} }
// return the runner/worker corresponding to this solver (optional)
virtual std::shared_ptr<RunnerBase> getRunner() {};
private: private:
/// main methods that all solvers must implement /// main methods that all solvers must implement
virtual void solveImpl(Matrix const& A, VectorX& x, VectorB const& b, virtual void solveImpl(Matrix const& A, VectorX& x, VectorB const& b,
SolverStatistics& statistics) = 0; SolverInfo& solverInfo) = 0;
}; };
} // end namespace AMDiS } // end namespace AMDiS
......
...@@ -2,8 +2,8 @@ ...@@ -2,8 +2,8 @@
namespace AMDiS namespace AMDiS
{ {
/// base-class for Preconditioner types /// Interface for Preconditioner types
template <class Matrix, class Vector> template <class Matrix, class VectorX, class VectorB = VectorX>
struct PreconditionerInterface struct PreconditionerInterface
{ {
/// Virtual destructor. /// Virtual destructor.
...@@ -16,10 +16,13 @@ namespace AMDiS ...@@ -16,10 +16,13 @@ namespace AMDiS
virtual void exit() = 0; virtual void exit() = 0;
/// Apply the preconditioner to a vector \p x and store the result in \p y /// Apply the preconditioner to a vector \p x and store the result in \p y
virtual void solve(Vector const& x, Vector& y) const = 0; virtual void solve(VectorX const& x, VectorX& y) const = 0;
/// Apply the transposed preconditioner to a vector \p x and store the result in \p y /// Apply the transposed preconditioner to a vector \p x and store the result in \p y
virtual void adjoint_solve(Vector const& x, Vector& y) const = 0; virtual void adjointSolve(VectorX const& x, VectorX& y) const
{
AMDIS_ERROR_EXIT("Must be implemented by derived class.");
}
}; };
} // end namespace AMDiS } // end namespace AMDiS
#pragma once #pragma once
#include <dune/amdis/linear_algebra/SolverStatistics.hpp> #include <dune/amdis/linear_algebra/SolverInfo.hpp>
namespace AMDiS namespace AMDiS
{ {
/// base-class for Runner / Worker types /// Interface for Runner / Worker types used in solver classes
template <class Matrix, class Vector> template <class Matrix, class VectorX, class VectorB = VectorX>
struct RunnerInterface class RunnerInterface
{ {
// virtual destructor protected:
using PreconBase = PreconditionerInterface<Matrix, VectorX, VectorB>;
public:
/// virtual destructor
virtual ~RunnerInterface() {} virtual ~RunnerInterface() {}
/// Is called at the beginning of a solution procedure /// Is called at the beginning of a solution procedure
...@@ -18,12 +22,19 @@ namespace AMDiS ...@@ -18,12 +22,19 @@ namespace AMDiS
virtual void exit() = 0; virtual void exit() = 0;
/// Solve the system A*x = b /// Solve the system A*x = b
virtual int solve(Matrix const& A, Vector& x, Vector const& b, virtual int solve(Matrix const& A, VectorX& x, VectorB const& b,
SolverStatistics& stat) = 0; SolverInfo& solverInfo) = 0;
/// Solve the adjoint system A^T*x = b /// Solve the adjoint system A^T*x = b
virtual int adjoint_solve(Matrix const& A, Vector& x, Vector const& b, virtual int adjointSolve(Matrix const& A, VectorX& x, VectorB const& b,
SolverStatistics& stat) = 0; SolverInfo& solverInfo)
{
AMDIS_ERROR_EXIT("Must be implemented by derived class.");
return 0;
}
virtual std::shared_ptr<PreconBase> getLeftPrecon() {}
virtual std::shared_ptr<PreconBase> getRightPrecon() {}
}; };
} // end namespace AMDiS } // end namespace AMDiS
...@@ -4,11 +4,12 @@ ...@@ -4,11 +4,12 @@
namespace AMDiS namespace AMDiS
{ {
/// Class that stores information about the solution process, like tolerances
class SolverStatistics /// and iteration counts and is passed to the solver and filled there.
class SolverInfo
{ {
public: public:
/// The constructor reads needed parameters and sets solvers \p prefix. /// The constructor reads needed parameters and sets solver \p prefix.
/** /**
* Reads parameters for a solver with name 'NAME': * Reads parameters for a solver with name 'NAME':
* NAME->absolute tolerance \ref aTol * NAME->absolute tolerance \ref aTol
...@@ -16,8 +17,13 @@ namespace AMDiS ...@@ -16,8 +17,13 @@ namespace AMDiS
* NAME->info \ref info * NAME->info \ref info
* NAME->break if tolerance not reached \ref breakTolNotReached * NAME->break if tolerance not reached \ref breakTolNotReached
**/ **/
explicit SolverStatistics(std::string prefix); explicit SolverInfo(std::string prefix)
{
Parameters::get(prefix + "->abolute tolerance", aTol);
Parameters::get(prefix + "->relative tolerance", rTol);
Parameters::get(prefix + "->info", info);
Parameters::get(prefix + "->break if tolerance not reached", breakTolNotReached);
}
/** \name getting methods /** \name getting methods
* \{ * \{
...@@ -47,10 +53,16 @@ namespace AMDiS ...@@ -47,10 +53,16 @@ namespace AMDiS
return info; return info;
} }
/// Returns \ref residual /// Returns \ref absResidual
double getResidual() const double getAbsResidual() const
{
return absResidual;
}
/// Returns \ref relResidual
double getRelResidual() const
{ {
return residual; return relResidual;
} }
/// Returns the initfile \ref prefix /// Returns the initfile \ref prefix
...@@ -59,6 +71,25 @@ namespace AMDiS ...@@ -59,6 +71,25 @@ namespace AMDiS
return prefix; return prefix;
} }
/// Returns \ref createMatrixData
bool doCreateMatrixData() const
{
return createMatrixData;
}
/// Returns \ref storeMatrixData
bool doStoreMatrixData() const
{
return storeMatrixData;
}
bool doBreak() const
{
return breakTolNotReached && (
(aTol > 1.e-30 && absResidual > aTol) ||
(rTol > 1.e-30 && relResidual > rTol) );
}
/** \} */ /** \} */
...@@ -73,46 +104,83 @@ namespace AMDiS ...@@ -73,46 +104,83 @@ namespace AMDiS
} }
/// Sets \ref rTol /// Sets \ref rTol
void setAbsTolerance(double tol) void setRelTolerance(double tol)
{ {
rTol = tol; rTol = tol;
} }
/// Sets \ref aTol
void setAbsResidual(double r)
{
absResidual = r;
}
/// Sets \ref rTol
void setRelResidual(double r)
{
relResidual = r;
}
/// Sets \ref info /// Sets \ref info
void setInfo(int i) void setInfo(int i)
{ {
info = i; info = i;
} }
/// Sets \ref info /// Sets \ref error
void setError(int e) void setError(int e)
{ {
error = e; error = e;
} }
/// Sets \ref createMatrixData
void setCreateMatrixData(bool b)
{
createMatrixData = b;
}
/// Sets \ref storeMatrixData
void setStoreMatrixData(bool b)
{
storeMatrixData = b;
}
/** \} */ /** \} */
private: private:
/// The initfile prefix to read parameters /// The initfile prefix to read parameters
std::string prefix; std::string prefix;
private:
/// The abolute tolerance /// The abolute tolerance
double aTol = 1.e-6; double aTol = 0;
/// The relative tolerance /// The relative tolerance
double rTol = 0.0; double rTol = 1.e-6;
/// Throw an error if tolerance could not be reached /// Throw an error if tolerance could not be reached
bool breakTolNotReached = true; bool breakTolNotReached = false;
/// The solver verbosity level /// The solver verbosity level
int info = 0; int info = 0;
// some parameters used internally /// The absolute residual, default (-1): not set
double absRresidual = -1.0; double absResidual = -1.0;
/// The relative residual, relative to the two_norm(b), default (-1): not set
double relResidual = -1.0; double relResidual = -1.0;
/// The error-code, default (-1): not set
int error = -1; int error = -1;
/// If true, the matrix will be initialized and the
/// corresponding runner of the system receives the
/// matrix in the init() method.
bool createMatrixData = true;
/// If false, the exit() method of the runner will be called.
bool storeMatrixData = false;
}; };
} // end namespace AMDiS } // end namespace AMDiS
#pragma once
#include <dune/amdis/linear_algebra/mtl/ITL_Preconditioner.hpp>
#include "itl/block_diagonal.hpp"
namespace AMDiS
{
template <class SubMatrix, size_t N, size_t M, class Vector>
struct PreconditionerCreator< BlockMTLMatrix<SubMatrix, N, M>, Vector >
{
using Matrix = BlockMTLMatrix<SubMatrix, N, M>;
using PreconBase = PreconditionerInterface<Matrix, Vector>;
template <template<class> class ITLPrecon>
using Precon = Preconditioner<Matrix, Vector, ITLPrecon<Matrix>>;
static std::unique_ptr<PreconBase> create(std::string name)
{
if (name == "diag" || name == "jacobi")
return std::make_unique<Precon<DiagonalPreconditioner>>();
else // by default, do nothing
return std::make_unique<Precon<IdentityPreconditioner>>();
}
};
} // end namespace AMDiS
#pragma once
#include <dune/amdis/linear_algebra/mtl/ITL_Solver.hpp>
namespace AMDiS
{
template <class SubMatrix, size_t N, size_t M, class Vector>
struct SolverCreator< BlockMTLMatrix<SubMatrix, N, M>, Vector >
{
using Matrix = BlockMTLMatrix<SubMatrix, N, M>;
using SolverBase = LinearSolverInterface<Matrix, Vector, Vector>;
template <class ITLSolver>
using Solver = LinearSolver<Matrix, Vector,
KrylovRunner<ITLSolver, Matrix, BaseVector<Vector>>>;
/// Instantiate a new linear solver
static std::unique_ptr<SolverBase> create(std::string name, std::string prefix)
{
if (name == "cg")
return std::make_unique<Solver<cg_solver_type>>(prefix);
else if (name == "cgs")
return std::make_unique<Solver<cgs_solver_type>>(prefix);
else if (name == "bicgstab" || name == "bcgs")
return std::make_unique<Solver<bicgstab_type>>(prefix);
else if (name == "tfqmr")
return std::make_unique<Solver<tfqmr_solver_type>>(prefix);
else if (name == "bicgstab_ell" || name == "bcgsl")
return std::make_unique<Solver<bicgstab_ell_type>>(prefix);
else if (name == "gmres")
return std::make_unique<Solver<gmres_type>>(prefix);
else if (name == "fgmres")
return std::make_unique<Solver<fgmres_type>>(prefix);
else if (name == "minres")
return std::make_unique<Solver<minres_solver_type>>(prefix);
else if (name == "gcr")
return std::make_unique<Solver<gcr_type>>(prefix);
// else if (name == "preonly")
// return std::make_unique<Solver<preonly_type>>(prefix);
else
AMDIS_ERROR_EXIT("Unknown Solver-name!");
}
};
} // end namespace AMDiS
...@@ -64,7 +64,7 @@ namespace AMDiS ...@@ -64,7 +64,7 @@ namespace AMDiS
VectorOut x_i(x[r_rows[_i]]); VectorOut x_i(x[r_rows[_i]]);
For<0, _M>::loop([this, &b, &x_i, &r_cols, &first, _i](const auto _j) { For<0, _M>::loop([this, &b, &x_i, &r_cols, &first, _i](const auto _j) {
auto const& A_ij = this->operator()(_i, _j); auto const& A_ij = this->operator()(_i, _j);
if (num_rows(block) > 0) { if (num_rows(A_ij) > 0) {
// a reference to the j'th block of b // a reference to the j'th block of b
const VectorIn b_j(b[r_cols[_j]]); const VectorIn b_j(b[r_cols[_j]]);
if (first) {