conspire/constitutive/hybrid/elastic/multiplicative/
mod.rs1#[cfg(test)]
2mod test;
3
4use crate::{
5 ABS_TOL,
6 constitutive::{
7 ConstitutiveError,
8 hybrid::{Hybrid, Multiplicative, MultiplicativeTrait},
9 solid::{Solid, elastic::Elastic},
10 },
11 math::{IDENTITY_10, Rank2, Tensor, TensorRank2, ZERO_10},
12 mechanics::{
13 CauchyStress, CauchyTangentStiffness, DeformationGradient, FirstPiolaKirchhoffStress,
14 FirstPiolaKirchhoffTangentStiffness, Scalar, SecondPiolaKirchhoffStress,
15 SecondPiolaKirchhoffTangentStiffness,
16 },
17};
18
19impl<C1, C2> Solid for Multiplicative<C1, C2> {
20 fn bulk_modulus(&self) -> &Scalar {
22 panic!()
23 }
24 fn shear_modulus(&self) -> &Scalar {
26 panic!()
27 }
28}
29
30impl<C1, C2> Elastic for Multiplicative<C1, C2>
31where
32 C1: Elastic,
33 C2: Elastic,
34{
35 fn cauchy_stress(
41 &self,
42 deformation_gradient: &DeformationGradient,
43 ) -> Result<CauchyStress, ConstitutiveError> {
44 let (deformation_gradient_1, deformation_gradient_2) =
45 self.deformation_gradients(deformation_gradient)?;
46 Ok(self
47 .constitutive_model_1()
48 .cauchy_stress(&deformation_gradient_1)?
49 / deformation_gradient_2.determinant())
50 }
51 fn cauchy_tangent_stiffness(
53 &self,
54 _: &DeformationGradient,
55 ) -> Result<CauchyTangentStiffness, ConstitutiveError> {
56 panic!()
57 }
58 fn first_piola_kirchhoff_stress(
64 &self,
65 deformation_gradient: &DeformationGradient,
66 ) -> Result<FirstPiolaKirchhoffStress, ConstitutiveError> {
67 let (deformation_gradient_1, deformation_gradient_2) =
68 self.deformation_gradients(deformation_gradient)?;
69 let deformation_gradient_2_inverse_transpose: TensorRank2<3, 0, 0> =
70 deformation_gradient_2.inverse_transpose().into();
71 Ok(self
72 .constitutive_model_1()
73 .first_piola_kirchhoff_stress(&deformation_gradient_1)?
74 * deformation_gradient_2_inverse_transpose)
75 }
76 fn first_piola_kirchhoff_tangent_stiffness(
78 &self,
79 _: &DeformationGradient,
80 ) -> Result<FirstPiolaKirchhoffTangentStiffness, ConstitutiveError> {
81 panic!()
82 }
83 fn second_piola_kirchhoff_stress(
89 &self,
90 deformation_gradient: &DeformationGradient,
91 ) -> Result<SecondPiolaKirchhoffStress, ConstitutiveError> {
92 let (deformation_gradient_1, deformation_gradient_2) =
93 self.deformation_gradients(deformation_gradient)?;
94 let deformation_gradient_2_inverse: TensorRank2<3, 0, 0> =
95 deformation_gradient_2.inverse().into();
96 Ok(&deformation_gradient_2_inverse
97 * self
98 .constitutive_model_1()
99 .second_piola_kirchhoff_stress(&deformation_gradient_1)?
100 * deformation_gradient_2_inverse.transpose())
101 }
102 fn second_piola_kirchhoff_tangent_stiffness(
104 &self,
105 _: &DeformationGradient,
106 ) -> Result<SecondPiolaKirchhoffTangentStiffness, ConstitutiveError> {
107 panic!()
108 }
109}
110
111impl<C1, C2> MultiplicativeTrait for Multiplicative<C1, C2>
112where
113 C1: Elastic,
114 C2: Elastic,
115{
116 fn deformation_gradients(
117 &self,
118 deformation_gradient: &DeformationGradient,
119 ) -> Result<(DeformationGradient, DeformationGradient), ConstitutiveError> {
120 if deformation_gradient.is_identity() {
121 Ok((IDENTITY_10, IDENTITY_10))
122 } else {
123 let mut deformation_gradient_1 = IDENTITY_10;
124 let mut deformation_gradient_2 = deformation_gradient.clone();
125 let mut deformation_gradient_2_old = IDENTITY_10;
126 let mut deformation_gradient_2_inverse_transpose: TensorRank2<3, 0, 0>;
127 let mut residual: FirstPiolaKirchhoffStress;
128 let mut residual_increment: FirstPiolaKirchhoffStress;
129 let mut residual_norm = 1.0;
130 let mut residual_old = ZERO_10;
131 let mut right_hand_side: FirstPiolaKirchhoffStress;
132 let mut steps: u8 = 0;
133 let steps_maximum: u8 = 50;
134 let mut step_size: Scalar;
135 while steps < steps_maximum {
136 deformation_gradient_1 =
137 (deformation_gradient * deformation_gradient_2.inverse()).into();
138 deformation_gradient_2_inverse_transpose =
139 deformation_gradient_2.inverse_transpose().into();
140 right_hand_side = (deformation_gradient_1.transpose()
141 * self
142 .constitutive_model_1()
143 .first_piola_kirchhoff_stress(&deformation_gradient_1)?
144 * deformation_gradient_2_inverse_transpose)
145 .into();
146 residual = self
147 .constitutive_model_2()
148 .first_piola_kirchhoff_stress(&deformation_gradient_2)?
149 - right_hand_side;
150 residual_norm = residual.norm();
151 if residual_norm >= ABS_TOL {
152 residual_increment = residual_old - &residual;
153 step_size = (deformation_gradient_2_old - &deformation_gradient_2)
154 .full_contraction(&residual_increment)
155 .abs()
156 / residual_increment.norm_squared();
157 deformation_gradient_2_old = deformation_gradient_2.clone();
158 residual_old = residual.clone();
159 deformation_gradient_2 -= residual * step_size;
160 } else {
161 break;
162 }
163 steps += 1;
164 }
165 if residual_norm >= ABS_TOL && steps == steps_maximum {
166 panic!("MAX STEPS REACHED")
167 } else {
168 Ok((deformation_gradient_1, deformation_gradient_2))
169 }
170 }
171 }
172}