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 let solution = solver
102 .minimize(
103 |variables: &Self::Variables| {
104 let (deformation_gradient, internal_variables) = variables.into();
105 Ok(self
106 .helmholtz_free_energy_density(deformation_gradient, internal_variables)?)
107 },
108 |variables: &Self::Variables| {
109 let (deformation_gradient, internal_variables) = variables.into();
110 Ok(TensorTuple::from((
111 self.first_piola_kirchhoff_stress(
112 deformation_gradient,
113 internal_variables,
114 )?,
115 self.internal_variables_residual(deformation_gradient, internal_variables)?,
116 )))
117 },
118 Self::Variables::from((
119 DeformationGradient::identity(),
120 self.internal_variables_initial(),
121 )),
122 EqualityConstraint::Linear(matrix, vector),
123 )
124 .map_err(|error| ConstitutiveError::upstream(error, self))?;
125 Ok(solution.into())
126 }
127}
128
129impl<T, V> SecondOrderMinimize<V> for T
130where
131 T: HyperelasticIV<V>,
132 V: Tensor,
133{
134 fn minimize(
135 &self,
136 applied_load: AppliedLoad,
137 solver: impl SecondOrderOptimizationBlock<
138 Quantity<EnergyDensity>,
139 DeformationGradient,
140 V,
141 FirstPiolaKirchhoffStress,
142 <Self as ElasticIV<V>>::Residual,
143 FirstPiolaKirchhoffTangentStiffness,
144 Self::TangentVu,
145 Self::TangentUv,
146 Self::TangentVv,
147 >,
148 strategy: SolveStrategy,
149 ) -> Result<(DeformationGradient, V), ConstitutiveError> {
150 let (constraint_external, constraint_internal) = bcs_block(self, applied_load);
151 solver
152 .minimize_block(
153 |deformation_gradient: &DeformationGradient, internal_variables: &V| {
154 Ok(self
155 .helmholtz_free_energy_density(deformation_gradient, internal_variables)?)
156 },
157 |deformation_gradient: &DeformationGradient, internal_variables: &V| {
158 Ok(self
159 .first_piola_kirchhoff_stress(deformation_gradient, internal_variables)?)
160 },
161 |deformation_gradient: &DeformationGradient, internal_variables: &V| {
162 Ok(self.internal_variables_residual(deformation_gradient, internal_variables)?)
163 },
164 |deformation_gradient: &DeformationGradient, internal_variables: &V| {
165 Ok(self.tangents(deformation_gradient, internal_variables)?)
166 },
167 (
168 DeformationGradient::identity(),
169 self.internal_variables_initial(),
170 ),
171 constraint_external,
172 constraint_internal,
173 None,
174 strategy,
175 )
176 .map_err(|error| ConstitutiveError::upstream(error, self))
177 }
178}