conspire/domain/vem/block/solid/hyperelastic/
mod.rs1use crate::{
2 constitutive::solid::hyperelastic::Hyperelastic,
3 domain::{ElementModelError, solid::hyperelastic::HyperelasticElements},
4 math::{HessianAccumulate, Quantity},
5 units::Energy,
6 vem::{
7 NodalCoordinates,
8 block::{
9 Block,
10 element::{VirtualElementError, solid::hyperelastic::HyperelasticVirtualElement},
11 solid::NodalStiffnessesSolidSymmetric,
12 },
13 },
14};
15
16impl<C, F> HyperelasticElements<3> for Block<C, F>
17where
18 C: Hyperelastic,
19 F: HyperelasticVirtualElement<C>,
20{
21 fn helmholtz_free_energy(
22 &self,
23 nodal_coordinates: &NodalCoordinates,
24 ) -> Result<Quantity<Energy>, ElementModelError> {
25 self.elements()
26 .iter()
27 .zip(self.elements_nodes())
28 .map(|(element, nodes)| {
29 element.helmholtz_free_energy(
30 self.constitutive_model(),
31 &Self::element_coordinates(nodal_coordinates, nodes),
32 )
33 })
34 .sum::<Result<_, VirtualElementError>>()
35 .map_err(|error| ElementModelError::upstream(error, self))
36 }
37 fn nodal_stiffnesses_symmetric_into(
38 &self,
39 nodal_coordinates: &NodalCoordinates,
40 nodal_stiffnesses: &mut NodalStiffnessesSolidSymmetric,
41 ) -> Result<(), ElementModelError> {
42 self.elements()
43 .iter()
44 .zip(self.elements_nodes())
45 .try_for_each(|(element, nodes)| {
46 element
47 .nodal_stiffnesses(
48 self.constitutive_model(),
49 &Self::element_coordinates(nodal_coordinates, nodes),
50 )?
51 .into_iter()
52 .zip(nodes)
53 .for_each(|(object, &node_a)| {
54 object
55 .into_iter()
56 .zip(nodes)
57 .for_each(|(nodal_stiffness, &node_b)| {
58 if node_a <= node_b {
59 nodal_stiffnesses.accumulate(node_a, node_b, nodal_stiffness)
60 }
61 })
62 });
63 Ok::<(), VirtualElementError>(())
64 })
65 .map_err(|error| ElementModelError::upstream(error, self))
66 }
67}