// ============================================================================ // == == // == AMDiS - Adaptive multidimensional simulations == // == == // ============================================================================ // == == // == TU Dresden == // == == // == Institut für Wissenschaftliches Rechnen == // == Zellescher Weg 12-14 == // == 01069 Dresden == // == germany == // == == // ============================================================================ // == == // == https://gforge.zih.tu-dresden.de/projects/amdis/ == // == == // ============================================================================ /** \file OEMSolver.h */ /** * \defgroup Solver Solver module * @{ @} * * \brief * Contains all classes needed for solving linear and non linear equation * systems. */ #ifndef AMDIS_OEM_SOLVER_H #define AMDIS_OEM_SOLVER_H #include "Global.h" #include "AMDiS_fwd.h" #include "Parameters.h" #include "SolverMatrix.h" #include "DOFVector.h" #include "SystemVector.h" #include "DOFMatrix.h" #include "ITL_Preconditioner.h" namespace AMDiS { /** * \ingroup Solver * *\brief * Solver for linear equation systems. */ class OEMSolver { public: typedef DOFMatrix::base_matrix_type matrix_type; typedef DOFMatrix::value_type value_type; /// The constructor reads needed parameters and sets solvers \ref name. OEMSolver(std::string str) : name(str), tolerance(0), relative(0), max_iter(1000), info(0), residual(0), print_cycle(100), iterations(-1), error(-1), multipleRhs(false), leftPrecon(NULL), rightPrecon(NULL) {} /// virtual ~OEMSolver() {} void initParameters() { FUNCNAME("OEMSolver::initParameters()"); GET_PARAMETER(0, name + "->tolerance", "%f", &tolerance); GET_PARAMETER(0, name + "->relative tolerance", "%f", &relative); GET_PARAMETER(0, name + "->max iteration", "%d", &max_iter); GET_PARAMETER(0, name + "->print cycle", "%d", &print_cycle); GET_PARAMETER(0, name + "->info", "%d", &info); } /** Set left Preconditioner * * It is assumed that the solver owns the preconditioner from this call. * That means that the preconditioner is deleted by the solver when not needed. */ void setLeftPrecon(ITL_BasePreconditioner* p) { if (leftPrecon) delete leftPrecon; leftPrecon = p; } /** Set right Preconditioner * * It is assumed that the solver owns the preconditioner from this call. * That means that the preconditioner is deleted by the solver when not needed. */ void setRightPrecon(ITL_BasePreconditioner* p) { if (rightPrecon) delete rightPrecon; rightPrecon = p; } /// Linear System to be solved in the derived class virtual int solveSystem(const DOFMatrix::base_matrix_type& A, mtl::dense_vector& x, const mtl::dense_vector& b) = 0; /// Solve a linear system for a scalar problem. int solveSystem(const SolverMatrix& A, DOFVector& x, DOFVector& b) { mtl::dense_vector xx(x.getUsedSize()), bb(b.getUsedSize()); // Copy rhs vector int counter = 0; DOFVector::Iterator it_b(&b, USED_DOFS); DOFVector::Iterator it_x(&x, USED_DOFS); for (it_b.reset(), it_x.reset(); !it_b.end(); ++it_b, ++it_x) { bb[counter] = *it_b; xx[counter] = *it_x; counter++; } int r = solveSystem(A.getMatrix(), xx, bb); // Copy solution vector to DOFVector counter = 0; for (it_x.reset(); !it_x.end(); ++it_x) *it_x = xx[counter++]; return r; } /// Solve a linear system for a vectorial problem. virtual int solveSystem(const SolverMatrix >& A, SystemVector& x, SystemVector& b) { int ns = x.getSize(), // Number of systems. size = x.getUsedSize(); // Size of all DOFVectors // Copy vectors mtl::dense_vector xx(size), bb(size); for (int i = 0, counter = 0; i < ns; i++) { DOFVector::Iterator it_b(b.getDOFVector(i), USED_DOFS); DOFVector::Iterator it_x(x.getDOFVector(i), USED_DOFS); for (it_b.reset(), it_x.reset(); !it_b.end(); ++it_b, ++it_x) { bb[counter] = *it_b; xx[counter] = *it_x; counter++; } } // Solver on DOFVector for single system int r = solveSystem(A.getMatrix(), xx, bb); for (int i = 0, counter = 0; i < ns; i++) { DOFVector::Iterator it(x.getDOFVector(i), USED_DOFS); for (it.reset(); !it.end(); ++it) *it = xx[counter++]; } return r; } /** \name getting methods * \{ */ /// Returns solvers \ref name. inline std::string getName() const { return name; } /// Returns \ref tolerance inline double getTolerance() const { return tolerance; } /// Returns \ref max_iter inline int getMaxIterations() const { return max_iter; } /// Returns \ref residual inline double getResidual() const { return residual; } /** \} */ /** \name setting methods * \{ */ /// Sets \ref tolerance inline void setTolerance(double tol) { tolerance = tol; } /// Sets \ref relative inline void setRelative(double rel) { relative = rel; } /// Sets \ref max_iter inline void setMaxIterations(int i) { max_iter = i; } /// Returns number of iterations in last run of an iterative solver inline int getIterations() { return iterations; } /// Returns error code in last run of an iterative solver inline int getErrorCode() { return error; } /// Sets \ref info inline void setInfo(int i) { info = i; } void setMultipleRhs(bool b) { multipleRhs = b; } /** \} */ protected: /// solvers name. std::string name; /// Solver tolerance |r|. Set in OEMSolver's constructor. double tolerance; /// Relative solver tolerance |r|/|r0|. Set in OEMSolver's constructor. double relative; /// maximal number of iterations. Set in OEMSolver's constructor. int max_iter; /// info level during solving the system. Set in OEMSolver's constructor. int info; /// current residual. double residual; /// Print cycle, after how many iterations the residuum norm is logged. int print_cycle; /// How many iterations were performed in last solver (not set by UmfPack) int iterations; /// Error code in last solver (not set by UmfPack) int error; /** \brief * If true, the solver has to solve multiple right hand sides with the same * matrix. Some solvers, e.g. direct once, may take advanteges from this knowledge, * as they can do the factorization of the matrix only once. */ bool multipleRhs; /// Left preconditioner (ignored by some iterative solvers and by UmfPack) ITL_BasePreconditioner *leftPrecon; /// Right preconditioner (ignored by some iterative solvers and by UmfPack) ITL_BasePreconditioner *rightPrecon; }; /** * \ingroup Solver * * \brief * Interface for creators of concrete OEMSolvers. */ class OEMSolverCreator : public CreatorInterface { public: virtual ~OEMSolverCreator() {} /// Sets \ref problem void setName(std::string str) { name = str; } protected: /** \brief * Pointer to the problem the solver will belong to. Needed as parameter * when constructing an OEMSolver */ std::string name; }; } #include "ITL_Solver.h" #endif // AMDIS_OEM_SOLVER_H