conspire/constitutive/hybrid/elastic/multiplicative/
mod.rs1#[cfg(test)]
2mod test;
3
4use crate::{
5 constitutive::{
6 ConstitutiveError,
7 hybrid::{Hybrid, Multiplicative, MultiplicativeTrait},
8 solid::{Solid, elastic::Elastic},
9 },
10 math::{
11 IDENTITY_10, Rank2, TensorRank2,
12 optimize::{EqualityConstraint, GradientDescent, ZerothOrderRootFinding},
13 },
14 mechanics::{
15 CauchyStress, CauchyTangentStiffness, DeformationGradient, FirstPiolaKirchhoffStress,
16 FirstPiolaKirchhoffTangentStiffness, Scalar, SecondPiolaKirchhoffStress,
17 SecondPiolaKirchhoffTangentStiffness,
18 },
19};
20use std::fmt::Debug;
21
22impl<C1, C2> Solid for Multiplicative<C1, C2>
23where
24 C1: Debug,
25 C2: Debug,
26{
27 fn bulk_modulus(&self) -> &Scalar {
29 panic!()
30 }
31 fn shear_modulus(&self) -> &Scalar {
33 panic!()
34 }
35}
36
37impl<C1, C2> Elastic for Multiplicative<C1, C2>
38where
39 C1: Elastic,
40 C2: Elastic,
41{
42 fn cauchy_stress(
48 &self,
49 deformation_gradient: &DeformationGradient,
50 ) -> Result<CauchyStress, ConstitutiveError> {
51 let (deformation_gradient_1, deformation_gradient_2) =
52 self.deformation_gradients(deformation_gradient)?;
53 Ok(self
54 .constitutive_model_1()
55 .cauchy_stress(&deformation_gradient_1)?
56 / deformation_gradient_2.determinant())
57 }
58 fn cauchy_tangent_stiffness(
60 &self,
61 _: &DeformationGradient,
62 ) -> Result<CauchyTangentStiffness, ConstitutiveError> {
63 panic!()
64 }
65 fn first_piola_kirchhoff_stress(
71 &self,
72 deformation_gradient: &DeformationGradient,
73 ) -> Result<FirstPiolaKirchhoffStress, ConstitutiveError> {
74 let (deformation_gradient_1, deformation_gradient_2) =
75 self.deformation_gradients(deformation_gradient)?;
76 let deformation_gradient_2_inverse_transpose: TensorRank2<3, 0, 0> =
77 deformation_gradient_2.inverse_transpose().into();
78 Ok(self
79 .constitutive_model_1()
80 .first_piola_kirchhoff_stress(&deformation_gradient_1)?
81 * deformation_gradient_2_inverse_transpose)
82 }
83 fn first_piola_kirchhoff_tangent_stiffness(
85 &self,
86 _: &DeformationGradient,
87 ) -> Result<FirstPiolaKirchhoffTangentStiffness, ConstitutiveError> {
88 panic!()
89 }
90 fn second_piola_kirchhoff_stress(
96 &self,
97 deformation_gradient: &DeformationGradient,
98 ) -> Result<SecondPiolaKirchhoffStress, ConstitutiveError> {
99 let (deformation_gradient_1, deformation_gradient_2) =
100 self.deformation_gradients(deformation_gradient)?;
101 let deformation_gradient_2_inverse: TensorRank2<3, 0, 0> =
102 deformation_gradient_2.inverse().into();
103 Ok(&deformation_gradient_2_inverse
104 * self
105 .constitutive_model_1()
106 .second_piola_kirchhoff_stress(&deformation_gradient_1)?
107 * deformation_gradient_2_inverse.transpose())
108 }
109 fn second_piola_kirchhoff_tangent_stiffness(
111 &self,
112 _: &DeformationGradient,
113 ) -> Result<SecondPiolaKirchhoffTangentStiffness, ConstitutiveError> {
114 panic!()
115 }
116}
117
118impl<C1, C2> MultiplicativeTrait for Multiplicative<C1, C2>
119where
120 C1: Elastic,
121 C2: Elastic,
122{
123 fn deformation_gradients(
124 &self,
125 deformation_gradient: &DeformationGradient,
126 ) -> Result<(DeformationGradient, DeformationGradient), ConstitutiveError> {
127 if deformation_gradient.is_identity() {
128 Ok((IDENTITY_10, IDENTITY_10))
129 } else {
130 match GradientDescent::default().root(
131 |deformation_gradient_2: &DeformationGradient| {
132 let deformation_gradient_1: DeformationGradient =
133 (deformation_gradient * deformation_gradient_2.inverse()).into();
134 let deformation_gradient_2_inverse_transpose: TensorRank2<3, 0, 0> =
135 deformation_gradient_2.inverse_transpose().into();
136 let right_hand_side: FirstPiolaKirchhoffStress = (deformation_gradient_1
137 .transpose()
138 * self
139 .constitutive_model_1()
140 .first_piola_kirchhoff_stress(&deformation_gradient_1)?
141 * deformation_gradient_2_inverse_transpose)
142 .into();
143 Ok(self
144 .constitutive_model_2()
145 .first_piola_kirchhoff_stress(deformation_gradient_2)?
146 - right_hand_side)
147 },
148 IDENTITY_10,
149 EqualityConstraint::None,
150 ) {
151 Ok(deformation_gradient_2) => {
152 let deformation_gradient_1 =
153 (deformation_gradient * deformation_gradient_2.inverse()).into();
154 Ok((deformation_gradient_1, deformation_gradient_2))
155 }
156 Err(error) => Err(ConstitutiveError::Upstream(
157 format!("{error}"),
158 format!("{self:?}"),
159 )),
160 }
161 }
162 }
163}