diff --git a/CMakeLists.txt b/CMakeLists.txt index a4aa863b266890293cb48ceaf21990120f4d303b..e9255bff6ac523e8bfdf61fe42044e4366d3993f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -187,6 +187,34 @@ else() endif() endif() +#------------------------------------------------------ +# Check for SLEPc +# defaults use SLEPc +set(PUGS_ENABLE_SLEPC AUTO CACHE STRING + "Choose one of: AUTO ON OFF") + +if (PUGS_ENABLE_SLEPC MATCHES "^(AUTO|ON)$") + if (PETSC_FOUND) + # SLEPc support is deactivated if PETSc is not found + pkg_check_modules(SLEPC SLEPc) + else() + message(STATUS "SLEPc support is deactivated since pugs will not be build with PETSc support") + set(SLEPc_FOUND FALSE) + unset(PUGS_HAS_SLEPC) + endif() + set(PUGS_HAS_SLEPC ${SLEPC_FOUND}) +else() + unset(PUGS_HAS_SLEPC) +endif() + +if (${SLEPC_FOUND}) + include_directories(SYSTEM ${SLEPC_INCLUDE_DIRS}) +else() + if (PUGS_ENABLE_SLEPC MATCHES "^ON$") + message(FATAL_ERROR "Could not find SLEPc!") + endif() +endif() + # ----------------------------------------------------- if (${MPI_FOUND}) @@ -558,6 +586,7 @@ target_link_libraries( PugsLanguageUtils kokkos ${PETSC_LIBRARIES} + ${SLEPC_LIBRARIES} ${PARMETIS_LIBRARIES} ${MPI_CXX_LINK_FLAGS} ${MPI_CXX_LIBRARIES} ${KOKKOS_CXX_FLAGS} @@ -615,6 +644,16 @@ else() endif() endif() +if (SLEPC_FOUND) + message(" SLEPc: ${SLEPC_VERSION}") +else() + if (PUGS_ENABLE_SLEPC MATCHES "^(AUTO|ON)$") + message(" SLEPc: not found!") + else() + message(" SLEPc: explicitly deactivated!") + endif() +endif() + if(CLANG_FORMAT) message(" clang-format: ${CLANG_FORMAT}") else() diff --git a/src/algebra/BiCGStab.hpp b/src/algebra/BiCGStab.hpp index dc62e370e6ec304cb2e4fd44d220218d9bd94283..82d3446791cd0a65065169d4f8d15f87120931a1 100644 --- a/src/algebra/BiCGStab.hpp +++ b/src/algebra/BiCGStab.hpp @@ -9,10 +9,10 @@ struct BiCGStab { - template <typename VectorType, typename MatrixType> + template <typename MatrixType, typename VectorType, typename RHSVectorType> BiCGStab(const MatrixType& A, VectorType& x, - const VectorType& b, + const RHSVectorType& b, const double epsilon, const size_t maximum_iteration, const bool verbose) diff --git a/src/algebra/CG.hpp b/src/algebra/CG.hpp index 7e653d8f95cddab4d5d1b7eb36481fd7690ef170..4ab52012a08732f21d57cf114bd873406bfd3898 100644 --- a/src/algebra/CG.hpp +++ b/src/algebra/CG.hpp @@ -8,10 +8,10 @@ struct CG { - template <typename VectorType, typename MatrixType> + template <typename MatrixType, typename VectorType, typename RHSVectorType> CG(const MatrixType& A, VectorType& x, - const VectorType& f, + const RHSVectorType& f, const double epsilon, const size_t maximum_iteration, const bool verbose = false) diff --git a/src/algebra/CMakeLists.txt b/src/algebra/CMakeLists.txt index d1f01ec310858be0e775514f934ce0a7c0e9da28..6310f48dcf69eb93e2c1178e05d32dbc7fe5afad 100644 --- a/src/algebra/CMakeLists.txt +++ b/src/algebra/CMakeLists.txt @@ -2,6 +2,13 @@ add_library( PugsAlgebra + EigenvalueSolver.cpp LinearSolver.cpp LinearSolverOptions.cpp - PETScWrapper.cpp) + PETScUtils.cpp) + +target_link_libraries( + PugsAlgebra + ${PETSC_LIBRARIES} + ${SLEPC_LIBRARIES} +) diff --git a/src/algebra/CRSMatrix.hpp b/src/algebra/CRSMatrix.hpp index 98297d759675fdb7fdbf8be1e638f19cba4cc562..edb85d5e87b6a347ad5bc4f82987fd9255154484 100644 --- a/src/algebra/CRSMatrix.hpp +++ b/src/algebra/CRSMatrix.hpp @@ -21,13 +21,29 @@ class CRSMatrix HostMatrix m_host_matrix; Array<const DataType> m_values; + size_t m_nb_rows; + size_t m_nb_columns; public: + PUGS_INLINE + bool + isSquare() const noexcept + { + return m_nb_rows == m_nb_columns; + } + PUGS_INLINE size_t numberOfRows() const { - return m_host_matrix.numRows(); + return m_nb_rows; + } + + PUGS_INLINE + size_t + numberOfColumns() const + { + return m_nb_columns; } auto @@ -75,6 +91,7 @@ class CRSMatrix } CRSMatrix(const SparseMatrixDescriptor<DataType, IndexType>& M) + : m_nb_rows{M.numberOfRows()}, m_nb_columns{M.numberOfColumns()} { { auto host_matrix = diff --git a/src/algebra/DenseMatrix.hpp b/src/algebra/DenseMatrix.hpp new file mode 100644 index 0000000000000000000000000000000000000000..8f15f125861d0cc9cce0aef716e63959f736d36b --- /dev/null +++ b/src/algebra/DenseMatrix.hpp @@ -0,0 +1,296 @@ +#ifndef DENSE_MATRIX_HPP +#define DENSE_MATRIX_HPP + +#include <algebra/TinyMatrix.hpp> +#include <algebra/Vector.hpp> +#include <utils/Array.hpp> +#include <utils/PugsAssert.hpp> +#include <utils/PugsMacros.hpp> +#include <utils/PugsUtils.hpp> +#include <utils/Types.hpp> + +template <typename DataType> +class DenseMatrix // LCOV_EXCL_LINE +{ + public: + using data_type = DataType; + using index_type = size_t; + + private: + size_t m_nb_rows; + size_t m_nb_columns; + Array<DataType> m_values; + + static_assert(std::is_same_v<typename decltype(m_values)::index_type, index_type>); + static_assert(std::is_arithmetic_v<DataType>, "Dense matrices expect arithmetic data"); + + // Allows const version to access our data + friend DenseMatrix<std::add_const_t<DataType>>; + + public: + PUGS_INLINE + bool + isSquare() const noexcept + { + return m_nb_rows == m_nb_columns; + } + + friend PUGS_INLINE DenseMatrix<std::remove_const_t<DataType>> + copy(const DenseMatrix& A) noexcept + { + return {A.m_nb_rows, A.m_nb_columns, copy(A.m_values)}; + } + + friend PUGS_INLINE DenseMatrix<std::remove_const_t<DataType>> + transpose(const DenseMatrix& A) + { + DenseMatrix<std::remove_const_t<DataType>> A_transpose{A.m_nb_columns, A.m_nb_rows}; + for (size_t i = 0; i < A.m_nb_rows; ++i) { + for (size_t j = 0; j < A.m_nb_columns; ++j) { + A_transpose(j, i) = A(i, j); + } + } + return A_transpose; + } + + friend PUGS_INLINE DenseMatrix + operator*(const DataType& a, const DenseMatrix& A) + { + DenseMatrix<std::remove_const_t<DataType>> aA = copy(A); + return aA *= a; + } + + template <typename DataType2> + PUGS_INLINE Vector<std::remove_const_t<DataType>> + operator*(const Vector<DataType2>& x) const + { + static_assert(std::is_same_v<std::remove_const_t<DataType>, std::remove_const_t<DataType2>>, + "incompatible data types"); + Assert(m_nb_columns == x.size()); + const DenseMatrix& A = *this; + Vector<std::remove_const_t<DataType>> Ax{m_nb_rows}; + for (size_t i = 0; i < m_nb_rows; ++i) { + std::remove_const_t<DataType> Axi = A(i, 0) * x[0]; + for (size_t j = 1; j < m_nb_columns; ++j) { + Axi += A(i, j) * x[j]; + } + Ax[i] = Axi; + } + return Ax; + } + + template <typename DataType2> + PUGS_INLINE DenseMatrix<std::remove_const_t<DataType>> + operator*(const DenseMatrix<DataType2>& B) const + { + static_assert(std::is_same_v<std::remove_const_t<DataType>, std::remove_const_t<DataType2>>, + "incompatible data types"); + Assert(m_nb_columns == B.numberOfRows()); + const DenseMatrix& A = *this; + DenseMatrix<std::remove_const_t<DataType>> AB{m_nb_rows, B.numberOfColumns()}; + + for (size_t i = 0; i < m_nb_rows; ++i) { + for (size_t j = 0; j < B.numberOfColumns(); ++j) { + std::remove_const_t<DataType> ABij = 0; + for (size_t k = 0; k < m_nb_columns; ++k) { + ABij += A(i, k) * B(k, j); + } + AB(i, j) = ABij; + } + } + return AB; + } + + template <typename DataType2> + PUGS_INLINE DenseMatrix& + operator/=(const DataType2& a) + { + const auto inv_a = 1. / a; + return (*this) *= inv_a; + } + + template <typename DataType2> + PUGS_INLINE DenseMatrix& + operator*=(const DataType2& a) + { + parallel_for( + m_values.size(), PUGS_LAMBDA(index_type i) { m_values[i] *= a; }); + return *this; + } + + template <typename DataType2> + PUGS_INLINE DenseMatrix& + operator-=(const DenseMatrix<DataType2>& B) + { + static_assert(std::is_same_v<std::remove_const_t<DataType>, std::remove_const_t<DataType2>>, + "incompatible data types"); + Assert(m_nb_rows == B.numberOfRows()); + Assert(m_nb_columns == B.numberOfColumns()); + + parallel_for( + m_values.size(), PUGS_LAMBDA(index_type i) { m_values[i] -= B.m_values[i]; }); + return *this; + } + + template <typename DataType2> + PUGS_INLINE DenseMatrix& + operator+=(const DenseMatrix<DataType2>& B) + { + static_assert(std::is_same_v<std::remove_const_t<DataType>, std::remove_const_t<DataType2>>, + "incompatible data types"); + Assert(m_nb_rows == B.numberOfRows()); + Assert(m_nb_columns == B.numberOfColumns()); + + parallel_for( + m_values.size(), PUGS_LAMBDA(index_type i) { m_values[i] += B.m_values[i]; }); + return *this; + } + + template <typename DataType2> + PUGS_INLINE DenseMatrix<std::remove_const_t<DataType>> + operator+(const DenseMatrix<DataType2>& B) const + { + static_assert(std::is_same_v<std::remove_const_t<DataType>, std::remove_const_t<DataType2>>, + "incompatible data types"); + Assert(m_nb_rows == B.numberOfRows()); + Assert(m_nb_columns == B.numberOfColumns()); + DenseMatrix<std::remove_const_t<DataType>> sum{B.numberOfRows(), B.numberOfColumns()}; + + parallel_for( + m_values.size(), PUGS_LAMBDA(index_type i) { sum.m_values[i] = m_values[i] + B.m_values[i]; }); + + return sum; + } + + template <typename DataType2> + PUGS_INLINE DenseMatrix<std::remove_const_t<DataType>> + operator-(const DenseMatrix<DataType2>& B) const + { + static_assert(std::is_same_v<std::remove_const_t<DataType>, std::remove_const_t<DataType2>>, + "incompatible data types"); + Assert(m_nb_rows == B.numberOfRows()); + Assert(m_nb_columns == B.numberOfColumns()); + DenseMatrix<std::remove_const_t<DataType>> difference{B.numberOfRows(), B.numberOfColumns()}; + + parallel_for( + m_values.size(), PUGS_LAMBDA(index_type i) { difference.m_values[i] = m_values[i] - B.m_values[i]; }); + + return difference; + } + + PUGS_INLINE + DataType& + operator()(index_type i, index_type j) const noexcept(NO_ASSERT) + { + Assert((i < m_nb_rows and j < m_nb_columns), "invalid indices"); + return m_values[i * m_nb_columns + j]; + } + + PUGS_INLINE + size_t + numberOfRows() const noexcept + { + return m_nb_rows; + } + + PUGS_INLINE + size_t + numberOfColumns() const noexcept + { + return m_nb_columns; + } + + PUGS_INLINE void + fill(const DataType& value) noexcept + { + m_values.fill(value); + } + + PUGS_INLINE DenseMatrix& operator=(ZeroType) noexcept + { + m_values.fill(0); + return *this; + } + + PUGS_INLINE DenseMatrix& operator=(IdentityType) noexcept(NO_ASSERT) + { + Assert(m_nb_rows == m_nb_columns, "Identity must be a square matrix"); + + m_values.fill(0); + parallel_for( + m_nb_rows, PUGS_LAMBDA(const index_type i) { m_values[i * m_nb_rows + i] = 1; }); + return *this; + } + + template <typename DataType2> + PUGS_INLINE DenseMatrix& + operator=(const DenseMatrix<DataType2>& A) noexcept + { + // ensures that DataType is the same as source DataType2 + static_assert(std::is_same<std::remove_const_t<DataType>, std::remove_const_t<DataType2>>(), + "Cannot assign DenseMatrix of different type"); + // ensures that const is not lost through copy + static_assert(((std::is_const<DataType2>() and std::is_const<DataType>()) or not std::is_const<DataType2>()), + "Cannot assign DenseMatrix of const to DenseMatrix of non-const"); + + m_nb_rows = A.m_nb_rows; + m_nb_columns = A.m_nb_columns; + m_values = A.m_values; + return *this; + } + + PUGS_INLINE + DenseMatrix& operator=(const DenseMatrix&) = default; + + PUGS_INLINE + DenseMatrix& operator=(DenseMatrix&&) = default; + + template <typename DataType2> + DenseMatrix(const DenseMatrix<DataType2>& A) + { + // ensures that DataType is the same as source DataType2 + static_assert(std::is_same<std::remove_const_t<DataType>, std::remove_const_t<DataType2>>(), + "Cannot assign DenseMatrix of different type"); + // ensures that const is not lost through copy + static_assert(((std::is_const<DataType2>() and std::is_const<DataType>()) or not std::is_const<DataType2>()), + "Cannot assign DenseMatrix of const to DenseMatrix of non-const"); + + this->operator=(A); + } + + DenseMatrix(const DenseMatrix&) = default; + + DenseMatrix(DenseMatrix&&) = default; + + explicit DenseMatrix(size_t nb_rows, size_t nb_columns) noexcept + : m_nb_rows{nb_rows}, m_nb_columns{nb_columns}, m_values{nb_rows * nb_columns} + {} + + explicit DenseMatrix(size_t nb_rows) noexcept : m_nb_rows{nb_rows}, m_nb_columns{nb_rows}, m_values{nb_rows * nb_rows} + {} + + template <size_t N> + explicit DenseMatrix(const TinyMatrix<N, DataType>& M) noexcept : m_nb_rows{N}, m_nb_columns{N}, m_values{N * N} + { + parallel_for( + N, PUGS_LAMBDA(const index_type i) { + for (size_t j = 0; j < N; ++j) { + m_values[i * N + j] = M(i, j); + } + }); + } + + DenseMatrix() noexcept : m_nb_rows{0}, m_nb_columns{0} {} + + private: + DenseMatrix(size_t nb_rows, size_t nb_columns, const Array<DataType> values) noexcept(NO_ASSERT) + : m_nb_rows{nb_rows}, m_nb_columns{nb_columns}, m_values{values} + { + Assert(m_values.size() == m_nb_rows * m_nb_columns, "incompatible sizes"); + } + + public: + ~DenseMatrix() = default; +}; + +#endif // DENSE_MATRIX_HPP diff --git a/src/algebra/EigenvalueSolver.cpp b/src/algebra/EigenvalueSolver.cpp new file mode 100644 index 0000000000000000000000000000000000000000..1d96d01f992d22a8346417dce85750d9b186749b --- /dev/null +++ b/src/algebra/EigenvalueSolver.cpp @@ -0,0 +1,152 @@ +#include <algebra/EigenvalueSolver.hpp> +#include <utils/pugs_config.hpp> + +#ifdef PUGS_HAS_SLEPC +#include <slepc.h> + +struct EigenvalueSolver::Internals +{ + static PetscReal + computeSmallestRealEigenvalueOfSymmetricMatrix(EPS& eps) + { + EPSSetWhichEigenpairs(eps, EPS_SMALLEST_REAL); + EPSSolve(eps); + + PetscReal smallest_eigenvalue; + EPSGetEigenpair(eps, 0, &smallest_eigenvalue, nullptr, nullptr, nullptr); + return smallest_eigenvalue; + } + + static PetscReal + computeLargestRealEigenvalueOfSymmetricMatrix(EPS& eps) + { + EPSSetWhichEigenpairs(eps, EPS_LARGEST_REAL); + EPSSolve(eps); + + PetscReal largest_eigenvalue; + EPSGetEigenpair(eps, 0, &largest_eigenvalue, nullptr, nullptr, nullptr); + return largest_eigenvalue; + } + + static void + computeAllEigenvaluesOfSymmetricMatrixInInterval(EPS& eps, const PetscReal left_bound, const PetscReal right_bound) + { + Assert(left_bound < right_bound); + EPSSetWhichEigenpairs(eps, EPS_ALL); + EPSSetInterval(eps, left_bound - 0.01 * std::abs(left_bound), right_bound + 0.01 * std::abs(right_bound)); + + ST st; + EPSGetST(eps, &st); + STSetType(st, STSINVERT); + + KSP ksp; + STGetKSP(st, &ksp); + KSPSetType(ksp, KSPPREONLY); + + PC pc; + KSPGetPC(ksp, &pc); + PCSetType(pc, PCCHOLESKY); + EPSSetFromOptions(eps); + + EPSSolve(eps); + } + + static void + computeAllEigenvaluesOfSymmetricMatrix(EPS& eps) + { + const PetscReal left_bound = computeSmallestRealEigenvalueOfSymmetricMatrix(eps); + const PetscReal right_bound = computeLargestRealEigenvalueOfSymmetricMatrix(eps); + + computeAllEigenvaluesOfSymmetricMatrixInInterval(eps, left_bound - 0.01 * std::abs(left_bound), + right_bound + 0.01 * std::abs(right_bound)); + } +}; + +void +EigenvalueSolver::computeForSymmetricMatrix(const PETScAijMatrixEmbedder& A, Array<double>& eigenvalues) +{ + EPS eps; + + EPSCreate(PETSC_COMM_SELF, &eps); + EPSSetOperators(eps, A, nullptr); + EPSSetProblemType(eps, EPS_HEP); + + Internals::computeAllEigenvaluesOfSymmetricMatrix(eps); + + PetscInt nb_eigenvalues; + EPSGetDimensions(eps, &nb_eigenvalues, nullptr, nullptr); + + eigenvalues = Array<double>(nb_eigenvalues); + for (PetscInt i = 0; i < nb_eigenvalues; ++i) { + EPSGetEigenpair(eps, i, &(eigenvalues[i]), nullptr, nullptr, nullptr); + } + + EPSDestroy(&eps); +} + +void +EigenvalueSolver::computeForSymmetricMatrix(const PETScAijMatrixEmbedder& A, + Array<double>& eigenvalues, + std::vector<Vector<double>>& eigenvector_list) +{ + EPS eps; + + EPSCreate(PETSC_COMM_SELF, &eps); + EPSSetOperators(eps, A, nullptr); + EPSSetProblemType(eps, EPS_HEP); + + Internals::computeAllEigenvaluesOfSymmetricMatrix(eps); + + PetscInt nb_eigenvalues; + EPSGetDimensions(eps, &nb_eigenvalues, nullptr, nullptr); + + eigenvalues = Array<double>(nb_eigenvalues); + eigenvector_list.reserve(nb_eigenvalues); + for (PetscInt i = 0; i < nb_eigenvalues; ++i) { + Vec Vr; + Vector<double> eigenvector{A.numberOfRows()}; + VecCreateSeqWithArray(PETSC_COMM_SELF, 1, A.numberOfRows(), &(eigenvector[0]), &Vr); + EPSGetEigenpair(eps, i, &(eigenvalues[i]), nullptr, Vr, nullptr); + VecDestroy(&Vr); + eigenvector_list.push_back(eigenvector); + } + + EPSDestroy(&eps); +} + +void +EigenvalueSolver::computeForSymmetricMatrix(const PETScAijMatrixEmbedder& A, + Array<double>& eigenvalues, + DenseMatrix<double>& P) +{ + EPS eps; + + EPSCreate(PETSC_COMM_SELF, &eps); + EPSSetOperators(eps, A, nullptr); + EPSSetProblemType(eps, EPS_HEP); + + Internals::computeAllEigenvaluesOfSymmetricMatrix(eps); + + PetscInt nb_eigenvalues; + EPSGetDimensions(eps, &nb_eigenvalues, nullptr, nullptr); + + eigenvalues = Array<double>(nb_eigenvalues); + P = DenseMatrix<double>(nb_eigenvalues, nb_eigenvalues); + + Array<double> eigenvector(nb_eigenvalues); + for (PetscInt i = 0; i < nb_eigenvalues; ++i) { + Vec Vr; + VecCreateSeqWithArray(PETSC_COMM_SELF, 1, A.numberOfRows(), &(eigenvector[0]), &Vr); + EPSGetEigenpair(eps, i, &(eigenvalues[i]), nullptr, Vr, nullptr); + VecDestroy(&Vr); + for (size_t j = 0; j < eigenvector.size(); ++j) { + P(j, i) = eigenvector[j]; + } + } + + EPSDestroy(&eps); +} + +#endif // PUGS_HAS_SLEPC + +EigenvalueSolver::EigenvalueSolver() {} diff --git a/src/algebra/EigenvalueSolver.hpp b/src/algebra/EigenvalueSolver.hpp new file mode 100644 index 0000000000000000000000000000000000000000..a9dd941b9bd87d3f0a79be5f36e5683ae8a1afb6 --- /dev/null +++ b/src/algebra/EigenvalueSolver.hpp @@ -0,0 +1,68 @@ +#ifndef EIGENVALUE_SOLVER_HPP +#define EIGENVALUE_SOLVER_HPP + +#include <algebra/PETScUtils.hpp> + +#include <algebra/DenseMatrix.hpp> +#include <algebra/Vector.hpp> +#include <utils/Array.hpp> +#include <utils/Exceptions.hpp> + +class EigenvalueSolver +{ + private: + struct Internals; + +#ifdef PUGS_HAS_SLEPC + void computeForSymmetricMatrix(const PETScAijMatrixEmbedder& A, Array<double>& eigenvalues); + + void computeForSymmetricMatrix(const PETScAijMatrixEmbedder& A, + Array<double>& eigenvalues, + std::vector<Vector<double>>& eigenvectors); + + void computeForSymmetricMatrix(const PETScAijMatrixEmbedder& A, Array<double>& eigenvalues, DenseMatrix<double>& P); +#endif // PUGS_HAS_SLEPC + + public: + template <typename MatrixType> + void + computeForSymmetricMatrix([[maybe_unused]] const MatrixType& A, [[maybe_unused]] Array<double>& eigenvalues) + { +#ifdef PUGS_HAS_SLEPC + this->computeForSymmetricMatrix(PETScAijMatrixEmbedder{A}, eigenvalues); +#else // PUGS_HAS_SLEPC + throw NotImplementedError("SLEPc is required to solve eigenvalue problems"); +#endif // PUGS_HAS_SLEPC + } + + template <typename MatrixType> + void + computeForSymmetricMatrix([[maybe_unused]] const MatrixType& A, + [[maybe_unused]] Array<double>& eigenvalues, + [[maybe_unused]] std::vector<Vector<double>>& eigenvectors) + { +#ifdef PUGS_HAS_SLEPC + this->computeForSymmetricMatrix(PETScAijMatrixEmbedder{A}, eigenvalues, eigenvectors); +#else // PUGS_HAS_SLEPC + throw NotImplementedError("SLEPc is required to solve eigenvalue problems"); +#endif // PUGS_HAS_SLEPC + } + + template <typename MatrixType> + void + computeForSymmetricMatrix([[maybe_unused]] const MatrixType& A, + [[maybe_unused]] Array<double>& eigenvalues, + [[maybe_unused]] DenseMatrix<double>& P) + { +#ifdef PUGS_HAS_SLEPC + this->computeForSymmetricMatrix(PETScAijMatrixEmbedder{A}, eigenvalues, P); +#else // PUGS_HAS_SLEPC + throw NotImplementedError("SLEPc is required to solve eigenvalue problems"); +#endif // PUGS_HAS_SLEPC + } + + EigenvalueSolver(); + ~EigenvalueSolver() = default; +}; + +#endif // EIGENVALUE_SOLVER_HPP diff --git a/src/algebra/LinearSolver.cpp b/src/algebra/LinearSolver.cpp index b3a4d9816f6bc6634f73a80b70ba304f82ed60b1..98e2a3a1c2caf8a041b6e69e71502bb6441647e7 100644 --- a/src/algebra/LinearSolver.cpp +++ b/src/algebra/LinearSolver.cpp @@ -3,6 +3,7 @@ #include <algebra/BiCGStab.hpp> #include <algebra/CG.hpp> +#include <algebra/PETScUtils.hpp> #ifdef PUGS_HAS_PETSC #include <petsc.h> @@ -130,10 +131,11 @@ struct LinearSolver::Internals } } + template <typename MatrixType, typename SolutionVectorType, typename RHSVectorType> static void - builtinSolveLocalSystem(const CRSMatrix<double, size_t>& A, - Vector<double>& x, - const Vector<double>& b, + builtinSolveLocalSystem(const MatrixType& A, + SolutionVectorType& x, + const RHSVectorType& b, const LinearSolverOptions& options) { if (options.precond() != LSPrecond::none) { @@ -166,48 +168,27 @@ struct LinearSolver::Internals return 0; } + template <typename MatrixType, typename SolutionVectorType, typename RHSVectorType> static void - petscSolveLocalSystem(const CRSMatrix<double, size_t>& A, - Vector<double>& x, - const Vector<double>& b, + petscSolveLocalSystem(const MatrixType& A, + SolutionVectorType& x, + const RHSVectorType& b, const LinearSolverOptions& options) { - Assert(x.size() == b.size() and x.size() == A.numberOfRows()); + Assert(x.size() == b.size() and x.size() == A.numberOfColumns() and A.isSquare()); Vec petscB; - VecCreateMPIWithArray(PETSC_COMM_WORLD, 1, b.size(), b.size(), &b[0], &petscB); + VecCreateMPIWithArray(PETSC_COMM_SELF, 1, b.size(), b.size(), &b[0], &petscB); Vec petscX; - VecCreateMPIWithArray(PETSC_COMM_WORLD, 1, x.size(), x.size(), &x[0], &petscX); + VecCreateMPIWithArray(PETSC_COMM_SELF, 1, x.size(), x.size(), &x[0], &petscX); - Array<PetscScalar> values = copy(A.values()); - - const auto A_row_indices = A.rowIndices(); - Array<PetscInt> row_indices{A_row_indices.size()}; - for (size_t i = 0; i < row_indices.size(); ++i) { - row_indices[i] = A_row_indices[i]; - } - - Array<PetscInt> column_indices{values.size()}; - size_t l = 0; - for (size_t i = 0; i < A.numberOfRows(); ++i) { - const auto row_i = A.row(i); - for (size_t j = 0; j < row_i.length; ++j) { - column_indices[l++] = row_i.colidx(j); - } - } - - Mat petscMat; - MatCreateSeqAIJWithArrays(PETSC_COMM_WORLD, x.size(), x.size(), &row_indices[0], &column_indices[0], &values[0], - &petscMat); - - MatAssemblyBegin(petscMat, MAT_FINAL_ASSEMBLY); - MatAssemblyEnd(petscMat, MAT_FINAL_ASSEMBLY); + PETScAijMatrixEmbedder petscA(A); KSP ksp; - KSPCreate(PETSC_COMM_WORLD, &ksp); + KSPCreate(PETSC_COMM_SELF, &ksp); KSPSetTolerances(ksp, options.epsilon(), 1E-100, 1E5, options.maximumIteration()); - KSPSetOperators(ksp, petscMat, petscMat); + KSPSetOperators(ksp, petscA, petscA); PC pc; KSPGetPC(ksp, &pc); @@ -288,8 +269,6 @@ struct LinearSolver::Internals KSPSolve(ksp, petscB, petscX); - // free used memory - MatDestroy(&petscMat); VecDestroy(&petscB); VecDestroy(&petscX); KSPDestroy(&ksp); @@ -298,11 +277,9 @@ struct LinearSolver::Internals #else // PUGS_HAS_PETSC // LCOV_EXCL_START + template <typename MatrixType, typename SolutionVectorType, typename RHSVectorType> static void - petscSolveLocalSystem(const CRSMatrix<double, size_t>&, - Vector<double>&, - const Vector<double>&, - const LinearSolverOptions&) + petscSolveLocalSystem(const MatrixType&, SolutionVectorType&, const RHSVectorType&, const LinearSolverOptions&) { checkHasLibrary(LSLibrary::petsc); throw UnexpectedError("unexpected situation should not reach this point!"); @@ -310,6 +287,33 @@ struct LinearSolver::Internals // LCOV_EXCL_STOP #endif // PUGS_HAS_PETSC + + template <typename MatrixType, typename SolutionVectorType, typename RHSVectorType> + static void + solveLocalSystem(const MatrixType& A, + SolutionVectorType& x, + const RHSVectorType& b, + const LinearSolverOptions& options) + { + switch (options.library()) { + case LSLibrary::builtin: { + builtinSolveLocalSystem(A, x, b, options); + break; + } + // LCOV_EXCL_START + case LSLibrary::petsc: { + // not covered since if PETSc is not linked this point is + // unreachable: LinearSolver throws an exception at construction + // in this case. + petscSolveLocalSystem(A, x, b, options); + break; + } + default: { + throw UnexpectedError(::name(options.library()) + " cannot solve local systems"); + } + // LCOV_EXCL_STOP + } + } }; bool @@ -325,26 +329,15 @@ LinearSolver::checkOptions(const LinearSolverOptions& options) const } void -LinearSolver::solveLocalSystem(const CRSMatrix<double, size_t>& A, Vector<double>& x, const Vector<double>& b) +LinearSolver::solveLocalSystem(const CRSMatrix<double, size_t>& A, Vector<double>& x, const Vector<const double>& b) { - switch (m_options.library()) { - case LSLibrary::builtin: { - Internals::builtinSolveLocalSystem(A, x, b, m_options); - break; - } - // LCOV_EXCL_START - case LSLibrary::petsc: { - // not covered since if PETSc is not linked this point is - // unreachable: LinearSolver throws an exception at construction - // in this case. - Internals::petscSolveLocalSystem(A, x, b, m_options); - break; - } - default: { - throw UnexpectedError(::name(m_options.library()) + " cannot solve local systems for sparse matrices"); - } - // LCOV_EXCL_STOP - } + Internals::solveLocalSystem(A, x, b, m_options); +} + +void +LinearSolver::solveLocalSystem(const DenseMatrix<double>& A, Vector<double>& x, const Vector<const double>& b) +{ + Internals::solveLocalSystem(A, x, b, m_options); } LinearSolver::LinearSolver(const LinearSolverOptions& options) : m_options{options} diff --git a/src/algebra/LinearSolver.hpp b/src/algebra/LinearSolver.hpp index 3ed5660bd9ce51c1e5ba5de3fe00c595aa96f1e7..3873374002a146c79a447a815d4ef6a57669883e 100644 --- a/src/algebra/LinearSolver.hpp +++ b/src/algebra/LinearSolver.hpp @@ -2,6 +2,7 @@ #define LINEAR_SOLVER_HPP #include <algebra/CRSMatrix.hpp> +#include <algebra/DenseMatrix.hpp> #include <algebra/LinearSolverOptions.hpp> #include <algebra/TinyMatrix.hpp> #include <algebra/TinyVector.hpp> @@ -15,21 +16,32 @@ class LinearSolver const LinearSolverOptions m_options; - void _solveLocalDense(size_t N, const double* A, double* x, const double* b); - public: bool hasLibrary(LSLibrary library) const; void checkOptions(const LinearSolverOptions& options) const; - void solveLocalSystem(const CRSMatrix<double, size_t>& A, Vector<double>& x, const Vector<double>& b); - template <size_t N> void solveLocalSystem(const TinyMatrix<N>& A, TinyVector<N>& x, const TinyVector<N>& b) { - this->_solveLocalDense(N, &A(0, 0), &x[0], &b[0]); + DenseMatrix A_dense{A}; + Vector<double> x_vector{N}; + Vector<double> b_vector{N}; + for (size_t i = 0; i < N; ++i) { + x_vector[i] = x[i]; + b_vector[i] = b[i]; + } + + this->solveLocalSystem(A_dense, x_vector, b_vector); + + for (size_t i = 0; i < N; ++i) { + x[i] = x_vector[i]; + } } + void solveLocalSystem(const CRSMatrix<double, size_t>& A, Vector<double>& x, const Vector<const double>& b); + void solveLocalSystem(const DenseMatrix<double>& A, Vector<double>& x, const Vector<const double>& b); + LinearSolver(); LinearSolver(const LinearSolverOptions& options); }; diff --git a/src/algebra/PETScUtils.cpp b/src/algebra/PETScUtils.cpp new file mode 100644 index 0000000000000000000000000000000000000000..5ed261353d93673267c3f4107c35f855bf643211 --- /dev/null +++ b/src/algebra/PETScUtils.cpp @@ -0,0 +1,74 @@ +#include <algebra/PETScUtils.hpp> + +#ifdef PUGS_HAS_PETSC + +PETScAijMatrixEmbedder::PETScAijMatrixEmbedder(const size_t nb_rows, const size_t nb_columns, const double* A) + : m_nb_rows{nb_rows}, m_nb_columns{nb_columns} +{ + MatCreate(PETSC_COMM_SELF, &m_petscMat); + MatSetSizes(m_petscMat, PETSC_DECIDE, PETSC_DECIDE, nb_rows, nb_columns); + MatSetFromOptions(m_petscMat); + MatSetType(m_petscMat, MATAIJ); + MatSetUp(m_petscMat); + + { + Array<PetscInt> row_indices(nb_rows); + for (size_t i = 0; i < nb_rows; ++i) { + row_indices[i] = i; + } + m_row_indices = row_indices; + } + + if (nb_rows == nb_columns) { + m_column_indices = m_row_indices; + } else { + Array<PetscInt> column_indices(nb_columns); + for (size_t i = 0; i < nb_columns; ++i) { + column_indices[i] = i; + } + m_column_indices = column_indices; + } + + MatSetValuesBlocked(m_petscMat, nb_rows, &(m_row_indices[0]), nb_columns, &(m_column_indices[0]), A, INSERT_VALUES); + + MatAssemblyBegin(m_petscMat, MAT_FINAL_ASSEMBLY); + MatAssemblyEnd(m_petscMat, MAT_FINAL_ASSEMBLY); +} + +PETScAijMatrixEmbedder::PETScAijMatrixEmbedder(const CRSMatrix<double, size_t>& A) + : m_nb_rows{A.numberOfRows()}, m_nb_columns{A.numberOfColumns()} +{ + const Array<PetscReal>& values = copy(A.values()); + + { + const auto& A_row_indices = A.rowIndices(); + Array<PetscInt> row_indices{A_row_indices.size()}; + for (size_t i = 0; i < row_indices.size(); ++i) { + row_indices[i] = A_row_indices[i]; + } + m_row_indices = row_indices; + + Array<PetscInt> column_indices{values.size()}; + size_t l = 0; + for (size_t i = 0; i < A.numberOfRows(); ++i) { + const auto row_i = A.row(i); + for (size_t j = 0; j < row_i.length; ++j) { + column_indices[l++] = row_i.colidx(j); + } + } + m_column_indices = column_indices; + } + + MatCreateSeqAIJWithArrays(PETSC_COMM_SELF, A.numberOfRows(), A.numberOfColumns(), &m_row_indices[0], + &m_column_indices[0], &values[0], &m_petscMat); + + MatAssemblyBegin(m_petscMat, MAT_FINAL_ASSEMBLY); + MatAssemblyEnd(m_petscMat, MAT_FINAL_ASSEMBLY); +} + +PETScAijMatrixEmbedder::~PETScAijMatrixEmbedder() +{ + MatDestroy(&m_petscMat); +} + +#endif // PUGS_HAS_PETSC diff --git a/src/algebra/PETScUtils.hpp b/src/algebra/PETScUtils.hpp new file mode 100644 index 0000000000000000000000000000000000000000..68748c02f5b36092cba6dce8ba3281a6d1cbb93b --- /dev/null +++ b/src/algebra/PETScUtils.hpp @@ -0,0 +1,67 @@ +#ifndef PETSC_UTILS_HPP +#define PETSC_UTILS_HPP + +#include <utils/pugs_config.hpp> + +#ifdef PUGS_HAS_PETSC + +#include <algebra/CRSMatrix.hpp> +#include <algebra/DenseMatrix.hpp> +#include <algebra/TinyMatrix.hpp> + +#include <petsc.h> + +class PETScAijMatrixEmbedder +{ + private: + Mat m_petscMat; + Array<PetscInt> m_row_indices; + Array<PetscInt> m_column_indices; + const size_t m_nb_rows; + const size_t m_nb_columns; + + PETScAijMatrixEmbedder(const size_t nb_rows, const size_t nb_columns, const double* A); + + public: + PUGS_INLINE + size_t + numberOfRows() const + { + return m_nb_rows; + } + + PUGS_INLINE + size_t + numberOfColumns() const + { + return m_nb_columns; + } + + PUGS_INLINE + operator Mat&() + { + return m_petscMat; + } + + PUGS_INLINE + operator const Mat&() const + { + return m_petscMat; + } + + template <size_t N> + PETScAijMatrixEmbedder(const TinyMatrix<N>& A) : PETScAijMatrixEmbedder{N, N, &A(0, 0)} + {} + + PETScAijMatrixEmbedder(const DenseMatrix<double>& A) + : PETScAijMatrixEmbedder{A.numberOfRows(), A.numberOfColumns(), &A(0, 0)} + {} + + PETScAijMatrixEmbedder(const CRSMatrix<double, size_t>& A); + + ~PETScAijMatrixEmbedder(); +}; + +#endif // PUGS_HAS_PETSC + +#endif // PETSC_UTILS_HPP diff --git a/src/algebra/SparseMatrixDescriptor.hpp b/src/algebra/SparseMatrixDescriptor.hpp index f63a17576d619bf692f36a00e5c0c4e373effdbf..d94ed468606a10ee15857a971abab20fb4be5b1a 100644 --- a/src/algebra/SparseMatrixDescriptor.hpp +++ b/src/algebra/SparseMatrixDescriptor.hpp @@ -63,6 +63,7 @@ class SparseMatrixDescriptor private: Array<SparseRowDescriptor> m_row_array; + const size_t m_nb_columns; public: PUGS_INLINE @@ -72,6 +73,13 @@ class SparseMatrixDescriptor return m_row_array.size(); } + PUGS_INLINE + size_t + numberOfColumns() const noexcept + { + return m_nb_columns; + } + SparseRowDescriptor& row(const IndexType i) { @@ -90,7 +98,7 @@ class SparseMatrixDescriptor operator()(const IndexType& i, const IndexType& j) { Assert(i < m_row_array.size()); - Assert(j < m_row_array.size()); + Assert(j < m_nb_columns); return m_row_array[i][j]; } @@ -98,7 +106,7 @@ class SparseMatrixDescriptor operator()(const IndexType& i, const IndexType& j) const { Assert(i < m_row_array.size()); - Assert(j < m_row_array.size()); + Assert(j < m_nb_columns); const auto& r = m_row_array[i]; // split to ensure const-ness of call return r[j]; } @@ -145,13 +153,17 @@ class SparseMatrixDescriptor return values; } - SparseMatrixDescriptor(size_t nb_row) : m_row_array{nb_row} + SparseMatrixDescriptor(size_t nb_rows, size_t nb_columns) : m_row_array{nb_rows}, m_nb_columns{nb_columns} { - for (size_t i = 0; i < nb_row; ++i) { - m_row_array[i][i] = 0; + if (nb_rows == nb_columns) { + for (size_t i = 0; i < nb_rows; ++i) { + m_row_array[i][i] = 0; + } } } + SparseMatrixDescriptor(size_t nb_rows) : SparseMatrixDescriptor{nb_rows, nb_rows} {} + ~SparseMatrixDescriptor() = default; }; diff --git a/src/algebra/TinyMatrix.hpp b/src/algebra/TinyMatrix.hpp index 636ff19c18112c582c8968e8dc6f4df5ebdee726..6c23b068bf1a8c8744e24ffbf60ec88b42b1317b 100644 --- a/src/algebra/TinyMatrix.hpp +++ b/src/algebra/TinyMatrix.hpp @@ -36,6 +36,12 @@ class [[nodiscard]] TinyMatrix } public: + PUGS_INLINE + constexpr bool isSquare() const noexcept + { + return true; + } + PUGS_INLINE constexpr size_t dimension() const { @@ -43,13 +49,19 @@ class [[nodiscard]] TinyMatrix } PUGS_INLINE - constexpr size_t nbRows() const + constexpr size_t numberOfValues() const + { + return this->dimension(); + } + + PUGS_INLINE + constexpr size_t numberOfRows() const { return N; } PUGS_INLINE - constexpr size_t nbColumns() const + constexpr size_t numberOfColumns() const { return N; } diff --git a/src/algebra/Vector.hpp b/src/algebra/Vector.hpp index 089efa633161f4d3e83d16a5fc666ad5f9fc1696..e9eace62afa018c31c9f727e779a01c9ce39ccd6 100644 --- a/src/algebra/Vector.hpp +++ b/src/algebra/Vector.hpp @@ -17,12 +17,23 @@ class Vector // LCOV_EXCL_LINE private: Array<DataType> m_values; + const bool m_deep_copies; + static_assert(std::is_same_v<typename decltype(m_values)::index_type, index_type>); // Allows const version to access our data friend Vector<std::add_const_t<DataType>>; public: + friend std::ostream& + operator<<(std::ostream& os, const Vector& x) + { + for (size_t i = 0; i < x.size(); ++i) { + os << ' ' << x[i]; + } + return os; + } + friend Vector<std::remove_const_t<DataType>> copy(const Vector& x) { @@ -56,7 +67,7 @@ class Vector // LCOV_EXCL_LINE // Does not use parallel_for to preserve sum order for (index_type i = 0; i < x.size(); ++i) { - sum += x.m_values[i] * y.m_values[i]; + sum += x[i] * y[i]; } return sum; @@ -152,20 +163,49 @@ class Vector // LCOV_EXCL_LINE template <typename DataType2> PUGS_INLINE Vector& - operator=(const Vector<DataType2>& vector) noexcept + operator=(const Vector<DataType2>& x) noexcept { - m_values = vector.m_values; + // ensures that DataType is the same as source DataType2 + static_assert(std::is_same<std::remove_const_t<DataType>, std::remove_const_t<DataType2>>(), + "Cannot assign Vector of different type"); + // ensures that const is not lost through copy + static_assert(((std::is_const<DataType2>() and std::is_const<DataType>()) or not std::is_const<DataType2>()), + "Cannot assign Vector of const to Vector of non-const"); + + if (m_deep_copies) { + copy_to(x.m_values, m_values); + } else { + m_values = x.m_values; + } return *this; } PUGS_INLINE - Vector& operator=(const Vector&) = default; + Vector& + operator=(const Vector& x) + { + if (m_deep_copies) { + copy_to(x.m_values, m_values); + } else { + m_values = x.m_values; + } + return *this; + } PUGS_INLINE - Vector& operator=(Vector&&) = default; + Vector& + operator=(Vector&& x) + { + if (m_deep_copies) { + copy_to(x.m_values, m_values); + } else { + m_values = x.m_values; + } + return *this; + } template <typename DataType2> - Vector(const Vector<DataType2>& x) + Vector(const Vector<DataType2>& x) : m_deep_copies{x.m_deep_copies} { // ensures that DataType is the same as source DataType2 static_assert(std::is_same<std::remove_const_t<DataType>, std::remove_const_t<DataType2>>(), @@ -174,14 +214,19 @@ class Vector // LCOV_EXCL_LINE static_assert(((std::is_const<DataType2>() and std::is_const<DataType>()) or not std::is_const<DataType2>()), "Cannot assign Vector of const to Vector of non-const"); - this->operator=(x); + m_values = x.m_values; + } + + explicit Vector(const Array<DataType>& values) : m_deep_copies{true} + { + m_values = values; } Vector(const Vector&) = default; Vector(Vector&&) = default; - Vector(size_t size) : m_values{size} {} + Vector(size_t size) : m_values{size}, m_deep_copies{false} {} ~Vector() = default; }; diff --git a/src/language/ast/ASTNodeArraySubscriptExpressionBuilder.cpp b/src/language/ast/ASTNodeArraySubscriptExpressionBuilder.cpp index e717044d1dea5fe6b85aec6c41941699c1e5ef65..dcb2441c8bf14452c1f7af56a6a55bcdf340ede0 100644 --- a/src/language/ast/ASTNodeArraySubscriptExpressionBuilder.cpp +++ b/src/language/ast/ASTNodeArraySubscriptExpressionBuilder.cpp @@ -29,9 +29,9 @@ ASTNodeArraySubscriptExpressionBuilder::ASTNodeArraySubscriptExpressionBuilder(A } } } else if (array_expression.m_data_type == ASTNodeDataType::matrix_t) { - Assert(array_expression.m_data_type.nbRows() == array_expression.m_data_type.nbColumns()); + Assert(array_expression.m_data_type.numberOfRows() == array_expression.m_data_type.numberOfColumns()); - switch (array_expression.m_data_type.nbRows()) { + switch (array_expression.m_data_type.numberOfRows()) { case 1: { node.m_node_processor = std::make_unique<ArraySubscriptProcessor<TinyMatrix<1>>>(node); break; diff --git a/src/language/ast/ASTNodeBuiltinFunctionExpressionBuilder.cpp b/src/language/ast/ASTNodeBuiltinFunctionExpressionBuilder.cpp index 412906b9d67291ed7901d3ac00943cc8a9107449..70d8e3b3ac10456eb28c0036fdfa31eb1630bcab 100644 --- a/src/language/ast/ASTNodeBuiltinFunctionExpressionBuilder.cpp +++ b/src/language/ast/ASTNodeBuiltinFunctionExpressionBuilder.cpp @@ -120,8 +120,8 @@ ASTNodeBuiltinFunctionExpressionBuilder::_getArgumentConverter(const ASTNodeData if constexpr (std::is_same_v<ParameterT, TinyMatrix<1>>) { switch (argument_node_sub_data_type.m_data_type) { case ASTNodeDataType::matrix_t: { - if ((argument_node_sub_data_type.m_data_type.nbRows() == 1) and - (argument_node_sub_data_type.m_data_type.nbColumns() == 1)) { + if ((argument_node_sub_data_type.m_data_type.numberOfRows() == 1) and + (argument_node_sub_data_type.m_data_type.numberOfColumns() == 1)) { return std::make_unique<FunctionTinyMatrixArgumentConverter<ParameterT, ParameterT>>(argument_number); } else { // LCOV_EXCL_START @@ -152,8 +152,8 @@ ASTNodeBuiltinFunctionExpressionBuilder::_getArgumentConverter(const ASTNodeData } else { switch (argument_node_sub_data_type.m_data_type) { case ASTNodeDataType::matrix_t: { - if ((argument_node_sub_data_type.m_data_type.nbRows() == parameter_v.nbRows()) and - (argument_node_sub_data_type.m_data_type.nbColumns() == parameter_v.nbColumns())) { + if ((argument_node_sub_data_type.m_data_type.numberOfRows() == parameter_v.numberOfRows()) and + (argument_node_sub_data_type.m_data_type.numberOfColumns() == parameter_v.numberOfColumns())) { return std::make_unique<FunctionTinyMatrixArgumentConverter<ParameterT, ParameterT>>(argument_number); } else { // LCOV_EXCL_START @@ -164,7 +164,7 @@ ASTNodeBuiltinFunctionExpressionBuilder::_getArgumentConverter(const ASTNodeData } case ASTNodeDataType::list_t: { if (argument_node_sub_data_type.m_parent_node.children.size() == - (parameter_v.nbRows() * parameter_v.nbColumns())) { + (parameter_v.numberOfRows() * parameter_v.numberOfColumns())) { return std::make_unique<FunctionTinyMatrixArgumentConverter<ParameterT, ParameterT>>(argument_number); } else { // LCOV_EXCL_START @@ -293,8 +293,8 @@ ASTNodeBuiltinFunctionExpressionBuilder::_getArgumentConverter(const ASTNodeData } } case ASTNodeDataType::matrix_t: { - Assert(arg_data_type.nbRows() == arg_data_type.nbColumns()); - switch (arg_data_type.nbRows()) { + Assert(arg_data_type.numberOfRows() == arg_data_type.numberOfColumns()); + switch (arg_data_type.numberOfRows()) { case 1: { return std::make_unique<FunctionTupleArgumentConverter<ParameterContentT, TinyMatrix<1>>>(argument_number); } @@ -370,8 +370,8 @@ ASTNodeBuiltinFunctionExpressionBuilder::_getArgumentConverter(const ASTNodeData } } case ASTNodeDataType::matrix_t: { - Assert(parameter_type.nbRows() == parameter_type.nbColumns()); - switch (parameter_type.nbRows()) { + Assert(parameter_type.numberOfRows() == parameter_type.numberOfColumns()); + switch (parameter_type.numberOfRows()) { case 1: { return get_function_argument_converter_for_matrix(TinyMatrix<1>{}); } @@ -439,8 +439,8 @@ ASTNodeBuiltinFunctionExpressionBuilder::_getArgumentConverter(const ASTNodeData } } case ASTNodeDataType::matrix_t: { - Assert(parameter_type.contentType().nbRows() == parameter_type.contentType().nbColumns()); - switch (parameter_type.contentType().nbRows()) { + Assert(parameter_type.contentType().numberOfRows() == parameter_type.contentType().numberOfColumns()); + switch (parameter_type.contentType().numberOfRows()) { case 1: { return get_function_argument_to_tuple_converter(TinyMatrix<1>{}); } diff --git a/src/language/ast/ASTNodeDataTypeBuilder.cpp b/src/language/ast/ASTNodeDataTypeBuilder.cpp index d8cf06824ea5cf070a07a84d4bf3bcc711f71a79..eb307e2c16893be52128166c973f4992e86f3cb4 100644 --- a/src/language/ast/ASTNodeDataTypeBuilder.cpp +++ b/src/language/ast/ASTNodeDataTypeBuilder.cpp @@ -266,10 +266,11 @@ ASTNodeDataTypeBuilder::_buildNodeDataTypes(ASTNode& n) const } } else if (image_domain_node.is_type<language::matrix_type>()) { ASTNodeDataType image_type = getMatrixDataType(image_domain_node); - if (image_type.nbRows() * image_type.nbColumns() != nb_image_expressions) { + if (image_type.numberOfRows() * image_type.numberOfColumns() != nb_image_expressions) { std::ostringstream message; - message << "expecting " << image_type.nbRows() * image_type.nbColumns() << " scalar expressions or an " - << dataTypeName(image_type) << ", found " << nb_image_expressions << " scalar expressions"; + message << "expecting " << image_type.numberOfRows() * image_type.numberOfColumns() + << " scalar expressions or an " << dataTypeName(image_type) << ", found " << nb_image_expressions + << " scalar expressions"; throw ParseError(message.str(), image_expression_node.begin()); } } else { diff --git a/src/language/ast/ASTNodeFunctionExpressionBuilder.cpp b/src/language/ast/ASTNodeFunctionExpressionBuilder.cpp index 15720a9f645616ad08588c5d00e5185d06482276..6c1db0335b2f46a8410baed7f02e59efa6ae49c8 100644 --- a/src/language/ast/ASTNodeFunctionExpressionBuilder.cpp +++ b/src/language/ast/ASTNodeFunctionExpressionBuilder.cpp @@ -112,8 +112,8 @@ ASTNodeFunctionExpressionBuilder::_getArgumentConverter(SymbolType& parameter_sy using ParameterT = std::decay_t<decltype(parameter_v)>; switch (node_sub_data_type.m_data_type) { case ASTNodeDataType::matrix_t: { - if ((node_sub_data_type.m_data_type.nbRows() == parameter_v.nbRows()) and - (node_sub_data_type.m_data_type.nbColumns() == parameter_v.nbColumns())) { + if ((node_sub_data_type.m_data_type.numberOfRows() == parameter_v.numberOfRows()) and + (node_sub_data_type.m_data_type.numberOfColumns() == parameter_v.numberOfColumns())) { return std::make_unique<FunctionTinyMatrixArgumentConverter<ParameterT, ParameterT>>(parameter_id); } else { // LCOV_EXCL_START @@ -187,9 +187,10 @@ ASTNodeFunctionExpressionBuilder::_getArgumentConverter(SymbolType& parameter_sy // LCOV_EXCL_STOP } case ASTNodeDataType::matrix_t: { - Assert(parameter_symbol.attributes().dataType().nbRows() == parameter_symbol.attributes().dataType().nbColumns()); + Assert(parameter_symbol.attributes().dataType().numberOfRows() == + parameter_symbol.attributes().dataType().numberOfColumns()); - switch (parameter_symbol.attributes().dataType().nbRows()) { + switch (parameter_symbol.attributes().dataType().numberOfRows()) { case 1: { return get_function_argument_converter_for_matrix(TinyMatrix<1>{}); } @@ -361,8 +362,8 @@ ASTNodeFunctionExpressionBuilder::_getFunctionProcessor(const ASTNodeDataType& r using ReturnT = std::decay_t<decltype(return_v)>; switch (function_component_expression.m_data_type) { case ASTNodeDataType::matrix_t: { - if ((function_component_expression.m_data_type.nbRows() == return_v.nbRows()) and - (function_component_expression.m_data_type.nbColumns() == return_v.nbColumns())) { + if ((function_component_expression.m_data_type.numberOfRows() == return_v.numberOfRows()) and + (function_component_expression.m_data_type.numberOfColumns() == return_v.numberOfColumns())) { return std::make_unique<FunctionExpressionProcessor<ReturnT, ReturnT>>(function_component_expression); } else { // LCOV_EXCL_START @@ -461,9 +462,9 @@ ASTNodeFunctionExpressionBuilder::_getFunctionProcessor(const ASTNodeDataType& r } } case ASTNodeDataType::matrix_t: { - Assert(return_value_type.nbRows() == return_value_type.nbColumns()); + Assert(return_value_type.numberOfRows() == return_value_type.numberOfColumns()); - switch (return_value_type.nbRows()) { + switch (return_value_type.numberOfRows()) { case 1: { if (function_component_expression.m_data_type == ASTNodeDataType::matrix_t) { return get_function_processor_for_expression_matrix(TinyMatrix<1>{}); @@ -624,15 +625,15 @@ ASTNodeFunctionExpressionBuilder::ASTNodeFunctionExpressionBuilder(ASTNode& node ASTNodeNaturalConversionChecker<AllowRToR1Conversion>{function_expression, matrix_type}; if (function_expression.is_type<language::expression_list>()) { - Assert(matrix_type.nbRows() * matrix_type.nbColumns() == function_expression.children.size()); + Assert(matrix_type.numberOfRows() * matrix_type.numberOfColumns() == function_expression.children.size()); - for (size_t i = 0; i < matrix_type.nbRows() * matrix_type.nbColumns(); ++i) { + for (size_t i = 0; i < matrix_type.numberOfRows() * matrix_type.numberOfColumns(); ++i) { function_processor->addFunctionExpressionProcessor( this->_getFunctionProcessor(ASTNodeDataType::build<ASTNodeDataType::double_t>(), node, *function_expression.children[i])); } - switch (matrix_type.nbRows()) { + switch (matrix_type.numberOfRows()) { case 2: { node.m_node_processor = std::make_unique<TupleToTinyMatrixProcessor<FunctionProcessor, 2>>(node, std::move(function_processor)); @@ -651,7 +652,7 @@ ASTNodeFunctionExpressionBuilder::ASTNodeFunctionExpressionBuilder(ASTNode& node } } else if (function_expression.is_type<language::integer>()) { if (std::stoi(function_expression.string()) == 0) { - switch (matrix_type.nbRows()) { + switch (matrix_type.numberOfRows()) { case 1: { node.m_node_processor = std::make_unique<FunctionExpressionProcessor<TinyMatrix<1>, ZeroType>>(function_expression); diff --git a/src/language/ast/ASTNodeListAffectationExpressionBuilder.cpp b/src/language/ast/ASTNodeListAffectationExpressionBuilder.cpp index 6b53db72a1a257f74196a56f6e2c83694531fd5f..dc438e61f5aa8ea2ad0f4d3d2b0879c0e2ec0f0e 100644 --- a/src/language/ast/ASTNodeListAffectationExpressionBuilder.cpp +++ b/src/language/ast/ASTNodeListAffectationExpressionBuilder.cpp @@ -85,19 +85,19 @@ ASTNodeListAffectationExpressionBuilder::_buildAffectationProcessor( using ValueT = std::decay_t<decltype(value)>; if constexpr (std::is_same_v<ValueT, TinyMatrix<1>>) { if ((node_sub_data_type.m_data_type == ASTNodeDataType::matrix_t) and - (node_sub_data_type.m_data_type.nbRows() == value.nbRows()) and - (node_sub_data_type.m_data_type.nbColumns() == value.nbColumns())) { + (node_sub_data_type.m_data_type.numberOfRows() == value.numberOfRows()) and + (node_sub_data_type.m_data_type.numberOfColumns() == value.numberOfColumns())) { list_affectation_processor->template add<ValueT, ValueT>(value_node); } else { add_affectation_processor_for_data(value, node_sub_data_type); } } else if constexpr (std::is_same_v<ValueT, TinyMatrix<2>> or std::is_same_v<ValueT, TinyMatrix<3>>) { if ((node_sub_data_type.m_data_type == ASTNodeDataType::matrix_t) and - (node_sub_data_type.m_data_type.nbRows() == value.nbRows()) and - (node_sub_data_type.m_data_type.nbColumns() == value.nbColumns())) { + (node_sub_data_type.m_data_type.numberOfRows() == value.numberOfRows()) and + (node_sub_data_type.m_data_type.numberOfColumns() == value.numberOfColumns())) { list_affectation_processor->template add<ValueT, ValueT>(value_node); } else if ((node_sub_data_type.m_data_type == ASTNodeDataType::list_t) and - (node_sub_data_type.m_parent_node.children.size() == value.nbRows() * value.nbColumns())) { + (node_sub_data_type.m_parent_node.children.size() == value.numberOfRows() * value.numberOfColumns())) { list_affectation_processor->template add<ValueT, AggregateDataVariant>(value_node); } else if (node_sub_data_type.m_parent_node.is_type<language::integer>()) { if (std::stoi(node_sub_data_type.m_parent_node.string()) == 0) { @@ -241,8 +241,8 @@ ASTNodeListAffectationExpressionBuilder::_buildAffectationProcessor( break; } case ASTNodeDataType::matrix_t: { - Assert(value_type.nbRows() == value_type.nbColumns()); - switch (value_type.nbRows()) { + Assert(value_type.numberOfRows() == value_type.numberOfColumns()); + switch (value_type.numberOfRows()) { case 1: { add_affectation_processor_for_matrix_data(TinyMatrix<1>{}, node_sub_data_type); break; diff --git a/src/language/node_processor/AffectationProcessor.hpp b/src/language/node_processor/AffectationProcessor.hpp index 07a52de44e09cba57cf5b60aba65e844ff7faa94..f24e8473be7717f4ddd2e8f20d3d2ab666f19001 100644 --- a/src/language/node_processor/AffectationProcessor.hpp +++ b/src/language/node_processor/AffectationProcessor.hpp @@ -141,8 +141,8 @@ class AffectationExecutor final : public IAffectationExecutor v[i]); } } else if constexpr (is_tiny_matrix_v<ValueT>) { - for (size_t i = 0, l = 0; i < m_lhs.nbRows(); ++i) { - for (size_t j = 0; j < m_lhs.nbColumns(); ++j, ++l) { + for (size_t i = 0, l = 0; i < m_lhs.numberOfRows(); ++i) { + for (size_t j = 0; j < m_lhs.numberOfColumns(); ++j, ++l) { std::visit( [&](auto&& Aij) { using Aij_T = std::decay_t<decltype(Aij)>; @@ -435,12 +435,12 @@ class AffectationProcessor final : public INodeProcessor } } else if (array_expression.m_data_type == ASTNodeDataType::matrix_t) { Assert(lhs_node.children.size() == 3); - Assert(array_expression.m_data_type.nbRows() == array_expression.m_data_type.nbColumns()); + Assert(array_expression.m_data_type.numberOfRows() == array_expression.m_data_type.numberOfColumns()); auto& index0_expression = *lhs_node.children[1]; auto& index1_expression = *lhs_node.children[2]; - switch (array_expression.m_data_type.nbRows()) { + switch (array_expression.m_data_type.numberOfRows()) { case 1: { using ArrayTypeT = TinyMatrix<1>; if (not std::holds_alternative<ArrayTypeT>(value)) { @@ -576,8 +576,8 @@ class AffectationToTinyMatrixFromListProcessor final : public AffectationToDataV static_assert(std::is_same_v<OperatorT, language::eq_op>, "forbidden affection operator for list to vectors"); ValueT v; - for (size_t i = 0, l = 0; i < v.nbRows(); ++i) { - for (size_t j = 0; j < v.nbColumns(); ++j, ++l) { + for (size_t i = 0, l = 0; i < v.numberOfRows(); ++i) { + for (size_t j = 0; j < v.numberOfColumns(); ++j, ++l) { std::visit( [&](auto&& child_value) { using T = std::decay_t<decltype(child_value)>; @@ -721,9 +721,9 @@ class AffectationToTupleFromListProcessor final : public AffectationToDataVarian } else if constexpr (is_tiny_matrix_v<ValueT>) { if constexpr (std::is_same_v<T, AggregateDataVariant>) { ValueT& A = tuple_value[i]; - Assert(A.nbRows() * A.nbColumns() == child_value.size()); - for (size_t j = 0, l = 0; j < A.nbRows(); ++j) { - for (size_t k = 0; k < A.nbColumns(); ++k, ++l) { + Assert(A.numberOfRows() * A.numberOfColumns() == child_value.size()); + for (size_t j = 0, l = 0; j < A.numberOfRows(); ++j) { + for (size_t k = 0; k < A.numberOfColumns(); ++k, ++l) { std::visit( [&](auto&& Ajk) { using Ti = std::decay_t<decltype(Ajk)>; @@ -927,9 +927,9 @@ class ListAffectationProcessor final : public INodeProcessor auto& index0_expression = *array_subscript_expression.children[1]; auto& index1_expression = *array_subscript_expression.children[2]; - Assert(array_expression.m_data_type.nbRows() == array_expression.m_data_type.nbColumns()); + Assert(array_expression.m_data_type.numberOfRows() == array_expression.m_data_type.numberOfColumns()); - switch (array_expression.m_data_type.nbRows()) { + switch (array_expression.m_data_type.numberOfRows()) { case 1: { using ArrayTypeT = TinyMatrix<1>; if (not std::holds_alternative<ArrayTypeT>(value)) { diff --git a/src/language/node_processor/ExecutionPolicy.hpp b/src/language/node_processor/ExecutionPolicy.hpp index 47fc3174ca5236c067bde9045a97f4d1c0fe160a..672daf5915808232285d76b2f6ea8492a3bdb7c2 100644 --- a/src/language/node_processor/ExecutionPolicy.hpp +++ b/src/language/node_processor/ExecutionPolicy.hpp @@ -34,12 +34,14 @@ class ExecutionPolicy return m_shared_values->size(); } - DataVariant& operator[](size_t i) + DataVariant& + operator[](size_t i) { return (*m_shared_values)[i]; } - const DataVariant& operator[](size_t i) const + const DataVariant& + operator[](size_t i) const { return (*m_shared_values)[i]; } diff --git a/src/language/node_processor/FunctionArgumentConverter.hpp b/src/language/node_processor/FunctionArgumentConverter.hpp index b13eb222b08cd2c0f5dde5e72d4de5626ef7758b..f747672e2c036ab59402610cb7170218f96c15e3 100644 --- a/src/language/node_processor/FunctionArgumentConverter.hpp +++ b/src/language/node_processor/FunctionArgumentConverter.hpp @@ -139,8 +139,8 @@ class FunctionTinyMatrixArgumentConverter final : public IFunctionArgumentConver exec_policy.currentContext()[m_argument_id] = std::move(value); } else if constexpr (std::is_same_v<ValueT, AggregateDataVariant>) { ExpectedValueType matrix_value{}; - for (size_t i = 0, l = 0; i < matrix_value.nbRows(); ++i) { - for (size_t j = 0; j < matrix_value.nbColumns(); ++j, ++l) { + for (size_t i = 0, l = 0; i < matrix_value.numberOfRows(); ++i) { + for (size_t j = 0; j < matrix_value.numberOfColumns(); ++j, ++l) { std::visit( [&](auto&& A_ij) { using Vi_T = std::decay_t<decltype(A_ij)>; diff --git a/src/language/node_processor/FunctionProcessor.hpp b/src/language/node_processor/FunctionProcessor.hpp index f8c86ea9e5cb51e169e48ecadc0b4770ef873cc8..cead55c20fd2e6b34edb4df510840d683fc8b5b8 100644 --- a/src/language/node_processor/FunctionProcessor.hpp +++ b/src/language/node_processor/FunctionProcessor.hpp @@ -38,8 +38,8 @@ class FunctionExpressionProcessor final : public INodeProcessor } else { static_assert(is_tiny_matrix_v<ReturnType>); - for (size_t i = 0, l = 0; i < return_value.nbRows(); ++i) { - for (size_t j = 0; j < return_value.nbColumns(); ++j, ++l) { + for (size_t i = 0, l = 0; i < return_value.numberOfRows(); ++i) { + for (size_t j = 0; j < return_value.numberOfColumns(); ++j, ++l) { std::visit( [&](auto&& Aij) { using Vi_T = std::decay_t<decltype(Aij)>; diff --git a/src/language/utils/ASTNodeDataType.cpp b/src/language/utils/ASTNodeDataType.cpp index 3550025dd36e05c46e8ca20ce49a45d6b0fff30b..ddea3a6dd9a6a79fda474bb93e05645d55dd7503 100644 --- a/src/language/utils/ASTNodeDataType.cpp +++ b/src/language/utils/ASTNodeDataType.cpp @@ -76,7 +76,7 @@ dataTypeName(const ASTNodeDataType& data_type) name = "R^" + std::to_string(data_type.dimension()); break; case ASTNodeDataType::matrix_t: - name = "R^" + std::to_string(data_type.nbRows()) + "x" + std::to_string(data_type.nbColumns()); + name = "R^" + std::to_string(data_type.numberOfRows()) + "x" + std::to_string(data_type.numberOfColumns()); break; case ASTNodeDataType::tuple_t: name = "(" + dataTypeName(data_type.contentType()) + "...)"; @@ -173,8 +173,8 @@ isNaturalConversion(const ASTNodeDataType& data_type, const ASTNodeDataType& tar } else if (data_type == ASTNodeDataType::vector_t) { return (data_type.dimension() == target_data_type.dimension()); } else if (data_type == ASTNodeDataType::matrix_t) { - return ((data_type.nbRows() == target_data_type.nbRows()) and - (data_type.nbColumns() == target_data_type.nbColumns())); + return ((data_type.numberOfRows() == target_data_type.numberOfRows()) and + (data_type.numberOfColumns() == target_data_type.numberOfColumns())); } else { return true; } diff --git a/src/language/utils/ASTNodeDataType.hpp b/src/language/utils/ASTNodeDataType.hpp index c31c9e15b6e8df0055aa4854bb7ede0a73318abd..ea744757cf68b5055605111d35acc14564b06b30 100644 --- a/src/language/utils/ASTNodeDataType.hpp +++ b/src/language/utils/ASTNodeDataType.hpp @@ -70,7 +70,7 @@ class ASTNodeDataType PUGS_INLINE size_t - nbRows() const + numberOfRows() const { Assert(std::holds_alternative<std::array<size_t, 2>>(m_details)); return std::get<std::array<size_t, 2>>(m_details)[0]; @@ -78,7 +78,7 @@ class ASTNodeDataType PUGS_INLINE size_t - nbColumns() const + numberOfColumns() const { Assert(std::holds_alternative<std::array<size_t, 2>>(m_details)); return std::get<std::array<size_t, 2>>(m_details)[1]; diff --git a/src/language/utils/ASTNodeNaturalConversionChecker.cpp b/src/language/utils/ASTNodeNaturalConversionChecker.cpp index 81a277574753dc3e8cc75871a07d8d8a3b1a0cc6..a05c5aa1b4fcc79d531ea51544fb47dc1b40698e 100644 --- a/src/language/utils/ASTNodeNaturalConversionChecker.cpp +++ b/src/language/utils/ASTNodeNaturalConversionChecker.cpp @@ -14,8 +14,8 @@ ASTNodeNaturalConversionChecker<RToR1Conversion>::_checkIsNaturalTypeConversion( if (not isNaturalConversion(data_type, target_data_type)) { if constexpr (std::is_same_v<RToR1ConversionStrategy, AllowRToR1Conversion>) { if (((target_data_type == ASTNodeDataType::vector_t) and (target_data_type.dimension() == 1)) or - ((target_data_type == ASTNodeDataType::matrix_t) and (target_data_type.nbRows() == 1) and - (target_data_type.nbColumns() == 1))) { + ((target_data_type == ASTNodeDataType::matrix_t) and (target_data_type.numberOfRows() == 1) and + (target_data_type.numberOfColumns() == 1))) { if (isNaturalConversion(data_type, ASTNodeDataType::build<ASTNodeDataType::double_t>())) { return; } @@ -93,10 +93,11 @@ ASTNodeNaturalConversionChecker<RToR1Conversion>::_checkIsNaturalExpressionConve switch (data_type) { case ASTNodeDataType::list_t: { const auto& content_type_list = data_type.contentTypeList(); - if (content_type_list.size() != (target_data_type.nbRows() * target_data_type.nbColumns())) { + if (content_type_list.size() != (target_data_type.numberOfRows() * target_data_type.numberOfColumns())) { std::ostringstream os; os << "incompatible dimensions in affectation: expecting " - << target_data_type.nbRows() * target_data_type.nbColumns() << ", but provided " << content_type_list.size(); + << target_data_type.numberOfRows() * target_data_type.numberOfColumns() << ", but provided " + << content_type_list.size(); throw ParseError(os.str(), std::vector{node.begin()}); } @@ -112,8 +113,8 @@ ASTNodeNaturalConversionChecker<RToR1Conversion>::_checkIsNaturalExpressionConve break; } case ASTNodeDataType::matrix_t: { - if ((data_type.nbRows() != target_data_type.nbRows()) or - (data_type.nbColumns() != target_data_type.nbColumns())) { + if ((data_type.numberOfRows() != target_data_type.numberOfRows()) or + (data_type.numberOfColumns() != target_data_type.numberOfColumns())) { std::ostringstream error_message; error_message << "invalid implicit conversion: "; error_message << rang::fgB::red << dataTypeName(data_type) << " -> " << dataTypeName(target_data_type) diff --git a/src/language/utils/BuiltinFunctionEmbedderUtils.cpp b/src/language/utils/BuiltinFunctionEmbedderUtils.cpp index ffe1112d0543fa644aa952a9599d9fb12eb5e383..1c7723ff1c3f2b510db742dd9b647f643b83d303 100644 --- a/src/language/utils/BuiltinFunctionEmbedderUtils.cpp +++ b/src/language/utils/BuiltinFunctionEmbedderUtils.cpp @@ -109,13 +109,13 @@ getBuiltinFunctionEmbedder(ASTNode& n) } bool is_castable = true; - if (target_type.nbRows() > 1) { + if (target_type.numberOfRows() > 1) { switch (arg_type) { case ASTNodeDataType::int_t: { break; } case ASTNodeDataType::list_t: { - if (arg_type.contentTypeList().size() != target_type.nbRows() * target_type.nbColumns()) { + if (arg_type.contentTypeList().size() != target_type.numberOfRows() * target_type.numberOfColumns()) { is_castable = false; break; } diff --git a/src/language/utils/EmbeddedIDiscreteFunctionOperators.cpp b/src/language/utils/EmbeddedIDiscreteFunctionOperators.cpp index 0e5a789ce31e645b8ccdde6c48009eca4275d76b..13def86d07990370bb7dce658dde09f8d06b565a 100644 --- a/src/language/utils/EmbeddedIDiscreteFunctionOperators.cpp +++ b/src/language/utils/EmbeddedIDiscreteFunctionOperators.cpp @@ -58,8 +58,8 @@ applyUnaryOperation(const std::shared_ptr<const IDiscreteFunction>& f) } } case ASTNodeDataType::matrix_t: { - Assert(f->dataType().nbRows() == f->dataType().nbColumns()); - switch (f->dataType().nbRows()) { + Assert(f->dataType().numberOfRows() == f->dataType().numberOfColumns()); + switch (f->dataType().numberOfRows()) { case 1: { auto fh = dynamic_cast<const DiscreteFunctionP0<Dimension, TinyMatrix<1>>&>(*f); return applyUnaryOperation<UnaryOperatorT>(fh); @@ -205,8 +205,8 @@ innerCompositionLaw(const std::shared_ptr<const IDiscreteFunction>& f, } case ASTNodeDataType::matrix_t: { Assert(f->descriptor().type() == DiscreteFunctionType::P0); - Assert(f->dataType().nbRows() == f->dataType().nbColumns()); - switch (f->dataType().nbRows()) { + Assert(f->dataType().numberOfRows() == f->dataType().numberOfColumns()); + switch (f->dataType().numberOfRows()) { case 1: { auto fh = dynamic_cast<const DiscreteFunctionP0<Dimension, TinyMatrix<1>>&>(*f); auto gh = dynamic_cast<const DiscreteFunctionP0<Dimension, TinyMatrix<1>>&>(*g); @@ -350,9 +350,9 @@ applyBinaryOperation(const DiscreteFunctionT& fh, const std::shared_ptr<const ID } } case ASTNodeDataType::matrix_t: { - Assert(g->dataType().nbRows() == g->dataType().nbColumns()); + Assert(g->dataType().numberOfRows() == g->dataType().numberOfColumns()); if constexpr (std::is_same_v<lhs_data_type, double> and std::is_same_v<language::multiply_op, BinOperatorT>) { - switch (g->dataType().nbRows()) { + switch (g->dataType().numberOfRows()) { case 1: { auto gh = dynamic_cast<const DiscreteFunctionP0<Dimension, TinyMatrix<1>>&>(*g); @@ -397,8 +397,8 @@ applyBinaryOperation(const std::shared_ptr<const IDiscreteFunction>& f, return applyBinaryOperation<BinOperatorT, Dimension>(fh, g); } case ASTNodeDataType::matrix_t: { - Assert(f->dataType().nbRows() == f->dataType().nbColumns()); - switch (f->dataType().nbRows()) { + Assert(f->dataType().numberOfRows() == f->dataType().numberOfColumns()); + switch (f->dataType().numberOfRows()) { case 1: { auto fh = dynamic_cast<const DiscreteFunctionP0<Dimension, TinyMatrix<1>>&>(*f); @@ -621,9 +621,9 @@ applyBinaryOperationWithLeftConstant(const DataType& a, const std::shared_ptr<co } } case ASTNodeDataType::matrix_t: { - Assert(f->dataType().nbRows() == f->dataType().nbColumns()); + Assert(f->dataType().numberOfRows() == f->dataType().numberOfColumns()); if constexpr (is_tiny_matrix_v<DataType>) { - switch (f->dataType().nbRows()) { + switch (f->dataType().numberOfRows()) { case 1: { if constexpr (std::is_same_v<DataType, TinyMatrix<1>>) { auto fh = dynamic_cast<const DiscreteFunctionP0<Dimension, TinyMatrix<1>>&>(*f); @@ -653,7 +653,7 @@ applyBinaryOperationWithLeftConstant(const DataType& a, const std::shared_ptr<co } } } else { - switch (f->dataType().nbRows()) { + switch (f->dataType().numberOfRows()) { case 1: { auto fh = dynamic_cast<const DiscreteFunctionP0<Dimension, TinyMatrix<1>>&>(*f); return applyBinaryOperationWithLeftConstant<BinOperatorT>(a, fh); @@ -747,9 +747,9 @@ applyBinaryOperationWithRightConstant(const std::shared_ptr<const IDiscreteFunct return applyBinaryOperationWithRightConstant<BinOperatorT>(fh, a); } case ASTNodeDataType::matrix_t: { - Assert(f->dataType().nbRows() == f->dataType().nbColumns()); + Assert(f->dataType().numberOfRows() == f->dataType().numberOfColumns()); if constexpr (is_tiny_matrix_v<DataType>) { - switch (f->dataType().nbRows()) { + switch (f->dataType().numberOfRows()) { case 1: { if constexpr (std::is_same_v<DataType, TinyMatrix<1>>) { auto fh = dynamic_cast<const DiscreteFunctionP0<Dimension, TinyMatrix<1>>&>(*f); @@ -779,7 +779,7 @@ applyBinaryOperationWithRightConstant(const std::shared_ptr<const IDiscreteFunct } } } else { - switch (f->dataType().nbRows()) { + switch (f->dataType().numberOfRows()) { case 1: { auto fh = dynamic_cast<const DiscreteFunctionP0<Dimension, TinyMatrix<1>>&>(*f); return applyBinaryOperationWithRightConstant<BinOperatorT>(fh, a); diff --git a/src/language/utils/EmbeddedIDiscreteFunctionUtils.hpp b/src/language/utils/EmbeddedIDiscreteFunctionUtils.hpp index 9321c3273d7955e77934f9f4233ae3603cf14990..981cd8be9ca166038b5aa4b913dae63488868b64 100644 --- a/src/language/utils/EmbeddedIDiscreteFunctionUtils.hpp +++ b/src/language/utils/EmbeddedIDiscreteFunctionUtils.hpp @@ -35,8 +35,8 @@ isSameDiscretization(const IDiscreteFunction& f, const IDiscreteFunction& g) return f.dataType().dimension() == g.dataType().dimension(); } case ASTNodeDataType::matrix_t: { - return (f.dataType().nbRows() == g.dataType().nbRows()) and - (f.dataType().nbColumns() == g.dataType().nbColumns()); + return (f.dataType().numberOfRows() == g.dataType().numberOfRows()) and + (f.dataType().numberOfColumns() == g.dataType().numberOfColumns()); } default: { throw UnexpectedError("invalid data type " + operand_type_name(f)); diff --git a/src/language/utils/EmbedderTable.hpp b/src/language/utils/EmbedderTable.hpp index 60441cec257aee69afc0caa72faf9a487fc736d0..68e1ddb5243e7c954745842e9e7d1e13677fcbca 100644 --- a/src/language/utils/EmbedderTable.hpp +++ b/src/language/utils/EmbedderTable.hpp @@ -21,7 +21,8 @@ class EmbedderTable } PUGS_INLINE - const std::shared_ptr<EmbedderT>& operator[](size_t embedder_id) const + const std::shared_ptr<EmbedderT>& + operator[](size_t embedder_id) const { Assert(embedder_id < m_embedder_list.size()); return m_embedder_list[embedder_id]; diff --git a/src/language/utils/PugsFunctionAdapter.hpp b/src/language/utils/PugsFunctionAdapter.hpp index b6d3a259dbb676d5f1259c058e0ea1f36fb925fd..3047652e3017fb2cd193b799a8edf454e3e4c22b 100644 --- a/src/language/utils/PugsFunctionAdapter.hpp +++ b/src/language/utils/PugsFunctionAdapter.hpp @@ -209,7 +209,7 @@ class PugsFunctionAdapter<OutputType(InputType...)> }; } else { // If this point is reached must be a 0 vector - return [](DataVariant&&) -> OutputType { return OutputType{ZeroType{}}; }; + return [](DataVariant &&) -> OutputType { return OutputType{ZeroType{}}; }; } } case ASTNodeDataType::double_t: { @@ -236,8 +236,8 @@ class PugsFunctionAdapter<OutputType(InputType...)> AggregateDataVariant& v = std::get<AggregateDataVariant>(result); OutputType x; - for (size_t i = 0, l = 0; i < x.nbRows(); ++i) { - for (size_t j = 0; j < x.nbColumns(); ++j, ++l) { + for (size_t i = 0, l = 0; i < x.numberOfRows(); ++i) { + for (size_t j = 0; j < x.numberOfColumns(); ++j, ++l) { std::visit( [&](auto&& Aij) { using Aij_T = std::decay_t<decltype(Aij)>; @@ -288,7 +288,7 @@ class PugsFunctionAdapter<OutputType(InputType...)> }; } else { // If this point is reached must be a 0 matrix - return [](DataVariant&&) -> OutputType { return OutputType{ZeroType{}}; }; + return [](DataVariant &&) -> OutputType { return OutputType{ZeroType{}}; }; } } case ASTNodeDataType::double_t: { diff --git a/src/mesh/ItemArray.hpp b/src/mesh/ItemArray.hpp index 1a2b004c9533921ab6531b6fa73c9a955badff57..5a16861a37b5642ba10977d8c9e2d5ecd25fd194 100644 --- a/src/mesh/ItemArray.hpp +++ b/src/mesh/ItemArray.hpp @@ -109,7 +109,7 @@ class ItemArray numberOfItems() const noexcept(NO_ASSERT) { Assert(this->isBuilt()); - return m_values.nbRows(); + return m_values.numberOfRows(); } PUGS_INLINE @@ -117,7 +117,7 @@ class ItemArray sizeOfArrays() const { Assert(this->isBuilt()); - return m_values.nbColumns(); + return m_values.numberOfColumns(); } template <typename DataType2> @@ -131,11 +131,11 @@ class ItemArray static_assert(((std::is_const_v<DataType2> and std::is_const_v<DataType>) or not std::is_const_v<DataType2>), "Cannot assign ItemArray of const to ItemArray of non-const"); - Assert((table.nbRows() * table.nbColumns() == 0) or this->isBuilt(), + Assert((table.numberOfRows() * table.numberOfColumns() == 0) or this->isBuilt(), "Cannot assign array of arrays to a non-built ItemArray\n"); - Assert(this->numberOfItems() == table.nbRows(), "Cannot assign a table of a different dimensions\n"); - Assert(this->sizeOfArrays() == table.nbColumns(), "Cannot assign a table of a different dimensions\n"); + Assert(this->numberOfItems() == table.numberOfRows(), "Cannot assign a table of a different dimensions\n"); + Assert(this->sizeOfArrays() == table.numberOfColumns(), "Cannot assign a table of a different dimensions\n"); m_values = table; diff --git a/src/mesh/SubItemArrayPerItem.hpp b/src/mesh/SubItemArrayPerItem.hpp index 501762ea6270b7ebf59b26c4afdea6edd552cc3e..9fd488bc5e6ebe3ea189368de8eeb67073e590ec 100644 --- a/src/mesh/SubItemArrayPerItem.hpp +++ b/src/mesh/SubItemArrayPerItem.hpp @@ -100,7 +100,7 @@ class SubItemArrayPerItem { static_assert(std::is_integral_v<ArrayIndexType>, "index must be an integral type"); Assert(this->isBuilt()); - Assert(static_cast<size_t>(i) < m_values.nbRows()); + Assert(static_cast<size_t>(i) < m_values.numberOfRows()); return m_values[i]; } @@ -109,7 +109,7 @@ class SubItemArrayPerItem numberOfArrays() const noexcept(NO_ASSERT) { Assert(this->isBuilt()); - return m_values.nbRows(); + return m_values.numberOfRows(); } PUGS_INLINE @@ -125,7 +125,7 @@ class SubItemArrayPerItem sizeOfArrays() const noexcept(NO_ASSERT) { Assert(this->isBuilt()); - return m_values.nbColumns(); + return m_values.numberOfColumns(); } template <typename IndexType> diff --git a/src/output/GnuplotWriter.cpp b/src/output/GnuplotWriter.cpp index 5cb59553a54df6f1b7c173066079110058c84330..324620fd67f3330bd92958fd8df8a8ccadfc5088 100644 --- a/src/output/GnuplotWriter.cpp +++ b/src/output/GnuplotWriter.cpp @@ -64,8 +64,8 @@ GnuplotWriter::_writePreamble(const OutputNamedItemDataSet& output_named_item_da fout << ' ' << i++ << ':' << name << '[' << j << ']'; } } else if constexpr (is_tiny_matrix_v<DataType>) { - for (size_t j = 0; j < DataType{}.nbRows(); ++j) { - for (size_t k = 0; k < DataType{}.nbColumns(); ++k) { + for (size_t j = 0; j < DataType{}.numberOfRows(); ++j) { + for (size_t k = 0; k < DataType{}.numberOfColumns(); ++k) { fout << ' ' << i++ << ':' << name << '(' << j << ',' << k << ')'; } } @@ -101,8 +101,8 @@ GnuplotWriter::_writeCellData(const CellValue<DataType>& cell_value, CellId cell fout << ' ' << value[i]; } } else if constexpr (is_tiny_matrix_v<std::decay_t<DataType>>) { - for (size_t i = 0; i < value.nbRows(); ++i) { - for (size_t j = 0; j < value.nbColumns(); ++j) { + for (size_t i = 0; i < value.numberOfRows(); ++i) { + for (size_t j = 0; j < value.numberOfColumns(); ++j) { fout << ' ' << value(i, j); } } @@ -209,8 +209,8 @@ GnuplotWriter::_writeNodeData(const NodeValue<DataType>& node_value, NodeId node fout << ' ' << value[i]; } } else if constexpr (is_tiny_matrix_v<std::decay_t<DataType>>) { - for (size_t i = 0; i < value.nbRows(); ++i) { - for (size_t j = 0; j < value.nbColumns(); ++j) { + for (size_t i = 0; i < value.numberOfRows(); ++i) { + for (size_t j = 0; j < value.numberOfColumns(); ++j) { fout << ' ' << value(i, j); } } diff --git a/src/output/GnuplotWriter1D.cpp b/src/output/GnuplotWriter1D.cpp index 31320054e6f244e9e0771190c539eecd733d66ee..a57405d3aabc4ef23aefd6bd2b5f74f2f1681fa3 100644 --- a/src/output/GnuplotWriter1D.cpp +++ b/src/output/GnuplotWriter1D.cpp @@ -74,8 +74,8 @@ GnuplotWriter1D::_writePreamble(const OutputNamedItemDataSet& output_named_item_ fout << ' ' << i++ << ':' << name << '[' << j << ']'; } } else if constexpr (is_tiny_matrix_v<DataType>) { - for (size_t j = 0; j < DataType{}.nbRows(); ++j) { - for (size_t k = 0; k < DataType{}.nbColumns(); ++k) { + for (size_t j = 0; j < DataType{}.numberOfRows(); ++j) { + for (size_t k = 0; k < DataType{}.numberOfColumns(); ++k) { fout << ' ' << i++ << ':' << name << '(' << j << ',' << k << ')'; } } @@ -199,8 +199,8 @@ GnuplotWriter1D::_writeItemDatas(const std::shared_ptr<const MeshType>& mesh, } } else if constexpr (is_tiny_matrix_v<DataT>) { size_t k = number_of_columns * index + column_number; - for (size_t i = 0; i < DataT{}.nbRows(); ++i) { - for (size_t j = 0; j < DataT{}.nbColumns(); ++j) { + for (size_t i = 0; i < DataT{}.numberOfRows(); ++i) { + for (size_t j = 0; j < DataT{}.numberOfColumns(); ++j) { values[k++] = item_data[item_id](i, j); } } diff --git a/src/output/WriterBase.cpp b/src/output/WriterBase.cpp index 40d08b305094c6c33576181a9d730e579656497e..21589e732ecde0a85491438ae7dba259b8ed3060 100644 --- a/src/output/WriterBase.cpp +++ b/src/output/WriterBase.cpp @@ -85,8 +85,8 @@ WriterBase::_register(const std::string& name, IDiscreteFunction::HandledItemDataType::vector) { throw UnexpectedError("invalid data type for vector data"); } else { - Assert(data_type.nbRows() == data_type.nbColumns(), "invalid matrix dimensions"); - switch (data_type.nbRows()) { + Assert(data_type.numberOfRows() == data_type.numberOfColumns(), "invalid matrix dimensions"); + switch (data_type.numberOfRows()) { case 1: { _register(name, dynamic_cast<const DiscreteFunctionType<Dimension, TinyMatrix<1, double>>&>(i_discrete_function), diff --git a/src/scheme/DiscreteFunctionInterpoler.cpp b/src/scheme/DiscreteFunctionInterpoler.cpp index c8eeaf94cb8d4f1037b28ebf65d377660464c093..11b19835eab3af91c0ea125359364831916cbc18 100644 --- a/src/scheme/DiscreteFunctionInterpoler.cpp +++ b/src/scheme/DiscreteFunctionInterpoler.cpp @@ -60,8 +60,8 @@ DiscreteFunctionInterpoler::_interpolate() const } } case ASTNodeDataType::matrix_t: { - Assert(data_type.nbColumns() == data_type.nbRows(), "undefined matrix type"); - switch (data_type.nbColumns()) { + Assert(data_type.numberOfColumns() == data_type.numberOfRows(), "undefined matrix type"); + switch (data_type.numberOfColumns()) { case 1: { return this->_interpolate<Dimension, TinyMatrix<1>>(); } diff --git a/src/scheme/DiscreteFunctionUtils.cpp b/src/scheme/DiscreteFunctionUtils.cpp index 56453a746a19b9ee999fe1548d7067250e2884eb..6d2e62da4fcdd9d1c785b01894ca3d4776dfae8c 100644 --- a/src/scheme/DiscreteFunctionUtils.cpp +++ b/src/scheme/DiscreteFunctionUtils.cpp @@ -53,12 +53,12 @@ shallowCopy(const std::shared_ptr<const Mesh<Connectivity<Dimension>>>& mesh, } } case ASTNodeDataType::matrix_t: { - if (discrete_function->dataType().nbRows() != discrete_function->dataType().nbColumns()) { + if (discrete_function->dataType().numberOfRows() != discrete_function->dataType().numberOfColumns()) { throw UnexpectedError( - "invalid data matrix dimensions: " + std::to_string(discrete_function->dataType().nbRows()) + "x" + - std::to_string(discrete_function->dataType().nbColumns())); + "invalid data matrix dimensions: " + std::to_string(discrete_function->dataType().numberOfRows()) + "x" + + std::to_string(discrete_function->dataType().numberOfColumns())); } - switch (discrete_function->dataType().nbRows()) { + switch (discrete_function->dataType().numberOfRows()) { case 1: { return shallowCopy(mesh, std::dynamic_pointer_cast<const DiscreteFunctionP0<Dimension, TinyMatrix<1>>>( discrete_function)); @@ -73,8 +73,8 @@ shallowCopy(const std::shared_ptr<const Mesh<Connectivity<Dimension>>>& mesh, } default: { throw UnexpectedError( - "invalid data matrix dimensions: " + std::to_string(discrete_function->dataType().nbRows()) + "x" + - std::to_string(discrete_function->dataType().nbColumns())); + "invalid data matrix dimensions: " + std::to_string(discrete_function->dataType().numberOfRows()) + "x" + + std::to_string(discrete_function->dataType().numberOfColumns())); } } } diff --git a/src/utils/Array.hpp b/src/utils/Array.hpp index 5eb834b85fb8f0679636531e740863286e912c3d..9fa02e95a41a5200260fab84cda211412c4747e2 100644 --- a/src/utils/Array.hpp +++ b/src/utils/Array.hpp @@ -85,10 +85,15 @@ class [[nodiscard]] Array Array& operator=(Array&&) = default; PUGS_INLINE - explicit Array(size_t size) : m_values("anonymous", size) + explicit Array(size_t size) { static_assert(not std::is_const<DataType>(), "Cannot allocate Array of const data: only view is " "supported"); + if constexpr (std::is_arithmetic_v<DataType>) { + m_values = Kokkos::View<DataType*>{Kokkos::view_alloc(Kokkos::WithoutInitializing, "anonymous"), size}; + } else { + m_values = Kokkos::View<DataType*>{"anonymous", size}; + } } PUGS_INLINE diff --git a/src/utils/BuildInfo.cpp b/src/utils/BuildInfo.cpp index 38d46007ef6cfcf470051e8546714db7041a7852..71d702c99ab86f7737b23a8ef42fa53845875cef 100644 --- a/src/utils/BuildInfo.cpp +++ b/src/utils/BuildInfo.cpp @@ -12,6 +12,10 @@ #include <petsc.h> #endif // PUGS_HAS_PETSC +#ifdef PUGS_HAS_SLEPC +#include <slepc.h> +#endif // PUGS_HAS_PETSC + std::string BuildInfo::type() { @@ -57,3 +61,14 @@ BuildInfo::petscLibrary() return "none"; #endif // PUGS_HAS_PETSC } + +std::string +BuildInfo::slepcLibrary() +{ +#ifdef PUGS_HAS_SLEPC + return std::to_string(SLEPC_VERSION_MAJOR) + "." + std::to_string(SLEPC_VERSION_MINOR) + "." + + std::to_string(SLEPC_VERSION_SUBMINOR); +#else + return "none"; +#endif // PUGS_HAS_SLEPC +} diff --git a/src/utils/BuildInfo.hpp b/src/utils/BuildInfo.hpp index 67134a782f595ccf68dc89cd29a6f273c7ce6140..bc83cf3f1426bcab2972ebb8466f790cadf8a9ef 100644 --- a/src/utils/BuildInfo.hpp +++ b/src/utils/BuildInfo.hpp @@ -10,6 +10,7 @@ struct BuildInfo static std::string kokkosDevices(); static std::string mpiLibrary(); static std::string petscLibrary(); + static std::string slepcLibrary(); }; #endif // BUILD_INFO_HPP diff --git a/src/utils/CMakeLists.txt b/src/utils/CMakeLists.txt index fe9b5e6fed3ff7ddd796ab0081ce144e8b535b90..7639963d4fc73094f2e79f64e9f9c9383426ac43 100644 --- a/src/utils/CMakeLists.txt +++ b/src/utils/CMakeLists.txt @@ -10,9 +10,17 @@ add_library( FPEManager.cpp Messenger.cpp Partitioner.cpp + PETScWrapper.cpp PugsUtils.cpp RevisionInfo.cpp - SignalManager.cpp) + SignalManager.cpp + SLEPcWrapper.cpp) + +target_link_libraries( + PugsUtils + ${PETSC_LIBRARIES} + ${SLEPC_LIBRARIES} +) # --------------- get git revision info --------------- diff --git a/src/algebra/PETScWrapper.cpp b/src/utils/PETScWrapper.cpp similarity index 92% rename from src/algebra/PETScWrapper.cpp rename to src/utils/PETScWrapper.cpp index dd11dc9772f11ad29ca4970c5b88656c623a3508..f88bbfd8a6bfd9de92d153e54c68e111f0b692b6 100644 --- a/src/algebra/PETScWrapper.cpp +++ b/src/utils/PETScWrapper.cpp @@ -1,4 +1,4 @@ -#include <algebra/PETScWrapper.hpp> +#include <utils/PETScWrapper.hpp> #include <utils/pugs_config.hpp> diff --git a/src/algebra/PETScWrapper.hpp b/src/utils/PETScWrapper.hpp similarity index 100% rename from src/algebra/PETScWrapper.hpp rename to src/utils/PETScWrapper.hpp diff --git a/src/utils/PugsUtils.cpp b/src/utils/PugsUtils.cpp index ad9e12e7ec4cdd01305cf8701c327894c7942304..d35fa95f43cb03810814ec6b62ed039842de1289 100644 --- a/src/utils/PugsUtils.cpp +++ b/src/utils/PugsUtils.cpp @@ -1,11 +1,12 @@ #include <utils/PugsUtils.hpp> -#include <algebra/PETScWrapper.hpp> #include <utils/BuildInfo.hpp> #include <utils/ConsoleManager.hpp> #include <utils/FPEManager.hpp> #include <utils/Messenger.hpp> +#include <utils/PETScWrapper.hpp> #include <utils/RevisionInfo.hpp> +#include <utils/SLEPcWrapper.hpp> #include <utils/SignalManager.hpp> #include <utils/pugs_build_info.hpp> @@ -55,6 +56,7 @@ pugsBuildInfo() os << "kokkos: " << rang::style::bold << BuildInfo::kokkosDevices() << rang::style::reset << '\n'; os << "MPI: " << rang::style::bold << BuildInfo::mpiLibrary() << rang::style::reset << '\n'; os << "PETSc: " << rang::style::bold << BuildInfo::petscLibrary() << rang::style::reset << '\n'; + os << "SLEPc: " << rang::style::bold << BuildInfo::slepcLibrary() << rang::style::reset << '\n'; os << "-------------------------------------------------------"; return os.str(); @@ -123,6 +125,7 @@ initialize(int& argc, char* argv[]) } PETScWrapper::initialize(argc, argv); + SLEPcWrapper::initialize(argc, argv); setDefaultOMPEnvironment(); Kokkos::initialize(argc, argv); @@ -152,6 +155,7 @@ void finalize() { Kokkos::finalize(); + SLEPcWrapper::finalize(); PETScWrapper::finalize(); parallel::Messenger::destroy(); } diff --git a/src/utils/SLEPcWrapper.cpp b/src/utils/SLEPcWrapper.cpp new file mode 100644 index 0000000000000000000000000000000000000000..2c7076d54f9cf438e34e54302041cd6e76633689 --- /dev/null +++ b/src/utils/SLEPcWrapper.cpp @@ -0,0 +1,26 @@ +#include <utils/SLEPcWrapper.hpp> + +#include <utils/pugs_config.hpp> + +#ifdef PUGS_HAS_SLEPC +#include <slepc.h> +#endif // PUGS_HAS_SLEPC + +namespace SLEPcWrapper +{ +void +initialize([[maybe_unused]] int& argc, [[maybe_unused]] char* argv[]) +{ +#ifdef PUGS_HAS_SLEPC + SlepcInitialize(&argc, &argv, 0, 0); +#endif // PUGS_HAS_SLEPC +} + +void +finalize() +{ +#ifdef PUGS_HAS_SLEPC + SlepcFinalize(); +#endif // PUGS_HAS_SLEPC +} +} // namespace SLEPcWrapper diff --git a/src/utils/SLEPcWrapper.hpp b/src/utils/SLEPcWrapper.hpp new file mode 100644 index 0000000000000000000000000000000000000000..8b64802339ba2c6d8c78aa3c7a86005e3fd013bf --- /dev/null +++ b/src/utils/SLEPcWrapper.hpp @@ -0,0 +1,10 @@ +#ifndef SLEPC_WRAPPER_HPP +#define SLEPC_WRAPPER_HPP + +namespace SLEPcWrapper +{ +void initialize(int& argc, char* argv[]); +void finalize(); +} // namespace SLEPcWrapper + +#endif // SLEPC_WRAPPER_HPP diff --git a/src/utils/Table.hpp b/src/utils/Table.hpp index eedc5e7d72c4c2f935f0ecafe0d24747c3b2d00e..8dae32b97b0d15a99256fd38c4f4f7c5ecf29588 100644 --- a/src/utils/Table.hpp +++ b/src/utils/Table.hpp @@ -21,12 +21,12 @@ class [[nodiscard]] Table friend Table<std::add_const_t<DataType>>; public: - PUGS_INLINE size_t nbRows() const noexcept + PUGS_INLINE size_t numberOfRows() const noexcept { return m_values.extent(0); } - PUGS_INLINE size_t nbColumns() const noexcept + PUGS_INLINE size_t numberOfColumns() const noexcept { return m_values.extent(1); } @@ -34,13 +34,13 @@ class [[nodiscard]] Table PUGS_INLINE Array<DataType> operator[](index_type i) const { - Assert(i < this->nbRows()); + Assert(i < this->numberOfRows()); return encapsulate(Kokkos::View<DataType*>(m_values, i, Kokkos::ALL)); } friend PUGS_INLINE Table<std::remove_const_t<DataType>> copy(const Table<DataType>& source) { - Table<std::remove_const_t<DataType>> image(source.nbRows(), source.nbColumns()); + Table<std::remove_const_t<DataType>> image(source.numberOfRows(), source.numberOfColumns()); Kokkos::deep_copy(image.m_values, source.m_values); return image; @@ -49,8 +49,8 @@ class [[nodiscard]] Table friend PUGS_INLINE void copy_to(const Table<DataType>& source, const Table<std::remove_const_t<DataType>>& destination) { - Assert(source.nbRows() == destination.nbRows()); - Assert(source.nbColumns() == destination.nbColumns()); + Assert(source.numberOfRows() == destination.numberOfRows()); + Assert(source.numberOfColumns() == destination.numberOfColumns()); Kokkos::deep_copy(destination.m_values, source.m_values); } @@ -66,8 +66,8 @@ class [[nodiscard]] Table PUGS_INLINE DataType& operator()(index_type i, index_type j) const noexcept(NO_ASSERT) { - Assert(i < this->nbRows()); - Assert(j < this->nbColumns()); + Assert(i < this->numberOfRows()); + Assert(j < this->numberOfColumns()); return m_values(i, j); } @@ -99,10 +99,16 @@ class [[nodiscard]] Table Table& operator=(Table&&) = default; PUGS_INLINE - explicit Table(size_t nb_lines, size_t nb_columns) : m_values("anonymous", nb_lines, nb_columns) + explicit Table(size_t nb_lines, size_t nb_columns) { static_assert(not std::is_const<DataType>(), "Cannot allocate Table of const data: only view is " "supported"); + if constexpr (std::is_arithmetic_v<DataType>) { + m_values = + Kokkos::View<DataType**>{Kokkos::view_alloc(Kokkos::WithoutInitializing, "anonymous"), nb_lines, nb_columns}; + } else { + m_values = Kokkos::View<DataType**>{"anonymous", nb_lines, nb_columns}; + } } PUGS_INLINE @@ -141,10 +147,10 @@ subTable(const Table<DataType>& table, typename Table<DataType>::index_type column_begin, typename Table<DataType>::index_type column_size) { - Assert(row_begin < table.nbRows()); - Assert(row_begin + row_size <= table.nbRows()); - Assert(column_begin < table.nbColumns()); - Assert(column_begin + column_size <= table.nbColumns()); + Assert(row_begin < table.numberOfRows()); + Assert(row_begin + row_size <= table.numberOfRows()); + Assert(column_begin < table.numberOfColumns()); + Assert(column_begin + column_size <= table.numberOfColumns()); return encapsulate(Kokkos::View<DataType**>(table.m_values, std::make_pair(row_begin, row_begin + row_size), std::make_pair(column_begin, column_begin + column_size))); } diff --git a/src/utils/pugs_config.hpp.in b/src/utils/pugs_config.hpp.in index 84a6d8fa0c2d50eb623d5d1c2b52765f5610de24..0736003b9f40c4f71feea089072c19d9238e4033 100644 --- a/src/utils/pugs_config.hpp.in +++ b/src/utils/pugs_config.hpp.in @@ -4,6 +4,7 @@ #cmakedefine PUGS_HAS_FENV_H #cmakedefine PUGS_HAS_MPI #cmakedefine PUGS_HAS_PETSC +#cmakedefine PUGS_HAS_SLEPC #cmakedefine SYSTEM_IS_LINUX #cmakedefine SYSTEM_IS_DARWIN diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 4bb227aac16a433471caa45bdfb8b8bc48f4f2bb..a56fb1f9d0b49108f1770f186cec453758cfd793 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -57,11 +57,13 @@ add_executable (unit_tests test_CRSGraph.cpp test_CRSMatrix.cpp test_DataVariant.cpp + test_DenseMatrix.cpp test_Demangle.cpp test_DiscreteFunctionDescriptorP0.cpp test_DiscreteFunctionDescriptorP0Vector.cpp test_DiscreteFunctionType.cpp test_DoWhileProcessor.cpp + test_EigenvalueSolver.cpp test_EmbeddedData.cpp test_EscapedString.cpp test_Exceptions.cpp diff --git a/tests/mpi_test_main.cpp b/tests/mpi_test_main.cpp index 68736ebe3c04ff1c171be3a96dcaca4fea58c17b..51a01b0cfa99b36995b8849fc1fdb94360d971ad 100644 --- a/tests/mpi_test_main.cpp +++ b/tests/mpi_test_main.cpp @@ -2,13 +2,13 @@ #include <Kokkos_Core.hpp> -#include <algebra/PETScWrapper.hpp> #include <language/utils/OperatorRepository.hpp> #include <mesh/DiamondDualConnectivityManager.hpp> #include <mesh/DiamondDualMeshManager.hpp> #include <mesh/MeshDataManager.hpp> #include <mesh/SynchronizerManager.hpp> #include <utils/Messenger.hpp> +#include <utils/PETScWrapper.hpp> #include <utils/pugs_config.hpp> #include <MeshDataBaseForTests.hpp> diff --git a/tests/test_ASTNodeDataType.cpp b/tests/test_ASTNodeDataType.cpp index 9316c27dbcf09f0f114500a6c04ca3dad1c8806b..023ec9963bcd66286c9ffcfcadbc4fb3b2abdbee 100644 --- a/tests/test_ASTNodeDataType.cpp +++ b/tests/test_ASTNodeDataType.cpp @@ -213,8 +213,8 @@ TEST_CASE("ASTNodeDataType", "[language]") SECTION("good node") { REQUIRE(getMatrixDataType(*type_node) == ASTNodeDataType::build<ASTNodeDataType::matrix_t>(3, 3)); - REQUIRE(getMatrixDataType(*type_node).nbRows() == 3); - REQUIRE(getMatrixDataType(*type_node).nbColumns() == 3); + REQUIRE(getMatrixDataType(*type_node).numberOfRows() == 3); + REQUIRE(getMatrixDataType(*type_node).numberOfColumns() == 3); } SECTION("bad node type") diff --git a/tests/test_CRSMatrix.cpp b/tests/test_CRSMatrix.cpp index 0f748fb37971fefb53cdc881d7452607c6dd3e6e..d6bfdaba966c0c36a5245af457954a6f53a0919d 100644 --- a/tests/test_CRSMatrix.cpp +++ b/tests/test_CRSMatrix.cpp @@ -26,6 +26,7 @@ TEST_CASE("CRSMatrix", "[algebra]") CRSMatrix<int, uint8_t> A{S}; REQUIRE(A.numberOfRows() == S.numberOfRows()); + REQUIRE(A.numberOfColumns() == S.numberOfColumns()); } SECTION("matrix vector product (simple)") @@ -43,7 +44,7 @@ TEST_CASE("CRSMatrix", "[algebra]") CRSMatrix<int, uint8_t> A{S}; - Vector<int> x{A.numberOfRows()}; + Vector<int> x{A.numberOfColumns()}; x = 0; x[0] = 1; @@ -117,7 +118,7 @@ TEST_CASE("CRSMatrix", "[algebra]") CRSMatrix<int, uint8_t> A{S}; - Vector<int> x{A.numberOfRows()}; + Vector<int> x{A.numberOfColumns()}; x[0] = 1; x[1] = 2; x[2] = 3; diff --git a/tests/test_DenseMatrix.cpp b/tests/test_DenseMatrix.cpp new file mode 100644 index 0000000000000000000000000000000000000000..6e2470fa0f325fab1e17eb0f51c2ad34a61c318b --- /dev/null +++ b/tests/test_DenseMatrix.cpp @@ -0,0 +1,344 @@ +#include <catch2/catch_test_macros.hpp> +#include <catch2/matchers/catch_matchers_all.hpp> + +#include <utils/PugsAssert.hpp> + +#include <algebra/DenseMatrix.hpp> +#include <algebra/Vector.hpp> + +// Instantiate to ensure full coverage is performed +template class DenseMatrix<int>; + +// clazy:excludeall=non-pod-global-static + +TEST_CASE("DenseMatrix", "[algebra]") +{ + SECTION("size") + { + DenseMatrix<int> A{2, 3}; + REQUIRE(A.numberOfRows() == 2); + REQUIRE(A.numberOfColumns() == 3); + } + + SECTION("write access") + { + DenseMatrix<int> A{2, 3}; + A(0, 0) = 0; + A(0, 1) = 1; + A(0, 2) = 2; + A(1, 0) = 3; + A(1, 1) = 4; + A(1, 2) = 5; + REQUIRE(A(0, 0) == 0); + REQUIRE(A(0, 1) == 1); + REQUIRE(A(0, 2) == 2); + REQUIRE(A(1, 0) == 3); + REQUIRE(A(1, 1) == 4); + REQUIRE(A(1, 2) == 5); + DenseMatrix<const int> const_A = A; + REQUIRE(const_A(0, 0) == 0); + REQUIRE(const_A(0, 1) == 1); + REQUIRE(const_A(0, 2) == 2); + REQUIRE(const_A(1, 0) == 3); + REQUIRE(const_A(1, 1) == 4); + REQUIRE(const_A(1, 2) == 5); + } + + SECTION("fill") + { + DenseMatrix<int> A{2, 3}; + A.fill(2); + REQUIRE(A(0, 0) == 2); + REQUIRE(A(0, 1) == 2); + REQUIRE(A(0, 2) == 2); + REQUIRE(A(1, 0) == 2); + REQUIRE(A(1, 1) == 2); + REQUIRE(A(1, 2) == 2); + } + + SECTION("copy constructor (shallow)") + { + DenseMatrix<int> A{2, 3}; + A(0, 0) = 0; + A(0, 1) = 1; + A(0, 2) = 2; + A(1, 0) = 3; + A(1, 1) = 4; + A(1, 2) = 5; + + const DenseMatrix<int> B = A; + REQUIRE(B(0, 0) == 0); + REQUIRE(B(0, 1) == 1); + REQUIRE(B(0, 2) == 2); + REQUIRE(B(1, 0) == 3); + REQUIRE(B(1, 1) == 4); + REQUIRE(B(1, 2) == 5); + } + + SECTION("copy (deep)") + { + DenseMatrix<int> A{2, 3}; + A(0, 0) = 0; + A(0, 1) = 1; + A(0, 2) = 2; + A(1, 0) = 3; + A(1, 1) = 4; + A(1, 2) = 5; + + const DenseMatrix<int> B = copy(A); + + A(0, 0) = 10; + A(0, 1) = 11; + A(0, 2) = 12; + A(1, 0) = 13; + A(1, 1) = 14; + A(1, 2) = 15; + + REQUIRE(B(0, 0) == 0); + REQUIRE(B(0, 1) == 1); + REQUIRE(B(0, 2) == 2); + REQUIRE(B(1, 0) == 3); + REQUIRE(B(1, 1) == 4); + REQUIRE(B(1, 2) == 5); + + REQUIRE(A(0, 0) == 10); + REQUIRE(A(0, 1) == 11); + REQUIRE(A(0, 2) == 12); + REQUIRE(A(1, 0) == 13); + REQUIRE(A(1, 1) == 14); + REQUIRE(A(1, 2) == 15); + } + + SECTION("self scalar multiplication") + { + DenseMatrix<int> A{2, 3}; + A(0, 0) = 0; + A(0, 1) = 1; + A(0, 2) = 2; + A(1, 0) = 3; + A(1, 1) = 4; + A(1, 2) = 5; + + A *= 2; + REQUIRE(A(0, 0) == 0); + REQUIRE(A(0, 1) == 2); + REQUIRE(A(0, 2) == 4); + REQUIRE(A(1, 0) == 6); + REQUIRE(A(1, 1) == 8); + REQUIRE(A(1, 2) == 10); + } + + SECTION("left scalar multiplication") + { + DenseMatrix<int> A{2, 3}; + A(0, 0) = 0; + A(0, 1) = 1; + A(0, 2) = 2; + A(1, 0) = 3; + A(1, 1) = 4; + A(1, 2) = 5; + + const DenseMatrix<int> B = 2 * A; + + REQUIRE(B(0, 0) == 0); + REQUIRE(B(0, 1) == 2); + REQUIRE(B(0, 2) == 4); + REQUIRE(B(1, 0) == 6); + REQUIRE(B(1, 1) == 8); + REQUIRE(B(1, 2) == 10); + } + + SECTION("product matrix vector") + { + DenseMatrix<int> A{2, 3}; + A(0, 0) = 6; + A(0, 1) = 1; + A(0, 2) = 2; + A(1, 0) = 3; + A(1, 1) = 4; + A(1, 2) = 5; + + Vector<int> x{3}; + x[0] = 7; + x[1] = 3; + x[2] = 4; + + Vector y = A * x; + REQUIRE(y[0] == 53); + REQUIRE(y[1] == 53); + } + + SECTION("self scalar division") + { + DenseMatrix<int> A{2, 3}; + A(0, 0) = 0; + A(0, 1) = 2; + A(0, 2) = 4; + A(1, 0) = 6; + A(1, 1) = 8; + A(1, 2) = 10; + + A /= 2; + + REQUIRE(A(0, 0) == 0); + REQUIRE(A(0, 1) == 1); + REQUIRE(A(0, 2) == 2); + REQUIRE(A(1, 0) == 3); + REQUIRE(A(1, 1) == 4); + REQUIRE(A(1, 2) == 5); + } + + SECTION("self minus") + { + DenseMatrix<int> A{2, 3}; + A(0, 0) = 0; + A(0, 1) = 1; + A(0, 2) = 2; + A(1, 0) = 3; + A(1, 1) = 4; + A(1, 2) = 5; + + DenseMatrix<int> B{2, 3}; + B(0, 0) = 5; + B(0, 1) = 6; + B(0, 2) = 4; + B(1, 0) = 2; + B(1, 1) = 1; + B(1, 2) = 3; + + A -= B; + + REQUIRE(A(0, 0) == -5); + REQUIRE(A(0, 1) == -5); + REQUIRE(A(0, 2) == -2); + REQUIRE(A(1, 0) == 1); + REQUIRE(A(1, 1) == 3); + REQUIRE(A(1, 2) == 2); + } + + SECTION("self sum") + { + DenseMatrix<int> A{2, 3}; + A(0, 0) = 0; + A(0, 1) = 1; + A(0, 2) = 2; + A(1, 0) = 3; + A(1, 1) = 4; + A(1, 2) = 5; + + DenseMatrix<int> B{2, 3}; + B(0, 0) = 5; + B(0, 1) = 6; + B(0, 2) = 4; + B(1, 0) = 2; + B(1, 1) = 1; + B(1, 2) = 3; + + A += B; + + REQUIRE(A(0, 0) == 5); + REQUIRE(A(0, 1) == 7); + REQUIRE(A(0, 2) == 6); + REQUIRE(A(1, 0) == 5); + REQUIRE(A(1, 1) == 5); + REQUIRE(A(1, 2) == 8); + } + + SECTION("sum") + { + DenseMatrix<int> A{2, 3}; + A(0, 0) = 6; + A(0, 1) = 5; + A(0, 2) = 4; + A(1, 0) = 3; + A(1, 1) = 2; + A(1, 2) = 1; + + DenseMatrix<int> B{2, 3}; + B(0, 0) = 0; + B(0, 1) = 1; + B(0, 2) = 2; + B(1, 0) = 3; + B(1, 1) = 4; + B(1, 2) = 5; + + DenseMatrix C = A + B; + REQUIRE(C(0, 0) == 6); + REQUIRE(C(0, 1) == 6); + REQUIRE(C(0, 2) == 6); + REQUIRE(C(1, 0) == 6); + REQUIRE(C(1, 1) == 6); + REQUIRE(C(1, 2) == 6); + } + + SECTION("difference") + { + DenseMatrix<int> A{2, 3}; + A(0, 0) = 6; + A(0, 1) = 5; + A(0, 2) = 4; + A(1, 0) = 3; + A(1, 1) = 2; + A(1, 2) = 1; + + DenseMatrix<int> B{2, 3}; + B(0, 0) = 0; + B(0, 1) = 1; + B(0, 2) = 2; + B(1, 0) = 3; + B(1, 1) = 4; + B(1, 2) = 5; + + DenseMatrix C = A - B; + REQUIRE(C(0, 0) == 6); + REQUIRE(C(0, 1) == 4); + REQUIRE(C(0, 2) == 2); + REQUIRE(C(1, 0) == 0); + REQUIRE(C(1, 1) == -2); + REQUIRE(C(1, 2) == -4); + } + + SECTION("transpose") + { + DenseMatrix<int> A{2, 3}; + A(0, 0) = 0; + A(0, 1) = 1; + A(0, 2) = 2; + A(1, 0) = 3; + A(1, 1) = 4; + A(1, 2) = 5; + + DenseMatrix B = transpose(A); + REQUIRE(B(0, 0) == 0); + REQUIRE(B(0, 1) == 3); + REQUIRE(B(1, 0) == 1); + REQUIRE(B(1, 1) == 4); + REQUIRE(B(2, 0) == 2); + REQUIRE(B(2, 1) == 5); + } + + SECTION("product matrix vector") + { + DenseMatrix<int> A{2, 3}; + A(0, 0) = 1; + A(0, 1) = 2; + A(0, 2) = 3; + A(1, 0) = 4; + A(1, 1) = 5; + A(1, 2) = 6; + + DenseMatrix<int> B{3, 2}; + B(0, 0) = 2; + B(0, 1) = 8; + B(1, 0) = 4; + B(1, 1) = 9; + B(2, 0) = 6; + B(2, 1) = 10; + + DenseMatrix C = A * B; + REQUIRE(C(0, 0) == 28); + REQUIRE(C(0, 1) == 56); + REQUIRE(C(1, 0) == 64); + REQUIRE(C(1, 1) == 137); + } +} diff --git a/tests/test_EigenvalueSolver.cpp b/tests/test_EigenvalueSolver.cpp new file mode 100644 index 0000000000000000000000000000000000000000..e779bce5600e32cf26b0fde7339693f8da69bcb1 --- /dev/null +++ b/tests/test_EigenvalueSolver.cpp @@ -0,0 +1,118 @@ +#include <catch2/catch_test_macros.hpp> +#include <catch2/matchers/catch_matchers_all.hpp> + +#include <algebra/CRSMatrix.hpp> +#include <algebra/DenseMatrix.hpp> +#include <algebra/EigenvalueSolver.hpp> +#include <algebra/SparseMatrixDescriptor.hpp> + +#include <utils/pugs_config.hpp> + +// clazy:excludeall=non-pod-global-static + +TEST_CASE("EigenvalueSolver", "[algebra]") +{ + SECTION("Sparse Matrices") + { + SECTION("symmetric system") + { + SparseMatrixDescriptor S{3}; + S(0, 0) = 3; + S(0, 1) = 2; + S(0, 2) = 4; + + S(1, 0) = 2; + S(1, 1) = 0; + S(1, 2) = 2; + + S(2, 0) = 4; + S(2, 1) = 2; + S(2, 2) = 3; + + CRSMatrix A{S}; + + SECTION("eigenvalues") + { + Array<double> eigenvalues; + +#ifdef PUGS_HAS_SLEPC + EigenvalueSolver{}.computeForSymmetricMatrix(A, eigenvalues); + REQUIRE(eigenvalues[0] == Catch::Approx(-1)); + REQUIRE(eigenvalues[1] == Catch::Approx(-1)); + REQUIRE(eigenvalues[2] == Catch::Approx(8)); +#else // PUGS_HAS_SLEPC + REQUIRE_THROWS_WITH(EigenvalueSolver{}.computeForSymmetricMatrix(A, eigenvalues), + "not implemented yet: SLEPc is required to solve eigenvalue problems"); +#endif // PUGS_HAS_SLEPC + } + + SECTION("eigenvalues and eigenvectors") + { + Array<double> eigenvalue_list; + std::vector<Vector<double>> eigenvector_list; + +#ifdef PUGS_HAS_SLEPC + EigenvalueSolver{}.computeForSymmetricMatrix(A, eigenvalue_list, eigenvector_list); + + REQUIRE(eigenvalue_list[0] == Catch::Approx(-1)); + REQUIRE(eigenvalue_list[1] == Catch::Approx(-1)); + REQUIRE(eigenvalue_list[2] == Catch::Approx(8)); + + DenseMatrix<double> P{3}; + DenseMatrix<double> PT{3}; + DenseMatrix<double> D{3}; + D = zero; + + for (size_t i = 0; i < 3; ++i) { + for (size_t j = 0; j < 3; ++j) { + P(i, j) = eigenvector_list[j][i]; + PT(i, j) = eigenvector_list[i][j]; + } + D(i, i) = eigenvalue_list[i]; + } + + DenseMatrix PDPT = P * D * PT; + for (size_t i = 0; i < 3; ++i) { + for (size_t j = 0; j < 3; ++j) { + REQUIRE(PDPT(i, j) - S(i, j) == Catch::Approx(0).margin(1E-13)); + } + } +#else // PUGS_HAS_SLEPC + REQUIRE_THROWS_WITH(EigenvalueSolver{}.computeForSymmetricMatrix(A, eigenvalue_list, eigenvector_list), + "not implemented yet: SLEPc is required to solve eigenvalue problems"); +#endif // PUGS_HAS_SLEPC + } + + SECTION("eigenvalues and passage matrix") + { + Array<double> eigenvalue_list; + DenseMatrix<double> P{}; + +#ifdef PUGS_HAS_SLEPC + EigenvalueSolver{}.computeForSymmetricMatrix(A, eigenvalue_list, P); + + REQUIRE(eigenvalue_list[0] == Catch::Approx(-1)); + REQUIRE(eigenvalue_list[1] == Catch::Approx(-1)); + REQUIRE(eigenvalue_list[2] == Catch::Approx(8)); + + DenseMatrix<double> D{3}; + D = zero; + for (size_t i = 0; i < 3; ++i) { + D(i, i) = eigenvalue_list[i]; + } + DenseMatrix PT = transpose(P); + + DenseMatrix PDPT = P * D * PT; + for (size_t i = 0; i < 3; ++i) { + for (size_t j = 0; j < 3; ++j) { + REQUIRE(PDPT(i, j) - S(i, j) == Catch::Approx(0).margin(1E-13)); + } + } +#else // PUGS_HAS_SLEPC + REQUIRE_THROWS_WITH(EigenvalueSolver{}.computeForSymmetricMatrix(A, eigenvalue_list, P), + "not implemented yet: SLEPc is required to solve eigenvalue problems"); +#endif // PUGS_HAS_SLEPC + } + } + } +} diff --git a/tests/test_InterpolateItemArray.cpp b/tests/test_InterpolateItemArray.cpp index cf65afdf42c803b15900be7fc96fdad23e9c230f..5e0bbd962bd9c24165956b9e17a223f80a187055 100644 --- a/tests/test_InterpolateItemArray.cpp +++ b/tests/test_InterpolateItemArray.cpp @@ -241,8 +241,8 @@ let scalar_non_linear_3d: R^3 -> R, x -> 2 * exp(x[0]) * sin(x[1]) * x[2] + 3; SECTION("interpolate on items list") { auto same_cell_value = [](auto interpolated, auto reference) -> bool { - for (size_t i = 0; i < interpolated.nbRows(); ++i) { - for (size_t j = 0; j < interpolated.nbColumns(); ++j) { + for (size_t i = 0; i < interpolated.numberOfRows(); ++i) { + for (size_t j = 0; j < interpolated.numberOfColumns(); ++j) { if (interpolated[i][j] != reference[i][j]) { return false; } diff --git a/tests/test_ItemArray.cpp b/tests/test_ItemArray.cpp index 2a76275324c4922ed0bad182ebcfa106c3d9b462..17337200786737dcc7b98c75eb18021cfd62a82d 100644 --- a/tests/test_ItemArray.cpp +++ b/tests/test_ItemArray.cpp @@ -120,8 +120,8 @@ TEST_CASE("ItemArray", "[mesh]") Table<size_t> table{cell_array.numberOfItems(), cell_array.sizeOfArrays()}; { size_t k = 0; - for (size_t i = 0; i < table.nbRows(); ++i) { - for (size_t j = 0; j < table.nbColumns(); ++j) { + for (size_t i = 0; i < table.numberOfRows(); ++i) { + for (size_t j = 0; j < table.numberOfColumns(); ++j) { table(i, j) = k++; } } diff --git a/tests/test_LinearSolver.cpp b/tests/test_LinearSolver.cpp index 5504ae390fd259eaa700a911b158bf6a6e46a625..1219c48e62d28a749383e115aef8b6e51a17e5ec 100644 --- a/tests/test_LinearSolver.cpp +++ b/tests/test_LinearSolver.cpp @@ -141,77 +141,52 @@ TEST_CASE("LinearSolver", "[algebra]") #endif // PUGS_HAS_PETSC } - SECTION("check linear solvers") + SECTION("Sparse Matrices") { - SECTION("symmetric system") + SECTION("check linear solvers") { - SparseMatrixDescriptor S{5}; - S(0, 0) = 2; - S(0, 1) = -1; + SECTION("symmetric system") + { + SparseMatrixDescriptor S{5}; + S(0, 0) = 2; + S(0, 1) = -1; - S(1, 0) = -1; - S(1, 1) = 2; - S(1, 2) = -1; + S(1, 0) = -1; + S(1, 1) = 2; + S(1, 2) = -1; - S(2, 1) = -1; - S(2, 2) = 2; - S(2, 3) = -1; + S(2, 1) = -1; + S(2, 2) = 2; + S(2, 3) = -1; - S(3, 2) = -1; - S(3, 3) = 2; - S(3, 4) = -1; + S(3, 2) = -1; + S(3, 3) = 2; + S(3, 4) = -1; - S(4, 3) = -1; - S(4, 4) = 2; + S(4, 3) = -1; + S(4, 4) = 2; - CRSMatrix A{S}; + CRSMatrix A{S}; - Vector<const double> x_exact = [] { - Vector<double> y{5}; - y[0] = 1; - y[1] = 3; - y[2] = 2; - y[3] = 4; - y[4] = 5; - return y; - }(); + Vector<const double> x_exact = [] { + Vector<double> y{5}; + y[0] = 1; + y[1] = 3; + y[2] = 2; + y[3] = 4; + y[4] = 5; + return y; + }(); - Vector<double> b = A * x_exact; + Vector<double> b = A * x_exact; - SECTION("builtin") - { - SECTION("CG no preconditioner") + SECTION("builtin") { - LinearSolverOptions options; - options.library() = LSLibrary::builtin; - options.method() = LSMethod::cg; - options.precond() = LSPrecond::none; - - Vector<double> x{5}; - x = 0; - - LinearSolver solver{options}; - - solver.solveLocalSystem(A, x, b); - Vector error = x - x_exact; - REQUIRE(std::sqrt(dot(error, error)) < 1E-10 * std::sqrt(dot(x_exact, x_exact))); - } - } - - SECTION("PETSc") - { -#ifdef PUGS_HAS_PETSC - - SECTION("CG") - { - LinearSolverOptions options; - options.library() = LSLibrary::petsc; - options.method() = LSMethod::cg; - options.precond() = LSPrecond::none; - options.verbose() = true; - SECTION("CG no preconditioner") { + LinearSolverOptions options; + options.library() = LSLibrary::builtin; + options.method() = LSMethod::cg; options.precond() = LSPrecond::none; Vector<double> x{5}; @@ -223,24 +198,83 @@ TEST_CASE("LinearSolver", "[algebra]") Vector error = x - x_exact; REQUIRE(std::sqrt(dot(error, error)) < 1E-10 * std::sqrt(dot(x_exact, x_exact))); } + } - SECTION("CG Diagonal") + SECTION("PETSc") + { +#ifdef PUGS_HAS_PETSC + + SECTION("CG") { - options.precond() = LSPrecond::diagonal; + LinearSolverOptions options; + options.library() = LSLibrary::petsc; + options.method() = LSMethod::cg; + options.precond() = LSPrecond::none; + options.verbose() = true; - Vector<double> x{5}; - x = 0; + SECTION("CG no preconditioner") + { + options.precond() = LSPrecond::none; - LinearSolver solver{options}; + Vector<double> x{5}; + x = 0; - solver.solveLocalSystem(A, x, b); - Vector error = x - x_exact; - REQUIRE(std::sqrt(dot(error, error)) < 1E-10 * std::sqrt(dot(x_exact, x_exact))); + LinearSolver solver{options}; + + solver.solveLocalSystem(A, x, b); + Vector error = x - x_exact; + REQUIRE(std::sqrt(dot(error, error)) < 1E-10 * std::sqrt(dot(x_exact, x_exact))); + } + + SECTION("CG Diagonal") + { + options.precond() = LSPrecond::diagonal; + + Vector<double> x{5}; + x = 0; + + LinearSolver solver{options}; + + solver.solveLocalSystem(A, x, b); + Vector error = x - x_exact; + REQUIRE(std::sqrt(dot(error, error)) < 1E-10 * std::sqrt(dot(x_exact, x_exact))); + } + + SECTION("CG ICholeski") + { + options.precond() = LSPrecond::incomplete_choleski; + + Vector<double> x{5}; + x = 0; + + LinearSolver solver{options}; + + solver.solveLocalSystem(A, x, b); + Vector error = x - x_exact; + REQUIRE(std::sqrt(dot(error, error)) < 1E-10 * std::sqrt(dot(x_exact, x_exact))); + } + + SECTION("CG AMG") + { + options.precond() = LSPrecond::amg; + + Vector<double> x{5}; + x = 0; + + LinearSolver solver{options}; + + solver.solveLocalSystem(A, x, b); + Vector error = x - x_exact; + REQUIRE(std::sqrt(dot(error, error)) < 1E-10 * std::sqrt(dot(x_exact, x_exact))); + } } - SECTION("CG ICholeski") + SECTION("Choleski") { - options.precond() = LSPrecond::incomplete_choleski; + LinearSolverOptions options; + options.library() = LSLibrary::petsc; + options.method() = LSMethod::choleski; + options.precond() = LSPrecond::none; Vector<double> x{5}; x = 0; @@ -252,9 +286,63 @@ TEST_CASE("LinearSolver", "[algebra]") REQUIRE(std::sqrt(dot(error, error)) < 1E-10 * std::sqrt(dot(x_exact, x_exact))); } - SECTION("CG AMG") +#else // PUGS_HAS_PETSC + SECTION("PETSc not linked") { - options.precond() = LSPrecond::amg; + LinearSolverOptions options; + options.library() = LSLibrary::petsc; + options.method() = LSMethod::cg; + options.precond() = LSPrecond::none; + + REQUIRE_THROWS_WITH(LinearSolver{options}, "error: PETSc is not linked to pugs. Cannot use it!"); + } +#endif // PUGS_HAS_PETSC + } + } + + SECTION("none symmetric system") + { + SparseMatrixDescriptor S{5}; + S(0, 0) = 2; + S(0, 1) = -1; + + S(1, 0) = -0.2; + S(1, 1) = 2; + S(1, 2) = -1; + + S(2, 1) = -1; + S(2, 2) = 4; + S(2, 3) = -2; + + S(3, 2) = -1; + S(3, 3) = 2; + S(3, 4) = -0.1; + + S(4, 3) = 1; + S(4, 4) = 3; + + CRSMatrix A{S}; + + Vector<const double> x_exact = [] { + Vector<double> y{5}; + y[0] = 1; + y[1] = 3; + y[2] = 2; + y[3] = 4; + y[4] = 5; + return y; + }(); + + Vector<double> b = A * x_exact; + + SECTION("builtin") + { + SECTION("BICGStab no preconditioner") + { + LinearSolverOptions options; + options.library() = LSLibrary::builtin; + options.method() = LSMethod::bicgstab; + options.precond() = LSPrecond::none; Vector<double> x{5}; x = 0; @@ -267,121 +355,153 @@ TEST_CASE("LinearSolver", "[algebra]") } } - SECTION("Choleski") + SECTION("PETSc") { - LinearSolverOptions options; - options.library() = LSLibrary::petsc; - options.method() = LSMethod::choleski; - options.precond() = LSPrecond::none; +#ifdef PUGS_HAS_PETSC - Vector<double> x{5}; - x = 0; + SECTION("BICGStab") + { + LinearSolverOptions options; + options.library() = LSLibrary::petsc; + options.method() = LSMethod::bicgstab; + options.precond() = LSPrecond::none; + options.verbose() = true; - LinearSolver solver{options}; + SECTION("BICGStab no preconditioner") + { + options.precond() = LSPrecond::none; - solver.solveLocalSystem(A, x, b); - Vector error = x - x_exact; - REQUIRE(std::sqrt(dot(error, error)) < 1E-10 * std::sqrt(dot(x_exact, x_exact))); - } + Vector<double> x{5}; + x = 0; -#else // PUGS_HAS_PETSC - SECTION("PETSc not linked") - { - LinearSolverOptions options; - options.library() = LSLibrary::petsc; - options.method() = LSMethod::cg; - options.precond() = LSPrecond::none; + LinearSolver solver{options}; - REQUIRE_THROWS_WITH(LinearSolver{options}, "error: PETSc is not linked to pugs. Cannot use it!"); - } -#endif // PUGS_HAS_PETSC - } - } + solver.solveLocalSystem(A, x, b); + Vector error = x - x_exact; + REQUIRE(std::sqrt(dot(error, error)) < 1E-10 * std::sqrt(dot(x_exact, x_exact))); + } - SECTION("none symmetric system") - { - SparseMatrixDescriptor S{5}; - S(0, 0) = 2; - S(0, 1) = -1; + SECTION("BICGStab Diagonal") + { + options.precond() = LSPrecond::diagonal; + + Vector<double> x{5}; + x = 0; - S(1, 0) = -0.2; - S(1, 1) = 2; - S(1, 2) = -1; + LinearSolver solver{options}; - S(2, 1) = -1; - S(2, 2) = 4; - S(2, 3) = -2; + solver.solveLocalSystem(A, x, b); + Vector error = x - x_exact; + REQUIRE(std::sqrt(dot(error, error)) < 1E-10 * std::sqrt(dot(x_exact, x_exact))); + } - S(3, 2) = -1; - S(3, 3) = 2; - S(3, 4) = -0.1; + SECTION("BICGStab ILU") + { + options.precond() = LSPrecond::incomplete_LU; - S(4, 3) = 1; - S(4, 4) = 3; + Vector<double> x{5}; + x = 0; - CRSMatrix A{S}; + LinearSolver solver{options}; - Vector<const double> x_exact = [] { - Vector<double> y{5}; - y[0] = 1; - y[1] = 3; - y[2] = 2; - y[3] = 4; - y[4] = 5; - return y; - }(); + solver.solveLocalSystem(A, x, b); + Vector error = x - x_exact; + REQUIRE(std::sqrt(dot(error, error)) < 1E-10 * std::sqrt(dot(x_exact, x_exact))); + } + } - Vector<double> b = A * x_exact; + SECTION("BICGStab2") + { + LinearSolverOptions options; + options.library() = LSLibrary::petsc; + options.method() = LSMethod::bicgstab2; + options.precond() = LSPrecond::none; - SECTION("builtin") - { - SECTION("BICGStab no preconditioner") - { - LinearSolverOptions options; - options.library() = LSLibrary::builtin; - options.method() = LSMethod::bicgstab; - options.precond() = LSPrecond::none; + SECTION("BICGStab2 no preconditioner") + { + options.precond() = LSPrecond::none; - Vector<double> x{5}; - x = 0; + Vector<double> x{5}; + x = 0; - LinearSolver solver{options}; + LinearSolver solver{options}; - solver.solveLocalSystem(A, x, b); - Vector error = x - x_exact; - REQUIRE(std::sqrt(dot(error, error)) < 1E-10 * std::sqrt(dot(x_exact, x_exact))); - } - } + solver.solveLocalSystem(A, x, b); + Vector error = x - x_exact; + REQUIRE(std::sqrt(dot(error, error)) < 1E-10 * std::sqrt(dot(x_exact, x_exact))); + } - SECTION("PETSc") - { -#ifdef PUGS_HAS_PETSC + SECTION("BICGStab2 Diagonal") + { + options.precond() = LSPrecond::diagonal; - SECTION("BICGStab") - { - LinearSolverOptions options; - options.library() = LSLibrary::petsc; - options.method() = LSMethod::bicgstab; - options.precond() = LSPrecond::none; - options.verbose() = true; + Vector<double> x{5}; + x = 0; - SECTION("BICGStab no preconditioner") + LinearSolver solver{options}; + + solver.solveLocalSystem(A, x, b); + Vector error = x - x_exact; + REQUIRE(std::sqrt(dot(error, error)) < 1E-10 * std::sqrt(dot(x_exact, x_exact))); + } + } + + SECTION("GMRES") { + LinearSolverOptions options; + options.library() = LSLibrary::petsc; + options.method() = LSMethod::gmres; options.precond() = LSPrecond::none; - Vector<double> x{5}; - x = 0; + SECTION("GMRES no preconditioner") + { + options.precond() = LSPrecond::none; - LinearSolver solver{options}; + Vector<double> x{5}; + x = 0; - solver.solveLocalSystem(A, x, b); - Vector error = x - x_exact; - REQUIRE(std::sqrt(dot(error, error)) < 1E-10 * std::sqrt(dot(x_exact, x_exact))); + LinearSolver solver{options}; + + solver.solveLocalSystem(A, x, b); + Vector error = x - x_exact; + REQUIRE(std::sqrt(dot(error, error)) < 1E-10 * std::sqrt(dot(x_exact, x_exact))); + } + + SECTION("GMRES Diagonal") + { + options.precond() = LSPrecond::diagonal; + + Vector<double> x{5}; + x = 0; + + LinearSolver solver{options}; + + solver.solveLocalSystem(A, x, b); + Vector error = x - x_exact; + REQUIRE(std::sqrt(dot(error, error)) < 1E-10 * std::sqrt(dot(x_exact, x_exact))); + } + + SECTION("GMRES ILU") + { + options.precond() = LSPrecond::incomplete_LU; + + Vector<double> x{5}; + x = 0; + + LinearSolver solver{options}; + + solver.solveLocalSystem(A, x, b); + Vector error = x - x_exact; + REQUIRE(std::sqrt(dot(error, error)) < 1E-10 * std::sqrt(dot(x_exact, x_exact))); + } } - SECTION("BICGStab Diagonal") + SECTION("LU") { - options.precond() = LSPrecond::diagonal; + LinearSolverOptions options; + options.library() = LSLibrary::petsc; + options.method() = LSMethod::lu; + options.precond() = LSPrecond::none; Vector<double> x{5}; x = 0; @@ -393,9 +513,69 @@ TEST_CASE("LinearSolver", "[algebra]") REQUIRE(std::sqrt(dot(error, error)) < 1E-10 * std::sqrt(dot(x_exact, x_exact))); } - SECTION("BICGStab ILU") +#else // PUGS_HAS_PETSC + SECTION("PETSc not linked") + { + LinearSolverOptions options; + options.library() = LSLibrary::petsc; + options.method() = LSMethod::cg; + options.precond() = LSPrecond::none; + + REQUIRE_THROWS_WITH(LinearSolver{options}, "error: PETSc is not linked to pugs. Cannot use it!"); + } +#endif // PUGS_HAS_PETSC + } + } + } + } + + SECTION("Dense Matrices") + { + SECTION("check linear solvers") + { + SECTION("symmetric system") + { + DenseMatrix<double> A{5}; + A = zero; + + A(0, 0) = 2; + A(0, 1) = -1; + + A(1, 0) = -1; + A(1, 1) = 2; + A(1, 2) = -1; + + A(2, 1) = -1; + A(2, 2) = 2; + A(2, 3) = -1; + + A(3, 2) = -1; + A(3, 3) = 2; + A(3, 4) = -1; + + A(4, 3) = -1; + A(4, 4) = 2; + + Vector<const double> x_exact = [] { + Vector<double> y{5}; + y[0] = 1; + y[1] = 3; + y[2] = 2; + y[3] = 4; + y[4] = 5; + return y; + }(); + + Vector<double> b = A * x_exact; + + SECTION("builtin") + { + SECTION("CG no preconditioner") { - options.precond() = LSPrecond::incomplete_LU; + LinearSolverOptions options; + options.library() = LSLibrary::builtin; + options.method() = LSMethod::cg; + options.precond() = LSPrecond::none; Vector<double> x{5}; x = 0; @@ -408,15 +588,80 @@ TEST_CASE("LinearSolver", "[algebra]") } } - SECTION("BICGStab2") + SECTION("PETSc") { - LinearSolverOptions options; - options.library() = LSLibrary::petsc; - options.method() = LSMethod::bicgstab2; - options.precond() = LSPrecond::none; +#ifdef PUGS_HAS_PETSC - SECTION("BICGStab2 no preconditioner") + SECTION("CG") { + LinearSolverOptions options; + options.library() = LSLibrary::petsc; + options.method() = LSMethod::cg; + options.precond() = LSPrecond::none; + options.verbose() = true; + + SECTION("CG no preconditioner") + { + options.precond() = LSPrecond::none; + + Vector<double> x{5}; + x = 0; + + LinearSolver solver{options}; + + solver.solveLocalSystem(A, x, b); + Vector error = x - x_exact; + REQUIRE(std::sqrt(dot(error, error)) < 1E-10 * std::sqrt(dot(x_exact, x_exact))); + } + + SECTION("CG Diagonal") + { + options.precond() = LSPrecond::diagonal; + + Vector<double> x{5}; + x = 0; + + LinearSolver solver{options}; + + solver.solveLocalSystem(A, x, b); + Vector error = x - x_exact; + REQUIRE(std::sqrt(dot(error, error)) < 1E-10 * std::sqrt(dot(x_exact, x_exact))); + } + + SECTION("CG ICholeski") + { + options.precond() = LSPrecond::incomplete_choleski; + + Vector<double> x{5}; + x = 0; + + LinearSolver solver{options}; + + solver.solveLocalSystem(A, x, b); + Vector error = x - x_exact; + REQUIRE(std::sqrt(dot(error, error)) < 1E-10 * std::sqrt(dot(x_exact, x_exact))); + } + + SECTION("CG AMG") + { + options.precond() = LSPrecond::amg; + + Vector<double> x{5}; + x = 0; + + LinearSolver solver{options}; + + solver.solveLocalSystem(A, x, b); + Vector error = x - x_exact; + REQUIRE(std::sqrt(dot(error, error)) < 1E-10 * std::sqrt(dot(x_exact, x_exact))); + } + } + + SECTION("Choleski") + { + LinearSolverOptions options; + options.library() = LSLibrary::petsc; + options.method() = LSMethod::choleski; options.precond() = LSPrecond::none; Vector<double> x{5}; @@ -429,9 +674,63 @@ TEST_CASE("LinearSolver", "[algebra]") REQUIRE(std::sqrt(dot(error, error)) < 1E-10 * std::sqrt(dot(x_exact, x_exact))); } - SECTION("BICGStab2 Diagonal") +#else // PUGS_HAS_PETSC + SECTION("PETSc not linked") + { + LinearSolverOptions options; + options.library() = LSLibrary::petsc; + options.method() = LSMethod::cg; + options.precond() = LSPrecond::none; + + REQUIRE_THROWS_WITH(LinearSolver{options}, "error: PETSc is not linked to pugs. Cannot use it!"); + } +#endif // PUGS_HAS_PETSC + } + } + + SECTION("none symmetric system") + { + DenseMatrix<double> A{5}; + A = zero; + + A(0, 0) = 2; + A(0, 1) = -1; + + A(1, 0) = -0.2; + A(1, 1) = 2; + A(1, 2) = -1; + + A(2, 1) = -1; + A(2, 2) = 4; + A(2, 3) = -2; + + A(3, 2) = -1; + A(3, 3) = 2; + A(3, 4) = -0.1; + + A(4, 3) = 1; + A(4, 4) = 3; + + Vector<const double> x_exact = [] { + Vector<double> y{5}; + y[0] = 1; + y[1] = 3; + y[2] = 2; + y[3] = 4; + y[4] = 5; + return y; + }(); + + Vector<double> b = A * x_exact; + + SECTION("builtin") + { + SECTION("BICGStab no preconditioner") { - options.precond() = LSPrecond::diagonal; + LinearSolverOptions options; + options.library() = LSLibrary::builtin; + options.method() = LSMethod::bicgstab; + options.precond() = LSPrecond::none; Vector<double> x{5}; x = 0; @@ -444,44 +743,153 @@ TEST_CASE("LinearSolver", "[algebra]") } } - SECTION("GMRES") + SECTION("PETSc") { - LinearSolverOptions options; - options.library() = LSLibrary::petsc; - options.method() = LSMethod::gmres; - options.precond() = LSPrecond::none; +#ifdef PUGS_HAS_PETSC - SECTION("GMRES no preconditioner") + SECTION("BICGStab") { + LinearSolverOptions options; + options.library() = LSLibrary::petsc; + options.method() = LSMethod::bicgstab; options.precond() = LSPrecond::none; + options.verbose() = true; - Vector<double> x{5}; - x = 0; + SECTION("BICGStab no preconditioner") + { + options.precond() = LSPrecond::none; - LinearSolver solver{options}; + Vector<double> x{5}; + x = 0; - solver.solveLocalSystem(A, x, b); - Vector error = x - x_exact; - REQUIRE(std::sqrt(dot(error, error)) < 1E-10 * std::sqrt(dot(x_exact, x_exact))); + LinearSolver solver{options}; + + solver.solveLocalSystem(A, x, b); + Vector error = x - x_exact; + REQUIRE(std::sqrt(dot(error, error)) < 1E-10 * std::sqrt(dot(x_exact, x_exact))); + } + + SECTION("BICGStab Diagonal") + { + options.precond() = LSPrecond::diagonal; + + Vector<double> x{5}; + x = 0; + + LinearSolver solver{options}; + + solver.solveLocalSystem(A, x, b); + Vector error = x - x_exact; + REQUIRE(std::sqrt(dot(error, error)) < 1E-10 * std::sqrt(dot(x_exact, x_exact))); + } + + SECTION("BICGStab ILU") + { + options.precond() = LSPrecond::incomplete_LU; + + Vector<double> x{5}; + x = 0; + + LinearSolver solver{options}; + + solver.solveLocalSystem(A, x, b); + Vector error = x - x_exact; + REQUIRE(std::sqrt(dot(error, error)) < 1E-10 * std::sqrt(dot(x_exact, x_exact))); + } } - SECTION("GMRES Diagonal") + SECTION("BICGStab2") { - options.precond() = LSPrecond::diagonal; + LinearSolverOptions options; + options.library() = LSLibrary::petsc; + options.method() = LSMethod::bicgstab2; + options.precond() = LSPrecond::none; - Vector<double> x{5}; - x = 0; + SECTION("BICGStab2 no preconditioner") + { + options.precond() = LSPrecond::none; - LinearSolver solver{options}; + Vector<double> x{5}; + x = 0; - solver.solveLocalSystem(A, x, b); - Vector error = x - x_exact; - REQUIRE(std::sqrt(dot(error, error)) < 1E-10 * std::sqrt(dot(x_exact, x_exact))); + LinearSolver solver{options}; + + solver.solveLocalSystem(A, x, b); + Vector error = x - x_exact; + REQUIRE(std::sqrt(dot(error, error)) < 1E-10 * std::sqrt(dot(x_exact, x_exact))); + } + + SECTION("BICGStab2 Diagonal") + { + options.precond() = LSPrecond::diagonal; + + Vector<double> x{5}; + x = 0; + + LinearSolver solver{options}; + + solver.solveLocalSystem(A, x, b); + Vector error = x - x_exact; + REQUIRE(std::sqrt(dot(error, error)) < 1E-10 * std::sqrt(dot(x_exact, x_exact))); + } + } + + SECTION("GMRES") + { + LinearSolverOptions options; + options.library() = LSLibrary::petsc; + options.method() = LSMethod::gmres; + options.precond() = LSPrecond::none; + + SECTION("GMRES no preconditioner") + { + options.precond() = LSPrecond::none; + + Vector<double> x{5}; + x = 0; + + LinearSolver solver{options}; + + solver.solveLocalSystem(A, x, b); + Vector error = x - x_exact; + REQUIRE(std::sqrt(dot(error, error)) < 1E-10 * std::sqrt(dot(x_exact, x_exact))); + } + + SECTION("GMRES Diagonal") + { + options.precond() = LSPrecond::diagonal; + + Vector<double> x{5}; + x = 0; + + LinearSolver solver{options}; + + solver.solveLocalSystem(A, x, b); + Vector error = x - x_exact; + REQUIRE(std::sqrt(dot(error, error)) < 1E-10 * std::sqrt(dot(x_exact, x_exact))); + } + + SECTION("GMRES ILU") + { + options.precond() = LSPrecond::incomplete_LU; + + Vector<double> x{5}; + x = 0; + + LinearSolver solver{options}; + + solver.solveLocalSystem(A, x, b); + Vector error = x - x_exact; + REQUIRE(std::sqrt(dot(error, error)) < 1E-10 * std::sqrt(dot(x_exact, x_exact))); + } } - SECTION("GMRES ILU") + SECTION("LU") { - options.precond() = LSPrecond::incomplete_LU; + LinearSolverOptions options; + options.library() = LSLibrary::petsc; + options.method() = LSMethod::lu; + options.precond() = LSPrecond::none; Vector<double> x{5}; x = 0; @@ -492,36 +900,19 @@ TEST_CASE("LinearSolver", "[algebra]") Vector error = x - x_exact; REQUIRE(std::sqrt(dot(error, error)) < 1E-10 * std::sqrt(dot(x_exact, x_exact))); } - } - - SECTION("LU") - { - LinearSolverOptions options; - options.library() = LSLibrary::petsc; - options.method() = LSMethod::lu; - options.precond() = LSPrecond::none; - - Vector<double> x{5}; - x = 0; - - LinearSolver solver{options}; - - solver.solveLocalSystem(A, x, b); - Vector error = x - x_exact; - REQUIRE(std::sqrt(dot(error, error)) < 1E-10 * std::sqrt(dot(x_exact, x_exact))); - } #else // PUGS_HAS_PETSC - SECTION("PETSc not linked") - { - LinearSolverOptions options; - options.library() = LSLibrary::petsc; - options.method() = LSMethod::cg; - options.precond() = LSPrecond::none; + SECTION("PETSc not linked") + { + LinearSolverOptions options; + options.library() = LSLibrary::petsc; + options.method() = LSMethod::cg; + options.precond() = LSPrecond::none; - REQUIRE_THROWS_WITH(LinearSolver{options}, "error: PETSc is not linked to pugs. Cannot use it!"); - } + REQUIRE_THROWS_WITH(LinearSolver{options}, "error: PETSc is not linked to pugs. Cannot use it!"); + } #endif // PUGS_HAS_PETSC + } } } } diff --git a/tests/test_PugsUtils.cpp b/tests/test_PugsUtils.cpp index f32e8014a76561a07aa3d70756641e0a9231238d..4632ae825bf9089834f90ba082d7481746885d28 100644 --- a/tests/test_PugsUtils.cpp +++ b/tests/test_PugsUtils.cpp @@ -50,6 +50,7 @@ TEST_CASE("PugsUtils", "[utils]") os << "kokkos: " << rang::style::bold << BuildInfo::kokkosDevices() << rang::style::reset << '\n'; os << "MPI: " << rang::style::bold << BuildInfo::mpiLibrary() << rang::style::reset << '\n'; os << "PETSc: " << rang::style::bold << BuildInfo::petscLibrary() << rang::style::reset << '\n'; + os << "SLEPc: " << rang::style::bold << BuildInfo::slepcLibrary() << rang::style::reset << '\n'; os << "-------------------------------------------------------"; return os.str(); diff --git a/tests/test_SparseMatrixDescriptor.cpp b/tests/test_SparseMatrixDescriptor.cpp index 8bd0c37c5cc9e294462fc92a759980dbc7a4a336..77bc890f7c4a53ea170de08bebb83de9b7e0fbed 100644 --- a/tests/test_SparseMatrixDescriptor.cpp +++ b/tests/test_SparseMatrixDescriptor.cpp @@ -51,10 +51,11 @@ TEST_CASE("SparseMatrixDescriptor", "[algebra]") } } - SECTION("number of columns") + SECTION("matrix size") { SparseMatrixDescriptor<int, uint8_t> S{5}; REQUIRE(S.numberOfRows() == 5); + REQUIRE(S.numberOfColumns() == 5); } SECTION("location operators") diff --git a/tests/test_SubItemArrayPerItem.cpp b/tests/test_SubItemArrayPerItem.cpp index b03353f0ebbff8fe3d6c5634020d1ea739668f57..d1cb315046b5450e975b7ced5e795103bb6453ad 100644 --- a/tests/test_SubItemArrayPerItem.cpp +++ b/tests/test_SubItemArrayPerItem.cpp @@ -80,7 +80,7 @@ TEST_CASE("SubItemArrayPerItem", "[mesh]") for (CellId cell_id = 0; cell_id < connectivity.numberOfCells(); ++cell_id) { is_correct &= (cell_to_node_matrix[cell_id].size() == node_array_per_cell.numberOfSubArrays(cell_id)) and - (node_array_per_cell.itemTable(cell_id).nbRows() == node_array_per_cell.numberOfSubArrays(cell_id)); + (node_array_per_cell.itemTable(cell_id).numberOfRows() == node_array_per_cell.numberOfSubArrays(cell_id)); } REQUIRE(is_correct); } @@ -89,8 +89,8 @@ TEST_CASE("SubItemArrayPerItem", "[mesh]") { bool is_correct = true; for (CellId cell_id = 0; cell_id < connectivity.numberOfCells(); ++cell_id) { - is_correct &= - (const_node_array_per_cell.itemTable(cell_id).nbRows() == node_array_per_cell.numberOfSubArrays(cell_id)); + is_correct &= (const_node_array_per_cell.itemTable(cell_id).numberOfRows() == + node_array_per_cell.numberOfSubArrays(cell_id)); } REQUIRE(is_correct); } @@ -576,7 +576,7 @@ TEST_CASE("SubItemArrayPerItem", "[mesh]") size_t i = 0; for (CellId cell_id = 0; cell_id < connectivity.numberOfCells(); ++cell_id) { const auto& cell_table = const_edge_arrays_per_cell.itemTable(cell_id); - for (size_t i_edge = 0; i_edge < cell_table.nbRows(); ++i_edge) { + for (size_t i_edge = 0; i_edge < cell_table.numberOfRows(); ++i_edge) { const auto& array = cell_table[i_edge]; for (size_t l = 0; l < array.size(); ++l, ++i) { is_same &= (array[l] == i * i + 1); @@ -640,7 +640,7 @@ TEST_CASE("SubItemArrayPerItem", "[mesh]") size_t i = 0; for (FaceId face_id = 0; face_id < connectivity.numberOfFaces(); ++face_id) { const auto& face_table = const_cell_arrays_per_face.itemTable(face_id); - for (size_t i_cell = 0; i_cell < face_table.nbRows(); ++i_cell) { + for (size_t i_cell = 0; i_cell < face_table.numberOfRows(); ++i_cell) { const auto& array = face_table[i_cell]; for (size_t l = 0; l < array.size(); ++l, ++i) { is_same &= (array[l] == 3 * i + 1); @@ -703,7 +703,7 @@ TEST_CASE("SubItemArrayPerItem", "[mesh]") size_t i = 0; for (NodeId node_id = 0; node_id < connectivity.numberOfNodes(); ++node_id) { const auto& node_table = const_face_arrays_per_node.itemTable(node_id); - for (size_t i_face = 0; i_face < node_table.nbRows(); ++i_face) { + for (size_t i_face = 0; i_face < node_table.numberOfRows(); ++i_face) { const auto& array = node_table[i_face]; for (size_t l = 0; l < array.size(); ++l, ++i) { is_same &= (array[l] == 3 + i * i); @@ -900,9 +900,9 @@ TEST_CASE("SubItemArrayPerItem", "[mesh]") if (connectivity.numberOfFaces() > 0) { FaceId face_id = 0; const auto& face_table = cell_array_per_face.itemTable(face_id); - REQUIRE_THROWS_AS(cell_array_per_face(face_id, face_table.nbRows()), AssertError); - REQUIRE_THROWS_AS(face_table[face_table.nbRows()], AssertError); - REQUIRE_THROWS_AS(cell_array_per_face.itemTable(face_id)[face_table.nbRows()], AssertError); + REQUIRE_THROWS_AS(cell_array_per_face(face_id, face_table.numberOfRows()), AssertError); + REQUIRE_THROWS_AS(face_table[face_table.numberOfRows()], AssertError); + REQUIRE_THROWS_AS(cell_array_per_face.itemTable(face_id)[face_table.numberOfRows()], AssertError); REQUIRE_THROWS_AS(cell_array_per_face.itemTable(face_id)[0][cell_array_per_face.sizeOfArrays()], AssertError); REQUIRE_THROWS_AS(cell_array_per_face.itemTable(face_id)[0][cell_array_per_face.sizeOfArrays()] = 2, AssertError); @@ -916,9 +916,9 @@ TEST_CASE("SubItemArrayPerItem", "[mesh]") if (connectivity.numberOfNodes() > 0) { NodeId node_id = 0; const auto& node_table = face_array_per_node.itemTable(node_id); - REQUIRE_THROWS_AS(face_array_per_node(node_id, node_table.nbRows()), AssertError); - REQUIRE_THROWS_AS(node_table[node_table.nbRows()], AssertError); - REQUIRE_THROWS_AS(face_array_per_node.itemTable(node_id)[node_table.nbRows()], AssertError); + REQUIRE_THROWS_AS(face_array_per_node(node_id, node_table.numberOfRows()), AssertError); + REQUIRE_THROWS_AS(node_table[node_table.numberOfRows()], AssertError); + REQUIRE_THROWS_AS(face_array_per_node.itemTable(node_id)[node_table.numberOfRows()], AssertError); REQUIRE_THROWS_AS(face_array_per_node.itemTable(node_id)[0][face_array_per_node.sizeOfArrays()], AssertError); REQUIRE_THROWS_AS(face_array_per_node.itemTable(node_id)[0][face_array_per_node.sizeOfArrays()] = 2, AssertError); @@ -932,9 +932,9 @@ TEST_CASE("SubItemArrayPerItem", "[mesh]") if (connectivity.numberOfCells() > 0) { CellId cell_id = 0; const auto& cell_table = edge_array_per_cell.itemTable(cell_id); - REQUIRE_THROWS_AS(edge_array_per_cell(cell_id, cell_table.nbRows()), AssertError); - REQUIRE_THROWS_AS(cell_table[cell_table.nbRows()], AssertError); - REQUIRE_THROWS_AS(edge_array_per_cell.itemTable(cell_id)[cell_table.nbRows()], AssertError); + REQUIRE_THROWS_AS(edge_array_per_cell(cell_id, cell_table.numberOfRows()), AssertError); + REQUIRE_THROWS_AS(cell_table[cell_table.numberOfRows()], AssertError); + REQUIRE_THROWS_AS(edge_array_per_cell.itemTable(cell_id)[cell_table.numberOfRows()], AssertError); REQUIRE_THROWS_AS(edge_array_per_cell.itemTable(cell_id)[0][edge_array_per_cell.sizeOfArrays()], AssertError); REQUIRE_THROWS_AS(edge_array_per_cell.itemTable(cell_id)[0][edge_array_per_cell.sizeOfArrays()] == 2, AssertError); @@ -948,9 +948,9 @@ TEST_CASE("SubItemArrayPerItem", "[mesh]") if (connectivity.numberOfEdges() > 0) { EdgeId edge_id = 0; const auto& edge_table = node_array_per_edge.itemTable(edge_id); - REQUIRE_THROWS_AS(node_array_per_edge(edge_id, edge_table.nbRows()), AssertError); - REQUIRE_THROWS_AS(edge_table[edge_table.nbRows()], AssertError); - REQUIRE_THROWS_AS(node_array_per_edge.itemTable(edge_id)[edge_table.nbRows()], AssertError); + REQUIRE_THROWS_AS(node_array_per_edge(edge_id, edge_table.numberOfRows()), AssertError); + REQUIRE_THROWS_AS(edge_table[edge_table.numberOfRows()], AssertError); + REQUIRE_THROWS_AS(node_array_per_edge.itemTable(edge_id)[edge_table.numberOfRows()], AssertError); REQUIRE_THROWS_AS(node_array_per_edge.itemTable(edge_id)[0][node_array_per_edge.sizeOfArrays()], AssertError); REQUIRE_THROWS_AS(node_array_per_edge.itemTable(edge_id)[0][node_array_per_edge.sizeOfArrays()] = 2, AssertError); diff --git a/tests/test_Table.cpp b/tests/test_Table.cpp index 3521476c375dba6a31e57dd2f55ad09430026d8a..5e738867a592c3f06a9fe8ac7bd958dbcf390e4e 100644 --- a/tests/test_Table.cpp +++ b/tests/test_Table.cpp @@ -13,15 +13,15 @@ template class Table<int>; TEST_CASE("Table", "[utils]") { Table<int> a(4, 3); - REQUIRE(a.nbRows() == 4); - REQUIRE(a.nbColumns() == 3); + REQUIRE(a.numberOfRows() == 4); + REQUIRE(a.numberOfColumns() == 3); REQUIRE(a[0].size() == 3); REQUIRE(a[1].size() == 3); REQUIRE(a[2].size() == 3); REQUIRE(a[3].size() == 3); - for (size_t i = 0; i < a.nbRows(); ++i) { - for (size_t j = 0; j < a.nbColumns(); ++j) { + for (size_t i = 0; i < a.numberOfRows(); ++i) { + for (size_t j = 0; j < a.numberOfColumns(); ++j) { a(i, j) = 2 * i + j; } } @@ -138,7 +138,7 @@ TEST_CASE("Table", "[utils]") (c(0, 1) == 2) and (c(1, 1) == 2) and (c(2, 1) == 2) and (c(3, 1) == 2) and // (c(0, 2) == 2) and (c(1, 2) == 2) and (c(2, 2) == 2) and (c(3, 2) == 2))); - Table<int> d{a.nbRows(), a.nbColumns()}; + Table<int> d{a.numberOfRows(), a.numberOfColumns()}; copy_to(a, d); REQUIRE(((a(0, 0) == 0) and (a(1, 0) == 2) and (a(2, 0) == 4) and (a(3, 0) == 6) and // @@ -168,10 +168,10 @@ TEST_CASE("Table", "[utils]") Table table = encapsulate(kokkos_view); - REQUIRE(table.nbRows() == kokkos_view.extent(0)); - REQUIRE(table.nbColumns() == kokkos_view.extent(1)); - for (size_t i = 0; i < table.nbRows(); ++i) { - for (size_t j = 0; j < table.nbColumns(); ++j) { + REQUIRE(table.numberOfRows() == kokkos_view.extent(0)); + REQUIRE(table.numberOfColumns() == kokkos_view.extent(1)); + for (size_t i = 0; i < table.numberOfRows(); ++i) { + for (size_t j = 0; j < table.numberOfColumns(); ++j) { REQUIRE(&table(i, j) == &kokkos_view(i, j)); } } @@ -189,13 +189,13 @@ TEST_CASE("Table", "[utils]") { SECTION("wrong row number") { - Table<int> b{2 * a.nbRows(), a.nbColumns()}; + Table<int> b{2 * a.numberOfRows(), a.numberOfColumns()}; REQUIRE_THROWS_AS(copy_to(a, b), AssertError); } SECTION("wrong column number") { - Table<int> c{a.nbRows(), 2 * a.nbColumns()}; + Table<int> c{a.numberOfRows(), 2 * a.numberOfColumns()}; REQUIRE_THROWS_AS(copy_to(a, c), AssertError); } } diff --git a/tests/test_TinyMatrix.cpp b/tests/test_TinyMatrix.cpp index 158512dbf67e80751c362c67385b454a1bd1e5c9..464e78448192f3dacc248d6c7fde8c63338449bb 100644 --- a/tests/test_TinyMatrix.cpp +++ b/tests/test_TinyMatrix.cpp @@ -206,16 +206,16 @@ TEST_CASE("TinyMatrix", "[algebra]") SECTION("checking for sizes") { - REQUIRE(TinyMatrix<1>{}.nbRows() == 1); - REQUIRE(TinyMatrix<1>{}.nbColumns() == 1); + REQUIRE(TinyMatrix<1>{}.numberOfRows() == 1); + REQUIRE(TinyMatrix<1>{}.numberOfColumns() == 1); REQUIRE(TinyMatrix<1>{}.dimension() == 1); - REQUIRE(TinyMatrix<2>{}.nbRows() == 2); - REQUIRE(TinyMatrix<2>{}.nbColumns() == 2); + REQUIRE(TinyMatrix<2>{}.numberOfRows() == 2); + REQUIRE(TinyMatrix<2>{}.numberOfColumns() == 2); REQUIRE(TinyMatrix<2>{}.dimension() == 4); - REQUIRE(TinyMatrix<3>{}.nbRows() == 3); - REQUIRE(TinyMatrix<3>{}.nbColumns() == 3); + REQUIRE(TinyMatrix<3>{}.numberOfRows() == 3); + REQUIRE(TinyMatrix<3>{}.numberOfColumns() == 3); REQUIRE(TinyMatrix<3>{}.dimension() == 9); } diff --git a/tests/test_main.cpp b/tests/test_main.cpp index ee1d0769b152c5b483214e0edc7d9313775cf416..b5316614d10c21cbe13bb5540cc0a13d7e4b4b24 100644 --- a/tests/test_main.cpp +++ b/tests/test_main.cpp @@ -2,13 +2,14 @@ #include <Kokkos_Core.hpp> -#include <algebra/PETScWrapper.hpp> #include <language/utils/OperatorRepository.hpp> #include <mesh/DiamondDualConnectivityManager.hpp> #include <mesh/DiamondDualMeshManager.hpp> #include <mesh/MeshDataManager.hpp> #include <mesh/SynchronizerManager.hpp> #include <utils/Messenger.hpp> +#include <utils/PETScWrapper.hpp> +#include <utils/SLEPcWrapper.hpp> #include <MeshDataBaseForTests.hpp> @@ -19,6 +20,7 @@ main(int argc, char* argv[]) Kokkos::initialize({4, -1, -1, true}); PETScWrapper::initialize(argc, argv); + SLEPcWrapper::initialize(argc, argv); Catch::Session session; int result = session.applyCommandLine(argc, argv); @@ -53,6 +55,7 @@ main(int argc, char* argv[]) } } + SLEPcWrapper::finalize(); PETScWrapper::finalize(); Kokkos::finalize();