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