Skip to main content

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

1use crate::{
2    constitutive::solid::elastic_viscoplastic::ElasticViscoplastic,
3    fem::{
4        ElementModelError, NodalCoordinates,
5        block::{
6            Block,
7            element::{
8                FiniteElementError, solid::elastic_viscoplastic::ElasticViscoplasticFiniteElement,
9            },
10        },
11        solid::{
12            NodalForcesSolid, NodalStiffnessesSolid,
13            elastic_viscoplastic::ElasticViscoplasticElements,
14        },
15    },
16    math::{
17        Scalar, Tensor, TensorTupleListVec, TensorTupleListVec2D, optimize::EqualityConstraint,
18    },
19    mechanics::DeformationGradientPlastic,
20};
21use std::array::from_fn;
22
23pub type ViscoplasticStateVariables<const G: usize, Y> =
24    TensorTupleListVec<DeformationGradientPlastic, Y, G>;
25
26pub type ViscoplasticStateVariablesHistory<const G: usize, Y> =
27    TensorTupleListVec2D<DeformationGradientPlastic, Y, G>;
28
29pub type ElasticViscoplasticBCs = fn(Scalar) -> EqualityConstraint;
30
31impl<C, F, const G: usize, const M: usize, const N: usize, const P: usize, Y>
32    ElasticViscoplasticElements<ViscoplasticStateVariables<G, Y>, 3> for Block<C, F, G, M, N, P>
33where
34    C: ElasticViscoplastic<Y>,
35    F: ElasticViscoplasticFiniteElement<C, G, M, N, P, Y>,
36    Y: Tensor,
37{
38    fn initial_state(&self) -> ViscoplasticStateVariables<G, Y> {
39        self.elements()
40            .iter()
41            .map(|_| from_fn(|_| self.constitutive_model().initial_state()).into())
42            .collect()
43    }
44    fn nodal_forces_into(
45        &self,
46        nodal_coordinates: &NodalCoordinates<3>,
47        state_variables: &ViscoplasticStateVariables<G, Y>,
48        nodal_forces: &mut NodalForcesSolid<3>,
49    ) -> Result<(), ElementModelError> {
50        match self
51            .elements()
52            .iter()
53            .zip(self.connectivity())
54            .zip(state_variables)
55            .try_for_each(|((element, nodes), state_variables_element)| {
56                element
57                    .nodal_forces(
58                        self.constitutive_model(),
59                        &Self::element_coordinates(nodal_coordinates, nodes),
60                        state_variables_element,
61                    )?
62                    .into_iter()
63                    .zip(nodes)
64                    .for_each(|(nodal_force, &node)| nodal_forces[node] += nodal_force);
65                Ok::<(), FiniteElementError>(())
66            }) {
67            Ok(()) => Ok(()),
68            Err(error) => Err(ElementModelError::Upstream(
69                format!("{error}"),
70                format!("{self:?}"),
71            )),
72        }
73    }
74    fn nodal_stiffnesses_into(
75        &self,
76        nodal_coordinates: &NodalCoordinates<3>,
77        state_variables: &ViscoplasticStateVariables<G, Y>,
78        nodal_stiffnesses: &mut NodalStiffnessesSolid<3>,
79    ) -> Result<(), ElementModelError> {
80        match self
81            .elements()
82            .iter()
83            .zip(self.connectivity())
84            .zip(state_variables)
85            .try_for_each(|((element, nodes), state_variables_element)| {
86                element
87                    .nodal_stiffnesses(
88                        self.constitutive_model(),
89                        &Self::element_coordinates(nodal_coordinates, nodes),
90                        state_variables_element,
91                    )?
92                    .into_iter()
93                    .zip(nodes)
94                    .for_each(|(object, &node_a)| {
95                        object
96                            .into_iter()
97                            .zip(nodes)
98                            .for_each(|(nodal_stiffness, &node_b)| {
99                                nodal_stiffnesses[node_a][node_b] += nodal_stiffness
100                            })
101                    });
102                Ok::<(), FiniteElementError>(())
103            }) {
104            Ok(()) => Ok(()),
105            Err(error) => Err(ElementModelError::Upstream(
106                format!("{error}"),
107                format!("{self:?}"),
108            )),
109        }
110    }
111    fn state_variables_evolution(
112        &self,
113        nodal_coordinates: &NodalCoordinates<3>,
114        state_variables: &ViscoplasticStateVariables<G, Y>,
115    ) -> Result<ViscoplasticStateVariables<G, Y>, ElementModelError> {
116        match self
117            .elements()
118            .iter()
119            .zip(self.connectivity())
120            .zip(state_variables)
121            .map(|((element, nodes), element_state_variables)| {
122                element.state_variables_evolution(
123                    self.constitutive_model(),
124                    &Self::element_coordinates(nodal_coordinates, nodes),
125                    element_state_variables,
126                )
127            })
128            .collect()
129        {
130            Ok(state_variables_evolution) => Ok(state_variables_evolution),
131            Err(error) => Err(ElementModelError::Upstream(
132                format!("{error}"),
133                format!("{self:?}"),
134            )),
135        }
136    }
137}