PySpice-org / PySpice

Simulate electronic circuit using Python and the Ngspice / Xyce simulators
https://pyspice.fabrice-salvaire.fr
GNU General Public License v3.0
652 stars 170 forks source link

PySpice duplicate declaration error in multithread parallel setting #322

Open YuxinPan opened 2 years ago

YuxinPan commented 2 years ago

Environment (OS, Python version, PySpice version, simulator)

Ubuntu 20.04, Python 3.9.7, PySpice 1.5

Expected Behaviour

Work with Python Thread for parallel circuit simulation

Actual Behaviour

Exception in thread Thread-9:
Traceback (most recent call last):
  File "/home/kyle/anaconda3/lib/python3.9/threading.py", line 973, in _bootstrap_inner
    self.run()
  File "/home/kyle/anaconda3/lib/python3.9/threading.py", line 910, in run
    self._target(*self._args, **self._kwargs)
  File "/tmp/ipykernel_621643/3113114828.py", line 15, in sim_thread
  File "/home/kyle/anaconda3/lib/python3.9/site-packages/PySpice/Spice/Netlist.py", line 1292, in simulator
    return CircuitSimulator.factory(self, *args, **kwargs)
  File "/home/kyle/anaconda3/lib/python3.9/site-packages/PySpice/Spice/Simulation.py", line 1167, in factory
    return sub_cls(circuit, *args, **kwargs)
  File "/home/kyle/anaconda3/lib/python3.9/site-packages/PySpice/Spice/NgSpice/Simulation.py", line 99, in __init__
    self._ngspice_shared = NgSpiceShared.new_instance()
  File "/home/kyle/anaconda3/lib/python3.9/site-packages/PySpice/Spice/NgSpice/Shared.py", line 449, in new_instance
    instance = cls(ngspice_id=ngspice_id, send_data=send_data, verbose=verbose)
  File "/home/kyle/anaconda3/lib/python3.9/site-packages/PySpice/Spice/NgSpice/Shared.py", line 479, in __init__
    self._load_library(verbose)
  File "/home/kyle/anaconda3/lib/python3.9/site-packages/PySpice/Spice/NgSpice/Shared.py", line 533, in _load_library
    ffi.cdef(fh.read())
  File "/home/kyle/anaconda3/lib/python3.9/site-packages/cffi/api.py", line 112, in cdef
    self._cdef(csource, override=override, packed=packed, pack=pack)
  File "/home/kyle/anaconda3/lib/python3.9/site-packages/cffi/api.py", line 126, in _cdef
    self._parser.parse(csource, override=override, **options)
  File "/home/kyle/anaconda3/lib/python3.9/site-packages/cffi/cparser.py", line 389, in parse
    self._internal_parse(csource)
  File "/home/kyle/anaconda3/lib/python3.9/site-packages/cffi/cparser.py", line 428, in _internal_parse
    realtype, quals = self._get_type_and_quals(
  File "/home/kyle/anaconda3/lib/python3.9/site-packages/cffi/cparser.py", line 674, in _get_type_and_quals
    tp = self._get_struct_union_enum_type('struct', type, name)
  File "/home/kyle/anaconda3/lib/python3.9/site-packages/cffi/cparser.py", line 821, in _get_struct_union_enum_type
    raise CDefError("duplicate declaration of struct %s" % name)
cffi.CDefError: <cdef source string>:7: duplicate declaration of struct ngcomplex

Steps to reproduce the behaviour

The minimally required code to reproduce this error is attached below:

from threading import Thread
from PySpice.Spice.Netlist import Circuit
from PySpice.Unit import *

def sim_thread(index):
    circuit = Circuit('Resistor Bridge')

    circuit.V('input', 1, circuit.gnd, 10@u_V)
    circuit.R(1, 1, 2, 2@u_kΩ)
    circuit.R(2, 1, 3, 1@u_kΩ)
    circuit.R(3, 2, circuit.gnd, 1@u_kΩ)
    circuit.R(4, 3, circuit.gnd, 2@u_kΩ)
    circuit.R(5, 3, 2, 2@u_kΩ)

    simulator = circuit.simulator(temperature=25, nominal_temperature=25)
    analysis = simulator.operating_point()

threads = [None] * 2

for i in range(len(threads)):
    threads[i] = Thread(target=sim_thread, args=(i,))
    threads[i].start()

for i in range(len(threads)):
    threads[i].join()

Note that the above code works when only 1 thread is called, indicating that the setup and environment are functioning (not an issue with single thread code).

YuxinPan commented 2 years ago

Hi @FabriceSalvaire !

I am wondering if you are aware of any successful implementation of PySpice simulation in multi-thread envorinment?

Thanks a lot.