version 0.4
linearalgebrahelper.hh
Go to the documentation of this file.
1// SPDX-FileCopyrightText: 2021-2024 The Ikarus Developers mueller@ibb.uni-stuttgart.de
2// SPDX-License-Identifier: LGPL-3.0-or-later
3
9#pragma once
10#include "concepts.hh"
11#include "traits.hh"
12
13#include <iosfwd>
14#include <random>
15#include <ranges>
16
17#include <dune/common/tuplevector.hh>
18#include <dune/functions/functionspacebases/lagrangebasis.hh>
19#include <dune/istl/bvector.hh>
20
21#include <Eigen/Core>
22
23#include <autodiff/forward/dual/dual.hpp>
24
25namespace Ikarus {
26
34 template <typename Derived>
35 auto orthonormalizeMatrixColumns(const Eigen::MatrixBase<Derived>& A) {
36 // Gram Schmidt Ortho
37 auto Q = A.eval();
38
39 Q.col(0).normalize();
40
41 for (int colIndex = 1; colIndex < Q.cols(); colIndex++) {
42 Q.col(colIndex) -= Q.leftCols(colIndex) * (Q.leftCols(colIndex).transpose() * A.col(colIndex));
43 Q.col(colIndex).normalize();
44 }
45
46 return Q;
47 }
48
56 template <typename ValueType>
57 auto viewAsFlatEigenVector(Dune::BlockVector<ValueType>& blockedVector) {
58 Eigen::Map<Eigen::VectorX<typename ValueType::field_type>> vec(&blockedVector.begin()->begin().operator*(),
59 blockedVector.size() * blockedVector[0].size());
60
61 return vec;
62 }
63
71 template <typename ValueType>
72 auto viewAsFlatEigenVector(const Dune::BlockVector<ValueType>& blockedVector) {
73 Eigen::Map<const Eigen::VectorX<typename ValueType::field_type>> vec(
74 &blockedVector.begin()->begin().operator*(), blockedVector.size() * blockedVector[0].size());
75
76 return vec;
77 }
78
87 template <typename ValueType>
88 auto viewAsEigenMatrixAsDynFixed(Dune::BlockVector<ValueType>& blockedVector) {
89 Eigen::Map<Eigen::Matrix<typename ValueType::field_type, Eigen::Dynamic, ValueType::valueSize, Eigen::RowMajor>>
90 vec(&blockedVector.begin()->begin().operator*(), blockedVector.size(), blockedVector[0].size());
91
92 return vec;
93 }
94
103 template <typename ValueType>
104 auto viewAsEigenMatrixAsDynFixed(const Dune::BlockVector<ValueType>& blockedVector) {
105 Eigen::Map<
106 const Eigen::Matrix<typename ValueType::field_type, Eigen::Dynamic, ValueType::valueSize, Eigen::RowMajor>>
107 vec(&blockedVector.begin()->begin().operator*(), blockedVector.size(), blockedVector[0].size());
108
109 return vec;
110 }
111
120 template <typename ValueType>
121 auto viewAsEigenMatrixFixedDyn(Dune::BlockVector<ValueType>& blockedVector) {
122 Eigen::Map<Eigen::Matrix<typename ValueType::field_type, ValueType::valueSize, Eigen::Dynamic>> vec(
123 &blockedVector.begin()->begin().operator*(), blockedVector[0].size(), blockedVector.size());
124
125 return vec;
126 }
127
135 template <typename ValueType>
136 auto viewAsEigenMatrixFixedDyn(const Dune::BlockVector<ValueType>& blockedVector) {
137 Eigen::Map<const Eigen::Matrix<typename ValueType::field_type, ValueType::valueSize, Eigen::Dynamic>> vec(
138 &blockedVector.begin()->begin().operator*(), blockedVector[0].size(), blockedVector.size());
139
140 return vec;
141 }
142
150 template <typename Type>
151 size_t correctionSize(const Dune::BlockVector<Type>& a) requires requires {
153 }
154 { return a.size() * Type::correctionSize; }
155
163 template <typename Type>
164 size_t valueSize(const Dune::BlockVector<Type>& a) requires requires {
166 }
167 { return a.size() * Type::valueSize; }
168
178 template <typename Type, typename Derived>
179 Dune::BlockVector<Type>& operator+=(Dune::BlockVector<Type>& a, const Eigen::MatrixBase<Derived>& b) requires(
180 Ikarus::Concepts::AddAssignAble<Type, decltype(b.template segment<Type::correctionSize>(0))>and requires() {
182 }) {
183 assert(correctionSize(a) == static_cast<size_t>(b.size()) && " The passed vector has wrong size");
184 for (auto i = 0U; i < a.size(); ++i)
185 a[i] += b.template segment<Type::correctionSize>(i * Type::correctionSize);
186 return a;
187 }
188
198 template <typename Type, typename Derived>
199 Dune::BlockVector<Type>& operator-=(Dune::BlockVector<Type>& a, const Eigen::MatrixBase<Derived>& b) requires(
200 Ikarus::Concepts::AddAssignAble<Type, decltype(b.template segment<Type::correctionSize>(0))>and requires() {
202 }) {
203 return a += (-b);
204 }
205
215 template <typename... Types, typename Derived>
216 Dune::TupleVector<Types...>& operator+=(Dune::TupleVector<Types...>& a, const Eigen::MatrixBase<Derived>& b) {
217 using namespace Dune::Indices;
218 size_t posStart = 0;
219 Dune::Hybrid::forEach(Dune::Hybrid::integralRange(Dune::index_constant<sizeof...(Types)>()), [&](const auto i) {
220 const size_t size = correctionSize(a[i]);
221 a[i] += b(Eigen::seqN(posStart, size));
222 posStart += size;
223 });
224
225 return a;
226 }
227
237 template <typename ManifoldPoint, typename Derived>
238 Dune::BlockVector<ManifoldPoint>&
239 addInEmbedding(Dune::BlockVector<ManifoldPoint>& a, const Eigen::MatrixBase<Derived>& b) requires(
241 decltype(b.template segment<ManifoldPoint::valueSize>(0))>and requires() {
243 }) {
244 assert(valueSize(a) == static_cast<size_t>(b.size()) && " The passed vector has wrong size");
245 for (auto i = 0U; i < a.size(); ++i)
246 a[i].addInEmbedding(b.template segment<ManifoldPoint::valueSize>(i * ManifoldPoint::valueSize));
247 return a;
248 }
249
257 template <typename Derived>
258 requires(!std::floating_point<Derived>) auto norm(const Eigen::MatrixBase<Derived>& v) { return v.norm(); }
259
266 auto norm(const std::floating_point auto& v) { return std::abs(v); }
267
277 template <typename Scalar, int size>
278 auto operator*(const Eigen::DiagonalMatrix<Scalar, size>& a, const Eigen::DiagonalMatrix<Scalar, size>& b) {
279 return (a.diagonal().cwiseProduct(b.diagonal())).asDiagonal();
280 }
281
291 template <typename Scalar, int size>
292 auto operator+=(Eigen::DiagonalMatrix<Scalar, size>& a, const Eigen::DiagonalMatrix<Scalar, size>& b) {
293 a.diagonal() += b.diagonal();
294 return a;
295 }
296
307 template <typename Derived, typename Scalar, int size>
308 auto operator+(const Eigen::MatrixBase<Derived>& a, const Eigen::DiagonalMatrix<Scalar, size>& b) {
309 auto c = a.derived().eval();
310 c.diagonal() += b.diagonal();
311 return c;
312 }
313
324 template <typename Derived, typename Scalar, int size>
325 auto operator+(const Eigen::DiagonalMatrix<Scalar, size>& a, const Eigen::MatrixBase<Derived>& b) {
326 return b + a;
327 }
328
337 template <typename Scalar, int size>
338 auto operator-(const Eigen::DiagonalMatrix<Scalar, size>& a) {
339 return (-a.diagonal()).asDiagonal();
340 }
341
351 template <typename Derived, typename Derived2>
352 auto operator+(const Eigen::MatrixBase<Derived>& a, const Eigen::DiagonalWrapper<Derived2>& b) {
353 auto c = a.derived().eval();
354 c.diagonal() += b.diagonal();
355 return c;
356 }
357
367 template <typename Derived, typename Derived2>
368 auto operator+(const Eigen::DiagonalWrapper<Derived>& a, const Eigen::MatrixBase<Derived2>& b) {
369 return b + a;
370 }
371
381 template <typename Scalar, int size>
382 std::ostream& operator<<(std::ostream& os, const Eigen::DiagonalMatrix<Scalar, size>& a) {
383 os << Eigen::Matrix<Scalar, size, size>(a);
384 return os;
385 }
386
394 template <typename Derived>
395 Derived sym(const Eigen::MatrixBase<Derived>& A) {
396 return 0.5 * (A + A.transpose());
397 }
398
406 template <typename Derived>
407 Derived skew(const Eigen::MatrixBase<Derived>& A) {
408 return 0.5 * (A - A.transpose());
409 }
410
417 template <typename Derived>
419 Eigen::IOFormat mapleFmt(Eigen::FullPrecision, 0, ", ", "|\n", "<", ">", "<", ">");
420 if constexpr (std::convertible_to<Derived, const Eigen::MatrixBase<Derived>&>) {
421 std::cout << "\n" << A.derived().format(mapleFmt) << std::endl;
422 } else { // branch for Eigen::DiagonalMatrix
423 using Scalar = typename Derived::Scalar;
424 using namespace Eigen;
425 constexpr int diag_size = EIGEN_SIZE_MIN_PREFER_DYNAMIC(Derived::RowsAtCompileTime, Derived::ColsAtCompileTime);
426 std::cout << "\n"
427 << Eigen::Matrix<Scalar, diag_size, diag_size>(A.derived().diagonal().asDiagonal()).format(mapleFmt)
428 << std::endl;
429 }
430 }
431
440 template <typename FieldVectorT>
441 auto createRandomVector(typename FieldVectorT::value_type lower = -1, typename FieldVectorT::value_type upper = 1) {
442 std::random_device rd;
443 std::mt19937 mt(rd());
444 std::uniform_real_distribution<typename FieldVectorT::value_type> dist(lower, upper);
445 auto rand = [&dist, &mt]() { return dist(mt); };
446 FieldVectorT vec;
447 std::generate(vec.begin(), vec.end(), rand);
448 return vec;
449 }
450
458 template <typename ScalarType>
459 Eigen::Matrix<ScalarType, 3, 3> skew(const Eigen::Vector<ScalarType, 3>& a) {
460 Eigen::Matrix<ScalarType, 3, 3> A;
461 A << 0, -a(2), a(1), a(2), 0, -a(0), -a(1), a(0), 0;
462 return A;
463 }
464
465 namespace Impl {
466 constexpr std::tuple<std::array<std::array<int, 2>, 1>, std::array<std::array<int, 2>, 3>,
467 std::array<std::array<int, 2>, 6>>
468 voigtIndices = {{{{0, 0}}}, {{{0, 0}, {1, 1}, {0, 1}}}, {{{0, 0}, {1, 1}, {2, 2}, {1, 2}, {0, 2}, {0, 1}}}};
469 }
470
479 template <int dim>
480 constexpr auto voigtNotationContainer = std::get<dim - 1>(Impl::voigtIndices);
481
494 template <typename Derived, size_t sizeOfCondensedIndices>
495 auto staticCondensation(const Eigen::MatrixBase<Derived>& E,
496 const std::array<size_t, sizeOfCondensedIndices>& indices) {
497 constexpr size_t colsFull = std::remove_cvref_t<Derived>::ColsAtCompileTime;
498 constexpr size_t rowsFull = std::remove_cvref_t<Derived>::RowsAtCompileTime;
499 static_assert(colsFull == rowsFull, "staticCondensation only allowed for square matrices");
500 std::array<size_t, rowsFull - sizeOfCondensedIndices> remainingIndices{};
501 std::ranges::set_difference(std::ranges::iota_view(size_t(0), size_t(colsFull)), indices, remainingIndices.begin());
502
503 auto K11 = E(remainingIndices, remainingIndices);
504 auto K12 = E(indices, remainingIndices);
505 auto K22 = E(indices, indices);
506
507 return (K11 - K12.transpose() * K22.inverse() * K12).eval();
508 }
509
522 template <typename Derived, size_t sizeOfRemovedCols>
523 auto removeCol(const Eigen::MatrixBase<Derived>& E, const std::array<size_t, sizeOfRemovedCols>& indices) {
524 constexpr size_t colsFull = std::remove_cvref_t<Derived>::ColsAtCompileTime;
525 constexpr size_t rowsFull = std::remove_cvref_t<Derived>::RowsAtCompileTime;
526 static_assert(colsFull == 1);
527
528 std::array<size_t, rowsFull - sizeOfRemovedCols> remainingIndices{};
529 std::ranges::set_difference(std::ranges::iota_view(size_t(0), size_t(rowsFull)), indices, remainingIndices.begin());
530
531 return (E(remainingIndices)).eval();
532 }
533
548 template <typename ST, typename MaterialImpl>
549 auto toVoigtAndMaybeReduce(const Eigen::Matrix<ST, 3, 3>& E, [[maybe_unused]] const MaterialImpl& material,
550 bool isStrain = true) {
551 if constexpr (!MaterialImpl::isReduced)
552 return toVoigt(E, isStrain);
553 else {
554 auto ev = toVoigt(E, isStrain);
555 static_assert(decltype(ev)::RowsAtCompileTime == 6 and decltype(ev)::ColsAtCompileTime == 1);
556
557 auto evRed = removeCol(ev, MaterialImpl::fixedVoigtIndices);
558 static_assert(decltype(evRed)::RowsAtCompileTime == 6 - MaterialImpl::fixedVoigtIndices.size()
559 and decltype(evRed)::ColsAtCompileTime == 1);
560 return evRed;
561 }
562 }
563
576 template <typename Material, typename Derived>
577 decltype(auto) enlargeIfReduced(const Eigen::MatrixBase<Derived>& E) {
578 if constexpr (!Concepts::EigenVector6<Derived> and Concepts::EigenVector<Derived>) {
579 static_assert(Material::isReduced, "You should only end up here, if your material is reduced");
580
581 auto freeindices = Material::MaterialImplType::freeVoigtIndices;
582 auto p_E = Eigen::Vector<typename Material::MaterialImplType::ScalarType, 6>::Zero().eval();
583 for (int ri = 0; auto i : freeindices)
584 p_E(i) = E(ri++);
585 return p_E;
586
587 } else if constexpr (Concepts::EigenMatrix66<
588 Derived> or Concepts::EigenMatrix33<Derived> or Concepts::EigenVector6<Derived>) {
589 return E.derived();
590 } else {
591 static_assert(Material::isReduced, "You should only end up here, if your material is reduced");
592
593 auto freeindices = Material::MaterialImpl::freeVoigtIndices;
594 auto p_E = Eigen::Matrix<typename Material::MaterialImpl::ScalarType, 6, 6>::Zero().eval();
595 for (int ri = 0; auto i : freeindices) {
596 for (int rj = 0; auto j : freeindices)
597 p_E(i, j) = E(ri, rj++);
598 ++ri;
599 }
600 return p_E;
601 }
602 }
603
604} // namespace Ikarus
Several concepts.
Contains stl-like type traits.
auto operator+(const Eigen::MatrixBase< Derived > &a, const Eigen::DiagonalMatrix< Scalar, size > &b)
Eigen::Matrix + Eigen::DiagonalMatrix addition missing in Eigen.
Definition: linearalgebrahelper.hh:308
Dune::BlockVector< Type > & operator-=(Dune::BlockVector< Type > &a, const Eigen::MatrixBase< Derived > &b)
Enables the -= operator for Dune::BlockVector += Eigen::Vector.
Definition: linearalgebrahelper.hh:199
auto norm(const Eigen::MatrixBase< Derived > &v)
Adding free norm function to Eigen types.
Definition: linearalgebrahelper.hh:258
Derived skew(const Eigen::MatrixBase< Derived > &A)
Returns the skew part of a matrix.
Definition: linearalgebrahelper.hh:407
auto staticCondensation(const Eigen::MatrixBase< Derived > &E, const std::array< size_t, sizeOfCondensedIndices > &indices)
Performs static condensation on a square matrix.
Definition: linearalgebrahelper.hh:495
auto removeCol(const Eigen::MatrixBase< Derived > &E, const std::array< size_t, sizeOfRemovedCols > &indices)
Removes specified columns from a matrix.
Definition: linearalgebrahelper.hh:523
decltype(auto) enlargeIfReduced(const Eigen::MatrixBase< Derived > &E)
Enlarges a matrix if it reduced in the context of material laws, i.e., VanishingStress If the materia...
Definition: linearalgebrahelper.hh:577
auto toVoigtAndMaybeReduce(const Eigen::Matrix< ST, 3, 3 > &E, const MaterialImpl &material, bool isStrain=true)
Converts a 3x3 matrix to Voigt notation, possibly reducing it based on material properties.
Definition: linearalgebrahelper.hh:549
void printForMaple(const Eigen::EigenBase< Derived > &A)
Method to print the matrix in a format that can directly be copied to Maple.
Definition: linearalgebrahelper.hh:418
auto viewAsFlatEigenVector(Dune::BlockVector< ValueType > &blockedVector)
View Dune::BlockVector as an Eigen::Vector.
Definition: linearalgebrahelper.hh:57
size_t correctionSize(const Dune::BlockVector< Type > &a)
Returns the total correction size of a block vector with a Manifold as the underlying type.
Definition: linearalgebrahelper.hh:151
auto createRandomVector(typename FieldVectorT::value_type lower=-1, typename FieldVectorT::value_type upper=1)
Creates a random vector of the specified type within a given range.
Definition: linearalgebrahelper.hh:441
constexpr auto voigtNotationContainer
Container for Voigt notation indices based on dimension.1D: 0,0 2D: 0,0 1,1 0,1 3D: 0,...
Definition: linearalgebrahelper.hh:480
auto operator-(const Eigen::DiagonalMatrix< Scalar, size > &a)
Unary minus for Eigen::DiagonalMatrix.
Definition: linearalgebrahelper.hh:338
auto orthonormalizeMatrixColumns(const Eigen::MatrixBase< Derived > &A)
Orthonormalizes all Matrix columns using Gram-Schmidt Orthogonalization.
Definition: linearalgebrahelper.hh:35
Derived sym(const Eigen::MatrixBase< Derived > &A)
Returns the symmetric part of a matrix.
Definition: linearalgebrahelper.hh:395
size_t valueSize(const Dune::BlockVector< Type > &a)
Returns the total value size of a block vector with a Manifold as the underlying type.
Definition: linearalgebrahelper.hh:164
auto viewAsEigenMatrixFixedDyn(Dune::BlockVector< ValueType > &blockedVector)
View Dune::BlockVector as an Eigen::Matrix with fixed rows depending on the size of the ValueType and...
Definition: linearalgebrahelper.hh:121
std::ostream & operator<<(std::ostream &os, const Eigen::DiagonalMatrix< Scalar, size > &a)
Output stream operator for Eigen::DiagonalMatrix.
Definition: linearalgebrahelper.hh:382
auto operator*(const Eigen::DiagonalMatrix< Scalar, size > &a, const Eigen::DiagonalMatrix< Scalar, size > &b)
Eigen::DiagonalMatrix Product Missing in Eigen.
Definition: linearalgebrahelper.hh:278
Dune::BlockVector< Type > & operator+=(Dune::BlockVector< Type > &a, const Eigen::MatrixBase< Derived > &b)
Enables the += operator for Dune::BlockVector += Eigen::Vector.
Definition: linearalgebrahelper.hh:179
Dune::BlockVector< ManifoldPoint > & addInEmbedding(Dune::BlockVector< ManifoldPoint > &a, const Eigen::MatrixBase< Derived > &b)
Enables the addition in the embedding space of a vector in the space M^n, where M is a manifold with ...
Definition: linearalgebrahelper.hh:239
auto viewAsEigenMatrixAsDynFixed(Dune::BlockVector< ValueType > &blockedVector)
View Dune::BlockVector as an Eigen::Matrix with dynamic rows and fixed columns depending on the size ...
Definition: linearalgebrahelper.hh:88
constexpr Eigen::Index toVoigt(Eigen::Index i, Eigen::Index j) noexcept
Converts 2D indices to Voigt notation index.
Definition: tensorutils.hh:167
Definition: simpleassemblers.hh:21
Definition: truncatedconjugategradient.hh:24
static constexpr bool isReduced
Static constant for determining if the material has vanishing stress components (is reduced).
Definition: interface.hh:81
Definition: concepts.hh:25
Concept defining the requirements for types that support in-place addition.
Definition: concepts.hh:310
Concept defining the requirements for Eigen vectors.
Definition: concepts.hh:381