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