From c4f4744374e3b4acb891e9fe1a1d368c4adcd2ce Mon Sep 17 00:00:00 2001 From: Oliver Sander <sander@igpm.rwth-aachen.de> Date: Fri, 25 Nov 2011 11:52:18 +0000 Subject: [PATCH] implement a simple quasi-Newton method [[Imported from SVN: r8261]] --- dune/gfe/riemanniantrsolver.cc | 36 +++++++++++++++++++++++++++------- 1 file changed, 29 insertions(+), 7 deletions(-) diff --git a/dune/gfe/riemanniantrsolver.cc b/dune/gfe/riemanniantrsolver.cc index bce54849..21b9b982 100644 --- a/dune/gfe/riemanniantrsolver.cc +++ b/dune/gfe/riemanniantrsolver.cc @@ -213,6 +213,8 @@ void RiemannianTrustRegionSolver<GridType,TargetSpace>::solve() // ///////////////////////////////////////////////////// double oldEnergy = assembler_->computeEnergy(x_); + bool quasiNewtonMethod = false; + bool recomputeHessian = true; for (int i=0; i<maxTrustRegionSteps_; i++) { @@ -237,12 +239,16 @@ void RiemannianTrustRegionSolver<GridType,TargetSpace>::solve() assembler_->assembleGradient(x_, rhs); std::cout << "gradient assembly took " << gradientTimer.elapsed() << " sec." << std::endl; gradientTimer.reset(); - assembler_->assembleMatrix(x_, - *hessianMatrix_, - i==0 // assemble occupation pattern only for the first call - ); - std::cout << "hessian assembly took " << gradientTimer.elapsed() << " sec." << std::endl; - + + if (recomputeHessian) { + assembler_->assembleMatrix(x_, + *hessianMatrix_, + i==0 // assemble occupation pattern only for the first call + ); + std::cout << "hessian assembly took " << gradientTimer.elapsed() << " sec." << std::endl; + } else + std::cout << "Reuse previous Hessian" << std::endl; + // The right hand side is the _negative_ gradient rhs *= -1; @@ -447,6 +453,9 @@ void RiemannianTrustRegionSolver<GridType,TargetSpace>::solve() // current energy becomes 'oldEnergy' for the next iteration oldEnergy = energy; + if (quasiNewtonMethod) + recomputeHessian = false; + } else if ( (oldEnergy-energy) / modelDecrease > 0.01 || std::abs(oldEnergy-energy) < 1e-12) { // successful iteration @@ -455,9 +464,22 @@ void RiemannianTrustRegionSolver<GridType,TargetSpace>::solve() // current energy becomes 'oldEnergy' for the next iteration oldEnergy = energy; + if (quasiNewtonMethod) + recomputeHessian = false; + } else { + // unsuccessful iteration - trustRegion.scale(0.5); + + // If quasi Newton method and we have used an old matrix: + // Try again with the actual Newton matrix + if (not recomputeHessian && quasiNewtonMethod) { + recomputeHessian = true; + } else { + // Decrease the trust-region radius + trustRegion.scale(0.5); + } + if (this->verbosity_ == NumProc::FULL) std::cout << "Unsuccessful iteration!" << std::endl; } -- GitLab