conspire/domain/fem/solid/elastic/
mod.rs

1use crate::{
2    constitutive::solid::elastic::Elastic,
3    fem::{
4        Blocks, FiniteElementModel, FiniteElementModelError, FirstOrderRoot, Model,
5        NodalCoordinates,
6        block::{
7            Block, element::solid::elastic::ElasticFiniteElement,
8            solid::elastic::ElasticFiniteElementBlock,
9        },
10        solid::{NodalForcesSolid, NodalStiffnessesSolid, SolidFiniteElementModel},
11    },
12    math::optimize::{EqualityConstraint, FirstOrderRootFinding, OptimizationError},
13};
14
15pub trait ElasticFiniteElementModel
16where
17    Self: SolidFiniteElementModel,
18{
19    fn nodal_forces(
20        &self,
21        nodal_coordinates: &NodalCoordinates,
22    ) -> Result<NodalForcesSolid, FiniteElementModelError>;
23    fn nodal_stiffnesses(
24        &self,
25        nodal_coordinates: &NodalCoordinates,
26    ) -> Result<NodalStiffnessesSolid, FiniteElementModelError>;
27}
28
29impl<B> ElasticFiniteElementModel for Model<B>
30where
31    B: ElasticFiniteElementModel,
32{
33    fn nodal_forces(
34        &self,
35        nodal_coordinates: &NodalCoordinates,
36    ) -> Result<NodalForcesSolid, FiniteElementModelError> {
37        self.blocks.nodal_forces(nodal_coordinates)
38    }
39    fn nodal_stiffnesses(
40        &self,
41        nodal_coordinates: &NodalCoordinates,
42    ) -> Result<NodalStiffnessesSolid, FiniteElementModelError> {
43        self.blocks.nodal_stiffnesses(nodal_coordinates)
44    }
45}
46
47impl<B1, B2> ElasticFiniteElementModel for Blocks<B1, B2>
48where
49    B1: ElasticFiniteElementModel,
50    B2: ElasticFiniteElementModel,
51{
52    fn nodal_forces(
53        &self,
54        nodal_coordinates: &NodalCoordinates,
55    ) -> Result<NodalForcesSolid, FiniteElementModelError> {
56        match Ok::<_, FiniteElementModelError>(
57            self.0.nodal_forces(nodal_coordinates)? + self.1.nodal_forces(nodal_coordinates)?,
58        ) {
59            Ok(nodal_forces) => Ok(nodal_forces),
60            Err(error) => Err(FiniteElementModelError::Upstream(
61                format!("{error}"),
62                format!("{self:?}"),
63            )),
64        }
65    }
66    fn nodal_stiffnesses(
67        &self,
68        nodal_coordinates: &NodalCoordinates,
69    ) -> Result<NodalStiffnessesSolid, FiniteElementModelError> {
70        match Ok::<_, FiniteElementModelError>(
71            self.0.nodal_stiffnesses(nodal_coordinates)?
72                + self.1.nodal_stiffnesses(nodal_coordinates)?,
73        ) {
74            Ok(nodal_stiffnesses) => Ok(nodal_stiffnesses),
75            Err(error) => Err(FiniteElementModelError::Upstream(
76                format!("{error}"),
77                format!("{self:?}"),
78            )),
79        }
80    }
81}
82
83impl<C, F, const G: usize, const M: usize, const N: usize, const P: usize> ElasticFiniteElementModel
84    for Block<C, F, G, M, N, P>
85where
86    C: Elastic,
87    F: ElasticFiniteElement<C, G, M, N, P>,
88{
89    fn nodal_forces(
90        &self,
91        nodal_coordinates: &NodalCoordinates,
92    ) -> Result<NodalForcesSolid, FiniteElementModelError> {
93        match ElasticFiniteElementBlock::nodal_forces(self, nodal_coordinates) {
94            Ok(nodal_forces) => Ok(nodal_forces),
95            Err(error) => Err(FiniteElementModelError::Upstream(
96                format!("{error}"),
97                format!("{self:?}"),
98            )),
99        }
100    }
101    fn nodal_stiffnesses(
102        &self,
103        nodal_coordinates: &NodalCoordinates,
104    ) -> Result<NodalStiffnessesSolid, FiniteElementModelError> {
105        match ElasticFiniteElementBlock::nodal_stiffnesses(self, nodal_coordinates) {
106            Ok(nodal_stiffnesses) => Ok(nodal_stiffnesses),
107            Err(error) => Err(FiniteElementModelError::Upstream(
108                format!("{error}"),
109                format!("{self:?}"),
110            )),
111        }
112    }
113}
114
115impl<B> FirstOrderRoot<NodalForcesSolid, NodalStiffnessesSolid, NodalCoordinates> for Model<B>
116where
117    B: ElasticFiniteElementModel,
118{
119    fn root(
120        &self,
121        equality_constraint: EqualityConstraint,
122        solver: impl FirstOrderRootFinding<NodalForcesSolid, NodalStiffnessesSolid, NodalCoordinates>,
123    ) -> Result<NodalCoordinates, OptimizationError> {
124        solver.root(
125            |nodal_coordinates: &NodalCoordinates| Ok(self.nodal_forces(nodal_coordinates)?),
126            |nodal_coordinates: &NodalCoordinates| Ok(self.nodal_stiffnesses(nodal_coordinates)?),
127            self.coordinates().clone().into(),
128            equality_constraint,
129        )
130    }
131}