From 52fc747dd49744ab1e02a9ae56ac1f8de41984d3 Mon Sep 17 00:00:00 2001 From: Oliver Sander <sander@igpm.rwth-aachen.de> Date: Mon, 6 Apr 2009 14:36:12 +0000 Subject: [PATCH] moved to new module dune-solvers [[Imported from SVN: r2351]] --- dune-solvers/solvers/cgsolver.cc | 165 +++++++++++++++++++++++++++++++ dune-solvers/solvers/cgsolver.hh | 61 ++++++++++++ 2 files changed, 226 insertions(+) create mode 100644 dune-solvers/solvers/cgsolver.cc create mode 100644 dune-solvers/solvers/cgsolver.hh diff --git a/dune-solvers/solvers/cgsolver.cc b/dune-solvers/solvers/cgsolver.cc new file mode 100644 index 00000000..7a5565b9 --- /dev/null +++ b/dune-solvers/solvers/cgsolver.cc @@ -0,0 +1,165 @@ +#include <cmath> +#include <limits> +#include <iomanip> + +template <class MatrixType, class VectorType> +void CGSolver<MatrixType, VectorType>::check() const +{ + if (!preconditioner_) + DUNE_THROW(SolverError, "You need to supply a preconditioner to a CG solver!"); + + preconditioner_->check(); + + if (!errorNorm_) + DUNE_THROW(SolverError, "You need to supply a norm to a CG solver!"); + +} + +template <class MatrixType, class VectorType> +void CGSolver<MatrixType, VectorType>::solve() +{ + + int i; + + VectorType& b = *rhs_; + + // Check whether the solver is set up properly + check(); + + // set up preconditioner + preconditioner_->preprocess(); + + if (this->verbosity_ != NumProc::QUIET) + std::cout << "--- CGSolver ---\n"; + + if (this->verbosity_ == NumProc::FULL) + { + std::cout << " iter"; + std::cout << " error"; + std::cout << " rate"; + std::string header = preconditioner_->getOutput(); + std::cout << header; + std::cout << std::endl; + std::cout << "-----"; + std::cout << "---------------"; + std::cout << "---------"; + for(int i=0; i<header.size(); ++i) + std::cout << "-"; + std::cout << std::endl; + } + + double error = std::numeric_limits<double>::max(); + + double normOfOldCorrection = 0; + double totalConvRate = 1; + maxTotalConvRate_ = 0; + int convRateCounter = 0; + + // overwrite b with defect + matrix_->mmv(*x_,b); + + VectorType p(*x_); // the search direction + VectorType q(*x_); // a temporary vector + + // some local variables + double rho,rholast,lambda,alpha,beta; + + // determine initial search direction + p = 0; // clear correction + + // apply preconditioner + preconditioner_->setProblem(*matrix_,p,b); + preconditioner_->iterate(); + p = preconditioner_->getSol(); + rholast = p*b; // orthogonalization + + // Loop until desired tolerance or maximum number of iterations is reached + for (i=0; i<this->maxIterations_ && (error>this->tolerance_ || std::isnan(error)); i++) { + + // Backup of the current solution for the error computation later on + VectorType oldSolution = *x_; + + // Perform one iteration step + // minimize in given search direction p + matrix_->mv(p,q); // q=Ap + alpha = p*q; // scalar product + lambda = rholast/alpha; // minimization + x_->axpy(lambda,p); // update solution + rhs_->axpy(-lambda,q); // update defect + + // determine new search direction + q = 0; // clear correction + + // apply preconditioner + preconditioner_->setProblem(*matrix_,q,b); + preconditioner_->iterate(); + q = preconditioner_->getSol(); + + rho = q*b; // orthogonalization + beta = rho/rholast; // scaling factor + p *= beta; // scale old search direction + p += q; // orthogonalization with correction + rholast = rho; // remember rho for recurrence + + // write iteration to file, if requested + if (this->historyBuffer_!="") { + VectorType intermediateSol = preconditioner_->getSol(); + + std::stringstream iSolFilename; + iSolFilename << this->historyBuffer_ << "/intermediatesolution_" << std::setw(4) << std::setfill('0') << i; + + std::ofstream file(iSolFilename.str().c_str(), std::ios::out|std::ios::binary); + if (not(file)) + DUNE_THROW(SolverError, "Couldn't open file " << iSolFilename << " for writing"); + + GenericVector::writeBinary(file, intermediateSol); + + file.close(); + } + + // Compute error + double oldNorm = errorNorm_->operator()(oldSolution); + oldSolution -= *x_; + + double normOfCorrection = errorNorm_->operator()(oldSolution); + + if (this->useRelativeError_) + error = normOfCorrection / oldNorm; + else + error = normOfCorrection; + + double convRate = normOfCorrection / normOfOldCorrection; + + normOfOldCorrection = normOfCorrection; + + if (!isinf(convRate) && !isnan(convRate)) { + totalConvRate *= convRate; + maxTotalConvRate_ = std::max(maxTotalConvRate_, std::pow(totalConvRate, 1/((double)convRateCounter+1))); + convRateCounter++; + } + + // Output + if (this->verbosity_ == NumProc::FULL) { + std::cout << std::setw(5) << i; + + std::cout << std::setiosflags(std::ios::scientific); + std::cout << std::setw(15) << std::setprecision(7) << error; + std::cout << std::resetiosflags(std::ios::scientific); + + std::cout << std::setiosflags(std::ios::fixed); + std::cout << std::setw(9) << std::setprecision(5) << convRate; + std::cout << std::resetiosflags(std::ios::fixed); + + std::cout << std::endl; + } + + } + + + if (this->verbosity_ != NumProc::QUIET) { + std::cout << "maxTotalConvRate: " << maxTotalConvRate_ << ", " + << i << " iterations performed\n"; + std::cout << "--------------------\n"; + } + +} diff --git a/dune-solvers/solvers/cgsolver.hh b/dune-solvers/solvers/cgsolver.hh new file mode 100644 index 00000000..096a5920 --- /dev/null +++ b/dune-solvers/solvers/cgsolver.hh @@ -0,0 +1,61 @@ +#ifndef CG_SOLVER_HH +#define CG_SOLVER_HH + +#include <dune/ag-common/iterativesolver.hh> +#include <dune/ag-common/lineariterationstep.hh> +#include <dune/ag-common/norms/norm.hh> + +/** \brief A conjugate gradient solver + * + */ +template <class MatrixType, class VectorType> +class CGSolver : public IterativeSolver<VectorType> +{ + static const int blocksize = VectorType::block_type::size; + +public: + + /** \brief Constructor taking all relevant data */ + + CGSolver(const MatrixType* matrix, + VectorType* x, + VectorType* rhs, + LinearIterationStep<MatrixType,VectorType>* preconditioner, + int maxIterations, + double tolerance, + Norm<VectorType>* errorNorm, + NumProc::VerbosityMode verbosity, + bool useRelativeError=true) + : IterativeSolver<VectorType>(tolerance,maxIterations,verbosity,useRelativeError), + matrix_(matrix), x_(x), rhs_(rhs), + preconditioner_(preconditioner), errorNorm_(errorNorm) + {} + + /** \brief Loop, call the iteration procedure + * and monitor convergence */ + virtual void solve(); + + /** \brief Checks whether all relevant member variables are set + * \exception SolverError if the iteration step is not set up properly + */ + virtual void check() const; + + const MatrixType* matrix_; + + VectorType* x_; + + VectorType* rhs_; + + //! The iteration step used by the algorithm + LinearIterationStep<MatrixType,VectorType>* preconditioner_; + + //! The norm used to measure convergence + Norm<VectorType>* errorNorm_; + + double maxTotalConvRate_; + +}; + +#include "cgsolver.cc" + +#endif -- GitLab