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::{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}