conspire/domain/fem/
mod.rs

1//! Finite element library.
2
3pub mod block;
4pub mod solid;
5
6use crate::{
7    math::{
8        TensorRank1Vec2D,
9        optimize::{EqualityConstraint, FirstOrderRootFinding, OptimizationError},
10    },
11    mechanics::Coordinates,
12};
13use std::fmt::{self, Debug, Display, Formatter};
14
15pub type NodalCoordinates = Coordinates<1>;
16pub type NodalCoordinatesHistory = TensorRank1Vec2D<3, 1>;
17pub type NodalReferenceCoordinates = Coordinates<0>;
18pub type NodalVelocities = Coordinates<1>;
19pub type NodalVelocitiesHistory = TensorRank1Vec2D<3, 1>;
20
21// Consider using a model-to-block node map to avoid all the extra allocations/operations in nodal_forces etc.
22// Would need to use a new trait for Blocks with the map in the receiver, and keep those maps in a Model field.
23// Try to compare the performance before and after before making a decision.
24
25// need to move solve routines from block to model
26// would then need to change how unit tests work
27
28// want to have mixed-C cases (viscoelastic + elastic) solve differently
29// will have like (B1: Elastic, B2: Viscoelastic) => ViscoelasticFiniteElementModel
30// just like constutituve/hybrid, and will have to impl combos specifically
31
32#[derive(Debug)]
33pub struct Model<B> {
34    // blocks: B,
35    // coordinates: NodalReferenceCoordinates,
36    pub blocks: B,
37    pub coordinates: NodalReferenceCoordinates,
38    // pub is temporary until From<...> is implemented
39}
40
41#[derive(Debug)]
42pub struct Blocks<B1, B2>(pub B1, pub B2); // pub is temporary
43
44pub struct Connectivities<C1, C2>(C1, C2);
45
46pub trait FiniteElementModel
47where
48    Self: Debug,
49{
50    fn coordinates(&self) -> &NodalReferenceCoordinates;
51}
52
53impl<B> FiniteElementModel for Model<B>
54where
55    B: Debug,
56{
57    fn coordinates(&self) -> &NodalReferenceCoordinates {
58        &self.coordinates
59    }
60}
61
62pub enum FiniteElementModelError {
63    Upstream(String, String),
64}
65
66impl Debug for FiniteElementModelError {
67    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
68        let error = match self {
69            Self::Upstream(error, model) => {
70                format!(
71                    "{error}\x1b[0;91m\n\
72                    In finite element model: {model}."
73                )
74            }
75        };
76        write!(f, "{error}\x1b[0m")
77    }
78}
79
80impl Display for FiniteElementModelError {
81    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
82        let error = match self {
83            Self::Upstream(error, model) => {
84                format!(
85                    "{error}\x1b[0;91m\n\
86                    In finite element model: {model}."
87                )
88            }
89        };
90        write!(f, "{error}\x1b[0m")
91    }
92}
93
94impl From<FiniteElementModelError> for String {
95    fn from(error: FiniteElementModelError) -> Self {
96        match error {
97            FiniteElementModelError::Upstream(error, model) => {
98                format!(
99                    "{error}\x1b[0;91m\n\
100                    In finite element model: {model}."
101                )
102            }
103        }
104    }
105}
106
107pub trait FirstOrderRoot<F, J, X> {
108    fn root(
109        &self,
110        equality_constraint: EqualityConstraint,
111        solver: impl FirstOrderRootFinding<F, J, X>,
112    ) -> Result<X, OptimizationError>;
113}