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

1use crate::{
2    constitutive::{ConstitutiveError, solid::hyperviscoelastic::Hyperviscoelastic},
3    fem::block::element::{
4        Element, ElementNodalCoordinates, FiniteElementError,
5        solid::{SolidFiniteElement, elastic_hyperviscous::ElasticHyperviscousFiniteElement},
6    },
7    math::{Scalar, Tensor},
8};
9
10pub trait HyperviscoelasticFiniteElement<C, const G: usize, const N: usize>
11where
12    C: Hyperviscoelastic,
13    Self: ElasticHyperviscousFiniteElement<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> HyperviscoelasticFiniteElement<C, G, N> for Element<G, N>
23where
24    C: Hyperviscoelastic,
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}