conspire/domain/fem/block/element/solid/elastic_hyperviscous/
mod.rs1use crate::{
2 constitutive::{ConstitutiveError, solid::elastic_hyperviscous::ElasticHyperviscous},
3 fem::block::element::{
4 Element, ElementNodalCoordinates, ElementNodalVelocities, FiniteElementError,
5 solid::{SolidFiniteElement, viscoelastic::ViscoelasticFiniteElement},
6 },
7 math::{Scalar, Tensor},
8};
9
10pub trait ElasticHyperviscousFiniteElement<C, const G: usize, const N: usize>
11where
12 C: ElasticHyperviscous,
13 Self: ViscoelasticFiniteElement<C, G, N>,
14{
15 fn viscous_dissipation(
16 &self,
17 constitutive_model: &C,
18 nodal_coordinates: &ElementNodalCoordinates<N>,
19 nodal_velocities: &ElementNodalVelocities<N>,
20 ) -> Result<Scalar, FiniteElementError>;
21 fn dissipation_potential(
22 &self,
23 constitutive_model: &C,
24 nodal_coordinates: &ElementNodalCoordinates<N>,
25 nodal_velocities: &ElementNodalVelocities<N>,
26 ) -> Result<Scalar, FiniteElementError>;
27}
28
29impl<C, const G: usize, const N: usize> ElasticHyperviscousFiniteElement<C, G, N> for Element<G, N>
30where
31 C: ElasticHyperviscous,
32{
33 fn viscous_dissipation(
34 &self,
35 constitutive_model: &C,
36 nodal_coordinates: &ElementNodalCoordinates<N>,
37 nodal_velocities: &ElementNodalVelocities<N>,
38 ) -> Result<Scalar, FiniteElementError> {
39 match self
40 .deformation_gradients(nodal_coordinates)
41 .iter()
42 .zip(
43 self.deformation_gradient_rates(nodal_coordinates, nodal_velocities)
44 .iter()
45 .zip(self.integration_weights().iter()),
46 )
47 .map(
48 |(deformation_gradient, (deformation_gradient_rate, integration_weight))| {
49 Ok::<_, ConstitutiveError>(
50 constitutive_model
51 .viscous_dissipation(deformation_gradient, deformation_gradient_rate)?
52 * integration_weight,
53 )
54 },
55 )
56 .sum()
57 {
58 Ok(helmholtz_free_energy) => Ok(helmholtz_free_energy),
59 Err(error) => Err(FiniteElementError::Upstream(
60 format!("{error}"),
61 format!("{self:?}"),
62 )),
63 }
64 }
65 fn dissipation_potential(
66 &self,
67 constitutive_model: &C,
68 nodal_coordinates: &ElementNodalCoordinates<N>,
69 nodal_velocities: &ElementNodalVelocities<N>,
70 ) -> Result<Scalar, FiniteElementError> {
71 match self
72 .deformation_gradients(nodal_coordinates)
73 .iter()
74 .zip(
75 self.deformation_gradient_rates(nodal_coordinates, nodal_velocities)
76 .iter()
77 .zip(self.integration_weights().iter()),
78 )
79 .map(
80 |(deformation_gradient, (deformation_gradient_rate, integration_weight))| {
81 Ok::<_, ConstitutiveError>(
82 constitutive_model.dissipation_potential(
83 deformation_gradient,
84 deformation_gradient_rate,
85 )? * integration_weight,
86 )
87 },
88 )
89 .sum()
90 {
91 Ok(helmholtz_free_energy) => Ok(helmholtz_free_energy),
92 Err(error) => Err(FiniteElementError::Upstream(
93 format!("{error}"),
94 format!("{self:?}"),
95 )),
96 }
97 }
98}