Skip to content
Snippets Groups Projects
Select Git revision
  • 5eaac22af999175d00f8c89d511a3f1af9ebfdc5
  • develop default protected
  • feature/advection
  • feature/composite-scheme-other-fluxes
  • origin/stage/bouguettaia
  • save_clemence
  • feature/local-dt-fsi
  • feature/variational-hydro
  • feature/gmsh-reader
  • feature/reconstruction
  • feature/kinetic-schemes
  • feature/composite-scheme-sources
  • feature/serraille
  • feature/composite-scheme
  • hyperplastic
  • feature/polynomials
  • feature/gks
  • feature/implicit-solver-o2
  • feature/coupling_module
  • feature/implicit-solver
  • feature/merge-local-dt-fsi
  • v0.5.0 protected
  • v0.4.1 protected
  • v0.4.0 protected
  • v0.3.0 protected
  • v0.2.0 protected
  • v0.1.0 protected
  • Kidder
  • v0.0.4 protected
  • v0.0.3 protected
  • v0.0.2 protected
  • v0 protected
  • v0.0.1 protected
33 results

AffectationProcessor.hpp

Blame
  • TinyMatrix.hpp 14.29 KiB
    #ifndef TINY_MATRIX_HPP
    #define TINY_MATRIX_HPP
    
    #include <algebra/TinyVector.hpp>
    #include <utils/InvalidData.hpp>
    #include <utils/NaNHelper.hpp>
    #include <utils/PugsAssert.hpp>
    #include <utils/PugsMacros.hpp>
    #include <utils/Types.hpp>
    
    #include <iostream>
    
    template <size_t M, size_t N = M, typename T = double>
    class [[nodiscard]] TinyMatrix
    {
     public:
      inline static constexpr size_t Dimension       = M * N;
      inline static constexpr size_t NumberOfRows    = M;
      inline static constexpr size_t NumberOfColumns = N;
    
      using data_type = T;
    
     private:
      static_assert((M > 0), "TinyMatrix number of rows must be strictly positive");
      static_assert((N > 0), "TinyMatrix number of columns must be strictly positive");
    
      T m_values[M * N];
    
      PUGS_FORCEINLINE
      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
      {
        m_values[M * N - 1 - sizeof...(args)] = t;
        if constexpr (sizeof...(args) > 0) {
          this->_unpackVariadicInput(std::forward<Args>(args)...);
        }
      }
    
      template <typename... Args>
      PUGS_FORCEINLINE constexpr void
      _unpackVariadicInput(const TinyVector<M, T>& t, Args&&... args) noexcept
      {
        for (size_t j = 0; j < M; ++j) {
          m_values[_index(j, N - 1 - sizeof...(args))] = t[j];
        }
        if constexpr (sizeof...(args) > 0) {
          this->_unpackVariadicInput(std::forward<Args>(args)...);
        }
      }
    
     public:
      [[nodiscard]] PUGS_INLINE constexpr bool
      isSquare() const noexcept
      {
        return M == N;
      }
    
      [[nodiscard]] PUGS_INLINE constexpr friend TinyMatrix<N, M, T>
      transpose(const TinyMatrix& A)
      {
        TinyMatrix<N, M, T> tA;
        for (size_t i = 0; i < M; ++i) {
          for (size_t j = 0; j < N; ++j) {
            tA(j, i) = A(i, j);
          }
        }
        return tA;
      }
    
      [[nodiscard]] PUGS_INLINE constexpr size_t
      dimension() const
      {
        return M * N;
      }
    
      [[nodiscard]] PUGS_INLINE constexpr size_t
      numberOfValues() const
      {
        return this->dimension();
      }
    
      [[nodiscard]] PUGS_INLINE constexpr size_t
      numberOfRows() const
      {
        return M;
      }
    
      [[nodiscard]] PUGS_INLINE constexpr size_t
      numberOfColumns() const
      {
        return N;
      }
    
      PUGS_INLINE constexpr TinyMatrix
      operator-() const
      {
        TinyMatrix opposite;
        for (size_t i = 0; i < M * N; ++i) {
          opposite.m_values[i] = -m_values[i];
        }
        return opposite;
      }
    
      PUGS_INLINE
      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)
      {
        return std::move(A *= t);
      }
    
      PUGS_INLINE
      constexpr TinyMatrix&
      operator*=(const T& t)
      {
        for (size_t i = 0; i < M * N; ++i) {
          m_values[i] *= t;
        }
        return *this;
      }
    
      [[nodiscard]] PUGS_INLINE constexpr friend T
      doubleDot(const TinyMatrix& A, const TinyMatrix& B)
      {
        T t = A.m_values[0] * B.m_values[0];
        for (size_t i = 1; i < M * N; ++i) {
          t += A.m_values[i] * B.m_values[i];
        }
        return t;
      }
    
      template <size_t P>
      PUGS_INLINE constexpr TinyMatrix<M, P, T>
      operator*(const TinyMatrix<N, P, T>& B) const
      {
        const TinyMatrix& A = *this;
        TinyMatrix<M, P, T> AB;
        for (size_t i = 0; i < M; ++i) {
          for (size_t j = 0; j < P; ++j) {
            T sum = A(i, 0) * B(0, j);
            for (size_t k = 1; k < N; ++k) {
              sum += A(i, k) * B(k, j);
            }
            AB(i, j) = sum;
          }
        }
        return AB;
      }
    
      PUGS_INLINE
      constexpr TinyVector<M, T>
      operator*(const TinyVector<N, T>& x) const
      {
        const TinyMatrix& A = *this;
        TinyVector<M, T> Ax;
        for (size_t i = 0; i < M; ++i) {
          T sum = A(i, 0) * x[0];
          for (size_t j = 1; j < N; ++j) {
            sum += A(i, j) * x[j];
          }
          Ax[i] = sum;
        }
        return Ax;
      }
    
      PUGS_INLINE
      constexpr friend std::ostream&
      operator<<(std::ostream& os, const TinyMatrix& A)
      {
        os << '[';
        for (size_t i = 0; i < M; ++i) {
          if (i > 0) {
            os << ',';
          }
          os << '[' << NaNHelper(A(i, 0));
          for (size_t j = 1; j < N; ++j) {
            os << ',' << NaNHelper(A(i, j));
          }
          os << ']';
        }
        os << ']';
    
        return os;
      }
    
      [[nodiscard]] PUGS_INLINE constexpr bool
      operator==(const TinyMatrix& A) const
      {
        for (size_t i = 0; i < M * N; ++i) {
          if (m_values[i] != A.m_values[i])
            return false;
        }
        return true;
      }
    
      [[nodiscard]] PUGS_INLINE constexpr bool
      operator!=(const TinyMatrix& A) const
      {
        return not this->operator==(A);
      }
    
      PUGS_INLINE
      constexpr TinyMatrix
      operator+(const TinyMatrix& A) const
      {
        TinyMatrix sum;
        for (size_t i = 0; i < M * N; ++i) {
          sum.m_values[i] = m_values[i] + A.m_values[i];
        }
        return sum;
      }
    
      PUGS_INLINE
      constexpr TinyMatrix
      operator+(TinyMatrix&& A) const
      {
        A += *this;
        return std::move(A);
      }
    
      PUGS_INLINE
      constexpr TinyMatrix
      operator-(const TinyMatrix& A) const
      {
        TinyMatrix difference;
        for (size_t i = 0; i < M * N; ++i) {
          difference.m_values[i] = m_values[i] - A.m_values[i];
        }
        return difference;
      }
    
      PUGS_INLINE
      constexpr TinyMatrix
      operator-(TinyMatrix&& A) const
      {
        for (size_t i = 0; i < M * N; ++i) {
          A.m_values[i] = m_values[i] - A.m_values[i];
        }
        return std::move(A);
      }
    
      PUGS_INLINE
      constexpr TinyMatrix&
      operator+=(const TinyMatrix& A)
      {
        for (size_t i = 0; i < M * N; ++i) {
          m_values[i] += A.m_values[i];
        }
        return *this;
      }
    
      PUGS_INLINE
      constexpr TinyMatrix&
      operator-=(const TinyMatrix& A)
      {
        for (size_t i = 0; i < M * N; ++i) {
          m_values[i] -= A.m_values[i];
        }
        return *this;
      }
    
      [[nodiscard]] PUGS_INLINE constexpr T&
      operator()(size_t i, size_t j) noexcept(NO_ASSERT)
      {
        Assert((i < M) and (j < N));
        return m_values[_index(i, j)];
      }
    
      [[nodiscard]] PUGS_INLINE constexpr const T&
      operator()(size_t i, size_t j) const noexcept(NO_ASSERT)
      {
        Assert((i < M) and (j < N));
        return m_values[_index(i, j)];
      }
    
      PUGS_INLINE constexpr TinyMatrix&
      operator=(ZeroType) noexcept
      {
        static_assert(std::is_arithmetic<T>(), "Cannot assign 'zero' value for non-arithmetic types");
        for (size_t i = 0; i < M * N; ++i) {
          m_values[i] = 0;
        }
        return *this;
      }
    
      PUGS_INLINE
      constexpr TinyMatrix&
      operator=(IdentityType) noexcept
      {
        static_assert(std::is_arithmetic<T>(), "Cannot assign 'identity' value for non-arithmetic types");
        for (size_t i = 0; i < M; ++i) {
          for (size_t j = 0; j < N; ++j) {
            m_values[_index(i, j)] = (i == j) ? 1 : 0;
          }
        }
        return *this;
      }
    
      PUGS_INLINE
      constexpr TinyMatrix& operator=(const TinyMatrix& A) noexcept = default;
    
      PUGS_INLINE
      constexpr TinyMatrix& operator=(TinyMatrix&& A) noexcept = default;
    
      template <typename... Args>
      PUGS_INLINE explicit constexpr TinyMatrix(const T& t, Args&&... args) noexcept
      {
        static_assert(sizeof...(args) == M * N - 1, "wrong number of parameters");
        this->_unpackVariadicInput(t, std::forward<Args>(args)...);
      }
    
      template <typename... Args>
      PUGS_INLINE explicit constexpr TinyMatrix(const TinyVector<M, T>& t, Args&&... args) noexcept
      {
        static_assert(sizeof...(args) == N - 1, "wrong number of parameters");
        this->_unpackVariadicInput(t, std::forward<Args>(args)...);
      }
    
      // One does not use the '=default' constructor to avoid (unexpected)
      // performances issues
      PUGS_INLINE
      constexpr TinyMatrix() noexcept
      {
    #ifndef NDEBUG
        for (size_t i = 0; i < M * N; ++i) {
          m_values[i] = invalid_data_v<T>;
        }
    #endif   // NDEBUG
      }
    
      PUGS_INLINE
      constexpr TinyMatrix(ZeroType) noexcept
      {
        static_assert(std::is_arithmetic<T>(), "Cannot construct from 'zero' value "
                                               "for non-arithmetic types");
        for (size_t i = 0; i < M * N; ++i) {
          m_values[i] = 0;
        }
      }
    
      PUGS_INLINE
      constexpr TinyMatrix(IdentityType) noexcept
      {
        static_assert(std::is_arithmetic<T>(), "Cannot construct from 'identity' "
                                               "value for non-arithmetic types");
        for (size_t i = 0; i < M; ++i) {
          for (size_t j = 0; j < N; ++j) {
            m_values[_index(i, j)] = (i == j) ? 1 : 0;
          }
        }
      }
    
      PUGS_INLINE
      constexpr TinyMatrix(const TinyMatrix&) noexcept = default;
    
      PUGS_INLINE
      TinyMatrix(TinyMatrix&& A) noexcept = default;
    
      PUGS_INLINE
      ~TinyMatrix() = default;
    };
    
    template <size_t M, size_t N, typename T>
    [[nodiscard]] PUGS_INLINE constexpr TinyMatrix<M, N, T>
    tensorProduct(const TinyVector<M, T>& x, const TinyVector<N, T>& y)
    {
      TinyMatrix<M, N, T> A;
      for (size_t i = 0; i < M; ++i) {
        for (size_t j = 0; j < N; ++j) {
          A(i, j) = x[i] * y[j];
        }
      }
      return A;
    }
    
    template <size_t N, typename T>
    [[nodiscard]] PUGS_INLINE constexpr T
    det(const TinyMatrix<N, N, T>& A)
    {
      static_assert(std::is_arithmetic<T>::value, "determinant is not defined for non-arithmetic types");
      static_assert(std::is_floating_point<T>::value, "determinant for arbitrary dimension N is defined for floating "
                                                      "point types only");
      TinyMatrix B = A;
    
      TinyVector<N, size_t> index;
      for (size_t i = 0; i < N; ++i) {
        index[i] = i;
      }
    
      T determinent = 1;
      for (size_t i = 0; i < N; ++i) {
        for (size_t j = i; j < N; ++j) {
          size_t l       = j;
          const size_t J = index[j];
          for (size_t k = j + 1; k < N; ++k) {
            if (std::abs(B(index[k], i)) > std::abs(B(J, i))) {
              l = k;
            }
          }
          if (l != j) {
            std::swap(index[l], index[j]);
            determinent *= -1;
          }
        }
        const size_t I = index[i];
        const T Bii    = B(I, i);
        if (Bii != 0) {
          const T inv_Bii = 1. / B(I, i);
          for (size_t k = i + 1; k < N; ++k) {
            const size_t K = index[k];
            const T factor = B(K, i) * inv_Bii;
            for (size_t l = i + 1; l < N; ++l) {
              B(K, l) -= factor * B(I, l);
            }
          }
        } else {
          return 0;
        }
      }
    
      for (size_t i = 0; i < N; ++i) {
        determinent *= B(index[i], i);
      }
      return determinent;
    }
    
    template <typename T>
    [[nodiscard]] PUGS_INLINE constexpr T
    det(const TinyMatrix<1, 1, T>& A)
    {
      static_assert(std::is_arithmetic<T>::value, "determinent is not defined for non-arithmetic types");
      return A(0, 0);
    }
    
    template <typename T>
    [[nodiscard]] PUGS_INLINE constexpr T
    det(const TinyMatrix<2, 2, T>& A)
    {
      static_assert(std::is_arithmetic<T>::value, "determinent is not defined for non-arithmetic types");
      return A(0, 0) * A(1, 1) - A(1, 0) * A(0, 1);
    }
    
    template <typename T>
    [[nodiscard]] PUGS_INLINE constexpr T
    det(const TinyMatrix<3, 3, T>& A)
    {
      static_assert(std::is_arithmetic<T>::value, "determinent is not defined for non-arithmetic types");
      return A(0, 0) * (A(1, 1) * A(2, 2) - A(2, 1) * A(1, 2)) - A(1, 0) * (A(0, 1) * A(2, 2) - A(2, 1) * A(0, 2)) +
             A(2, 0) * (A(0, 1) * A(1, 2) - A(1, 1) * A(0, 2));
    }
    
    template <size_t M, size_t N, typename T>
    [[nodiscard]] PUGS_INLINE constexpr TinyMatrix<M - 1, N - 1, T>
    getMinor(const TinyMatrix<M, N, T>& A, size_t I, size_t J)
    {
      static_assert(M >= 2 and N >= 2, "minor calculation requires at least 2x2 matrices");
      Assert((I < M) and (J < N));
      TinyMatrix<M - 1, N - 1, T> m;
      for (size_t i = 0; i < I; ++i) {
        for (size_t j = 0; j < J; ++j) {
          m(i, j) = A(i, j);
        }
        for (size_t j = J + 1; j < N; ++j) {
          m(i, j - 1) = A(i, j);
        }
      }
      for (size_t i = I + 1; i < M; ++i) {
        for (size_t j = 0; j < J; ++j) {
          m(i - 1, j) = A(i, j);
        }
        for (size_t j = J + 1; j < N; ++j) {
          m(i - 1, j - 1) = A(i, j);
        }
      }
      return m;
    }
    
    template <size_t N, typename T>
    [[nodiscard]] PUGS_INLINE T
    trace(const TinyMatrix<N, N, T>& A)
    {
      static_assert(std::is_arithmetic<T>::value, "trace is not defined for non-arithmetic types");
    
      T t = A(0, 0);
      for (size_t i = 1; i < N; ++i) {
        t += A(i, i);
      }
      return t;
    }
    
    template <size_t M, size_t N, typename T>
    [[nodiscard]] PUGS_INLINE constexpr decltype(std::sqrt(std::declval<T>()))
    frobeniusNorm(const TinyMatrix<M, N, T>& A)
    {
      static_assert(std::is_arithmetic<T>::value, "norm is not defined for non-arithmetic types");
      static_assert(std::is_floating_point<T>::value, "Frobenius norm is defined for floating point types only");
    
      return std::sqrt(doubleDot(A, A));
    }
    
    template <size_t N, typename T>
    [[nodiscard]] PUGS_INLINE constexpr TinyMatrix<N, N, T> inverse(const TinyMatrix<N, N, T>& A);
    
    template <typename T>
    [[nodiscard]] PUGS_INLINE constexpr TinyMatrix<1, 1, T>
    inverse(const TinyMatrix<1, 1, T>& A)
    {
      static_assert(std::is_arithmetic<T>::value, "inverse is not defined for non-arithmetic types");
      static_assert(std::is_floating_point<T>::value, "inverse is defined for floating point types only");
    
      TinyMatrix<1, 1, T> A_1(1. / A(0, 0));
      return A_1;
    }
    
    template <size_t N, typename T>
    [[nodiscard]] PUGS_INLINE constexpr T
    cofactor(const TinyMatrix<N, N, T>& A, size_t i, size_t j)
    {
      static_assert(std::is_arithmetic<T>::value, "cofactor is not defined for non-arithmetic types");
      const T sign = ((i + j) % 2) ? -1 : 1;
    
      return sign * det(getMinor(A, i, j));
    }
    
    template <typename T>
    [[nodiscard]] PUGS_INLINE constexpr TinyMatrix<2, 2, T>
    inverse(const TinyMatrix<2, 2, T>& A)
    {
      static_assert(std::is_arithmetic<T>::value, "inverse is not defined for non-arithmetic types");
      static_assert(std::is_floating_point<T>::value, "inverse is defined for floating point types only");
    
      const T determinent     = det(A);
      const T inv_determinent = 1. / determinent;
    
      TinyMatrix<2, 2, T> A_cofactors_T(A(1, 1), -A(0, 1), -A(1, 0), A(0, 0));
      return A_cofactors_T *= inv_determinent;
    }
    
    template <typename T>
    [[nodiscard]] PUGS_INLINE constexpr TinyMatrix<3, 3, T>
    inverse(const TinyMatrix<3, 3, T>& A)
    {
      static_assert(std::is_arithmetic<T>::value, "inverse is not defined for non-arithmetic types");
      static_assert(std::is_floating_point<T>::value, "inverse is defined for floating point types only");
    
      const T determinent = det(A);
    
      TinyMatrix<3, 3, T> A_cofactors_T(cofactor(A, 0, 0), cofactor(A, 1, 0), cofactor(A, 2, 0), cofactor(A, 0, 1),
                                        cofactor(A, 1, 1), cofactor(A, 2, 1), cofactor(A, 0, 2), cofactor(A, 1, 2),
                                        cofactor(A, 2, 2));
    
      return A_cofactors_T *= 1. / determinent;
    }
    
    #endif   // TINYMATRIX_HPP