summaryrefslogtreecommitdiff
path: root/MIL_testing/spice_backend.py
blob: 674ae30267105509d55404418b3f4e6c38c47f86 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
import subprocess
import re

class SpiceBackend:
    """This is what actually does all of the spice stuff"""
    def __init__(self, device_file: str):
        self.conductance = 0
        self.voltage = 0
        self.current = 0
        self.time = 0

    def simulate(self, voltage_signal: float, return_current: bool = False) -> float:
        """runs the simulation for one time step"""
        len_voltage_signal = 1
        try:
            len_voltage_signal = len(voltage_signal)
        except:
            voltage_signal = [voltage_signal]

        if return_current:
            current = np.zeros(len_voltage_signal)

        for t in enumerate(len_voltage_signal):
            result = self.run_spice(voltage_signal)

            single_current = result.current
            self.conductance = result.conductance

            if return_current:
                current[t] = single_current

        if return_current:
            return current


    def set_conductance(self, conductance: float):
        """Handled by spice now"""
        """Could probably still add some safety checks just to be sure later"""
        self.conductance = conductance

    def run_spice(self, voltage: float) -> float:
        """returns the current after given a voltage signal"""
        #need to find a way to pass voltage signal to ngspice here
        #also maybe a time series resolution??
        result = subprocess.run(
                ["ngspice" "-b" "spicefile.cir"],
                capture_output=True,
                text=True
        )
        if result.returncode != 0:
            raise RuntimeError(result.stderr)

        # parse current into float variable
        output = result.stdout
        #is there a better (less rigid) way of grabbing the output
        current_match = re.search("final_current = ([-\deE.+]+)", output)
        if current_match is None:
            raise RuntimeError("Could not find current in ngspice output")

        current = float(current_match.group(1))

        if abs(voltage) > 1e-12:
            conductance = current / voltage
        else:
            conductance = self.conductance

        return {
                "current": current,
                "conductance": conductance,
        }