12#if HAVE_DUNE_LOCALFEFUNCTIONS
13 #include <dune/fufem/boundarypatch.hh>
14 #include <dune/geometry/quadraturerules.hh>
15 #include <dune/geometry/type.hh>
16 #include <dune/localfefunctions/cachedlocalBasis/cachedlocalBasis.hh>
17 #include <dune/localfefunctions/expressions/greenLagrangeStrains.hh>
18 #include <dune/localfefunctions/impl/standardLocalFunction.hh>
19 #include <dune/localfefunctions/manifolds/realTuple.hh>
46 template <Concepts::Material DEV, Concepts::Material VOL>
47 struct DPConstitutiveDriver
51 auto Uhat(
const auto& Estrain)
const {
return vol_.template storedEnergy<strainType>(Estrain); }
53 auto storedEnergy(
const auto& Estrain,
const auto& p) {
54 auto Wdev = dev_.template storedEnergy<strainType>(Estrain);
55 auto uhat = Uhat(Estrain);
56 return Wdev + p * uhat - (1.0 / (2.0 * kappa_)) * Dune::power(p, 2);
59 auto firstDerivatives(
const auto& Estrain,
const auto& p)
const {
60 const auto Sdev = dev_.template stresses<strainType, true>(Estrain);
61 const auto dUdE = vol_.template stresses<strainType, true>(Estrain);
62 const auto S = (Sdev + p * dUdE).eval();
63 return std::make_tuple(dUdE, S);
66 auto secondDerivative(
const auto& Estrain,
const auto& p)
const {
67 const auto Cdev = dev_.template tangentModuli<strainType, true>(Estrain);
68 const auto d2UdE2 = vol_.template tangentModuli<strainType, true>(Estrain);
69 const auto C = (Cdev + p * d2UdE2).eval();
73 double kappa()
const {
return kappa_; }
75 DEV deviatoricMaterial()
const {
return dev_; }
76 VOL volumetricMaterial()
const {
return vol_; }
78 DPConstitutiveDriver(
const DEV& dev,
const VOL& vol,
double kappa)
88 template <
typename STO>
90 auto reboundDEV = dev_.template rebind<STO>();
91 auto reboundVOL = vol_.template rebind<STO>();
92 return DPConstitutiveDriver<decltype(reboundDEV), decltype(reboundVOL)>(reboundDEV, reboundVOL, kappa_);
102template <
typename PreFE,
typename FE,
typename PRE>
103class DisplacementPressure;
109template <Concepts::Material MAT>
115 template <
typename PreFE,
typename FE>
128template <
typename PreFE,
typename FE,
typename PRE>
143 decltype(std::declval<LocalView>().tree().child(Dune::Indices::_0).child(0).finiteElement().localBasis());
145 decltype(std::declval<LocalView>().tree().child(Dune::Indices::_1).finiteElement().localBasis());
147 template <
typename ST>
148 using VectorXOptRef = std::optional<std::reference_wrapper<const Eigen::VectorX<ST>>>;
155 template <
template <
typename,
int,
int>
class RT>
158 template <
typename ST =
double>
161 template <
typename ST =
double>
162 using BopType = Eigen::Matrix<ST, strainDim, myDim>;
164 template <
typename ST =
double>
165 using KgType = Eigen::Matrix<ST, myDim, myDim>;
169 template <
typename MAT>
172 template <
typename MAT>
183 : constitutiveDriver_([](const auto& mat) {
187 static_assert(Pre::Material::isHyperelastic,
"DisplacementPressure is only implemented for the hyperelastic case.");
195 const auto& localView = underlying().localView();
196 const auto& element = localView.element();
197 auto& firstChild = localView.tree().child(Dune::Indices::_0);
198 const auto& firstFE = firstChild.child(0).finiteElement();
200 auto& secondChild = localView.tree().child(Dune::Indices::_1);
201 const auto& secondFE = secondChild.finiteElement();
203 geo_ = std::make_shared<const Geometry>(element.geometry());
204 numberOfNodes_ = firstFE.size();
205 order_ = 2 * firstFE.localBasis().order();
206 localBasisU_ = Dune::CachedLocalBasis(firstFE.localBasis());
207 localBasisP_ = Dune::CachedLocalBasis(secondFE.localBasis());
209 if (underlying().quadratureRule()) {
210 localBasisU_.bind(underlying().quadratureRule().value(), Dune::bindDerivatives(0, 1));
211 localBasisP_.bind(underlying().quadratureRule().value(), Dune::bindDerivatives(0, 1));
213 localBasisU_.bind(defaultQuadratureRule<myDim>(element, order_), Dune::bindDerivatives(0, 1));
214 localBasisP_.bind(defaultQuadratureRule<myDim>(element, order_), Dune::bindDerivatives(0, 1));
227 template <
typename ScalarType =
double>
231 Ikarus::FEHelper::localSolutionBlockVectorComposite<Traits>(d, underlying().localView(), Dune::Indices::_0, dx);
232 Dune::StandardLocalFunction uFunction(localBasisU_, disp, geo_);
244 template <
typename ScalarType =
double>
248 Ikarus::FEHelper::localSolutionBlockVectorScalar<Traits>(d, underlying().localView(), Dune::Indices::_1, dx);
250 Dune::StandardLocalFunction pFunction(localBasisP_, pressure, geo_);
262 template <
typename ScalarType =
double>
269 [[nodiscard]]
int order()
const {
return order_; }
270 const Dune::CachedLocalBasis<std::remove_cvref_t<LocalBasisTypeU>>&
localBasis()
const {
return localBasisU_; }
271 const Dune::CachedLocalBasis<std::remove_cvref_t<LocalBasisTypeP>>&
localBasisP()
const {
return localBasisP_; }
273 template <
typename ScalarType =
double>
276 return constitutiveDriver_.template rebind<ScalarType>();
278 return constitutiveDriver_;
288 template <
template <
typename,
int,
int>
class RT>
289 requires(supportsResultType<RT>())
291 return [&](
const Eigen::Vector<double, strainDim>& strainInVoigt,
double p) {
292 if constexpr (isSameResultType<RT, ResultTypes::PK2Stress> or isSameResultType<RT, ResultTypes::PK2StressFull>) {
293 auto [dev, vol] = [&]() {
294 if constexpr (isSameResultType<RT, ResultTypes::PK2StressFull> and PRE::Material::isReduced)
295 return std::make_pair(constitutiveDriver_.deviatoricMaterial().underlying(),
296 constitutiveDriver_.volumetricMaterial().underlying());
298 return std::make_pair(constitutiveDriver_.deviatoricMaterial(), constitutiveDriver_.volumetricMaterial());
302 dev.template stresses<strainType>(enlargeIfReduced<typename PRE::Material>(strainInVoigt)) +
303 p * vol.template stresses<strainType>(enlargeIfReduced<typename PRE::Material>(strainInVoigt))};
317 template <
template <
typename,
int,
int>
class RT>
318 requires(supportsResultType<RT>())
320 Dune::PriorityTag<1>)
const {
321 using namespace Dune::DerivativeDirections;
323 if constexpr (isSameResultType<RT, ResultTypes::PK2Stress> or isSameResultType<RT, ResultTypes::PK2StressFull>) {
327 const auto rFunction = resultFunction<RT>();
328 const auto H = uFunction.evaluateDerivative(local, Dune::wrt(spatialAll), Dune::on(gridElement));
329 const auto p = pFunction.evaluate(local, Dune::on(gridElement)).eval();
330 const auto E = (0.5 * (H.transpose() + H + H.transpose() * H)).eval();
332 return rFunction(
toVoigt(E), p[0]);
338 const auto& underlying()
const {
return static_cast<const FE&
>(*this); }
339 auto& underlying() {
return static_cast<FE&
>(*this); }
340 std::shared_ptr<const Geometry> geo_;
341 Dune::CachedLocalBasis<std::remove_cvref_t<LocalBasisTypeU>> localBasisU_;
342 Dune::CachedLocalBasis<std::remove_cvref_t<LocalBasisTypeP>> localBasisP_;
344 size_t numberOfNodes_{0};
358 template <
typename ST>
361 return [&](
const FE::template
KgType<ST>& kgIJ,
const int I,
const int J,
const auto& gp) {
362 const auto geo = underlying().localView().element().geometry();
363 const double intElement = geo.integrationElement(gp.position()) * gp.weight();
364 K.template block<FE::myDim, FE::myDim>(I *
FE::myDim, J *
FE::myDim) += kgIJ * intElement;
377 template <
typename ST>
381 [&](
const auto& C,
const BopType<ST>& bopI,
const BopType<ST>& bopJ,
const int I,
const int J,
const auto& gp) {
382 const double intElement = geo_->integrationElement(gp.position()) * gp.weight();
383 K.template block<myDim, myDim>(I *
myDim, J *
myDim) += (bopI.transpose() * C * bopJ) * intElement;
398 template <
typename ST>
402 const double intElement = geo_->integrationElement(gp.position()) * gp.weight();
403 force.template segment<myDim>(
myDim * I) += bopI.transpose() * stresses * intElement;
415 template <
typename ST>
418 using namespace Dune::DerivativeDirections;
419 using namespace Dune;
423 for (
const auto& [gpIndex, gp] : eps.viewOverIntegrationPoints()) {
424 const auto EVoigt = eps.evaluate(gpIndex, on(gridElement));
425 const auto p = pFunction.evaluate(gpIndex, on(gridElement)).eval();
427 auto e = constitutiveDriver<ST>().storedEnergy(EVoigt, p[0]);
428 energy += e * geo_->integrationElement(gp.position()) * gp.weight();
442 template <
typename ScalarType>
444 typename Traits::template MatrixType<> K,
447 static_assert(Dune::AlwaysFalse<ScalarType>::value,
448 "DisplacementPressure element does not support matrix calculations for autodiff scalars");
450 using namespace Dune::DerivativeDirections;
451 using namespace Dune;
454 auto pFE = underlying().localView().tree().child(Dune::Indices::_1);
455 auto plocalBasis = pFE.finiteElement().localBasis();
456 std::vector<Dune::FieldVector<double, 1>> Np;
459 const auto kMFunction = materialStiffnessMatrixFunction<ScalarType>(par, K, dx);
460 const auto kGFunction = geometricStiffnessMatrixFunction<ScalarType>(par, K, dx);
461 for (
const auto& [gpIndex, gp] : eps.viewOverIntegrationPoints()) {
462 const auto EVoigt = (eps.evaluate(gpIndex, on(gridElement))).eval();
463 const auto p = pFunction.evaluate(gpIndex, on(gridElement)).eval();
464 plocalBasis.evaluateFunction(gp.position(), Np);
465 const auto intElement = geo_->integrationElement(gp.position()) * gp.weight();
467 auto [dUdE, S] = constitutiveDriver<ScalarType>().firstDerivatives(EVoigt, p[0]);
468 auto C = constitutiveDriver<ScalarType>().secondDerivative(EVoigt, p[0]);
471 for (
size_t i = 0; i < numberOfNodes_; ++i) {
472 const auto bopI = eps.evaluateDerivative(gpIndex, wrt(coeff(i)), on(gridElement));
473 for (
size_t j = 0; j < numberOfNodes_; ++j) {
474 const auto bopJ = eps.evaluateDerivative(gpIndex, wrt(coeff(j)), on(gridElement));
475 const auto kgIJ = eps.evaluateDerivative(gpIndex, wrt(coeff(i, j)), along(S), on(gridElement));
476 kMFunction(C, bopI, bopJ, i, j, gp);
477 kGFunction(kgIJ, i, j, gp);
482 for (
size_t i = 0; i < numberOfNodes_; ++i) {
483 const auto bopI = eps.evaluateDerivative(gpIndex, wrt(coeff(i)), on(gridElement));
484 for (
auto j : Dune::range(pFE.size())) {
485 auto jIdx = pFE.localIndex(j);
486 const auto upTerm = (bopI.transpose() * dUdE * Np[j][0]).eval();
487 K.template block<myDim, 1>(i *
myDim, jIdx) += upTerm * intElement;
492 for (
auto i : Dune::range(pFE.size())) {
493 auto iIdx = pFE.localIndex(i);
494 for (
size_t j = 0; j < numberOfNodes_; ++j) {
495 const auto bopJ = eps.evaluateDerivative(gpIndex, wrt(coeff(j)), on(gridElement));
496 const auto upTerm = (bopJ.transpose() * dUdE * Np[i][0]).
transpose().eval();
497 K.template block<1, myDim>(iIdx, j *
myDim) += upTerm * intElement;
502 for (
auto i : Dune::range(pFE.size())) {
503 auto iIdx = pFE.localIndex(i);
504 for (
auto j : Dune::range(pFE.size())) {
505 auto jIdx = pFE.localIndex(j);
506 auto ppTerm = Np[i][0] * (1.0 / constitutiveDriver_.kappa()) * Np[j][0];
507 K(iIdx, jIdx) -= ppTerm * intElement;
513 template <
typename ScalarType>
519 static_assert(Dune::AlwaysFalse<ScalarType>::value,
520 "DisplacementPressure element does not support scalar calculations for autodiff scalars");
524 template <
typename ScalarType>
526 typename Traits::template VectorType<ScalarType> force,
529 static_assert(Dune::AlwaysFalse<ScalarType>::value,
530 "DisplacementPressure element does not support vector calculations for autodiff scalars");
532 using namespace Dune::DerivativeDirections;
533 using namespace Dune;
537 auto pFE = underlying().localView().tree().child(Dune::Indices::_1);
538 auto plocalBasis = pFE.finiteElement().localBasis();
539 std::vector<Dune::FieldVector<double, 1>> Np;
541 const auto fIntFunction = internalForcesFunction<ScalarType>(par, force, dx);
543 for (
const auto& [gpIndex, gp] : eps.viewOverIntegrationPoints()) {
544 const auto EVoigt = (eps.evaluate(gpIndex, on(gridElement))).eval();
545 const auto p = pFunction.evaluate(gpIndex, on(gridElement)).eval();
546 plocalBasis.evaluateFunction(gp.position(), Np);
548 auto [dUdE, S] = constitutiveDriver<ScalarType>().firstDerivatives(EVoigt, p[0]);
549 auto Uhat = constitutiveDriver<ScalarType>().Uhat(EVoigt);
552 for (
size_t i = 0; i < numberOfNodes_; ++i) {
553 const auto bopI = eps.evaluateDerivative(gpIndex, wrt(coeff(i)), on(gridElement));
554 fIntFunction(S, bopI, i, gp);
558 for (
auto i : Dune::range(pFE.size())) {
559 auto iIdx = pFE.localIndex(i);
560 auto pTerm = Np[i][0] * (Uhat - p[0] / constitutiveDriver_.kappa());
561 force(iIdx) += pTerm * geo_->integrationElement(gp.position()) * gp.weight();
573template <Concepts::Material MAT>
582 #error DisplacementPressure depends on dune-localfefunctions, which is not included
Free function for creating a tensor product quadrature rule and other Dune::Quadrature rule utils.
Collection of fallback default functions.
Helper for transform between Dune linear algebra types and Eigen.
Helper for the autodiff library.
Header file for various EAS functions.
Definition of several material related enums.
Definition of helper struct and function to decompose a hyperelastic material model.
Header file for types of loads in Ikarus finite element mechanics.
Material property functions and conversion utilities.
Contains the FE class, which is used as a base class for all finite elements. It provides information...
Definition of the LinearElastic class for finite element mechanics computations.
constexpr Eigen::Index toVoigt(Eigen::Index i, Eigen::Index j) noexcept
Converts 2D indices to Voigt notation index.
Definition: tensorutils.hh:182
Definition: assemblermanipulatorbuildingblocks.hh:22
MatrixAffordance
A strongly typed enum class representing the matrix affordance.
Definition: ferequirements.hh:65
auto displacementPressure(const MAT &mat)
A helper function to create a displacement-pressure pre finite element.
Definition: displacementpressure.hh:574
VectorAffordance
A strongly typed enum class representing the vector affordance.
Definition: ferequirements.hh:50
auto transpose(const Eigen::EigenBase< Derived > &A)
ScalarAffordance
A strongly typed enum class representing the scalar affordance.
Definition: ferequirements.hh:39
auto decomposeHyperelasticAndGetMaterialParameters(const MAT &mat)
A helper function to decompose a hyperelastic material model and get the underlying deviatoric materi...
Definition: decomposehyperelastic.hh:47
Definition: utils/dirichletvalues.hh:35
FE class is a base class for all finite elements.
Definition: febase.hh:79
static constexpr int myDim
Definition: febase.hh:95
FETraits< BH, useEigenRef, useFlat > Traits
Definition: febase.hh:38
Class representing the requirements for finite element calculations.
Definition: ferequirements.hh:224
const SolutionVectorType & globalSolution() const
Get the global solution vector.
Definition: ferequirements.hh:314
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
Base class for element definitions that provides common functionality for ResultTypes.
Definition: feresulttypes.hh:277
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
std::conditional_t< useFlat, FlatBasis, UntouchedBasis > Basis
Type of the basis version.
Definition: fetraits.hh:39
typename Basis::GridView GridView
Type of the grid view.
Definition: fetraits.hh:45
typename BasisHandler::FlatBasis FlatBasis
Type of the flat basis.
Definition: fetraits.hh:33
typename LocalView::Element Element
Type of the grid element.
Definition: fetraits.hh:48
static constexpr int mydim
Dimension of the geometry.
Definition: fetraits.hh:63
DisplacementPressure class represents a displacement-pressure finite element.
Definition: displacementpressure.hh:130
decltype(std::declval< LocalView >().tree().child(Dune::Indices::_0).child(0).finiteElement().localBasis()) LocalBasisTypeU
Definition: displacementpressure.hh:143
static constexpr auto strainType
Definition: displacementpressure.hh:152
DisplacementPressure(const Pre &pre)
Constructor for the DisplacementPressure class.
Definition: displacementpressure.hh:182
typename Traits::Geometry Geometry
Definition: displacementpressure.hh:137
static constexpr auto stressType
Definition: displacementpressure.hh:153
decltype(auto) constitutiveDriver() const
Definition: displacementpressure.hh:274
auto calculateAtImpl(const Requirement &req, const Dune::FieldVector< double, Traits::mydim > &local, Dune::PriorityTag< 1 >) const
Calculates a requested result at a specific local position.
Definition: displacementpressure.hh:319
typename Pre::Material MaterialType
Definition: displacementpressure.hh:167
void calculateVectorImpl(const Requirement &par, VectorAffordance affordance, typename Traits::template VectorType< ScalarType > force, const VectorXOptRef< ScalarType > &dx=std::nullopt) const
Definition: displacementpressure.hh:525
int order() const
Definition: displacementpressure.hh:269
std::optional< std::reference_wrapper< const Eigen::VectorX< ST > > > VectorXOptRef
Definition: displacementpressure.hh:148
typename Traits::Basis Basis
Definition: displacementpressure.hh:133
auto geometricStiffnessMatrixFunction(const Requirement &par, typename Traits::template MatrixType< ST > &K, const VectorXOptRef< ST > &dx=std::nullopt) const
Get a lambda function that evaluates the geometric part of the stiffness matrix (Kg) for a given inte...
Definition: displacementpressure.hh:359
typename Traits::Element Element
Definition: displacementpressure.hh:139
Impl::DPConstitutiveDriver< DecomposedDevType< MaterialType >, DecomposedVolType< MaterialType > > DPConstitutiveDriverType
Definition: displacementpressure.hh:176
auto resultFunction() const
Get a lambda function that evaluates the requested result type for a given strain (in Voigt notation)...
Definition: displacementpressure.hh:290
typename Materials::DecomposedMaterialTypes< MaterialType >::DevType DecomposedDevType
Definition: displacementpressure.hh:170
const Geometry & geometry() const
Definition: displacementpressure.hh:267
size_t numberOfNodes() const
Definition: displacementpressure.hh:268
const Dune::CachedLocalBasis< std::remove_cvref_t< LocalBasisTypeU > > & localBasis() const
Definition: displacementpressure.hh:270
typename Traits::GridView GridView
Definition: displacementpressure.hh:138
typename Traits::LocalView LocalView
Definition: displacementpressure.hh:136
void bindImpl()
A helper function to bind the local view to the element.
Definition: displacementpressure.hh:194
auto materialStiffnessMatrixFunction(const Requirement &par, typename Traits::template MatrixType< ST > &K, const VectorXOptRef< ST > &dx=std::nullopt) const
Get a lambda function that evaluates the material part of the stiffness matrix (Ke + Ku) for a given ...
Definition: displacementpressure.hh:378
Eigen::Matrix< ST, myDim, myDim > KgType
Definition: displacementpressure.hh:165
PRE Pre
Definition: displacementpressure.hh:140
typename Materials::DecomposedMaterialTypes< MaterialType >::VolType DecomposedVolType
Definition: displacementpressure.hh:173
static constexpr int strainDim
Definition: displacementpressure.hh:151
typename Traits::FlatBasis FlatBasis
Definition: displacementpressure.hh:134
void calculateMatrixImpl(const Requirement &par, const MatrixAffordance &affordance, typename Traits::template MatrixType<> K, const VectorXOptRef< ScalarType > &dx=std::nullopt) const
Calculate the matrix associated with the given Requirement.
Definition: displacementpressure.hh:443
Eigen::Vector< ST, strainDim > StrainType
Definition: displacementpressure.hh:159
auto strainFunction(const Requirement &par, const VectorXOptRef< ScalarType > &dx=std::nullopt) const
The strain function for the given Requirement.
Definition: displacementpressure.hh:263
auto displacementFunction(const Requirement &par, const VectorXOptRef< ScalarType > &dx=std::nullopt) const
Get the displacement function for the given Requirement.
Definition: displacementpressure.hh:228
auto internalForcesFunction(const Requirement &par, typename Traits::template VectorType< ST > &force, const VectorXOptRef< ST > &dx=std::nullopt) const
Get a lambda function that evaluates the internal force vector for a given strain,...
Definition: displacementpressure.hh:399
decltype(std::declval< LocalView >().tree().child(Dune::Indices::_1).finiteElement().localBasis()) LocalBasisTypeP
Definition: displacementpressure.hh:145
static constexpr int myDim
Definition: displacementpressure.hh:150
auto pressureFunction(const Requirement &par, const VectorXOptRef< ScalarType > &dx=std::nullopt) const
Get the pressure function for the given Requirement.
Definition: displacementpressure.hh:245
Eigen::Matrix< ST, strainDim, myDim > BopType
Definition: displacementpressure.hh:162
auto calculateScalarImpl(const Requirement &par, ScalarAffordance affordance, const VectorXOptRef< ScalarType > &dx=std::nullopt) const -> ScalarType
Definition: displacementpressure.hh:514
const Dune::CachedLocalBasis< std::remove_cvref_t< LocalBasisTypeP > > & localBasisP() const
Definition: displacementpressure.hh:271
auto energyFunction(const Requirement &par, const VectorXOptRef< ST > &dx=std::nullopt) const
Get a lambda function that evaluates the internal energy at a given integration point and its index.
Definition: displacementpressure.hh:416
A PreFE struct for displacement-pressure elements.
Definition: displacementpressure.hh:111
MAT material
Definition: displacementpressure.hh:113
MAT Material
Definition: displacementpressure.hh:112
std::tuple_element_t< 1, TupleType > VolType
Type of the pure volumetric material model.
Definition: decomposehyperelastic.hh:25
std::tuple_element_t< 0, TupleType > DevType
Type of the pure deviatoric material model.
Definition: decomposehyperelastic.hh:24
Definition: utils/dirichletvalues.hh:37
Concept to check if the underlying scalar type is a dual type.
Definition: utils/concepts.hh:625
Implementation of the Hyperelastic material model.