Source code for solcore.spice.spice

""" Solves an electrical circuit using SPICE. The input must be a correctly formated SPICE file and the output will be
the raw result from SPICE or after some processing, depending of what is requested. """

import numpy
import os
import subprocess
import tempfile
import solcore


[docs]class SpiceSolverError(Exception): pass
[docs]class spice: engine = os.environ.get("SOLCORE_SPICE") if os.environ.get("SOLCORE_SPICE") is not None else solcore.config.spice() input_file = "current_spice.cir" output_file = "current_spice.out"
[docs]def solve_circuit(spice_file_contents, engine=spice.engine, raw=True): """ Sends the spice-readable file to the spice engine which will run it and store the data in a temporary folder. Once the process is finished, it collects the data and returns it. If raw=False, this function will return only lines that start with a number. Depending of what was the output, the result might make sense or not. It is safer to ask for the raw data as it allows you to collect all the output from spice and deal with it as convenient, depending on the application. :param spice_file_contents: string formated as a spice-readable file contaning the design of the circuit and the instructions :param engine: the spice engine. :param raw: whether to produce the raw output or after some processing. :return: depending of the value of raw, this might be all the output of spice or just an array of data """ spice.engine = engine if not spice.engine: raise SpiceSolverError("Spice solver not found.") with tempfile.TemporaryDirectory(prefix="tmp", suffix="_sc3NGSPICE") as working_directory: spice_file_path = os.path.join(working_directory, spice.input_file) spice_output_path = os.path.join(working_directory, spice.output_file) with open(spice_file_path, "w") as f: f.write(spice_file_contents) this_process = subprocess.Popen([spice.engine, '-b', spice_file_path, '-o', spice_output_path]) this_process.wait() # this_process = subprocess.run([spice.engine, '-b', spice_file_path, '-o', spice_output_path]) with open(spice_output_path, "r") as f: raw_results = f.read() if raw: # We return all the output return raw_results else: # We return just the lines starting with a number, which is OK in certain simple cases lines = raw_results.split("\n") data = [] for line in lines: if len(line) == 0 or line[0] not in "1234567890.": continue # print (line) i, *rest = line.split() # print (len(rest)) data.append([float(element) for element in rest]) return numpy.array(data).transpose()
[docs]def get_raw_from_spice(spice_file_contents, engine=spice): """ Dummy function included for backwards compatibility with solcore3 """ results = solve_circuit(spice_file_contents, engine) return results
[docs]def send_to_spice(spice_file_contents, engine=spice): """ Dummy function included for backwards compatibility with solcore3 """ results = solve_circuit(spice_file_contents, engine, raw=False) return results
if __name__ == '__main__': import matplotlib.pyplot as plt engine = spice.engine circuit = """Multiple dc sources v1 1 0 r1 1 0 3.3k .dc v1 0 24 1 .print dc i(v1) .end """ data = solve_circuit(circuit, engine=engine, raw=False) print(data) plt.plot(data[0], data[1]) plt.show()