Skip to main content

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