conspire/constitutive/solid/hyperelastic/internal_variables/
mod.rs1use crate::{
4 constitutive::{
5 ConstitutiveError,
6 solid::elastic::{
7 AppliedLoad,
8 internal_variables::{ElasticIV, bcs, bcs_block},
9 },
10 },
11 math::{
12 Quantity, Tensor, TensorArray, TensorTuple,
13 optimize::{
14 EqualityConstraint, FirstOrderOptimization, SecondOrderOptimizationBlock, SolveStrategy,
15 },
16 },
17 mechanics::{
18 DeformationGradient, FirstPiolaKirchhoffStress, FirstPiolaKirchhoffTangentStiffness,
19 },
20 units::EnergyDensity,
21};
22
23pub trait HyperelasticIV<V>
25where
26 Self: ElasticIV<V>,
27{
28 fn helmholtz_free_energy_density(
34 &self,
35 deformation_gradient: &DeformationGradient,
36 internal_variables: &V,
37 ) -> Result<Quantity<EnergyDensity>, ConstitutiveError>;
38}
39
40pub trait FirstOrderMinimize<V> {
42 type Residuals;
44 type Variables;
46 fn minimize(
52 &self,
53 applied_load: AppliedLoad,
54 solver: impl FirstOrderOptimization<Quantity<EnergyDensity>, Self::Residuals, Self::Variables>,
55 ) -> Result<(DeformationGradient, V), ConstitutiveError>;
56}
57
58pub trait SecondOrderMinimize<V>
60where
61 Self: ElasticIV<V>,
62 V: Tensor,
63{
64 fn minimize(
70 &self,
71 applied_load: AppliedLoad,
72 solver: impl SecondOrderOptimizationBlock<
73 Quantity<EnergyDensity>,
74 DeformationGradient,
75 V,
76 FirstPiolaKirchhoffStress,
77 <Self as ElasticIV<V>>::Residual,
78 FirstPiolaKirchhoffTangentStiffness,
79 Self::TangentVu,
80 Self::TangentUv,
81 Self::TangentVv,
82 >,
83 strategy: SolveStrategy,
84 ) -> Result<(DeformationGradient, V), ConstitutiveError>;
85}
86
87impl<T, V> FirstOrderMinimize<V> for T
88where
89 T: HyperelasticIV<V>,
90 T: ElasticIV<V>,
91 V: Tensor,
92{
93 type Residuals = TensorTuple<FirstPiolaKirchhoffStress, <T as ElasticIV<V>>::Residual>;
94 type Variables = TensorTuple<DeformationGradient, V>;
95 fn minimize(
96 &self,
97 applied_load: AppliedLoad,
98 solver: impl FirstOrderOptimization<Quantity<EnergyDensity>, Self::Residuals, Self::Variables>,
99 ) -> Result<(DeformationGradient, V), ConstitutiveError> {
100 let (matrix, vector) = bcs(self, applied_load);
101 match solver.minimize(
102 |variables: &Self::Variables| {
103 let (deformation_gradient, internal_variables) = variables.into();
104 Ok(self.helmholtz_free_energy_density(deformation_gradient, internal_variables)?)
105 },
106 |variables: &Self::Variables| {
107 let (deformation_gradient, internal_variables) = variables.into();
108 Ok(TensorTuple::from((
109 self.first_piola_kirchhoff_stress(deformation_gradient, internal_variables)?,
110 self.internal_variables_residual(deformation_gradient, internal_variables)?,
111 )))
112 },
113 Self::Variables::from((
114 DeformationGradient::identity(),
115 self.internal_variables_initial(),
116 )),
117 EqualityConstraint::Linear(matrix, vector),
118 ) {
119 Ok(solution) => Ok(solution.into()),
120 Err(error) => Err(ConstitutiveError::Upstream(
121 format!("{error}"),
122 format!("{self:?}"),
123 )),
124 }
125 }
126}
127
128impl<T, V> SecondOrderMinimize<V> for T
129where
130 T: HyperelasticIV<V>,
131 V: Tensor,
132{
133 fn minimize(
134 &self,
135 applied_load: AppliedLoad,
136 solver: impl SecondOrderOptimizationBlock<
137 Quantity<EnergyDensity>,
138 DeformationGradient,
139 V,
140 FirstPiolaKirchhoffStress,
141 <Self as ElasticIV<V>>::Residual,
142 FirstPiolaKirchhoffTangentStiffness,
143 Self::TangentVu,
144 Self::TangentUv,
145 Self::TangentVv,
146 >,
147 strategy: SolveStrategy,
148 ) -> Result<(DeformationGradient, V), ConstitutiveError> {
149 let (constraint_external, constraint_internal) = bcs_block(self, applied_load);
150 match solver.minimize_block(
151 |deformation_gradient: &DeformationGradient, internal_variables: &V| {
152 Ok(self.helmholtz_free_energy_density(deformation_gradient, internal_variables)?)
153 },
154 |deformation_gradient: &DeformationGradient, internal_variables: &V| {
155 Ok(self.first_piola_kirchhoff_stress(deformation_gradient, internal_variables)?)
156 },
157 |deformation_gradient: &DeformationGradient, internal_variables: &V| {
158 Ok(self.internal_variables_residual(deformation_gradient, internal_variables)?)
159 },
160 |deformation_gradient: &DeformationGradient, internal_variables: &V| {
161 Ok(self.tangents(deformation_gradient, internal_variables)?)
162 },
163 (
164 DeformationGradient::identity(),
165 self.internal_variables_initial(),
166 ),
167 constraint_external,
168 constraint_internal,
169 None,
170 strategy,
171 ) {
172 Ok(solution) => Ok(solution),
173 Err(error) => Err(ConstitutiveError::Upstream(
174 format!("{error}"),
175 format!("{self:?}"),
176 )),
177 }
178 }
179}