Running Parametric Sweeps

Parametric sweeps allow us to explore the behavior of circuits as we change their parameters, and also define the basis upon which Parameter Tuning with Optimization is performed. In this example, we will load the Butterworth filter example circuit and run a parametric sweep over its component values. If you have not already, we recommend reviewing Running Transient Analysis, as we will be building on top of the concepts covered within.

using CedarEDA
using CedarEDA.SIFactors: f, p, n, u, m, k, M, G

# Load simple butterworth circuit
sm = SimManager("butterworth.spice")
SimManager for 'butterworth.spice', with parameters:
 - l1 (default: 1.2n)
 - c2 (default: 430p)
 - l3 (default: 390n)
 - r4 (default: 50)
 - freq (default: 10M)

After loading the spice code into the SimManager object, we can create our first parameterized sweep by creating a SimParameterization object and specifying the params keyword argument with a ProductSweep. Here we define ranges for the parameters using Julia's step range syntax which allows specifying start:step:end to easily create a list of numbers. We also set tolerances for the solve, as well as the timespan over which this solve should occur.

sp = SimParameterization(sm;
    # Sweep over these SPICE .parameters
    params = ProductSweep(
        l1 = 0.5n:0.25u:2.3u, # 10 values (step is 0.25u)
        c2 = 100p:100p:800p, # 8 values (step is 100p)
    ),
    abstol_dc = 10f,
    abstol_tran = 100u,
    reltol_tran = 1u,
    # 10 periods of the source sinusoid at 10MHz
    tspan = (0.0, 10/10M),
)
SimParameterization with parameterization:
 - c2 (8 values: 100p .. 800p)
 - l1 (10 values: 500p .. 2.2505u)
Total: 80 simulations to sweep over.

Once our SimParameterization object is created, we run a transient simulation which will run a sweep across the set of parameter values defined in the sp object:

# Ensure that we plot `node_vout` by default
set_saved_signals!(sp, [
    sp.probes.node_vout,
]);

# Run the transient simulations
ts = tran!(sp)

# Explore our solution via Transient analysis
explore(sp, ts)
Example block output

Accessing sweep solution data

As mentioned in Transient solution objects, SolutionSet objects are shaped the same as their originating parameterization. In this example, we have two parameters combined in a ProductSweep, resulting in a 8x10 matrix of simulations. These simulations are directly accessable by index. Here we demonstrate selecting two extremal simulations along the l1 axis and plotting them on top of eachother using inspect():

inspect([
    ts.tran.node_vout[1, 4],
    ts.tran.node_vout[8, 4],
])
Example block output

The parameter data for each simulation is also available through ts.parameters:

ts.parameters.l1[1, 1]
5.0e-10
ts.parameters.c2[1, 1]
1.0e-10

Parametric sweeps will be used extensively throughout the rest of this documentation. See Running DC Analysis and Parameter Tuning with Optimization for more examples.

Parameter sweep types

CedarEDA supports multiple types and combinations of parameter sweeps:

CedarSim.ProductSweepFunction
ProductSweep(args...)

Takes the given Sweep specifications and produces the cartesian product of the individual inputs:

ProductSweep(R1 = 1:4, R2 = 1:4, R3 = 1:4)

ProductSweep(:R1 => 1:4, :R2 => 1:4)
CedarSim.TandemSweepFunction
TandemSweep(args...)

Takes the given Sweep specifications and produces an iterator that emits each input in tandem. Note that all inputs must have the same length!

TandemSweep(R1 = 1:4, R2 = 1:4)
CedarSim.SerialSweepType
SerialSweep(args...)

Takes the given Sweep specifications and produces an iterator that emits each input in serial.

SerialSweep(R1 = 1:4, R2 = 1:4)
CedarSim.sweepvarsFunction
sweepvars(sp::SimParameterization)

Return a Set{Symbol} of the parameters that are swept over in the given SimParameterization object.

sweepvars(sweep)

Return the full Set of variables (in the form of symbols) that can be set when iterating over the given sweep object.

They can be nested and combined to create complex sweeps:

sp = SimParameterization(sm;
    params = ProductSweep(
        r4 = range(0.1, 10.0; length=10),
        c2 = 0.2,
        TandemSweep(
            l1 = [0.1, 0.5, 1.0],
            w = 1:3,
        ),
    )
)
SimParameterization with parameterization:
 - c2 = 0.2
 - l1 (3 values: 100m .. 1)
 - r4 (10 values: 100m .. 10)
 - w  (3 values: 1 .. 3)
Total: 30 simulations to sweep over.