version 0.4
autodifffe.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
11#include <autodiff/forward/dual/dual.hpp>
12#include <autodiff/forward/dual/eigen.hpp>
13
17
18namespace Ikarus {
19
29 template <typename RealFE_, typename FERequirementType_ = FERequirements<>, bool useEigenRef = false,
30 bool forceAutoDiff = false>
31 class AutoDiffFE : public RealFE_ {
32 public:
33 using RealFE = RealFE_;
34 using Basis = typename RealFE::Basis;
36 using LocalView = typename Traits::LocalView;
37 using Element = typename Traits::Element;
39
46 void calculateMatrix(const FERequirementType& req, typename Traits::template MatrixType<> h) const {
47 // real element implements calculateMatrix by itself, then we simply forward the call
48 if constexpr (requires { RealFE::calculateMatrix(req, h); } and not forceAutoDiff) {
49 RealFE::calculateMatrix(req, h);
50 } else if constexpr (requires {
51 this->template calculateVectorImpl<autodiff::dual>(
52 req, std::declval<typename Traits::template VectorType<autodiff::dual>>(),
53 std::declval<const Eigen::VectorXdual&>());
54 }) {
55 // real element implements calculateVector by itself, therefore we only need first order derivatives
56 Eigen::VectorXdual dx(this->localView().size());
57 Eigen::VectorXdual g(this->localView().size());
58 dx.setZero();
59 auto f = [&](auto& x) -> auto& {
60 g.setZero();
61 this->template calculateVectorImpl<autodiff::dual>(req, g, x);
62 return g;
63 };
64 jacobian(f, autodiff::wrt(dx), at(dx), g, h);
65 } else if constexpr (requires {
66 this->template calculateScalarImpl<autodiff::dual2nd>(
67 req, std::declval<typename Traits::template VectorType<autodiff::dual2nd>>());
68 }) {
69 // real element implements calculateScalar by itself, therefore we need second order derivatives
70 Eigen::VectorXdual2nd dx(this->localView().size());
71 Eigen::VectorXd g;
72 autodiff::dual2nd e;
73 dx.setZero();
74 auto f = [&](auto& x) { return this->template calculateScalarImpl<autodiff::dual2nd>(req, x); };
75 hessian(f, autodiff::wrt(dx), at(dx), e, g, h);
76 } else
77 static_assert(Dune::AlwaysFalse<AutoDiffFE>::value,
78 "Appropriate calculateScalarImpl or calculateVectorImpl functions are not implemented for the "
79 "chosen element.");
80 }
81
88 void calculateVector(const FERequirementType& req, typename Traits::template VectorType<> g) const {
89 // real element implements calculateVector by itself, then we simply forward the call
90 if constexpr (requires {
91 this->template calculateVectorImpl<double>(
92 req, std::declval<typename Traits::template VectorType<double>>(),
93 std::declval<const Eigen::VectorXd&>());
94 }
95 and not forceAutoDiff) {
96 return this->template calculateVectorImpl<double>(req, g);
97 } else if constexpr (requires {
98 this->template calculateScalarImpl<autodiff::dual>(
99 req, std::declval<const Eigen::VectorXdual&>());
100 }) {
101 // real element implements calculateScalar by itself, therefore we need first order derivatives
102 Eigen::VectorXdual dx(this->localView().size());
103 dx.setZero();
104 autodiff::dual e;
105 auto f = [&](auto& x) { return this->template calculateScalarImpl<autodiff::dual>(req, x); };
106 gradient(f, autodiff::wrt(dx), at(dx), e, g);
107 } else
108 static_assert(Dune::AlwaysFalse<AutoDiffFE>::value,
109 "Appropriate calculateScalarImpl function is not implemented for the "
110 "chosen element.");
111 }
112
120 void calculateLocalSystem(const FERequirementType& req, typename Traits::template MatrixType<> h,
121 typename Traits::template VectorType<> g) const {
122 Eigen::VectorXdual2nd dx(this->localView().size());
123 dx.setZero();
124 auto f = [&](auto& x) { return this->calculateScalarImpl(req, x); };
125 hessian(f, autodiff::wrt(dx), at(dx), g, h);
126 }
127
134 [[nodiscard]] double calculateScalar(const FERequirementType& par) const {
135 // real element implements calculateScalar by itself, then we simply forward the call
136 if constexpr (requires { RealFE::calculateScalar(par); }) {
137 return RealFE::calculateScalar(par);
138 } else if constexpr (requires { this->calculateScalarImpl(par); }) {
139 // real element only implements the protected calculateScalarImpl by itself, thus we call that one.
140 return this->calculateScalarImpl(par);
141 } else {
142 static_assert(Dune::AlwaysFalse<AutoDiffFE>::value,
143 "Appropriate calculateScalar and calculateScalarImpl functions are not implemented for the "
144 "chosen element.");
145 }
146 }
147
153 const RealFE& realFE() const { return *this; }
154
162 template <typename... Args>
163 explicit AutoDiffFE(Args&&... args) : RealFE{std::forward<Args>(args)...} {}
164 };
165} // namespace Ikarus
Contains stl-like type traits.
Material property functions and conversion utilities.
Definition of the LinearElastic class for finite element mechanics computations.
Definition: simpleassemblers.hh:21
AutoDiffFE class, an automatic differentiation wrapper for finite elements.
Definition: autodifffe.hh:31
AutoDiffFE(Args &&... args)
Constructor for the AutoDiffFE class. Forward the construction to the underlying element.
Definition: autodifffe.hh:163
typename Traits::Element Element
Type of the element.
Definition: autodifffe.hh:37
double calculateScalar(const FERequirementType &par) const
Calculate the scalar value associated with the finite element.
Definition: autodifffe.hh:134
void calculateMatrix(const FERequirementType &req, typename Traits::template MatrixType<> h) const
Calculate the matrix associated with the finite element.
Definition: autodifffe.hh:46
void calculateVector(const FERequirementType &req, typename Traits::template VectorType<> g) const
Calculate the vector associated with the finite element.
Definition: autodifffe.hh:88
typename Traits::LocalView LocalView
Type of the local view.
Definition: autodifffe.hh:36
typename Traits::FERequirementType FERequirementType
Type of the Finite Element Requirements.
Definition: autodifffe.hh:38
typename RealFE::Basis Basis
Type of the basis.
Definition: autodifffe.hh:34
void calculateLocalSystem(const FERequirementType &req, typename Traits::template MatrixType<> h, typename Traits::template VectorType<> g) const
Calculate the local system associated with the finite element.
Definition: autodifffe.hh:120
RealFE_ RealFE
Type of the base finite element.
Definition: autodifffe.hh:33
const RealFE & realFE() const
Get the reference to the base finite element.
Definition: autodifffe.hh:153
Traits for handling finite elements.see https://en.wikipedia.org/wiki/Lam%C3%A9_parameters.
Definition: physicshelper.hh:68
typename LocalView::Element Element
Type of the grid element.
Definition: physicshelper.hh:88
typename FlatBasis::LocalView LocalView
Type of the local view.
Definition: physicshelper.hh:82
FERequirements_ FERequirementType
Type of the requirements for the finite element.
Definition: physicshelper.hh:73