conspire/domain/fem/solid/hyperelastic_viscoplastic/
mod.rs1use crate::{
2 fem::{
3 Blocks, ElasticViscoplasticAndElastic, ElementModel, ElementModelError, Elements, Model,
4 NodalCoordinates, NodalCoordinatesHistory,
5 block::{
6 band_from_neighbors, finalize_node_neighbors,
7 solid::elastic_viscoplastic::ElasticViscoplasticBCs,
8 },
9 solid::{
10 NodalForcesSolid, NodalStiffnessesSolid,
11 elastic_viscoplastic::ElasticViscoplasticElements, hyperelastic::HyperelasticElements,
12 },
13 },
14 math::{
15 Scalar, Tensor, TensorTuple, TensorVec,
16 integrate::{ExplicitDaeSecondOrderMinimize, IntegrationError},
17 optimize::SecondOrderOptimization,
18 },
19 mechanics::Times,
20};
21
22pub trait HyperelasticViscoplasticElements<S, const D: usize>
23where
24 Self: ElasticViscoplasticElements<S, D>,
25{
26 fn helmholtz_free_energy(
27 &self,
28 nodal_coordinates: &NodalCoordinates<D>,
29 state_variables: &S,
30 ) -> Result<Scalar, ElementModelError>;
31}
32
33impl<B, S, const D: usize> HyperelasticViscoplasticElements<S, D> for Model<B, D>
34where
35 B: HyperelasticViscoplasticElements<S, D>,
36{
37 fn helmholtz_free_energy(
38 &self,
39 nodal_coordinates: &NodalCoordinates<D>,
40 state_variables: &S,
41 ) -> Result<Scalar, ElementModelError> {
42 self.blocks
43 .helmholtz_free_energy(nodal_coordinates, state_variables)
44 }
45}
46
47impl<B1, B2, S, const D: usize> HyperelasticViscoplasticElements<S, D>
48 for ElasticViscoplasticAndElastic<B1, B2>
49where
50 B1: HyperelasticViscoplasticElements<S, D>,
51 B2: HyperelasticElements<D>,
52{
53 fn helmholtz_free_energy(
54 &self,
55 nodal_coordinates: &NodalCoordinates<D>,
56 state_variables: &S,
57 ) -> Result<Scalar, ElementModelError> {
58 Ok(self
59 .0
60 .helmholtz_free_energy(nodal_coordinates, state_variables)?
61 + self.1.helmholtz_free_energy(nodal_coordinates)?)
62 }
63}
64
65impl<B1, B2, S1, S2, const D: usize> HyperelasticViscoplasticElements<TensorTuple<S1, S2>, D>
66 for Blocks<B1, B2>
67where
68 B1: HyperelasticViscoplasticElements<S1, D>,
69 B2: HyperelasticViscoplasticElements<S2, D>,
70 S1: Tensor,
71 S2: Tensor,
72{
73 fn helmholtz_free_energy(
74 &self,
75 nodal_coordinates: &NodalCoordinates<D>,
76 state_variables: &TensorTuple<S1, S2>,
77 ) -> Result<Scalar, ElementModelError> {
78 Ok(self
79 .0
80 .helmholtz_free_energy(nodal_coordinates, &state_variables.0)?
81 + self
82 .1
83 .helmholtz_free_energy(nodal_coordinates, &state_variables.1)?)
84 }
85}
86
87pub trait SecondOrderMinimize<S, H, const D: usize>
88where
89 S: Tensor,
90 H: TensorVec<Item = S>,
91{
92 fn minimize(
93 &self,
94 integrator: impl ExplicitDaeSecondOrderMinimize<
95 Scalar,
96 NodalForcesSolid<D>,
97 NodalStiffnessesSolid<D>,
98 S,
99 NodalCoordinates<D>,
100 H,
101 NodalCoordinatesHistory<D>,
102 >,
103 solver: impl SecondOrderOptimization<
104 Scalar,
105 NodalForcesSolid<D>,
106 NodalStiffnessesSolid<D>,
107 NodalCoordinates<D>,
108 >,
109 time: &[Scalar],
110 bcs: ElasticViscoplasticBCs,
111 ) -> Result<(Times, NodalCoordinatesHistory<D>, H), IntegrationError>;
112}
113
114impl<B, S, H, const D: usize> SecondOrderMinimize<S, H, D> for Model<B, D>
115where
116 B: HyperelasticViscoplasticElements<S, D>,
117 S: Tensor,
118 H: TensorVec<Item = S>,
119{
120 fn minimize(
121 &self,
122 integrator: impl ExplicitDaeSecondOrderMinimize<
123 Scalar,
124 NodalForcesSolid<D>,
125 NodalStiffnessesSolid<D>,
126 S,
127 NodalCoordinates<D>,
128 H,
129 NodalCoordinatesHistory<D>,
130 >,
131 solver: impl SecondOrderOptimization<
132 Scalar,
133 NodalForcesSolid<D>,
134 NodalStiffnessesSolid<D>,
135 NodalCoordinates<D>,
136 >,
137 time: &[Scalar],
138 bcs: ElasticViscoplasticBCs,
139 ) -> Result<(Times, NodalCoordinatesHistory<D>, H), IntegrationError> {
140 let mut neighbors = vec![Vec::new(); self.coordinates().len()];
141 self.node_neighbors(&mut neighbors);
142 finalize_node_neighbors(&mut neighbors);
143 let banded = band_from_neighbors(&neighbors, &bcs(time[0]), D);
144 let (time_history, state_variables_history, _, nodal_coordinates_history) = integrator
145 .integrate(
146 |_: Scalar, state_variables: &S, nodal_coordinates: &NodalCoordinates<D>| {
147 Ok(self
148 .blocks
149 .state_variables_evolution(nodal_coordinates, state_variables)?)
150 },
151 |_: Scalar, state_variables: &S, nodal_coordinates: &NodalCoordinates<D>| {
152 Ok(self
153 .blocks
154 .helmholtz_free_energy(nodal_coordinates, state_variables)?)
155 },
156 |_: Scalar, state_variables: &S, nodal_coordinates: &NodalCoordinates<D>| {
157 Ok(self
158 .blocks
159 .nodal_forces(nodal_coordinates, state_variables)?)
160 },
161 |_: Scalar, state_variables: &S, nodal_coordinates: &NodalCoordinates<D>| {
162 Ok(self
163 .blocks
164 .nodal_stiffnesses(nodal_coordinates, state_variables)?)
165 },
166 solver,
167 time,
168 (
169 self.blocks.initial_state(),
170 self.coordinates().clone().into(),
171 ),
172 bcs,
173 Some(banded),
174 )?;
175 Ok((
176 time_history,
177 nodal_coordinates_history,
178 state_variables_history,
179 ))
180 }
181}