version 0.4.8
easfunctions/displacementgradient.hh
Go to the documentation of this file.
1// SPDX-FileCopyrightText: 2021-2026 The Ikarus Developers ikarus@ibb.uni-stuttgart.de
2// SPDX-License-Identifier: LGPL-3.0-or-later
3
11#pragma once
12
13#include <dune/common/fvector.hh>
14#include <dune/localfefunctions/eigenDuneTransformations.hh>
15#include <dune/localfefunctions/expressions/greenLagrangeStrains.hh>
16
17#include <Eigen/Core>
18
20
21namespace Ikarus::EAS {
29{
44 template <typename GEO, typename EAST>
45 static auto computeDisplacementGradient(const GEO& geo, const auto& uFunction,
47 const EAST& easFunction, const auto& alpha) {
48 using ST = typename std::remove_cvref_t<decltype(uFunction)>::ctype;
49 constexpr int myDim = GEO::mydimension;
50 using MatrixType = Eigen::Matrix<ST, myDim, myDim>;
51
52 using namespace Dune::DerivativeDirections;
53 using namespace Dune;
54
55 const MatrixType Hc = toEigen(uFunction.evaluateDerivative(gpPos, wrt(spatialAll), on(gridElement))).eval();
56 const typename EAST::HType Harray = easFunction(gpPos);
57 constexpr int enhancedStrainSize = EAST::enhancedStrainSize;
58 typename EAST::AnsatzType Htilde;
59 Htilde.setZero(); // zeros returned if Harray is empty
60 for (const auto p : Dune::range(enhancedStrainSize))
61 Htilde += Harray[p] * alpha[p];
62 const MatrixType H = Hc + Htilde;
63 return H;
64 }
65
80 template <typename GEO, typename EAST>
81 static auto value(const GEO& geo, const auto& uFunction, const Dune::FieldVector<double, GEO::mydimension>& gpPos,
82 const EAST& easFunction, const auto& alpha) {
83 using ST = typename std::remove_cvref_t<decltype(uFunction)>::ctype;
84 constexpr int myDim = GEO::mydimension;
85 const Eigen::Matrix<ST, myDim, myDim> H = computeDisplacementGradient(geo, uFunction, gpPos, easFunction, alpha);
86 const Eigen::Matrix<ST, myDim, myDim> E = 0.5 * (H + H.transpose() + H.transpose() * H);
87 return toVoigt(E, true).eval();
88 }
89
110 template <int wrtCoeff, typename GEO, typename EAST>
111 static auto firstDerivative(const GEO& geo, const auto& uFunction, const auto& localBasis, const auto& gpIndex,
112 const Dune::FieldVector<double, GEO::mydimension>& gpPos, const EAST& easFunction,
113 const auto& alpha, const int node = sNaN) {
114 using namespace Dune::DerivativeDirections;
115 using namespace Dune;
116 using ST = typename std::remove_cvref_t<decltype(uFunction)>::ctype;
117 constexpr int myDim = GEO::mydimension;
118 static_assert(myDim == 2 or myDim == 3,
119 "An enhancement of displacement gradient can only be performed for the 2D or 3D case.");
120 constexpr int strainSize = myDim * (myDim + 1) / 2;
121 using MatrixType = Eigen::Matrix<ST, myDim, myDim>;
122
123 const MatrixType F = computeDeformationGradient(geo, uFunction, gpPos, easFunction, alpha)
124 .transpose()
125 .eval(); // transposed such that the rows are u_{,1} and u_{,2}
126 const auto g0 = F.row(0);
127 const auto g1 = F.row(1);
128
129 if constexpr (wrtCoeff == 0) { // E,d
130 const auto gradUdI = uFunction.evaluateDerivative(gpIndex, wrt(spatialAll, coeff(node)), on(gridElement));
131
132 Eigen::Vector<ST, myDim> dN;
133 for (const auto i : Dune::range(myDim))
134 dN[i] = getDiagonalEntry(gradUdI[i], 0);
135 Eigen::Matrix<ST, strainSize, myDim> bopI;
136 bopI.row(0) = dN[0] * g0;
137 bopI.row(1) = dN[1] * g1;
138 if constexpr (myDim == 2)
139 bopI.row(2) = dN[1] * g0 + dN[0] * g1;
140 else {
141 const auto g2 = F.row(2);
142 bopI.row(2) = dN[2] * g2;
143 bopI.row(3) = dN[2] * g1 + dN[1] * g2;
144 bopI.row(4) = dN[2] * g0 + dN[0] * g2;
145 bopI.row(5) = dN[1] * g0 + dN[0] * g1;
146 }
147 return bopI.eval();
148 } else if constexpr (wrtCoeff == 1) { // E,a
149 const typename EAST::HType Harray = easFunction(gpPos);
150 constexpr int enhancedStrainSize = EAST::enhancedStrainSize;
151 Eigen::Matrix<ST, strainSize, enhancedStrainSize> M;
152 M.setZero(); // zeros returned if Harray is empty
153 for (const auto p : Dune::range(enhancedStrainSize)) {
154 const MatrixType Htilde = Harray[p];
155 M(0, p) = Htilde.col(0).dot(g0);
156 M(1, p) = Htilde.col(1).dot(g1);
157 if constexpr (myDim == 2)
158 M(2, p) = Htilde.col(1).dot(g0) + Htilde.col(0).dot(g1);
159 else {
160 const auto g2 = F.row(2);
161 M(2, p) = Htilde.col(2).dot(g2);
162 M(3, p) = Htilde.col(2).dot(g1) + Htilde.col(1).dot(g2);
163 M(4, p) = Htilde.col(2).dot(g0) + Htilde.col(0).dot(g2);
164 M(5, p) = Htilde.col(1).dot(g0) + Htilde.col(0).dot(g1);
165 }
166 }
167 return M.eval();
168 } else
169 static_assert(Dune::AlwaysFalse<GEO>::value,
170 "firstDerivative can only be called with wrtCoeff as 0 and 1 indicating first derivative of the "
171 "Green-Lagrange strain w.r.t d and "
172 "alpha, respectively.");
173 }
174
199 template <int wrtCoeff, typename GEO, typename ST, typename EAST>
200 static auto secondDerivative(const GEO& geo, const auto& uFunction, const auto& localBasis, const auto& gpIndex,
202 const Eigen::Vector<ST, GEO::mydimension*(GEO::mydimension + 1) / 2>& S,
203 const EAST& easFunction, const auto& alpha, const int I = sNaN, const int J = sNaN) {
204 constexpr int myDim = GEO::mydimension;
205 using namespace Dune::DerivativeDirections;
206 using namespace Dune;
207 static_assert(myDim == 2 or myDim == 3,
208 "An enhancement of displacement gradient can only be performed for the 2D or 3D case.");
209 if constexpr (wrtCoeff == 0) { // E_dd = Ec_dd (as Etilde,dd = 0)
210 const auto strainFunction = Dune::greenLagrangeStrains(uFunction);
211 const auto kg = strainFunction.evaluateDerivative(gpIndex, wrt(coeff(I, J)), along(S), on(gridElement));
212 return kg.eval();
213 } else if constexpr (wrtCoeff == 1) { // E_aa
214 constexpr int enhancedStrainSize = EAST::enhancedStrainSize;
215 const typename EAST::HType Harray = easFunction(gpPos);
216 auto kg = Eigen::Matrix<ST, enhancedStrainSize, enhancedStrainSize>::Zero().eval();
217
218 for (const auto i : Dune::range(myDim)) {
219 for (const auto j : Dune::range(myDim)) {
220 const auto sij = 0.5 * S[toVoigt<myDim>(i, j)];
221 for (const auto p : Dune::range(enhancedStrainSize))
222 for (const auto q : Dune::range(enhancedStrainSize)) {
223 const auto Hq = Harray[q];
224 kg(p, q) += sij * (Harray[p].col(i).transpose() * Harray[q].col(j) +
225 Harray[p].col(j).transpose() * Harray[q].col(i))
226 .sum();
227 }
228 }
229 }
230 return kg;
231 } else if constexpr (wrtCoeff == 2) { // E_ad
232 constexpr int enhancedStrainSize = EAST::enhancedStrainSize;
233 const typename EAST::HType Harray = easFunction(gpPos);
234 auto kg = Eigen::Matrix<ST, enhancedStrainSize, myDim>::Zero().eval();
235 const auto gradUdI = uFunction.evaluateDerivative(gpIndex, wrt(spatialAll, coeff(I)), on(gridElement));
236
237 std::array<Eigen::Matrix<ST, myDim, myDim>, myDim> dNIdT;
238 std::ranges::fill(dNIdT, Eigen::Matrix<ST, myDim, myDim>::Zero());
239 for (const auto i : Dune::range(myDim))
240 for (const auto j : Dune::range(myDim))
241 dNIdT[i](i, j) = getDiagonalEntry(gradUdI[j], 0);
242
243 for (const auto i : Dune::range(myDim)) {
244 for (const auto j : Dune::range(myDim)) {
245 const auto sij = 0.5 * S[toVoigt<myDim>(i, j)];
246 for (const auto p : Dune::range(enhancedStrainSize))
247 for (const auto q : Dune::range(myDim)) {
248 kg(p, q) += sij * (Harray[p].col(i).transpose() * dNIdT[q].col(j) +
249 Harray[p].col(j).transpose() * dNIdT[q].col(i))
250 .sum();
251 }
252 }
253 }
254 return kg;
255 } else
256 static_assert(
257 Dune::AlwaysFalse<GEO>::value,
258 "secondDerivative can only be called with wrtCoeff as 0, 1 and 2 indicating second derivative of the "
259 "Green-Lagrange strain w.r.t d and "
260 "alpha and the mixed derivative, respectively.");
261 }
262
264 static constexpr auto name() { return std::string("Displacement Gradient"); }
265
266private:
267 static constexpr int sNaN = std::numeric_limits<int>::signaling_NaN();
268
269 template <typename GEO, typename EAST>
270 static auto computeDeformationGradient(const GEO& geo, const auto& uFunction,
272 const EAST& easFunction, const auto& alpha) {
273 using ST = typename std::remove_cvref_t<decltype(uFunction)>::ctype;
274 constexpr int myDim = GEO::mydimension;
275 using MatrixType = Eigen::Matrix<ST, myDim, myDim>;
276 const MatrixType H = computeDisplacementGradient(geo, uFunction, gpPos, easFunction, alpha);
277 const MatrixType F = (MatrixType::Identity() + H).eval();
278 return F;
279 }
280};
281
282} // namespace Ikarus::EAS
Helper for the Eigen::Tensor types.
constexpr Eigen::Index toVoigt(Eigen::Index i, Eigen::Index j) noexcept
Converts 2D indices to Voigt notation index.
Definition: tensorutils.hh:182
Definition: easfunctions/displacementgradient.hh:21
Definition: utils/dirichletvalues.hh:36
A struct computing the value, first and second derivatives of the Green-Lagrange strain tensor (in Vo...
Definition: easfunctions/displacementgradient.hh:29
static auto computeDisplacementGradient(const GEO &geo, const auto &uFunction, const Dune::FieldVector< double, GEO::mydimension > &gpPos, const EAST &easFunction, const auto &alpha)
Compute the displacement gradient at a given integration point.
Definition: easfunctions/displacementgradient.hh:45
static auto value(const GEO &geo, const auto &uFunction, const Dune::FieldVector< double, GEO::mydimension > &gpPos, const EAST &easFunction, const auto &alpha)
Compute the strain vector at a given integration point.
Definition: easfunctions/displacementgradient.hh:81
static constexpr auto name()
The name of the strain measure enhanced w.r.t EAS method.
Definition: easfunctions/displacementgradient.hh:264
static auto firstDerivative(const GEO &geo, const auto &uFunction, const auto &localBasis, const auto &gpIndex, const Dune::FieldVector< double, GEO::mydimension > &gpPos, const EAST &easFunction, const auto &alpha, const int node=sNaN)
Compute the first derivative of the Green-Lagrange strain w.r.t d or alpha for a given node and integ...
Definition: easfunctions/displacementgradient.hh:111
static auto secondDerivative(const GEO &geo, const auto &uFunction, const auto &localBasis, const auto &gpIndex, const Dune::FieldVector< double, GEO::mydimension > &gpPos, const Eigen::Vector< ST, GEO::mydimension *(GEO::mydimension+1)/2 > &S, const EAST &easFunction, const auto &alpha, const int I=sNaN, const int J=sNaN)
Compute the second derivative of the Green-Lagrange strain w.r.t d or alpha for a given node and inte...
Definition: easfunctions/displacementgradient.hh:200
Definition: utils/dirichletvalues.hh:38