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::elastic_hyperviscous::ElasticHyperviscousFiniteElement, surface::SurfaceElement,
6    },
7    math::{Scalar, Tensor},
8};
9
10pub trait HyperviscoelasticFiniteElement<
11    C,
12    const G: usize,
13    const M: usize,
14    const N: usize,
15    const P: usize,
16> where
17    C: Hyperviscoelastic,
18    Self: ElasticHyperviscousFiniteElement<C, G, M, N, P>,
19{
20    fn helmholtz_free_energy(
21        &self,
22        constitutive_model: &C,
23        nodal_coordinates: &ElementNodalCoordinates<N>,
24    ) -> Result<Scalar, FiniteElementError>;
25}
26
27impl<C, const G: usize, const N: usize, const O: usize, const P: usize>
28    HyperviscoelasticFiniteElement<C, G, 3, N, P> for Element<G, N, O>
29where
30    C: Hyperviscoelastic,
31    Self: ElasticHyperviscousFiniteElement<C, G, 3, N, P>,
32{
33    fn helmholtz_free_energy(
34        &self,
35        constitutive_model: &C,
36        nodal_coordinates: &ElementNodalCoordinates<N>,
37    ) -> Result<Scalar, FiniteElementError> {
38        helmholtz_free_energy::<_, _, _, _, _, O, _>(self, constitutive_model, nodal_coordinates)
39    }
40}
41
42impl<C, const G: usize, const N: usize, const O: usize, const P: usize>
43    HyperviscoelasticFiniteElement<C, G, 2, N, P> for SurfaceElement<G, N, O>
44where
45    C: Hyperviscoelastic,
46    Self: ElasticHyperviscousFiniteElement<C, G, 2, N, P>,
47{
48    fn helmholtz_free_energy(
49        &self,
50        constitutive_model: &C,
51        nodal_coordinates: &ElementNodalCoordinates<N>,
52    ) -> Result<Scalar, FiniteElementError> {
53        helmholtz_free_energy::<_, _, _, _, _, O, _>(self, constitutive_model, nodal_coordinates)
54    }
55}
56
57fn helmholtz_free_energy<
58    C,
59    F,
60    const G: usize,
61    const M: usize,
62    const N: usize,
63    const O: usize,
64    const P: usize,
65>(
66    element: &F,
67    constitutive_model: &C,
68    nodal_coordinates: &ElementNodalCoordinates<N>,
69) -> Result<Scalar, FiniteElementError>
70where
71    C: Hyperviscoelastic,
72    F: ElasticHyperviscousFiniteElement<C, G, M, N, P>,
73{
74    match element
75        .deformation_gradients(nodal_coordinates)
76        .iter()
77        .zip(element.integration_weights())
78        .map(|(deformation_gradient, integration_weight)| {
79            Ok::<_, ConstitutiveError>(
80                constitutive_model.helmholtz_free_energy_density(deformation_gradient)?
81                    * integration_weight,
82            )
83        })
84        .sum()
85    {
86        Ok(helmholtz_free_energy) => Ok(helmholtz_free_energy),
87        Err(error) => Err(FiniteElementError::Upstream(
88            format!("{error}"),
89            format!("{element:?}"),
90        )),
91    }
92}