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

1use crate::{
2    constitutive::{ConstitutiveError, solid::elastic_hyperviscous::ElasticHyperviscous},
3    fem::block::element::{
4        Element, ElementNodalCoordinates, ElementNodalVelocities, FiniteElementError,
5        solid::viscoelastic::ViscoelasticFiniteElement, surface::SurfaceElement,
6    },
7    math::{Scalar, Tensor},
8};
9
10pub trait ElasticHyperviscousFiniteElement<
11    C,
12    const G: usize,
13    const M: usize,
14    const N: usize,
15    const P: usize,
16> where
17    C: ElasticHyperviscous,
18    Self: ViscoelasticFiniteElement<C, G, M, N, P>,
19{
20    fn viscous_dissipation(
21        &self,
22        constitutive_model: &C,
23        nodal_coordinates: &ElementNodalCoordinates<N>,
24        nodal_velocities: &ElementNodalVelocities<N>,
25    ) -> Result<Scalar, FiniteElementError>;
26    fn dissipation_potential(
27        &self,
28        constitutive_model: &C,
29        nodal_coordinates: &ElementNodalCoordinates<N>,
30        nodal_velocities: &ElementNodalVelocities<N>,
31    ) -> Result<Scalar, FiniteElementError>;
32}
33
34impl<C, const G: usize, const N: usize, const O: usize, const P: usize>
35    ElasticHyperviscousFiniteElement<C, G, 3, N, P> for Element<G, N, O>
36where
37    C: ElasticHyperviscous,
38    Self: ViscoelasticFiniteElement<C, G, 3, N, P>,
39{
40    fn viscous_dissipation(
41        &self,
42        constitutive_model: &C,
43        nodal_coordinates: &ElementNodalCoordinates<N>,
44        nodal_velocities: &ElementNodalVelocities<N>,
45    ) -> Result<Scalar, FiniteElementError> {
46        viscous_dissipation::<_, _, _, _, _, O, _>(
47            self,
48            constitutive_model,
49            nodal_coordinates,
50            nodal_velocities,
51        )
52    }
53    fn dissipation_potential(
54        &self,
55        constitutive_model: &C,
56        nodal_coordinates: &ElementNodalCoordinates<N>,
57        nodal_velocities: &ElementNodalVelocities<N>,
58    ) -> Result<Scalar, FiniteElementError> {
59        dissipation_potential::<_, _, _, _, _, O, _>(
60            self,
61            constitutive_model,
62            nodal_coordinates,
63            nodal_velocities,
64        )
65    }
66}
67
68impl<C, const G: usize, const N: usize, const O: usize, const P: usize>
69    ElasticHyperviscousFiniteElement<C, G, 2, N, P> for SurfaceElement<G, N, O>
70where
71    C: ElasticHyperviscous,
72    Self: ViscoelasticFiniteElement<C, G, 2, N, P>,
73{
74    fn viscous_dissipation(
75        &self,
76        constitutive_model: &C,
77        nodal_coordinates: &ElementNodalCoordinates<N>,
78        nodal_velocities: &ElementNodalVelocities<N>,
79    ) -> Result<Scalar, FiniteElementError> {
80        viscous_dissipation::<_, _, _, _, _, O, _>(
81            self,
82            constitutive_model,
83            nodal_coordinates,
84            nodal_velocities,
85        )
86    }
87    fn dissipation_potential(
88        &self,
89        constitutive_model: &C,
90        nodal_coordinates: &ElementNodalCoordinates<N>,
91        nodal_velocities: &ElementNodalVelocities<N>,
92    ) -> Result<Scalar, FiniteElementError> {
93        dissipation_potential::<_, _, _, _, _, O, _>(
94            self,
95            constitutive_model,
96            nodal_coordinates,
97            nodal_velocities,
98        )
99    }
100}
101
102fn viscous_dissipation<
103    C,
104    F,
105    const G: usize,
106    const M: usize,
107    const N: usize,
108    const O: usize,
109    const P: usize,
110>(
111    element: &F,
112    constitutive_model: &C,
113    nodal_coordinates: &ElementNodalCoordinates<N>,
114    nodal_velocities: &ElementNodalVelocities<N>,
115) -> Result<Scalar, FiniteElementError>
116where
117    C: ElasticHyperviscous,
118    F: ViscoelasticFiniteElement<C, G, M, N, P>,
119{
120    match element
121        .deformation_gradients(nodal_coordinates)
122        .iter()
123        .zip(
124            element
125                .deformation_gradient_rates(nodal_coordinates, nodal_velocities)
126                .iter()
127                .zip(element.integration_weights()),
128        )
129        .map(
130            |(deformation_gradient, (deformation_gradient_rate, integration_weight))| {
131                Ok::<_, ConstitutiveError>(
132                    constitutive_model
133                        .viscous_dissipation(deformation_gradient, deformation_gradient_rate)?
134                        * integration_weight,
135                )
136            },
137        )
138        .sum()
139    {
140        Ok(helmholtz_free_energy) => Ok(helmholtz_free_energy),
141        Err(error) => Err(FiniteElementError::Upstream(
142            format!("{error}"),
143            format!("{element:?}"),
144        )),
145    }
146}
147
148fn dissipation_potential<
149    C,
150    F,
151    const G: usize,
152    const M: usize,
153    const N: usize,
154    const O: usize,
155    const P: usize,
156>(
157    element: &F,
158    constitutive_model: &C,
159    nodal_coordinates: &ElementNodalCoordinates<N>,
160    nodal_velocities: &ElementNodalVelocities<N>,
161) -> Result<Scalar, FiniteElementError>
162where
163    C: ElasticHyperviscous,
164    F: ViscoelasticFiniteElement<C, G, M, N, P>,
165{
166    match element
167        .deformation_gradients(nodal_coordinates)
168        .iter()
169        .zip(
170            element
171                .deformation_gradient_rates(nodal_coordinates, nodal_velocities)
172                .iter()
173                .zip(element.integration_weights()),
174        )
175        .map(
176            |(deformation_gradient, (deformation_gradient_rate, integration_weight))| {
177                Ok::<_, ConstitutiveError>(
178                    constitutive_model
179                        .dissipation_potential(deformation_gradient, deformation_gradient_rate)?
180                        * integration_weight,
181                )
182            },
183        )
184        .sum()
185    {
186        Ok(helmholtz_free_energy) => Ok(helmholtz_free_energy),
187        Err(error) => Err(FiniteElementError::Upstream(
188            format!("{error}"),
189            format!("{element:?}"),
190        )),
191    }
192}