conspire/domain/fem/solid/elastic/
mod.rs1use 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}