Skip to main content

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

1pub mod internal_variables;
2
3use crate::{
4    constitutive::solid::hyperelastic::Hyperelastic,
5    fem::{
6        ElementModelError, NodalCoordinates,
7        block::{
8            Block,
9            element::{
10                FiniteElementError, planar::PlanarHyperelasticFiniteElement,
11                solid::hyperelastic::HyperelasticFiniteElement,
12            },
13        },
14        solid::{
15            NodalStiffnessesSolidSymmetric, elastic::ElasticElements,
16            hyperelastic::HyperelasticElements,
17        },
18    },
19    math::{HessianAccumulate, Quantity},
20    units::Energy,
21};
22
23impl<C, F, const G: usize, const M: usize, const N: usize, const P: usize> HyperelasticElements<3>
24    for Block<C, F, G, M, N, P>
25where
26    C: Hyperelastic,
27    F: HyperelasticFiniteElement<C, G, M, N, P>,
28    Self: ElasticElements<3>,
29{
30    fn helmholtz_free_energy(
31        &self,
32        nodal_coordinates: &NodalCoordinates<3>,
33    ) -> Result<Quantity<Energy>, ElementModelError> {
34        self.elements()
35            .iter()
36            .zip(self.connectivity())
37            .map(|(element, nodes)| {
38                element.helmholtz_free_energy(
39                    self.constitutive_model(),
40                    &Self::element_coordinates(nodal_coordinates, nodes),
41                )
42            })
43            .sum::<Result<_, FiniteElementError>>()
44            .map_err(|error| ElementModelError::upstream(error, self))
45    }
46    fn nodal_stiffnesses_symmetric_into(
47        &self,
48        nodal_coordinates: &NodalCoordinates<3>,
49        nodal_stiffnesses: &mut NodalStiffnessesSolidSymmetric<3>,
50    ) -> Result<(), ElementModelError> {
51        self.elements()
52            .iter()
53            .zip(self.connectivity())
54            .try_for_each(|(element, nodes)| {
55                element
56                    .nodal_stiffnesses(
57                        self.constitutive_model(),
58                        &Self::element_coordinates(nodal_coordinates, nodes),
59                    )?
60                    .into_iter()
61                    .zip(nodes)
62                    .for_each(|(object, &node_a)| {
63                        object
64                            .into_iter()
65                            .zip(nodes)
66                            .for_each(|(nodal_stiffness, &node_b)| {
67                                if node_a <= node_b {
68                                    nodal_stiffnesses.accumulate(node_a, node_b, nodal_stiffness)
69                                }
70                            })
71                    });
72                Ok::<(), FiniteElementError>(())
73            })
74            .map_err(|error| ElementModelError::upstream(error, self))
75    }
76}
77
78impl<C, F, const G: usize, const N: usize, const P: usize> HyperelasticElements<2>
79    for Block<C, F, G, 2, N, P>
80where
81    C: Hyperelastic,
82    F: PlanarHyperelasticFiniteElement<C, G, N, P>,
83    Self: ElasticElements<2>,
84{
85    fn helmholtz_free_energy(
86        &self,
87        nodal_coordinates: &NodalCoordinates<2>,
88    ) -> Result<Quantity<Energy>, ElementModelError> {
89        self.elements()
90            .iter()
91            .zip(self.connectivity())
92            .map(|(element, nodes)| {
93                element.helmholtz_free_energy(
94                    self.constitutive_model(),
95                    &Self::element_coordinates(nodal_coordinates, nodes),
96                )
97            })
98            .sum::<Result<_, FiniteElementError>>()
99            .map_err(|error| ElementModelError::upstream(error, self))
100    }
101    fn nodal_stiffnesses_symmetric_into(
102        &self,
103        nodal_coordinates: &NodalCoordinates<2>,
104        nodal_stiffnesses: &mut NodalStiffnessesSolidSymmetric<2>,
105    ) -> Result<(), ElementModelError> {
106        self.elements()
107            .iter()
108            .zip(self.connectivity())
109            .try_for_each(|(element, nodes)| {
110                element
111                    .nodal_stiffnesses(
112                        self.constitutive_model(),
113                        &Self::element_coordinates(nodal_coordinates, nodes),
114                    )?
115                    .into_iter()
116                    .zip(nodes)
117                    .for_each(|(object, &node_a)| {
118                        object
119                            .into_iter()
120                            .zip(nodes)
121                            .for_each(|(nodal_stiffness, &node_b)| {
122                                if node_a <= node_b {
123                                    nodal_stiffnesses.accumulate(node_a, node_b, nodal_stiffness)
124                                }
125                            })
126                    });
127                Ok::<(), FiniteElementError>(())
128            })
129            .map_err(|error| ElementModelError::upstream(error, self))
130    }
131}