1use crate::{
2 fem::{
3 Blocks, ElasticViscoplasticAndElastic, ElementModel, ElementModelError, Elements, Model,
4 NodalCoordinates, NodalCoordinatesHistory,
5 block::solid::elastic_viscoplastic::ElasticViscoplasticBCs,
6 solid::{NodalForcesSolid, NodalStiffnessesSolid, elastic::ElasticElements},
7 },
8 math::{
9 Derivative, Differentiate, Quantity, Tensor, TensorTuple, TensorVec,
10 integrate::{ExplicitDaeFirstOrderRoot, IntegrationError},
11 optimize::FirstOrderRootFinding,
12 },
13 mechanics::Times,
14 units::Time,
15};
16
17pub trait ElasticViscoplasticElements<S, const D: usize>
18where
19 Self: Elements,
20 S: Differentiate,
21{
22 fn initial_state(&self) -> S;
23 fn nodal_forces_into(
24 &self,
25 nodal_coordinates: &NodalCoordinates<D>,
26 state_variables: &S,
27 nodal_forces: &mut NodalForcesSolid<D>,
28 ) -> Result<(), ElementModelError>;
29 fn nodal_forces(
30 &self,
31 nodal_coordinates: &NodalCoordinates<D>,
32 state_variables: &S,
33 ) -> Result<NodalForcesSolid<D>, ElementModelError> {
34 let mut nodal_forces = NodalForcesSolid::zero(nodal_coordinates.len());
35 self.nodal_forces_into(nodal_coordinates, state_variables, &mut nodal_forces)?;
36 Ok(nodal_forces)
37 }
38 fn nodal_stiffnesses_into(
39 &self,
40 nodal_coordinates: &NodalCoordinates<D>,
41 state_variables: &S,
42 nodal_stiffnesses: &mut NodalStiffnessesSolid<D>,
43 ) -> Result<(), ElementModelError>;
44 fn nodal_stiffnesses(
45 &self,
46 nodal_coordinates: &NodalCoordinates<D>,
47 state_variables: &S,
48 ) -> Result<NodalStiffnessesSolid<D>, ElementModelError> {
49 let mut nodal_stiffnesses = NodalStiffnessesSolid::zero(nodal_coordinates.len());
50 self.nodal_stiffnesses_into(nodal_coordinates, state_variables, &mut nodal_stiffnesses)?;
51 Ok(nodal_stiffnesses)
52 }
53 fn state_variables_evolution(
54 &self,
55 nodal_coordinates: &NodalCoordinates<D>,
56 state_variables: &S,
57 ) -> Result<Derivative<S>, ElementModelError>;
58}
59
60impl<B, S, const D: usize> ElasticViscoplasticElements<S, D> for Model<B, D>
61where
62 B: ElasticViscoplasticElements<S, D>,
63 S: Differentiate,
64{
65 fn initial_state(&self) -> S {
66 self.blocks.initial_state()
67 }
68 fn nodal_forces_into(
69 &self,
70 nodal_coordinates: &NodalCoordinates<D>,
71 state_variables: &S,
72 nodal_forces: &mut NodalForcesSolid<D>,
73 ) -> Result<(), ElementModelError> {
74 self.blocks
75 .nodal_forces_into(nodal_coordinates, state_variables, nodal_forces)
76 }
77 fn nodal_stiffnesses_into(
78 &self,
79 nodal_coordinates: &NodalCoordinates<D>,
80 state_variables: &S,
81 nodal_stiffnesses: &mut NodalStiffnessesSolid<D>,
82 ) -> Result<(), ElementModelError> {
83 self.blocks
84 .nodal_stiffnesses_into(nodal_coordinates, state_variables, nodal_stiffnesses)
85 }
86 fn state_variables_evolution(
87 &self,
88 nodal_coordinates: &NodalCoordinates<D>,
89 state_variables: &S,
90 ) -> Result<Derivative<S>, ElementModelError> {
91 self.blocks
92 .state_variables_evolution(nodal_coordinates, state_variables)
93 }
94}
95
96impl<B1, B2, S, const D: usize> ElasticViscoplasticElements<S, D>
97 for ElasticViscoplasticAndElastic<B1, B2>
98where
99 B1: ElasticViscoplasticElements<S, D>,
100 B2: ElasticElements<D>,
101 S: Differentiate,
102{
103 fn initial_state(&self) -> S {
104 self.0.initial_state()
105 }
106 fn nodal_forces_into(
107 &self,
108 nodal_coordinates: &NodalCoordinates<D>,
109 state_variables: &S,
110 nodal_forces: &mut NodalForcesSolid<D>,
111 ) -> Result<(), ElementModelError> {
112 self.0
113 .nodal_forces_into(nodal_coordinates, state_variables, nodal_forces)?;
114 self.1.nodal_forces_into(nodal_coordinates, nodal_forces)
115 }
116 fn nodal_stiffnesses_into(
117 &self,
118 nodal_coordinates: &NodalCoordinates<D>,
119 state_variables: &S,
120 nodal_stiffnesses: &mut NodalStiffnessesSolid<D>,
121 ) -> Result<(), ElementModelError> {
122 self.0
123 .nodal_stiffnesses_into(nodal_coordinates, state_variables, nodal_stiffnesses)?;
124 self.1
125 .nodal_stiffnesses_into(nodal_coordinates, nodal_stiffnesses)
126 }
127 fn state_variables_evolution(
128 &self,
129 nodal_coordinates: &NodalCoordinates<D>,
130 state_variables: &S,
131 ) -> Result<Derivative<S>, ElementModelError> {
132 self.0
133 .state_variables_evolution(nodal_coordinates, state_variables)
134 }
135}
136
137impl<B1, B2, S1, S2, const D: usize> ElasticViscoplasticElements<TensorTuple<S1, S2>, D>
138 for Blocks<B1, B2>
139where
140 B1: ElasticViscoplasticElements<S1, D>,
141 B2: ElasticViscoplasticElements<S2, D>,
142 S1: Differentiate + Tensor,
143 S2: Differentiate + Tensor,
144 Derivative<S1>: Tensor,
145 Derivative<S2>: Tensor,
146{
147 fn initial_state(&self) -> TensorTuple<S1, S2> {
148 (self.0.initial_state(), self.1.initial_state()).into()
149 }
150 fn nodal_forces_into(
151 &self,
152 nodal_coordinates: &NodalCoordinates<D>,
153 state_variables: &TensorTuple<S1, S2>,
154 nodal_forces: &mut NodalForcesSolid<D>,
155 ) -> Result<(), ElementModelError> {
156 self.0
157 .nodal_forces_into(nodal_coordinates, &state_variables.0, nodal_forces)?;
158 self.1
159 .nodal_forces_into(nodal_coordinates, &state_variables.1, nodal_forces)
160 }
161 fn nodal_stiffnesses_into(
162 &self,
163 nodal_coordinates: &NodalCoordinates<D>,
164 state_variables: &TensorTuple<S1, S2>,
165 nodal_stiffnesses: &mut NodalStiffnessesSolid<D>,
166 ) -> Result<(), ElementModelError> {
167 self.0
168 .nodal_stiffnesses_into(nodal_coordinates, &state_variables.0, nodal_stiffnesses)?;
169 self.1
170 .nodal_stiffnesses_into(nodal_coordinates, &state_variables.1, nodal_stiffnesses)
171 }
172 fn state_variables_evolution(
173 &self,
174 nodal_coordinates: &NodalCoordinates<D>,
175 state_variables: &TensorTuple<S1, S2>,
176 ) -> Result<Derivative<TensorTuple<S1, S2>>, ElementModelError> {
177 Ok((
178 self.0
179 .state_variables_evolution(nodal_coordinates, &state_variables.0)?,
180 self.1
181 .state_variables_evolution(nodal_coordinates, &state_variables.1)?,
182 )
183 .into())
184 }
185}
186
187pub trait FirstOrderRoot<S, R, H, const D: usize>
188where
189 S: Differentiate + Tensor,
190 R: TensorVec<Item = Derivative<S>>,
191 H: TensorVec<Item = S>,
192{
193 fn root(
194 &self,
195 integrator: impl ExplicitDaeFirstOrderRoot<
196 NodalForcesSolid<D>,
197 NodalStiffnessesSolid<D>,
198 S,
199 NodalCoordinates<D>,
200 H,
201 NodalCoordinatesHistory<D>,
202 R,
203 >,
204 solver: impl FirstOrderRootFinding<
205 NodalForcesSolid<D>,
206 NodalStiffnessesSolid<D>,
207 NodalCoordinates<D>,
208 >,
209 time: &[Quantity<Time>],
210 bcs: ElasticViscoplasticBCs,
211 ) -> Result<(Times, NodalCoordinatesHistory<D>, H), IntegrationError>;
212}
213
214impl<B, S, R, H, const D: usize> FirstOrderRoot<S, R, H, D> for Model<B, D>
215where
216 B: ElasticViscoplasticElements<S, D>,
217 S: Differentiate + Tensor,
218 R: TensorVec<Item = Derivative<S>>,
219 H: TensorVec<Item = S>,
220{
221 fn root(
222 &self,
223 integrator: impl ExplicitDaeFirstOrderRoot<
224 NodalForcesSolid<D>,
225 NodalStiffnessesSolid<D>,
226 S,
227 NodalCoordinates<D>,
228 H,
229 NodalCoordinatesHistory<D>,
230 R,
231 >,
232 solver: impl FirstOrderRootFinding<
233 NodalForcesSolid<D>,
234 NodalStiffnessesSolid<D>,
235 NodalCoordinates<D>,
236 >,
237 time: &[Quantity<Time>],
238 bcs: ElasticViscoplasticBCs,
239 ) -> Result<(Times, NodalCoordinatesHistory<D>, H), IntegrationError> {
240 let (time_history, state_variables_history, _, nodal_coordinates_history) = integrator
241 .integrate(
242 |_: Quantity<Time>,
243 state_variables: &S,
244 nodal_coordinates: &NodalCoordinates<D>| {
245 Ok(self
246 .blocks
247 .state_variables_evolution(nodal_coordinates, state_variables)?)
248 },
249 |_: Quantity<Time>,
250 state_variables: &S,
251 nodal_coordinates: &NodalCoordinates<D>| {
252 Ok(self
253 .blocks
254 .nodal_forces(nodal_coordinates, state_variables)?)
255 },
256 |_: Quantity<Time>,
257 state_variables: &S,
258 nodal_coordinates: &NodalCoordinates<D>| {
259 Ok(self
260 .blocks
261 .nodal_stiffnesses(nodal_coordinates, state_variables)?)
262 },
263 solver,
264 time,
265 (
266 self.blocks.initial_state(),
267 self.coordinates().clone().into(),
268 ),
269 bcs,
270 )?;
271 Ok((
272 time_history,
273 nodal_coordinates_history,
274 state_variables_history,
275 ))
276 }
277}