use crate::BasicComponent;
use crate::ComponentRef;
use crate::ConnectionRef;
use crate::EquationRef;
use crate::NetRef;
use crate::RspiceError;
use crate::TransientMatrix;
use crate::TransientResult;
use crate::TransientVector;
pub struct Circuit {
n_nets: usize,
n_components: usize,
n_connections: usize,
components: Vec<(Box<dyn BasicComponent>, Vec<usize>, usize)>,
nets: Vec<Vec<usize>>,
}
impl Circuit {
pub fn new() -> Self {
Self {
n_nets: 0,
n_components: 0,
n_connections: 0,
components: Vec::new(),
nets: Vec::new(),
}
}
pub fn createNet(&mut self) -> NetRef {
let index = self.n_nets;
self.n_nets += 1;
self.nets.push(Vec::new());
NetRef { index: index }
}
pub fn createBasicComponent(
&mut self,
mut component: Box<dyn BasicComponent>,
nets: Vec<NetRef>,
) -> ComponentRef {
self.n_components += 1;
let mut raw_nets = Vec::new();
let mut connections = Vec::new();
let mut raw_connections = Vec::new();
let mut equations = Vec::new();
let first_connection = self.n_connections;
for net in &nets {
raw_nets.push(net.index);
connections.push(ConnectionRef {
index: self.n_connections,
});
raw_connections.push(self.n_connections);
equations.push(EquationRef {
index: self.n_connections * 2,
});
equations.push(EquationRef {
index: self.n_connections * 2 + 1,
});
self.nets[net.index].push(self.n_connections);
self.n_connections += 1;
}
component.initCircuit(nets, connections, equations);
self.components
.push((component, raw_nets, first_connection));
ComponentRef {
connections: raw_connections,
}
}
pub fn performTransientAnalysis(
&mut self,
duration: f64,
step: f64,
) -> Result<TransientResult, RspiceError> {
let mut matrix = TransientMatrix::new(self.n_nets, self.n_connections);
for net in 0..self.n_nets {
for connection in &self.nets[net] {
*matrix.raw_current_term(net * 2, *connection) = 1.0;
}
for connection in &self.nets[net] {
*matrix.raw_current_derivative_term(net * 2 + 1, *connection) = 1.0;
}
}
for component in &mut self.components {
component.0.initTransient(&mut matrix);
}
let mut result = Vec::new();
let mut t = 0.0;
loop {
let result_at_t = matrix.solve()?;
result.push(result_at_t.clone());
if t >= duration {
break;
}
let wrapped_result = TransientVector::new(result_at_t.into(), self.n_nets);
for component in &mut self.components {
component
.0
.updateTransient(&mut matrix, &wrapped_result, t, step);
}
t += step;
}
let mut result_components = Vec::new();
for component in &self.components {
result_components.push((component.1.clone(), component.2));
}
Ok(TransientResult {
values_over_time: result,
step: step,
n_nets: self.n_nets,
components: result_components,
})
}
}