Skip to main content

conspire/domain/
mod.rs

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