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

1use crate::{
2    constitutive::solid::hyperelastic_viscoplastic::HyperelasticViscoplastic,
3    fem::{
4        NodalCoordinates, NodalCoordinatesHistory,
5        block::{
6            Block, FiniteElementBlockError, band,
7            element::solid::hyperelastic_viscoplastic::HyperelasticViscoplasticFiniteElement,
8            solid::{
9                NodalForcesSolid, NodalStiffnessesSolid,
10                elastic_viscoplastic::{
11                    ElasticViscoplasticBCs, ElasticViscoplasticFiniteElementBlock,
12                    ViscoplasticStateVariables, ViscoplasticStateVariablesHistory,
13                },
14            },
15        },
16    },
17    math::{
18        Scalar, Tensor,
19        integrate::{ExplicitDaeSecondOrderMinimize, IntegrationError},
20        optimize::SecondOrderOptimization,
21    },
22    mechanics::Times,
23};
24use std::array::from_fn;
25
26pub trait HyperelasticViscoplasticFiniteElementBlock<
27    C,
28    F,
29    const G: usize,
30    const M: usize,
31    const N: usize,
32    const P: usize,
33    Y,
34> where
35    C: HyperelasticViscoplastic<Y>,
36    F: HyperelasticViscoplasticFiniteElement<C, G, M, N, P, Y>,
37    Self: ElasticViscoplasticFiniteElementBlock<C, F, G, M, N, P, Y>,
38    Y: Tensor,
39{
40    fn helmholtz_free_energy(
41        &self,
42        nodal_coordinates: &NodalCoordinates,
43        state_variables: &ViscoplasticStateVariables<G, Y>,
44    ) -> Result<Scalar, FiniteElementBlockError>;
45    fn minimize(
46        &self,
47        integrator: impl ExplicitDaeSecondOrderMinimize<
48            Scalar,
49            NodalForcesSolid,
50            NodalStiffnessesSolid,
51            ViscoplasticStateVariables<G, Y>,
52            NodalCoordinates,
53            ViscoplasticStateVariablesHistory<G, Y>,
54            NodalCoordinatesHistory,
55        >,
56        solver: impl SecondOrderOptimization<
57            Scalar,
58            NodalForcesSolid,
59            NodalStiffnessesSolid,
60            NodalCoordinates,
61        >,
62        time: &[Scalar],
63        bcs: ElasticViscoplasticBCs,
64    ) -> Result<
65        (
66            Times,
67            NodalCoordinatesHistory,
68            ViscoplasticStateVariablesHistory<G, Y>,
69        ),
70        IntegrationError,
71    >;
72}
73
74impl<C, F, const G: usize, const M: usize, const N: usize, const P: usize, Y>
75    HyperelasticViscoplasticFiniteElementBlock<C, F, G, M, N, P, Y> for Block<C, F, G, M, N, P>
76where
77    C: HyperelasticViscoplastic<Y>,
78    F: HyperelasticViscoplasticFiniteElement<C, G, M, N, P, Y>,
79    Self: ElasticViscoplasticFiniteElementBlock<C, F, G, M, N, P, Y>,
80    Y: Tensor,
81{
82    fn helmholtz_free_energy(
83        &self,
84        nodal_coordinates: &NodalCoordinates,
85        state_variables: &ViscoplasticStateVariables<G, Y>,
86    ) -> Result<Scalar, FiniteElementBlockError> {
87        match self
88            .elements()
89            .iter()
90            .zip(self.connectivity())
91            .zip(state_variables)
92            .map(|((element, nodes), state_variables_element)| {
93                element.helmholtz_free_energy(
94                    self.constitutive_model(),
95                    &Self::element_coordinates(nodal_coordinates, nodes),
96                    state_variables_element,
97                )
98            })
99            .sum()
100        {
101            Ok(helmholtz_free_energy) => Ok(helmholtz_free_energy),
102            Err(error) => Err(FiniteElementBlockError::Upstream(
103                format!("{error}"),
104                format!("{self:?}"),
105            )),
106        }
107    }
108    fn minimize(
109        &self,
110        integrator: impl ExplicitDaeSecondOrderMinimize<
111            Scalar,
112            NodalForcesSolid,
113            NodalStiffnessesSolid,
114            ViscoplasticStateVariables<G, Y>,
115            NodalCoordinates,
116            ViscoplasticStateVariablesHistory<G, Y>,
117            NodalCoordinatesHistory,
118        >,
119        solver: impl SecondOrderOptimization<
120            Scalar,
121            NodalForcesSolid,
122            NodalStiffnessesSolid,
123            NodalCoordinates,
124        >,
125        time: &[Scalar],
126        bcs: ElasticViscoplasticBCs,
127    ) -> Result<
128        (
129            Times,
130            NodalCoordinatesHistory,
131            ViscoplasticStateVariablesHistory<G, Y>,
132        ),
133        IntegrationError,
134    > {
135        let banded = band(
136            self.connectivity(),
137            &bcs(time[0]),
138            self.coordinates().len(),
139            3,
140        );
141        let (time_history, state_variables_history, _, nodal_coordinates_history) = integrator
142            .integrate(
143                |_: Scalar,
144                 state_variables: &ViscoplasticStateVariables<G, Y>,
145                 nodal_coordinates: &NodalCoordinates| {
146                    Ok(self.state_variables_evolution(nodal_coordinates, state_variables)?)
147                },
148                |_t: Scalar,
149                 state_variables: &ViscoplasticStateVariables<G, Y>,
150                 nodal_coordinates: &NodalCoordinates| {
151                    Ok(self.helmholtz_free_energy(nodal_coordinates, state_variables)?)
152                },
153                |_t: Scalar,
154                 state_variables: &ViscoplasticStateVariables<G, Y>,
155                 nodal_coordinates: &NodalCoordinates| {
156                    Ok(self.nodal_forces(nodal_coordinates, state_variables)?)
157                },
158                |_t: Scalar,
159                 state_variables: &ViscoplasticStateVariables<G, Y>,
160                 nodal_coordinates: &NodalCoordinates| {
161                    Ok(self.nodal_stiffnesses(nodal_coordinates, state_variables)?)
162                },
163                solver,
164                time,
165                (
166                    self.elements()
167                        .iter()
168                        .map(|_| from_fn(|_| self.constitutive_model().initial_state()).into())
169                        .collect(),
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}