conspire/domain/fem/block/element/solid/elastic_viscoplastic/
mod.rs1use crate::{
2 constitutive::solid::elastic_viscoplastic::ElasticViscoplastic,
3 fem::block::element::{
4 Element, ElementNodalCoordinates, FiniteElement, FiniteElementError,
5 solid::{
6 ElementNodalForcesSolid, ElementNodalStiffnessesSolid, SolidFiniteElement,
7 viscoplastic::ViscoplasticStateVariables,
8 },
9 },
10 math::{ContractSecondFourthIndicesWithFirstIndicesOf, Tensor},
11 mechanics::{FirstPiolaKirchhoffStressList, FirstPiolaKirchhoffTangentStiffnessList},
12};
13
14pub trait ElasticViscoplasticFiniteElement<
15 C,
16 const G: usize,
17 const M: usize,
18 const N: usize,
19 const P: usize,
20> where
21 C: ElasticViscoplastic,
22 Self: SolidFiniteElement<G, M, N, P>,
23{
24 fn nodal_forces(
25 &self,
26 constitutive_model: &C,
27 nodal_coordinates: &ElementNodalCoordinates<N>,
28 state_variables: &ViscoplasticStateVariables<G>,
29 ) -> Result<ElementNodalForcesSolid<N>, FiniteElementError>;
30 fn nodal_stiffnesses(
31 &self,
32 constitutive_model: &C,
33 nodal_coordinates: &ElementNodalCoordinates<N>,
34 state_variables: &ViscoplasticStateVariables<G>,
35 ) -> Result<ElementNodalStiffnessesSolid<N>, FiniteElementError>;
36 fn state_variables_evolution(
37 &self,
38 constitutive_model: &C,
39 nodal_coordinates: &ElementNodalCoordinates<N>,
40 state_variables: &ViscoplasticStateVariables<G>,
41 ) -> Result<ViscoplasticStateVariables<G>, FiniteElementError>;
42}
43
44impl<C, const G: usize, const N: usize, const O: usize, const P: usize>
45 ElasticViscoplasticFiniteElement<C, G, 3, N, P> for Element<G, N, O>
46where
47 C: ElasticViscoplastic,
48 Self: SolidFiniteElement<G, 3, N, P>,
49{
50 fn nodal_forces(
51 &self,
52 constitutive_model: &C,
53 nodal_coordinates: &ElementNodalCoordinates<N>,
54 state_variables: &ViscoplasticStateVariables<G>,
55 ) -> Result<ElementNodalForcesSolid<N>, FiniteElementError> {
56 match self
57 .deformation_gradients(nodal_coordinates)
58 .iter()
59 .zip(state_variables)
60 .map(|(deformation_gradient, state_variable)| {
61 let (deformation_gradient_p, _) = state_variable.into();
62 constitutive_model
63 .first_piola_kirchhoff_stress(deformation_gradient, deformation_gradient_p)
64 })
65 .collect::<Result<FirstPiolaKirchhoffStressList<G>, _>>()
66 {
67 Ok(first_piola_kirchhoff_stresses) => Ok(first_piola_kirchhoff_stresses
68 .iter()
69 .zip(
70 self.gradient_vectors()
71 .iter()
72 .zip(self.integration_weights()),
73 )
74 .map(
75 |(first_piola_kirchhoff_stress, (gradient_vectors, integration_weight))| {
76 gradient_vectors
77 .iter()
78 .map(|gradient_vector| {
79 (first_piola_kirchhoff_stress * gradient_vector)
80 * integration_weight
81 })
82 .collect()
83 },
84 )
85 .sum()),
86 Err(error) => Err(FiniteElementError::Upstream(
87 format!("{error}"),
88 format!("{self:?}"),
89 )),
90 }
91 }
92 fn nodal_stiffnesses(
93 &self,
94 constitutive_model: &C,
95 nodal_coordinates: &ElementNodalCoordinates<N>,
96 state_variables: &ViscoplasticStateVariables<G>,
97 ) -> Result<ElementNodalStiffnessesSolid<N>, FiniteElementError> {
98 match self
99 .deformation_gradients(nodal_coordinates)
100 .iter()
101 .zip(state_variables)
102 .map(|(deformation_gradient, state_variable)| {
103 let (deformation_gradient_p, _) = state_variable.into();
104 constitutive_model.first_piola_kirchhoff_tangent_stiffness(
105 deformation_gradient,
106 deformation_gradient_p,
107 )
108 })
109 .collect::<Result<FirstPiolaKirchhoffTangentStiffnessList<G>, _>>()
110 {
111 Ok(first_piola_kirchhoff_tangent_stiffnesses) => {
112 Ok(first_piola_kirchhoff_tangent_stiffnesses
113 .iter()
114 .zip(
115 self.gradient_vectors()
116 .iter()
117 .zip(self.integration_weights()),
118 )
119 .map(
120 |(
121 first_piola_kirchhoff_tangent_stiffness,
122 (gradient_vectors, integration_weight),
123 )| {
124 gradient_vectors
125 .iter()
126 .map(|gradient_vector_a| {
127 gradient_vectors
128 .iter()
129 .map(|gradient_vector_b| {
130 first_piola_kirchhoff_tangent_stiffness
131 .contract_second_fourth_indices_with_first_indices_of(
132 gradient_vector_a,
133 gradient_vector_b,
134 )
135 * integration_weight
136 })
137 .collect()
138 })
139 .collect()
140 },
141 )
142 .sum())
143 }
144 Err(error) => Err(FiniteElementError::Upstream(
145 format!("{error}"),
146 format!("{self:?}"),
147 )),
148 }
149 }
150 fn state_variables_evolution(
151 &self,
152 constitutive_model: &C,
153 nodal_coordinates: &ElementNodalCoordinates<N>,
154 state_variables: &ViscoplasticStateVariables<G>,
155 ) -> Result<ViscoplasticStateVariables<G>, FiniteElementError> {
156 match self
157 .deformation_gradients(nodal_coordinates)
158 .iter()
159 .zip(state_variables)
160 .map(|(deformation_gradient, state_variable)| {
161 constitutive_model.state_variables_evolution(deformation_gradient, state_variable)
162 })
163 .collect::<Result<ViscoplasticStateVariables<G>, _>>()
164 {
165 Ok(state_variables_evolution) => Ok(state_variables_evolution),
166 Err(error) => Err(FiniteElementError::Upstream(
167 format!("{error}"),
168 format!("{self:?}"),
169 )),
170 }
171 }
172}