diff --git a/src/common/aka_types.hh b/src/common/aka_types.hh index cfc56dd31..c9e62e945 100644 --- a/src/common/aka_types.hh +++ b/src/common/aka_types.hh @@ -1,559 +1,549 @@ /** * @file aka_types.hh * * @author Nicolas Richart * * @date creation: Thu Feb 17 2011 * @date last modification: Wed Dec 09 2020 * * @brief description of the "simple" types * * * @section LICENSE * * Copyright (©) 2010-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne) * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * Akantu is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. * * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * * You should have received a copy of the GNU Lesser General Public License * along with Akantu. If not, see . * */ /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "aka_compatibilty_with_cpp_standard.hh" #include "aka_error.hh" /* -------------------------------------------------------------------------- */ #include #include #include #include #include #ifndef AKANTU_AKA_TYPES_HH #define AKANTU_AKA_TYPES_HH /* -------------------------------------------------------------------------- */ #define EIGEN_DEFAULT_DENSE_INDEX_TYPE akantu::Idx #define EIGEN_DEFAULT_MATRIX_STORAGE_ORDER_OPTION Eigen::ColMajor #define EIGEN_DEFAULT_IO_FORMAT \ Eigen::IOFormat(Eigen::StreamPrecision, Eigen::DontAlignCols, ", ", ", ", \ "[", "]", "[", "]") /* -------------------------------------------------------------------------- */ #define EIGEN_MATRIXBASE_PLUGIN "aka_types_eigen_matrix_base_plugin.hh" #define EIGEN_MATRIX_PLUGIN "aka_types_eigen_matrix_plugin.hh" #define EIGEN_PLAINOBJECTBASE_PLUGIN \ "aka_types_eigen_plain_object_base_plugin.hh" -#if __cplusplus > 201703L -#define EIGEN_MAX_CPP_VER 20 -#elif __cplusplus > 201402L -#define EIGEN_MAX_CPP_VER 17 -#elif __cplusplus > 201103L -#define EIGEN_MAX_CPP_VER 14 -#else -#define EIGEN_MAX_CPP_VER 11 -#endif - #include #include /* -------------------------------------------------------------------------- */ namespace aka { template struct is_eigen_map : public std::false_type {}; template struct is_eigen_map> : public std::true_type {}; /* -------------------------------------------------------------------------- */ template struct is_eigen_matrix : public std::false_type {}; template struct is_eigen_matrix< Eigen::Matrix<_Scalar, _Rows, _Cols, _Options, _MaxRows, _MaxCols>> : public std::true_type {}; /* -------------------------------------------------------------------------- */ template struct is_eigen_matrix_base : public std::false_type {}; template struct is_eigen_matrix_base> : public std::true_type {}; } // namespace aka namespace akantu { using Eigen::Ref; template using Vector = Eigen::Matrix; template using Matrix = Eigen::Matrix; template using VectorProxy = Eigen::Map::value, const Vector, n>, Vector, n>>>; template using MatrixProxy = Eigen::Map::value, const Matrix, m, n>, Matrix, m, n>>>; using VectorXr = Vector; using MatrixXr = Matrix; enum NormType : int8_t { L_1 = 1, L_2 = 2, L_inf = -1 }; struct TensorTraitBase {}; template struct TensorTrait : public TensorTraitBase {}; } // namespace akantu namespace aka { template using is_vector = aka::bool_constant< std::remove_reference_t>::IsVectorAtCompileTime>; template inline constexpr bool is_vector_v = is_vector::value; template using is_matrix = aka::negation>; template inline constexpr bool is_matrix_v = is_matrix::value; template using are_vectors = aka::conjunction...>; template inline constexpr bool are_vectors_v = are_vectors::value; template using are_matrices = aka::conjunction...>; template inline constexpr bool are_matrices_v = are_matrices::value; template using enable_if_matrices_t = std::enable_if_t::value>; template using enable_if_vectors_t = std::enable_if_t::value>; /* -------------------------------------------------------------------------- */ template struct is_tensor : public std::is_base_of {}; template struct is_tensor> : public std::true_type {}; template struct is_tensor> : public std::true_type {}; template struct is_tensor> : public std::true_type {}; template using is_tensor_n = std::is_base_of, T>; template inline constexpr bool is_tensor_v = is_tensor::value; template inline constexpr bool is_tensor_n_v = is_tensor_n::value; template using enable_if_tensors_n = std::enable_if< aka::conjunction< is_tensor_n..., std::is_same< std::common_type_t...>, std::decay_t>...>::value, T>; template using enable_if_tensors_n_t = typename enable_if_tensors_n::type; } // namespace aka namespace akantu { // fwd declaration template class TensorBase; template class TensorProxy; template class Tensor; } // namespace akantu /* -------------------------------------------------------------------------- */ #include "aka_view_iterators.hh" /* -------------------------------------------------------------------------- */ #include "aka_tensor.hh" /* -------------------------------------------------------------------------- */ namespace akantu { class ArrayBase; /* -------------------------------------------------------------------------- */ namespace details { template struct MapPlainObjectType { using type = T; }; template struct MapPlainObjectType< Eigen::Map> { using type = PlainObjectType; }; template using MapPlainObjectType_t = typename MapPlainObjectType::type; template struct EigenMatrixViewHelper {}; template struct EigenMatrixViewHelper { using type = Eigen::Matrix; }; template struct EigenMatrixViewHelper { using type = Eigen::Matrix; }; template using EigenMatrixViewHelper_t = typename EigenMatrixViewHelper::type; template class EigenView { static_assert(sizeof...(sizes) == 1 or sizeof...(sizes) == 2, "Eigen only supports Vector and Matrices"); private: template < class A = Array, std::enable_if_t>::value> * = nullptr> auto array_size() const { return array.get().size() * array.get().getNbComponent(); } template < class A = Array, std::enable_if_t>::value> * = nullptr> auto array_size() const { return array.get().size(); } using ArrayRef_t = decltype(std::ref(std::declval())); public: using size_type = typename std::decay_t::size_type; using value_type = typename std::decay_t::value_type; EigenView(Array && array, decltype(sizes)... sizes_) : array(std::ref(array)), sizes_(sizes_...) {} EigenView(Array && array) : array(array), sizes_(sizes...) {} EigenView(const EigenView & other) = default; EigenView(EigenView && other) noexcept = default; auto operator=(const EigenView & other) -> EigenView & = default; auto operator=(EigenView && other) noexcept -> EigenView & = default; template ::value> * = nullptr> decltype(auto) begin() { return aka::make_from_tuple<::akantu::view_iterator< Eigen::Map>>>( std::tuple_cat(std::make_tuple(array.get().data()), sizes_)); } template ::value> * = nullptr> decltype(auto) end() { return aka::make_from_tuple<::akantu::view_iterator< Eigen::Map>>>( std::tuple_cat(std::make_tuple(array.get().data() + array_size()), sizes_)); } decltype(auto) begin() const { return aka::make_from_tuple<::akantu::view_iterator< Eigen::Map>>>( std::tuple_cat(std::make_tuple(array.get().data()), sizes_)); } decltype(auto) end() const { return aka::make_from_tuple<::akantu::view_iterator< Eigen::Map>>>( std::tuple_cat(std::make_tuple(array.get().data() + array_size()), sizes_)); } private: ArrayRef_t array; std::tuple sizes_; }; } // namespace details template decltype(auto) make_view(Array && array, Idx rows = RowsAtCompileTime) { return details::EigenView( std::forward(array), rows); } template decltype(auto) make_view(Array && array, Idx rows = RowsAtCompileTime, Idx cols = ColsAtCompileTime) { return details::EigenView( std::forward(array), rows, cols); } template decltype(auto) make_const_view(const Array & array, Idx rows = RowsAtCompileTime) { return make_view(array, rows); } template decltype(auto) make_const_view(const Array & array, Idx rows = RowsAtCompileTime, Idx cols = ColsAtCompileTime) { return make_view(array, rows, cols); } } // namespace akantu namespace Eigen { template EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void MatrixBase::zero() { return this->fill(0.); } /* -------------------------------------------------------------------------- */ /* Vector */ /* -------------------------------------------------------------------------- */ template template ::value and ED::IsVectorAtCompileTime> *> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE decltype(auto) MatrixBase::begin() { return ::akantu::view_iterator( this->derived().data()); } template template ::value and ED::IsVectorAtCompileTime> *> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE decltype(auto) MatrixBase::end() { return ::akantu::view_iterator( this->derived().data() + this->size()); } template template *> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE decltype(auto) MatrixBase::begin() const { using Scalar = typename Derived::Scalar; return ::akantu::const_view_iterator(this->derived().data()); } template template *> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE decltype(auto) MatrixBase::end() const { using Scalar = typename Derived::Scalar; return ::akantu::const_view_iterator(this->derived().data() + this->size()); } /* -------------------------------------------------------------------------- */ /* Matrix */ /* -------------------------------------------------------------------------- */ template template ::value and not ED::IsVectorAtCompileTime> *> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE decltype(auto) MatrixBase::begin() { return ::akantu::view_iterator< Map>>( this->derived().data(), this->rows()); } template template ::value and not ED::IsVectorAtCompileTime> *> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE decltype(auto) MatrixBase::end() { return ::akantu::view_iterator< Map>>( this->derived().data() + this->size(), this->rows()); } template template *> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE decltype(auto) MatrixBase::begin() const { using Scalar = typename Derived::Scalar; return ::akantu::const_view_iterator< Map>>( const_cast(this->derived().data()), this->rows()); } template template *> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE decltype(auto) MatrixBase::end() const { using Scalar = typename Derived::Scalar; return ::akantu::const_view_iterator< Map>>( const_cast(this->derived().data()) + this->size(), this->rows()); } template template EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void MatrixBase::eig(MatrixBase & values) const { EigenSolver>> solver(*this, false); using OtherScalar = typename OtherDerived::Scalar; // as advised by the Eigen developers even though this is a UB // auto & values = const_cast &>(values_); if constexpr (std::is_floating_point{}) { values = solver.eigenvalues().real(); } else { values = solver.eigenvalues(); } } template template EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void MatrixBase::eig(MatrixBase & values, MatrixBase & vectors, bool sort) const { EigenSolver>> solver(*this, true); // as advised by the Eigen developers even though this is a UB // auto & values = const_cast &>(values_); // auto & vectors = const_cast &>(vectors_); auto norm = this->norm(); using OtherScalar = typename D1::Scalar; if ((solver.eigenvectors().imag().template lpNorm() > 1e-15 * norm) and std::is_floating_point::value) { AKANTU_EXCEPTION("This matrix has complex eigenvectors()"); } if (not sort) { if constexpr (std::is_floating_point{}) { values = solver.eigenvalues().real(); vectors = solver.eigenvectors().real(); } else { values = solver.eigenvalues(); vectors = solver.eigenvectors(); } return; } if (not std::is_floating_point::value) { AKANTU_EXCEPTION("Cannot sort complex eigen values"); } values = solver.eigenvalues().real(); PermutationMatrix P(values.size()); P.setIdentity(); std::sort(P.indices().data(), P.indices().data() + P.indices().size(), [&values](const Index & a, const Index & b) { return (values(a) - values(b)) > 0; }); if constexpr (std::is_floating_point{}) { values = P.transpose() * values; vectors = solver.eigenvectors().real() * P; } return; } template template EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void MatrixBase::eigh(const MatrixBase & values_) const { SelfAdjointEigenSolver< akantu::details::MapPlainObjectType_t>> solver(*this, EigenvaluesOnly); // as advised by the Eigen developers even though this is a UB auto & values = const_cast &>(values_); values = solver.eigenvalues(); } template template EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void MatrixBase::eigh(const MatrixBase & values_, const MatrixBase & vectors_, bool sort) const { SelfAdjointEigenSolver< akantu::details::MapPlainObjectType_t>> solver(*this, ComputeEigenvectors); // as advised by the Eigen developers, even though this is a UB auto & values = const_cast &>(values_); auto & vectors = const_cast &>(vectors_); if (not sort) { values = solver.eigenvalues(); vectors = solver.eigenvectors(); return; } values = solver.eigenvalues(); PermutationMatrix P(values.size()); P.setIdentity(); std::sort(P.indices().data(), P.indices().data() + P.indices().size(), [&values](const Index & a, const Index & b) { return (values(a) - values(b)) > 0; }); values = P.transpose() * values; vectors = solver.eigenvectors() * P; // permutes the columns (eigen vectors) } } // namespace Eigen namespace std { template struct is_convertible, Eigen::Map> : aka::bool_constant::value> {}; } // namespace std #endif /* AKANTU_AKA_TYPES_HH */