conspire/domain/vem/block/element/solid/hyperviscoelastic/
mod.rs1use crate::{
2 constitutive::{ConstitutiveError, solid::hyperviscoelastic::Hyperviscoelastic},
3 domain::block::element::solid::hyperviscoelastic::HyperviscoelasticElement,
4 math::{Quantity, Tensor},
5 units::Energy,
6 vem::block::element::{
7 Element, ElementNodalCoordinates, VirtualElement, VirtualElementError,
8 solid::{SolidElement, elastic_hyperviscous::ElasticHyperviscousVirtualElement},
9 },
10};
11
12pub trait HyperviscoelasticVirtualElement<C>
13where
14 C: Hyperviscoelastic,
15 Self: ElasticHyperviscousVirtualElement<C> + HyperviscoelasticElement<C>,
16{
17}
18
19impl<T, C> HyperviscoelasticVirtualElement<C> for T
20where
21 C: Hyperviscoelastic,
22 T: ElasticHyperviscousVirtualElement<C> + HyperviscoelasticElement<C>,
23{
24}
25
26impl<C> HyperviscoelasticElement<C> for Element
27where
28 C: Hyperviscoelastic,
29{
30 fn helmholtz_free_energy(
31 &self,
32 constitutive_model: &C,
33 nodal_coordinates: &ElementNodalCoordinates,
34 ) -> Result<Quantity<Energy>, VirtualElementError> {
35 let tetrahedra_energy = self
36 .tetrahedra()
37 .iter()
38 .zip(self.tetrahedra_coordinates(nodal_coordinates).iter())
39 .map(|(tetrahedron, tetrahedron_coordinates)| {
40 tetrahedron.helmholtz_free_energy(constitutive_model, tetrahedron_coordinates)
41 })
42 .sum::<Result<Quantity<Energy>, _>>()
43 .map_err(|error| self.upstream(error))?;
44 let polyhedron_energy = self
45 .deformation_gradients(nodal_coordinates)
46 .iter()
47 .zip(self.integration_weights())
48 .map(|(deformation_gradient, integration_weight)| {
49 Ok::<_, ConstitutiveError>(
50 constitutive_model.helmholtz_free_energy_density(deformation_gradient)?
51 * integration_weight,
52 )
53 })
54 .sum::<Result<Quantity<Energy>, _>>()
55 .map_err(|error| self.upstream(error))?;
56 Ok(polyhedron_energy * (1.0 - self.stabilization())
57 + tetrahedra_energy * self.stabilization())
58 }
59}