Skip to main content

conspire/domain/fem/block/solid/elastic/internal_variables/
mod.rs

1use std::ops::{Div, Mul};
2
3use crate::{
4    constitutive::solid::elastic::internal_variables::ElasticIV,
5    fem::{
6        ElementModelError, NodalCoordinates,
7        block::{
8            Block,
9            element::{
10                FiniteElementError, solid::elastic::internal_variables::ElasticIVFiniteElement,
11            },
12        },
13        solid::{
14            NodalForcesSolid, NodalStiffnessesSolid,
15            elastic::internal_variables::{ElasticIVElements, InternalVariablesField},
16        },
17    },
18    math::{
19        Erase, Jacobian, Matrix, Quantity, Scalar, Solution, Tensor, Vector,
20        optimize::NewtonRaphson,
21    },
22    units::{Dimensionless, UnitDiv},
23};
24
25impl<C, F, const G: usize, const M: usize, const N: usize, const P: usize, V, E>
26    ElasticIVElements<G, V, 3> for Block<C, F, G, M, N, P>
27where
28    C: ElasticIV<V>,
29    C::Residual: Erase<Erased = E>,
30    F: ElasticIVFiniteElement<C, G, M, N, P, V, E>,
31    E: Tensor,
32    for<'a> &'a C::Residual: Div<C::TangentVv, Output = V>,
33    for<'a> &'a V: Mul<Quantity<Dimensionless>, Output = V> + Mul<Scalar, Output = V>,
34    for<'a> &'a Matrix: Mul<&'a V, Output = Vector>,
35    V: Erase<Erased = E> + Jacobian + Solution,
36    <V as Tensor>::Unit: UnitDiv<<V as Tensor>::Unit, Output = Dimensionless>,
37{
38    fn internal_variables_initial(&self) -> InternalVariablesField<G, V> {
39        self.elements()
40            .iter()
41            .map(|element| element.internal_variables_initial(self.constitutive_model()))
42            .collect()
43    }
44    fn internal_variables_increment(
45        &self,
46        nodal_coordinates: &NodalCoordinates<3>,
47        internal_variables: &InternalVariablesField<G, V>,
48        nodal_decrement: &NodalCoordinates<3>,
49        step: Scalar,
50    ) -> Result<InternalVariablesField<G, V>, ElementModelError> {
51        self.elements()
52            .iter()
53            .zip(self.connectivity())
54            .zip(internal_variables)
55            .map(|((element, nodes), internal_variables_element)| {
56                element.internal_variables_increment(
57                    self.constitutive_model(),
58                    &Self::element_coordinates(nodal_coordinates, nodes),
59                    internal_variables_element,
60                    &Self::element_coordinates(nodal_decrement, nodes),
61                    step,
62                )
63            })
64            .collect::<Result<InternalVariablesField<G, V>, _>>()
65            .map_err(|error| ElementModelError::upstream(error, self))
66    }
67    fn internal_variables_root(
68        &self,
69        local_solver: &NewtonRaphson,
70        nodal_coordinates: &NodalCoordinates<3>,
71        internal_variables: &InternalVariablesField<G, V>,
72    ) -> Result<InternalVariablesField<G, V>, ElementModelError> {
73        self.elements()
74            .iter()
75            .zip(self.connectivity())
76            .zip(internal_variables)
77            .map(|((element, nodes), internal_variables_element)| {
78                element.internal_variables_root(
79                    local_solver,
80                    self.constitutive_model(),
81                    &Self::element_coordinates(nodal_coordinates, nodes),
82                    internal_variables_element,
83                )
84            })
85            .collect::<Result<InternalVariablesField<G, V>, _>>()
86            .map_err(|error| ElementModelError::upstream(error, self))
87    }
88    fn nodal_forces_into(
89        &self,
90        nodal_coordinates: &NodalCoordinates<3>,
91        internal_variables: &InternalVariablesField<G, V>,
92        nodal_forces: &mut NodalForcesSolid<3>,
93    ) -> Result<(), ElementModelError> {
94        self.elements()
95            .iter()
96            .zip(self.connectivity())
97            .zip(internal_variables)
98            .try_for_each(|((element, nodes), internal_variables_element)| {
99                element
100                    .nodal_forces(
101                        self.constitutive_model(),
102                        &Self::element_coordinates(nodal_coordinates, nodes),
103                        internal_variables_element,
104                    )?
105                    .into_iter()
106                    .zip(nodes)
107                    .for_each(|(nodal_force, &node)| nodal_forces[node] += nodal_force);
108                Ok::<(), FiniteElementError>(())
109            })
110            .map_err(|error| ElementModelError::upstream(error, self))
111    }
112    fn nodal_forces_eliminated_into(
113        &self,
114        nodal_coordinates: &NodalCoordinates<3>,
115        internal_variables: &InternalVariablesField<G, V>,
116        nodal_forces: &mut NodalForcesSolid<3>,
117    ) -> Result<(), ElementModelError> {
118        self.elements()
119            .iter()
120            .zip(self.connectivity())
121            .zip(internal_variables)
122            .try_for_each(|((element, nodes), internal_variables_element)| {
123                element
124                    .nodal_forces_eliminated(
125                        self.constitutive_model(),
126                        &Self::element_coordinates(nodal_coordinates, nodes),
127                        internal_variables_element,
128                    )?
129                    .into_iter()
130                    .zip(nodes)
131                    .for_each(|(nodal_force, &node)| nodal_forces[node] += nodal_force);
132                Ok::<(), FiniteElementError>(())
133            })
134            .map_err(|error| ElementModelError::upstream(error, self))
135    }
136    fn nodal_stiffnesses_into(
137        &self,
138        nodal_coordinates: &NodalCoordinates<3>,
139        internal_variables: &InternalVariablesField<G, V>,
140        nodal_stiffnesses: &mut NodalStiffnessesSolid<3>,
141    ) -> Result<(), ElementModelError> {
142        self.elements()
143            .iter()
144            .zip(self.connectivity())
145            .zip(internal_variables)
146            .try_for_each(|((element, nodes), internal_variables_element)| {
147                element
148                    .nodal_stiffnesses(
149                        self.constitutive_model(),
150                        &Self::element_coordinates(nodal_coordinates, nodes),
151                        internal_variables_element,
152                    )?
153                    .into_iter()
154                    .zip(nodes)
155                    .for_each(|(object, &node_a)| {
156                        object
157                            .into_iter()
158                            .zip(nodes)
159                            .for_each(|(nodal_stiffness, &node_b)| {
160                                nodal_stiffnesses[node_a][node_b] += nodal_stiffness
161                            })
162                    });
163                Ok::<(), FiniteElementError>(())
164            })
165            .map_err(|error| ElementModelError::upstream(error, self))
166    }
167}