From 4315a5219fe98fa990465b9cbec7f33f78bc1aad Mon Sep 17 00:00:00 2001 From: Slaven Peles Date: Fri, 5 Apr 2024 19:18:22 -0400 Subject: [PATCH 01/11] Separate files for linear solvers base classes. --- resolve/CMakeLists.txt | 10 +- resolve/LinSolver.cpp | 175 +---------------------- resolve/LinSolver.hpp | 96 ++----------- resolve/LinSolverDirect.cpp | 100 +++++++++++++ resolve/LinSolverDirect.hpp | 55 +++++++ resolve/LinSolverDirectCpuILU0.hpp | 3 +- resolve/LinSolverDirectCuSolverGLU.hpp | 7 +- resolve/LinSolverDirectCuSolverRf.hpp | 6 +- resolve/LinSolverDirectCuSparseILU0.hpp | 9 +- resolve/LinSolverDirectKLU.hpp | 4 +- resolve/LinSolverDirectRocSolverRf.hpp | 10 +- resolve/LinSolverDirectRocSparseILU0.hpp | 9 +- resolve/LinSolverDirectSerialILU0.hpp | 3 +- resolve/LinSolverIterative.cpp | 100 +++++++++++++ resolve/LinSolverIterative.hpp | 57 ++++++++ resolve/LinSolverIterativeFGMRES.hpp | 4 +- resolve/LinSolverIterativeRandFGMRES.hpp | 4 +- 17 files changed, 377 insertions(+), 275 deletions(-) create mode 100644 resolve/LinSolverDirect.cpp create mode 100644 resolve/LinSolverDirect.hpp create mode 100644 resolve/LinSolverIterative.cpp create mode 100644 resolve/LinSolverIterative.hpp diff --git a/resolve/CMakeLists.txt b/resolve/CMakeLists.txt index 33d8953c..a4198dbb 100644 --- a/resolve/CMakeLists.txt +++ b/resolve/CMakeLists.txt @@ -11,6 +11,8 @@ add_subdirectory(utilities) # C++ files set(ReSolve_SRC LinSolver.cpp + LinSolverDirect.cpp + LinSolverIterative.cpp GramSchmidt.cpp LinSolverIterativeFGMRES.cpp LinSolverDirectCpuILU0.cpp @@ -36,8 +38,8 @@ set(ReSolve_CUDASDK_SRC # C++ code that links to ROCm libraries set(ReSolve_ROCM_SRC - LinSolverDirectRocSolverRf.cpp - LinSolverDirectRocSparseILU0.cpp + LinSolverDirectRocSolverRf.cpp + LinSolverDirectRocSparseILU0.cpp ) # Header files to be installed @@ -45,6 +47,8 @@ set(ReSolve_HEADER_INSTALL Common.hpp cusolver_defs.hpp LinSolver.hpp + LinSolverDirect.hpp + LinSolverIterative.hpp LinSolverIterativeFGMRES.hpp LinSolverDirectCpuILU0.hpp SystemSolver.hpp @@ -52,7 +56,7 @@ set(ReSolve_HEADER_INSTALL MemoryUtils.hpp) set(ReSolve_KLU_HEADER_INSTALL - LinSolverDirectKLU.hpp + LinSolverDirectKLU.hpp ) set(ReSolve_LUSOL_HEADER_INSTALL diff --git a/resolve/LinSolver.cpp b/resolve/LinSolver.cpp index 6fbc1d02..a7b125c9 100644 --- a/resolve/LinSolver.cpp +++ b/resolve/LinSolver.cpp @@ -1,3 +1,10 @@ +/** + * @file LinSolverIterative.cpp + * @author Kasia Swirydowicz (kasia.swirydowicz@pnnl.gov) + * @author Slaven Peles (peless@ornl.gov) + * @brief Implementation of linear solver base class. + * + */ #include #include @@ -23,174 +30,6 @@ namespace ReSolve return 1.0; } - // - // Direct solver methods implementations - // - - LinSolverDirect::LinSolverDirect() - { - L_ = nullptr; - U_ = nullptr; - P_ = nullptr; - Q_ = nullptr; - } - - LinSolverDirect::~LinSolverDirect() - { - } - - int LinSolverDirect::setup(matrix::Sparse* A, - matrix::Sparse* /* L */, - matrix::Sparse* /* U */, - index_type* /* P */, - index_type* /* Q */, - vector_type* /* rhs */) - { - if (A == nullptr) { - return 1; - } - this->A_ = A; - return 0; - } - - int LinSolverDirect::analyze() - { - return 1; - } //the same as symbolic factorization - - int LinSolverDirect::factorize() - { - return 1; - } - - int LinSolverDirect::refactorize() - { - return 1; - } - - matrix::Sparse* LinSolverDirect::getLFactor() - { - return nullptr; - } - - matrix::Sparse* LinSolverDirect::getUFactor() - { - return nullptr; - } - - index_type* LinSolverDirect::getPOrdering() - { - return nullptr; - } - - index_type* LinSolverDirect::getQOrdering() - { - return nullptr; - } - - void LinSolverDirect::setPivotThreshold(real_type tol) - { - pivot_threshold_tol_ = tol; - } - - void LinSolverDirect::setOrdering(int ordering) - { - ordering_ = ordering; - } - - void LinSolverDirect::setHaltIfSingular(bool is_halt) - { - halt_if_singular_ = is_halt; - } - - real_type LinSolverDirect::getMatrixConditionNumber() - { - out::error() << "Solver does not implement returning system matrix condition number.\n"; - return -1.0; - } - - // - // Iterative solver methods implementations - // - - LinSolverIterative::LinSolverIterative() - { - } - - LinSolverIterative::~LinSolverIterative() - { - } - - int LinSolverIterative::setup(matrix::Sparse* A) - { - if (A == nullptr) { - return 1; - } - this->A_ = A; - return 0; - } - - real_type LinSolverIterative::getFinalResidualNorm() const - { - return final_residual_norm_; - } - - real_type LinSolverIterative::getInitResidualNorm() const - { - return initial_residual_norm_; - } - - index_type LinSolverIterative::getNumIter() const - { - return total_iters_; - } - - - real_type LinSolverIterative::getTol() - { - return tol_; - } - - index_type LinSolverIterative::getMaxit() - { - return maxit_; - } - - index_type LinSolverIterative::getRestart() - { - return restart_; - } - - index_type LinSolverIterative::getConvCond() - { - return conv_cond_; - } - - bool LinSolverIterative::getFlexible() - { - return flexible_; - } - - int LinSolverIterative::setOrthogonalization(GramSchmidt* /* gs */) - { - out::error() << "Solver does not implement setting orthogonalization.\n"; - return 1; - } - - void LinSolverIterative::setTol(real_type new_tol) - { - this->tol_ = new_tol; - } - - void LinSolverIterative::setMaxit(index_type new_maxit) - { - this->maxit_ = new_maxit; - } - - void LinSolverIterative::setConvCond(index_type new_conv_cond) - { - this->conv_cond_ = new_conv_cond; - } } diff --git a/resolve/LinSolver.hpp b/resolve/LinSolver.hpp index 7d918c78..52c3c1e4 100644 --- a/resolve/LinSolver.hpp +++ b/resolve/LinSolver.hpp @@ -1,4 +1,12 @@ +/** + * @file LinSolverIterative.hpp + * @author Kasia Swirydowicz (kasia.swirydowicz@pnnl.gov) + * @author Slaven Peles (peless@ornl.gov) + * @brief Declaration of linear solver base class. + * + */ #pragma once + #include #include "Common.hpp" @@ -22,8 +30,10 @@ namespace ReSolve // Forward declaration of MatrixHandler class class MatrixHandler; - class GramSchmidt; - + /** + * @brief Base class for all linear solvers. + * + */ class LinSolver { protected: @@ -44,84 +54,4 @@ namespace ReSolve VectorHandler* vector_handler_{nullptr}; }; - class LinSolverDirect : public LinSolver - { - public: - LinSolverDirect(); - virtual ~LinSolverDirect(); - virtual int setup(matrix::Sparse* A = nullptr, - matrix::Sparse* L = nullptr, - matrix::Sparse* U = nullptr, - index_type* P = nullptr, - index_type* Q = nullptr, - vector_type* rhs = nullptr); - - virtual int analyze(); //the same as symbolic factorization - virtual int factorize(); - virtual int refactorize(); - virtual int solve(vector_type* rhs, vector_type* x) = 0; - virtual int solve(vector_type* x) = 0; - - virtual matrix::Sparse* getLFactor(); - virtual matrix::Sparse* getUFactor(); - virtual index_type* getPOrdering(); - virtual index_type* getQOrdering(); - - virtual void setPivotThreshold(real_type tol); - virtual void setOrdering(int ordering); - virtual void setHaltIfSingular(bool is_halt); - - virtual real_type getMatrixConditionNumber(); - - protected: - matrix::Sparse* L_{nullptr}; - matrix::Sparse* U_{nullptr}; - index_type* P_{nullptr}; - index_type* Q_{nullptr}; - - int ordering_{1}; // 0 = AMD, 1 = COLAMD, 2 = user provided P, Q - real_type pivot_threshold_tol_{0.1}; - bool halt_if_singular_{false}; - }; - - class LinSolverIterative : public LinSolver - { - public: - LinSolverIterative(); - virtual ~LinSolverIterative(); - virtual int setup(matrix::Sparse* A); - virtual int resetMatrix(matrix::Sparse* A) = 0; - virtual int setupPreconditioner(std::string type, LinSolverDirect* LU_solver) = 0; - - virtual int solve(vector_type* rhs, vector_type* init_guess) = 0; - - virtual real_type getFinalResidualNorm() const; - virtual real_type getInitResidualNorm() const; - virtual index_type getNumIter() const; - - virtual int setOrthogonalization(GramSchmidt* gs); - - real_type getTol(); - index_type getMaxit(); - index_type getRestart(); - index_type getConvCond(); - bool getFlexible(); - - void setTol(real_type new_tol); - void setMaxit(index_type new_maxit); - virtual int setRestart(index_type new_restart) = 0; - void setConvCond(index_type new_conv_cond); - virtual int setFlexible(bool new_flexible) = 0; - - protected: - real_type initial_residual_norm_; - real_type final_residual_norm_; - index_type total_iters_; - - real_type tol_{1e-14}; - index_type maxit_{100}; - index_type restart_{10}; - index_type conv_cond_{0}; - bool flexible_{true}; // if can be run as "normal" GMRES if needed, set flexible_ to false. Default is true of course. - }; -} +} // namespace ReSolve diff --git a/resolve/LinSolverDirect.cpp b/resolve/LinSolverDirect.cpp new file mode 100644 index 00000000..bc40bdc1 --- /dev/null +++ b/resolve/LinSolverDirect.cpp @@ -0,0 +1,100 @@ +/** + * @file LinSolverIterative.cpp + * @author Kasia Swirydowicz (kasia.swirydowicz@pnnl.gov) + * @author Slaven Peles (peless@ornl.gov) + * @brief Implementation of direct solver base class. + * + */ +#include +#include + +#include + + +namespace ReSolve +{ + using out = io::Logger; + + LinSolverDirect::LinSolverDirect() + { + L_ = nullptr; + U_ = nullptr; + P_ = nullptr; + Q_ = nullptr; + } + + LinSolverDirect::~LinSolverDirect() + { + } + + int LinSolverDirect::setup(matrix::Sparse* A, + matrix::Sparse* /* L */, + matrix::Sparse* /* U */, + index_type* /* P */, + index_type* /* Q */, + vector_type* /* rhs */) + { + if (A == nullptr) { + return 1; + } + A_ = A; + return 0; + } + + int LinSolverDirect::analyze() + { + return 1; + } //the same as symbolic factorization + + int LinSolverDirect::factorize() + { + return 1; + } + + int LinSolverDirect::refactorize() + { + return 1; + } + + matrix::Sparse* LinSolverDirect::getLFactor() + { + return nullptr; + } + + matrix::Sparse* LinSolverDirect::getUFactor() + { + return nullptr; + } + + index_type* LinSolverDirect::getPOrdering() + { + return nullptr; + } + + index_type* LinSolverDirect::getQOrdering() + { + return nullptr; + } + + void LinSolverDirect::setPivotThreshold(real_type tol) + { + pivot_threshold_tol_ = tol; + } + + void LinSolverDirect::setOrdering(int ordering) + { + ordering_ = ordering; + } + + void LinSolverDirect::setHaltIfSingular(bool is_halt) + { + halt_if_singular_ = is_halt; + } + + real_type LinSolverDirect::getMatrixConditionNumber() + { + out::error() << "Solver does not implement returning system matrix condition number.\n"; + return -1.0; + } + +} // namespace ReSolve diff --git a/resolve/LinSolverDirect.hpp b/resolve/LinSolverDirect.hpp new file mode 100644 index 00000000..d41b325d --- /dev/null +++ b/resolve/LinSolverDirect.hpp @@ -0,0 +1,55 @@ +/** + * @file LinSolverIterative.hpp + * @author Kasia Swirydowicz (kasia.swirydowicz@pnnl.gov) + * @author Slaven Peles (peless@ornl.gov) + * @brief Declaration of direct solver base class. + * + */ +#pragma once + +#include +#include + +namespace ReSolve +{ + class LinSolverDirect : public LinSolver + { + public: + LinSolverDirect(); + virtual ~LinSolverDirect(); + virtual int setup(matrix::Sparse* A = nullptr, + matrix::Sparse* L = nullptr, + matrix::Sparse* U = nullptr, + index_type* P = nullptr, + index_type* Q = nullptr, + vector_type* rhs = nullptr); + + virtual int analyze(); //the same as symbolic factorization + virtual int factorize(); + virtual int refactorize(); + virtual int solve(vector_type* rhs, vector_type* x) = 0; + virtual int solve(vector_type* x) = 0; + + virtual matrix::Sparse* getLFactor(); + virtual matrix::Sparse* getUFactor(); + virtual index_type* getPOrdering(); + virtual index_type* getQOrdering(); + + virtual void setPivotThreshold(real_type tol); + virtual void setOrdering(int ordering); + virtual void setHaltIfSingular(bool is_halt); + + virtual real_type getMatrixConditionNumber(); + + protected: + matrix::Sparse* L_{nullptr}; + matrix::Sparse* U_{nullptr}; + index_type* P_{nullptr}; + index_type* Q_{nullptr}; + + int ordering_{1}; // 0 = AMD, 1 = COLAMD, 2 = user provided P, Q + real_type pivot_threshold_tol_{0.1}; + bool halt_if_singular_{false}; + }; + +} diff --git a/resolve/LinSolverDirectCpuILU0.hpp b/resolve/LinSolverDirectCpuILU0.hpp index f6af356e..8ade9e7a 100644 --- a/resolve/LinSolverDirectCpuILU0.hpp +++ b/resolve/LinSolverDirectCpuILU0.hpp @@ -6,8 +6,9 @@ * */ #pragma once + #include "Common.hpp" -#include "LinSolver.hpp" +#include #include namespace ReSolve diff --git a/resolve/LinSolverDirectCuSolverGLU.hpp b/resolve/LinSolverDirectCuSolverGLU.hpp index 17004eb6..e2af4874 100644 --- a/resolve/LinSolverDirectCuSolverGLU.hpp +++ b/resolve/LinSolverDirectCuSolverGLU.hpp @@ -1,8 +1,11 @@ #pragma once -#include "Common.hpp" -#include "LinSolver.hpp" + #include "cusolver_defs.hpp" + +#include "Common.hpp" #include +#include + namespace ReSolve { // Forward declaration of vector::Vector class diff --git a/resolve/LinSolverDirectCuSolverRf.hpp b/resolve/LinSolverDirectCuSolverRf.hpp index 9fca9fcb..a0734c2e 100644 --- a/resolve/LinSolverDirectCuSolverRf.hpp +++ b/resolve/LinSolverDirectCuSolverRf.hpp @@ -1,8 +1,10 @@ #pragma once -#include "Common.hpp" -#include "LinSolver.hpp" + #include "cusolverRf.h" + +#include "Common.hpp" #include +#include namespace ReSolve { diff --git a/resolve/LinSolverDirectCuSparseILU0.hpp b/resolve/LinSolverDirectCuSparseILU0.hpp index 6cfdffe7..0a99de8f 100644 --- a/resolve/LinSolverDirectCuSparseILU0.hpp +++ b/resolve/LinSolverDirectCuSparseILU0.hpp @@ -1,12 +1,13 @@ #pragma once -#include "Common.hpp" -#include "LinSolver.hpp" -#include -#include #include #include +#include "Common.hpp" +#include +#include +#include + namespace ReSolve { // Forward declaration of vector::Vector class diff --git a/resolve/LinSolverDirectKLU.hpp b/resolve/LinSolverDirectKLU.hpp index fe477c84..ecec7a24 100644 --- a/resolve/LinSolverDirectKLU.hpp +++ b/resolve/LinSolverDirectKLU.hpp @@ -1,7 +1,9 @@ #pragma once + #include "klu.h" + #include "Common.hpp" -#include "LinSolver.hpp" +#include namespace ReSolve { diff --git a/resolve/LinSolverDirectRocSolverRf.hpp b/resolve/LinSolverDirectRocSolverRf.hpp index 3e2658d4..244dbe55 100644 --- a/resolve/LinSolverDirectRocSolverRf.hpp +++ b/resolve/LinSolverDirectRocSolverRf.hpp @@ -1,13 +1,15 @@ #pragma once -#include "Common.hpp" -#include "LinSolver.hpp" -#include -#include #include #include #include #include + +#include "Common.hpp" +#include +#include +#include + namespace ReSolve { // Forward declaration of vector::Vector class diff --git a/resolve/LinSolverDirectRocSparseILU0.hpp b/resolve/LinSolverDirectRocSparseILU0.hpp index f1f97104..36f31c2b 100644 --- a/resolve/LinSolverDirectRocSparseILU0.hpp +++ b/resolve/LinSolverDirectRocSparseILU0.hpp @@ -1,14 +1,15 @@ #pragma once -#include "Common.hpp" -#include "LinSolver.hpp" -#include -#include #include #include #include +#include "Common.hpp" +#include +#include +#include + namespace ReSolve { // Forward declaration of vector::Vector class diff --git a/resolve/LinSolverDirectSerialILU0.hpp b/resolve/LinSolverDirectSerialILU0.hpp index e28e152a..7f667a62 100644 --- a/resolve/LinSolverDirectSerialILU0.hpp +++ b/resolve/LinSolverDirectSerialILU0.hpp @@ -1,9 +1,10 @@ #pragma once + #include "Common.hpp" -#include "LinSolver.hpp" #include #include +#include namespace ReSolve { diff --git a/resolve/LinSolverIterative.cpp b/resolve/LinSolverIterative.cpp new file mode 100644 index 00000000..29ce214c --- /dev/null +++ b/resolve/LinSolverIterative.cpp @@ -0,0 +1,100 @@ +/** + * @file LinSolverIterative.cpp + * @author Kasia Swirydowicz (kasia.swirydowicz@pnnl.gov) + * @author Slaven Peles (peless@ornl.gov) + * @brief Implementation of iterative solver base class. + * + */ +#include +#include +#include +#include + + +namespace ReSolve +{ + using out = io::Logger; + + + LinSolverIterative::LinSolverIterative() + { + } + + LinSolverIterative::~LinSolverIterative() + { + } + + int LinSolverIterative::setup(matrix::Sparse* A) + { + if (A == nullptr) { + return 1; + } + this->A_ = A; + return 0; + } + + real_type LinSolverIterative::getFinalResidualNorm() const + { + return final_residual_norm_; + } + + real_type LinSolverIterative::getInitResidualNorm() const + { + return initial_residual_norm_; + } + + index_type LinSolverIterative::getNumIter() const + { + return total_iters_; + } + + + real_type LinSolverIterative::getTol() + { + return tol_; + } + + index_type LinSolverIterative::getMaxit() + { + return maxit_; + } + + index_type LinSolverIterative::getRestart() + { + return restart_; + } + + index_type LinSolverIterative::getConvCond() + { + return conv_cond_; + } + + bool LinSolverIterative::getFlexible() + { + return flexible_; + } + + int LinSolverIterative::setOrthogonalization(GramSchmidt* /* gs */) + { + out::error() << "Solver does not implement setting orthogonalization.\n"; + return 1; + } + + void LinSolverIterative::setTol(real_type new_tol) + { + this->tol_ = new_tol; + } + + void LinSolverIterative::setMaxit(index_type new_maxit) + { + this->maxit_ = new_maxit; + } + + void LinSolverIterative::setConvCond(index_type new_conv_cond) + { + this->conv_cond_ = new_conv_cond; + } +} + + + diff --git a/resolve/LinSolverIterative.hpp b/resolve/LinSolverIterative.hpp new file mode 100644 index 00000000..ad73b72a --- /dev/null +++ b/resolve/LinSolverIterative.hpp @@ -0,0 +1,57 @@ +/** + * @file LinSolverIterative.hpp + * @author Kasia Swirydowicz (kasia.swirydowicz@pnnl.gov) + * @author Slaven Peles (peless@ornl.gov) + * @brief Declaration of iterative solver base class. + * + */ +#pragma once + +#include +#include + +namespace ReSolve +{ + class GramSchmidt; + + class LinSolverIterative : public LinSolver + { + public: + LinSolverIterative(); + virtual ~LinSolverIterative(); + virtual int setup(matrix::Sparse* A); + virtual int resetMatrix(matrix::Sparse* A) = 0; + virtual int setupPreconditioner(std::string type, LinSolverDirect* LU_solver) = 0; + + virtual int solve(vector_type* rhs, vector_type* init_guess) = 0; + + virtual real_type getFinalResidualNorm() const; + virtual real_type getInitResidualNorm() const; + virtual index_type getNumIter() const; + + virtual int setOrthogonalization(GramSchmidt* gs); + + real_type getTol(); + index_type getMaxit(); + index_type getRestart(); + index_type getConvCond(); + bool getFlexible(); + + void setTol(real_type new_tol); + void setMaxit(index_type new_maxit); + virtual int setRestart(index_type new_restart) = 0; + void setConvCond(index_type new_conv_cond); + virtual int setFlexible(bool new_flexible) = 0; + + protected: + real_type initial_residual_norm_; + real_type final_residual_norm_; + index_type total_iters_; + + real_type tol_{1e-14}; + index_type maxit_{100}; + index_type restart_{10}; + index_type conv_cond_{0}; + bool flexible_{true}; // if can be run as "normal" GMRES if needed, set flexible_ to false. Default is true of course. + }; +} diff --git a/resolve/LinSolverIterativeFGMRES.hpp b/resolve/LinSolverIterativeFGMRES.hpp index d5bf29ed..67dcb01b 100644 --- a/resolve/LinSolverIterativeFGMRES.hpp +++ b/resolve/LinSolverIterativeFGMRES.hpp @@ -5,11 +5,13 @@ * */ #pragma once + #include "Common.hpp" #include #include -#include "LinSolver.hpp" #include "GramSchmidt.hpp" +#include +#include namespace ReSolve { diff --git a/resolve/LinSolverIterativeRandFGMRES.hpp b/resolve/LinSolverIterativeRandFGMRES.hpp index 3b1a7ae8..68f1c3a5 100644 --- a/resolve/LinSolverIterativeRandFGMRES.hpp +++ b/resolve/LinSolverIterativeRandFGMRES.hpp @@ -5,8 +5,10 @@ * */ #pragma once + #include "Common.hpp" -#include "LinSolver.hpp" +#include +#include namespace ReSolve { From 05a3227ff369580f2d174ce279e9c2d3734ce30a Mon Sep 17 00:00:00 2001 From: Slaven Peles Date: Mon, 8 Apr 2024 20:41:42 -0400 Subject: [PATCH 02/11] Set/get CLI parameters (first stab). --- resolve/LinSolver.cpp | 1 + resolve/LinSolver.hpp | 38 +++++- resolve/LinSolverIterativeFGMRES.cpp | 145 +++++++++++++++++++++-- resolve/LinSolverIterativeFGMRES.hpp | 11 ++ resolve/LinSolverIterativeRandFGMRES.cpp | 110 +++++++++++++++++ resolve/LinSolverIterativeRandFGMRES.hpp | 11 ++ tests/functionality/testSysRandGMRES.cpp | 12 +- 7 files changed, 312 insertions(+), 16 deletions(-) diff --git a/resolve/LinSolver.cpp b/resolve/LinSolver.cpp index a7b125c9..ccb5e72d 100644 --- a/resolve/LinSolver.cpp +++ b/resolve/LinSolver.cpp @@ -5,6 +5,7 @@ * @brief Implementation of linear solver base class. * */ + #include #include diff --git a/resolve/LinSolver.hpp b/resolve/LinSolver.hpp index 52c3c1e4..31c53fa2 100644 --- a/resolve/LinSolver.hpp +++ b/resolve/LinSolver.hpp @@ -7,7 +7,9 @@ */ #pragma once +#include #include + #include "Common.hpp" namespace ReSolve @@ -29,6 +31,8 @@ namespace ReSolve // Forward declaration of MatrixHandler class class MatrixHandler; + + class SolverParameters; /** * @brief Base class for all linear solvers. @@ -44,14 +48,44 @@ namespace ReSolve virtual ~LinSolver(); real_type evaluateResidual(); + + virtual int setCliParam(const std::string /* id */, const std::string /* value */) + { + return 1; + } + + virtual int getCliParam(const std::string /* id */, std::string& /* value */) + { + return 1; + } + + virtual int getCliParam(const std::string /* id */, index_type& /* value */) + { + return 1; + } + + virtual int getCliParam(const std::string /* id */, real_type& /* value */) + { + return 1; + } + + virtual int getCliParam(const std::string /* id */, bool& /* value */) + { + return 1; + } + + virtual int printCliParam(const std::string /* id */) + { + return 1; + } protected: matrix::Sparse* A_{nullptr}; - real_type* rhs_{nullptr}; - real_type* sol_{nullptr}; MatrixHandler* matrix_handler_{nullptr}; VectorHandler* vector_handler_{nullptr}; + + std::map params_list_; }; } // namespace ReSolve diff --git a/resolve/LinSolverIterativeFGMRES.cpp b/resolve/LinSolverIterativeFGMRES.cpp index c14ae9c7..43d94a40 100644 --- a/resolve/LinSolverIterativeFGMRES.cpp +++ b/resolve/LinSolverIterativeFGMRES.cpp @@ -25,6 +25,7 @@ namespace ReSolve vector_handler_ = vector_handler; GS_ = gs; setMemorySpace(); + initParamList(); } LinSolverIterativeFGMRES::LinSolverIterativeFGMRES(index_type restart, @@ -46,6 +47,7 @@ namespace ReSolve vector_handler_ = vector_handler; GS_ = gs; setMemorySpace(); + initParamList(); } LinSolverIterativeFGMRES::~LinSolverIterativeFGMRES() @@ -136,18 +138,31 @@ namespace ReSolve tolrel = 1e-16; } } - int exit_cond = 0; - if (conv_cond_ == 0) { - exit_cond = ((std::abs(rnorm - ZERO) <= EPSILON)); - } else { - if (conv_cond_ == 1) { - exit_cond = ((std::abs(rnorm - ZERO) <= EPSILON) || (rnorm < tol_)); - } else { - if (conv_cond_ == 2) { - exit_cond = ((std::abs(rnorm - ZERO) <= EPSILON) || (rnorm < (tol_*bnorm))); - } - } + + bool exit_cond = false; + switch (conv_cond_) + { + case 0: + exit_cond = ((std::abs(rnorm - ZERO) <= EPSILON)); + break; + case 1: + exit_cond = ((std::abs(rnorm - ZERO) <= EPSILON) || (rnorm < tol_)); + break; + case 2: + exit_cond = ((std::abs(rnorm - ZERO) <= EPSILON) || (rnorm < (tol_*bnorm))); + break; } + // if (conv_cond_ == 0) { + // exit_cond = ((std::abs(rnorm - ZERO) <= EPSILON)); + // } else { + // if (conv_cond_ == 1) { + // exit_cond = ((std::abs(rnorm - ZERO) <= EPSILON) || (rnorm < tol_)); + // } else { + // if (conv_cond_ == 2) { + // exit_cond = ((std::abs(rnorm - ZERO) <= EPSILON) || (rnorm < (tol_*bnorm))); + // } + // } + // } if (exit_cond) { outer_flag = 0; final_residual_norm_ = rnorm; @@ -376,6 +391,105 @@ namespace ReSolve return 0; } + int LinSolverIterativeFGMRES::setCliParam(const std::string id, const std::string value) + { + switch (params_list_[id]) + { + case TOL: + setTol(atof(value.c_str())); + break; + case MAXIT: + setMaxit(atoi(value.c_str())); + break; + case RESTART: + setRestart(atoi(value.c_str())); + break; + case CONV_COND: + setRestart(atoi(value.c_str())); + break; + case FLEXIBLE: + bool is_flexible = (value == "yes"); + setFlexible(is_flexible); + break; + } + return 0; + } + + int LinSolverIterativeFGMRES::getCliParam(const std::string id, std::string& /* value */) + { + switch (params_list_[id]) + { + default: + out::error() << "Unknown string parameter " << id << "\n"; + return 1; + } + return 0; + } + + int LinSolverIterativeFGMRES::getCliParam(const std::string id, index_type& value) + { + switch (params_list_[id]) + { + case MAXIT: + value = getMaxit(); + break; + case RESTART: + value = getRestart(); + break; + case CONV_COND: + value = getConvCond(); + break; + default: + out::error() << "Unknown integer parameter " << id << "\n"; + return 1; + } + return 0; + } + + int LinSolverIterativeFGMRES::getCliParam(const std::string id, real_type& value) + { + switch (params_list_[id]) + { + case TOL: + value = getTol(); + break; + default: + out::error() << "Unknown real parameter " << id << "\n"; + return 1; + } + return 0; + } + + int LinSolverIterativeFGMRES::getCliParam(const std::string id, bool& value) + { + switch (params_list_[id]) + { + case FLEXIBLE: + value = getFlexible(); + default: + out::error() << "Unknown boolean parameter " << id << "\n"; + return 1; + } + return 0; + } + + int LinSolverIterativeFGMRES::printCliParam(const std::string id) + { + switch (params_list_[id]) + { + case TOL: + std::cout << getTol() << "\n"; + break; + case MAXIT: + std::cout << getMaxit() << "\n"; + break; + default: + out::error() << "Unknown parameter " << id << "\n"; + return 1; + } + return 0; + } + // // Private methods // @@ -442,4 +556,13 @@ namespace ReSolve } } + void LinSolverIterativeFGMRES::initParamList() + { + params_list_["tol"] = TOL; + params_list_["maxit"] = MAXIT; + params_list_["restart"] = RESTART; + params_list_["conv_cond"] = CONV_COND; + params_list_["flexible"] = FLEXIBLE; + } + } // namespace diff --git a/resolve/LinSolverIterativeFGMRES.hpp b/resolve/LinSolverIterativeFGMRES.hpp index 67dcb01b..af75f0f7 100644 --- a/resolve/LinSolverIterativeFGMRES.hpp +++ b/resolve/LinSolverIterativeFGMRES.hpp @@ -49,10 +49,21 @@ namespace ReSolve int setRestart(index_type restart) override; int setFlexible(bool is_flexible) override; + int setCliParam(const std::string id, const std::string value) override; + int getCliParam(const std::string id, std::string& value) override; + int getCliParam(const std::string id, index_type& value) override; + int getCliParam(const std::string id, real_type& value) override; + int getCliParam(const std::string id, bool& value) override; + int printCliParam(const std::string id) override; + + private: + enum ParamaterIDs {TOL=0, MAXIT, RESTART, CONV_COND, FLEXIBLE}; + private: int allocateSolverData(); int freeSolverData(); void setMemorySpace(); + void initParamList(); void precV(vector_type* rhs, vector_type* x); ///< Apply preconditioner memory::MemorySpace memspace_; diff --git a/resolve/LinSolverIterativeRandFGMRES.cpp b/resolve/LinSolverIterativeRandFGMRES.cpp index 0944275d..0a74dad1 100644 --- a/resolve/LinSolverIterativeRandFGMRES.cpp +++ b/resolve/LinSolverIterativeRandFGMRES.cpp @@ -39,6 +39,7 @@ namespace ReSolve GS_ = gs; setMemorySpace(); + initParamList(); } LinSolverIterativeRandFGMRES::LinSolverIterativeRandFGMRES(index_type restart, @@ -62,6 +63,7 @@ namespace ReSolve GS_ = gs; setMemorySpace(); + initParamList(); } LinSolverIterativeRandFGMRES::~LinSolverIterativeRandFGMRES() @@ -494,6 +496,105 @@ namespace ReSolve return 0; } + int LinSolverIterativeRandFGMRES::setCliParam(const std::string id, const std::string value) + { + switch (params_list_[id]) + { + case TOL: + setTol(atof(value.c_str())); + break; + case MAXIT: + setMaxit(atoi(value.c_str())); + break; + case RESTART: + setRestart(atoi(value.c_str())); + break; + case CONV_COND: + setRestart(atoi(value.c_str())); + break; + case FLEXIBLE: + bool is_flexible = (value == "yes"); + setFlexible(is_flexible); + break; + } + return 0; + } + + int LinSolverIterativeRandFGMRES::getCliParam(const std::string id, std::string& /* value */) + { + switch (params_list_[id]) + { + default: + out::error() << "Unknown string parameter " << id << "\n"; + return 1; + } + return 0; + } + + int LinSolverIterativeRandFGMRES::getCliParam(const std::string id, index_type& value) + { + switch (params_list_[id]) + { + case MAXIT: + value = getMaxit(); + break; + case RESTART: + value = getRestart(); + break; + case CONV_COND: + value = getConvCond(); + break; + default: + out::error() << "Unknown integer parameter " << id << "\n"; + return 1; + } + return 0; + } + + int LinSolverIterativeRandFGMRES::getCliParam(const std::string id, real_type& value) + { + switch (params_list_[id]) + { + case TOL: + value = getTol(); + break; + default: + out::error() << "Unknown real parameter " << id << "\n"; + return 1; + } + return 0; + } + + int LinSolverIterativeRandFGMRES::getCliParam(const std::string id, bool& value) + { + switch (params_list_[id]) + { + case FLEXIBLE: + value = getFlexible(); + default: + out::error() << "Unknown boolean parameter " << id << "\n"; + return 1; + } + return 0; + } + + int LinSolverIterativeRandFGMRES::printCliParam(const std::string id) + { + switch (params_list_[id]) + { + case TOL: + std::cout << getTol() << "\n"; + break; + case MAXIT: + std::cout << getMaxit() << "\n"; + break; + default: + out::error() << "Unknown parameter " << id << "\n"; + return 1; + } + return 0; + } + // // Private methods // @@ -636,4 +737,13 @@ namespace ReSolve } } + void LinSolverIterativeRandFGMRES::initParamList() + { + params_list_["tol"] = TOL; + params_list_["maxit"] = MAXIT; + params_list_["restart"] = RESTART; + params_list_["conv_cond"] = CONV_COND; + params_list_["flexible"] = FLEXIBLE; + } + } // namespace ReSolve diff --git a/resolve/LinSolverIterativeRandFGMRES.hpp b/resolve/LinSolverIterativeRandFGMRES.hpp index 68f1c3a5..147a0d56 100644 --- a/resolve/LinSolverIterativeRandFGMRES.hpp +++ b/resolve/LinSolverIterativeRandFGMRES.hpp @@ -70,12 +70,23 @@ namespace ReSolve index_type getKrand(); int setSketchingMethod(SketchingMethod method); + int setCliParam(const std::string id, const std::string value) override; + int getCliParam(const std::string id, std::string& value) override; + int getCliParam(const std::string id, index_type& value) override; + int getCliParam(const std::string id, real_type& value) override; + int getCliParam(const std::string id, bool& value) override; + int printCliParam(const std::string id) override; + + private: + enum ParamaterIDs {TOL=0, MAXIT, RESTART, CONV_COND, FLEXIBLE}; + private: int allocateSolverData(); int freeSolverData(); int allocateSketchingData(); int freeSketchingData(); void setMemorySpace(); + void initParamList(); void precV(vector_type* rhs, vector_type* x); ///< Apply preconditioner memory::MemorySpace memspace_; diff --git a/tests/functionality/testSysRandGMRES.cpp b/tests/functionality/testSysRandGMRES.cpp index cbc000c4..af779c65 100644 --- a/tests/functionality/testSysRandGMRES.cpp +++ b/tests/functionality/testSysRandGMRES.cpp @@ -129,9 +129,12 @@ int test(int argc, char *argv[]) real_type norm_b = 0.0; // Set solver options - real_type tol = 1e-12; + //real_type tol = 1e-12; solver.getIterativeSolver().setMaxit(2500); - solver.getIterativeSolver().setTol(tol); + // solver.getIterativeSolver().setTol(tol); + solver.getIterativeSolver().setCliParam("tol", "1e-12"); + real_type tol = 0.0; + solver.getIterativeSolver().getCliParam("tol", tol); matrix_handler.setValuesChanged(true, memspace); @@ -139,7 +142,10 @@ int test(int argc, char *argv[]) status = solver.setMatrix(A); error_sum += status; - solver.getIterativeSolver().setRestart(200); + // solver.getIterativeSolver().setRestart(200); + solver.getIterativeSolver().setCliParam("restart", "200"); + std::cout << "restart = "; + solver.getIterativeSolver().printCliParam("restart"); if (method == "randgmres") { solver.setSketchingMethod(sketch); } From b5e136362ce1ca6a8b3bed7cadee4a4655e7f178 Mon Sep 17 00:00:00 2001 From: Slaven Peles Date: Thu, 13 Jun 2024 12:30:33 -0400 Subject: [PATCH 03/11] Fixed parameter management bugs in RandFGMRES and FGMRES classes. --- resolve/LinSolverIterativeFGMRES.cpp | 6 +++++- resolve/LinSolverIterativeRandFGMRES.cpp | 6 +++++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/resolve/LinSolverIterativeFGMRES.cpp b/resolve/LinSolverIterativeFGMRES.cpp index 43d94a40..83320135 100644 --- a/resolve/LinSolverIterativeFGMRES.cpp +++ b/resolve/LinSolverIterativeFGMRES.cpp @@ -405,7 +405,7 @@ namespace ReSolve setRestart(atoi(value.c_str())); break; case CONV_COND: - setRestart(atoi(value.c_str())); + setConvCond(atoi(value.c_str())); break; case FLEXIBLE: bool is_flexible = (value == "yes"); @@ -466,6 +466,7 @@ namespace ReSolve { case FLEXIBLE: value = getFlexible(); + break; default: out::error() << "Unknown boolean parameter " << id << "\n"; return 1; @@ -483,6 +484,9 @@ namespace ReSolve case MAXIT: std::cout << getMaxit() << "\n"; break; + case RESTART: + std::cout << getRestart() << "\n"; + break; default: out::error() << "Unknown parameter " << id << "\n"; return 1; diff --git a/resolve/LinSolverIterativeRandFGMRES.cpp b/resolve/LinSolverIterativeRandFGMRES.cpp index 0a74dad1..fe5b17a7 100644 --- a/resolve/LinSolverIterativeRandFGMRES.cpp +++ b/resolve/LinSolverIterativeRandFGMRES.cpp @@ -510,7 +510,7 @@ namespace ReSolve setRestart(atoi(value.c_str())); break; case CONV_COND: - setRestart(atoi(value.c_str())); + setConvCond(atoi(value.c_str())); break; case FLEXIBLE: bool is_flexible = (value == "yes"); @@ -571,6 +571,7 @@ namespace ReSolve { case FLEXIBLE: value = getFlexible(); + break; default: out::error() << "Unknown boolean parameter " << id << "\n"; return 1; @@ -588,6 +589,9 @@ namespace ReSolve case MAXIT: std::cout << getMaxit() << "\n"; break; + case RESTART: + std::cout << getRestart() << "\n"; + break; default: out::error() << "Unknown parameter " << id << "\n"; return 1; From 3206f99f28cfc7d7a091343afd5a903176393b5d Mon Sep 17 00:00:00 2001 From: Slaven Peles Date: Thu, 13 Jun 2024 12:47:34 -0400 Subject: [PATCH 04/11] Add correct include file to LUSOL. --- resolve/LinSolverDirectLUSOL.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resolve/LinSolverDirectLUSOL.hpp b/resolve/LinSolverDirectLUSOL.hpp index 24a53b3d..3393f496 100644 --- a/resolve/LinSolverDirectLUSOL.hpp +++ b/resolve/LinSolverDirectLUSOL.hpp @@ -4,7 +4,7 @@ #include #include -#include +#include #include namespace ReSolve From 6ac0bbd84e77bb739186e3003dd359269acbbf8d Mon Sep 17 00:00:00 2001 From: Slaven Peles Date: Fri, 27 Sep 2024 22:33:42 -0400 Subject: [PATCH 05/11] Add unit test for setting/getting solver params. --- resolve/Common.hpp | 6 +- resolve/LinSolverIterativeFGMRES.cpp | 18 ++-- resolve/LinSolverIterativeRandFGMRES.cpp | 27 +++-- tests/unit/CMakeLists.txt | 1 + tests/unit/params/CMakeLists.txt | 18 ++++ tests/unit/params/ParamTests.hpp | 122 +++++++++++++++++++++++ tests/unit/params/runParamTests.cpp | 28 ++++++ 7 files changed, 194 insertions(+), 26 deletions(-) create mode 100644 tests/unit/params/CMakeLists.txt create mode 100644 tests/unit/params/ParamTests.hpp create mode 100644 tests/unit/params/runParamTests.cpp diff --git a/resolve/Common.hpp b/resolve/Common.hpp index 6ee1723e..f8b54af6 100644 --- a/resolve/Common.hpp +++ b/resolve/Common.hpp @@ -13,11 +13,7 @@ namespace ReSolve { constexpr double EPSMAC = 1.0e-16; - // TODO: let cmake manage these. combined with the todo above relating to cstdint - // this is related to resolve/lusol/lusol_precision.f90. whatever is here should - // have an equivalent there - - // NOTE: i'd love to make this std::float64_t but we're not on c++23 + /// @todo Provide CMake option to se these types at config time using real_type = double; using index_type = std::int32_t; diff --git a/resolve/LinSolverIterativeFGMRES.cpp b/resolve/LinSolverIterativeFGMRES.cpp index 83320135..b71a0786 100644 --- a/resolve/LinSolverIterativeFGMRES.cpp +++ b/resolve/LinSolverIterativeFGMRES.cpp @@ -152,17 +152,7 @@ namespace ReSolve exit_cond = ((std::abs(rnorm - ZERO) <= EPSILON) || (rnorm < (tol_*bnorm))); break; } - // if (conv_cond_ == 0) { - // exit_cond = ((std::abs(rnorm - ZERO) <= EPSILON)); - // } else { - // if (conv_cond_ == 1) { - // exit_cond = ((std::abs(rnorm - ZERO) <= EPSILON) || (rnorm < tol_)); - // } else { - // if (conv_cond_ == 2) { - // exit_cond = ((std::abs(rnorm - ZERO) <= EPSILON) || (rnorm < (tol_*bnorm))); - // } - // } - // } + if (exit_cond) { outer_flag = 0; final_residual_norm_ = rnorm; @@ -487,6 +477,12 @@ namespace ReSolve case RESTART: std::cout << getRestart() << "\n"; break; + case CONV_COND: + std::cout << getConvCond() << "\n"; + break; + case FLEXIBLE: + std::cout << getFlexible() << "\n"; + break; default: out::error() << "Unknown parameter " << id << "\n"; return 1; diff --git a/resolve/LinSolverIterativeRandFGMRES.cpp b/resolve/LinSolverIterativeRandFGMRES.cpp index fe5b17a7..92798b75 100644 --- a/resolve/LinSolverIterativeRandFGMRES.cpp +++ b/resolve/LinSolverIterativeRandFGMRES.cpp @@ -177,14 +177,21 @@ namespace ReSolve tolrel = 1e-16; } } - int exit_cond = 0; - if (conv_cond_ == 0) { - exit_cond = ((std::abs(rnorm - ZERO) <= EPSILON)); - } else if (conv_cond_ == 1) { - exit_cond = ((std::abs(rnorm - ZERO) <= EPSILON) || (rnorm < tol_)); - } else if (conv_cond_ == 2) { - exit_cond = ((std::abs(rnorm - ZERO) <= EPSILON) || (rnorm < (tol_*bnorm))); + + bool exit_cond = false; + switch (conv_cond_) + { + case 0: + exit_cond = ((std::abs(rnorm - ZERO) <= EPSILON)); + break; + case 1: + exit_cond = ((std::abs(rnorm - ZERO) <= EPSILON) || (rnorm < tol_)); + break; + case 2: + exit_cond = ((std::abs(rnorm - ZERO) <= EPSILON) || (rnorm < (tol_*bnorm))); + break; } + if (exit_cond) { outer_flag = 0; final_residual_norm_ = rnorm; @@ -259,9 +266,9 @@ namespace ReSolve h_H_[i * (restart_ + 1) + k] = -h_s_[k1] * t + h_c_[k1] * h_H_[i * (restart_ + 1) + k]; } } // if (i != 0) - double Hii = h_H_[i * (restart_ + 1) + i]; - double Hii1 = h_H_[(i) * (restart_ + 1) + i + 1]; - double gam = std::sqrt(Hii * Hii + Hii1 * Hii1); + real_type Hii = h_H_[i * (restart_ + 1) + i]; + real_type Hii1 = h_H_[(i) * (restart_ + 1) + i + 1]; + real_type gam = std::sqrt(Hii * Hii + Hii1 * Hii1); if(std::abs(gam - ZERO) <= EPSILON) { gam = EPSMAC; diff --git a/tests/unit/CMakeLists.txt b/tests/unit/CMakeLists.txt index a8586342..b58a9419 100644 --- a/tests/unit/CMakeLists.txt +++ b/tests/unit/CMakeLists.txt @@ -10,3 +10,4 @@ add_subdirectory(matrix) add_subdirectory(vector) add_subdirectory(utilities) add_subdirectory(memory) +add_subdirectory(params) diff --git a/tests/unit/params/CMakeLists.txt b/tests/unit/params/CMakeLists.txt new file mode 100644 index 00000000..2120c84c --- /dev/null +++ b/tests/unit/params/CMakeLists.txt @@ -0,0 +1,18 @@ +#[[ + +@brief Build ReSolve solver configuration parameter management unit tests + +@author Slaven Peles + +]] + +# Build logger tests +add_executable(runParamTests.exe runParamTests.cpp) +target_link_libraries(runParamTests.exe PRIVATE ReSolve) + +# Install tests +set(installable_tests runParamTests.exe) +install(TARGETS ${installable_tests} + RUNTIME DESTINATION bin/resolve/tests/unit) + +add_test(NAME param_test COMMAND $) diff --git a/tests/unit/params/ParamTests.hpp b/tests/unit/params/ParamTests.hpp new file mode 100644 index 00000000..c2e84ffb --- /dev/null +++ b/tests/unit/params/ParamTests.hpp @@ -0,0 +1,122 @@ +/** + * @file ParamTests.hpp + * @brief Contains definition of ParamTests class. + * @author Slaven Peles + */ + +#pragma once +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace ReSolve { namespace tests { + /** + * @brief Class implementing unit tests for Param class. + * + * The ParamTests class is implemented entirely in this header file. + * Adding new unit test requires simply adding another method to this + * class. + */ + class ParamTests : TestBase + { + public: + ParamTests(){} + virtual ~ParamTests(){} + + TestOutcome paramSetGet() + { + TestStatus success; + + success = true; + + index_type restart = -1; + real_type tol = -1.0; + index_type maxit = -1; + index_type conv_cond = -1; + + LinAlgWorkspaceCpu workspace; + workspace.initializeHandles(); + + MatrixHandler matrix_handler(&workspace); + VectorHandler vector_handler(&workspace); + + GramSchmidt gs(&vector_handler, GramSchmidt::cgs2); + + // Constructor sets parameters + LinSolverIterativeFGMRES solver(restart, + tol, + maxit, + conv_cond, + &matrix_handler, + &vector_handler, + &gs); + + index_type restart_out = 0; + real_type tol_out = 0.0; + index_type maxit_out = 0; + index_type conv_cond_out = 0; + bool flexible_out = false; + + // Use getters to read parameters set by the constructor + solver.getCliParam("restart", restart_out ); + solver.getCliParam("tol", tol_out ); + solver.getCliParam("maxit", maxit_out ); + solver.getCliParam("conv_cond", conv_cond_out); + solver.getCliParam("flexible", flexible_out ); + + // Check getters + success *= (restart == restart_out); + success *= (maxit == maxit_out); + success *= (conv_cond == conv_cond_out); + success *= isEqual(tol, tol_out); + success *= flexible_out; // Default is flexible = true + + // Pick different parameter values from the input + std::string restart_in = "2"; + std::string tol_in = "2.0"; + std::string maxit_in = "2"; + std::string conv_cond_in = "2"; + std::string flexible_in = "no"; + + restart = atoi(restart_in.c_str()); + tol = atof(tol_in.c_str()); + maxit = atoi(maxit_in.c_str()); + conv_cond = atoi(conv_cond_in.c_str()); + + // Use setters to change FGMRES solver parameters + solver.setCliParam("restart", restart_in ); + solver.setCliParam("tol", tol_in ); + solver.setCliParam("maxit", maxit_in ); + solver.setCliParam("conv_cond", conv_cond_in); + solver.setCliParam("flexible", flexible_in ); + + // Read new values + solver.getCliParam("restart", restart_out ); + solver.getCliParam("tol", tol_out ); + solver.getCliParam("maxit", maxit_out ); + solver.getCliParam("conv_cond", conv_cond_out); + solver.getCliParam("flexible", flexible_out ); + + // Check setters + success *= (restart == restart_out); + success *= (maxit == maxit_out); + success *= (conv_cond == conv_cond_out); + success *= isEqual(tol, tol_out); + success *= !flexible_out; // flexible was set to "no" + + return success.report(__func__); + } + + + private: + + }; // class ParamTests + +}} // namespace ReSolve::tests diff --git a/tests/unit/params/runParamTests.cpp b/tests/unit/params/runParamTests.cpp new file mode 100644 index 00000000..5b406ad1 --- /dev/null +++ b/tests/unit/params/runParamTests.cpp @@ -0,0 +1,28 @@ +/** + * @file runParamTests.cpp + * @brief Driver for Param class tests. + * @author Slaven Peles + */ + +#include +#include + +#include +#include "ParamTests.hpp" + +int main() +{ + using namespace ReSolve::io; + + // Create ParamTests object + ReSolve::tests::ParamTests test; + + // Create test results accounting object + ReSolve::tests::TestingResults result; + + // Run tests + result += test.paramSetGet(); + + // Return tests summary + return result.summary(); +} From 993782c6f5e42b9b1515ad1f6ef660cdb5a7a96d Mon Sep 17 00:00:00 2001 From: Slaven Peles Date: Sun, 15 Dec 2024 01:14:06 -0500 Subject: [PATCH 06/11] Check if parameters exist before setting/getting them. --- resolve/LinSolver.cpp | 9 ++++++++ resolve/LinSolver.hpp | 4 +++- resolve/LinSolverIterativeFGMRES.cpp | 27 ++++++++++++------------ resolve/LinSolverIterativeRandFGMRES.cpp | 27 ++++++++++++------------ 4 files changed, 40 insertions(+), 27 deletions(-) diff --git a/resolve/LinSolver.cpp b/resolve/LinSolver.cpp index ccb5e72d..d8b11fd1 100644 --- a/resolve/LinSolver.cpp +++ b/resolve/LinSolver.cpp @@ -31,6 +31,15 @@ namespace ReSolve return 1.0; } + int LinSolver::getParamId(std::string id) + { + auto it = params_list_.find(id); + if (it == params_list_.end()) { + out::error() << "Unknown parameter " << id << ".\n"; + return 999; + } + return (*it).second; + } } diff --git a/resolve/LinSolver.hpp b/resolve/LinSolver.hpp index 31c53fa2..2d536985 100644 --- a/resolve/LinSolver.hpp +++ b/resolve/LinSolver.hpp @@ -79,7 +79,9 @@ namespace ReSolve return 1; } - protected: + protected: + int getParamId(std::string id); + matrix::Sparse* A_{nullptr}; MatrixHandler* matrix_handler_{nullptr}; diff --git a/resolve/LinSolverIterativeFGMRES.cpp b/resolve/LinSolverIterativeFGMRES.cpp index b71a0786..6318aa11 100644 --- a/resolve/LinSolverIterativeFGMRES.cpp +++ b/resolve/LinSolverIterativeFGMRES.cpp @@ -383,7 +383,7 @@ namespace ReSolve int LinSolverIterativeFGMRES::setCliParam(const std::string id, const std::string value) { - switch (params_list_[id]) + switch (getParamId(id)) { case TOL: setTol(atof(value.c_str())); @@ -398,19 +398,20 @@ namespace ReSolve setConvCond(atoi(value.c_str())); break; case FLEXIBLE: - bool is_flexible = (value == "yes"); - setFlexible(is_flexible); + setFlexible(value == "yes"); break; + default: + std::cout << "Setting parameter failed!\n"; } return 0; } int LinSolverIterativeFGMRES::getCliParam(const std::string id, std::string& /* value */) { - switch (params_list_[id]) + switch (getParamId(id)) { default: - out::error() << "Unknown string parameter " << id << "\n"; + out::error() << "Trying to get unknown string parameter " << id << "\n"; return 1; } return 0; @@ -418,7 +419,7 @@ namespace ReSolve int LinSolverIterativeFGMRES::getCliParam(const std::string id, index_type& value) { - switch (params_list_[id]) + switch (getParamId(id)) { case MAXIT: value = getMaxit(); @@ -430,7 +431,7 @@ namespace ReSolve value = getConvCond(); break; default: - out::error() << "Unknown integer parameter " << id << "\n"; + out::error() << "Trying to get unknown integer parameter " << id << "\n"; return 1; } return 0; @@ -438,13 +439,13 @@ namespace ReSolve int LinSolverIterativeFGMRES::getCliParam(const std::string id, real_type& value) { - switch (params_list_[id]) + switch (getParamId(id)) { case TOL: value = getTol(); break; default: - out::error() << "Unknown real parameter " << id << "\n"; + out::error() << "Trying to get unknown real parameter " << id << "\n"; return 1; } return 0; @@ -452,13 +453,13 @@ namespace ReSolve int LinSolverIterativeFGMRES::getCliParam(const std::string id, bool& value) { - switch (params_list_[id]) + switch (getParamId(id)) { case FLEXIBLE: value = getFlexible(); break; default: - out::error() << "Unknown boolean parameter " << id << "\n"; + out::error() << "Trying to get unknown boolean parameter " << id << "\n"; return 1; } return 0; @@ -466,7 +467,7 @@ namespace ReSolve int LinSolverIterativeFGMRES::printCliParam(const std::string id) { - switch (params_list_[id]) + switch (getParamId(id)) { case TOL: std::cout << getTol() << "\n"; @@ -484,7 +485,7 @@ namespace ReSolve std::cout << getFlexible() << "\n"; break; default: - out::error() << "Unknown parameter " << id << "\n"; + out::error() << "Trying to print unknown parameter " << id << "\n"; return 1; } return 0; diff --git a/resolve/LinSolverIterativeRandFGMRES.cpp b/resolve/LinSolverIterativeRandFGMRES.cpp index 92798b75..de86f70e 100644 --- a/resolve/LinSolverIterativeRandFGMRES.cpp +++ b/resolve/LinSolverIterativeRandFGMRES.cpp @@ -505,7 +505,7 @@ namespace ReSolve int LinSolverIterativeRandFGMRES::setCliParam(const std::string id, const std::string value) { - switch (params_list_[id]) + switch (getParamId(id)) { case TOL: setTol(atof(value.c_str())); @@ -520,19 +520,20 @@ namespace ReSolve setConvCond(atoi(value.c_str())); break; case FLEXIBLE: - bool is_flexible = (value == "yes"); - setFlexible(is_flexible); + setFlexible(value == "yes"); break; + default: + std::cout << "Setting parameter failed!\n"; } return 0; } int LinSolverIterativeRandFGMRES::getCliParam(const std::string id, std::string& /* value */) { - switch (params_list_[id]) + switch (getParamId(id)) { default: - out::error() << "Unknown string parameter " << id << "\n"; + out::error() << "Trying to get unknown string parameter " << id << "\n"; return 1; } return 0; @@ -540,7 +541,7 @@ namespace ReSolve int LinSolverIterativeRandFGMRES::getCliParam(const std::string id, index_type& value) { - switch (params_list_[id]) + switch (getParamId(id)) { case MAXIT: value = getMaxit(); @@ -552,7 +553,7 @@ namespace ReSolve value = getConvCond(); break; default: - out::error() << "Unknown integer parameter " << id << "\n"; + out::error() << "Trying to get unknown integer parameter " << id << "\n"; return 1; } return 0; @@ -560,13 +561,13 @@ namespace ReSolve int LinSolverIterativeRandFGMRES::getCliParam(const std::string id, real_type& value) { - switch (params_list_[id]) + switch (getParamId(id)) { case TOL: value = getTol(); break; default: - out::error() << "Unknown real parameter " << id << "\n"; + out::error() << "Trying to get unknown real parameter " << id << "\n"; return 1; } return 0; @@ -574,13 +575,13 @@ namespace ReSolve int LinSolverIterativeRandFGMRES::getCliParam(const std::string id, bool& value) { - switch (params_list_[id]) + switch (getParamId(id)) { case FLEXIBLE: value = getFlexible(); break; default: - out::error() << "Unknown boolean parameter " << id << "\n"; + out::error() << "Trying to get unknown boolean parameter " << id << "\n"; return 1; } return 0; @@ -588,7 +589,7 @@ namespace ReSolve int LinSolverIterativeRandFGMRES::printCliParam(const std::string id) { - switch (params_list_[id]) + switch (getParamId(id)) { case TOL: std::cout << getTol() << "\n"; @@ -600,7 +601,7 @@ namespace ReSolve std::cout << getRestart() << "\n"; break; default: - out::error() << "Unknown parameter " << id << "\n"; + out::error() << "Trying to print unknown parameter " << id << "\n"; return 1; } return 0; From 4b44fc78267041d77989c17b269d3e0463dbd31c Mon Sep 17 00:00:00 2001 From: Slaven Peles Date: Sun, 15 Dec 2024 21:48:55 -0500 Subject: [PATCH 07/11] Move GMRES specific methods out of iterative solver base class. --- resolve/LinSolverIterative.cpp | 20 ---------------- resolve/LinSolverIterative.hpp | 6 ----- resolve/LinSolverIterativeFGMRES.cpp | 30 +++++++++++++++++++++++- resolve/LinSolverIterativeFGMRES.hpp | 8 +++++-- resolve/LinSolverIterativeRandFGMRES.cpp | 29 ++++++++++++++++++++++- resolve/LinSolverIterativeRandFGMRES.hpp | 8 +++++-- tests/functionality/testSysRandGMRES.cpp | 19 +++++++-------- tests/functionality/testSysRefactor.cpp | 5 ++-- 8 files changed, 81 insertions(+), 44 deletions(-) diff --git a/resolve/LinSolverIterative.cpp b/resolve/LinSolverIterative.cpp index 29ce214c..de812a41 100644 --- a/resolve/LinSolverIterative.cpp +++ b/resolve/LinSolverIterative.cpp @@ -59,21 +59,6 @@ namespace ReSolve return maxit_; } - index_type LinSolverIterative::getRestart() - { - return restart_; - } - - index_type LinSolverIterative::getConvCond() - { - return conv_cond_; - } - - bool LinSolverIterative::getFlexible() - { - return flexible_; - } - int LinSolverIterative::setOrthogonalization(GramSchmidt* /* gs */) { out::error() << "Solver does not implement setting orthogonalization.\n"; @@ -89,11 +74,6 @@ namespace ReSolve { this->maxit_ = new_maxit; } - - void LinSolverIterative::setConvCond(index_type new_conv_cond) - { - this->conv_cond_ = new_conv_cond; - } } diff --git a/resolve/LinSolverIterative.hpp b/resolve/LinSolverIterative.hpp index ad73b72a..9f5c93eb 100644 --- a/resolve/LinSolverIterative.hpp +++ b/resolve/LinSolverIterative.hpp @@ -33,15 +33,9 @@ namespace ReSolve real_type getTol(); index_type getMaxit(); - index_type getRestart(); - index_type getConvCond(); - bool getFlexible(); void setTol(real_type new_tol); void setMaxit(index_type new_maxit); - virtual int setRestart(index_type new_restart) = 0; - void setConvCond(index_type new_conv_cond); - virtual int setFlexible(bool new_flexible) = 0; protected: real_type initial_residual_norm_; diff --git a/resolve/LinSolverIterativeFGMRES.cpp b/resolve/LinSolverIterativeFGMRES.cpp index 6318aa11..f3a5946c 100644 --- a/resolve/LinSolverIterativeFGMRES.cpp +++ b/resolve/LinSolverIterativeFGMRES.cpp @@ -381,6 +381,34 @@ namespace ReSolve return 0; } + /** + * @brief Set the convergence condition for GMRES solver + * + * @param[in] conv_cond - Possible values: 0, 1, 2 + * @return int - error code, 0 if successful + */ + int LinSolverIterativeFGMRES::setConvergenceCondition(index_type conv_cond) + { + conv_cond_ = conv_cond; + return 0; + } + + index_type LinSolverIterativeFGMRES::getRestart() const + { + return restart_; + } + + index_type LinSolverIterativeFGMRES::getConvCond() const + { + return conv_cond_; + } + + bool LinSolverIterativeFGMRES::getFlexible() const + { + return flexible_; + } + + int LinSolverIterativeFGMRES::setCliParam(const std::string id, const std::string value) { switch (getParamId(id)) @@ -395,7 +423,7 @@ namespace ReSolve setRestart(atoi(value.c_str())); break; case CONV_COND: - setConvCond(atoi(value.c_str())); + setConvergenceCondition(atoi(value.c_str())); break; case FLEXIBLE: setFlexible(value == "yes"); diff --git a/resolve/LinSolverIterativeFGMRES.hpp b/resolve/LinSolverIterativeFGMRES.hpp index af75f0f7..5a2dd56c 100644 --- a/resolve/LinSolverIterativeFGMRES.hpp +++ b/resolve/LinSolverIterativeFGMRES.hpp @@ -46,8 +46,12 @@ namespace ReSolve int setupPreconditioner(std::string name, LinSolverDirect* LU_solver) override; int setOrthogonalization(GramSchmidt* gs) override; - int setRestart(index_type restart) override; - int setFlexible(bool is_flexible) override; + int setRestart(index_type restart); + int setFlexible(bool is_flexible); + int setConvergenceCondition(index_type conv_cond); + index_type getRestart() const; + index_type getConvCond() const; + bool getFlexible() const; int setCliParam(const std::string id, const std::string value) override; int getCliParam(const std::string id, std::string& value) override; diff --git a/resolve/LinSolverIterativeRandFGMRES.cpp b/resolve/LinSolverIterativeRandFGMRES.cpp index de86f70e..5e34abcc 100644 --- a/resolve/LinSolverIterativeRandFGMRES.cpp +++ b/resolve/LinSolverIterativeRandFGMRES.cpp @@ -503,6 +503,33 @@ namespace ReSolve return 0; } + /** + * @brief Set the convergence condition for GMRES solver + * + * @param[in] conv_cond - Possible values: 0, 1, 2 + * @return int - error code, 0 if successful + */ + int LinSolverIterativeRandFGMRES::setConvergenceCondition(index_type conv_cond) + { + conv_cond_ = conv_cond; + return 0; + } + + index_type LinSolverIterativeRandFGMRES::getRestart() const + { + return restart_; + } + + index_type LinSolverIterativeRandFGMRES::getConvCond() const + { + return conv_cond_; + } + + bool LinSolverIterativeRandFGMRES::getFlexible() const + { + return flexible_; + } + int LinSolverIterativeRandFGMRES::setCliParam(const std::string id, const std::string value) { switch (getParamId(id)) @@ -517,7 +544,7 @@ namespace ReSolve setRestart(atoi(value.c_str())); break; case CONV_COND: - setConvCond(atoi(value.c_str())); + setConvergenceCondition(atoi(value.c_str())); break; case FLEXIBLE: setFlexible(value == "yes"); diff --git a/resolve/LinSolverIterativeRandFGMRES.hpp b/resolve/LinSolverIterativeRandFGMRES.hpp index 147a0d56..3c1cebba 100644 --- a/resolve/LinSolverIterativeRandFGMRES.hpp +++ b/resolve/LinSolverIterativeRandFGMRES.hpp @@ -64,8 +64,12 @@ namespace ReSolve int setupPreconditioner(std::string name, LinSolverDirect* LU_solver) override; int setOrthogonalization(GramSchmidt* gs) override; - int setRestart(index_type restart) override; - int setFlexible(bool is_flexible) override; + int setRestart(index_type restart); + int setFlexible(bool is_flexible); + int setConvergenceCondition(index_type conv_cond); + index_type getRestart() const; + index_type getConvCond() const; + bool getFlexible() const; index_type getKrand(); int setSketchingMethod(SketchingMethod method); diff --git a/tests/functionality/testSysRandGMRES.cpp b/tests/functionality/testSysRandGMRES.cpp index af779c65..0a62e19d 100644 --- a/tests/functionality/testSysRandGMRES.cpp +++ b/tests/functionality/testSysRandGMRES.cpp @@ -36,7 +36,7 @@ using vector_type = ReSolve::vector::Vector; template static int test(int argc, char* argv[]); static void processInputs(std::string& method, std::string& gs, std::string& sketch); -static std::string headerInfo(const std::string& method, const std::string& gs, const std::string& sketch, bool flexible); +static std::string headerInfo(const std::string& method, const std::string& gs, const std::string& sketch, std::string flexible); static ReSolve::matrix::Csr* generateMatrix(const index_type N, ReSolve::memory::MemorySpace memspace); static ReSolve::vector::Vector* generateRhs(const index_type N, ReSolve::memory::MemorySpace memspace); @@ -82,10 +82,7 @@ int test(int argc, char *argv[]) std::string sketch = opt ? (*opt).second : "count"; opt = options.getParamFromKey("-x"); - bool flexible = true; - if(opt) { - flexible = !((*opt).second == "no"); - } + std::string flexible = opt ? (*opt).second : "yes"; processInputs(method, gs, sketch); @@ -130,7 +127,8 @@ int test(int argc, char *argv[]) // Set solver options //real_type tol = 1e-12; - solver.getIterativeSolver().setMaxit(2500); + // solver.getIterativeSolver().setMaxit(2500); + solver.getIterativeSolver().setCliParam("maxit", "2500"); // solver.getIterativeSolver().setTol(tol); solver.getIterativeSolver().setCliParam("tol", "1e-12"); real_type tol = 0.0; @@ -149,7 +147,7 @@ int test(int argc, char *argv[]) if (method == "randgmres") { solver.setSketchingMethod(sketch); } - solver.getIterativeSolver().setFlexible(flexible); + solver.getIterativeSolver().setCliParam("flexible", flexible); // Set preconditioner (default in this case ILU0) status = solver.preconditionerSetup(); @@ -222,12 +220,13 @@ void processInputs(std::string& method, std::string& gs, std::string& sketch) } } -std::string headerInfo(const std::string& method, const std::string& gs, const std::string& sketch, bool flexible) +std::string headerInfo(const std::string& method, const std::string& gs, const std::string& sketch, std::string flexible) { + bool is_flexible = !(flexible == "no"); std::string header("Results for "); if (method == "randgmres") { header += "randomized "; - header += flexible ? "FGMRES" : "GMRES"; + header += is_flexible ? "FGMRES" : "GMRES"; header += " solver\n"; header += "\t Sketching method: "; if (sketch == "count") { @@ -236,7 +235,7 @@ std::string headerInfo(const std::string& method, const std::string& gs, const s header += "fast Walsh-Hadamard transform\n"; } } else if (method == "fgmres") { - header += flexible ? "FGMRES" : "GMRES"; + header += is_flexible ? "FGMRES" : "GMRES"; header += " solver\n"; } else { return header + "unknown method\n"; diff --git a/tests/functionality/testSysRefactor.cpp b/tests/functionality/testSysRefactor.cpp index 1ae563d7..5b294b9a 100644 --- a/tests/functionality/testSysRefactor.cpp +++ b/tests/functionality/testSysRefactor.cpp @@ -65,7 +65,7 @@ int main(int argc, char *argv[]) // Configure solver (CUDA-based solver needs slightly different // settings than HIP-based one) solver.setRefinementMethod("fgmres", "cgs2"); - solver.getIterativeSolver().setRestart(100); + solver.getIterativeSolver().setCliParam("restart", "100"); if (memory_space == "hip") { solver.getIterativeSolver().setMaxit(200); } @@ -299,7 +299,8 @@ int main(int argc, char *argv[]) // Get solver parameters real_type tol = solver.getIterativeSolver().getTol(); - index_type restart = solver.getIterativeSolver().getRestart(); + index_type restart = 0; + solver.getIterativeSolver().getCliParam("restart", restart); index_type maxit = solver.getIterativeSolver().getMaxit(); // Get solver stats From 8e1bd44561ae39bf6888da14d5c783681fe01bd2 Mon Sep 17 00:00:00 2001 From: Slaven Peles Date: Mon, 16 Dec 2024 22:34:31 -0500 Subject: [PATCH 08/11] Clean up GMRES tests. --- tests/functionality/testSysRandGMRES.cpp | 60 +++++++++++++++++------- 1 file changed, 42 insertions(+), 18 deletions(-) diff --git a/tests/functionality/testSysRandGMRES.cpp b/tests/functionality/testSysRandGMRES.cpp index 0a62e19d..3d639817 100644 --- a/tests/functionality/testSysRandGMRES.cpp +++ b/tests/functionality/testSysRandGMRES.cpp @@ -32,14 +32,30 @@ using real_type = ReSolve::real_type; using index_type = ReSolve::index_type; using vector_type = ReSolve::vector::Vector; -// Forward declarations of helper functions that create test linear system -template +// +// Forward declarations of helper test functions +// + +/// Main test function +template static int test(int argc, char* argv[]); + +/// Checks if inputs are valid, otherwise sets defaults static void processInputs(std::string& method, std::string& gs, std::string& sketch); -static std::string headerInfo(const std::string& method, const std::string& gs, const std::string& sketch, std::string flexible); + +/// Creates string with test description +static std::string headerInfo(const std::string& method, + const std::string& gs, + const std::string& sketch, + std::string flexible); + +/// Generates test system matrix static ReSolve::matrix::Csr* generateMatrix(const index_type N, ReSolve::memory::MemorySpace memspace); + +/// Generates system rhs vector static ReSolve::vector::Vector* generateRhs(const index_type N, ReSolve::memory::MemorySpace memspace); + int main(int argc, char *argv[]) { int error_sum = 0; @@ -57,7 +73,11 @@ int main(int argc, char *argv[]) return error_sum; } -template +// +// Test functions definitions +// + +template int test(int argc, char *argv[]) { // Error sum needs to be 0 at the end for test to PASS. @@ -87,7 +107,7 @@ int test(int argc, char *argv[]) processInputs(method, gs, sketch); // Create workspace and initialize its handles. - T workspace; + workspace_type workspace; workspace.initializeHandles(); // Create linear algebra handlers @@ -126,13 +146,12 @@ int test(int argc, char *argv[]) real_type norm_b = 0.0; // Set solver options - //real_type tol = 1e-12; - // solver.getIterativeSolver().setMaxit(2500); solver.getIterativeSolver().setCliParam("maxit", "2500"); - // solver.getIterativeSolver().setTol(tol); solver.getIterativeSolver().setCliParam("tol", "1e-12"); - real_type tol = 0.0; - solver.getIterativeSolver().getCliParam("tol", tol); + + // Tolerance value to output + real_type tol_out = 0.0; + solver.getIterativeSolver().getCliParam("tol", tol_out); matrix_handler.setValuesChanged(true, memspace); @@ -140,14 +159,12 @@ int test(int argc, char *argv[]) status = solver.setMatrix(A); error_sum += status; - // solver.getIterativeSolver().setRestart(200); - solver.getIterativeSolver().setCliParam("restart", "200"); - std::cout << "restart = "; - solver.getIterativeSolver().printCliParam("restart"); + // Solver options can be changed even after solver workspace is allocated. if (method == "randgmres") { solver.setSketchingMethod(sketch); } solver.getIterativeSolver().setCliParam("flexible", flexible); + solver.getIterativeSolver().setCliParam("restart", "200"); // Set preconditioner (default in this case ILU0) status = solver.preconditionerSetup(); @@ -164,7 +181,7 @@ int test(int argc, char *argv[]) std::cout << std::defaultfloat << headerInfo(method, gs, sketch, flexible) << "\t Hardware backend: " << hwbackend << "\n" - << "\t Solver tolerance: " << tol << "\n" + << "\t Solver tolerance: " << tol_out << "\n" << std::scientific << std::setprecision(16) << "\t Initial residual norm: ||b-Ax_0||_2 : " << solver.getIterativeSolver().getInitResidualNorm() << " \n" @@ -181,7 +198,7 @@ int test(int argc, char *argv[]) std::cout << "Result is not a finite number!\n"; error_sum++; } - if (final_norm/norm_b > (10.0 * tol)) { + if (final_norm/norm_b > (10.0 * tol_out)) { std::cout << "Result inaccurate!\n"; error_sum++; } @@ -213,14 +230,21 @@ void processInputs(std::string& method, std::string& gs, std::string& sketch) method = "fgmres"; } - if (gs != "cgs1" && gs != "cgs2" && gs != "mgs" && gs != "mgs_two_sync" && gs != "mgs_pm") { + if (gs != "cgs1" && + gs != "cgs2" && + gs != "mgs" && + gs != "mgs_two_sync" && + gs != "mgs_pm") { std::cout << "Unknown orthogonalization " << gs << "\n"; std::cout << "Setting orthogonalization to the default (CGS2).\n\n"; gs = "cgs2"; } } -std::string headerInfo(const std::string& method, const std::string& gs, const std::string& sketch, std::string flexible) +std::string headerInfo(const std::string& method, + const std::string& gs, + const std::string& sketch, + std::string flexible) { bool is_flexible = !(flexible == "no"); std::string header("Results for "); From db4c50bf1b407b4a217b0e555e8dd562e866679b Mon Sep 17 00:00:00 2001 From: Slaven Peles Date: Thu, 19 Dec 2024 22:11:41 -0500 Subject: [PATCH 09/11] Move GMRES specific parameters to GMRES classes. --- resolve/LinSolverIterative.hpp | 8 +++----- resolve/LinSolverIterativeFGMRES.hpp | 4 ++++ resolve/LinSolverIterativeRandFGMRES.hpp | 4 ++++ 3 files changed, 11 insertions(+), 5 deletions(-) diff --git a/resolve/LinSolverIterative.hpp b/resolve/LinSolverIterative.hpp index 9f5c93eb..1f763a4d 100644 --- a/resolve/LinSolverIterative.hpp +++ b/resolve/LinSolverIterative.hpp @@ -42,10 +42,8 @@ namespace ReSolve real_type final_residual_norm_; index_type total_iters_; - real_type tol_{1e-14}; - index_type maxit_{100}; - index_type restart_{10}; - index_type conv_cond_{0}; - bool flexible_{true}; // if can be run as "normal" GMRES if needed, set flexible_ to false. Default is true of course. + // Parameters common for all iterative solvers + real_type tol_{1e-14}; ///< Solver tolerance + index_type maxit_{100}; ///< Maximum solver iterations }; } diff --git a/resolve/LinSolverIterativeFGMRES.hpp b/resolve/LinSolverIterativeFGMRES.hpp index 5a2dd56c..0c00062a 100644 --- a/resolve/LinSolverIterativeFGMRES.hpp +++ b/resolve/LinSolverIterativeFGMRES.hpp @@ -63,6 +63,10 @@ namespace ReSolve private: enum ParamaterIDs {TOL=0, MAXIT, RESTART, CONV_COND, FLEXIBLE}; + index_type restart_{10}; ///< GMRES restart + index_type conv_cond_{0}; ///< GMRES convergence condition + bool flexible_{true}; ///< If using flexible GMRES (FGMRES) algorithm + private: int allocateSolverData(); int freeSolverData(); diff --git a/resolve/LinSolverIterativeRandFGMRES.hpp b/resolve/LinSolverIterativeRandFGMRES.hpp index 3c1cebba..8e1d2d97 100644 --- a/resolve/LinSolverIterativeRandFGMRES.hpp +++ b/resolve/LinSolverIterativeRandFGMRES.hpp @@ -84,6 +84,10 @@ namespace ReSolve private: enum ParamaterIDs {TOL=0, MAXIT, RESTART, CONV_COND, FLEXIBLE}; + index_type restart_{10}; ///< GMRES restart + index_type conv_cond_{0}; ///< GMRES convergence condition + bool flexible_{true}; ///< If using flexible GMRES (FGMRES) algorithm + private: int allocateSolverData(); int freeSolverData(); From 655590cd5c087300a72206d45f96038c88ed2306 Mon Sep 17 00:00:00 2001 From: Slaven Peles Date: Thu, 19 Dec 2024 23:12:22 -0500 Subject: [PATCH 10/11] Remove dead code from LinSolver class. --- resolve/LinSolver.hpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/resolve/LinSolver.hpp b/resolve/LinSolver.hpp index 2d536985..289ed1b4 100644 --- a/resolve/LinSolver.hpp +++ b/resolve/LinSolver.hpp @@ -32,8 +32,7 @@ namespace ReSolve // Forward declaration of MatrixHandler class class MatrixHandler; - class SolverParameters; - + /** * @brief Base class for all linear solvers. * From fe0af5479fce8e7971f8ec2afd2babd580fadfcb Mon Sep 17 00:00:00 2001 From: Slaven Peles Date: Fri, 27 Dec 2024 16:06:24 -0500 Subject: [PATCH 11/11] Use more intuitive parameter getters. --- resolve/LinSolver.cpp | 2 +- resolve/LinSolver.hpp | 20 +++++++-------- resolve/LinSolverIterative.cpp | 4 +-- resolve/LinSolverIterative.hpp | 4 +-- resolve/LinSolverIterativeFGMRES.cpp | 32 +++++++++++------------- resolve/LinSolverIterativeFGMRES.hpp | 10 ++++---- resolve/LinSolverIterativeRandFGMRES.cpp | 32 +++++++++++------------- resolve/LinSolverIterativeRandFGMRES.hpp | 10 ++++---- tests/functionality/testSysRandGMRES.cpp | 3 +-- tests/functionality/testSysRefactor.cpp | 3 +-- tests/unit/params/ParamTests.hpp | 26 ++++++++----------- 11 files changed, 65 insertions(+), 81 deletions(-) diff --git a/resolve/LinSolver.cpp b/resolve/LinSolver.cpp index d8b11fd1..8536d9e1 100644 --- a/resolve/LinSolver.cpp +++ b/resolve/LinSolver.cpp @@ -31,7 +31,7 @@ namespace ReSolve return 1.0; } - int LinSolver::getParamId(std::string id) + int LinSolver::getParamId(std::string id) const { auto it = params_list_.find(id); if (it == params_list_.end()) { diff --git a/resolve/LinSolver.hpp b/resolve/LinSolver.hpp index 289ed1b4..3be52cea 100644 --- a/resolve/LinSolver.hpp +++ b/resolve/LinSolver.hpp @@ -53,33 +53,33 @@ namespace ReSolve return 1; } - virtual int getCliParam(const std::string /* id */, std::string& /* value */) + virtual std::string getCliParamString(const std::string /* id */) const { - return 1; + return ""; } - virtual int getCliParam(const std::string /* id */, index_type& /* value */) + virtual index_type getCliParamInt(const std::string /* id */) const { - return 1; + return -1; } - virtual int getCliParam(const std::string /* id */, real_type& /* value */) + virtual real_type getCliParamReal(const std::string /* id */) const { - return 1; + return 1.0; } - virtual int getCliParam(const std::string /* id */, bool& /* value */) + virtual bool getCliParamBool(const std::string /* id */) const { - return 1; + return false; } - virtual int printCliParam(const std::string /* id */) + virtual int printCliParam(const std::string /* id */) const { return 1; } protected: - int getParamId(std::string id); + int getParamId(std::string id) const; matrix::Sparse* A_{nullptr}; diff --git a/resolve/LinSolverIterative.cpp b/resolve/LinSolverIterative.cpp index de812a41..ed1b97cc 100644 --- a/resolve/LinSolverIterative.cpp +++ b/resolve/LinSolverIterative.cpp @@ -49,12 +49,12 @@ namespace ReSolve } - real_type LinSolverIterative::getTol() + real_type LinSolverIterative::getTol() const { return tol_; } - index_type LinSolverIterative::getMaxit() + index_type LinSolverIterative::getMaxit() const { return maxit_; } diff --git a/resolve/LinSolverIterative.hpp b/resolve/LinSolverIterative.hpp index 1f763a4d..4b9ee5f9 100644 --- a/resolve/LinSolverIterative.hpp +++ b/resolve/LinSolverIterative.hpp @@ -31,8 +31,8 @@ namespace ReSolve virtual int setOrthogonalization(GramSchmidt* gs); - real_type getTol(); - index_type getMaxit(); + real_type getTol() const; + index_type getMaxit() const; void setTol(real_type new_tol); void setMaxit(index_type new_maxit); diff --git a/resolve/LinSolverIterativeFGMRES.cpp b/resolve/LinSolverIterativeFGMRES.cpp index f3a5946c..7a7d9d03 100644 --- a/resolve/LinSolverIterativeFGMRES.cpp +++ b/resolve/LinSolverIterativeFGMRES.cpp @@ -434,66 +434,62 @@ namespace ReSolve return 0; } - int LinSolverIterativeFGMRES::getCliParam(const std::string id, std::string& /* value */) + std::string LinSolverIterativeFGMRES::getCliParamString(const std::string id) const { switch (getParamId(id)) { default: out::error() << "Trying to get unknown string parameter " << id << "\n"; - return 1; } - return 0; + return ""; } - int LinSolverIterativeFGMRES::getCliParam(const std::string id, index_type& value) + index_type LinSolverIterativeFGMRES::getCliParamInt(const std::string id) const { switch (getParamId(id)) { case MAXIT: - value = getMaxit(); + return getMaxit(); break; case RESTART: - value = getRestart(); + return getRestart(); break; case CONV_COND: - value = getConvCond(); + return getConvCond(); break; default: out::error() << "Trying to get unknown integer parameter " << id << "\n"; - return 1; } - return 0; + return -1; } - int LinSolverIterativeFGMRES::getCliParam(const std::string id, real_type& value) + real_type LinSolverIterativeFGMRES::getCliParamReal(const std::string id) const { switch (getParamId(id)) { case TOL: - value = getTol(); + return getTol(); break; default: out::error() << "Trying to get unknown real parameter " << id << "\n"; - return 1; } - return 0; + return std::numeric_limits::quiet_NaN(); } - int LinSolverIterativeFGMRES::getCliParam(const std::string id, bool& value) + bool LinSolverIterativeFGMRES::getCliParamBool(const std::string id) const { switch (getParamId(id)) { case FLEXIBLE: - value = getFlexible(); + return getFlexible(); break; default: out::error() << "Trying to get unknown boolean parameter " << id << "\n"; - return 1; } - return 0; + return false; } - int LinSolverIterativeFGMRES::printCliParam(const std::string id) + int LinSolverIterativeFGMRES::printCliParam(const std::string id) const { switch (getParamId(id)) { diff --git a/resolve/LinSolverIterativeFGMRES.hpp b/resolve/LinSolverIterativeFGMRES.hpp index 0c00062a..cfdd6c44 100644 --- a/resolve/LinSolverIterativeFGMRES.hpp +++ b/resolve/LinSolverIterativeFGMRES.hpp @@ -54,11 +54,11 @@ namespace ReSolve bool getFlexible() const; int setCliParam(const std::string id, const std::string value) override; - int getCliParam(const std::string id, std::string& value) override; - int getCliParam(const std::string id, index_type& value) override; - int getCliParam(const std::string id, real_type& value) override; - int getCliParam(const std::string id, bool& value) override; - int printCliParam(const std::string id) override; + std::string getCliParamString(const std::string id) const override; + index_type getCliParamInt(const std::string id) const override; + real_type getCliParamReal(const std::string id) const override; + bool getCliParamBool(const std::string id) const override; + int printCliParam(const std::string id) const override; private: enum ParamaterIDs {TOL=0, MAXIT, RESTART, CONV_COND, FLEXIBLE}; diff --git a/resolve/LinSolverIterativeRandFGMRES.cpp b/resolve/LinSolverIterativeRandFGMRES.cpp index 5e34abcc..c044ad44 100644 --- a/resolve/LinSolverIterativeRandFGMRES.cpp +++ b/resolve/LinSolverIterativeRandFGMRES.cpp @@ -555,66 +555,62 @@ namespace ReSolve return 0; } - int LinSolverIterativeRandFGMRES::getCliParam(const std::string id, std::string& /* value */) + std::string LinSolverIterativeRandFGMRES::getCliParamString(const std::string id) const { switch (getParamId(id)) { default: out::error() << "Trying to get unknown string parameter " << id << "\n"; - return 1; } - return 0; + return ""; } - int LinSolverIterativeRandFGMRES::getCliParam(const std::string id, index_type& value) + index_type LinSolverIterativeRandFGMRES::getCliParamInt(const std::string id) const { switch (getParamId(id)) { case MAXIT: - value = getMaxit(); + return getMaxit(); break; case RESTART: - value = getRestart(); + return getRestart(); break; case CONV_COND: - value = getConvCond(); + return getConvCond(); break; default: out::error() << "Trying to get unknown integer parameter " << id << "\n"; - return 1; } - return 0; + return -1; } - int LinSolverIterativeRandFGMRES::getCliParam(const std::string id, real_type& value) + real_type LinSolverIterativeRandFGMRES::getCliParamReal(const std::string id) const { switch (getParamId(id)) { case TOL: - value = getTol(); + return getTol(); break; default: out::error() << "Trying to get unknown real parameter " << id << "\n"; - return 1; } - return 0; + return std::numeric_limits::quiet_NaN(); } - int LinSolverIterativeRandFGMRES::getCliParam(const std::string id, bool& value) + bool LinSolverIterativeRandFGMRES::getCliParamBool(const std::string id) const { switch (getParamId(id)) { case FLEXIBLE: - value = getFlexible(); + return getFlexible(); break; default: out::error() << "Trying to get unknown boolean parameter " << id << "\n"; - return 1; } - return 0; + return false; } - int LinSolverIterativeRandFGMRES::printCliParam(const std::string id) + int LinSolverIterativeRandFGMRES::printCliParam(const std::string id) const { switch (getParamId(id)) { diff --git a/resolve/LinSolverIterativeRandFGMRES.hpp b/resolve/LinSolverIterativeRandFGMRES.hpp index 8e1d2d97..842b3cc8 100644 --- a/resolve/LinSolverIterativeRandFGMRES.hpp +++ b/resolve/LinSolverIterativeRandFGMRES.hpp @@ -75,11 +75,11 @@ namespace ReSolve int setSketchingMethod(SketchingMethod method); int setCliParam(const std::string id, const std::string value) override; - int getCliParam(const std::string id, std::string& value) override; - int getCliParam(const std::string id, index_type& value) override; - int getCliParam(const std::string id, real_type& value) override; - int getCliParam(const std::string id, bool& value) override; - int printCliParam(const std::string id) override; + std::string getCliParamString(const std::string id) const override; + index_type getCliParamInt(const std::string id) const override; + real_type getCliParamReal(const std::string id) const override; + bool getCliParamBool(const std::string id) const override; + int printCliParam(const std::string id) const override; private: enum ParamaterIDs {TOL=0, MAXIT, RESTART, CONV_COND, FLEXIBLE}; diff --git a/tests/functionality/testSysRandGMRES.cpp b/tests/functionality/testSysRandGMRES.cpp index 3d639817..00cee65a 100644 --- a/tests/functionality/testSysRandGMRES.cpp +++ b/tests/functionality/testSysRandGMRES.cpp @@ -150,8 +150,7 @@ int test(int argc, char *argv[]) solver.getIterativeSolver().setCliParam("tol", "1e-12"); // Tolerance value to output - real_type tol_out = 0.0; - solver.getIterativeSolver().getCliParam("tol", tol_out); + real_type tol_out = solver.getIterativeSolver().getCliParamReal("tol"); matrix_handler.setValuesChanged(true, memspace); diff --git a/tests/functionality/testSysRefactor.cpp b/tests/functionality/testSysRefactor.cpp index 5b294b9a..a0682aff 100644 --- a/tests/functionality/testSysRefactor.cpp +++ b/tests/functionality/testSysRefactor.cpp @@ -299,8 +299,7 @@ int main(int argc, char *argv[]) // Get solver parameters real_type tol = solver.getIterativeSolver().getTol(); - index_type restart = 0; - solver.getIterativeSolver().getCliParam("restart", restart); + index_type restart = solver.getIterativeSolver().getCliParamInt("restart"); index_type maxit = solver.getIterativeSolver().getMaxit(); // Get solver stats diff --git a/tests/unit/params/ParamTests.hpp b/tests/unit/params/ParamTests.hpp index c2e84ffb..e70716d2 100644 --- a/tests/unit/params/ParamTests.hpp +++ b/tests/unit/params/ParamTests.hpp @@ -58,18 +58,12 @@ namespace ReSolve { namespace tests { &vector_handler, &gs); - index_type restart_out = 0; - real_type tol_out = 0.0; - index_type maxit_out = 0; - index_type conv_cond_out = 0; - bool flexible_out = false; - // Use getters to read parameters set by the constructor - solver.getCliParam("restart", restart_out ); - solver.getCliParam("tol", tol_out ); - solver.getCliParam("maxit", maxit_out ); - solver.getCliParam("conv_cond", conv_cond_out); - solver.getCliParam("flexible", flexible_out ); + index_type restart_out = solver.getCliParamInt("restart"); + real_type tol_out = solver.getCliParamReal("tol"); + index_type maxit_out = solver.getCliParamInt("maxit"); + index_type conv_cond_out = solver.getCliParamInt("conv_cond"); + bool flexible_out = solver.getCliParamBool("flexible"); // Check getters success *= (restart == restart_out); @@ -98,11 +92,11 @@ namespace ReSolve { namespace tests { solver.setCliParam("flexible", flexible_in ); // Read new values - solver.getCliParam("restart", restart_out ); - solver.getCliParam("tol", tol_out ); - solver.getCliParam("maxit", maxit_out ); - solver.getCliParam("conv_cond", conv_cond_out); - solver.getCliParam("flexible", flexible_out ); + restart_out = solver.getCliParamInt("restart"); + tol_out = solver.getCliParamReal("tol"); + maxit_out = solver.getCliParamInt("maxit"); + conv_cond_out = solver.getCliParamInt("conv_cond"); + flexible_out = solver.getCliParamBool("flexible"); // Check setters success *= (restart == restart_out);