Skip to main content

conspire/constitutive/solid/hyperelastic/blatz_ko/
mod.rs

1#[cfg(test)]
2mod test;
3
4use crate::{
5    constitutive::{
6        ConstitutiveError,
7        solid::{Solid, elastic::Elastic, hyperelastic::Hyperelastic},
8    },
9    math::{IDENTITY, Quantity, Rank2, TensorRank4},
10    mechanics::{CauchyStress, CauchyTangentStiffness, Deformation, DeformationGradient, Scalar},
11    units::{EnergyDensity, Stress},
12};
13
14#[doc = include_str!("doc.md")]
15#[derive(Clone, Debug)]
16pub struct BlatzKo {
17    /// The bulk modulus $`\kappa`$.
18    pub bulk_modulus: Quantity<Stress>,
19    /// The shear modulus $`\mu`$.
20    pub shear_modulus: Quantity<Stress>,
21    /// The mixing parameter $`f`$.
22    pub mixing_parameter: Scalar,
23}
24
25impl BlatzKo {
26    /// Returns the mixing parameter.
27    pub fn mixing_parameter(&self) -> Scalar {
28        self.mixing_parameter
29    }
30    fn n(&self) -> Scalar {
31        0.5 * self.bulk_modulus().value() / self.shear_modulus().value() - 1.0 / 3.0
32    }
33}
34
35impl Solid for BlatzKo {
36    fn bulk_modulus(&self) -> Quantity<Stress> {
37        self.bulk_modulus
38    }
39    fn shear_modulus(&self) -> Quantity<Stress> {
40        self.shear_modulus
41    }
42}
43
44impl Elastic for BlatzKo {
45    #[doc = include_str!("cauchy_stress.md")]
46    fn cauchy_stress(
47        &self,
48        deformation_gradient: &DeformationGradient,
49    ) -> Result<CauchyStress, ConstitutiveError> {
50        let jacobian = self.jacobian(deformation_gradient)?;
51        let n = self.n();
52        let f = self.mixing_parameter();
53        let left_cauchy_green_deformation = deformation_gradient.left_cauchy_green();
54        let inverse_left_cauchy_green_deformation = left_cauchy_green_deformation.inverse();
55        let k = (1.0 - f) * jacobian.powf(2.0 * n) - f * jacobian.powf(-2.0 * n);
56        Ok(
57            (left_cauchy_green_deformation * f - inverse_left_cauchy_green_deformation * (1.0 - f)
58                + IDENTITY * k)
59                * (self.shear_modulus() / jacobian),
60        )
61    }
62    #[doc = include_str!("cauchy_tangent_stiffness.md")]
63    fn cauchy_tangent_stiffness(
64        &self,
65        deformation_gradient: &DeformationGradient,
66    ) -> Result<CauchyTangentStiffness, ConstitutiveError> {
67        let jacobian = self.jacobian(deformation_gradient)?;
68        let inverse_transpose_deformation_gradient = deformation_gradient.inverse_transpose();
69        let n = self.n();
70        let f = self.mixing_parameter();
71        let left_cauchy_green_deformation = deformation_gradient.left_cauchy_green();
72        let inverse_left_cauchy_green_deformation = left_cauchy_green_deformation.inverse();
73        let jacobian_pos = jacobian.powf(2.0 * n);
74        let jacobian_neg = jacobian.powf(-2.0 * n);
75        let k = (1.0 - f) * jacobian_pos - f * jacobian_neg;
76        let k_prime = 2.0 * n * ((1.0 - f) * jacobian_pos + f * jacobian_neg);
77        let shear_modulus_over_jacobian = self.shear_modulus() / jacobian;
78        Ok(((TensorRank4::dyad_ik_jl(&IDENTITY, deformation_gradient)
79            + TensorRank4::dyad_il_jk(deformation_gradient, &IDENTITY)
80            - TensorRank4::dyad_ij_kl(
81                &left_cauchy_green_deformation,
82                &inverse_transpose_deformation_gradient,
83            ))
84            * f
85            + (TensorRank4::dyad_ik_jl(
86                &inverse_left_cauchy_green_deformation,
87                &inverse_transpose_deformation_gradient,
88            ) + TensorRank4::dyad_il_jk(
89                &inverse_transpose_deformation_gradient,
90                &inverse_left_cauchy_green_deformation,
91            ) + TensorRank4::dyad_ij_kl(
92                &inverse_left_cauchy_green_deformation,
93                &inverse_transpose_deformation_gradient,
94            )) * (1.0 - f)
95            + TensorRank4::dyad_ij_kl(&IDENTITY, &inverse_transpose_deformation_gradient)
96                * (k_prime - k))
97            * shear_modulus_over_jacobian)
98    }
99}
100
101impl Hyperelastic for BlatzKo {
102    #[doc = include_str!("helmholtz_free_energy_density.md")]
103    fn helmholtz_free_energy_density(
104        &self,
105        deformation_gradient: &DeformationGradient,
106    ) -> Result<Quantity<EnergyDensity>, ConstitutiveError> {
107        let jacobian = self.jacobian(deformation_gradient)?;
108        let n = self.n();
109        let f = self.mixing_parameter();
110        let left_cauchy_green_deformation = deformation_gradient.left_cauchy_green();
111        let first_invariant = left_cauchy_green_deformation.trace();
112        let second_invariant = left_cauchy_green_deformation.second_invariant();
113        let third_invariant = jacobian.powi(2);
114        Ok(0.5
115            * self.shear_modulus()
116            * (f * (first_invariant - 3.0 + (third_invariant.powf(-n) - 1.0) / n)
117                + (1.0 - f)
118                    * (second_invariant / third_invariant - 3.0
119                        + (third_invariant.powf(n) - 1.0) / n)))
120    }
121}