12#if HAVE_DUNE_LOCALFEFUNCTIONS
13 #include <dune/localfefunctions/derivativetransformators.hh>
14 #include <dune/localfefunctions/linearAlgebraHelper.hh>
15 #include <dune/localfefunctions/meta.hh>
26template <
typename PreFE,
typename FE,
typename ES>
27class EnhancedAssumedStrains;
38 template <
typename PreFE,
typename FE>
53template <
typename PreFE,
typename FE,
typename ESF>
55 :
public std::conditional_t<std::same_as<ESF, EAS::LinearStrain>,
56 ResultTypeBase<ResultTypes::linearStress, ResultTypes::linearStressFull>,
57 ResultTypeBase<ResultTypes::PK2Stress, ResultTypes::PK2StressFull>>
70 template <
typename ST>
71 using VectorXOptRef = std::optional<std::reference_wrapper<const Eigen::VectorX<ST>>>;
73 template <
template <
typename,
int,
int>
class RT>
82 "EAS method is only implemented for the total Lagrangian setting.");
84 not(FE::strainType ==
StrainTags::linear) or (std::same_as<EnhancedStrainFunction, EAS::LinearStrain>),
85 "If FE::strainType is linear, then enhancedStrain must also be linear.");
124 template <
template <
typename,
int,
int>
class RT>
125 requires(EnhancedAssumedStrains::template supportsResultType<RT>())
127 Dune::PriorityTag<2>)
const {
128 if constexpr (isSameResultType<RT, ResultTypes::linearStress> or isSameResultType<RT, ResultTypes::PK2Stress> or
129 isSameResultType<RT, ResultTypes::linearStressFull> or
130 isSameResultType<RT, ResultTypes::PK2StressFull>) {
131 const auto ufunc = underlying().displacementFunction(req);
132 const auto rFunction = underlying().template resultFunction<RT>();
134 const auto geo = underlying().localView().element().geometry();
137 auto calculateAtContribution = [&]<
typename EAST>(
const EAST& easFunction) {
138 Eigen::VectorXd alpha;
140 if constexpr (EAST::enhancedStrainSize != 0) {
141 typename EAST::DType D;
142 calculateDAndLMatrix(easFunction, req, D, L_);
143 alpha = -D.inverse() * L_ * disp;
145 const auto enhancedStrain = EnhancedStrainFunction::value(geo, ufunc, local, easFunction, alpha);
146 resultWrapper = rFunction(enhancedStrain);
148 easVariant_(calculateAtContribution);
149 return resultWrapper;
151 DUNE_THROW(Dune::NotImplemented,
"The requested result type is not supported");
175 assert(underlying().localView().bound());
176 easVariant_.
bind(underlying().localView().element().geometry());
190 const std::remove_reference_t<
typename Traits::template VectorType<>>& correction) {
193 auto correctAlpha = [&]<
typename EAST>(
const EAST& easFunction) {
194 if constexpr (EAST::enhancedStrainSize != 0) {
195 const auto& Rtilde = calculateRtilde<ScalarType>(par);
196 const auto localdxBlock = Ikarus::FEHelper::localSolutionBlockVector<Traits, Eigen::VectorXd, double>(
197 correction, underlying().localView());
199 constexpr int enhancedStrainSize = EAST::enhancedStrainSize;
200 Eigen::Matrix<double, enhancedStrainSize, enhancedStrainSize> D;
201 calculateDAndLMatrix(easFunction, par, D, L_);
202 this->alpha_ -= D.inverse() * (Rtilde + (L_ * localdx));
206 easVariant_(correctAlpha);
210 const auto& numberOfNodes = underlying().numberOfNodes();
214 DUNE_THROW(Dune::NotImplemented,
"EAS is only supported for Q1, Q2 and H1 elements");
217 template <
typename ScalarType>
219 typename Traits::template MatrixType<> K,
222 DUNE_THROW(Dune::NotImplemented,
"MatrixAffordance not implemented: " +
toString(affordance));
225 const auto geo = underlying().localView().element().geometry();
226 const auto& uFunction = underlying().displacementFunction(par, dx);
227 const auto& kMFunction = underlying().template materialStiffnessMatrixFunction<ScalarType>(par, K, dx);
228 const auto& kGFunction = underlying().template geometricStiffnessMatrixFunction<ScalarType>(par, K, dx);
229 const auto numberOfNodes = underlying().numberOfNodes();
230 const auto& localBasis = underlying().localBasis();
232 auto calculateMatrixContribution = [&]<
typename EAST>(
const EAST& easFunction) {
233 for (
const auto& [gpIndex, gp] : uFunction.viewOverIntegrationPoints()) {
234 const auto enhancedStrain = EnhancedStrainFunction::value(geo, uFunction, gp.position(), easFunction, alpha_);
235 const auto stresses = underlying().stress(enhancedStrain);
236 for (
size_t i = 0; i < numberOfNodes; ++i) {
237 const auto E_dI = EnhancedStrainFunction::template firstDerivative<0>(geo, uFunction, localBasis, gpIndex,
238 gp.position(), easFunction, alpha_, i);
239 for (
size_t j = 0; j < numberOfNodes; ++j) {
240 const auto E_dJ = EnhancedStrainFunction::template firstDerivative<0>(
241 geo, uFunction, localBasis, gpIndex, gp.position(), easFunction, alpha_, j);
242 const auto E_dd = EnhancedStrainFunction::template secondDerivative<0>(
243 geo, uFunction, localBasis, gpIndex, gp.position(), stresses, easFunction, alpha_, i, j);
244 kMFunction(enhancedStrain, E_dI, E_dJ, i, j, gp);
245 kGFunction(E_dd, i, j, gp);
250 if constexpr (EAST::enhancedStrainSize != 0) {
251 typename EAST::DType D;
252 calculateDAndLMatrix(easFunction, par, D, L_);
253 K.template triangularView<Eigen::Upper>() -= L_.transpose() * D.inverse() * L_;
254 K.template triangularView<Eigen::StrictlyLower>() = K.transpose();
257 easVariant_(calculateMatrixContribution);
260 template <
typename ScalarType>
265 return underlying().template energyFunction<ScalarType>(par, dx)();
267 DUNE_THROW(Dune::NotImplemented,
268 "EAS element do not support any scalar calculations, i.e. they are not derivable from a potential");
271 template <
typename ScalarType>
273 typename Traits::template VectorType<ScalarType> force,
276 DUNE_THROW(Dune::NotImplemented,
"VectorAffordance not implemented: " +
toString(affordance));
279 const auto geo = underlying().localView().element().geometry();
280 const auto& uFunction = underlying().displacementFunction(par, dx);
281 const auto numberOfNodes = underlying().numberOfNodes();
282 const auto& localBasis = underlying().localBasis();
283 const auto fIntFunction = underlying().template internalForcesFunction<ScalarType>(par, force, dx);
285 auto calculateForceContribution = [&]<
typename EAST>(
const EAST& easFunction) {
286 for (
const auto& [gpIndex, gp] : uFunction.viewOverIntegrationPoints()) {
287 const auto enhancedStrain = EnhancedStrainFunction::value(geo, uFunction, gp.position(), easFunction, alpha_);
288 const auto stresses = underlying().stress(enhancedStrain);
289 for (
size_t i = 0; i < numberOfNodes; ++i) {
290 const auto E_dI = EnhancedStrainFunction::template firstDerivative<0>(geo, uFunction, localBasis, gpIndex,
291 gp.position(), easFunction, alpha_, i);
292 fIntFunction(stresses, E_dI, i, gp);
295 if constexpr (EAST::enhancedStrainSize != 0) {
300 typename EAST::DType D;
301 calculateDAndLMatrix(easFunction, par, D, L_);
302 const auto& Rtilde = calculateRtilde(par, dx);
303 force -= L_.transpose() * D.inverse() * Rtilde;
306 easVariant_(calculateForceContribution);
309 template <
typename MT,
typename BC>
311 if constexpr (std::same_as<MT, NonLinearSolverMessages>) {
312 using NLSState =
typename BC::State;
322 mutable Eigen::MatrixXd L_;
323 Eigen::VectorXd alpha_;
326 const auto& underlying()
const {
return static_cast<const FE&
>(*this); }
327 auto& underlying() {
return static_cast<FE&
>(*this); }
332 void initializeState() {
337 template <
int enhancedStrainSize>
338 void calculateDAndLMatrix(
const auto& easFunction,
const auto& par,
339 Eigen::Matrix<double, enhancedStrainSize, enhancedStrainSize>& DMat,
340 Eigen::MatrixX<double>& LMat)
const {
341 using namespace Dune;
342 using namespace Dune::DerivativeDirections;
344 const auto& uFunction = underlying().displacementFunction(par);
345 const auto geo = underlying().localView().element().geometry();
346 const auto numberOfNodes = underlying().numberOfNodes();
347 const auto& localBasis = underlying().localBasis();
349 LMat.setZero(enhancedStrainSize, underlying().localView().size());
350 for (
const auto& [gpIndex, gp] : uFunction.viewOverIntegrationPoints()) {
351 const auto enhancedStrain = EnhancedStrainFunction::value(geo, uFunction, gp.position(), easFunction, alpha_);
352 const auto C = underlying().materialTangent(enhancedStrain);
353 const auto stresses = underlying().stress(enhancedStrain);
354 const double intElement = geo.integrationElement(gp.position()) * gp.weight();
355 const auto E_a = EnhancedStrainFunction::template firstDerivative<1>(geo, uFunction, localBasis, gpIndex,
356 gp.position(), easFunction, alpha_);
357 const auto E_aa = EnhancedStrainFunction::template secondDerivative<1>(
358 geo, uFunction, localBasis, gpIndex, gp.position(), stresses, easFunction, alpha_);
359 DMat += (E_a.transpose() * C * E_a + E_aa) * intElement;
360 for (
size_t i = 0U; i < numberOfNodes; ++i) {
361 const auto E_dI = EnhancedStrainFunction::template firstDerivative<0>(geo, uFunction, localBasis, gpIndex,
362 gp.position(), easFunction, alpha_, i);
363 const auto E_ad = EnhancedStrainFunction::template secondDerivative<2>(
364 geo, uFunction, localBasis, gpIndex, gp.position(), stresses, easFunction, alpha_, i);
365 LMat.template block<enhancedStrainSize, myDim>(0,
myDim * i) +=
366 (E_a.transpose() * C * E_dI + E_ad) * intElement;
371 template <
typename ScalarType>
372 Eigen::VectorX<ScalarType> calculateRtilde(
const Requirement& par,
373 const VectorXOptRef<ScalarType>& dx = std::nullopt)
const {
374 const auto geo = underlying().localView().element().geometry();
375 const auto& uFunction = underlying().displacementFunction(par, dx);
376 const auto& localBasis = underlying().localBasis();
377 Eigen::VectorX<ScalarType> Rtilde;
380 auto calculateRtildeContribution = [&]<
typename EAST>(
const EAST& easFunction) {
381 for (
const auto& [gpIndex, gp] : uFunction.viewOverIntegrationPoints()) {
382 const auto enhancedStrain = EnhancedStrainFunction::value(geo, uFunction, gp.position(), easFunction, alpha_);
383 const auto E_a = EnhancedStrainFunction::template firstDerivative<1>(geo, uFunction, localBasis, gpIndex,
384 gp.position(), easFunction, alpha_);
385 const double intElement = geo.integrationElement(gp.position()) * gp.weight();
386 auto stresses = underlying().stress(enhancedStrain);
387 Rtilde += (E_a.transpose() * stresses).eval() * intElement;
391 easVariant_(calculateRtildeContribution);
402template <
typename ES = EAS::LinearStrain>
403auto eas(
int numberOfInternalVariables = 0) {
412 #error EnhancedAssumedStrains depends on dune-localfefunctions, which is not included
Definition of several material related enums.
Definition of the EAS variants.
Definition of the LinearElastic class for finite element mechanics computations.
Enums for observer messages.
NonLinearSolverMessages
Enum class defining non-linear solver-related messages.
Definition: broadcastermessages.hh:22
auto viewAsFlatEigenVector(Dune::BlockVector< ValueType > &blockedVector)
View Dune::BlockVector as an Eigen::Vector.
Definition: linearalgebrahelper.hh:57
Definition: assemblermanipulatorbuildingblocks.hh:22
MatrixAffordance
A strongly typed enum class representing the matrix affordance.
Definition: ferequirements.hh:64
auto eas(int numberOfInternalVariables=0)
A helper function to create an enhanced assumed strain pre finite element.
Definition: enhancedassumedstrains.hh:403
VectorAffordance
A strongly typed enum class representing the vector affordance.
Definition: ferequirements.hh:49
constexpr std::string toString(DBCOption _e)
Definition: dirichletbcenforcement.hh:8
ScalarAffordance
A strongly typed enum class representing the scalar affordance.
Definition: ferequirements.hh:38
Definition: utils/dirichletvalues.hh:30
FE class is a base class for all finite elements.
Definition: febase.hh:79
FETraits< BH, useEigenRef, useFlat > Traits
Definition: febase.hh:38
Class representing the requirements for finite element calculations.
Definition: ferequirements.hh:223
Container that is used for FE Results. It gives access to the stored value, but can also be used to a...
Definition: feresulttypes.hh:164
Traits for handling finite elements.
Definition: fetraits.hh:25
typename Basis::LocalView LocalView
Type of the local view.
Definition: fetraits.hh:42
typename Element::Geometry Geometry
Type of the element geometry.
Definition: fetraits.hh:51
double ctype
Type used for coordinates.
Definition: fetraits.hh:57
typename Basis::GridView GridView
Type of the grid view.
Definition: fetraits.hh:45
static constexpr int mydim
Dimension of the geometry.
Definition: fetraits.hh:63
Wrapper class for using Enhanced Assumed Strains (EAS) with displacement based elements.
Definition: enhancedassumedstrains.hh:58
std::optional< std::reference_wrapper< const Eigen::VectorX< ST > > > VectorXOptRef
Definition: enhancedassumedstrains.hh:71
FERequirements< FESolutions::displacement, FEParameter::loadfactor > Requirement
Definition: enhancedassumedstrains.hh:61
void calculateMatrixImpl(const Requirement &par, const MatrixAffordance &affordance, typename Traits::template MatrixType<> K, const VectorXOptRef< ScalarType > &dx=std::nullopt) const
Definition: enhancedassumedstrains.hh:218
void easApplicabilityCheck() const
Definition: enhancedassumedstrains.hh:209
void calculateVectorImpl(const Requirement &par, VectorAffordance affordance, typename Traits::template VectorType< ScalarType > force, const VectorXOptRef< ScalarType > &dx=std::nullopt) const
Definition: enhancedassumedstrains.hh:272
auto calculateAtImpl(const Requirement &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:126
void bindImpl()
Definition: enhancedassumedstrains.hh:174
ScalarType calculateScalarImpl(const Requirement &par, ScalarAffordance affordance, const VectorXOptRef< ScalarType > &dx=std::nullopt) const
Definition: enhancedassumedstrains.hh:261
ESF EnhancedStrainFunction
Definition: enhancedassumedstrains.hh:66
bool isDisplacementBased() const
Checks if the element is displacement-based and the EAS is turned off.
Definition: enhancedassumedstrains.hh:94
void setEASType(int numberOfInternalVariables)
Sets the EAS type for 2D elements.
Definition: enhancedassumedstrains.hh:159
EnhancedAssumedStrains(const Pre &pre)
Constructor for Enhanced Assumed Strains elements.
Definition: enhancedassumedstrains.hh:80
typename Traits::Geometry Geometry
Definition: enhancedassumedstrains.hh:63
const auto & internalVariable() const
Gets the internal state variable alpha for the EAS element.
Definition: enhancedassumedstrains.hh:171
static constexpr int myDim
Definition: enhancedassumedstrains.hh:68
void subscribeToImpl(BC &bc)
Definition: enhancedassumedstrains.hh:310
const auto & easVariant() const
Gets the variant representing the type of Enhanced Assumed Strains (EAS).
Definition: enhancedassumedstrains.hh:101
typename Traits::GridView GridView
Definition: enhancedassumedstrains.hh:64
typename Traits::LocalView LocalView
Definition: enhancedassumedstrains.hh:62
void updateStateImpl(const Requirement &par, const std::remove_reference_t< typename Traits::template VectorType<> > &correction)
Updates the internal state variable alpha_ at the end of an iteration before the update of the displa...
Definition: enhancedassumedstrains.hh:189
auto numberOfInternalVariables() const
Gets the number of EAS parameters based on the current EAS type.
Definition: enhancedassumedstrains.hh:108
A PreFE struct for Enhanced Assumed Strains.
Definition: enhancedassumedstrains.hh:35
int numberOfParameters
Definition: enhancedassumedstrains.hh:36
void bind(const GEO &geometry)
Definition: easvariants.hh:95
auto numberOfInternalVariables() const
A helper function to get the number of EAS parameters.
Definition: easvariants.hh:79
bool isDisplacmentBased() const
A helper function to identify if the formulation is purely displacement-based, i.e....
Definition: easvariants.hh:88
void setEASType(int numberOfInternalVariables)
Definition: easvariants.hh:90
Definition: utils/dirichletvalues.hh:32
Concept to check if the underlying strain and stress tag correspond to a total Lagrangian formulation...
Definition: utils/concepts.hh:670