conspire/domain/cbm/block/solid/hyperelastic/
mod.rs1use super::super::{
2 Block,
3 node::solid::{elastic::ElasticElement, hyperelastic::HyperelasticElement},
4};
5use crate::{
6 constitutive::{ConstitutiveError, solid::hyperelastic::Hyperelastic},
7 domain::{ElementModelError, NodalCoordinates, solid::NodalStiffnessesSolidSymmetric},
8 math::{HessianAccumulate, Quantity},
9 units::Energy,
10};
11
12pub use crate::domain::solid::hyperelastic::HyperelasticElements;
13
14impl<C> HyperelasticElements<3> for Block<C>
15where
16 C: Hyperelastic,
17{
18 fn helmholtz_free_energy(
19 &self,
20 nodal_coordinates: &NodalCoordinates<3>,
21 ) -> Result<Quantity<Energy>, ElementModelError> {
22 self.nodes
23 .iter()
24 .map(|node| node.helmholtz_free_energy(&self.constitutive_model, nodal_coordinates))
25 .sum::<Result<_, ConstitutiveError>>()
26 .map_err(|error| ElementModelError::upstream(error, self))
27 }
28 fn nodal_stiffnesses_symmetric_into(
29 &self,
30 nodal_coordinates: &NodalCoordinates<3>,
31 nodal_stiffnesses: &mut NodalStiffnessesSolidSymmetric<3>,
32 ) -> Result<(), ElementModelError> {
33 self.nodes
34 .iter()
35 .try_for_each(|node| {
36 node.nodal_stiffnesses(&self.constitutive_model, nodal_coordinates)?
37 .into_iter()
38 .zip(node.neighbors())
39 .for_each(|(row, &neighbor_a)| {
40 row.into_iter()
41 .zip(node.neighbors())
42 .for_each(|(block, &neighbor_b)| {
43 if neighbor_a <= neighbor_b {
44 nodal_stiffnesses.accumulate(neighbor_a, neighbor_b, block)
45 }
46 })
47 });
48 Ok::<(), ConstitutiveError>(())
49 })
50 .map_err(|error| ElementModelError::upstream(error, self))
51 }
52}