Skip to content

Circuit construction ​

Define topology and bind component values. Start with the circuit guide.

See the API overview for other analyses and conventions for units and array ordering.

JosephsonCircuits.Ground Constant
julia
Ground

The distinguished global electrical reference. Ground may appear as an endpoint in any connection group, and as the negative pin of an interface port. The ground net is always named "0".

For uniformity with ordinary components, ground may also be declared in the components list and referenced through its single terminal:

julia
Circuit([:r1 => Resistor(50.0), :gnd => Ground()],
    [[(:r1, 1)], [(:r1, 2), (:gnd, 1)]])

Ground() and Ground are the same object, so both spellings work in both positions. A ground instance is sugar for the reference net rather than a device: every reference to its terminal resolves to the global ground net, however many instances are declared and at whatever level of the hierarchy, and it contributes no flattened component.

source
JosephsonCircuits.Circuit Type
julia
Circuit(components, connections, interface = nothing;
    pins = nothing, ports = nothing, validate = true)

The public typed circuit representation.

  • components associates unique instance identifiers (symbols, strings, or integers) with component models, typically as a vector of pairs.

  • connections describes which component endpoints are electrically connected, as groups (tuples of endpoints on one net), pairs (port to port bonds), and Net entries.

  • interface optionally exposes pins and ports so that the circuit can be used as a component inside another circuit.

The pins and ports keywords are sugar for the positional interface: Circuit(components, connections; pins = ..., ports = ...) is Circuit(components, connections, Interface(pins = ..., ports = ...)). Give the interface one way or the other, not both.

The constructor validates identifiers, endpoint references, connector namespaces, and the interface, so that errors point at the construction site, but stores the collections exactly as given: no data is copied, and a thousand instances of one subcircuit hold a thousand references to the same object. Use elaborate to flatten the hierarchy.

Endpoint grammar

writtenmeaning
(:inst, k)scalar terminal or pin k in a group; port k in a pair
(:inst, p, t)terminal t (1 signal, 2 reference) of port p
Groundthe global reference net "0"
(:gnd, 1) with :gnd => Ground()the same reference net, component style
PortRef/PinRefexplicit namespace selection

In a group every endpoint is scalar. In a pair a => b, endpoints resolve in the port namespace of components which expose ports, and the pair expands to signal-to-signal and reference-to-reference groups; components without ports fall back to scalar endpoints, making a pair of scalar endpoints sugar for a two element group. A key which exists both as a pin and as a port of a subcircuit is an error in a pair and requires PortRef or PinRef.

Connection groups may be written as tuples or vectors of endpoints. Vectors are recommended for large or generated groups: a vector is one type whatever its length, where every distinct tuple shape is a separate type for the compiler to specialize on.

Examples

julia
circuit = Circuit(
    [:l1 => Inductor(1e-9), :c1 => Capacitor(100e-15), :p1 => Port(1)],
    [[(:p1, 1), (:l1, 1)],
     [(:l1, 2), (:c1, 1)],
     [(:c1, 2), (:p1, 2), Ground]],
)
source
JosephsonCircuits.Circuit Method
julia
Circuit(netlist::AbstractVector, circuitdefs::AbstractDict)

Construct a typed Circuit from a tuple netlist, which is deprecated: this warns and will be removed in a future release. Each entry is (name, node1, node2, value) and the component type is taken from the prefix of name: Lj (Josephson junction), L, C, K (mutual inductor, whose "nodes" are the two inductor names), I, R, and P (port, whose value is the port number). Only this adapter reads a name prefix; typed component models never infer behavior from an instance name. The one argument Circuit(netlist) reads a tuple netlist the same way when its entries end in values rather than typed components.

Node labels become net names, so compile of the result gives the same tables the tuple netlist always produced. A port's reference impedance is the value of the single resistor placed across it, which the adapter records as the port's LegacyTermination. When circuitdefs is given, values are resolved with valuetonumber during conversion; otherwise they pass through unchanged and circuitdefs is given to the analysis as usual.

Examples

julia
julia> Circuit([("P1","1","0",1),("R1","1","0",50.0),("C1","1","0",1e-12)]) isa Circuit
true
source
JosephsonCircuits.Circuit Method
julia
Circuit(netlist::AbstractVector; pins = nothing, ports = nothing)

Construct a Circuit from a netlist: a vector of entries (name, nodes..., component), one per component instance, each listing the node of every terminal in terminal order, as a SPICE netlist does.

  • name is the instance identifier, a Symbol or a string.

  • The nodes are integers, strings or symbols. Node 0 (or "0", or Ground) is ground. Every entry naming a node joins its net, and the nets carry the node names.

  • component is a typed component model, and the entry lists one node per terminal in terminal order: two for a lumped element or a port; for a ScatteringParameters block the signal and reference terminal of each port in turn, or the signal terminal alone when the block is grounded; for a subcircuit Circuit one per interface pin, in the order the pins were declared.

  • A MutualInductor has no terminals. Its entry names the two inductors it couples in place of nodes, and the component is written MutualInductor(K).

pins and ports declare an interface as they do for the connection-group form, so a netlist can define a subcircuit.

The netlist is the connection-group form with the groups written out by node, and builds exactly that: the components in netlist order and one named connection group per node. What the connection-group form expresses beyond a node list, such as the bundled port views of pair connections, is written in that form.

A vector of entries carrying values under type-prefixed names, ("C1", "1", "0", 1e-12), is the deprecated tuple netlist, which this method reads, with a warning, through the adapter in circuit/legacy.jl.

Examples

julia
julia> circuit = Circuit([
           (:p1, 1, 0, Port(1; Z0 = 50.0)),
           (:cc, 1, 2, Capacitor(100e-15)),
           (:jj, 2, 0, JosephsonJunction(1000e-12)),
           (:cj, 2, 0, Capacitor(1000e-15))]);

julia> compile(circuit).nodenames
3-element Vector{String}:
 "0"
 "1"
 "2"
source
JosephsonCircuits.CompiledCircuit Type
julia
CompiledCircuit

An elaborated circuit lowered to a flat table of two terminal components, with index groups by component kind.

Fields

The flat table, in elaboration order:

  • componentnames: the hierarchical instance path of each entry. A matched port's own termination is the entry named "<port path>/termination".

  • componenttypes: the type symbol of each entry: :C, :R, :L, :Lj (a NonlinearInductor, whatever its relation), :I, :K (a mutual inductor) or :P (a port).

  • componentvalues: the value of each entry as written; the reference impedance for a port.

  • nodeindices: a 2 by ncomponents matrix of the node indices of each entry, ground being node 1; both zero for a mutual inductor.

  • junctioncprs: the PolynomialCPR of each :Lj entry whose current-phase relation is not the sinusoidal Josephson one. Empty for every circuit which does not ask for another, and the solvers then evaluate sin and cos.

  • componenttemperatures: the temperature of each entry which states one, keyed by flat index.

  • couplings: resolved (coupling, inductor1, inductor2) flat indices, in coupling table order; the names of the coupled inductors are componentnames at those indices, see coupledinductornames.

  • nodenames, Nnodes: the node names in sorted order (ground first) and their count.

  • componentnamedict: component name to flat index.

  • topology: the branches and the oriented incidence matrix, see CircuitTopology.

The groups, each a vector of flat indices in table order:

  • capacitors, resistors, inductors, junctions (:Lj), currentsources, mutualinductors.

The records which keep their own structure:

  • ports::Vector{CompiledPort}, in elaboration order.

  • scatteringblocks::Vector{CompiledScatteringBlock}, one per block instance.

See compile.

source
JosephsonCircuits.ComponentNotSupportedError Type
julia
ComponentNotSupportedError(msg)

An exception thrown when a component in the typed circuit representation parses, validates, and elaborates successfully but is not yet supported by the numerical solvers.

source
JosephsonCircuits.Interface Type
julia
Interface(; pins, ports = nothing)

The interface of a hierarchical circuit, exposing internal endpoints as scalar pins and optionally grouping pins into oriented two terminal wave port views.

pins maps external keys (integers or symbols) to internal scalar endpoints, analogous to the pin list of a SPICE .subckt:

julia
pins = [1 => (:jj1, 1), 2 => (:jj2, 2), 3 => (:cap, 2)]

ports optionally maps external port keys to (positive, negative) pairs of pin keys, where the negative entry may be Ground:

julia
ports = [1 => (1, 3), 2 => (2, 3)]

The parent circuit physically binds pins; connecting port to port with pair syntax is shorthand which expands to the pin connections.

The explicit call is optional: Circuit(components, connections; pins = ..., ports = ...) constructs the same interface through keywords.

source
JosephsonCircuits.Net Type
julia
Net(name, endpoints)

A named connection group: all endpoints belong to the same electrical net, which is given the name name for diagnostics and outputs. Unnamed nets are named automatically. Names attached to the ground net are ignored; the ground net is always named "0".

Examples

julia
Net(:bias, ((:source, 1), (:device, 2)))
source
JosephsonCircuits.PinRef Type
julia
PinRef(instance, key)

An explicit reference to the scalar pin or terminal key of the component instance instance, for use when a bare (instance, key) tuple would be ambiguous between a scalar pin and a port.

source
JosephsonCircuits.PortRef Type
julia
PortRef(instance, key)

An explicit reference to the bundled two terminal port key of the component instance instance, for use in pair connections when a bare (instance, key) tuple would be ambiguous between a scalar pin and a port.

source
JosephsonCircuits.IctoLj Method
julia
IctoLj(Ic)

The junction inductance Lj = phi0/Ic in Henries of a Josephson junction with critical current Ic in Amperes.

Examples

julia
julia> IctoLj(1e-6)
3.291059784754534e-10
source
JosephsonCircuits.LjtoIc Method
julia
LjtoIc(Lj)

The critical current Ic = phi0/Lj in Amperes of a Josephson junction with junction inductance Lj in Henries.

Examples

julia
julia> LjtoIc(100e-12)
3.2910597847545335e-6
source
JosephsonCircuits.compile Method
julia
compile(elab::ElaboratedCircuit; sorting = :name)
compile(circuit::Circuit; sorting = :name)
compile(c::CompiledCircuit; sorting = :name)

Lower a circuit to a CompiledCircuit. A Circuit is elaborated first; a CompiledCircuit is returned unchanged, and asking it for a node order other than the one it carries is an error.

Components appear in the table in elaboration order, with a matched port's own termination emitted as a resistor entry directly after the port. A net which only components shorted across it touch is the ground net (see shortednets). Nodes are numbered by calcnodesorting with ground first; the default sorting = :name sorts the net names as strings, since hierarchical net names are not integers, and :number sorts integer node names by value.

Only components the solvers support can be lowered: a component with other than two terminals which is not a scattering block throws a ComponentNotSupportedError naming the instance. A circuit with no connection to Ground throws an ArgumentError.

source
JosephsonCircuits.numericmatrices Method
julia
numericmatrices(circuit, circuitdefs; Nmodes = 1)
numericmatrices(psc::CompiledCircuit, circuitdefs;
    Nmodes = 1)
numericmatrices(psc::CompiledCircuit, vvn; Nmodes = 1)

The CircuitMatrices of a circuit with its component values resolved to numbers with circuitdefs, at the mode count Nmodes, with every matrix entry repeated Nmodes times along the diagonal. The third form takes the already resolved values vvn, so that a second call at a different mode count (the signal grid of hblinsolve after the pump grid of hbnlsolve) does not resolve them again.

See also CircuitMatrices, numericmatrices, assemblematrices, orderedports, portreferenceimpedances, and noiseindices.

Examples

julia
circuit = Circuit(
    [:p1 => Port(1; Z0 = :Rleft),
     :i1 => CurrentSource(:Ipump),
     :cc => Capacitor(:Cc),
     :jj => JosephsonJunction(:Lj),
     :cj => Capacitor(:Cj),
     :gnd => Ground()],
    [[(:p1, 1), (:i1, 1), (:cc, 1)],
     [(:cc, 2), (:jj, 1), (:cj, 1)],
     [(:p1, 2), (:i1, 2), (:jj, 2), (:cj, 2), (:gnd, 1)]])
circuitdefs = Dict(:Lj => 1000.0e-12, :Cc => 100.0e-15, :Cj => 1000.0e-15, :Rleft => 50.0, :Ipump => 1.0e-8)
JosephsonCircuits.testshow(stdout,numericmatrices(circuit,circuitdefs))

# output
JosephsonCircuits.CircuitMatrices(sparse([1, 2, 1, 2], [1, 1, 2, 2], [1.0e-13, -1.0e-13, -1.0e-13, 1.1e-12], 2, 2), sparse([1], [1], [0.02], 2, 2), sparsevec(Int64[], Float64[], 2), sparsevec([2], [1.0e-9], 2), sparsevec([2], [1.0e-9], 2), sparse(Int64[], Int64[], Float64[], 2, 2), sparse(Int64[], Int64[], Float64[], 2, 2), sparse([1, 2], [1, 2], [1, 1], 2, 2), [1], [1], [50.0], [2], 1.0e-9, Any[50.0, 50.0, 1.0e-8, 1.0e-13, 1.0e-9, 1.0e-12], nothing)
julia
circuit = Circuit(
    [:p1 => Port(1; Z0 = :Rleft),
     :i1 => CurrentSource(:Ipump),
     :cc => Capacitor(:Cc),
     :jj => JosephsonJunction(:Lj),
     :cj => Capacitor(:Cj),
     :gnd => Ground()],
    [[(:p1, 1), (:i1, 1), (:cc, 1)],
     [(:cc, 2), (:jj, 1), (:cj, 1)],
     [(:p1, 2), (:i1, 2), (:jj, 2), (:cj, 2), (:gnd, 1)]])
circuitdefs = Dict(:Lj => 1000.0e-12, :Cc => 100.0e-15, :Cj => 1000.0e-15, :Rleft => 50.0, :Ipump => 1.0e-8)
psc = JosephsonCircuits.compile(circuit)
JosephsonCircuits.testshow(stdout,numericmatrices(psc, circuitdefs))

# output
JosephsonCircuits.CircuitMatrices(sparse([1, 2, 1, 2], [1, 1, 2, 2], [1.0e-13, -1.0e-13, -1.0e-13, 1.1e-12], 2, 2), sparse([1], [1], [0.02], 2, 2), sparsevec(Int64[], Float64[], 2), sparsevec([2], [1.0e-9], 2), sparsevec([2], [1.0e-9], 2), sparse(Int64[], Int64[], Float64[], 2, 2), sparse(Int64[], Int64[], Float64[], 2, 2), sparse([1, 2], [1, 2], [1, 1], 2, 2), [1], [1], [50.0], [2], 1.0e-9, Any[50.0, 50.0, 1.0e-8, 1.0e-13, 1.0e-9, 1.0e-12], nothing)
source
JosephsonCircuits.symbolicmatrices Method
julia
symbolicmatrices(circuit; Nmodes = 1)
symbolicmatrices(psc::CompiledCircuit; Nmodes = 1)

The CircuitMatrices of a circuit with its component values left symbolic, so that the capacitance and inverse inductance matrices can be inspected as expressions. The mutually coupled inductor branches are excluded from the inverse inductance matrix and represented by auxiliary branch currents instead (see circuit/mna.jl), so no symbolic linear solve is needed. The expressions are those of Symbolics, which is loaded for them (using Symbolics): a value written as a name is the variable of that name, and one written as a Symbolics value is itself.

See also CircuitMatrices, numericmatrices, assemblematrices, orderedports, portreferenceimpedances, and noiseindices.

Examples

julia
julia> using Symbolics

julia> circuit = Circuit(
           [:p1 => Port(1; Z0 = :Rleft),
            :i1 => CurrentSource(:Ipump),
            :cc => Capacitor(:Cc),
            :jj => JosephsonJunction(:Lj),
            :cj => Capacitor(:Cj),
            :gnd => Ground()],
           [[(:p1, 1), (:i1, 1), (:cc, 1)],
            [(:cc, 2), (:jj, 1), (:cj, 1)],
            [(:p1, 2), (:i1, 2), (:jj, 2), (:cj, 2), (:gnd, 1)]]);

julia> m = symbolicmatrices(circuit);

julia> m.Cnm[1, 2], m.Cnm[2, 2]
(-Cc, Cc + Cj)

julia> m.Gnm[1, 1], m.Ljb[2]
(1 / Rleft, Lj)
source

Physical constants ​

The flux quanta follow from the exact SI values of the Planck constant and the elementary charge.

JosephsonCircuits.Phi0 Constant
julia
const Phi0

The magnetic flux quantum h/(2e) in Weber (equivalently H_A), 2_pi*phi0.

source
JosephsonCircuits.boltzmann_constant Constant
julia
const boltzmann_constant

The Boltzmann constant k_B, 1.380649e-23 J/K, used with reduced_planck_constant to convert a physical temperature into the thermal occupation of a mode (see thermaloccupation) and a noise in quanta into a noise temperature (see noisetemperature).

source
JosephsonCircuits.elementary_charge Constant
julia
const elementary_charge

The elementary charge e, 1.602176634e-19 C, exact in the SI.

source
JosephsonCircuits.phi0 Constant
julia
const phi0

The reduced magnetic flux quantum hbar/(2e) in Weber (equivalently H*A). This is the flux scale that relates a Josephson junction's inductance to its critical current, Ic = phi0/Lj, and the unit in which the branch phases of the harmonic balance solution are measured.

source
JosephsonCircuits.planck_constant Constant
julia
const planck_constant

The Planck constant h, 6.62607015e-34 J*s, exact in the SI.

source
JosephsonCircuits.reduced_planck_constant Constant
julia
const reduced_planck_constant

The reduced Planck constant hbar = h/(2*pi) in J*s.

source
JosephsonCircuits.speed_of_light Constant
julia
const speed_of_light

The speed of light in vacuum, 2.99792458e8 m/s, the default phase velocity of a TransmissionLine.

source