ngspice/test_cases/multiple_devices/test_multiple.py

173 lines
4.9 KiB
Python
Raw Permalink Normal View History

""" test OSDI simulation of resistor and capacitor
"""
import os, shutil
import numpy as np
import pandas as pd
2022-05-10 11:22:25 +02:00
import sys
sys.path.append(
os.path.abspath(os.path.join(os.path.dirname(__file__), os.path.pardir)))
2022-05-10 11:22:25 +02:00
from testing import prepare_test
# This test runs a DC, AC and Transient Simulation of a simple resistor and resistor.
# The capacitor and resistor are available as C files and need to be compiled to a shared objects
# and then bet put into /usr/local/share/ngspice/osdi:
#
# > make osdi_resistor
2022-05-07 13:39:16 +02:00
# > cp resistor_osdi.osdi /usr/local/share/ngspice/osdi/resistor_osdi.osdi
# > make osdi_capacitor
2022-05-07 13:39:16 +02:00
# > cp capacitor_osdi.osdi /usr/local/share/ngspice/osdi/capacitor_osdi.osdi
#
# The integration test proves the functioning of the OSDI interface.
# Future tests will target Verilog-A models like HICUM/L2 that should yield exactly the same results as the Ngspice implementation.
2022-05-10 11:22:25 +02:00
directory = os.path.dirname(__file__)
def test_ngspice():
2022-05-10 11:22:25 +02:00
dir_osdi, dir_built_in = prepare_test(directory)
# read DC simulation results
dc_data_osdi = pd.read_csv(os.path.join(dir_osdi, "dc_sim.ngspice"), sep="\\s+")
2022-05-10 11:22:25 +02:00
dc_data_built_in = pd.read_csv(
os.path.join(dir_built_in, "dc_sim.ngspice"), sep="\\s+"
)
id_osdi = dc_data_osdi["i(vsense)"].to_numpy()
2022-05-10 11:22:25 +02:00
id_built_in = dc_data_built_in["i(vsense)"].to_numpy()
# read AC simulation results
ac_data_osdi = pd.read_csv(os.path.join(dir_osdi, "ac_sim.ngspice"), sep="\\s+")
2022-05-10 11:22:25 +02:00
ac_data_built_in = pd.read_csv(
os.path.join(dir_built_in, "ac_sim.ngspice"), sep="\\s+"
)
# read TR simulation results
tr_data_osdi = pd.read_csv(os.path.join(dir_osdi, "tr_sim.ngspice"), sep="\\s+")
2022-05-10 11:22:25 +02:00
tr_data_built_in = pd.read_csv(
os.path.join(dir_built_in, "tr_sim.ngspice"), sep="\\s+"
)
# test simulation results
id_osdi = dc_data_osdi["i(vsense)"].to_numpy()
id_built_in = dc_data_built_in["i(vsense)"].to_numpy()
# np.testing.assert_allclose(id_osdi[0:20], id_built_in[0:20], rtol=0.01)
return (
dc_data_osdi,
dc_data_built_in,
ac_data_osdi,
ac_data_built_in,
tr_data_osdi,
tr_data_built_in,
)
if __name__ == "__main__":
(
dc_data_osdi,
dc_data_built_in,
ac_data_osdi,
ac_data_built_in,
tr_data_osdi,
tr_data_built_in,
) = test_ngspice()
import matplotlib.pyplot as plt
# DC Plot
pd_built_in = dc_data_built_in["v(d)"] * dc_data_built_in["i(vsense)"]
pd_osdi = dc_data_osdi["v(d)"] * dc_data_osdi["i(vsense)"]
fig, ax1 = plt.subplots()
ax1.plot(
dc_data_built_in["v(d)"],
dc_data_built_in["i(vsense)"] * 1e3,
label="built-in",
linestyle=" ",
marker="x",
)
ax1.plot(
dc_data_built_in["v(d)"],
dc_data_built_in["v(d)"] / 10 * 1e3,
label="analytical",
linestyle="--",
marker="s",
)
ax1.plot(
dc_data_osdi["v(d)"],
dc_data_osdi["i(vsense)"] * 1e3,
label="OSDI",
)
ax1.set_ylabel(r"$I_{\mathrm{P}} (\mathrm{mA})$")
ax1.set_xlabel(r"$V_{\mathrm{PM}}(\mathrm{V})$")
plt.legend()
# AC Plot
omega = 2 * np.pi * ac_data_osdi["frequency"]
z_analytical = 1 / 10
fig = plt.figure()
plt.semilogx(
ac_data_built_in["frequency"],
ac_data_built_in["i(vsense)"] * 1e3,
label="built-in",
linestyle=" ",
marker="x",
)
plt.semilogx(
ac_data_built_in["frequency"],
np.ones_like(ac_data_built_in["frequency"]) * z_analytical * 1e3,
label="analytical",
linestyle="--",
marker="s",
)
plt.semilogx(
ac_data_osdi["frequency"], ac_data_osdi["i(vsense)"] * 1e3, label="OSDI"
)
plt.xlabel("$f(\\mathrm{H})$")
plt.ylabel("$\\Re \\left\{ Y_{11} \\right\} (\\mathrm{mS})$")
plt.legend()
fig = plt.figure()
plt.semilogx(
ac_data_built_in["frequency"],
ac_data_built_in["i(vsense).1"] / omega,
label="built-in",
linestyle=" ",
marker="x",
)
plt.semilogx(
ac_data_built_in["frequency"],
np.ones_like(ac_data_built_in["i(vsense).1"]) *5,
label="analytical",
linestyle="--",
marker="s",
)
plt.semilogx(
ac_data_osdi["frequency"],
ac_data_osdi["i(vsense).1"] / omega,
label="OSDI",
)
plt.ylim(4, 6)
plt.xlabel("$f(\\mathrm{H})$")
plt.ylabel("$\\Im\\left\{Y_{11}\\right\}/(\\omega) (\\mathrm{F})$")
plt.legend()
# TR plot
fig = plt.figure()
plt.plot(
tr_data_built_in["time"] * 1e9,
tr_data_built_in["i(vsense)"] * 1e3,
label="built-in",
linestyle=" ",
marker="x",
)
plt.plot(
tr_data_osdi["time"] * 1e9,
tr_data_osdi["i(vsense)"] * 1e3,
label="OSDI",
)
plt.xlabel(r"$t(\mathrm{nS})$")
plt.ylabel(r"$I_{\mathrm{D}}(\mathrm{mA})$")
plt.legend()
plt.show()