RatRod_rs/
model.rs

1use std::{collections::HashMap, rc::Rc, fs::{self, File}, process::exit, io::Write};
2
3use sparse_matrix::{matrix::coo_mat::CooMat, vector::Vector};
4
5use crate::{elements::{Element, ElementType, truss::Truss, beam::Beam, ElementTrait}, node::Node, material::Material, section::Section};
6
7use serde::{Serialize, Deserialize};
8
9use serde_json_any_key::any_key_map;
10
11#[derive(Debug, Serialize, Deserialize, PartialEq)]
12pub struct Model{
13    pub epsilon                 :   f64,
14    pub dimension               :   u8,
15    pub degrees_of_freedom      :   u8,
16    pub f                       :   Vector, 
17    pub u                       :   Vector, 
18    pub m                       :   CooMat, 
19    pub f_r                     :   Vector, 
20    pub u_r                     :   Vector, 
21    pub m_r                     :   CooMat, 
22    pub u_boundary_conditions   :   Vec<Option<f64>>,
23    #[serde(with = "any_key_map")]
24    pub elements                :   HashMap<Vec<usize>,Box<Element>>,
25    pub nodes                   :   Vec<Rc<Node>>,
26    pub materials               :   Vec<Rc<Material>>,
27    pub sections                :   Vec<Rc<Section>>
28}
29
30impl Model{
31    pub fn new(dim : u8, epsilon : f64) -> Self{
32        let dof = match dim {
33            1 => 1,
34            2 => 3,
35            3 => 6,
36            _ => panic!()
37        };
38        Model {
39            epsilon,
40            degrees_of_freedom      :   dof,
41            dimension               :   dim,
42            f                       :   Vector::null(0),
43            u                       :   Vector::null(0),
44            m                       :   CooMat::new(0, 0),
45            f_r                     :   Vector::null(0),
46            u_r                     :   Vector::null(0),
47            m_r                     :   CooMat::new(0,0),
48            u_boundary_conditions   :   vec![],
49            elements                :   HashMap::new(),
50            nodes                   :   vec![],
51            materials               :   vec![],
52            sections                :   vec![]
53        }
54    }
55
56    pub fn save(&self, file: &str) {
57        let to_write = serde_json::to_string(&self).expect("Unable to serialize model");
58        fs::write(file, to_write).expect("Unable to write file");
59    }
60
61    pub fn load(file: &str) -> Self {
62        let file_content = fs::read_to_string(file).expect("Unable to read file");
63        serde_json::from_str(&file_content).expect("Unable to process the file")
64    }
65
66    pub fn add_element(&mut self, element : ElementType, nodes : Vec<usize>, material : usize, section : usize) -> &mut Self{
67        self.elements.insert(nodes.clone(), Box::new(
68                match element {
69                    ElementType::Truss => Element::Truss(Truss { nodes : (self.nodes[nodes[0]].clone(), self.nodes[nodes[1]].clone()), material : self.materials[material].clone(), section : self.sections[section].clone()}),
70                    ElementType::Beam => Element::Beam(Beam { nodes : (self.nodes[nodes[0]].clone(), self.nodes[nodes[1]].clone()), material : self.materials[material].clone(), section : self.sections[section].clone()})
71                }));
72        self
73    }
74
75    pub fn add_node(&mut self, node : Node) -> &mut Self {
76        self.nodes.push(Rc::new(node));
77        self.m.rows += self.degrees_of_freedom as usize;
78        self.m.columns += self.degrees_of_freedom as usize;
79        for _ in 0..self.degrees_of_freedom{
80            self.f.values.push(0.);
81            self.u.values.push(0.);
82            self.u_boundary_conditions.push(None);
83        }
84        self
85    }
86
87    pub fn add_material(&mut self, material : Material) -> &mut Self {
88        self.materials.push(Rc::new(material));
89        self
90    }
91
92    pub fn add_section(&mut self, section : Section) -> &mut Self {
93        self.sections.push(Rc::new(section));
94        self
95    }
96
97    pub fn solve(&mut self) -> &mut Self{
98        for (nodes, element) in &self.elements {
99            self.m += element.get_matrix(self.dimension, self.m.rows, nodes);
100        }
101        self.reduce();
102        let p_r = self.m_r.to_csr();
103        self.u_r = p_r.minres(&self.f_r, self.epsilon).unwrap();
104        self.developp();
105        let problem = self.m.to_csr();
106        self.f = (&problem * &self.u).unwrap();
107        self
108    }
109
110    pub fn reduce(&mut self) -> &mut Self {
111        self.m_r  = self.m.clone();
112        let mut reduced_vector = vec![];
113        let mut j = 0;
114        for i in 0..self.u_boundary_conditions.len(){
115            if self.u_boundary_conditions[i] != None {
116                self.m_r.drop_row(j);
117                self.m_r.drop_col(j);
118                self.m_r.rows -= 1;
119                self.m_r.columns -= 1;
120            } else {
121                reduced_vector.push(self.f.values[i]);
122                j+=1;
123            }
124        }
125        self.f_r = Vector { values : reduced_vector };
126        self
127    }
128
129    pub fn developp(&mut self) -> &mut Self {
130        let mut j = 0;
131        for i in 0..self.u_boundary_conditions.len(){
132            match self.u_boundary_conditions[i] {
133                Some(value) => self.u.values[i] = value,
134                None => {
135                    self.u.values[i] = self.u_r.values[j];
136                    j+=1;
137                },
138            }
139        }
140        self
141    }
142
143    pub fn add_u_boundary_condition(&mut self, node : usize, field : u8, value : f64) -> &mut Self {
144        self.u_boundary_conditions[self.degrees_of_freedom  as usize * node + field as usize] = Some(value);
145        self
146    }
147
148    pub fn remove_u_boundary_condition(&mut self, node : usize, field : u8) -> &mut Self {
149        self.u_boundary_conditions[self.degrees_of_freedom  as usize * node + field as usize] = None;
150        self
151    }
152
153    pub fn set_force(&mut self, node : usize, field : u8, value : f64) -> &mut Self{
154        self.f.values[self.degrees_of_freedom as usize * node + field as usize] = value;
155        self
156    }
157}