12#include <autodiff/forward/dual/dual.hpp>
13#include <autodiff/forward/dual/eigen.hpp>
33template <
typename DEV,
typename VOL = NoVolumetricPart>
36 static_assert(std::is_same_v<DEV, Deviatoric<typename DEV::DeviatoricFunction>>);
37 static_assert(std::is_same_v<VOL, Volumetric<typename VOL::VolumetricFunction>>);
43 static constexpr int dim = 3;
46 using MaterialTensor = Eigen::TensorFixedSize<ScalarType, Eigen::Sizes<dim, dim, dim, dim>>;
51 std::conditional_t<hasVolumetricPart, std::pair<MaterialParametersDEV, MaterialParametersVOL>,
64 [[nodiscard]]
constexpr static std::string
nameImpl() noexcept {
66 return "Hyperelastic (" + DEV::name() +
", " + VOL::name() +
")";
68 return "Hyperelastic (" + DEV::name() +
")";
91 return {dev_.materialParameters(), vol_.materialParameter()};
93 return dev_.materialParameters();
102 template <
typename Derived>
104 static_assert(Concepts::EigenMatrixOrVoigtNotation3<Derived>);
106 const auto lambdas = principalStretches(C, Eigen::EigenvaluesOnly).first;
107 auto J = detF(C, lambdas);
109 return deviatoricEnergy(C, lambdas) + vol_.storedEnergy(J);
119 template <
bool voigt,
typename Derived>
121 static_assert(Concepts::EigenMatrixOrVoigtNotation3<Derived>);
122 if constexpr (!voigt) {
123 const auto [lambdas, N] = principalStretches(C);
124 auto J = detF(C, lambdas);
126 const auto Sdev = deviatoricStress(C, lambdas, N);
127 const auto Svol = transformVolumetricStresses(vol_.firstDerivative(J), C, J);
131 static_assert(voigt ==
false,
"Hyperelastic does not support returning stresses in Voigt notation");
141 template <
bool voigt,
typename Derived>
143 static_assert(Concepts::EigenMatrixOrVoigtNotation3<Derived>);
144 if constexpr (!voigt) {
145 const auto [lambdas, N] = principalStretches(C);
146 auto J = detF(C, lambdas);
148 const auto moduliDev = transformDeviatoricTangentModuli(dev_.tangentModuli(lambdas), N);
149 const auto moduliVol = transformVolumetricTangentModuli(vol_.firstDerivative(J), vol_.secondDerivative(J), C, J);
151 return moduliDev + moduliVol;
153 static_assert(voigt ==
false,
"Hyperelastic does not support returning tangent moduli in Voigt notation");
161 template <
typename STO>
163 auto reboundDEV = dev_.template rebind<STO>();
171 inline static constexpr auto dimensionRange() {
return Dune::range(
dim); }
173 template <
typename ST>
174 Eigen::Matrix<ST, dim, dim> transformDeviatoricStresses(
const Eigen::Vector<ST, dim>& principalStress,
175 const Eigen::Matrix<ST, dim, dim>& N)
const {
176 return (N * principalStress.asDiagonal() * N.transpose()).eval();
179 template <
typename ST>
180 Eigen::Matrix<ST, dim, dim> transformVolumetricStresses(ST Uprime,
const auto& C, ST J)
const {
181 return J * Uprime * C.inverse();
184 template <
typename ST>
185 auto transformDeviatoricTangentModuli(
const Eigen::TensorFixedSize<ST, Eigen::Sizes<dim, dim, dim, dim>>& L,
186 const Eigen::Matrix<ST, dim, dim>& N)
const {
187 Eigen::TensorFixedSize<ST, Eigen::Sizes<dim, dim, dim, dim>> moduli{};
189 auto indexList = std::array<Eigen::Index, 2>({
dim,
dim});
191 for (
const auto i : dimensionRange())
192 for (
const auto k : dimensionRange()) {
194 auto NiNi =
tensorView(
dyadic(N.col(i).eval(), N.col(i).eval()), indexList);
195 auto NkNk =
tensorView(
dyadic(N.col(k).eval(), N.col(k).eval()), indexList);
197 moduli += L(i, i, k, k) *
dyadic(NiNi, NkNk);
201 auto NiNk =
tensorView(
dyadic(N.col(i).eval(), N.col(k).eval()), indexList);
202 auto NkNi =
tensorView(
dyadic(N.col(k).eval(), N.col(i).eval()), indexList);
204 moduli += L(i, k, i, k) *
dyadic(NiNk, NiNk + NkNi);
211 template <
typename ST>
212 auto transformVolumetricTangentModuli(
const ST& Uprime,
const ST& Uprimeprime,
const auto& C, ST J)
const {
213 const auto invC = C.inverse().eval();
214 const auto CTinv =
tensorView(invC, std::array<Eigen::Index, 2>({3, 3}));
216 Eigen::TensorFixedSize<ST, Eigen::Sizes<3, 3, 3, 3>> moduli =
217 (J * ((Uprime + J * Uprimeprime) *
dyadic(CTinv, CTinv) -
224 template <
typename Derived>
225 auto principalStretches(
const Eigen::MatrixBase<Derived>& Craw,
int options = Eigen::ComputeEigenvectors)
const {
226 auto C = Impl::maybeFromVoigt(Craw);
227 return Impl::principalStretches<typename Derived::Scalar>(C, options);
240 template <
typename Derived,
typename ST>
241 ST detF(
const Eigen::MatrixBase<Derived>& C,
const Eigen::Vector<ST, 3>& lambda)
const {
243 const auto detC = sqrt(C.derived().eval().determinant());
246 const auto detC = Impl::determinantFromPrincipalValues(lambda);
247 Impl::checkPositiveOrAbort(detC);
258 template <
typename Derived,
typename ST>
259 requires(std::same_as<typename Derived::Scalar, ST>)
260 auto deviatoricEnergy(
const Eigen::MatrixBase<Derived>& C,
const Eigen::Vector<ST, 3>& lambdasST)
const {
261 if constexpr (not Concepts::AutodiffScalar<ST>) {
262 return dev_.storedEnergy(lambdasST);
263 }
else if constexpr (std::is_same_v<ST, autodiff::dual>) {
265 const auto Cvec =
toVoigt(C.derived());
266 const auto realCVec = autodiff::derivative<0>(Cvec);
267 const auto dualCVec = autodiff::derivative<1>(Cvec);
269 const auto [lambdas, N] = principalStretches(realCVec);
271 e.val = dev_.storedEnergy(lambdas);
272 e.grad = (transformDeviatoricStresses(dev_.stresses(lambdas), N).transpose() / 2 *
fromVoigt(dualCVec)).trace();
274 }
else if constexpr (std::is_same_v<ST, autodiff::dual2nd>) {
276 const auto Cvec =
toVoigt(C.derived());
277 const auto realCVec = derivative<0>(Cvec);
278 const auto dualC =
fromVoigt(Cvec.unaryExpr([](
auto& v) { return v.grad.val; }).eval());
279 const auto dualC2 =
fromVoigt(Cvec.unaryExpr([](
auto& v) { return v.val.grad; }).eval());
280 const auto [lambdas, N] = principalStretches(realCVec);
282 e.val = dev_.storedEnergy(lambdas);
283 e.grad.val = (transformDeviatoricStresses(dev_.stresses(lambdas), N).transpose() / 2 * dualC).trace();
284 e.val.grad = e.grad.val;
286 const auto Cmoduli = transformDeviatoricTangentModuli(dev_.tangentModuli(lambdas), N);
287 const Eigen::array<Eigen::IndexPair<Eigen::Index>, 2> double_contraction = {Eigen::IndexPair<Eigen::Index>(2, 0),
288 Eigen::IndexPair<Eigen::Index>(3, 1)};
289 const Eigen::array<Eigen::IndexPair<Eigen::Index>, 2> double_contraction2 = {
290 Eigen::IndexPair<Eigen::Index>(0, 0), Eigen::IndexPair<Eigen::Index>(1, 1)};
291 const auto tCdual =
tensorView(dualC, std::array<Eigen::Index, 2>({3, 3}));
292 const auto tCdualT =
tensorView(dualC2, std::array<Eigen::Index, 2>({3, 3}));
293 const auto prod = Cmoduli.contract(tCdual, double_contraction);
294 const Eigen::Tensor<double, 0> res = tCdualT.contract(prod, double_contraction2);
295 e.grad.grad = res(0) / 4.0;
299 static_assert(Dune::AlwaysFalse<Derived>::value,
"No fitting ScalarType.");
309 template <
typename Derived,
typename ST>
310 requires(std::same_as<typename Derived::Scalar, ST>)
311 auto deviatoricStress(
const Eigen::MatrixBase<Derived>& C,
const Eigen::Vector<ST, dim>& lambdasST,
312 Eigen::Matrix<ST, dim, dim> NST)
const {
313 if constexpr (not Concepts::AutodiffScalar<ST>) {
314 return transformDeviatoricStresses(dev_.stresses(lambdasST), NST);
315 }
else if constexpr (std::is_same_v<ST, autodiff::dual>) {
316 constexpr int nVoigtIndices = 6;
317 Eigen::Vector<autodiff::dual, nVoigtIndices> g;
318 const auto Cvec =
toVoigt(C.derived());
319 const auto realCVec = derivative<0>(Cvec);
321 const auto dualC =
fromVoigt(Cvec.unaryExpr([](
const auto& v) { return v.grad; }).eval());
322 const auto [lambdas, N] = principalStretches(realC);
324 const auto stresses =
toVoigt(transformDeviatoricStresses(dev_.stresses(lambdas), N));
325 const auto Cmoduli =
toVoigt(transformDeviatoricTangentModuli(dev_.tangentModuli(lambdas), N));
326 Eigen::Vector<double, nVoigtIndices> stressDirectionalDerivatrive = Cmoduli *
toVoigt(dualC);
327 stressDirectionalDerivatrive.topRows<3>() /= 2.0;
329 for (
int i = 0; i < nVoigtIndices; ++i) {
331 g[i].grad = stressDirectionalDerivatrive[i];
336 static_assert(Dune::AlwaysFalse<Derived>::value,
"No fitting ScalarType.");
Helper for the Eigen::Tensor types.
Implementation of the volumetric part of a hyperelastic material.
helper functions used by material model implementations.
constexpr Eigen::Index toVoigt(Eigen::Index i, Eigen::Index j) noexcept
Converts 2D indices to Voigt notation index.
Definition: tensorutils.hh:179
Eigen::Tensor< typename Derived::Scalar, rank > tensorView(const Eigen::EigenBase< Derived > &matrix, const std::array< T, rank > &dims)
View an Eigen matrix as an Eigen Tensor with specified dimensions.
Definition: tensorutils.hh:32
auto fourthOrderIKJL(const Eigen::MatrixBase< AType > &A, const Eigen::MatrixBase< BType > &B)
Computes the IKJL product of two matrices.
Definition: tensorutils.hh:135
auto dyadic(const auto &A_ij, const auto &B_kl)
Computes the dyadic product of two Eigen tensors.
Definition: tensorutils.hh:47
auto fromVoigt(const Eigen::Matrix< ST, size, 1, Options, maxSize, 1 > &EVoigt, bool isStrain=true)
Converts a vector given in Voigt notation to a matrix.
Definition: tensorutils.hh:284
auto symTwoSlots(const Eigen::TensorFixedSize< ScalarType, Eigen::Sizes< dim, dim, dim, dim > > &t, const std::array< size_t, 2 > &slots)
Creates a symmetric fourth-order tensor in the two specified slots of the input tensor.
Definition: tensorutils.hh:158
Definition: arrudaboyce.hh:27
Implementation of a general Hyperelastic Material material model.
Definition: finiteelements/mechanics/materials/hyperelastic/interface.hh:35
Hyperelastic(const DEV &dev)
Definition: finiteelements/mechanics/materials/hyperelastic/interface.hh:71
static constexpr bool stressAcceptsVoigt
Definition: finiteelements/mechanics/materials/hyperelastic/interface.hh:59
static constexpr bool energyAcceptsVoigt
Definition: finiteelements/mechanics/materials/hyperelastic/interface.hh:57
static constexpr auto tangentModuliTag
Definition: finiteelements/mechanics/materials/hyperelastic/interface.hh:56
typename DEV::ScalarType ScalarType
Definition: finiteelements/mechanics/materials/hyperelastic/interface.hh:39
const DEV & deviatoricFunction() const
Returns the deviatoric function.
Definition: finiteelements/mechanics/materials/hyperelastic/interface.hh:81
static constexpr bool moduliAcceptsVoigt
Definition: finiteelements/mechanics/materials/hyperelastic/interface.hh:61
std::conditional_t< hasVolumetricPart, std::pair< MaterialParametersDEV, MaterialParametersVOL >, MaterialParametersDEV > MaterialParameters
Definition: finiteelements/mechanics/materials/hyperelastic/interface.hh:52
StressMatrix stressesImpl(const Eigen::MatrixBase< Derived > &C) const
Computes the stresses in the Hyperelastic material model.
Definition: finiteelements/mechanics/materials/hyperelastic/interface.hh:120
static constexpr int dim
Definition: finiteelements/mechanics/materials/hyperelastic/interface.hh:43
auto rebind() const
Rebinds the material to a different scalar type.
Definition: finiteelements/mechanics/materials/hyperelastic/interface.hh:162
typename VOL::MaterialParameter MaterialParametersVOL
Definition: finiteelements/mechanics/materials/hyperelastic/interface.hh:49
MaterialTensor tangentModuliImpl(const Eigen::MatrixBase< Derived > &C) const
Computes the tangent moduli in the Hyperelastic material model.
Definition: finiteelements/mechanics/materials/hyperelastic/interface.hh:142
StrainMatrix StressMatrix
Definition: finiteelements/mechanics/materials/hyperelastic/interface.hh:45
static constexpr bool stressToVoigt
Definition: finiteelements/mechanics/materials/hyperelastic/interface.hh:58
ScalarType storedEnergyImpl(const Eigen::MatrixBase< Derived > &C) const
Computes the total stored energy in the Hyperelastic material model.
Definition: finiteelements/mechanics/materials/hyperelastic/interface.hh:103
static constexpr auto stressTag
Definition: finiteelements/mechanics/materials/hyperelastic/interface.hh:55
static constexpr double derivativeFactorImpl
Definition: finiteelements/mechanics/materials/hyperelastic/interface.hh:62
Eigen::Matrix< ScalarType, dim, dim > StrainMatrix
Definition: finiteelements/mechanics/materials/hyperelastic/interface.hh:44
const MaterialParameters materialParametersImpl() const
Returns the material parameters stored in the deviatoric part of the material.
Definition: finiteelements/mechanics/materials/hyperelastic/interface.hh:89
typename DEV::MaterialParameters MaterialParametersDEV
Definition: finiteelements/mechanics/materials/hyperelastic/interface.hh:48
static constexpr bool isAutoDiff
Definition: finiteelements/mechanics/materials/hyperelastic/interface.hh:41
static constexpr bool hasVolumetricPart
Definition: finiteelements/mechanics/materials/hyperelastic/interface.hh:40
const VOL & volumetricFunction() const
Returns the volumetric function.
Definition: finiteelements/mechanics/materials/hyperelastic/interface.hh:84
Hyperelastic(const DEV &dev, const VOL &vol)
Definition: finiteelements/mechanics/materials/hyperelastic/interface.hh:76
static constexpr auto strainTag
Definition: finiteelements/mechanics/materials/hyperelastic/interface.hh:54
static constexpr bool moduliToVoigt
Definition: finiteelements/mechanics/materials/hyperelastic/interface.hh:60
static constexpr std::string nameImpl() noexcept
Definition: finiteelements/mechanics/materials/hyperelastic/interface.hh:64
Eigen::TensorFixedSize< ScalarType, Eigen::Sizes< dim, dim, dim, dim > > MaterialTensor
Definition: finiteelements/mechanics/materials/hyperelastic/interface.hh:46
Interface classf or materials.
Definition: finiteelements/mechanics/materials/interface.hh:80
auto stresses(const Eigen::MatrixBase< Derived > &Eraw) const
Get the stresses of the material.
Definition: finiteelements/mechanics/materials/interface.hh:160
Concept to check if the underlying scalar type is a dual type.
Definition: utils/concepts.hh:606
Contains the Material interface class and related template functions for material properties.
Implementation of the interface for the deviatoric part of a hyperelastic material.
Header file including concepts for hyperelastic material models.