version 0.4.1
enhancedassumedstrains.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
10#pragma once
11
12#if HAVE_DUNE_LOCALFEFUNCTIONS
13 #include <dune/localfefunctions/derivativetransformators.hh>
14 #include <dune/localfefunctions/linearAlgebraHelper.hh>
15 #include <dune/localfefunctions/meta.hh>
16
21
22namespace Ikarus {
23
24template <typename PreFE, typename FE>
25class EnhancedAssumedStrains;
26
31{
33
34 template <typename PreFE, typename FE>
36};
37
48template <typename PreFE, typename FE>
50{
51public:
54 using LocalView = typename Traits::LocalView;
55 using Geometry = typename Traits::Geometry;
56 using GridView = typename Traits::GridView;
58
59 using SupportedResultTypes = std::tuple<decltype(makeRT<ResultTypes::linearStress>())>;
60
65 explicit EnhancedAssumedStrains(const Pre& pre) { this->setEASType(pre.numberOfParameters); }
66
72 bool isDisplacementBased() const { return easVariant_.isDisplacmentBased(); }
73
79 const auto& easVariant() const { return easVariant_; }
80
86 auto numberOfEASParameters() const { return easVariant_.numberOfEASParameters(); }
87
102 template <template <typename, int, int> class RT>
104 Dune::PriorityTag<2>) const {
106 return underlying().template calculateAtImpl<RT>(req, local, Dune::PriorityTag<1>());
107
108 using namespace Dune::Indices;
109 using namespace Dune::DerivativeDirections;
110 auto resultVector = underlying().template calculateAtImpl<RT>(req, local, Dune::PriorityTag<1>());
111 if constexpr (isSameResultType<RT, ResultTypes::linearStress>) {
113 RTWrapper resultWrapper;
114
115 auto calculateAtContribution = [&]<typename EAST>(const EAST& easFunction) {
116 typename EAST::DType D;
117 calculateDAndLMatrix(easFunction, req, D, L_);
118 const auto ufunc = underlying().displacementFunction(req);
119 const auto disp = Dune::viewAsFlatEigenVector(ufunc.coefficientsRef());
120 const auto C = underlying().materialTangentFunction(req);
121 const auto alpha = (-D.inverse() * L_ * disp).eval();
122 const auto M = easFunction.calcM(local);
123 const auto CEval = C(local);
124 auto easStress = (CEval * M * alpha).eval();
125 resultWrapper = resultVector.asVec() + easStress;
126 };
127 easVariant_(calculateAtContribution);
128 return resultWrapper;
129 }
130 }
131
138 if (numberOfEASParameters != 0)
140 easVariant_.setEASType(numberOfEASParameters);
141 }
142
143protected:
144 void bindImpl() {
145 assert(underlying().localView().bound());
146 easVariant_.bind(underlying().localView().element().geometry());
147 }
148
149public:
150protected:
151 inline void easApplicabilityCheck() const {
152 const auto& numberOfNodes = underlying().numberOfNodes();
153 assert(not(not((numberOfNodes == 4 and Traits::mydim == 2) or (numberOfNodes == 8 and Traits::mydim == 3)) and
154 (not isDisplacementBased())) &&
155 "EAS only supported for Q1 or H1 elements");
156 }
157
158 template <typename ScalarType>
160 const FERequirementType& par, typename Traits::template MatrixType<> K,
161 const std::optional<std::reference_wrapper<const Eigen::VectorX<ScalarType>>>& dx = std::nullopt) const {
162 using namespace Dune::DerivativeDirections;
163 using namespace Dune;
166 return;
167
168 decltype(auto) LMat = [this]() -> decltype(auto) {
169 if constexpr (std::is_same_v<ScalarType, double>)
170 return [this]() -> Eigen::MatrixXd& { return L_; }();
171 else
172 return Eigen::MatrixX<ScalarType>{};
173 }();
174
175 auto calculateMatrixContribution = [&]<typename EAST>(const EAST& easFunction) {
176 typename EAST::DType D;
177 calculateDAndLMatrix(easFunction, par, D, LMat, dx);
178
179 K.template triangularView<Eigen::Upper>() -= LMat.transpose() * D.inverse() * LMat;
180 K.template triangularView<Eigen::StrictlyLower>() = K.transpose();
181 };
182 easVariant_(calculateMatrixContribution);
183 }
184
185 template <typename ScalarType>
186 inline ScalarType calculateScalarImpl(
187 const FERequirementType& par,
188 const std::optional<std::reference_wrapper<const Eigen::VectorX<ScalarType>>>& dx = std::nullopt) const {
191 return 0.0;
192 DUNE_THROW(Dune::NotImplemented,
193 "EAS element do not support any scalar calculations, i.e. they are not derivable from a potential");
194 }
195
196 template <typename ScalarType>
198 const FERequirementType& par, typename Traits::template VectorType<ScalarType> force,
199 const std::optional<std::reference_wrapper<const Eigen::VectorX<ScalarType>>>& dx = std::nullopt) const {
201 using namespace Dune;
202 using namespace Dune::DerivativeDirections;
203 const auto uFunction = underlying().displacementFunction(par, dx);
204 auto strainFunction = underlying().strainFunction(par, dx);
205 const auto& numberOfNodes = underlying().numberOfNodes();
206
207 auto calculateForceContribution = [&]<typename EAST>(const EAST& easFunction) {
208 typename EAST::DType D;
209 calculateDAndLMatrix(easFunction, par, D, L_);
210
211 decltype(auto) LMat = [this]() -> decltype(auto) {
212 if constexpr (std::is_same_v<ScalarType, double>)
213 return [this]() -> Eigen::MatrixXd& { return L_; }();
214 else
215 return Eigen::MatrixX<ScalarType>{};
216 }();
217 const auto disp = Dune::viewAsFlatEigenVector(uFunction.coefficientsRef());
218 const auto alpha = (-D.inverse() * L_ * disp).eval();
219 const auto geo = underlying().localView().element().geometry();
220 auto C = underlying().materialTangentFunction(par);
221
222 for (const auto& [gpIndex, gp] : strainFunction.viewOverIntegrationPoints()) {
223 const auto M = easFunction.calcM(gp.position());
224 const double intElement = geo.integrationElement(gp.position()) * gp.weight();
225 const auto CEval = C(gpIndex);
226 auto stresses = (CEval * M * alpha).eval();
227 for (size_t i = 0; i < numberOfNodes; ++i) {
228 const auto bopI = strainFunction.evaluateDerivative(gpIndex, wrt(coeff(i)), on(gridElement));
229 force.template segment<Traits::worlddim>(Traits::worlddim * i) += bopI.transpose() * stresses * intElement;
230 }
231 }
232 };
233 easVariant_(calculateForceContribution);
234 }
235
236private:
237 EAS::Impl::EASVariant<Geometry> easVariant_;
238 mutable Eigen::MatrixXd L_;
239
240 //> CRTP
241 const auto& underlying() const { return static_cast<const FE&>(*this); }
242 auto& underlying() { return static_cast<FE&>(*this); }
243
244 template <typename ScalarType, int enhancedStrainSize>
245 void calculateDAndLMatrix(
246 const auto& easFunction, const auto& par, Eigen::Matrix<double, enhancedStrainSize, enhancedStrainSize>& DMat,
247 Eigen::MatrixX<ScalarType>& LMat,
248 const std::optional<std::reference_wrapper<const Eigen::VectorX<ScalarType>>>& dx = std::nullopt) const {
249 using namespace Dune;
250 using namespace Dune::DerivativeDirections;
251
252 auto strainFunction = underlying().strainFunction(par, dx);
253 const auto C = underlying().materialTangentFunction(par);
254 const auto geo = underlying().localView().element().geometry();
255 const auto numberOfNodes = underlying().numberOfNodes();
256 DMat.setZero();
257 LMat.setZero(enhancedStrainSize, underlying().localView().size());
258 for (const auto& [gpIndex, gp] : strainFunction.viewOverIntegrationPoints()) {
259 const auto M = easFunction.calcM(gp.position());
260 const auto CEval = C(gpIndex);
261 const double detJTimesW = geo.integrationElement(gp.position()) * gp.weight();
262 DMat += M.transpose() * CEval * M * detJTimesW;
263 for (size_t i = 0U; i < numberOfNodes; ++i) {
264 const size_t I = Traits::worlddim * i;
265 const auto Bi = strainFunction.evaluateDerivative(gpIndex, wrt(coeff(i)), on(gridElement));
266 LMat.template block<enhancedStrainSize, Traits::worlddim>(0, I) += M.transpose() * CEval * Bi * detJTimesW;
267 }
268 }
269 }
270};
271
277auto eas(int numberOfEASParameters = 0) {
278 EnhancedAssumedStrainsPre pre(numberOfEASParameters);
279
280 return pre;
281}
282
283} // namespace Ikarus
284
285#else
286 #error EnhancedAssumedStrains depends on dune-localfefunctions, which is not included
287#endif
Definition of the LinearElastic class for finite element mechanics computations.
Definition of the EAS variants.
Implementation of the finite element CRTP mixin class.
auto viewAsFlatEigenVector(Dune::BlockVector< ValueType > &blockedVector)
View Dune::BlockVector as an Eigen::Vector.
Definition: linearalgebrahelper.hh:57
Definition: simpleassemblers.hh:22
auto eas(int numberOfEASParameters=0)
A helper function to create an enhanced assumed strain pre finite element.
Definition: enhancedassumedstrains.hh:277
Definition: utils/dirichletvalues.hh:28
FE class is a base class for all finite elements.
Definition: febase.hh:81
FETraits< BH, FER, useEigenRef, useFlat > Traits
Definition: febase.hh:40
Container that is used for FE Results. It gives access to the stored value, but can also be used to a...
Definition: feresulttypes.hh:155
Traits for handling finite elements.
Definition: fetraits.hh:26
FER FERequirementType
Type of the requirements for the finite element.
Definition: fetraits.hh:31
typename Basis::LocalView LocalView
Type of the local view.
Definition: fetraits.hh:46
typename Basis::GridView GridView
Type of the grid view.
Definition: fetraits.hh:49
static constexpr int worlddim
Dimension of the world space.
Definition: fetraits.hh:64
static constexpr int mydim
Dimension of the geometry.
Definition: fetraits.hh:67
typename Element::Geometry Geometry
Type of the element geometry.
Definition: fetraits.hh:55
Wrapper class for using Enhanced Assumed Strains (EAS) with displacement based elements.
Definition: enhancedassumedstrains.hh:50
auto calculateAtImpl(const FERequirementType &req, const Dune::FieldVector< double, Traits::mydim > &local, Dune::PriorityTag< 2 >) const
Calculates a requested result at a specific local position using the Enhanced Assumed Strains (EAS) m...
Definition: enhancedassumedstrains.hh:103
void calculateVectorImpl(const FERequirementType &par, typename Traits::template VectorType< ScalarType > force, const std::optional< std::reference_wrapper< const Eigen::VectorX< ScalarType > > > &dx=std::nullopt) const
Definition: enhancedassumedstrains.hh:197
typename Traits::GridView GridView
Definition: enhancedassumedstrains.hh:56
typename Traits::LocalView LocalView
Definition: enhancedassumedstrains.hh:54
EnhancedAssumedStrains(const Pre &pre)
Constructor for Enhanced Assumed Strains elements.
Definition: enhancedassumedstrains.hh:65
const auto & easVariant() const
Gets the variant representing the type of Enhanced Assumed Strains (EAS).
Definition: enhancedassumedstrains.hh:79
ScalarType calculateScalarImpl(const FERequirementType &par, const std::optional< std::reference_wrapper< const Eigen::VectorX< ScalarType > > > &dx=std::nullopt) const
Definition: enhancedassumedstrains.hh:186
void easApplicabilityCheck() const
Definition: enhancedassumedstrains.hh:151
typename Traits::FERequirementType FERequirementType
Definition: enhancedassumedstrains.hh:53
void bindImpl()
Definition: enhancedassumedstrains.hh:144
bool isDisplacementBased() const
Checks if the element is displacement-based and the EAS is turned off.
Definition: enhancedassumedstrains.hh:72
std::tuple< decltype(makeRT< ResultTypes::linearStress >())> SupportedResultTypes
Definition: enhancedassumedstrains.hh:59
void setEASType(int numberOfEASParameters)
Sets the EAS type for 2D elements.
Definition: enhancedassumedstrains.hh:137
void calculateMatrixImpl(const FERequirementType &par, typename Traits::template MatrixType<> K, const std::optional< std::reference_wrapper< const Eigen::VectorX< ScalarType > > > &dx=std::nullopt) const
Definition: enhancedassumedstrains.hh:159
auto numberOfEASParameters() const
Gets the number of EAS parameters based on the current EAS type.
Definition: enhancedassumedstrains.hh:86
typename Traits::Geometry Geometry
Definition: enhancedassumedstrains.hh:55
A PreFE struct for Enhanced Assumed Strains.
Definition: enhancedassumedstrains.hh:31
int numberOfParameters
Definition: enhancedassumedstrains.hh:32
Definition: utils/dirichletvalues.hh:30