diff --git a/CMakeLists.txt b/CMakeLists.txt index f3f5c8478558efc0a3116f3dfc8fddbb1e0d176a..3f62e1b88ed577fa73bbfddc6ff2263c8925ec0e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -447,7 +447,7 @@ if("${CMAKE_BUILD_TYPE}" STREQUAL "Coverage") COMMAND ${FASTCOV} -q --gcov "${GCOV_BIN}" --include "${PUGS_SOURCE_DIR}/src" - --exclude "${PUGS_SOURCE_DIR}/src/main.cpp" "${PUGS_SOURCE_DIR}/src/utils/BacktraceManager.*" + --exclude "${PUGS_SOURCE_DIR}/src/main.cpp" "${PUGS_SOURCE_DIR}/src/utils/BacktraceManager.*" "${PUGS_SOURCE_DIR}/src/utils/FPEManager.*" "${PUGS_SOURCE_DIR}/src/utils/SignalManager.*" --lcov -o coverage.info -n COMMAND ${LCOV} --gcov "${GCOV_BIN}" --list coverage.info diff --git a/src/algebra/TinyMatrix.hpp b/src/algebra/TinyMatrix.hpp index a4499baa4677f09bc7edd3c1e3c59d41c9b3557d..0635f1b32b12d29bbbaa85273d6c49d92aba12ca 100644 --- a/src/algebra/TinyMatrix.hpp +++ b/src/algebra/TinyMatrix.hpp @@ -11,7 +11,7 @@ #include <iostream> template <size_t N, typename T = double> -class TinyMatrix +class [[nodiscard]] TinyMatrix { public: using data_type = T; @@ -21,15 +21,13 @@ class TinyMatrix static_assert((N > 0), "TinyMatrix size must be strictly positive"); PUGS_FORCEINLINE - constexpr size_t - _index(size_t i, size_t j) const noexcept // LCOV_EXCL_LINE (due to forced inline) + constexpr size_t _index(size_t i, size_t j) const noexcept // LCOV_EXCL_LINE (due to forced inline) { return i * N + j; } template <typename... Args> - PUGS_FORCEINLINE constexpr void - _unpackVariadicInput(const T& t, Args&&... args) noexcept + PUGS_FORCEINLINE constexpr void _unpackVariadicInput(const T& t, Args&&... args) noexcept { m_values[N * N - 1 - sizeof...(args)] = t; if constexpr (sizeof...(args) > 0) { @@ -39,8 +37,7 @@ class TinyMatrix public: PUGS_INLINE - constexpr TinyMatrix - operator-() const + constexpr TinyMatrix operator-() const { TinyMatrix opposed; for (size_t i = 0; i < N * N; ++i) { @@ -50,23 +47,20 @@ class TinyMatrix } PUGS_INLINE - constexpr friend TinyMatrix - operator*(const T& t, const TinyMatrix& A) + constexpr friend TinyMatrix operator*(const T& t, const TinyMatrix& A) { TinyMatrix B = A; return B *= t; } PUGS_INLINE - constexpr friend TinyMatrix - operator*(const T& t, TinyMatrix&& A) + constexpr friend TinyMatrix operator*(const T& t, TinyMatrix&& A) { return std::move(A *= t); } PUGS_INLINE - constexpr TinyMatrix& - operator*=(const T& t) + constexpr TinyMatrix& operator*=(const T& t) { for (size_t i = 0; i < N * N; ++i) { m_values[i] *= t; @@ -75,8 +69,7 @@ class TinyMatrix } PUGS_INLINE - constexpr TinyMatrix - operator*(const TinyMatrix& B) const + constexpr TinyMatrix operator*(const TinyMatrix& B) const { const TinyMatrix& A = *this; TinyMatrix AB; @@ -93,8 +86,7 @@ class TinyMatrix } PUGS_INLINE - constexpr TinyVector<N, T> - operator*(const TinyVector<N, T>& x) const + constexpr TinyVector<N, T> operator*(const TinyVector<N, T>& x) const { const TinyMatrix& A = *this; TinyVector<N, T> Ax; @@ -109,8 +101,7 @@ class TinyMatrix } PUGS_INLINE - constexpr friend std::ostream& - operator<<(std::ostream& os, const TinyMatrix& A) + constexpr friend std::ostream& operator<<(std::ostream& os, const TinyMatrix& A) { if constexpr (N == 1) { os << A(0, 0); @@ -129,8 +120,7 @@ class TinyMatrix } PUGS_INLINE - constexpr bool - operator==(const TinyMatrix& A) const + constexpr bool operator==(const TinyMatrix& A) const { for (size_t i = 0; i < N * N; ++i) { if (m_values[i] != A.m_values[i]) @@ -140,15 +130,13 @@ class TinyMatrix } PUGS_INLINE - constexpr bool - operator!=(const TinyMatrix& A) const + constexpr bool operator!=(const TinyMatrix& A) const { return not this->operator==(A); } PUGS_INLINE - constexpr TinyMatrix - operator+(const TinyMatrix& A) const + constexpr TinyMatrix operator+(const TinyMatrix& A) const { TinyMatrix sum; for (size_t i = 0; i < N * N; ++i) { @@ -158,8 +146,7 @@ class TinyMatrix } PUGS_INLINE - constexpr TinyMatrix - operator+(TinyMatrix&& A) const + constexpr TinyMatrix operator+(TinyMatrix&& A) const { for (size_t i = 0; i < N * N; ++i) { A.m_values[i] += m_values[i]; @@ -168,8 +155,7 @@ class TinyMatrix } PUGS_INLINE - constexpr TinyMatrix - operator-(const TinyMatrix& A) const + constexpr TinyMatrix operator-(const TinyMatrix& A) const { TinyMatrix difference; for (size_t i = 0; i < N * N; ++i) { @@ -179,8 +165,7 @@ class TinyMatrix } PUGS_INLINE - constexpr TinyMatrix - operator-(TinyMatrix&& A) const + constexpr TinyMatrix operator-(TinyMatrix&& A) const { for (size_t i = 0; i < N * N; ++i) { A.m_values[i] = m_values[i] - A.m_values[i]; @@ -189,8 +174,7 @@ class TinyMatrix } PUGS_INLINE - constexpr TinyMatrix& - operator+=(const TinyMatrix& A) + constexpr TinyMatrix& operator+=(const TinyMatrix& A) { for (size_t i = 0; i < N * N; ++i) { m_values[i] += A.m_values[i]; @@ -199,8 +183,7 @@ class TinyMatrix } PUGS_INLINE - constexpr void - operator+=(const volatile TinyMatrix& A) volatile + constexpr void operator+=(const volatile TinyMatrix& A) volatile { for (size_t i = 0; i < N * N; ++i) { m_values[i] += A.m_values[i]; @@ -208,8 +191,7 @@ class TinyMatrix } PUGS_INLINE - constexpr TinyMatrix& - operator-=(const TinyMatrix& A) + constexpr TinyMatrix& operator-=(const TinyMatrix& A) { for (size_t i = 0; i < N * N; ++i) { m_values[i] -= A.m_values[i]; @@ -218,16 +200,14 @@ class TinyMatrix } PUGS_INLINE - constexpr T& - operator()(size_t i, size_t j) noexcept(NO_ASSERT) + constexpr T& operator()(size_t i, size_t j) noexcept(NO_ASSERT) { Assert((i < N) and (j < N)); return m_values[_index(i, j)]; } PUGS_INLINE - constexpr const T& - operator()(size_t i, size_t j) const noexcept(NO_ASSERT) + constexpr const T& operator()(size_t i, size_t j) const noexcept(NO_ASSERT) { Assert((i < N) and (j < N)); return m_values[_index(i, j)]; @@ -299,7 +279,7 @@ class TinyMatrix constexpr TinyMatrix(const TinyMatrix&) noexcept = default; PUGS_INLINE - TinyMatrix(TinyMatrix&& A) noexcept = default; + TinyMatrix(TinyMatrix && A) noexcept = default; PUGS_INLINE ~TinyMatrix() = default; diff --git a/src/algebra/TinyVector.hpp b/src/algebra/TinyVector.hpp index 07690a826ef13040e42baca75daac425fa199333..3f3c10920f5ae75c6b37a0761393cad19a77786b 100644 --- a/src/algebra/TinyVector.hpp +++ b/src/algebra/TinyVector.hpp @@ -11,7 +11,7 @@ #include <cmath> template <size_t N, typename T = double> -class TinyVector +class [[nodiscard]] TinyVector { public: inline static constexpr size_t Dimension = N; @@ -22,8 +22,7 @@ class TinyVector static_assert((N > 0), "TinyVector size must be strictly positive"); template <typename... Args> - PUGS_FORCEINLINE constexpr void - _unpackVariadicInput(const T& t, Args&&... args) noexcept + PUGS_FORCEINLINE constexpr void _unpackVariadicInput(const T& t, Args&&... args) noexcept { m_values[N - 1 - sizeof...(args)] = t; if constexpr (sizeof...(args) > 0) { @@ -33,8 +32,7 @@ class TinyVector public: PUGS_INLINE - constexpr TinyVector - operator-() const + constexpr TinyVector operator-() const { TinyVector opposed; for (size_t i = 0; i < N; ++i) { @@ -44,15 +42,13 @@ class TinyVector } PUGS_INLINE - constexpr size_t - dimension() const + constexpr size_t dimension() const { return N; } PUGS_INLINE - constexpr bool - operator==(const TinyVector& v) const + constexpr bool operator==(const TinyVector& v) const { for (size_t i = 0; i < N; ++i) { if (m_values[i] != v.m_values[i]) @@ -62,8 +58,7 @@ class TinyVector } PUGS_INLINE - constexpr bool - operator!=(const TinyVector& v) const + constexpr bool operator!=(const TinyVector& v) const { return not this->operator==(v); } @@ -79,8 +74,7 @@ class TinyVector } PUGS_INLINE - constexpr TinyVector& - operator*=(const T& t) + constexpr TinyVector& operator*=(const T& t) { for (size_t i = 0; i < N; ++i) { m_values[i] *= t; @@ -103,8 +97,7 @@ class TinyVector } PUGS_INLINE - constexpr friend std::ostream& - operator<<(std::ostream& os, const TinyVector& v) + constexpr friend std::ostream& operator<<(std::ostream& os, const TinyVector& v) { os << '(' << v.m_values[0]; for (size_t i = 1; i < N; ++i) { @@ -115,8 +108,7 @@ class TinyVector } PUGS_INLINE - constexpr TinyVector - operator+(const TinyVector& v) const + constexpr TinyVector operator+(const TinyVector& v) const { TinyVector sum; for (size_t i = 0; i < N; ++i) { @@ -126,8 +118,7 @@ class TinyVector } PUGS_INLINE - constexpr TinyVector - operator+(TinyVector&& v) const + constexpr TinyVector operator+(TinyVector&& v) const { for (size_t i = 0; i < N; ++i) { v.m_values[i] += m_values[i]; @@ -136,8 +127,7 @@ class TinyVector } PUGS_INLINE - constexpr TinyVector - operator-(const TinyVector& v) const + constexpr TinyVector operator-(const TinyVector& v) const { TinyVector difference; for (size_t i = 0; i < N; ++i) { @@ -147,8 +137,7 @@ class TinyVector } PUGS_INLINE - constexpr TinyVector - operator-(TinyVector&& v) const + constexpr TinyVector operator-(TinyVector&& v) const { for (size_t i = 0; i < N; ++i) { v.m_values[i] = m_values[i] - v.m_values[i]; @@ -157,8 +146,7 @@ class TinyVector } PUGS_INLINE - constexpr TinyVector& - operator+=(const TinyVector& v) + constexpr TinyVector& operator+=(const TinyVector& v) { for (size_t i = 0; i < N; ++i) { m_values[i] += v.m_values[i]; @@ -167,8 +155,7 @@ class TinyVector } PUGS_INLINE - constexpr void - operator+=(const volatile TinyVector& v) volatile + constexpr void operator+=(const volatile TinyVector& v) volatile { for (size_t i = 0; i < N; ++i) { m_values[i] += v.m_values[i]; @@ -176,8 +163,7 @@ class TinyVector } PUGS_INLINE - constexpr TinyVector& - operator-=(const TinyVector& v) + constexpr TinyVector& operator-=(const TinyVector& v) { for (size_t i = 0; i < N; ++i) { m_values[i] -= v.m_values[i]; @@ -241,7 +227,7 @@ class TinyVector constexpr TinyVector(const TinyVector&) noexcept = default; PUGS_INLINE - constexpr TinyVector(TinyVector&& v) noexcept = default; + constexpr TinyVector(TinyVector && v) noexcept = default; PUGS_INLINE ~TinyVector() noexcept = default; diff --git a/src/language/PEGGrammar.hpp b/src/language/PEGGrammar.hpp index fb3b1d74abf6ba0d33113ec95996c6a270edb77d..553a2797c8cf227ab88d4b977f9f727b671a4c7a 100644 --- a/src/language/PEGGrammar.hpp +++ b/src/language/PEGGrammar.hpp @@ -55,11 +55,13 @@ struct character : if_must_else< one< '\\' >, escaped_c, ascii::any> {}; struct open_parent : seq< one< '(' >, ignored > {}; struct close_parent : seq< one< ')' >, ignored > {}; -struct literal : if_must< one< '"' >, until< one< '"' >, character > > {}; +struct literal : star< minus<character, one < '"' > > >{}; + +struct quoted_literal : if_must< one< '"' >, seq< literal, one< '"' > > >{}; struct import_kw : TAO_PEGTL_KEYWORD("import") {}; -struct LITERAL : seq< literal, ignored >{}; +struct LITERAL : seq< quoted_literal, ignored >{}; struct REAL : seq< real, ignored >{}; diff --git a/src/language/utils/ASTPrinter.cpp b/src/language/utils/ASTPrinter.cpp index 9bf18bdcf88f6399283750dac9ab0b38d8bf0400..8cc88b530997eb3cc9cccb176c3812c41dceea1f 100644 --- a/src/language/utils/ASTPrinter.cpp +++ b/src/language/utils/ASTPrinter.cpp @@ -14,9 +14,10 @@ ASTPrinter::_print(std::ostream& os, const ASTNode& node) const } os << rang::fg::reset; - if (node.is_type<language::name>() or node.is_type<language::literal>() or node.is_type<language::integer>() or - node.is_type<language::real>()) { + if (node.is_type<language::name>() or node.is_type<language::integer>() or node.is_type<language::real>()) { os << ':' << rang::fgB::green << node.string() << rang::fg::reset; + } else if (node.is_type<language::literal>()) { + os << ":\"" << rang::fgB::green << node.string() << rang::fg::reset << '"'; } if (m_info & static_cast<InfoBaseType>(Info::data_type)) { diff --git a/src/mesh/Connectivity.hpp b/src/mesh/Connectivity.hpp index 3bf5cd4201c574749e5b6a67a2b6c4d667bd88f1..f8e4dafdb7a46473434645c26e46ee1c00f86117 100644 --- a/src/mesh/Connectivity.hpp +++ b/src/mesh/Connectivity.hpp @@ -12,7 +12,7 @@ #include <mesh/RefId.hpp> #include <mesh/RefItemList.hpp> #include <mesh/SubItemValuePerItem.hpp> -#include <utils/CSRGraph.hpp> +#include <utils/CRSGraph.hpp> #include <utils/Exceptions.hpp> #include <utils/PugsAssert.hpp> #include <utils/PugsMacros.hpp> @@ -542,36 +542,20 @@ class Connectivity final : public IConnectivity } PUGS_INLINE - CSRGraph + CRSGraph cellToCellGraph() const { std::vector<std::set<int>> cell_cells(this->numberOfCells()); - if constexpr (true) { - const auto& face_to_cell_matrix = this->faceToCellMatrix(); + const auto& face_to_cell_matrix = this->faceToCellMatrix(); - for (FaceId l = 0; l < this->numberOfFaces(); ++l) { - const auto& face_to_cell = face_to_cell_matrix[l]; - if (face_to_cell.size() > 1) { - const CellId cell_0 = face_to_cell[0]; - const CellId cell_1 = face_to_cell[1]; + for (FaceId l = 0; l < this->numberOfFaces(); ++l) { + const auto& face_to_cell = face_to_cell_matrix[l]; + if (face_to_cell.size() > 1) { + const CellId cell_0 = face_to_cell[0]; + const CellId cell_1 = face_to_cell[1]; - cell_cells[cell_0].insert(cell_1); - cell_cells[cell_1].insert(cell_0); - } - } - } else { - const auto& node_to_cell_matrix = this->nodeToCellMatrix(); - - for (NodeId l = 0; l < this->numberOfNodes(); ++l) { - const auto& node_to_cell = node_to_cell_matrix[l]; - for (size_t i_cell = 0; i_cell < node_to_cell.size(); ++i_cell) { - const CellId cell_0 = node_to_cell[i_cell]; - for (size_t j_cell = 0; j_cell < i_cell; ++j_cell) { - const CellId cell_1 = node_to_cell[j_cell]; - cell_cells[cell_0].insert(cell_1); - cell_cells[cell_1].insert(cell_0); - } - } + cell_cells[cell_0].insert(cell_1); + cell_cells[cell_1].insert(cell_0); } } @@ -590,7 +574,7 @@ class Connectivity final : public IConnectivity } } } - return CSRGraph(entries, neighbors); + return CRSGraph(entries, neighbors); } PUGS_INLINE diff --git a/src/mesh/ConnectivityDispatcher.cpp b/src/mesh/ConnectivityDispatcher.cpp index 82bf2a2e006a13d0806b2d88b1dc54715a0cc116..6b73d967d4d4fcb37e1376bf1d9306826d25fb1f 100644 --- a/src/mesh/ConnectivityDispatcher.cpp +++ b/src/mesh/ConnectivityDispatcher.cpp @@ -1,6 +1,7 @@ #include <mesh/ConnectivityDispatcher.hpp> -#include <mesh/ItemOfItemType.hpp> +#include <mesh/ItemOfItemType.hpp> +#include <utils/CRSGraph.hpp> #include <utils/Partitioner.hpp> #include <iostream> @@ -12,7 +13,7 @@ void ConnectivityDispatcher<Dimension>::_buildNewOwner() { if constexpr (item_type == ItemType::cell) { - CSRGraph connectivity_graph = m_connectivity.cellToCellGraph(); + CRSGraph connectivity_graph = m_connectivity.cellToCellGraph(); Partitioner P; CellValue<int> cell_new_owner(m_connectivity); diff --git a/src/mesh/Mesh.hpp b/src/mesh/Mesh.hpp index d04807650cd08c0b96a7259cbe5756596d54aad1..e78383978469292d6529eb931b432406612f7220 100644 --- a/src/mesh/Mesh.hpp +++ b/src/mesh/Mesh.hpp @@ -4,7 +4,6 @@ #include <algebra/TinyVector.hpp> #include <mesh/IMesh.hpp> #include <mesh/ItemValue.hpp> -#include <utils/CSRGraph.hpp> #include <memory> diff --git a/src/utils/Array.hpp b/src/utils/Array.hpp index 42ae7f61c375a9cb544020063f827c43dcf5e143..560f60ce7015c06fa68c80121b43f86179a05e83 100644 --- a/src/utils/Array.hpp +++ b/src/utils/Array.hpp @@ -10,7 +10,7 @@ #include <algorithm> template <typename DataType> -class Array +class [[nodiscard]] Array { public: using data_type = DataType; @@ -23,15 +23,12 @@ class Array friend Array<std::add_const_t<DataType>>; public: - PUGS_INLINE - size_t - size() const noexcept + PUGS_INLINE size_t size() const noexcept { return m_values.extent(0); } - friend PUGS_INLINE Array<std::remove_const_t<DataType>> - copy(const Array<DataType>& source) + friend PUGS_INLINE Array<std::remove_const_t<DataType>> copy(const Array<DataType>& source) { Array<std::remove_const_t<DataType>> image(source.size()); Kokkos::deep_copy(image.m_values, source.m_values); @@ -42,16 +39,14 @@ class Array template <typename DataType2, typename... RT> friend PUGS_INLINE Array<DataType2> encapsulate(const Kokkos::View<DataType2*, RT...>& values); - PUGS_INLINE - DataType& operator[](index_type i) const noexcept(NO_ASSERT) + PUGS_INLINE DataType& operator[](index_type i) const noexcept(NO_ASSERT) { Assert(i < m_values.extent(0)); return m_values[i]; } PUGS_INLINE - void - fill(const DataType& data) const + void fill(const DataType& data) const { static_assert(not std::is_const<DataType>(), "Cannot modify Array of const"); @@ -61,8 +56,7 @@ class Array } template <typename DataType2> - PUGS_INLINE Array& - operator=(const Array<DataType2>& array) noexcept + PUGS_INLINE Array& operator=(const Array<DataType2>& array) 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>>(), @@ -81,7 +75,7 @@ class Array Array& operator=(Array&&) = default; PUGS_INLINE - Array(size_t size) : m_values("anonymous", size) + explicit Array(size_t size) : m_values("anonymous", size) { static_assert(not std::is_const<DataType>(), "Cannot allocate Array of const data: only view is " "supported"); @@ -94,14 +88,13 @@ class Array Array(const Array&) = default; template <typename DataType2> - PUGS_INLINE - Array(const Array<DataType2>& array) noexcept + PUGS_INLINE Array(const Array<DataType2>& array) noexcept { this->operator=(array); } PUGS_INLINE - Array(Array&&) = default; + Array(Array &&) = default; PUGS_INLINE ~Array() = default; diff --git a/src/utils/CRSGraph.hpp b/src/utils/CRSGraph.hpp new file mode 100644 index 0000000000000000000000000000000000000000..59b74ab57b16db757e95d1b74e72b4e296bfc026 --- /dev/null +++ b/src/utils/CRSGraph.hpp @@ -0,0 +1,47 @@ +#ifndef CRS_GRAPH_HPP +#define CRS_GRAPH_HPP + +#include <utils/Array.hpp> + +class CRSGraph +{ + private: + Array<const int> m_entries; + Array<const int> m_neighbors; + + public: + size_t + numberOfNodes() const + { + Assert(m_entries.size() > 0); + return m_entries.size() - 1; + } + + const Array<const int>& + entries() const + { + return m_entries; + } + + const Array<const int>& + neighbors() const + { + return m_neighbors; + } + + CRSGraph& operator=(CRSGraph&&) = delete; + CRSGraph& operator=(const CRSGraph&) = delete; + + CRSGraph(const Array<int>& entries, const Array<int>& neighbors) : m_entries(entries), m_neighbors(neighbors) + { + Assert(m_entries.size() > 0); + Assert(static_cast<size_t>(m_entries[m_entries.size() - 1]) == m_neighbors.size()); + } + + CRSGraph() = delete; + CRSGraph(CRSGraph&&) = delete; + CRSGraph(const CRSGraph&) = delete; + ~CRSGraph() = default; +}; + +#endif // CRS_GRAPH_HPP diff --git a/src/utils/CSRGraph.hpp b/src/utils/CSRGraph.hpp deleted file mode 100644 index a3ae85dcced1897fc54901903c919f0009761d74..0000000000000000000000000000000000000000 --- a/src/utils/CSRGraph.hpp +++ /dev/null @@ -1,46 +0,0 @@ -#ifndef CSR_GRAPH_HPP -#define CSR_GRAPH_HPP - -#include <utils/Array.hpp> - -class CSRGraph -{ - private: - Array<int> m_entries; - Array<int> m_neighbors; - - public: - size_t - numberOfNodes() const - { - Assert(m_entries.size() > 0); - return m_entries.size() - 1; - } - - const Array<int>& - entries() const - { - return m_entries; - } - - const Array<int>& - neighbors() const - { - return m_neighbors; - } - - CSRGraph& operator=(CSRGraph&&) = default; - CSRGraph& operator=(const CSRGraph&) = default; - - CSRGraph(const Array<int>& entries, const Array<int>& neighbors) : m_entries(entries), m_neighbors(neighbors) - { - Assert(m_entries.size() > 0); - } - - CSRGraph() = default; - CSRGraph(CSRGraph&&) = default; - CSRGraph(const CSRGraph&) = default; - ~CSRGraph() = default; -}; - -#endif // CSR_GRAPH_HPP diff --git a/src/utils/CastArray.hpp b/src/utils/CastArray.hpp index 120bcc25c1f5dd9da75a387016bad8d2b5175688..d329b4ef35f70f3a612ca430c45d0ec23bb7ed9d 100644 --- a/src/utils/CastArray.hpp +++ b/src/utils/CastArray.hpp @@ -8,7 +8,7 @@ #include <iostream> template <typename DataType, typename CastDataType> -class CastArray +class [[nodiscard]] CastArray { public: using data_type = CastDataType; @@ -20,8 +20,7 @@ class CastArray public: PUGS_INLINE - const size_t& - size() const + const size_t& size() const { return m_size; } @@ -39,17 +38,10 @@ class CastArray PUGS_INLINE CastArray& operator=(CastArray&&) = default; - PUGS_INLINE - CastArray() : m_size(0), m_values(nullptr) - { - ; - } - - PUGS_INLINE - CastArray(const Array<DataType>& array) + explicit CastArray(const Array<DataType>& array) : m_array(array), m_size(sizeof(DataType) * array.size() / sizeof(CastDataType)), - m_values((array.size() == 0) ? nullptr : reinterpret_cast<CastDataType*>(&(array[0]))) + m_values((array.size() == 0) ? nullptr : reinterpret_cast<CastDataType*>(&(static_cast<DataType&>(array[0])))) { static_assert((std::is_const_v<CastDataType> and std::is_const_v<DataType>) or (not std::is_const_v<DataType>), "CastArray cannot remove const attribute"); @@ -59,9 +51,8 @@ class CastArray } } - PUGS_INLINE - CastArray(DataType& value) - : m_size(sizeof(DataType) / sizeof(CastDataType)), m_values(reinterpret_cast<CastDataType*>(&(value))) + explicit CastArray(DataType & value) + : m_size(sizeof(DataType) / sizeof(CastDataType)), m_values(reinterpret_cast<CastDataType*>(&value)) { static_assert((std::is_const_v<CastDataType> and std::is_const_v<DataType>) or (not std::is_const_v<DataType>), "CastArray cannot remove const attribute"); @@ -70,13 +61,13 @@ class CastArray } PUGS_INLINE - CastArray(DataType&& value) = delete; + CastArray(DataType && value) = delete; PUGS_INLINE CastArray(const CastArray&) = default; PUGS_INLINE - CastArray(CastArray&&) = default; + CastArray(CastArray &&) = default; PUGS_INLINE ~CastArray() = default; diff --git a/src/utils/EscapedString.hpp b/src/utils/EscapedString.hpp index ed525abd0368614fb756fd8c7795bb1c7ea178c6..cf0f0c676ebd2998673c62870b07e52bf04e0269 100644 --- a/src/utils/EscapedString.hpp +++ b/src/utils/EscapedString.hpp @@ -1,6 +1,7 @@ #ifndef ESCAPED_STRING_HPP #define ESCAPED_STRING_HPP +#include <utils/Exceptions.hpp> #include <utils/PugsMacros.hpp> #include <sstream> @@ -11,7 +12,7 @@ PUGS_INLINE std::string unescapeString(std::string_view input_string) { std::stringstream ss; - for (size_t i = 1; i < input_string.size() - 1; ++i) { + for (size_t i = 0; i < input_string.size(); ++i) { char c = input_string[i]; if (c == '\\') { ++i; @@ -81,11 +82,15 @@ escapeString(std::string_view input_string) ss << R"(\\)"; break; } + case '\'': { + ss << R"(\')"; + break; + } case '\"': { ss << R"(\")"; break; } - case '?': { + case '\?': { ss << R"(\?)"; break; } diff --git a/src/utils/Messenger.hpp b/src/utils/Messenger.hpp index 437ea62a0d734274900c8af1b474749813e1aeaa..cfe312a0884ae0718ee76c41855ce8b063fecffd 100644 --- a/src/utils/Messenger.hpp +++ b/src/utils/Messenger.hpp @@ -168,7 +168,7 @@ class Messenger typename RecvArrayType, typename... SendT, typename... RecvT> - RecvArrayType<RecvT...> + void _allToAll(const SendArrayType<SendT...>& sent_array, RecvArrayType<RecvT...>& recv_array) const { #ifdef PUGS_HAS_MPI @@ -189,7 +189,6 @@ class Messenger #else // PUGS_HAS_MPI value_copy(sent_array, recv_array); #endif // PUGS_HAS_MPI - return recv_array; } template <template <typename... SendT> typename SendArrayType, diff --git a/src/utils/Partitioner.cpp b/src/utils/Partitioner.cpp index 43ee64851b8d63e80afaf4d6960fe8015c1fa675..347b07da6bffdf62d0218ca5231ed9e03a9c698f 100644 --- a/src/utils/Partitioner.cpp +++ b/src/utils/Partitioner.cpp @@ -15,7 +15,7 @@ #include <utils/Exceptions.hpp> Array<int> -Partitioner::partition(const CSRGraph& graph) +Partitioner::partition(const CRSGraph& graph) { std::cout << "Partitioning graph into " << rang::style::bold << parallel::size() << rang::style::reset << " parts\n"; @@ -26,7 +26,7 @@ Partitioner::partition(const CSRGraph& graph) std::vector<float> tpwgts(npart, 1. / npart); std::vector<float> ubvec{1.05}; - std::vector<int> options{1, 1, 0}; + std::vector<int> options{1, 0, 0}; int edgecut = 0; Array<int> part(0); @@ -57,15 +57,20 @@ Partitioner::partition(const CSRGraph& graph) part = Array<int>(local_number_of_nodes); std::vector<int> vtxdist{0, local_number_of_nodes}; - const Array<int>& entries = graph.entries(); - const Array<int>& neighbors = graph.neighbors(); + const Array<const int>& entries = graph.entries(); + const Array<const int>& neighbors = graph.neighbors(); + + int* entries_ptr = const_cast<int*>(&(entries[0])); + int* neighbors_ptr = const_cast<int*>(&(neighbors[0])); int result = - ParMETIS_V3_PartKway(&(vtxdist[0]), &(entries[0]), &(neighbors[0]), NULL, NULL, &wgtflag, &numflag, &ncon, &npart, + ParMETIS_V3_PartKway(&(vtxdist[0]), entries_ptr, neighbors_ptr, NULL, NULL, &wgtflag, &numflag, &ncon, &npart, &(tpwgts[0]), &(ubvec[0]), &(options[0]), &edgecut, &(part[0]), &parmetis_comm); + // LCOV_EXCL_START if (result == METIS_ERROR) { throw UnexpectedError("Metis Error"); } + // LCOV_EXCL_STOP MPI_Comm_free(&parmetis_comm); } @@ -78,9 +83,11 @@ Partitioner::partition(const CSRGraph& graph) #else // PUGS_HAS_MPI Array<int> -Partitioner::partition(const CSRGraph&) +Partitioner::partition(const CRSGraph& graph) { - return Array<int>(0); + Array<int> partition{graph.entries().size() - 1}; + partition.fill(0); + return partition; } #endif // PUGS_HAS_MPI diff --git a/src/utils/Partitioner.hpp b/src/utils/Partitioner.hpp index 30f50723acff089cd1a21fa4f289030f5bbdf7a3..2c720bfd87e7853e12cd0736a46c5eda246f085f 100644 --- a/src/utils/Partitioner.hpp +++ b/src/utils/Partitioner.hpp @@ -1,7 +1,7 @@ #ifndef PARTITIONER_HPP #define PARTITIONER_HPP -#include <utils/CSRGraph.hpp> +#include <utils/CRSGraph.hpp> class Partitioner { @@ -10,7 +10,7 @@ class Partitioner Partitioner(const Partitioner&) = default; ~Partitioner() = default; - Array<int> partition(const CSRGraph& graph); + Array<int> partition(const CRSGraph& graph); }; #endif // PARTITIONER_HPP diff --git a/src/utils/PugsUtils.cpp b/src/utils/PugsUtils.cpp index 8f388c5b492dcd8065ed77740d322556bdc76db3..d54bd333f93107a1e093038764ebe7f088ace9df 100644 --- a/src/utils/PugsUtils.cpp +++ b/src/utils/PugsUtils.cpp @@ -19,6 +19,10 @@ #include <iostream> +// LCOV_EXCL_START + +// This function cannot be unit-tested: run once when pugs starts + std::string initialize(int& argc, char* argv[]) { @@ -98,6 +102,12 @@ initialize(int& argc, char* argv[]) return filename; } +// LCOV_EXCL_STOP + +// LCOV_EXCL_START + +// This function cannot be unit-tested: run once when pugs stops + void finalize() { @@ -105,3 +115,5 @@ finalize() PETScWrapper::finalize(); parallel::Messenger::destroy(); } + +// LCOV_EXCL_STOP diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 11680e00f08cc7aa5ed80d9ed022fd3705bc8078..a08e1a689cf3041dd62b90c81630381581b83f38 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -45,16 +45,23 @@ add_executable (unit_tests test_BinaryExpressionProcessor_equality.cpp test_BinaryExpressionProcessor_logic.cpp test_BiCGStab.cpp + test_BuildInfo.cpp test_BuiltinFunctionEmbedder.cpp test_BuiltinFunctionEmbedderTable.cpp test_BuiltinFunctionProcessor.cpp + test_CastArray.cpp + test_ConsoleManager.cpp test_CG.cpp test_ContinueProcessor.cpp test_ConcatExpressionProcessor.cpp + test_CRSGraph.cpp test_CRSMatrix.cpp test_DataVariant.cpp + test_Demangle.cpp test_DoWhileProcessor.cpp test_EmbeddedData.cpp + test_EscapedString.cpp + test_Exceptions.cpp test_ExecutionPolicy.cpp test_FakeProcessor.cpp test_ForProcessor.cpp @@ -86,7 +93,8 @@ add_executable (unit_tests add_executable (mpi_unit_tests mpi_test_main.cpp - mpi_test_Messenger.cpp + test_Messenger.cpp + test_Partitioner.cpp ) add_library(test_Pugs_MeshDataBase diff --git a/tests/test_Array.cpp b/tests/test_Array.cpp index 3b8dd45878d07747cae3b4e761266c8d9bf14293..0071da34de3f6c5ae3173cb282a5a995462b47c5 100644 --- a/tests/test_Array.cpp +++ b/tests/test_Array.cpp @@ -197,6 +197,23 @@ TEST_CASE("Array", "[utils]") } } + SECTION("checking for Kokkos::View encaspulation") + { + { + Kokkos::View<double*> kokkos_view("anonymous", 10); + for (size_t i = 0; i < kokkos_view.size(); ++i) { + kokkos_view[i] = i; + } + + Array array = encapsulate(kokkos_view); + + REQUIRE(array.size() == kokkos_view.size()); + for (size_t i = 0; i < array.size(); ++i) { + REQUIRE(&array[i] == &kokkos_view[i]); + } + } + } + #ifndef NDEBUG SECTION("checking for bounds violation") { diff --git a/tests/test_BuildInfo.cpp b/tests/test_BuildInfo.cpp new file mode 100644 index 0000000000000000000000000000000000000000..335cc74e420122f61a59067c0df89e416e55c2ba --- /dev/null +++ b/tests/test_BuildInfo.cpp @@ -0,0 +1,65 @@ +#include <catch2/catch.hpp> + +#include <utils/BuildInfo.hpp> +#include <utils/pugs_build_info.hpp> +#include <utils/pugs_config.hpp> + +#include <sstream> + +#ifdef PUGS_HAS_MPI +#include <mpi.h> +#endif // PUGS_HAS_MPI + +#ifdef PUGS_HAS_PETSC +#include <petsc.h> +#endif // PUGS_HAS_PETSC + +// clazy:excludeall=non-pod-global-static + +TEST_CASE("BuildInfo", "[utils]") +{ + SECTION("type") + { + REQUIRE(BuildInfo::type() == PUGS_BUILD_TYPE); + } + + SECTION("compiler") + { + std::stringstream compiler_info; + compiler_info << PUGS_BUILD_COMPILER << " (" << PUGS_BUILD_COMPILER_VERSION << ")" << std::ends; + REQUIRE(BuildInfo::compiler() == compiler_info.str()); + } + + SECTION("kokkos") + { + REQUIRE(BuildInfo::kokkosDevices() == PUGS_BUILD_KOKKOS_DEVICES); + } + + SECTION("mpi") + { +#ifdef PUGS_HAS_MPI + const std::string mpi_library = []() { + int length; + char mpi_version[MPI_MAX_LIBRARY_VERSION_STRING]; + MPI_Get_library_version(mpi_version, &length); + return std::string(mpi_version); + }(); + + REQUIRE(BuildInfo::mpiLibrary() == mpi_library); +#else + REQUIRE(BuildInfo::mpiLibrary() == "none"); +#endif // PUGS_HAS_MPI + } + + SECTION("petsc") + { +#ifdef PUGS_HAS_PETSC + const std::string petsc_library = std::to_string(PETSC_VERSION_MAJOR) + "." + std::to_string(PETSC_VERSION_MINOR) + + "." + std::to_string(PETSC_VERSION_SUBMINOR); + + REQUIRE(BuildInfo::petscLibrary() == petsc_library); +#else + REQUIRE(BuildInfo::petscLibrary() == "none"); +#endif // PUGS_HAS_PETSC + } +} diff --git a/tests/test_CRSGraph.cpp b/tests/test_CRSGraph.cpp new file mode 100644 index 0000000000000000000000000000000000000000..5c2fc7f287249468886f557d30bbb5740216f114 --- /dev/null +++ b/tests/test_CRSGraph.cpp @@ -0,0 +1,39 @@ +#include <catch2/catch.hpp> + +#include <utils/CRSGraph.hpp> + +// clazy:excludeall=non-pod-global-static + +TEST_CASE("CRSGraph", "[utils]") +{ + Array<int> entries{5}; + Array<int> neighbors{9}; + + entries[0] = 0; + neighbors[0] = 0; + neighbors[1] = 1; + + entries[1] = 2; + neighbors[2] = 1; + neighbors[3] = 3; + + entries[2] = 4; + neighbors[4] = 2; + neighbors[5] = 1; + neighbors[6] = 3; + + entries[3] = 7; + neighbors[7] = 0; + neighbors[8] = 1; + + entries[4] = 9; + + CRSGraph graph(entries, neighbors); + + REQUIRE(graph.numberOfNodes() == 4); + + REQUIRE(entries.size() == graph.entries().size()); + REQUIRE(&entries[0] == &graph.entries()[0]); + REQUIRE(neighbors.size() == graph.neighbors().size()); + REQUIRE(&neighbors[0] == &graph.neighbors()[0]); +} diff --git a/tests/test_CastArray.cpp b/tests/test_CastArray.cpp new file mode 100644 index 0000000000000000000000000000000000000000..6a014045cfaf19a039dcaf0be97edaa81bea8522 --- /dev/null +++ b/tests/test_CastArray.cpp @@ -0,0 +1,88 @@ +#include <catch2/catch.hpp> + +#include <utils/ArrayUtils.hpp> +#include <utils/CastArray.hpp> + +// clazy:excludeall=non-pod-global-static + +TEST_CASE("CastArray", "[utils]") +{ + SECTION("explicit cast Array -> CastArray") + { + Array<double> x_double{5}; + x_double[0] = 1; + x_double[1] = 2; + x_double[2] = 3; + x_double[3] = 4; + x_double[4] = 5; + + CastArray<double, char> x_char{x_double}; + + REQUIRE(x_char.size() * sizeof(char) == x_double.size() * sizeof(double)); + + Array<char> y_char{x_char.size()}; + for (size_t i = 0; i < x_char.size(); ++i) { + y_char[i] = x_char[i]; + } + + CastArray<char, double> y_double{y_char}; + REQUIRE(y_char.size() * sizeof(char) == y_double.size() * sizeof(double)); + + REQUIRE(&(y_double[0]) != &(x_double[0])); + + for (size_t i = 0; i < y_double.size(); ++i) { + REQUIRE(y_double[i] == x_double[i]); + } + } + + SECTION("explicit cast value -> CastArray") + { + double x = 3; + + CastArray<double, char> x_char(x); + + REQUIRE(x_char.size() * sizeof(char) == sizeof(double)); + } + + SECTION("invalid cast array") + { + Array<char> x_char{13}; + + REQUIRE_THROWS_WITH((CastArray<char, double>{x_char}), + "unexpected error: cannot cast array to the chosen data type"); + } + + SECTION("cast array utilities") + { + SECTION("Array -> CastArray") + { + Array<double> x_double{5}; + x_double[0] = 1.3; + x_double[1] = 3.2; + x_double[2] = -4; + x_double[3] = 6.2; + x_double[4] = -1.6; + + CastArray<double, short> x_short{x_double}; + auto x_short_from = cast_array_to<short>::from(x_double); + + REQUIRE(x_short_from.size() == x_short.size()); + for (size_t i = 0; i < x_short_from.size(); ++i) { + REQUIRE(x_short_from[i] == x_short[i]); + } + } + + SECTION("Value -> CastArray") + { + double x = 3.14; + + CastArray<double, short> x_short{x}; + auto x_short_from = cast_value_to<short>::from(x); + + REQUIRE(x_short_from.size() == x_short.size()); + for (size_t i = 0; i < x_short_from.size(); ++i) { + REQUIRE(x_short_from[i] == x_short[i]); + } + } + } +} diff --git a/tests/test_ConsoleManager.cpp b/tests/test_ConsoleManager.cpp new file mode 100644 index 0000000000000000000000000000000000000000..4387d7042065df80406ba3ba1c06ba44ec3f9e97 --- /dev/null +++ b/tests/test_ConsoleManager.cpp @@ -0,0 +1,32 @@ +#include <catch2/catch.hpp> + +#include <utils/ConsoleManager.hpp> + +#include <rang.hpp> + +// clazy:excludeall=non-pod-global-static + +TEST_CASE("ConsoleManager", "[utils]") +{ + SECTION("is terminal") + { + const bool is_terminal = rang::rang_implementation::isTerminal(std::cout.rdbuf()); + + REQUIRE(is_terminal == ConsoleManager::isTerminal(std::cout)); + } + + SECTION("control settings") + { + const rang::control saved_control = rang::rang_implementation::controlMode(); + + ConsoleManager::init(true); + + REQUIRE(rang::rang_implementation::controlMode() == rang::control::Force); + + ConsoleManager::init(false); + + REQUIRE(rang::rang_implementation::controlMode() == rang::control::Off); + + rang::setControlMode(saved_control); + } +} diff --git a/tests/test_Demangle.cpp b/tests/test_Demangle.cpp new file mode 100644 index 0000000000000000000000000000000000000000..a3489fd2d629fe835e3ce247a8ac8008bb06ff9d --- /dev/null +++ b/tests/test_Demangle.cpp @@ -0,0 +1,37 @@ +#include <catch2/catch.hpp> + +#include <utils/Demangle.hpp> + +#include <cxxabi.h> + +// clazy:excludeall=non-pod-global-static + +TEST_CASE("Demangle", "[utils]") +{ + SECTION("demangle success") + { + const std::string mangled = typeid(std::string).name(); + + int status = -1; + char* cxa_demangled = abi::__cxa_demangle(mangled.data(), NULL, NULL, &status); + + REQUIRE(status == 0); + + std::string demangled{cxa_demangled}; + free(cxa_demangled); + + REQUIRE(demangled == demangle<std::string>()); + } + + SECTION("demangle failed") + { + const std::string mangled = "not_mangled"; + + int status = -1; + abi::__cxa_demangle(mangled.data(), NULL, NULL, &status); + + REQUIRE(status != 0); + + REQUIRE((std::string{"not_mangled"} == demangle("not_mangled"))); + } +} diff --git a/tests/test_EscapedString.cpp b/tests/test_EscapedString.cpp new file mode 100644 index 0000000000000000000000000000000000000000..3dca01496813ca51e6b52afd1be3c446bc7df54b --- /dev/null +++ b/tests/test_EscapedString.cpp @@ -0,0 +1,22 @@ +#include <catch2/catch.hpp> + +#include <utils/EscapedString.hpp> + +// clazy:excludeall=non-pod-global-static + +TEST_CASE("EscapedString", "[utils]") +{ + SECTION("escape string") + { + const std::string s = "foo\'\\\"\?\a\b\f\n\r\t\vbar"; + + REQUIRE(escapeString(s) == R"(foo\'\\\"\?\a\b\f\n\r\t\vbar)"); + } + + SECTION("unescape string") + { + const std::string s = R"(foo\'\\\"\?\a\b\f\n\r\t\vbar)"; + + REQUIRE(unescapeString(s) == std::string{"foo\'\\\"\?\a\b\f\n\r\t\vbar"}); + } +} diff --git a/tests/test_Exceptions.cpp b/tests/test_Exceptions.cpp new file mode 100644 index 0000000000000000000000000000000000000000..25b181ae165aef26cd25942cc52741a2606b50ac --- /dev/null +++ b/tests/test_Exceptions.cpp @@ -0,0 +1,20 @@ +#include <catch2/catch.hpp> + +#include <utils/Exceptions.hpp> + +// clazy:excludeall=non-pod-global-static + +TEST_CASE("Exceptions", "[utils]") +{ + SECTION("exceptions message") + { + RawError raw_error{"a raw error"}; + REQUIRE(std::string{raw_error.what()} == "a raw error"); + + UnexpectedError unexpected_error{"an unexpected error"}; + REQUIRE(std::string{unexpected_error.what()} == "unexpected error: an unexpected error"); + + NotImplementedError not_implemented_error{"not implemented error"}; + REQUIRE(std::string{not_implemented_error.what()} == "not implemented yet: not implemented error"); + } +} diff --git a/tests/mpi_test_Messenger.cpp b/tests/test_Messenger.cpp similarity index 98% rename from tests/mpi_test_Messenger.cpp rename to tests/test_Messenger.cpp index 19d89851c82020c0f10e4eaeac919595059e8fab..022a5c07e4b16db81dc69ec236a1482d1138d6d1 100644 --- a/tests/mpi_test_Messenger.cpp +++ b/tests/test_Messenger.cpp @@ -471,4 +471,11 @@ TEST_CASE("Messenger", "[mpi]") std::remove("barrier_test"); } + + SECTION("errors") + { + int argc = 0; + char** argv = nullptr; + REQUIRE_THROWS_WITH((parallel::Messenger::create(argc, argv)), "unexpected error: Messenger already created"); + } } diff --git a/tests/test_Partitioner.cpp b/tests/test_Partitioner.cpp new file mode 100644 index 0000000000000000000000000000000000000000..9af1fc6c6f24be33aa5363696f36cab5909e6e7d --- /dev/null +++ b/tests/test_Partitioner.cpp @@ -0,0 +1,86 @@ +#include <catch2/catch.hpp> + +#include <utils/Messenger.hpp> +#include <utils/Partitioner.hpp> + +#include <set> + +// clazy:excludeall=non-pod-global-static + +TEST_CASE("Partitioner", "[utils]") +{ + SECTION("one graph split to all") + { + Partitioner partitioner; + + std::vector<int> entries_vector; + std::vector<int> neighbors_vector; + + entries_vector.push_back(neighbors_vector.size()); + + if (parallel::rank() == 0) { + neighbors_vector.push_back(1); + neighbors_vector.push_back(2); + neighbors_vector.push_back(4); + entries_vector.push_back(neighbors_vector.size()); + + neighbors_vector.push_back(0); + neighbors_vector.push_back(3); + neighbors_vector.push_back(5); + entries_vector.push_back(neighbors_vector.size()); + + neighbors_vector.push_back(0); + neighbors_vector.push_back(2); + neighbors_vector.push_back(5); + entries_vector.push_back(neighbors_vector.size()); + + neighbors_vector.push_back(0); + neighbors_vector.push_back(2); + neighbors_vector.push_back(5); + entries_vector.push_back(neighbors_vector.size()); + + neighbors_vector.push_back(3); + neighbors_vector.push_back(5); + neighbors_vector.push_back(7); + entries_vector.push_back(neighbors_vector.size()); + + neighbors_vector.push_back(3); + neighbors_vector.push_back(5); + neighbors_vector.push_back(6); + entries_vector.push_back(neighbors_vector.size()); + + neighbors_vector.push_back(5); + neighbors_vector.push_back(6); + neighbors_vector.push_back(7); + entries_vector.push_back(neighbors_vector.size()); + + neighbors_vector.push_back(3); + neighbors_vector.push_back(5); + neighbors_vector.push_back(7); + entries_vector.push_back(neighbors_vector.size()); + + neighbors_vector.push_back(4); + neighbors_vector.push_back(6); + neighbors_vector.push_back(7); + entries_vector.push_back(neighbors_vector.size()); + } + + Array<int> entries = convert_to_array(entries_vector); + Array<int> neighbors = convert_to_array(neighbors_vector); + + CRSGraph graph{entries, neighbors}; + + Array<int> partitioned = partitioner.partition(graph); + + REQUIRE((partitioned.size() + 1) == entries.size()); + + if (parallel::rank() == 0) { + std::set<int> assigned_ranks; + for (size_t i = 0; i < partitioned.size(); ++i) { + assigned_ranks.insert(partitioned[i]); + } + + REQUIRE(assigned_ranks.size() == parallel::size()); + } + } +}