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