conspire/constitutive/
mod.rs

1//! Constitutive model library.
2
3#[cfg(test)]
4pub mod test;
5
6pub mod fluid;
7pub mod hybrid;
8pub mod multiphysics;
9pub mod solid;
10pub mod thermal;
11
12use crate::{
13    defeat_message,
14    math::{Scalar, TensorError, TestError},
15    mechanics::{Deformation, DeformationError, DeformationGradientGeneral},
16};
17use std::fmt::{self, Debug, Display, Formatter};
18
19/// Required methods for constitutive models.
20pub trait Constitutive
21where
22    Self: Clone + Debug,
23{
24    /// Calculates and returns the Jacobian.
25    fn jacobian<const I: usize, const J: usize>(
26        &self,
27        deformation_gradient: &DeformationGradientGeneral<I, J>,
28    ) -> Result<Scalar, ConstitutiveError> {
29        match deformation_gradient.jacobian() {
30            Err(DeformationError::InvalidJacobian(jacobian)) => Err(
31                ConstitutiveError::InvalidJacobian(jacobian, format!("{self:?}")),
32            ),
33            Ok(jacobian) => Ok(jacobian),
34        }
35    }
36}
37
38/// Possible errors encountered in constitutive models.
39pub enum ConstitutiveError {
40    Custom(String, String),
41    InvalidJacobian(Scalar, String),
42    Upstream(String, String),
43}
44
45impl From<ConstitutiveError> for String {
46    fn from(error: ConstitutiveError) -> Self {
47        match error {
48            ConstitutiveError::Custom(message, constitutive_model) => format!(
49                "\x1b[1;91m{message}\x1b[0;91m\n\
50                        In constitutive model: {constitutive_model}."
51            ),
52            ConstitutiveError::InvalidJacobian(jacobian, constitutive_model) => format!(
53                "\x1b[1;91mInvalid Jacobian: {jacobian:.6e}.\x1b[0;91m\n\
54                        In constitutive model: {constitutive_model}."
55            ),
56            ConstitutiveError::Upstream(error, constitutive_model) => format!(
57                "{error}\x1b[0;91m\n\
58                    In constitutive model: {constitutive_model}."
59            ),
60        }
61    }
62}
63
64impl From<ConstitutiveError> for TestError {
65    fn from(error: ConstitutiveError) -> Self {
66        Self {
67            message: error.to_string(),
68        }
69    }
70}
71
72impl From<TensorError> for ConstitutiveError {
73    fn from(error: TensorError) -> Self {
74        ConstitutiveError::Custom(
75            error.to_string(),
76            "unknown (temporary error handling)".to_string(),
77        )
78    }
79}
80
81impl Debug for ConstitutiveError {
82    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
83        let error = match self {
84            Self::Custom(message, constitutive_model) => format!(
85                "\x1b[1;91m{message}\x1b[0;91m\n\
86                 In constitutive model: {constitutive_model}."
87            ),
88            Self::InvalidJacobian(jacobian, constitutive_model) => {
89                format!(
90                    "\x1b[1;91mInvalid Jacobian: {jacobian:.6e}.\x1b[0;91m\n\
91                    In constitutive model: {constitutive_model}."
92                )
93            }
94            Self::Upstream(error, constitutive_model) => {
95                format!(
96                    "{error}\x1b[0;91m\n\
97                    In constitutive model: {constitutive_model}."
98                )
99            }
100        };
101        write!(f, "\n{}\n\x1b[0;2;31m{}\x1b[0m\n", error, defeat_message())
102    }
103}
104
105impl Display for ConstitutiveError {
106    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
107        let error = match self {
108            Self::Custom(message, constitutive_model) => format!(
109                "\x1b[1;91m{message}\x1b[0;91m\n\
110                 In constitutive model: {constitutive_model}."
111            ),
112            Self::InvalidJacobian(jacobian, constitutive_model) => {
113                format!(
114                    "\x1b[1;91mInvalid Jacobian: {jacobian:.6e}.\x1b[0;91m\n\
115                    In constitutive model: {constitutive_model}."
116                )
117            }
118            Self::Upstream(error, constitutive_model) => {
119                format!(
120                    "{error}\x1b[0;91m\n\
121                    In constitutive model: {constitutive_model}."
122                )
123            }
124        };
125        write!(f, "{error}\x1b[0m")
126    }
127}
128
129impl PartialEq for ConstitutiveError {
130    fn eq(&self, other: &Self) -> bool {
131        match self {
132            Self::Custom(a, b) => match other {
133                Self::Custom(c, d) => a == c && b == d,
134                _ => false,
135            },
136            Self::InvalidJacobian(a, b) => match other {
137                Self::InvalidJacobian(c, d) => a == c && b == d,
138                _ => false,
139            },
140            Self::Upstream(a, b) => match other {
141                Self::Upstream(c, d) => a == c && b == d,
142                _ => false,
143            },
144        }
145    }
146}