conspire/constitutive/solid/hyperelastic/hencky/
mod.rs1#[cfg(test)]
2mod test;
3
4use crate::{
5 constitutive::{
6 ConstitutiveError,
7 solid::{Solid, TWO_THIRDS, elastic::Elastic, hyperelastic::Hyperelastic},
8 },
9 math::{ContractThirdFourthWithFirstSecond, IDENTITY, Quantity, Rank2, TensorRank4},
10 mechanics::{CauchyStress, CauchyTangentStiffness, Deformation, DeformationGradient},
11 units::{EnergyDensity, Stress},
12};
13
14#[doc = include_str!("doc.md")]
15#[derive(Clone, Debug)]
16pub struct Hencky {
17 pub bulk_modulus: Quantity<Stress>,
19 pub shear_modulus: Quantity<Stress>,
21}
22
23impl Solid for Hencky {
24 fn bulk_modulus(&self) -> Quantity<Stress> {
25 self.bulk_modulus
26 }
27 fn shear_modulus(&self) -> Quantity<Stress> {
28 self.shear_modulus
29 }
30}
31
32impl Elastic for Hencky {
33 #[doc = include_str!("cauchy_stress.md")]
34 fn cauchy_stress(
35 &self,
36 deformation_gradient: &DeformationGradient,
37 ) -> Result<CauchyStress, ConstitutiveError> {
38 let jacobian = self.jacobian(deformation_gradient)?;
39 let (deviatoric_strain, strain_trace) = (deformation_gradient
40 .left_cauchy_green()
41 .logm()
42 .map_err(|error| {
43 ConstitutiveError::upstream(error, self)
44 })? * 0.5)
45 .deviatoric_and_trace();
46 Ok(deviatoric_strain * (2.0 * self.shear_modulus() / jacobian)
47 + IDENTITY * (self.bulk_modulus() * strain_trace / jacobian))
48 }
49 #[doc = include_str!("cauchy_tangent_stiffness.md")]
50 fn cauchy_tangent_stiffness(
51 &self,
52 deformation_gradient: &DeformationGradient,
53 ) -> Result<CauchyTangentStiffness, ConstitutiveError> {
54 let jacobian = self.jacobian(deformation_gradient)?;
55 let left_cauchy_green = deformation_gradient.left_cauchy_green();
56 let (deviatoric_strain, strain_trace) = (left_cauchy_green
57 .logm()
58 .map_err(|error| ConstitutiveError::upstream(error, self))?
59 * 0.5)
60 .deviatoric_and_trace();
61 let scaled_deformation_gradient = deformation_gradient * self.shear_modulus() / jacobian;
62 Ok((left_cauchy_green
63 .dlogm()
64 .map_err(|error| ConstitutiveError::upstream(error, self))?
65 .contract_third_fourth_with_first_second(
66 &(TensorRank4::dyad_il_jk(&scaled_deformation_gradient, &IDENTITY)
67 + TensorRank4::dyad_ik_jl(&IDENTITY, &scaled_deformation_gradient)),
68 ))
69 + (TensorRank4::dyad_ij_kl(
70 &(IDENTITY
71 * ((self.bulk_modulus() - TWO_THIRDS * self.shear_modulus()) / jacobian)
72 - deviatoric_strain * (2.0 * self.shear_modulus() / jacobian)
73 - IDENTITY * (self.bulk_modulus() * strain_trace / jacobian)),
74 &deformation_gradient.inverse_transpose(),
75 )))
76 }
77}
78
79impl Hyperelastic for Hencky {
80 #[doc = include_str!("helmholtz_free_energy_density.md")]
81 fn helmholtz_free_energy_density(
82 &self,
83 deformation_gradient: &DeformationGradient,
84 ) -> Result<Quantity<EnergyDensity>, ConstitutiveError> {
85 let _jacobian = self.jacobian(deformation_gradient)?;
86 let strain = deformation_gradient
87 .left_cauchy_green()
88 .logm()
89 .map_err(|error| ConstitutiveError::upstream(error, self))?
90 * 0.5;
91 Ok(self.shear_modulus() * strain.squared_trace()
92 + 0.5
93 * (self.bulk_modulus() - TWO_THIRDS * self.shear_modulus())
94 * strain.trace().powi(2))
95 }
96}