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}