conspire/domain/fem/block/solid/hyperelastic/internal_variables/
mod.rs1use crate::{
2 constitutive::solid::hyperelastic::internal_variables::HyperelasticIV,
3 fem::{
4 ElementModelError, NodalCoordinates,
5 block::{
6 Block, element::FiniteElementError,
7 element::solid::hyperelastic::internal_variables::HyperelasticIVFiniteElement,
8 },
9 solid::{
10 elastic::internal_variables::{ElasticIVElements, InternalVariablesField},
11 hyperelastic::internal_variables::HyperelasticIVElements,
12 },
13 },
14 math::{Erase, Jacobian, Matrix, Quantity, Scalar, Solution, Tensor, Vector},
15 units::{Dimensionless, Energy, UnitDiv},
16};
17use std::ops::{Div, Mul};
18
19impl<C, F, const G: usize, const M: usize, const N: usize, const P: usize, V, E>
20 HyperelasticIVElements<G, V, 3> for Block<C, F, G, M, N, P>
21where
22 C: HyperelasticIV<V>,
23 C::Residual: Erase<Erased = E>,
24 F: HyperelasticIVFiniteElement<C, G, M, N, P, V, E>,
25 Self: ElasticIVElements<G, V, 3>,
26 E: Tensor,
27 for<'a> &'a C::Residual: Div<C::TangentVv, Output = V>,
28 for<'a> &'a V: Mul<Quantity<Dimensionless>, Output = V> + Mul<Scalar, Output = V>,
29 for<'a> &'a Matrix: Mul<&'a V, Output = Vector>,
30 V: Erase<Erased = E> + Jacobian + Solution,
31 <V as Tensor>::Unit: UnitDiv<<V as Tensor>::Unit, Output = Dimensionless>,
32{
33 fn helmholtz_free_energy(
34 &self,
35 nodal_coordinates: &NodalCoordinates<3>,
36 internal_variables: &InternalVariablesField<G, V>,
37 ) -> Result<Quantity<Energy>, ElementModelError> {
38 self.elements()
39 .iter()
40 .zip(self.connectivity())
41 .zip(internal_variables)
42 .map(|((element, nodes), internal_variables_element)| {
43 element.helmholtz_free_energy(
44 self.constitutive_model(),
45 &Self::element_coordinates(nodal_coordinates, nodes),
46 internal_variables_element,
47 )
48 })
49 .sum::<Result<_, FiniteElementError>>()
50 .map_err(|error| ElementModelError::upstream(error, self))
51 }
52}