Skip to main content

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

1use crate::{
2    constitutive::{ConstitutiveError, solid::hyperelastic_viscoplastic::HyperelasticViscoplastic},
3    domain::block::element::solid::{
4        hyperelastic_viscoplastic::HyperelasticViscoplasticElement,
5        viscoplastic::ViscoplasticStateVariables,
6    },
7    math::{Differentiable, Quantity, Tensor},
8    units::Energy,
9    vem::block::element::{
10        Element, ElementNodalCoordinates, VirtualElement, VirtualElementError,
11        solid::{SolidElement, elastic_viscoplastic::ElasticViscoplasticVirtualElement},
12    },
13};
14
15pub trait HyperelasticViscoplasticVirtualElement<C, Y>
16where
17    C: HyperelasticViscoplastic<Y>,
18    Y: Differentiable + Tensor,
19    Self: ElasticViscoplasticVirtualElement<C, Y> + HyperelasticViscoplasticElement<C, 1, Y>,
20{
21}
22
23impl<T, C, Y> HyperelasticViscoplasticVirtualElement<C, Y> for T
24where
25    C: HyperelasticViscoplastic<Y>,
26    Y: Differentiable + Tensor,
27    T: ElasticViscoplasticVirtualElement<C, Y> + HyperelasticViscoplasticElement<C, 1, Y>,
28{
29}
30
31impl<C, Y> HyperelasticViscoplasticElement<C, 1, Y> for Element
32where
33    C: HyperelasticViscoplastic<Y>,
34    Y: Differentiable + Tensor,
35{
36    fn helmholtz_free_energy(
37        &self,
38        constitutive_model: &C,
39        nodal_coordinates: &ElementNodalCoordinates,
40        state_variables: &ViscoplasticStateVariables<1, Y>,
41    ) -> Result<Quantity<Energy>, VirtualElementError> {
42        let tetrahedra_energy = self
43            .tetrahedra()
44            .iter()
45            .zip(self.tetrahedra_coordinates(nodal_coordinates).iter())
46            .map(|(tetrahedron, tetrahedron_coordinates)| {
47                tetrahedron.helmholtz_free_energy(
48                    constitutive_model,
49                    tetrahedron_coordinates,
50                    state_variables,
51                )
52            })
53            .sum::<Result<Quantity<Energy>, _>>()
54            .map_err(|error| self.upstream(error))?;
55        let polyhedron_energy = self
56            .deformation_gradients(nodal_coordinates)
57            .iter()
58            .zip(state_variables)
59            .zip(self.integration_weights())
60            .map(
61                |((deformation_gradient, state_variable), integration_weight)| {
62                    let (deformation_gradient_p, _) = state_variable.into();
63                    Ok::<_, ConstitutiveError>(
64                        constitutive_model.helmholtz_free_energy_density(
65                            deformation_gradient,
66                            deformation_gradient_p,
67                        )? * integration_weight,
68                    )
69                },
70            )
71            .sum::<Result<Quantity<Energy>, _>>()
72            .map_err(|error| self.upstream(error))?;
73        Ok(polyhedron_energy * (1.0 - self.stabilization())
74            + tetrahedra_energy * self.stabilization())
75    }
76}