KASKADE 7 development version
elastoVariationalFunctionals.hh
Go to the documentation of this file.
1/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2/* */
3/* This file is part of the library KASKADE 7 */
4/* https://www.zib.de/research/projects/kaskade7-finite-element-toolbox */
5/* */
6/* Copyright (C) 2015-2019 Zuse Institute Berlin */
7/* */
8/* KASKADE 7 is distributed under the terms of the ZIB Academic License. */
9/* see $KASKADE/academic.txt */
10/* */
11/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
12
13#ifndef FEM_DIFFOPS_ELASTOVARIATIONALFUNCTIONALS_HH
14#define FEM_DIFFOPS_ELASTOVARIATIONALFUNCTIONALS_HH
15
17
18namespace Kaskade
19{
20 namespace Elastomechanics
21 {
22
42 template <class HyperelasticEnergy, class StrainTensor>
44 {
45 public:
46 using Scalar = typename HyperelasticEnergy::Scalar;
47 static int const dim = HyperelasticEnergy::dim;
49
56 template <typename... Args>
58 : energy(std::forward<Args>(args)...)
59 {
60 }
61
67 HyperelasticVariationalFunctional(HyperelasticEnergy const& energy_, StrainTensor const& strain_)
68 : du(0), energy(energy_), strain(strain_)
69 {
70 }
71
82 {
83 du = du0;
84 strain = StrainTensor(du);
85 energy.setLinearizationPoint(strain.d0());
86 }
87
91 Scalar d0() const
92 {
93 return energy.d0();
94 }
95
100 {
101 // TODO: I have doubts that this is the most efficient implementation...
103
104 // step trough all spatial dimensions and test with vectorial test function
105 // with values only in that direction.
106 for (int i=0; i<dim; ++i) {
108 dv[i] = arg.derivative[0];
109
111 ret[i] = energy.d1(dE);
112 }
113
114 return ret;
115 }
116
128 {
129 // TODO: I have doubts that this is the most efficient implementation...
131
132 // In a double loop, step trough all spatial dimensions and test with vectorial test functions
133 // with values only in that direction.
134 // TODO: due to symmetry, can we skip half the computation?
135 for (int i=0; i<dim; ++i)
136 {
138 dv1[i] = arg1.derivative[0];
140
141 for (int j=0; j<dim; ++j)
142 {
144 dv2[j] = arg2.derivative[0];
147
148 // according to product rule...
149 ret[i][j] = energy.d2(dE1,dE2) + energy.d1(ddE);
150 }
151 }
152 return ret;
153 }
154
161 HyperelasticEnergy& getHyperelasticEnergy()
162 {
163 return energy;
164 }
165
169 HyperelasticEnergy const& getHyperelasticEnergy() const
170 {
171 return energy;
172 }
173
177 Tensor const& getDu() const
178 {
179 return du;
180 }
181
185 StrainTensor const& getStrain() const
186 {
187 return strain;
188 }
189
197 Tensor stress() const { return energy.stress(); }
198
208 {
209 Tensor F = du;
210 for (int i=0; i<dim; ++i)
211 F[i][i] += 1; // F = I + ux
212
213 return F*stress()*transpose(F) / F.determinant();
214 }
215
216 protected:
218 HyperelasticEnergy energy;
219 StrainTensor strain;
220 };
221
222 // ---------------------------------------------------------------------------------------------------------
223
233 template <int dim_, class Scalar_=double>
235 : public HyperelasticVariationalFunctional<MaterialLaws::StVenantKirchhoff<dim_,Scalar_>,LinearizedGreenLagrangeTensor<Scalar_,dim_>>
236 {
239
240
241 public:
242 using Scalar = Scalar_;
243
244 private:
245 Scalar lambda, mu;
246
247 public:
248 static int const dim = dim_;
249
255 : LameNavier(ElasticModulus(1,1)) {}
256
258 : Base(moduli), lambda(moduli.lame()), mu(moduli.shear())
259 {
260 }
261
268 {
270 ret *= lambda * trace(this->strain.d0());
271 ret += 2*mu * (this->strain.d0()*arg.derivative[0]);
272
273 return ret;
274 }
275
281 {
283
284 for (int i=0; i<dim; ++i) {
285 double trace_ev = arg1.derivative[0][i];
286
287 for (int j=0; j<dim; ++j) {
288 double trace_ew = arg2.derivative[0][j];
289 double ct = arg1.derivative[0][j] * arg2.derivative[0][i];
290 if (j == i) {
291 for (int k = 0; k < dim; ++k) {
292 ct += arg1.derivative[0][k] * arg2.derivative[0][k];
293 }
294 }
295 ret[i][j] += lambda*trace_ev*trace_ew + mu*ct;
296 }
297 }
298 return ret;
299 }
300
306 void setElasticModuli(ElasticModulus const& modulus)
307 {
308 lambda = modulus.lame();
309 mu = modulus.shear();
310 this->energy = Energy(modulus);
311 }
312
317 {
318 return ElasticModulus(lambda,mu);
319 }
320
329 {
330 // The implementation follows Braess, Finite Elemente, Chapter VI.3
331 Dune::FieldMatrix<Scalar,dim*(dim+1)/2,dim*(dim+1)/2> C(0.0);
332
333 if (dim==3)
334 {
335 C[0][0] = lambda+2*mu; C[0][1] = lambda; C[0][2] = lambda;
336 C[1][0] = lambda; C[1][1] = lambda+2*mu; C[1][2] = lambda;
337 C[2][0] = lambda; C[2][1] = lambda; C[2][2] = lambda+2*mu;
338 for (int i=3; i<6; ++i)
339 C[i][i] = 2*mu;
340 }
341 else if (dim==2)
342 {
343 C[0][0] = lambda+2*mu; C[0][1] = lambda;
344 C[1][0] = lambda; C[1][1] = lambda+2*mu;
345 C[2][2] = 2*mu;
346 }
347 return C;
348 }
349
356 {
358
359 if (dim==3)
360 {
361 result[0] = A[0]*x[0] + A[3]*x[1] + A[4]*x[2];
362 result[1] = A[3]*x[0] + A[1]*x[1] + A[5]*x[2];
363 result[2] = A[4]*x[0] + A[5]*x[1] + A[2]*x[2];
364 }
365 else if (dim==2)
366 {
367 result[0] = A[0]*x[0] + A[2]*x[1];
368 result[1] = A[2]*x[0] + A[1]*x[1];
369 }
370 else if (dim==1)
371 {
372 abort();
373 }
374
375 return result;
376 }
377
388 {
389 Dune::FieldMatrix<Scalar,dim*(dim+1)/2,dim*dim> E(0.0);
390
391 if (dim==3)
392 {
393 E[0][0] = 2; // diagonal elements of epsilon
394 E[1][4] = 2;
395 E[2][8] = 2;
396 E[3][1] = 1; E[3][3] = 1; // off-diagonal elements of epsilon
397 E[4][2] = 1; E[4][6] = 1;
398 E[5][5] = 1; E[5][7] = 1;
399 }
400 else if (dim==2)
401 {
402 E[0][0] = 2;
403 E[1][3] = 2;
404 E[2][1] = 1; E[2][2] = 1;
405 } else if (dim==1)
406 E[0][0] = 2;
407
408 E *= 0.5;
409 return E;
410 }
411 };
412
413 // ---------------------------------------------------------------------------------------------------------
414
428 template <class Scalar, int dim>
430 public:
447
462 Dune::FieldMatrix<Scalar,dim,dim> const& mat1, Dune::FieldVector<Scalar,dim*(dim-1)/2> const& mat2);
463
470
478
487 Dune::FieldMatrix<Scalar,dim*(dim+1)/2,dim*(dim+1)/2> const& stiffnessMatrix() const { return stiffness; }
488
493 {
494 du0 = du0_;
495 }
496
500 Scalar d0() const;
501
508
519
520 void setLinear(bool lin){
521 linear = lin;
522 }
523
524
525 private:
526 Dune::FieldMatrix<Scalar,dim,dim> orth; // the orthonormal matrix mapping material to global coordinates
527 Dune::FieldMatrix<Scalar,dim*(dim+1)/2,dim*(dim+1)/2> stiffness;
528 Dune::FieldMatrix<Scalar,dim,dim> du0; // the linearization point of the displacement derivative
529 bool linear;
530 };
531
532 // ---------------------------------------------------------------------------------------------------------
533
541 template <class HyperelasticEnergy, class StrainTensor>
543 {
544 public:
546 using Scalar = typename HyperelasticEnergy::Scalar;
548 static constexpr int dim = HyperelasticEnergy::dim;
549
555
560 {
561 return deformationDerivative();
562 }
563
568 {
569 Tensor F = energy.getDu();
570 for (int i=0; i<dim; ++i)
571 F[i][i] += 1; // F = I + du
572 return F;
573 }
574
578 Tensor d0() const
579 {
580 // T(du) = F(du) * Sigma(du) Sigma is second Pioala Kirchhoff stress
582 }
583
589 // T'[dv] = F'[dv] * Sigma(du) + F * Sigma'[dv]
590 // F'[dv] = dv
591 // Sigma'[dv] = W''(E(du))[E'(du)[dv]] W is hyperelastic energy (depending on strain E)
593 }
594
603 // T''[dv,dw] = dv*W''(E)[E'[dw]] + dw*W''(E)[E'[dv]] + F*Sigma''[dv,dw]
604 // Sigma''[dv,dw] = W'''(E)[E'[dv],E'[dw]] + W''(E)[E''[dv,dw]]
605 Tensor result{};
606 result += argv.derivative*spkStressD1(argw);
607 result += argw.derivative*spkStressD1(argv);
608 //result += deformationGradient()*energyD3DeDf(energy.getStrain().d1(argv.derivative), energy.getStrain().d1(argw.derivative));
610 return result;
611 }
612
613 protected:
614 // directional derivative of second Piola Kirchhoff stress in direction of displacement gradient
616 // Sigma'[dv] = W''(E(du))[E'(du)[dv]]
617 return energyD2De(energy.getStrain().d1(arg.derivative));
618 }
619
620 // directional derivative of first derivative of stored energy in direction of strain e
621 Tensor energyD2De(Tensor const& e) const {
622 // W''(E(du))[E'(du)[dv]]
623 Tensor sigma;
624
625 for (int i=0; i<dim; ++i)
626 for (int j=0; j<=i; ++j)
627 {
628 Tensor e2(0);
629 e2[i][j] = 1;
630 sigma[i][j] = energy.getHyperelasticEnergy().d2(e, e2);
631 }
632
633 for (int i=0; i<dim-1; ++i)
634 for (int j=i+1; j<dim; ++j)
635 sigma[i][j] = sigma[j][i];
636
637 return sigma;
638 }
639
640// Tensor energyD3DeDf(Tensor const& e, Tensor const& f) {
641// // Todo: implement, only needed if hyperelastic energy has non vanishing third derivatives (with respect to strain)
642// return Tensor{};
643// }
644
645 public:
647 };
648
649 // ---------------------------------------------------------------------------------------------------------
650
651 }
652}
653
654#endif
Material parameters for isotropic linearly elastic materials.
Definition: elasto.hh:53
double shear() const
Returns the shear modulus , also known as Lame's second parameter .
Definition: elasto.hh:76
double lame() const
Returns the first Lame parameter .
Definition: elasto.hh:85
Represents the first Piola Kirchhoff stress as known in nonlinear elasticity. The Piola-Kirchhoff str...
Tensor deformationGradient() const
DEPRECATED, use deformationDerivative instead.
Tensor d0() const
d0 provides access to the current first Piola Kirchhoff stress.
FirstPiolaKirchhoffStress(EnergyFunctional const &ef)
FirstPiolaKirchhoffStress constructs first Piola Kirchhoff stress object from current state of elasti...
Tensor d2(VariationalArg< Scalar, dim, dim > const &argv, VariationalArg< Scalar, dim, dim > const &argw) const
d2 provides access to the second directional derivative (in directions of some displacement derivativ...
Tensor deformationDerivative() const
deformationGradient provides access to the current deformation derivative .
Tensor d1(VariationalArg< Scalar, dim, dim > const &arg) const
d1 provides access to the first directional derivative (in direction of some displacement derivative)...
Tensor spkStressD1(VariationalArg< Scalar, dim, dim > const &arg) const
General base class for variational functionals defined in terms of hyperelastic stored energies.
HyperelasticEnergy const & getHyperelasticEnergy() const
getHyperelasticEnergy provides read access to the stored energy density.
Dune::FieldVector< Scalar, dim > d1(VariationalArg< Scalar, dim > const &arg) const
Computes the directional derivative of the hyperelastic stored energy density.
HyperelasticEnergy & getHyperelasticEnergy()
Provides access to the stored energy density.
Tensor cauchyStress() const
Returns the Cauchy stress tensor corresponding to the current displacement derivative.
Tensor d2(VariationalArg< Scalar, dim > const &arg1, VariationalArg< Scalar, dim > const &arg2) const
Computes the second directional derivative of the hyperelastic stored energy density.
Tensor const & getDu() const
getDu provides read access to the current displacement derivative.
Scalar d0() const
Computes the hyperelastic stored energy density.
HyperelasticVariationalFunctional(HyperelasticEnergy const &energy_, StrainTensor const &strain_)
Constructor.
Tensor stress() const
Returns the 2nd Piola-Kirchhoff stress tensor corresponding to the current displacement derivative.
StrainTensor const & getStrain() const
getStrain provides read access to the current strain tensor.
void setLinearizationPoint(Tensor const &du0)
Defines the displacement derivative around which to linearize.
Convenience class for handling linear elastomechanics.
Base::Tensor d2(VariationalArg< Scalar, dim > const &arg1, VariationalArg< Scalar, dim > const &arg2) const
d2 As the base method, computes the second directional derivative of the hyperelastic stored energy d...
Dune::FieldVector< Scalar, dim > d1(VariationalArg< Scalar, dim > const &arg) const
d1 As the base method, computes the directional derivative of the hyperelastic stored energy density.
Dune::FieldMatrix< Scalar, dim *(dim+1)/2, dim *(dim+1)/2 > strainToStressMatrix() const
Returns the matrix mapping the strain tensor to the stress tensor: .
Dune::FieldMatrix< Scalar, dim *(dim+1)/2, dim *dim > displacementDerivativeToStrainMatrix() const
returns the matrix mapping the displacement derivative to the strain tensor:
ElasticModulus getElasticModuli()
Retrieve current material properties.
void setElasticModuli(ElasticModulus const &modulus)
Define material properties.
static Dune::FieldVector< Scalar, dim > mv(Dune::FieldVector< Scalar, dim *(dim+1)/2 > const &A, Dune::FieldVector< Scalar, dim > const &x)
Computes the symmetric matrix times vector product, when the matrix is compactly stored in a dim*(dim...
LameNavier()
Constructor. Both Lame constants are initialized to 1, the linearization point to .
Tensor d0() const
The linearized Green-Lagrange strain tensor .
Definition: elasto.hh:308
The St. Venant-Kirchhoff material, foundation of linear elastomechanics.
Convenience class for handling orthotropic materials in linear elastomechanics.
void setLinearizationPoint(Dune::FieldMatrix< Scalar, dim, dim > const &du0_)
Defines the displacement derivative around which to linearize.
OrthotropicLameNavier(Dune::FieldMatrix< Scalar, dim, dim > const &orth_, Dune::FieldMatrix< Scalar, dim, dim > const &mat_)
Constructor.
OrthotropicLameNavier(Dune::FieldMatrix< Scalar, dim, dim > const &orth_, Dune::FieldMatrix< Scalar, dim, dim > const &mat1, Dune::FieldVector< Scalar, dim *(dim-1)/2 > const &mat2)
Constructor.
Dune::FieldVector< Scalar, dim > d1(VariationalArg< Scalar, dim > const &arg) const
Computes the elastic energy .
Scalar d0() const
Computes the elastic energy .
OrthotropicLameNavier(ElasticModulus const &p)
Default constructor.
Dune::FieldMatrix< Scalar, dim, dim > d2(VariationalArg< Scalar, dim > const &arg1, VariationalArg< Scalar, dim > const &arg2) const
Computes the local Hessian of the variational functional. For scalar functions , the values and deriv...
Dune::FieldMatrix< Scalar, dim *(dim+1)/2, dim *(dim+1)/2 > const & stiffnessMatrix() const
Returns the stiffness tensor.
T trace(Dune::FieldMatrix< T, n, n > const &A)
Matrix trace .
Definition: fixdune.hh:515
T transpose(T x)
A class that stores values, gradients, and Hessians of evaluated shape functions.
Dune::FieldMatrix< Scalar, components, dim > derivative
The shape function's spatial derivative, a components x dim matrix.