runmat_analysis_fea/assembly/elements/solid/
material.rs1use serde::{Deserialize, Serialize};
2use thiserror::Error;
3
4#[derive(Debug, Clone, Copy, PartialEq, Serialize, Deserialize)]
5pub struct SolidMaterial {
6 pub youngs_modulus_pa: f64,
7 pub poisson_ratio: f64,
8}
9
10pub(super) type ElasticityMatrix = [[f64; 6]; 6];
11
12#[derive(Debug, Error, Clone, PartialEq)]
13pub enum SolidMaterialError {
14 #[error("solid material Young's modulus must be positive and finite")]
15 InvalidYoungsModulus,
16 #[error("solid material Poisson ratio must be finite and in (-1, 0.5)")]
17 InvalidPoissonRatio,
18}
19
20impl SolidMaterial {
21 pub fn validate(self) -> Result<(), SolidMaterialError> {
22 if !self.youngs_modulus_pa.is_finite() || self.youngs_modulus_pa <= 0.0 {
23 return Err(SolidMaterialError::InvalidYoungsModulus);
24 }
25 if !self.poisson_ratio.is_finite()
26 || self.poisson_ratio <= -1.0
27 || self.poisson_ratio >= 0.5
28 {
29 return Err(SolidMaterialError::InvalidPoissonRatio);
30 }
31 Ok(())
32 }
33
34 pub fn lame_lambda_pa(self) -> Result<f64, SolidMaterialError> {
35 self.validate()?;
36 Ok(self.youngs_modulus_pa * self.poisson_ratio
37 / ((1.0 + self.poisson_ratio) * (1.0 - 2.0 * self.poisson_ratio)))
38 }
39
40 pub fn shear_modulus_pa(self) -> Result<f64, SolidMaterialError> {
41 self.validate()?;
42 Ok(self.youngs_modulus_pa / (2.0 * (1.0 + self.poisson_ratio)))
43 }
44}
45
46pub(super) fn elasticity_matrix(
47 material: SolidMaterial,
48) -> Result<ElasticityMatrix, SolidMaterialError> {
49 let lambda = material.lame_lambda_pa()?;
50 let mu = material.shear_modulus_pa()?;
51 let mut matrix = [[0.0; 6]; 6];
52 for (row, diagonal) in matrix.iter_mut().enumerate().take(3) {
53 diagonal[..3].fill(lambda);
54 diagonal[row] += 2.0 * mu;
55 }
56 matrix[3][3] = mu;
57 matrix[4][4] = mu;
58 matrix[5][5] = mu;
59 Ok(matrix)
60}