Skip to main content

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

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