Skip to main content

conspire/domain/fem/
mod.rs

1//! Finite element library.
2
3pub mod block;
4mod from;
5pub mod solid;
6pub mod thermal;
7
8use crate::math::{
9    Style, StyledError, TensorRank1Vec, TensorRank1Vec2D,
10    assert::AssertionError,
11    optimize::{
12        EqualityConstraint, FirstOrderOptimization, FirstOrderRootFinding, OptimizationError,
13        SecondOrderOptimization, ZerothOrderRootFinding,
14    },
15    styled_error,
16};
17use std::fmt::Debug;
18
19pub type NodalCoordinates<const D: usize> = TensorRank1Vec<D, 1>;
20pub type NodalCoordinatesHistory<const D: usize> = TensorRank1Vec2D<D, 1>;
21pub type NodalReferenceCoordinates<const D: usize> = TensorRank1Vec<D, 0>;
22pub type NodalVelocities<const D: usize> = TensorRank1Vec<D, 1>;
23pub type NodalVelocitiesHistory<const D: usize> = TensorRank1Vec2D<D, 1>;
24
25#[derive(Debug)]
26pub struct Model<B, const D: usize> {
27    blocks: B,
28    coordinates: NodalReferenceCoordinates<D>,
29}
30
31#[derive(Debug)]
32pub struct Blocks<B1, B2>(B1, B2);
33
34#[derive(Debug)]
35pub struct ElasticViscoplasticAndElastic<B1, B2>(B1, B2);
36
37pub trait ElementModel<const D: usize>
38where
39    Self: Debug,
40{
41    fn coordinates(&self) -> &NodalReferenceCoordinates<D>;
42}
43
44pub trait Elements
45where
46    Self: Debug,
47{
48    fn node_neighbors(&self, neighbors: &mut [Vec<usize>]);
49}
50
51impl<B, const D: usize> Elements for Model<B, D>
52where
53    B: Elements,
54{
55    fn node_neighbors(&self, neighbors: &mut [Vec<usize>]) {
56        self.blocks.node_neighbors(neighbors)
57    }
58}
59
60impl<B1, B2> Elements for Blocks<B1, B2>
61where
62    B1: Elements,
63    B2: Elements,
64{
65    fn node_neighbors(&self, neighbors: &mut [Vec<usize>]) {
66        self.0.node_neighbors(neighbors);
67        self.1.node_neighbors(neighbors)
68    }
69}
70
71impl<B1, B2> Elements for ElasticViscoplasticAndElastic<B1, B2>
72where
73    B1: Elements,
74    B2: Elements,
75{
76    fn node_neighbors(&self, neighbors: &mut [Vec<usize>]) {
77        self.0.node_neighbors(neighbors);
78        self.1.node_neighbors(neighbors)
79    }
80}
81
82impl<B, const D: usize> Model<B, D> {
83    pub fn blocks(&self) -> &B {
84        &self.blocks
85    }
86}
87
88impl<B, const D: usize> ElementModel<D> for Model<B, D>
89where
90    B: Debug,
91{
92    fn coordinates(&self) -> &NodalReferenceCoordinates<D> {
93        &self.coordinates
94    }
95}
96
97pub enum ElementModelError {
98    Upstream(String, String),
99}
100
101impl From<ElementModelError> for String {
102    fn from(error: ElementModelError) -> Self {
103        error.message(&Style::detect())
104    }
105}
106
107impl StyledError for ElementModelError {
108    fn message(&self, style: &Style) -> String {
109        let c = style.frame;
110        match self {
111            Self::Upstream(error, model) => format!(
112                "{error}{c}\n\
113                In element model: {model}."
114            ),
115        }
116    }
117}
118
119styled_error!(ElementModelError);
120
121pub trait ZerothOrderRoot<X> {
122    fn root(
123        &self,
124        equality_constraint: EqualityConstraint,
125        solver: impl ZerothOrderRootFinding<X>,
126    ) -> Result<X, OptimizationError>;
127}
128
129pub trait FirstOrderRoot<F, J, X> {
130    fn root(
131        &self,
132        equality_constraint: EqualityConstraint,
133        solver: impl FirstOrderRootFinding<F, J, X>,
134    ) -> Result<X, OptimizationError>;
135}
136
137pub trait FirstOrderMinimize<F, X> {
138    fn minimize(
139        &self,
140        equality_constraint: EqualityConstraint,
141        solver: impl FirstOrderOptimization<F, X>,
142    ) -> Result<X, OptimizationError>;
143}
144
145pub trait SecondOrderMinimize<F, J, H, X> {
146    fn minimize(
147        &self,
148        equality_constraint: EqualityConstraint,
149        solver: impl SecondOrderOptimization<F, J, H, X>,
150    ) -> Result<X, OptimizationError>;
151}
152
153impl<B, const D: usize> From<(B, NodalReferenceCoordinates<D>)> for Model<B, D> {
154    fn from((blocks, coordinates): (B, NodalReferenceCoordinates<D>)) -> Self {
155        Self {
156            blocks,
157            coordinates,
158        }
159    }
160}
161
162impl From<ElementModelError> for AssertionError {
163    fn from(error: ElementModelError) -> Self {
164        Self {
165            message: error.to_string(),
166        }
167    }
168}