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}