13#include <unsupported/Eigen/CXX11/Tensor>
15#include <dune/common/promotiontraits.hh>
31template <
typename Derived,
typename T, auto rank>
33 const std::array<T, rank>& dims) {
34 return Eigen::TensorMap<
const Eigen::TensorFixedSize<
35 const typename Derived::Scalar, Eigen::Sizes<Derived::RowsAtCompileTime, Derived::ColsAtCompileTime>>>(
36 matrix.derived().eval().data(), dims);
47auto dyadic(
const auto& A_ij,
const auto& B_kl) {
48 Eigen::array<Eigen::IndexPair<long>, 0> empty_index_list = {};
49 return A_ij.contract(B_kl, empty_index_list).eval();
60template <
typename ST,
int size>
61auto dyadic(
const Eigen::Vector<ST, size>& a,
const Eigen::Vector<ST, size>& b) {
62 return (a * b.transpose()).eval();
72template <
typename ScalarType =
double,
int dim = 3>
74 Eigen::TensorFixedSize<ScalarType, Eigen::Sizes<dim, dim, dim, dim>> idTensor;
75 for (
int i = 0; i < dim; ++i)
76 for (
int j = 0; j < dim; ++j)
77 for (
int k = 0; k < dim; ++k)
78 for (
int l = 0; l < dim; ++l)
79 idTensor(i, j, k, l) = 0.5 * ((i == k) * (j == l) + (i == l) * (j == k));
94template <
typename ScalarType =
double,
int dim = 3>
96 Eigen::TensorFixedSize<ScalarType, Eigen::Sizes<dim, dim, dim, dim>> res;
97 for (
int i = 0; i < dim; ++i)
98 for (
int j = 0; j < dim; ++j)
99 for (
int k = 0; k < dim; ++k)
100 for (
int l = 0; l < dim; ++l)
101 res(i, j, k, l) = 0.5 * (A(i, k) * B(j, l) + A(i, l) * B(j, k));
113template <
typename ScalarType =
double,
int dim = 3>
115 Eigen::TensorFixedSize<ScalarType, Eigen::Sizes<dim, dim, dim, dim>> idTensor;
117 for (
int i = 0; i < dim; ++i)
118 for (
int k = 0; k < dim; ++k)
119 idTensor(i, i, k, k) = 1.0;
134template <
typename AType,
typename BType>
135auto fourthOrderIKJL(
const Eigen::MatrixBase<AType>& A,
const Eigen::MatrixBase<BType>& B) {
136 static_assert(AType::RowsAtCompileTime == BType::RowsAtCompileTime);
137 static_assert(AType::ColsAtCompileTime == BType::ColsAtCompileTime);
138 using ScalarResultType =
typename Dune::PromotionTraits<typename AType::Scalar, typename BType::Scalar>::PromotedType;
139 constexpr int dim = AType::RowsAtCompileTime;
140 Eigen::TensorFixedSize<ScalarResultType, Eigen::Sizes<dim, dim, dim, dim>> res;
141 for (
int i = 0; i < dim; ++i)
142 for (
int j = 0; j < dim; ++j)
143 for (
int k = 0; k < dim; ++k)
144 for (
int l = 0; l < dim; ++l)
145 res(i, j, k, l) = A(i, k) * B(j, l);
157template <
typename ScalarType,
long int dim>
158auto symTwoSlots(
const Eigen::TensorFixedSize<ScalarType, Eigen::Sizes<dim, dim, dim, dim>>& t,
159 const std::array<size_t, 2>& slots) {
160 std::array<size_t, 4> shuffleSlot;
161 std::iota(shuffleSlot.begin(), shuffleSlot.end(), 0);
162 std::swap(shuffleSlot[slots[0]], shuffleSlot[slots[1]]);
163 return (0.5 * (t + t.shuffle(shuffleSlot))).eval();
179constexpr Eigen::Index
toVoigt(Eigen::Index i, Eigen::Index j)
noexcept {
182 if ((i == 1 and j == 2) or (i == 2 and j == 1))
184 if ((i == 0 and j == 2) or (i == 2 and j == 0))
186 if ((i == 0 and j == 1) or (i == 1 and j == 0))
188 assert(i < 3 and j < 3 &&
"For Voigt notation the indices need to be 0,1 or 2.");
189 __builtin_unreachable();
206template <
typename ScalarType =
double>
207Eigen::Matrix<ScalarType, 6, 6>
toVoigt(
const Eigen::TensorFixedSize<ScalarType, Eigen::Sizes<3, 3, 3, 3>>& ft) {
208 Eigen::Matrix<ScalarType, 6, 6> mat;
209 for (Eigen::Index i = 0; i < 3; ++i)
210 for (Eigen::Index j = 0; j < 3; ++j)
211 for (Eigen::Index k = 0; k < 3; ++k)
212 for (Eigen::Index l = 0; l < 3; ++l)
236template <
typename ST,
int size,
int Options,
int maxSize>
237requires((size > 0 and size <= 3) or (maxSize > 0 and maxSize <= 3 and size == Eigen::Dynamic))
238auto toVoigt(
const Eigen::Matrix<ST, size, size, Options, maxSize, maxSize>& E,
bool isStrain =
true) {
239 constexpr bool isFixedSized = (size != Eigen::Dynamic);
240 const ST possibleStrainFactor = isStrain ? 2.0 : 1.0;
242 const size_t inputSize = isFixedSized ? size : E.rows();
243 auto EVoigt = [&]() {
244 if constexpr (isFixedSized) {
245 Eigen::Vector<ST, (size * (size + 1)) / 2> EVoigt;
246 EVoigt.template head<size>() = E.diagonal();
249 Eigen::Matrix<ST, Eigen::Dynamic, 1, Options, 6, 1> EVoigt;
250 EVoigt.resize((inputSize * (inputSize + 1)) / 2);
251 EVoigt.template head(inputSize) = E.diagonal();
257 EVoigt(2) = E(0, 1) * possibleStrainFactor;
258 else if (inputSize == 3) {
259 EVoigt(inputSize) = E(1, 2) * possibleStrainFactor;
260 EVoigt(inputSize + 1) = E(0, 2) * possibleStrainFactor;
261 EVoigt(inputSize + 2) = E(0, 1) * possibleStrainFactor;
281template <
typename ST,
int size,
int Options,
int maxSize>
282requires((size == 1 or size == 3 or size == 6) or
283 ((maxSize == 1 or maxSize == 3 or maxSize == 6) and size ==
Eigen::Dynamic))
284auto
fromVoigt(const
Eigen::Matrix<ST, size, 1, Options, maxSize, 1>& EVoigt,
bool isStrain = true) {
285 constexpr bool isFixedSized = (size != Eigen::Dynamic);
286 const ST possibleStrainFactor = isStrain ? 0.5 : 1.0;
288 const size_t inputSize = isFixedSized ? size : EVoigt.size();
289 const size_t matrixSize =
290 isFixedSized ? (-1 +
ct_sqrt(1 + 8 * size)) / 2 : (-1 +
static_cast<int>(std::sqrt(1 + 8 * inputSize))) / 2;
293 if constexpr (isFixedSized) {
294 Eigen::Matrix<ST, matrixSize, matrixSize> E;
295 E.diagonal() = EVoigt.template head<matrixSize>();
298 Eigen::Matrix<ST, Eigen::Dynamic, Eigen::Dynamic, Options, 3, 3> E;
299 E.resize(matrixSize, matrixSize);
300 E.diagonal() = EVoigt.template head(matrixSize);
305 if (matrixSize == 2) {
306 E(0, 1) = E(1, 0) = EVoigt(2) * possibleStrainFactor;
307 }
else if (matrixSize == 3) {
308 E(2, 1) = E(1, 2) = EVoigt(matrixSize) * possibleStrainFactor;
309 E(2, 0) = E(0, 2) = EVoigt(matrixSize + 1) * possibleStrainFactor;
310 E(1, 0) = E(0, 1) = EVoigt(matrixSize + 2) * possibleStrainFactor;
339 assert(i < 6 &&
"For Voigt notation the indices need to be 0 and 5.");
340 __builtin_unreachable();
355template <
typename ScalarType>
356auto fromVoigt(
const Eigen::Matrix<ScalarType, 6, 6>& CVoigt) {
357 Eigen::TensorFixedSize<ScalarType, Eigen::Sizes<3, 3, 3, 3>> C;
359 for (
size_t i = 0; i < 6; ++i) {
360 for (
size_t j = 0; j < 6; ++j) {
363 C(firstIndices[0], firstIndices[1], secondIndices[0], secondIndices[1]) = CVoigt(i, j);
379template <
typename Geometry>
381 const auto& referenceElement = Dune::ReferenceElements<double, 2>::general(geometry.type());
382 const auto quadPos0 = referenceElement.position(0, 0);
384 const auto jacobianinvT0 = toEigen(geometry.jacobianInverseTransposed(quadPos0));
385 const auto detJ0 = geometry.integrationElement(quadPos0);
387 auto jaco = (jacobianinvT0).inverse().eval();
388 auto J11 = jaco(0, 0);
389 auto J12 = jaco(0, 1);
390 auto J21 = jaco(1, 0);
391 auto J22 = jaco(1, 1);
394 { J11 * J11, J12 * J12, J11 * J12},
395 { J21 * J21, J22 * J22, J21 * J22},
396 {2.0 * J11 * J21, 2.0 * J12 * J22, J21 * J12 + J11 * J22}
399 return T0.inverse() * detJ0;
412template <
typename Geometry>
414 const auto& referenceElement = Dune::ReferenceElements<double, 3>::general(geometry.type());
415 const auto quadPos0 = referenceElement.position(0, 0);
417 const auto jacobianinvT0 = toEigen(geometry.jacobianInverseTransposed(quadPos0));
418 const auto detJ0 = geometry.integrationElement(quadPos0);
420 auto jaco = (jacobianinvT0).inverse().eval();
421 auto J11 = jaco(0, 0);
422 auto J12 = jaco(0, 1);
423 auto J13 = jaco(0, 2);
424 auto J21 = jaco(1, 0);
425 auto J22 = jaco(1, 1);
426 auto J23 = jaco(1, 2);
427 auto J31 = jaco(2, 0);
428 auto J32 = jaco(2, 1);
429 auto J33 = jaco(2, 2);
432 Eigen::Matrix<double, 6, 6> T0 {
433 {J11 * J11, J12 * J12, J13 * J13, J11 * J12, J11 * J13, J12 * J13},
434 {J21 * J21, J22 * J22, J23 * J23, J21 * J22, J21 * J23, J22 * J23},
435 {J31 * J31, J32 * J32, J33 * J33, J31 * J32, J31 * J33, J32 * J33},
436 {2.0 * J11 * J21, 2.0 * J12 * J22, 2.0 * J13 * J23, J11 * J22 + J21 * J12, J11 * J23 + J21 * J13, J12 * J23 + J22 * J13},
437 {2.0 * J11 * J31, 2.0 * J12 * J32, 2.0 * J13 * J33, J11 * J32 + J31 * J12, J11 * J33 + J31 * J13, J12 * J33 + J32 * J13},
438 {2.0 * J31 * J21, 2.0 * J32 * J22, 2.0 * J33 * J23, J31 * J22 + J21 * J32, J31 * J23 + J21 * J33, J32 * J23 + J22 * J33}
442 return T0.inverse() * detJ0;
Implementation of math related algorithms.
auto symmetricIdentityFourthOrder()
Generates a symmetric identity fourth-order tensor.
Definition: tensorutils.hh:73
auto symmetricFourthOrder(const auto &A, const auto &B)
Generates a symmetric fourth-order tensor based on two second-order input tensors.
Definition: tensorutils.hh:95
constexpr Eigen::Index toVoigt(Eigen::Index i, Eigen::Index j) noexcept
Converts 2D indices to Voigt notation index.
Definition: tensorutils.hh:179
Eigen::Tensor< typename Derived::Scalar, rank > tensorView(const Eigen::EigenBase< Derived > &matrix, const std::array< T, rank > &dims)
View an Eigen matrix as an Eigen Tensor with specified dimensions.
Definition: tensorutils.hh:32
auto fourthOrderIKJL(const Eigen::MatrixBase< AType > &A, const Eigen::MatrixBase< BType > &B)
Computes the IKJL product of two matrices.
Definition: tensorutils.hh:135
auto dyadic(const auto &A_ij, const auto &B_kl)
Computes the dyadic product of two Eigen tensors.
Definition: tensorutils.hh:47
auto identityFourthOrder()
Generates an identity fourth-order tensor.
Definition: tensorutils.hh:114
auto fromVoigt(const Eigen::Matrix< ST, size, 1, Options, maxSize, 1 > &EVoigt, bool isStrain=true)
Converts a vector given in Voigt notation to a matrix.
Definition: tensorutils.hh:284
auto symTwoSlots(const Eigen::TensorFixedSize< ScalarType, Eigen::Sizes< dim, dim, dim, dim > > &t, const std::array< size_t, 2 > &slots)
Creates a symmetric fourth-order tensor in the two specified slots of the input tensor.
Definition: tensorutils.hh:158
Definition: assemblermanipulatorbuildingblocks.hh:22
Eigen::Matrix3d calcTransformationMatrix2D(const Geometry &geometry)
Calculates the 2D transformation matrix.
Definition: tensorutils.hh:380
Eigen::Matrix< double, 6, 6 > calcTransformationMatrix3D(const Geometry &geometry)
Calculates the 3D transformation matrix.
Definition: tensorutils.hh:413
constexpr T ct_sqrt(T x)
Compile-time square root for integer types.
Definition: math.hh:47
Definition: truncatedconjugategradient.hh:24
Definition: utils/concepts.hh:30