conspire/domain/fem/block/solid/hyperelastic/
mod.rs1use 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}