Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
amdis
amdis-core
Commits
07cf0c03
Commit
07cf0c03
authored
Dec 29, 2020
by
Praetorius, Simon
Browse files
Simplify linear algebra backend LinearSolver
parent
ac9e1f4c
Changes
40
Hide whitespace changes
Inline
Side-by-side
amdis/CreatorMap.hpp
View file @
07cf0c03
...
...
@@ -41,7 +41,7 @@ namespace AMDiS
}
/// Creates a object of the type corresponding to key.
static
CreatorInterface
<
BaseClass
>*
get
Creator
(
std
::
string
key
,
std
::
string
initFileStr
)
static
CreatorInterface
<
BaseClass
>*
get
(
std
::
string
key
,
std
::
string
initFileStr
)
{
init
();
...
...
amdis/LinearAlgebra.hpp
View file @
07cf0c03
...
...
@@ -3,8 +3,9 @@
#if AMDIS_BACKEND == AMDIS_BACKEND_MTL
#include <amdis/linearalgebra/mtl/Constraints.hpp>
#include <amdis/linearalgebra/mtl/ITL_Solver.hpp>
#include <amdis/linearalgebra/mtl/ITL_Preconditioner.hpp>
#include <amdis/linearalgebra/mtl/LinearSolver.hpp>
#include <amdis/linearalgebra/mtl/Preconditioners.hpp>
#include <amdis/linearalgebra/mtl/Solvers.hpp>
#include <amdis/linearalgebra/mtl/Traits.hpp>
#include <amdis/linearalgebra/mtl/MatrixBackend.hpp>
#include <amdis/linearalgebra/mtl/VectorBackend.hpp>
...
...
@@ -12,7 +13,8 @@
#elif AMDIS_BACKEND == AMDIS_BACKEND_EIGEN
#include <amdis/linearalgebra/eigen/Constraints.hpp>
#include <amdis/linearalgebra/eigen/SolverCreator.hpp>
#include <amdis/linearalgebra/eigen/LinearSolver.hpp>
#include <amdis/linearalgebra/eigen/Solvers.hpp>
#include <amdis/linearalgebra/eigen/Traits.hpp>
#include <amdis/linearalgebra/eigen/MatrixBackend.hpp>
#include <amdis/linearalgebra/eigen/VectorBackend.hpp>
...
...
@@ -20,7 +22,7 @@
#elif AMDIS_BACKEND == AMDIS_BACKEND_PETSC
#include <amdis/linearalgebra/petsc/Constraints.hpp>
#include <amdis/linearalgebra/petsc/
SolverCreato
r.hpp>
#include <amdis/linearalgebra/petsc/
LinearSolve
r.hpp>
#include <amdis/linearalgebra/petsc/Traits.hpp>
#include <amdis/linearalgebra/petsc/MatrixBackend.hpp>
#include <amdis/linearalgebra/petsc/VectorBackend.hpp>
...
...
@@ -28,9 +30,9 @@
#elif AMDIS_BACKEND == AMDIS_BACKEND_ISTL
#include <amdis/linearalgebra/istl/Constraints.hpp>
#include <amdis/linearalgebra/istl/
ISTL
Solver.hpp>
#include <amdis/linearalgebra/istl/Precon
Creator
.hpp>
#include <amdis/linearalgebra/istl/Solver
Creator
.hpp>
#include <amdis/linearalgebra/istl/
Linear
Solver.hpp>
#include <amdis/linearalgebra/istl/Precon
ditioners
.hpp>
#include <amdis/linearalgebra/istl/Solver
s
.hpp>
#include <amdis/linearalgebra/istl/Traits.hpp>
#include <amdis/linearalgebra/istl/MatrixBackend.hpp>
#include <amdis/linearalgebra/istl/VectorBackend.hpp>
...
...
@@ -39,5 +41,4 @@
#include <amdis/linearalgebra/MatrixFacade.hpp>
#include <amdis/linearalgebra/VectorFacade.hpp>
#include <amdis/linearalgebra/LinearSolver.hpp>
#include <amdis/linearalgebra/SolverInfo.hpp>
#include <amdis/linearalgebra/LinearSolverInterface.hpp>
amdis/ProblemStat.hpp
View file @
07cf0c03
...
...
@@ -79,7 +79,7 @@ namespace AMDiS
using
PartitionSet
=
typename
LinAlgTraits
::
PartitionSet
;
public:
using
LinearSolver
=
LinearSolverInterface
<
Mat
,
Vec
>
;
using
LinearSolver
=
LinearSolverInterface
<
Mat
,
Vec
,
Vec
>
;
using
SystemMatrix
=
BiLinearForm
<
GlobalBasis
,
GlobalBasis
,
typename
Traits
::
CoefficientType
,
LinAlgTraits
>
;
using
SystemVector
=
LinearForm
<
GlobalBasis
,
typename
Traits
::
CoefficientType
,
LinAlgTraits
>
;
using
SolutionVector
=
DOFVector
<
GlobalBasis
,
typename
Traits
::
CoefficientType
,
LinAlgTraits
>
;
...
...
amdis/ProblemStat.inc.hpp
View file @
07cf0c03
...
...
@@ -228,10 +228,8 @@ void ProblemStat<Traits>::createSolver()
std
::
string
solverName
=
"default"
;
Parameters
::
get
(
name_
+
"->solver"
,
solverName
);
auto
solverCreator
=
named
(
CreatorMap
<
LinearSolver
>::
getCreator
(
solverName
,
name_
+
"->solver"
));
linearSolver_
=
solverCreator
->
createWithString
(
name_
+
"->solver"
);
using
Solver
=
AMDiS
::
LinearSolver
<
Mat
,
Vec
,
Vec
>
;
linearSolver_
=
std
::
make_shared
<
Solver
>
(
solverName
,
name_
+
"->solver"
);
}
...
...
@@ -348,28 +346,26 @@ template <class Traits>
void
ProblemStat
<
Traits
>::
solve
(
AdaptInfo
&
/*adaptInfo*/
,
bool
createMatrixData
,
bool
storeMatrixData
)
{
Dune
::
Timer
t
;
SolverInfo
solverInfo
(
name_
+
"->solver"
);
solverInfo
.
setCreateMatrixData
(
createMatrixData
);
solverInfo
.
setStoreMatrixData
(
storeMatrixData
);
Dune
::
InverseOperatorResult
stat
;
solution_
->
resize
();
linearSolver_
->
solve
(
*
systemMatrix_
,
*
solution_
,
*
rhs_
,
solverInfo
);
if
(
solverInfo
.
info
()
>
0
)
{
msg
(
"solution of discrete system needed {} seconds"
,
t
.
elapsed
());
if
(
createMatrixData
)
linearSolver_
->
init
(
systemMatrix_
->
impl
());
if
(
solverInfo
.
absResidual
()
>=
0.0
)
{
if
(
solverInfo
.
relResidual
()
>=
0.0
)
msg
(
"Residual norm: ||b-Ax|| = {}, ||b-Ax||/||b|| = {}"
,
solverInfo
.
absResidual
(),
solverInfo
.
relResidual
());
else
msg
(
"Residual norm: ||b-Ax|| = {}"
,
solverInfo
.
absResidual
());
}
}
// solve the linear system
linearSolver_
->
apply
(
solution_
->
impl
(),
rhs_
->
impl
(),
stat
);
if
(
!
storeMatrixData
)
linearSolver_
->
finish
();
info
(
2
,
"solution of discrete system needed {} seconds"
,
stat
.
elapsed
);
if
(
stat
.
reduction
>=
0.0
)
info
(
1
,
"Residual norm: ||b-Ax||/||b-Ax^0|| = {}"
,
stat
.
reduction
);
test_exit
(
!
solverInfo
.
doBreak
()
||
!
solverInfo
.
error
(),
"Could not solver the linear system!"
);
bool
ignoreConverged
=
false
;
Parameters
::
get
(
name_
+
"->solver->ignore converged"
,
ignoreConverged
);
test_exit
(
stat
.
converged
||
ignoreConverged
,
"Could not solver the linear system!"
);
}
...
...
amdis/linearalgebra/CMakeLists.txt
View file @
07cf0c03
...
...
@@ -5,12 +5,9 @@ install(FILES
Constraints.hpp
DOFMapping.hpp
DOFMapping.inc.hpp
LinearSolver.hpp
LinearSolverInterface.hpp
MatrixFacade.hpp
ParallelIndexSet.hpp
RunnerInterface.hpp
SolverInfo.hpp
SparsityPattern.hpp
SymmetryStructure.hpp
Traits.hpp
...
...
amdis/linearalgebra/LinearSolver.hpp
deleted
100644 → 0
View file @
ac9e1f4c
#pragma once
#include <string>
#include <dune/common/timer.hh>
// AMDiS includes
#include <amdis/CreatorInterface.hpp>
#include <amdis/Output.hpp>
#include <amdis/linearalgebra/LinearSolverInterface.hpp>
#include <amdis/linearalgebra/SolverInfo.hpp>
namespace
AMDiS
{
/** \ingroup Solver
*
* \brief
* Wrapper class for various solvers. These solvers
* are parametrized by MatrixType and VectorType. The different
* algorithms, like krylov subspace methods or other external
* solvers where the backend provides an interface, can be assigned
* by different Runner objects.
**/
template
<
class
Mat
,
class
Vec
,
class
Runner
>
class
LinearSolver
:
public
LinearSolverInterface
<
Mat
,
Vec
>
{
using
Self
=
LinearSolver
;
using
Super
=
LinearSolverInterface
<
Mat
,
Vec
>
;
public:
/// A creator to be used instead of the constructor.
struct
Creator
:
CreatorInterfaceName
<
Super
>
{
std
::
unique_ptr
<
Super
>
createWithString
(
std
::
string
prefix
)
override
{
return
std
::
make_unique
<
Self
>
(
prefix
);
}
};
public:
/// Constructor
template
<
class
...
Args
>
explicit
LinearSolver
(
std
::
string
prefix
,
Args
&&
...
args
)
:
runner_
(
prefix
,
FWD
(
args
)...)
{}
Runner
*
runner
()
override
{
return
&
runner_
;
}
protected:
/// Implements \ref LinearSolverInterface::solveImpl()
void
solveImpl
(
Mat
const
&
A
,
Vec
&
x
,
Vec
const
&
b
,
SolverInfo
&
solverInfo
)
override
{
Dune
::
Timer
t
;
if
(
solverInfo
.
doCreateMatrixData
())
{
// init matrix or wrap block-matrix or ...
runner_
.
init
(
A
.
matrix
());
}
if
(
solverInfo
.
info
()
>
0
)
msg
(
"prepare solver needed {} seconds"
,
t
.
elapsed
());
int
error
=
runner_
.
solve
(
A
.
matrix
(),
x
.
vector
(),
b
.
vector
(),
solverInfo
);
solverInfo
.
setError
(
error
);
if
(
!
solverInfo
.
doStoreMatrixData
())
runner_
.
exit
();
}
private:
/// redirect the implementation to a runner implementing a \ref RunnerInterface
Runner
runner_
;
};
}
// end namespace AMDiS
amdis/linearalgebra/LinearSolverInterface.hpp
View file @
07cf0c03
#pragma once
#include <amdis/Output.hpp>
#include <amdis/linearalgebra/RunnerInterface.hpp>
/**
* \defgroup Solver Solver module
* @{ <img src="solver.png"> @}
*
* \brief
* Contains all classes needed for solving linear and non linear equation
* systems.
*/
#include <dune/istl/solver.hh>
namespace
AMDiS
{
class
SolverInfo
;
template
<
class
T
,
template
<
class
>
class
MatrixImpl
>
class
MatrixFacade
;
template
<
class
T
,
template
<
class
>
class
VectorImpl
>
class
VectorFacade
;
/// Abstract base class for linear solvers
template
<
class
Mat
,
class
Vec
>
template
<
class
M
,
class
X
,
class
Y
=
X
>
class
LinearSolverInterface
{
public:
/// Destructor.
virtual
~
LinearSolverInterface
()
=
default
;
/// Public method to call in order to solve a linear system Ax = b.
/**
* The method redirects to the specific linear solver and prints statistics
* 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.
**/
template
<
class
TA
,
class
TX
,
class
TY
,
template
<
class
>
class
MI
,
template
<
class
>
class
VI
>
void
solve
(
MatrixFacade
<
TA
,
MI
>
const
&
A
,
VectorFacade
<
TX
,
VI
>&
x
,
VectorFacade
<
TY
,
VI
>
const
&
b
,
SolverInfo
&
solverInfo
)
{
solveImpl
(
A
.
impl
(),
x
.
impl
(),
b
.
impl
(),
solverInfo
);
}
/// \brief Prepare the solve (and preconditioner), e.g. make a factorization
/// of the matrix, or extract its diagonal in a jacobian precon.
virtual
void
init
(
M
const
&
A
)
=
0
;
virtual
RunnerInterface
<
Mat
,
Vec
>*
runner
()
{
error_exit
(
"Must be implemented by derived class."
);
return
nullptr
;
}
/// \brief Cleanup the solver, e.g. free the previously created factorization.
virtual
void
finish
()
=
0
;
protected:
/// main methods that all solvers must implement
virtual
void
solveImpl
(
Mat
const
&
A
,
Vec
&
x
,
Vec
const
&
b
,
SolverInfo
&
solverInfo
)
=
0
;
/// \brief Apply the inverse operator to the rhs vector b
virtual
void
apply
(
X
&
x
,
Y
const
&
b
,
Dune
::
InverseOperatorResult
&
res
)
=
0
;
};
}
// end namespace AMDiS
amdis/linearalgebra/RunnerInterface.hpp
deleted
100644 → 0
View file @
ac9e1f4c
#pragma once
#include <amdis/Output.hpp>
namespace
AMDiS
{
class
SolverInfo
;
/// Interface for Runner / Worker types used in solver classes
template
<
class
Mat
,
class
Vec
>
class
RunnerInterface
{
using
M
=
typename
Mat
::
BaseMatrix
;
using
X
=
typename
Vec
::
BaseVector
;
using
Y
=
typename
Vec
::
BaseVector
;
public:
/// virtual destructor
virtual
~
RunnerInterface
()
=
default
;
/// Is called at the beginning of a solution procedure
virtual
void
init
(
M
const
&
A
)
=
0
;
/// Is called at the end of a solution procedure
virtual
void
exit
()
=
0
;
/// Solve the system A*x = b
virtual
int
solve
(
M
const
&
A
,
X
&
x
,
Y
const
&
b
,
SolverInfo
&
solverInfo
)
=
0
;
/// Solve the system A*x = b
virtual
int
adjointSolve
(
M
const
&
A
,
X
&
x
,
Y
const
&
b
,
SolverInfo
&
solverInfo
)
{
error_exit
(
"Must be implemented by derived class."
);
return
0
;
}
};
}
// end namespace AMDiS
amdis/linearalgebra/SolverInfo.hpp
deleted
100644 → 0
View file @
ac9e1f4c
#pragma once
#include <string>
#include <amdis/Initfile.hpp>
namespace
AMDiS
{
/// 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 solver \p prefix.
/**
* Reads parameters for a solver with name 'NAME':
* NAME->info \ref info_
* NAME->break if tolerance not reached \ref breakTolNotReached_
**/
explicit
SolverInfo
(
std
::
string
const
&
prefix
)
:
prefix_
(
prefix
)
{
Parameters
::
get
(
prefix
+
"->info"
,
info_
);
Parameters
::
get
(
prefix
+
"->break if tolerance not reached"
,
breakTolNotReached_
);
}
/** \name getting methods
* \{
*/
/// Returns error code in last run of an iterative solver
int
error
()
const
{
return
error_
;
}
/// Returns info
int
info
()
const
{
return
info_
;
}
/// Returns \ref absResidual_
double
absResidual
()
const
{
return
absResidual_
;
}
/// Returns \ref relResidual_
double
relResidual
()
const
{
return
relResidual_
;
}
/// Returns \ref createMatrixData
bool
doCreateMatrixData
()
const
{
return
createMatrixData_
;
}
/// Returns \ref storeMatrixData
bool
doStoreMatrixData
()
const
{
return
storeMatrixData_
;
}
bool
doBreak
()
const
{
return
breakTolNotReached_
;
}
/** \} */
/** \name setting methods
* \{
*/
/// Sets \ref absResidual_
void
setAbsResidual
(
double
r
)
{
absResidual_
=
r
;
}
/// Sets \ref relResidual_
void
setRelResidual
(
double
r
)
{
relResidual_
=
r
;
}
/// Sets \ref info_
void
setInfo
(
int
i
)
{
info_
=
i
;
}
/// 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_
;
/// Throw an error if tolerance could not be reached
bool
breakTolNotReached_
=
false
;
/// The solver verbosity level
int
info_
=
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
amdis/linearalgebra/eigen/CMakeLists.txt
View file @
07cf0c03
...
...
@@ -2,11 +2,12 @@ install(FILES
Constraints.hpp
DirectRunner.hpp
IterativeRunner.hpp
LinearSolver.hpp
MatrixBackend.hpp
MatrixSize.hpp
PreconConfig.hpp
SolverConfig.hpp
Solver
Creator
.hpp
Solver
s
.hpp
Traits.hpp
VectorBackend.hpp
DESTINATION
${
CMAKE_INSTALL_INCLUDEDIR
}
/amdis/linearalgebra/eigen
)
amdis/linearalgebra/eigen/DirectRunner.hpp
View file @
07cf0c03
#pragma once
#include <
algorithm
>
#include <
memory
>
#include <string>
#include <amdis/linearalgebra/RunnerInterface.hpp>
#include <amdis/linearalgebra/SolverInfo.hpp>
#include <amdis/CreatorInterface.hpp>
#include <amdis/Initfile.hpp>
#include <amdis/linearalgebra/LinearSolverInterface.hpp>
#include <amdis/linearalgebra/eigen/SolverConfig.hpp>
namespace
AMDiS
...
...
@@ -12,19 +13,25 @@ namespace AMDiS
/**
* \ingroup Solver
* \class AMDiS::DirectRunner
* \brief \implements
Runner
In
t
er
face
for the (external) direct solvers
* \brief \implements
Dune::
In
v
er
seOperator
for the (external) direct solvers
*/
template
<
class
M
at
,
class
Vec
,
template
<
class
>
class
Solver
>
template
<
class
M
,
class
X
,
class
Y
,
template
<
class
>
class
Solver
>
class
DirectRunner
:
public
Runn
erInterface
<
M
at
,
Vec
>
:
public
LinearSolv
erInterface
<
M
,
X
,
Y
>
{
using
M
=
typename
Mat
::
BaseMatrix
;
using
X
=
typename
Vec
::
BaseVector
;
using
Y
=
typename
Vec
::
BaseVector
;
protected:
using
Self
=
DirectRunner
;
using
EigenSolver
=
Solver
<
M
>
;
public:
struct
Creator
final
:
CreatorInterfaceName
<
LinearSolverInterface
<
M
,
X
,
Y
>>
{
std
::
unique_ptr
<
LinearSolverInterface
<
M
,
X
,
Y
>>
createWithString
(
std
::
string
prefix
)
final
{
return
std
::
make_unique
<
Self
>
(
prefix
);
}
};
public:
/// Constructor.
DirectRunner
(
std
::
string
const
&
prefix
)
...
...
@@ -34,7 +41,7 @@ namespace AMDiS
Parameters
::
get
(
prefix
+
"->reuse pattern"
,
reusePattern_
);
}
///
Implements \ref RunnerIn
te
r
fac
e::init()
///
initialize the matrix and maybe compu
te
fac
torization
void
init
(
M
const
&
A
)
override
{
if
(
!
reusePattern_
||
!
initialized_
)
{
...
...
@@ -43,29 +50,23 @@ namespace AMDiS
}
solver_
.
factorize
(
A
);
test_exit
(
solver_
.
info
()
==
Eigen
::
Success
,
"Error in solver.compute(matrix)"
);
test_exit
(
solver_
.
info
()
==
Eigen
::
Success
,
"Error in solver.compute(matrix)"
);
}
/// Implements \ref
Runn
erInterface::
exit
()
void
exit
()
override
/// Implements \ref
LinearSolv
erInterface::
finish
()
void
finish
()
override
{
initialized_
=
false
;
}
/// Implements \ref
Runn
erInterface::
solve
()
int
solve
(
M
const
&
A
,
X
&
x
,
Y
const
&
b
,
SolverInfo
&
solverInfo
)
/// Implements \ref
LinearSolv
erInterface::
apply
()
void
apply
(
X
&
x
,
Y
const
&
b
,
Dune
::
InverseOperatorResult
&
stat
)
override
{
Dune
::
Timer
t
;
x
=
solver_
.
solve
(
b
);
Y
r
=
b
;
if
(
x
.
norm
()
!=
0
)
r
-=
A
*
x
;
solverInfo
.
setAbsResidual
(
r
.
norm
());
solverInfo
.
setError
(
solver_
.
info
());
return
solver_
.
info
()
==
Eigen
::
Success
?
0
:
1
;
stat
.
converged
=
(
solver_
.
info
()
==
Eigen
::
Success
);
stat
.
elapsed
=
t
.
elapsed
();
}
private:
...
...
@@ -73,4 +74,5 @@ namespace AMDiS
bool
reusePattern_
=
false
;
bool
initialized_
=
false
;
};
}
}
// end namespace AMDiS
amdis/linearalgebra/eigen/IterativeRunner.hpp
View file @
07cf0c03
#pragma once
#include <
dune/istl/preconditioner.hh
>
#include <
memory
>
#include <amdis/linearalgebra/RunnerInterface.hpp>
#include <amdis/linearalgebra/SolverInfo.hpp>
#include <amdis/CreatorInterface.hpp>
#include <amdis/Initfile.hpp>
#include <amdis/linearalgebra/LinearSolverInterface.hpp>
#include <amdis/linearalgebra/eigen/PreconConfig.hpp>
#include <amdis/linearalgebra/eigen/SolverConfig.hpp>
namespace
AMDiS
{
template
<
class
M
at
,
class
Vec
,
class
IterativeSolver
>
template
<
class
M
,
class
X
,
class
Y
,
class
IterativeSolver
>
class
IterativeRunner
:
public
Runn
erInterface
<
M
at
,
Vec
>
:
public
LinearSolv
erInterface
<
M
,
X
,
Y
>
{
using
M
=
typename
Mat
::
BaseMatrix
;
using
X
=
typename
Vec
::
BaseVector
;
using
Y
=
typename
Vec
::
BaseVector
;