Skip to main content

conspire/domain/vem/block/element/solid/hyperelastic/
mod.rs

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