conspire/constitutive/solid/hyperelastic/internal_variables/
mod.rs1use crate::{
4 constitutive::{
5 ConstitutiveError,
6 solid::elastic::{
7 AppliedLoad,
8 internal_variables::{ElasticIV, bcs},
9 },
10 },
11 math::{
12 Scalar, Tensor, TensorArray, TensorTuple,
13 optimize::{EqualityConstraint, FirstOrderOptimization, SecondOrderOptimization},
14 },
15 mechanics::{DeformationGradient, FirstPiolaKirchhoffTangentStiffness},
16};
17
18pub trait HyperelasticIV<V, T1, T2, T3>
20where
21 Self: ElasticIV<V, T1, T2, T3>,
22{
23 fn helmholtz_free_energy_density(
29 &self,
30 deformation_gradient: &DeformationGradient,
31 internal_variables: &V,
32 ) -> Result<Scalar, ConstitutiveError>;
33}
34
35pub trait FirstOrderMinimize<V, T1, T2, T3> {
37 type Variables;
39 fn minimize(
45 &self,
46 applied_load: AppliedLoad,
47 solver: impl FirstOrderOptimization<Scalar, Self::Variables>,
48 ) -> Result<(DeformationGradient, V), ConstitutiveError>;
49}
50
51pub trait SecondOrderMinimize<V, T1, T2, T3>
53where
54 T1: Tensor,
55 T2: Tensor,
56 T3: Tensor,
57 V: Tensor,
58{
59 type Variables;
61 fn minimize(
67 &self,
68 applied_load: AppliedLoad,
69 solver: impl SecondOrderOptimization<
70 Scalar,
71 Self::Variables,
72 TensorTuple<FirstPiolaKirchhoffTangentStiffness, TensorTuple<T1, TensorTuple<T2, T3>>>,
73 Self::Variables,
74 >,
75 ) -> Result<(DeformationGradient, V), ConstitutiveError>;
76}
77
78impl<T, V, T1, T2, T3> FirstOrderMinimize<V, T1, T2, T3> for T
79where
80 T: HyperelasticIV<V, T1, T2, T3>,
81 T1: Tensor,
82 T2: Tensor,
83 T3: Tensor,
84 T: ElasticIV<V, T1, T2, T3>,
85 V: Tensor,
86{
87 type Variables = TensorTuple<DeformationGradient, V>;
88 fn minimize(
89 &self,
90 applied_load: AppliedLoad,
91 solver: impl FirstOrderOptimization<Scalar, Self::Variables>,
92 ) -> Result<(DeformationGradient, V), ConstitutiveError> {
93 let (matrix, vector) = bcs(self, applied_load);
94 match solver.minimize(
95 |variables: &Self::Variables| {
96 let (deformation_gradient, internal_variables) = variables.into();
97 Ok(self.helmholtz_free_energy_density(deformation_gradient, internal_variables)?)
98 },
99 |variables: &Self::Variables| {
100 let (deformation_gradient, internal_variables) = variables.into();
101 Ok(TensorTuple::from((
102 self.first_piola_kirchhoff_stress(deformation_gradient, internal_variables)?,
103 self.internal_variables_residual(deformation_gradient, internal_variables)?,
104 )))
105 },
106 Self::Variables::from((
107 DeformationGradient::identity(),
108 self.internal_variables_initial(),
109 )),
110 EqualityConstraint::Linear(matrix, vector),
111 ) {
112 Ok(solution) => Ok(solution.into()),
113 Err(error) => Err(ConstitutiveError::Upstream(
114 format!("{error}"),
115 format!("{self:?}"),
116 )),
117 }
118 }
119}
120
121impl<T, V, T1, T2, T3> SecondOrderMinimize<V, T1, T2, T3> for T
122where
123 T1: Tensor,
124 T2: Tensor,
125 T3: Tensor,
126 T: HyperelasticIV<V, T1, T2, T3>,
127 V: Tensor,
128{
129 type Variables = TensorTuple<DeformationGradient, V>;
130 fn minimize(
131 &self,
132 applied_load: AppliedLoad,
133 solver: impl SecondOrderOptimization<
134 Scalar,
135 Self::Variables,
136 TensorTuple<FirstPiolaKirchhoffTangentStiffness, TensorTuple<T1, TensorTuple<T2, T3>>>,
137 Self::Variables,
138 >,
139 ) -> Result<(DeformationGradient, V), ConstitutiveError> {
140 let (matrix, vector) = bcs(self, applied_load);
141 match solver.minimize(
142 |variables: &Self::Variables| {
143 let (deformation_gradient, internal_variables) = variables.into();
144 Ok(self.helmholtz_free_energy_density(deformation_gradient, internal_variables)?)
145 },
146 |variables: &Self::Variables| {
147 let (deformation_gradient, internal_variables) = variables.into();
148 Ok(TensorTuple::from((
149 self.first_piola_kirchhoff_stress(deformation_gradient, internal_variables)?,
150 self.internal_variables_residual(deformation_gradient, internal_variables)?,
151 )))
152 },
153 |variables: &Self::Variables| {
154 let (deformation_gradient, internal_variables) = variables.into();
155 let tangent_0 = self.first_piola_kirchhoff_tangent_stiffness(
156 deformation_gradient,
157 internal_variables,
158 )?;
159 let (tangent_1, tangent_2, tangent_3) =
160 self.internal_variables_tangents(deformation_gradient, internal_variables)?;
161 Ok((tangent_0, (tangent_1, (tangent_2, tangent_3).into()).into()).into())
162 },
163 Self::Variables::from((
164 DeformationGradient::identity(),
165 self.internal_variables_initial(),
166 )),
167 EqualityConstraint::Linear(matrix, vector),
168 None,
169 ) {
170 Ok(solution) => Ok(solution.into()),
171 Err(error) => Err(ConstitutiveError::Upstream(
172 format!("{error}"),
173 format!("{self:?}"),
174 )),
175 }
176 }
177}