diff --git a/dune/solvers/test/Makefile.am b/dune/solvers/test/Makefile.am index 81abd3f17c35a2df474f3451d86d553561ad37cf..a4cdd073bb13ceef6c8958394d0a3bb8e596663b 100644 --- a/dune/solvers/test/Makefile.am +++ b/dune/solvers/test/Makefile.am @@ -2,6 +2,7 @@ # list of tests to run TESTS = genericvectortoolstest \ lowrankoperatortest \ + mmgtest \ multigridtest \ nulloperatortest \ obstacletnnmgtest \ @@ -34,6 +35,11 @@ lowrankoperatortest_CPPFLAGS = $(COMMON_CPPFLAGS) $(GRID_CPPFLAGS) lowrankoperatortest_LDADD = $(COMMON_LDADD) $(GRID_LDADD) lowrankoperatortest_LDFLAGS = $(COMMON_LDFLAGS) $(GRID_LDFLAGS) +mmgtest_SOURCES = mmgtest.cc +mmgtest_CPPFLAGS = $(COMMON_CPPFLAGS) $(GRID_CPPFLAGS) $(IPOPT_CPPFLAGS) +mmgtest_LDADD = $(COMMON_LDADD) $(GRID_LDADD) $(IPOPT_LIBS) +mmgtest_LDFLAGS = $(COMMON_LDFLAGS) $(GRID_LDFLAGS) $(IPOPT_LIBS) + multigridtest_SOURCES = multigridtest.cc multigridtest_CPPFLAGS = $(COMMON_CPPFLAGS) $(GRID_CPPFLAGS) multigridtest_LDADD = $(COMMON_LDADD) $(GRID_LDADD) diff --git a/dune/solvers/test/mmgtest.cc b/dune/solvers/test/mmgtest.cc new file mode 100644 index 0000000000000000000000000000000000000000..ce8d5e4294e4847746ae8df45ea100b6e4d2f3f4 --- /dev/null +++ b/dune/solvers/test/mmgtest.cc @@ -0,0 +1,217 @@ +#include <config.h> + +#include <iostream> +#include <sstream> + +// dune-common includes +#include <dune/common/bitsetvector.hh> + +// dune-istl includes +#include <dune/istl/bcrsmatrix.hh> + +// dune-grid includes +#include <dune/grid/yaspgrid.hh> +#include <dune/grid/io/file/vtk/vtkwriter.hh> + +// dune-solver includes +#include <dune/solvers/norms/energynorm.hh> +#include <dune/solvers/iterationsteps/mmgstep.hh> +#include <dune/solvers/transferoperators/mandelobsrestrictor.hh> + + +#include "common.hh" + +template <class DomainType, class RangeType> +class ConstantFunction : + public Dune::VirtualFunction<DomainType, RangeType> +{ + public: + ConstantFunction(double c): + c_(c) + {} + + void evaluate(const DomainType& x, RangeType& y) const + { + y = c_; + } + + private: + double c_; +}; + + +template<class GridType, class MatrixType, class VectorType, class BitVector> +void solveObstacleProblemByMMGSolver(const GridType& grid, const MatrixType& mat, VectorType& x, const VectorType& rhs, const BitVector& ignore, int maxIterations=100, double tolerance=1.0e-10) +{ + typedef VectorType Vector; + typedef MatrixType Matrix; + typedef EnergyNorm<Matrix, Vector> Norm; + typedef QuadraticIPOptSolver<MatrixType,VectorType> Solver; + + // create double obstacle constraints +#if 0 + const int blockSize = VectorType::block_type::dimension; + + BoxConstraintVector boxConstraints(rhs.size()); + for (int i = 0; i < boxConstraints.size(); ++i) + { + for (int j = 0; j < blockSize; ++j) + { + boxConstraints[i].lower(j) = -1; + boxConstraints[i].upper(j) = +1; + } + } +#endif + + ///////////////////////////////////////////////////////////// + // Create a monotone multigrid solver + ///////////////////////////////////////////////////////////// + + // First create a Gauss-seidel base solver + ProjectedBlockGSStep<MatrixType, VectorType>* baseSolverStep = new ProjectedBlockGSStep<MatrixType, VectorType>; + + EnergyNorm<MatrixType, VectorType>* baseEnergyNorm = new EnergyNorm<MatrixType, VectorType>(*baseSolverStep); + + ::LoopSolver<VectorType>* baseSolver = new ::LoopSolver<VectorType>(baseSolverStep, + 100, // base iterations + 1e-8, // tolerance + baseEnergyNorm, + Solver::QUIET); + + // Make pre and postsmoothers + ProjectedBlockGSStep<MatrixType, VectorType>* presmoother = new ProjectedBlockGSStep<MatrixType, VectorType>; + ProjectedBlockGSStep<MatrixType, VectorType>* postsmoother = new ProjectedBlockGSStep<MatrixType, VectorType>; + + MonotoneMGStep<MatrixType, VectorType>* mmgStep = new MonotoneMGStep<MatrixType, VectorType>(); + + mmgStep->setMGType(3, 3, 1); + mmgStep->ignoreNodes_ = &ignore; + mmgStep->basesolver_ = baseSolver; + mmgStep->setSmoother(presmoother, postsmoother); + mmgStep->obstacleRestrictor_= new MandelObstacleRestrictor<VectorType>(); + mmgStep->hasObstacle_ = NULL; + mmgStep->verbosity_ = Solver::QUIET; + + EnergyNorm<MatrixType,VectorType>* h1SemiNorm = new EnergyNorm<MatrixType,VectorType>(mat); + + LoopSolver<VectorType> solver (mmgStep, + 100, // iterations + 1e-6, // tolerance + h1SemiNorm, + Solver::REDUCED); + // solve problem + solver.solve(); +} + + + + + +template <class GridType> +bool checkWithGrid(const GridType& grid, const std::string fileName="") +{ + bool passed = true; + + static const int dim = GridType::dimension; + + typedef typename Dune::FieldMatrix<double, 1, 1> MatrixBlock; + typedef typename Dune::FieldVector<double, 1> VectorBlock; + typedef typename Dune::BCRSMatrix<MatrixBlock> Matrix; + typedef typename Dune::BlockVector<VectorBlock> Vector; + typedef typename Dune::BitSetVector<1> BitVector; + + typedef typename GridType::LeafGridView GridView; + typedef typename Dune::FieldVector<double, dim> DomainType; + typedef typename Dune::FieldVector<double, 1> RangeType; + + + const GridView gridView = grid.leafView(); + + Matrix A; + constructPQ1Pattern(gridView, A); + A=0.0; + assemblePQ1Stiffness(gridView, A); + + Vector rhs(A.N()); + rhs = 0; + ConstantFunction<DomainType, RangeType> f(50); + assemblePQ1RHS(gridView, rhs, f); + + Vector u(A.N()); + u = 0; + + BitVector ignore(A.N()); + ignore.unsetAll(); + markBoundaryDOFs(gridView, ignore); + + + solveObstacleProblemByMMGSolver(grid, A, u, rhs, ignore); + + if (fileName!="") + { + typename Dune::VTKWriter<GridView> vtkWriter(gridView); + vtkWriter.addVertexData(u, "solution"); + vtkWriter.write(fileName); + } + + return passed; +} + + +template <int dim> +bool checkWithYaspGrid(int refine, const std::string fileName="") +{ + bool passed = true; + + typedef Dune::YaspGrid<dim> GridType; + + typename Dune::FieldVector<typename GridType::ctype,dim> L(1.0); + typename Dune::FieldVector<int,dim> s(1); + typename Dune::FieldVector<bool,dim> periodic(false); + + GridType grid(L, s, periodic, 0); + + for (int i = 0; i < refine; ++i) + grid.globalRefine(1); + + std::cout << "Testing with YaspGrid<" << dim << ">" << std::endl; + std::cout << "Number of levels: " << (grid.maxLevel()+1) << std::endl; + std::cout << "Number of leaf nodes: " << grid.leafView().size(dim) << std::endl; + + passed = passed and checkWithGrid(grid, fileName); + + + return passed; +} + + + + +int main(int argc, char** argv) try +{ + bool passed(true); + + + int refine1d = 16; + int refine2d = 8; + int refine3d = 5; + + if (argc>1) + std::istringstream(argv[1]) >> refine1d; + if (argc>2) + std::istringstream(argv[2]) >> refine2d; + if (argc>3) + std::istringstream(argv[3]) >> refine3d; + + passed = passed and checkWithYaspGrid<1>(refine1d, "obstacletnnmgtest_yasp_1d_solution"); + passed = passed and checkWithYaspGrid<2>(refine2d, "obstacletnnmgtest_yasp_2d_solution"); + passed = passed and checkWithYaspGrid<3>(refine3d, "obstacletnnmgtest_yasp_3d_solution"); + + return passed ? 0 : 1; +} +catch (Dune::Exception e) { + + std::cout << e << std::endl; + +} +