Skip to content

Elastic moduli ​

<!– crosslinks: written by .github/scripts/crosslinks.py from docs/crosslinks.toml; do not edit –>

<!– /crosslinks –>

An isotropic linear elastic material has two independent constants, and six of them are in common use: the bulk modulus , Young's modulus , Lamé's first parameter , the shear modulus , Poisson's ratio and the P-wave (oedometric) modulus . Any two of them fix the others. TensND makes the tensor the meeting point: the stiffness, or the compliance, is built from any pair, and any modulus is read from either, so that a conversion is one function inside another.

to …write
build a stiffness from two moduliiso_stiffness_<pair>(a, b), e.g. iso_stiffness_young_poisson(E, ν) or iso_stiffness_E_ν(E, ν)
build a compliance from two moduliiso_compliance_<pair>(a, b), e.g. iso_compliance_young_poisson(E, ν)
read one modulusyoung_modulus(ℂ), poisson_ratio(ℂ), …, or young_modulus(𝕊; role = :compliance)
read two moduliyoung_poisson(ℂ) (E_ν(ℂ)), lame_shear(ℂ) (λ_μ(ℂ)), …, with the same role
work in 2-D (plane strain)the same builders with Val(2) first
switch between plane strain and plane stressplane_strain_stiffness, plane_stress_stiffness, plane_stress_to_plane_strain, plane_strain_to_plane_stress

The stiffness and its moduli ​

In dimension 3 the stiffness is          , a TensISO{4,3}. The other moduli follow from :

Each has its reader, bulk_modulus, young_modulus, lame_lambda, shear_modulus, poisson_ratio and pwave_modulus, and each pair too, named after its two moduli in the order : bulk_shear, young_poisson, lame_shear, young_pwave, …

julia
using TensND

ℂ = iso_stiffness_young_poisson(70.0, 0.33)   # an aluminum, GPa
(k = bulk_modulus(ℂ), E = young_modulus(ℂ), λ = lame_lambda(ℂ),
 μ = shear_modulus(ℂ), ν = poisson_ratio(ℂ), M = pwave_modulus(ℂ))
(k = 68.62745098039215, E = 70.0, λ = 51.08359133126935, μ = 26.31578947368421, ν = 0.33, M = 103.71517027863777)

Stiffness or compliance ​

The compliance is       with   and  . Every reader takes the keyword role, which says which of the two it is given: :stiffness, the default, or :compliance. Each modulus then has a formula of its own on each, written directly on the two coefficients, never through an inverse:

moduluson     on     
  
  
    
  
julia
𝕊 = iso_compliance_young_poisson(70.0, 0.33)   # the same aluminum
young_poisson(𝕊; role = :compliance)
(70.0, 0.33)

The compliance builders write directly as well: from ,       . Nothing in a TensISO tells a stiffness from a compliance: the role is the caller's to give, and a compliance read as a stiffness gives the moduli of another material.

Building from any pair ​

The stiffness of a pair is iso_stiffness_<pair>, and its compliance iso_compliance_<pair> (iso_compliance for ), with the same names. The fifteen pairs, and how each gives (the formulas are those of the classical conversion table, in this notation):

pairbuilder
iso_stiffness_bulk_young   
iso_stiffness_bulk_lame 
iso_stiffness 
iso_stiffness_bulk_poisson   
iso_stiffness_bulk_pwave  
iso_stiffness_young_lame  
iso_stiffness_young_shear  
iso_stiffness_young_poisson   
iso_stiffness_young_pwave    
iso_stiffness_lame_shear
iso_stiffness_lame_poisson 
iso_stiffness_lame_pwave 
iso_stiffness_shear_poisson 
iso_stiffness_shear_pwave 
iso_stiffness_poisson_pwave   

with   and  . These two pairs solve a quadratic equation. From the root kept is the only one with   . From both roots are materials, one with   and one with  , and and cannot tell them apart; the one kept is  .

The pair says nothing of at  , where   as well. A conversion reads the result on the stiffness:

julia
E, ν = young_poisson(iso_stiffness_lame_shear(40.0, 26.0))
(67.75757575757575, 0.30303030303030304)
julia
young_shear(iso_stiffness_bulk_poisson(70.0, 0.25))
(105.0, 42.0)

Shorter names ​

The pairs without the P-wave modulus also have the names of their symbols, in ASCII and with Greek letters, as exact aliases: k_mu and k_μ are bulk_shear, E_nu and E_ν are young_poisson, λ_μ and lambda_mu are lame_shear, and the builders likewise, iso_stiffness_E_nu, iso_stiffness_E_ν, iso_stiffness_λ_μ, … and iso_compliance_E_nu, iso_compliance_E_ν, iso_compliance_λ_μ, …. The pairs with have none: k_M or μ_M name the moduli of a matrix in MeanFieldHomogenization, and the two meanings would be read one for the other.

julia
k, μ = k_μ(iso_stiffness_E_ν(70.0, 0.33))
(68.62745098039215, 26.31578947368421)

Symbolic moduli ​

No formula depends on the sign of a value, so the moduli may be symbols. With SymPy, the closed forms come out exactly:

julia
using SymPyPythonCall
λ, μ = symbols("λ μ", positive = true)
ℂ = iso_stiffness_lame_shear(λ, μ)
simplify(young_modulus(ℂ)), simplify(poisson_ratio(ℂ))
(μ*(3*λ + 2*μ)/(λ + μ), λ/(2*(λ + μ)))

They go through ForwardDiff as well: a derivative of a modulus with respect to another pair is that of the composition.

julia
using ForwardDiff
ForwardDiff.derivative(ν -> shear_modulus(iso_stiffness_young_poisson(70.0, ν)), 0.33)
-19.78630787495053

Two dimensions ​

A TensISO{4,2} is the in-plane stiffness of a 3-D material under plane strain,      . Its , , , and are those of the 3-D material, while its bulk modulus is the in-plane one,   , the factor of over the dimension, as for bulk_shear. Every builder takes the dimension as a first argument Val(2) (Val(3) is the default):

julia
ℂ₂ = iso_stiffness_young_poisson(Val(2), 70.0, 0.33)
bulk_shear(ℂ₂), young_poisson(ℂ₂)
((77.39938080495357, 26.31578947368421), (70.0, 0.33000000000000007))

On a 2-D compliance     , with    and  , the readers use

and the compliance builders take Val(2) as the stiffness builders do:

julia
𝕊₂ = iso_compliance_young_poisson(Val(2), 70.0, 0.33)
young_poisson(𝕊₂; role = :compliance)
(70.0, 0.32999999999999996)

The pairs with then use the in-plane bulk modulus:   ,   ,   , and, from ,   . That last quadratic has two roots of physical materials, of Poisson's ratios and  ; the one kept is   .

Plane strain and plane stress ​

A 2-D computation on a 3-D material assumes either plane strain,  , or plane stress,  . plane_strain_stiffness and plane_stress_stiffness give the in-plane stiffness of each. Plane strain keeps the in-plane block of ; plane stress eliminates from  , which keeps and replaces by

julia
ℂ = iso_stiffness_young_poisson(70.0, 0.33)
lame_shear(plane_strain_stiffness(ℂ)), lame_shear(plane_stress_stiffness(ℂ))
((51.08359133126936, 26.31578947368421), (25.92301649646505, 26.31578947368421))

Both are TensISO{4,2}, so a plane-stress state is computed with the plane-strain formulas of another material. plane_stress_to_plane_strain gives its moduli and plane_strain_to_plane_stress goes back:

julia
E′, ν′ = plane_stress_to_plane_strain(70.0, 0.33)
young_poisson(plane_stress_stiffness(ℂ)) .≈ (E′, ν′)
(true, true)