rspice 0.1.0

Pure-Rust circuit simulation backend
Documentation
use crate::BasicComponent;
use crate::ComponentRef;
use crate::ConnectionRef;
use crate::NetRef;

/// The result of running a transient simulation.
///
/// Can be queried for voltages and currents at different points in time.
pub struct TransientResult {
    // for each time point, a vector of values as appearing in the matrix
    pub(crate) values_over_time: Vec<Vec<f64>>,
    pub(crate) step: f64,
    pub(crate) n_nets: usize,
    // basic component, list of connected nets, index of first connection
    pub(crate) components: Vec<(Vec<usize>, usize)>,
}

impl TransientResult {
    fn voltage_at_step(&self, net: NetRef, step: usize) -> f64 {
        self.values_over_time[step][net.index * 2]
    }

    pub fn voltage_at(&self, net: NetRef, time: f64) -> f64 {
        let prev = (time / self.step).floor() as usize;
        let next = (time / self.step).ceil() as usize;
        let voltage_at_prev = self.voltage_at_step(net, prev);
        if prev == next {
            voltage_at_prev
        } else {
            let voltage_at_next = self.voltage_at_step(net, next);
            let x = time / self.step - prev as f64;
            x * voltage_at_next + (1. - x) * voltage_at_prev
        }
    }

    fn current_at_step(&self, component: &ComponentRef, terminal: usize, step: usize) -> f64 {
        self.values_over_time[step][(self.n_nets + component.connections[terminal]) * 2]
    }

    pub fn current_at(&self, component: &ComponentRef, terminal: usize, time: f64) -> f64 {
        let prev = (time / self.step).floor() as usize;
        let next = (time / self.step).ceil() as usize;
        let current_at_prev = self.current_at_step(component, terminal, prev);
        if prev == next {
            current_at_prev
        } else {
            let current_at_next = self.current_at_step(component, terminal, next);
            let x = time / self.step - prev as f64;
            x * current_at_next + (1. - x) * current_at_prev
        }
    }

    pub fn connected_net(&self, connection: &ConnectionRef) -> NetRef {
        for component in &self.components {
            let index = connection.index - component.1;
            if index < component.0.len() {
                return NetRef {
                    index: component.0[index],
                };
            }
        }
        panic!();
    }
}