From 16374b9e2a4666d6344ed2bce4aeb87d1a2b075c Mon Sep 17 00:00:00 2001 From: Lisa Julia Nebel <lisa_julia.nebel@tu-dresden.de> Date: Thu, 16 Apr 2020 15:22:54 +0200 Subject: [PATCH] Cleanup of the TrustRegionSolver class Mainly issues related to dune-parmg. --- dune/elasticity/common/trustregionsolver.cc | 143 +++++++------------- dune/elasticity/common/trustregionsolver.hh | 6 + 2 files changed, 55 insertions(+), 94 deletions(-) diff --git a/dune/elasticity/common/trustregionsolver.cc b/dune/elasticity/common/trustregionsolver.cc index 5d16bf1..0d1da51 100644 --- a/dune/elasticity/common/trustregionsolver.cc +++ b/dune/elasticity/common/trustregionsolver.cc @@ -40,16 +40,8 @@ setup(const typename BasisType::GridView::Grid& grid, int nu2, int baseIterations, double baseTolerance) -{ -#if HAVE_DUNE_PARMG - Dune::Timer setupTimer; - mgSetup_ = std::make_unique<MGSetup>(grid); - mgSetup_->overlap(true); - mgSetup_->setupSmoother(1.0); - if (grid.comm().rank()==0) - std::cout << "Parallel multigrid setup took " << setupTimer.stop() << " seconds." << std::endl; -#endif +{ grid_ = &grid; assembler_ = assembler; x_ = x; @@ -59,10 +51,30 @@ setup(const typename BasisType::GridView::Grid& grid, innerIterations_ = multigridIterations; innerTolerance_ = mgTolerance; ignoreNodes_ = std::make_shared<Dune::BitSetVector<blocksize>>(dirichletNodes); + baseIterations_ = baseIterations; + baseTolerance_ = baseTolerance; int numLevels = grid_->maxLevel()+1; -#if !HAVE_DUNE_PARMG +#if HAVE_DUNE_PARMG + Dune::Timer setupTimer; + mgSetup_ = std::make_unique<MGSetup>(grid); + mgSetup_->overlap(false); + mgSetup_->ignore(std::const_pointer_cast<Dune::BitSetVector<blocksize> >(ignoreNodes_)); + + BasisType feBasis(grid.levelGridView(grid.maxLevel())); + DuneFunctionsBasis<BasisType> basis(feBasis); + + innerMultigridStep_ = std::make_unique<Dune::ParMG::Multigrid<VectorType> >(); + innerMultigridStep_->mu_ = mu; + innerMultigridStep_->preSmootherSteps_ = nu1; + innerMultigridStep_->postSmootherSteps_ = nu2; + + if (grid.comm().rank()==0) + std::cout << "Parallel multigrid setup took " << setupTimer.stop() << " seconds." << std::endl; +#else + DuneFunctionsBasis<BasisType> basis(grid.leafGridView()); + // //////////////////////////////// // Create a multigrid solver // //////////////////////////////// @@ -87,11 +99,6 @@ setup(const typename BasisType::GridView::Grid& grid, baseNorm, Solver::QUIET); #endif -#endif - -#if HAVE_DUNE_PARMG - mgSetup_->ignore(std::const_pointer_cast<Dune::BitSetVector<blocksize> >(ignoreNodes_)); -#else // Make pre and postsmoothers auto presmoother = std::make_shared< TrustRegionGSStep<MatrixType, CorrectionType> >(); auto postsmoother = std::make_shared< TrustRegionGSStep<MatrixType, CorrectionType> >(); @@ -108,13 +115,6 @@ setup(const typename BasisType::GridView::Grid& grid, // ////////////////////////////////////////////////////////////////////////////////////// // Assemble a Laplace matrix to create a norm that's equivalent to the H1-norm // ////////////////////////////////////////////////////////////////////////////////////// - -#if HAVE_DUNE_PARMG - BasisType feBasis(grid.levelGridView(grid.maxLevel())); - DuneFunctionsBasis<BasisType> basis(feBasis); -#else - DuneFunctionsBasis<BasisType> basis(grid.leafGridView()); -#endif OperatorAssembler<DuneFunctionsBasis<BasisType>,DuneFunctionsBasis<BasisType>,Dune::Partitions::Interior> operatorAssembler(basis, basis); LaplaceAssembler<GridType, @@ -129,19 +129,6 @@ setup(const typename BasisType::GridView::Grid& grid, h1SemiNorm_ = std::make_shared< H1SemiNorm<CorrectionType> >(*A); -#if HAVE_DUNE_PARMG - innerMultigridStep_ = std::make_unique<Dune::ParMG::Multigrid<VectorType> >(); - innerMultigridStep_->mu_ = mu; - innerMultigridStep_->preSmootherSteps_ = nu1; - innerMultigridStep_->postSmootherSteps_ = nu2; -#else - innerSolver_ = std::make_shared<LoopSolver<CorrectionType> >(mmgStep, - innerIterations_, - innerTolerance_, - h1SemiNorm_, - Solver::REDUCED); -#endif - // ////////////////////////////////////////////////////////////////////////////////////// // Assemble a mass matrix to create a norm that's equivalent to the L2-norm // This will be used to monitor the gradient @@ -167,6 +154,11 @@ setup(const typename BasisType::GridView::Grid& grid, indices.exportIdx(*hessianMatrix_); #if !HAVE_DUNE_PARMG + innerSolver_ = std::make_shared<LoopSolver<CorrectionType> >(mmgStep, + innerIterations_, + innerTolerance_, + h1SemiNorm_, + Solver::REDUCED); // //////////////////////////////////// // Create the transfer operators // //////////////////////////////////// @@ -248,9 +240,6 @@ void TrustRegionSolver<BasisType,VectorType>::solve() BasisType basis(grid_->levelGridView(grid_->maxLevel())); BasisType coarseBasis(grid_->levelGridView(0)); std::vector<BoxConstraint<typename VectorType::field_type, blocksize>> coarseTrustRegionObstacles(coarseBasis.size()); - int numLevels = grid_->maxLevel()+1; - - auto& levelOp = mgSetup_->levelOps_; #endif MaxNormTrustRegion<blocksize> trustRegion(basis.size(), initialTrustRegionRadius_); @@ -287,6 +276,10 @@ void TrustRegionSolver<BasisType,VectorType>::solve() *hessianMatrix_, i==0 // assemble occupation pattern only for the first call ); +#if HAVE_DUNE_PARMG + std::function<void(VectorType&)> accumulate = Dune::ParMG::makeAccumulate<VectorType>(*(mgSetup_->comms_.back())); + accumulate(rhs); +#endif rhs *= -1; // The right hand side is the _negative_ gradient @@ -306,15 +299,13 @@ void TrustRegionSolver<BasisType,VectorType>::solve() if (this->verbosity_ == Solver::FULL) std::cout << "Assembly took " << gradientTimer.elapsed() << " sec." << std::endl; - // Transfer matrix data - stiffnessMatrix = *hessianMatrix_; - #if HAVE_DUNE_PARMG - Dune::ParMG::collectDiagonal(stiffnessMatrix, *mgSetup_->comms_.back()); + if (!mgSetup_->overlap()) + Dune::ParMG::collectDiagonal(*hessianMatrix_, *mgSetup_->comms_.back()); mgSetup_->matrix(hessianMatrix_); - - levelOp.back().maybeRestrictToMaster(rhs); #endif + // Transfer matrix data + stiffnessMatrix = *hessianMatrix_; recomputeGradientHessian = false; @@ -323,17 +314,22 @@ void TrustRegionSolver<BasisType,VectorType>::solve() CorrectionType corr(rhs.size()); corr = 0; + //Take the obstacles on the finest grid and give them to the multigrid solver, it will create a hierarchy for all coarser grids + trustRegionObstacles = trustRegion.obstacles(); + #if ! HAVE_DUNE_PARMG mgStep->setProblem(stiffnessMatrix, corr, rhs); - trustRegionObstacles = trustRegion.obstacles(); mgStep->setObstacles(trustRegionObstacles); #else - mgSetup_->setupLevelOps(); + mgSetup_->setupObstacles(std::make_shared< std::vector<BoxConstraint<typename VectorType::field_type, blocksize>> >(trustRegionObstacles)); + mgSetup_->setupSmoother(damping_); + + auto& levelOp = mgSetup_->levelOps_; bool enableCoarseCorrection = true; if (enableCoarseCorrection) - mgSetup_->setupCoarseIPOPTSolver(); + mgSetup_->setupCoarseIPOPTSolver(baseTolerance_, baseIterations_); else mgSetup_->setupCoarseNullSolver(); @@ -343,29 +339,15 @@ void TrustRegionSolver<BasisType,VectorType>::solve() using ProjGS = Dune::ParMG::ParallelProjectedGS<MatrixType, VectorType>; using namespace Dune::ParMG; - auto& levelOp = mgSetup_->levelOps_; - trustRegionObstacles = trustRegion.obstacles(); - for (int i = 0; i < coarseTrustRegionObstacles.size(); i++) - coarseTrustRegionObstacles[i] = trustRegionObstacles[i]; - mgSetup_->setCoarseObstacles(coarseTrustRegionObstacles); ProjGS projGs(&stiffnessMatrix, &trustRegionObstacles, mgSetup_->ignores_.back().get()); projGs.accumulate([&](VectorType& x) { levelOp.back().maybeCopyFromMaster(x); }); projGs.dampening(1.0); - std::function<void(VectorType&)> collect = Dune::ParMG::makeCollect<VectorType>(*(mgSetup_->comms_.back())); std::function<void(VectorType&)> restrictToMaster = [op=levelOp.back()](VectorType& x) { op.maybeRestrictToMaster(x); }; - - auto energyFunctional = Dune::ParMG::makeParallelEnergyFunctional( - stiffnessMatrix, - rhs, - grid_->comm(), - //collect - restrictToMaster - ); - // matrix, b, dofmap, master); + restrictToMaster(rhs); //Distributed energy norm auto energyNorm = Dune::ParMG::parallelEnergyNorm<VectorType>(stiffnessMatrix, restrictToMaster, grid_->comm()); @@ -377,30 +359,16 @@ void TrustRegionSolver<BasisType,VectorType>::solve() levelOp.back().maybeCopyFromMaster(corr); - double J = 0.0; VectorType b; unsigned step = 0; - int activeObstacles; MPI_Barrier(grid_->comm()); - auto realIterationStep = [&](VectorType& correction) { - auto& project = projGs.project_; - projGs.apply(correction, rhs); - // prepare truncation - auto currentIgnore = std::make_shared<Dune::BitSetVector<VectorType::block_type::dimension> >(*ignoreNodes_); - auto extraIgnore = std::make_shared<Dune::BitSetVector<VectorType::block_type::dimension> >(ignoreNodes_->size(), false); - project.ignoreActive(correction, *currentIgnore); - project.ignoreActive(correction, *extraIgnore); - mgSetup_->ignore(currentIgnore); - assert(currentIgnore->count() - ignoreNodes_->count() == extraIgnore->count()); - activeObstacles = extraIgnore->count(); - + auto realIterationStep = [&](VectorType& innerIterate) { // Create vector b to keep rhs untouched! b = rhs; - innerMultigridStep_->apply(correction, b); - - project(correction); - J = energyFunctional(correction); + // The variable innerIterate is the correction that will be added + // to the current iterate in the trust region step. + innerMultigridStep_->apply(innerIterate, b); ++step; }; @@ -410,22 +378,9 @@ void TrustRegionSolver<BasisType,VectorType>::solve() auto innerSolver_ = std::make_shared< LoopSolver<CorrectionType> >(iterationStep, innerIterations_, innerTolerance_, - // h1SemiNorm_, + // h1SemiNorm_, //TODO: test this! solverNorm, NumProc::QUIET); - innerSolver_->addCriterion( - [&]() { - return Dune::formatString(" % 12.10e", J); - }, - " energy " - ); - - innerSolver_->addCriterion( - [&]() { - return Dune::formatString(" % 9d", activeObstacles); - }, - " activeObs" - ); #endif innerSolver_->preprocess(); diff --git a/dune/elasticity/common/trustregionsolver.hh b/dune/elasticity/common/trustregionsolver.hh index 1b87165..d819a2a 100644 --- a/dune/elasticity/common/trustregionsolver.hh +++ b/dune/elasticity/common/trustregionsolver.hh @@ -119,6 +119,12 @@ protected: /** \brief Error tolerance of the multigrid QP solver */ double innerTolerance_; + /** \brief Maximum number of base solver iterations */ + int baseIterations_; + + /** \brief Error tolerance of the base solver inside the multigrid QP solver */ + double baseTolerance_; + /** \brief Hessian matrix */ std::shared_ptr<MatrixType> hessianMatrix_; -- GitLab