1use crate::{
2 constitutive::solid::hyperelastic_viscoplastic::HyperelasticViscoplastic,
3 fem::{
4 NodalCoordinates, NodalCoordinatesHistory,
5 block::{
6 Block, FiniteElementBlockError, band,
7 element::solid::hyperelastic_viscoplastic::HyperelasticViscoplasticFiniteElement,
8 solid::{
9 NodalForcesSolid, NodalStiffnessesSolid,
10 elastic_viscoplastic::{
11 ElasticViscoplasticBCs, ElasticViscoplasticFiniteElementBlock,
12 ViscoplasticStateVariables, ViscoplasticStateVariablesHistory,
13 },
14 },
15 },
16 },
17 math::{
18 Scalar, Tensor,
19 integrate::{ExplicitDaeSecondOrderMinimize, IntegrationError},
20 optimize::SecondOrderOptimization,
21 },
22 mechanics::Times,
23};
24use std::array::from_fn;
25
26pub trait HyperelasticViscoplasticFiniteElementBlock<
27 C,
28 F,
29 const G: usize,
30 const M: usize,
31 const N: usize,
32 const P: usize,
33 Y,
34> where
35 C: HyperelasticViscoplastic<Y>,
36 F: HyperelasticViscoplasticFiniteElement<C, G, M, N, P, Y>,
37 Self: ElasticViscoplasticFiniteElementBlock<C, F, G, M, N, P, Y>,
38 Y: Tensor,
39{
40 fn helmholtz_free_energy(
41 &self,
42 nodal_coordinates: &NodalCoordinates,
43 state_variables: &ViscoplasticStateVariables<G, Y>,
44 ) -> Result<Scalar, FiniteElementBlockError>;
45 fn minimize(
46 &self,
47 integrator: impl ExplicitDaeSecondOrderMinimize<
48 Scalar,
49 NodalForcesSolid,
50 NodalStiffnessesSolid,
51 ViscoplasticStateVariables<G, Y>,
52 NodalCoordinates,
53 ViscoplasticStateVariablesHistory<G, Y>,
54 NodalCoordinatesHistory,
55 >,
56 solver: impl SecondOrderOptimization<
57 Scalar,
58 NodalForcesSolid,
59 NodalStiffnessesSolid,
60 NodalCoordinates,
61 >,
62 time: &[Scalar],
63 bcs: ElasticViscoplasticBCs,
64 ) -> Result<
65 (
66 Times,
67 NodalCoordinatesHistory,
68 ViscoplasticStateVariablesHistory<G, Y>,
69 ),
70 IntegrationError,
71 >;
72}
73
74impl<C, F, const G: usize, const M: usize, const N: usize, const P: usize, Y>
75 HyperelasticViscoplasticFiniteElementBlock<C, F, G, M, N, P, Y> for Block<C, F, G, M, N, P>
76where
77 C: HyperelasticViscoplastic<Y>,
78 F: HyperelasticViscoplasticFiniteElement<C, G, M, N, P, Y>,
79 Self: ElasticViscoplasticFiniteElementBlock<C, F, G, M, N, P, Y>,
80 Y: Tensor,
81{
82 fn helmholtz_free_energy(
83 &self,
84 nodal_coordinates: &NodalCoordinates,
85 state_variables: &ViscoplasticStateVariables<G, Y>,
86 ) -> Result<Scalar, FiniteElementBlockError> {
87 match self
88 .elements()
89 .iter()
90 .zip(self.connectivity())
91 .zip(state_variables)
92 .map(|((element, nodes), state_variables_element)| {
93 element.helmholtz_free_energy(
94 self.constitutive_model(),
95 &Self::element_coordinates(nodal_coordinates, nodes),
96 state_variables_element,
97 )
98 })
99 .sum()
100 {
101 Ok(helmholtz_free_energy) => Ok(helmholtz_free_energy),
102 Err(error) => Err(FiniteElementBlockError::Upstream(
103 format!("{error}"),
104 format!("{self:?}"),
105 )),
106 }
107 }
108 fn minimize(
109 &self,
110 integrator: impl ExplicitDaeSecondOrderMinimize<
111 Scalar,
112 NodalForcesSolid,
113 NodalStiffnessesSolid,
114 ViscoplasticStateVariables<G, Y>,
115 NodalCoordinates,
116 ViscoplasticStateVariablesHistory<G, Y>,
117 NodalCoordinatesHistory,
118 >,
119 solver: impl SecondOrderOptimization<
120 Scalar,
121 NodalForcesSolid,
122 NodalStiffnessesSolid,
123 NodalCoordinates,
124 >,
125 time: &[Scalar],
126 bcs: ElasticViscoplasticBCs,
127 ) -> Result<
128 (
129 Times,
130 NodalCoordinatesHistory,
131 ViscoplasticStateVariablesHistory<G, Y>,
132 ),
133 IntegrationError,
134 > {
135 let banded = band(
136 self.connectivity(),
137 &bcs(time[0]),
138 self.coordinates().len(),
139 3,
140 );
141 let (time_history, state_variables_history, _, nodal_coordinates_history) = integrator
142 .integrate(
143 |_: Scalar,
144 state_variables: &ViscoplasticStateVariables<G, Y>,
145 nodal_coordinates: &NodalCoordinates| {
146 Ok(self.state_variables_evolution(nodal_coordinates, state_variables)?)
147 },
148 |_t: Scalar,
149 state_variables: &ViscoplasticStateVariables<G, Y>,
150 nodal_coordinates: &NodalCoordinates| {
151 Ok(self.helmholtz_free_energy(nodal_coordinates, state_variables)?)
152 },
153 |_t: Scalar,
154 state_variables: &ViscoplasticStateVariables<G, Y>,
155 nodal_coordinates: &NodalCoordinates| {
156 Ok(self.nodal_forces(nodal_coordinates, state_variables)?)
157 },
158 |_t: Scalar,
159 state_variables: &ViscoplasticStateVariables<G, Y>,
160 nodal_coordinates: &NodalCoordinates| {
161 Ok(self.nodal_stiffnesses(nodal_coordinates, state_variables)?)
162 },
163 solver,
164 time,
165 (
166 self.elements()
167 .iter()
168 .map(|_| from_fn(|_| self.constitutive_model().initial_state()).into())
169 .collect(),
170 self.coordinates().clone().into(),
171 ),
172 bcs,
173 Some(banded),
174 )?;
175 Ok((
176 time_history,
177 nodal_coordinates_history,
178 state_variables_history,
179 ))
180 }
181}