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