conspire/constitutive/solid/hyperelastic/arruda_boyce/
mod.rs1#[cfg(test)]
2mod test;
3
4use super::*;
5use crate::math::special::{inverse_langevin, langevin_derivative};
6
7#[doc = include_str!("model.md")]
8#[derive(Debug)]
9pub struct ArrudaBoyce<P> {
10 parameters: P,
11}
12
13impl<P> ArrudaBoyce<P>
14where
15 P: Parameters,
16{
17 pub fn number_of_links(&self) -> &Scalar {
19 self.parameters.get(2)
20 }
21}
22
23impl<P> Constitutive<P> for ArrudaBoyce<P>
24where
25 P: Parameters,
26{
27 fn new(parameters: P) -> Self {
28 Self { parameters }
29 }
30}
31
32impl<P> Solid for ArrudaBoyce<P>
33where
34 P: Parameters,
35{
36 fn bulk_modulus(&self) -> &Scalar {
37 self.parameters.get(0)
38 }
39 fn shear_modulus(&self) -> &Scalar {
40 self.parameters.get(1)
41 }
42}
43
44impl<P> Elastic for ArrudaBoyce<P>
45where
46 P: Parameters,
47{
48 #[doc = include_str!("cauchy_stress.md")]
49 fn cauchy_stress(
50 &self,
51 deformation_gradient: &DeformationGradient,
52 ) -> Result<CauchyStress, ConstitutiveError> {
53 let jacobian = self.jacobian(deformation_gradient)?;
54 let (
55 deviatoric_isochoric_left_cauchy_green_deformation,
56 isochoric_left_cauchy_green_deformation_trace,
57 ) = (deformation_gradient.left_cauchy_green() / jacobian.powf(TWO_THIRDS))
58 .deviatoric_and_trace();
59 let gamma =
60 (isochoric_left_cauchy_green_deformation_trace / 3.0 / self.number_of_links()).sqrt();
61 if gamma >= 1.0 {
62 Err(ConstitutiveError::Custom(
63 "Maximum extensibility reached.".to_string(),
64 deformation_gradient.clone(),
65 format!("{:?}", &self),
66 ))
67 } else {
68 let gamma_0 = (1.0 / self.number_of_links()).sqrt();
69 Ok(deviatoric_isochoric_left_cauchy_green_deformation
70 * (self.shear_modulus() * inverse_langevin(gamma) / inverse_langevin(gamma_0)
71 * gamma_0
72 / gamma
73 / jacobian)
74 + IDENTITY * self.bulk_modulus() * 0.5 * (jacobian - 1.0 / jacobian))
75 }
76 }
77 #[doc = include_str!("cauchy_tangent_stiffness.md")]
78 fn cauchy_tangent_stiffness(
79 &self,
80 deformation_gradient: &DeformationGradient,
81 ) -> Result<CauchyTangentStiffness, ConstitutiveError> {
82 let jacobian = self.jacobian(deformation_gradient)?;
83 let inverse_transpose_deformation_gradient = deformation_gradient.inverse_transpose();
84 let left_cauchy_green_deformation = deformation_gradient.left_cauchy_green();
85 let deviatoric_left_cauchy_green_deformation = left_cauchy_green_deformation.deviatoric();
86 let (
87 deviatoric_isochoric_left_cauchy_green_deformation,
88 isochoric_left_cauchy_green_deformation_trace,
89 ) = (left_cauchy_green_deformation / jacobian.powf(TWO_THIRDS)).deviatoric_and_trace();
90 let gamma =
91 (isochoric_left_cauchy_green_deformation_trace / 3.0 / self.number_of_links()).sqrt();
92 if gamma >= 1.0 {
93 Err(ConstitutiveError::Custom(
94 "Maximum extensibility reached.".to_string(),
95 deformation_gradient.clone(),
96 format!("{:?}", &self),
97 ))
98 } else {
99 let gamma_0 = (1.0 / self.number_of_links()).sqrt();
100 let eta = inverse_langevin(gamma);
101 let scaled_shear_modulus =
102 gamma_0 / inverse_langevin(gamma_0) * self.shear_modulus() * eta
103 / gamma
104 / jacobian.powf(FIVE_THIRDS);
105 let scaled_deviatoric_isochoric_left_cauchy_green_deformation =
106 deviatoric_left_cauchy_green_deformation * scaled_shear_modulus;
107 let term = CauchyTangentStiffness::dyad_ij_kl(
108 &scaled_deviatoric_isochoric_left_cauchy_green_deformation,
109 &(deviatoric_isochoric_left_cauchy_green_deformation
110 * &inverse_transpose_deformation_gradient
111 * ((1.0 / eta / langevin_derivative(eta) - 1.0 / gamma)
112 / 3.0
113 / self.number_of_links()
114 / gamma)),
115 );
116 Ok(
117 (CauchyTangentStiffness::dyad_ik_jl(&IDENTITY, deformation_gradient)
118 + CauchyTangentStiffness::dyad_il_jk(deformation_gradient, &IDENTITY)
119 - CauchyTangentStiffness::dyad_ij_kl(&IDENTITY, deformation_gradient)
120 * (TWO_THIRDS))
121 * scaled_shear_modulus
122 + CauchyTangentStiffness::dyad_ij_kl(
123 &(IDENTITY * (0.5 * self.bulk_modulus() * (jacobian + 1.0 / jacobian))
124 - scaled_deviatoric_isochoric_left_cauchy_green_deformation
125 * (FIVE_THIRDS)),
126 &inverse_transpose_deformation_gradient,
127 )
128 + term,
129 )
130 }
131 }
132}
133
134impl<P> Hyperelastic for ArrudaBoyce<P>
135where
136 P: Parameters,
137{
138 #[doc = include_str!("helmholtz_free_energy_density.md")]
139 fn helmholtz_free_energy_density(
140 &self,
141 deformation_gradient: &DeformationGradient,
142 ) -> Result<Scalar, ConstitutiveError> {
143 let jacobian = self.jacobian(deformation_gradient)?;
144 let isochoric_left_cauchy_green_deformation =
145 deformation_gradient.left_cauchy_green() / jacobian.powf(TWO_THIRDS);
146 let gamma =
147 (isochoric_left_cauchy_green_deformation.trace() / 3.0 / self.number_of_links()).sqrt();
148 if gamma >= 1.0 {
149 Err(ConstitutiveError::Custom(
150 "Maximum extensibility reached.".to_string(),
151 deformation_gradient.clone(),
152 format!("{:?}", &self),
153 ))
154 } else {
155 let eta = inverse_langevin(gamma);
156 let gamma_0 = (1.0 / self.number_of_links()).sqrt();
157 let eta_0 = inverse_langevin(gamma_0);
158 Ok(3.0 * gamma_0 / eta_0
159 * self.shear_modulus()
160 * self.number_of_links()
161 * (gamma * eta
162 - gamma_0 * eta_0
163 - (eta_0 * eta.sinh() / (eta * eta_0.sinh())).ln())
164 + 0.5 * self.bulk_modulus() * (0.5 * (jacobian.powi(2) - 1.0) - jacobian.ln()))
165 }
166 }
167}