Skip to content
Snippets Groups Projects
Commit 265acf0a authored by Elias Pipping's avatar Elias Pipping
Browse files

Tests: Add and use SymmetricSampleProblem class

Such sample problems are set up in more than one place.
This change avoids code duplication
parent aec19234
No related branches found
No related tags found
No related merge requests found
...@@ -61,52 +61,24 @@ struct CGTestSuite ...@@ -61,52 +61,24 @@ struct CGTestSuite
bool passed = true; bool passed = true;
typedef typename Dune::FieldMatrix<double, 1, 1> MatrixBlock; using Problem =
typedef typename Dune::FieldVector<double, 1> VectorBlock; SymmetricSampleProblem<1, typename GridType::LevelGridView>;
typedef typename Dune::BCRSMatrix<MatrixBlock> Matrix; Problem p(grid.levelGridView(grid.maxLevel()));
typedef typename Dune::BlockVector<VectorBlock> Vector;
typedef typename Dune::BitSetVector<1> BitVector;
typedef typename GridType::LevelGridView GridView;
const GridView gridView = grid.levelGridView(grid.maxLevel());
Matrix A;
constructPQ1Pattern(gridView, A);
A=0.0;
assemblePQ1Stiffness(gridView, A);
EnergyNorm<Matrix, Vector> energyNorm(A);
Vector u(A.N()), u_sol(A.N());
u = 0;
for (size_t i=0; i<u.size(); ++i)
u_sol[i] = (1.0*rand())/RAND_MAX;
Vector rhs(A.N());
A.mv(u_sol, rhs);
BitVector ignore(A.N());
ignore.unsetAll();
markBoundaryDOFs(gridView, ignore);
// set Dirichlet values
for (size_t i=0; i<u.size(); ++i)
if (ignore[i][0])
u[i] = u_sol[i];
const auto verbosity = Solver::REDUCED; const auto verbosity = Solver::REDUCED;
const bool relativeErrors = false; const bool relativeErrors = false;
Analyser<Vector> analyser(u_sol, energyNorm, solveTol); Analyser<typename Problem::Vector> analyser(p.u_ex, p.energyNorm,
solveTol);
{ {
std::string const testCase = "CGSolver "; std::string const testCase = "CGSolver ";
Vector u_copy = u; typename Problem::Vector u_copy = p.u;
Vector rhs_copy = rhs; typename Problem::Vector rhs_copy = p.rhs;
CGSolver<Matrix,Vector> solver(&A, &u_copy, &rhs_copy, nullptr, CGSolver<typename Problem::Matrix, typename Problem::Vector> solver(
maxIterations, stepTol, &energyNorm, &p.A, &u_copy, &rhs_copy, nullptr, maxIterations, stepTol,
verbosity, relativeErrors); &p.energyNorm, verbosity, relativeErrors);
solver.check(); solver.check();
solver.preprocess(); solver.preprocess();
solver.solve(); solver.solve();
...@@ -116,16 +88,19 @@ struct CGTestSuite ...@@ -116,16 +88,19 @@ struct CGTestSuite
{ {
std::string const testCase = "CGSolver, preconditioned "; std::string const testCase = "CGSolver, preconditioned ";
Vector u_copy = u; typename Problem::Vector u_copy = p.u;
Vector rhs_copy = rhs; typename Problem::Vector rhs_copy = p.rhs;
using BGS = BlockGSStep<Matrix,Vector,BitVector>; using BGS =
BlockGSStep<typename Problem::Matrix, typename Problem::Vector,
typename Problem::BitVector>;
BGS blockgs(BGS::Direction::SYMMETRIC); BGS blockgs(BGS::Direction::SYMMETRIC);
blockgs.ignoreNodes_ = new BitVector(u.size(), false); blockgs.ignoreNodes_ =
new typename Problem::BitVector(p.u.size(), false);
CGSolver<Matrix,Vector> solver(&A, &u_copy, &rhs_copy, &blockgs, CGSolver<typename Problem::Matrix, typename Problem::Vector> solver(
maxIterations, stepTol, &energyNorm, &p.A, &u_copy, &rhs_copy, &blockgs, maxIterations, stepTol,
verbosity, relativeErrors); &p.energyNorm, verbosity, relativeErrors);
solver.check(); solver.check();
solver.preprocess(); solver.preprocess();
solver.solve(); solver.solve();
...@@ -135,12 +110,15 @@ struct CGTestSuite ...@@ -135,12 +110,15 @@ struct CGTestSuite
{ {
std::string const testCase = "Dune::Solvers::CGStep "; std::string const testCase = "Dune::Solvers::CGStep ";
Vector u_copy = u; typename Problem::Vector u_copy = p.u;
Vector rhs_copy = rhs; typename Problem::Vector rhs_copy = p.rhs;
Dune::Solvers::CGStep<Matrix,Vector> cgStep(A, u_copy, rhs_copy); Dune::Solvers::CGStep<typename Problem::Matrix,
::LoopSolver<Vector> solver(&cgStep, maxIterations, stepTol, &energyNorm, typename Problem::Vector> cgStep(p.A, u_copy,
verbosity, relativeErrors); rhs_copy);
::LoopSolver<typename Problem::Vector> solver(
&cgStep, maxIterations, stepTol, &p.energyNorm, verbosity,
relativeErrors);
solver.check(); solver.check();
solver.preprocess(); solver.preprocess();
solver.solve(); solver.solve();
...@@ -150,16 +128,23 @@ struct CGTestSuite ...@@ -150,16 +128,23 @@ struct CGTestSuite
{ {
std::string const testCase = "Dune::Solvers::CGStep, preconditioned"; std::string const testCase = "Dune::Solvers::CGStep, preconditioned";
Vector u_copy = u; typename Problem::Vector u_copy = p.u;
Vector rhs_copy = rhs; typename Problem::Vector rhs_copy = p.rhs;
using BGS = BlockGSStep<Matrix,Vector,BitVector>; using BGS =
BlockGSStep<typename Problem::Matrix, typename Problem::Vector,
typename Problem::BitVector>;
BGS blockgs(BGS::Direction::SYMMETRIC); BGS blockgs(BGS::Direction::SYMMETRIC);
blockgs.ignoreNodes_ = new BitVector(u.size(), false); blockgs.ignoreNodes_ =
new typename Problem::BitVector(p.u.size(), false);
Dune::Solvers::CGStep<Matrix,Vector> cgStep(A, u_copy, rhs_copy, blockgs);
::LoopSolver<Vector> solver(&cgStep, maxIterations, stepTol, &energyNorm, Dune::Solvers::CGStep<typename Problem::Matrix,
verbosity, relativeErrors); typename Problem::Vector> cgStep(p.A, u_copy,
rhs_copy,
blockgs);
::LoopSolver<typename Problem::Vector> solver(
&cgStep, maxIterations, stepTol, &p.energyNorm, verbosity,
relativeErrors);
solver.check(); solver.check();
solver.preprocess(); solver.preprocess();
solver.solve(); solver.solve();
......
...@@ -348,6 +348,61 @@ void markBoundaryDOFs(const GridView& gridView, BitVector& isBoundary) ...@@ -348,6 +348,61 @@ void markBoundaryDOFs(const GridView& gridView, BitVector& isBoundary)
} }
} }
template <size_t blocksize, class GridView>
class SymmetricSampleProblem {
public:
typedef typename Dune::FieldMatrix<double, blocksize, blocksize> MatrixBlock;
typedef typename Dune::FieldVector<double, blocksize> VectorBlock;
typedef typename Dune::BCRSMatrix<MatrixBlock> Matrix;
typedef typename Dune::BlockVector<VectorBlock> Vector;
typedef typename Dune::BitSetVector<blocksize> BitVector;
typedef EnergyNorm<Matrix, Vector> Norm;
SymmetricSampleProblem(GridView const& gridView) {
constructPQ1Pattern(gridView, A);
A = 0.0;
assemblePQ1Stiffness(gridView, A);
energyNorm.setMatrix(&A);
ignore.resize(A.N());
ignore.unsetAll();
markBoundaryDOFs(gridView, ignore);
u.resize(A.N());
u_ex.resize(A.N());
rhs.resize(A.N());
randomize();
}
void randomize() {
// Set up a random 'solution'
u = 0;
for (size_t i = 0; i < u.size(); ++i)
for (size_t j = 0; j < blocksize; ++j) {
// in case of no dirichlet values you can make the
// matrix pd hereby
// A[i][i][j][j] += 0.5*std::abs(A[0][0][0][0]);
u_ex[i][j] = (1.0 * rand()) / RAND_MAX;
}
// Construct right hand side corresponding to the 'solution'
A.mv(u_ex, rhs);
// set dirichlet values
for (size_t i = 0; i < u.size(); ++i)
for (size_t j = 0; j < blocksize; ++j)
if (ignore[i][j])
u[i][j] = u_ex[i][j];
}
Matrix A;
Vector u;
Vector u_ex;
Vector rhs;
BitVector ignore;
Norm energyNorm;
};
template<class GridType, class TestSuite> template<class GridType, class TestSuite>
bool checkWithGrid(TestSuite& suite, int uniformRefinements) bool checkWithGrid(TestSuite& suite, int uniformRefinements)
......
...@@ -43,45 +43,13 @@ struct MultigridTestSuite ...@@ -43,45 +43,13 @@ struct MultigridTestSuite
bool passed = true; bool passed = true;
typedef typename Dune::FieldMatrix<double, blocksize, blocksize> MatrixBlock; using Problem =
typedef typename Dune::FieldVector<double, blocksize> VectorBlock; SymmetricSampleProblem<1, typename GridType::LevelGridView>;
typedef typename Dune::BCRSMatrix<MatrixBlock> Matrix; Problem p(grid.levelGridView(grid.maxLevel()));
typedef typename Dune::BlockVector<VectorBlock> Vector;
typedef typename Dune::BitSetVector<blocksize> BitVector;
typedef typename GridType::LevelGridView GridView; typedef typename Problem::Vector Vector;
typedef typename Problem::Matrix Matrix;
typedef typename Problem::BitVector BitVector;
const GridView gridView = grid.levelGridView(grid.maxLevel());
Matrix A;
constructPQ1Pattern(gridView, A);
A=0.0;
assemblePQ1Stiffness(gridView, A);
Vector u(A.N()), u_ex(A.N());
u = 0;
for (size_t i=0; i<u.size(); ++i)
for (size_t j=0; j<blocksize; ++j)
{
u_ex[i][j] = (1.0*rand())/RAND_MAX;
// A[i][i][j][j] += 0.5*std::abs(A[0][0][0][0]); // in case of no dirichlet values you can make the matrix pd hereby
}
Vector rhs(A.N());
A.mv(u_ex, rhs);
BitVector ignore(A.N());
ignore.unsetAll();
markBoundaryDOFs(gridView, ignore);
// set dirichlet values
for (size_t i=0; i<u.size(); ++i)
for (size_t j=0; j<blocksize; ++j)
if (ignore[i][j])
u[i][j] = u_ex[i][j];
typedef EnergyNorm<Matrix, Vector> Norm;
typedef ::LoopSolver<Vector> Solver; typedef ::LoopSolver<Vector> Solver;
typedef MultigridStep<Matrix, Vector, BitVector> MGStep; typedef MultigridStep<Matrix, Vector, BitVector> MGStep;
typedef MultigridTransfer<Vector, BitVector, Matrix> Transfer; typedef MultigridTransfer<Vector, BitVector, Matrix> Transfer;
...@@ -98,71 +66,51 @@ struct MultigridTestSuite ...@@ -98,71 +66,51 @@ struct MultigridTestSuite
transfer[i] = t; transfer[i] = t;
} }
// we want to control errors with respect to the energy norm induced by the matrix
Norm energynorm(A);
// set up smoothers and basesolver // set up smoothers and basesolver
Smoother smoother, basesolver_step; Smoother smoother, basesolver_step;
Norm basenorm(basesolver_step); typename Problem::Norm basenorm(basesolver_step);
Solver basesolver(&basesolver_step, 1, 1e-10, &basenorm, Solver::QUIET); Solver basesolver(&basesolver_step, 1, 1e-10, &basenorm, Solver::QUIET);
// create iteration step and set all kinds of data // create iteration step and set all kinds of data
MGStep mgStep; MGStep mgStep;
mgStep.setTransferOperators(transfer); mgStep.setTransferOperators(transfer);
mgStep.setProblem(A,u,rhs); mgStep.setProblem(p.A,p.u,p.rhs);
mgStep.setSmoother(&smoother); mgStep.setSmoother(&smoother);
mgStep.setMGType(1,3,3); mgStep.setMGType(1,3,3);
mgStep.ignoreNodes_ = &ignore; mgStep.ignoreNodes_ = &p.ignore;
mgStep.basesolver_ = &basesolver; mgStep.basesolver_ = &basesolver;
// create loop solver // create loop solver
Solver solver(&mgStep, maxIterations, tol, &energynorm, Solver::FULL); Solver solver(&mgStep, maxIterations, tol, &p.energyNorm, Solver::FULL);
// solve problem // solve problem
solver.preprocess(); solver.preprocess();
solver.solve(); solver.solve();
u = mgStep.getSol(); p.u = mgStep.getSol();
if (energynorm.diff(u,u_ex)>tol*10) if (p.energyNorm.diff(p.u,p.u_ex)>tol*10)
{ {
std::cout << "The MultigridStep did not produce a satisfactory result. ||u-u_ex||=" << energynorm.diff(u,u_ex) << std::endl; std::cout << "The MultigridStep did not produce a satisfactory result. ||u-u_ex||=" << p.energyNorm.diff(p.u,p.u_ex) << std::endl;
std::cout << "||u_ex||=" << energynorm(u_ex) << std::endl; std::cout << "||u_ex||=" << p.energyNorm(p.u_ex) << std::endl;
passed = false; passed = false;
} }
p.randomize();
// now solve with the same operator but different rhs (and dirichlet values)
// create new exact solution
for (size_t i=0; i<u.size(); ++i)
for (size_t j=0; j<blocksize; ++j)
u_ex[i][j] = (1.0*rand())/RAND_MAX;
// ... and its corresponding rhs
A.mv(u_ex, rhs);
// set initial iterate (remember that the iterationStep member points to u)
u = 0.0;
// set dirichlet values
for (size_t i=0; i<u.size(); ++i)
for (size_t j=0; j<blocksize; ++j)
if (ignore[i][j])
u[i][j] = u_ex[i][j];
// reset rhs in mgStep without calling preprocess subsequently // reset rhs in mgStep without calling preprocess subsequently
mgStep.setRhs(rhs); mgStep.setRhs(p.rhs);
solver.solve(); solver.solve();
u = mgStep.getSol(); p.u = mgStep.getSol();
if (energynorm.diff(u,u_ex)>tol*10) if (p.energyNorm.diff(p.u,p.u_ex)>tol*10)
{ {
std::cout << "The MultigridStep did not produce a satisfactory result after calling setRhs(). ||u-u_ex||=" << energynorm.diff(u,u_ex) << std::endl; std::cout << "The MultigridStep did not produce a satisfactory result after calling setRhs(). ||u-u_ex||=" << p.energyNorm.diff(p.u,p.u_ex) << std::endl;
std::cout << "||u_ex||=" << energynorm(u_ex) << std::endl; std::cout << "||u_ex||=" << p.energyNorm(p.u_ex) << std::endl;
passed = false; passed = false;
} }
......
...@@ -34,52 +34,14 @@ struct UMFPackSolverTestSuite ...@@ -34,52 +34,14 @@ struct UMFPackSolverTestSuite
bool passed = true; bool passed = true;
typedef typename Dune::FieldMatrix<double, blocksize, blocksize> MatrixBlock; using Problem =
typedef typename Dune::FieldVector<double, blocksize> VectorBlock; SymmetricSampleProblem<blocksize, typename GridType::LeafGridView>;
typedef typename Dune::BCRSMatrix<MatrixBlock> Matrix; Problem p(grid.leafGridView());
typedef typename Dune::BlockVector<VectorBlock> Vector;
typedef typename Dune::BitSetVector<blocksize> BitVector;
typedef EnergyNorm<Matrix, Vector> Norm;
const auto gridView = grid.leafGridView();
Matrix A;
constructPQ1Pattern(gridView, A);
A=0.0;
assemblePQ1Stiffness(gridView, A);
// Set up a random 'solution'
Vector u(A.N()), u_ex(A.N());
u = 0;
for (size_t i=0; i<u.size(); ++i)
for (size_t j=0; j<blocksize; ++j)
{
u_ex[i][j] = (1.0*rand())/RAND_MAX;
// A[i][i][j][j] += 0.5*std::abs(A[0][0][0][0]); // in case of no dirichlet values you can make the matrix pd hereby
}
// Construct right hand side corresponding to the 'solution'
Vector rhs(A.N());
A.mv(u_ex, rhs);
BitVector ignore(A.N());
ignore.unsetAll();
markBoundaryDOFs(gridView, ignore);
// set dirichlet values
for (size_t i=0; i<u.size(); ++i)
for (size_t j=0; j<blocksize; ++j)
if (ignore[i][j])
u[i][j] = u_ex[i][j];
// we want to control errors with respect to the energy norm induced by the matrix
Norm energynorm(A);
typedef Solvers::UMFPackSolver<Matrix,Vector> Solver;
// create loop solver typedef Solvers::UMFPackSolver<typename Problem::Matrix,
Solver solver(A,u,rhs); typename Problem::Vector> Solver;
solver.ignoreNodes_ = &ignore; Solver solver(p.A,p.u,p.rhs);
solver.ignoreNodes_ = &p.ignore;
// solve problem // solve problem
solver.preprocess(); solver.preprocess();
...@@ -87,10 +49,10 @@ struct UMFPackSolverTestSuite ...@@ -87,10 +49,10 @@ struct UMFPackSolverTestSuite
//std::cout << u_ex << std::endl; //std::cout << u_ex << std::endl;
if (energynorm.diff(u,u_ex)>tol*10) if (p.energyNorm.diff(p.u,p.u_ex)>tol*10)
{ {
std::cout << "The UMFPackSolver did not produce a satisfactory result. ||u-u_ex||=" << energynorm.diff(u,u_ex) << std::endl; std::cout << "The UMFPackSolver did not produce a satisfactory result. ||u-u_ex||=" << p.energyNorm.diff(p.u,p.u_ex) << std::endl;
std::cout << "||u_ex||=" << energynorm(u_ex) << std::endl; std::cout << "||u_ex||=" << p.energyNorm(p.u_ex) << std::endl;
passed = false; passed = false;
} }
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment