conspire/domain/fem/block/solid/elastic_viscoplastic/
mod.rs1use crate::{
2 constitutive::solid::elastic_viscoplastic::ElasticViscoplastic,
3 fem::{
4 ElementModelError, NodalCoordinates,
5 block::{
6 Block,
7 element::{
8 FiniteElementError, solid::elastic_viscoplastic::ElasticViscoplasticFiniteElement,
9 },
10 },
11 solid::{
12 NodalForcesSolid, NodalStiffnessesSolid,
13 elastic_viscoplastic::ElasticViscoplasticElements,
14 },
15 },
16 math::{
17 Scalar, Tensor, TensorTupleListVec, TensorTupleListVec2D, optimize::EqualityConstraint,
18 },
19 mechanics::DeformationGradientPlastic,
20};
21use std::array::from_fn;
22
23pub type ViscoplasticStateVariables<const G: usize, Y> =
24 TensorTupleListVec<DeformationGradientPlastic, Y, G>;
25
26pub type ViscoplasticStateVariablesHistory<const G: usize, Y> =
27 TensorTupleListVec2D<DeformationGradientPlastic, Y, G>;
28
29pub type ElasticViscoplasticBCs = fn(Scalar) -> EqualityConstraint;
30
31impl<C, F, const G: usize, const M: usize, const N: usize, const P: usize, Y>
32 ElasticViscoplasticElements<ViscoplasticStateVariables<G, Y>, 3> for Block<C, F, G, M, N, P>
33where
34 C: ElasticViscoplastic<Y>,
35 F: ElasticViscoplasticFiniteElement<C, G, M, N, P, Y>,
36 Y: Tensor,
37{
38 fn initial_state(&self) -> ViscoplasticStateVariables<G, Y> {
39 self.elements()
40 .iter()
41 .map(|_| from_fn(|_| self.constitutive_model().initial_state()).into())
42 .collect()
43 }
44 fn nodal_forces_into(
45 &self,
46 nodal_coordinates: &NodalCoordinates<3>,
47 state_variables: &ViscoplasticStateVariables<G, Y>,
48 nodal_forces: &mut NodalForcesSolid<3>,
49 ) -> Result<(), ElementModelError> {
50 match self
51 .elements()
52 .iter()
53 .zip(self.connectivity())
54 .zip(state_variables)
55 .try_for_each(|((element, nodes), state_variables_element)| {
56 element
57 .nodal_forces(
58 self.constitutive_model(),
59 &Self::element_coordinates(nodal_coordinates, nodes),
60 state_variables_element,
61 )?
62 .into_iter()
63 .zip(nodes)
64 .for_each(|(nodal_force, &node)| nodal_forces[node] += nodal_force);
65 Ok::<(), FiniteElementError>(())
66 }) {
67 Ok(()) => Ok(()),
68 Err(error) => Err(ElementModelError::Upstream(
69 format!("{error}"),
70 format!("{self:?}"),
71 )),
72 }
73 }
74 fn nodal_stiffnesses_into(
75 &self,
76 nodal_coordinates: &NodalCoordinates<3>,
77 state_variables: &ViscoplasticStateVariables<G, Y>,
78 nodal_stiffnesses: &mut NodalStiffnessesSolid<3>,
79 ) -> Result<(), ElementModelError> {
80 match self
81 .elements()
82 .iter()
83 .zip(self.connectivity())
84 .zip(state_variables)
85 .try_for_each(|((element, nodes), state_variables_element)| {
86 element
87 .nodal_stiffnesses(
88 self.constitutive_model(),
89 &Self::element_coordinates(nodal_coordinates, nodes),
90 state_variables_element,
91 )?
92 .into_iter()
93 .zip(nodes)
94 .for_each(|(object, &node_a)| {
95 object
96 .into_iter()
97 .zip(nodes)
98 .for_each(|(nodal_stiffness, &node_b)| {
99 nodal_stiffnesses[node_a][node_b] += nodal_stiffness
100 })
101 });
102 Ok::<(), FiniteElementError>(())
103 }) {
104 Ok(()) => Ok(()),
105 Err(error) => Err(ElementModelError::Upstream(
106 format!("{error}"),
107 format!("{self:?}"),
108 )),
109 }
110 }
111 fn state_variables_evolution(
112 &self,
113 nodal_coordinates: &NodalCoordinates<3>,
114 state_variables: &ViscoplasticStateVariables<G, Y>,
115 ) -> Result<ViscoplasticStateVariables<G, Y>, ElementModelError> {
116 match self
117 .elements()
118 .iter()
119 .zip(self.connectivity())
120 .zip(state_variables)
121 .map(|((element, nodes), element_state_variables)| {
122 element.state_variables_evolution(
123 self.constitutive_model(),
124 &Self::element_coordinates(nodal_coordinates, nodes),
125 element_state_variables,
126 )
127 })
128 .collect()
129 {
130 Ok(state_variables_evolution) => Ok(state_variables_evolution),
131 Err(error) => Err(ElementModelError::Upstream(
132 format!("{error}"),
133 format!("{self:?}"),
134 )),
135 }
136 }
137}