conspire/constitutive/solid/hyperelastic/isihara/
mod.rs1#[cfg(test)]
2mod test;
3
4use crate::{
5 constitutive::{
6 ConstitutiveError,
7 solid::{FIVE_THIRDS, Solid, TWO_THIRDS, elastic::Elastic, hyperelastic::Hyperelastic},
8 },
9 math::{IDENTITY, Quantity, Rank2, TensorRank4},
10 mechanics::{CauchyStress, CauchyTangentStiffness, Deformation, DeformationGradient, Scalar},
11 units::{EnergyDensity, Stress},
12};
13
14const FOUR_THIRDS: Scalar = 4.0 / 3.0;
15
16#[doc = include_str!("doc.md")]
17#[derive(Clone, Debug)]
18pub struct Isihara {
19 pub bulk_modulus: Quantity<Stress>,
21 pub shear_modulus: Quantity<Stress>,
23 pub extra_modulus: Quantity<Stress>,
25 pub quadratic_modulus: Quantity<Stress>,
27}
28
29impl Isihara {
30 pub fn extra_modulus(&self) -> Quantity<Stress> {
32 self.extra_modulus
33 }
34 pub fn quadratic_modulus(&self) -> Quantity<Stress> {
36 self.quadratic_modulus
37 }
38}
39
40impl Solid for Isihara {
41 fn bulk_modulus(&self) -> Quantity<Stress> {
42 self.bulk_modulus
43 }
44 fn shear_modulus(&self) -> Quantity<Stress> {
45 self.shear_modulus
46 }
47}
48
49impl Elastic for Isihara {
50 #[doc = include_str!("cauchy_stress.md")]
51 fn cauchy_stress(
52 &self,
53 deformation_gradient: &DeformationGradient,
54 ) -> Result<CauchyStress, ConstitutiveError> {
55 let jacobian = self.jacobian(deformation_gradient)?;
56 let isochoric_left_cauchy_green_deformation =
57 deformation_gradient.left_cauchy_green() / jacobian.powf(TWO_THIRDS);
58 let first_invariant = isochoric_left_cauchy_green_deformation.trace();
59 let dw_di1 = 0.5 * (self.shear_modulus() - self.extra_modulus())
60 + self.quadratic_modulus() * (first_invariant - 3.0);
61 Ok(
62 ((isochoric_left_cauchy_green_deformation.deviatoric() * (dw_di1 * 2.0)
63 - isochoric_left_cauchy_green_deformation
64 .inverse()
65 .deviatoric()
66 * self.extra_modulus())
67 + IDENTITY * (self.bulk_modulus() * 0.5 * (jacobian.powi(2) - 1.0)))
68 / jacobian,
69 )
70 }
71 #[doc = include_str!("cauchy_tangent_stiffness.md")]
72 fn cauchy_tangent_stiffness(
73 &self,
74 deformation_gradient: &DeformationGradient,
75 ) -> Result<CauchyTangentStiffness, ConstitutiveError> {
76 let jacobian = self.jacobian(deformation_gradient)?;
77 let inverse_transpose_deformation_gradient = deformation_gradient.inverse_transpose();
78 let left_cauchy_green_deformation = deformation_gradient.left_cauchy_green();
79 let isochoric_left_cauchy_green_deformation =
80 left_cauchy_green_deformation.clone() / jacobian.powf(TWO_THIRDS);
81 let first_invariant = isochoric_left_cauchy_green_deformation.trace();
82 let dw_di1 = 0.5 * (self.shear_modulus() - self.extra_modulus())
83 + self.quadratic_modulus() * (first_invariant - 3.0);
84 let scaled_dw_di1 = dw_di1 * 2.0 / jacobian.powf(FIVE_THIRDS);
85 let inverse_isochoric_left_cauchy_green_deformation =
86 isochoric_left_cauchy_green_deformation.inverse();
87 let deviatoric_inverse_isochoric_left_cauchy_green_deformation =
88 inverse_isochoric_left_cauchy_green_deformation.deviatoric();
89 let term_1 = TensorRank4::dyad_ij_kl(
90 &inverse_isochoric_left_cauchy_green_deformation,
91 &inverse_transpose_deformation_gradient,
92 ) * TWO_THIRDS
93 - TensorRank4::dyad_ik_jl(
94 &inverse_isochoric_left_cauchy_green_deformation,
95 &inverse_transpose_deformation_gradient,
96 )
97 - TensorRank4::dyad_il_jk(
98 &inverse_transpose_deformation_gradient,
99 &inverse_isochoric_left_cauchy_green_deformation,
100 );
101 let term_3 = TensorRank4::dyad_ij_kl(
102 &deviatoric_inverse_isochoric_left_cauchy_green_deformation,
103 &inverse_transpose_deformation_gradient,
104 );
105 let term_2 = TensorRank4::dyad_ij_kl(
106 &IDENTITY,
107 &((deviatoric_inverse_isochoric_left_cauchy_green_deformation * TWO_THIRDS)
108 * &inverse_transpose_deformation_gradient),
109 );
110 let d_first_invariant_dw_di1_df = deformation_gradient
111 * (4.0 * self.quadratic_modulus() / jacobian.powf(TWO_THIRDS))
112 - inverse_transpose_deformation_gradient.clone()
113 * (FOUR_THIRDS * self.quadratic_modulus() * first_invariant);
114 let extra_term_1 = TensorRank4::dyad_ij_kl(
115 &isochoric_left_cauchy_green_deformation.deviatoric(),
116 &d_first_invariant_dw_di1_df,
117 ) / jacobian;
118 Ok((TensorRank4::dyad_ik_jl(&IDENTITY, deformation_gradient)
119 + TensorRank4::dyad_il_jk(deformation_gradient, &IDENTITY)
120 - TensorRank4::dyad_ij_kl(&IDENTITY, deformation_gradient) * (TWO_THIRDS))
121 * scaled_dw_di1
122 + TensorRank4::dyad_ij_kl(
123 &(IDENTITY * (0.5 * self.bulk_modulus() * (jacobian + 1.0 / jacobian))
124 - left_cauchy_green_deformation.deviatoric() * (scaled_dw_di1 * FIVE_THIRDS)),
125 &inverse_transpose_deformation_gradient,
126 )
127 - (term_1 + term_2 - term_3) * self.extra_modulus() / jacobian
128 + extra_term_1)
129 }
130}
131
132impl Hyperelastic for Isihara {
133 #[doc = include_str!("helmholtz_free_energy_density.md")]
134 fn helmholtz_free_energy_density(
135 &self,
136 deformation_gradient: &DeformationGradient,
137 ) -> Result<Quantity<EnergyDensity>, ConstitutiveError> {
138 let jacobian = self.jacobian(deformation_gradient)?;
139 let isochoric_left_cauchy_green_deformation =
140 deformation_gradient.left_cauchy_green() / jacobian.powf(TWO_THIRDS);
141 let first_invariant = isochoric_left_cauchy_green_deformation.trace();
142 let second_invariant = isochoric_left_cauchy_green_deformation.second_invariant();
143 Ok(0.5
144 * ((self.shear_modulus() - self.extra_modulus()) * (first_invariant - 3.0)
145 + self.extra_modulus() * (second_invariant - 3.0)
146 + self.quadratic_modulus() * (first_invariant - 3.0).powi(2)
147 + self.bulk_modulus() * (0.5 * (jacobian.powi(2) - 1.0) - jacobian.ln())))
148 }
149}