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        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}