Liebe Gitlab-Nutzer, lieber Gitlab-Nutzer, es ist nun möglich sich mittels des ZIH-Logins/LDAP an unserem Dienst anzumelden. Ein Anmelden über dieses erzeugt ein neues Konto. Das alte Konto ist über den Reiter "Standard" erreichbar. Die Administratoren

Dear Gitlab user, it is now possible to log in to our service using the ZIH login/LDAP. Logging in via this will create a new account. The old account can be accessed via the "Standard" tab. The administrators

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
#include "linear_algebra/LinearSolverInterface.hpp"
#include "linear_algebra/SolverInfo.hpp"
#if defined(AMDIS_BACKEND_ISTL)
#include "linear_algebra/istl/SystemVector.hpp"
......@@ -11,6 +14,8 @@
#include "linear_algebra/mtl/SystemVector.hpp"
#include "linear_algebra/mtl/SystemMatrix.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)
......
......@@ -61,8 +61,8 @@ namespace AMDiS
using SystemMatrixType = SystemMatrix<FeSpaces>;
using OperatorType = Operator<MeshView>;
using LinearSolverType = LinearSolver<typename SystemMatrixType::MultiMatrix,
typename SystemVectorType::MultiVector>;
using LinearSolverType = LinearSolverInterface<typename SystemMatrixType::MultiMatrix,
typename SystemVectorType::MultiVector>;
public:
/// \brief Constructor. Takes the name of the problem that is used to
......@@ -213,7 +213,12 @@ namespace AMDiS
//
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
bool storeMatrixData)
{
Timer t;
SolverInfo solverInfo(name + "->solver");
solverInfo.setCreateMatrixData(createMatrixData);
solverInfo.setStoreMatrixData(storeMatrixData);
solution->compress();
linearSolver->solve(adaptInfo, systemMatrix->getMatrix(),
solution->getVector(), rhs->getVector());
linearSolver->solve(systemMatrix->getMatrix(),
solution->getVector(), rhs->getVector(),
solverInfo);
AMDIS_MSG("solution of discrete system needed " << t.elapsed() << " seconds");
// adaptInfo.setSolverIterations(statistics.iterations);
// adaptInfo.setSolverResidual(statistics.reduction);
if (solverInfo.getInfo() > 0) {
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 @@
* systems.
*/
#include <dune/amdis/linear_algebra/Preconditioner.hpp>
#include <dune/amdis/linear_algebra/SolverStatistics.hpp>
#include <dune/amdis/linear_algebra/LinearAlgebraBase.hpp>
#include <dune/amdis/linear_algebra/PreconditionerInterface.hpp>
#include <dune/amdis/linear_algebra/RunnerInterface.hpp>
#include <dune/amdis/linear_algebra/SolverInfo.hpp>
namespace AMDiS
{
......@@ -20,6 +23,11 @@ namespace AMDiS
template <class Matrix, class VectorX, class VectorB = VectorX>
class LinearSolverInterface
{
protected:
using RunnerBase = RunnerInterface<Matrix, BaseVector<VectorX>,
BaseVector<VectorB>>;
public:
/// Destructor.
virtual ~LinearSolverInterface() {}
......@@ -29,21 +37,23 @@ namespace AMDiS
* and error estimations at the end.
*
* The parameters correspond to
* \p A A block-matrix that represents the system-matrix.
* \p x A block-vector for the unknown components.
* \p b A block-vector for the right-hand side of the linear system.
* \p A A [block-]matrix that represents the system-matrix.
* \p x A [block-]vector for the unknown components.
* \p b A [block-]vector for the right-hand side of the linear system.
**/
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:
/// main methods that all solvers must implement
virtual void solveImpl(Matrix const& A, VectorX& x, VectorB const& b,
SolverStatistics& statistics) = 0;
SolverInfo& solverInfo) = 0;
};
} // end namespace AMDiS
......
......@@ -2,8 +2,8 @@
namespace AMDiS
{
/// base-class for Preconditioner types
template <class Matrix, class Vector>
/// Interface for Preconditioner types
template <class Matrix, class VectorX, class VectorB = VectorX>
struct PreconditionerInterface
{
/// Virtual destructor.
......@@ -16,10 +16,13 @@ namespace AMDiS
virtual void exit() = 0;
/// 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
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
#pragma once
#include <dune/amdis/linear_algebra/SolverStatistics.hpp>
#include <dune/amdis/linear_algebra/SolverInfo.hpp>
namespace AMDiS
{
/// base-class for Runner / Worker types
template <class Matrix, class Vector>
struct RunnerInterface
/// Interface for Runner / Worker types used in solver classes
template <class Matrix, class VectorX, class VectorB = VectorX>
class RunnerInterface
{
// virtual destructor
protected:
using PreconBase = PreconditionerInterface<Matrix, VectorX, VectorB>;
public:
/// virtual destructor
virtual ~RunnerInterface() {}
/// Is called at the beginning of a solution procedure
......@@ -18,12 +22,19 @@ namespace AMDiS
virtual void exit() = 0;
/// Solve the system A*x = b
virtual int solve(Matrix const& A, Vector& x, Vector const& b,
SolverStatistics& stat) = 0;
virtual int solve(Matrix const& A, VectorX& x, VectorB const& b,
SolverInfo& solverInfo) = 0;
/// Solve the adjoint system A^T*x = b
virtual int adjoint_solve(Matrix const& A, Vector& x, Vector const& b,
SolverStatistics& stat) = 0;
virtual int adjointSolve(Matrix const& A, VectorX& x, VectorB const& b,
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
......@@ -4,11 +4,12 @@
namespace AMDiS
{
class SolverStatistics
/// Class that stores information about the solution process, like tolerances
/// and iteration counts and is passed to the solver and filled there.
class SolverInfo
{
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':
* NAME->absolute tolerance \ref aTol
......@@ -16,8 +17,13 @@ namespace AMDiS
* NAME->info \ref info
* 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
* \{
......@@ -47,10 +53,16 @@ namespace AMDiS
return info;
}
/// Returns \ref residual
double getResidual() const
/// Returns \ref absResidual
double getAbsResidual() const
{
return absResidual;
}
/// Returns \ref relResidual
double getRelResidual() const
{
return residual;
return relResidual;
}
/// Returns the initfile \ref prefix
......@@ -59,6 +71,25 @@ namespace AMDiS
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
}
/// Sets \ref rTol
void setAbsTolerance(double tol)
void setRelTolerance(double tol)
{
rTol = tol;
}
/// Sets \ref aTol
void setAbsResidual(double r)
{
absResidual = r;
}
/// Sets \ref rTol
void setRelResidual(double r)
{
relResidual = r;
}
/// Sets \ref info
void setInfo(int i)
{
info = i;
}
/// Sets \ref info
/// Sets \ref error
void setError(int e)
{
error = e;
}
/// Sets \ref createMatrixData
void setCreateMatrixData(bool b)
{
createMatrixData = b;
}
/// Sets \ref storeMatrixData
void setStoreMatrixData(bool b)
{
storeMatrixData = b;
}
/** \} */
private:
/// The initfile prefix to read parameters
std::string prefix;
private:
/// The abolute tolerance
double aTol = 1.e-6;
double aTol = 0;
/// The relative tolerance
double rTol = 0.0;
double rTol = 1.e-6;
/// Throw an error if tolerance could not be reached
bool breakTolNotReached = true;
bool breakTolNotReached = false;
/// The solver verbosity level
int info = 0;
// some parameters used internally
double absRresidual = -1.0;
/// The absolute residual, default (-1): not set
double absResidual = -1.0;
/// The relative residual, relative to the two_norm(b), default (-1): not set
double relResidual = -1.0;
/// The error-code, default (-1): not set
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
#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
VectorOut x_i(x[r_rows[_i]]);
For<0, _M>::loop([this, &b, &x_i, &r_cols, &first, _i](const auto _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
const VectorIn b_j(b[r_cols[_j]]);
if (first) {
......
#pragma once
#include <dune/amdis/linear_algebra/LinearAlgebraBase.hpp>
namespace AMDiS
{
/// A simple block-vector class
......@@ -17,6 +19,18 @@ namespace AMDiS
/// The type of the elements of the MTLVector
using value_type = typename MTLVector::value_type;
};
namespace Impl
{
/// Specialization of Impl::BaseVector from \file LinearSolverInterface.hpp
template <class MTLVector, size_t N>
struct BaseVector<BlockMTLVector<MTLVector, N>>
{
using type = MTLVector;
};
}
/// Return the number of overall rows of a BlockMTLVector
template <class MTLVector, size_t _N>
......@@ -30,7 +44,7 @@ namespace AMDiS
}
/// Return the number of overall columns of a BlockMTLVector
template <class MTLVector, size_t _N,>
template <class MTLVector, size_t _N>
inline size_t num_cols(BlockMTLVector<MTLVector, _N> const& vec)
{
return 1;
......@@ -48,7 +62,7 @@ namespace AMDiS
inline void set_to_zero(BlockMTLVector<MTLVector, _N>& vec)
{
For<0, _N>::loop([&](const auto _i) {
set_to_zero(std::get<_i>(vec);
set_to_zero(std::get<_i>(vec));
});
}
......@@ -58,7 +72,7 @@ namespace AMDiS
template <class BlockVector, class Vector>
struct BlockVectorWrapper
{
BlockVectorWrapper(blockVector& blockVector,
BlockVectorWrapper(BlockVector& blockVector,
bool copyBack = std::is_const<BlockVector>::value)
: blockVector(blockVector)
, vector(num_rows(blockVector))
......
......@@ -15,12 +15,7 @@
namespace AMDiS
{
template <class Matrix, class Vector>
struct PreconditionerCreator
{
using PreconBase = PreconditionerInterface<Matrix, Vector>;
static std::unique_ptr<PreconBase> create(std::string name, std::string prefix);
};
struct PreconditionerCreator;
/**
* \ingroup Solver
......@@ -82,27 +77,30 @@ namespace AMDiS
template <class Matrix>
using ICPreconditioner = itl::pc::ic_0<Matrix>;
template <class Matrix, class Vector>
std::unique_ptr<typename PreconditionerCreator<Matrix, Vector>::PreconBase>
PreconditionerCreator<Matrix, Vector>::create(std::string name)
{
template <template<class> class ITLPrecon>
using Type = typename Preconditioner<Matrix, Vector, ITLPrecon<Matrix>>;
template <class T, class Param, class Vector>
struct PreconditionerCreator<mtl::compressed2D<T, Param>, Vector>
{
using Matrix = mtl::compressed2D<T, Param>;
using PreconBase = PreconditionerInterface<Matrix, Vector>;
if (name == "diag" || name == "jacobi")
return std::make_unique<Type<DiagonalPreconditioner>>();
else if (name == "masslumping")
return std::make_unique<Type<cMassLumpingPreconditioner>>();
else if (name == "ilu" || name == "ilu0")
return std::make_unique<Type<ILUPreconditioner>>();
else if (name == "ic" || name == "ic0")
return std::make_unique<Type<ICPreconditioner>>();
else // by default, do nothing
return std::make_unique<Type<IdentityPreconditioner>>();
}
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 if (name == "masslumping")
return std::make_unique<Precon<MassLumpingPreconditioner>>();
else if (name == "ilu" || name == "ilu0")
return std::make_unique<Precon<ILUPreconditioner>>();