Skip to main content

conspire/domain/fem/solid/elastic_viscoplastic/
mod.rs

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}