From 535694632e9ebc197475d5649ec249c310b134c1 Mon Sep 17 00:00:00 2001 From: Slaven Peles Date: Fri, 27 Sep 2024 22:33:42 -0400 Subject: [PATCH] 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 1e1a0efa..bad2d5c0 100644 --- a/resolve/LinSolverIterativeFGMRES.cpp +++ b/resolve/LinSolverIterativeFGMRES.cpp @@ -160,17 +160,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; @@ -495,6 +485,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 69e6d1fc..6da805ac 100644 --- a/resolve/LinSolverIterativeRandFGMRES.cpp +++ b/resolve/LinSolverIterativeRandFGMRES.cpp @@ -186,14 +186,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; @@ -268,9 +275,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(); +}