Skip to main content

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

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