PySpice-org / PySpice

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

Cannot load library 'libngspice.dylib' macOS #376

Open tommydb26 opened 5 months ago

tommydb26 commented 5 months ago

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

macOS, python3.12, PySpice 1.5

I'm trying to download PySpice on mac, using pip to install PySpice, and homebrew to install ngspice and libngspice. But, anytime I try to run a simulation — like with the following code — I get the following error.

Code:

circuit = Circuit('MyCircuit')
circuit.V('out', 'OUT', circuit.gnd, 13330)
circuit.PieceWiseLinearCurrentSource('in', circuit.gnd, 'IN', list(zip(t, q)))

for node in G.nodes:
    n = G.nodes[node]
    if n['kind'] in ('R', 'L', 'C'):
        pals = list(nx.neighbors(G, node))
        assert len(pals) == 2, node
        pals = list(map(lambda x: circuit.gnd if x=='GND' else x, pals))
        if n['kind'] == 'R':
            circuit.R(node, *pals, n['R'])
        if n['kind'] == 'C':
            circuit.C(node, *pals, n['C'])
        if n['kind'] == 'L':
            circuit.L(node, *pals, n['L'])

sim = circuit.simulator()
res = sim.transient(step_time=1/fs, end_time=len(t)/fs)

Error: OSError: cannot load library 'libngspice.dylib': dlopen(libngspice.dylib, 0x0002): tried: 'libngspice.dylib' (no such file), '/System/Volumes/Preboot/Cryptexes/OSlibngspice.dylib' (no such file), '/usr/lib/libngspice.dylib' (no such file, not in dyld cache), 'libngspice.dylib' (no such file), '/usr/lib/libngspice.dylib' (no such file, not in dyld cache). Additionally, ctypes.util.find_library() did not manage to locate a library called 'libngspice.dylib'

Please help!

JTSvejda commented 4 months ago

I'm having the same problem on MacOS Sonoma 14.5, Python 3.12.4, PySpice 1.5

I've checked my homebrew installation of ngspice, which itself works if I ran it directly. Within the installation folder I searched for the necessary lib and got the following output, which might be of help to debug the problem:

➜  / find /opt -name libngspice.\*
/opt/homebrew/var/homebrew/locks/libngspice.formula.lock
/opt/homebrew/lib/libngspice.0.dylib
/opt/homebrew/lib/libngspice.dylib
/opt/homebrew/Cellar/libngspice/42/.brew/libngspice.rb
/opt/homebrew/Cellar/libngspice/42/lib/libngspice.0.dylib
/opt/homebrew/Cellar/libngspice/42/lib/libngspice.dylib

I also would love this issue to be solved :)

JTSvejda commented 4 months ago

I've found a workaround. If you installed ngspice for example with homebrew, the lib is located in /opt/homebrew/lib. You can set the macOS environment variable DYLD_LIBRARY_PATH which behaves like LD_LIBRARY_PATH used by dlopen() to include the correct directory. The command would be as follows:

export DYLD_LIBRARY_PATH=$DYLD_LIBRARY_PATH:/opt/homebrew/lib

If you are using vscodium and the debugger, you can add the following to the launch.json:

"env": {
        "DYLD_LIBRARY_PATH": "/opt/homebrew/lib"
      }
ali1234 commented 3 months ago

This happens because of incorrect usage of ctypes.util.find_library. From the documentation:

Try to find a library and return a pathname. name is the library name without any prefix like lib, suffix like .so, .dylib or version number (this is the form used for the posix linker option -l).

PySpice calls it with the argument libngspice.dylib (or libngspice.so on Linux.) This would only work if the library was named liblibngspice.dylib.dylib.