# AC simulation of arbitrary networks (from spice netlists)

**URL:** https://discourse.julialang.org/t/ac-simulation-of-arbitrary-networks-from-spice-netlists/117972
**Category:** General Usage
**Created:** [August 8, 2024, 7:59pm UTC](https://discourse.julialang.org/t/ac-simulation-of-arbitrary-networks-from-spice-netlists/117972 "2024-08-08T19:59:36Z")
**Posts on this page:** 5
**Page:** 1

<div class="post-metadata">

### Author: ![Maarco3108](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/maarco3108/32/211185_2.png) [@Maarco3108](https://discourse.julialang.org/u/Maarco3108)
#### Post date: [August 8, 2024, 7:59pm UTC](https://discourse.julialang.org/t/ac-simulation-of-arbitrary-networks-from-spice-netlists/117972/1 "2024-08-08T19:59:36Z")

</div>

Hello guys,

I want to create a Julia project for AC simulation of arbitrary networks (from spice netlists) using nodal or loop analysis and then calculate voltage and currents for all elements.

There are only R, L, C lumped elements and a voltage source and the nodes are named 0 and Nxxx in the netlist.

My goal is to read some netlists from spice and automatically solve the ODEs.

Are there maybe any libraries for that?

---

<div class="post-metadata">

### Author: ![dawbarton](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dawbarton/32/215461_2.png) [@dawbarton](https://discourse.julialang.org/u/dawbarton)
#### Post date: [August 8, 2024, 9:48pm UTC](https://discourse.julialang.org/t/ac-simulation-of-arbitrary-networks-from-spice-netlists/117972/2 "2024-08-08T21:48:12Z")

</div>

I don’t know this general area very well, but you could start by taking a look at [https://github.com/CedarEDA/CedarEDA.jl](https://github.com/CedarEDA/CedarEDA.jl). It seems to do what you want but it might not be completely (publicly) available yet.

---

<div class="post-metadata">

### Author: ![kpobrien](https://avatars.discourse-cdn.com/v4/letter/k/c0e974/32.png) [@kpobrien](https://discourse.julialang.org/u/kpobrien)
#### Post date: [August 9, 2024, 1:15pm UTC](https://discourse.julialang.org/t/ac-simulation-of-arbitrary-networks-from-spice-netlists/117972/3 "2024-08-09T13:15:52Z")

</div>

Would a periodic steady state or frequency domain solution satisfy your requirements?

---

<div class="post-metadata">

### Author: ![Maarco3108](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/maarco3108/32/211185_2.png) [@Maarco3108](https://discourse.julialang.org/u/Maarco3108)
#### Post date: [August 9, 2024, 5:18pm UTC](https://discourse.julialang.org/t/ac-simulation-of-arbitrary-networks-from-spice-netlists/117972/4 "2024-08-09T17:18:21Z")

</div>

A solution in the frequency domain would meet the requirements since I only need to calculate the node voltages at a fixed frequency of 100 Hz in the first step.

---

<div class="post-metadata">

### Author: ![kpobrien](https://avatars.discourse-cdn.com/v4/letter/k/c0e974/32.png) [@kpobrien](https://discourse.julialang.org/u/kpobrien)
#### Post date: [August 9, 2024, 9:48pm UTC](https://discourse.julialang.org/t/ac-simulation-of-arbitrary-networks-from-spice-netlists/117972/5 "2024-08-09T21:48:08Z")

</div>

In that case, you might find [JosephsonCircuits.jl](https://github.com/kpobrien/JosephsonCircuits.jl) helpful. It is a harmonic balance solver for arbitrary netlists containing capacitors, inductors, resistors, mutual inductors, and Josephson junctions (which you don’t need). It performs nodal analysis in the node flux basis. Here is an example of simulating the scattering parameters and node voltages of a transmission line with an impedance mismatch. The input is a SPICE style netlist with a unique component name, the two nodes, and the component value (here I define them with symbolic variables but you can enter numbers if you prefer):

```julia
using JosephsonCircuits
using Plots

@variables R C L
circuit = Tuple{String,String,String,Num}[]

# port on the input side
push!(circuit,("P$(1)_$(0)","1","0",1))
push!(circuit,("R$(1)_$(0)","1","0",R))
Ncells=50
#first half unit cell
push!(circuit,("C$(1)_$(0)","1","0",C/2))
push!(circuit,("L$(1)_$(2)","1","2",L)) 

j=2
for i = 2:Ncells-1
    
    push!(circuit,("C$(j)_$(0)","$(j)","$(0)",C))
    push!(circuit,("L$(j)_$(j+1)","$(j)","$(j+1)",L))

    # increment the index
    j+=1

end

#last jj
push!(circuit,("C$(j)_$(0)","$(j)","$(0)",C/2))
push!(circuit,("R$(j)_$(0)","$(j)","$(0)",R))
# port on the output side
push!(circuit,("P$(j)_$(0)","$(j)","$(0)",2))

circuitdefs = Dict(
    L => 5e-10,
    C => 45.0e-15,
    R => 50.0,
)

w=2*pi*(1.0:0.01:80)*1e9
@time sol = hblinsolve(w, circuit, circuitdefs;returnvoltage=true)

p1=plot(sol.w/(2*pi*1e9),
    10*log10.(abs2.(sol.S(
            outputmode=(0,),
            outputport=2,
            inputmode=(0,),
            inputport=1,
            freqindex=:),
    )),
    ylim=(-40,30),label="S21",
    xlabel="Signal Frequency (GHz)",
    legend=:bottomright,
    title="Scattering Parameters",
    ylabel="dB")

plot!(sol.w/(2*pi*1e9),
    10*log10.(abs2.(sol.S((0,),1,(0,),2,:))),
    label="S12",
    )

plot!(sol.w/(2*pi*1e9),
    10*log10.(abs2.(sol.S((0,),1,(0,),1,:))),
    label="S11",
    )

plot!(sol.w/(2*pi*1e9),
    10*log10.(abs2.(sol.S((0,),2,(0,),2,:))),
    label="S22",
    )

```

![image](https://global.discourse-cdn.com/julialang/original/3X/b/1/b1240705799027ff099b2ef77006cf21dff57f3d.png)

and we can compare the simulated voltages at one node to those from the SPICE solver WRspice packaged in XicTools\_jll.jl (or Xyce.jl, etc).

```julia
using XicTools_jll
n = JosephsonCircuits.exportnetlist(circuit,circuitdefs);
input = JosephsonCircuits.wrspice_input_ac(n.netlist,sol.w/(2*pi),(2,1),n.portcurrent); # warning: this wrapper code is very crude
@time output = JosephsonCircuits.spice_run(input,XicTools_jll.wrspice());

```

and plot them both:

```julia
plot(sol.w/(2*pi*1e9),real.(sol.voltage(
        outputmode=(0,),
        node="1",
        inputmode=(0,),
        inputport=1,
        freqindex=:)),label="Re, JosephsonCircuits.jl",ylabel="Voltage (V)",xlabel="Frequency (GHz)")
plot!(sol.w/(2*pi*1e9),imag.(sol.voltage(
        outputmode=(0,),
        node="1",
        inputmode=(0,),
        inputport=1,
        freqindex=:)),label="Im, JosephsonCircuits.jl")

plot!(sol.w/(2*pi*1e9),
    real.(output.values["V"][1,:]),
    linecolor=:black,
    linestyle=:dash,
    label="Re, WRspice")
plot!(sol.w/(2*pi*1e9),
    imag.(output.values["V"][1,:]),
    linecolor=:gray,
    linestyle=:dash,
    label="Im, WRspice")

```

![image](https://global.discourse-cdn.com/julialang/original/3X/b/d/bdf11073c889d423024452ba25e5ca297d5ffbd4.png)

You could also take the sparse capacitance, conductance, and inverse inductances matrices generated from the netlist and solve them yourself (a lot of the codebase is for dealing with nonlinear systems and quantum noise which you probably don’t need). Here is a snippet of code to generate those:

```julia
nm = JosephsonCircuits.numericmatrices(circuit, circuitdefs);
# capacitance matrix
nm.Cnm
# inverse inductance matrix
nm.invLnm
# conductance matrix
nm.Gnm

```
