From 6eedc659d9b7cd595d6b7aa513db8e7fb6c95de8 Mon Sep 17 00:00:00 2001
From: LABOURASSE Emmanuel <labourassee@gmail.com>
Date: Thu, 3 Sep 2020 10:59:23 +0200
Subject: [PATCH] Add a class for the polynomial basis management

---
 src/analysis/PolynomialBasis.hpp | 105 +++++++++++++++++++++++++++++++
 tests/test_PolynomialBasis.cpp   |  42 +++++++++++++
 2 files changed, 147 insertions(+)
 create mode 100644 src/analysis/PolynomialBasis.hpp
 create mode 100644 tests/test_PolynomialBasis.cpp

diff --git a/src/analysis/PolynomialBasis.hpp b/src/analysis/PolynomialBasis.hpp
new file mode 100644
index 000000000..c8e782b79
--- /dev/null
+++ b/src/analysis/PolynomialBasis.hpp
@@ -0,0 +1,105 @@
+#ifndef POLYNOMIALBASIS_HPP
+#define POLYNOMIALBASIS_HPP
+
+#include <algebra/TinyVector.hpp>
+#include <analysis/Polynomial.hpp>
+#include <utils/Messenger.hpp>
+
+enum class BasisType
+{
+  canonical
+};
+
+template <size_t N>
+class PolynomialBasis
+{
+ private:
+  static_assert((N >= 0), "Number of elements in the basis must be non-negative");
+  TinyVector<N + 1, Polynomial<N>> m_elements;
+  BasisType m_basis_type;
+  PUGS_INLINE
+  constexpr PolynomialBasis<N>&
+  _buildCanonicalBasis()
+  {
+    for (size_t i = 0; i <= N; i++) {
+      TinyVector<N + 1> coefficients(zero);
+      coefficients[i] = 1;
+      elements()[i]   = Polynomial<N>(coefficients);
+    }
+    return *this;
+  }
+
+ public:
+  PUGS_INLINE
+  constexpr size_t
+  size() const
+  {
+    return N + 1;
+  }
+
+  PUGS_INLINE
+  constexpr size_t
+  degree() const
+  {
+    return N;
+  }
+
+  PUGS_INLINE
+  constexpr BasisType&
+  type()
+  {
+    return m_basis_type;
+  }
+
+  PUGS_INLINE
+  std::string_view
+  displayType()
+  {
+    switch (m_basis_type) {
+    case BasisType::canonical:
+      return "canonical";
+    default:
+      return "unknown basis type";
+    }
+  }
+
+  PUGS_INLINE
+  constexpr const TinyVector<N + 1, Polynomial<N>>&
+  elements() const
+  {
+    return m_elements;
+  }
+
+  PUGS_INLINE
+  constexpr TinyVector<N + 1, Polynomial<N>>&
+  elements()
+  {
+    return m_elements;
+  }
+
+  PUGS_INLINE
+  constexpr PolynomialBasis<N>&
+  build(BasisType basis_type)
+  {
+    type() = basis_type;
+    switch (basis_type) {
+    case BasisType::canonical: {
+      return _buildCanonicalBasis();
+      break;
+    }
+    default:
+      throw UnexpectedError("unknown basis type");
+    }
+  }
+  PUGS_INLINE constexpr PolynomialBasis(const TinyVector<N + 1, Polynomial<N>>& elements) noexcept
+    : m_elements{elements}
+  {}
+
+  PUGS_INLINE
+  constexpr PolynomialBasis(TinyVector<N + 1, Polynomial<N>>&& elements) noexcept : m_elements{elements} {}
+
+  PUGS_INLINE
+  constexpr PolynomialBasis() noexcept = default;
+  ~PolynomialBasis()                   = default;
+};
+#endif   // POLYNOMIAL_HPP
diff --git a/tests/test_PolynomialBasis.cpp b/tests/test_PolynomialBasis.cpp
new file mode 100644
index 000000000..933797bb3
--- /dev/null
+++ b/tests/test_PolynomialBasis.cpp
@@ -0,0 +1,42 @@
+#include <catch2/catch.hpp>
+
+#include <Kokkos_Core.hpp>
+
+#include <utils/PugsAssert.hpp>
+#include <utils/Types.hpp>
+
+#include <algebra/TinyMatrix.hpp>
+#include <analysis/Polynomial.hpp>
+#include <analysis/PolynomialBasis.hpp>
+
+// Instantiate to ensure full coverage is performed
+template class Polynomial<0>;
+template class Polynomial<1>;
+template class Polynomial<2>;
+template class PolynomialBasis<2>;
+
+// clazy:excludeall=non-pod-global-static
+
+TEST_CASE("PolynomialBasis", "[analysis]")
+{
+  SECTION("construction")
+  {
+    TinyVector<3, Polynomial<2>> elements;
+    REQUIRE_NOTHROW(PolynomialBasis<2>(elements));
+    REQUIRE_NOTHROW(PolynomialBasis<2>());
+  }
+  SECTION("size")
+  {
+    PolynomialBasis<2> B;
+    REQUIRE(B.size() == 3);
+    REQUIRE(B.degree() == 2);
+  }
+  SECTION("build")
+  {
+    PolynomialBasis<2> B;
+    REQUIRE(B.displayType() == "unknown basis type");
+    B.build(BasisType::canonical);
+    REQUIRE(B.elements()[1] == Polynomial<2>{{0, 1, 0}});
+    REQUIRE(B.elements()[2] == Polynomial<2>{{0, 0, 1}});
+  }
+}
-- 
GitLab