conspire/domain/fem/block/solid/hyperelastic_viscoplastic/
mod.rs1use crate::{
2 constitutive::solid::hyperelastic_viscoplastic::HyperelasticViscoplastic,
3 fem::{
4 ElementModelError, NodalCoordinates,
5 block::{
6 Block, element::FiniteElementError,
7 element::solid::hyperelastic_viscoplastic::HyperelasticViscoplasticFiniteElement,
8 solid::elastic_viscoplastic::ViscoplasticStateVariables,
9 },
10 solid::{
11 elastic_viscoplastic::ElasticViscoplasticElements,
12 hyperelastic_viscoplastic::HyperelasticViscoplasticElements,
13 },
14 },
15 math::{Differentiable, Quantity, Tensor},
16 units::Energy,
17};
18
19impl<C, F, const G: usize, const M: usize, const N: usize, const P: usize, Y>
20 HyperelasticViscoplasticElements<ViscoplasticStateVariables<G, Y>, 3>
21 for Block<C, F, G, M, N, P>
22where
23 C: HyperelasticViscoplastic<Y>,
24 F: HyperelasticViscoplasticFiniteElement<C, G, M, N, P, Y>,
25 Self: ElasticViscoplasticElements<ViscoplasticStateVariables<G, Y>, 3>,
26 Y: Differentiable + Tensor,
27{
28 fn helmholtz_free_energy(
29 &self,
30 nodal_coordinates: &NodalCoordinates<3>,
31 state_variables: &ViscoplasticStateVariables<G, Y>,
32 ) -> Result<Quantity<Energy>, ElementModelError> {
33 self.elements()
34 .iter()
35 .zip(self.connectivity())
36 .zip(state_variables)
37 .map(|((element, nodes), state_variables_element)| {
38 element.helmholtz_free_energy(
39 self.constitutive_model(),
40 &Self::element_coordinates(nodal_coordinates, nodes),
41 state_variables_element,
42 )
43 })
44 .sum::<Result<_, FiniteElementError>>()
45 .map_err(|error| ElementModelError::upstream(error, self))
46 }
47}