Skip to main content

conspire/domain/fem/block/element/solid/hyperelastic/
mod.rs

1pub mod internal_variables;
2
3use crate::{
4    constitutive::{ConstitutiveError, solid::hyperelastic::Hyperelastic},
5    fem::block::element::{
6        Element, ElementNodalCoordinates, FiniteElementError, solid::elastic::ElasticFiniteElement,
7        surface::SurfaceElement,
8    },
9    math::{Quantity, Tensor},
10    units::Energy,
11};
12
13pub trait HyperelasticFiniteElement<
14    C,
15    const G: usize,
16    const M: usize,
17    const N: usize,
18    const P: usize,
19> where
20    C: Hyperelastic,
21    Self: ElasticFiniteElement<C, G, M, N, P>,
22{
23    fn helmholtz_free_energy(
24        &self,
25        constitutive_model: &C,
26        nodal_coordinates: &ElementNodalCoordinates<N>,
27    ) -> Result<Quantity<Energy>, FiniteElementError>;
28}
29
30impl<C, const G: usize, const N: usize, const O: usize, const P: usize>
31    HyperelasticFiniteElement<C, G, 3, N, P> for Element<3, G, N, O>
32where
33    C: Hyperelastic,
34    Self: ElasticFiniteElement<C, G, 3, N, P>,
35{
36    fn helmholtz_free_energy(
37        &self,
38        constitutive_model: &C,
39        nodal_coordinates: &ElementNodalCoordinates<N>,
40    ) -> Result<Quantity<Energy>, FiniteElementError> {
41        helmholtz_free_energy::<_, _, _, _, _, O, _>(self, constitutive_model, nodal_coordinates)
42    }
43}
44
45impl<C, const G: usize, const N: usize, const O: usize, const P: usize>
46    HyperelasticFiniteElement<C, G, 2, N, P> for SurfaceElement<G, N, O>
47where
48    C: Hyperelastic,
49    Self: ElasticFiniteElement<C, G, 2, N, P>,
50{
51    fn helmholtz_free_energy(
52        &self,
53        constitutive_model: &C,
54        nodal_coordinates: &ElementNodalCoordinates<N>,
55    ) -> Result<Quantity<Energy>, FiniteElementError> {
56        helmholtz_free_energy::<_, _, _, _, _, O, _>(self, constitutive_model, nodal_coordinates)
57    }
58}
59
60fn helmholtz_free_energy<
61    C,
62    F,
63    const G: usize,
64    const M: usize,
65    const N: usize,
66    const O: usize,
67    const P: usize,
68>(
69    element: &F,
70    constitutive_model: &C,
71    nodal_coordinates: &ElementNodalCoordinates<N>,
72) -> Result<Quantity<Energy>, FiniteElementError>
73where
74    C: Hyperelastic,
75    F: ElasticFiniteElement<C, G, M, N, P>,
76{
77    element
78        .deformation_gradients(nodal_coordinates)
79        .iter()
80        .zip(element.integration_weights())
81        .map(|(deformation_gradient, integration_weight)| {
82            Ok::<_, ConstitutiveError>(
83                constitutive_model.helmholtz_free_energy_density(deformation_gradient)?
84                    * integration_weight,
85            )
86        })
87        .sum::<Result<_, ConstitutiveError>>()
88        .map_err(|error| FiniteElementError::upstream(error, element))
89}