constitutive_laws.h
Go to the documentation of this file.
1// LIC// ====================================================================
2// LIC// This file forms part of oomph-lib, the object-oriented,
3// LIC// multi-physics finite-element library, available
4// LIC// at http://www.oomph-lib.org.
5// LIC//
6// LIC// Copyright (C) 2006-2026 Matthias Heil and Andrew Hazel
7// LIC//
8// LIC// This library is free software; you can redistribute it and/or
9// LIC// modify it under the terms of the GNU Lesser General Public
10// LIC// License as published by the Free Software Foundation; either
11// LIC// version 2.1 of the License, or (at your option) any later version.
12// LIC//
13// LIC// This library is distributed in the hope that it will be useful,
14// LIC// but WITHOUT ANY WARRANTY; without even the implied warranty of
15// LIC// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16// LIC// Lesser General Public License for more details.
17// LIC//
18// LIC// You should have received a copy of the GNU Lesser General Public
19// LIC// License along with this library; if not, write to the Free Software
20// LIC// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21// LIC// 02110-1301 USA.
22// LIC//
23// LIC// The authors may be contacted at oomph-lib@maths.man.ac.uk.
24// LIC//
25// LIC//====================================================================
26// Header file for ConstitutiveLaw objects that will be used in all
27// elasticity-type elements
28
29#ifndef OOMPH_CONSTITUTIVE_LAWS_HEADER
30#define OOMPH_CONSTITUTIVE_LAWS_HEADER
31
32// Config header
33#ifdef HAVE_CONFIG_H
34#include <oomph-lib-config.h>
35#endif
36
37// OOMPH-LIB includes
39#include "generic/matrices.h"
40
41namespace oomph
42{
43 //=====================================================================
44 /// Base class for strain energy functions to be used in solid
45 /// mechanics computations.
46 //====================================================================
48 {
49 public:
50 /// Constructor takes no arguments
52
53 /// Empty virtual destructor
55
56
57 /// Return the strain energy in terms of the strain tensor
58 virtual double W(const DenseMatrix<double>& gamma)
59 {
60 std::string error_message =
61 "The strain-energy function as a function of the strain-tensor,\n";
62 error_message +=
63 "gamma, is not implemented for this strain energy function.\n";
64
65 throw OomphLibError(
67 return 0.0;
68 }
69
70
71 /// Return the strain energy in terms of the strain invariants
72 virtual double W(const Vector<double>& I)
73 {
74 std::string error_message =
75 "The strain-energy function as a function of the strain\n ";
76 error_message +=
77 "invariants, I1, I2, I3, is not implemented for this strain\n ";
78 error_message += "energy function\n";
79
80 throw OomphLibError(
82 return 0.0;
83 }
84
85
86 /// Return the derivatives of the strain energy function with
87 /// respect to the components of the strain tensor (default is to use
88 /// finite differences).
89 virtual void derivative(const DenseMatrix<double>& gamma,
91 {
92 throw OomphLibError(
93 "Sorry, the FD setup of dW/dgamma hasn't been implemented yet",
96 }
97
98
99 /// Return the derivatives of the strain energy function with
100 /// respect to the strain invariants. Default version is to use finite
101 /// differences
103 {
104 // Calculate the derivatives of the strain-energy-function wrt the strain
105 // invariants
106 double FD_Jstep = 1.0e-8; // Usual comments about global stuff
107 double energy = W(I);
108
109 // Loop over the strain invariants
110 for (unsigned i = 0; i < 3; i++)
111 {
112 // Store old value
113 double I_prev = I[i];
114 // Increase ith strain invariant
115 I[i] += FD_Jstep;
116 // Get the new value of the strain energy
117 double energy_new = W(I);
118 // Calculate the value of the derivative
120 // Reset value of ith strain invariant
121 I[i] = I_prev;
122 }
123 }
124
125 /// Pure virtual function in which the user must declare if the
126 /// constitutive equation requires an incompressible formulation
127 /// in which the volume constraint is enforced explicitly.
128 /// Used as a sanity check in PARANOID mode.
130 };
131
132
133 ////////////////////////////////////////////////////////////////////
134 ////////////////////////////////////////////////////////////////////
135 ////////////////////////////////////////////////////////////////////
136
137
138 //=====================================================================
139 /// MooneyRivlin strain-energy function.
140 /// with constitutive parameters C1 and C2:
141 /// \f[ W = C_1 (I_0 - 3) + C_2 (I_1 - 3) \f]
142 /// where incompressibility (\f$ I_2 \equiv 1\f$) is assumed.
143 //====================================================================
145 {
146 public:
147 /// Constructor takes the pointer to the value of the constants
148 MooneyRivlin(double* c1_pt, double* c2_pt)
150 {
151 }
152
153 /// Empty Virtual destructor
154 virtual ~MooneyRivlin() {}
155
156 /// Return the strain energy in terms of strain tensor
157 double W(const DenseMatrix<double>& gamma)
158 {
159 return StrainEnergyFunction::W(gamma);
160 }
161
162 /// Return the strain energy in terms of the strain invariants
163 double W(const Vector<double>& I)
164 {
165 return (*C1_pt) * (I[0] - 3.0) + (*C2_pt) * (I[1] - 3.0);
166 }
167
168
169 /// Return the derivatives of the strain energy function with
170 /// respect to the strain invariants
172 {
173 dWdI[0] = (*C1_pt);
174 dWdI[1] = (*C2_pt);
175 dWdI[2] = 0.0;
176 }
177
178 /// Pure virtual function in which the user must declare if the
179 /// constitutive equation requires an incompressible formulation
180 /// in which the volume constraint is enforced explicitly.
181 /// Used as a sanity check in PARANOID mode. True
183 {
184 return true;
185 }
186
187
188 private:
189 /// Pointer to first Mooney Rivlin constant
190 double* C1_pt;
191
192 /// Pointer to second Mooney Rivlin constant
193 double* C2_pt;
194 };
195
196
197 ////////////////////////////////////////////////////////////////////
198 ////////////////////////////////////////////////////////////////////
199 ////////////////////////////////////////////////////////////////////
200
201
202 //=====================================================================
203 /// Generalisation of Mooney Rivlin constitutive law to compressible
204 /// media as suggested on p. 553 of Fung, Y.C. & Tong, P. "Classical and
205 /// Computational Solid Mechanics" World Scientific (2001).
206 /// Input parameters are Young's modulus E, Poisson ratio nu and
207 /// the Mooney-Rivlin constant C1. In the small-deformation-limit
208 /// the behaviour becomes equivalent to that of linear elasticity
209 /// with the same E and nu.
210 ///
211 /// Note that there's a factor of 2 difference between C1 and the Mooney
212 /// Rivlin C1!
213 //====================================================================
215 {
216 public:
217 /// Constructor takes the pointers to the constitutive parameters:
218 /// Poisson's ratio, the Mooney-Rivlin parameter. Young's modulus is set
219 /// to 1, implying that it has been used to scale the stresses
220 GeneralisedMooneyRivlin(double* nu_pt, double* c1_pt)
222 Nu_pt(nu_pt),
223 C1_pt(c1_pt),
224 E_pt(new double(1.0)),
226 {
227 }
228
229 /// Constructor takes the pointers to the constitutive parameters:
230 /// Poisson's ratio, the Mooney-Rivlin parameter and Young's modulus
231 GeneralisedMooneyRivlin(double* nu_pt, double* c1_pt, double* e_pt)
233 Nu_pt(nu_pt),
234 C1_pt(c1_pt),
235 E_pt(e_pt),
237 {
238 }
239
240
241 /// Virtual destructor
243 {
244 if (Must_delete_e) delete E_pt;
245 }
246
247 /// Return the strain energy in terms of strain tensor
248 double W(const DenseMatrix<double>& gamma)
249 {
250 return StrainEnergyFunction::W(gamma);
251 }
252
253
254 /// Return the strain energy in terms of the strain invariants
255 double W(const Vector<double>& I)
256 {
257 double G = (*E_pt) / (2.0 * (1.0 + (*Nu_pt)));
258 return 0.5 * ((*C1_pt) * (I[0] - 3.0) + (G - (*C1_pt)) * (I[1] - 3.0) +
259 ((*C1_pt) - 2.0 * G) * (I[2] - 1.0) +
260 (1.0 - (*Nu_pt)) * G * (I[2] - 1.0) * (I[2] - 1.0) /
261 (2.0 * (1.0 - 2.0 * (*Nu_pt))));
262 }
263
264
265 /// Return the derivatives of the strain energy function with
266 /// respect to the strain invariants
268 {
269 double G = (*E_pt) / (2.0 * (1.0 + (*Nu_pt)));
270 dWdI[0] = 0.5 * (*C1_pt);
271 dWdI[1] = 0.5 * (G - (*C1_pt));
272 dWdI[2] = 0.5 * ((*C1_pt) - 2.0 * G +
273 2.0 * (1.0 - (*Nu_pt)) * G * (I[2] - 1.0) /
274 (2.0 * (1.0 - 2.0 * (*Nu_pt))));
275 }
276
277
278 /// Pure virtual function in which the user must declare if the
279 /// constitutive equation requires an incompressible formulation
280 /// in which the volume constraint is enforced explicitly.
281 /// Used as a sanity check in PARANOID mode. False.
283 {
284 return false;
285 }
286
287 private:
288 /// Poisson's ratio
289 double* Nu_pt;
290
291 /// Mooney-Rivlin parameter
292 double* C1_pt;
293
294 /// Young's modulus
295 double* E_pt;
296
297 /// Boolean flag to indicate if storage for elastic modulus
298 /// must be deleted in destructor
300 };
301
302
303 ////////////////////////////////////////////////////////////////////
304 ////////////////////////////////////////////////////////////////////
305 ////////////////////////////////////////////////////////////////////
306
307 //===================================================================
308 /// Neo Hookean constitutive law in terms of Young's modulus and
309 /// Poisson ratio
310 //===================================================================
312 {
313 public:
314 /// The constructor takes the pointers to values of material parameters:
315 /// Poisson's ratio and Young's modulus.
316 NeoHookean(double* nu_pt, double* e_pt)
318 {
319 }
320
321 /// The constructor takes the pointer to value of
322 /// Poisson's ratio. Young's modulus is set to E=1.0,
323 /// implying that all stresses have been non-dimensionalised
324 /// on on it.
325 NeoHookean(double* nu_pt)
327 Nu_pt(nu_pt),
328 E_pt(new double(1.0)),
330 {
331 }
332
333 /// Virtual destructor
334 virtual ~NeoHookean()
335 {
336 if (Must_delete_e) delete E_pt;
337 }
338
339 /// Return the strain energy in terms of strain tensor
340 double W(const DenseMatrix<double>& gamma)
341 {
342 return StrainEnergyFunction::W(gamma);
343 }
344
345 /// Return the strain energy in terms of the strain invariants
346 double W(const Vector<double>& I)
347 {
348 double nu = *Nu_pt;
349 double e = *E_pt;
350 return 0.5 * e *
351 (0.5 * (I[0] - 3.0) - 0.5 * log(I[2]) +
352 (nu / (1.0 - 2.0 * nu)) * 0.25 * log(I[2]) * log(I[2])) /
353 (1.0 + nu);
354 }
355
356 /// Return the derivatives of the strain energy function with
357 /// respect to the strain invariants
359 {
360 double nu = *Nu_pt;
361 double e = *E_pt;
362 dWdI[0] = 0.25 * e / (1.0 + nu);
363 dWdI[1] = 0.0;
364 dWdI[2] = 0.5 * e * (-0.5 + (nu / (1.0 - 2.0 * nu)) * 0.5 * log(I[2])) /
365 ((1.0 + nu) * I[2]);
366 }
367
368 /// Pure virtual function in which the user must declare if the
369 /// constitutive equation requires an incompressible formulation
370 /// in which the volume constraint is enforced explicitly.
371 /// Used as a sanity check in PARANOID mode. False.
373 {
374 return false;
375 }
376
377 private:
378 /// Young's modulus
379 double* E_pt;
380
381 /// Poisson's ratio
382 double* Nu_pt;
383
384 /// Boolean indicating if Young's modulus must be deleted in destructor
386 };
387
388 ////////////////////////////////////////////////////////////////////
389 ////////////////////////////////////////////////////////////////////
390 ////////////////////////////////////////////////////////////////////
391
392 //=====================================================================
393 /// Neo Hookean constitutive law (incompressible version)
394 /// No argument for Poisson ratio here - it must be equal to 0.5
395 //====================================================================
397 {
398 public:
399 /// The constructor takes Young's modulus as an argument
404
405 /// Argument-free constructor
410
411 /// Virtual destructor
413 {
414 if (Must_delete_e) delete E_pt;
415 }
416
417 /// Return the strain energy in terms of strain tensor
418 double W(const DenseMatrix<double>& gamma)
419 {
420 return StrainEnergyFunction::W(gamma);
421 }
422
423 /// Return the strain energy in terms of the strain invariants
424 double W(const Vector<double>& I)
425 {
426 double e = *E_pt;
427 double nu = 0.5;
428 return 0.25 * e * (I[0] - 3.0) / (1.0 + nu);
429 }
430
431 /// Return the derivatives of the strain energy function with
432 /// respect to the strain invariants
434 {
435 double e = *E_pt;
436 double nu = 0.5;
437 dWdI[0] = 0.25 * e / (1.0 + nu);
438 dWdI[1] = 0.0;
439 dWdI[2] = 0.0;
440 }
441
442 /// Pure virtual function in which the user must declare if the
443 /// constitutive equation requires an incompressible formulation
444 /// in which the volume constraint is enforced explicitly.
445 /// Used as a sanity check in PARANOID mode. True.
447 {
448 return true;
449 }
450
451 private:
452 /// Young's modulus
453 double* E_pt;
454
455 /// Boolean indicating if Young's modulus must be deleted in destructor
457 };
458
459 ////////////////////////////////////////////////////////////////////
460 ////////////////////////////////////////////////////////////////////
461 ////////////////////////////////////////////////////////////////////
462
463 //===========================================================================
464 /// A class for constitutive laws for elements that solve
465 /// the equations of solid mechanics based upon the principle of virtual
466 /// displacements. In that formulation, the information required from a
467 /// constitutive law is the (2nd Piola-Kirchhoff) stress tensor
468 /// \f$ \sigma^{ij} \f$ as a function of the (Green) strain
469 /// \f$ \gamma^{ij} \f$:
470 /// \f[ \sigma^{ij} = \sigma^{ij}(\gamma_{ij}). \f]
471 /// The Green strain is defined as
472 /// \f[ \gamma_{ij} = \frac{1}{2} (G_{ij} - g_{ij}), \ \ \ \ \ \ \ \ \ \ \ (1) \f]
473 /// where \f$G_{ij} \f$ and \f$ g_{ij}\f$ are the metric tensors
474 /// in the deformed and undeformed (stress-free) configurations, respectively.
475 /// A specific ConstitutiveLaw needs to be implement the pure
476 /// virtual function
477 /// \code
478 /// ConstitutiveLaw::calculate_second_piola_kirchhoff_stress(...)
479 /// \endcode
480 /// Equation (1) shows that the strain may be calculated from the
481 /// undeformed and deformed metric tensors. Frequently, these tensors are
482 /// also required in the constitutive law itself.
483 /// To avoid unnecessary re-computation of these quantities, we
484 /// pass the deformed and undeformed metric tensor to
485 /// \c calculate_second_piola_kirchhoff_stress(...)
486 /// rather than the strain tensor itself.
487 ///
488 /// The functional form of the constitutive equation is different
489 /// for compressible/incompressible/near-incompressible behaviour
490 /// and we provide interfaces that are appropriate for all of these cases.
491 /// -# \b Compressible \b Behaviour: \n If the material is compressible,
492 /// the stress can be computed from the deformed and undeformed
493 /// metric tensors,
494 ///
495 /// \f[ \sigma^{ij} = \sigma^{ij}(\gamma_{ij}) = \sigma^{ij}\bigg( \frac{1}{2} (G_{ij} - g_{ij})\bigg), \f]
496 /// using the interface
497 /// \code
498 /// // 2nd Piola Kirchhoff stress tensor
499 /// DenseMatrix<double> sigma(DIM,DIM);
500 ///
501 /// // Metric tensor in the undeformed (stress-free) configuration
502 /// DenseMatrix<double> g(DIM,DIM);
503 ///
504 /// // Metric tensor in the deformed configuration
505 /// DenseMatrix<double> G(DIM,DIM);
506 ///
507 /// // Compute stress from the two metric tensors:
508 /// calculate_second_piola_kirchhoff_stress(g,G,sigma);
509 /// \endcode
510 /// \n \n \n
511 /// -# \b Incompressible \b Behaviour: \n If the material is incompressible,
512 /// its deformation is constrained by the condition that
513 ///
514 /// \f[ \det G_{ij} - \det g_{ij}= 0 \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ (2) \f]
515 /// which ensures that the volume of infinitesimal material
516 /// elements remains constant during the deformation. This
517 /// condition is typically enforced by a Lagrange multiplier which
518 /// plays the role of a pressure. In such cases, the
519 /// stress tensor has form
520 ///
521 /// \f[ \sigma^{ij} = -p G^{ij} + \overline{\sigma}^{ij}\big(\gamma_{kl}\big), \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ (3) \f]
522 /// where only the deviatoric part of the stress tensor,
523 /// \f$ \overline{\sigma}^{ij}, \f$ depends directly on the
524 /// strain. The pressure \f$ p \f$ needs to be determined
525 /// independently from (2).
526 /// Given the deformed and undeformed metric tensors,
527 /// the computation of the stress tensor \f$ \sigma^{ij} \f$
528 /// for an incompressible
529 /// material therefore requires the computation of the following
530 /// quantities:
531 /// - The deviatoric stress \f$ \overline{\sigma}^{ij} \f$
532 /// - The contravariant deformed metric tensor \f$ G^{ij} \f$
533 /// - The determinant of the deformed
534 /// metric tensors, \f$ \det G_{ij}, \f$ which
535 /// is required in equation (2) whose solution determines the pressure.
536 /// .
537 /// \n
538 /// These quantities can be obtained from the following interface \n
539 /// \code
540 /// // Deviatoric part of the 2nd Piola Kirchhoff stress tensor
541 /// DenseMatrix<double> sigma_dev(DIM,DIM);
542 ///
543 /// // Metric tensor in the undeformed (stress-free) configuration
544 /// DenseMatrix<double> g(DIM,DIM);
545 ///
546 /// // Metric tensor in the deformed configuration
547 /// DenseMatrix<double> G(DIM,DIM);
548 ///
549 /// // Determinant of the deformed metric tensor
550 /// double Gdet;
551 ///
552 /// // Contravariant deformed metric tensor
553 /// DenseMatrix<double> G_contra(DIM,DIM);
554 ///
555 /// // Compute stress from the two metric tensors:
556 /// calculate_second_piola_kirchhoff_stress(g,G,sigma_dev,G_contra,Gdet);
557 /// \endcode
558 /// \n \n \n
559 /// -# \b Nearly \b Incompressible \b Behaviour: \n If the material is nearly
560 /// incompressible, it is advantageous to split the stress into
561 /// its deviatoric and hydrostatic parts by writing the
562 /// constitutive law in the form
563 ///
564 /// \f[ \sigma^{ij} = -p G^{ij} + \overline{\sigma}^{ij}\big(\gamma_{kl}\big), \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ (3) \f]
565 /// where the deviatoric part of the stress tensor,
566 /// \f$ \overline{\sigma}^{ij}, \f$ depends on the
567 /// strain. This form of the constitutive
568 /// law is identical to that of the incompressible
569 /// case and it involves a pressure \f$ p \f$ which needs to be
570 /// determined from an additional equation. In the
571 /// incompressible case, this equation was given by the incompressibility
572 /// constraint (2). Here, we need to augment the constitutive law (3) by
573 /// a separate equation for the pressure. Generally this takes the
574 /// form
575 ///
576 /// \f[ p = - \kappa \ d \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ (4) \f]
577 /// where \f$ \kappa \f$ is the "bulk modulus", a material property
578 /// that needs to be specified by the constitutive law.
579 /// \f$ d \f$ is the (generalised) dilatation, i.e. the relative change
580 /// in the volume of an infinitesimal material element (or some
581 /// suitable generalised quantitiy that is related to it). As the
582 /// material approaches incompressibility, \f$ \kappa \to \infty\f$, so
583 /// that infinitely large pressures would be required to achieve any change
584 /// in volume. To facilitate the implementation of (4) as the equation for
585 /// the pressure, we re-write it in the form
586 /// \f[ p \ \frac{1}{\kappa} + d\big(g_{ij},G_{ij}\big) = 0 \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ (5) \f]
587 /// which only involves quantities that remain finite
588 /// as we approach true incompressibility.
589 /// \n
590 /// Given the deformed and undeformed metric tensors,
591 /// the computation of the stress tensor \f$ \sigma^{ij} \f$
592 /// for a nearly incompressible
593 /// material therefore requires the computation of the following
594 /// quantities:
595 /// - The deviatoric stress \f$ \overline{\sigma}^{ij} \f$
596 /// - The contravariant deformed metric tensor \f$ G^{ij} \f$
597 /// - The generalised dilatation \f$ d \f$
598 /// - The inverse of the bulk modulus \f$ \kappa \f$
599 /// .
600 /// \n
601 /// These quantities can be obtained from the following interface \n
602 /// \code
603 /// // Deviatoric part of the 2nd Piola Kirchhoff stress tensor
604 /// DenseMatrix<double> sigma_dev(DIM,DIM);
605 ///
606 /// // Metric tensor in the undeformed (stress-free) configuration
607 /// DenseMatrix<double> g(DIM,DIM);
608 ///
609 /// // Metric tensor in the deformed configuration
610 /// DenseMatrix<double> G(DIM,DIM);
611 ///
612 /// // Contravariant deformed metric tensor
613 /// DenseMatrix<double> G_contra(DIM,DIM);
614 ///
615 /// // Inverse of the bulk modulus
616 /// double inv_kappa;
617 ///
618 /// // Generalised dilatation
619 /// double gen_dil;
620 ///
621 /// // Compute stress from the two metric tensors:
622 /// calculate_second_piola_kirchhoff_stress(g,G,sigma_dev,G_contra,inv_kappa,gen_dil);
623 /// \endcode
624 //==========================================================================
626 {
627 protected:
628 /// Test whether a matrix is square
630
631 /// Test whether two matrices are of equal dimensions
633 const DenseMatrix<double>& M2);
634
635 /// Check for errors in the input,
636 /// i.e. check that the dimensions of the arrays are all consistent
638 const DenseMatrix<double>& G,
639 DenseMatrix<double>& sigma);
640
641 /// Calculate a contravariant tensor from a covariant tensor,
642 /// and return the determinant of the covariant tensor.
645
646 /// Calculate the derivatives of the contravariant tensor
647 /// and the derivatives of the determinant of the covariant tensor
648 /// with respect to the components of the covariant tensor
652
653
654 public:
655 /// Empty constructor
657
658
659 /// Empty virtual destructor
660 virtual ~ConstitutiveLaw() {}
661
662
663 /// Calculate the contravariant 2nd Piola Kirchhoff
664 /// stress tensor. Arguments are the
665 /// covariant undeformed and deformed metric tensor and the
666 /// matrix in which to return the stress tensor
668 const DenseMatrix<double>& g,
669 const DenseMatrix<double>& G,
670 DenseMatrix<double>& sigma) = 0;
671
672 /// Calculate the derivatives of the contravariant
673 /// 2nd Piola Kirchhoff stress tensor with respect to the deformed metric
674 /// tensor. Arguments are the
675 /// covariant undeformed and deformed metric tensor, the current value of
676 /// the stress tensor and the
677 /// rank four tensor in which to return the derivatives of the stress tensor
678 /// The default implementation uses finite differences, but can be
679 /// overloaded for constitutive laws in which an analytic formulation
680 /// is possible.
681 /// If the boolean flag symmetrize_tensor is false, only the
682 /// "upper triangular" entries of the tensor will be filled in. This is
683 /// a useful efficiency when using the derivatives in Jacobian calculations.
685 const DenseMatrix<double>& g,
686 const DenseMatrix<double>& G,
687 const DenseMatrix<double>& sigma,
689 const bool& symmetrize_tensor = true);
690
691
692 /// Calculate the deviatoric part
693 /// \f$ \overline{ \sigma^{ij}}\f$ of the contravariant
694 /// 2nd Piola Kirchhoff stress tensor \f$ \sigma^{ij}\f$.
695 /// Also return the contravariant deformed metric
696 /// tensor and the determinant of the deformed metric tensor.
697 /// This form is appropriate
698 /// for truly-incompressible materials for which
699 /// \f$ \sigma^{ij} = - p G^{ij} +\overline{ \sigma^{ij}} \f$
700 /// where the "pressure" \f$ p \f$ is determined by
701 /// \f$ \det G_{ij} - \det g_{ij} = 0 \f$.
703 const DenseMatrix<double>& g,
704 const DenseMatrix<double>& G,
707 double& Gdet)
708 {
709 throw OomphLibError(
710 "Incompressible formulation not implemented for this constitutive law",
713 }
714
715 /// Calculate the derivatives of the contravariant
716 /// 2nd Piola Kirchhoff stress tensor \f$ \sigma^{ij}\f$.
717 /// with respect to the deformed metric tensor.
718 /// Also return the derivatives of the determinant of the
719 /// deformed metric tensor with respect to the deformed metric tensor.
720 /// This form is appropriate
721 /// for truly-incompressible materials.
722 /// The default implementation uses finite differences for the
723 /// derivatives that depend on the constitutive law, but not
724 /// for the derivatives of the determinant, which are generic.
725 /// / If the boolean flag symmetrize_tensor is false, only the
726 /// "upper triangular" entries of the tensor will be filled in. This is
727 /// a useful efficiency when using the derivatives in Jacobian calculations.
729 const DenseMatrix<double>& g,
730 const DenseMatrix<double>& G,
731 const DenseMatrix<double>& sigma,
732 const double& detG,
733 const double& interpolated_solid_p,
736 const bool& symmetrize_tensor = true);
737
738
739 /// Calculate the deviatoric part of the contravariant
740 /// 2nd Piola Kirchoff stress tensor. Also return the contravariant
741 /// deformed metric tensor, the generalised dilatation, \f$ d, \f$ and
742 /// the inverse of the bulk modulus \f$ \kappa\f$. This form is appropriate
743 /// for near-incompressible materials for which
744 /// \f$ \sigma^{ij} = -p G^{ij} + \overline{ \sigma^{ij}} \f$
745 /// where the "pressure" \f$ p \f$ is determined from
746 /// \f$ p / \kappa - d =0 \f$.
748 const DenseMatrix<double>& g,
749 const DenseMatrix<double>& G,
752 double& gen_dil,
753 double& inv_kappa)
754 {
755 throw OomphLibError(
756 "Near-incompressible formulation not implemented for constitutive law",
759 }
760
761 /// Calculate the derivatives of the contravariant
762 /// 2nd Piola Kirchoff stress tensor with respect to the deformed metric
763 /// tensor. Also return the derivatives of the generalised dilatation,
764 /// \f$ d, \f$ with respect to the deformed metric tensor.
765 /// This form is appropriate
766 /// for near-incompressible materials.
767 /// The default implementation uses finite differences.
768 /// If the boolean flag symmetrize_tensor is false, only the
769 /// "upper triangular" entries of the tensor will be filled in. This is
770 /// a useful efficiency when using the derivatives in Jacobian calculations.
772 const DenseMatrix<double>& g,
773 const DenseMatrix<double>& G,
774 const DenseMatrix<double>& sigma,
775 const double& gen_dil,
776 const double& inv_kappa,
777 const double& interpolated_solid_p,
780 const bool& symmetrize_tensor = true);
781
782
783 /// Pure virtual function in which the user must declare if the
784 /// constitutive equation requires an incompressible formulation
785 /// in which the volume constraint is enforced explicitly.
786 /// Used as a sanity check in PARANOID mode.
788 };
789
790
791 /////////////////////////////////////////////////////////////////////////
792 /////////////////////////////////////////////////////////////////////////
793 /////////////////////////////////////////////////////////////////////////
794
795
796 //========================================================================
797 /// Class for a "non-rational" extension of classical linear elasticity
798 /// to large displacements:
799 /// \f[ \sigma^{ij} = E^{ijkl} \gamma_{kl} \f]
800 /// where
801 /// \f[ E^{ijkl} = \frac{E}{(1+\nu)} \left( \frac{\nu}{(1-2\nu)} G^{ij} G^{kl} + \frac{1}{2} \left( G^{ik} G^{jl} + G^{il} G^{jk} \right) \right) \f]
802 /// For small strains \f$ (| G_{ij} - g_{ij} | \ll 1)\f$ this approaches
803 /// the version appropriate for linear elasticity, obtained
804 /// by replacing \f$ G^{ij}\f$ with \f$ g^{ij}\f$.
805 ///
806 /// We provide three versions of \c calculate_second_piola_kirchhoff_stress():
807 /// -# If \f$ \nu \ne 1/2 \f$ (and not close to \f$ 1/2 \f$), the
808 /// constitutive law can be used directly in the above form, using
809 /// the deformed and undeformed metric tensors as input.
810 /// -# If the material is incompressible (\f$ \nu = 1/2 \f$),
811 /// the first term in the above expression for \f$ E^{ijkl} \f$
812 /// is singular. We re-write the constitutive equation for this
813 /// case as
814 ///
815 /// \f[ \sigma^{ij} = -p G^{ij} + \frac{E}{3} \left( G^{ik} G^{jl} + G^{il} G^{jk} \right) \gamma_{kl} \f]
816 /// where the pressure \f$ p \f$ needs to be determined independently
817 /// via the incompressibility constraint.
818 /// In this case, the stress returned by
819 /// \c calculate_second_piola_kirchhoff_stress()
820 /// contains only the deviatoric part of the 2nd Piola Kirchhoff stress,
821 ///
822 /// \f[ \overline{\sigma}^{ij} = \frac{E}{3} \left( G^{ik} G^{jl} + G^{il} G^{jk} \right) \gamma_{kl}. \f]
823 /// The function also returns the contravariant metric tensor
824 /// \f$ G^{ij}\f$ (since it is needed to form the complete stress
825 /// tensor), and the determinant of the deformed covariant metric
826 /// tensor \f$ {\tt detG} = \det G_{ij} \f$ (since it is needed
827 /// in the equation that enforces the incompressibility).
828 /// -# If \f$ \nu \approx 1/2 \f$, the original form of the
829 /// constitutive equation could be used, but the resulting
830 /// equations tend to be ill-conditioned since they contain
831 /// the product of the large "bulk modulus"
832 ///
833 /// \f[ \kappa = \frac{E\nu}{(1+\nu)(1-2\nu)} \f]
834 /// and the small "generalised dilatation"
835 ///
836 /// \f[ d = \frac{1}{2} G^{ij} (G_{ij}-g_{ij}). \f]
837 /// [\f$ d \f$ represents the actual dilatation in the small
838 /// strain limit; for large deformations it doesn't have
839 /// any sensible interpretation (or does it?). It is simply
840 /// the term that needs to go to zero as \f$ \kappa \to \infty\f$.]
841 /// In this case, the stress returned by
842 /// \c calculate_second_piola_kirchhoff_stress()
843 /// contains only the deviatoric part of the 2nd Piola Kirchhoff stress,
844 ///
845 /// \f[ \overline{\sigma}^{ij} = \frac{E}{3} \left( G^{ik} G^{jl} + G^{il} G^{jk} \right) \gamma_{kl}. \f]
846 /// The function also returns the contravariant metric tensor
847 /// \f$ G^{ij}\f$ (since it is needed to form the complete stress
848 /// tensor), the inverse of the bulk modulus, and the generalised
849 /// dilatation (since they are needed in the equation
850 /// that determines the pressure).
851 ///
852 //=========================================================================
854 {
855 public:
856 /// The constructor takes the pointers to values of material parameters:
857 /// Poisson's ratio and Young's modulus.
858 GeneralisedHookean(double* nu_pt, double* e_pt)
860 {
861 }
862
863 /// The constructor takes the pointers to value of
864 /// Poisson's ratio . Young's modulus is set to E=1.0,
865 /// implying that all stresses have been non-dimensionalised
866 /// on on it.
867 GeneralisedHookean(double* nu_pt)
868 : ConstitutiveLaw(),
869 Nu_pt(nu_pt),
870 E_pt(new double(1.0)),
872 {
873 }
874
875
876 /// Virtual destructor
878 {
879 if (Must_delete_e) delete E_pt;
880 }
881
882 /// Calculate the contravariant 2nd Piola Kirchhoff
883 /// stress tensor. Arguments are the
884 /// covariant undeformed and deformed metric tensor and the
885 /// matrix in which to return the stress tensor
887 const DenseMatrix<double>& G,
888 DenseMatrix<double>& sigma);
889
890
891 /// Calculate the deviatoric part
892 /// \f$ \overline{ \sigma^{ij}}\f$ of the contravariant
893 /// 2nd Piola Kirchhoff stress tensor \f$ \sigma^{ij}\f$.
894 /// Also return the contravariant deformed metric
895 /// tensor and the determinant of the deformed metric tensor.
896 /// This form is appropriate
897 /// for truly-incompressible materials for which
898 /// \f$ \sigma^{ij} = - p G^{ij} +\overline{ \sigma^{ij}} \f$
899 /// where the "pressure" \f$ p \f$ is determined by
900 /// \f$ \det G_{ij} - \det g_{ij} = 0 \f$.
902 const DenseMatrix<double>& G,
905 double& Gdet);
906
907
908 /// Calculate the deviatoric part of the contravariant
909 /// 2nd Piola Kirchoff stress tensor. Also return the contravariant
910 /// deformed metric tensor, the generalised dilatation, \f$ d, \f$ and
911 /// the inverse of the bulk modulus \f$ \kappa\f$. This form is appropriate
912 /// for near-incompressible materials for which
913 /// \f$ \sigma^{ij} = -p G^{ij} + \overline{ \sigma^{ij}} \f$
914 /// where the "pressure" \f$ p \f$ is determined from
915 /// \f$ p / \kappa - d =0 \f$.
917 const DenseMatrix<double>& G,
920 double& gen_dil,
921 double& inv_kappa);
922
923
924 /// Pure virtual function in which the writer must declare if the
925 /// constitutive equation requires an incompressible formulation
926 /// in which the volume constraint is enforced explicitly.
927 /// Used as a sanity check in PARANOID mode. False.
929 {
930 return false;
931 }
932
933 private:
934 /// Poisson ratio
935 double* Nu_pt;
936
937 /// Young's modulus
938 double* E_pt;
939
940 /// Boolean flag to indicate if storage for elastic modulus
941 /// must be deleted in destructor
943 };
944
945
946 /////////////////////////////////////////////////////////////////////////
947 /////////////////////////////////////////////////////////////////////////
948 /////////////////////////////////////////////////////////////////////////
949
950
951 //=====================================================================
952 /// A class for constitutive laws derived from strain-energy functions.
953 /// Theory is in Green and Zerna.
954 //=====================================================================
956 {
957 private:
958 /// Pointer to the strain energy function
960
961 public:
962 /// Constructor takes a pointer to the strain energy function
968
969 /// Calculate the contravariant 2nd Piola Kirchhoff
970 /// stress tensor. Arguments are the
971 /// covariant undeformed and deformed metric tensor and the
972 /// matrix in which to return the stress tensor.
973 /// Uses correct 3D invariants for 2D (plane strain) problems.
975 const DenseMatrix<double>& G,
976 DenseMatrix<double>& sigma);
977
978
979 /// Calculate the deviatoric part
980 /// \f$ \overline{ \sigma^{ij}}\f$ of the contravariant
981 /// 2nd Piola Kirchhoff stress tensor \f$ \sigma^{ij}\f$.
982 /// Also return the contravariant deformed metric
983 /// tensor and the determinant of the deformed metric tensor.
984 /// This form is appropriate
985 /// for truly-incompressible materials for which
986 /// \f$ \sigma^{ij} = - p G^{ij} +\overline{ \sigma^{ij}} \f$
987 /// where the "pressure" \f$ p \f$ is determined by
988 /// \f$ \det G_{ij} - \det g_{ij} = 0 \f$.
990 const DenseMatrix<double>& G,
993 double& Gdet);
994
995
996 /// Calculate the deviatoric part of the contravariant
997 /// 2nd Piola Kirchoff stress tensor. Also return the contravariant
998 /// deformed metric tensor, the generalised dilatation, \f$ d, \f$ and
999 /// the inverse of the bulk modulus \f$ \kappa\f$. This form is appropriate
1000 /// for near-incompressible materials for which
1001 /// \f$ \sigma^{ij} = -p G^{ij} + \overline{ \sigma^{ij}} \f$
1002 /// where the "pressure" \f$ p \f$ is determined from
1003 /// \f$ p / \kappa - d =0 \f$.
1005 const DenseMatrix<double>& G,
1008 double& gen_dil,
1009 double& inv_kappa);
1010
1011
1012 /// State if the constitutive equation requires an incompressible
1013 /// formulation in which the volume constraint is enforced explicitly.
1014 /// Used as a sanity check in PARANOID mode. This is determined
1015 /// by interrogating the associated strain energy function.
1020 };
1021
1022} // namespace oomph
1023
1024#endif
e
Definition cfortran.h:571
cstr elem_len * i
Definition cfortran.h:603
A class for constitutive laws for elements that solve the equations of solid mechanics based upon the...
void error_checking_in_input(const DenseMatrix< double > &g, const DenseMatrix< double > &G, DenseMatrix< double > &sigma)
Check for errors in the input, i.e. check that the dimensions of the arrays are all consistent.
virtual void calculate_second_piola_kirchhoff_stress(const DenseMatrix< double > &g, const DenseMatrix< double > &G, DenseMatrix< double > &sigma_dev, DenseMatrix< double > &Gcontra, double &gen_dil, double &inv_kappa)
Calculate the deviatoric part of the contravariant 2nd Piola Kirchoff stress tensor....
virtual bool requires_incompressibility_constraint()=0
Pure virtual function in which the user must declare if the constitutive equation requires an incompr...
double calculate_contravariant(const DenseMatrix< double > &Gcov, DenseMatrix< double > &Gcontra)
Calculate a contravariant tensor from a covariant tensor, and return the determinant of the covariant...
virtual void calculate_d_second_piola_kirchhoff_stress_dG(const DenseMatrix< double > &g, const DenseMatrix< double > &G, const DenseMatrix< double > &sigma, RankFourTensor< double > &d_sigma_dG, const bool &symmetrize_tensor=true)
Calculate the derivatives of the contravariant 2nd Piola Kirchhoff stress tensor with respect to the ...
void calculate_d_contravariant_dG(const DenseMatrix< double > &Gcov, RankFourTensor< double > &dGcontra_dG, DenseMatrix< double > &d_detG_dG)
Calculate the derivatives of the contravariant tensor and the derivatives of the determinant of the c...
bool is_matrix_square(const DenseMatrix< double > &M)
Test whether a matrix is square.
ConstitutiveLaw()
Empty constructor.
bool are_matrices_of_equal_dimensions(const DenseMatrix< double > &M1, const DenseMatrix< double > &M2)
Test whether two matrices are of equal dimensions.
virtual void calculate_second_piola_kirchhoff_stress(const DenseMatrix< double > &g, const DenseMatrix< double > &G, DenseMatrix< double > &sigma)=0
Calculate the contravariant 2nd Piola Kirchhoff stress tensor. Arguments are the covariant undeformed...
virtual ~ConstitutiveLaw()
Empty virtual destructor.
virtual void calculate_second_piola_kirchhoff_stress(const DenseMatrix< double > &g, const DenseMatrix< double > &G, DenseMatrix< double > &sigma_dev, DenseMatrix< double > &G_contra, double &Gdet)
Calculate the deviatoric part of the contravariant 2nd Piola Kirchhoff stress tensor ....
Class for a "non-rational" extension of classical linear elasticity to large displacements:
virtual ~GeneralisedHookean()
Virtual destructor.
bool Must_delete_e
Boolean flag to indicate if storage for elastic modulus must be deleted in destructor.
GeneralisedHookean(double *nu_pt)
The constructor takes the pointers to value of Poisson's ratio . Young's modulus is set to E=1....
void calculate_second_piola_kirchhoff_stress(const DenseMatrix< double > &g, const DenseMatrix< double > &G, DenseMatrix< double > &sigma)
Calculate the contravariant 2nd Piola Kirchhoff stress tensor. Arguments are the covariant undeformed...
double * E_pt
Young's modulus.
bool requires_incompressibility_constraint()
Pure virtual function in which the writer must declare if the constitutive equation requires an incom...
double * Nu_pt
Poisson ratio.
GeneralisedHookean(double *nu_pt, double *e_pt)
The constructor takes the pointers to values of material parameters: Poisson's ratio and Young's modu...
Generalisation of Mooney Rivlin constitutive law to compressible media as suggested on p....
GeneralisedMooneyRivlin(double *nu_pt, double *c1_pt)
Constructor takes the pointers to the constitutive parameters: Poisson's ratio, the Mooney-Rivlin par...
bool requires_incompressibility_constraint()
Pure virtual function in which the user must declare if the constitutive equation requires an incompr...
double W(const Vector< double > &I)
Return the strain energy in terms of the strain invariants.
bool Must_delete_e
Boolean flag to indicate if storage for elastic modulus must be deleted in destructor.
double * E_pt
Young's modulus.
GeneralisedMooneyRivlin(double *nu_pt, double *c1_pt, double *e_pt)
Constructor takes the pointers to the constitutive parameters: Poisson's ratio, the Mooney-Rivlin par...
virtual ~GeneralisedMooneyRivlin()
Virtual destructor.
double W(const DenseMatrix< double > &gamma)
Return the strain energy in terms of strain tensor.
void derivatives(Vector< double > &I, Vector< double > &dWdI)
Return the derivatives of the strain energy function with respect to the strain invariants.
double * Nu_pt
Poisson's ratio.
double * C1_pt
Mooney-Rivlin parameter.
Neo Hookean constitutive law (incompressible version) No argument for Poisson ratio here - it must be...
double W(const Vector< double > &I)
Return the strain energy in terms of the strain invariants.
virtual ~IncompressibleNeoHookean()
Virtual destructor.
bool requires_incompressibility_constraint()
Pure virtual function in which the user must declare if the constitutive equation requires an incompr...
IncompressibleNeoHookean()
Argument-free constructor.
double W(const DenseMatrix< double > &gamma)
Return the strain energy in terms of strain tensor.
double * E_pt
Young's modulus.
IncompressibleNeoHookean(double *e_pt)
The constructor takes Young's modulus as an argument.
void derivatives(Vector< double > &I, Vector< double > &dWdI)
Return the derivatives of the strain energy function with respect to the strain invariants.
bool Must_delete_e
Boolean indicating if Young's modulus must be deleted in destructor.
A class for constitutive laws derived from strain-energy functions. Theory is in Green and Zerna.
StrainEnergyFunction * Strain_energy_function_pt
Pointer to the strain energy function.
bool requires_incompressibility_constraint()
State if the constitutive equation requires an incompressible formulation in which the volume constra...
IsotropicStrainEnergyFunctionConstitutiveLaw(StrainEnergyFunction *const &strain_energy_function_pt)
Constructor takes a pointer to the strain energy function.
void calculate_second_piola_kirchhoff_stress(const DenseMatrix< double > &g, const DenseMatrix< double > &G, DenseMatrix< double > &sigma)
Calculate the contravariant 2nd Piola Kirchhoff stress tensor. Arguments are the covariant undeformed...
MooneyRivlin strain-energy function. with constitutive parameters C1 and C2:
void derivatives(Vector< double > &I, Vector< double > &dWdI)
Return the derivatives of the strain energy function with respect to the strain invariants.
double * C2_pt
Pointer to second Mooney Rivlin constant.
virtual ~MooneyRivlin()
Empty Virtual destructor.
double W(const DenseMatrix< double > &gamma)
Return the strain energy in terms of strain tensor.
double W(const Vector< double > &I)
Return the strain energy in terms of the strain invariants.
double * C1_pt
Pointer to first Mooney Rivlin constant.
MooneyRivlin(double *c1_pt, double *c2_pt)
Constructor takes the pointer to the value of the constants.
bool requires_incompressibility_constraint()
Pure virtual function in which the user must declare if the constitutive equation requires an incompr...
Neo Hookean constitutive law in terms of Young's modulus and Poisson ratio.
virtual ~NeoHookean()
Virtual destructor.
double * Nu_pt
Poisson's ratio.
bool requires_incompressibility_constraint()
Pure virtual function in which the user must declare if the constitutive equation requires an incompr...
void derivatives(Vector< double > &I, Vector< double > &dWdI)
Return the derivatives of the strain energy function with respect to the strain invariants.
NeoHookean(double *nu_pt, double *e_pt)
The constructor takes the pointers to values of material parameters: Poisson's ratio and Young's modu...
NeoHookean(double *nu_pt)
The constructor takes the pointer to value of Poisson's ratio. Young's modulus is set to E=1....
bool Must_delete_e
Boolean indicating if Young's modulus must be deleted in destructor.
double W(const DenseMatrix< double > &gamma)
Return the strain energy in terms of strain tensor.
double * E_pt
Young's modulus.
double W(const Vector< double > &I)
Return the strain energy in terms of the strain invariants.
An OomphLibError object which should be thrown when an run-time error is encountered....
Base class for strain energy functions to be used in solid mechanics computations.
StrainEnergyFunction()
Constructor takes no arguments.
virtual bool requires_incompressibility_constraint()=0
Pure virtual function in which the user must declare if the constitutive equation requires an incompr...
virtual void derivative(const DenseMatrix< double > &gamma, DenseMatrix< double > &dWdgamma)
Return the derivatives of the strain energy function with respect to the components of the strain ten...
virtual ~StrainEnergyFunction()
Empty virtual destructor.
virtual double W(const DenseMatrix< double > &gamma)
Return the strain energy in terms of the strain tensor.
virtual void derivatives(Vector< double > &I, Vector< double > &dWdI)
Return the derivatives of the strain energy function with respect to the strain invariants....
virtual double W(const Vector< double > &I)
Return the strain energy in terms of the strain invariants.
TAdvectionDiffusionReactionElement<NREAGENT,DIM,NNODE_1D> elements are isoparametric triangular DIM-d...
DRAIG: Change all instances of (SPATIAL_DIM) to (DIM-1).