Skip to content

Commit 9b4bbef

Browse files
henrij22AlexanderMueller
authored and
AlexanderMueller
committed
Add vanishing strain wrapper (for plane strain) (#317)
1 parent d05187e commit 9b4bbef

36 files changed

+1345
-501
lines changed

CHANGELOG.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ SPDX-License-Identifier: LGPL-3.0-or-later
4343
- Python:
4444
- Bindings for Enums can now be done conveniently with the `ENUM_BINDINGS` macro.
4545
- The finite element functions `calculateMatrix`, `calculateVector`, and `calculateScalar` now directly accept the affordances.
46-
- The assembler bindings now also accept affordances and `DBCOption`, and they are also renamed to simply `matrix`, `vector`
46+
- The assembler bindings now also accept affordances and `DBCOption`, and they are also renamed to simply `matrix`, `vector`
4747
and `scalar`.
4848
- The assemblers also export the binding functions to bind the assemblers.
4949
- Added a new class `AssemblerManipulator` that wraps an existing assembler
@@ -55,6 +55,7 @@ SPDX-License-Identifier: LGPL-3.0-or-later
5555
- Add a truss element ([#302](https://github.com/ikarus-project/ikarus/pull/302))
5656
- Add an About Ikarus page in the documentation ([#291](https://github.com/ikarus-project/ikarus/pull/291))
5757
- Add new class `Vtk::Writer`, which implements some convenience methods over the existing `dune-vtk` module ([#309](https://github.com/ikarus-project/ikarus/pull/309))
58+
- Add `VanishingStrain` material (useful for example for plane strain case), also refactor the constructor of `LinearElastic` to take any linear material law ([#317](https://github.com/ikarus-project/ikarus/pull/317))
5859

5960
## Release v0.4 (Ganymede)
6061

ikarus/finiteelements/mechanics/linearelastic.hh

Lines changed: 19 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -26,18 +26,21 @@
2626

2727
namespace Ikarus {
2828

29-
template <typename PreFE, typename FE>
29+
template <typename PreFE, typename FE, typename PRE>
3030
class LinearElastic;
3131

3232
/**
3333
* \brief A PreFE struct for linear elastic elements.
34+
* \tparam MAT Type of the material.
3435
*/
36+
template <Concepts::GeometricallyLinearMaterial MAT>
3537
struct LinearElasticPre
3638
{
37-
YoungsModulusAndPoissonsRatio material;
39+
using Material = MAT;
40+
MAT material;
3841

3942
template <typename PreFE, typename FE>
40-
using Skill = LinearElastic<PreFE, FE>;
43+
using Skill = LinearElastic<PreFE, FE, LinearElasticPre>;
4144
};
4245

4346
/**
@@ -48,7 +51,7 @@ struct LinearElasticPre
4851
* \tparam PreFE The type of the pre finite element.
4952
* \tparam FE The type of the finite element.
5053
*/
51-
template <typename PreFE, typename FE>
54+
template <typename PreFE, typename FE, typename PRE>
5255
class LinearElastic : public ResultTypeBase<ResultTypes::linearStress>
5356
{
5457
public:
@@ -61,7 +64,8 @@ public:
6164
using Geometry = typename Traits::Geometry;
6265
using GridView = typename Traits::GridView;
6366
using Element = typename Traits::Element;
64-
using Pre = LinearElasticPre;
67+
using Material = PRE::Material;
68+
using Pre = PRE;
6569

6670
static constexpr int myDim = Traits::mydim;
6771
using LocalBasisType = decltype(std::declval<LocalView>().tree().child(0).finiteElement().localBasis());
@@ -115,7 +119,8 @@ public:
115119
return uFunction;
116120
}
117121
/**
118-
* \brief Gets the strain function for the given Requirement and optional displacement vector.
122+
* \brief Gets the strain function for the given Requirement and optional di
123+
splacement vector.
119124
*
120125
* \tparam ScalarType The scalar type for the strain vector.
121126
* \param par The Requirement object.
@@ -135,10 +140,8 @@ public:
135140
* \return The material tangent matrix.
136141
*/
137142
auto materialTangent() const {
138-
if constexpr (myDim == 2)
139-
return planeStressLinearElasticMaterialTangent(mat_.emodul, mat_.nu);
140-
else if constexpr (myDim == 3)
141-
return linearElasticMaterialTangent3D(mat_.emodul, mat_.nu);
143+
// Since that material is independent of the strains, a zero strain is passed here
144+
return mat_.template tangentModuli<StrainTags::linear, true>(Eigen::Vector<double, 6>::Zero());
142145
}
143146

144147
/**
@@ -187,7 +190,7 @@ private:
187190

188191
std::shared_ptr<const Geometry> geo_;
189192
Dune::CachedLocalBasis<std::remove_cvref_t<LocalBasisType>> localBasis_;
190-
YoungsModulusAndPoissonsRatio mat_;
193+
Material mat_;
191194
size_t numberOfNodes_{0};
192195
int order_{};
193196

@@ -257,11 +260,13 @@ protected:
257260

258261
/**
259262
* \brief A helper function to create a linear elastic pre finite element.
260-
* \param mat Material parameters for the linear elastic element.
263+
* \tparam MAT Type of the material.
264+
* \param mat Material parameters for the non-linear elastic element.
261265
* \return A linear elastic pre finite element.
262266
*/
263-
auto linearElastic(const YoungsModulusAndPoissonsRatio& mat) {
264-
LinearElasticPre pre(mat);
267+
template <typename MAT>
268+
auto linearElastic(const MAT& mat) {
269+
LinearElasticPre<MAT> pre(mat);
265270

266271
return pre;
267272
}

ikarus/finiteelements/mechanics/materials.hh

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,4 +13,5 @@
1313
#include <ikarus/finiteelements/mechanics/materials/neohooke.hh>
1414
#include <ikarus/finiteelements/mechanics/materials/svk.hh>
1515
#include <ikarus/finiteelements/mechanics/materials/tags.hh>
16+
#include <ikarus/finiteelements/mechanics/materials/vanishingstrain.hh>
1617
#include <ikarus/finiteelements/mechanics/materials/vanishingstress.hh>

ikarus/finiteelements/mechanics/materials/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,5 +10,7 @@ install(
1010
svk.hh
1111
tags.hh
1212
vanishingstress.hh
13+
vanishingstrain.hh
14+
vanishinghelpers.hh
1315
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/ikarus/finiteelements/mechanics/materials
1416
)

ikarus/finiteelements/mechanics/materials/interface.hh

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,9 @@ struct Material;
2424

2525
template <auto stressIndexPair, typename MImpl>
2626
struct VanishingStress;
27+
28+
template <auto strainIndexPair, typename MImpl>
29+
struct VanishingStrain;
2730
#endif
2831

2932
/**
@@ -78,9 +81,10 @@ struct Material
7881
using MaterialImpl = MI; ///< Type of material implementation
7982

8083
/**
81-
* \brief Static constant for determining if the material has vanishing stress components (is reduced).
84+
* \brief Static constant for determining if the material has vanishing stress or strain components (is reduced).
8285
*/
83-
static constexpr bool isReduced = traits::isSpecializationNonTypeAndTypes<VanishingStress, MaterialImpl>::value;
86+
static constexpr bool isReduced = traits::isSpecializationNonTypeAndTypes<VanishingStress, MaterialImpl>::value or
87+
traits::isSpecializationNonTypeAndTypes<VanishingStrain, MaterialImpl>::value;
8488

8589
/**
8690
* \brief Const accessor to the underlying material (CRTP).
@@ -101,7 +105,21 @@ struct Material
101105
*
102106
* \return Name of the material.
103107
*/
104-
[[nodiscard]] constexpr std::string name() const { return impl().nameImpl(); }
108+
[[nodiscard]] constexpr static std::string name() { return MI::nameImpl(); }
109+
110+
/**
111+
* \brief Returns the material parameters stored in the implemented material.
112+
* \return Material parameter.
113+
*/
114+
[[nodiscard]] auto materialParameters() const { return impl().materialParametersImpl(); }
115+
116+
/**
117+
* \brief This factor denotes the differences between the returned stresses and moduli and the passed strain
118+
* \details For neoHooke the inserted quantity is $C$ the Green-Lagrangian strain tensor, the function relation
119+
* between the energy and the stresses is $S = 1 \dfrac{\partial\psi(E)}{\partial E}$. This factor is the pre factor,
120+
* which is the difference to the actual derivative, which is written here
121+
*/
122+
static constexpr double derivativeFactor = MI::derivativeFactorImpl;
105123

106124
/**
107125
* \brief Return the stored potential energy of the material.

ikarus/finiteelements/mechanics/materials/linearelasticity.hh

Lines changed: 23 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -34,38 +34,39 @@ namespace Ikarus {
3434
template <typename ST>
3535
struct LinearElasticityT : Material<LinearElasticityT<ST>>
3636
{
37-
[[nodiscard]] constexpr std::string nameImpl() const noexcept { return "LinearElasticity"; }
38-
3937
using ScalarType = ST;
4038
using Base = StVenantKirchhoffT<ScalarType>;
4139

40+
using field_type = ScalarType;
41+
static constexpr int worldDimension = 3;
42+
using StrainMatrix = Eigen::Matrix<ScalarType, worldDimension, worldDimension>;
43+
using StressMatrix = StrainMatrix;
44+
using MaterialParameters = typename Base::MaterialParameters;
45+
46+
static constexpr auto strainTag = StrainTags::linear;
47+
static constexpr auto stressTag = StressTags::linear;
48+
static constexpr auto tangentModuliTag = TangentModuliTags::Material;
49+
static constexpr bool energyAcceptsVoigt = Base::energyAcceptsVoigt;
50+
static constexpr bool stressToVoigt = Base::stressToVoigt;
51+
static constexpr bool stressAcceptsVoigt = Base::stressAcceptsVoigt;
52+
static constexpr bool moduliToVoigt = Base::moduliToVoigt;
53+
static constexpr bool moduliAcceptsVoigt = Base::moduliAcceptsVoigt;
54+
static constexpr double derivativeFactorImpl = Base::derivativeFactorImpl;
55+
56+
[[nodiscard]] constexpr static std::string nameImpl() noexcept { return "LinearElasticity"; }
57+
4258
/**
4359
* \brief Constructor for LinearElasticityT.
4460
*
4561
* \param mpt The LamesFirstParameterAndShearModulus object.
4662
*/
47-
explicit LinearElasticityT(const LamesFirstParameterAndShearModulus& mpt)
63+
explicit LinearElasticityT(const MaterialParameters& mpt)
4864
: svk_{mpt} {}
4965

50-
using field_type = ScalarType;
51-
static constexpr int worldDimension = 3;
52-
using StrainMatrix = Eigen::Matrix<ScalarType, worldDimension, worldDimension>;
53-
using StressMatrix = StrainMatrix;
54-
55-
static constexpr auto strainTag = StrainTags::linear;
56-
static constexpr auto stressTag = StressTags::linear;
57-
static constexpr auto tangentModuliTag = TangentModuliTags::Material;
58-
static constexpr bool energyAcceptsVoigt = Base::energyAcceptsVoigt;
59-
static constexpr bool stressToVoigt = Base::stressToVoigt;
60-
static constexpr bool stressAcceptsVoigt = Base::stressAcceptsVoigt;
61-
static constexpr bool moduliToVoigt = Base::moduliToVoigt;
62-
static constexpr bool moduliAcceptsVoigt = Base::moduliAcceptsVoigt;
63-
64-
// This factor denotes the differences between the returned stresses and moduli
65-
// and the passed strain. For neoHooke the inserted quantity is C, the right Cauchy-Green tensor.
66-
// The function relation between the energy and the stresses is S = 2*\partial \psi(C)/ \partial C.
67-
// This factor is a pre-factor, which is the difference to the actual derivative is written here.
68-
static constexpr double derivativeFactor = 1;
66+
/**
67+
* \brief Returns the material parameters stored in the material
68+
*/
69+
MaterialParameters materialParametersImpl() const { return svk_.materialParametersImpl(); }
6970

7071
/**
7172
* \brief Calculates the stored energy in the material.

ikarus/finiteelements/mechanics/materials/neohooke.hh

Lines changed: 32 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -35,29 +35,35 @@ namespace Ikarus {
3535
template <typename ST>
3636
struct NeoHookeT : public Material<NeoHookeT<ST>>
3737
{
38-
[[nodiscard]] constexpr std::string nameImpl() const noexcept { return "NeoHooke"; }
38+
using ScalarType = ST;
39+
static constexpr int worldDimension = 3;
40+
using StrainMatrix = Eigen::Matrix<ScalarType, worldDimension, worldDimension>;
41+
using StressMatrix = StrainMatrix;
42+
using MaterialParameters = LamesFirstParameterAndShearModulus;
43+
44+
static constexpr auto strainTag = StrainTags::rightCauchyGreenTensor;
45+
static constexpr auto stressTag = StressTags::PK2;
46+
static constexpr auto tangentModuliTag = TangentModuliTags::Material;
47+
static constexpr bool energyAcceptsVoigt = false;
48+
static constexpr bool stressToVoigt = false;
49+
static constexpr bool stressAcceptsVoigt = false;
50+
static constexpr bool moduliToVoigt = false;
51+
static constexpr bool moduliAcceptsVoigt = false;
52+
static constexpr double derivativeFactorImpl = 2;
53+
54+
[[nodiscard]] constexpr static std::string nameImpl() noexcept { return "NeoHooke"; }
3955

4056
/**
4157
* \brief Constructor for NeoHookeT.
4258
* \param mpt The Lame's parameters (first parameter and shear modulus).
4359
*/
44-
explicit NeoHookeT(const LamesFirstParameterAndShearModulus& mpt)
45-
: lambdaAndmu_{mpt} {}
60+
explicit NeoHookeT(const MaterialParameters& mpt)
61+
: materialParameter_{mpt} {}
4662

47-
using ScalarType = ST;
48-
static constexpr int worldDimension = 3;
49-
using StrainMatrix = Eigen::Matrix<ScalarType, worldDimension, worldDimension>;
50-
using StressMatrix = StrainMatrix;
51-
52-
static constexpr auto strainTag = StrainTags::rightCauchyGreenTensor;
53-
static constexpr auto stressTag = StressTags::PK2;
54-
static constexpr auto tangentModuliTag = TangentModuliTags::Material;
55-
static constexpr bool energyAcceptsVoigt = false;
56-
static constexpr bool stressToVoigt = false;
57-
static constexpr bool stressAcceptsVoigt = false;
58-
static constexpr bool moduliToVoigt = false;
59-
static constexpr bool moduliAcceptsVoigt = false;
60-
static constexpr double derivativeFactor = 2;
63+
/**
64+
* \brief Returns the material parameters stored in the material
65+
*/
66+
MaterialParameters materialParametersImpl() const { return materialParameter_; }
6167

6268
/**
6369
* \brief Computes the stored energy in the Neo-Hookean material model.
@@ -71,7 +77,8 @@ struct NeoHookeT : public Material<NeoHookeT<ST>>
7177
if constexpr (!Concepts::EigenVector<Derived>) {
7278
const auto traceC = C.trace();
7379
const auto logdetF = log(sqrt(C.determinant()));
74-
return lambdaAndmu_.mu / 2.0 * (traceC - 3 - 2 * logdetF) + lambdaAndmu_.lambda / 2.0 * logdetF * logdetF;
80+
return materialParameter_.mu / 2.0 * (traceC - 3 - 2 * logdetF) +
81+
materialParameter_.lambda / 2.0 * logdetF * logdetF;
7582
} else
7683
static_assert(!Concepts::EigenVector<Derived>,
7784
"NeoHooke energy can only be called with a matrix and not a vector in Voigt notation");
@@ -91,7 +98,8 @@ struct NeoHookeT : public Material<NeoHookeT<ST>>
9198
if constexpr (!Concepts::EigenVector<Derived>) {
9299
const auto logdetF = log(sqrt(C.determinant()));
93100
const auto invC = C.inverse().eval();
94-
return (lambdaAndmu_.mu * (StrainMatrix::Identity() - invC) + lambdaAndmu_.lambda * logdetF * invC).eval();
101+
return (materialParameter_.mu * (StrainMatrix::Identity() - invC) + materialParameter_.lambda * logdetF * invC)
102+
.eval();
95103
} else
96104
static_assert(!Concepts::EigenVector<Derived>,
97105
"NeoHooke can only be called with a matrix and not a vector in Voigt notation");
@@ -115,8 +123,9 @@ struct NeoHookeT : public Material<NeoHookeT<ST>>
115123
const auto CTinv = tensorView(invC, std::array<Eigen::Index, 2>({3, 3}));
116124
static_assert(Eigen::TensorFixedSize<ScalarType, Eigen::Sizes<3, 3>>::NumIndices == 2);
117125
Eigen::TensorFixedSize<ScalarType, Eigen::Sizes<3, 3, 3, 3>> moduli =
118-
(lambdaAndmu_.lambda * dyadic(CTinv, CTinv) +
119-
2 * (lambdaAndmu_.mu - lambdaAndmu_.lambda * logdetF) * symTwoSlots(fourthOrderIKJL(invC, invC), {2, 3}))
126+
(materialParameter_.lambda * dyadic(CTinv, CTinv) +
127+
2 * (materialParameter_.mu - materialParameter_.lambda * logdetF) *
128+
symTwoSlots(fourthOrderIKJL(invC, invC), {2, 3}))
120129
.eval();
121130
return moduli;
122131
} else
@@ -130,11 +139,11 @@ struct NeoHookeT : public Material<NeoHookeT<ST>>
130139
*/
131140
template <typename STO>
132141
auto rebind() const {
133-
return NeoHookeT<STO>(lambdaAndmu_);
142+
return NeoHookeT<STO>(materialParameter_);
134143
}
135144

136145
private:
137-
LamesFirstParameterAndShearModulus lambdaAndmu_;
146+
MaterialParameters materialParameter_;
138147
};
139148

140149
/**

ikarus/finiteelements/mechanics/materials/strainconversions.hh

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ decltype(auto) createDeformationGradient(const Eigen::MatrixBase<Derived>& eMB)
8383
else if constexpr (tag == StrainTags::displacementGradient)
8484
return (e + Derived::Identity()).eval();
8585
else if constexpr (tag == StrainTags::rightCauchyGreenTensor) {
86-
return (e.sqrt()).eval(); // this looses information, since the rotation information from an original F is lost!
86+
return (e.sqrt()).eval(); // this looses information, since the rotation information from the original F is lost!
8787
}
8888
}
8989

@@ -125,14 +125,14 @@ decltype(auto) createRightCauchyGreen(const Eigen::MatrixBase<Derived>& eMB) {
125125
* \tparam from Type of the source strain tag.
126126
* \tparam to Type of the target strain tag.
127127
* \tparam Derived Type of the Eigen matrix.
128-
* \param eRaw Eigen matrix representing the input strain.
128+
* \param eRaw Eigen matrix representing the input strain (can be in Voigt notation).
129129
* \return The transformed strain matrix.
130130
*/
131131
template <StrainTags from, StrainTags to, typename Derived>
132132
decltype(auto) transformStrain(const Eigen::MatrixBase<Derived>& eRaw) {
133133
static_assert((from == to) or (from != StrainTags::linear and to != StrainTags::linear),
134134
"No useful transformation available for linear strains.");
135-
decltype(auto) e = Impl::mayTransformFromVoigt(eRaw, true);
135+
decltype(auto) e = Impl::mayTransformFromVoigt(eRaw.eval(), true);
136136
if constexpr (from == to)
137137
return e;
138138
else if constexpr (to == StrainTags::greenLagrangian)

0 commit comments

Comments
 (0)