conspire/domain/fem/block/element/solid/hyperelastic/
mod.rs1use crate::{
2 constitutive::{ConstitutiveError, solid::hyperelastic::Hyperelastic},
3 fem::block::element::{
4 Element, ElementNodalCoordinates, FiniteElementError,
5 solid::{SolidFiniteElement, elastic::ElasticFiniteElement},
6 },
7 math::{Scalar, Tensor},
8};
9
10pub trait HyperelasticFiniteElement<C, const G: usize, const N: usize>
11where
12 C: Hyperelastic,
13 Self: ElasticFiniteElement<C, G, N>,
14{
15 fn helmholtz_free_energy(
16 &self,
17 constitutive_model: &C,
18 nodal_coordinates: &ElementNodalCoordinates<N>,
19 ) -> Result<Scalar, FiniteElementError>;
20}
21
22impl<C, const G: usize, const N: usize> HyperelasticFiniteElement<C, G, N> for Element<G, N>
23where
24 C: Hyperelastic,
25{
26 fn helmholtz_free_energy(
27 &self,
28 constitutive_model: &C,
29 nodal_coordinates: &ElementNodalCoordinates<N>,
30 ) -> Result<Scalar, FiniteElementError> {
31 match self
32 .deformation_gradients(nodal_coordinates)
33 .iter()
34 .zip(self.integration_weights().iter())
35 .map(|(deformation_gradient, integration_weight)| {
36 Ok::<_, ConstitutiveError>(
37 constitutive_model.helmholtz_free_energy_density(deformation_gradient)?
38 * integration_weight,
39 )
40 })
41 .sum()
42 {
43 Ok(helmholtz_free_energy) => Ok(helmholtz_free_energy),
44 Err(error) => Err(FiniteElementError::Upstream(
45 format!("{error}"),
46 format!("{self:?}"),
47 )),
48 }
49 }
50}