Additional interfaces and internals
These lower-level utilities and internal types are documented for source readers. Their presence does not imply the compatibility guarantees of a public interface. See Implementation notes for a source map, or return to the public API.
JosephsonCircuits.JosephsonCircuits Module
JosephsonCircuitsA simulator for superconducting circuits containing Josephson junctions, capacitors, inductors, mutual inductors, resistors, and multiport scattering parameter blocks, in the frequency domain and in time.
Circuits are solved by harmonic balance in a modified nodal analysis formulation in the node flux basis. A strong periodic drive (the pump) is solved with hbnlsolve, the circuit is linearized about that operating point and swept over weak signal frequencies with hblinsolve, and hbsolve runs the two in sequence. From the linearized solution the package computes scattering parameters, noise scattering parameters, quantum efficiency, commutation relations, and adjoint-method sensitivities with respect to component values or, through designsensitivities, to the design parameters of a Julia function which gives the circuit's values.
The same compiled circuit, on the same node flux unknowns, can also be integrated directly in physical time with transientsolve, for pulsed drives and for drives with more tones than a harmonic grid can hold, with the exact tangent and adjoint of the recorded time steps.
A circuit is written as a Circuit of typed component models; the netlist of (name, node1, node2, value) tuples is deprecated and is converted to one. The stages a circuit passes through, and the files that implement them, are listed next to the include statements below.
JosephsonCircuits.CALLABLE_FORMS Constant
CALLABLE_FORMSThe ways a callable provider may be called. See CallableMatrixProvider.
JosephsonCircuits.FCONJ Constant
FCONJFlag bit marking a slot of the frequency domain array which is a conjugate symmetry target, so the value gathered for it is conjugated. See NonlinearTermPlan.
JosephsonCircuits.FORWARDSENSITIVITYSTAMPBYTES Constant
FORWARDSENSITIVITYSTAMPBYTESThe byte budget of the operating point stamps of the forward sensitivity contraction, one complex value per stored entry of the linearized system matrix per component, which the sweep holds throughout. With sensitivitymode = :auto the reverse order, whose memory does not grow with the number of components (see REVERSESENSITIVITYCHUNKBYTES), is taken when the stamps would exceed it.
JosephsonCircuits.FWIDE Constant
FWIDEFlag bit marking a slot of the frequency domain array whose source mode is not self conjugate, so the imaginary part of the source occupies the real slot after the one addressed. See NonlinearTermPlan.
JosephsonCircuits.IMPEDANCE_C Constant
IMPEDANCE_CThe integer code impedance uses for a capacitor; see impedancecode.
JosephsonCircuits.IMPEDANCE_L Constant
IMPEDANCE_LThe integer code impedance uses for an inductor; see impedancecode.
JosephsonCircuits.IMPEDANCE_R Constant
IMPEDANCE_RThe integer code impedance uses for a resistor; see impedancecode.
JosephsonCircuits.REVERSESENSITIVITYCHUNKBYTES Constant
REVERSESENSITIVITYCHUNKBYTESThe byte budget of one chunk of the reverse contraction's dense buffers, which sets the column count calcSsensitivityreverse! works in.
JosephsonCircuits.AbstractComponent Type
AbstractComponentThe supertype of the component models of the typed circuit representation. A component is a concrete struct holding its data; behavior is given by methods such as nterminals and hasports in circuit/parse.jl. A Circuit with an Interface is also a component.
JosephsonCircuits.AbstractDCModel Type
AbstractDCModelThe supertype of the zero frequency models a ScatteringParameters may declare, written as dcmodel.
ScatteringLimit() (the default) evaluates the block's own scattering data at zero frequency. OpenDC, ShortDC, ThroughDC and ScatteringDC state it instead.
JosephsonCircuits.AbstractFactorization Type
AbstractFactorizationA sparse factorization method. A concrete method f implements factorize(f, A), which computes a factorization of A (the symbolic analysis and the first numeric factorization), and refactorize!(f, F, A), which refactorizes A into the existing F reusing its symbolic analysis and returns F, or nothing when the method has no in place refactorization.
The methods are KLUfactorization, LUfactorization, QRfactorization, CUDSSFactorization and BlockFactorization.
JosephsonCircuits.AbstractHBNonlinearSolver Type
AbstractHBNonlinearSolverA method of solving the operating point, the method of hbnlsolve and hbsolve: NewtonKrylov, Newton, QuasiNewton, Staged or ExternalSolver.
JosephsonCircuits.AbstractMatrixProvider Type
AbstractMatrixProviderThe supertype of the sources of frequency dependent matrix data: the scattering parameters and noise covariance of a ScatteringParameters. A provider implements evaluateprovider! and providersize. Its data lives in the shared component definition and is never copied per instance.
JosephsonCircuits.AbstractModeCoupling Type
AbstractModeCouplingThe mode coupling family of AbstractPreconditionerSpec: the Jacobian with its mode coupling restricted to a selected set and reduced to the mode diagonal elsewhere, factorized; see ModeCouplingPreconditioner. Each member carries the AbstractFactorization it is built with in its factorization field, nothing for the backend's default (KLU on the host, cuDSS on a device).
JosephsonCircuits.AbstractPortTermination Type
AbstractPortTerminationThe supertype of the external environments a Port may own. A termination is the source and load the port sees looking outward, which is distinct from the reference impedance the port normalizes its waves to, even where the two are numerically equal.
JosephsonCircuits.AbstractPreconditioner Type
AbstractPreconditionerSupertype of the preconditioners of nlsolvekrylov!. A preconditioner pc approximates the Jacobian of the nonlinear system by something which can be inverted cheaply, and must implement two methods:
updatepreconditioner!(pc, x): rebuildpcat the pointx,applypreconditioner!(z, pc, r): overwritezwithinv(P)*r.
The Jacobian itself is never required, only its approximation, so the nonlinear solve stays matrix-free. See ModeCouplingPreconditioner for the harmonic balance Jacobian with its mode coupling restricted, and FloquetPreconditioner for that wrapped in a deflation subspace.
The rest of the interface is hooks the driver calls with an inert default, which a preconditioner implements when it has something to say:
| hook | default | who implements it |
|---|---|---|
pointmoved!(pc) | nothing | a deflation, whose pair goes stale |
stalled!(pc) | nothing | Clusters, which remeasures |
escalatepreconditioner!(pc) | false | mode coupling, a deflation deferring it |
usescycleharvest(pc), harvestcycle!(pc, ws, j) | false, nothing | a deflation |
isexactpreconditioner(pc) | false | an exact factorization |
hasnewcandidates(pc) | false | a deflation with candidates its last build did not take in |
deflationsize, deflationrebuilds | 0, 0 | a deflation |
deflationproducts | 0 | a deflation, a cluster probe |
A preconditioner which wraps another subtypes AbstractWrappedPreconditioner and defines innerpreconditioner; every hook it does not implement itself is then forwarded to the inner one, so that wrapping never silently turns a hook off.
JosephsonCircuits.AbstractPreconditionerSpec Type
AbstractPreconditionerSpecHow the Newton-Krylov solver preconditions its linear solves: one of the mode coupling family, BlockDiagonal, FullJacobian, HarmonicBand, MeasuredBand, Clusters and CouplingMask, each built with a factorization, Automatic, which picks among them by the problem and the memory, or Floquet, a deflation wrapping one of them. The solver builds the runtime preconditioner from the value.
JosephsonCircuits.AbstractStageInfo Type
AbstractStageInfoThe supertype of every per-stage diagnostic record stored in the stages vector of a SolverInfo. Each solver contributes its own concrete record type instead of adding fields to a shared struct: IterationInfo for the Newton family (with the Krylov linear-solve records where the solver is nlsolvekrylov!), StagedStageInfo for the source continuation driver, and future methods add their own. Every record follows two field conventions so generic reporting works across methods – converged::Bool and iterations::Int – and everything else belongs to the record type itself.
JosephsonCircuits.AbstractTransientIntegrator Type
AbstractTransientIntegratorThe time stepping rules transientsolve chooses between, Trapezoidal, GaussLegendre and BackwardEuler.
JosephsonCircuits.AbstractWrappedPreconditioner Type
AbstractWrappedPreconditionerA preconditioner which wraps another and presents it in different coordinates, at a different size or under a correction. Subtypes define innerpreconditioner and their own updatepreconditioner! and applypreconditioner!; every other hook of the interface forwards to the inner preconditioner unless the wrapper defines it, so escalation, deflation and its diagnostics reach the inner one through any number of wrappers. A wrapper which changes coordinates must define the hooks whose arguments carry vectors of its own coordinates (harvestcycle!) if the inner preconditioner reads them in its own.
JosephsonCircuits.AndersonState Type
AndersonState(x::AbstractVector, depth::Integer)Preallocated state for Anderson acceleration of the Newton fixed point iteration G(x) = x + deltax: the difference history, the previous iterate/update pair it is built from, the assembled correction vector, and the buffers of the thin QR factorization which solves the extrapolation least squares problem.
The history lives in fixed n×depth matrices with circular column indexing. andersonhistory! overwrites one column per recorded step and updates the indices. All access to the history columns is through age-ordered indices, so results are independent of the physical column layout.
JosephsonCircuits.BathLadder Type
BathLadderOne ladder of the pump of a pumped block over a transient's bath frequencies: the family (rows, cols, K) of the signed frequencies on it (see pumpedfamily), and the bath frequencies whose positive and whose negative mode it holds, by their index among the frequencies of the calculation. A pair of bath frequencies has a normal term when both their positive modes are on one ladder and an anomalous one when the positive mode of one and the negative mode of the other are, so a ladder carries exactly the pair terms of the frequencies it holds.
JosephsonCircuits.BlockDiagonal Type
BlockDiagonal(; factorization = nothing)The mode block diagonal: one small independent factorization per mode, and no coupling. Cheap, and sufficient for weak drives; on a strongly pumped device it stalls and is grown to the full Jacobian by escalation. Its factors grow linearly with the mode count where the full Jacobian's grow with its square, so this is the setting for a one tone problem too large for the full Jacobian Automatic picks.
JosephsonCircuits.BlockJacobian Type
BlockJacobianThe operator a BlockFactorization factorizes: a BlockStructure and the Fourier coefficients of cos(phi(t)) at the current point. Handed to tryfactorize! in place of a sparse matrix.
JosephsonCircuits.BlockLU Type
BlockLUThe factors of a batched block LU over a symbolic structure: the supernodes' diagonal blocks, panels and explicit inverses, each (rows, columns, nb), the Schur updates between them and the work blocks. Allocated by blocklu from a clustersymbolic structure, factorized in place by blocklu! once its blocks hold values, and applied by substitute!.
Fields
N,nb,n: supernodes, batch, order.perm,range,rowidx: the elimination order (position in the factorization to natural slot) and each supernode's positions and panel rows.D,L,U,Dinv: the blocks; afterblocklu!,Lis scaled by the inverse andDinvholds it.tasks,scratch: the Schur updates of each supernode and the work blocks by size.pivots: the pivot indices of the host's dense LU of a diagonal block.
JosephsonCircuits.BlockModulation Type
BlockModulationOne modulated output of a pumped block realized in time: the output matrix C over the block's states of the cosine (quadrature = 1) or sine (quadrature = 2) filter of the harmonic k, whose output the reflected wave carries multiplied by 2 cos(k wp t) or -2 sin(k wp t) and by the block's envelope.
JosephsonCircuits.BlockStructure Type
BlockStructureWhat a ModeCouplingPreconditioner holds in place of a sparse structure when its factorization is a BlockFactorization: the block factorizations of the mode clusters, the mode block diagonal for the modes left single (nothing when there are none), the assembly ingredients on the backend, refreshed when the system is rebound (refreshvalues!), work vectors in the factorization's precision, and the backend.
JosephsonCircuits.BoundCircuit Type
BoundCircuitA CompiledCircuit with its component values resolved to numbers, grouped by kind.
Each group is a concrete vector in the compiled group order, so capacitors[k] is the value of the component at flat index circuit.capacitors[k]. Element types are chosen per group exactly as the matrix assembly chooses them, so a lossy capacitance does not make the resistances complex.
A component whose value depends on the frequency holds a value in its group which leaves it open, a zero capacitance or an infinite resistance or inductance, so that the matrices assembled from the groups describe the circuit without it; frequencydependent records it, and the terms of FrequencyDependentTerms add it at each mode frequency.
Fields
circuit: theCompiledCircuit.capacitors,resistors,inductors,junctions,mutualinductors: the values of each group, in the compiled group order, every nonlinear inductor's among the junctions. The current sources are read fromvalues, so they have no group here.values: the flat component table, resolved to numbers.frequencydependent: theFrequencyDependentComponents, ornothingwhen no value depends on the frequency.
JosephsonCircuits.BranchStampPlan Type
BranchStampPlanThe branch each component of a group occupies, and where it lands in the branch vector.
nzind is the sorted list of branches the group touches and dest[k] is the position of group member k within it. Two components on one branch share a destination and are folded together in the order they appear.
The branch of a component is a dictionary lookup on its node pair, and there is one per component per assembly; doing it once is most of what this plan saves.
sourceJosephsonCircuits.CallableMatrixProvider Type
CallableMatrixProvider(f, n, form = :matrix)A matrix provider which evaluates the callable f at each requested angular frequency for an n by n matrix. form says how f is called: :matrix (f(w) returns a fresh n by n matrix, the natural way to write a block by hand and the default) or :inplace (f(dest, w) writes into one, which matters when the same provider is evaluated many thousands of times); see CALLABLE_FORMS.
JosephsonCircuits.CanonicalJacobianPlan Type
CanonicalJacobianPlanThe canonical Jacobian's pattern and the fixed arithmetic which fills it.
Fields
J: the pattern, and the buffer the values are written into.source: for each stored entry of the internal Jacobian, where it lands, or zero when it lands in a row a reference replaces.fixedindex,fixedvalue: the direct current block's constant entries, including the single one of each reference row.
See canonicaljacobianplan and canonicaljacobian!.
JosephsonCircuits.CanonicalPreconditioner Type
CanonicalPreconditioner(inner, work::CanonicalWork)An internal coordinate preconditioner presented in canonical coordinates.
The mode blocks the inner preconditioner is built from include the zero frequency mode, so it is applied where it was built, on the internal block of the canonical vector through internalpart, with no copy and no permutation, rather than the preconditioner being rederived. That is exact, and it keeps the two paths taking the same iterations.
JosephsonCircuits.CanonicalWork Type
CanonicalWorkThe workspaces a canonical evaluation needs, and the explicit direct current block.
Fields
layout: theCompositeLayoutthe canonical state is written in.xint,Fint: an internal state and an internal residual, for the interfaces which need one of their own; the solve reads and writes the internal block of the canonical vector in place.transport: theTransportRows.blockrows: the scattering blocks' own zero frequency rows, ornothing.dwork: the resistor current the coupling drives into the nodes.pinning: the reference rows, ornothing. SeeDCPinning.dcindex,dclocal: the canonical positions of the direct current subsystem's unknowns, and the same positions local to the window.window: the canonical positions of the window, on the backend the state is on, for the gather and the scatter.Fwindow,uwindow: the window itself, on that backend.update: the block in its matrix form, where the state lives, ornothingon the host, where the scalar walk ofaddtransportwindow!is already the cheaper of the two.
The constructor CanonicalWork(L, proto; transport, blockrows, nnodaldc) checks that the transport coupling drives only the first nnodaldc zero frequency entries, the flux of each node; any after them belong to auxiliary branch currents.
JosephsonCircuits.CircuitMatrices Type
CircuitMatrices(Cnm::SparseMatrixCSC, Gnm::SparseMatrixCSC, Lb::SparseVector,
Ljb::SparseVector, Ljbm::SparseVector, Mb::SparseMatrixCSC,
invLnm::SparseMatrixCSC, Rbnm::SparseMatrixCSC{Int, Int},
portindices::Vector{Int}, portnumbers::Vector{Int},
portimpedances::Vector, portenvironmentindices::Vector{Int}, Lmean,
vvn)The matrices of a compiled circuit at a given mode count: the capacitance, conductance and inverse inductance matrices in the node basis, the inductance vectors in the branch basis, the mutual inductance matrix, the incidence matrix, the port data, and the resolved component values. Built by numericmatrices and symbolicmatrices.
Fields
Cnm: the capacitance matrix in the node basis with each element duplicated along the diagonal Nmodes times.Gnm: the conductance matrix in the node basis with each element duplicated along the diagonal Nmodes times.Lb: vector of branch linear inductances.Ljb: vector of branch Josephson junction inductances.Ljbm: vector of branch Josephson junction inductances with each element duplicated Nmodes times.Mb: the mutual inductance matrix in the branch basis.invLnm: the inverse inductance matrix in the node basis, with each element duplicated along the diagonal Nmodes times. It excludes the mutually coupled inductor branches, which the solvers represent with auxiliary branch current variables (see circuit/mna.jl).Rbnm::SparseMatrixCSC{Int, Int}: incidence matrix to convert between the node and branch bases.portindices::Vector{Int}: vector of indices at which ports occur.portnumbers::Vector{Int}: vector of port numbers.portimpedances::Vector: the reference impedance of each port, ordered by port number. This is what the waves are normalized to, and it is defined for every port whether or not the port owns an environment.portenvironmentindices::Vector{Int}: vector of indices at which the port owned environments occur, ordered by port number, with zero for a port which owns none.Lmean: the mean of the linear and Josephson inductances, zero when the circuit has none; the solvers replace it by the solver scale ofcalcsolverscaleunder the same name.vvn: the vector of component values with the definitions substituted.frequencydependent: theFrequencyDependentTermsof the components whose values depend on the frequency, which the matrices hold open, a zero capacitance or an infinite resistance or inductance, so thatLbholds the inductance of a branch's other inductors and an infinite one on a branch without any; ornothing.
JosephsonCircuits.CircuitMatrixPlan Type
CircuitMatrixPlanEverything about a circuit's matrices which depends on its topology but not on its values, for one mode count.
Holds the nodal, branch and mutual stamp plans, the ports and the mode expanded incidence matrix. Rebinding at new component values reuses all of it; only the values are refilled. See circuitmatrixplan and assemblematrices.
A plan depends on the compiled circuit alone; the scratch of a refill is a CircuitMatrixWorkspace, one per solve.
JosephsonCircuits.CircuitMatrixWorkspace Type
CircuitMatrixWorkspace(plan::CircuitMatrixPlan, nm::CircuitMatrices)Scratch for refilling matrices built from plan. Reuse it with the same patterns and numeric types, and keep separate workspaces for concurrent solves.
JosephsonCircuits.CircuitTopology Type
CircuitTopology(edge2indexdict, Rbn, Nbranches)The branches of a compiled circuit, which is what the solvers read of its graph.
Fields
edge2indexdict: maps a branch(node1, node2)in either orientation to its branch index, the row ofRbnit occupies.Rbn: the sparse oriented incidence matrix,NbranchesbyNnodes - 1; the ground node column is omitted.Nbranches: the number of branches,size(Rbn, 1).
compile builds one for every circuit, see circuittopology.
JosephsonCircuits.ClusterBlocks Type
ClusterBlocksThe block factorization of one cluster of modes over the circuit graph: the BlockLU of the supernodes, the natural slots its blocks are assembled from, and the work arrays of a solve. Built by clusterblocks, assembled by assembleblocks!, factorized by blocklu! and applied by clustersolve!.
JosephsonCircuits.ClusterProbe Type
ClusterProbeThe state of a Clusters request: the block diagonal preconditioner the probe solves with, the probe vector and its per mode norms, the probed strength matrix W, the couplings taken so far and the current cluster mask, and the flag stalled! raises to remeasure. See probecouplings! and spectralclusters.
JosephsonCircuits.Clusters Type
Clusters(; factorization = nothing)Clusters of modes measured from the operator: the block Jacobi coupling strengths are probed and modes merged in decreasing strength until the couplings left between clusters are contractive; see spectralclusters. Probed at the first point and again whenever the solver reports a slow linear solve; the clusters only grow within a solve. With a BlockFactorization each cluster is one dense block factorization over the circuit graph, whose factors take less memory than those of FullJacobian.
JosephsonCircuits.CompiledPort Type
CompiledPortAn analysis port and the environment it owns.
environment is the flat table index of the port's own termination, or 0 when the port owns none. It is recorded here when the port is compiled, so nothing downstream needs to look for a resistor on the port's branch, and a port may share its terminals with any number of ordinary device resistors. temperature is the physical temperature in kelvin of that termination (see MatchedTermination), zero for a port which owns none.
The reference impedance is not stored here: it is the value of the port's own entry in the flat component table, at component, so it is bound like every other value and read from the bound table by portreferenceimpedances.
JosephsonCircuits.CompiledScatteringBlock Type
CompiledScatteringBlockA multiport ScatteringParameters instance after compilation: its definition, its instance path, and the node of the signal and reference terminal of each port, signalnodes[p] and refnodes[p]. A block has no entries in the flat component table.
JosephsonCircuits.ComponentPerturbation Type
ComponentPerturbationThe derivative of the scaled equations of a TransientProblem with respect to a relative perturbation p -> r*p at r = 1 of the value of each of a set of named components, which the tangent and the adjoint of a recorded transient carry as directions and objectives of their own (see transientsensitivity). The equations are affine in C, 1/R, 1/L and 1/Lj, so the derivative is the component's own contribution to each matrix, with a sign, as SensitivityStamp has it for the linearized solve, built from the same classification (componentstamp) so that the two solvers support the same components and reject the same ones. A component which is a port's own termination moves the port's reference impedance and conductance with it, as the linearized solve has it, which enters the port waves directly (see directcoefficients).
Fields
names: the component names, in the order of the directions.entries,hostentries: the derivatives as their stored entries, onePerturbationEntriesper kind on the backend and on the host, which the adjoint contracts its multipliers against; a component touches a few entries, so the contraction and its work are the size of the entries, not of the state times the components.forcing: for a tangent, the derivatives of the scaled capacitance, conductance, stiffness and junction current of every component stacked,dC,dG,dL,dJon the backend with rows(c - 1)n + 1tocnholding componentc's, so one product gives every component's forcing at once, andhdG,hdL,hdJon the host for the endpoint of a Gauss-Legendre step; the tangent's directions are dense right hand sides in any case.nothingfor an adjoint, which never forms them.states: whether any component reads the state; the junctions alone read only the phases the record always holds.ports: the row of the port whose termination each component is, the row of its trace, or zero.
JosephsonCircuits.CompositeLayout Type
CompositeLayoutThe canonical state layout, [internal | vdc], and where the zero frequency entries of the internal state are.
Fields
rdim: the length of the internal real state, which is the first block.ndc: the number of zero frequency entries in it: one per node and one per auxiliary unknown, in internal order.nvdc: the length of the explicit voltage block, which follows. Zero until a circuit injects direct current.dcpos: for thekth zero frequency entry, its position in the internal state.
The direct current window is the ndc + nvdc entries the block reads and writes: the zero frequency entries first, then the voltages. Window entry k sits at canonical position windowindex(L, k).
See compositelayout.
JosephsonCircuits.ConnectionPlan Type
ConnectionPlan{T}The merges by which connectS! connects networks, which connectS_initialize works out from the numbers of ports of the networks and the connections alone. steps holds a merge (a, b, k, l) for each connection, in order: port k of the network at slot a is joined to port l of the network at slot b, the merged network taking slot a, or to its own port l when a == b. The networks left at the end are those at the slots remaining, with the ports ports, tuples of network name and port number. nports holds the number of ports of the network at each slot before the merges, which the networks the plan is applied to must have.
JosephsonCircuits.ConstantMatrixProvider Type
ConstantMatrixProvider(A)A frequency independent matrix provider wrapping the matrix A.
JosephsonCircuits.CouplingMask Type
CouplingMask(mask; factorization = nothing)The mode coupling set given in full: mask is a square Bool matrix over the retained modes of the solve, in the order of the modes of its NonlinearHB, and the block of the Jacobian coupling column mode m2 into row mode m1 is kept where mask[m1, m2]. Every other member of the family is a mask of this kind (couplingmask); this one takes it as written, for a structure the others do not express.
JosephsonCircuits.DCAugmentation Type
DCAugmentationThe explicit direct current block of an HBNonlinearProblem.
Fields
work: theCanonicalWorkholding the layout, the transport rows and the blocks' zero frequency rows.jplan: theCanonicalJacobianPlan, ornothingwhen no Jacobian was assembled.jint: the internal Jacobian the plan reads, ornothing.keep: the diagonalDover the direct current window: one where a row is added to and zero where the block replaces it.constant: the block's drive dependent constant, at the drive the problem was built with.dcmatrix: the transpose of the block's constant matrixM, restricted to the window, which is what the transposed product needs.scale: the drive scale, kept in step withsetdrive!.win: the canonical positions of the direct current window, which the transposed product gathers and scatters by, held because they are a property of the layout and the product runs inside the Krylov loop.dwork,Fwork,zwork,mwork: workspaces for the transposed product.
JosephsonCircuits.DCBlockDescriptor Type
DCBlockDescriptorThe zero frequency constitutive pencil of one scattering block.
Fields
B0,C0:(I - S(0)) R^(-1/2)and(I + S(0)) R^(1/2), so the block's rows readB0 V - C0 i = 0.signalnodes,refnodes: the terminals of each port.auxbase: the auxiliary index base, as inStampedScatteringBlock.name: the block's first port, for messages.
JosephsonCircuits.DCBlockRows Type
DCBlockRowsThe zero frequency rows of every scattering block in a circuit, ready to be applied to a canonical state.
Fields
descriptors: oneDCBlockDescriptorper block.currentindex: for each block, the window position of each port's zero frequency current: its slot among the zero frequency entries of the state, one per node and then one per auxiliary unknown.signalcomponent,refcomponent: for each block, the static flux component of each port terminal, or zero where the average voltage is held at zero by a path to ground through inductance.scale: the solver scale (seecalcsolverscale), which carries the average voltage into the units the stamp's rows are written in.transportterms:(component, window position of the current, sign)for each block current which crosses a static flux component boundary.
The units are the stamp's throughout. At a nonzero frequency the block's row is B (im w scale phi) - C i, so the stamp's voltage is scale/phi0 times the physical one; the explicit direct current coordinate is v = V/phi0, so the same voltage is scale * v and the row is B0 (scale dv) - C0 i with the current the solver already carries.
JosephsonCircuits.DCConductancePlan Type
DCConductancePlanThe topology of the direct current voltage block.
Built from the circuit and its assembled conductance; holds nothing which depends on the sources. It exists whenever there is a zero frequency mode, with no components when every node is held at zero by an inductive path to ground, so that the block relations and the classification have the nodal rows and the conductance to work from.
Fields
modeindex: the zero frequency mode.components: the nodes of each floating static flux component.componentof: the component index of each node, zero for a node whose average voltage is fixed at zero by a path to ground through inductance.lift:P, mapping a component voltage to its nodes.conductance:G0, the direct current conductance in the solver's scaled units.reduced:Y = P'G0P, the conductance seen between components.voltagescale:Z0/Lscale, which puts an average voltage in the units of a block current. In the solver's units a voltage isV/phi0and a currentI Lscale/phi0, so the voltage across the reference impedanceZ0isZ0/Lscaletimes the current through it. The classification scales the average voltages by it (seedcpinning).
JosephsonCircuits.DCConductanceSolution Type
DCConductanceSolutionThe solved average voltages and the direct current they carry.
nodevoltage is in volts, indexed by node with ground first and identically zero. On a floating island only voltage differences are physical; one component of it is held at zero as a reference.
A solution exists exactly when the analysis has a zero frequency mode. When no direct current is injected it is the zero every average voltage sits at, which is an answer and not the absence of one: a node shorted to ground sits at zero volts. Only an analysis with no zero frequency mode has no average voltage to report.
Fields
nodevoltage: volts, indexed by node with ground first and identically zero.scaledcurrent:G0 P v, the direct current each node carries in the solver's scaled units, with ground dropped; what the Kirchhoff current law validation andapplydcconductanceread.
JosephsonCircuits.DCFactorization Type
DCFactorizationThe factorization of the direct current subsystem and the indices it acts on, resident on a backend.
Fields
index: the canonical position of each subsystem coordinate.perm,factors: for a subsystem of at mostDCDEVICESOLVEMAXunknowns, the row permutation and the packed unit lower and upper triangle of its denselu, which the kernel substitutes through; empty for a larger one.work: a device scratch vector of lengthn, the permuted right hand side and then the solution.n: the subsystem size.lu,host: the sparse factorization on the host and a host vector of lengthn, which a subsystem larger thanDCDEVICESOLVEMAXis solved with.
JosephsonCircuits.DCOperatingPoint Type
DCOperatingPointThe explicit direct current block at a converged point.
Fields
work: theCanonicalWorkcarrying the layout, the transport rows and the blocks' zero frequency rows.u: the converged canonical state,[internal | vdc]: the internal real state as the solver evaluates it, followed by the explicit average voltages (seeCompositeLayout).jacobian: the canonical Jacobian there, which is the one the implicit function theorem applies to when the block is active.keep: the rows the block adds to rather than replaces (dckeep), which mask the harmonic part of a residual derivative.
JosephsonCircuits.DCPinning Type
DCPinningThe references a singular direct current subsystem needs: which redundant equations to give up, and which coordinate each one fixes at zero.
A direction the descriptor does not determine may be pinned only when nothing outside the descriptor can see it. Write the rest of the harmonic residual's dependence on the direct current unknowns as H, the zero frequency nodal currents they drive; a null direction N is a gauge exactly when H N = 0.
The common case is a floating island's average voltage. A conductance island with no path to ground has zero row sums, so raising every voltage in it by the same amount drives no current anywhere, and only differences were ever physical. Choosing a reference there changes nothing.
An ideal through in parallel with an inductor is the opposite. Its free direction is the division of current between the two ideal branches, which cancels in the transport row because both terminals lie in one static flux component, and does not cancel at the nodes: it injects +d at one and -d at the other, moving the inductor current, the static flux across it and, through a junction, the nonlinear operating point. H N is nonzero, and the circuit is refused rather than given one of infinitely many answers.
A reference is written as y_c = 0 for a chosen coordinate rather than as a minimum norm condition on the whole direction. The subsystem mixes volts and amperes, so a minimum norm row is not invariant under a change of units, while fixing one coordinate is; and the row it produces has a single entry.
Fields
rows: positions in the subsystem whose equation is replaced.cols: the coordinate each replaced row fixes at zero.
JosephsonCircuits.DCUpdate Type
DCUpdateThe direct current block's contribution to the residual as keep .* Fw + M*uw + c, in whatever array type the state uses.
cresidual carries the injected current; the Jacobian vector product uses the same M and keep with no constant, the two differing only by that.
JosephsonCircuits.DeviceBlockNoisePlan Type
DeviceBlockNoisePlanThe noise channels of the dissipative scattering blocks, on a backend.
Where the host path reads the auxiliary port current rows of an adjoint solution it has brought back, this describes the same channels as flat tables, so blocknoisefactorkernel! and blocknoisecontractkernel! can form them where the solution already is. The scattering data itself comes from the DeviceProviders the stamps are evaluated through, so this holds only what those do not: which block each entry is, where its auxiliary rows and its factor live, which entry each channel belongs to, and which entries form the factors: the instances of one definition share its factors, formed at its first.
JosephsonCircuits.DeviceFrequencyDependentStamps Type
DeviceFrequencyDependentStampsThe stamps of the frequency dependent components of a linearized system (see FrequencyDependentStamps) on a backend, for a batch of signal frequencies.
assemblesweep! covers the terms which are a constant quadratic in the signal frequency, and the matrices it reads hold these components open. Their values are those of their functions at the mode frequencies, arbitrary Julia callables, so the functions are evaluated on the host, each distinct one once a mode frequency, into the batch's table, a column per frequency and a row per function and mode, which is sent; a kernel then forms each stamp from its row of the table and adds it (applyfrequencydependent!).
The table serves both directions of a sweep: the value of a stamp does not depend on the direction the system is assembled in, only its destination does, so the adjoint direction gets a second view with destinations of its own (see transposedestinations).
JosephsonCircuits.DeviceNoisePlan Type
DeviceNoisePlanThe noise ports of a circuit, on a backend, for noiseoutputwavekernel!: their nodes, impedance codes, and the value of each at each mode, a column per port. A port whose component value depends on the frequency is the row of its function in the linearized system's table of their values (a TableRow): the ports tableports, of the rows tablerows, whose columns of valueshost each signal frequency fills from the table and sends.
JosephsonCircuits.DeviceProviders Type
DeviceProvidersThe scattering blocks of a stamp system on a backend, as flat tables.
The values a batch of system matrices needs are otherwise computed on the host, because a callable provider is an arbitrary Julia function. A block whose data is tabulated or constant is not: its evaluation is a search and an interpolation, which is the shape a kernel wants. When every block of a circuit is one of those, the whole evaluation moves to the backend and the host does nothing per frequency at all.
A constant block is stored as a one point table, so it needs no separate path. Which frequency a block is evaluated at still depends on its negative frequency rule, and a range which must not be extrapolated is checked on the host before each batch, because a kernel cannot raise.
sourceJosephsonCircuits.DeviceScatteringStamps Type
DeviceScatteringStampsThe scattering block contribution to a batch of system matrices on a backend.
assemblesweep! covers the terms which are a constant quadratic in the signal frequency, which the scattering blocks are not: each is evaluated through its own provider, an arbitrary callable or an interpolation of tabulated data, so its values have to be computed on the host. What is left is a gather-add into the stored entries, which is this.
The values serve both directions of a sweep: a block's contribution does not depend on the direction the system is assembled in, only on where in that system's stored order each scalar lands. So they are computed and sent once, and the adjoint direction gets a second view of them with its own destinations (see transposedestinations).
The values are computed on the host, because a callable provider is an arbitrary Julia function. A block whose data is tabulated or constant needs no host at all; see plandeviceproviders.
JosephsonCircuits.DeviceSparsePattern Type
DeviceSparsePattern{Ti,V}The sparsity structure of a sparse matrix, compressed by columns, resident on a backend. Carries no values: it describes where the stored entries are, which is all the device path needs of the Jacobian's structure.
The Jacobian is held transposed on a device, so this is usually the pattern of the transpose and its columns are the Jacobian's rows.
Fields
colptr,rowval: the compressed columns.m,n: the shape of the matrix this describes, sosize(p) == (m, n).
JosephsonCircuits.DeviceSweep Type
DeviceSweepThe state of a linearized sweep computed on a device a batch of frequencies at a time, built by devicesolutions and driven by four verbs: solvebatch! solves the batch beginning at a frequency index and stages its solutions on the host, forwardsolution! and adjointsolution! fill the solution of any frequency of the staged batch, and adjointdevice hands out the adjoint solution of a frequency where it was computed, for the noise scattering parameters.
Fields
backend,nb,F: the backend, the batch size and the number of frequencies.w,wpumpmodes,wshost,wsdev: the signal frequencies, the pump mode offsets, and the frequencies of the current batch on the host and on the device.fwd,adj: the batch of each direction,(plan, rowptr, colind, nzval, X, B, B0, equil)on the sparse device factorization path,B0the unscaled right-hand side each batch scales intoB, or(X,)on the block path, andnothingwhen no adjoint was asked for.fstage,astage: the staging of each direction,(full, rows, rowsd, gathered, host).blocks: the block path's(plan, nzval, B, F, X, Xadj), ornothing.scatstamps,scatstampsadjoint,providers: the scattering block stamps of each direction and the providers they are evaluated through.fdstamps,fdstampsadjoint: the stamps of the frequency dependent components of each direction (DeviceFrequencyDependentStamps), ornothingwhen there are none.sweeps: the cuDSS sweep of each direction, made on the first batch.solverkwargs: the factorization's options, forwarded to each sweep as it is made so a caller can override the sweep's own defaults.batchlo: the first signal frequency of the batch currently staged.
JosephsonCircuits.DeviceValuedSparseMatrix Type
DeviceValuedSparseMatrix{Tv,P,V} <: AbstractMatrix{Tv}A sparse matrix whose values live on a device, in the stored order of a compressed sparse row matrix, and whose structure is a DeviceSparsePattern on the same backend.
The structure is held as the transpose, because the compressed columns of the transpose are the compressed rows of this matrix: patterntranspose is therefore a row pointer and a column index array already, and a device sparse matrix can be built from it with no conversion at all. That is also the form realjacobianstructure produces directly when asked for it with transposed = true, which is why nothing here permutes anything.
Use nonzeros to reach the device values, and rowpointer and columnindices to reach the structure. An entry is not read one at a time, so a factorization which does not have a method for this type fails on it rather than reading it element by element.
Fields
patterntranspose: the stored transpose, aDeviceSparsePattern.nzval: the values on the device, in the stored order of the transpose.
JosephsonCircuits.ElaboratedCircuit Type
ElaboratedCircuit(definitions, definitionof, instancepaths,
terminaloffsets, terminalnets, netnames, couplings)The flattened result of elaborate: the hierarchy resolved to a list of primitive instances, definitions deduplicated by identity, and nets numbered densely with the ground net first.
Fields
definitions::Vector{Any}: the unique component definitions, deduplicated by object identity, so that a thousand instances of one shared definition store its data once.definitionof::Vector{Int}: for each flattened primitive instance, the index of its definition indefinitions.instancepaths::Vector{String}: the hierarchical path of each instance, such as "cell37/cap", with "/" as the separator.terminaloffsets::Vector{Int}: offsets intoterminalnetsin CSR layout; the terminals of instanceiareterminalnets[terminaloffsets[i]:terminaloffsets[i+1]-1].terminalnets::Vector{Int}: the net index of every instance terminal. Net 1 is the ground net.netnames::Vector{String}: the net names;netnames[1] == "0"is the ground net. User suppliedNetnames win over automatic names; nested names are hierarchical, such as "cell37/net2".couplings::Vector{NTuple{3,Int}}: for each mutual inductor, the flattened instance indices(mutualinductor, inductor1, inductor2).
JosephsonCircuits.ErasedFunction Type
ErasedFunction(f)A callable which calls f and returns nothing, with f held in a field of type Any. Code which calls it is compiled once whatever f is, where a closure over an HBSystem has a type of its own for every precision, backend, tone count and layout of the system. Each call is one dynamic dispatch, and its arguments cross it boxed unless they are heap objects already, so it suits a call which does heavy work on arrays: the residual and the Jacobian-vector product of nlsolvekrylov!.
JosephsonCircuits.ErasedPreconditioner Type
ErasedPreconditioner(pc::AbstractPreconditioner)pc held in a field of abstract type, the counterpart of ErasedFunction for a preconditioner: code which applies it is compiled once whatever pc is, and every hook reaches pc through one dynamic dispatch. A column view, which GMRES applies the preconditioner to at every Arnoldi step, crosses the dispatch as its matrix and its column index rather than as a view, which the dispatch would box.
JosephsonCircuits.FactorizationCache Type
FactorizationCache(factorization = nothing)A mutable holder for a factorization object, so that tryfactorize! can refactorize into it across calls, and for the fill reducing ordering of the sparsity pattern it factorizes, so that a fresh factorization of the same pattern takes that ordering rather than choosing again (fillordering). Starts empty (nothing) when constructed without an argument. The ordering is chosen by the first fresh factorization of a pattern, or handed in by seedordering!.
Examples
julia> JosephsonCircuits.FactorizationCache(JosephsonCircuits.KLU.klu(JosephsonCircuits.sparse([1, 2], [1, 2], [1/2, 1/2], 2, 2)));JosephsonCircuits.FillOrdering Type
FillOrdering(perm, fill)
FillOrdering(perm, fill, rows)A fill reducing ordering of a sparsity pattern as fillordering chooses it: the permutation perm, perm[k] the original index of the column of the kth pivot, rows that of its row, perm itself unless the diagonal of the pattern has structural zeros, and fill, the entries of one triangular factor of the pattern under it, diagonal included, as symbolicfill predicts them. kluordered sizes the first allocation of a fresh factorization from fill, and sparsefactorbytes the memory of the factors. The choice depends only on the pattern, so one serves every factorization of it: a FactorizationCache holds the one it was handed or chose (seedordering!).
JosephsonCircuits.FloatingBalance Type
FloatingBalanceThe floating subnetworks of a TransientProblem which its drives feed, judged whenever the drives are evaluated (checkbalance): a net current into a subnetwork no element connects to ground has no path back. islands indexes the problem's floatingcomponents and nodes names their nodes; net[k, r] is the net injection of a unit current of drive k into island r, a column for each island holding the drives which feed it, two islands at most for a drive's two terminals, constant[r] the net constant current into it and magnitude[r] the sum of the magnitudes that net gathers, and the total may differ from zero by terms roundings of the magnitudes it sums.
JosephsonCircuits.Floquet Type
Floquet(inner = BlockDiagonal(); size = 20, harvest = 4,
candidates = 3*size, ranktol = nothing, benefittol = 1e-6)The preconditioner inner wrapped in a FloquetPreconditioner: the residual-image deflation with physical candidates. harvest is the number of singular directions taken from every GMRES restart cycle, candidates the size of the candidate bank, ranktol the rank tolerance of the residual image (nothing for the precision's default) and benefittol the predicted improvement below which a candidate is not built in.
JosephsonCircuits.FloquetPreconditioner Type
FloquetPreconditioner(spec::Floquet, inner::AbstractPreconditioner, jvp!,
b::AbstractVector; state = nothing)Augments a base preconditioner with a low-rank correction for the few global channels it represents badly, in the residual-image A-DEF1 form.
The hypothesis this is built on is not that the harmonic balance Jacobian J is low rank, which it is not, but that the defect of a cheap base preconditioner,
D = I - J*inv(P),has low effective rank: that a mode block diagonal already solves almost every direction of a multi-tone problem, and what it leaves is a handful of global spectral-spatial channels — an amplifier's signal-idler pair, a dominant conversion channel, a weakly damped Floquet mode. Those are the directions this deflates.
The residual-image form
Candidate correction vectors X0 are held in the physical state space, not in a residual or Krylov coordinate system. At each rebuild their exact images Y0 = J*X0 are formed and factorized, Y0 = U*S*V'. Keeping the numerically significant rank r,
C = U[:, 1:r], X = X0*V[:, 1:r]*inv(S[1:r])so that
J*X = C and C'C = Ihold by construction. With W = X - inv(P)*C the preconditioner is
inv(Pdef) = inv(P) + W*C'applied as z = inv(P)*r + W*(C'*r): one base solve and two dense mat-vecs with an n by r matrix, and no Jacobian product. Because J*X = C exactly,
J*inv(Pdef)*C = J*(inv(P)*C + W) = J*X = C,so range(C) is an exact eigenspace of the right preconditioned operator at eigenvalue one and GMRES never has to resolve those directions again.
Why not the Galerkin pairing
A deflation may instead build its coarse correction from G = Z'*J*Z and a truncated pseudo inverse of it. That pairing is the natural one for a symmetric positive definite system. This Jacobian is none of those things: it is nonsymmetric, strongly nonnormal, and near a parametric threshold nearly singular. A perfectly good correction direction can then have J*z large while z'*J*z is nearly zero, which makes G ill conditioned for a reason that has nothing to do with the quality of z. Orthonormalizing the image J*X instead of the pairing X'*J*X removes that failure mode, needs no projected inverse at application time, and measures the subspace in the Euclidean norm GMRES actually minimizes.
Candidates
Candidates come from the harvest, which takes the smallest singular directions of the rectangular Hessenberg of the Arnoldi factorization of each restart cycle of each solve (harvestcycle!): directions robust on a nonnormal operator. They are mapped through the current preconditioner into physical coordinates before being stored, so that a candidate stays meaningful after the Jacobian moves.
No candidate is trusted. The residual-image factorization decides the rank, which removes candidates that rediscovered the same channel, and each surviving direction is then tested for whether the base preconditioner needs help with it at all,
eta = norm(x - inv(P)*J*x)/norm(x),with directions below benefittol dropped: physically interesting but numerically easy channels cost nothing to carry and are not carried. For an amplifier this is the asymmetry between the amplified quadrature, which needs a large correction, and its deamplified partner, which often does not.
That test is applied in the eigenbasis of W'W and nowhere else, which is not a detail. The rank-revealing factorization pins down range(C) but not a basis of it, and the basis it happens to return is arbitrary whenever the retained singular values are close together — which is the normal case here, not a degenerate one, because equalizing candidates by their image norms is what makes those singular values close. eta is not invariant under a rotation of the subspace, so measured in an arbitrary basis a correction of true rank two can present as six columns of comparable eta, each holding a mixture of what the base misses and what it handles, and nothing is droppable. The eigenvectors of W'W diagonalize the correction, so they are the one basis in which the split is visible; they also order the directions by how much correction each carries, which is the order the cap at size wants.
Cost
Per application: one base solve and two dense mat-vecs. Per rebuild: k Jacobian products for the candidate images and r base solves for inv(P)*C. A rebuild happens when the base is rebuilt and, lazily, when the point moves under a frozen base (pointmoved!).
Options
The fields of the Floquet value spec, validated at its construction:
size = 20: the largest active rank retained. When more directions survive both filters the update is compressed to thesizeprincipal directions ofW'W, that is, those carrying the most correction.harvest = 4: smallest singular directions taken per restart cycle.candidates = 3*size: the candidate bank's capacity. The active directions of the last rebuild are always kept, and older candidates are dropped first. A rebuild resets the bank to the active set, so the capacity bounds what the harvests bank between two rebuilds,harvestdirections for every restart cycle of their solves.ranktol = eps(T)^(3/8): relative singular value threshold for the residual-image rank. The candidates' images are equalized to unit norm, so a small singular value of their block means two images nearly parallel, a channel two sources rediscovered, not a small image; the threshold is the angle below which they count as one. The rank is read off the Gram matrix of the images, whose roundoff isk*epson the squared singular values, so the threshold sits abovesqrt(k*eps)with margin (eps^(3/8)is1.4e-6in double precision).benefittol = 1e-6: theetabelow which a direction is judged already handled by the base.
The constructor's own keyword state = nothing is a FloquetState to start from, the candidates of a previous solve of a nearby system, which the harvests of this solve mutate; a fresh FloquetState(b) is built when none is given.
The intended base is the mode block diagonal, and everything here is either a dense level 3 kernel on a small block or a device gemv, with the k by k factorizations on the host, so the pairing ports to a GPU for the same reason that one does. The three-argument application reads r after writing z, so the two must not alias.
JosephsonCircuits.FloquetState Type
FloquetState(b::AbstractVector)The part of a FloquetPreconditioner that outlives one solve: the candidate physical correction vectors X, an n by k matrix allocated like b. A candidate is a direction of the unknowns; its image under the current Jacobian is recomputed at every rebuild, so it means the same thing after the base has been rebuilt or rebound to a new operating point. HBReuse carries one across a cached sweep and replaces it only after a converged solve.
JosephsonCircuits.FourierIndices Type
FourierIndices(vectomatmap::Vector{Int}, conjsourceindices::Vector{Int},
conjtargetindices::Vector{Int}, hbmatmodes::ModeDifferences{N},
hbconjmatindices::Matrix{Int})A simple structure to hold time and frequency domain information for the signals, particularly the indices for converting between the node flux vectors and matrices. The hbmatmodes matrix holds the differences of the modes, which describe the coupling between the modes (the derivative of the residual with respect to the node fluxes), while the hbconjmatindices matrix is built from the sums of the modes, aliased back onto the sampled grid, and describes the coupling between the modes and the complex conjugates of the modes (the derivative of the residual with respect to the complex conjugates of the node fluxes).
The differences are computed entry by entry when read (ModeDifferences): a solve places them on the sampled grid with hbmatindices, with aliasing for the exact Jacobian and without it for the holomorphic one, and selects the preconditioner's bands by them. See also fourierindices.
JosephsonCircuits.Frequencies Type
Frequencies(Nharmonics::NTuple{N, Int}, Nw::NTuple{N,Int}, Nt::NTuple{N,Int},
coords::Vector{CartesianIndex{N}}, modes::Vector{NTuple{N,Int}})A simple structure to hold time and frequency domain information for the signals. See also calcfreqsrdft and calcfreqsdft.
Fields
Nharmonics::NTuple{N, Int}: The number of harmonics of each frequency the grid samples, which setsNwandNt; the modes kept may be fewer.Nw::NTuple{N,Int}: The dimensions of the frequency domain signal for a single node.Nt::NTuple{N,Int}: The dimensions of the time domain signal for a single node.coords::Vector{CartesianIndex{N}}: The coordinates of each mixing products.modes::Vector{NTuple{N,Int}}: The mode indices of each mixing product, eg. (0,0), (1,0), (2,1).
JosephsonCircuits.FrequencyDependentComponents Type
FrequencyDependentComponentsThe capacitors, resistors and inductors of a bound circuit whose values are FrequencyDependent: the distinct functions of their values, as === tells them apart, in providers, and for each group the position of each such component in it and the index of its function.
JosephsonCircuits.FrequencyDependentStamps Type
FrequencyDependentStampsThe terms of the frequency dependent components of a linearized system (see FrequencyDependentTerms) placed in its system matrix: for each term at each mode, the stored entry it adds to, the mode, and the term's kind, sign and function, an index into the distinct functions providers. Their values at the mode frequencies of a signal frequency are a table filled once (see providertable), which assemblesystemmatrix! and the noise waves read.
JosephsonCircuits.FrequencyDependentTerms Type
FrequencyDependentTermsThe stamps of the frequency dependent components of a circuit on its capacitance, conductance and inverse inductance matrices, at one mode: for each, the matrix (kind, 1 the capacitance, 2 the conductance, 3 the inverse inductance), the row and column of its entry in the one mode matrix, the sign of the stamp, and the index of its function among providers. The matrices hold the circuit without these components; a term adds at its entry of every mode, of frequency w, the sign times the value of its function at abs(w), the capacitance, or its inverse, the conductance of a resistance or the inverse of an inductance, conjugated where w is negative, as any value of those matrices is.
JosephsonCircuits.FrequencySweepPlan Type
FrequencySweepPlanEverything needed to assemble the linearized system matrix of hblinsolve at many signal frequencies at once, on a backend.
The per-frequency assembly of assemblesystemmatrix! is
A = AoLjnm + invLnm + im*Gnm*w - Cnm*w^2 + Amna0with the frequency of each stored entry taken from its column's mode, and with the stored value of every term conjugated where that mode frequency is negative (see modevalue). Each stored entry is therefore an independent quadratic in its own mode frequency, and the whole assembly collapses to four constant coefficient vectors and one kernel:
A[q] = cst[q] + sel(kinvL[q]) + im*wm*sel(kG[q]) - wm^2*sel(kC[q])where wm = ws + wpumpmodes[mode of q] and sel conjugates when wm < 0. The terms which share a frequency power and a conjugation rule are summed into one coefficient at build time: Amna0, the coupled inductances, is conjugated at a negative mode frequency as invLnm is, and goes with it, while AoLjnm, the pump's junction term, is evaluated at the signed modes and is not conjugated. Conjugation distributes over a sum, so this is exact.
Because the coefficients do not depend on the signal frequency, one kernel fills the stored values of a whole batch of frequencies, which is what a uniform batch wants, whether cuDSS's or the batched block factorization's: the batch shares one sparsity pattern and one symbolic analysis, and only the values differ. The matrices hold the components whose values depend on the frequency open, so the coefficients leave them out; their stamps are added to the batch by applyfrequencydependent!.
Fields
colof: the matrix column of each stored entry, from which its mode follows, so the kernel needs no search. For the forward structure this is also the structure's own column index array; for the transposed one it is not, so it is carried separately.cst,kinvL,kG,kC: the four coefficient vectors, in the stored order of whichever structure the plan was built for (compressed sparse row of the matrix for the forward plan, the matrix's own stored order for the adjoint one).wpump: the pump mode frequency offsets of the signal modes.assemble!,backend: the compiled assembly kernel and the backend it was compiled for.nmodes,nnz: the mode count the kernel takes a column's mode from, and the number of stored entries, which sizes the value matrix.
JosephsonCircuits.FullJacobian Type
FullJacobian(; factorization = nothing)Every mode coupling: the full Jacobian, an exact preconditioner and a direct solve. With a BlockFactorization this is the dense block factorization over the circuit graph, which Automatic chooses for two or more tones when its factors fit in memory.
JosephsonCircuits.FunctionOperator Type
FunctionOperator(f!, n)Wraps an in-place product f!(y, v) as a mul!-able operator of dimension n, so the Krylov machinery can be written against mul! alone while still accepting a bare closure.
JosephsonCircuits.GMRESWorkspace Type
GMRESWorkspace{T<:AbstractFloat}Preallocated storage for gmres! with a restart length of m on a system of dimension n. Holds the n x (m+1) Arnoldi basis V, the (m+1) x m Hessenberg matrix H as the Givens rotations leave it, the Givens rotations cs and sn which reduce it, the least squares right hand side s, its solution y, three length n work vectors, the two length m staging buffers hd and cd of the block Gram-Schmidt projection, allocated like V, and external, the workspace an external linear solver (KrylovJL) keeps between the solves of one system, nothing until one is made.
The dominant cost is V, which is n*(m+1) numbers, so m trades memory and orthogonalization work against restart frequency. It is not paid up front: the basis is allocated with a few columns and grows, by doubling, to what the iteration uses, up to m + 1. A restart length long enough for the hardest solve is then free on the easy ones, where a warm started Newton step takes a handful of Arnoldi steps, and the cost of a solve is no longer dominated by touching a basis it never fills. See ensurecolumns!.
JosephsonCircuits.GMRESWorkspace Method
GMRESWorkspace(b::AbstractVector{T}, m::Integer)Build a workspace for a restart length of m on a system whose right hand side is b. The system sized arrays are allocated with similar(b), so they live wherever b does and the iteration runs on that device; the projected m x m quantities are host arrays regardless, because the Givens rotations and the back substitution index them entry by entry.
JosephsonCircuits.HBLinearizedSystem Type
HBLinearizedSystemEverything needed to assemble the linearized harmonic balance system matrix on the signal frequency grid at any signal frequency, built with the same plan machinery (plancomplexjacobian and addjosephsonterm!) used for the Jacobians of the nonlinear system by HBSystem. hblinsolve constructs one of these and its per-frequency solves are expressed through it, so any external use of this object is exercising exactly the production linearized solver path.
Use assemblesystemmatrix! to assemble
A(ws) = AoLjnm + invLnm + im*Gnm*W - Cnm*W^2(with the negative frequency mode conjugations and the frequency dependent values resolved, as the linearized solver does) into a matrix sharing the sparsity structure of the Asparse field, at the signal frequency ws, for either the pump modulation AoLjnm or its complex conjugate. Operator products and adjoint products are then sparse matrix-vector products with the assembled matrix, mul!(y, A, v) and mul!(y, A', v), suitable for iterative solves and sensitivity adjoints.
Unlike HBSystem, no time domain matrix-free product is provided, deliberately: a Fourier transform based product computes a cyclic convolution on the pump grid, whereas the assembled matrix uses the explicit truncation of hbmatindices (the zeros of Amatrixindices), dropping the couplings which fall outside the grid instead of wrapping them. The assembled matrix defines the linearized solver, so products must match it exactly; since the pump modulation contribution is precomputed, assembling at a frequency costs about the same as one matrix-vector product would, and every product thereafter is a plain sparse matrix-vector product.
JosephsonCircuits.HBLinearizedSystem Method
HBLinearizedSystem(Amatrixindices::Matrix, Ljb::SparseVector,
Rbnm::SparseMatrixCSC, Nmodes::Integer, Nbranches::Integer,
phimatrix::Array, invLnm::SparseMatrixCSC, Gnm::SparseMatrixCSC,
Cnm::SparseMatrixCSC, terms, Amna0::SparseMatrixCSC, wpumpmodes;
scattering = nothing)Construct an HBLinearizedSystem from the signal frequency grid index matrix Amatrixindices (see hbmatindices), the Josephson junction data, the Fourier coefficients of cos(phi(t)) of the pump in phimatrix, the linear term matrices, which hold the frequency dependent components open, with the terms of those components (see FrequencyDependentTerms, or nothing without any), and the frequency independent augmentation Amna0 (the coupled inductor and scattering block port current rows; see calcAmnaind), whose entries are merged into the sparsity structure. scattering is the ScatteringStampSystem of the circuit's scattering blocks, whose pattern is merged as well, or nothing. Builds the sparsity structure and Josephson map with plancomplexjacobian and assembles the pump modulation contribution (the adjoint takes its conjugate) with addjosephsonterm!.
JosephsonCircuits.HBOperatingPoint Type
HBOperatingPoint(sys, x, jacobian, modelayout, Lscale, wmodes,
coupledbranches, Nmodes, dc)The converged pump operating point of hbnlsolve together with everything needed to propagate a component perturbation through it: the HBSystem evaluation object, the converged augmented state, the exact Jacobian of the equivalent real system assembled there, and the scale and layout of the augmented system.
Requested with returnoperatingpoint = true. The Jacobian is the exact Jacobian of the equivalent real system, assembled with assemblerealjacobian!, rather than the complex holomorphic Jacobian of the QuasiNewton method, which is only an approximation: the harmonic balance residual is not complex differentiable, so the implicit function theorem does not hold with the holomorphic Jacobian, while in the real representation it applies directly.
JosephsonCircuits.HBReuse Type
HBReuse()What one solve builds and a later solve of the same circuit at new component values, drive or tone frequencies takes over: the aliased mode coupling index, the padded linear term with its augmentation (PaddedLinearTerm), the HBSystem with its transforms and workspaces, and what the method solves with: under NewtonKrylov the mode coupling preconditioner with its structure and symbolic factorization, the deflation candidates of the last converged solve under a Floquet preconditioner, and the Krylov vectors; under Newton and QuasiNewton the assembled Jacobian with its plan and the factorization with its fill reducing ordering. A circuit which injects direct current is solved by Newton in the canonical coordinates of its direct current block, whose Jacobian plan, ordering and factorization are built at every point rather than kept. Hand one as reuse to the method of hbnlsolve on a mode set and circuit matrices already built, which is the one hbcache calls; it is filled by the first solve and rebound to the new values by every later one, so a sweep pays for its transforms, index maps, orderings and factorization symbolics once, and each Newton-Krylov solve starts from the deflation subspace the previous one harvested rather than from nothing. The preconditioner keeps the coupling set an escalation or a measurement grew it to, since the next point of a sweep generally needs it too; JosephsonCircuits.reset! drops it. hbcache carries one for its sweeps. An ExternalSolver does not read it. The kept objects are mutable and belong to one solve at a time: do not share a reuse between concurrent solves.
Every solve which shares it must be of the same circuit topology on the same mode grid with the same options, which is what a cache guarantees; a solve on another set of modes, at tone frequencies at which the frequency of a mode changes its sign (which decides whether the mode is conjugated), of a system whose sparse structure moved, or of junctions whose current-phase relation changed its kind or its degree, is refused rather than rebound. The component values, the drive, the tone frequencies, the port impedances and the coefficients of the relations among them move freely: other tone frequencies rewrite the mode frequencies the linear term, the system, its plans and the preconditioner read, and restamp the scattering blocks. A solve whose method asks for another preconditioner builds that one in place of the one held.
sourceJosephsonCircuits.HBSystem Type
HBSystemEverything needed to evaluate the harmonic balance nonlinear system and its derivatives at a point: the linear term matrices, the Josephson junction data, the frequency domain packing maps and Fourier transform plans, the real representation layout, optional precomputed Jacobian assembly plans, and preallocated workspaces.
Set the evaluation point with setpoint!, then evaluate any of:
residual!: the residualF(x) = B(sin.(A*x)) + K*x - b,jacobianvectorproduct!: the exact matrix-free Jacobian-vector productJ(x)*v = B(cos.(A*x) .* (A*v)) + K*v,hessianvectorproduct!: the exact matrix-free second directional derivativeH(x)[v, w] = B(-sin.(A*x) .* (A*v) .* (A*w)),jacobian!: the assembled complex (holomorphic) or exact real Jacobian via the precomputed plans,
where A is the linear map from the unknowns to the time domain branch fluxes on the Josephson junctions, B the linear map from a time domain signal back to the node vector, and K the frequency dependent linear terms. Each entry point evaluates in the complex representation or in the equivalent real one, whichever the element type of the output (and direction) vectors is, so the same object serves both the QuasiNewton and Newton methods of hbnlsolve as well as matrix-free solvers.
The time domain branch fluxes and the pointwise sine and cosine at the current point are cached, so repeated products at the same point (eg. the many Jacobian-vector products of a Krylov solve) cost only two Fourier transforms and the linear term each.
Every field the evaluations read is typed by a parameter of the struct, and the loops are behind function barriers which specialize on the concrete argument types. The Jacobian assembly plans are held untyped, so that the type of a system, and everything compiled for it, is the same whichever method's plans it holds; an assembly reaches its plan through one dynamic dispatch. The workspaces of the residual and the matrix-free products are parameterized on their array types rather than fixed to Array, so they can live on whichever KernelAbstractions backend the system was built for.
JosephsonCircuits.HBSystem Type
HBSystem(Rbnm, invLnm, Gnm, Cnm, wmodesm, wmodes2m, bnm, Ljb,
Ljbm, Lscale, Nbranches, freqindexmap, conjsourceindices, conjtargetindices,
phimatrix, phimatrixtd, irfftplan, rfftplan, modelayout,
realjacobianplan, complexjacobianplan, backend = CPU();
realbackward = true, relations = nothing)Construct an HBSystem from the ingredients assembled by hbnlsolve, allocating the workspaces. phimatrix and phimatrixtd are adopted as the frequency domain and one of the time domain workspaces. realjacobianplan and complexjacobianplan may be nothing, in which case the corresponding jacobian! method is unavailable. realbackward = false skips building the real representation of the linear term in the nonlinear term plan, which only a solve in the real representation applies; see plannonlinearterm. backend is the KernelAbstractions backend on which the index mapped kernels run and on which the plan and the workspaces of the residual and the matrix-free products are allocated; CPU() is the default and the reference. phimatrix and phimatrixtd are adopted as given, so pass them already on the backend, and the time domain workspaces derived from them with similar follow. relations are the JunctionRelations of the junctions, or nothing when every one of them is the sinusoidal Josephson relation, for which the evaluations take sin and cos directly. They are moved to the backend and to the working precision here, and the cache of the second derivative is allocated only when there is one to hold.
JosephsonCircuits.HarmonicBand Type
HarmonicBand(p; factorization = nothing)The couplings whose harmonic offset is within p, an Integer number of offset shells or a per tone tuple of integer bounds, held as Ints whatever integers they are written in; see modebandmask. Grown on escalation by one shell, or to the next offset each tone's grid realizes.
JosephsonCircuits.HybridWorkspace Type
HybridWorkspace()Reusable scratch for evaluatehybrid!.
Every call needs the same six small buffers: which frequencies are nonzero, those frequencies, the scattering parameters there, the two square roots of the reference impedances, and the unsigned frequencies the providers are evaluated at. A line whose every cell is its own block evaluates thousands of blocks at every signal frequency, so the buffers are kept and reused: they are reallocated only when a block needs a larger one, which for a circuit whose blocks are all the same size is once.
A workspace is mutable and is written by every call, so it belongs to one task: scatteringvalues! takes one, which its callers make per call when they are not given one, and a caller which passes one gives each thread its own.
JosephsonCircuits.InverseInductancePlan Type
InverseInductancePlanThe fixed pattern of the inverse nodal inductance matrix, and which branch inductances feed it.
positions selects the retained branches out of the assembled branch inductance vector: the coupled ones are dropped, because the solvers carry them as auxiliary MNA currents instead.
JosephsonCircuits.IterationInfo Type
IterationInfo(tr::NewtonTrace, krylov = [])The record of a solve from its trace, with the Krylov records of nlsolvekrylov! when there are any.
JosephsonCircuits.IterationInfo Type
IterationInfo(converged, iterations, normresidual, alpha, backtracks,
andersonaccepted, krylov, reason)Diagnostics recorded for a call of nlsolve! or nlsolvekrylov!.
Fields
converged: whether the iterations converged.iterations: the number of Newton iterations performed.normresidual: the norm of the residual at the start of each iteration.alpha: the accepted step size for each iteration, or NaN for iterations where an Anderson extrapolation was accepted instead of a Newton step.backtracks: the number of linesearch backtracks for each iteration.andersonaccepted: whether an Anderson extrapolation was accepted for each iteration.krylov: aKrylovSolveInforecord for every linear solve performed bynlsolvekrylov!, with one entry per GMRES call rather than per Newton step, so that retries and rescues are visible. Empty for the direct solvers, which take each step from a factorization.reason: why the iteration ended.:converged;:iterationswhen the Newton step budget was spent;:workwhen the Krylov work budget was spent (nlsolvekrylov!only);:linesearchwhen the Newton direction admits no step: a line search with no decrease at all (innlsolvekrylov!again after a retry from a rebuilt preconditioner when the rebuild can change the step), two in a row with a decrease short of the Armijo condition, which is a stall, or a direction which is not a descent direction, or whose merit or slope is not finite (innlsolvekrylov!after its exact rescue);:progresswhen the residual stopped coming down, or comes down too slowly to reach the tolerance within the remaining budget, and its rate is not improving (residualstalled; a first stall is given a fresh history, with a recovery innlsolvekrylov!, a rebuilt preconditioner and exact Newton steps, and the stall is reported only if it persists);:nonfinitewhen the residual norm at the starting point is not finite, which ends the iteration before any step;:externalfor anExternalSolverwhich reported failure or whose root misses the tolerance.stallmessagespells each out.
JosephsonCircuits.JunctionRelations Type
JunctionRelations(value, derivative, negsecond, third,
polynomialjunctions, sinusoidaljunctions)The current-phase relations of the Josephson junction branches of a circuit, whose junction axis is the order of the nonzero entries of the branch inductance vector Ljb, the order of the junction axis of every time domain array the solvers hold.
A relation is either the sinusoidal Josephson one or a PolynomialCPR, and the junctions are grouped by kind once: polynomialjunctions and sinusoidaljunctions are the ascending positions on the junction axis of each, so that each relation is evaluated over its own junctions alone. The polynomial coefficients of the polynomial junctions sit in the rows of value, in the order of polynomialjunctions, in evalpoly order along the second axis and padded with zeros to one common degree, so that a single Horner loop evaluates them all; derivative and negsecond hold the coefficients of the first derivative and of the negative of the second, which is the combination the Hessian and the derivative of the linearized system with respect to the operating point are written in, and third those of the third derivative, which the trilinear form of the problem interface takes.
A circuit whose junctions are all sinusoidal, which is every circuit that does not ask for anything else, has the empty table (see allsinusoidal), and the solvers take the plain sin and cos of the Josephson relation.
JosephsonCircuits.JunctionStructure Type
JunctionStructureWhat every assembly of the Josephson term reads about the junctions, built once per system and precision and shared by the plans which assemble from it: the incidence triple product as a per node pair table, the coefficient Lscale/Lj of each junction, and the mode coupling index matrices, on the backend. The values which move with the component values, lmolj, are refreshed in place by refreshvalues!, so every plan holding the structure sees the new values at once; the table and the index matrices are fixed by the topology and the mode grid.
Fields
pairptr,pairrow,pairjunc,paircoef: the incidence triple product per ordered node pair, fromjunctionpairtable, on the backend;hostpairptr,hostpairrow: the pointer and row of the table on the host, for the node graph of a block factorization.lmolj:Lscale/Ljper junction, on the backend.ami,amc: the mode coupling index matrices, on the backend.nodesandsigns: the (node, sign) pairs of each branch, on the host.nmodes,nfreq: the mode count and the frequency grid stride intophimatrix.
JosephsonCircuits.KrylovSolveInfo Type
KrylovSolveInfoDiagnostics for a single linear solve of nlsolvekrylov!.
There is one record per GMRES call, not per Newton step. A Newton step can contain up to three: the first solve, a refresh-and-retry when the preconditioner has drifted, and a rescue solve when the resulting direction is not a descent direction. Recording per solve rather than per step is what makes the retry structure visible; a one-entry-per-step vector cannot express it, and the extra solves are exactly where the expensive failures hide.
Fields
iteration: the outer Newton step this solve belongs to. Repeated values mark a retry or a rescue.role::stepfor the solve which produces the step,:retryfor the refresh-and-retry after a solve that did not reach tolerance,:rescuefor the solve after a non-descent direction.normF: the nonlinear residual norm at the point of the solve, the right hand side norm.forcing: the requested relative tolerance, the Eisenstat-Walker forcing term for this step.residualratio: the achieved explicit linear residual ratio. The pair (forcing,residualratio) is the diagnosis of an oversolving or undersolving forcing sequence: a looseforcingsatisfied in one iteration at aresidualrationear one is a solve that did almost nothing while reporting success.iterations,cycles,reason: as returned bygmres!.refreshed: whether the preconditioner was rebuilt immediately before this solve.escalated: whetherescalatepreconditioner!grew the preconditioner after this solve.stagnated: whether the step was discarded and replaced by the preconditioner solve.slope:dot(F, J*deltax)/normF^2, a scale free measure of direction quality from an exact matrix-free product.-1is the Newton direction; a small magnitude is a weak descent direction, which is what a loose solve against a stale preconditioner produces.NaNwhen not computed.alpha,backtracks,armijo: the linesearch outcome for the step this solve produced.armijois false when the step was merely the best decreasing trial rather than an Armijo accepted one.time: seconds since the start of the nonlinear solve, so that the residual history can be plotted against wall time with the refreshes and escalations marked.escalationrequested: whether an escalation was requested after this solve; withescalatedfalse, that is an escalation the preconditioner refused: it was exact already, had no larger coupling set to grow into, or the grown factors would not fit its memory budget.deflationsize,deflationrebuilds,precondtime: the active rank of the recycled deflation, how many times it has been built, and the wall time spent applying the preconditioner in this solve.products,deflationproducts: the exact operator products this linear solve took, and the running count of those the preconditioner took itself, a deflation wrapper for its builds and aClustersrequest for its probes. The cost of a solve is in these, not initerationsalone: every restart cycle recomputes the residual.
JosephsonCircuits.KrylovVectors Type
KrylovVectors(x, F, m)The system sized vectors of one Newton-Krylov solve: the GMRES workspace for a restart length of m, and the step, the trial point, the product and the best residual, allocated like x and F. Handed back to nlsolvekrylov! through its workspace argument they are reused across solves of one system, which a sweep over component values is.
JosephsonCircuits.LegacyTermination Type
LegacyTermination(component)The port owned environment of a tuple netlist: a resistor the netlist already contains, named by its instance identifier.
Internal. A tuple netlist states a port's impedance by placing a resistor across it and carries no role marker, so the adapter finds that resistor once and records which one it is. Everything downstream then reads the port's environment from the port, exactly as for a native matched port, and nothing searches for a resistor sharing a port's branch.
sourceJosephsonCircuits.LinearTermGather Type
LinearTermGather{VI,NT}The constant linear term invLnm + im*Gnm*wmodesm - Cnm*wmodes2m of an assembly plan: the stored entries of the plan it reaches, and the three matrices it is read from, on the plan's backend.
A stored entry takes something from the linear term only if its complex position is stored in one of the three matrices, which the structure fixes whatever the values, and most entries of a Jacobian couple modes through the junctions alone. So the entries the linear term reaches are found once, when the plan is built, and refreshlinear! rewrites those and nothing else for new component values: every other entry takes zero, whatever the values.
Fields
pos: the stored entry of the plan each reached entry is, or zero where the plan's structure does not store it.row,col: the complex position it belongs to.part: for a real plan, its offset(dr, dc)in the real block of that position, as2dr + dc; empty for a complex plan.inputs: the three matrices compressed by columns, each with the mode frequency diagonal it multiplies, named and ordered aslinearentrytakes them. The values are the plan's own copies, which a refresh overwrites.
JosephsonCircuits.LinearizedArrays Type
LinearizedArrays(requests::LinearizedRequests; Nports, Nmodes,
Nnoisechannels, Ncomponents, Nnodes, Nfrequencies)The preallocated output arrays of one hblinsolve run, filled per frequency by hblinsolve_inner!. An output which was not requested is a zero size array of the same dimensionality, which signals, through isempty, that it is not to be computed. The output shapes and the request conditions are defined here and nowhere else.
JosephsonCircuits.LinearizedRequests Type
LinearizedRequests(; S, Snoise, Cnoise, Vout, Ssensitivity, QE, CM,
nbar, nodeflux, nodefluxadjoint, voltage, voltageadjoint)The outputs asked of one hblinsolve run, each field true when the keyword return followed by its name is (S for returnS): the arrays LinearizedArrays allocates, and the outputs the last stage of the sweep returns, keyed when asked. Made once from the keywords.
JosephsonCircuits.LinearizedWorkspace Type
LinearizedWorkspaceThe scratch of one worker's pass over a range of signal frequencies in hblinsolve_inner!.
The largest buffers are the size of the solution and of the system matrix, so a worker is given one workspace once and reuses it across every range of frequencies it is handed. This is what lets the device path hand out one batch of frequencies at a time while keeping the host work parallel.
sourceJosephsonCircuits.LinearizedWorkspace Method
LinearizedWorkspace(arrays::LinearizedArrays, sensitivity, lsys, Nports,
Nmodes, Nnoisechannels, Nwpumpmodes, factorization;
assembles::Bool = true, ordering = nothing, pumpordering = nothing)Make the scratch of one worker. assembles is false when the solutions are supplied from elsewhere and nothing writes into a copy of the system matrix, which on a large problem is the biggest allocation here. ordering and pumpordering, when given, are the fill reducing orderings of the system matrix and of the pump Jacobian (see fillordering), which the worker's first factorizations then take rather than choose.
JosephsonCircuits.ModeCouplingPreconditioner Type
ModeCouplingPreconditionerA preconditioner for the matrix-free Newton-Krylov solve of the harmonic balance system: the Jacobian materialized with its mode coupling restricted to a coupling set (couplingmask) and reduced to the mode diagonal everywhere else, then factorized.
The restriction is applied while the Jacobian is materialized, not afterwards: the assembly plan is built from mode coupling index matrices whose dropped couplings have been zeroed by restrictmodecoupling, so the restricted operator is assembled directly into its own, sparser, structure by the same assemblerealjacobian! which assembles the full Jacobian, from the same Fourier coefficients of cos(phi(t)) and the same linear term matrices. No submatrices are extracted, and the sparsity of the restricted structure is what makes its sparse LU cheap.
The default is BlockDiagonal, the mode block diagonal. Its factorization is a batch of small independent per mode factorizations rather than one large sparse factorization, which is what makes it scale. On a strongly pumped device the block diagonal alone stalls, and escalatepreconditioner! is the safety net.
Fields
P: the restricted Jacobian's sparsity structure. ASparseMatrixCSCon the host, and on a backend aDeviceSparsePatternof the transpose, which is the row major structure a device sparse matrix wants.sys: theHBSystemthe Jacobian is assembled from.cache: theFactorizationCacheholding the factorization ofP.factorization: theAbstractFactorizationofP. A block factorization which meets a singular supernode is replaced by the backend's sparse factorization (seerefactorize!).coupling: the coupling set currently factorized, aBlockDiagonal,FullJacobian,HarmonicBandorCouplingMask; aMeasuredBandorClustersrequest is held as the band or mask it has grown to so far.escalations: the number of times the coupling set has been grown.fallbacks: the number of times a block factorization met a singular supernode and was replaced by the backend's sparse factorization (seerefactorize!).plan: thePreconditionerPlan, the structural ingredients from whichbuildcouplingrebuilds the pattern, the assembly plan and the values for a new coupling set, so the set can be grown after construction, among them the mode count and the harmonic offset of every mode pair aHarmonicBandand aMeasuredBandare built from; it carries the precision of the factors, and is replaced when they are promoted to the iteration's.measuredband: theMeasuredBandrequest whose bandwidth is measured at every update,nothingwhen none was asked for.deviceplan,nzval: the assembly plan and the values it writes, rebuilt on escalation; on a hostnzvalaliases the stored values ofP.clusterprobe: the state of aClustersrequest,nothingotherwise.budget: the memory the factors of a grown coupling set may take, by escalation, by the growth of a measured band or cluster mask, or by the fallback from a singular supernode, ornothingfor the backend's memory budget at the time (memorybudget); set by tests, not by a constructor keyword.sizes,sizings: the size of every coupling set sized so far, which its structure alone decides, and the number of sizings (couplingsize!).
JosephsonCircuits.ModeCouplingPreconditioner Method
ModeCouplingPreconditioner(sys::HBSystem, Amatrixindices::Matrix,
Amatrixconjindices::Matrix, Rbnm::SparseMatrixCSC, Nmodes::Integer,
Nbranches::Integer, Nfreq::Integer, layout::ModeLayout;
spec::AbstractModeCoupling = BlockDiagonal(), precision = nothing,
Amatrixmodes = nothing)Build a ModeCouplingPreconditioner of the system sys, whose junctions and linear terms its assembly reads, from the structure of its Jacobian: the mode coupling index matrices, the incidence matrix, the counts and the mode layout (the PreconditionerPlan). spec is the member of the mode coupling family to build (BlockDiagonal, FullJacobian, HarmonicBand, MeasuredBand, Clusters, CouplingMask, or Automatic, which is resolved by resolveautomatic at construction to the member which fits this problem and this backend's free memory), carrying the factorization it is built with, the backend's default (KLU on the host, cuDSS on a device) when it carries none. A BlockFactorization eliminates the circuit graph with dense blocks over the clusters of the coupling set instead of factorizing a sparse matrix. precision is the floating point type of the factorization, nothing for that of the system. Amatrixmodes is the harmonic offset of every mode pair, needed by HarmonicBand and MeasuredBand.
JosephsonCircuits.ModeDifferences Type
ModeDifferences{N} <: AbstractMatrix{NTuple{N,Int}}The mode difference modes[i] .- modes[j] of every pair of modes, the harmonic offset of each mode coupling, computed when an entry is read rather than stored.
JosephsonCircuits.ModeLayout Type
ModeLayout(isreal::AbstractVector{Bool}, dim::Integer)Layout of one axis of length dim (a complex dimension), built from a length- nmodes mask of which modes are real. dim must be an integer multiple of nmodes. Complex index i owns real slots ptr[i]:ptr[i+1]-1, one when its mode is real and two otherwise; inv maps a real slot back to its complex index; rdim is the resulting real dimension.
Fields
nmodes,dim,rdim: the mode count, the complex dimension and the real dimension.isreal: the mask over the modes.ptr,inv: the slot ranges and the inverse map, as above.
JosephsonCircuits.ModulatedRationalProvider Type
ModulatedRationalProvider(cosine::RationalScatteringProvider,
sine::RationalScatteringProvider)The harmonic transfer function of a LinearizedScattering block for a harmonic k > 0 as fitted for the transient: H_k(nu) = G_c(i nu) + i G_s(i nu) with G_c and G_s real rational functions, the cosine and sine parts G_c(nu) = (H_k(nu) + conj(H_k(-nu)))/2 and G_s(nu) = (H_k(nu) - conj(H_k(-nu)))/(2i), each realized as a stable state space with no feedthrough, since a conversion vanishes at infinite frequency. Natively valid at signed frequencies. In time the block multiplies the output of the cosine filter by 2 cos(k wp t) and that of the sine filter by -2 sin(k wp t), which is 2 Re[exp(i k wp t) (h_k * a)], the sum of the harmonics k and -k of a real system.
JosephsonCircuits.MutualStampPlan Type
MutualStampPlanThe mutual inductance stamps: every coupling resolved once against the graph to the two branches it couples and the sign the netlist's terminal order gives it, so a refill reads the three values of a coupling and nothing structural. components holds, for each coupling, the position of its coefficient among the bound circuit's mutual inductors and of its two inductances among its inductors, so the values are read from those typed groups. sharedbranches lists the coupled branches on which more than one inductor sits, which a refill refuses when the coupling is nonzero.
JosephsonCircuits.NewtonTrace Type
NewtonTrace{T}The record and the acceptance rules shared by the two Newton loops, nlsolve! and nlsolvekrylov!: the residual norm history, the step lengths and backtrack counts of every trial, the count of consecutive line searches which returned the best decreasing trial rather than an Armijo step, the tolerance, and why the iteration ended. The loops differ in how they compute a direction and in what they do about a stall; what a step is, when the iteration has converged and when repeated short steps are a stall, they share here, through tracestart!, tracetrial!, tracestep! and tracestalled. The history vectors are the ones the IterationInfo of the solve reports, so a loop may read normresidual directly for its forcing terms and records.
Fields
normresidual: the residual norm at the starting point and after every step taken.alpha,backtracks,andersonaccepted: per trial, the step length, the trial evaluations after the first, and whether the step lies on the accelerated path.atol: the tolerance in force, the absolute one or the relative one times the initial norm, whichever is larger.maxbacktrackfailures,backtrackfailures: the stall threshold and the consecutive count against it.converged,reason: the outcome.
JosephsonCircuits.NoPortTermination Type
NoPortTermination()No port owned environment, written as termination = nothing. The port remains an excitation and observation boundary with its reference impedance intact, but contributes no physical loading of its own.
JosephsonCircuits.NodalStampPlan Type
NodalStampPlanThe fixed pattern and stamp destinations of a nodal matrix.
dest[k] is the position in nzval which contribution k accumulates into, src[k] names the group value it comes from, and weights[k] holds its incidence coefficient, 1 on the diagonal and -1 off it. invert inverts the value after applying that coefficient, so a conductance is -1/R off the diagonal.
The plan is built once per topology; assemblenodal! is a scatter-add which allocates nothing.
JosephsonCircuits.NoiseReduction Type
NoiseReductionThe noise scattering matrix reduced to what the quantum efficiency and the commutation relations read of it: two numbers per output port mode.
Both consume Snoise, a row per noise channel mode c and a column per output port mode i, only through a sum over the noise index. The quantum efficiency reads sum_c channelnoise[c]*abs2(Snoise[c,i]), the symmetrized noise the channels put at output i, each weighted by its own nbar + 1/2; the commutation relations read sum_c sign(w_c)*abs2(Snoise[c,i]), the same power weighted by the sign of the channel's mode frequency and without the state of the channel, which is why the commutation relations do not depend on temperature. A channel of the conjugate kind, one of a block which states its noise (see noisechannelsigns), enters the second sum with its sign reversed. The first is also the diagonal of the noise covariance matrix of calcnoisecovariance!.
On a circuit whose loss is spread along the line that is a reduction of thousands of rows to one number per port mode, so when the noise scattering parameters are not themselves an output there is no reason to bring the matrix to the host at all: devicenoise returns the reduction, and the host loop forms it from its matrix with noisereduction!. Passed to calcqe! and calccm!.
Fields
symmetrized:sum_c channelnoise[c]*abs2(Snoise[c, i])per output modei.signed:sum_c sign(w_c)*abs2(Snoise[c, i]), with no channel state.
JosephsonCircuits.NonlinearTermPlan Type
NonlinearTermPlan{Ti<:Integer,T<:Real,VI,VT,VC,VF,KF,KB,KFC,KBC,KRC,KCR,B}Fully precomputed, device-generic plan for the two linear maps which surround the pointwise time domain nonlinearity of the harmonic balance system:
the map
Afrom the unknowns to the frequency domain coefficients of the Josephson junction branch fluxes, which folds together the real to complex conversion of the equivalent real representation, the incidence matrix productRbnm*z, the gather onto the Josephson branches, and the packing into the array the inverse real transform consumes (phivectortomatrix!), andthe map
Bfrom the frequency domain coefficients back to the node vector, which folds together the unpacking of the transform's array, theLscale/Ljbranch scaling, the transposed incidence matrix product, the frequency dependent linear termK, and the complex to real conversion.
Both are expressed, in the complex representation and in the equivalent real one, as KernelAbstractions kernels in which one work item owns one output slot and reads only precomputed index maps, so neither contains a scatter, an atomic, or a write conflict, and both run unchanged on a device once the arrays are moved there. The maps are fixed at the sparsity structure and mode frequencies of the system, so they are built once by plannonlinearterm. The topology of the maps does not depend on the representation, so the two share the incidence entries and the Josephson segment lists and differ only in how a source is addressed and in which form of the linear term matrix they gather.
Only the pointwise time domain function between the two maps distinguishes the entry points of the system, so one plan serves all of them:
| entry point | between the transforms | linear term |
|---|---|---|
residual! | sin(phitd) | + K*x - b |
jacobianvectorproduct! | cos(phitd) .* dirtd | + K*v |
hessianvectorproduct! | -sin(phitd).*dirtd.*dirtd2 | none |
Fields
The forward map stores, per slot of the frequency domain array, the at most two entries of the corresponding row of the incidence matrix. A row of a branch incidence matrix has at most two entries because a branch is an edge and one of its two nodes may be the ground node, so no segment structure and no inner loop is needed:
n1,n2: the real slot holding the real part of the source node flux, or zero when the entry is absent.cn1,cn2: the same entries addressed as complex indices, for the complex representation.s1,s2: the corresponding incidence matrix entries.flags:FCONJwhen the slot is a conjugate symmetry target andFWIDEwhen the source mode is not self conjugate, so its imaginary part occupies the next real slot.
The backward map stores, per complex output index, a segment of contributions gathered from the frequency domain array, and the linear term in compressed sparse row form:
bptr,bsrc,bcoef: the segment of frequency domain slots of the Josephson branches incident to that node, with the incidence matrix entry timesLscale/Ljas the coefficient.kptr,kidx,kcoef: the real form of the linear term matrixK, stored transposed so applying it is a gather over the entries of one output row. Empty when the plan was built withrealbackward = false, whichhasrealbackwardreports.cptr,cidx,ccoef: the same for the complex form ofK.kptrzero,cptrzero: the row pointers of an empty linear term of each form, for applying the Josephson part alone.lptr,lwide: the first real slot of each complex index and whether that mode is not self conjugate.forward!,backward!,forwardcomplex!,backwardcomplex!,realtocomplex!,complextoreal!: the compiled kernels of the two maps in each representation and of the conversions between them.backend,nslots,ncomplex: the backend, the number of real slots and the number of complex indices.
JosephsonCircuits.NonlinearTermTransposePlan Type
NonlinearTermTransposePlanThe transposed gather maps of a NonlinearTermPlan, and the two kernels which apply them. Built once by plannonlineartermtranspose. See hbvjp!.
Fields
tbptr,tbnode,tbcoef: per frequency domain slot, the segment of complex node indices which gather that slot in the backward map, with the same coefficients. The transpose of the Josephson contribution.tfptr,tfslot,tfcoef,tfimag: per real slot of the unknowns, the segment of frequency domain slots which read it in the forward map.tfcoefcarries the incidence entry with theFCONJsign and the conjugate multiplicitysalready folded in;tfimagsays whether the entry reads the imaginary rather than the real part of the slot.ktptr,ktrow,ktcoef: the transpose of the real form of the linear term, gathered by output index.gtscale: the conjugate multiplicity of each frequency domain slot, one for a bin whose conjugate partner is also stored (the zero and Nyquist frequencies of the first dimension, the only one the real transform truncates) and two otherwise.backwardtranspose!,forwardtranspose!: the compiled kernels.backend,nslots,rdim: the backend, the number of frequency domain slots and the real dimension of the unknowns.
JosephsonCircuits.PaddedLinearTerm Type
PaddedLinearTermThe frequency dependent linear term of the augmented system, padded to the auxiliary variables with the modified nodal analysis augmentation folded in, together with the index maps which refill it from a new assembly of the unpadded matrices. A sweep over component values builds this once and then moves values only: the padding, the union with the augmentation and the incidence matrix's empty columns are structure, which the values do not change (see hbcache).
Fields
Rbnm: the incidence matrix with its empty auxiliary columns.invLnm,Gnm,Cnm: the padded matrices,invLnmwithAmnaadded.Amna: the augmentation, whose value dependent entries are the coupled inductor rows ofcalcAmnaindand the scattering block term ofscatteringlinearterm, whose node flux columns carry the solver scale.pind: the positions of the coupled inductor rows' entries innonzeros(Amna).pblock: the positions of the scattering block term's entries innonzeros(Amna).scale: the solver scale the block term is stamped at.pinv,pamna: the positions of the unpadded inverse inductance entries and ofAmna's entries innonzeros(invLnm).bnm: the drive in the padded node basis.wmodesm,wmodes2m: the mode frequency diagonals over the padded system.stampedblocks: the scattering blocks as stamped, which the direct current path reads.
JosephsonCircuits.PaddedLinearTerm Method
PaddedLinearTerm(Rbnm, invLnm, Gnm, Cnm, Amna, AmnaL, blockterm, scale,
invLnm0, bnm, wmodesm, wmodes2m, stampedblocks)Record a padded linear term as hbnlsolve assembled it, with the unpadded inverse inductance invLnm0, the coupled inductor rows AmnaL and the scattering block term blockterm (or nothing when the circuit has no blocks) at the solver scale scale it was assembled from, so that refill! can reproduce the assembly at new values. Returns nothing when the coupled inductor rows or the block term share an entry with the rest of the augmentation, which a refill by overwrite could not reproduce exactly.
JosephsonCircuits.PairLadder Type
PairLadderThe covariance E and the commutator C of the quadratures of a pumped block's noise wave over one ladder of its bath frequencies, the indices frequencies of those the ladder relates, square over their quadratures in the order (frequency, port, quadrature). The block between the frequencies a and b holds the four real blocks xx, xp, px and pp from the symmetrized normal correlator N and anomalous one M of the wave's amplitudes at the two frequencies, in quanta, the vacuum's N being one half: xx = Re(N + M), pp = Re(N - M), xp = Im N - Im M, px = -(Im N + Im M), and C the same with N and M replaced by i times the commutators of the amplitudes. N can be nonzero when the frequencies differ by a multiple of the pump frequency and M when they sum to one, both read from the block's noise over the family of the bath frequencies, its harmonic covariances and the commutator of its multi-mode scattering matrix as pumpednoisematrices assembles and completes them over the modes of a solve at once (see bathfamily), so the two solvers share one definition of the block's noise. The contraction of a response's columns at the ladder's frequencies, R, is R E R' and R C R', two products per ladder.
JosephsonCircuits.ParsedLevel Type
ParsedLevelThe normalized form of one circuit level, what the elaboration reads: the component table, the connection groups, the interface pins, the ground ties and the mutual inductors, each with names resolved to instance indices and terminals. Built by parsecircuitlevel.
JosephsonCircuits.PassiveNetwork Type
PassiveNetwork(network_name, scattering_parameters; noise = false)
PassiveNetwork(network_name, scattering_parameters, noise_covariances)
PassiveNetwork(network_name, scattering_parameters, port_names;
noise = false)
PassiveNetwork(network_name, scattering_parameters, noise_covariances,
port_names)A network to connect: its name, its scattering parameters, their noise covariances and the names of its ports, (network_name, i) for port i by default. Without noise covariances, noise = false leaves an empty array in their place, which connectS! and solveS! replace with the passive covariance (I - S*S')/2 of the scattering parameters S as they are when noise is connected, and noise = true computes that covariance at construction. The noise keyword of the constructors given noise covariances has no effect.
JosephsonCircuits.PerturbationEntries Type
PerturbationEntriesThe stored entries of one kind of derivative of the components, for the contraction of an adjoint: the forcing of component c is -dM_c A for the derivative dM_c and the state A its kind reads, so its contraction against the multipliers M is the sum over the entries (i, j, v) of dM_c of -v A[j] M[i], taken as the gather of the rows j of A and i of M by two selection matrices, their product, and the sum into the components by a matrix carrying the values, every one the size of the entries.
JosephsonCircuits.PiecewiseTabulatedProvider Type
PiecewiseTabulatedProvider(tables::Vector{TabulatedMatrixProvider})Tabulated data in several disjoint bands, each a TabulatedMatrixProvider over its own frequencies, evaluated by the band a frequency falls in and zero between and beyond them, the data of a response known only in the bands it was sampled over. The harmonic transfer functions of a LinearizedScattering block built from a solve are of this kind: the signal band shifted by every harmonic of the pump, with nothing in between, across which one spline would swing wildly.
JosephsonCircuits.PolynomialCPRDerivative Type
PolynomialCPRDerivative(a)The analytic derivative of a PolynomialCPR, produced by cprderivative. Callable.
JosephsonCircuits.PortDiagonal Type
PortDiagonal(values, rows = Colon())A port argument handed to a conversion kernel as the diagonal matrix of its values at the frequency, restricted to the ports rows: values is a vector with one value per port, the same at every frequency, or a matrix with one row per port and one column per frequency. See convertperfrequency!.
JosephsonCircuits.PreconditionerPlan Type
PreconditionerPlanThe structural ingredients from which a ModeCouplingPreconditioner rebuilds its pattern, its assembly plan and its values for a new coupling set (buildcoupling) and sizes the factors a coupling set would take (couplingsize): the Jacobian index matrices, the incidence matrix, the counts, the mode layout, the mode offsets and the requested precision. Everything with a value in it is read from the system at the time of the rebuild, so a system rebound to new values is what a rebuild sees. The preconditioner holds it in a field of abstract type; the two parameters, the mode offsets (whose tuple length is the tone count) and the precision, are what a rebuild dispatches on.
JosephsonCircuits.RationalScatteringProvider Type
RationalScatteringProvider(A, B, C, D)A scattering matrix given as the real state space realization S(s) = D + C (s I - A)^(-1) B of a passive rational multiport, the form a vector fit of measured or simulated scattering data takes and the one the transient solver realizes in time, dz/dt = A z + B a, b = C z + D a on the incident and reflected power waves. The provider holds a copy of the realization and takes the real Schur form of A when it is built, A itself where it is already quasi-triangular in LAPACK's standard form, so a signed angular frequency is evaluated by a quasi-triangular solve on those factors, without forming an inverse; the realization is fixed from then on. A realization whose A is block diagonal in real poles and rotations [α -β; β α], each pole a run of equal blocks as many as its residue's rank, as a fitted block's is, is evaluated pole by pole instead, in the fit's pole-residue form, at the cost of the ports squared per pole rather than per state, for each pole whose residue has rank above one; the Schur form is then taken of the states of the others alone. Built by RationalScattering, which validates it.
JosephsonCircuits.ReverseSensitivity Type
ReverseSensitivity(op, sys, dFr, T, fftplan, nzrow, nzcol,
realindexmap, branchnodes, slots)Everything the reverse mode contraction of calcSsensitivityreverse! needs, precomputed once and shared read only across the signal frequencies.
JosephsonCircuits.ReverseSensitivity Method
ReverseSensitivity(op::HBOperatingPoint, lsys, dFr, slots)Precompute the reverse mode contraction data: the branch flux map (calcbranchtimedomainmap), the transform of the pump harmonic grid, the row and the column of each nonzero of the linearized system matrix, and the offset of each entry of the augmented state in its real representation. dFr holds the residual derivative columns and slots[k] is the output slot of Ssensitivity column k accumulates into, so that several columns belonging to one design parameter can share a slot.
JosephsonCircuits.ReverseSensitivityBuffers Type
ReverseSensitivityBuffers(rev::ReverseSensitivity, NPM::Integer)The mutable work arrays of one invocation of calcSsensitivityreverse!, allocated once per batch of signal frequencies rather than at every frequency. Each thread of hblinsolve owns its own set; the ReverseSensitivity itself is shared read only. The time domain arrays of the transposed transform have one dimension per pump tone and one per junction, and their type is the parameter, so that the contraction reads them concretely.
JosephsonCircuits.RotatedMatrixProvider Type
RotatedMatrixProvider(provider, delays; offset = 0.0, phase = 1)The covariance of the noise a block emits, stated by provider, moved to other reference planes: the entry from q to p is multiplied by phase and by cis((w + offset)*delays[p] - w*delays[q]), which takes a lossless line of delays[p] seconds off each port, the wave p emits carrying cis(-w*delay) along it and the wave it is correlated with the conjugate. offset is how far above the frequency asked for the emitting side is read: zero for the covariance of an ordinary block, and k*wp for the harmonic covariance V_k(nu) = <n(nu + k wp) n(nu)'> of a pumped block, whose correlated waves are the harmonic k of its pump apart. phase has unit modulus, a pump phase cis(k*phi) for such a harmonic.
The two sides carry opposite phases, as a correlation's do, where the scattering matrix of the same block carries the sum of its delays, so this is the transformation of a covariance, or of a pumped harmonic covariance, and a block refuses it as scattering data. The phase is applied to what provider returns at each requested frequency rather than to data it stores, so it composes with the interpolation and the extrapolation that provider declares instead of changing what they mean, and a provider of any kind can carry it. This is the change of reference plane a fit makes to a stated covariance when a delay is taken out of the data (see RationalScattering).
JosephsonCircuits.ScatteringNoisePlan Type
ScatteringNoisePlanThe noise channels of the dissipative ScatteringParameters components of a circuit: which blocks of a ScatteringStampSystem carry noise and where their channels sit in the rows of the noise scattering matrix.
A block which absorbs must add noise, or its output would violate the commutation relations. In the wave domain its constitutive equation is b = S a + n with an added noise wave whose commutator is K = I - S S' and whose symmetrized covariance in the vacuum is K/2, and in the hybrid stamp
im*w_m*scale*B(w_m) phi - C(w_m) i = 2 nthat noise is a source in the auxiliary port current rows. A block with n ports therefore carries n noise channels, one per column of the triangular factor of I - S S' (psdcholesky!), each weighted by its symmetrized noise nbar + 1/2; those of a lossless block are identically zero, so only blocks which are not provablylossless are given channels.
A block which states its noise with a NoiseCovariance V, which is how an active block declares it, carries 2n channels: n from the factor of V + K/2, which emit like modes in their vacuum, and n from the factor of V - K/2, which emit like the conjugates of modes and enter the commutation relations with the opposite sign (see noisechannelsigns). Every channel carries the vacuum's half photon, so the block adds half their sum, V, and their difference is K: the block adds the noise it states and its output obeys the commutation relations, and neither kind carries a temperature.
The channels of the blocks follow the noise ports of the dissipative lumped components in the rows of Snoise, with the same channel-major-mode-minor ordering.
JosephsonCircuits.ScatteringNoiseWorkspace Type
ScatteringNoiseWorkspace()The scratch of scatteringnoisewaves!: the scattering parameters at the mode frequencies, the noise covariance and its factor in one flat array, and the buffer of unsigned frequencies. Reused across frequencies by one worker.
JosephsonCircuits.ScatteringStampSystem Type
ScatteringStampSystemThe contribution of the ScatteringParameters components of a parsed circuit to the harmonic balance system matrix, as hybrid (wave to modified nodal analysis) stamps: one auxiliary port current variable per port and mode, the constant Kirchhoff current law couplings kcl of those currents into the node equations, and the constitutive equations
im*w_m*scale*B(w_m) phi - C(w_m) i = 0per port and mode, whose frequency dependent coefficient entries are described by the sparsity pattern plus, per scalar contribution, the block, port pair, sign, mode, destination index, and which coefficient (B, stamped with the im*w_m*scale factor which turns a node flux into a voltage, or C, stamped as -C). The contribution of a time invariant block is diagonal in mode space, since it cannot convert frequencies; a pumped block (LinearizedScattering) couples the modes its pump connects. This representation exists for every scattering matrix (see evaluatehybrid!); no admittance conversion is performed.
The values side is a pure gather-add over precomputable per (block, mode) coefficients, so the values are computed here and a device adds them with a kernel; see DeviceScatteringStamps.
Fields
blocks: theStampedScatteringBlocks.kcl: the constant Kirchhoff current law couplings of the auxiliary port currents, folded into the modified nodal analysis augmentation.pattern: the sparsity pattern of the constitutive rows.patternindex,Aindex: where each stored entry ofpatternlands in the system matrix, and the stored position it is added at.blockindex,pindex,qindex,modeindex: for each contribution, the block, the port pair and the mode it reads its coefficient from.coeff,sign: the per contribution coefficient buffer and sign.inmodeindex,coupled: for each contribution, the mode of its column, the row's own except for a pumped block, and the ordinal amongpumpedof the pumped block it belongs to, zero for a block which does not convert.pumped,pumpedk: the pumped blocks, as indices intoblocks, and the harmonic by which each couples each pair of modes (seepumpedharmonics).Nmodes: the mode count.scale: the solver scale the rows are written in.iscale: the scale of the auxiliary port current unknowns. The stored unknown isi/iscale, so every auxiliary column isiscaletimes the unscaled one; withiscaleone over the solver inductance scale (seeauxcurrentscale) a port current is written in the same units as a node flux. The outputs are unaffected: they are read from the nodal components of a solution, and the block noise is contracted against the auxiliary rows of an adjoint solution, which a scale on the unknowns leaves alone. Anything which reads a forward auxiliary component as a current multiplies it byiscale.firstof: for each block, the first block holding its definition, whose coefficients and data its instances read.
JosephsonCircuits.ScatteringWorkspace Type
ScatteringWorkspace()Reusable scratch for scatteringvalues!: a HybridWorkspace and the coefficient arrays of every block.
Those arrays have to be live at once, because the contributions are ordered by their destination in the system matrix rather than by block, so they cannot be one buffer reused block by block. They can be reused from one frequency to the next, which is what this is for: a sweep over a line whose every cell is its own block otherwise allocates two arrays per block at every signal frequency.
A workspace is written by every call, so it belongs to one task. A caller which sweeps on several threads gives each one its own.
sourceJosephsonCircuits.SensitivityStamp Type
SensitivityStamp(kind, rows, cols, vals, portindex, parameter, portscale)
SensitivityStamp(kind, rows, cols, vals, portindex)The derivative of the linearized harmonic balance system matrix with respect to a relative (logarithmic) perturbation of one component value, p -> r*p evaluated at r = 1. The system matrix is affine in C, 1/R, 1/L and 1/Lj, so the derivative is that component's own contribution to the system matrix, with a sign: positive for the capacitance and negative for the quantities which enter inversely.
kind selects how the stamp is assembled at each signal frequency, mirroring assemblesystemmatrix!:
:C:-vals*wmodes2m, the component's capacitance matrix,:G:-im*vals*wmodesm, the component's conductance matrix,:invL:-vals, the component's inverse inductance matrix,:Lj: the constant values, the negative of the pump modulated Josephson contribution of that junction alone,:S: the derivative stamp of a scattering block (blocksensitivitystamp),:P: no entries, the reference impedance of a port which owns no termination, which enters only the normalization of the port's waves (sensitivitystamp).
The stamp is the triplet (rows, cols, vals) of the component's own contribution, built by calcsensitivitystamps, and each value is scaled by the mode frequency of its column at assembly. portindex is the ordinal of the port whose reference impedance this component is, its termination or the port itself (see sensitivityportordinals), or zero; a port selects the additional wave normalization term of calcSsensitivity!.
parameter is the design parameter this stamp contributes to, or zero for the relative form, where every component is its own output slot. portscale is (dZport/dtheta)/Zport for a port impedance stamp, one for the relative form. pattern is the entries' positions as a sparse matrix (StampPattern), which the contraction fills at each frequency; a stamp with the entries of another, rescaled or copied, shares its pattern.
JosephsonCircuits.SizedPreconditioner Type
SizedPreconditioner(pc, n, pointstamp)A preconditioner carrying its dimension, so it satisfies the size/ eltype/mul! contract external Krylov solvers check, and the point stamp of the problem whose evaluation point it sets, which every update moves (see JacobianOperator).
JosephsonCircuits.SolverInfo Type
SolverInfo(stages, initialresidual, finalresidual, converged,
sourcefold)Diagnostics describing the nonlinear solution process of hbnlsolve.
Fields
stages: the per-stage records (subtypes ofAbstractStageInfo), one for each invocation of the nonlinear solver, in the order they ran. The direct and Krylov solvers record oneIterationInfo;method = Staged()records oneStagedStageInfoper attempted continuation stage, each carrying its inner solver records. Every record hasconvergedanditerationsfields; the rest is method specific.initialresidual: the norm of the residual at the initial value.finalresidual: the norm of the residual at the returned solution.converged: whether the solve converged: the solver reported convergence, and the point it returned satisfies the original, ungauged Kirchhoff current law equations, which an incompatibility absorbed by a gauge fixing equation violates. AStagedsolve which gave up has not converged, whatever its last attempt reported.sourcefold:NaN, except for aStagedsolve which found the solution branch ending below the requested drive, where it is the last drive fraction the continuation converged at.
JosephsonCircuits.SourceTuple Type
SourceTuple{N}The canonical form of a source: a named tuple (mode, port, current) with the mode as N integers, one harmonic index per tone, the port as an integer and the current as a complex number. See sourcetable.
JosephsonCircuits.SparseBlockFactorization Type
SparseBlockFactorizationThe BlockFactorization of a sparse matrix whose unknowns come in node blocks: the matrix of the linearized solve, Nmodes unknowns per circuit node (and per auxiliary variable of the modified nodal analysis), whose sparse LU has the block structure of the matrix itself. Built by factorize from the pattern: the node graph is read off the pattern and ordered by KLU, one node per supernode (blocksymbolic), and every stored entry of the matrix is mapped once to its place in a diagonal block or a panel, so a refactorization is one scatter of the stored values and one block LU.
The factorization holds nb systems with the one pattern, the frequencies of a batch of a device sweep (one on the host): every block is an array (rows, columns, nb) and every dense operation of the factorization and the solves is one batched call over the batch (batchedinverse!, batchedmul!), which is what fills a device with the many small blocks of a chain. Solves take a right-hand side shared by the batch or one per system, a GEMM per block, and the transposed system from the same factors; factors in single precision refine against the double residual formed from the matrix's own blocks kept in double (blockresidual!), at close to twice the memory, since the originals cost as much as the single precision factors.
Fields
lu: theBlockLU, the factors and the Schur schedule shared with the preconditioner's clusters.fills: per block, the stored entries which land in it.original: the matrix's own blocks in its precision when refining.scale,diagidx: the equilibration of single precision factors, the symmetric diagonal scaling by the inverse square roots of the diagonal magnitudes, which brings a linearized matrix's entries (inverse inductances against capacitances times squared frequencies) to order one before single precision arithmetic sees them;nothingin double.A: the sparse pattern matrix;refineandrefinesteps: whether the solves refine against the double residual and the most steps they take;backend;work: the work arrays of the last right-hand side width.
JosephsonCircuits.SpiceRaw Type
SpiceRaw(header::SpiceRawHeader, variables::Dict{String, Vector{String}},
values::Dict{String,T})A simple structure to hold the SPICE raw file contents including the header, variables, and values.
sourceJosephsonCircuits.SpiceRawHeader Type
SpiceRawHeader(title::String, date::String, plotname::String,
flags::String, nvariables::Int, npoints::Int, command::String,
option::String)A simple structure to hold the SPICE raw file header.
sourceJosephsonCircuits.StageCorrection Type
StageCorrectionThe exact stage solve of a circuit with a pumped block. The frozen operator of a step carries every block's unconverted response alone, as the system assembles it once; a pumped block's converted outputs, with the weights of each stage's time, act on the block's port rows alone, so the true stage operator is the frozen one plus a correction of rank twice the block's ports, J = J* + U V', with U the scatter onto the block's rows at each stage and, at stage i, V' = -sum_j delta_ij W_ij: the outputs W_ij of each converted term j on the stacked states from the stage unknowns, weighted by the term's weight delta_ij at the stage's time. It is taken exactly by the Woodbury identity: a solve c = J*^(-1) r is corrected to c - K M^(-1) V' c with K = J*^(-1) U and M = I + V' K per column of the batch. K and the products W_ij K depend on the factorization alone and are built when it is refreshed; M is combined from them at each step's weights. The frozen operator never changes with the modulation, so a pumped block refactorizes only when the junctions ask. The tangent and the adjoint solve the true stage operator directly (see StagePlan).
JosephsonCircuits.StagePlan Type
StagePlanThe real matrix of a Gauss-Legendre step's two stages, which the tangent and the adjoint solve. On the stage stacked unknowns [stage 1; stage 2] its block (i, l) is
A2_il C/h^2 + A1_il G/h + delta_il (L + J_i) - B_il,with A1 and A2 the entries of the inverse tableau and of its square, J_i the junction stamp at stage i's phases, so that each stage has its own stiffness, and B_il the rational blocks' coupling of the stages at stage i's weights, the converted outputs of a pumped block among them. Its pattern is the step operator's with the junction pairs and the blocks' coupling, in every block. The plan holds the pattern on the host, the values' gather in the matrix's own order (see StageGather), which a host factorization and the adjoint's device factorization read, and on a device in its transpose's order, which the device reads the matrix in for the tangent; the counts of the junctions and of the output terms; whether the matrix is constant, without junctions and converted outputs; and the host's fill reducing ordering of the pattern, each node's two stages together in the step operator's order, rows and columns, which differ where the step operator's diagonal has gaps.
JosephsonCircuits.StagedStageInfo Type
StagedStageInfoOne attempted stage of stagedhbnlsolve. Every attempt is stored in solverinfo.stages of the returned solution in the order it ran, including stalled steps and growth retreats, so the whole continuation walk can be examined afterwards.
Fields
converged: whether this attempt's inner solve converged.iterations: total inner Newton iterations of the attempt.grid: the harmonic truncation the attempt solved on.sfrom: the last accepted drive fraction before the attempt.starget: the drive fraction the attempt targeted.ds:starget - sfrom(negative for a growth retreat).action::advance(drive step on the current grid),:grow(a solve on a newly grown grid after carrying a converged point up, and the drive retreats of a carried point which has not converged on its grid yet),:final(a full-drive solve on the finest grid), or:evaluate(the point a schedule which gave up returns, carried to the finest grid and evaluated there at full drive without a Newton step).accepted: whether the attempt's result was kept as the new operating point (a stalled attempt, and an evaluation, are recorded but not accepted).seconds: wall time of the attempt, including the stage's system assembly.finalresidual: the residual norm the attempt ended at.inner: the inner solver's own stage records (IterationInfo), with their Krylov linear-solve diagnostics when the inner method is aNewtonKrylov.
JosephsonCircuits.StampContraction Type
StampContraction(stamps, NPM)One worker's scratch for the stamp contraction of calcSsensitivity!: the stored values of each stamp's StampPattern, filled at each frequency, the stamp times the forward solution and the adjoint solution, each over the rows the stamp reaches and sized for the stamp which reaches the most, and the NPM by NPM contraction of the output and the input port mode pairs.
JosephsonCircuits.StampPattern Type
StampPattern(rows, cols)The positions of a sensitivity stamp's entries at rows and cols as a sparse matrix over the rows and the columns of the system they reach: matrix holds the pattern, valuemap[t] is the stored entry the stamp's entry t adds to (a merged stamp repeats a position wherever two of its components share a node), and rows and cols are the rows and the columns of the system the matrix's rows and columns are. The contraction fills the values at each frequency (StampContraction).
JosephsonCircuits.StampedScatteringBlock Type
StampedScatteringBlockOne scattering block instance, with the nodes its ports attach to and the position of the auxiliary port current variables which carry its currents.
auxbase locates them: port p at mode m is the state index auxbase + (p-1)*Nmodes + m. That is the same current the zero frequency row treats as an unknown, which is how a block becomes visible at direct current; see DCBlockRows.
JosephsonCircuits.StructureComplexJacobianPlan Type
StructureComplexJacobianPlan{TJ,VT,LG}The complex Jacobian on a backend: the Josephson map of StructureComplexJosephsonPlan and the constant linear term of each stored entry, gathered once where it reaches (LinearTermGather), which is what assemblecomplexjacobian! adds to it.
JosephsonCircuits.StructureComplexJosephsonPlan Type
StructureComplexJosephsonPlan{Ti,VI,JS,K,B}The Josephson contribution to the complex Jacobian, as a linear map from the Fourier coefficients of cos(phi(t)) to the stored entries of a matrix with a given structure.
Each stored entry is computed from the circuit's structure rather than gathered from one entry per contribution. It is used both to assemble the Jacobian and on its own, as the map applied to other coefficient arrays by the linearized solve, which is why it is a plan for the Josephson term rather than for the whole Jacobian.
Fields
colptr,rowval: the stored structure, the transpose whentransposed.junctions: theJunctionStructure, of which the pair table, the junction coefficients andamiare read.transposed: as inStructureRealJacobianPlan.assemble!,backend: the compiled kernel, one work item per stored column for a host structure in the natural orientation and one per stored entry otherwise, and its backend.n: the number of stored entries.
JosephsonCircuits.StructureRealJacobianPlan Type
StructureRealJacobianPlanEverything the structure aware assembly reads, on a backend. There is no segmented gather here and nothing proportional to the number of contributions: the largest arrays are the sparsity structure and the precomputed linear term, both of which are one entry per stored entry of the Jacobian rather than one per contribution.
Fields
colptr,rowval: the stored structure, which is the Jacobian's transpose whentransposed, so that a column of it is a row of the Jacobian.lin: the constant frequency dependent linear contribution of each stored entry.linear: theLinearTermGatherwhich refresheslin.junctions: theJunctionStructure, the incidence triple product, the junction coefficients and the mode coupling index matrices, shared with every other plan of the system.transposed: whether the stored structure is the Jacobian's transpose, which it is on a device and is not for a matrix meant to be factorized directly.linv,lptr: the mode layout of the rows and the columns, the square Jacobian having one, and its inverse, which turn a stored entry back into a (node, mode) pair.slots: on a host, for a structure in the natural orientation, the decode of every real index of the layout (realslot), from which the assembly of a stored column reads the rows of its entries;nothingon a device and for a transposed structure, whose kernel decodes both sides of each entry.assemble!,backend: the compiled kernel, sized at plan time, and the KernelAbstractions backend it runs on.n: the number of stored entries, checked byassemblerealjacobian!.
JosephsonCircuits.SweepEquilibration Type
SweepEquilibrationThe row and column scaling of the system matrices of one direction of a batch.
cuDSS chooses its pivots within the blocks its ordering fixes, by the size of the candidates, and perturbs a pivot below an absolute threshold (see the extension's configure!), so the units the equations and the unknowns are written in decide which candidates it can tell apart and which it perturbs. The linearized system is assembled in physical units: a node's row holds admittances, while the constitutive row of a coupled inductor branch holds the incidence of its node fluxes and, on its diagonal, the inductance itself, many orders smaller. So each system of a batch is scaled here: every row is divided by its largest entry, then every column of the result by its largest, which makes the pivot candidates of every row and column comparable; the right-hand side of each system is divided by the same row scales, and its solution by the column scales on the way out. cuDSS's matching, which permutes and scales the matrix ahead of the factorization, is not supported for a uniform batch.
Fields
rowptr: the row pointer of the structure the solver is handed, whose rows are contiguous in the stored values.order,segptr: the stored entries of that structure grouped by its column, so one work item owns a column and no two write the same scale.rowscale,scale: the scale of each row and of each column of each system of the batch.
JosephsonCircuits.TabulatedMatrixProvider Type
TabulatedMatrixProvider(frequencies, values; interpolation = :cubic,
extrapolation = :error)A matrix provider for tabulated data. frequencies is a strictly increasing vector of angular frequencies in radians per second and values is an array of dimensions (n, n, length(frequencies)).
interpolation may be :cubic (the default) or :linear. Cubic interpolation evaluates the cubic spline through each entry's samples, which follows a rotating phase far more closely than the chords between them; a table too short for a cubic takes the highest order it determines, the parabola through three samples or the line through two. A spline can overshoot between samples, so a quantity bounded in the data – a scattering entry's magnitude, say – can exceed the bound a little between them; a bound guaranteed at every frequency takes a passive fit, see RationalScattering.
extrapolation may be :error (the default), :constant, :linear or :zero. With :error, any requested frequency outside the tabulated range throws an error listing the offending frequencies; extrapolation of tabulated data is deliberately opt-in. :constant holds the end values beyond the ends, :linear continues from them with the interpolant's end slopes, and :zero is zero beyond them, the data of a response known to vanish outside the band it was sampled over.
JosephsonCircuits.TransientBlock Type
TransientBlockA scattering parameter block as the transient realizes it: the real constant scattering matrix S at the reference impedances R of its ports, the node of the signal and the reference terminal of each port (zero for ground), the index of the first of its port current unknowns, and the block's path. Its ports carry the hybrid constitutive equation of the linearized solver, (I - S) R^(-1/2) v - (I + S) R^(1/2) i = 0, with v the port voltages and i the port currents entering the block through the signal terminals, as auxiliary unknowns whose Kirchhoff couplings enter the node equations; nothing is inverted, so a short or an open is stamped exactly, and a scattering entry within roundoff of one is snapped to it, so a fitted feedthrough on the unit circle carries the exact zeros of its hybrid coefficients (see snapscattering). A block whose matrix depends on frequency carries its rational part as states, and a pumped block the states of every filter of its harmonics, the unconverted output on C and the converted ones modulated (see BlockModulation).
JosephsonCircuits.TransientIQPlan Type
TransientIQPlanReusable causal I/Q measurement plan. times are the right edges of complete windows; centertimes subtract the filter's groupdelay. The carrier frequencies, bandwidth3db and noisebandwidth are angular, in rad/s, and times in seconds. noisebandwidth is one-sided, pi*sum(abs2, taps)/dt, for the unity-DC-gain low-pass filter. ports are the port numbers of the carriers and rows the row of each port's trace, the ports in the order of their numbers.
The FFT workspace is mutable. Use separate plans for concurrent measurements.
sourceJosephsonCircuits.TransientLine Type
TransientLineAn ideal lossless transmission line as the transient realizes it: its characteristic impedance Z, its delay, and the signal and reference node of each of its two ports (zero for ground). In time the line is the method of characteristics: at each port the current into the line is v/Z - 2 q/sqrt(Z), a conductance 1/Z at the line's own impedance plus a current from the wave q that entered the far port a delay earlier, and the wave leaving a port, a = v/sqrt(Z) - q, is kept as the port's history for the far port to read a delay later. Nothing is inverted and nothing resonates in the equations, since the round trips that make the line's admittance singular in frequency are the recursion through the history; a mismatch to the connected circuit is the shared node. The delay must be at least one step, so that every wave a step reads is accepted history, and the read interpolates the endpoint history with the centered Lagrange stencil of up to six samples, a quintic where the delay leaves three accepted samples past the query and of lower order for a shorter delay.
JosephsonCircuits.TransientNoiseBath Type
TransientNoiseBathOne bath: its name, the rows of the equations its source enters with its weights there, the port it terminates (zero otherwise), its resistance (zero for a block channel) and its temperature. A resistor's source is a Norton current delivered to the node at its first terminal and drawn from the node at its second, the opposite sense of a CurrentSource there, which its noise does not see; a port's is delivered to the port's first (positive) terminal and drawn from its second, the port's own source convention, so the current enters the port wave as a port source's does; a block channel's source is an emitted noise wave, a combination of the block's ports weighted by an eigenvector of I - S S' times the square root of its eigenvalue, or one port of a block whose channels are correlated by a group (see TransientNoiseBaths), entering the port current rows as the source 2 eta of the hybrid equation. transientinjection builds the columns.
JosephsonCircuits.TransientNoiseBaths Type
TransientNoiseBathsThe baths of a TransientProblem, from transientnoisebaths.
JosephsonCircuits.TransientProblem Type
TransientProblemA compiled circuit with its matrices at one mode, its modified nodal analysis augmentation, its bound drives and its port data, ready to be integrated in time by transientsolve. Built by transientproblem.
Fields
circuit,matrices: the compiled circuit and itsCircuitMatricesat one mode, with real values.Nnodal,Naux: the node flux unknowns and the auxiliary branch currents of the mutually coupled inductors; the state hasNnodal + Nauxentries.Lscale: the inductance scale of the equations, the mean inductance of the circuit as harmonic balance uses at zero frequency, fixed for the problem so that a state is independent of the step: an auxiliary currentiis stored asLscale*i/phi0.coupledbranches,floatingcomponents,gaugeindices: the branches the augmentation promotes, the subnetworks no element connects to ground, whose flux offset is free, and the gauge rows fixing it.inertialess: the directions of the state that carry no inertia, one set of state indices per subnetwork of the capacitive graph no capacitor connects to ground, including every unknown no capacitor touches; the algebraic constraints a state must satisfy at the start lie along them.algebraic: the directions among them that carry no dissipation either, one set per subnetwork no capacitor or resistor connects to ground, each a union of inertialess ones; along them the equations constrain the flux alone, and the rate is what the constraint differentiated says.directions,constraints: the algebraic directions as the columns of a sparse matrix over the state, in the order ofalgebraic, and the constraints along them as the rows of one over the equations, the combinations of the equations which no rate enters.injection: the unscaled injection of a unit current of each drive into the node equations, one sparse column per drive, in the orientation of the drive.drives: the bound drives, in the order ofinjection's columns.constantcurrent: the unscaled constant node current of the netlist's current sources not replaced by a drive.balance: the floating subnetworks the drives feed, whose net current is judged whenever the drives are evaluated, seeFloatingBalance.ports: the compiled ports in the order of their numbers, the order of every port axis of the transient, as of harmonic balance's.portpositive,portnegative,portimpedances,portconductances: the node of each port terminal (zero for ground), the reference impedance and the conductance of the termination the port owns, in the order ofports, for the port waves.blocks: the scattering parameter blocks with a realization in time, seeTransientBlock, whose port currents are auxiliary unknowns after the coupled inductor currents.lines: the ideal transmission lines, seeTransientLine, whose wave histories the solve keeps.relations: the current-phase relation of every junction, in the order of the junction rows ofRJ, ornothingwhere every junction is sinusoidal.C,G,L,lineE: the scaled capacitance, conductance and augmented inverse inductance the transient steps, with the stamps of the blocks and the lines, and the lines' incidence, on the host.RJ,lmolj: the junction rows of the incidence and the coefficientsLscale/Lj, in the order ofrelations.
JosephsonCircuits.TransientQuantumPlan Type
TransientQuantumPlanA finite-record, positive-frequency temporal-mode measurement. Rows of its output are (X1,P1,X2,P2,...), with [X,P]=im and vacuum variance 1/2. coefficients[:,j] specifies mode j in the positive-frequency Fourier basis, whose bins are at the angular frequencies, 2pi*k/(N*dt) in rad/s; gram accounts for overlapping modes on the same port. vacuum and commutator are the corresponding real covariance and commutator matrices. ports are the port numbers of the modes and rows the row of each port's trace, the ports in the order of their numbers. Numeric measurement weights live on backend; metadata remain on the host. Storage is O(samples*modes). Batch selected windows for long sliding records.
JosephsonCircuits.TransientSystem Type
TransientSystemThe scaled system of a TransientProblem at one step size and one stepping rule, on one backend: the padded and scaled capacitance, conductance and augmented inverse inductance matrices, the junction incidence and coefficients, the drive injection, the port readout, the real Jacobian plan of harmonic balance at one mode carrying the step's linear term, the Jacobian it fills and the factorization of it, and the projection onto the algebraic constraints with the reading of the rate along them. Built by transientsystem; transientsolve, the tangent and the adjoint all step on it.
JosephsonCircuits.TransmissionLineProvider Type
TransmissionLineProvider(Z0, delay)The scattering parameter provider of an ideal lossless transmission line of characteristic impedance Z0 and one way delay delay seconds, referenced to Z0: S11 = S22 = 0 and S21 = S12 = exp(-im_ω_delay). Natively valid on signed frequencies.
JosephsonCircuits.TransportRows Type
TransportRowsThe transport rows Y v = j of the explicit direct current block, together with the coupling into the zero frequency nodal rows.
Fields
plan: the topology.Y:P'G0P, unreferenced. It is singular on a floating island, which is correct: these rows state the physics and say nothing about where the potential is measured from.j: the injected current.coupling:G0 P, the resistor current each component's voltage drives into the nodes, indexed by node with ground dropped.
See transportrows and DCConductancePlan.
JosephsonCircuits.ValueMaps Type
ValueMapsWhere each value array of a NonlinearTermPlan and the linear term it was built from read their numbers, under a fixed structure, so that new component values can be written into them without rebuilding anything.
Fields
ml,mg,mc: for each stored entry ofKnm, the stored entry ofinvLnm,GnmandCnmit takes, or zero.kmap,kre,kim: for each entry of the real form of the linear term, the entry ofKnmit comes from and the coefficient of its real and its imaginary part, which are0or±1.cmap: for each entry of the complex form, the entry ofKnm.bjunc,bsgn: for each Josephson coefficient, its junction and the incidence entry, so the coefficient isbsgntimes the junction'sLscale/Lj.knz: the entries ofKnm, on the backend where the plan lives, refilled at each refresh.
Found by valuemaps, which probes the conversions with tagged values rather than restating their rules.
JosephsonCircuits.WorkerBlockSensitivity Type
WorkerBlockSensitivityOne worker's private state for the scattering block sensitivity stamps: its own copy of the stamp vector (the lumped stamps are shared read only, the :S stamps' values are private because they are rebuilt at every signal frequency), the derivative systems, and the evaluation scratch.
JosephsonCircuits.A_B_to_symplectic_pair Method
A_B_to_symplectic_pair(A::AbstractMatrix, B::AbstractMatrix; atol = 0,
rtol = ...)Given A (2n×2n) and B (2n×4n) such that A*Ω*A' + B*ΩE*B' = Ω, return the symplectic matrix S = [A B; C D] with respect to Ωtot = Ω ⊕ ΩE, in pair operator order.
C (4n×2n) and D (4n×4n) are constructed here; atol and rtol are the tolerances of the rank decisions that construction makes.
JosephsonCircuits.B_from_X_Y_quadrature Method
B_from_X_Y_quadrature(Omega, X::AbstractMatrix{<:Real},
Y::AbstractMatrix{<:Real}; hbar = 1, atol = 0, rtol = ...)Return the real 2n x 4n block B, from an environment of 2n modes in block operator order to the n modes of the system, which realizes the completely positive trace preserving (CPTP) map of the quadrature transformation X and noise Y with the environment in the vacuum: X*Omega*transpose(X) + B*ΩE*transpose(B) = Omega, with ΩE the block ordered symplectic form of the environment, and Y = (hbar/2)*B*transpose(B). Omega is the symplectic form of the system and hbar the scale of the covariances of is_cptp.
B is a square root of (2/hbar)*K, with K = Y + im*(hbar/2)*(Omega - X*Omega*transpose(X)) the matrix of is_cptp, which is Hermitian and positive semi-definite for a CPTP map, and so Y, its real part. K is judged as is_cptp judges it, to the same tolerance tol = max(atol, rtol*s) of the scale s = norm(Y) + (hbar/2)*norm(Omega)*(1 + opnorm(X)^2): an eigenvalue down to -tol is rounding and taken as zero, and a map is_cptp refuses throws an ArgumentError.
JosephsonCircuits.B_from_X_Y_quadrature_block Method
B_from_X_Y_quadrature_block(X::AbstractMatrix{<:Real},
Y::AbstractMatrix{<:Real}; hbar = 1, atol = 0, rtol = ...)B_from_X_Y_quadrature for the quadrature transformation X and noise Y in block operator order: the block B of a symplectic matrix S = [X B; C D] with the environment in the vacuum, Y = (hbar/2)*B*B' in the units of hbar of is_cptp.
JosephsonCircuits.B_from_X_Y_quadrature_pair Method
B_from_X_Y_quadrature_pair(X::AbstractMatrix{<:Real},
Y::AbstractMatrix{<:Real}; hbar = 1, atol = 0, rtol = ...)B_from_X_Y_quadrature_block in pair operator order, the columns of B too, in the units of hbar of is_cptp.
JosephsonCircuits.CMtokeyed Method
CMtokeyed(CM, outputmodes, outputportnumbers, w)Convert a commutation relation array CM vs frequency w to a keyed array. Return the keyed array.
Examples
julia> JosephsonCircuits.CMtokeyed([1 2;3 4;;;],[(0,)],[1,2],[1.0,1.1])
3-dimensional KeyedArray(NamedDimsArray(...)) with keys:
↓ outputmode ∈ 1-element Vector{Tuple{Int64}}
→ outputport ∈ 2-element Vector{Int64}
◪ freqindex ∈ 2-element UnitRange{Int64}
And data, 1×2×2 Array{Int64, 3}:
[:, :, 1] ~ (:, :, 1):
(1) (2)
(0,) 1 3
[:, :, 2] ~ (:, :, 2):
(1) (2)
(0,) 2 4JosephsonCircuits.Cnoisetokeyed Method
Cnoisetokeyed(Cnoise, outputmodes, outputportnumbers, w)Convert an added noise covariance array Cnoise vs frequency w to a keyed array. Both of its first two indices run over the output port modes: Cnoise[i,j] is the covariance of the noise at the output i with the conjugate of the noise at the output j, so the axes are outputmode and outputport for i, conjoutputmode and conjoutputport for j, and freqindex. Return the keyed array.
Examples
julia> JosephsonCircuits.Cnoisetokeyed([11 12;21 22;;;],[(0,)],[1,2],[1.0])
5-dimensional KeyedArray(NamedDimsArray(...)) with keys:
↓ outputmode ∈ 1-element Vector{Tuple{Int64}}
→ outputport ∈ 2-element Vector{Int64}
◪ conjoutputmode ∈ 1-element Vector{Tuple{Int64}}
▨ conjoutputport ∈ 2-element Vector{Int64}
▨ freqindex ∈ 1-element UnitRange{Int64}
And data, 1×2×1×2×1 Array{Int64, 5}:
[:, :, 1, 1, 1] ~ (:, :, (0,), 1, 1):
(1) (2)
(0,) 11 21
[:, :, 1, 2, 1] ~ (:, :, (0,), 2, 1):
(1) (2)
(0,) 12 22JosephsonCircuits.R_block_to_pair Method
R_block_to_pair(n::Integer)Return the 2n x 2n permutation matrix which takes a vector of n modes in block order to pair order.
Examples
julia> JosephsonCircuits.R_block_to_pair(2)
4×4 SparseArrays.SparseMatrixCSC{Int64, Int64} with 4 stored entries:
1 ⋅ ⋅ ⋅
⋅ ⋅ 1 ⋅
⋅ 1 ⋅ ⋅
⋅ ⋅ ⋅ 1JosephsonCircuits.R_ladder_to_quadrature_block Method
R_ladder_to_quadrature_block(n::Integer)The block ordered form of R_ladder_to_quadrature_pair.
Examples
julia> JosephsonCircuits.R_ladder_to_quadrature_block(1)
2×2 Matrix{ComplexF64}:
0.707107+0.0im 0.707107+0.0im
0.0-0.707107im 0.0+0.707107imJosephsonCircuits.R_ladder_to_quadrature_pair Method
R_ladder_to_quadrature_pair(n::Integer)Return the 2n x 2n unitary matrix which takes the ladder operators of n modes in pair order to their quadratures, x = (a + adag)/sqrt(2) and p = -im*(a - adag)/sqrt(2), in pair order.
Examples
julia> JosephsonCircuits.R_ladder_to_quadrature_pair(1)
2×2 SparseArrays.SparseMatrixCSC{ComplexF64, Int64} with 4 stored entries:
0.707107+0.0im 0.707107+0.0im
0.0-0.707107im 0.0+0.707107imJosephsonCircuits.R_pair_to_block Method
R_pair_to_block(n::Integer)Return the 2n x 2n permutation matrix which takes a vector of n modes in pair order to block order.
Examples
julia> JosephsonCircuits.R_pair_to_block(2)
4×4 SparseArrays.SparseMatrixCSC{Int64, Int64} with 4 stored entries:
1 ⋅ ⋅ ⋅
⋅ ⋅ 1 ⋅
⋅ 1 ⋅ ⋅
⋅ ⋅ ⋅ 1JosephsonCircuits.R_quadrature_to_ladder_block Method
R_quadrature_to_ladder_block(n::Integer)The block ordered form of R_quadrature_to_ladder_pair.
Examples
julia> JosephsonCircuits.R_quadrature_to_ladder_block(2)
4×4 Matrix{ComplexF64}:
0.707107+0.0im 0.0+0.0im 0.0+0.707107im 0.0+0.0im
0.0+0.0im 0.707107+0.0im 0.0+0.0im 0.0+0.707107im
0.707107+0.0im 0.0+0.0im 0.0-0.707107im 0.0+0.0im
0.0+0.0im 0.707107+0.0im 0.0+0.0im 0.0-0.707107imJosephsonCircuits.R_quadrature_to_ladder_pair Method
R_quadrature_to_ladder_pair(n::Integer)Return the 2n x 2n unitary matrix which takes the quadratures of n modes in pair order to their ladder operators, a = (x + im*p)/sqrt(2) and adag = (x - im*p)/sqrt(2), in pair order; the inverse of R_ladder_to_quadrature_pair.
Examples
julia> JosephsonCircuits.R_quadrature_to_ladder_pair(2)
4×4 SparseArrays.SparseMatrixCSC{ComplexF64, Int64} with 8 stored entries:
0.707107+0.0im 0.0+0.707107im ⋅ ⋅
0.707107+0.0im 0.0-0.707107im ⋅ ⋅
⋅ ⋅ 0.707107+0.0im 0.0+0.707107im
⋅ ⋅ 0.707107+0.0im 0.0-0.707107imJosephsonCircuits.Snoisetokeyed Method
Snoisetokeyed(Snoise, inputmodes, components, outputmodes,
outputportnumbers, w)Convert a noise scattering parameter array Snoise vs frequency w to a keyed array. Return the keyed array.
Examples
julia> JosephsonCircuits.Snoisetokeyed([11 12;21 22;;;],[(0,)],["C1","C2"],[(0,)],[1,2],[1.0])
5-dimensional KeyedArray(NamedDimsArray(...)) with keys:
↓ inputmode ∈ 1-element Vector{Tuple{Int64}}
→ component ∈ 2-element Vector{String}
◪ outputmode ∈ 1-element Vector{Tuple{Int64}}
▨ outputport ∈ 2-element Vector{Int64}
▨ freqindex ∈ 1-element UnitRange{Int64}
And data, 1×2×1×2×1 Array{Int64, 5}:
[:, :, 1, 1, 1] ~ (:, :, (0,), 1, 1):
("C1") ("C2")
(0,) 11 21
[:, :, 1, 2, 1] ~ (:, :, (0,), 2, 1):
("C1") ("C2")
(0,) 12 22JosephsonCircuits.Ssensitivitytokeyed Method
Ssensitivitytokeyed(Ssensitivity, outputmodes, outputportnumbers,
inputmodes, inputportnumbers, components, w)Return the scattering parameter sensitivity array as a keyed array with axes (outputmode, outputport, inputmode, inputport, component, freqindex).
sourceJosephsonCircuits.Stokeyed Method
Stokeyed(S, outputmodes, outputportnumbers, inputmodes, inputportnumbers)Convert a scattering parameter array S to a keyed array. Returned the keyed array.
Examples
julia> JosephsonCircuits.Stokeyed([11 12;21 22],[(0,)],[1,2],[(0,)],[1,2])
4-dimensional KeyedArray(NamedDimsArray(...)) with keys:
↓ outputmode ∈ 1-element Vector{Tuple{Int64}}
→ outputport ∈ 2-element Vector{Int64}
◪ inputmode ∈ 1-element Vector{Tuple{Int64}}
▨ inputport ∈ 2-element Vector{Int64}
And data, 1×2×1×2 Array{Int64, 4}:
[:, :, 1, 1] ~ (:, :, (0,), 1):
(1) (2)
(0,) 11 21
[:, :, 1, 2] ~ (:, :, (0,), 2):
(1) (2)
(0,) 12 22JosephsonCircuits.Stokeyed Method
Stokeyed(S, outputmodes, outputportnumbers, inputmodes,
inputportnumbers, w)Convert a scattering parameter array S vs frequency w to a keyed array. Returned the keyed array.
Examples
julia> JosephsonCircuits.Stokeyed([11 12;21 22;;;],[(0,)],[1,2],[(0,)],[1,2],[1.0])
5-dimensional KeyedArray(NamedDimsArray(...)) with keys:
↓ outputmode ∈ 1-element Vector{Tuple{Int64}}
→ outputport ∈ 2-element Vector{Int64}
◪ inputmode ∈ 1-element Vector{Tuple{Int64}}
▨ inputport ∈ 2-element Vector{Int64}
▨ freqindex ∈ 1-element UnitRange{Int64}
And data, 1×2×1×2×1 Array{Int64, 5}:
[:, :, 1, 1, 1] ~ (:, :, (0,), 1, 1):
(1) (2)
(0,) 11 21
[:, :, 1, 2, 1] ~ (:, :, (0,), 2, 1):
(1) (2)
(0,) 12 22JosephsonCircuits.X_Y_to_bogoliubov_block Method
X_Y_to_bogoliubov_block(X::AbstractMatrix, Y::AbstractMatrix; atol = 0,
rtol = ...)The ladder form of X_Y_to_symplectic_block, with X, Y and the Bogoliubov matrix returned in block operator order, and the symmetrized covariances and the tolerances of X_Y_to_bogoliubov_pair.
JosephsonCircuits.X_Y_to_bogoliubov_pair Method
X_Y_to_bogoliubov_pair(X::AbstractMatrix, Y::AbstractMatrix; atol = 0,
rtol = ...)The ladder form of X_Y_to_symplectic_pair: return a Bogoliubov matrix of 3n modes, in pair operator order, which realizes the CPTP map of the ladder transformation X and noise Y of n modes with an environment in the vacuum. Y is a symmetrized covariance with the vacuum I/2 (is_cptp_ladder_pair), so the block B of the Bogoliubov matrix from the environment to the system adds Y = B*B'/2. A map which is not CPTP to the tolerances atol and rtol of is_cptp_ladder_pair throws an ArgumentError.
JosephsonCircuits.X_Y_to_symplectic_block Method
X_Y_to_symplectic_block(X::AbstractMatrix{<:Real}, Y::AbstractMatrix{<:Real};
hbar = 1, atol = 0, rtol = ...)The block ordered form of X_Y_to_symplectic_pair for X and Y in block order, in the units of hbar of is_cptp and to its tolerances: S is in the block order of all 3n modes, so X is the submatrix of the rows and columns [1:n; 3n+1:4n] of S.
JosephsonCircuits.X_Y_to_symplectic_pair Method
X_Y_to_symplectic_pair(X::AbstractMatrix{<:Real}, Y::AbstractMatrix{<:Real};
hbar = 1, atol = 0, rtol = ...)Return a symplectic matrix S of 3n modes, in pair operator order, whose restriction to the first n modes with an environment of 2n modes in the vacuum is the completely positive trace preserving (CPTP) map of the quadrature transformation X and noise Y of n modes: X is the upper left 2n x 2n block of S, and its upper right block B adds the noise Y = (hbar/2)*B*transpose(B) from the vacuum (hbar/2)*I, in the convention of is_cptp. A map which is not CPTP to the tolerances atol and rtol of is_cptp throws an ArgumentError (B_from_X_Y_quadrature).
JosephsonCircuits.Ymin_from_X Method
Ymin_from_X(Omega, X; method = 1, hbar = 1)Return the noise Y = (hbar/2)*|im*Δ|, with Δ = Omega - X*Omega*transpose(X) and |H| the absolute value of a Hermitian matrix, which makes the Gaussian map of the quadrature transformation X completely positive and trace preserving for the symplectic form Omega, in the units of hbar of is_cptp. It is minimal: no noise below it in the positive semi-definite order makes the map CPTP.
method selects the factorization |im*Δ| is computed from: 1, the default, an eigendecomposition of im*Δ; 2, a Schur decomposition of Δ; 3, a singular value decomposition of Δ.
JosephsonCircuits.Ymin_from_X_quadrature_block Method
Ymin_from_X_quadrature_block(X; method = 1, hbar = 1)Ymin_from_X for the quadrature transformation X in block operator order, in the units of hbar of is_cptp.
JosephsonCircuits.Ymin_from_X_quadrature_pair Method
Ymin_from_X_quadrature_pair(X; method = 1, hbar = 1)Ymin_from_X for the quadrature transformation X in pair operator order, in the units of hbar of is_cptp.
JosephsonCircuits._harvestfloquet! Method
_harvestfloquet!(pc::FloquetPreconditioner, Vj, Hj)Harvest candidate correction vectors from an Arnoldi factorization with basis Vj (n by j) and rectangular Hessenberg Hj (j + 1 by j, host resident) and return pc.
The harvest right singular vectors of Hj with the smallest singular values are taken, the directions this Krylov space found the preconditioned operator shrinks most. Hj may be the Hessenberg of the Arnoldi relation or the triangular one the Givens rotations of gmres! leave in its place: the rotations are orthogonal and act from the left, so the two share their singular values and right singular vectors.
These are Krylov-space directions. Each is lifted through the Arnoldi basis and then mapped through the current complete preconditioner, x = B*u, into the physical state space before being stored, because that is the space in which a direction still means something once the Jacobian has moved: at the next point the exact image J*x is recomputed and the coarse space rebuilt around it, whereas a stored residual direction would have to be reinterpreted against an operator it was never measured on.
Nothing is rebuilt here. The preconditioner must not change under a running GMRES, so a harvest only appends to the candidate bank and leaves the active blocks as they are; the next build, at the next Newton step, takes the candidates in (hasnewcandidates).
JosephsonCircuits._rebuildfloquet! Method
_rebuildfloquet!(pc::FloquetPreconditioner)Rebuild the active basis from the candidate bank at the current point: the exact images Y0 = J*X0, the rank-revealing factorization which makes J*X = C with C'C = I, the base solves inv(P)*C, the correction strength filter, and the compression to size.
Costs k Jacobian products and r base solves for k candidates and active rank r.
JosephsonCircuits.activemoderows Function
activemoderows(Nmodes::Integer, Amatrixindices::Matrix,
Bmatrixindices::Union{Matrix,Nothing} = nothing)For each column mode, return the sorted list of row modes for which the frequency domain index matrix Amatrixindices (or, if provided, Bmatrixindices) has a nonzero entry, ie. the row modes which contribute to the Jacobian sparsity structure in that column mode.
JosephsonCircuits.add_modes Method
add_modes(connections::AbstractVector{Vector{Tuple{T,Int}}},
Nmodes::Integer) where {T}Assume the scattering parameter matrices are multi-mode and connections specifies the connections between physical ports. Return the connections vector with the existing connections re-numbered and with added connections between every mode associated with each physical port.
Examples
julia> connections = [[("S1",3),("S2",4)],[("S1",2),("S2",1)]];JosephsonCircuits.add_modes(connections,2)
4-element Vector{Vector{Tuple{String, Int64}}}:
[("S1", 5), ("S2", 7)]
[("S1", 6), ("S2", 8)]
[("S1", 3), ("S2", 1)]
[("S1", 4), ("S2", 2)]JosephsonCircuits.add_modes Method
add_modes(connections::AbstractVector{Tuple{T,T,Int,Int}},
Nmodes::Integer) where {T}Assume the scattering parameter matrices are multi-mode and connections specifies the connections between physical ports. Return the connections vector with the existing connections re-numbered and with added connections between every mode associated with each physical port.
Examples
julia> connections = [("S1","S2",3,4),("S1","S2",2,1)];JosephsonCircuits.add_modes(connections,2)
4-element Vector{Tuple{String, String, Int64, Int64}}:
("S1", "S2", 5, 7)
("S1", "S2", 6, 8)
("S1", "S2", 3, 1)
("S1", "S2", 4, 2)JosephsonCircuits.add_splitters Method
add_splitters(networks::AbstractVector{PassiveNetwork{T,N}},
connections::AbstractVector{Vector{Tuple{T,Int}}};
small_splitters = true) where {T,N}Return the networks and connections with splitters (ideal lossless symmetrical reciprocal networks) and connections to the splitters added when more than two ports intersect. connections is also converted from a vector of vectors of tuples where the tuple contains the network and the port such as [[(:S1,1),(:S2,1)]] to a vector of tuples where the tuple contains the two networks and ports being connected [(:S1,:S2,1,1)]. With small_splitters = true an N port splitter is built by combining N-2 three port splitters; with false it is a single N port splitter. Each splitter is a network with a new name: a UUID for network names which are strings or symbols, and the integer after the largest name for integer names.
References
S. F. Cao, Y. C. Jiao, and Z. Zhang. "Applications of Generalized Cascade Scattering Matrix on the Microwave Circuits and Antenna Arrays". International Journal of Antennas and Propagation Vol. 2015, 759439, doi:10.1155/2015/759439.
sourceJosephsonCircuits.add_splitters Method
add_splitters(networks, connections::AbstractVector{Tuple{T,T,Int,Int}};
small_splitters = true) where TConnections already in the pairwise (network1, network2, port1, port2) form are returned unchanged along with networks; splitters must already have been added.
JosephsonCircuits.addblockdc! Method
addblockdc!(Fc, r::DCBlockRows, u, v)Replace each block's zero frequency row in Fc, which holds -i, by the block's own relation B0 (scale dv) - C0 i, with the block currents read from u at the positions r.currentindex gives them and the average voltages from v.
The correction is added rather than written, because the row also carries the Kirchhoff coupling of the current into the node equations, which is unchanged and must survive.
sourceJosephsonCircuits.addblocktransport! Method
addblocktransport!(Fv, r::DCBlockRows, u)Add the block currents which cross a component boundary to that component's transport row, reading each current from u at the position r.currentindex gives it.
Every one of them, unconditionally. A reference row is chosen after this, from the assembled descriptor, so there is no row here which is known in advance to be redundant and no current which may be dropped on the grounds that it lands in one.
sourceJosephsonCircuits.addconstantsources! Method
addconstantsources!(bbm, componenttypes, componentnames, nodeindices,
vvn, topology, modes, Lscale, Nmodes)Add the constant current sources of the netlist to the source vector in the branch basis: a CurrentSource component of value I drives the zero frequency mode, on its own branch and in the orientation the graph gave that branch, as the transient reads it. It drives I through itself from its first terminal to its second: it draws the current from the node at its first terminal and delivers it to the node at its second, the opposite sense of a port source, which injects its current into the port's first (positive) terminal. The mode must be retained: a nonzero source without it is an error, so that a netlist carrying a constant source is never solved without its bias in silence.
JosephsonCircuits.addjosephsonterm! Method
addjosephsonterm!(nzval::AbstractVector,
plan::StructureComplexJosephsonPlan, phimatrix)Write the Josephson contribution into nzval, overwriting it.
JosephsonCircuits.adjointdevice Method
adjointdevice(ds::DeviceSweep, i::Integer)The adjoint solution of frequency i of the staged batch where it was computed, a view into the device batch, for the noise scattering parameters which are formed there rather than brought back (see devicenoise). A read of the solved batch, so several workers may hold different frequencies of it at once.
JosephsonCircuits.adjointnoisesigns! Method
adjointnoisesigns!(Snoise::AbstractMatrix, wmodes, Nmodes::Integer)The sign the adjoint route owes the noise scattering matrix: multiply Snoise[c, i] by the sign of the channel's mode frequency times the sign of the port's.
Snoise is formed by the adjoint identity, from the transposed system driven at the ports and read at the channels, because that costs one solve per port rather than one per channel. The output wave read at a channel c is kval_c * i*w_c * phi_c, with the signed mode frequency the voltage of a flux carries, and it is divided by the input wave at the port i, kval_i * Z_i * I_i / 2, which carries no frequency. The scattering matrix the channel's own drive would give is the reverse, kval_i * i*w_i * phi_i over kval_c * Z_c * I_c / 2, and by reciprocity of the transposed system the two flux responses per unit current are the same. With kval^2 = 1/(|w| Z) the ratio of the adjoint quantity to the true one is sign(w_c) * sign(w_i): the magnitudes agree, and the sign of every entry between a positive and a negative frequency mode is reversed. This restores it, so that Snoise is the scattering matrix from the channel's incoming wave to the port's outgoing wave in the same signed frequency convention as S; a resistor's channel is then exactly a port of its impedance in vacuum, and the cross terms of the added noise covariance between positive and negative frequency outputs compose with S as a Gaussian channel does. The quantum efficiency and the commutation relations read only magnitudes and do not see this.
JosephsonCircuits.adjointsolution! Method
adjointsolution!(phin, ds::DeviceSweep, i::Integer)The adjoint counterpart of forwardsolution!.
JosephsonCircuits.aliasmode Method
aliasmode(mode::NTuple{N,Int}, Nt::NTuple{N,Int})Alias the mode mode back onto the sampled grid with Nt time domain samples along each dimension, returning the canonical stored mode and whether the stored element is the complex conjugate of the requested mode. The first dimension is the RDFT dimension of a real signal, which stores only the modes from 0 to Nt[1] ÷ 2; a mode which aliases onto the other half of that dimension is stored as the complex conjugate at the negated mode. The other dimensions are full DFT dimensions whose stored modes range from -(Nt[d]-1) ÷ 2 - iseven(Nt[d]) to (Nt[d]-1) ÷ 2.
Examples
julia> JosephsonCircuits.aliasmode((3,), (8,))
((3,), false)
julia> JosephsonCircuits.aliasmode((5,), (8,))
((3,), true)
julia> JosephsonCircuits.aliasmode((8,), (8,))
((0,), false)
julia> JosephsonCircuits.aliasmode((1, 3), (8, 4))
((1, -1), false)JosephsonCircuits.allsinusoidal Method
allsinusoidal(r::JunctionRelations)Whether every junction of r is the sinusoidal Josephson one, which is the empty table: the solvers hold a table always, so that their type does not depend on what the circuit holds, and an empty one means the plain sin and cos of the Josephson relation.
JosephsonCircuits.amalgamate Method
amalgamate(parent, post, later, nrows; maxrows = typemax(Int))Merge the elimination tree into its fundamental supernodes: walking the postorder, a node joins the supernode of its child when it is that child's parent, the child is its only child, and the child's structure after fill, later[child], is the node and the node's own structure later[node]. The rest of a child's structure always lies within its parent's, so the test is length(later[child]) == length(later[node]) + 1. The merged diagonal block and panel then hold no entry the node by node factors would not hold: a merge takes no zero into the factors, whatever the circuit, so a chain keeps its block bidiagonal factors while the separators of a meshed circuit, dense after fill, are eliminated as one block. maxrows bounds the rows of a supernode; the linearized solve, which merges nothing, passes the rows of one node (blocksymbolic). Each supernode is returned as its list of nodes, in elimination order.
JosephsonCircuits.andersoncorrection! Method
andersoncorrection!(s::AndersonState, deltax; rtol = eps(T)^(3//4)) -> BoolAssemble the Type-II Anderson correction cₖ = (Sₖ + Yₖ)γₖ into s.correction from the current history and the Newton update deltax. Return true when a usable correction was produced and false otherwise, such as when the history is empty or the coefficient solve fails or produces non-finite values, in which case s.correction must not be used.
The real extrapolation coefficients γ minimize ||ΔF*γ - deltax|| through a thin QR factorization of the history ΔF, by two passes of modified Gram-Schmidt in the preallocated buffers, and back substitution. The history is truncated at the first column whose norm collapses after orthogonalization, below rtol times the largest norm seen, since it is linearly dependent on the older ones; the leading columns are well conditioned and the coefficients of the rest are zero. All history access is through age-ordered column indices (oldest first). The coefficients are constrained real because for the harmonic balance quasi-Newton map the error operator is antilinear (involves complex conjugation), so complex coefficients cannot cancel the error modes; real coefficients correspond to Anderson acceleration of the equivalent real system.
JosephsonCircuits.andersonhistory! Method
andersonhistory!(s::AndersonState, x, deltax)Record one step into the Anderson history. Once a previous iterate/update pair exists, write the differences x - xprev and deltax - deltaxprev into the oldest history column in place, then refresh the previous pair, so each stored difference spans exactly one step. The first call after construction (or after a full reset) only establishes the pair.
JosephsonCircuits.andersonrestart! Method
andersonrestart!(s::AndersonState)Discard the entire Anderson history (but keep the preallocated storage). This can be used after, for example, linesearch failures which suggest the local Anderson model was not useful. The previous iterate/update pair is kept, so the acceleration resumes from the next accepted step's difference.
sourceJosephsonCircuits.applybackwardjosephsontranspose! Method
applybackwardjosephsontranspose!(P, tplan, plan, w)Apply the transposed Josephson backward map, scaled by the inverse conjugate multiplicity.
sourceJosephsonCircuits.applybackwardterm! Method
applybackwardterm!(out::AbstractVector, plan::NonlinearTermPlan,
phimatrix::AbstractArray, z::AbstractVector;
addlinearterm::Bool = true)Apply the backward map of a NonlinearTermPlan, writing the node vector. Dispatches on the element type of out: a real vector receives the equivalent real representation and a complex vector the complex one, and z must be in the same representation. With addlinearterm = true the frequency dependent linear term applied to z is added in the same pass; with addlinearterm = false only the Josephson contribution is written, as the second directional derivative requires, and z is not read.
JosephsonCircuits.applydcconductance Method
applydcconductance(bnm, plan, sol, Nmodes)Subtract the direct current the resistors and blocks carry from the zero frequency rows of the source.
The solve does not use this: it carries the average voltages as unknowns and the currents reach the nodes through the coupling. What needs it is the Kirchhoff validation, which reconstructs its residual from the system alone and so knows nothing of that coupling; correcting the source here, and adding the same current back to the residual, hands it a consistent pair.
sourceJosephsonCircuits.applydcsolve! Method
applydcsolve!(z, r, d::DCFactorization)Solve the direct current subsystem for the coordinates of r it owns and write the answer into the same coordinates of z, in place: on the backend the factorization lives on, or, for a subsystem larger than DCDEVICESOLVEMAX, on the host between a gather and a scatter there.
JosephsonCircuits.applydcupdate! Method
applydcupdate!(Fw, uw, up::DCUpdate; residual = true)Apply the direct current block in its matrix form.
sourceJosephsonCircuits.applyfft! Method
applyfft!(fd::AbstractArray{Complex{T}}, td::AbstractArray{T}, rfftplan)The second half of applynl!: the frequency domain coefficients fd of the time domain signal td, the inverse of applyifft! with the same normalization convention. A nothing plan is the identity.
The real to complex transform of an out of place plan reads td and leaves it as it was (FFTW and cuFFT alike; only the complex to real direction of applyifft! may destroy its input), so a caller may hand in a cached time domain array directly.
JosephsonCircuits.applyffttranspose! Method
applyffttranspose!(alpha::Array{Complex{T}}, P::Array{Complex{T}},
padded::Array{Complex{T}}, fftplan)Apply the transpose of applyfft!: given a covector P on the stored frequency domain coefficients, compute the covector alpha on the time domain samples such that sum(alpha .* td) == sum(P .* applyfft(td)) for every real time domain array td, exactly, including the truncated first dimension of the real transform.
This is a forward transform again, not a new kernel: the discrete Fourier matrix is symmetric, so the transpose of the transform which produces the stored coefficients is the full complex transform of those coefficients zero padded along the first dimension (the only dimension the real transform truncates; applyfft! stores only its non negative harmonics), with the same 1/prod(Nt) normalization. padded is a work array the size of the time domain grid and alpha may not alias it. The last dimension, the Josephson junction index, is not transformed, exactly as in applyfft!.
Used by the reverse order sensitivity contraction to transpose the map from the time domain samples to the Fourier coefficients of cos(phi(t)), through the same transform plans and normalization which define the forward map, for any number of tones.
JosephsonCircuits.applyforwardterm! Method
applyforwardterm!(phimatrix::AbstractArray, plan::NonlinearTermPlan,
z::AbstractVector)Apply the forward map of a NonlinearTermPlan, writing the frequency domain coefficients of the Josephson junction branch fluxes for the point or direction z. Dispatches on the element type: a real vector is taken in the equivalent real representation and a complex vector in the complex one.
JosephsonCircuits.applyforwardtranspose! Method
applyforwardtranspose!(out, tplan, Q, w)Apply the transposed forward map and add the transposed linear term. Overwrites out.
JosephsonCircuits.applyfrequencydependent! Method
applyfrequencydependent!(nzval::AbstractMatrix,
st::DeviceFrequencyDependentStamps, wpump, ws)Add the stamps of the frequency dependent components into the stored values nzval of a batch of system matrices at the signal frequencies ws, from the table stagefrequencydependent! staged for the batch; wpump holds the pump mode offsets of the signal modes.
JosephsonCircuits.applyifft! Method
applyifft!(td::AbstractArray{T}, fd::AbstractArray{Complex{T}}, irfftplan)The first half of applynl!: the physical time domain signal td from the frequency domain coefficients fd, with the normalization convention of applynl!, so that linear operations can be interleaved with the pointwise time domain nonlinearities. applyfft! is the other half, and applynl! is their composition with a pointwise function between them. A nothing plan (a system with no junctions) is the identity.
NOTE: applyifft! may overwrite fd.
JosephsonCircuits.applynl! Method
applynl!(fd::AbstractArray{Complex{T}}, td::AbstractArray{T}, f,
irfftplan, rfftplan)
applynl!(fd, td, f, ::Nothing, ::Nothing)Apply the nonlinear function f to the frequency domain data by transforming to the time domain, applying the function, then transforming back to the frequency domain, overwriting the contents of fd and td in the process. We use plans for the forward and reverse RFFT prepared by plan_applynl.
Examples
fd=ones(Complex{Float64},3,2)
td, irfftplan, rfftplan = JosephsonCircuits.plan_applynl(fd)
JosephsonCircuits.applynl!(fd, td, cos, irfftplan, rfftplan)
fd
# output
3×2 Matrix{ComplexF64}:
0.856732+0.0im 0.856732+0.0im
-0.143268+0.0im -0.143268+0.0im
-0.143268+0.0im -0.143268+0.0imJosephsonCircuits.applypreconditioner! Function
applypreconditioner!(z::AbstractVector, pc::AbstractPreconditioner,
r::AbstractVector)Overwrite z with the action of the inverse of the preconditioner pc on r and return z.
JosephsonCircuits.applyrealtocomplex! Method
applyrealtocomplex!(xc::AbstractVector, plan::NonlinearTermPlan,
xr::AbstractVector)
applycomplextoreal!(xr::AbstractVector, plan::NonlinearTermPlan,
xc::AbstractVector)Convert a node vector between the complex representation and the equivalent real one through the layout the plan carries, as a conflict free kernel on the plan's backend, or as a plain loop on the host. These are the device capable counterparts of real_to_complex! and complex_to_real! for the two representations of an HBSystem point, which advance a serial cursor and read a BitVector.
JosephsonCircuits.applyrelationnl! Method
applyrelationnl!(fd, td, work, relations, coefficients, trig, irfftplan,
rfftplan)applynl! with the per junction relation of relations in place of a single function: coefficients are the polynomial coefficients to evaluate, one row per polynomial junction of the table, and trig is what its sinusoidal junctions take instead. work is a time domain array the size of td, which the Horner loop reads while it writes td.
JosephsonCircuits.applyscatteringstamps! Method
applyscatteringstamps!(nzval::AbstractMatrix, st::DeviceScatteringStamps)Add the staged scattering values into the stored values nzval of a batch of system matrices. stagescatteringstamps! must have run for the batch nzval was assembled at.
JosephsonCircuits.asoperator Method
asoperator(A, n)A itself when it is already mul!-able, and a FunctionOperator when it is a bare in-place product.
The Krylov solvers of this package apply the Jacobian through mul!, which is the interface every external linear algebra package in the ecosystem consumes. Normalizing here means a JacobianOperator can be handed straight through with no wrapper, while the older closure form keeps working.
JosephsonCircuits.assembleblocks! Method
assembleblocks!(C::ClusterBlocks, S::BlockStructure, phimatrix)Assemble the diagonal blocks and panels of one cluster from the Fourier coefficients phimatrix of cos(phi(t)) and the linear terms.
JosephsonCircuits.assemblebranch! Method
assemblebranch!(nzval, seen, plan::BranchStampPlan, values, combine)Fold values into the branch vector nzval against a fixed set of branches.
combine is applied to the running value and the new one in the order the components appear, matching sparsevec's combination of duplicate indices: two inductors on one branch combine as a parallel inductance. With combine = nothing every branch holds one component, as the junction plan guarantees (see junctionstampplan), and each value is written to its branch, with no seen to keep.
JosephsonCircuits.assemblebranch Method
assemblebranch(::Type{T}, plan::BranchStampPlan, values, combine, Nmodes)The branch vector of values, repeated along the diagonal for Nmodes.
JosephsonCircuits.assemblecomplexjacobian! Method
assemblecomplexjacobian!(nzval::AbstractVector,
plan::StructureComplexJacobianPlan, phimatrix)Assemble the stored values of the complex Jacobian: the Josephson map applied to the Fourier coefficients, plus the constant linear term.
sourceJosephsonCircuits.assembleinvinductance Method
assembleinvinductance(::Type{T}, plan, Lb, Nmodes)The inverse nodal inductance matrix of the branch inductances Lb.
JosephsonCircuits.assemblematrices! Function
assemblematrices!(nm::CircuitMatrices, plan::CircuitMatrixPlan,
b::BoundCircuit, work = CircuitMatrixWorkspace(plan, nm))The matrices of nm at the values of b, written into the storage nm already has. The patterns are the plan's and do not move, so only the stored values are rewritten: the nodal matrices and the mutual inductance matrix through their stamp plans into a scratch the size of one mode and then repeated, and the branch vectors directly. Each group of b must have the element type its matrix was built with, which the solver cache checks before it refills. Pass a CircuitMatrixWorkspace(plan, nm) to reuse scratch across calls; the default allocates scratch for this call. The returned CircuitMatrices shares its matrix storage with nm; value-dependent metadata is rebuilt.
This is the sweep's assembly: hbsolve! calls it at every point.
JosephsonCircuits.assemblematrices Method
assemblematrices(plan::CircuitMatrixPlan, b::BoundCircuit)The CircuitMatrices of a bound circuit, assembled against the fixed patterns of plan.
The assembly of numericmatrices and of the solvers: every stamp, the mutual inductances included, on the plan's patterns and resolved couplings and ports, so that only the values and the solver scale are read at an assembly. The numeric types are the bound circuit's.
JosephsonCircuits.assemblenodal! Method
assemblenodal!(nzval, seen, plan::NodalStampPlan, values)Accumulate the stamps of values into nzval against a fixed pattern.
Contributions to one position are summed in the order the components appear, the order in which sparse combines duplicate coordinates.
JosephsonCircuits.assemblenodal Method
assemblenodal(::Type{T}, plan::NodalStampPlan, values, Nmodes)The nodal matrix of values, repeated along the diagonal for Nmodes.
JosephsonCircuits.assemblerealjacobian! Method
assemblerealjacobian!(nzval::AbstractVector,
plan::StructureRealJacobianPlan, phimatrix::AbstractArray;
synchronize = true)Assemble the stored values of the real Jacobian into nzval from the Fourier coefficients of cos(phi(t)), using the circuit's structure rather than a precomputed gather. On a device the assembly kernel is synchronized before returning unless synchronize = false, for a caller which orders the work on the stream itself, as the transient step does.
JosephsonCircuits.assemblescattering! Function
assemblescattering!(A::SparseMatrixCSC, ssys::ScatteringStampSystem,
wmodes::AbstractVector, work::ScatteringWorkspace = ScatteringWorkspace())Add the frequency dependent constitutive entries of the scattering blocks at the signed mode frequencies wmodes into the values of the system matrix A: sign*im*w_m*scale*B[p,q](w_m) on the node flux columns and -C[p,q](w_m) on the auxiliary current columns, with the coefficients evaluated per block by evaluatehybrid! (which applies the negative frequency rule of each block, so the negative mode entries carry the complex conjugate data exactly as the conjugation of the conductance matrix does for resistors). The destination indices must have been set with setscatteringindexmap!. Thread safe when each thread has its own work and its own A: blocks are read only.
JosephsonCircuits.assemblesweep! Method
assemblesweep!(nzval::AbstractMatrix, plan::FrequencySweepPlan,
ws::AbstractVector)Assemble the stored values of the linearized system matrix at each signal frequency of ws into the corresponding column of nzval, which must have one row per stored entry and one column per frequency.
Every stored value is written, so nzval need not be zeroed first.
JosephsonCircuits.assemblesystemmatrix! Method
assemblesystemmatrix!(A::SparseMatrixCSC, lsys::HBLinearizedSystem,
wmodes::AbstractVector; conjugatepump::Bool = false,
scatteringwork = ScatteringWorkspace(),
table = providertable(lsys, wmodes))Assemble the linearized harmonic balance system matrix into A, which must share the sparsity structure of lsys.Asparse, at the mode frequencies wmodes, ws .+ lsys.wpumpmodes at the signal frequency ws. The frequency scaling and the negative frequency conjugation are applied per column from the mode index, without materializing system sized diagonals, and the frequency dependent components are added at their mode frequencies. With conjugatepump = true the complex conjugate of the pump modulation contribution is used, which for a circuit without scattering blocks is a similarity transformation of the transposed system, as below. The negative frequency mode entries of the linear term matrices are conjugated and any frequency dependent ones resolved, exactly as in the per-frequency loop of hblinsolve, which calls this function. Returns A.
The conjugated pump system is a diagonal similarity transformation of the transposed forward system,
A(conjugate pump) = D*transpose(A(pump))*inv(D),with D diagonal, equal to one on every node flux row. Nothing else contributes, so long as the circuit has no scattering blocks: the auxiliary rows of the promoted coupled inductors are already symmetric (see calcAmnaind); the linear term matrices are symmetric and mode diagonal, so the column indexed frequency scaling and conjugation of sparseaddconjsubst! are symmetric under transposition; and the transpose of the pump modulation contribution exchanges the mode pair, mapping each difference harmonic to its complex conjugate, which is the same as conjugating the pump. The hybrid rows of a ScatteringParameters do break it: their constant Kirchhoff couplings and frequency dependent constitutive entries exchange under transposition, and no diagonal D undoes that, so with blocks the two are different matrices.
The adjoint solutions the noise, quantum efficiency, commutation relation and adjoint node output calculations read are in every case the solutions of the transposed system: by the adjoint identity, the response at an output port to a source anywhere in the circuit is that source contracted against the transposed solution driven at the port. hblinsolve obtains them with trysolvetranspose! on the factorization of the forward system, which costs a pair of triangular solves rather than an assembly and a factorization at every signal frequency. Where the similarity holds, the conjugated pump assembly is the independent construction that equivalence is tested against. scatteringwork is the scratch of the scattering block evaluation, one per worker in a sweep, so that a frequency allocates nothing for it. table holds the values of the system's distinct frequency dependent functions at wmodes (see providertable), which a sweep fills once per frequency for the assembly and the noise waves alike; without it, it is filled here.
JosephsonCircuits.atfrequency Method
atfrequency(a, i)The port argument a at the frequency index i: a number is the same everywhere, a vector holds one value per port for every frequency, a matrix has one column per frequency, and a PortDiagonal is the diagonal matrix of its ports there.
JosephsonCircuits.autonne_takagi Method
autonne_takagi(M::AbstractMatrix{<:Real}; atol = 0, rtol = ...)Return a vector Λ and a unitary matrix W for input matrix M such that M == W*Diagonal(Λ)*transpose(W) where M is a symmetric real matrix M = transpose(M), to the tolerances atol and rtol as for a complex M; its symmetric part is factorized.
They are returned as the named tuple (Λ, W), as for a complex M, with Λ the magnitudes of the eigenvalues of M in decreasing order and each column of W the eigenvector times 1 or im, the square root of the sign of its eigenvalue (1 for a zero eigenvalue).
JosephsonCircuits.autonne_takagi Method
autonne_takagi(M::AbstractMatrix; atol = 0, rtol = ...)Return a vector Λ and a unitary matrix W for a symmetric complex input matrix M such that M == W*Diagonal(Λ)*transpose(W) where M satisfies M = transpose(M). Note that if M complex this means M is not Hermitian. M must be symmetric to the tolerances atol and rtol of isapprox (the default rtol is the square root of the machine epsilon of its element type, and zero when atol is given); its symmetric part (M + transpose(M))/2 is factorized.
They are returned as the named tuple (Λ, W), with Λ the singular values of M in decreasing order, as for a real M. W is U*sqrt(Z) for the singular value decomposition M = U*Diagonal(Λ)*V' and the unitary Z = U'*conj(V), whose square root is taken with its eigenvalues rotated away from the branch cut by optimum_eigenvalue_angle.
References
[1] A. M. Chebotarev and A. E. Teretenkov, “Singular value decomposition for the Takagi factorization of symmetric matrices,” Applied Mathematics and Computation, vol. 234, pp. 380–384, May 2014, doi: 10.1016/j.amc.2014.01.170. [2] M. Houde, W. McCutcheon, and N. Quesada, “Matrix decompositions in Quantum Optics: Takagi/Autonne, Bloch-Messiah/Euler, Iwasawa, and Williamson,” Can. J. Phys., vol. 102, no. 10, pp. 497–507, Oct. 2024, doi: 10.1139/cjp-2024-0070. [3] https://github.com/XanaduAI/thewalrus/pull/403
sourceJosephsonCircuits.auxcurrentscale Method
auxcurrentscale(Lscale)The scale of the auxiliary port current unknowns of the scattering blocks in the linearized system, one over the solver inductance scale (see calcsolverscale).
A node unknown is a flux and an auxiliary unknown is a current, and flux over current is an inductance, so this writes the two in the same units, which puts the auxiliary columns of the system on the scale of the nodal ones. The nonlinear solve carries the same relation on its node fluxes, since those are its Newton unknowns; the linearized solve carries it on the port currents, which nothing outside the solve reads. A circuit with no scale to take leaves the unknowns as they are.
sourceJosephsonCircuits.backtracking_linesearch! Method
backtracking_linesearch!(f!, F, xcandidate, x0, deltax, ϕ0, dϕ0dα;
ls = Backtracking(), correction = nothing, beta = 1.0,
Fbest = copy(F), ϕfullstep = nothing)Backtracking line search on the curvilinear trial path:
`x(α) = x0 + α*deltax - beta*α²*correction`with objective ϕ(α) = 0.5*||F(x(α))||², following Nocedal & Wright section 3.5 with the addition of a curvilinear path. The α² term is a correction to the approximate Jacobian, which improves convergence on strongly driven three wave mixing problems. Its α² scaling makes it vanish at α = 0 with its derivative, so it changes neither the merit function nor its slope at the starting point, and the Armijo condition is that of the straight path. correction is the Anderson acceleration (Anderson mixing) correction of nlsolve!. When correction == nothing or beta == 0 the path is the straight path x + α*deltax.
F holds the residual at x0, from which ϕ0 was computed, and Fbest is scratch: the search keeps there the residual of its best trial, starting from the residual at x0, and restores it into F when it ends without an accepted step. When ϕfullstep is given, F and xcandidate hold the full step instead, and Fbest must hold the residual at x0.
quadratic_trial_step performs a quadratic interpolation on the full-step data to estimate the trial step α at which the minimum of the merit function occurs. The full step data consists of the merit function value ϕ0 and derivative dϕ0dα at the starting point α=0 and the merit function value ϕfullstep at the full step α=1, evaluated first when the caller does not provide it. A full step which quadratic_trial_step returns as measured has passed the Armijo sufficient-decrease condition ϕα <= ϕ0 + c1*α*dϕ0dα and is returned.
Otherwise trial evaluations alternate with the cubic fits of cubic_trial_step until a trial satisfies the condition, which is returned, or maxbacktracks trials have been made, when the best of them is. The Armijo constant c1, the safeguards of the fits, the trial budget maxbacktracks and whether the fits are made at all are the fields of ls, a Backtracking. Without interpolation neither fit is made: the first backtrack is to α = 1/2 and every later one multiplies α by safeguardhigh, with the Armijo test at each trial.
This function always leaves xcandidate == x(α) and F holds the residual there (for α == 0 that is the residual at x0).
Returns (α, ϕα, accepted, backtracks):
accepted == true:αsatisfies the α-scaled Armijo conditionϕα <= ϕ0 + c1*α*dϕ0dα, andϕαis its measured objective value.accepted == false: maxbacktracks was reached.αis the best (lowest measured ϕ) trial found, which may still be a useful step; if no trial produced any decrease at all,α == 0andϕα == ϕ0.backtrackscounts the trial evaluations after the full step, so the total number off!residual evaluations is exactlybacktracks + 1: the failure path restores the best trial's residual from a copy saved when it was measured (Fbest, a caller-suppliable scratch buffer whose contents are clobbered), never by re-evaluating.
JosephsonCircuits.backwardjosephsontransposekernel! Method
backwardjosephsontransposekernel!(P, tbptr, tbnode, tbcoef, w, lptr,
lwide, gtscale)Transpose of the Josephson contribution of the backward map, one work item per frequency domain slot. Each item gathers the nodes which read its slot and writes its own entry of P, so the writes are disjoint and no atomic is needed.
Divides by the conjugate multiplicity in the same pass, which is the first half of the adjoint of applyfft!.
The imaginary part of a self-conjugate bin is deliberately not zeroed here. The pairing never sees it, so zeroing looks harmless, and in one dimension it is. In more than one it is wrong: the real part has to be taken after the transform along the remaining dimensions, not before, and the two differ as soon as the first-dimension zero-frequency slice has more than one element. The complex-to-real transform already discards exactly the right component, so the correct action here is none.
sourceJosephsonCircuits.backwardtermkernel! Method
backwardtermkernel!(out, bptr, bsrc, bcoef, phimatrix, kptr, kidx, kcoef,
xr, lptr, lwide)Evaluate the map from the frequency domain coefficients back to the node vector in the equivalent real representation, one work item per complex output index. Each work item gathers the coefficients of the Josephson branches incident to its node, scaled by the incidence matrix entry and Lscale/Lj, then gathers the one or two rows of the real form of the linear term matrix applied to xr, and writes the one or two real slots it owns. Those slots are disjoint across work items. Passing the kptrzero field of the plan as kptr switches the linear term off. See NonlinearTermPlan.
JosephsonCircuits.backwardtermkernelcomplex! Method
backwardtermkernelcomplex!(out, bptr, bsrc, bcoef, phimatrix, kptr, kidx,
kcoef, xc)The complex representation counterpart of backwardtermkernel!. Each work item owns one complex output entry, gathers the same segment of Josephson contributions and one row of the complex form of the linear term matrix, so the real slot bookkeeping of the real representation is not needed. Passing the cptrzero field of the plan as kptr switches the linear term off. See NonlinearTermPlan.
JosephsonCircuits.batchedinverse! Method
batchedinverse!(Dinv, D, F, backend, pivots, status)For each k, Dinv[:, :, k] becomes the inverse of D[:, :, k], with F scratch of the same size: a loop of pivoted dense LU solves on the host, which pivot into pivots, at least as long as a block; one batched call on a device (the CUDA extension), which keeps its pivots there. A singular block throws a SingularException on the host, and on a device sets the entry of its system in status, the device vector blocklu! reads once after its last supernode (a batch of one block, which cuSOLVER factorizes, throws at once).
JosephsonCircuits.batchedmul! Method
batchedmul!(C, A, B, alpha, beta, tA::Bool, backend)C[:, :, k] = alpha*op(A[:, :, k])*B[:, :, k] + beta*C[:, :, k] for every k, op the transpose when tA is set: a loop of mul! on the host, one strided batched GEMM on a device (the CUDA extension).
JosephsonCircuits.bathamplitude Method
bathamplitude(bath, w, dw)The peak amplitude 2 sqrt(hbar w dw/(2pi R)) of the cosine and sine Norton currents representing one quadrature pair of bath at the angular frequency w with the quadrature weight dw, both in rad/s. With the independent quadratures at variance nbar + 1/2 the current's variance over the band is (2 hbar w/R) coth(hbar w/2kT) dw/(2pi), Johnson's 4kT/R dw/(2pi) classically. A block channel's wave has the amplitude sqrt(hbar w dw/(2pi)).
JosephsonCircuits.bathfamily Method
bathfamily(block::LinearizedScattering, frequencies)The bath frequencies, angular in rad/s, for a pumped block as the ladders of its pump, one BathLadder each: the modes of a transient's noise are the signed frequencies w and -w, as the linearized solver's modes are its, and a block couples nothing between frequencies which are not a multiple of its pump apart, so the modes are grouped by ladder (see pumpladders) and each ladder gets the outputs its data covers with every input which feeds them.
Its noise is assembled, completed and read one ladder at a time (see pumpednoisematrices), so every pair term of the group is an entry of the matrix of one ladder and nothing of the block's noise is ever a matrix over all the bath frequencies, whose size would grow with the square of their number.
JosephsonCircuits.bindvalues Method
bindvalues(c::CompiledCircuit, values)A BoundCircuit from the flat value table values, the component values resolved with componentvaluestonumber: the values gathered into the per group arrays, each in the element type its group promotes to. A name the definitions did not give, a value which is neither a number nor symbolic, and a frequency dependent junction, mutual coupling or coupled inductor are refused naming their components.
The topology, the groups and the assembly plans do not depend on the values, so a sweep binds its values at each point and refills the matrices on the same plan, as long as each group keeps its element type.
sourceJosephsonCircuits.bloch_messiah_block Method
bloch_messiah_block(S::AbstractMatrix{<:Real})Return the Bloch-Messiah (Euler) decomposition O, D, Q of the symplectic matrix S = O*Diagonal(D)*Q where O and Q are orthogonal-symplectic matrices and Diagonal(D) is a symplectic-diagonal and positive definite matrix. This is also called the symplectic singular value decomposition (SVD). The matrices are symplectic with respect to the block symplectic form Ω.
This decomposition is unique up to permutations and or degeneracies of the Takagi-Autonne singular values.
The singular values are the same as the regular SVD, but the ordering of the singular values and order/signs of the factors are different, in order to make them orthogonal-symplectic.
References
[1] G. Cariolaro and G. Pierobon, “Reexamination of Bloch-Messiah reduction,” Phys. Rev. A, vol. 93, no. 6, p. 062115, Jun. 2016, doi: 10.1103/PhysRevA.93.062115. [2] G. Cariolaro and G. Pierobon, “Bloch-Messiah reduction of Gaussian unitaries by Takagi factorization,” Phys. Rev. A, vol. 94, no. 6, p. 062109, Dec. 2016, doi: 10.1103/PhysRevA.94.062109. [3] M. Houde, W. McCutcheon, and N. Quesada, “Matrix decompositions in Quantum Optics: Takagi/Autonne, Bloch-Messiah/Euler, Iwasawa, and Williamson,” Can. J. Phys., vol. 102, no. 10, pp. 497–507, Oct. 2024, doi: 10.1139/cjp-2024-0070.
sourceJosephsonCircuits.bloch_messiah_pair Method
bloch_messiah_pair(S::AbstractMatrix{<:Real})The pair ordered form of bloch_messiah_block: S, the factors and D are in pair order, and the factors symplectic with respect to the pair ordered symplectic form.
JosephsonCircuits.block_to_pair Method
block_to_pair(S::AbstractMatrix)Return the matrix S with its rows and columns in block order reordered to pair order.
JosephsonCircuits.block_to_pair Method
block_to_pair(r::AbstractVector)Examples
r = [:x1, :x2, :x3, :x4, :p1, :p2, :p3, :p4]
JosephsonCircuits.block_to_pair(r)
# output
8-element Vector{Symbol}:
:x1
:p1
:x2
:p2
:x3
:p3
:x4
:p4JosephsonCircuits.block_to_pair2 Method
block_to_pair2(S::AbstractMatrix)Return the matrix S with its rows and columns in block order reordered to pair order, as block_to_pair, by products with the permutation matrices R_block_to_pair.
JosephsonCircuits.block_to_pair2 Method
block_to_pair2(r::AbstractVector)Return the vector r in block order reordered to pair order, as block_to_pair, by a product with the permutation matrix R_block_to_pair.
JosephsonCircuits.block_to_pair_perm Method
block_to_pair_perm(n::Int)Return a vector p which permutes the block operator ordering into the pair operator ordering.
Return a 2n length vector p which permutes the block operator ordering r = [x1,...,xn,p1,...,pn] to the pair operator ordering r[p] = (x_1,p_1,...,x_n,p_n).
Examples
r = [:x1, :x2, :x3, :x4, :p1, :p2, :p3, :p4]
p = JosephsonCircuits.block_to_pair_perm(4)
r[p]
# output
8-element Vector{Symbol}:
:x1
:p1
:x2
:p2
:x3
:p3
:x4
:p4JosephsonCircuits.blockanalysis Method
blockanalysis(f::BlockFactorization, A::SparseMatrixCSC; blocksize,
backend = CPU(), nb = 1, refine = BLOCKREFINESTEPS)The SparseBlockFactorization of the pattern of A before its first numeric factorization: the symbolic analysis with node blocks of blocksize unknowns (the linearized solve passes its mode count), one node per supernode (blocksymbolic), and the blocks of nb systems of the pattern allocated on backend with the destinations of the stored entries in them. fillandfactorize! factorizes it from the values of a batch, as the device sweep does for each of its batches, and factorize from A's. Precision from f; Float32 factors of a double matrix refine against the double residual for at most refine steps (BLOCKREFINESTEPS, six, by default, until the residual stops halving, see refinedsolve!); refine = 0 leaves the solutions single precision solutions of the double system, computed entirely in single precision.
JosephsonCircuits.blockcontributions Method
blockcontributions(ssys)The positions of each block's contributions among those of the stamp system ssys, in their order, one vector per block, from one pass over them: what targetstampsystems takes of the block of a pair.
JosephsonCircuits.blockfactorbytes Method
blockfactorbytes(::Type{T}, keep::AbstractMatrix{Bool}, adj, order,
Nmodes::Integer, layout::ModeLayout)The bytes a BlockFactorization in precision T of the coupling mask keep will hold on the backend: the diagonal blocks, their inverses, the panels, the scratch of the largest blocks and the work vectors, over every cluster of the mask. Exact for the floating point storage the factorization allocates (the Int32 index maps are not counted), from the symbolic analysis alone, so a caller can decide whether the factors fit before building anything.
JosephsonCircuits.blocklu! Method
blocklu!(lu::BlockLU, backend)The right-looking block LU of the blocks lu holds, in place, over the batch: for each supernode in order, the pivoted dense LU of its diagonal block and the explicit inverse from it, the panel below scaled by that inverse, and the product of the scaled panel with the panel to the right subtracted from the later blocks it reaches. After this the panels and inverses are the factors. A singular diagonal block throws a SingularException, on a device once the last supernode is done (see batchedinverse!).
JosephsonCircuits.blocklu Method
blocklu(::Type{T}, sym, backend; nb = 1)Allocate the BlockLU of the symbolic structure sym in precision T on backend, nb systems deep, with its Schur schedule: a supernode's panel product lands, through index maps, in the diagonal block or a panel of each later supernode it reaches.
JosephsonCircuits.blocknodegraph Method
blocknodegraph(A::SparseMatrixCSC, blocksize::Integer)The node graph of a matrix whose unknowns come in contiguous blocks of blocksize (a trailing shorter block allowed): the slot lists of the nodes and the symmetric adjacency read off the pattern.
JosephsonCircuits.blocknoisecontractkernel! Method
blocknoisecontractkernel!The noise output waves of the scattering block channels, one work item per (channel, mode, right hand side).
The noise a block adds is a source in its auxiliary port current rows, so by the adjoint identity its contribution at an output port is that source contracted against those same rows of the adjoint solution: sqrt(abs(w)) sum_p L[p,c] i[p]. Nothing else of the solution is read, which is why the adjoint solutions of a circuit with dissipative blocks need not come back from the backend at all.
JosephsonCircuits.blocknoisefactorkernel! Method
blocknoisefactorkernel!The factor L of the commutator I - S S' of the noise wave of each dissipative scattering block definition at each mode frequency, one work item per (definition, mode), from tabulated or constant scattering data. The entries of factorentries are the first instances of the definitions, whose factors the other instances read.
The factorization is psdcholesky!, which the host path runs too, so the two agree on the channels themselves and not only on the sums over them. Its covariance is built from 2 n^3 interpolations rather than caching the n^2 scattering parameters, because a work item has nowhere to cache them and a block has few ports.
JosephsonCircuits.blockpairordinals Method
blockpairordinals(psc::CompiledCircuit, blockpairs)The ordinal among the scattering blocks of psc of the block each pair of blockpairs names, or zero where it names none, resolved as scatteringblockindex resolves a name, "<path>/port1" included, from one table of the blocks' paths.
JosephsonCircuits.blockresidual! Method
blockresidual!(R, lu::BlockLU, o, X, B, w, backend, transposed::Bool)R_k = B - A_k X_k for the batch, or B - transpose(A_k) X_k with transposed, from the matrix's own blocks o kept for the refinement, a batched dense product per block, in the matrix's precision, on the work arrays w of the right-hand side's width.
JosephsonCircuits.blocksensitivitystamp Method
blocksensitivitystamp(rows, cols, parameter)The SensitivityStamp skeleton of a scattering block parameter: the entries at rows and cols its instance's contributions reach (see targetstampsystems) with zero values, which each worker fills at each signal frequency (refreshblockstamps!). Kind :S carries no further frequency scaling, exactly as :Lj does.
JosephsonCircuits.blocksolve! Method
blocksolve!(X, F::SparseBlockFactorization, B; transposed = false)Overwrite X (n x W x nb) with the solutions of A_k X_k = B (or transpose(A_k) X_k = B) for the batch, B (n x W) shared by the batch or (n x W x nb) one per system: every operation a batched dense product over a whole block, the right-hand side's columns and the batch. Forward substitution through the scaled panels, back substitution through the panels and the inverses; for the transposed system the same factors read the other way round, (D ⊕ U)ᵀ first as a lower block triangular solve with the transposed inverses, then (I + L)ᵀ backward.
JosephsonCircuits.blockstampvals! Method
blockstampvals!(vals, dsys, wmodes, work, buf, position)Add to vals (the entries of a block parameter's stamp) the derivative of the block contribution at the signed mode frequencies wmodes: the values of the derivative system dsys (see targetstampsystems), whose block's data is dS/dtheta, with its hybrid coefficients the derivatives of B and C (see evaluatehybrid!), scattered through position. The instances of one parameter share a stamp, each through positions of its own. buf is scratch at least as long as the system's contributions.
JosephsonCircuits.blockstructure Method
blockstructure(::Type{T}, sys, Amatrixindices::Matrix,
Amatrixconjindices::Matrix, keep::AbstractMatrix{Bool},
Rbnm::SparseMatrixCSC, Nmodes::Integer, Nbranches::Integer,
Nfreq::Integer, layout::ModeLayout, singletons)The BlockStructure for the coupling mask keep: one ClusterBlocks per connected component of two or more modes of the retained coupling graph, over the circuit-node graph ordered by klunodeorder. singletons is the block diagonal preconditioner for the remaining modes, or nothing.
JosephsonCircuits.blocksymbolic Method
blocksymbolic(A::SparseMatrixCSC, blocksize::Integer)The symbolic structure (clustersymbolic) of the block factorization of the linearized solve: the node graph of A with blocksize unknowns per node (blocknodegraph), ordered by KLU, one node per supernode. The factorization and the memory estimates that choose it and size a device sweep's batches take it from here. Pivoting stays within a supernode's diagonal block, and a merged block, which the separators of a meshed circuit would form, can be ill conditioned at a frequency where the matrix is not, which costs the solution more digits than node by node elimination does; the preconditioner's clusters merge (amalgamate), since their accuracy costs only iterations.
JosephsonCircuits.blocksystembytes Method
blocksystembytes(::Type{T}, sym; refine = false, TA = T)The bytes one system of a SparseBlockFactorization in precision T holds, from the symbolic structure: blocks, panels, inverses, scratch, and the original blocks in TA when refining. What sizes the batch of a device sweep.
JosephsonCircuits.branchendpoints Method
branchendpoints(Rbn::SparseMatrixCSC, Nbranches::Int)The two nodes of every branch in the order the incidence matrix Rbn oriented it, as (from, to): branch b leaves from[b] and enters to[b]. Rbn carries -1 at a branch's source and 1 at its destination, and has no column for the ground node, which is node 1, so a branch with a terminal there keeps the initial value at that end.
One walk over the stored entries names the endpoints of every branch at once, which is where the mutual couplings read theirs from.
sourceJosephsonCircuits.branchnodesandsigns Method
branchnodesandsigns(Rbnm::SparseMatrixCSC, Nmodes::Integer,
Nbranches::Integer)Recover, for each branch, the list of (node, sign) pairs from the incidence matrix Rbnm = diagrepeat(Rbn, Nmodes) which converts node fluxes to branch fluxes. Verifies that Rbnm has the expected mode-diagonal structure (each entry connects a branch-mode to a node-mode of the same mode index, with the same value for every mode) and throws an error otherwise.
JosephsonCircuits.branchstampplan Method
branchstampplan(c::CompiledCircuit, group, edge2indexdict, Nbranches)Build the BranchStampPlan of a two terminal group.
JosephsonCircuits.buildcoupling Method
buildcoupling(plan::PreconditionerPlan, S::AbstractModeCoupling, sys,
factorization)The pattern P, the assembly plan and the values it writes for the coupling set S of the system sys, factorized by factorization: the triple a ModeCouplingPreconditioner holds, rebuilt when its coupling set grows. On a device backend the Jacobian is built transposed, because its stored order is then the row major order a device sparse matrix and a device direct solver want; on a host the assembly writes straight into the stored values of P. A block factorization eliminates the circuit graph with dense blocks over the clusters of the coupling set, and the modes left single by the block diagonal are handed to this same preconditioner with the empty coupling set and the backend's sparse factorization.
JosephsonCircuits.calcAmna Method
calcAmna(gaugeindices::Vector{Int}, Ntot::Int)The constant gauge fixing rows of the augmented harmonic balance system of hbnlsolve: a one on the diagonal for each index in gaugeindices, one per floating component of the static flux-stiffness graph and zero-frequency mode (see calcdcgaugeindices), in an Ntot square sparse matrix. Because the Kirchhoff current law equations of a floating component are consistent but redundant at DC whenever the direct current subsystem has a solution, which dcpinning checks, this term, a one on the diagonal for each gauge index, renders the system nonsingular while the reference node fluxes are driven to exactly zero and all original equations remain satisfied.
The augmented state is the (Nnodes-1)*Nmodes node fluxes followed by the auxiliary variables of the mutually coupled inductor branches (calcAmnaind) and of the scattering block port currents, with the mode index fastest. These equations are linear, so the matrix is constant during the nonlinear solve and is its own contribution to the Jacobian.
JosephsonCircuits.calcAmnaind Method
calcAmnaind(coupledbranches::Vector{Int}, Lb::SparseVector,
Mb::SparseMatrixCSC, Rbn::SparseMatrixCSC, Nmodes::Int,
auxoffset::Int, Ntot::Int, Lscale)Calculate the constant sparse matrix which augments the harmonic balance system with auxiliary branch current variables for the mutually coupled inductors. For each coupled branch b and mode m an auxiliary variable u is added at index auxoffset + (r-1)*Nmodes + m (with r the position of b in coupledbranches) together with the branch flux constitutive equation
sum_p Rbn[b,p]*phi_p - sum_k (L[b,k]/Lscale)*u_k = 0,
where L[b,k] is the branch inductance matrix (the branch self inductances on the diagonal and the mutual inductances Mb off the diagonal), and the auxiliary variable enters the Kirchhoff current law equation of each node p of the branch with coefficient Rbn[b,p]. In the scaled units of the nonlinear solver the auxiliary variable is u = Lscale*i/phi0 with i the physical branch current in the orientation of the incidence matrix; the linearized solver uses Lscale = 1 and unscaled branch currents. All entries are real and frequency independent. Eliminating the auxiliary variables recovers exactly the coupled part of the nodal inverse inductance stamp, Lscale*Rbn'*inv(L)*Rbn (unit tested as a Schur complement identity), so the formulation is algebraically equivalent to the nodal one wherever the branch inductance matrix is invertible. Its entries remain bounded as the coupling coefficient approaches one, and unlike the nodal formulation it remains well posed at perfect coupling (|k| = 1) whenever the surrounding circuit determines the branch currents. Coupling between inductors sharing a single branch is rejected with an informative error (see mnacoupledbranches); a coupling matrix which leaves some branch current combination physically undetermined would produce a singular system caught at factorization.
JosephsonCircuits.calcCjIcmean Method
calcCjIcmean(Ic::AbstractVector, C::AbstractVector)The critical current and the capacitance of the one WRSPICE jj model the junctions of a netlist share, from the critical current Ic and the shunt capacitance C of each junction branch: the mean Icmean of the critical currents, and Cj = CjoIc*Icmean with CjoIc the smallest ratio of a branch's capacitance to its critical current, clamped to the WRSPICE maximum of 0.99e-6. Every junction then takes its critical current and the capacitance the model gives it, and the rest of its shunt capacitance is a separate capacitor, which is why the smallest ratio is the one. A junction without shunt capacitance, and critical currents below 0.02 or above 50 times the mean, which the model cannot span, are refused. Returns (Cj, Icmean).
Examples
julia> Ic = JosephsonCircuits.LjtoIc.([1.0e-9, 1.1e-9]);
julia> JosephsonCircuits.calcCjIcmean(Ic, [1.0e-12, 1.2e-12])
(3.1100514965930345e-13, 3.141466158174782e-7)
julia> Ic = JosephsonCircuits.LjtoIc.([2.0e-9, 1.1e-9]);
julia> JosephsonCircuits.calcCjIcmean(Ic, [1.0e-12, 1.2e-12])
(2.2955141998662873e-13, 2.3187012119861487e-7)JosephsonCircuits.calcCnoise! Method
calcCnoise!(Cnoise, S)Calculate the symmetrized noise covariance (I - S S')/2 a passive network emits in its vacuum, for a scattering matrix in the field ladder operator basis. Overwrites Cnoise with output.
JosephsonCircuits.calcCnoise Method
calcCnoise(S::AbstractMatrix{T}) where {T}Return the symmetrized noise covariance a passive linear network with the scattering parameter matrix S emits in its vacuum, (I - S S')/2 by Bosma's theorem, in quanta: the half photon of the vacuum times the commutator I - S S'. The network can be lossy and non-reciprocal; in equilibrium at a temperature where a mode's occupation is nbar it emits (nbar + 1/2)(I - S S').
Examples
julia> JosephsonCircuits.calcCnoise(JosephsonCircuits.S_splitter!(zeros(Complex{Float64},2,2)))
2×2 Matrix{ComplexF64}:
0.0+0.0im 0.0+0.0im
0.0+0.0im 0.0+0.0im
julia> S = rand(Complex{Float64},3,3);isapprox(JosephsonCircuits.calcCnoise(S),([1.0 0 0;0 1 0;0 0 1].-S*S')./2)
trueJosephsonCircuits.calcSsensitivity! Method
calcSsensitivity!(Ssensitivity, stamps, dAop, dA, dAphin, phin,
phinadjoint, S, gamma, beta, work, wmodes, Nmodes)Calculate the derivative of the scattering matrix with respect to a relative (logarithmic) perturbation of each component value, p -> r*p evaluated at r = 1, at the pump operating point, with the adjoint method. Overwrites Ssensitivity. stamps are the fixed operating point stamps of each component (see SensitivityStamp); dAop holds, per component, the values of the operating point contribution to dA in the sparsity structure of the linearized system matrix, or is empty when the operating point is held fixed; dA and dAphin are scratch of the size of the system matrix and the solution, and work is the worker's StampContraction for these stamps.
Differentiating the linearized system A*phi = b, whose source terms do not depend on any component value, gives dphi = -inv(A)*dA*phi, so with the adjoint solutions lam of the transposed system driven by the output functionals of calcsensitivityscaling!,
dS[(j,n),(i,m)] = -gamma[(j,n)]*beta[(i,m)]
*transpose(lam[:,(j,n)])*dA*phi[:,(i,m)].The adjoint source vectors are the source vectors of the forward problem scaled by im*w_n, which is folded into gamma, so phinadjoint, the solution of the transposed system already computed for the noise and quantum efficiency calculations, is used directly. A stamp's part is factored: its values fill its pattern (StampPattern), the pattern multiplies the rows of phin at its columns, and one dense product with the rows of phinadjoint at its rows gives the contraction, so a stamp of nnz entries over nr rows costs nnz*NPM + nr*NPM^2 rather than nnz*NPM^2.
When the perturbed component is a port's reference impedance, the termination it owns or a port which owns none (whose stamp has no entries), the wave normalization of calcinputwaves! moves as well, contributing the additional closed form term -(portscale/2)*(P*(S+I) + (S+I)*P) with P the projector onto that port and portscale one in the relative form (the design parameter form carries (dZport/dp)/Zport), which is exact for constant real port impedances.
JosephsonCircuits.calcSsensitivityreverse! Method
calcSsensitivityreverse!(Ssensitivity, rev::ReverseSensitivity, lsys,
phin, phinadjoint, gamma, beta, cache,
bufs::ReverseSensitivityBuffers)Add the contribution of the shift of the pump operating point to the scattering parameter sensitivities, contracting in the reverse order so that the cost per component is a sparse inner product rather than a product against a matrix which is dense on the sparsity structure of the linearized system.
For each pair of output and input port modes (a,b), the transpose of the Josephson scatter of addjosephsonterm! gives
transpose(lam_a)*dAop_k*phi_b
= sum_s P[s]*dcos_k[s] + Q[s]*conj(dcos_k[s]),with P and Q accumulated over the scatter lists of the plan. Since dcos_k is the directional derivative of the Fourier coefficients of cos(phi_b(t)) along the operating point shift (cosdirectionalderivative!), that is a linear functional of the shift, and with
alpha = T(P), gam = conj(T(Q)), eta = -sin(phi_b(t)).*(alpha + gam)with T the transposed transform (applyffttranspose! through rev.fftplan), and its covector is the transpose of the branch flux map applied to eta. Finally the implicit function theorem gives dx_k = -inv(J)*dF_k, so pushing that covector through the transposed Jacobian once per output pair leaves a sparse inner product with dF_k for each component. The cost per signal frequency is (Nports*Nmodes)^2 transposed solves, independent of the number of components, instead of one product against the full sparsity structure per component. The solves are batched into multi right hand side calls whose column count is set by the REVERSESENSITIVITYCHUNKBYTES budget, which amortizes the per-call overhead of the sparse triangular solves while keeping the per batch work matrices memory bounded.
The transform of the pump harmonic grid is applied one dimension at a time, so this supports any number of pump tones.
sourceJosephsonCircuits.calc_noise_covariances Method
calc_noise_covariances(scattering_parameters; noise = true)Return the noise covariances (I - S*S')/2 of a passive network at every frequency of its scattering parameters S (Bosma's theorem), or, with noise = false, an empty array of their type, which stands for that covariance where networks are connected: see PassiveNetwork.
JosephsonCircuits.calcblockresidualsensitivity Method
calcblockresidualsensitivity(op::HBOperatingPoint, psc, blockpairs)The derivative of the harmonic balance residual with respect to each scattering block design parameter of blockpairs = [(blockpath, parameterindex, derivativeblock)], at the operating point, in the real representation of the augmented residual (one column per pair, matching the columns calcresidualsensitivity produces for lumped pairs).
A block enters the nonlinear system as a constant matrix folded into the inverse inductance augmentation, so it moves the pump operating point and its residual derivative is +dA_block/dtheta applied to the converged state: the linear term enters the residual with a plus sign, and unlike the lumped :invL case – whose minus encodes d(1/L)/d(ln L) = -1/L, the derivative of the component law, not a residual sign – the block derivative is computed directly. The derivative matrix is stamped as the linearized stamps are (see blockstampvals!), on a stamp system rebuilt for the pump mode grid with the geometry the operating point already determines: the augmented dimension is the state length and the block auxiliary variables occupy its tail.
With an explicit direct current block the columns are in canonical coordinates, as the lumped ones are (see calcresidualsensitivity): the harmonic column gathered and masked by the rows the block writes over, plus the derivative of the block's own zero frequency rows B0 (scale dv) - C0 i (see addblockdc!), which depend on the parameter through S(0) when the block reads its zero frequency behavior from its data rather than stating a dcmodel.
JosephsonCircuits.calcbranchtimedomainmap Method
calcbranchtimedomainmap(sys, Nmodes, NLj)The matrix of the map from the branch fluxes of one Josephson junction to its physical time domain branch flux, with the real and the imaginary part of each mode as separate columns. The map is the same for every junction, because the packing and the inverse transform act on each junction independently, so it is built once by transforming unit branch fluxes with phivectortomatrix! and applyifft!, which keeps the conjugate mode bookkeeping inside the functions which define it. This is the transpose of the linear map from the unknowns to the time domain branch fluxes, restricted to one junction.
JosephsonCircuits.calccm! Method
calccm!(cm, S, w, noise::NoiseReduction; comp = similar(cm))Overwrite cm with the bosonic commutation relations of a scattering matrix S in the field ladder operator basis: the sum of abs2 along each row, each column weighted by the sign of its mode frequency w[(j-1) % length(w) + 1], plus the signed noise power noise.signed of the NoiseReduction noise of the noise scattering matrix of the dissipative elements at each output. Represents energy conservation. The sum is compensated, and comp is its scratch, one entry per row.
Examples
julia> nonoise = JosephsonCircuits.NoiseReduction(zeros(2), zeros(2));
julia> JosephsonCircuits.calccm!(zeros(2), Complex{Float64}[3/5 4/5;4/5 3/5], [1], nonoise)
2-element Vector{Float64}:
1.0
1.0
julia> JosephsonCircuits.calccm!(zeros(2), [1 1e-100 2e-100 1;1 0 0 1], [1, -1], nonoise)
2-element Vector{Float64}:
3.0e-200
0.0
julia> JosephsonCircuits.calccm!(zeros(2), [3/5 4/5;4/5 3/5], [-1, 1], nonoise)
2-element Vector{Float64}:
0.28000000000000014
-0.28000000000000014
julia> w = [1, -1]; n = JosephsonCircuits.noisereduction!(JosephsonCircuits.NoiseReduction(zeros(2), zeros(2)), [1 2; 3 4; 5 6; 7 8], w, fill(0.5, 4));
julia> JosephsonCircuits.calccm!(zeros(2), [1 2;3 4], w, n)
2-element Vector{Float64}:
-35.0
-47.0JosephsonCircuits.calcdcgaugeindices Method
calcdcgaugeindices(floatingcomponents::Vector{Vector{Int}},
wmodes::Vector, Nmodes::Int)Return the indices of the node flux variables to which a gauge fixing equation will be added. For each floating component of the static flux-stiffness graph from calcstaticfluxcomponents and each mode with zero frequency (DC), one index is returned, corresponding to the lowest-numbered node of the component (the reference node). The DC flux of a floating component only enters the equations through differences of node fluxes within the component, so exactly one constraint per component and zero-frequency mode removes the gauge degree of freedom without overconstraining the system. The DC node flux reported as zero depends on the node ordering (the sorting keyword of compile): the reference is the lowest-numbered node of each component after sorting. All physical quantities are gauge independent and unaffected by this choice.
Examples
julia> JosephsonCircuits.calcdcgaugeindices([[2],[3,4]],[0.0,2pi*4e9],2)
2-element Vector{Int64}:
1
3
julia> JosephsonCircuits.calcdcgaugeindices([[2],[3,4]],[2pi*4e9,2pi*8e9],2)
Int64[]JosephsonCircuits.calcfreqs Method
calcfreqs(Nharmonics::NTuple{N,Int}, Nw::NTuple{N,Int}, Nt::NTuple{N,Int})Calculate the dimensions of the DFT or RFDT in the frequency domain and the time domain given a tuple of the number of harmonics. Eg. 0,w,2w,3w would be 3 harmonics. Also calculate the possible modes and their coordinates in the frequency domain RDFT array. See also calcfreqsrdft and calcfreqsdft.
JosephsonCircuits.calcfreqsdft Method
calcfreqsdft(Nharmonics::NTuple{N,Int})Calculate the dimensions of the DFT in the frequency domain and the time domain given a tuple of the number of harmonics. Eg. 0,w,2w,3w would be 3 harmonics. Also calculate the possible modes and their coordinates in the frequency domain DFT array.
Arguments
Nharmonics: is a tuple of the number of harmonics to calculate for each frequency.
Returns
Frequencies: A simple structure to hold time and frequency domain information for the signal for a single node. SeeFrequencies.
JosephsonCircuits.calcfreqsrdft Method
calcfreqsrdft(Nharmonics::NTuple{N,Int})Calculate the dimensions of the RDFT in the frequency domain and the time domain given a tuple of the number of harmonics. Eg. 0,w,2w,3w would be 3 harmonics. Also calculate the possible modes and their coordinates in the frequency domain RDFT array.
Arguments
Nharmonics: is a tuple of the number of harmonics to calculate for each frequency.
Returns
Frequencies: A simple structure to hold time and frequency domain information for the signal for a single node. SeeFrequencies.
JosephsonCircuits.calcimpedance Method
calcimpedance(c, type, w)The impedance at the mode frequency w of a component of value c and type type: :R, :C, :L, or :P for a port, whose impedance is its reference impedance. The value is resolved at w by substitutefreq and impedance conjugates it at a negative frequency.
Examples
julia> JosephsonCircuits.calcimpedance(30.0,:C,1.0)
0.0 - 0.03333333333333333im
julia> JosephsonCircuits.calcimpedance(30.0,:L,1.0)
0.0 + 30.0im
julia> JosephsonCircuits.calcimpedance(30.0,:R,1.0)
30.0 + 0.0im
julia> JosephsonCircuits.calcimpedance(30.0,:C,-1.0)
-0.0 + 0.03333333333333333im
julia> JosephsonCircuits.calcimpedance(30.0,:L,-1.0)
-0.0 - 30.0im
julia> JosephsonCircuits.calcimpedance(30.0,:R,-1.0)
30.0 + 0.0im
julia> JosephsonCircuits.calcimpedance(JosephsonCircuits.FrequencyDependent(w->30*w),:L,2.0)
0.0 + 120.0im
julia> JosephsonCircuits.calcimpedance(JosephsonCircuits.FrequencyDependent(w->30*w),:L,-2.0)
-0.0 - 120.0im
julia> JosephsonCircuits.calcimpedance(JosephsonCircuits.FrequencyDependent(w->30*w),:R,-2.0)
60.0 + 0.0imJosephsonCircuits.calcinputwaves! Method
calcinputwaves!(inputwave, sourcecurrents, portindices, portimpedances,
componenttypes, wmodes)The incident power wave of each port mode (i-1)*Nmodes+j, driven by the source current sourcecurrents[(i-1)*Nmodes+j], as defined in (except in units of sqrt(photons/second) instead of sqrt(power)) K. Kurokawa, "Power Waves and the Scattering Matrix", IEEE Trans. Micr. Theory and Tech. 13, 194–202 (1965) doi: 10.1109/TMTT.1965.1125964
A port is a source current s in parallel with its impedance Z, so the current it drives into the circuit is I = s - V/Z and the incident wave kval*(V + Z*I)/2 is kval*Z*s/2, whatever the solution; kval is portwavescale.
Examples
julia> JosephsonCircuits.calcinputwaves!(zeros(ComplexF64, 1), ComplexF64[1],
[1], [50.0], [:P], [1.0])
1-element Vector{ComplexF64}:
3.5355339059327378 + 0.0imJosephsonCircuits.calcjunctionrelations Method
calcjunctionrelations(componenttypes::Vector{Symbol},
nodeindices::Matrix{Int}, junctioncprs::AbstractDict,
edge2indexdict::Dict, Ljb::SparseVector)The JunctionRelations of the junctions of a circuit, ordered by the nonzero entries of the branch inductance vector Ljb, which is the order every solver indexes its junction axis by. Returns nothing when every junction is the sinusoidal Josephson one, which is the case the solvers evaluate as plain sin and cos.
junctioncprs is keyed by the flat component index, as it is on a CompiledCircuit; a junction is placed by the branch its two nodes make, the same way the assembly places its inductance.
JosephsonCircuits.calcmodefreqs Method
calcmodefreqs(w::NTuple{N},modes::Vector{NTuple{N,Int}})Calculate the frequencies of the modes given a tuple of fundamental frequencies and a vector of tuples containing the mixing products and harmonics.
Examples
julia> JosephsonCircuits.calcmodefreqs((1., 1.1),[(0, 0), (1, 0), (2, 0), (0, 1), (1, 1), (2, 1)])
6-element Vector{Float64}:
0.0
1.0
2.0
1.1
2.1
3.1JosephsonCircuits.calcnodefluxsensitivity Method
calcnodefluxsensitivity(op::HBOperatingPoint, dFr::AbstractMatrix;
factorization = KLUfactorization())Solve dx/dr = -inv(J)*(dF/dr) for the residual sensitivities dFr of calcresidualsensitivity, with one factorization of sensitivityjacobian at the operating point: the canonical Jacobian when a direct current block is active, the harmonic one otherwise. Returns a matrix whose columns are dx/dr for each component, in the complex representation of the augmented state.
JosephsonCircuits.calcnodesorting Method
calcnodesorting(uniquenodevector::Vector{String};sorting=:number)The permutation which sorts the node names in uniquenodevector according to sorting, with the ground node "0" moved to the front in every case. Throws an ArgumentError if there is no ground node.
Keywords
sorting = :number: parse the names as integers and sort numerically. Throws anArgumentErrorif a name is not an integer.sorting = :name: sort the names as strings, so that"101"sorts before"11".sorting = :none: keep the names in order of first appearance, apart from moving ground to the front.
Examples
julia> JosephsonCircuits.calcnodesorting(["30","11","0","2"];sorting=:name)
4-element Vector{Int64}:
3
2
4
1
julia> JosephsonCircuits.calcnodesorting(["30","11","0","2"];sorting=:number)
4-element Vector{Int64}:
3
4
2
1
julia> JosephsonCircuits.calcnodesorting(["30","11","0","2"];sorting=:none)
4-element Vector{Int64}:
3
1
2
4JosephsonCircuits.calcnoisecovariance! Function
calcnoisecovariance!(Cnoise, Snoise, channelnoise,
work = similar(Snoise))The added noise covariance at the output ports,
Cnoise[i,i'] = sum_c channelnoise[c] Snoise[c,i] conj(Snoise[c,i'])which is the Y of the Gaussian channel whose X is the scattering matrix: the map takes an input covariance to X sigma X' + Y. Snoise describes the transformation and channelnoise the state of each channel, its symmetrized noise nbar + 1/2 in quanta, so this is where the two meet and where a temperature shows up.
Formed as one matrix product, transpose(Snoise)*work with work the noise scaled conjugate of Snoise, as the device sweep forms it; work is scratch of the size of Snoise, which a sweep holds in its workspace.
JosephsonCircuits.calcoperatingpointstamps Method
calcoperatingpointstamps(op::HBOperatingPoint, lsys, dx)Calculate the contribution of a shift of the pump operating point to the derivative of the linearized system matrix, for each column of dx. The linearized system matrix depends on the operating point only through the Fourier coefficients of cos(phi_b(t)) of the Josephson junction branch fluxes, so the contribution is the directional derivative of those coefficients along the operating point shift (cosdirectionalderivative!) scattered into the system matrix through the same plan which assembles it (addjosephsonterm!), so the mode coupling and its truncation agree exactly. Returns a vector of nonzero value vectors aligned with the sparsity structure of the system matrix, which are frequency independent.
JosephsonCircuits.calcoutputwaves! Function
calcoutputwaves!(outputwave, phin, sourcecurrents, portindices,
portimpedances, nodeindices, componenttypes, wmodes, table = nothing)The outgoing power wave of each port mode (the rows) in each solution column of the node fluxes phin, kval*(V - conj(Z)*I)/2 in the units of calcinputwaves!, with the port voltage V of calcportvoltage and the port current I = s - V/Z.
sourcecurrents[r,k] is the source current s of the port mode r in the solution column k. A sweep drives one port mode per column, so its source currents are the Diagonal of portsourcecurrents: a port which shares a node with the driven one carries no source current of its own. nothing means that no port carries a source, which is how the noise ports are read from the adjoint solutions. A port value which depends on the frequency, given as its row of a linearized system's table of the values of its frequency dependent functions, is read from table at each mode (see providertable).
Examples
A port of 50 ohms from node 2 to ground at the mode frequency 1, driven by a unit source current. Across a short the wave is reflected with the opposite sign; into an open circuit, V = Z*s, it is reflected whole; and the same voltage with no source is the wave the port carries away.
julia> phishort = ComplexF64[0;;]; phiopen = ComplexF64[50/im;;];
julia> args = ([1], [50.0], [2; 1;;], [:P], [1.0]);
julia> JosephsonCircuits.calcoutputwaves!(zeros(ComplexF64, 1, 1), phishort,
ComplexF64[1;;], args...)
1×1 Matrix{ComplexF64}:
-3.5355339059327378 + 0.0im
julia> JosephsonCircuits.calcoutputwaves!(zeros(ComplexF64, 1, 1), phiopen,
ComplexF64[1;;], args...)
1×1 Matrix{ComplexF64}:
3.5355339059327378 + 0.0im
julia> JosephsonCircuits.calcoutputwaves!(zeros(ComplexF64, 1, 1), phiopen,
nothing, args...)
1×1 Matrix{ComplexF64}:
7.0710678118654755 + 0.0imJosephsonCircuits.calcphiindices Method
calcphiindices(frequencies::Frequencies{N},
conjsymdict::Dict{CartesianIndex{N},CartesianIndex{N}})Return the indices which map the elements of the frequency domain vector to the corresponding elements of the frequency domain array. Also return the indices conjsourceindices whose data should be copied from the vector to conjtargetindices in the array then complex conjugated.
Arguments
frequencies: the retained frequencies, whose coordinates are the positions of the vector's elements in the frequency domain array.conjsymdict: the conjugate symmetric pairs of coordinates of the array (seeconjsym); a retained coordinate with a pair has its conjugate written at the paired coordinate.
Returns
indexmap: the indices which map the elements of the frequency domain vector elements to the corresponding elements of the frequency domain arrayconjsourceindices: data should be copied from hereconjtargetindices: data should be copied to here and conjugated
Examples
freq = JosephsonCircuits.Frequencies{2}((4, 3), (5, 7), (9, 7), CartesianIndex{2}[CartesianIndex(2, 1), CartesianIndex(4, 1), CartesianIndex(1, 2), CartesianIndex(3, 2), CartesianIndex(2, 3), CartesianIndex(1, 4), CartesianIndex(2, 6), CartesianIndex(3, 7)], [(1, 0), (3, 0), (0, 1), (2, 1), (1, 2), (0, 3), (1, -2), (2, -1)])
conjsymdict = Dict{CartesianIndex{2}, CartesianIndex{2}}(CartesianIndex(1, 2) => CartesianIndex(1, 7), CartesianIndex(1, 3) => CartesianIndex(1, 6), CartesianIndex(1, 4) => CartesianIndex(1, 5))
JosephsonCircuits.calcphiindices(freq, conjsymdict)
# output
([2, 4, 6, 8, 12, 16, 27, 33], [6, 16], [31, 21])freq = JosephsonCircuits.calcfreqsrdft((4,3));
truncfreq = JosephsonCircuits.truncfreqs(freq;dc=false,odd=true,even=false,maxintermodorder=3)
noconjtruncfreq = JosephsonCircuits.removeconjfreqs(truncfreq)
conjsymdict = JosephsonCircuits.conjsym(noconjtruncfreq)
JosephsonCircuits.calcphiindices(noconjtruncfreq,conjsymdict)
# output
([2, 4, 6, 8, 12, 16, 27, 33], [6, 16], [31, 21])JosephsonCircuits.calcportvoltage Method
calcportvoltage(key1, key2, phin, wmodes, Nmodes, j, k)The port voltage of mode j for the drive column k of the node flux solution phin, at the port between the node indices key1 and key2 (with 1 meaning ground): the node flux difference times im*wmodes[j], with the sign of the canonical orientation of the port branch when one node is ground.
JosephsonCircuits.calcqe! Method
calcqe!(qe, S, noise::NoiseReduction; inputnoise,
vout = similar(qe, size(S, 1)), comp = similar(vout))Overwrite qe with the quantum efficiency matrix of a scattering matrix S in the field ladder operator basis: abs2(S[i,j]) over twice the symmetrized noise at output i (see outputnoise!), which every input brings in its own state, inputnoise[j], its nbar + 1/2, and the noise channels of the NoiseReduction noise add. The input j counts in its own state too, so a warm source lowers the efficiency of a measurement of its signal even through a lossless circuit. vout and comp are the scratch of that noise and its compensated sum, one entry per row; vout holds the noise on return.
Examples
julia> nonoise = JosephsonCircuits.NoiseReduction(zeros(2), zeros(2)); vacuum = [0.5, 0.5];
julia> JosephsonCircuits.calcqe!(zeros(2, 2), [3/5 4/5;4/5 3/5], nonoise; inputnoise = vacuum)
2×2 Matrix{Float64}:
0.36 0.64
0.64 0.36
julia> JosephsonCircuits.calcqe!(zeros(2, 2), Complex{Float64}[3/5 4/5;4/5 3/5], nonoise; inputnoise = vacuum)
2×2 Matrix{Float64}:
0.36 0.64
0.64 0.36
julia> n = JosephsonCircuits.noisereduction!(JosephsonCircuits.NoiseReduction(zeros(2), zeros(2)), [1 4;2 5;3 6], [1], fill(0.5, 3));
julia> JosephsonCircuits.calcqe!(zeros(2, 2), [1 2;3 4], n; inputnoise = vacuum)
2×2 Matrix{Float64}:
0.0526316 0.210526
0.0882353 0.156863
julia> JosephsonCircuits.calcqe!(zeros(2, 2), [1.0 0.0; 0.0 1.0], nonoise; inputnoise = [1.5, 0.5])
2×2 Matrix{Float64}:
0.333333 0.0
0.0 1.0JosephsonCircuits.calcqeideal Method
calcqeideal(S::AbstractArray)Calculate the ideal (best possible) quantum efficiency for each element of a scattering matrix. See also calcqeideal!.
Examples
julia> JosephsonCircuits.calcqeideal([3/5 4/5;4/5 3/5])
2×2 Matrix{Float64}:
1.0 1.0
1.0 1.0
julia> JosephsonCircuits.calcqeideal(Complex{Float64}[3/5 4/5;4/5 3/5])
2×2 Matrix{Float64}:
1.0 1.0
1.0 1.0JosephsonCircuits.calcresidualsensitivity Function
calcresidualsensitivity(op::HBOperatingPoint, psc, nm,
sensitivityindices, alphas = ones(Complex{Float64}, length(sensitivityindices)))Calculate the derivative of the harmonic balance residual with respect to a relative (logarithmic) perturbation of each component value, at the operating point. alphas scales the direction of each column: the derivative of column k is with respect to alphas[k]*r applied to component sensitivityindices[k], which is how a design parameter's direction alpha = (dv/dp)/v is folded into the residual derivative of a component (see designsensitivities). Combined with the implicit function theorem applied to F(x, r) = 0 in the equivalent real representation,
dx/dr = -inv(J)*(dF/dr),with J the exact real Jacobian retained by hbnlsolve, this gives the derivative of the operating point itself (see calcnodefluxsensitivity). Returns a sparse matrix whose columns are dF/dr for each component, in the real representation of the augmented residual: each component touches only its own rows (its nodes and modes, or a junction branch's Kirchhoff rows), so the storage scales with the touched entries rather than with Nstate*Ncomponents.
The residual is affine in C, 1/R and 1/L, so those parameter derivatives are that component's own contribution to the linear term applied to the converged state, with a sign, built from the shared classification of componentstamp with the same nondimensionalization and negative frequency conjugation the solver applies. The Josephson junction term is the residual's own sine contribution restricted to that junction.
Note that the auxiliary unknowns of the modified nodal analysis formulation, the currents of the mutually coupled inductors and of the scattering block ports, are scaled by the solver scale (see calcsolverscale), which itself depends on the port impedances, so for a port's termination the auxiliary rows of the returned derivative differ from a finite difference of a re-solve by that change of normalization. The node flux rows, which are the physical quantity and the only rows the linearized system depends on, are unaffected.
JosephsonCircuits.calcscatteringmatrix! Method
calcscatteringmatrix!(S, inputwave::AbstractVector, outputwave::AbstractMatrix)The scattering matrix of a sweep, whose solution column k is driven at the port mode k alone, so that outputwave = S * Diagonal(inputwave): each column of outputwave divided by its input wave.
Examples
julia> inputwave = [1.0, 2.0]; outputwave = [im/sqrt(2) sqrt(2); 1/sqrt(2) im*sqrt(2)];
julia> S = zeros(ComplexF64, 2, 2); JosephsonCircuits.calcscatteringmatrix!(S, inputwave, outputwave); S
2×2 Matrix{ComplexF64}:
0.0+0.707107im 0.707107+0.0im
0.707107+0.0im 0.0+0.707107imJosephsonCircuits.calcscatteringmatrix! Method
calcscatteringmatrix!(S, inputwave::Vector, outputwave::Vector)The scattering matrix is defined as outputwave = S * inputwave.
Examples
julia> inputwave=[1.0,0.0];outputwave=[im/sqrt(2), 1/sqrt(2)];S = zeros(Complex{Float64},2,2);JosephsonCircuits.calcscatteringmatrix!(S,inputwave,outputwave);S
2×2 Matrix{ComplexF64}:
0.0+0.707107im 0.0+0.0im
0.707107+0.0im 0.0+0.0imJosephsonCircuits.calcsensitivityscaling! Method
calcsensitivityscaling!(gamma, beta, inputwave, sourcecurrents,
portindices, portimpedances, componenttypes, wmodes, Nmodes)Calculate the scalars which convert the derivative of the node fluxes into the derivative of the scattering parameters. Writing the output wave of calcoutputwaves! as a linear functional of the node fluxes, the part which depends on them is (1/2)*kval*(1 + conj(Z)/Z)*im*w_n*(phi_n1 - phi_n2), and the scattering parameters divide by the input wave, so
dS[(j,n),(i,m)] = gamma[(j,n)]*beta[(i,m)]
*(dphi[node1,(j,n)] - dphi[node2,(j,n)])with gamma = (1/2)*kval*(1 + conj(Z)/Z)*im*w_n/s_{(j,n)} and beta = 1/inputwave[(i,m)]. The node flux difference is contracted with the adjoint solution by calcSsensitivity!, which is why the im*w_n factor of the port voltage is folded into gamma here: it is exactly the factor relating the adjoint source vector to the source vector of the forward problem.
s_{(j,n)} is the source current of the port's own unit drive, sourcecurrents of portsourcecurrents, ±1 depending on whether the canonical orientation of the port branch in the incidence matrix agrees with the node order of the port component. The adjoint solution is the solve against the source columns of bnm, which carry the canonical branch orientation, while the output functional differences the node fluxes in the component node order, so their ratio enters the contraction. Without it the sensitivities of any output at a port written with its nodes in the opposite order of the branch orientation would have the wrong sign, even though the scattering parameters themselves, which use s consistently in both the input and the output waves, would be correct.
JosephsonCircuits.calcsensitivitystamps Method
calcsensitivitystamps(sensitivityindices, psc, nm, lsys, phimatrix,
coupledbranches, Nmodes)Build the SensitivityStamp of each component in sensitivityindices. The classification and the entries of a capacitor, an inductor or a resistor come from sensitivitystamp, which is shared with the residual derivatives of calcresidualsensitivity, so the two grids cannot disagree on which components are supported or how they are built; the node rows lead the augmented state, so the entries need no padding. A port which owns no termination has no entries. The Josephson junction stamp is the pump modulated contribution of that junction alone, obtained by scattering the Fourier coefficients of cos(phi(t)) of that junction through the same plan (addjosephsonterm!) which assembles the system matrix, so the mode coupling and its truncation agree exactly.
JosephsonCircuits.calcsolverscale Method
calcsolverscale(w, componenttypes::Vector{Symbol}, vvn::Vector,
portimpedances::Vector, Lscale)Calculate the inductance scale used to nondimensionalize the nonlinear harmonic balance system: the Kirchhoff current law rows are multiplied by this scale (divided by the reduced flux quantum), the Josephson terms enter as ratios of this scale to the junction inductances, and the auxiliary variables of the modified nodal analysis formulation are branch currents in units of the corresponding natural current scale. The scale is
Lscale = Z0/w0
with Z0 the geometric mean of the constant real port reference impedances (falling back to the geometric mean of all constant real resistors and then to 50 ohms when none are present) and w0 the geometric mean of the absolute values of the nonzero drive frequencies. With this choice the natural current unit is phi0*w0/Z0, the entries of the scaled system are dimensionless and of order one for circuits driven near their characteristic impedance and frequency, the auxiliary branch currents have magnitudes comparable to the node fluxes, in circuits without inductors too, and the residual tolerance atol becomes independent of the unit system of the problem. Because the scale multiplies rows only, and the auxiliary variables are internal, the returned node fluxes and all physical quantities are unchanged in exact arithmetic.
When every drive frequency is zero the mean inductance Lscale is returned instead, since no frequency scale is available.
JosephsonCircuits.calcsourcecurrent Method
calcsourcecurrent(key1, key2, bnm, Nmodes, j, k)The source current of mode j for the drive column k of the source terms bnm, at the port between the node indices key1 and key2 (with 1 meaning ground): the difference of the two nodes' currents, halved, or the one node's current with the sign of the canonical orientation of the port branch when the other is ground.
JosephsonCircuits.calcsources Method
calcsources(modes, sources, portindices, portnumbers, nodeindices,
edge2indexdict, Lscale, Nnodes, Nbranches, Nmodes)The source vector in the branch basis: for each source, the current at its port and mode scaled by Lscale/phi0, at the index of that port's branch and mode; zero elsewhere. A source at a port the circuit does not have, at a mode the truncation removed, or at the zero frequency mode with a complex amplitude is an ArgumentError.
Examples
modes = [(0,), (1,)]
sources = [(mode = (0,), port = 1, current = 0.0005), (mode = (1,), port = 1, current = 1.0e-10)]
portindices = [1]
portnumbers = [1]
nodeindices = [2 2 2 2 0 2 3 4 3 3; 1 1 1 1 0 3 4 1 1 1]
edge2indexdict = Dict((1, 2) => 1, (3, 1) => 2, (1, 3) => 2, (4, 1) => 3, (2, 1) => 1, (1, 4) => 3, (3, 4) => 4, (4, 3) => 4)
Lscale = 1.005e-9 + 0.0im
Nnodes = 4
Nbranches = 4
Nmodes = 2
JosephsonCircuits.calcsources(modes, sources, portindices, portnumbers,
nodeindices, edge2indexdict, Lscale, Nnodes, Nbranches, Nmodes)
# output
8-element Vector{ComplexF64}:
1526.8637851180192 + 0.0im
0.0003053727570236038 + 0.0im
0.0 + 0.0im
0.0 + 0.0im
0.0 + 0.0im
0.0 + 0.0im
0.0 + 0.0im
0.0 + 0.0imJosephsonCircuits.calcspicesortperms Method
calcspicesortperms(variabledict::Dict{String,Vector{String}})The permutation which sorts the variables of each type of a rawfile, by the name and the node parsespicevariable reads from each: by name, and for a name by node, the numbered nodes in numerical order before the nodes named by words, which keep their order. So a rawfile may mix nodes named by numbers and by words, and v(2) comes before v(10).
Examples
julia> JosephsonCircuits.calcspicesortperms(Dict("V" => ["v(10)", "v(out)", "v(2)", "v(1)"]))["V"]
4-element Vector{Int64}:
4
3
1
2JosephsonCircuits.calcstaticfluxcomponents Method
calcstaticfluxcomponents(componenttypes::Vector{Symbol},
nodeindices::Matrix{Int}, vvn::Vector, Nnodes::Int)Return the connected components of the static flux-stiffness graph which do not contain the ground node, as a vector of vectors of "one indexed" node indices (so 1 is the ground node and does not appear in the output). The graph has the circuit nodes as vertices and an edge for every linear inductor and every Josephson junction whose value provides static (zero frequency) flux stiffness: finite numeric values contribute an edge, while a non-finite numeric value does not. Symbolic values are assumed to provide finite, nonzero static stiffness; a symbolic element whose zero-frequency stiffness vanishes or diverges will break this function. Resistors and capacitors contribute no edges because they provide no static flux stiffness in the node flux basis. Mutual inductances also contribute no edges because they couple branch fluxes without providing a galvanic connection. With the coupled branches represented by auxiliary branch current variables (see calcAmnaind), a singular coupling matrix (a perfectly coupled pair, |k| = 1) does not add flux null directions: the constitutive equations constrain the branch fluxes rather than freeing them, so this graph classification of the flux gauge freedom remains sound. Any degeneracies which exist at perfect coupling live in the branch current space (a branch current combination which the surrounding circuit leaves physically undetermined) and produce a singular system caught at factorization. Mutual coupling between inductors sharing a single branch is rejected up front (see mnacoupledbranches).
The DC flux of each returned "floating" component is defined only up to a common shift (a gauge degree of freedom). The modified nodal analysis formulation adds one gauge fixing equation per floating component and zero-frequency mode, see calcdcgaugeindices. A net direct current injected into a floating component is carried by the explicit average voltage block when the component has a conductive path to somewhere that can absorb it; only a component with no such path has no solution, which dcpinning refuses.
Examples
julia> JosephsonCircuits.calcstaticfluxcomponents([:P,:R,:C,:Lj,:C],[2 2 2 3 4;1 1 3 4 1],[1,50.0,1e-13,1e-9,1e-12],4)
2-element Vector{Vector{Int64}}:
[2]
[3, 4]
julia> JosephsonCircuits.calcstaticfluxcomponents([:P,:R,:L],[2 2 2;1 1 1],[1,50.0,1e-9],2)
Vector{Int64}[]
julia> JosephsonCircuits.calcstaticfluxcomponents([:P,:R,:L],[2 2 2;1 1 1],[1,50.0,Inf],2)
1-element Vector{Vector{Int64}}:
[2]JosephsonCircuits.candeviceevaluate Method
candeviceevaluate(ssys)Whether every block of a stamp system has data a kernel can evaluate, which is tabulated or constant. A callable provider is an arbitrary Julia function and stays on the host.
sourceJosephsonCircuits.canonicaldim Method
canonicaldim(L::CompositeLayout)The length of the canonical state.
sourceJosephsonCircuits.canonicalfj Method
canonicalfj(fjreal!, work::CanonicalWork, Jint, plan)Wrap an internal coordinate residual and Jacobian closure for a direct solve method: the residual in canonical coordinates, and the canonical Jacobian filled through plan.
The matrix is filled rather than replaced, because the solver factorizes the one it was handed. Its pattern is fixed – the internal pattern plus the direct current block, neither of which moves between iterations – and the plan is built from it once.
sourceJosephsonCircuits.canonicaljacobian! Method
canonicaljacobian!(plan::CanonicalJacobianPlan, Jint::SparseMatrixCSC)Fill the plan's matrix from an internal Jacobian and return it.
The flux block is Jint as it is, since the internal state is the first block of the canonical one. What is added is the explicit direct current block and its couplings, in the same places the residual adds them: the resistor current the average voltages drive into the zero frequency nodal rows, the transport rows and the block currents they carry across a component boundary, and each block's own zero frequency row in place of the i = 0 the stamp wrote. A reference row is a replacement rather than an addition, which is why the internal entries landing in it are dropped when the plan is built rather than zeroed here.
The matrix-free product is the reference this is checked against: for every unit vector the two must agree exactly, which is a sharper test than any finite difference of the residual would be.
sourceJosephsonCircuits.canonicaljacobianplan Method
canonicaljacobianplan(Jint::SparseMatrixCSC, work::CanonicalWork)Build the CanonicalJacobianPlan for an internal Jacobian pattern.
Only the pattern of Jint is read, not its values, so the plan is valid for every point the solve visits. It stops being valid if that pattern moves, which it must not. The direct current block's entries are those of its matrix form, dcupdate, which is read off the residual, so the Jacobian and the residual agree by construction.
JosephsonCircuits.canonicaljvp Method
canonicaljvp(jvpreal!, work::CanonicalWork)Wrap an internal coordinate Jacobian vector product so it takes and returns canonical vectors.
sourceJosephsonCircuits.canonicalresidual Method
canonicalresidual(fjreal!, work::CanonicalWork)Wrap an internal coordinate residual and Jacobian closure so it takes and returns canonical vectors.
sourceJosephsonCircuits.canonicalresidual Method
canonicalresidual(dF::SparseMatrixCSC, keep::Vector{Float64}, N)The harmonic residual derivative columns dF in the N canonical coordinates of the direct current block: the gather copies the harmonic rows, which lead the canonical vector, and the rows the block replaces rather than adds to are masked out by keep (dckeep). Linear in the stored entries of dF; the block's own dependence on the parameters is added by the caller.
JosephsonCircuits.canonicalresult! Method
canonicalresult!(xr, Fr, u, Fc, work)The outcome of a solve in the canonical coordinates of an explicit direct current block: its state u and residual Fc scattered back into the real harmonic state xr and residual Fr, and the canonical state returned on the host, which is the point the whole system is differentiated at and whose average voltages are the direct current solution. The block currents beside the voltages stay in the state, where the operating point and the sensitivities read them.
JosephsonCircuits.cayley_transform Method
cayley_transform(Omega, M)The Cayley transform (I + Omega*M)*inv(I - Omega*M), which takes Omega*M of the Lie algebra of the group preserving the form Omega to a member of that group: a symplectic matrix for the symplectic form and a symmetric M, a pseudo-unitary one for an indefinite Hermitian form and a skew-Hermitian M, as the random matrices of these groups are made.
JosephsonCircuits.checkblockcontract Method
checkblockcontract(block::ScatteringParameters, S, V, w; name = nothing)Hold the data of block at the angular frequency w to what the block declares, and throw an ArgumentError saying where it does not. S is the block's scattering matrix at w and V the covariance its NoiseCovariance states there, either nothing where it is not known:
the data is finite;
a stated covariance is Hermitian, no entry of
V - V'larger than the covariance'satoltimes its largest entry, or than itsatolfor a covariance of entries below one;it is at least what the commutation relations require of the block, the smallest eigenvalue of
V - K/2and ofV + K/2withK = I - S S'(seequantumnoisemargin) no lower than-atolwith the covariance'satol, unless it is completed to them;a block declared
Losslessis unitary, no entry ofI - S S'(seeunitaritydeviation) larger than the block'satol;any other block which does not state its noise is passive, the smallest eigenvalue of
I - S S'(seepassivitymargin) no lower than-atolwith the block'satol.
w is nothing for data which is the same at every frequency, and name is the block's instance in a circuit; both are for the message. The construction of a block holds every sample its data stores to this contract, and a solver holds the data it evaluates to it, so the same data is given the same verdict wherever it is read.
JosephsonCircuits.checkblockdeclarations Method
checkblockdeclarations(ssys::Union{Nothing,ScatteringStampSystem}, w,
wpumpmodes)Hold every block of ssys which does not convert to what it declares (see checkblockcontract), to its own atol, at the frequencies the sweep solves at, every signal frequency at every pump mode, where its construction could not: wherever a callable is evaluated, beyond the knots of a table, and wherever a block which states its noise is read, since its covariance and its scattering matrix meet in the commutation relations, which construction checks only at a sample holding both. Throws where the data is not what the block declares: a block which is not passive unless it states its noise, one declared Lossless which is not unitary, or a covariance less than the commutation relations require.
Each definition is checked once, whatever its instances. Runs at every solve, whether or not a noise output is asked for: a block is accepted or refused on its declaration and not on the outputs. A pumped block is checked by checkpumpedblockmodels.
JosephsonCircuits.checkblockpair Method
checkblockpair(block, derivative, name)Refuse a block pair, for the block instance name, whose block or derivative is not a ScatteringParameters: the derivative is stamped in the block's place, and only an ordinary block states one (see designblockjacobian); a pumped block (LinearizedScattering) has none.
JosephsonCircuits.checkcachekwargs Method
checkcachekwargs(kwargs)Validate the solver keywords an hbcache stores for every solve. x0 and reuse are the cache's own to manage and are refused, as is keyedarrays = true, since the state is kept as plain vectors (false is accepted); so are returnsystem = true and debugJacobian = true, whose solves return the system rather than a solution; so is method = Staged(), which the compiled circuit solve does not take; and so is any keyword that solve does not accept, which would otherwise fail at the first hbsolve! with a method error.
JosephsonCircuits.checkcomponentvaluesdefined Method
checkcomponentvaluesdefined(componentnames::Vector, vvn::Vector)Check that every circuit component value resolved: a value which is still a name, one the circuit definitions circuitdefs do not give, or a symbolic value with a variable they do not define, is reported in an ArgumentError naming its component and the names it depends on. A frequency dependent value is a closure of the frequency, resolved per frequency by freqsubst, and passes. Called by hbnlsolve and hblinsolve before any computation, and by the binding of the values to the circuit when a name is left, so a forgotten definition fails immediately with the actual cause.
Examples
julia> JosephsonCircuits.checkcomponentvaluesdefined(["P1","R1"], Any[1, FrequencyDependent(w -> 1/(w*50.0))])
julia> try JosephsonCircuits.checkcomponentvaluesdefined(["P1","R1"], Any[1, :R2]) catch e; occursin("R1 has the value", sprint(showerror, e)) end
trueJosephsonCircuits.checkcoupledloss Method
checkcoupledloss(psc::CompiledCircuit, vvn)Refuse the noise outputs of a circuit in which a mutual inductor, or an inductor it couples, has a lossy (complex) value. The noise channel of a lossy inductance is a source across its own terminals, normalized by its own impedance. The loss of a coupled inductance sits in its branch of the coupled group, and its noise would enter as correlated sources at the terminals of every branch the group couples, which these channels do not model. The scattering parameters of such a circuit are solved exactly.
sourceJosephsonCircuits.checkissymbolic Method
checkissymbolic(a)Whether a is a symbolic value of the Symbolics extension, which adds the methods, rather than a number: without the extension no value is.
Examples
julia> JosephsonCircuits.checkissymbolic(1.0)
falseJosephsonCircuits.checkjunctioncurrents Method
checkjunctioncurrents(nl::NonlinearHB, psc::CompiledCircuit)The check checkjunctiondc of the junctions of a converged solution with a zero frequency mode, from its node fluxes: the junction phases on the time grid of its transforms, and the mean of their sine. A continuation, whose stage solves leave the check to the outcome, runs it once on its outcome with this.
JosephsonCircuits.checkjunctiondc Function
checkjunctiondc(sintd::AbstractArray, junctionbranches, branchnames,
sinusoidal = nothing; atol = 1e-2)Warn about a Josephson junction carrying nearly its critical current at zero frequency.
The static flux partition treats a junction of finite inductance as a short at zero frequency, which puts its two terminals in one component and is what lets the transport rows be the component sum of the nodal equations. That is true of a junction in the zero voltage state and false of one which is running, and the difference is whether the junction can carry the direct current asked of it: the branch current is Ic*sin(phi), so its zero frequency part is Ic times the time average of sin(phi), and no zero voltage state exists once that average would have to exceed Ic.
A junction whose current-phase relation is a PolynomialCPR is skipped: the bound below is the one of the sinusoidal relation, and what a polynomial does past the range it was fitted on is the user's to judge.
The solver cannot report the failure itself. sin is bounded, so the average it finds is always a fraction of one, and a circuit which has no periodic solution converges to the nearest thing which is one rather than announcing that it does not exist. What can be reported is the approach: a junction whose direct current is within a percent of its critical current is at the edge of the partition's assumption, and a result there should be checked against a run at a lower drive.
This is a heuristic about the operating point and not a proof of dynamic stability, which harmonic balance does not decide.
sourceJosephsonCircuits.checknoform Method
checknoform(form::Symbol, what::AbstractString)Reject a form for a provider which is not a callable. How a function is called means nothing for data which is already stored.
JosephsonCircuits.checkpumpconjugates Method
checkpumpconjugates(blocks::Vector{StampedScatteringBlock}, wmodes)Refuse a pumped block of blocks which converts, with an entry above its tolerance, the conjugate of one retained mode of a pump solve into another, the two frequencies of wmodes summing to a harmonic of its pump: the pump solve's linear term is complex linear in the retained modes and does not carry a term in their conjugates, so with a source the operating point would be wrong. Called for every solve with a source, whether its operator is new or reused.
JosephsonCircuits.checkpumpedblock Method
checkpumpedblock(block::LinearizedScattering, wmodes, K, name, at)
checkpumpedblock(block::LinearizedScattering, rows, cols, K, name, at)Check the noise model of a pumped block over the signed mode frequencies wmodes coupled by the harmonics K, or over the output modes rows fed by the input modes cols (see pumpednoisematrices): a declared Lossless requires J - S J S' to vanish there, to the block's atol, and a stated NoiseCovariance requires V - K/2 and V + K/2 to be positive semidefinite, to the block's atol or the covariance's, whichever is larger, relative to the square of the largest entry of S, and a covariance must have finite, Hermitian entries, to the same tolerance of its own largest entry. Throws otherwise, naming the block name and the frequency at.
The covariance a completed noise model states is held to its entries like any other, since the completion repairs a covariance and does not stand in for one: what it adds is the negative part of a Hermitian matrix, which is not defined for data that is neither. It is held to them over the whole domain the completion reads, the modes of each ladder padded by the noise model's multiples of the pump frequency (see paddedladder), and not over the modes of the solve alone, since that is the matrix the negative part is taken of; the completion then reads data this has passed. Only the positive semidefiniteness a completed model establishes is left unchecked, so such a block reads its stated covariance alone and never assembles the scattering matrix it would be completed against.
JosephsonCircuits.checkpumpedblockmodels Method
checkpumpedblockmodels(ssys::Union{Nothing,ScatteringStampSystem}, w,
wpumpmodes)Check what every pumped block of ssys declares, its losslessness or its stated covariance, over the modes of the solve at each signal frequency (see checkpumpedblock), and throw where it is not met. The sweep's modes are the one place the multi-mode matrices of a pumped block are known, and the family its noise is completed over. Runs at every solve, whether or not a noise output is asked for, since a lossless pumped block emits nothing only if it is lossless: a block is accepted or refused on its declaration and not on the outputs. A block whose covariance is completed has what it states checked for finite, Hermitian entries and the relations it meets by construction left alone. Each definition is checked once, whatever its instances.
JosephsonCircuits.checkpumpedblocks Method
checkpumpedblocks(p::TransientProblem, frequencies)Check the noise model of every pumped block of p over the family of the bath frequencies, angular in rad/s, the signed frequencies as its outputs with every input which feeds them (see bathfamily), a declared Lossless or a stated NoiseCovariance (see checkpumpedblock), and throw where one is not met: the pair terms of the noise are read from this family. A fitted block, whose covariance is completed to the commutation relations of its filters, meets them by construction and has what it states checked for finite, Hermitian entries; a block built from filters by hand is checked as its data.
JosephsonCircuits.checkstaticstiffnessvalues Method
checkstaticstiffnessvalues(componenttypes::Vector{Symbol}, vvn::Vector)Check that every linear inductor and Josephson junction has a finite, nonzero numeric value (or a symbolic value), and throw an ArgumentError otherwise. Symbolic values are accepted under the documented assumption that their zero-frequency stiffness is finite and nonzero (the analysis will fail otherwise), see calcstaticfluxcomponents.
Examples
julia> JosephsonCircuits.checkstaticstiffnessvalues([:P,:R,:L],[1,50.0,1e-9])JosephsonCircuits.checksweepoptions Method
checksweepoptions(w, nbatches, psc, backend, factorization,
temperature, sensitivitynames, sensitivitypairs,
sensitivityblockpairs, nsensitivityparameters, sensitivitymode,
returnSsensitivity)Refuse the inputs and options of the sweep which do not need the pump before anything is built: hblinsolve checks them first, and hbsolve before it solves the pump. Refused are signal frequencies which are not finite or none at all, fewer than one batch, a temperature which is not finite and nonnegative, an unknown sensitivitymode, sensitivity pairs without nsensitivityparameters or beside sensitivitynames, a CUDSSFactorization for a sweep on the host, a QRfactorization, whose factors have no transposed solve (trysolvetranspose!) for the outputs which read the noise, the sensitivities or the adjoint node outputs, and, when the sensitivities are asked for, a component named for one which is not a capacitor, an inductor, a resistor or a junction, where a pair may also name a port which owns no termination.
JosephsonCircuits.circuitmatrixplan Method
circuitmatrixplan(c::CompiledCircuit; Nmodes = 1)Build the CircuitMatrixPlan of a compiled circuit. The plan depends on neither the values nor their types.
The conductance plan covers the resistors and the port owned environments together, because an environment is realized as an ordinary resistor.
sourceJosephsonCircuits.circuitnodegraph Method
circuitnodegraph(pairptr, pairrow, invLnm::SparseMatrixCSC,
Gnm::SparseMatrixCSC, Cnm::SparseMatrixCSC, Nmodes::Integer,
nnodes::Integer)The adjacency lists of the circuit-node graph: two nodes are adjacent when a junction pair table entry or a stored entry of the linear term matrices couples them. This is the graph the block factorization eliminates.
sourceJosephsonCircuits.circuitorder Method
circuitorder(sys, Rbnm::SparseMatrixCSC, Nmodes::Integer,
Nbranches::Integer, layout::ModeLayout)The circuit-node graph of the system and KLU's elimination order of it, the two symbolic ingredients a block factorization and its memory prediction share.
sourceJosephsonCircuits.circuittopology Method
circuittopology(componenttypes, nodeindices, Nnodes)
circuittopology(branchvector, Nnodes)The CircuitTopology of the branch carrying components listed by componenttypes and nodeindices, or of the branches branchvector given as (node1, node2) tuples, over Nnodes nodes with ground being node 1; see extractbranches for which components make a branch.
The branches are the edges of the undirected graph of those endpoints, in ascending order of their endpoints, oriented from the lower to the higher node index. A component whose two terminals are the same node is a branch with no incidence entries: it carries its value and couples no node.
sourceJosephsonCircuits.circuitvariables Function
circuitvariables(a)The variables of a symbolic value of the Symbolics extension, which defines the methods, for the check of the values to name.
sourceJosephsonCircuits.clusterblocks Method
clusterblocks(::Type{T}, modes, adj, order, Nmodes::Integer,
layout::ModeLayout, backend; tree = eliminationtree(adj, order))The ClusterBlocks of one cluster, its storage allocated on backend in precision T: the block LU, a batch of one, of the symbolic block structure clustersymbolic finds for modes on the circuit-node graph adj under the node order, with the natural slots its blocks are assembled from. tree is the elimination of the graph, shared by the clusters of one graph.
JosephsonCircuits.clustersolve! Method
clustersolve!(x::AbstractVector, C::ClusterBlocks, r::AbstractVector,
backend)Overwrite the cluster's slots of x with the solution of the cluster's factorized operator against the cluster's slots of r; the other slots of x are untouched. The gather by the elimination order, the substitutions of substitute! and the scatter back, a batch of one.
JosephsonCircuits.clustersymbolic Method
clustersymbolic(modes, adj, order, Nmodes::Integer, layout::ModeLayout;
tree = eliminationtree(adj, order))The symbolic block structure of one cluster, on the host and without allocating any factor storage: the fundamental supernodes (amalgamate) of the elimination tree of the circuit-node graph adj under the node order, restricted to the real-layout slots of modes, the positions of every supernode, its panel rows after fill, and the offsets the Schur updates scatter through. clusterblocks allocates from it and blockfactorbytes sizes it. The elimination tree (eliminationtree) depends on the graph and the order alone, so a caller structuring several clusters of one graph computes it once.
JosephsonCircuits.columnindices Method
columnindices(A::DeviceValuedSparseMatrix)The compressed sparse row column indices of A, which are the row indices of the transpose it stores.
JosephsonCircuits.commutationmargin Method
commutationmargin(V::AbstractMatrix, K::AbstractMatrix)The smallest eigenvalue of V - K/2 and of V + K/2, which is nonnegative when the symmetrized noise covariance V meets the commutation relations of the commutator K: V + K/2 and V - K/2 then factor into the channels of either kind (see NoiseCovariance).
JosephsonCircuits.compare Method
compare(x,y)Compare two values for the tests: isequal, except that floating point arrays are compared with a tolerance (comparearray), the solver result structures are compared field by field (comparestruct), and the solver diagnostics are ignored.
JosephsonCircuits.comparearray Method
comparearray(x::AbstractArray{T},y::AbstractArray{T}; rtol = 1e-6) where TWhether two arrays have the same size and differ in the 2-norm by at most rtol times the larger of their norms, so that the comparison holds the same digits whatever the scale of the values, and an array compares equal to zero only when it is zero.
Examples
julia> JosephsonCircuits.comparearray([1,2],[1,2,3])
false
julia> JosephsonCircuits.comparearray([1,2],[1,2,])
true
julia> JosephsonCircuits.comparearray([3e-8, 4e-8], [0.0, 0.0])
false
julia> JosephsonCircuits.comparearray([3e-8, 4e-8], [3e-8, 4e-8*(1 + 1e-9)])
trueJosephsonCircuits.comparestruct Method
comparestruct(x,y)Compare two structures of the same type field by field with compare, which compares floating point arrays with a tolerance and ignores the solver diagnostics.
Examples
julia> JosephsonCircuits.comparestruct(JosephsonCircuits.NoiseReduction([1.0], [2.0]),JosephsonCircuits.NoiseReduction([1.0], [2.0]))
true
julia> JosephsonCircuits.comparestruct(JosephsonCircuits.warmup(),JosephsonCircuits.warmup())
true
julia> JosephsonCircuits.comparestruct(nothing,nothing)
true
julia> JosephsonCircuits.compare(nothing,nothing)
true
julia> t = JosephsonCircuits.CircuitTopology(Dict((1, 2) => 1, (3, 1) => 2, (1, 3) => 2, (2, 1) => 1), JosephsonCircuits.SparseArrays.sparse([1, 2], [1, 2], [1, 1], 2, 2), 2);JosephsonCircuits.compare(t,t)
trueJosephsonCircuits.completecovariance Method
completecovariance(V, K)The symmetrized covariance V completed to the commutation relations of the commutator K: V + neg(V - K/2) + neg(V + K/2) with neg the negative part, which makes V - K/2 and V + K/2 positive semidefinite, so that the channels formed from them exist (see NoiseCovariance); each addition is positive semidefinite and vanishes where V already meets the relations. For V = 0 it is |K|/2, the least total noise a Gaussian channel with the map of K can add for its output to obey the commutation relations, the least in the trace, which is the Ymin of the quantum optics functions in the basis of the modes; for a stated V the addition is sufficient and not in general the least. The negative part of a matrix is not that of its parts, so a pumped block is completed over a padded ladder (see completedcovariance).
JosephsonCircuits.completedcovariance Method
completedcovariance(block::LinearizedScattering, rows, cols)The covariance of a pumped block whose noise model is completed, over the output modes rows fed by the input modes cols of a solve: the covariance the block states, completed to the commutation relations (see completecovariance) over the ladder of the rows padded by the noise model's padding multiples of the pump frequency on either side, with every input which feeds it, and restricted to the rows, so that the block's noise is one model whatever modes a solve keeps, to the precision of the padding; plus the vacuum of the inputs which feed the rows and are not among cols, S_c S_c'/2 for the scattering S_c from them, which a solve without those modes traces out, so that the covariance meets the commutator of the rows over the inputs the solve has.
Every row a solve asks for is completed, including one the block's data does not reach, which scatters nothing and so absorbs everything and carries the vacuum its commutator requires, as the stamp of the block takes it. The block couples nothing between frequencies which are not a multiple of the pump apart, so the rows are completed one ladder at a time (see pumpladders), the negative part of a matrix of independent blocks being the negative part of each; a block which does not convert couples nothing along a ladder either and needs no padding around a row.
JosephsonCircuits.complex_to_real! Method
complex_to_real!(xr, xc, isreal) -> xrComplex -> real. The imaginary part of a real mode is never read.
sourceJosephsonCircuits.complex_to_real Method
complex_to_real(A, rowlayout, collayout) -> SparseMatrixCSC{T,Ti}Real form of x -> A*x under the row layout of its output and the column layout of its input, so that complex_to_real(A, rl, cl) * complex_to_real(x, cl.isreal) == complex_to_real(A*x, rl.isreal), with the index type Ti of A. Runs one O(nnz) pass to size the output, then one to fill it.
JosephsonCircuits.complextorealkernel! Method
complextorealkernel!(xr, xc, lptr, lwide)Contract the complex representation of a node vector into the equivalent real one, one work item per complex entry. The imaginary part of a self conjugate mode is never read. The one or two real slots each work item writes are disjoint from every other's, so this is conflict free. The inverse of realtocomplexkernel!. See NonlinearTermPlan.
JosephsonCircuits.componentindex Method
componentindex(c::CompiledCircuit, name)The flat table index of the component named name, a Symbol or a String. A name which is not in the circuit is an ArgumentError naming it. This is the one place a name becomes an index, so every entry point refuses an unknown one the same way.
JosephsonCircuits.componentlookups Method
componentlookups(coupledbranches, Ljb)Constant time lookups for componentstamp, built once per stamp table rather than searched per component: the set of mutually coupled branches and the ordinal of a junction branch within Ljb.nzind. Without these the classification repeats linear searches per component, which becomes quadratic over a large sensitivity set.
JosephsonCircuits.componentnports Method
componentnports(c)The number of ports of a multiport component: the ports of a ScatteringParameters or a LinearizedScattering. Part of the connector protocol with nterminals and hasports.
JosephsonCircuits.componentstamp Method
componentstamp(idx::Integer, psc::CompiledCircuit, nm::CircuitMatrices,
lookups, Nmodes::Integer)Classify the component at index idx for sensitivity analysis and build its raw one-component stamp, without any solver scaling, negative frequency conjugation, or padding, which the callers apply for their own grids. Returns a named tuple (kind, rows, cols, vals, junction):
kind = :C,:Gor:invL:rows,colsandvalsare the entries of the component's capacitance, conductance or inverse inductance matrix over the node flux unknowns, ground dropped and the mode fastest, in the order a compressed sparse column matrix stores them, andjunctionis zero;kind = :Lj: there are no entries, andjunctionis the ordinal of the Josephson junction within the junction branch vectornm.Ljb.
The entries are the ones the stamp plans of the system matrices (nodalstampplan and inverseinductanceplan) give a single component, written from its own two terminals: its value on the diagonal of each of its nodes and its negative between them, a conductance being the reciprocal of the resistance, formed after the sign as the plan forms it, and an inverse inductance that of the inductance. So a stamp costs a constant, one to four entries per mode, whatever the size of the circuit.
This is the single definition of which components are supported: :C, :L, :R and :Lj with numeric values. Mutually coupled inductors and components with symbolic (frequency dependent) values throw, with the same message from both the fixed operating point stamps (calcsensitivitystamps) and the residual derivatives (calcresidualsensitivity). lookups are the constant time tables of componentlookups.
JosephsonCircuits.componentvaluestonumber Method
componentvaluestonumber(componentvalues::Vector,circuitdefs::Dict)Resolve each component value in componentvalues at the definitions circuitdefs with valuetonumber, the definitions gathered by name once for the whole table (definitionsbyname), and return the results as a Vector{Any}: the table mixes real and complex values (a port's entry is its reference impedance), symbolic values and frequency dependent values, and the groups the assembly reads are typed when they are gathered from it (see grouptype), so the table itself has one type for every circuit.
Examples
julia> JosephsonCircuits.componentvaluestonumber([:Lj1,:Lj2],Dict(:Lj1=>1e-12,:Lj2=>2e-12))
2-element Vector{Any}:
1.0e-12
2.0e-12JosephsonCircuits.compositelayout Method
compositelayout(ml::ModeLayout, modes::AbstractVector{<:Tuple}; kwargs...)Build the canonical layout from the mode index tuples, taking the zero frequency mode to be the one whose indices are all zero.
sourceJosephsonCircuits.compositelayout Method
compositelayout(ml::ModeLayout, isdc::AbstractVector{Bool};
nvdc = 0)Build the canonical layout for a state whose internal layout is ml, where isdc[t] marks mode t as the zero frequency one.
A zero frequency mode is self conjugate, so it occupies one internal entry rather than two; isdc must therefore imply ml.isreal. The converse does not hold, since a Nyquist mode is self conjugate without being direct current, which is why the split is made on isdc and not on ml.isreal.
JosephsonCircuits.conjnegfreq! Method
conjnegfreq!(A, wmodes)Take the complex conjugate of any element of A which would be negative when multipled from the right by a diagonal matrix consisting of wmodes replicated along the diagonal. Overwrite A with the output.
Each axis of A should be an integer multiple of the length of wmodes.
Examples
julia> A = JosephsonCircuits.SparseArrays.sparse([1,2,1,2], [1,1,2,2], [1+1im,1+1im,1+1im,1+1im],2,2);JosephsonCircuits.conjnegfreq!(A,[-1,1]);A
2×2 SparseArrays.SparseMatrixCSC{Complex{Int64}, Int64} with 4 stored entries:
1-1im 1+1im
1-1im 1+1imJosephsonCircuits.conjsym Method
conjsym(Nw::NTuple{N, Int}, Nt::NTuple{N, Int})Calculate the conjugate symmetries in the multi-dimensional frequency domain data.
sourceJosephsonCircuits.conjugateladder Method
conjugateladder(block::LinearizedScattering)Check the stated harmonic covariances of a pumped block against the conjugate ladder and throw where they disagree. The noise of a real wave has the covariance between the conjugates of two modes equal to the conjugate of the covariance between the modes, so the harmonic covariances obey
V_k(-nu - k wp) = transpose(V_k(nu)),which is how the noise at a frequency a covariance holds no data at is read from the data at its image (see NoiseCovariance). Where a table holds both a knot and its image the two state the same noise and must agree, to the block's atol or the covariance's, whichever is larger, of the largest entry of the table; a constant covariance is its own image and so is symmetric, a Hermitian one real. A rotation (see RotatedMatrixProvider) is checked on the covariance it returns, at the knots of the table it turns or at zero for a constant, each with its image. A callable is what it is at each frequency and is not checked.
JosephsonCircuits.conjugatemultiplicity Method
conjugatemultiplicity(fd, td)The number of harmonics of the real time domain signal each stored bin of the frequency domain array represents: one when the bin's conjugate partner is also stored, two otherwise.
The real transform truncates only the first dimension, so the partner of a bin is stored exactly when its first index is the zero or the Nyquist frequency. This is the factor which distinguishes the adjoint of applyifft! from applyfft!, and getting it wrong gives a vjp which is correct on self-conjugate modes and wrong by a factor of two on every other one.
JosephsonCircuits.conversiontype Method
conversiontype(x, args...)The element type of the conversion of the array x with the port arguments args: the kernels divide, so it is a floating point type (or whatever type the division of x's element type gives), and it is complex when x or a port argument is.
JosephsonCircuits.convertcopy Method
convertcopy(kernel!, x, a)The two port chain conversions in place on one copy of x: the kernel kernel!(y_i, a_i) converts the matrix at every frequency index of the copy, with the port argument given at that frequency by atfrequency; a matrix x is converted directly.
JosephsonCircuits.convertperfrequency! Method
convertperfrequency!(kernel!, y, x, args...)
convertperfrequency(kernel!, x, args...)Convert the matrix x[:, :, i] into y[:, :, i] at every frequency index i of the trailing dimensions of x by the kernel kernel!(y_i, x_i, tmp, args_i...), with tmp a scratch matrix and each port argument given at that frequency by atfrequency. The allocating form converts into an array like x, and for a matrix x, one frequency, calls the kernel directly. There is one method per number of port arguments, none, one or two, so that no argument map is compiled per kernel and argument type. The type parameter makes the method specialize on the kernel, which Julia does not do on its own for a function argument.
JosephsonCircuits.cosdirectionalderivative! Method
cosdirectionalderivative!(dcos::Array, sys::HBSystem, v::AbstractVector)Evaluate the directional derivative, along v, of the Fourier coefficients of cos(phi_b(t)) of the Josephson junction branch fluxes at the point set with setpoint!, in place. Those coefficients parameterize the pump modulation of the linearized harmonic balance system (see HBLinearizedSystem), so this is what propagates a shift of the pump operating point into the linearized system matrix. The derivative has the coefficients of -sin.(A*x).*(A*v), computed on the same time grid and with the same normalization as the residual, so no separate transform convention is introduced. Shares the cached time domain sine with hessianvectorproduct!, of which this is the first half.
dcos is a host array, and so therefore is sys: the only caller is the sensitivity contraction, and an HBOperatingPoint holds a host system whichever backend solved for it.
JosephsonCircuits.cosphibandwidths Method
cosphibandwidths(sys::HBSystem, Amatrixindices::Matrix,
Amatrixmodes::AbstractMatrix; tol = 1e-2, budget = 0.25)The per-tone harmonic bandwidth of the Josephson coupling at the current point, as the tuple of the largest offset in each tone which carries a coefficient of cos(phi(t)) above tol relative to the largest.
This is the bandwidth modebandmask should be given, measured rather than guessed, from the Fourier coefficients updatepreconditioner! computes anyway: the assembly reads phimatrix[abs(ind) + Nfreq*(b-1)] for ind = Amatrixindices[m1,m2], and this takes the largest of those entries over the branches b once per Fourier index, then reads it for every mode pair and records how far from the diagonal the coupling stays significant, at a cost of one pass over the coefficients and one over the mode pairs.
The measurement is per tone, and that anisotropy is the point. Jacobi-Anger gives the coefficient at a multi-tone offset m as a product over the tones, chat_m ~ prod_k J_{m_k}(delta_k), with delta_k the phase amplitude tone k contributes. Its support is therefore a rectangle whose sides are set by each delta_k separately, not a ball: a strongly pumped tone earns a wide bandwidth and a weak one collapses to zero, because J_n(delta) falls off super geometrically once n exceeds delta. Keeping a ball instead spends fill on offsets in the weak tones which carry nothing, and the difference is large: a weakly driven second tone collapses the rectangle to its strong tone's side, where a ball wide enough for the strong tone keeps every offset of the weak one.
A tone whose grid is short enough that offsets alias will report a large bandwidth. That is not a failure: the aliased coupling is really there, and a bandwidth which saturates that tone's grid costs nothing extra because the grid had no room to be truncated in the first place.
sourceJosephsonCircuits.cosphimatrix Method
cosphimatrix(sys::HBSystem)The Fourier coefficients of cos(phi(t)) at the current point, from which the Jacobians are assembled: transformed once per point into a buffer of the system's own, which no residual or product touches, and returned as is thereafter. Read it, do not write it.
JosephsonCircuits.countscatteringports Method
countscatteringports(psc::CompiledCircuit)The total number of scattering block ports of the circuit, which is the number of auxiliary port current variables per mode.
sourceJosephsonCircuits.coupledinductornames Method
coupledinductornames(c::CompiledCircuit)The names of the two inductors each mutual inductor couples, two per :K entry in the order the couplings are listed. Read from the couplings the compilation resolved, which is where the pairing lives; the names are for printing and for the output objects.
JosephsonCircuits.couplingmask Method
couplingmask(S::AbstractModeCoupling, Nmodes::Integer, Amatrixmodes)The Nmodes x Nmodes mask of the mode couplings the set S retains.
JosephsonCircuits.couplingsize! Method
couplingsize!(pc::ModeCouplingPreconditioner, S::AbstractModeCoupling,
factorization, plan; budget)The bytes and ordering of couplingsize for the coupling set S factorized by factorization from the matrix plan assembles, sized once per preconditioner: the size of a set depends on the structure alone, which a rebind! keeps, so it is kept by the set's mask, its factorization and the precision of its factors, and compared with the budget of the moment rather than sized again. A bound kept from a refusal is replaced by the size when a larger budget asks for it.
JosephsonCircuits.couplingsize Method
couplingsize(plan::PreconditionerPlan, S::AbstractModeCoupling, sys,
factorization; budget = typemax(Int))The memory the factors of the coupling set S would take, sized from the symbolic structure alone, as (bytes, ordering, exact): bytes from the block predictor for block factors, and for a sparse factorization from the fill of the ordering a KLU factorization of the host pattern takes (sparsefactorbytes), with that fill reducing ordering, which the factorization of the pattern can be handed rather than choose again (nothing for block factors); and whether bytes is the size or a bound from below. A coupling set carrying its own factorization is sized with that one. This is what lets a coupling set be refused before it is built; a preconditioner sizes each set once (couplingsize!). A sparse pattern is built only when the bound its mask gives (sparsefactorbound) is within budget; a set whose bound exceeds it is refused with the bound, so that sizing a set too large for the memory does not build its pattern, which takes more than its factors.
JosephsonCircuits.cprderivative Function
cprderivative(cpr)The analytic derivative of a PolynomialCPR, or of one of its derivatives, as a callable PolynomialCPRDerivative. The solvers differentiate the other relation they evaluate, the sinusoidal Josephson one, as cos and -sin themselves.
JosephsonCircuits.cscvaluepermutation Method
cscvaluepermutation(A::SparseMatrixCSC)The permutation p for which nonzeros(A)[p] is the stored-value order of the compressed sparse row form of A.
A device sparse matrix is CSR, and building one from a host SparseMatrixCSC converts the layout, which permutes the stored values. A numeric refactorization which reuses the symbolic analysis must therefore push new values through the same permutation rather than copying nonzeros straight into the device array: the pattern is unchanged, but the order is not.
The permutation depends only on the sparsity pattern, so it is computed once alongside the analysis and reused for every subsequent refactorization.
sourceJosephsonCircuits.cubic_trial_step Method
cubic_trial_step(α0, α1, ϕ0, ϕα0, ϕα1, dϕ0dα, ls::Backtracking)Return a tuple (αtrial, ϕtrial, measured): the step αtrial which minimizes a cubic fitted to the merit function ϕ(α) = f(xₖ + α pₖ) on [0, α1], the merit ϕtrial there, and measured, whether ϕtrial was evaluated rather than estimated from the fit. The fit takes the merit at α = 0, α = α0 and α = α1 and its derivative dϕ(α)/dα|α = 0. A latest trial α1 which satisfies the α-scaled Armijo sufficient-decrease condition ϕ(α1) <= ϕ(0) + α1 c1 (dϕ(α)/dα|α = 0) is returned without a fit.
Based on Nocedal and Wright, chapter 3 section 5.
Arguments
α0: the trial before the latest,0 < α1 < α0 <= 1.α1: the latest trial.ϕ0: the value of the merit function atα = 0, finite.ϕα0:ϕ(α0), the value of the merit function atα = α0, finite.ϕα1:ϕ(α1), the value of the merit function atα = α1.dϕ0dα:dϕ(α)/dα|α=0, the derivative of the merit function with respect toαatα = 0, finite and negative.ls: theBacktrackingwhich gives the constantc1of the α-scaled Armijo conditionϕ(α) <= ϕ(0) + α c1 (dϕ(α)/dα|α = 0)and the safeguards which bound the proposed step, relative to the latest trialα1:safeguardlowthe smallest, which bounds the cut a single fit makes before the caller evaluates the merit at the step it proposes, andsafeguardhighthe largest, so that every backtrack cuts the step by at least this factor. A trialα1which satisfies the Armijo condition is returned unclamped.
The search makes its trials in this order and hands only finite merits as ϕα0, the callers check ϕ0 and dϕ0dα before any search, and ls checked its settings when it was built, so none of these is checked here.
Returns
αtrial: the step the cubic fit predicts to minimize the merit function, within the safeguards.ϕtrial: the merit atαtrial, measured or predicted. A predicted one is the fit's: the line search evaluates the trial point and tests the Armijo condition there before accepting the step.measured:truewhen the latest trialα1itself is returned, having satisfied the Armijo condition, so thatϕtrialis its measured merit, andfalsewhenϕtrialis the fit's estimate.
JosephsonCircuits.cudssbatchlimit Method
cudssbatchlimit(persystem::Integer, nrhs::Integer, budget::Integer)The systems of a uniform cuDSS batch: as many as budget bytes hold at persystem bytes a system, at least one, and no more than uniformbatchlimit allows.
JosephsonCircuits.dcblockdescriptor Method
dcblockdescriptor(sb::StampedScatteringBlock; atol = 1e-10,
required = true)Evaluate the zero frequency pencil of a stamped block.
The matrix comes from the block's AbstractDCModel: by default from its own scattering data evaluated at zero, and from the stated model when the block declared one.
Evaluated or stated, S(0) must be real and finite. A complex zero frequency scattering matrix describes a block with no direct current limit, which is refused here rather than resolved by a convention, on the same principle as a complex direct current conductance.
A block which states no model and whose data has no zero frequency value is refused when required, which is the case when direct current is injected and the block would have to carry its share. When none is, the block is open at zero frequency, which is the i = 0 row the stamp already writes, and nothing is returned so the caller leaves that row alone: a block which cannot say what it does at direct current, and is asked to carry none, carries none. Tabulated data which starts above zero is the common case, and a circuit driven at its pump alone is not refused for it.
JosephsonCircuits.dcblockrows Method
dcblockrows(blocks, componentof, Nmodes, modeindex, nnodaldc, scale;
required = true)Build the DCBlockRows for the stamped blocks of a circuit.
nnodaldc is the point in the zero frequency block where the nodal entries end and the auxiliary ones begin. A block with no zero frequency data is refused when required and left open otherwise; see dcblockdescriptor.
JosephsonCircuits.dcconductanceplan Method
dcconductanceplan(floatingcomponents, Gnm, wmodes, Nmodes, Nnodes,
voltagescale)Build the DCConductancePlan, or nothing when there is no zero frequency mode and so no average voltage at all. voltagescale is Z0/Lscale, the reference impedance over the solver scale (see calcsolverscale).
Neither an empty conductance nor an empty set of floating components is a reason to build none. A circuit whose only direct current devices are scattering blocks has an empty G0 and still needs the block rows; a circuit whose every node is held at zero by an inductive path to ground has no voltage to solve for and still has block currents to classify, and gating on either left such a block with the artificial i = 0 row the stamp writes and nothing looking at whether that row is right.
Throws an ArgumentError when the zero frequency conductance has a non-finite or non-real entry, which has no direct current meaning.
JosephsonCircuits.dccoupling Method
dccoupling(work::CanonicalWork)H: the zero frequency nodal current each direct current unknown drives, with the unknowns in the order dcsubsystemindices gives.
This is everything outside the direct current subsystem which can see those unknowns. The average voltages reach the rest of the residual only as the resistor current G0 P v added to the zero frequency nodal rows, and a block port current only as the +1 and -1 it contributes at its two terminals. Nothing else in the harmonic residual reads them, so a direction with H N = 0 is invisible to the whole problem and not only to the subsystem, which is the condition a reference has to meet.
The transport rows are the component sums of these same nodal rows, which is why H and the subsystem cannot disagree about a sign: Y = P' (G0 P) and a block current enters its signal component's row with the sign it enters its signal node's row.
JosephsonCircuits.dcinjected Method
dcinjected(plan::DCConductancePlan, bnm::AbstractVector, Nmodes)Whether any direct current is injected into a static flux component.
When none is, every average voltage is zero, and so is every block port current a nonsingular relation determines from them, so the explicit block has nothing to find: the i = 0 rows the scattering stamp writes are then the right answer rather than a simplification, and the block is classified but not carried. Whether the relations are nonsingular in a way the circuit can see is what the classification decides, and it does not depend on this.
The test is an exact zero and not a tolerance. A drive is either declared at the zero frequency mode or it is not: calcsources writes the coefficient of a mode which no source names as exactly zero, so this asks a structural question and gets a structural answer. A small but nonzero direct current is a direct current, and is solved for.
JosephsonCircuits.dckeep Method
dckeep(work::CanonicalWork)The diagonal which is zero on the rows the direct current block replaces rather than adds to, over the whole canonical vector.
Read off the block by probing it, so it cannot disagree with the residual it describes.
sourceJosephsonCircuits.dclimit Method
dclimit(sb::StampedScatteringBlock, n, atol)The zero frequency scattering matrix read from a block's own data, or nothing and the reason the data has none: :range when it is tabulated and does not reach zero, :nonfinite when the value there is unbounded, :complex when it has no real limit.
A table which does not reach zero states S(0) only by holding or continuing its end values there; one which refuses to extrapolate, one which is zero beyond its band, which is a statement about the band and not about direct current, and a piecewise table outside its bands have no data at zero.
Read and not decided: what to do about a block with no zero frequency data depends on whether direct current is asked of it, which is the caller's question. See dcblockdescriptor.
JosephsonCircuits.dcpinning Method
dcpinning(work::CanonicalWork; maxdense = 64)Return the DCPinning a singular direct current subsystem needs, nothing when it is nonsingular, or throw when it has no solution or an undetermined direction the rest of the circuit can see.
The subsystem this reads, dcsubsystem(work), must be the complete unreferenced descriptor: every transport row and every block relation, with no reference chosen, which is why this is called once at CanonicalWork construction, before any reference exists. Choosing one earlier, from the resistors alone, can discard a row a block has made necessary, and no later check can recover it.
The subsystem is decided in the units of the block currents, its average voltages scaled by the plan's voltagescale, and equilibrated (see equilibrate). It falls into blocks which share no row or column, an island on its own or the islands and block currents a chain of blocks joins, and each is decomposed alone, by its singular values, or by sparse QR when it has more than maxdense rows or columns (see dcnullblocks).
JosephsonCircuits.dcprobes Method
dcprobes(work::CanonicalWork)The coordinates of the direct current subsystem which dcupdate probes together, as groups, and the window rows each coordinate reaches, as the columns of a pattern over the window. Coordinates in one group reach no row in common, so one pass reads each of them from rows of its own.
A coordinate reaches the rows of its terms in the subsystem, before anything cancels (a cancelling sum depends on the order its terms are added in), the reference row which fixes it, its coupling into the nodal rows for an average voltage, and its own row for a block current, which the block's relation adds to. The groups are a greedy coloring of the coordinates which share a row, so their number is bounded by how many coordinates one row reaches, not by the size of the circuit.
sourceJosephsonCircuits.dcresidualsensitivity Function
dcresidualsensitivity(dc::DCOperatingPoint, psc, nm, scale,
sensitivityindices, alphas)The direct current block's own contribution to the residual sensitivity, in canonical coordinates.
The canonical residual is D G F(S u) + M u + s c, so its derivative with respect to a component value is the harmonic one gathered and masked, plus (dM/dr) u. Only the conductance depends on a lumped component value, and it enters twice: as the transport rows Y = P' G0 P and as the coupling G0 P into the zero frequency nodal rows. A capacitor, an inductor and a junction are open circuits, a short and a short at zero frequency, none of which carries a conductance, so they contribute nothing here, and their derivative is the harmonic rows alone.
The perturbation is relative by default: G0 is proportional to 1/R, so a relative change in R scales the whole stamp by -1; alphas carries an absolute direction dv/dp instead, of which only the real part reaches the direct current conductance rows.
JosephsonCircuits.dcscatteringmatrix Method
dcscatteringmatrix(m::AbstractDCModel, n)The n by n real zero frequency scattering matrix of a stated model: OpenDC, ShortDC, ThroughDC or ScatteringDC. ScatteringLimit states none and has no method here; it is handled by evaluating the block's own data. Throws for a ThroughDC with n != 2 or a ScatteringDC of the wrong dimension.
JosephsonCircuits.dcsolutionfrom Method
dcsolutionfrom(plan::DCConductancePlan, v::AbstractVector)Package the solved component voltages as a DCConductanceSolution, the one form in which the direct current answer is reported.
JosephsonCircuits.dcsourcecurrent Method
dcsourcecurrent(plan::DCConductancePlan, bnm, Nmodes)The direct current injected into each static flux component, validated.
The zero frequency mode is self conjugate, so its source coefficient is real by construction; an imaginary part there is not a small direct current but a sign that the source assembly or the mode layout is wrong, and taking the real part of it would carry that error silently into the answer. It is refused instead, against a tolerance relative to the largest coefficient of the zero frequency source, so the decision does not depend on the units the circuit is written in.
sourceJosephsonCircuits.dcsubsystem Method
dcsubsystem(work::CanonicalWork)The direct current block [v; i] of the canonical Jacobian, as a sparse matrix: the transport rows and the blocks' zero frequency rows, in the order dcsubsystemindices gives, with the reference rows of the work's pinning in place of the equations they replace.
JosephsonCircuits.dcsubsystemindices Method
dcsubsystemindices(work::CanonicalWork)The canonical positions the direct current subsystem occupies: the explicit voltage block, then every block port's zero frequency current.
sourceJosephsonCircuits.dcsubsystemlocal Method
dcsubsystemlocal(work::CanonicalWork)The same positions, local to the window.
sourceJosephsonCircuits.dcsubsystemrhs Method
dcsubsystemrhs(work::CanonicalWork)The constant side of the direct current subsystem: the injected current on the transport rows, zero on the blocks' own rows.
sourceJosephsonCircuits.dcupdate Method
dcupdate(work::CanonicalWork)Build the DCUpdate by probing addtransportwindow!, so the matrix form and the scalar form agree by construction. The probes are the coordinates of the direct current subsystem (work.dclocal), the only ones the block reads, in the groups dcprobes forms.
JosephsonCircuits.defaultgridladder Method
defaultgridladder(Nharmonics::NTuple{N,Int})The default coarse to fine ladder of retained harmonic caps for stagedhbnlsolve: Nharmonics halved repeatedly in every dimension down to two harmonics, a tone with two or fewer keeping its own, coarsest first and Nharmonics last.
JosephsonCircuits.definitionsbyname Method
definitionsbyname(circuitdefs)The definitions keyed by the name each key gives (see definitionname), with their values as given; a key which gives no name is left out. A name may be defined under its symbol, its string or, with the Symbolics extension, its variable, and one defined under two of them with different values is refused rather than resolved by the order of the dictionary. A table already keyed by name is returned as it is.
JosephsonCircuits.definitiontable Method
definitiontable(circuitdefs)The component definitions as a Dict{Any,Any}, whatever the key and value types of the dictionary given.
JosephsonCircuits.deflationproducts Method
deflationproducts(pc)The number of Jacobian products the preconditioner pc has taken itself: a FloquetPreconditioner's, one per candidate at every build, and a ModeCouplingPreconditioner's with Clusters, one per mode at every probe. Together with products in KrylovSolveInfo this is the exact cost of a solve.
JosephsonCircuits.deflationrebuilds Method
deflationrebuilds(pc)How many times the image pair of a FloquetPreconditioner has been built.
JosephsonCircuits.deflationsize Method
deflationsize(pc)The number of directions the active deflation pair of a FloquetPreconditioner spans. Zero for a preconditioner which does not deflate.
JosephsonCircuits.deprecatedfactorization Method
deprecatedfactorization(to, method, factorization)The method of a solve given factorization, the keyword with which hbnlsolve took the sparse factorization of its Newton iteration in v0.5.4. The factorization is now an option of the method: given beside the default, a NewtonKrylov, its deprecation goes to the entry point or the messages of the call (see warndeprecations), and the solve takes Newton(factorization = factorization), as v0.5.4 did; given beside another method it is refused.
JosephsonCircuits.deprecatedsolverkeywords Method
deprecatedsolverkeywords(to, atol; ftol = nothing,
switchofflinesearchtol = nothing, alphamin = nothing,
maxharmonics = nothing, maxpumpharmonics = nothing)The absolute residual tolerance of a solve given the deprecated keywords of the nonlinear solvers: ftol when it is given, which is atol under its old name, and atol otherwise. The deprecation of each keyword given goes to the entry point or the messages of the call (see warndeprecations); switchofflinesearchtol and alphamin, which the line search no longer has, and maxharmonics of hbnlsolve and maxpumpharmonics of hbsolve, whose role the retained harmonics took, are ignored.
JosephsonCircuits.derivativeat Method
derivativeat(r::JunctionRelations, phi)The derivative of the relation of every junction at the branch phases phi, cos.(phi) for the Josephson relation: the differential inductance which every Jacobian and every linearization is built from. The counterpart of relationat, with derivativeinto! as its in place form.
JosephsonCircuits.derivativeinto! Method
derivativeinto!(out, r::JunctionRelations, phi)derivativeat writing into out, which may not alias phi. A circuit whose junctions are all sinusoidal takes a single broadcast of cos.
JosephsonCircuits.designblockjacobian Method
designblockjacobian(circuit, parameters)The scattering block dependence of a circuit on its design parameters: for each ScatteringParameters block of the compiled circuit and each parameter its derivatives names, a derivative block whose scattering matrix is the block's stated dS/dp. A block which states no derivative for a parameter does not depend on it. Returns a vector of (blockpath, parameterindex, derivativeblock), by block and, within a block, in the order of parameters. Each block's derivatives are read once, against a table of the parameters' positions.
JosephsonCircuits.designdirections Method
designdirections(psc::CompiledCircuit, v::NamedTuple, J::AbstractMatrix)The nonzero derivatives of the component values of psc with respect to the design parameters, from the values v of the names its components are written in and their Jacobian J, a row per name of v and a column per parameter: a component written as a name takes that name's row, and one written as a number depends on no parameter. A component whose value is frequency dependent is not among them, and neither is a port which owns a termination, whose reference impedance is the value of that termination, which is. Returns (components, values, entries): the flat indices of the components, in compiled order, their values, and a triplet (k, j, dv/dp) per nonzero derivative of the kth of them with respect to parameter j, by parameter and then by component, so that the cost grows with the dependences rather than with the components times the parameters.
JosephsonCircuits.devicecomplexjacobianpattern Method
devicecomplexjacobianpattern(n, Nmodes, adjacency, activem1,
linearmatrices, backend)The sparsity structure of the complex Jacobian, from the node adjacency, the mode couplings activem1 which survive the frequency grid, and the structures of the constant linear term linearmatrices, built on backend and returned there as a DeviceSparsePattern.
JosephsonCircuits.deviceexpandrealpattern Method
deviceexpandrealpattern(outerptr, outerrowval, layout::ModeLayout,
n::Integer, backend)Expand the structure of a square complex matrix, whose rows and columns are both in layout, into the structure of its real representation, where each complex entry becomes a block of up to two by two real entries, and return it on backend as a DeviceSparsePattern.
The number of real entries a complex index contributes is the same for every one of its real columns, so the column pointer is a gather of per index counts followed by a prefix sum, and the row indices are then one work item per column with nothing to coordinate.
sourceJosephsonCircuits.devicenoise Method
devicenoise(plan::DeviceNoisePlan, blockplan, providers,
adjointsolution, nrhs, wpumpmodes, w, keepmatrix, temperatures)A callback which computes the noise scattering parameters of a signal frequency from the adjoint solutions on the backend.
temperatures is one temperature per noise channel; the state of each channel, its symmetrized noise nbar + 1/2, weighs its waves where they are reduced, so nothing downstream of this knows about temperature.
blockplan is the DeviceBlockNoisePlan of the dissipative scattering blocks, or nothing when there are none; their channels follow the noise ports of the lumped components in the rows, as they do on the host, and are evaluated through the same DeviceProviders providers the stamps are.
Returned in the form hblinsolve_inner! takes as presolvednoise: called with the frequency index, its input waves, the destination for the noise scattering matrix, that for the noise covariance or nothing, and the table of the values of the frequency dependent functions at the frequency's modes (see providertable), from which the values of the noise ports which depend on the frequency are read, it returns the NoiseReduction the quantum efficiency and the commutation relations read.
The adjoint solution never leaves the backend, and neither does the noise scattering matrix unless keepmatrix: on a line with loss spread along it that matrix has a row per noise port mode and is the largest thing in the sweep, while what is read of it is one number per port mode.
Snoise is each column of the noise output waves divided by the input wave of its port mode, with the sign the adjoint route owes it (see adjointnoisesigns!); the scale of each column is formed on the host, where the input waves are.
JosephsonCircuits.devicesolutions Function
devicesolutions(lsys::HBLinearizedSystem, bnm, w, backend, forward,
adjoint = nothing; factorization = nothing, refine = true,
budget = memorybudget(backend))The DeviceSweep which computes the solutions of the linearized system on backend a batch of frequencies at a time. factorization is the linearized solve's factorization: a BlockFactorization takes the batched block path below, anything else the cuDSS one. refine asks single precision block factors to refine against the double residual; false is the fully single precision sweep. budget is the device memory the batch may take.
The sweep is driven by solvebatch!, which solves the batch of frequencies beginning at an index and stages its solutions on the host; forwardsolution! and adjointsolution! then fill the solution of any frequency of that batch, and adjointdevice hands out the adjoint solution of a frequency where it was computed, for the noise scattering parameters, which are formed there rather than brought back (see devicenoise). The providers field is the DeviceProviders the scattering blocks are evaluated through, or nothing when there are none or they cannot be evaluated on backend; the noise channels of the dissipative blocks are read through the same one. The components whose values depend on the frequency are stamped from a table of their functions' values at the batch's modes, which the host fills for each batch (DeviceFrequencyDependentStamps).
The split is what keeps the host work parallel. solvebatch! is the only verb which touches the device; once it has returned, its batch's frequencies can be post-processed by as many workers as the host path uses, because reading a solution touches staged host memory and nothing else.
The systems of a batch share one sparsity pattern, so cuDSS, or the block factorization (blockanalysis), analyzes it once and then factorizes and solves each batch together, from the values of one assemblesweep!. With a sparse device factorization the batch size is capped by uniformbatchlimit and by budget (memorybudget by default) at cuDSS's own estimate of the batch's factorization, from the analysis of its forward direction, with the values, solutions and right hand sides of each direction (cudssbatchlimit): the largest batch those arrays allow is analyzed and kept when the estimate fits beside them, and a smaller one made when it does not. With a BlockFactorization the cap does not apply and the batch is sized by blocksystembytes, the factors, the originals when refining, the solutions of both directions and the value matrix of one system, against budget and the length of the sweep.
forward and adjoint each describe what a direction needs, as a named tuple (full, rows). With full the whole solution is copied back, which the node flux, voltage and sensitivity outputs need; otherwise only rows are gathered and returned, which for the scattering parameters is a handful of port rows out of the whole circuit (see portsolutionrows).
With a sparse device factorization the adjoint direction is a second uniform batch over the transposed system: cuDSS 0.8 cannot solve against the transpose of a factorization, so unlike the host, which gets its adjoint solutions from the forward factors with trysolvetranspose!, it pays a second analysis and a second factorization per batch. A BlockFactorization solves both directions from the one factorization, reading the same factors the other way round (blocksolve! with transposed = true), and assembles one batch of values in the stored column order for both.
JosephsonCircuits.diagrepeat Method
diagrepeat(A::SparseMatrixCSC, Nmodes::Integer)Return a sparse matrix with each element of A duplicated along the diagonal Nmodes times.
Examples
julia> JosephsonCircuits.diagrepeat(JosephsonCircuits.SparseArrays.sparse([1,1,2,2], [1,2,1,2], [1,2,3,4],2,2),2)
4×4 SparseArrays.SparseMatrixCSC{Int64, Int64} with 8 stored entries:
1 ⋅ 2 ⋅
⋅ 1 ⋅ 2
3 ⋅ 4 ⋅
⋅ 3 ⋅ 4JosephsonCircuits.diagrepeat Method
diagrepeat(A::SparseVector, Nmodes::Integer)Return a sparse vector with each element of A duplicated along the diagonal Nmodes times.
Examples
julia> JosephsonCircuits.diagrepeat(JosephsonCircuits.SparseArrays.sparsevec([1,2],[1,2]),2)
4-element SparseArrays.SparseVector{Int64, Int64} with 4 stored entries:
[1] = 1
[2] = 1
[3] = 2
[4] = 2JosephsonCircuits.direct_sum Method
direct_sum(A; n::Integer=1)Return the direct sum of n copies of the matrix A, the block diagonal matrix kron(I(n), A).
JosephsonCircuits.directcoefficients Method
directcoefficients(sys, quantity)The derivative of the port wave coefficients of outputcoefficients with respect to a relative perturbation of a port's own termination, which moves the port's reference impedance and its termination conductance together, z -> r z and g -> g/r, as the linearized solve moves them: -cv/2 and cd/2 for a wave, since z g is unchanged, and nothing for the voltage.
JosephsonCircuits.dualsearch! Method
dualsearch!(f!, F, xcandidate, x, deltax, ϕ0, dϕ0dα, ϕcand,
correction, betak, Fbest, Fspare, Fatx; ls = Backtracking(),
curvedpriority = false)Search selection for a rejected Anderson candidate: Both the curvilinear search x + α*deltax - betak*α²*correction and the plain damped-Newton search are run, and the better accepted point is taken. F and xcandidate should hold the candidate's residual and trial point (the curved path's α = 1), ϕcand the merit, and Fbest the residual at x.
An iteration costs a Jacobian evaluation, a factorization and a linear solve, which for a device such as a TWPA take an order of magnitude longer than a residual evaluation, so the extra residual evaluations of a second search are worth spending on a better step.
If both searches fail, the better best-effort point is returned and accepted is false. Fatx preserves the residual at x across the searches (which clobber Fbest with best-trial copies), so that the plain search starts, as backtracking_linesearch! requires, with the residual at x in F.
Returns (α, ϕα, accepted, backtracks, usedcorrection), where usedcorrection reports whether the returned point lies on the curved path, and backtracks counts ALL trial evaluations after the candidate (the curved search's backtracks plus the plain search's full step and backtracks), so the iteration's residual evaluations are exactly 1 + backtracks.
JosephsonCircuits.elaborate Method
elaborate(circuit::Circuit; maxdepth = 64)Recursively flatten the hierarchy of circuit into an ElaboratedCircuit. Elaboration:
assigns each primitive instance a stable hierarchical path such as "cell37/cap";
substitutes subcircuit interface pins with parent nets and allocates fresh internal nets for every subcircuit instance;
deduplicates component definitions by object identity, so shared definitions and their data appear once;
parses and validates each unique circuit definition once, however many times it is instantiated;
resolves mutual inductor couplings to flattened instance indices;
rejects recursive circuit definitions.
A repeated subcircuit definition is parsed once and the parse reused for every instance, so the work per instance is proportional to the instance's own size. maxdepth bounds the nesting depth.
JosephsonCircuits.eliminationtree Method
eliminationtree(adj, order::AbstractVector{<:Integer})The symbolic elimination of the node graph adj under order, returned as (parent, post, later). parent[a] is the node eliminated first among those coupled to a after a, following the fill, or zero for a root; post is the postorder of this elimination tree, the order the supernodes are eliminated in; and later[a] lists the nodes after a that a is coupled to once the fill is included. Every postorder of the tree eliminates with the same fill, and every coupling of the filled graph joins a node to one of its ancestors, so later holds in the postorder as well.
JosephsonCircuits.emptyrelations Method
emptyrelations(A::AbstractArray)The empty JunctionRelations, of the array types of A, which is what a circuit of sinusoidal junctions alone holds.
JosephsonCircuits.ensurecolumns! Method
ensurecolumns!(ws::GMRESWorkspace, k)Return the basis ws.V with at least k columns, replacing it with a wider one when it has fewer. The columns built so far are copied across; the new ones are uninitialized, as the whole basis was before. The width doubles and is capped at size(ws.H, 1), which is m + 1, so a basis never grows past the restart length.
JosephsonCircuits.equilibrate! Method
equilibrate!(nzval::AbstractMatrix, B, B0, eq::SweepEquilibration,
backend)Divide each row of each system of the batch by its largest entry, then each column of the result by its largest, recording the scales in eq, and write into B the right-hand side B0 of every system divided by that system's row scales.
JosephsonCircuits.erased Method
erased(f)
erased(pc::AbstractPreconditioner)The residual or product f as an ErasedFunction, and pc as an ErasedPreconditioner; either unchanged when it is erased already.
JosephsonCircuits.escalatepreconditioner! Method
escalatepreconditioner!(pc::AbstractPreconditioner)Make the preconditioner pc a better approximation of the Jacobian, at greater cost, and return true; return false when it cannot be improved further. Called by nlsolvekrylov!, when its method's escalate is on, after every linear solve which fails to reach the forcing tolerance, the symptom of a preconditioner too crude for the problem (stagnation alone is deliberately not the trigger). The default method returns false, which is correct for any preconditioner that is already exact or has no cheaper/costlier settings. A preconditioner which can grow must also refuse when the grown factors would not fit in memory: the driver records the refusal and carries on with what it has rather than let a rescue exhaust the machine.
JosephsonCircuits.escalatepreconditioner! Method
escalatepreconditioner!(pc::ModeCouplingPreconditioner)Grow the coupling set, a band to the next offset each tone realizes and any other set to every mode, and rebuild, returning true if it grew. Returns false when the set is already full, and when the factors of the grown set are predicted (couplingsize!) to exceed pc.budget, the backend's memory budget (memorybudget) unless set, in which case nothing is built: the driver records the refusal and carries on with the set it has rather than let a rescue exhaust the machine.
This is the safety net of the block diagonal. A block diagonal preconditioner is cheap, but on a strongly pumped device it leaves the preconditioned operator nearly singular in a few directions, which stalls GMRES: the residual polynomial is pinned at p(0) = 1 and so cannot be made small near the origin.
For every set but a band, escalation goes straight to the full Jacobian rather than growing the set gradually, because there is no reliable way to know in advance which modes carry those directions (a band has a measured width to step, so it grows one realized offset per tone at a time first). Criteria based on the linear response of the circuit, on the mode frequencies, and on the mode diagonal blocks were each measured and none generalized across devices: the deficiency is a specific direction inside a mode's subspace rather than a property of the mode, and any per mode score averages it away. The full set is exact, so the method is never less robust than a direct solve, only faster when the block diagonal suffices.
The full set held in less precision than the iteration, single precision block factors or a CUDSSFactorization with a precision, is not exact either: its factors approximate the Jacobian to their own precision and can be too poor to converge the Krylov solve. Its escalation is the same coupling set in the iteration's precision, the factorization and the plan the matrix is assembled from promoted by withprecision; a reduced precision factorization of a smaller set grows the set first and escalates its precision once the set is full.
See FloquetPreconditioner for the alternative, which absorbs the same deficiency by measuring the directions rather than enlarging the factorization.
JosephsonCircuits.evaluatecovariance! Function
evaluatecovariance!(dest::AbstractArray{Complex{Float64},3},
block::ScatteringParameters, ws::AbstractVector,
absbuffer = nothing)Evaluate the stated noise covariance of block, whose noise model is a NoiseCovariance, at the signed angular frequencies ws with the block's negative frequency rule, as evaluatescattering! does the scattering parameters: the covariance of a wave at a negative frequency is the conjugate of that at the positive one.
JosephsonCircuits.evaluatehybrid! Method
evaluatehybrid!(B, C, block::ScatteringParameters, ws::AbstractVector,
work::HybridWorkspace; derivative = false)Evaluate the coefficient matrices of the hybrid (wave to modified nodal analysis) constitutive equations of block at the signed angular frequencies ws:
B(w) v - C(w) i = 0, B = (I - S(w)) R^(-1/2), C = (I + S(w)) R^(1/2),with R the diagonal of the reference impedances, v the port voltages and i the port currents (which the solvers carry as auxiliary variables). The diagonal multiplies on the right: with the power waves a = (R^(-1/2) v + R^(1/2) i)/2 and b = (R^(-1/2) v - R^(1/2) i)/2 and b = S a, the entry (p, q) of I - S scales with the impedance of port q, the port whose voltage it multiplies, so a block whose ports have different reference impedances is not symmetric between the two sides. This representation exists for every scattering matrix: unlike the admittance Y = R^(-1/2)(I-S)(I+S)^(-1)R^(-1/2), nothing is inverted, so blocks whose I+S is singular somewhere (an ideal short S = -1, or a lossless through line at each of its half wavelength resonances, where det(I+S) = 1-exp(-2*im*theta) = 0) are stamped exactly.
The scattering parameters are evaluated with the negative frequency rule of the block through evaluatescattering! at the native reference impedances; no renormalization of the data is performed. At exactly zero frequency the rows are replaced by i = 0 (B = 0, C = I): the node flux basis carries no DC voltage, and direct currents flow only through the inductive branches of the static flux stiffness graph, so a scattering block carries no direct current, consistent with the treatment of resistors.
With derivative, the data of block is the derivative dS/dtheta of a block's scattering matrix with respect to a parameter, and B and C are the derivatives of that block's coefficients, -dS R^(-1/2) and dS R^(1/2): the identity parts do not depend on the parameter, and neither do the zero frequency rows, which are zero.
work is the HybridWorkspace whose scratch is reused across calls.
JosephsonCircuits.evaluatehybridpumped! Method
evaluatehybridpumped!(B, C, block::LinearizedScattering, ws, K,
work::ScatteringWorkspace)The coefficient matrices of the hybrid constitutive equations of a pumped block over the modes at the signed frequencies ws, as evaluatehybrid! gives them for a block which does not convert, with the modes coupled: B[p, q, m, n] and C[p, q, m, n] are the entries of (I - S) R^(-1/2) and (I + S) R^(1/2) from input port q at mode n to output port p at mode m, where the multi-mode scattering matrix is S[(p, m), (q, n)] = H_k[p, q](ws[n]) for the harmonic k = K[m, n] (see pumpedharmonics), the negative harmonics by H_{-k}(nu) = conj(H_k(-nu)), and zero where the modes are not coupled. The rows and columns of a mode at zero frequency carry only the identity, the i = 0 row of the stamp.
JosephsonCircuits.evaluateprovider! Method
evaluateprovider!(dest::AbstractArray{T,3}, p::AbstractMatrixProvider,
ws::AbstractVector)Evaluate the provider at the angular frequencies ws, writing the matrix at frequency ws[i] into dest[:,:,i]. This is the batch, in-place evaluation contract used at analysis time: the caller evaluates each definition once per frequency grid and caches the result, so instances sharing a definition share one evaluation.
JosephsonCircuits.evaluatescattering! Function
evaluatescattering!(dest::AbstractArray{Complex{Float64},3},
block::ScatteringParameters, ws::AbstractVector,
absbuffer = nothing)Evaluate the scattering parameters of block at the signed angular frequencies ws, applying the block's negative frequency rule, and write the matrix at ws[i] into dest[:,:,i]. With ConjugateSymmetry the provider is evaluated at abs.(ws) and conjugated where ws[i] < 0; absbuffer, a Vector{Float64} the caller may pass, holds the absolute frequencies and avoids one allocation per call.
JosephsonCircuits.export_netlist! Method
export_netlist!(io::IO, circuit, circuitdefs)Export the netlist in circuit to the IOBuffer or IOStream io.
Examples
julia> io = IOBuffer();JosephsonCircuits.export_netlist!(io, [("P","1","0",1),("R","1","0",50.0)],Dict());println(String(take!(io)))
P 1 0 1
R 1 0 50.0JosephsonCircuits.export_netlist Method
export_netlist(filename, circuit, circuitdefs)Export the netlist in circuit to the file with name and path filename.
JosephsonCircuits.export_netlist Method
export_netlist(filename, circuit)Export the netlist in circuit to the file with name and path filename.
JosephsonCircuits.exportnetlist Method
exportnetlist(circuit, circuitdefs::Dict; port::Int = 1, jj::Bool = true,
vm::Real = 9.9)
exportnetlist(psc::CompiledCircuit, circuitdefs::Dict; port::Int = 1,
jj::Bool = true, vm::Real = 9.9)
exportnetlist(psc::CompiledCircuit, componentvalues::AbstractVector;
port::Int = 1, jj::Bool = true, vm::Real = 9.9)
exportnetlist(circuit; port::Int = 1, jj::Bool = true, vm::Real = 9.9)Export a circuit as a WRSPICE netlist. Returns a named tuple with the netlist as a string in netlist, the port number in port, the node count in Nnodes, and in junctions one entry per jj model instance written, in the order of the netlist, with the flat component index of the junction the instance realizes in index and the name of its phase node, whose voltage WRSPICE reports as the junction phase in radians, in phasenode; portnodes and portcurrent are placeholders fixed at 1, since the source nodes and amplitude are given directly to wrspice_input_transient or wrspice_input_ac. A fully numeric circuit needs no circuitdefs; a compiled circuit whose values are already numbers can be given those values directly as a vector in compiled component order. port is the port number the sources are applied to, recorded in the output.
The elements of one kind between the same two nodes are written as one line, named after the first of them, whatever their order in the circuit: capacitances add, and inductances, junctions and resistances combine in parallel (see spicebranches). An inductor which a mutual inductor couples keeps a line of its own, which the coupling names. A resistor of infinite resistance is an open and writes no line. A port writes the resistor of its termination, and a current source writes no line: the drives are given to wrspice_input_transient or wrspice_input_ac, and WRspice writes the sources of a transient problem itself. An ideal TransmissionLine is written as the SPICE lossless line element with its impedance and delay; any other scattering block has no SPICE element and is refused, as is a value which is complex or not a number.
Component values are resolved with circuitdefs. With jj = true each Josephson junction is written as an instance of one WRSPICE jj model whose critical current is the mean over the junctions and whose capacitance to critical current ratio is the smallest such ratio over them, clamped to the WRSPICE maximum of 0.99e-6 (see calcCjIcmean); the part of each junction's shunt capacitance above what the model provides is written as a separate capacitor. The model needs a shunt capacitance on every junction and junctions of comparable size, and its relation is the sinusoidal one, so a NonlinearInductor with another relation is refused. The phase nodes of the instances are numbered past the circuit's nets, so none coincides with a net. vm, in volts, is the model's product of the critical current and the subgap resistance, which sets its subgap loss: WRSPICE's own default, 16.5 mV, is very lossy and its range 8 to 100 mV, which the model's force = 1 lets vm exceed, so that the default 9.9 V makes the loss small, though not zero. With jj = false each junction is written as its linear inductance, which none of the model's conditions apply to.
Examples
circuit = Circuit(
[:P1 => Port(1; Z0 = :R),
:C1 => Capacitor(:Cc),
:Lj1 => JosephsonJunction(:Lj),
:C2 => Capacitor(:Cj),
:gnd => Ground()],
[Net("1", [(:P1, 1), (:C1, 1)]),
Net("2", [(:C1, 2), (:Lj1, 1), (:C2, 1)]),
Net("0", [(:P1, 2), (:Lj1, 2), (:C2, 2), (:gnd, 1)])])
circuitdefs = Dict(
:Lj =>1000.0e-12,
:Cc => 100.0e-15,
:Cj => 1000.0e-15,
:R => 50.0)
println(JosephsonCircuits.exportnetlist(circuit, circuitdefs;port = 1, jj = true).netlist)
println("")
println(JosephsonCircuits.exportnetlist(circuit, circuitdefs;port = 1, jj = false).netlist)
# output
* SPICE Simulation
RP1_termination 1 0 50.0
C1 1 2 100.0f
B1 2 0 3 jjk ics=0.32910597847545336u
C2 2 0 674.1850813093012f
.model jjk jj(rtype=0,cct=1,icrit=0.32910597847545336u,cap=325.8149186906988f,force=1,vm=9.9)
* SPICE Simulation
RP1_termination 1 0 50.0
C1 1 2 100.0f
Lj1 2 0 1000.0000000000001p
C2 2 0 1000.0fcircuit = Circuit(
[:P1 => Port(1; Z0 = :R),
:C1 => Capacitor(:Cc),
:L1 => Inductor(:L1),
:L2 => Inductor(:L2),
:C2 => Capacitor(:Cj1),
:C3 => Capacitor(:Cj2),
:I1 => CurrentSource(:I1),
:gnd => Ground()],
[Net("1", [(:P1, 1), (:C1, 1)]),
Net("2", [(:C1, 2), (:L1, 1), (:L2, 1), (:C2, 1), (:C3, 1), (:I1, 1)]),
Net("0", [(:P1, 2), (:L1, 2), (:L2, 2), (:C2, 2), (:C3, 2), (:I1, 2),
(:gnd, 1)])])
circuitdefs = Dict(
:L1 =>2000.0e-12,
:L2 =>2000.0e-12,
:Cc => 100.0e-15,
:Cj1 => 500.0e-15,
:Cj2 => 500.0e-15,
:R => 50.0,
:I1 =>0.1)
println(JosephsonCircuits.exportnetlist(circuit, circuitdefs;port = 1, jj = true).netlist)
println("")
println(JosephsonCircuits.exportnetlist(circuit, circuitdefs;port = 1, jj = false).netlist)
# output
* SPICE Simulation
RP1_termination 1 0 50.0
C1 1 2 100.0f
L1 2 0 1000.0000000000001p
C2 2 0 1000.0f
* SPICE Simulation
RP1_termination 1 0 50.0
C1 1 2 100.0f
L1 2 0 1000.0000000000001p
C2 2 0 1000.0fcircuit = Circuit(
[:P1 => Port(1; Z0 = :Rleft),
:L1 => Inductor(:L1),
:Lj1 => JosephsonJunction(:Lj1),
:L2 => Inductor(:L2),
:K1 => MutualInductor(:K1, :L1, :L2),
:C2 => Capacitor(:C2),
:C3 => Capacitor(:C3),
:gnd => Ground()],
[Net("1", [(:P1, 1), (:L1, 1)]),
Net("2", [(:Lj1, 1), (:L2, 1), (:C2, 1), (:C3, 1)]),
Net("0", [(:P1, 2), (:L1, 2), (:Lj1, 2), (:L2, 2), (:C2, 2), (:C3, 2),
(:gnd, 1)])])
circuitdefs = Dict(
:Rleft => 50.0,
:L1 => 1000.0e-12,
:Lj1 => 1000.0e-12,
:K1 => 0.1,
:L2 => 1000.0e-12,
:C2 => 1000.0e-15,
:C3 => 1000.0e-15)
println(JosephsonCircuits.exportnetlist(circuit, circuitdefs;port = 1, jj = true).netlist)
println("")
println(JosephsonCircuits.exportnetlist(circuit, circuitdefs;port = 1, jj = false).netlist)
# output
* SPICE Simulation
RP1_termination 1 0 50.0
L1 1 0 1000.0000000000001p
B1 2 0 3 jjk ics=0.32910597847545336u
C2 2 0 1674.185081309301f
L2 2 0 1000.0000000000001p
K1 L1 L2 0.1
.model jjk jj(rtype=0,cct=1,icrit=0.32910597847545336u,cap=325.8149186906988f,force=1,vm=9.9)
* SPICE Simulation
RP1_termination 1 0 50.0
L1 1 0 1000.0000000000001p
Lj1 2 0 1000.0000000000001p
L2 2 0 1000.0000000000001p
K1 L1 L2 0.1
C2 2 0 2000.0fcircuit = Circuit(
[:P1 => Port(1; Z0 = :Rleft),
:L1 => Inductor(:L1),
:Lj1 => JosephsonJunction(:Lj1),
:L2 => Inductor(:L2),
:K1 => MutualInductor(:K1, :L2, :L1),
:C2 => Capacitor(:C2),
:C3 => Capacitor(:C3),
:gnd => Ground()],
[Net("1", [(:P1, 1), (:L1, 1)]),
Net("2", [(:Lj1, 1), (:L2, 1), (:C2, 1), (:C3, 1)]),
Net("0", [(:P1, 2), (:L1, 2), (:Lj1, 2), (:L2, 2), (:C2, 2), (:C3, 2),
(:gnd, 1)])])
circuitdefs = Dict(
:Rleft => 50.0,
:L1 => 1000.0e-12,
:Lj1 => 1000.0e-12,
:K1 => 0.1,
:L2 => 1000.0e-12,
:C2 => 1000.0e-15,
:C3 => 1000.0e-15)
println(JosephsonCircuits.exportnetlist(circuit, circuitdefs;port = 1, jj = true).netlist)
println("")
println(JosephsonCircuits.exportnetlist(circuit, circuitdefs;port = 1, jj = false).netlist)
# output
* SPICE Simulation
RP1_termination 1 0 50.0
L1 1 0 1000.0000000000001p
B1 2 0 3 jjk ics=0.32910597847545336u
C2 2 0 1674.185081309301f
L2 2 0 1000.0000000000001p
K1 L2 L1 0.1
.model jjk jj(rtype=0,cct=1,icrit=0.32910597847545336u,cap=325.8149186906988f,force=1,vm=9.9)
* SPICE Simulation
RP1_termination 1 0 50.0
L1 1 0 1000.0000000000001p
Lj1 2 0 1000.0000000000001p
L2 2 0 1000.0000000000001p
K1 L2 L1 0.1
C2 2 0 2000.0fJosephsonCircuits.extractbranches Method
extractbranches(componenttypes::Vector{Symbol},nodeindexarray::Matrix{Int})The (node1, node2) branches of the components which define the circuit graph: inductors (:L), Josephson junctions (:Lj), current sources (:I) and ports (:P). Capacitors, resistors and mutual inductors do not create branches.
Components sharing a branch produce duplicate tuples, which circuittopology merges into one branch.
Examples
julia> JosephsonCircuits.extractbranches([:P,:I,:R,:C,:Lj,:C],[2 2 2 2 3 3; 1 1 1 3 1 1])
3-element Vector{Tuple{Int64, Int64}}:
(2, 1)
(2, 1)
(3, 1)JosephsonCircuits.factorizationprecision Method
factorizationprecision(f::AbstractFactorization)The floating point type the matrix handed to f is built and factorized in, nothing when it follows the iteration's. Only CUDSSFactorization has one; KLU and UMFPACK factorize in double precision whatever they are handed. BlockFactorization also takes a precision, but for the dense blocks it builds itself, while the sparse matrix it is handed stays in the iteration's type, so it has none here.
JosephsonCircuits.factorize Method
factorize(f::BlockFactorization, A::SparseMatrixCSC; blocksize,
backend = CPU(), nb = 1, refine = BLOCKREFINESTEPS)The SparseBlockFactorization of A, its analysis (blockanalysis, whose keywords these are) factorized from A's values in every slot of its nb systems.
JosephsonCircuits.fftplans Method
fftplans(fd::AbstractArray{Complex{T}}, td::AbstractArray{T},
stepsperperiod::Int, backend::Backend)Create the inverse real transform plan from the frequency domain array fd to the time domain array td, and the forward plan back, on the given KernelAbstractions backend. The transform runs over all but the last dimension, the last being the Josephson junction index. The inverse plan is the unnormalized backward transform, which gives the time domain samples in the convention of applyifft! with no scaling pass; the forward plan is unnormalized too, and applyfft! scales it.
The CPU() method uses FFTW. A device backend supplies its own method, which is the only thing the residual and the matrix-free products need that the core package cannot provide without taking on the device dependency: every other step of those is either a plain array operation or a kernel of NonlinearTermPlan. Load the package extension for the device (for CUDA, using CUDA) to get its method.
JosephsonCircuits.fillandfactorize! Method
fillandfactorize!(F::SparseBlockFactorization, vals::AbstractMatrix)Refactorize the batch from the stored values vals, one column per system in the order of nonzeros of the pattern, on the backend: the device sweep assembles the values of a batch of frequencies there.
JosephsonCircuits.fillordering Method
fillordering(factorization::AbstractFactorization, A; blocksize = 1)The fill reducing ordering factorization chooses for the sparsity pattern of A: for a KLUfactorization the better of AMD and METIS nested dissection by predicted flops (kluordered), as a FillOrdering carrying its predicted fill, or nothing for KLU's own when neither can be formed or A is not square; nothing for any other factorization, which orders a matrix itself. blocksize is the number of rows of each node of a pattern whose rows come in contiguous node blocks, as a harmonic balance system's modes do: METIS then orders the graph of the nodes, and the default of one, or a size which does not divide the rows, has it order the rows. The ordering depends only on the pattern, so one choice serves every factorization of it: a FactorizationCache keeps the one it chose, and one chosen elsewhere can be handed to it (seedordering!).
JosephsonCircuits.find_duplicate_connections Method
find_duplicate_connections(
connections::AbstractVector{Tuple{T,T,Int,Int}}) where {T}Return a vector of tuples of (connection, counts) where counts is the number of times a given connection appears.
sourceJosephsonCircuits.find_duplicate_network_names Method
find_duplicate_network_names(
networks::AbstractVector{PassiveNetwork{T,N}}) where {T,N}Return a vector of tuples of (networkname, counts) where counts is the number of times a given network name appears.
sourceJosephsonCircuits.forwardsolution! Method
forwardsolution!(phin, ds::DeviceSweep, i::Integer)
adjointsolution!(phin, ds::DeviceSweep, i::Integer)Fill phin with the forward or adjoint solution of frequency i of the batch staged by the last solvebatch!: the whole solution when the direction was staged in full, otherwise only its gathered rows. The form hblinsolve_inner! takes as presolved and presolvedadjoint.
JosephsonCircuits.forwardtermkernel! Method
forwardtermkernel!(phimatrix, n1, s1, n2, s2, flags, xr)Evaluate the map from the equivalent real representation of the unknowns to the frequency domain coefficients of the Josephson junction branch fluxes, one work item per slot of phimatrix. Each work item gathers the at most two node fluxes of its branch through the incidence matrix entries held in the plan, assembles the complex coefficient from the real slots of the real representation, and conjugates it when the slot is a conjugate symmetry target. Every slot is written exactly once, so the destination needs no zeroing and the stores are contiguous. See NonlinearTermPlan.
JosephsonCircuits.forwardtermkernelcomplex! Method
forwardtermkernelcomplex!(phimatrix, cn1, s1, cn2, s2, flags, xc)The complex representation counterpart of forwardtermkernel!, which gathers the same at most two node fluxes through the same incidence entries but addresses them as complex indices, so no real slot arithmetic is needed and the FWIDE flag is not consulted. See NonlinearTermPlan.
JosephsonCircuits.forwardtransposekernel! Method
forwardtransposekernel!(out, tfptr, tfslot, tfcoef, tfimag, Q, ktptr,
ktrow, ktcoef, w)Transpose of the forward map plus the transposed linear term, one work item per real slot of the unknowns. Each item gathers the frequency domain slots which read it and the entries of the transposed linear term which land on it, and writes the single slot it owns.
sourceJosephsonCircuits.fourierindices Method
fourierindices(freq::Frequencies)Generate the indices used in the RDFT or DFT and inverse RDFT or DFT and converting between a node flux vector for solving system and the matrices for the Fourier analysis. See also FourierIndices, Frequencies, calcfreqsrdft and calcfreqsdft.
JosephsonCircuits.freememory Method
freememory(backend)The free memory of backend in bytes: the host's for CPU(); on a CUDA backend (defined by the CUDA extension) the device's, with what CUDA.jl's memory pool holds without an array in it, which an allocation takes first. What Automatic, linearizedfactorization and the device sweep's batch size their choices against.
JosephsonCircuits.freqsubst Function
freqsubst(A::SparseMatrixCSC, terms, kind, wmodes::AbstractVector,
table = providertable(terms, wmodes))The matrix A, of length(wmodes) modes with the mode index fastest, as a SparseMatrixCSC{ComplexF64} on the same pattern, with the frequency dependent terms of kind among terms (see FrequencyDependentTerms, nothing for none) added at each mode, each from the value of its function at the magnitude of the mode frequency, read from table, a row per function and a column per mode, which the matrices of the other kinds can share. The values are the result's own, so that writing them, as the pump solve's conjugation and scaling do, leaves A as it was; the pattern is shared. A negative mode frequency is not conjugated here (see conjnegfreq!).
Examples
julia> A = JosephsonCircuits.diagrepeat(JosephsonCircuits.SparseArrays.sparse([1,2,1], [1,2,2], [1,2,3],2,2),2);
julia> JosephsonCircuits.freqsubst(A, nothing, 1, [-1.0, 2.0])
4×4 SparseArrays.SparseMatrixCSC{ComplexF64, Int64} with 6 stored entries:
1.0+0.0im ⋅ 3.0+0.0im ⋅
⋅ 1.0+0.0im ⋅ 3.0+0.0im
⋅ ⋅ 2.0+0.0im ⋅
⋅ ⋅ ⋅ 2.0+0.0imJosephsonCircuits.frequencydependentcircuit Method
frequencydependentcircuit(psc, circuitdefs, symfreqvar, to)A compiled circuit whose values depending on the symbolic frequency variable symfreqvar are rewritten as FrequencyDependent closures resolving them at circuitdefs and at the frequency, its deprecation going to the entry point or the messages of the call (see warndeprecations).
Every other value is left as it was, including one which still depends on a parameter the definitions do not give, so that the undefined parameter is still reported by checkcomponentvaluesdefined naming its component rather than failing later inside a closure.
JosephsonCircuits.frequencydependentterms Method
frequencydependentterms(plan::CircuitMatrixPlan,
fd::FrequencyDependentComponents)The FrequencyDependentTerms of the frequency dependent components fd of a circuit, from the stamp plans: each contribution of a capacitor or resistor, and each of the inverse inductance of the branch of an inductor, which the coupled branches never are. nothing for nothing.
JosephsonCircuits.gathercanonical! Method
gathercanonical!(u, rint, L::CompositeLayout)Write the internal real state rint into the internal block of the canonical state u, a copy.
The vdc block has no internal counterpart and is left untouched, so a caller which keeps explicit direct current coordinates in u does not lose them here. A solve calls this to form its starting point, and iterates on the internal block of u through internalpart with no copy; the problem interface, which hands out states and residuals of its own, calls it for each.
JosephsonCircuits.gatherportrows! Method
gatherportrows!(out, X, rows, backend)Gather the rows named by rows from every right hand side of every system of the batch X into out, with a kernel on backend. See portsolutionrows.
JosephsonCircuits.gathervalues! Method
gathervalues!(dest::AbstractArray, src::AbstractVector,
index::AbstractArray)dest[k] = src[index[k]] for every k, as a KernelAbstractions kernel on the backend of dest, which src and index must share. The device side of the windowed copies of the canonical layout (_gatherwindow!): index is an injection, so no element is written twice and no atomic is needed.
JosephsonCircuits.get_ports Method
get_ports(network::Tuple{T, N, Vector{Tuple{T, Int}}}) where {T,N}Return the ports for a network network. The ports are already present in the network.
Examples
julia> JosephsonCircuits.get_ports((:S1,[0.0 1.0;1.0 0.0],[(:S1,1),(:S2,3)]))
2-element Vector{Tuple{Symbol, Int64}}:
(:S1, 1)
(:S2, 3)JosephsonCircuits.get_ports Method
get_ports(network::Tuple{T, N}) where {T,N}
get_ports(network::Tuple{T, N, AbstractArray{<:Number}}) where {T,N}Return the ports for a network network given without port names, (name, S) or (name, S, C). The ports are generated based on the network name, numbered in order.
Examples
julia> JosephsonCircuits.get_ports((:S1,[0.0 1.0;1.0 0.0]))
2-element Vector{Tuple{Symbol, Int64}}:
(:S1, 1)
(:S1, 2)JosephsonCircuits.gmres! Method
gmres!(x, Aop!, b, ws::GMRESWorkspace; Mop! = nothing, rtol = 1e-6,
atol = 0.0, maxrestarts = 10, oncycle = nothing)Solve A*x = b with restarted GMRES from the zero start, overwriting x with the solution, where mul!(w, Aop, v) computes w = A*v and the optional Mop! applies a preconditioner z = M \ v, either as a bare in-place closure Mop!(z, v) or as an AbstractPreconditioner, which is applied through applypreconditioner!. The matrix A is never formed; only its action is required, which is what makes this usable with the matrix-free jacobianvectorproduct!.
Preconditioning is applied on the right, solving A*inv(M)*u = b and then x = inv(M)*u. Right preconditioning keeps the recurrence's residual estimate equal to the true residual of the original system, so the stopping test is on norm(b - A*x) and does not depend on the quality of M. Because M is held fixed across a solve, the preconditioner is applied once per Arnoldi step and once more per cycle of two or more steps, rather than being stored for every basis vector; a cycle of one step reuses the application its step made.
The Arnoldi basis is built by block classical Gram-Schmidt with an unconditional second pass, CGS2 (gmres_orthogonalize!). A subdiagonal which collapses relative to the vector it came from is a (lucky) breakdown: the Krylov space is invariant, the reduced least squares solution is exact, and the cycle ends there rather than continuing with a spurious basis vector. The residual is recomputed explicitly at every restart so restarts cannot drift from the recurrence estimate.
Converges when norm(b - A*x) <= max(rtol*norm(b), atol), a norm which is not finite never. Returns the named tuple (iterations, residual, converged, cycles, reason, precondtime, residualvector, products), where iterations counts Arnoldi steps across all cycles, cycles the number of restart cycles begun, reason is one of :converged, :breakdown (an unhappy breakdown: the Krylov space went invariant without the residual coming down), :stagnation (a cycle failed to reduce the explicit residual, or produced a non-finite one; a non-finite product or preconditioner application ends its cycle at that Arnoldi step and leaves x where the cycle started), :nonfinite (the norm of b is not finite, from an entry which is not or from finite entries whose norm overflows, and sets no tolerance: nothing is solved, x is zero and residual that norm), or :iterationlimit, precondtime the seconds spent applying the preconditioner, and residualvector the final residual b - A*x when it was formed explicitly (nothing otherwise; the caller reads it with get, as it does precondtime and products).
iterations is not the total number of Aop! calls: each cycle costs one further application for the explicit residual recomputation; products in the returned tuple is that total, not counting products a preconditioner takes inside its own application. maxrestarts bounds the number of cycles including the first, so the Arnoldi work is capped at maxrestarts*m steps. oncycle(ws, j), when given, is called at the end of every cycle with the workspace still holding that cycle's j Arnoldi vectors, for a caller which harvests from each cycle (harvestcycle!); it must only read the workspace.
Allocation free once the basis has grown to the columns the iteration uses (ensurecolumns!), apart from whatever Aop! and Mop! themselves allocate.
JosephsonCircuits.gmres_applyrotations! Method
gmres_applyrotations!(H, cs, sn, s, j)Reduce column j of the Hessenberg matrix H to upper triangular form: apply the j-1 previous Givens rotations to the new column, compute and store the rotation which annihilates the new subdiagonal H[j+1, j], and apply it to the least squares right hand side s. After this the magnitude of s[j+1] is the residual norm of the least squares problem, which with right preconditioning is the true residual norm of the original system. Allocation free.
JosephsonCircuits.gmres_correction! Method
gmres_correction!(x, ws::GMRESWorkspace, j, Mop!)Solve the reduced j x j triangular least squares problem by back substitution, assemble the correction u = V[:, 1:j]*y in the Krylov basis, undo the right preconditioning once with Mop! (or not at all when Mop! === nothing), and add the result to x in place. After a cycle of one step the preconditioned basis vector its Arnoldi step left in ws.z is scaled and added instead, without applying Mop! again. A zero diagonal entry, which can only arise from an exact breakdown, contributes a zero coefficient rather than a division by zero. Allocation free.
JosephsonCircuits.gmres_givens Method
gmres_givens(a, b)The Givens rotation (c, s, r) with c*a + s*b = r and -s*a + c*b = 0, computed through hypot so it cannot overflow, with the identity rotation returned for the zero input.
JosephsonCircuits.gmres_orthogonalize! Method
gmres_orthogonalize!(w, V, H, hd, c, j)Orthogonalize w against the first j Arnoldi basis vectors (the columns of V) by block classical Gram-Schmidt with one reorthogonalization (CGS2), accumulating the coefficients into column j of the Hessenberg matrix H. c is scratch of length at least j. Both passes accumulate into the same entries of H, so H remains the exact projection. Writes the subdiagonal H[j+1, j] and returns (hsub, normw0): the norm of the orthogonalized w and its norm on entry, the pair the caller compares to detect a breakdown.
CGS2 is chosen over modified Gram-Schmidt with a DGKS test for its shape rather than its accuracy, which is equivalent: both are orthogonal to machine precision. Each pass here is two level 2 BLAS calls over the whole basis, where the modified form is j dependent pairs of a dot product and an axpy, each dot having to complete before the axpy that follows it. The second pass is unconditional, which costs what the DGKS path costs whenever it does reorthogonalize and removes a branch on a freshly computed scalar. Neither the coefficient vector nor the branch has to reach the host, which is what makes this form usable on a device.
JosephsonCircuits.groupdestinations Method
groupdestinations(destinations)Group scalar contributions by the stored entry they are added to, as (order, dest, segptr): the contributions sorted by destination, the distinct destinations, and the offset of each one's run in order, so that group k is order[segptr[k]:segptr[k+1]-1] and every one of its members has destination dest[k].
This is what lets scatteringstampkernel! accumulate without an atomic: distinct groups write distinct addresses.
JosephsonCircuits.halmos_dilation Method
halmos_dilation(S; atol = 0, rtol = ...)Return the Halmos dilation of the passive lossy scattering parameter matrix S. This converts a passive lossy scattering parameter matrix into a lossless (unitary) scattering parameter matrix, [S sqrt(I - S*S'); sqrt(I - S'*S) -S'], whose ports after the first size(S, 1) carry the loss of S. An n by m matrix S dilates to an n + m by n + m one, twice the number of ports for a square S.
S is passive when none of its singular values exceeds one. A singular value above one by no more than max(atol, rtol), as rounding leaves those of a lossless S, is taken as one; beyond that S is refused. The default rtol is that of isapprox and is_unitary, the square root of the machine epsilon of the element type of S, and zero when atol is given.
Examples
julia> JosephsonCircuits.is_unitary(JosephsonCircuits.halmos_dilation([0.1 0;0 0.1]))
trueReferences
[1] P. L. Robinson, “Julia operators and Halmos dilations,” Mar. 25, 2018, arXiv:1803.09329. doi: 10.48550/arXiv.1803.09329. [2] B. Sz.-Nagy, C. Foias, H. Bercovici, and L. Kérchy, Harmonic Analysis of Operators on Hilbert Space. New York, NY: Springer, 2010. doi: 10.1007/978-1-4419-6094-8. [3] P. R. Halmos, “Normal dilations and extensions of operators,” Summa Brasiliensis Mathematicae, vol. II, no. VI, pp. 125–134, Dec. 1950. [4] J. J. Schäffer, “On Unitary Dilations of Contractions,” Proceedings of the American Mathematical Society, vol. 6, no. 2, pp. 322–322, 1955, doi: 10.2307/2032368. [5] B. Szőkefalvi-Nagy, “Sur les contractions de l’espace de Hilbert,” ACTA SCIENTIARUM MATHEMATICARUM, vol. 15, pp. 87–92, 1954.
sourceJosephsonCircuits.harvestcycle! Method
harvestcycle!(pc::AbstractPreconditioner, ws::GMRESWorkspace, j::Integer)Give the preconditioner pc the Arnoldi factorization of the restart cycle which has just ended, j vectors of it, before gmres! overwrites the workspace with the next cycle, so that it can extract information for the next solve from every cycle, the early full ones included. Called through the oncycle callback of gmres! for a preconditioner which asks for it (usescycleharvest). The default does nothing, which is correct for any preconditioner that does not recycle.
JosephsonCircuits.hasnewcandidates Method
hasnewcandidates(pc::AbstractPreconditioner)Whether pc holds deflation candidates its last build did not take in, which a rebuild at the same point would: those a FloquetPreconditioner banked from the harvests of the solves since its last build. false for a preconditioner which does not deflate. nlsolvekrylov! reads it to tell whether retrying a step whose line search found no decrease, from a preconditioner rebuilt at its point, can change the step.
JosephsonCircuits.hasports Method
hasports(component)Whether the component exposes bundled two terminal port views addressable in pair connections.
sourceJosephsonCircuits.hasrealbackward Method
hasrealbackward(plan::NonlinearTermPlan)Whether plan carries the real form of the linear term, and so whether the real representation backward map can be applied. False for a plan built with realbackward = false. The complex representation is always available.
JosephsonCircuits.hbconjmatind Method
hbconjmatind(truncfrequencies::Frequencies{N})Returns a matrix describing which indices of the frequency domain matrix (from the RFFT) to pull out and use in the conjugate harmonic balance matrix, which is built from the sums of the modes, aliased back onto the sampled grid, and describes the coupling between the modes and the complex conjugates of the modes (the derivative of the residual with respect to the complex conjugates of the node fluxes). A negative index means we take the complex conjugate of that element. A zero index means that term is not present, so skip it. See also hbmatindices.
Examples
julia> freq = JosephsonCircuits.calcfreqsrdft((3,));JosephsonCircuits.hbconjmatind(JosephsonCircuits.removeconjfreqs(JosephsonCircuits.truncfreqs(freq;dc=true,odd=true,even=true,maxintermodorder=2)))
4×4 Matrix{Int64}:
1 2 3 4
2 3 4 -4
3 4 -4 -3
4 -4 -3 -2JosephsonCircuits.hbconjmatind Method
hbconjmatind(frequencies::Frequencies{N},
truncfrequencies::Frequencies{N})Returns a matrix describing which indices of the frequency domain matrix (from the RFFT) to pull out and use in the conjugate harmonic balance matrix, which is built from the sums of the modes truncfrequencies.modes[i] + truncfrequencies.modes[j], aliased back onto the sampled grid described by frequencies. A negative index means we take the complex conjugate of that element. A zero index means that term is not present, so skip it. See also hbmatindices.
JosephsonCircuits.hblinearsolve! Method
hblinearsolve!(ls, deltax, jvp!, F, ws, Mop!; rtol, atol, maxrestarts,
oncycle = nothing)Solve for the Newton step and return the output named tuple gmres! produces. converged, residual, iterations, cycles and reason are required; residualvector (the explicit final residual, which the line search slope reads, at the cost of one extra Jacobian product when it is missing), precondtime and products are read with get and may be omitted by an external solver. jvp!(y, v) applies the Jacobian, in place, and Mop! is the preconditioner, an AbstractPreconditioner or a closure Mop!(z, r). oncycle is the per-cycle callback of gmres!, which a solver that does not restart may ignore.
This is the one part of the Newton-Krylov loop with nothing harmonic balance specific about it: an operator, a right hand side, a preconditioner and a tolerance. Putting it behind an interface lets an external Krylov library be substituted without touching anything else.
sourceJosephsonCircuits.hblinsolve_inner! Method
hblinsolve_inner!(ws::LinearizedWorkspace, arrays::LinearizedArrays,
sensitivity, lsys, bnm, ports, channels, nodeindices,
componenttypes, w, wpumpmodes, Nmodes, wi, factorization;
presolved = nothing, presolvedadjoint = nothing,
presolvednoise = nothing, presolvedtable = nothing, refine = true)Solve the linearized problem at the frequencies w[wi], using the workspace ws, assembling each system matrix from the HBLinearizedSystem lsys with assemblesystemmatrix! and writing the results into the LinearizedArrays arrays through per frequency views. An empty output array means that output was not requested; small working matrices stand in for outputs which are computed but not stored (S when only the quantum efficiency needs it).
sensitivity is a named tuple with the fixed operating point stamps, the operating point dAop stamps of the forward contraction order, the ReverseSensitivity of the reverse order, or nothing, and the blockentries of the scattering block parameters, one (stamp index, derivative system, positions) per block pair, from which each worker rebuilds the block stamps at every frequency (see WorkerBlockSensitivity). channels is a named tuple with the noise channels of the sweep: the indices and impedances of the dissipative components, the plan of the channels of the scattering blocks (ScatteringNoisePlan, or nothing), their number N, the temperatures of every channel and the signs of each in the commutation relations (see noisechannelsigns). ports is a named tuple with the ports' component indices, their reference impedances and the temperatures of their terminations, in the order of the port axes. presolved, presolvedadjoint and presolvednoise are callbacks which replace the assemble, factorize and solve of a frequency, the transposed solve, and the noise scattering calculation with solutions computed elsewhere, which is how the device sweep hands back its batches (see devicesolutions); a caller which supplies the solution supplies the transposed one too whenever an output reads it, since the transposed solve here needs the factors of a solve here. presolvedtable fills the values of the frequency dependent functions at a frequency's modes from where they were evaluated for its solve, in place of evaluating them again.
Different frequency ranges may be computed in parallel: lsys, sensitivity and arrays (through disjoint views) are shared, and each task has its own ws.
JosephsonCircuits.hbmatindices Method
hbmatindices(frequencies::Frequencies{N},
Amatrixmodes::AbstractMatrix{NTuple{N,Int}}; alias::Bool = false)The index matrix of the harmonic balance matrix, which describes the coupling between the modes: for the mode difference of each pair of modes in Amatrixmodes (the ModeDifferences of the retained modes), the element of the frequency domain array of the untruncated grid frequencies (from the RFFT or FFT) that coupling reads. A negative index means the complex conjugate of that element is taken, and a zero index that the term is not present, so it is skipped. With alias = true a difference which falls outside the sampled grid is aliased back onto it by the periodicity of the discrete transform (aliasmode) rather than dropped; the linearized solver uses alias = false, which makes the assembled matrix an explicit truncation. The differences are an argument so that a solve which needs the indices both with and without aliasing forms them once.
Examples
pumpfreq = JosephsonCircuits.calcfreqsrdft((4,))
signalfreq = JosephsonCircuits.truncfreqs(
JosephsonCircuits.calcfreqsdft((4,));
dc=false,odd=true,even=false,maxintermodorder=2,
)
JosephsonCircuits.hbmatindices(pumpfreq,
JosephsonCircuits.ModeDifferences(signalfreq.modes))
# output
4×4 Matrix{Int64}:
1 -3 5 3
3 1 0 5
-5 0 1 -3
-3 -5 3 1pumpfreq = JosephsonCircuits.calcfreqsrdft((4,))
signalfreq = JosephsonCircuits.truncfreqs(
JosephsonCircuits.calcfreqsdft((4,));
dc=false,odd=true,even=false,maxintermodorder=2,
)
JosephsonCircuits.hbmatindices(pumpfreq,
JosephsonCircuits.ModeDifferences(signalfreq.modes); alias = true)
# output
4×4 Matrix{Int64}:
1 -3 5 3
3 1 -4 5
-5 4 1 -3
-3 -5 3 1JosephsonCircuits.hessianvectorproduct! Method
hessianvectorproduct!(Hvw::AbstractVector, sys::HBSystem,
v::AbstractVector, w::AbstractVector)Evaluate the exact matrix-free second directional derivative of the harmonic balance nonlinear system, H(x)[v, w] = B(-sin.(A*x) .* (A*v) .* (A*w)), at the point set with setpoint!, in place. The frequency dependent linear terms are linear in x so they do not contribute. Dispatches on the element types: complex vectors receive the complex representation and real vectors the equivalent real representation. The product is symmetric in v and w. Useful for continuation and bifurcation tracking methods which require directional second derivatives.
JosephsonCircuits.hostrelations Method
hostrelations(r::JunctionRelations)
hostrelations(r::JunctionRelations, rows::AbstractVector{Int})The table on the host, for the host loops which cannot read a device array, and with rows the table of that subset of the junctions, in that order, which is what a projection onto part of the circuit reads.
JosephsonCircuits.hostsparse Method
hostsparse(A::DeviceValuedSparseMatrix)
hostsparse(A::SparseMatrixCSC)Bring a matrix whose values live on a backend home as an ordinary SparseMatrixCSC, copying both the structure and the values. A host matrix is returned unchanged.
The structure is held as the transpose (see DeviceValuedSparseMatrix), so this is a copy back followed by a sparse transpose rather than a reinterpretation. Both are proportional to the number of stored entries of the one matrix, which is why this is worth doing for something retained once, such as the real Jacobian of a pump operating point, and not for something produced per signal frequency, such as a solution of the linearized system.
JosephsonCircuits.hostsystem Method
hostsystem(sys::HBSystem, Nbranches::Integer, bnm, relations)An HBSystem on the host in double precision at the values of sys, with its own transforms, workspaces and copies of the value arrays: the system the operating point of a solve on a device, in single precision, or through a reuse is differentiated on. The source bnm and the junction relations relations (nothing when every junction is sinusoidal) are the double precision ones the solve was set up with, rather than the copies sys holds in the precision of its iteration.
JosephsonCircuits.impedance Method
impedance(c, code::Integer, w)The impedance of a component of value c and type code at frequency w, conjugating the stored value at a negative frequency.
The numeric implementation, called by calcimpedance on the host and directly from the kernels which compute power waves on a backend.
JosephsonCircuits.impedancecode Method
impedancecode(type)The impedance code of a component type, or an error for a type which has no impedance.
JosephsonCircuits.import_netlist! Method
import_netlist!(io::IO, circuit)Import the netlist from the IOBuffer or IOStream io to the vector of tuples circuit.
Examples
julia> io = IOBuffer();circuit1=[("P","1","0",1),("R","1","0",50.0)];JosephsonCircuits.export_netlist!(io,circuit1,Dict());circuit2 = Tuple{String,String,String,Any}[];JosephsonCircuits.import_netlist!(io,circuit2);circuit2
2-element Vector{Tuple{String, String, String, Any}}:
("P", "1", "0", 1.0)
("R", "1", "0", 50.0)JosephsonCircuits.import_netlist Method
import_netlist(filename)Import the netlist from the file with name and path filename and return it as a vector of (name, node1, node2, value) tuples. The value field is Any: a number for a literal, a symbol for a name and a Symbolics value for an expression (see parsecomponentvalue).
JosephsonCircuits.indefinite_hermitian_form_block Method
indefinite_hermitian_form_block(n::Int)Return the 2n x 2n matrix representing the indefinite Hermitian form Σ for n modes in the annihilation and creation operator basis with block order ξ = [a_1,...,a_n,adag_1,...,adag_n] where Σ = [1_n 0_n;0_n -1_n]. 0_n is an n by n matrix of zeros and 1_n is an n by n identity matrix.
Examples
julia> using LinearAlgebra
julia> JosephsonCircuits.indefinite_hermitian_form_block(2)
4×4 Diagonal{Int64, Vector{Int64}}:
1 ⋅ ⋅ ⋅
⋅ 1 ⋅ ⋅
⋅ ⋅ -1 ⋅
⋅ ⋅ ⋅ -1JosephsonCircuits.indefinite_hermitian_form_pair Method
indefinite_hermitian_form_pair(n)Return the 2n x 2n matrix representing the indefinite Hermitian form Σ for n modes in the annihilation and creation operator basis with pair order ξ = [a_1,adag_1,...,a_n,adag_n] where Σ = direct sum of n of σ3 where σ3 = [1 0; 0 -1].
Examples
julia> JosephsonCircuits.indefinite_hermitian_form_pair(2)
4×4 SparseArrays.SparseMatrixCSC{Int64, Int64} with 4 stored entries:
1 ⋅ ⋅ ⋅
⋅ -1 ⋅ ⋅
⋅ ⋅ 1 ⋅
⋅ ⋅ ⋅ -1JosephsonCircuits.initialblockcurrents! Method
initialblockcurrents!(x, Amna, Nnodal, auxoffset)Set the port currents of the scattering blocks, the unknowns of x after auxoffset, to the values the blocks' constitutive rows of the augmentation Amna give at the node fluxes x[1:Nnodal], so that a start from node fluxes begins with those rows at zero, as the coupled inductor currents do (mnainitialauxind!), rather than with a residual which is the blocks' whole response. The rows are linear in the fluxes and the currents, and are solved for the currents by a sparse QR, so a current they do not determine (that of a block which is a short at a mode) stays at zero.
JosephsonCircuits.initialguess Method
initialguess(x0)The initial guess x0 of a nonlinear solve as a Vector{ComplexF64}, empty when there is none (nothing); a node flux matrix of a previous solve, keyed or plain, is flattened in the solver's own layout.
JosephsonCircuits.innerpreconditioner Function
innerpreconditioner(pc::AbstractWrappedPreconditioner)The preconditioner pc wraps.
JosephsonCircuits.instancedefinition Method
instancedefinition(elab::ElaboratedCircuit, i::Integer)The component definition of flattened instance i.
JosephsonCircuits.instanceterminals Method
instanceterminals(elab::ElaboratedCircuit, i::Integer)A view of the net indices of the terminals of flattened instance i.
JosephsonCircuits.interconnectS_inner! Method
interconnectS_inner!(Sout, Cout, Sa, Sb, Ca, Cb, k::Int, l::Int,
batch::AbstractArray)See interconnectS for description.
JosephsonCircuits.interconnectS_inner! Method
interconnectS_inner!(Sout,Sa,Sb,k::Int,l::Int,batch::AbstractArray)See interconnectS for description.
JosephsonCircuits.interconnectSports Method
interconnectSports(portsa::AbstractVector, portsb::AbstractVector, k::Int,
l::Int)Return the ports, such as tuples of (networkname, portindex), with portsa from the first network and portsb from the second network after ports k and l from the first and second networks have been connected. If the first network has n ports and the second network has m ports, then the combined network has (m+n-2) ports. See connectS for more information.
Examples
julia> JosephsonCircuits.interconnectSports([(:S1,1),(:S1,2),(:S1,3),(:S1,4),(:S1,5)],[(:S2,1),(:S2,2),(:S2,3),(:S2,4),(:S2,5)],3,4)
8-element Vector{Tuple{Symbol, Int64}}:
(:S1, 1)
(:S1, 2)
(:S1, 4)
(:S1, 5)
(:S2, 1)
(:S2, 2)
(:S2, 3)
(:S2, 5)JosephsonCircuits.internalpart Method
internalpart(u::AbstractVector, L::CompositeLayout)The internal block of a canonical vector u, as a view: the first L.rdim entries, which the harmonic system reads and writes in place.
JosephsonCircuits.interpolate_scattering Method
interpolate_scattering(w0::AbstractVector, S::AbstractArray, w::AbstractArray;
extrap = false, extrap_value = 0.0)Interpolate the scattering parameters S, an array of size (nports, nports, length(w0)) tabulated at the strictly increasing frequencies w0, at least three of them, onto the frequencies w. w may be a matrix such as the one returned by wmatrix, in which case the result has one matrix per entry of it.
Each entry is interpolated as the product of a delay and a slowly varying complex function: the delay tau is the least squares slope of the unwrapped phase of the samples, and the real and imaginary parts of the undelayed samples S*cis(w0*tau) are interpolated quadratically, then multiplied by cis(-w*tau). A delay line is then followed exactly however often its phase winds between the samples, and a transmission zero, where the magnitude has a kink and the phase a step, is crossed smoothly.
A negative frequency takes the complex conjugate of the value at its magnitude. A frequency within rounding of an end of w0, such as an idler of wmatrix formed from the signal and the pump, takes the value at that end. With extrap = true a frequency whose magnitude is outside w0 takes the value extrap_value (conjugated at a negative frequency); otherwise it is a DomainError.
Examples
w = 0.01:0.01:1.0
S = JosephsonCircuits.ABCD_tline(50,w)
isapprox(S,JosephsonCircuits.interpolate_scattering(w,S,w))
# output
trueJosephsonCircuits.intraconnectS_inner! Method
intraconnectS_inner!(Sout, Sa, k::Int, l::Int, batch::AbstractArray)See intraconnectS for description.
JosephsonCircuits.intraconnectSports Method
intraconnectSports(portsa::AbstractVector, k::Int, l::Int)Return the ports portsa of a network, such as tuples of (networkname, portindex), after its ports k and l have been connected. See connectS for more information.
Examples
julia> JosephsonCircuits.intraconnectSports([(:S1,1),(:S1,2),(:S1,3),(:S1,4),(:S1,5)],3,4)
3-element Vector{Tuple{Symbol, Int64}}:
(:S1, 1)
(:S1, 2)
(:S1, 5)JosephsonCircuits.inv_bogoliubov_block Method
inv_bogoliubov_block(S)Return the inverse of the Bogoliubov matrix S computed from transpose(Ω)*transpose(S)*Ω where Ω is the symplectic form for block operator ordering.
Examples
julia> S = JosephsonCircuits.rand_bogoliubov_block(2);isapprox(inv(S),JosephsonCircuits.inv_bogoliubov_block(S))
trueJosephsonCircuits.inv_bogoliubov_pair Method
inv_bogoliubov_pair(S)Return the inverse of the Bogoliubov matrix S computed from transpose(Ω)*transpose(S)*Ω where Ω is the symplectic form for pair operator ordering.
Examples
julia> S = JosephsonCircuits.rand_bogoliubov_pair(2);isapprox(inv(S),JosephsonCircuits.inv_bogoliubov_pair(S))
trueJosephsonCircuits.inv_symplectic_block Method
inv_symplectic_block(S)Return the inverse of the symplectic matrix S computed from transpose(Ω)*transpose(S)*Ω where Ω is the symplectic form for block operator ordering.
Examples
julia> S = JosephsonCircuits.rand_symplectic_block(2);isapprox(inv(S),JosephsonCircuits.inv_symplectic_block(S))
trueJosephsonCircuits.inv_symplectic_pair Method
inv_symplectic_pair(S)Return the inverse of the symplectic matrix S computed from transpose(Ω)*transpose(S)*Ω where Ω is the symplectic form for pair operator ordering.
Examples
julia> S = JosephsonCircuits.rand_symplectic_pair(2);isapprox(inv(S),JosephsonCircuits.inv_symplectic_pair(S))
trueJosephsonCircuits.inverseinductanceplan Method
inverseinductanceplan(topology, inductivebranches, coupled)Build the InverseInductancePlan from the incidence matrix of topology, the branches which carry an inductance, and the branches which are mutually coupled.
JosephsonCircuits.is_bogoliubov_block Method
is_bogoliubov_block(M) -> BoolReturn true if the matrix M is Bogoliubov, M ∈ Sp(2n, ℂ) ∩ U(n, n), with block operator order and false otherwise.
JosephsonCircuits.is_bogoliubov_pair Method
is_bogoliubov_pair(M) -> BoolReturn true if the matrix M is Bogoliubov, M ∈ Sp(2n, ℂ) ∩ U(n, n), with pair operator order and false otherwise.
JosephsonCircuits.is_conjugate_symplectic_block Method
is_conjugate_symplectic_block(M) -> BoolReturn true if the matrix M is conjugate symplectic, M*Ω*M' == Ω with Ω the symplectic form of block operator order, and false otherwise.
JosephsonCircuits.is_conjugate_symplectic_pair Method
is_conjugate_symplectic_pair(M) -> BoolReturn true if the matrix M is conjugate symplectic, M*Ω*M' == Ω with Ω the symplectic form of pair operator order, and false otherwise.
JosephsonCircuits.is_cptp Method
is_cptp(Omega, X, Y; hbar = 1, atol = 0, rtol = ...) -> BoolReturn true if the Gaussian map V -> X*V*X' + Y of the transformation X and the noise Y is completely positive and trace preserving for the symplectic form Omega, that is if K = Y + im*(hbar/2)*(Omega - X*Omega*X') is Hermitian and positive semi-definite, and false otherwise.
The quadrature functions share one convention, with the scale hbar. The quadratures of a mode with the ladder operators [a, adag] = 1 are x = sqrt(hbar/2)*(a + adag) and p = -im*sqrt(hbar/2)*(a - adag), with [x, p] = im*hbar; the covariance of the quadratures r is V = ⟨{Δr, Δrᵀ}⟩/2, and that of the vacuum (hbar/2)*I. The default hbar = 1 counts the vacuum as half a photon, as circuit quantum electrodynamics does; hbar = 2 gives the covariance σ of Serafini, whose vacuum is I, and the condition of his Eq. 5.37. hbar must be finite and positive.
K is a difference of terms which cancel, exactly so for a noiseless map (Y = 0 with X symplectic), so it is judged against their scale s = norm(Y) + (hbar/2)*norm(Omega)*(1 + opnorm(X)^2) rather than against itself: K is Hermitian when norm(K - K') <= tol and positive semi-definite when the smallest eigenvalue of its Hermitian part is at least -tol, with tol = max(atol, rtol*s). The default rtol is the square root of the machine epsilon of the element type, and zero when atol is given.
References
A. Serafini, "Quantum Continuous Variables: A Primer of Theoretical Methods," CRC Press (2017).
sourceJosephsonCircuits.is_cptp_ladder_block Method
is_cptp_ladder_block(X, Y; atol = 0, rtol = ...) -> Boolis_cptp_ladder_pair in block operator order.
JosephsonCircuits.is_cptp_ladder_pair Method
is_cptp_ladder_pair(X, Y; atol = 0, rtol = ...) -> Boolis_cptp for the ladder (Bogoliubov) transformation X and noise Y in pair operator order. The ladder operators are dimensionless, [a, adag] = 1, and Y is a symmetrized covariance ⟨{Δξ, Δξ†}⟩/2 of ξ = [a_1, adag_1, ...], whose vacuum is I/2; ladder_to_quadrature_pair takes it to the quadrature covariance at hbar = 1.
JosephsonCircuits.is_cptp_quadrature_block Method
is_cptp_quadrature_block(X, Y; hbar = 1, atol = 0, rtol = ...) -> Boolis_cptp for the quadrature transformation X and noise Y in block operator order, in the units of hbar stated there.
JosephsonCircuits.is_cptp_quadrature_pair Method
is_cptp_quadrature_pair(X, Y; hbar = 1, atol = 0, rtol = ...) -> Boolis_cptp for the quadrature transformation X and noise Y in pair operator order, in the units of hbar stated there.
JosephsonCircuits.is_orthogonal Method
is_orthogonal(M) -> BoolReturn true if the matrix M is orthogonal, M ∈ O(n), and false otherwise.
Tests if M is square and satisfies the condition M*transpose(M)==I where I is the identity matrix. A rectangular matrix with orthonormal rows, such as [1 0], is not orthogonal.
JosephsonCircuits.is_orthogonal_bogoliubov_block Method
is_orthogonal_bogoliubov_block(M) -> BoolReturn true if the matrix M is orthogonal Bogoliubov, M ∈ Sp(2n, ℂ) ∩ U(n, n) ∩ U(2n) ≅ U(n), with block operator order and false otherwise.
JosephsonCircuits.is_orthogonal_bogoliubov_pair Method
is_orthogonal_bogoliubov_pair(M) -> BoolReturn true if the matrix M is orthogonal Bogoliubov, M ∈ Sp(2n, ℂ) ∩ U(n, n) ∩ U(2n) ≅ U(n), with pair operator order and false otherwise.
JosephsonCircuits.is_orthogonal_symplectic_block Method
is_orthogonal_symplectic_block(M) -> BoolReturn true if the matrix M is orthogonal symplectic, M ∈ Sp(2n, ℝ) ∩ O(2n) ≅ U(n), with block operator order and false otherwise.
JosephsonCircuits.is_orthogonal_symplectic_pair Method
is_orthogonal_symplectic_pair(M) -> BoolReturn true if the matrix M is orthogonal symplectic, M ∈ Sp(2n, ℝ) ∩ O(2n) ≅ U(n), with pair operator order and false otherwise.
JosephsonCircuits.is_positive_definite Method
is_positive_definite(M) -> BoolReturn true if the matrix M is positive definite and false otherwise.
JosephsonCircuits.is_positive_definite_symplectic_block Method
is_positive_definite_symplectic_block(S) -> BoolReturn true if the matrix S is positive definite and symplectic, S ∈ Sp(2n, ℝ) or S ∈ Sp(2n, ℂ), with block operator order and false otherwise.
JosephsonCircuits.is_positive_definite_symplectic_pair Method
is_positive_definite_symplectic_pair(S) -> BoolReturn true if the matrix S is positive definite and symplectic, S ∈ Sp(2n, ℝ) or S ∈ Sp(2n, ℂ), with pair operator order and false otherwise.
JosephsonCircuits.is_positive_semi_definite Method
is_positive_semi_definite(M) -> BoolReturn true if the matrix M is positive semi-definite and false otherwise.
JosephsonCircuits.is_pseudo_unitary Method
is_pseudo_unitary(Σ,M) -> BoolReturn true if the matrix M is pseudo-unitary, M ∈ U(n, n), and false otherwise.
Tests if M satisfies the pseudo-unitary condition M*Σ*M'==Σ where Σ is a user supplied matrix representing the indefinite Hermitian form.
See also indefinite_hermitian_form_pair, indefinite_hermitian_form_block, is_pseudo_unitary_block, and is_pseudo_unitary_pair.
JosephsonCircuits.is_pseudo_unitary_block Method
is_pseudo_unitary_block(M) -> BoolReturn true if the matrix M is pseudo-unitary, M ∈ U(n, n), with block operator order and false otherwise.
Tests if M*Σ*M'==Σ where Σ is a matrix representing the indefinite Hermitian form with block operator order.
See also indefinite_hermitian_form_block.
JosephsonCircuits.is_pseudo_unitary_pair Method
is_pseudo_unitary_pair(M) -> BoolReturn true if the matrix M is pseudo-unitary, M ∈ U(n, n), with pair operator order and false otherwise.
Tests if M*Σ*M'==Σ where Σ is a matrix representing the indefinite Hermitian form with pair operator order.
See also indefinite_hermitian_form_pair.
JosephsonCircuits.is_symplectic Method
is_symplectic(Ω, S) -> BoolReturn true if the matrix S is symplectic, S ∈ Sp(2n, ℝ) or S ∈ Sp(2n, ℂ), and false otherwise.
Tests if S satisfies the symplectic condition S*Ω*transpose(S)==Ω where Ω is a user supplied symplectic form.
See also symplectic_form_block, symplectic_form_pair, is_symplectic_block, and is_symplectic_pair.
JosephsonCircuits.is_symplectic_block Method
is_symplectic_block(S) -> BoolReturn true if the matrix S is symplectic, S ∈ Sp(2n, ℝ) or S ∈ Sp(2n, ℂ), with block operator order and false otherwise.
Tests if S satisfies the symplectic condition S*Ω*transpose(S)==Ω where Ω is the matrix representing the symplectic form with block operator order.
See also symplectic_form_block.
JosephsonCircuits.is_symplectic_pair Method
is_symplectic_pair(S) -> BoolReturn true if the matrix S is symplectic, S ∈ Sp(2n, ℝ) or S ∈ Sp(2n, ℂ), with pair operator order and false otherwise.
Tests if S satisfies the symplectic condition S*Ω*transpose(S)==Ω where Ω is the matrix representing the symplectic form with pair operator order.
See also symplectic_form_pair.
JosephsonCircuits.is_unitary Method
is_unitary(M) -> BoolReturn true if the matrix M is unitary, M ∈ U(n), and false otherwise.
Tests if M is square and satisfies the condition M*M'==I where I is the identity matrix. A rectangular matrix with orthonormal rows, such as [1 0], is not unitary.
JosephsonCircuits.isaugmented Method
isaugmented(p::HBNonlinearProblem)Whether p carries an explicit direct current block, so that its unknowns are the canonical state rather than the harmonic one.
JosephsonCircuits.isexactpreconditioner Method
isexactpreconditioner(pc::AbstractPreconditioner)Whether pc currently applies the exact Jacobian, so that a deflation or composition layered on top of it can contribute nothing. false for any preconditioner that does not say otherwise.
JosephsonCircuits.isgrounded Method
isgrounded(c)Whether a multiport component's second terminals are all tied to ground, so that only its first terminals connect (grounded = true at construction).
JosephsonCircuits.ismnaresistance Method
ismnaresistance(value)Return true if value is a constant, real, finite, nonzero resistance, which is what the port impedance scale of calcsolverscale is taken from. Real numbers and complex numbers with zero imaginary part are accepted; symbolic values, values with nonzero imaginary part, zeros, and non-finite values return false.
Examples
julia> JosephsonCircuits.ismnaresistance(50.0)
true
julia> JosephsonCircuits.ismnaresistance(50.0+0.0im)
true
julia> JosephsonCircuits.ismnaresistance(50.0+1.0im)
false
julia> JosephsonCircuits.ismnaresistance(0.0)
falseJosephsonCircuits.isnumericallyzero Method
isnumericallyzero(value, terms)Return true if value, the floating point result of a linear combination of the given terms, is approximately zero up to roundoff error.
Examples
julia> JosephsonCircuits.isnumericallyzero(2*pi*1.0 + (2*pi*(5e9-1) - 2*pi*5e9), (2*pi*1.0, -2*pi*5e9, 2*pi*(5e9-1)))
true
julia> JosephsonCircuits.isnumericallyzero(2*pi*1.0, (2*pi*1.0, 0.0, 0.0))
falseJosephsonCircuits.isolatedsubnetworks Method
isolatedsubnetworks(c::CompiledCircuit)The subnetworks which no element connects to ground: the connected components of the nodes joined by every capacitor, resistor, inductor, junction and scattering block port, whatever their values, leaving out the one which holds ground. Each is a sorted vector of node indices.
sourceJosephsonCircuits.issinusoidal Method
issinusoidal(c::NonlinearInductor)Whether the current-phase relation of c is the sinusoidal Josephson relation sin, which the solvers evaluate as sin and cos (see junctioncpr). Every NonlinearInductor compiles to the :Lj type, and one with another relation has it recorded beside the table (see CompiledCircuit).
JosephsonCircuits.iwasawa_block Method
iwasawa_block(S::AbstractMatrix)Return the Iwasawa (KAN) decomposition K, A, N of the symplectic matrix S. K is a unitary symplectic matrix (maximal compact), A is a diagonal symplectic matrix (Abelian), and N is a block upper triangular symplectic matrix whose first diagonal block is unit upper triangular (nilpotent). The matrices are symplectic with respect to the block symplectic form Ω. This decomposition is unique.
References
[1] Arvind, B. Dutta, N. Mukunda, and R. Simon, “The real symplectic groups in quantum mechanics and optics,” Pramana - J Phys, vol. 45, no. 6, pp. 471–497, Dec. 1995, doi: 10.1007/BF02848172. [2] M. Benzi and N. Razouk, “On the Iwasawa decomposition of a symplectic matrix,” Applied Mathematics Letters, vol. 20, no. 3, pp. 260–265, Mar. 2007, doi: 10.1016/j.aml.2006.04.004. [3] M. Houde, W. McCutcheon, and N. Quesada, “Matrix decompositions in Quantum Optics: Takagi/Autonne, Bloch-Messiah/Euler, Iwasawa, and Williamson,” Can. J. Phys., vol. 102, no. 10, pp. 497–507, Oct. 2024, doi: 10.1139/cjp-2024-0070.
sourceJosephsonCircuits.iwasawa_bogoliubov_block Method
iwasawa_bogoliubov_block(S::AbstractMatrix)The Iwasawa decomposition iwasawa_block of the Bogoliubov matrix S of the ladder operators in block order, through its quadrature form: the factors are Bogoliubov matrices in block order.
JosephsonCircuits.iwasawa_bogoliubov_pair Method
iwasawa_bogoliubov_pair(S::AbstractMatrix)The Iwasawa decomposition iwasawa_block of the Bogoliubov matrix S of the ladder operators in pair order, through its quadrature form: the factors are Bogoliubov matrices in pair order.
JosephsonCircuits.iwasawa_pair Method
iwasawa_pair(S::AbstractMatrix)The pair ordered form of iwasawa_block: S and the factors are in pair order.
JosephsonCircuits.jacobian! Method
jacobian!(Jx::SparseMatrixCSC{<:Complex}, sys::HBSystem)
jacobian!(Jr::SparseMatrixCSC{<:Real}, sys::HBSystem)
jacobian!(A::DeviceValuedSparseMatrix, sys::HBSystem)Assemble the Jacobian of the harmonic balance nonlinear system at the point set with setpoint!, in place, using the precomputed plans. Dispatches on the element type of the matrix: a complex matrix receives the complex holomorphic Jacobian (an approximation to the exact Jacobian, used by the QuasiNewton method, via assemblecomplexjacobian!) and a real matrix the exact Jacobian of the equivalent real system (used by the Newton method, via assemblerealjacobian!). A DeviceValuedSparseMatrix receives the same into its device values, and nothing crosses to the host: the coefficients are already on the backend and the assembly runs there. The corresponding plan must have been provided when the HBSystem was constructed; the method taking a plan explicitly is documented below.
JosephsonCircuits.jacobian! Method
jacobian!(Jr::SparseMatrixCSC, plan::StructureRealJacobianPlan,
sys::HBSystem)Assemble the real Jacobian described by plan at the point set with setpoint!, in place. This is the method jacobian!(Jr, sys) delegates to with the plan stored in sys; taking the plan explicitly lets a different plan, built over the same system, be assembled from the same Fourier coefficients of cos(phi(t)) and the same linear term matrices.
JosephsonCircuits.jacobianvectorproduct! Method
jacobianvectorproduct!(Jv::AbstractVector, sys::HBSystem,
v::AbstractVector)Evaluate the exact matrix-free Jacobian-vector product of the harmonic balance nonlinear system, J(x)*v = B(cos.(A*x) .* (A*v)) + K*v, at the point set with setpoint!, in place. Dispatches on the element types: complex vectors receive the complex representation and real vectors the equivalent real representation, for which the product equals the assembled real Jacobian (jacobian!) applied to vr up to floating point roundoff, including the self-conjugate (eg. DC) modes. Each product costs two Fourier transforms and the linear term; the time domain cosine is cached across products at the same point. Suitable as the operator for Krylov methods.
JosephsonCircuits.jjnodeadjacency Method
jjnodeadjacency(Ljb::SparseVector, nodesandsigns, Nnodes::Integer)For each node, return the sorted, deduplicated list of nodes which share at least one Josephson junction branch with it (including itself), from the per-branch (node, sign) lists in nodesandsigns (see branchnodesandsigns) restricted to the Josephson branches in Ljb. Used to enumerate the columns of the Jacobian sparsity structure directly in compressed sparse column form.
JosephsonCircuits.josephsonadjoint! Method
josephsonadjoint!(P, Q, plan::StructureComplexJosephsonPlan,
w::AbstractVector)Apply the transpose of the Josephson map: accumulate w, which is indexed by stored entry, back onto the Fourier coefficients it was gathered from.
The plain and conjugated contributions land in P and Q respectively, because the caller treats the two halves differently downstream. Which of the two a stored entry belongs to is decided by the sign of its mode coupling index, and a stored entry names one mode pair, so an entry contributes to one of them and never both.
This runs on the host: it is a scatter with collisions, it is used only by the sensitivity calculation, and that calculation is a host loop throughout.
sourceJosephsonCircuits.junctioncpr Function
junctioncpr(c::NonlinearInductor, path)The relation the solvers evaluate for c: nothing for the sinusoidal Josephson relation, which they hold as sin and cos, or the PolynomialCPR they evaluate by Horner. Any other callable throws, since a relation the solvers cannot write down is one they cannot transform.
The coefficients are converted to Float64 here, so that the table the solvers build is concrete whatever the user wrote them as.
JosephsonCircuits.junctionpairtable Method
junctionpairtable(::Type{Ti}, ::Type{T}, Ljb::SparseVector, nodesandsigns,
Nnodes::Integer)The junctions incident on each ordered node pair, as a compressed sparse column structure over the second node: ptr, the row n1, the junction, and the product of the two incidence signs.
This is the whole of the incidence triple product, and it has one entry per (junction, node, node) triple: four per junction for a two terminal one.
The entries of a pair are ordered by junction index, which fixes the order the assembly sums them in. That order is part of the result, because floating point addition is not associative.
sourceJosephsonCircuits.junctionrelations Method
junctionrelations(cprs::AbstractVector)The JunctionRelations of the junctions whose relations are cprs, one entry per junction in the order of the junction axis, each either nothing for the sinusoidal Josephson relation or a PolynomialCPR. Returns nothing when every entry is nothing.
JosephsonCircuits.junctionstructure Method
junctionstructure(::Type{T}, Amatrixindices::Matrix,
Amatrixconjindices::Matrix, Ljb::SparseVector, Lscale,
Rbnm::SparseMatrixCSC, Nmodes::Integer, Nbranches::Integer,
Nfreq::Integer, backend)Build the JunctionStructure of a system in precision T on backend. The pair table is indexed in Int32, which the node and junction counts never exceed; a plan's own structure keeps whatever index type its size needs.
JosephsonCircuits.klunodeorder Method
klunodeorder(adj::AbstractVector{<:AbstractVector{<:Integer}})The elimination order of the circuit nodes from KLU's symbolic analysis of the node graph: its block triangular form permutation followed by the fill reducing ordering within the blocks. On a chain this walks the chain; on a meshed circuit it fills less than a bandwidth reducing order and gives a far shallower elimination tree.
sourceJosephsonCircuits.kluordered Method
kluordered(A::SparseMatrixCSC; kwargs...)
kluordered(A::SparseMatrixCSC, ordering; kwargs...)KLU.klu(A) with its fill reducing ordering chosen by measurement (fillordering), or handed in as ordering: a FillOrdering, or nothing for KLU's own. KLU's own default, AMD on the pattern of A + A', is the right ordering for most circuit matrices and a pathological one for some of the mode-coupling patterns the preconditioners of this package factorize: the harmonic band of a two-tone line is a mode lattice crossed with the spatial chain, a grid-like graph, on which minimum degree fills many times more than nested dissection. Nested dissection is not uniformly better either: on the full Jacobian of the same line it fills more than AMD.
So both permutations are computed, AMD and METIS nested dissection, each through the CHOLMOD library that ships with Julia, the flops of the factorization each would need are predicted from the elimination tree (symbolicfill), and the cheaper one is handed to KLU as a given ordering; a harmonic balance sweep has METIS order the graph of its nodes rather than of its rows (fillordering's blocksize). KLU takes a given ordering without the maximum transversal it finds for its own, so where the diagonal of A has structural zeros, as the Jacobian of a circuit with scattering blocks can have, a maximum transversal matches its rows to columns first: the pattern so permuted is ordered, its fill predicted, and KLU is handed the row and the column permutations, a zero-free diagonal for its pivots. Should either ordering fail, KLU's default is used. Everything before the numeric factorization is symbolic and depends only on the sparsity pattern: the numeric refactorizations of the pattern reuse the whole analysis, and a FactorizationCache keeps the ordering for every fresh factorization of it.
KLU has no estimate of the fill of an ordering it is handed, and reserves ten times the entries of A for each factor, which it trims once the factorization is done. A FillOrdering carries the fill its choice predicted, which is the size of each factor under it without pivoting, so KLU is asked for that, with the margin it gives its own AMD estimate, and grows a factor which pivoting fills beyond it. kwargs are check and allowsingular of KLU.klu.
JosephsonCircuits.klupivotgrowth Method
klupivotgrowth(F::KLU.KLUFactorization)The largest pivot of the KLU factorization F in magnitude. KLU factorizes the matrix with each row scaled to a largest entry of one, so this bounds the growth of the elimination from below, and it is what a pivot which has become small inflates: eliminating with a pivot of size d adds entries of size 1/d to the rows it updates, and to their diagonal when the pattern is structurally symmetric, as circuit matrices are. O(n), read from the diagonal of U KLU keeps.
JosephsonCircuits.klurefactor! Method
klurefactor!(F::KLU.KLUFactorization, A::SparseMatrixCSC, pivottol;
kwargs...)Refactorize F from the values of A, whose pattern is the one F was analyzed for, with the pivot sequence of its last factorization (KLU.klu!), and factorize the same values again with fresh partial pivoting (KLU.klu_factor!, which reuses the symbolic analysis) when that sequence is unstable for them: when a pivot is exactly zero, or when the pivot growth (klupivotgrowth) exceeds 1/pivottol. kwargs are those of KLU.klu!. Returns F.
JosephsonCircuits.ladder_to_quadrature_block Method
ladder_to_quadrature_block(S::AbstractMatrix)Return the matrix S, which maps ladder operators in block order [a_1, ..., adag_1, ...] to others, as the map between the quadratures in block order [x_1, ..., p_1, ...]: R1*S*R2' with R1 and R2 the matrices of R_ladder_to_quadrature_block for the rows and the columns of S.
JosephsonCircuits.ladder_to_quadrature_block Method
ladder_to_quadrature_block(r::AbstractVector)Return the vector r of ladder operators in block order [a_1, ..., adag_1, ...] in the basis of the quadratures in block order [x_1, ..., p_1, ...], R*r with R the matrix of R_ladder_to_quadrature_block.
JosephsonCircuits.ladder_to_quadrature_pair Method
ladder_to_quadrature_pair(S::AbstractMatrix)Return the matrix S, which maps ladder operators in pair order [a_1, adag_1, ...] to others, as the map between the quadratures in pair order [x_1, p_1, ...]: R1*S*R2' with R1 and R2 the matrices of R_ladder_to_quadrature_pair for the rows and the columns of S.
JosephsonCircuits.ladder_to_quadrature_pair Method
ladder_to_quadrature_pair(r::AbstractVector)Return the vector r of ladder operators in pair order [a_1, adag_1, ...] in the basis of the quadratures in pair order [x_1, p_1, ...], R*r with R the matrix of R_ladder_to_quadrature_pair.
JosephsonCircuits.ladder_to_scattering_block! Method
ladder_to_scattering_block!(S_scattering, S_bogoliubov, w; atol = 0,
rtol = ...)In place version of ladder_to_scattering_block, writing into S_scattering.
JosephsonCircuits.ladder_to_scattering_block Method
ladder_to_scattering_block(S_bogoliubov, w; atol = 0, rtol = ...)Return the scattering matrix whose ladder (Bogoliubov) form in block operator order is S_bogoliubov, between modes of signed frequencies w; the inverse of scattering_to_ladder_block. See ladder_to_scattering_pair for the tolerances.
JosephsonCircuits.ladder_to_scattering_pair! Method
ladder_to_scattering_pair!(S_scattering, S_bogoliubov, w; atol = 0,
rtol = ...)In place version of ladder_to_scattering_pair, writing into S_scattering.
JosephsonCircuits.ladder_to_scattering_pair Method
ladder_to_scattering_pair(S_bogoliubov, w; atol = 0, rtol = ...)Return the scattering matrix whose ladder (Bogoliubov) form in pair operator order is S_bogoliubov, between modes of signed frequencies w; the inverse of scattering_to_ladder_pair. Each entry is the average of the two entries of the form holding it and its conjugate; if their difference, or an entry of the form which should be zero, exceeds max(atol, rtol*norm(S_bogoliubov)), it is an error. The default rtol is the smaller dimension of S_bogoliubov times the machine epsilon of its element type, and zero when atol is given. Input which is not of floating point type, such as symbolic input, is converted with both tolerances zero.
JosephsonCircuits.ldiv_2x2 Method
ldiv_2x2(fact,b)Solve the linear system A*x = b for x using left division when given fact which is the LU factorization of A. A singular A is solved when the system is consistent, with the unknown of a zero diagonal entry of the upper triangular factor taken as zero; otherwise an ArgumentError is thrown.
JosephsonCircuits.linearentry Method
linearentry(lcolptr, lrowval, lnzval, gcolptr, growval, gnzval, wm,
ccolptr, crowval, cnzval, wm2, ci, cj, dr, dc)
linearentry(lcolptr, lrowval, lnzval, gcolptr, growval, gnzval, wm,
ccolptr, crowval, cnzval, wm2, ci, cj)The constant linear term invLnm + im*Gnm*wmodesm - Cnm*wmodes2m at the complex position (ci, cj): the entry at offset (dr, dc) of its real block (realblockterm), or without an offset the complex value. The three matrices, compressed by columns, are looked up at the position, the last two scaled by the mode frequency diagonals wm and wm2 at the column, and summed in the order invLnm, Gnm, Cnm: floating point addition is not associative, so the order is part of the result.
JosephsonCircuits.lineargather Method
lineargather(::Type{Ti}, colptr, rowval, invLnm, Gnm, Cnm, wmodesm,
wmodes2m, layout, lptr, transposed::Bool, backend)The LinearTermGather of a plan whose structure is colptr, rowval on backend, the Jacobian's transpose when transposed. Every position stored in one of the three matrices is expanded to the entries of its real block through layout, whose pointer lptr is on the backend, or kept whole for a complex plan (layout = lptr = nothing), and located in the structure. The walk is over the entries of the three matrices, so it costs their size and not the plan's.
JosephsonCircuits.linearizedfactorization Method
linearizedfactorization(A::SparseMatrixCSC, Nmodes::Integer,
ntones::Integer, backend; nbatches = 1,
budget = memorybudget(backend))The factorization of the linearized solve when none is given. One tone takes the backend's sparse factorization, KLUfactorization on the host and CUDSSFactorization on a device. Two or more tones take BlockFactorization in double when the factors of one system (blocksystembytes), times the nbatches host batches, which hold one each, fit in budget, and the sparse factorization otherwise. Several tones make the node blocks large and dense, which the block factorization eliminates with dense LAPACK and BLAS-3 kernels where a scalar factorization works one entry at a time. It pivots within a node block only and stops at a singular one with a SingularException, where hblinsolve solves its sweep again with the sparse factorization, which pivots across the whole matrix; KLU also keeps the sparsity within the node blocks, which the resonators of a line have, and takes less memory.
JosephsonCircuits.linearizedoutputs Method
linearizedoutputs(; ...)The last stage of hblinsolve: the LinearizedHB of the sweep, its arrays keyed by mode, port, node and frequency when asked. It takes the compiled circuit for the names it records, which no stage before it reads.
JosephsonCircuits.linearizedsensitivity Method
linearizedsensitivity(; ..., reversecrossover = 8)The second stage of hblinsolve: the components and the scattering block parameters the sensitivities are taken with respect to, the sensitivity stamps of the requested ones, and the operating point contribution in the contraction order chosen (sensitivitymode), either as forward stamps or as a ReverseSensitivity. Returns the named tuple the workers of the sweep read (see hblinsolve_inner!), whose arrays are empty when no sensitivity was asked for, and the names and the indices of the sensitivity axis which the outputs record. The keywords are the fields of linearizedsetup this stage reads, the operating point and the sensitivity arrays, and reversecrossover, the number of components per scattering parameter, (Nports*Nmodes)^2 of them, past which sensitivitymode = :auto takes the reverse order: the cost of a transposed solve of the pump Jacobian in products against the linearized system, estimated, which is not critical since near the crossover either order costs about the same.
JosephsonCircuits.linearizedsetup Method
linearizedsetup(w, psc, vvn, signalfreq, nonlinear,
factorization, backend, temperature; nbatches, wantsnoise,
blocksensitivities)The first stage of hblinsolve: the circuit matrices at the signal mode count, the pump's cosine transform from the nonlinear solution (or unity without one), the mode frequencies and the checks on them, the modified nodal analysis padding, the port sources, the noise channels with their temperatures, the HBLinearizedSystem with its system matrix assembled, and the factorization the sweep uses, chosen for the host when blocksensitivities says that sensitivities with respect to scattering block parameters are asked for, whose stamps keep the sweep there. Returned as a named tuple whose fields the later stages read by name.
JosephsonCircuits.linearizedsweep! Method
linearizedsweep!(; ...)The third stage of hblinsolve: the sweep over the signal frequencies, on the backend in batches when the system allows it and on host threads otherwise, each frequency solved by hblinsolve_inner! into the LinearizedArrays returned. The keywords are the fields of the two stages before which this one reads, among them sensitivity, the named tuple of linearizedsensitivity, the length Ncomponents of the sensitivity axis, and the LinearizedRequests requests.
JosephsonCircuits.linearterm! Method
linearterm!(Knm, maps::ValueMaps, invLnm, Gnm, Cnm, wmodesm, wmodes2m)linearterm in place, through the maps: the same three terms in the same order, so the values are the ones the allocating form gives.
JosephsonCircuits.linearterm Method
linearterm(invLnm, Gnm, Cnm, wmodesm::Diagonal, wmodes2m::Diagonal,
T = Float64)Collapse the frequency dependent linear terms of the harmonic balance system into the single sparse matrix of element type Complex{T}
K = invLnm + im*Gnm*wmodesm - Cnm*wmodes2mso that applying them is one gather over the entries of an output row rather than three sparse matrix-vector products and two diagonal scalings through two temporaries. The mode frequency diagonals are fixed for the lifetime of an HBSystem, so this is formed once when the system is constructed and handed to plannonlinearterm, which stores it transposed in both representations.
Every stored entry of the three matrices has its place in K, a zero valued one included, so that the structure of K is that of the circuit and not of the values it was formed at, which a system rebound to other values (see rebind!) relies on; only the frequency terms of a zero frequency column, which vanish whatever the values, are left out.
JosephsonCircuits.linesearchevaluate! Method
linesearchevaluate!(f!, F, xcandidate, x, α, deltax, beta, correction)Evaluate the line search merit function at the trial step α: generate the trial point with linesearchtrialpoint!, evaluate the residual there with f!(F, xcandidate), and return merit(F). xcandidate and F contain the trial point and its residual when this function finishes.
JosephsonCircuits.linesearchtrialpoint! Method
linesearchtrialpoint!(xcandidate, x, α, deltax, beta, correction)Overwrite xcandidate with the line search trial points on the curvilinear path: xcandidate = x + α*deltax - beta*α²*correction, or the straight path x + α*deltax when correction == nothing or beta == 0. Overwrites and returns xcandidate.
JosephsonCircuits.lu_2x2 Method
lu_2x2(A)Return the LU factorization of a 2 by 2 matrix as a StaticArrays.LU struct. Perform the LU factorization even if A is singular.
JosephsonCircuits.matrixprovider Method
matrixprovider(x, T; n = nothing, interpolation = :cubic,
extrapolation = :error, form = :matrix)Normalize user input into an AbstractMatrixProvider with element type T: a matrix becomes a ConstantMatrixProvider, a tuple (frequencies, values) a TabulatedMatrixProvider, a callable of angular frequency a CallableMatrixProvider (which requires the dimension n and accepts form), and an existing provider is returned as is. n, when given, is checked against the data.
JosephsonCircuits.memorybudget Method
memorybudget(backend)The bytes the factors and batches a solve sizes for itself may take on backend: FREEMEMORYSHARE, half, of its free memory (freememory). What Automatic (resolveautomatic), the growth of a preconditioner's coupling set (escalatepreconditioner!), linearizedfactorization and the batch of the device sweep (devicesolutions) are held to.
JosephsonCircuits.mergecolumns Method
mergecolumns(dF, grouping)The residual derivative columns dF of the pairs summed by the groups of grouping, one column per group, the grouping of mergestamps: one product with the incidence of the pairs on their groups, so that a sparse dF stays sparse and the merge costs its stored entries. Each group's sum runs over its pairs in their order.
JosephsonCircuits.mergestamps Method
mergestamps(stamps, grouping)Concatenate the stamps of each group of grouping into one. A design parameter typically touches many components – a single junction inductance across a two thousand cell line – and the contraction cost is per stamp, so merging turns one contraction per component into one per parameter (and kind). The grouping comes from parametergrouping, so it is the same one applied to the residual derivative columns.
JosephsonCircuits.merit Method
merit(F)The line search merit function ϕ = 0.5*||F||² = real(0.5*dot(F, F)). The dot product conjugates the first argument so this can be used for real or complex vectors.
JosephsonCircuits.meritslope! Method
meritslope!(Jv, jvp, p, F, ϕ0, w)The slope real(F' J p) of the merit function ϕ = F'F/2 along the step p, where p = -Δ for a linear solve J Δ ≈ F which left the explicit residual w = F - J Δ.
Then J p = w - F and the slope is real(F'w) - 2ϕ0: one inner product, with the Jacobian vector product the solve already paid for. Without a valid residual (w === nothing), the product is taken.
JosephsonCircuits.mnacoupledbranches Method
mnacoupledbranches(Mb::SparseMatrixCSC)Return the sorted branch indices which participate in mutual inductive coupling, the union of the row and column supports of the branch mutual inductance matrix Mb. These branches are assigned auxiliary branch current variables by the modified nodal analysis formulation instead of being eliminated through the inverse of the branch inductance matrix, so the system matrix entries remain bounded as the coupling coefficient approaches one, where the inverse inductance entries of the nodal formulation diverge as 1/(1-k^2).
JosephsonCircuits.mnagaugenormalize! Method
mnagaugenormalize!(x::AbstractVector,
floatingcomponents::Vector{Vector{Int}}, wmodes::Vector,
Nmodes::Int)Transform an initial guess into the gauge selected by the gauge fixing equations by subtracting, for each floating component of the static flux-stiffness graph and each zero-frequency mode, the flux of the component's reference node from the fluxes of all nodes of the component. A common shift of the DC fluxes of a floating component leaves every branch flux, and therefore every physical circuit quantity and every Kirchhoff current law residual, unchanged - it is exactly the gauge degree of freedom - but it does enter the gauge fixing rows. Normalizing the guess makes physically equivalent initial values produce identical augmented residuals and makes the reference-node gauge rows exactly zero at the initial value.
sourceJosephsonCircuits.mnainitialauxind! Method
mnainitialauxind!(x::AbstractVector, coupledbranches::Vector{Int},
Lb::SparseVector, Mb::SparseMatrixCSC, Rbn::SparseMatrixCSC,
Nmodes::Int, auxoffset::Int, Lscale)Initialize the auxiliary branch current variables of the mutually coupled inductors consistently with the node fluxes in x, by solving the branch inductance system (L/Lscale)*u = Rbn*phi over the coupled branches, with one sparse factorization for every mode, which zeros their constitutive rows exactly. If the branch inductance matrix is singular (a perfectly coupled pair, |k| = 1) the auxiliary variables are left unchanged: the full system can still be well posed and solvable in that case, because the constitutive equations use the un-inverted branch inductance matrix, so only this warm start refinement is skipped.
JosephsonCircuits.mnapad Method
mnapad(A::SparseMatrixCSC, Naux::Int)Pad the sparse matrix A with Naux empty rows and columns, returning a square matrix suitable for the augmented modified nodal analysis system.
JosephsonCircuits.mnaungaugedkcl Method
mnaungaugedkcl(F::AbstractVector, x::AbstractVector,
gaugeindices::Vector{Int}, Nnodal::Int)Reconstruct the residuals of the original, ungauged Kirchhoff current law equations from the augmented residual F and the state x. The gauge fixing equations add x[g] to the augmented residual of each gauge row g, so the physical residual is F[g] - x[g] at the gauge rows and F[i] elsewhere in the node block. This is the quantity which must be small for the reported solution to satisfy the original circuit equations: a gauge equation can otherwise absorb an incompatibility (for example a net direct current injected into a floating subnetwork which slipped past the direct current subsystem's solvability check) into the arbitrary flux reference while the augmented residual converges to zero.
JosephsonCircuits.mnavalidatekcl Method
mnavalidatekcl(F::AbstractVector, x::AbstractVector,
gaugeindices::Vector{Int}, Nnodal::Int, bnm::AbstractVector, atol;
kclfactor = 10)Validate the original, ungauged Kirchhoff current law equations at a converged solution by reconstructing their residuals with mnaungaugedkcl and comparing their infinity norm against a block-relative infinity-norm tolerance,
kclfactor*atol*(1 + norm(bnm[1:Nnodal], Inf)),
so both sides have the same per-row interpretation and the accepted error in any one equation does not grow with the number of driven rows. The tolerance is deliberately independent of the achieved augmented residual (which would be circular) and of the auxiliary current entries of the state, which are not Kirchhoff current law quantities. A non-finite reconstructed norm, or a non-finite source scale (which would make the tolerance infinite and accept anything), fails the validation. Returns (ok, normkcl, kcltol) so a diagnostic can report the achieved residual against the applied tolerance.
JosephsonCircuits.modebandmask Method
modebandmask(Amatrixmodes::AbstractMatrix, p)Return the Nmodes x Nmodes boolean matrix of mode coupling blocks retained by a bandwidth restriction on the harmonic offset: the block coupling column mode m2 into row mode m1 is kept when the offset between them, Amatrixmodes[m1, m2] = modes[m1] .- modes[m2], is within p.
This is the restriction the structure of the Jacobian asks for. Multiplication by cos(phi(t)) is a convolution in the harmonic index, so the nonlinear part of the Jacobian is block Toeplitz in the offset m1 - m2: every block shares the junction incidence sparsity and they differ only by the Fourier coefficient of cos(phi(t)) at that offset. Those coefficients are Bessel-like in the junction phase amplitude and fall off quickly once the offset exceeds it, so truncating by offset keeps the large blocks and drops the small ones.
p may be
an
Integer: the number of offset shells retained beyond the diagonal, where a shell is one distinct value of the total intermodulation ordersum(abs, offset)that the retained mode set actually realizes, oran
NTuple{N,Integer}: an absolute per-tone bound,abs.(offset) .<= p, for a grid whose coupling is anisotropic, eg. a strong pump and a weak second tone.
Counting shells rather than bounding the raw offset matters, because the offsets a mode set realizes are not the integers. With the usual odd-harmonic-only truncation every mode difference is even, so sum(abs, offset) <= 1 retains exactly what <= 0 does and a raw bound of one would silently be the block diagonal. A shell count is also the quantity the coupling decays in: the Fourier coefficients of cos(phi(t)) live on the harmonic lattice of phi, and the shells are the lattice distances that lattice actually has.
p = 0 is the mode block diagonal and a p large enough to cover the grid is the full Jacobian, so the bandwidth is a graded ladder between the two, which escalatepreconditioner! climbs one step at a time.
Examples
julia> modes = [(-1,), (0,), (1,)];
julia> A = [modes[i] .- modes[j] for i in 1:3, j in 1:3];
julia> JosephsonCircuits.modebandmask(A, 0)
3×3 Matrix{Bool}:
1 0 0
0 1 0
0 0 1
julia> JosephsonCircuits.modebandmask(A, 1)
3×3 Matrix{Bool}:
1 1 0
1 1 1
0 1 1JosephsonCircuits.modeclusters Method
modeclusters(keep::AbstractMatrix{Bool})The connected components of two or more modes of the coupling graph whose edges are the off-diagonal true entries of keep, read symmetrically; each as its sorted mode list.
JosephsonCircuits.modes_ports_to_ports_modes_block Method
modes_ports_to_ports_modes_block(S::AbstractMatrix,Nmodes::Int)Reorder both axes of the block ordered ladder or quadrature form S of a scattering matrix of Nmodes modes per port from (modes, ports) to (ports, modes) ordering, each of the two blocks of an axis alike; see modes_ports_to_ports_modes_perm. Half the length of each axis must be a multiple of Nmodes.
Examples
S = [:S11 :S12 :S13 :S14 :S15 :S16 :S17 :S18; :S21 :S22 :S23 :S24 :S25 :S26 :S27 :S28; :S31 :S32 :S33 :S34 :S35 :S36 :S37 :S38; :S41 :S42 :S43 :S44 :S45 :S46 :S47 :S48; :S51 :S52 :S53 :S54 :S55 :S56 :S57 :S58; :S61 :S62 :S63 :S64 :S65 :S66 :S67 :S68; :S71 :S72 :S73 :S74 :S75 :S76 :S77 :S78; :S81 :S82 :S83 :S84 :S85 :S86 :S87 :S88]
JosephsonCircuits.modes_ports_to_ports_modes_block(S,2)
# output
8×8 Matrix{Symbol}:
:S11 :S13 :S12 :S14 :S15 :S17 :S16 :S18
:S31 :S33 :S32 :S34 :S35 :S37 :S36 :S38
:S21 :S23 :S22 :S24 :S25 :S27 :S26 :S28
:S41 :S43 :S42 :S44 :S45 :S47 :S46 :S48
:S51 :S53 :S52 :S54 :S55 :S57 :S56 :S58
:S71 :S73 :S72 :S74 :S75 :S77 :S76 :S78
:S61 :S63 :S62 :S64 :S65 :S67 :S66 :S68
:S81 :S83 :S82 :S84 :S85 :S87 :S86 :S88JosephsonCircuits.modes_ports_to_ports_modes_pair Method
modes_ports_to_ports_modes_pair(S::AbstractMatrix,Nmodes::Int)Reorder both axes of the pair ordered ladder or quadrature form S of a scattering matrix of Nmodes modes per port from (modes, ports) to (ports, modes) ordering, moving the two operators of each scattering index together; see modes_ports_to_ports_modes_perm. Half the length of each axis must be a multiple of Nmodes.
Examples
S = [:S11 :S12 :S13 :S14 :S15 :S16 :S17 :S18; :S21 :S22 :S23 :S24 :S25 :S26 :S27 :S28; :S31 :S32 :S33 :S34 :S35 :S36 :S37 :S38; :S41 :S42 :S43 :S44 :S45 :S46 :S47 :S48; :S51 :S52 :S53 :S54 :S55 :S56 :S57 :S58; :S61 :S62 :S63 :S64 :S65 :S66 :S67 :S68; :S71 :S72 :S73 :S74 :S75 :S76 :S77 :S78; :S81 :S82 :S83 :S84 :S85 :S86 :S87 :S88]
JosephsonCircuits.modes_ports_to_ports_modes_pair(S,2)
# output
8×8 Matrix{Symbol}:
:S11 :S12 :S15 :S16 :S13 :S14 :S17 :S18
:S21 :S22 :S25 :S26 :S23 :S24 :S27 :S28
:S51 :S52 :S55 :S56 :S53 :S54 :S57 :S58
:S61 :S62 :S65 :S66 :S63 :S64 :S67 :S68
:S31 :S32 :S35 :S36 :S33 :S34 :S37 :S38
:S41 :S42 :S45 :S46 :S43 :S44 :S47 :S48
:S71 :S72 :S75 :S76 :S73 :S74 :S77 :S78
:S81 :S82 :S85 :S86 :S83 :S84 :S87 :S88JosephsonCircuits.modes_ports_to_ports_modes_perm Method
modes_ports_to_ports_modes_perm(Nports,Nmodes)Return a permutation vector that converts one axis of a scattering matrix with Nports ports and Nmodes modes from (modes, ports) ordering to (ports, modes) ordering, the inverse of ports_modes_to_modes_ports_perm, where the orderings are described.
Examples
For 2 ports and 4 modes the (modes, ports) ordering is [(p1,m1), (p1,m2), (p1,m3), (p1,m4), (p2,m1), (p2,m2), (p2,m3), (p2,m4)] and the (ports, modes) ordering is [(p1,m1), (p2,m1), (p1,m2), (p2,m2), (p1,m3), (p2,m3), (p1,m4), (p2,m4)]:
julia> p = JosephsonCircuits.modes_ports_to_ports_modes_perm(2,4)
8-element Vector{Int64}:
1
5
2
6
3
7
4
8JosephsonCircuits.modes_ports_to_ports_modes_scattering Method
modes_ports_to_ports_modes_scattering(S::AbstractMatrix,Nmodes::Int)Reorder both axes of the scattering matrix S of Nmodes modes per port from (modes, ports) to (ports, modes) ordering; see modes_ports_to_ports_modes_perm. The length of each axis must be a multiple of Nmodes.
Examples
S = [:S11 :S12 :S13 :S14 :S15 :S16 :S17 :S18; :S21 :S22 :S23 :S24 :S25 :S26 :S27 :S28; :S31 :S32 :S33 :S34 :S35 :S36 :S37 :S38; :S41 :S42 :S43 :S44 :S45 :S46 :S47 :S48; :S51 :S52 :S53 :S54 :S55 :S56 :S57 :S58; :S61 :S62 :S63 :S64 :S65 :S66 :S67 :S68; :S71 :S72 :S73 :S74 :S75 :S76 :S77 :S78; :S81 :S82 :S83 :S84 :S85 :S86 :S87 :S88]
JosephsonCircuits.modes_ports_to_ports_modes_scattering(S,2)
# output
8×8 Matrix{Symbol}:
:S11 :S13 :S15 :S17 :S12 :S14 :S16 :S18
:S31 :S33 :S35 :S37 :S32 :S34 :S36 :S38
:S51 :S53 :S55 :S57 :S52 :S54 :S56 :S58
:S71 :S73 :S75 :S77 :S72 :S74 :S76 :S78
:S21 :S23 :S25 :S27 :S22 :S24 :S26 :S28
:S41 :S43 :S45 :S47 :S42 :S44 :S46 :S48
:S61 :S63 :S65 :S67 :S62 :S64 :S66 :S68
:S81 :S83 :S85 :S87 :S82 :S84 :S86 :S88JosephsonCircuits.modeslotindex Method
modeslotindex(layout::ModeLayout)The vector, of length layout.rdim, giving the mode index of each slot of the real representation.
JosephsonCircuits.modevalue Method
modevalue(v, w)The value a linear term matrix entry contributes in a column belonging to a mode with (signed) frequency w: the stored value for the non negative frequency modes and its complex conjugate for the negative frequency modes. This is the single definition of the negative frequency conjugation convention, used by conjnegfreq! (which bakes it into a matrix), by sparseaddconjsubst! (which applies it during assembly), and by sensitivitystampvalue (which applies it to the sensitivity stamps).
JosephsonCircuits.mutualstampplan Method
mutualstampplan(c::CompiledCircuit)Build the MutualStampPlan of a compiled circuit and its graph, and return it with the sorted branches the couplings touch. The sign of each coupling's stamps carries it from the terminal order the netlist declared to the orientation the graph gave its two branches. A coupling names two inductors, which the parse of the circuit holds it to.
JosephsonCircuits.ncomponents Method
ncomponents(c::CompiledCircuit)The number of entries in the flat component table.
sourceJosephsonCircuits.needsadjointsolve Method
needsadjointsolve(arrays::LinearizedArrays,
noiseportimpedanceindices, noiseplan)Whether the transposed (adjoint) linearized system must be solved at each signal frequency: for the scattering parameter sensitivities always, and otherwise when a consumer of the adjoint solution (the noise scattering parameters, the noise covariances, the quantum efficiency, the occupations, the commutation relations, or the adjoint node outputs) is requested together with a source of it. The dissipative scattering blocks of the ScatteringNoisePlan noiseplan, nothing without any, are such a source, as the lumped noise ports are.
This does not depend on the frequency, and both the host loop and the device sweep test it, the latter to decide whether to allocate and solve the adjoint direction at all (with cuDSS a whole second factorization, with a block factorization a second solve against the same factors).
sourceJosephsonCircuits.negsecondat Method
negsecondat(r::JunctionRelations, phi)The negative of the second derivative of the relation of every junction at the branch phases phi, sin.(phi) for the Josephson relation: the change of the differential inductance with the phase, which the derivative of a linearization with respect to the phases carries. The counterpart of derivativeat.
JosephsonCircuits.ninstances Method
ninstances(elab::ElaboratedCircuit)The number of flattened primitive instances.
sourceJosephsonCircuits.nlsolve! Method
nlsolve!(fj!, F, J, x; iterations = 1000, atol = 1e-8, rtol = 0.0,
factorization = KLUfactorization(), cache = FactorizationCache(),
linesearch = Backtracking(), andersondepth = 5, andersonbeta = 1.0,
andersonacceptfactor = 0.9)Newton's method with a line search and Anderson acceleration, suited to quasi-Newton problems with an approximate Jacobian. fj!(F, J, x) must write the residual into F when F !== nothing and the Jacobian into J when J !== nothing. x is updated in place and holds the solution on return; F holds the residual there.
Each iteration solves J*pₖ = -F for the Newton step and forms the Type-II Anderson correction cₖ = (Sₖ + Yₖ)γₖ from a depth- andersondepth history of iterate and update differences (the Newton fixed point map G(x) = x + pₖ has fixed point residual pₖ, which is stored). The step is then chosen by measurement:
- The Anderson candidate
x + pₖ - andersonbeta*cₖis evaluated, and
accepted if its residual norm improves on the current one by at least andersonacceptfactor. An accepted candidate records alpha = NaN.
- Otherwise both line searches are run and compared: the curvilinear path
x + α*pₖ - andersonbeta*α²*cₖ, starting from the value of (1), and the linear path x + α*pₖ; the point with the lower merit function is taken. A curvilinear trial point which satisfies the Armijo condition at the full step is accepted without comparison. After both line searches have failed the solver gives the curved path priority, taking the linear path only when the curved one produces non-finite values. See dualsearch!.
- Without a usable correction (an empty history, or a failed coefficient
solve) only the linear line search runs.
A stall of an iteration which took accelerated steps is retried once from the initial point with the curved path given priority, within the same budget of iterations steps; the record keeps both attempts, the second's residual norms following the first's. A retry which fails and ends above where the first attempt ended returns the first attempt's point, whose residual norm then closes the record.
Keywords
iterations = 1000: the maximum number of Newton iterations, over both attempts.atol = 1e-8: converged whennorm(F) <= atol.rtol = 0.0: a relative tolerance; the effective tolerance ismax(atol, rtol*norm(F0))withF0the initial residual.factorization = KLUfactorization(): the sparse factorization ofJ.cache = FactorizationCache(): theFactorizationCacheJis factorized into. A caller which solves again with a matrix of the same pattern hands in the one of the last solve, whose fill reducing ordering and symbolic analysis the refactorizations then reuse.linesearch = Backtracking(): theBacktrackingof every search of the iteration, the curvilinear one included: the Armijo constant, the safeguards, the trial budget, whether a backtrack is fitted or halved, and the count of consecutive failed searches which is a stall.andersondepth = 5: the history depth;0disables the acceleration.andersonbeta = 1.0: correction strength.andersonacceptfactor = 0.9: candidate accept threshold, in (0, 1); smaller is stricter.
Returns an IterationInfo with per-iteration diagnostics: normresidual (residual norms, starting at the initial point), alpha (step lengths; NaN marks an accepted candidate), backtracks (trial evaluations after each iteration's first), andersonaccepted (true when the taken step lies on the curved path), and reason, why the iteration ended: :converged, :iterations, :linesearch (no decrease at all, two consecutive steps short of the Armijo condition, or a direction which is not a descent direction, or whose merit or slope is not finite, which the factorization of an approximate Jacobian can give), :progress (the residual stopped coming down, or comes down too slowly to reach the tolerance within the steps left, and its rate is not improving, residualstalled; a first such judgement is given a fresh history, and the attempt ends if the stall persists over it), or :nonfinite (the residual norm at the initial point is not finite, and no step is taken); see stallmessage.
JosephsonCircuits.nlsolvekrylov! Method
nlsolvekrylov!(fj!, jvp!, F, x, pc::AbstractPreconditioner,
method::NewtonKrylov = NewtonKrylov(); iterations = 1000,
atol = 1e-8, rtol = 0.0, workspace = nothing, forcingmin = 1e-10,
forcingmax = 0.9, forcingstart = 0.3, forcinggamma = 0.9,
forcingalpha = (1 + sqrt(5))/2, stagnation = 0.9, slowrate = 0.5,
linearfloor = 0.1)Inexact (Newton-Krylov) solver for a real system: the Newton step is taken from gmres! on the exact matrix-free product jvp!(y, v) rather than from a factorization of an assembled Jacobian. fj!(F, J, x) evaluates the residual and Jacobian as in nlsolve!, accepting nothing for either. x is updated in place and F holds the residual at the returned x.
The Jacobian enters only through jvp! and through the right preconditioner pc (see AbstractPreconditioner), so a preconditioner much cheaper than the Jacobian makes each Newton step much cheaper than a direct one. ModeCouplingPreconditioner is the harmonic balance Jacobian with its mode coupling restricted, and is exact when every mode is retained.
The linear solver of the Newton step, the refresh policy and the escalation are the linearsolver, refresh and escalate of method, a NewtonKrylov whose preconditioner and precision are not read here: the preconditioner is pc, built by the caller.
pc is rebuilt according to refresh: before every step for Always, by the measured rule of Probe, and for Never only when forced. A rebuild is forced regardless of the policy when a solve makes progress but misses its tolerance, when a step is not a descent direction, when the line search finds no decrease and the rebuild can change the step (below), and after a successful escalation. The linear tolerance follows the Eisenstat-Walker choice 2 forcing sequence forcinggamma*(|F_k|/|F_{k-1}|)^forcingalpha, clamped to [forcingmin, forcingmax] and started at forcingstart, with an absolute floor of linearfloor times the tolerance in force, max(atol, rtol*norm(F0)), so late solves are not pushed below the nonlinear tolerance. Because the preconditioner can be stale, the linesearch slope is always taken from an exact matrix-free product, and a direction which is not a descent direction is solved for again, at the same forcing, from a rebuilt preconditioner before the iteration is declared stalled; for an exact preconditioner that is the exact Newton step.
The globalization is the plain damped-Newton path of nlsolve!: the backtracking_linesearch! of nlsolve! with the method's Backtracking, which on Armijo failure still takes the best decreasing trial, with consecutive failures counted against its maxfailures, and a step with no decrease retried once from a rebuilt preconditioner before stopping when the rebuild can change it: when the preconditioner the step came from was not rebuilt at its point, or has changed since in a way a rebuild takes in (an escalation granted, a slow solve reported, on which a Clusters request remeasures, candidates a deflation banked, see hasnewcandidates). Against a preconditioner rebuilt there and unchanged the retry would repeat the step, and the solve stops at once. There is deliberately no Anderson acceleration here: the Krylov steps are near-exact Newton steps, and the solver is kept simple.
Keywords
iterations = 1000: the maximum number of Newton iterations.atol = 1e-8: converged whennorm(F) <= atol.rtol = 0.0: an additional relative test,norm(F) <= rtol*norm(F0)withF0the initial residual, satisfied when either holds. A residual whose terms are of sizescannot be driven below abouteps*showever exact the step, so an absolute tolerance is a statement about the problem's units; a relative one is not.workspace = nothing: aRefholding theKrylovVectorsof a previous solve of the same system, or holdingnothing, in which case the vectors are allocated and stored into it for the next solve. With noRefat all they are allocated and dropped.forcingmin = 1e-10,forcingmax = 0.9,forcingstart = 0.3,forcinggamma = 0.9,forcingalpha = (1 + sqrt(5))/2: the clamp, the first term and the parameters of the forcing sequence, on the ranges Eisenstat-Walker choice 2 is defined on:0 < forcingmin <= forcingstart <= forcingmax < 1,0 < forcinggamma <= 1and1 < forcingalpha <= 2.stagnation = 0.9: a linear solve which does not bring the linear residual below this fraction of the residual norm is stagnated, and the preconditioner solve is taken as the step.slowrate = 0.5: a linear solve whose residual was multiplied, on average, by more than this factor per Arnoldi step is reported to the preconditioner as slow (stalled!); none is underNever.linearfloor = 0.1: the absolute floor of the linear solves, as a fraction of the nonlinear tolerance in force.
And, read off method: linearsolver, the linear solver of the Newton step, a GMRES or a KrylovJL; refresh, when the preconditioner is rebuilt, Always before every step, by the measured rule of Probe, or Never except when forced (either way a solve which made progress but missed its tolerance, a non-descent direction, a line search with no decrease which a rebuild can change, and a successful escalation force a rebuild); and escalate, whether a preconditioner whose linear solve fails to reach its tolerance is escalated (see escalatepreconditioner!), within the memory the grown factors are predicted to take; a refused escalation is recorded (escalationrequested in the Krylov record) and the solve carries on.
The forcing sequence, the thresholds of a stagnated and of a slow linear solve and the floor of the linear solves are keywords of this function rather than options of the method; Never turns off the slow-solve report and the count rule. The line search is the method's Backtracking, interpolating by default. Two budgets bound the work: iterations Newton steps, and iterations restart lengths of Arnoldi steps in total, so that a preconditioner which runs every linear solve to its limit cannot turn the step budget into hours. A residual which has stopped coming down, or comes down too slowly to reach the tolerance within the remaining budget, and whose rate is not improving (residualstalled) gets one recovery, a rebuilt preconditioner and exact Newton steps from then on, and ends the solve if it persists.
These are the settings hbnlsolve runs with; a caller changes them through the NewtonKrylov method object (preconditioner, linearsolver, refresh, escalate, linesearch, precision) and through hbnlsolve's own iterations, atol and rtol.
Returns an IterationInfo with the same per-iteration diagnostics as nlsolve! (the andersonaccepted record is always false) and a reason of :converged, :iterations, :work (the Arnoldi budget was spent), :linesearch (no decrease, after the retry when one is made, or a direction which is not a descent direction after the exact rescue), :progress, or :nonfinite (the residual norm at the initial point is not finite, and no step is taken).
JosephsonCircuits.nnets Method
nnets(elab::ElaboratedCircuit)The number of nets including the ground net.
sourceJosephsonCircuits.nodalstampplan Method
nodalstampplan(c::CompiledCircuit, group, Nnodes; invert = false)Build the NodalStampPlan of a two terminal group.
group is a vector of flat component indices, so the same function plans the capacitance from the capacitors and the conductance from the resistors and the port environments alike.
JosephsonCircuits.nodecomponents Method
nodecomponents(Nnodes::Int, edges)The connected components of Nnodes nodes joined by edges, given as (node1, node2) pairs, leaving out the component which contains ground (node 1). Each component is a sorted vector of node indices and the components are sorted by their lowest node.
A union-find with path halving, unioning toward the lower node index so that ground is the root of its own component. Which components are floating depends on which branches count as an edge, so each caller supplies its own: the static flux stiffness of the direct current gauge (calcstaticfluxcomponents), the conduction paths of the transient (transientfloatingcomponents), and every element and block port of the subnetworks harmonic balance refuses (isolatedsubnetworks).
JosephsonCircuits.nodevariabletokeyed Method
nodevariabletokeyed(nodevariable, outputmodes, nodenames, inputmodes,
inputportnumbers, w)Convert a node variable array nodevariable (such as node flux or node voltage) vs frequency w to a keyed array. Return the keyed array.
Examples
julia> JosephsonCircuits.nodevariabletokeyed([1 2;3 4;;;],[(0,),(1,)],["0","1"],[(0,),(1,)],[1],[1.0])
5-dimensional KeyedArray(NamedDimsArray(...)) with keys:
↓ outputmode ∈ 2-element Vector{Tuple{Int64}}
→ node ∈ 1-element Vector{String}
◪ inputmode ∈ 2-element Vector{Tuple{Int64}}
▨ inputport ∈ 1-element Vector{Int64}
▨ freqindex ∈ 1-element UnitRange{Int64}
And data, 2×1×2×1×1 Array{Int64, 5}:
[:, :, 1, 1, 1] ~ (:, :, (0,), 1, 1):
("1")
(0,) 1
(1,) 3
[:, :, 2, 1, 1] ~ (:, :, (1,), 1, 1):
("1")
(0,) 2
(1,) 4JosephsonCircuits.nodevariabletokeyed Method
nodevariabletokeyed(nodevariable::AbstractVector, nodenames)Convert a node variable with one value per node, such as the average direct current voltage, to a keyed array.
nodevariable excludes ground, as every node keyed output does, so it is keyed by nodenames[2:end] exactly as the node flux is.
JosephsonCircuits.nodevariabletokeyed Method
nodevariabletokeyed(nodevariable, outputmodes, nodenames)Convert a node variable array nodevariable (such as node flux or node voltage) to a keyed array. Return the keyed array.
Examples
julia> JosephsonCircuits.nodevariabletokeyed([1 2;3 4],[(0,),(1,)],["0","1","2"])
2-dimensional KeyedArray(NamedDimsArray(...)) with keys:
↓ outputmode ∈ 2-element Vector{Tuple{Int64}}
→ node ∈ 2-element Vector{String}
And data, 2×2 Matrix{Int64}:
("1") ("2")
(0,) 1 2
(1,) 3 4JosephsonCircuits.noisechannelnames Method
noisechannelnames(componentnames, noiseportimpedanceindices, noiseplan,
ssys)The name of each row of the noise scattering matrix: the dissipative lumped components first, then the channels of the dissipative scattering blocks.
sourceJosephsonCircuits.noisechannelsigns Method
noisechannelsigns(noiseportimpedanceindices, noiseplan, ssys)The sign kind of each channel of the noise scattering matrix in the commutation relations, in the order noisechannelnames gives them, or nothing when every channel is of the first kind: 1 for a channel which emits like a mode in its vacuum, whose rows count with the sign of their mode frequency; -1 for a channel of the conjugate kind, the second half of the channels of a block which states its noise (see ScatteringNoisePlan), whose rows count with the opposite sign, since what it emits is the conjugate of a mode; and 2 and -2 for the channels of a pumped block which states its noise, which span all its modes at once, so that every row of one counts with the fixed sign of its kind (see pumpedblocknoisewaves!).
JosephsonCircuits.noisechanneltemperatures Method
noisechanneltemperatures(psc::CompiledCircuit,
noiseportimpedanceindices, noiseplan, ssys, temperature)The temperature of each row of the noise scattering matrix, in the order noisechannelnames gives them.
temperature is the analysis default, which every dissipative element takes unless it states one of its own. A lumped component states it as Resistor(R; temperature = T) and a ScatteringParameters as noise = ThermalEquilibrium(T), both of which are recorded by compile as it lowers the circuit; a component which states none takes the default.
The channels of a block which states its noise with a NoiseCovariance are at zero temperature: the covariance it states is the whole of its noise, which the vacuum's half photon on each of its channels gives back (see ScatteringNoisePlan).
JosephsonCircuits.noisecovariance! Method
noisecovariance!(L, off, n, S, soff)The commutator I - S S' of the noise wave of an n port block, twice its covariance in the vacuum, into the length n*n column major block of L at off, from the scattering matrix in the same layout at soff in S.
Only the lower triangle is written, which is all psdcholesky! reads: the covariance is Hermitian.
JosephsonCircuits.noiseindices Method
noiseindices(c::CompiledCircuit, values; frequencies = ())The flat table indices of the internal dissipative components, which are the noise channels of the linearized analysis: every resistor which is not a port's own termination, and every capacitor or inductor whose resolved value in values is lossy, a number with a nonzero imaginary part or a frequency dependent value with one at any of the angular frequencies, the mode frequencies of a sweep, over which each distinct function is evaluated once however many components share it. Where such a value is lossless its channel carries no noise. Without frequencies a frequency dependent value is no channel.
A port termination is an external bath rather than an internal channel and is excluded by its role; any other resistor across a port's nodes is an ordinary device resistor and is included.
sourceJosephsonCircuits.noiseoutputwavekernel! Method
noiseoutputwavekernel!The output power waves at the noise ports, from the adjoint solution, one work item per (noise port, mode, right hand side).
This is calcoutputwaves! with no source current, as the host reads the noise ports; the input waves it is divided by come from the source terms alone and are computed on the host. values holds the value of each noise port at each mode, a column per port.
JosephsonCircuits.noisereduction! Function
noisereduction!(noise::NoiseReduction, Snoise, w, channelnoise,
channelsigns = nothing)Reduce the noise scattering matrix Snoise, a row per noise channel mode and a column per output port mode, to the two sums the quantum efficiency and the commutation relations read, into noise; see NoiseReduction. w holds the mode frequencies, the mode of row c being (c-1) % length(w) + 1, channelnoise the symmetrized noise nbar + 1/2 of each row, and channelsigns the sign kind of each channel, the channel of row c being (c-1) ÷ length(w) + 1, in the second sum, one everywhere when nothing: 1 and -1 multiply the sign of the row's mode frequency, 2 and -2 are the fixed signs 1 and -1 (see noisechannelsigns). Each sum is compensated (Kahan-Babuska-Neumaier).
Examples
julia> Snoise = [1 2; 3 4; 5 6; 7 8]; vacuum = fill(0.5, 4);
julia> n = JosephsonCircuits.noisereduction!(JosephsonCircuits.NoiseReduction(zeros(2), zeros(2)), Snoise, [1, -1], vacuum); (n.symmetrized, n.signed)
([42.0, 60.0], [-32.0, -40.0])
julia> n = JosephsonCircuits.noisereduction!(JosephsonCircuits.NoiseReduction(zeros(2), zeros(2)), Snoise, [1, -1], vacuum, [1.0, -1.0]); (n.symmetrized, n.signed)
([42.0, 60.0], [16.0, 16.0])JosephsonCircuits.noisewavescale Method
noisewavescale(portimpedance, w)The outgoing wave per unit voltage of a port which carries no source, a noise channel, whose current is the one the voltage drives through its own impedance: kval*(V + conj(Z)*V/Z)/2 = kval*real(Z)/Z*V with kval the portwavescale, written as sqrt(real(Z))/(Z*sqrt(abs(w))) so that an element with no loss at w, whose channel carries nothing there, gives zero rather than an infinite scale times a zero voltage term. w is nonzero: the sweep, which reads the noise channels, refuses a mode at zero frequency.
JosephsonCircuits.nonlinearmatrices Method
nonlinearmatrices(nm::CircuitMatrices, w, componenttypes, wmodes)The linear term of the nonlinear solve from the circuit matrices nm: the solver scale (see calcsolverscale) and the reference impedance Z0 it is built on, and the capacitance, conductance and inverse inductance matrices with the mode frequencies wmodes resolved in frequency dependent values, the entries of the negative frequency modes conjugated and the rows scaled, as SparseMatrixCSC{ComplexF64,Int} whatever the element types of nm; the branch vectors and the port lists come along. A stage of its own in front of nonlinearsetup, so that the setup and everything after it is compiled once for every way the circuit's values were typed rather than once per combination of them.
JosephsonCircuits.nonlinearoutputs Method
nonlinearoutputs(; psc, info, dcsol, dccanonical, w, frequencies, atol,
keyedarrays, returnoperatingpoint, ...)The NonlinearHB of a solve: the checks on the accepted point (the ungauged Kirchhoff current law, held to atol, the tolerance the solve stopped at, and the junctions' direct current), the node fluxes and the scattering parameters at the pump modes, keyed when asked, the operating point with its assembled Jacobian when asked, and the direct current node voltages. The remaining keywords are the fields of nonlinearsetup this stage reads, info and dccanonical what the solve returned, and dcsol the direct current solution.
JosephsonCircuits.nonlinearsetup Method
nonlinearsetup(w, sources, frequencies, indices, psc, m, x0,
backend, precision, reuse; needjx, needjr, devicex,
realrepresentation)Everything the nonlinear solve of hbnlsolve needs before a method is applied: the mode frequencies and the checks on them, the scaled and frequency substituted linear term, the modified nodal analysis augmentation with its direct current block, the initial value in the real representation, the assembled Jacobians the method asked for (needjx the complex one, needjr the real one, devicex the complex one on the backend), the HBSystem with its residual closures fj! and fjreal!, and the canonical work of an explicit direct current block. reuse is an HBReuse whose objects are taken over, or nothing.
Returned as a named tuple, whose fields the solve and the outputs stages read by name; it is the seam between them. This stage depends on the tone count, the matrices, the precision, the backend and the reuse, and not on the method, so a solve with a different method compiles it again only when one of those differs.
sourceJosephsonCircuits.norm2 Method
norm2(v::AbstractVector)The Euclidean norm of v: for a Float64 vector formed through the inner product, sqrt(dot(v, v)), and otherwise LinearAlgebra.norm.
LinearAlgebra.norm scales its argument before squaring so that an entry cannot overflow or underflow on its way to the sum. On a device that guard is not free in double precision: cuBLAS routes a Float64 vector to a scaled nrm2 kernel running at a small fraction of memory bandwidth, where the inner product runs at the bandwidth, and that kernel would be the largest single device kernel of a double precision solve. In single precision cuBLAS selects another kernel with no such gap, and the narrower exponent range of a shorter float is where the guard is worth the most, so the inner product is used for Float64 alone.
It is safe there. The vectors this is applied to are carried at the scale of the harmonic balance residual of a nondimensionalized system, which runs from a few units down to the solver tolerance, and squaring that stays far inside the double precision exponent: overflow would need an entry above 1e154, and underflow to zero an entry below 1e-162. This is deliberately not exported and not used outside the Krylov solver; anything whose scale is not controlled should keep using norm.
JosephsonCircuits.nterminals Method
nterminals(component)The number of scalar electrical terminals of a component model. Two terminal lumped components have 2; a ScatteringParameters has two per port; a MutualInductor has none because it couples branches, not nets; a Ground instance has one, which is the reference net itself. The terminals of a hierarchical Circuit are the pins of its Interface, which the parse and the elaboration read there.
JosephsonCircuits.numericvalues Method
numericvalues(c::CompiledCircuit, definitions)The flat value table of a compiled circuit resolved at definitions, with every entry a number. A value which still depends on a name the definitions do not give, and one which is frequency dependent rather than a number, are both refused naming their component, so a caller which can work with neither fails with the cause rather than downstream. The definitions may be any dictionary.
JosephsonCircuits.nvoltages Method
nvoltages(t::TransportRows)The number of explicit average voltages, one per floating static flux component.
sourceJosephsonCircuits.nwindow Method
nwindow(L::CompositeLayout)The length of the direct current window.
sourceJosephsonCircuits.nzposition Method
nzposition(S::SparseMatrixCSC, i::Integer, j::Integer)The position of the stored entry (i, j) in the value array of S, whose row indices are sorted within a column, found by a binary search of the column. An entry S does not store is an ArgumentError.
JosephsonCircuits.optimum_eigenvalue_angle Method
optimum_eigenvalue_angle(values; target_angle = pi)For eigenvalues values on or near the unit circle, the angle of the midpoint of the widest empty arc between them, and the angle of the rotation which moves that midpoint to target_angle (by default pi, so that the rotated eigenvalues lie as far as they can from the branch cut of the logarithm and the square root). The arcs are the counterclockwise gaps between the sorted angles of the eigenvalues, the last one running from the largest angle around to the smallest, so that eigenvalues clustered on a short arc leave the rest of the circle as the widest gap. After https://github.com/XanaduAI/thewalrus/pull/403.
Examples
Eigenvalues clustered about 1.5 leave the widest gap about 1.5 - pi, and the rotation by -1.5 moves it to pi:
julia> optimum_angle, optimum_rotation = JosephsonCircuits.optimum_eigenvalue_angle(cis.([1.4, 1.5, 1.6]));
julia> round(optimum_angle, digits = 4), round(optimum_rotation, digits = 4)
(-1.6416, -1.5)JosephsonCircuits.orderedports Method
orderedports(c::CompiledCircuit)The ports of a compiled circuit ordered by port number. Throws an ArgumentError for duplicate port numbers, a port with both terminals on one node, or two ports on the same branch. Every port list the assembly reads is built from this one, so the indices, the numbers, the environments and the reference impedances are in one order.
JosephsonCircuits.outputnoise! Method
outputnoise!(vout, comp, S, inputnoise, noise::NoiseReduction)The symmetrized noise at each output i of the scattering matrix S, the diagonal of the output covariance S*Diagonal(inputnoise)*S' + Cnoise: sum_j inputnoise[j]*abs2(S[i,j]), each input carrying its own nbar + 1/2, the vacuum's 1/2 or more, plus what the noise channels of the NoiseReduction noise put there. The sum is compensated (Kahan-Babuska-Neumaier), its corrections in comp, one entry per row. The occupation of output i is vout[i] - 1/2 and the quantum efficiency abs2(S[i,j])/(2*vout[i]).
Examples
julia> JosephsonCircuits.outputnoise!(zeros(2), zeros(2), [3/5 4/5; 4/5 3/5],
[0.5, 0.5], JosephsonCircuits.NoiseReduction(zeros(2), zeros(2)))
2-element Vector{Float64}:
0.5
0.5JosephsonCircuits.pair_to_block Method
pair_to_block(S::AbstractMatrix)Return the matrix S with its rows and columns in pair order reordered to block order.
JosephsonCircuits.pair_to_block Method
pair_to_block(r::AbstractVector)Examples
r = [:x1, :p1, :x2, :p2, :x3, :p3, :x4, :p4]
JosephsonCircuits.pair_to_block(r)
# output
8-element Vector{Symbol}:
:x1
:x2
:x3
:x4
:p1
:p2
:p3
:p4JosephsonCircuits.pair_to_block2 Method
pair_to_block2(S::AbstractMatrix)Return the matrix S with its rows and columns in pair order reordered to block order, as pair_to_block, by products with the permutation matrices R_pair_to_block.
JosephsonCircuits.pair_to_block2 Method
pair_to_block2(r::AbstractVector)Return the vector r in pair order reordered to block order, as pair_to_block, by a product with the permutation matrix R_pair_to_block.
JosephsonCircuits.pair_to_block_perm Method
pair_to_block_perm(n::Int)Return a 2n length vector p which permutes the pair operator ordering r = [x_1,p_1,...,x_n,p_n] to the block operator ordering r[p] = (x1,...,xn,p1,...,pn).
Examples
r = [:x1, :p1, :x2, :p2, :x3, :p3, :x4, :p4]
p = JosephsonCircuits.pair_to_block_perm(4)
r[p]
# output
8-element Vector{Symbol}:
:x1
:x2
:x3
:x4
:p1
:p2
:p3
:p4JosephsonCircuits.parametergrouping Method
parametergrouping(pairs, componentindices, componenttypes, portordinal)The grouping of the sensitivity pairs (componentname, parameterindex, alpha) into merged stamps: pairs which share a stamp kind, a design parameter and a port ordinal merge into one contraction. componentindices[i] is the parsed circuit index of pair i. Returns (grouping, slots), the pair indices of each group and the design parameter each group accumulates into.
Computed from the parsed circuit alone, before any stamp exists, because the residual derivative columns and the operating point solves must be merged with the same grouping as the stamps, and both are needed earlier than the stamps are built.
sourceJosephsonCircuits.parametricsources Method
parametricsources(sources)Whether a current of sources is a name, or a symbolic value, rather than a number, so that it moves with the definitions.
JosephsonCircuits.parametrictones Method
parametrictones(w)Whether a tone frequency of w is a name, or a symbolic value, rather than a number, so that it moves with the definitions.
JosephsonCircuits.parse_connections_sparse Method
parse_connections_sparse(networks::AbstractVector{PassiveNetwork{T,N}},
connections::AbstractVector{Tuple{T,T,Int,Int}}) where {T,N}Return the indices of the internal ports porti_indices, the external ports porte_indices, the vector of port tuples ports, the vectors of the networks' scattering parameters and noise covariances, the connection matrix gamma, the sparse matrix Sindices of the indices into the networks' arrays of its entries, and a sparse matrix S of that structure with its values unset. S holds the networks' scattering parameters at one frequency as a block diagonal matrix.
References
V. A. Monaco and P. Tiberio, "Computer-Aided Analysis of Microwave Circuits," in IEEE Transactions on Microwave Theory and Techniques, vol. 22, no. 3, pp. 249-263, Mar. 1974, doi: 10.1109/TMTT.1974.1128208.
sourceJosephsonCircuits.parsecircuitlevel Function
parsecircuitlevel(c::Circuit, interfacecache = IdDict{Any,InterfaceIndex}())Parse and validate one level of a circuit description into a ParsedLevel: the component table, the connection groups, the interface pins, the ground ties and the mutual inductors. The Circuit constructor runs it to validate its arguments, and the elaboration runs it on every level it flattens. interfacecache holds the key lookup of each subcircuit's interface found so far, so that an elaboration builds each one once however many instances the subcircuit has.
JosephsonCircuits.parsecomponentvalue Method
parsecomponentvalue(s::AbstractString)Parse a SPICE netlist component value: a number, a name, returned as a symbol, or an expression, which Symbolics reads, as the netlist reader of v0.5.4 did, and which needs it loaded (using Symbolics). Nothing is evaluated into a module, so a netlist cannot introduce arbitrary code.
JosephsonCircuits.parsespicevariable Method
parsespicevariable(variable::String)The name and the node of a rawfile variable, which calcspicesortperms sorts by. A number after the leading word of the variable, V1(5) or V-1, is the node and the word the name; else a number within the leading word splits it, V1 being the name V and the node 1; and a variable without a number is its own name and node. A variable which does not start with a word character is refused.
Examples
julia> JosephsonCircuits.parsespicevariable("V1(5)")
("V1", 5)
julia> JosephsonCircuits.parsespicevariable("V1")
("V", 1)
julia> JosephsonCircuits.parsespicevariable("V-1")
("V", 1)
julia> JosephsonCircuits.parsespicevariable("frequency")
("frequency", "frequency")JosephsonCircuits.passiveconstant Method
passiveconstant(D; tol = 1e-6, margin = tol)The constant term D with every singular value above sqrt(1 + tol), where its dissipation I - D'D falls below -tol, brought to 1 - margin, leaving the singular vectors alone. D is the model at infinite frequency. The passivity enforcement changes it with the residues, by the least change over the samples; bringing it under one before the residues are fitted instead has the residues fitted to what is left over the samples, the least change of the fit with its poles. tol is how far below zero the dissipation must fall for a singular value to be treated as active, and belongs with the tolerance the block is validated against; margin is how far under one it is put, and belongs with the margin the enforcement aims for. Follows Gustavsen, IEEE Transactions on Electromagnetic Compatibility 67(3), 2025, section X-A.
JosephsonCircuits.passivitymargin Method
passivitymargin(S::AbstractMatrix)Return the minimum eigenvalue of I - S S', which is nonnegative for a passive scattering matrix.
sourceJosephsonCircuits.perfrequency! Method
perfrequency!(kernel!, y, args...)Fill the network parameter matrix y[:, :, i] at every frequency index i of the trailing dimensions of y by the scalar kernel kernel!, with each array argument indexed at i and each scalar argument the same at every frequency. An array argument must have the size of the trailing dimensions of y. The type parameters make the method specialize on the kernel and on the argument types, which Julia does not do on its own for a function argument and for arguments only passed on; without them the kernel is called through a dynamic dispatch at every frequency.
JosephsonCircuits.perfrequency Method
perfrequency(kernel!, f, args...)The allocating form of perfrequency!: the matrices of the network f at every frequency of the array arguments, in an array whose element type is the one f returns for scalars, found by evaluating f once on the first element of each array argument.
JosephsonCircuits.perronbound Method
perronbound(W::AbstractMatrix, nzs, roots; rtol = 1e-6, maxiter = 1000)An upper bound on the spectral radius of the couplings of the nonnegative matrix W between clusters, roots[i] naming the cluster of mode i and nzs listing the positions (i, j) at which W is positive.
For any positive vector v the Collatz-Wielandt ratios (Wv)_i/v_i bracket the spectral radius of a nonnegative matrix, their largest from above and their smallest from below, and along a power iteration the bracket narrows. The iteration is that of W + I, whose vectors stay positive and which converges where that of W alternates: on a pattern of period two, a coupling strong one way and weak the other, the norm of W^k v alternates between two values neither of which is the radius. It stops once the largest ratio is below one, when the bracket has closed to rtol, or when the largest ratio has stopped falling, and returns the smallest largest ratio seen.
JosephsonCircuits.phivectortomatrix! Method
phivectortomatrix!(phivector::AbstractVector,phimatrix::AbstractArray,
indexmap::Vector{Int},conjsourceindices::Vector{Int},
conjtargetindices::Vector{Int},Nbranches::Int)The harmonic balance method requires a vector with all of the conjugate symmetric terms removed and potentially other terms dropped if specified by the user ( for example, intermodulation products which are not of interest) whereas the Fourier transform operates on multidimensional arrays with the proper conjugate symmetries and with dropped terms set to zero. This function converts a vector to an array with the above properties.
Examples
freqindexmap = [2, 4, 6, 8, 12, 16, 27, 33]
conjsourceindices = [16, 6]
conjtargetindices = [21, 31]
Nbranches = 1
phivector = 1im.*Complex.(1:Nbranches*length(freqindexmap));
phimatrix=zeros(Complex{Float64},5,7,1)
JosephsonCircuits.phivectortomatrix!(phivector,
phimatrix,
freqindexmap,
conjsourceindices,
conjtargetindices,
Nbranches,
)
phimatrix
# output
5×7×1 Array{ComplexF64, 3}:
[:, :, 1] =
0.0+0.0im 0.0+3.0im 0.0+0.0im 0.0+6.0im 0.0-6.0im 0.0+0.0im 0.0-3.0im
0.0+1.0im 0.0+0.0im 0.0+5.0im 0.0+0.0im 0.0+0.0im 0.0+7.0im 0.0+0.0im
0.0+0.0im 0.0+4.0im 0.0+0.0im 0.0+0.0im 0.0+0.0im 0.0+0.0im 0.0+8.0im
0.0+2.0im 0.0+0.0im 0.0+0.0im 0.0+0.0im 0.0+0.0im 0.0+0.0im 0.0+0.0im
0.0+0.0im 0.0+0.0im 0.0+0.0im 0.0+0.0im 0.0+0.0im 0.0+0.0im 0.0+0.0imJosephsonCircuits.pivot_rows Method
pivot_rows(A11,A21)Return true if pivoting during LU decomposition.
Examples
julia> JosephsonCircuits.pivot_rows(0,:A21)
true
julia> JosephsonCircuits.pivot_rows(1,:A21)
falseJosephsonCircuits.pivot_rows Method
pivot_rows(A11::Union{T,Complex{T}},
A21::Union{T,Complex{T}}) where {T<:AbstractFloat}Return true if pivoting during LU decomposition.
Examples
julia> JosephsonCircuits.pivot_rows(0.1+0.0im,0.9+0.1im)
true
julia> JosephsonCircuits.pivot_rows(0.9+0.1im,0.1+0.0im)
falseJosephsonCircuits.plan_applyffttranspose Method
plan_applyffttranspose(td::Array{T})Create the complex transform plan for applyffttranspose!, the transpose of applyfft! on the same grid. A work array the size of the time domain grid is allocated for planning and discarded; the caller passes its own padded at apply time. The plan assumes the alignment every array Julia allocates has, so it serves the per-thread work arrays each caller allocates; FFTW refuses an array without it rather than computing on it.
JosephsonCircuits.plan_applynl Method
plan_applynl(fd::AbstractArray{Complex{T}}, backend::Backend = CPU())Creates an empty time domain data array and the inverse and forward plans for the RFFT of an array of frequency domain data. See also applynl!. A system with no junctions has nothing to transform: for an empty fd the two plans are nothing, and applying them is the identity.
JosephsonCircuits.plancomplexjacobian Method
plancomplexjacobian(Amatrixindices::Matrix, Ljb::SparseVector, Lscale,
Rbnm::SparseMatrixCSC, Nmodes::Integer, Nbranches::Integer,
Nfreq::Integer, invLnm::SparseMatrixCSC, Gnm::SparseMatrixCSC,
Cnm::SparseMatrixCSC)Build the complex Jacobian sparse matrix Jx (with the same sparsity structure spaddkeepzeros applied to Rbnm'*AoLjbm*Rbnm and the linear term matrices would produce, including stored numerical zeros) and the StructureComplexJosephsonPlan which writes the Josephson term into it: the map from the Fourier coefficients of cos(phi(t)) to the Josephson branch matrix AoLjbm (Amatrixindices, with negative entries denoting complex conjugation and zeros denoting dropped couplings) and the circuit's incidence triple product Rbnm'*AoLjbm*Rbnm as a per node pair table (junctionpairtable), read backwards at assembly time.
The plan reads a JunctionStructure built here on the host in the precision the scale and the inductances give. The linear term is not part of the plan. The nonlinear solve gathers it once for its mode frequencies with planstructurecomplexjacobian, which takes this plan as its josephson; the linearized solve builds its own index maps for the matrices it substitutes per frequency.
Returns the tuple (Jx, josephson).
JosephsonCircuits.plandeviceblocknoise Method
plandeviceblocknoise(ssys, noiseplan, Nmodes, backend)Build a DeviceBlockNoisePlan from a ScatteringNoisePlan, or nothing when there is none.
JosephsonCircuits.plandevicefrequencydependent Method
plandevicefrequencydependent(fd, dest, nzA, nbatch, backend, Nmodes)Build a DeviceFrequencyDependentStamps from the stamps fd of a linearized system, with their destinations dest in the stored order the batch uses (see sweepdestinations), or nothing when fd is nothing.
JosephsonCircuits.plandevicenoise Method
plandevicenoise(nodeindices, componenttypes, noiseportimpedanceindices,
noiseportimpedances, Nmodes, backend)Build a DeviceNoisePlan for the noise ports of a circuit, whose values noiseportimpedances are numbers or, where they depend on the frequency, rows of the linearized system's table of their functions' values.
JosephsonCircuits.plandeviceproviders Method
plandeviceproviders(ssys, nbatch, backend, wpumpmodes, scale)Build a DeviceProviders for a stamp system whose blocks can all be evaluated by a kernel, or nothing otherwise.
JosephsonCircuits.plandevicescattering Method
plandevicescattering(ssys, Aindexcsr, nzA, nbatch, backend, Nmodes)Build a DeviceScatteringStamps from a scattering stamp system whose destination indices have already been mapped into the stored order the batch uses, or nothing when ssys is nothing.
JosephsonCircuits.planequilibration Method
planequilibration(rowptr, colind::AbstractVector{<:Integer}, n, nb,
backend)The SweepEquilibration of a batch of nb systems of order n handed to the solver as the structure rowptr (on the backend) and colind (on the host).
JosephsonCircuits.planfrequencysweep Method
planfrequencysweep(lsys::HBLinearizedSystem, backend;
adjoint::Bool = false)Build a FrequencySweepPlan for lsys on backend, together with the compressed sparse row structure a device direct solver factorizes, as (plan, rowptr, colind, colindhost). The column index array comes back on the host as well, which is where the grouping of planequilibration is built.
With adjoint the structure and the coefficients describe the transpose of the system matrix, whose solutions are the adjoint ones the noise, quantum efficiency and sensitivity calculations need. That transpose is free to form: compressed sparse row of the transpose is compressed sparse column of the matrix, which is how the host holds it, so the adjoint plan is the same coefficients in their original order against the original structure.
With cuDSS the adjoint costs a second symbolic analysis and a second numeric factorization per batch, because cuDSS 0.8 has no transposed solve (its "solve_mode" is documented in the header as unsupported), so the factors of the forward system cannot be reused the way the host reuses them with trysolvetranspose!. The block path asks for the adjoint plan for a different reason: its coefficients are in the matrix's own stored order, which is the order a SparseBlockFactorization fills its blocks from, and it costs no second factorization, since the block factors solve both directions.
JosephsonCircuits.plannonlinearterm Function
plannonlinearterm(Rbnm::SparseMatrixCSC, Ljb::SparseVector, Lscale,
Nbranches::Integer, freqindexmap::Vector{Int},
conjsourceindices::Vector{Int}, conjtargetindices::Vector{Int},
phimatrix::AbstractArray, Knm::SparseMatrixCSC, layout::ModeLayout,
backend = CPU(); realbackward = true)Build the NonlinearTermPlan for the harmonic balance system described by the incidence matrix Rbnm, the Josephson inductances Ljb, the frequency domain packing maps, the frequency domain array phimatrix which fixes the slot layout, the collapsed linear term matrix Knm (see linearterm) and the real representation layout.
The per branch node and sign lists of the forward map come from branchnodesandsigns, the same function the assembled Jacobian plans use, which also verifies that Rbnm has the expected mode-diagonal diagrepeat structure. The backward map reads the columns of Rbnm directly, because the entries of column k are exactly the branch rows contributing to output k, which is what makes the transposed product a gather.
Throws an ArgumentError if a branch touches more than two nodes, which the forward map's flat two entry form assumes.
realbackward = false leaves out the real representation of the linear term, the largest allocation of the plan, which only the backward map of the real representation reads; a solve which stays in the complex representation (method = QuasiNewton()) never applies it.
JosephsonCircuits.plannonlineartermtranspose Method
plannonlineartermtranspose(plan, modelayout, fd, td)Build the NonlinearTermTransposePlan of a NonlinearTermPlan, on the plan's backend.
JosephsonCircuits.planscatteringnoise Method
planscatteringnoise(ssys)The ScatteringNoisePlan of a ScatteringStampSystem, or nothing when the circuit has no scattering blocks or every block either declares Lossless or is provablylossless.
Passive and ThermalEquilibrium carry the covariance of the block's loss, differing only in the temperature the channels are at, and give a block one channel per port; Lossless declares there are none; and a NoiseCovariance states the covariance outright and gives a block two channels per port. A block's constructor admits no other noise model, and a pumped block's only the last two.
JosephsonCircuits.planstructurecomplexjacobian Method
planstructurecomplexjacobian(Jx::SparseMatrixCSC,
junctions::JunctionStructure, invLnm, Gnm, Cnm, wmodesm, wmodes2m,
backend; transposed = false, josephson = nothing)Build a StructureComplexJacobianPlan for the structure of Jx: the Josephson map over junctions, built here unless one built for the same structure, backend and orientation is handed in as josephson (the plan plancomplexjacobian returns), and the constant linear term at the mode frequencies wmodesm, gathered once on backend.
JosephsonCircuits.planstructurecomplexjosephson Method
planstructurecomplexjosephson(Jx::SparseMatrixCSC,
junctions::JunctionStructure, backend; transposed = false)Build a StructureComplexJosephsonPlan for the structure of Jx.
JosephsonCircuits.planstructurerealjacobian Method
planstructurerealjacobian(Jt, T::Type{<:Real}, junctions::JunctionStructure,
invLnm, Gnm, Cnm, wmodesm, wmodes2m, layout::ModeLayout, backend;
transposed = true)Build a StructureRealJacobianPlan with values of type T for the real Jacobian whose structure is Jt, its rows and columns both in the real representation layout, stored transposed (as a device factorization wants it) when transposed = true and in the natural orientation otherwise. Nothing here is proportional to the number of contributions: what is stored is junctionpairtable, whose size is set by the circuit rather than by the mode count, and the constant linear term, which is gathered on backend at the entries it reaches (LinearTermGather) and is zero at the others.
JosephsonCircuits.pointmoved! Method
pointmoved!(pc::AbstractPreconditioner)Tell the preconditioner that the operator it approximates has changed without it having been rebuilt, and return pc. The default does nothing. A FloquetPreconditioner marks its image pair stale, so that the next application rebuilds it from the current Jacobian. Called by nlsolvekrylov! at every Newton step which does not rebuild the preconditioner; wrappers forward it.
JosephsonCircuits.pointsystem Method
pointsystem(op::HBOperatingPoint)A system at the operating point with a point and workspaces of its own, sharing the rest of op.sys (workspacetwin). What differentiates an operating point evaluates on one of these rather than on op.sys, since an evaluation writes the point and the workspaces of its system: the operating point is left as it was built, and one operating point serves concurrent calls.
JosephsonCircuits.polar Method
polar(A)Return a positive semi-definite matrix P and unitary matrix U such that A = P U. A is a square real or complex matrix.
If A is symplectic, both P and U are symplectic.
This definition is different from wikipedia https://en.wikipedia.org/wiki/Polar_decomposition
References
[1] M. Houde, W. McCutcheon, and N. Quesada, “Matrix decompositions in Quantum Optics: Takagi/Autonne, Bloch-Messiah/Euler, Iwasawa, and Williamson,” Can. J. Phys., vol. 102, no. 10, pp. 497–507, Oct. 2024, doi: 10.1139/cjp-2024-0070. [2] https://en.wikipedia.org/wiki/Polar_decomposition#Relation_to_the_SVD
sourceJosephsonCircuits.portdiagonal Method
portdiagonal(a)
porthalves(a)A port impedance argument as the kernels take it: a number stays a number and an array becomes a PortDiagonal; porthalves splits the ports in two, the first half the input ports of a chain matrix and the second half its output ports.
JosephsonCircuits.portreferenceimpedances Method
portreferenceimpedances(ports::Vector{CompiledPort}, values)The reference impedance of each port of orderedports, read from a bound flat value table.
A port's environment field carries the other half of its role: the flat index of the termination it owns, or zero for a port which owns none. That index says which entry realizes the impedance, which the noise classification needs (a port termination is an external bath, not an internal noise channel) and the sensitivities need (perturbing that entry also moves the wave normalization).
This is the impedance the incoming and outgoing waves are normalized to. It is the port's declared Z0, which is the value of the port's own entry in the table, and it is read from there for every port, whatever the port owns: a symbolic or swept impedance then resolves the same way a component value does, and an unterminated port resolves the same way a matched one. The two cannot disagree with an environment either, because a matched environment is generated with the port's own Z0, and a port whose termination names a resistor has that resistor's value as its Z0.
A bound value must be a finite positive real number. The constructor lets a symbol or a deferred value through so that it can be bound; this is where what it bound to is checked, before any matrix or wave is built from it.
sourceJosephsonCircuits.ports_modes_to_modes_ports_block Method
ports_modes_to_modes_ports_block(S::AbstractMatrix,Nmodes::Int)Reorder both axes of the block ordered ladder or quadrature form S of a scattering matrix of Nmodes modes per port from (ports, modes) to (modes, ports) ordering, each of the two blocks of an axis alike; see ports_modes_to_modes_ports_perm. Half the length of each axis must be a multiple of Nmodes.
Examples
S = [:S11 :S12 :S13 :S14 :S15 :S16 :S17 :S18; :S21 :S22 :S23 :S24 :S25 :S26 :S27 :S28; :S31 :S32 :S33 :S34 :S35 :S36 :S37 :S38; :S41 :S42 :S43 :S44 :S45 :S46 :S47 :S48; :S51 :S52 :S53 :S54 :S55 :S56 :S57 :S58; :S61 :S62 :S63 :S64 :S65 :S66 :S67 :S68; :S71 :S72 :S73 :S74 :S75 :S76 :S77 :S78; :S81 :S82 :S83 :S84 :S85 :S86 :S87 :S88]
JosephsonCircuits.ports_modes_to_modes_ports_block(S,2)
# output
8×8 Matrix{Symbol}:
:S11 :S13 :S12 :S14 :S15 :S17 :S16 :S18
:S31 :S33 :S32 :S34 :S35 :S37 :S36 :S38
:S21 :S23 :S22 :S24 :S25 :S27 :S26 :S28
:S41 :S43 :S42 :S44 :S45 :S47 :S46 :S48
:S51 :S53 :S52 :S54 :S55 :S57 :S56 :S58
:S71 :S73 :S72 :S74 :S75 :S77 :S76 :S78
:S61 :S63 :S62 :S64 :S65 :S67 :S66 :S68
:S81 :S83 :S82 :S84 :S85 :S87 :S86 :S88JosephsonCircuits.ports_modes_to_modes_ports_pair Method
ports_modes_to_modes_ports_pair(S::AbstractMatrix,Nmodes::Int)Reorder both axes of the pair ordered ladder or quadrature form S of a scattering matrix of Nmodes modes per port from (ports, modes) to (modes, ports) ordering, moving the two operators of each scattering index together; see ports_modes_to_modes_ports_perm. Half the length of each axis must be a multiple of Nmodes.
Examples
S = [:S11 :S12 :S13 :S14 :S15 :S16 :S17 :S18; :S21 :S22 :S23 :S24 :S25 :S26 :S27 :S28; :S31 :S32 :S33 :S34 :S35 :S36 :S37 :S38; :S41 :S42 :S43 :S44 :S45 :S46 :S47 :S48; :S51 :S52 :S53 :S54 :S55 :S56 :S57 :S58; :S61 :S62 :S63 :S64 :S65 :S66 :S67 :S68; :S71 :S72 :S73 :S74 :S75 :S76 :S77 :S78; :S81 :S82 :S83 :S84 :S85 :S86 :S87 :S88]
JosephsonCircuits.ports_modes_to_modes_ports_pair(S,2)
# output
8×8 Matrix{Symbol}:
:S11 :S12 :S15 :S16 :S13 :S14 :S17 :S18
:S21 :S22 :S25 :S26 :S23 :S24 :S27 :S28
:S51 :S52 :S55 :S56 :S53 :S54 :S57 :S58
:S61 :S62 :S65 :S66 :S63 :S64 :S67 :S68
:S31 :S32 :S35 :S36 :S33 :S34 :S37 :S38
:S41 :S42 :S45 :S46 :S43 :S44 :S47 :S48
:S71 :S72 :S75 :S76 :S73 :S74 :S77 :S78
:S81 :S82 :S85 :S86 :S83 :S84 :S87 :S88JosephsonCircuits.ports_modes_to_modes_ports_perm Method
ports_modes_to_modes_ports_perm(Nports,Nmodes)Return a permutation vector that converts one axis of a scattering matrix with Nports ports and Nmodes modes from (ports, modes) ordering to (modes, ports) ordering. In (ports, modes) ordering the port index runs fastest, as in an array of size (Nports, Nmodes): port p of mode m is at p + (m-1)*Nports. In (modes, ports) ordering the mode index runs fastest, which is the order of the solvers' scattering matrices: mode m of port p is at m + (p-1)*Nmodes. Entry k of the permutation is the index in (ports, modes) ordering of the entry that goes to index k.
Examples
For 2 ports and 4 modes the (ports, modes) ordering is [(p1,m1), (p2,m1), (p1,m2), (p2,m2), (p1,m3), (p2,m3), (p1,m4), (p2,m4)] and the (modes, ports) ordering is [(p1,m1), (p1,m2), (p1,m3), (p1,m4), (p2,m1), (p2,m2), (p2,m3), (p2,m4)]:
julia> p = JosephsonCircuits.ports_modes_to_modes_ports_perm(2,4)
8-element Vector{Int64}:
1
3
5
7
2
4
6
8JosephsonCircuits.ports_modes_to_modes_ports_scattering Method
ports_modes_to_modes_ports_scattering(S::AbstractMatrix,Nmodes::Int)Reorder both axes of the scattering matrix S of Nmodes modes per port from (ports, modes) to (modes, ports) ordering; see ports_modes_to_modes_ports_perm. The length of each axis must be a multiple of Nmodes.
Examples
S = [:S11 :S12 :S13 :S14 :S15 :S16 :S17 :S18; :S21 :S22 :S23 :S24 :S25 :S26 :S27 :S28; :S31 :S32 :S33 :S34 :S35 :S36 :S37 :S38; :S41 :S42 :S43 :S44 :S45 :S46 :S47 :S48; :S51 :S52 :S53 :S54 :S55 :S56 :S57 :S58; :S61 :S62 :S63 :S64 :S65 :S66 :S67 :S68; :S71 :S72 :S73 :S74 :S75 :S76 :S77 :S78; :S81 :S82 :S83 :S84 :S85 :S86 :S87 :S88]
JosephsonCircuits.ports_modes_to_modes_ports_scattering(S,2)
# output
8×8 Matrix{Symbol}:
:S11 :S15 :S12 :S16 :S13 :S17 :S14 :S18
:S51 :S55 :S52 :S56 :S53 :S57 :S54 :S58
:S21 :S25 :S22 :S26 :S23 :S27 :S24 :S28
:S61 :S65 :S62 :S66 :S63 :S67 :S64 :S68
:S31 :S35 :S32 :S36 :S33 :S37 :S34 :S38
:S71 :S75 :S72 :S76 :S73 :S77 :S74 :S78
:S41 :S45 :S42 :S46 :S43 :S47 :S44 :S48
:S81 :S85 :S82 :S86 :S83 :S87 :S84 :S88JosephsonCircuits.portsolutionrows Method
portsolutionrows(nodeindices, portindices, Nmodes::Integer)The rows of a solution of the linearized system which the scattering parameter calculation reads: for each port, each of its two nodes which is not ground, and each mode.
calcoutputwaves! reads a solution only through calcportvoltage, which touches these rows and no others. On a backend the solutions are produced there, so gathering these rows and copying back only them replaces a transfer of the whole solution, which is the same size as the state of the whole circuit, with one the size of the scattering matrix.
JosephsonCircuits.portsourcecurrents Method
portsourcecurrents(bnm, portindices, nodeindices, Nmodes)The source current of each port mode in its own column of the source terms bnm of a sweep, whose column (i-1)*Nmodes+j is a unit current source at the port i and the mode j and at no other port, even one which shares a node with it: ±1, the sign by which the orientation of the port branch in the incidence matrix differs from the node order of the port component (see calcsourcecurrent). These are all the source currents the waves of a sweep need, and they do not depend on the frequency.
Examples
julia> bnm = ComplexF64[1 0; 0 1]; # port 1 from node 2 to ground, port 2 from ground to node 3
julia> JosephsonCircuits.portsourcecurrents(bnm, [1, 2], [2 1; 1 3], 1)
2-element Vector{ComplexF64}:
1.0 + 0.0im
-1.0 - 0.0imJosephsonCircuits.portsources Method
portsources(Rbnm::SparseMatrixCSC, portbranches, Nmodes::Integer,
Nauxmna::Integer)The right hand sides of the linearized sweep: a unit current source at each port and mode, in the node basis, with Nauxmna zero rows for the auxiliary unknowns below the nodal ones. The source of the port on branch b at mode j is the row (b-1)*Nmodes + j of the branch incidence Rbnm, so each column is read off Rbnm in one pass over its stored entries, the columns in the order of portbranches, the modes of each port in turn.
JosephsonCircuits.portwavescale Method
portwavescale(portimpedance, w)The scale factor of the Kurokawa power waves at a port with impedance portimpedance and (signed) mode frequency w, in units of sqrt(photons/second) rather than sqrt(power): 1/sqrt(real(Z))/sqrt(abs(w)), and zero at zero frequency, where the wave normalization is singular. This is the single definition used by the waves (calcinputwaves!, calcoutputwaves!) and by the sensitivity scaling (calcsensitivityscaling!), so the two cannot drift apart.
The zero is a convention and not an approximation, and it is what keeps the direct current out of the waves. The voltage those functions reconstruct is im*w*phi, which is zero at zero frequency whatever the average voltage is; a circuit with an explicit direct current block has a physical zero frequency voltage which that reconstruction cannot see. Returning it through this scale would mix a voltage the extractor does not know about into a normalization which does not exist there. The direct current operating point is reported as a voltage instead.
JosephsonCircuits.pre_iwasawa_block Method
pre_iwasawa_block(S::AbstractMatrix)Return the pre-Iwasawa decomposition E, D, F of the symplectic matrix S = [S11 S12; S21 S22] in block operator order, S = E*D*F. With A0 = sqrt(S11*transpose(S11) + S12*transpose(S12)), D = [A0 0; 0 inv(A0)] is block diagonal, E = [I 0; C0*inv(A0) I] with C0 = (S21*transpose(S11) + S22*transpose(S12))*inv(A0) is lower block triangular with identity diagonal blocks, and F = [X Y; -Y X] with X = inv(A0)*S11 and Y = inv(A0)*S12 is symplectic, and orthogonal for a real S.
References
[1] M. Houde, W. McCutcheon, and N. Quesada, “Matrix decompositions in Quantum Optics: Takagi/Autonne, Bloch-Messiah/Euler, Iwasawa, and Williamson,” Can. J. Phys., vol. 102, no. 10, pp. 497–507, Oct. 2024, doi: 10.1139/cjp-2024-0070. [2] Arvind, B. Dutta, N. Mukunda, and R. Simon, “The real symplectic groups in quantum mechanics and optics,” Pramana - J Phys, vol. 45, no. 6, pp. 471–497, Dec. 1995, doi: 10.1007/BF02848172.
sourceJosephsonCircuits.pre_iwasawa_pair Method
pre_iwasawa_pair(S::AbstractMatrix)The pair ordered form of pre_iwasawa_block: S and the factors are in pair order.
JosephsonCircuits.preconditionedproduct! Method
preconditionedproduct!(w, z, Aop, M, v)One right preconditioned Arnoldi step: overwrite z with inv(M)*v and w with A*z, and return the seconds spent inside the preconditioner. The timing excludes the Jacobian product so that precondtime in KrylovSolveInfo means the same thing whatever the preconditioner.
JosephsonCircuits.preparenoise Method
preparenoise(noise, n)The noise model of a block as it is stored: a NoiseCovariance with its data as a matrix provider of the block's dimension n, and any other model unchanged. The data is checked with the block's (see checkblockcontract).
JosephsonCircuits.probecouplings! Method
probecouplings!(pr::ClusterProbe, sys::HBSystem, Nmodes::Integer)Measure the block norms of the block Jacobi iteration matrix at the current point, one Jacobian product and one block diagonal solve per mode: the column j of pr.W holds, for every mode, the norm of what the block diagonal solve of the product of the Jacobian with a random vector on mode j's slots leaves on that mode, relative to the input. This is the coupling strength the cluster rule sorts by, and it includes the gain of the receiving mode's block, which a coefficient of cos(phi(t)) alone does not: a large coefficient into a stiff mode's block moves little, and a small one into a soft mode's block can move much.
JosephsonCircuits.provablylossless Method
provablylossless(block::ScatteringParameters)Whether the scattering data can be shown to be unitary at every frequency to the block's atol from the data alone (see unitaritybound): a constant and a table can be, a lossless line is by construction, and a callable, whose values away from any sampled frequency are unknown, and a realization, whose norms are costly to bound, are not.
A block which is not provably lossless carries noise channels (ScatteringNoisePlan), and those of a block which is in fact lossless are identically zero, so a false costs work. A true leaves out channels whose commutator I - S S' is within the block's atol of zero, the tolerance a block declared Lossless is held to.
JosephsonCircuits.providersize Method
providersize(p::AbstractMatrixProvider)Return the matrix dimension n of the n by n matrices produced by the provider.
sourceJosephsonCircuits.psdcholesky! Method
psdcholesky!(L, off, n)Overwrite the length n*n column major block of L at off, whose lower triangle holds a Hermitian positive semidefinite matrix V, with a lower triangular factor satisfying L L' = V.
The noise covariance of a block which is transparent in some direction, such as a series element, is singular, and rounding can make that of a lossless block slightly indefinite, so this is not a plain Cholesky factorization: a pivot which is not positive is taken as zero, which for a positive semidefinite matrix means its whole column is zero and there is nothing to divide by. The strict upper triangle held the covariance and is zeroed, so the result is the factor and nothing else.
Any factor of the covariance describes the same noise: the channels are defined only up to a unitary mixing among them, and the quantum efficiency and the commutation relations read only sums over them. A triangular factor is chosen over an eigendecomposition because it is a few lines of arithmetic with no iteration, so the host and a kernel can share it and agree to the last bit.
sourceJosephsonCircuits.pumpedblocknoisewaves! Method
pumpedblocknoisewaves!(noiseoutputwave, block::LinearizedScattering, sb,
wmodes, phiadj, rowoffset, Nmodes, K)The noise output waves of the channels of a pumped block which states its noise, into the rows of noiseoutputwave after rowoffset, as blocknoisewaves! does for a block which does not convert.
The block's noise is one wave over all its ports and modes at once, of covariance V and commutator K = J - S J S' (see pumpednoisematrices), so its channels are the columns of the factors of V + K/2, which emit like modes in their vacuum, and of V - K/2, which emit like their conjugates, each channel carrying the vacuum's half photon; each column spans the port current rows of every mode. The block has 2 nports channel slots of Nmodes rows each in the noise scattering matrix, and the columns are laid out over those rows, a column per row, the first nports slots holding the first kind and the rest the second, so that every row is one channel; their sign kinds are fixed (see noisechannelsigns). Each row is the contraction of its column against the adjoint solution over all the block's rows, with the square root of each mode's frequency, and is multiplied by the sign of its own row's mode frequency, which the adjoint route's sign (see adjointnoisesigns!) then undoes, so that after it the entry carries the sign of the output port mode's frequency, as the entry of a lumped channel does.
JosephsonCircuits.pumpedfamily Method
pumpedfamily(block::LinearizedScattering, nus; reach = true, keep = false)The output modes a pumped block's data reaches from the frequencies nus, every input mode which feeds them, and the harmonic coupling each pair, as (rows, cols, K) for pumpednoisematrices: the outputs are the signed frequencies a harmonic of the block apart from one of nus, or nus themselves with reach = false, into which the block holds an entry from an input a harmonic apart that its data covers, and at which a stated covariance holds its row, and the inputs are every such input, which reach one harmonic further out than the outputs where the data goes so far. Frequencies within roundoff of one another are one mode, and K[m, n] is typemin(Int) where the block holds no entry from cols[n] to rows[m]. Validating the outputs against every input which reaches them, rather than one set of modes against itself, keeps a truncation of the inputs at the edge of the set from counting as a violation by the data.
With keep every frequency is an output whether the block's data reaches it or not, which is how a completed covariance is formed (see completedcovariance): a frequency the data does not reach is one the block scatters nothing at, an output of the circuit all the same, and its row of the commutator is the one it has there.
JosephsonCircuits.pumpedharmonics Method
pumpedharmonics(block::LinearizedScattering, offsets::AbstractVector)The harmonic of block which couples each pair of modes of a circuit, as a matrix over (output mode, input mode) of the multiple of the block's pump by which the modes' frequency offsets differ, or typemin(Int) where they differ by no such multiple or by one the block does not convert by. Throws if the block converts and no pair of modes is a pump apart, which is a circuit solved without the block's pump.
JosephsonCircuits.pumpednoisematrices Method
pumpednoisematrices(block::LinearizedScattering, wmodes, K;
complete = true)
pumpednoisematrices(block::LinearizedScattering, rows, cols, K;
complete = true)The multi-mode matrices of a pumped block at the signed mode frequencies wmodes, over the index (p - 1)*Nmodes + m of port p at mode m, in the units of the solver's outputs, waves of photons per second: its scattering matrix S, from its harmonic transfer functions on power waves through the harmonic K[m, n] coupling each pair of modes (see pumpedharmonics) and the square root of the frequency ratio; the commutator J - S J S' of the noise its output needs, with J the signs of the mode frequencies; and, for a block which states its noise, the covariance V from its harmonic covariances, V_{-k}(nu) being V_k(nu - k wp)', or nothing. The rows and columns of a mode at zero frequency are left zero, the wave normalization being singular there. With the output modes rows and the input modes cols given apart, K[m, n] coupling rows[m] to cols[n], S is the block from the inputs to the outputs, the commutator J_rows - S J_cols S' is that of the outputs with every input which reaches them, and V is over the outputs: what validates a set of outputs without truncating the inputs they are fed by (see pumpedfamily). The covariance of a block whose noise model is completed is the completed one, from completedcovariance, unless complete = false asks for the covariance as stated.
JosephsonCircuits.pumpmodeset Method
pumpmodeset(w, Nharmonics, Nevaluationharmonics; dc = false,
odd = true, even = false, maxintermodorder = Inf,
frequencywindow = (0, Inf), retained = Nharmonics)The modes of a nonlinear (pump) solve and their Fourier indices, as (frequencies, indices): the modes of the transform grid of Nevaluationharmonics harmonics of each tone of w which the truncations keep, with at most retained harmonics of each tone (truncfreqs), without their conjugates (removeconjfreqs), and their fourierindices. Nevaluationharmonics must be at least Nharmonics in every tone, and is an ArgumentError otherwise; retained is Nharmonics except on a stage of a continuation which retains fewer. A truncation which retains no mode is an ArgumentError naming the options which make it.
JosephsonCircuits.pumpsourcecurrents Method
pumpsourcecurrents(sources, modes, portindices, portnumbers, nodeindices)The source current of each port mode (i-1)*Nmodes+j of a pump solve, in units of the flux quantum: the sum of the currents the sources give at the port i and the mode j, with the sign by which the orientation of the port branch differs from the node order of the port, as portsourcecurrents reads it for a sweep. A port no source drives has none, even one which shares a node with a driven port.
JosephsonCircuits.quadratic_trial_step Method
quadratic_trial_step(ϕ0, ϕ1, dϕ0dα, ls::Backtracking)Return a tuple (αtrial, ϕtrial, measured): the step αtrial which minimizes a quadratic fitted to the merit function ϕ(α) = f(xₖ + α pₖ) on [0, 1], the merit ϕtrial there, and measured, whether ϕtrial was evaluated rather than estimated from the fit. The fit takes the merit at α = 0 and at α = 1 and its derivative dϕ(α)/dα|α = 0. A full step α = 1 which satisfies the Armijo sufficient-decrease condition ϕ(1) <= ϕ(0) + c1 dϕ(α)/dα|α = 0 is returned without a fit.
Based on Nocedal and Wright, chapter 3 section 5.
Arguments
ϕ0:ϕ(0), the value of the merit function atα = 0, finite.ϕ1:ϕ(1), the value of the merit function atα = 1.dϕ0dα:dϕ(α)/dα|α=0, the derivative of the merit function with respect toαatα = 0, finite and negative.ls: theBacktrackingwhich gives the constantc1of the Armijo condition and the safeguards which bound the proposed step. The lower one,safeguardlow, protects against large (eg. order of magnitude) reductions in the step size without an additional function evaluation, which would occur outside of this function; the fitted minimizer of a full step which fails the Armijo condition is below1/(2(1 - c1)), so the upper one,safeguardhigh, acts only when it is set below that.
The callers check ϕ0 and dϕ0dα before any search, and ls checked its settings when it was built, so neither is checked here.
Returns
αtrial: the step the quadratic fit predicts to minimize the merit function, within the safeguards, or the full step.ϕtrial: the merit atαtrial, measured or predicted. A predicted one is the fit's: the line search evaluates the trial point and tests the Armijo condition there before accepting the step.measured:truewhen the full step is returned, having satisfied the Armijo condition, so thatϕtrialis its measured merit, andfalsewhenϕtrialis an estimate.
JosephsonCircuits.quadrature_to_ladder_block Method
quadrature_to_ladder_block(S::AbstractMatrix)Return the matrix S, which maps quadratures in block order [x_1, ..., p_1, ...] to others, as the map between the ladder operators in block order [a_1, ..., adag_1, ...]: R1*S*R2' with R1 and R2 the matrices of R_quadrature_to_ladder_block for the rows and the columns of S.
JosephsonCircuits.quadrature_to_ladder_block Method
quadrature_to_ladder_block(r::AbstractVector)Return the vector r of quadratures in block order [x_1, ..., p_1, ...] in the basis of the ladder operators in block order [a_1, ..., adag_1, ...], R*r with R the matrix of R_quadrature_to_ladder_block.
JosephsonCircuits.quadrature_to_ladder_pair Method
quadrature_to_ladder_pair(S::AbstractMatrix)Return the matrix S, which maps quadratures in pair order [x_1, p_1, ...] to others, as the map between the ladder operators in pair order [a_1, adag_1, ...]: R1*S*R2' with R1 and R2 the matrices of R_quadrature_to_ladder_pair for the rows and the columns of S.
JosephsonCircuits.quadrature_to_ladder_pair Method
quadrature_to_ladder_pair(r::AbstractVector)Return the vector r of quadratures in pair order [x_1, p_1, ...] in the basis of the ladder operators in pair order [a_1, adag_1, ...], R*r with R the matrix of R_quadrature_to_ladder_pair.
JosephsonCircuits.quadrature_to_scattering_block! Method
quadrature_to_scattering_block!(S_scattering, S_symplectic, w; atol = 0,
rtol = ...)In place version of quadrature_to_scattering_block, writing into S_scattering.
JosephsonCircuits.quadrature_to_scattering_block Method
quadrature_to_scattering_block(S_symplectic, w; atol = 0, rtol = ...)Return the scattering matrix whose quadrature (symplectic) form in block operator order is S_symplectic, between modes of signed frequencies w; the inverse of scattering_to_quadrature_block. See quadrature_to_scattering_pair for the tolerances.
JosephsonCircuits.quadrature_to_scattering_pair! Method
quadrature_to_scattering_pair!(S_scattering, S_symplectic, w; atol = 0,
rtol = ...)In place version of quadrature_to_scattering_pair, writing into S_scattering.
JosephsonCircuits.quadrature_to_scattering_pair Method
quadrature_to_scattering_pair(S_symplectic, w; atol = 0, rtol = ...)Return the scattering matrix whose quadrature (symplectic) form in pair operator order is S_symplectic, between modes of signed frequencies w; the inverse of scattering_to_quadrature_pair. The real and the imaginary part of each entry are the averages of the two entries of its block holding each; if the differences exceed max(atol, rtol*norm(S_symplectic)), it is an error. See ladder_to_scattering_pair for the default tolerances.
JosephsonCircuits.quantumnoisemargin Method
quantumnoisemargin(V::AbstractMatrix, S::AbstractMatrix)The commutationmargin of the noise covariance V against K = I - S S', which is nonnegative when V is one a block with the scattering matrix S can add without violating the commutation relations.
JosephsonCircuits.rand_bogoliubov_block Method
rand_bogoliubov_block(n::Integer)Return a random 2n x 2n Bogoliubov matrix S, S ∈ Sp(2n, ℂ) ∩ U(n, n) =: Bog(n), with block operator order.
JosephsonCircuits.rand_bogoliubov_pair Method
rand_bogoliubov_pair(n::Integer)Return a random 2n x 2n Bogoliubov matrix S, S ∈ Sp(2n, ℂ) ∩ U(n, n) =: Bog(n), with pair operator order.
JosephsonCircuits.rand_conjugate_symplectic_block Method
rand_conjugate_symplectic_block(T, n::Integer)Return a random 2n x 2n conjugate symplectic matrix S, S*Ω*S' == Ω, of element type T, with block operator order.
JosephsonCircuits.rand_conjugate_symplectic_pair Method
rand_conjugate_symplectic_pair(T, n::Integer)
rand_conjugate_symplectic_pair(n::Integer)The pair ordered form of rand_conjugate_symplectic_block.
JosephsonCircuits.rand_cptp_ladder_block Method
rand_cptp_ladder_block(T, nsys; nenv = nsys, sigma_env = I(2*nenv))
rand_cptp_ladder_block(nsys; nenv = nsys)Return a random CPTP map (X, Y) of nsys modes in the ladder basis with block operator order, with an environment of nenv modes and the symmetrized covariances of rand_cptp_ladder_pair.
JosephsonCircuits.rand_cptp_ladder_pair Method
rand_cptp_ladder_pair(T, nsys; nenv = nsys, sigma_env = I(2*nenv))
rand_cptp_ladder_pair(nsys; nenv = nsys)Return a random CPTP map (X, Y) of nsys modes in the ladder basis with pair operator order: the system block X of a random Bogoliubov matrix of nsys + nenv modes and the noise Y = B*sigma_env*B' its system-environment block B adds from an environment of nenv modes with covariance sigma_env. The covariances are symmetrized, with the vacuum I/2 of is_cptp_ladder_pair; the default sigma_env = I is a thermal state of half a photon in each mode. T is the element type, Complex{Float64} by default.
JosephsonCircuits.rand_cptp_quadrature_block Method
rand_cptp_quadrature_block(T, nsys; nenv = nsys, hbar = 1,
sigma_env = hbar*I(2*nenv))
rand_cptp_quadrature_block(nsys; nenv = nsys, hbar = 1)Return a random completely positive trace preserving (CPTP) map (X, Y) of nsys modes in the quadrature basis with block operator order: the system block X of a random symplectic matrix of nsys + nenv modes and the noise Y = B*sigma_env*transpose(B) its system-environment block B adds from an environment of nenv modes with covariance sigma_env. The covariances are in the units of hbar of is_cptp, whose vacuum is (hbar/2)*I; the default sigma_env = hbar*I is a thermal state of half a photon in each mode, and a given sigma_env is taken in these units as it is. T is the element type, Float64 by default.
JosephsonCircuits.rand_cptp_quadrature_pair Method
rand_cptp_quadrature_pair(T, nsys; nenv = nsys, hbar = 1,
sigma_env = hbar*I(2*nenv))
rand_cptp_quadrature_pair(nsys; nenv = nsys, hbar = 1)Return a random CPTP map (X, Y) of nsys modes in the quadrature basis with pair operator order, with an environment of nenv modes, in the units of hbar of is_cptp; see rand_cptp_quadrature_block.
JosephsonCircuits.rand_orthogonal Method
rand_orthogonal(n::Integer)A random n by n orthogonal matrix, rand_unitary of a real matrix.
JosephsonCircuits.rand_orthogonal_bogoliubov_block Method
rand_orthogonal_bogoliubov_block(n::Integer)Return a random 2n x 2n orthogonal Bogoliubov matrix S, S ∈ Sp(2n, ℂ) ∩ U(n, n) ∩ U(2n) ≅ U(n), with block operator order.
JosephsonCircuits.rand_orthogonal_bogoliubov_pair Method
rand_orthogonal_bogoliubov_pair(n::Integer)Return a random 2n x 2n orthogonal Bogoliubov matrix S, S ∈ Sp(2n, ℂ) ∩ U(n, n) ∩ U(2n) ≅ U(n), with pair operator order.
JosephsonCircuits.rand_orthogonal_symplectic_block Method
rand_orthogonal_symplectic_block(n::Integer)Return a random 2n x 2n orthogonal symplectic matrix S, S ∈ Sp(2n, ℝ) ∩ O(2n) ≅ U(n), with block operator order.
JosephsonCircuits.rand_orthogonal_symplectic_pair Method
rand_orthogonal_symplectic_pair(n::Integer)Return a random 2n x 2n orthogonal symplectic matrix S, S ∈ Sp(2n, ℝ) ∩ O(2n) ≅ U(n) with pair operator order.
JosephsonCircuits.rand_positive_definite Method
rand_positive_definite(T, n::Integer)
rand_positive_definite(n::Integer)A random n by n positive definite matrix of element type T (Float64 by default), A*A' for a random matrix A; see rand_positive_semi_definite.
JosephsonCircuits.rand_positive_definite_symplectic_block Method
rand_positive_definite_symplectic_block(T, n::Integer)Return a random 2n x 2n positive definite symplectic matrix S, S ∈ Sp(2n, ℝ) or S ∈ Sp(2n, ℂ), depending on the type T with block operator order.
JosephsonCircuits.rand_positive_definite_symplectic_block Method
rand_positive_definite_symplectic_block(n::Integer)Return a random 2n x 2n positive definite symplectic matrix S, S ∈ Sp(2n, ℝ), with block operator order.
JosephsonCircuits.rand_positive_definite_symplectic_pair Method
rand_positive_definite_symplectic_pair(T, n::Integer)Return a random 2n x 2n positive definite symplectic matrix S, S ∈ Sp(2n, ℝ) or S ∈ Sp(2n, ℂ), depending on the type T with pair operator order.
JosephsonCircuits.rand_positive_definite_symplectic_pair Method
rand_positive_definite_symplectic_pair(n::Integer)Return a random 2n x 2n positive definite symplectic matrix S, S ∈ Sp(2n, ℝ), with pair operator order.
JosephsonCircuits.rand_positive_semi_definite Method
rand_positive_semi_definite(T, n, m)
rand_positive_semi_definite(n, m)A random (n + m) by (n + m) positive semidefinite matrix of rank at most n and element type T (Float64 by default), as A*A' for a random (n + m) by n matrix A with entries uniform in [0, 1).
JosephsonCircuits.rand_pseudo_unitary_block Method
rand_pseudo_unitary_block(n::Integer)Return a random 2n x 2n pseudo-unitary matrix S, S ∈ U(n, n), with block operator order.
JosephsonCircuits.rand_pseudo_unitary_pair Method
rand_pseudo_unitary_pair(n::Integer)Return a random 2n x 2n pseudo-unitary matrix S, S ∈ U(n, n), with pair operator order.
JosephsonCircuits.rand_symplectic_block Method
rand_symplectic_block(T, n::Integer)Return a random 2n x 2n symplectic matrix S, S ∈ Sp(2n, ℝ) or S ∈ Sp(2n, ℂ), depending on the type T with block operator order.
JosephsonCircuits.rand_symplectic_block Method
rand_symplectic_block(n::Integer)Return a random 2n x 2n symplectic matrix S, S ∈ Sp(2n, ℝ), with block operator order.
JosephsonCircuits.rand_symplectic_pair Method
rand_symplectic_pair(n::Integer)Return a random 2n x 2n symplectic matrix S, S ∈ Sp(2n, ℝ), with pair operator order.
JosephsonCircuits.rand_unitary Method
rand_unitary(T, n::Integer)
rand_unitary(n::Integer)A random n by n unitary matrix, the exponential of the skew-Hermitian part of a random matrix of element type T (ComplexF64 by default); see is_unitary.
JosephsonCircuits.real_to_complex! Method
real_to_complex!(xc, xr, isreal) -> xcReal -> complex. The imaginary part of a real mode is written as an explicit zero, so the result does not depend on what was in xc beforehand.
JosephsonCircuits.realblockterm Method
realblockterm(v, dr, dc)The entry at offset (dr, dc) of the real block a complex value v contributes: the two by two block [real(v) -imag(v); imag(v) real(v)] which multiplication by v is in the (real, imag) coordinates of a complex mode, of which a self conjugate (real) mode keeps only the first row, the first column, or both. The one rule behind every real form in the package: the sparse complex_to_real, the real Jacobian assembly and the block factorization values.
JosephsonCircuits.realdim Method
realdim(dim, isreal) -> IntLength of the real form of a dim-long complex axis under mask isreal.
JosephsonCircuits.realjacobiancolumnitem! Method
realjacobiancolumnitem!(nzval, rr, colptr, rowval, lin, phimatrix,
pairptr, pairrow, pairjunc, paircoef, lmolj, ami, amc, slots, Nfreq)Assemble the stored column rr of a host plan in the natural orientation, which the row kernel and the host loop share. The column is decoded once, and the row of each entry read from slots, the decode of every real index (realslottable); the entry is then what realstructureentry gives, plus the linear term.
JosephsonCircuits.realjacobianstructure Method
realjacobianstructure(Amatrixindices::Matrix, Amatrixconjindices::Matrix,
Ljb::SparseVector, Rbnm::SparseMatrixCSC, Nmodes::Integer,
Nbranches::Integer, invLnm, Gnm, Cnm, layout::ModeLayout,
::Type{T} = Float64; transposed = false, backend = CPU())The sparsity structure P of the real Jacobian. The Jacobian is square, its rows and columns both in the real representation layout.
P is a SparseMatrixCSC with zero values on a host and a DeviceSparsePattern on a backend, which is what a device factorization can be built from without a conversion. transposed returns the structure of the transpose, whose stored order is the row major order of the Jacobian.
Nothing sized by the circuit is built on the host on a backend: the complex pattern is built and transposed there and expanded there, and the only host inputs are the node adjacency and the active mode rows.
sourceJosephsonCircuits.realjosephsonentry Method
realjosephsonentry(::Type{T}, rowslot, colslot, Nfreq, ami, amc, pairptr,
pairrow, pairjunc, paircoef, lmolj, phimatrix)The Josephson contribution to the stored entry of the real Jacobian whose row and column decode to rowslot and colslot (realslot), which is what every real assembly computes: the two kernels and the host loop here and the block preconditioner's blockassemblykernel!.
The junctions incident on the node pair of the entry are looked up, and their contributions summed. (r0, c0) and (r0+1, c0+1) are the real part entries and (r0+1, c0) and (r0, c0+1) the imaginary part ones, so a stored entry belongs to exactly one of the two and only one kind of contribution can reach it.
JosephsonCircuits.realslot Method
realslot(r, linv, lptr, Nmodes)The decode of the real index r of a layout with inverse linv and pointer lptr: the offset of r within the real block of its complex index, the width of that block, and the node and the mode of the complex index.
JosephsonCircuits.realstructureentry Method
realstructureentry(::Type{T}, rri, rci, Nmodes, Nfreq, ami, amc, pairptr,
pairrow, pairjunc, paircoef, lmolj, linv, lptr, phimatrix)The Josephson contribution to the stored entry of the real Jacobian at row rri and column rci, both decoded here (realslot): what the per entry kernel and the block preconditioner's blockassemblykernel! compute for each entry. The per column assembly of a host decodes its stored column once instead, and both sum the contribution with realjosephsonentry.
JosephsonCircuits.realtocomplexkernel! Method
realtocomplexkernel!(xc, xr, lptr, lwide)Expand the equivalent real representation of a node vector into the complex one, one work item per complex entry, reading the real slot layout the plan already carries. The imaginary part of a self conjugate mode is written as an explicit zero, so the result does not depend on what was in xc beforehand. Each work item owns its own entry, so this is conflict free. Unlike the scalar real_to_complex!, which advances a serial cursor and reads a BitVector, it runs on a device. See NonlinearTermPlan.
JosephsonCircuits.rebind! Method
rebind!(sys::HBSystem, invLnm, Gnm, Cnm, bnm, Ljb, Ljbm, Lscale;
maps::ValueMaps, relations, realjacobianplan = sys.realjacobianplan,
complexjacobianplan = sys.complexjacobianplan)The same system at new component values: the linear term matrices, the source, the junction inductances, the coefficients of the junctions' current-phase relations and the scale are replaced by the new ones, in place where the arrays live and by a new struct sharing them where a scalar does. The mode frequencies are read from the diagonals the system holds, which a solve at other tone frequencies rewrites in place before the rebind (see HBReuse). The transforms, the index maps, the kernels and every workspace stay, and the values are written through maps, the ValueMaps of the system, so what it allocates is the two temporaries of the source vector, the junction length vectors of the refreshed coefficients, and the temporaries of the relations. relations are the new JunctionRelations on the host, or nothing when every junction is sinusoidal, as the constructor takes them.
The structure must not have moved: a sparse pattern which differs from the one the system was built on is refused, because the plans are built on the pattern and a value which moves it is a new circuit and not a new point. So are relations of another shape, a junction which turned from the sinusoidal relation to a polynomial one or back, or a polynomial of another degree, whose tables and workspaces the system was not built with.
The assembly plans of the Jacobians hold the gathered linear term and, in their JunctionStructure, Lscale/Lj; a plan the system holds is refreshed to the new values here, and a plan passed as realjacobianplan or complexjacobianplan, built for the new values by a solve which needs a Jacobian the system did not hold, is installed instead.
JosephsonCircuits.rebind! Method
rebind!(pc::ModeCouplingPreconditioner, sys::HBSystem)The same preconditioner over a system rebound to new component values: the structure, the coupling set and the factorization's symbolic analysis are kept, and the constant linear contribution of its assembly plan and the junction coefficients are refreshed from the system at the next refactorization (refactorize!), so that a solve which takes no step pays nothing for them. The next updatepreconditioner! refactorizes the numbers.
JosephsonCircuits.refactorize! Method
refactorize!(pc::ModeCouplingPreconditioner)Assemble the restricted Jacobian at the system's current point and factorize it: what updatepreconditioner! does after setting the point and choosing the coupling set. The constant values of the assembly which a rebind! left to be refreshed are refreshed first.
A block factorization does not pivot across supernodes, so a supernode whose diagonal block is singular stops it although the whole matrix need not be singular: a node whose stiffness at some mode frequency lives in a promoted branch current (the current of a coupled inductor, the port current of a scattering block) has an exactly zero diagonal there when its own elements resonate. When that happens the preconditioner switches to the backend's sparse factorization, which pivots over the whole matrix, and keeps it for the rest of the solve: of the same coupling set when its factors fit the budget an escalation keeps to (escalatepreconditioner!), and of the mode block diagonal, which an escalation may grow, when they do not.
JosephsonCircuits.refill! Method
refill!(lin::PaddedLinearTerm, invLnm, Gnm, Cnm, AmnaL, bbm, Rbnm0;
blockterm = nothing, scale = lin.scale[])Move the values of a new assembly of the unpadded matrices, of the coupled inductor rows AmnaL (or nothing when there are none) and of the branch drive bbm into the padded linear term, in place, and with them the scattering block term blockterm stamped at the solver scale scale, which is needed only when the scale moved. The result is entry for entry what hbnlsolve assembles from the same inputs.
JosephsonCircuits.refinedsolve! Method
refinedsolve!(X, F::SparseBlockFactorization, B; transposed = false,
rtol = 4*eps(real(eltype(B))), contraction = 1/2)The batched solve, refined against the residual when the factors are in single precision: X += F \ (B - A X) for at most refinesteps steps, each system until its residual is within rtol*norm(B), the rounding of the double residual, or until a step fails to bring its residual below contraction times the last. Exact factors solve once.
JosephsonCircuits.refreshblockstamps! Method
refreshblockstamps!(wbs::WorkerBlockSensitivity, wmodes)Rebuild this worker's :S stamp values at the signed mode frequencies wmodes.
JosephsonCircuits.refreshlinear! Method
refreshlinear!(lin, g::LinearTermGather, invLnm, Gnm, Cnm, wmodesm,
wmodes2m, backend)Write the linear term at the values of invLnm, Gnm and Cnm into the entries of lin it reaches: the new values are copied into the gather's own, and linearentry is evaluated at each reached entry, a plain loop on the host and a kernel on a device. The matrices must have the structure the gather was built on.
JosephsonCircuits.refreshvalues! Method
refreshvalues!(plan::StructureComplexJacobianPlan, invLnm, Gnm, Cnm,
wmodesm, wmodes2m, Ljb, Lscale)Rewrite the gathered linear term and the junction coefficients of a complex plan for new component values under the same structure.
sourceJosephsonCircuits.refreshvalues! Method
refreshvalues!(plan::StructureRealJacobianPlan, invLnm, Gnm, Cnm,
wmodesm, wmodes2m, Ljb, Lscale)Rewrite the value arrays of an assembly plan for new component values under the same structure: the constant linear term at the entries it reaches (refreshlinear!), and Lscale/Lj per junction. The incidence products and the structure are what they were.
JosephsonCircuits.refreshvalues! Method
refreshvalues!(S::BlockStructure, sys::HBSystem)The assembly ingredients of a block structure refreshed from a system rebound to new component values: the linear term matrices, the junction coefficients and the pair table. The structure and the ordering are kept.
sourceJosephsonCircuits.refreshvalues! Method
refreshvalues!(js::JunctionStructure, Ljb::SparseVector, Lscale)Rewrite the junction coefficients Lscale/Lj of a structure for new component values; the table and the index matrices are what they were. The junctions must be the same ones.
JosephsonCircuits.refreshvalues! Method
refreshvalues!(plan::NonlinearTermPlan, maps::ValueMaps, Knm, Ljb, Lscale)Rewrite the value arrays of a plan through its ValueMaps: up to three passes over the arrays where they live (the real form only when the plan has one, the Josephson coefficients only when there are junctions), plain loops on the host and kernels on a device; nothing the size of the plan is allocated, a junction length vector of coefficients is.
JosephsonCircuits.relationat Method
relationat(r::JunctionRelations, phi)The current-phase relation of every junction at the branch phases phi, whose first axis is the junction: sin.(phi) when every relation is the Josephson one, and the polynomials by Horner otherwise. Allocating, for the setup, the diagnostics and the noise, which are not inside a step loop; relationinto! is the in place form the steps take.
phi and the table must live on the same backend, so a host path takes a host table from hostrelations.
JosephsonCircuits.relationinto! Method
relationinto!(out, r::JunctionRelations, phi)relationat writing into out, which may not alias phi. A circuit whose junctions are all sinusoidal takes a single broadcast of sin.
JosephsonCircuits.releasearray! Method
releasearray!(x)Return the memory of the device array x to its backend's memory pool at once, rather than when the collector finds the array; x must not be used again. A no-op on the host; the CUDA extension frees a CUDA array.
JosephsonCircuits.releasesweep! Method
releasesweep!(ds::DeviceSweep)Return the device memory of a finished sweep at once rather than when the collector finds it (releasearray!): the factors, values, solutions and right-hand sides of its batches, the staging of its solutions, and cuDSS's factorizations. The next solve or sweep sizes itself against the free memory (freememory), which memory the collector has not yet found would shrink. ds is not used afterwards.
JosephsonCircuits.removeconjfreqs Method
removeconjfreqs(frequencies::Frequencies{N})Return a new Frequencies struct with the conjugate symmetric terms in the DFT or RDFT removed.
sourceJosephsonCircuits.removedimpedancekeywords Method
removedimpedancekeywords(to; returnZ = nothing, returnZadjoint = nothing,
returnZsensitivity = nothing, returnZsensitivityadjoint = nothing)A deprecation, going to the entry point or the messages of the call (see warndeprecations), when any of the impedance outputs v0.5.4's hbsolve and hblinsolve took is given: no output replaces them, and they are otherwise ignored. hbsolve, its single pump form and hblinsolve hand them here.
JosephsonCircuits.removefreqs Method
removefreqs(frequencies::Frequencies{N},
removemodes::AbstractVector{NTuple{N,Int}})
removefreqs(frequencies::Frequencies{N},
removecoords::AbstractVector{CartesianIndex{N}})Return a new Frequencies without the modes removemodes, or without the modes at the coordinates removecoords, keeping the others in their order.
JosephsonCircuits.reparameterize Method
reparameterize(stamp::SensitivityStamp, alpha, parameter)The same stamp expressed as the derivative with respect to a real design parameter rather than a relative perturbation of the component value.
A component's contribution to the system matrix is linear in its value c, and the negative frequency conjugation is applied to the stored value at contraction time (sensitivitystampvalue), so
d/dtheta modevalue(c, w) = modevalue(dc/dtheta, w),and the stamp for theta is the stamp for c rescaled by alpha = (dc/dtheta)/c. Nothing else changes: the sparsity, the kind and the frequency scaling are all properties of the component, not of the parameterization.
This is what makes the real parameter form correct for complex component values, where the relative form is not. A relative perturbation moves c along itself, so dS/dr is a single complex number which cannot resolve the two real directions of a complex c; carrying dc/dtheta as the direction resolves them, because a real theta which rotates c in the complex plane produces a dc/dtheta which is not parallel to c.
JosephsonCircuits.residual! Method
residual!(F::AbstractVector, sys::HBSystem)Evaluate the residual of the harmonic balance nonlinear system, F = B(sin.(A*x)) + K*x - b, at the point set with setpoint!, in place. Dispatches on the element type of F: a complex vector receives the complex representation and a real vector the equivalent real representation.
JosephsonCircuits.residualstalled Function
residualstalled(normF::AbstractVector, start::Integer,
history::Integer = STALLHISTORY; atol = nothing, remaining = nothing)Whether the residual history normF[start:end] has stalled. The whole history from start is judged, once it is at least history points long: it is split in half and a geometric rate taken over each. A later rate better than the earlier one is an iteration accelerating into a Newton basin, never a stall. Otherwise the residual has stalled when it is flat or rising, and, given the tolerance atol and a budget of remaining further steps, when the steps its later rate projects to the tolerance, log(atol/normF)/log(rate), exceed the budget. A plateau after a long descent is judged against the whole descent, so it is a stall only once it is long enough to bring the later rate to one; a caller which wants a fresh judgement moves start forward, as the Krylov loop does after its recovery.
The projection is what ends a solve whose line search keeps finding a decrease: along a descent direction a short enough step always meets the Armijo condition, and the residual can creep for the whole iteration budget without its rate reaching one. Near a plateau the projection diverges, so a loop takes it only after giving a first stall a fresh history: the Krylov loop with a recovery (a rebuilt preconditioner and exact steps), the direct loop, whose steps are exact already, with the fresh history alone.
sourceJosephsonCircuits.resolveautomatic Method
resolveautomatic(sys, Rbnm, Nmodes, Nbranches, layout, Amatrixmodes,
backend; budget = memorybudget(backend))The member of the mode coupling family an Automatic request stands for on this problem: FullJacobian with the backend's sparse factorization for one tone; otherwise FullJacobian with single precision block factors when blockfactorbytes is within budget, and MeasuredBand when it is not.
One tone takes the full Jacobian for one Krylov iteration per Newton step and no escalation, without sizing its factors first: they grow with the square of the mode count, which one tone keeps low, and a problem too large for them wants preconditioner = BlockDiagonal(). The exact step is no more robust from a cold start than an inexact one; a cold start no line search reaches is the continuation problem Staged exists for.
JosephsonCircuits.restrictmodecoupling Method
restrictmodecoupling(Amatrixindices::Matrix, keep::AbstractMatrix{Bool})Return a copy of a mode coupling index matrix (Amatrixindices or Amatrixconjindices, see hbmatindices) with the couplings not selected by keep set to zero.
This is the whole of the coarse frequency grid transformation. A zero entry of these matrices already means "this coupling falls outside the retained grid and is dropped", which planstructurerealjacobian honors when it builds the sparsity structure (through activemoderows) and when it assembles the values. Zeroing entries therefore produces a Jacobian assembly plan for the mode restricted operator directly: the restricted Jacobian is materialized with the restricted structure rather than assembled in full and masked afterwards, so the saving is realized in the sparsity, the fill in, and the factorization, not just in the arithmetic.
The frequency dependent linear terms invLnm, Gnm and Cnm (including the modified nodal analysis augmentation and the gauge fixing equations) are mode diagonal by construction, so they are unaffected by the restriction and are kept exactly. All of the mode coupling of the Jacobian lives in these two index matrices.
JosephsonCircuits.roundingfloor Method
roundingfloor(n, precision, b; margin = 16)The residual norm below which an iteration in precision over n unknowns cannot drive a residual whose terms are of the size of the source b: the sqrt(n)*eps(precision) accumulation of the rounding of a sum of terms of size norm(b), times margin for room to spare.
JosephsonCircuits.rowpointer Method
rowpointer(A::DeviceValuedSparseMatrix)The compressed sparse row pointer of A, which is the column pointer of the transpose it stores.
JosephsonCircuits.scalecolumns Method
scalecolumns(A::SparseMatrixCSC, d::AbstractVector)A*Diagonal(d) with every stored entry of a column whose d is nonzero kept, a zero valued one included, and the columns whose d is zero left empty.
Examples
julia> A = JosephsonCircuits.SparseArrays.sparse([1, 2, 1], [1, 1, 2], [0.0, 2.0, 3.0], 2, 2);
julia> JosephsonCircuits.scalecolumns(A, [2.0, 0.0])
2×2 SparseArrays.SparseMatrixCSC{Float64, Int64} with 2 stored entries:
0.0 ⋅
4.0 ⋅JosephsonCircuits.scattercanonical! Method
scattercanonical!(rint, u, L::CompositeLayout)Write the internal block of the canonical state u into rint, a copy. The inverse of gathercanonical! on that block.
JosephsonCircuits.scattering_to_block_perm Method
scattering_to_block_perm(p0::Vector{Int})Return the permutation of an axis of the block ordered form of a scattering matrix, in which scattering index i has its two operators at i and i+n for n scattering indices, that moves the scattering indices as the permutation p0 of the scattering matrix does, in each block alike. For example the permutation from (ports, modes) to (modes, ports) ordering of 2 ports and 4 modes, ports_modes_to_modes_ports_perm, becomes:
Examples
julia> JosephsonCircuits.scattering_to_block_perm(JosephsonCircuits.ports_modes_to_modes_ports_perm(2,4))
16-element Vector{Int64}:
1
3
5
7
2
4
6
8
9
11
13
15
10
12
14
16JosephsonCircuits.scattering_to_ladder_block! Method
scattering_to_ladder_block!(S_bogoliubov, S_scattering, w)In place version of scattering_to_ladder_block, writing into S_bogoliubov.
JosephsonCircuits.scattering_to_ladder_block Method
scattering_to_ladder_block(S_scattering::AbstractMatrix, w)Return the ladder (Bogoliubov) form, in block operator order ξ = [a_1, ..., a_n, a_1', ..., a_n'], of the scattering matrix S_scattering between modes of signed frequencies w; see scattering_to_ladder_pair.
JosephsonCircuits.scattering_to_ladder_block Method
scattering_to_ladder_block(S_scattering::AbstractVector, w)Return the ladder vector [a_1, ..., a_n, a_1', ..., a_n'] of the vector of amplitudes S_scattering of modes of signed frequencies w; see scattering_to_ladder_pair.
JosephsonCircuits.scattering_to_ladder_pair! Method
scattering_to_ladder_pair!(S_bogoliubov, S_scattering, w)In place version of scattering_to_ladder_pair, writing into S_bogoliubov.
JosephsonCircuits.scattering_to_ladder_pair Method
scattering_to_ladder_pair(S_scattering::AbstractMatrix, w)Return the ladder (Bogoliubov) form, in pair operator order ξ = [a_1, a_1', ..., a_n, a_n'], of the scattering matrix S_scattering between modes of signed frequencies w. A mode of positive frequency is an annihilation operator a and any other a creation operator a', the mode of scattering index i having the frequency w[mod(i-1, length(w))+1]. Each entry and its conjugate take two of the four entries of the two by two block of its row and column, according to the operators of the two modes, and the other two are zero. S_scattering may be rectangular.
See also ladder_to_scattering_pair, scattering_to_ladder_block and scattering_to_quadrature_pair.
JosephsonCircuits.scattering_to_ladder_pair Method
scattering_to_ladder_pair(S_scattering::AbstractVector, w)Return the ladder vector [a_1, a_1', ..., a_n, a_n'] of the vector of amplitudes S_scattering of modes of signed frequencies w: each amplitude and its conjugate, in the order of an annihilation operator (a mode of positive frequency) and its conjugate, or of a creation operator's conjugate and itself. The length of S_scattering must be a multiple of that of w.
JosephsonCircuits.scattering_to_pair_perm Method
scattering_to_pair_perm(p0::Vector{Int})Return the permutation of an axis of the pair ordered form of a scattering matrix, in which scattering index i has its two operators at 2i-1 and 2i, that moves the scattering indices as the permutation p0 of the scattering matrix does, each pair together. For example the permutation from (ports, modes) to (modes, ports) ordering of 2 ports and 4 modes, ports_modes_to_modes_ports_perm, becomes:
Examples
julia> JosephsonCircuits.scattering_to_pair_perm(JosephsonCircuits.ports_modes_to_modes_ports_perm(2,4))
16-element Vector{Int64}:
1
2
5
6
9
10
13
14
3
4
7
8
11
12
15
16JosephsonCircuits.scattering_to_quadrature_block! Method
scattering_to_quadrature_block!(S_symplectic, S_scattering, w)In place version of scattering_to_quadrature_block, writing into S_symplectic.
JosephsonCircuits.scattering_to_quadrature_block Method
scattering_to_quadrature_block(S_scattering::AbstractMatrix, w)Return the quadrature (symplectic) form, in block operator order r = [x_1, ..., x_n, p_1, ..., p_n], of the scattering matrix S_scattering between modes of signed frequencies w; see scattering_to_quadrature_pair.
JosephsonCircuits.scattering_to_quadrature_block Method
scattering_to_quadrature_block(S_scattering::AbstractVector, w)Return the quadrature vector [x_1, ..., x_n, p_1, ..., p_n] of the vector of amplitudes S_scattering of modes of signed frequencies w; see scattering_to_quadrature_pair.
JosephsonCircuits.scattering_to_quadrature_pair! Method
scattering_to_quadrature_pair!(S_symplectic, S_scattering, w)In place version of scattering_to_quadrature_pair, writing into S_symplectic.
JosephsonCircuits.scattering_to_quadrature_pair Method
scattering_to_quadrature_pair(S_scattering::AbstractMatrix, w)Return the quadrature (symplectic) form, in pair operator order r = [x_1, p_1, ..., x_n, p_n], of the scattering matrix S_scattering between modes of signed frequencies w, with a = (x + im*p)/sqrt(2) for an annihilation operator a; see scattering_to_ladder_pair for the modes. Each entry takes the real two by two block of multiplication by it, turned for creation operators. The form is real even when S_scattering is complex.
JosephsonCircuits.scattering_to_quadrature_pair Method
scattering_to_quadrature_pair(S_scattering::AbstractVector, w)Return the quadrature vector [x_1, p_1, ..., x_n, p_n] of the vector of amplitudes S_scattering of modes of signed frequencies w, with x = sqrt(2)*real(a) and p = sqrt(2)*imag(a) for the amplitude a of an annihilation operator (a mode of positive frequency) and p of the opposite sign for that of a creation operator. The length of S_scattering must be a multiple of that of w.
JosephsonCircuits.scatteringblockindex Method
scatteringblockindex(c::CompiledCircuit, name)The position in c.scatteringblocks of the block whose instance path is name, a string, a symbol or an integer instance id, or zero when there is none. A block is also named by the "<path>/port1" spelling its stamp carries, which is what the solver messages and the sensitivity labels print.
JosephsonCircuits.scatteringlinearterm Method
scatteringlinearterm(ssys::ScatteringStampSystem, wmodes::AbstractVector)The constant sparse matrix of the scattering block contribution of the stamp system ssys at the fixed mode frequencies wmodes (the constitutive entries plus the Kirchhoff current law couplings of the auxiliary port currents). Used by the nonlinear (pump) solver, where the mode frequencies do not change: the contribution is folded into the frequency independent linear term alongside the augmentation matrix of the coupled inductor branches, so the residual, Jacobian, and solver machinery operate on the augmented system unchanged.
JosephsonCircuits.scatteringnoisenames Method
scatteringnoisenames(plan::ScatteringNoisePlan,
ssys::ScatteringStampSystem)The name of each noise channel of the plan, for labelling the rows of a keyed noise scattering matrix. A block with more than one port has one channel per port, distinguished by a channel number, because the columns of the factor of I - S S' mix the ports and no single port owns a channel. The channels of the conjugate kind of a block which states its noise follow its channels of the first kind, marked with a prime.
JosephsonCircuits.scatteringnoisewaves! Function
scatteringnoisewaves!(noiseoutputwave, plan::ScatteringNoisePlan,
ssys::ScatteringStampSystem, phiadj, wmodes, rowoffset,
work = ScatteringNoiseWorkspace())Write the noise output waves of the scattering block channels of plan into the rows of noiseoutputwave after rowoffset, from the adjoint solution phiadj at the mode frequencies wmodes.
The noise wave n of a block enters its constitutive equation as a source in the auxiliary port current rows, so by the adjoint identity its contribution to the output is that source contracted against those same rows of the adjoint solution, weighted by the factor L of the commutator L L' = I - S S', which a channel's symmetrized noise then weighs:
noiseoutputwave[channel c] = sqrt(abs(w)) sum_p L[p,c] i[p]phiadj must be the solution of the transposed system, which is what hblinsolve solves for its adjoint. The conjugated pump system, which is the same matrix for a circuit without blocks, is not: it agrees with the transposed system in the node flux rows and not in the auxiliary port current rows, and on a non reciprocal block the two differ by the direction the block transmits in, so contracting it would give a block which emits its noise backwards.
A block which states its noise with a NoiseCovariance V has its channels of the first kind weighted by the factor of V + K/2 and, in the rows after them, its channels of the conjugate kind by the factor of V - K/2, with K = I - S S', which checkblockdeclarations has admitted at every mode frequency of the sweep, or which a completed covariance meets by construction.
JosephsonCircuits.scatteringstampsystem Method
scatteringstampsystem(blocks::Vector{CompiledScatteringBlock}, Nmodes;
auxoffset, Ntotal, scale = 1.0, modeoffsets, iscale = 1.0)The stamp system of the compiled scattering blocks of a circuit.
A compiled block is one instance carrying its own terminal map, so the blocks need no regrouping and no check: a block cannot be missing a port, cannot repeat one, and cannot be confused with another instance of the same definition. The auxiliary port currents of each block follow those of the block before it, from auxoffset. modeoffsets are the frequency offsets of the modes, which a pumped block's coupling between them reads, and iscale the scale of the auxiliary port current unknowns; see scatteringstampsystem.
JosephsonCircuits.scatteringstampsystem Method
scatteringstampsystem(blocks::Vector{StampedScatteringBlock}, Nmodes,
Ntotal, scale; modeoffsets, iscale = 1.0)The positional inner form of scatteringstampsystem, everything past the point where the blocks and their terminals are known: the Kirchhoff current law couplings, the constitutive pattern and the contribution tables of a ScatteringStampSystem. Unlike the keyword form it never returns nothing.
modeoffsets are the frequency offsets of the modes from the signal, in radians per second. A LinearizedScattering block couples the modes whose offsets differ by a harmonic of its pump, and the contributions between such pairs are entered on top of the diagonal ones; a block which does not convert takes no notice of them.
iscale is the scale of the auxiliary port current unknowns; see ScatteringStampSystem.
JosephsonCircuits.scatteringvalues! Method
scatteringvalues!(values::AbstractVector, ssys::ScatteringStampSystem,
wmodes::AbstractVector, work::ScatteringWorkspace;
derivative = false)The value each scalar contribution of the scattering blocks adds to the system matrix at the signed mode frequencies wmodes, in the order of ssys.Aindex. With derivative the blocks, none of them pumped, hold the derivatives of scattering matrices, and the values are the derivatives of the contributions (see evaluatehybrid!).
This is the half of assemblescattering! which has to run on the host, because it evaluates each block through its provider, which may be an arbitrary callable or an interpolation of tabulated data. What is left is a gather-add of these values into the stored entries, which is where the two backends part company: the host adds them here, and a device adds them with a kernel (see DeviceScatteringStamps). Splitting it this way is what lets both backends stamp identical values.
JosephsonCircuits.scattervalues! Method
scattervalues!(dest::AbstractVector, src::AbstractVector,
index::AbstractArray)dest[index[k]] = src[k] for every k, as a KernelAbstractions kernel on the backend of src. The inverse of gathervalues! when index is a permutation; index must not repeat, or the writes race.
JosephsonCircuits.seedordering! Method
seedordering!(cache::FactorizationCache, A::SparseMatrixCSC, ordering)Hand cache the fill reducing ordering ordering of the sparsity pattern of A, so that its fresh factorizations of that pattern take it instead of choosing one: how the caches of several workers factorizing one pattern, or the successive solves of one pattern, share one choice. ordering is what fillordering returns, a FillOrdering or nothing. The ordering a cache holds, cache.ordering, is one to hand to another. Returns cache.
JosephsonCircuits.segmentbydest! Method
segmentbydest!(seg, perm, dest, backend)Group dest into contiguous segments by value, writing the segment pointer into seg and, into perm, the positions of dest ordered by segment.
The result is a permutation rather than a copy: the caller gathers whatever payload it has through perm, which keeps this independent of how many arrays travel with the destinations.
The grouping is stable, which is what leaves the column indices of a transposed structure ascending within each row (transposepattern). A histogram with an atomic cursor is not stable, so the order the positions were emitted in is restored afterwards by sorting each segment. A segment is a row of the structure being transposed, and the sort costs its length times the displacement the cursor introduced, which is none on the CPU backend and depends on the scheduling on a device.
JosephsonCircuits.selfconjmodes Method
selfconjmodes(frequencies::Frequencies)Return a vector of booleans indicating which of the modes of frequencies are their own complex conjugates on the sampled grid, which is the case when twice the mode aliases to zero along every dimension. The Fourier coefficients of a real signal at those modes, such as dc, are purely real.
Examples
julia> freq = JosephsonCircuits.removeconjfreqs(JosephsonCircuits.truncfreqs(JosephsonCircuits.calcfreqsrdft((3,));dc=true,odd=true,even=true));JosephsonCircuits.selfconjmodes(freq)
4-element Vector{Bool}:
1
0
0
0JosephsonCircuits.sensitivitydim Method
sensitivitydim(op::HBOperatingPoint)The dimension of the space the residual derivatives and the adjoint covectors live in: canonical with a direct current block, and the real representation of the augmented harmonic state without one.
sourceJosephsonCircuits.sensitivityjacobian Method
sensitivityjacobian(op::HBOperatingPoint)The Jacobian the implicit function theorem applies to at op: the canonical one when an explicit direct current block is active, and the harmonic one otherwise.
The forward and the reverse contraction both solve against this, forward through it and reverse through its transpose, so naming it once is what keeps the two orders solving the same system.
sourceJosephsonCircuits.sensitivitypairtable Method
sensitivitypairtable(pairs)
sensitivityblockpairtable(pairs)The (name, parameter, direction) sensitivity pairs of a component or of a scattering block as vectors of one tuple type, the direction of a component pair as a complex number.
JosephsonCircuits.sensitivityportordinals Method
sensitivityportordinals(nm::CircuitMatrices)The port whose reference impedance each component is, by its ordinal among the ports, keyed by the component's index: the termination a port owns, and a port which owns none, whose own value is its reference impedance. A sensitivity taken with respect to one of these moves the normalization of that port's waves as well (see calcSsensitivity!), and the pairs of a design parameter group by it.
JosephsonCircuits.sensitivitystamp Method
sensitivitystamp(idx, psc, nm, lookups, Nmodes)The raw one-component stamp of a sensitivity of the linearized solve: the classification of componentstamp, and for a port which owns no termination one with no entries, of kind :P. Such a port's reference impedance enters neither the system matrix nor the harmonic balance residual, only the normalization of its waves, which calcSsensitivity! adds by the port's ordinal. The reference impedance of a port which owns a termination is the value of that termination, and the port is refused.
JosephsonCircuits.sensitivitystampvalue Method
sensitivitystampvalue(stamp::SensitivityStamp, t::Integer, wmodes,
Nmodes)The value of entry t of the derivative of the linearized harmonic balance system matrix with respect to a relative perturbation of the component of stamp, at the mode frequencies wmodes. Applies the same per mode frequency scaling and negative frequency mode conjugation as assemblesystemmatrix!, which are indexed by the column.
JosephsonCircuits.setfactorization Method
setfactorization(s::AbstractModeCoupling, f)The mode coupling set s with its factorization replaced by f, whatever it carried. A preconditioner holds its coupling set so: built from the set it is asked for with the factorization that set carries or the backend's default, and rebuilt with each factorization it changes to, so that the set always carries the factorization of its factors. Defined for the sets a preconditioner holds; MeasuredBand and Clusters are rewritten into one of them when it is built, and an Automatic is resolved to one before (resolveautomatic).
JosephsonCircuits.setpoint! Method
setpoint!(sys::HBSystem, x::AbstractVector)Set the point at which residual!, jacobianvectorproduct!, hessianvectorproduct! and jacobian! evaluate the harmonic balance nonlinear system, and cache the time domain branch fluxes there. Accepts the complex vector of node fluxes or the equivalent real representation, dispatched on the element type. Returns sys.
A point equal to the one the system holds, handed in as an array of the type the system holds it in or as a view of one (as the evaluations of the canonical state with direct current hand it in), is not set again: the branch fluxes and every evaluation cached at it (the sine, the cosine and its transform) stay. A solver resynchronizing the system after a step, or a preconditioner setting the point it is rebuilt at, pays an O(n) comparison rather than a transform. The point a system is built with is NaN, which no point equals.
JosephsonCircuits.setscatteringindexmap! Method
setscatteringindexmap!(ssys::ScatteringStampSystem,
A::SparseMatrixCSC)Point the destination indices of the frequency dependent contributions at the nonzero values of the system matrix A, whose sparsity structure must contain the pattern of ssys (ensure this by merging ssys.pattern into the structure before calling, as HBLinearizedSystem does; the constant ssys.kcl couplings are folded into the constant augmentation matrix instead).
JosephsonCircuits.shortednets Method
shortednets(elab::ElaboratedCircuit)The net each net of elab is compiled as: the ground net (1) for a net whose every terminal belongs to a component, or a port of a scattering block, shorted across that net, and the net itself otherwise.
A component whose two terminals are one node carries no current and couples no node, so a net which only such components touch is a node with no equation of its own: every frequency domain solve would meet it as an empty row. On the ground net the components are the self loops they are at any other node, and the node is gone.
sourceJosephsonCircuits.showstruct Method
showstruct(io::IO,out)Print the struct out to io as its constructor name (without type parameters) applied to its fields, each printed with testshow.
Examples
julia> JosephsonCircuits.testshow(stdout,JosephsonCircuits.NoiseReduction([1.0, 2.0], [3.0, -4.0]))
JosephsonCircuits.NoiseReduction{Vector{Float64}}([1.0, 2.0], [3.0, -4.0])
julia> JosephsonCircuits.testshow(IOBuffer(),JosephsonCircuits.warmup())JosephsonCircuits.sinusoidalmask Method
sinusoidalmask(r::JunctionRelations)Whether each junction of r, along the junction axis, has the sinusoidal Josephson relation, on the host.
JosephsonCircuits.snapscattering Method
snapscattering(S::AbstractMatrix)The real scattering matrix S with every entry within 1e-12 of a perfect open, short or isolation snapped to the exact 1, -1 or 0, which is how a block realized in time stamps it. The hybrid coefficients I - S and I + S of a port whose feedthrough reaches the unit circle then hold exact zeros where the algebra has them, so the endpoint's rate system sees a zero row rather than the roundoff residue of one, which its balancing would otherwise scale up into an equation whose inverted singular value multiplies the residual by the reciprocal of machine epsilon at every step. The snap moves an entry by less than 1e-12, far below any scattering the data resolves.
JosephsonCircuits.solveS_update! Method
solveS_update!(See, Sei, Sie, Sii, See_indices, Sei_indices,
Sie_indices, Sii_indices, networkdata, i)Update the sparse matrices See, Sei, Sie, and Sii using the indices from See_indices, Sei_indices, Sie_indices, and Sii_indices which are indices into networkdata with frequency index i.
JosephsonCircuits.solvebatch! Method
solvebatch!(ds::DeviceSweep, lo::Integer)Solve the batch of frequencies beginning at index lo on the device and stage its solutions on the host. This is the only verb which touches the device; once it has returned, the batch's frequencies can be read by as many workers as the host path uses through forwardsolution! and adjointsolution!, because reading a solution touches staged host memory and nothing else.
JosephsonCircuits.solveonbackend! Method
solveonbackend!(fj!, F, J, x, backend; kwargs...)Solve the nonlinear system on the backend its Jacobian and factorization live on, returning the iteration information and writing the converged state back into the host vectors F and x.
The state has to go where the Jacobian is, so that the assembly, the linear solve and the line search all stay on one side. On CPU() tobackend adopts the caller's vectors and the copies back are between an array and itself, so this is exactly nlsolve!.
JosephsonCircuits.solvequasinewton! Method
solvequasinewton!(method; ...)
solvenewton!(method; ...)
solvenewtonkrylov!(method; ...)
solveexternal!(method; ...)Solve the system nonlinearsetup built, each with the fields it reads passed by name: the quasi-Newton iteration on the complex holomorphic Jacobian, Newton's method on the equivalent real system, the Newton-Krylov iteration with its mode coupling preconditioner, or the caller's own solver through a problem object. The state x, xr, F and Fr of the setup is updated in place. canonwork is the explicit direct current block, or nothing without one, in which case the system is solved as stamped. Returns the IterationInfo of the solve and the converged canonical state on the host, nothing without an explicit direct current block.
JosephsonCircuits.solverkwargs Method
solverkwargs(factorization)The options a factorization hands to the solver it wraps, so a caller which does not know which factorization it has can forward them unconditionally. Every factorization carries its own kwargs to its own factorize; this is for the batched paths, which reach their solver without one.
JosephsonCircuits.solverprecision Method
solverprecision(m::AbstractHBNonlinearSolver)The floating point type the method iterates in: Float64 for every method but NewtonKrylov, whose precision it is. A Staged method solves its stages with its inner method, which is the one asked.
JosephsonCircuits.sortnodes Method
sortnodes(uniquenodevector, nodeindexvector, order)Apply the precomputed sorting permutation order (see calcnodesorting), returning the sorted names, the renumbered component node indices as a 2 by Ncomponents matrix, and the renumbering itself, invperm(order), whose jth entry is the new index of the node whose old index was j: compile renumbers the nodes of the scattering blocks with it, since they have no component table entry to be re-read from.
JosephsonCircuits.sourcetable Method
sourcetable(sources, w, definitions = nothing)The sources as a Vector{SourceTuple{N}} for the N tones of w. sources is any iterable of named tuples with the fields mode, port and current. A current is a number, or a name, as a component value may be, resolved at definitions. A source whose mode does not have one integer per tone, whose port is not an integer or whose current is not a number at the definitions is an ArgumentError.
JosephsonCircuits.spaddkeepzeros Method
spaddkeepzeros(A::SparseMatrixCSC, B::SparseMatrixCSC)Add sparse matrices A and B and return the result, keeping any structural zeros, unlike the default Julia sparse matrix addition functions.
Examples
julia> A = JosephsonCircuits.SparseArrays.sprand(10,10,0.2); B = JosephsonCircuits.SparseArrays.sprand(10,10,0.2);JosephsonCircuits.spaddkeepzeros(A,B) == A+B
trueA = JosephsonCircuits.SparseArrays.sparse([1,2,1], [1,2,2], [1,2,0],2,2);
B = JosephsonCircuits.SparseArrays.sparse([1,2], [1,2], [1,1],2,2);
JosephsonCircuits.spaddkeepzeros(A,B)
# output
2×2 SparseArrays.SparseMatrixCSC{Int64, Int64} with 3 stored entries:
2 0
⋅ 3JosephsonCircuits.sparseadd! Method
sparseadd!(A::SparseMatrixCSC, c::Number, As::SparseMatrixCSC, indexmap)Add sparse matrices A and c*As and return the result in A. The sparse matrix As must have nonzero entries only in a subset of the positions in A which have nonzero (structural zeros are ok) entries.
Examples
A = JosephsonCircuits.SparseArrays.sparse([1,2,1], [1,2,2], [1,2,-3],2,2)
As = JosephsonCircuits.SparseArrays.sparse([1,1], [1,2], [3,4],2,2)
indexmap = JosephsonCircuits.sparseaddmap(A,As)
JosephsonCircuits.sparseadd!(A,2,As,indexmap)
A
# output
2×2 SparseArrays.SparseMatrixCSC{Int64, Int64} with 3 stored entries:
7 5
⋅ 2JosephsonCircuits.sparseaddconjsubst! Method
sparseaddconjsubst!(A::SparseMatrixCSC, c::Number, As::SparseMatrixCSC,
indexmap, wmodes::AbstractVector, power::Integer)Perform A += c*As*Ad with Ad the implicit diagonal whose entry in column i is the signed mode frequency of that column raised to power, wmodes[(i-1) % length(wmodes) + 1]^power, with the mode index fastest over the nodes and any auxiliary variables, and each value of As complex conjugated in every column whose mode frequency is negative (modevalue). The frequency and the conjugation of a column are computed from its index rather than read from materialized diagonals, so nothing is allocated.
JosephsonCircuits.sparseaddmap Method
sparseaddmap(A::SparseMatrixCSC, B::SparseMatrixCSC)Return a vector of length nnz(B) which maps the indices of elements of B in B.nzval to the corresponding indices in A.nzval. The sparse matrix B must have elements in a subset of the positions in A which have nonzero entries (structural zeros are elements); an element of B with no position in A is an ArgumentError. Each column is one merge of the sorted row indices of the two matrices, whatever their index type.
Examples
A = JosephsonCircuits.SparseArrays.sparse([1,2,1], [1,2,2], [1,2,-3],2,2)
As = JosephsonCircuits.SparseArrays.sparse([1], [2], [4],2,2)
JosephsonCircuits.sparseaddmap(A,As)
# output
1-element Vector{Int64}:
2A = JosephsonCircuits.SparseArrays.sparse([1,2,1], [1,2,2], [1,2,-3],2,2)
As = JosephsonCircuits.SparseArrays.sparse([1,2], [1,2], [4,2],2,2)
JosephsonCircuits.sparseaddmap(A,As)
# output
2-element Vector{Int64}:
1
3JosephsonCircuits.sparsefactorbound Method
sparsefactorbound(::Type{T}, keep::AbstractMatrix{Bool},
plan::PreconditionerPlan, sys)A bound from below on the bytes of the sparse factors of the coupling mask keep in precision T, from the mask and the junction incidence, with no pattern built: the real Jacobian holds, for every ordered pair of nodes a junction couples and every retained mode pair with a coupling, the real block of that mode pair, and the factors hold at least the pattern and the diagonal, each entry with its index, as sparsefactorbytes counts them.
JosephsonCircuits.sparsefactorbytes Method
sparsefactorbytes(P::SparseMatrixCSC, ::Type{T}, ordering)The bytes a sparse LU of the pattern P in precision T would hold, each entry with its index, from the symbolic analysis alone: the entries of L and U under ordering, the fill reducing ordering a KLU factorization of P takes (fillordering), which are twice the fill that ordering predicts, fill entries each with the diagonal counted in both, or under the natural order, which bounds them, when ordering is nothing. What escalation to a larger coupling set is budgeted against on any backend; a device factorization orders differently, but the fill of the same pattern is of the same size.
JosephsonCircuits.spectralclusters Method
spectralclusters(W::AbstractMatrix)Cluster the modes by coupling strength: starting from every mode alone, merge the two clusters of the strongest coupling not yet inside a cluster, in decreasing strength W[i,j] + W[j,i], until the couplings left between clusters have block Jacobi spectral radius below one. Returns the cluster index of every mode, bounds from above on the radius before and after (perronbound), and the couplings taken.
The value one is not a threshold to tune: for a nonnegative comparison matrix of block norms, a spectral radius below one is the condition under which the block Jacobi iteration on the omitted couplings contracts, so the rule keeps exactly enough coupling inside the clusters for what is left outside to be correctable. It finds collective chains that no pairwise threshold does: on a two tone line every single coupling of the difference ladder is weak but the ladder as a whole is not, and the rule closes it.
The radius is bounded from above, so the clusters are only accepted when what is left between them contracts. A merge only removes couplings from between the clusters, and the spectral radius of a nonnegative matrix does not grow when its entries shrink, so the first point of the merge sequence at which the remainder contracts is found by bisection over the sorted couplings.
sourceJosephsonCircuits.spice_raw_load Method
spice_raw_load(filename)Read the binary rawfile of a WRSPICE or Xyce analysis, transient or frequency domain. The file format is documented in the WRSPICE manual in Appendix 1, File Formats, A.1 Rawfile Format; the Xyce rawfile format is very similar and described here.
Returns a SpiceRaw: the header, and for each type of variable, V for the node voltages, S for the time of a transient or Hz for the frequency of an AC analysis, the names of the variables of that type in variables and their values in values, a matrix with one row per variable and one column per point, real or complex as the header's flags say. The variables of each type are sorted by calcspicesortperms. A rawfile in the ASCII format is refused.
JosephsonCircuits.spice_run Method
spice_run(inputs::AbstractVector, spicecmd; ntasks::Int = Sys.CPU_THREADS)Run each input of inputs as spice_run does, ntasks WRSPICE processes at a time, and return their rawfiles in the order of the inputs. The processes run in parallel whatever the number of Julia threads, since the tasks only wait on them, so ntasks is the number of logical processors by default.
JosephsonCircuits.spice_run Method
spice_run(input, spicecmd)Run WRSPICE in batch mode on the input input, a string, with the command spicecmd, the path of the executable or the command wrspice_cmd returns, and return the rawfile the run writes as spice_raw_load reads it. The input and the rawfile are written in a temporary directory, which is removed when the run ends, however it ends. The write command of the input's control block must not name a file, so that the rawfile is the one given on the command line.
A run which fails, writes no rawfile, or aborts, when WRSPICE writes the plot of its constants in place of the analysis, is an error which quotes what WRSPICE printed.
sourceJosephsonCircuits.spicebranches Method
spicebranches(psc::CompiledCircuit, componentvalues::AbstractVector)The entries of a compiled circuit merged by branch, as the netlist export writes them. Entries of one kind between the same two nodes are one branch, whatever their order in the table, with their values combined by sumvalues; the couplings between the same two inductors are one branch too, and an inductor which a mutual inductor couples is a branch of its own, since the coupling names it. Ports, whose terminations are resistors of the table, and current sources are left out.
Returns (branches, position): the branches in the order they first appear, each a named tuple of its type, the flat index of its first entry, whose name and terminal order its line takes, and its merged value; and the position of each merged branch in branches by (type, node1, node2), the node indices sorted, or (:K, inductor1, inductor2). Every value must be a real number (see spicevalue).
JosephsonCircuits.stagedeviceproviders! Method
stagedeviceproviders!(values, dp::DeviceProviders, w, lo, k)Compute the scattering values of the batch of frequencies beginning at lo directly on the backend, into values.
The host part of this is the batch's own signal frequencies and, for a block whose data must not be extrapolated, a check of the range it will be evaluated over. Nothing per block or per contribution crosses to the host.
sourceJosephsonCircuits.stagedhbnlsolve Method
stagedhbnlsolve(m::Staged, w::NTuple{N,Float64}, Nharmonics,
sources::Vector{SourceTuple{N}}, psc::CompiledCircuit,
circuitdefs::Dict{Any,Any}; kwargs...)Source continuation on an adaptively grown harmonic grid, reached through hbnlsolve(...; method = Staged(...)); the schedule is the Staged value m, validated at its construction. kwargs are the keywords of hbnlsolve (iterations, atol, Nevaluationharmonics, frequencywindow, maxintermodorder, dc, odd, even, keyedarrays, sensitivitynames, returnoperatingpoint, backend), which are forwarded to every stage.
Near a critical drive the Newton basin is small and the iteration count large, so those iterations are spent where they are cheap. The drive is climbed in warm started steps with only a small set of harmonics retained as unknowns, and each larger retained set is warm started from the last by matching mode tuples. A step scales every source of the drive by its fraction, the ports' and the netlist's constant current sources alike, as setdrive! scales a problem's. The nonlinearity is always evaluated on the full Nevaluationharmonics transform grid, so that every stage sees the same aliasing of the nonlinear products; the ladder only controls the modes retained as unknowns, so it is the linear solves which shrink. The mode set, the circuit matrices, the system with its transforms, the preconditioner's symbolic factorization and the Krylov workspace of a grid are built once and rebound to each drive step on it (HBReuse), so a step costs its Newton iterations and little else.
The schedule adapts in both directions, because each truncation has its own solvability boundary and the boundaries are not monotone in the grid: a stalled drive step is cut (halved by default); a stall at the minimum step grows the grid at the current converged drive; and a point carried to a larger grid which fails to reconverge there retreats the drive on that grid until it converges, before the schedule grows past it. Interior points converge only to interioratol under a small iteration budget, since they exist to keep the iterate inside the basin, and the one expensive solve, the finest grid at full drive, starts inside the basin with the caller's atol and iterations.
Only a stall from a point converged on the finest grid itself is reported as bracketing a fold, the end of the solution branch (the self oscillation threshold) between the last converged drive fraction and the stalled one; the report is what the search saw, not a proof that no operating point exists at the requested drive. Before reporting it, and only when the stalled target was below full drive, one further solve at full drive is attempted from the last converged point with the caller's own method and tolerance, since a coexisting branch may reach it; failing that, the solve returns not converged with a warning stating the bracket, and solverinfo.sourcefold holds the last converged drive fraction (it stays NaN for the other ways a schedule ends). No path throws: a schedule which cannot reach the point (its attempts spent, a carried point which does not reconverge, a first stage which converges at no drive down to the minimum step) warns, returns not converged, and records the whole walk in solverinfo.stages. What it returns is at the modes of the finest grid, at full drive and with the keyed arrays and the operating point asked for, like the outcome of a direct method which does not converge: its last attempt when that was such a solve, and otherwise its last converged point, or its last attempt when nothing converged, carried to the finest grid and evaluated there by the inner method given no iterations, an attempt recorded as :evaluate; with no attempt before it, the cold start is evaluated.
Keywords
grids = defaultgridladder(Nharmonics): the coarse to fine ladder of retained harmonic caps, whose last entry must equalNharmonics.s0 = 0.5: the first drive fraction attempted.smin = 0.02: the minimum drive step; a stall below it grows the grid.interioratol = 1e-7,interioriterations = 60: the tolerance and the Newton budget of the interior points. The budget is small on purpose: a stalled probe is evident within tens of iterations, and interior stalls are the overhead of the walk.inner = NewtonKrylov(): the method of every stage.interiorescalation = false: whether interior stage solves may escalate their preconditioner to the full Jacobian. Off by default, because an interior probe exists only to produce a cheap warm start, and at a high tone count the full factorization may not fit in memory; a probe which fails without escalation is a stall, which the schedule answers with a smaller step. The final solve keeps the caller's escalation behavior.maxattempts = 60: a bound on the number of solves the schedule makes, every one counted: the drive steps, the retreats and growths, the branch-end jump, and the evaluation of the point a schedule which gives up returns. A solve short of full drive on the finest grid is made only when the budget leaves one more beside it, for that evaluation.verbose = false: print one line per stage solve.warnnotconverged = true: warn when the schedule ends without the requested point, and run the checks of the point it reaches which warn, once. The stage solves never warn: a stage which does not converge is how the schedule finds its step.
The steps of the walk are keywords of this function rather than options of the method: stepgrowth = 2.0, the factor a converged drive step grows the next by, up to full drive; stepcut = 0.5, the factor a stalled one is cut by; retreatfactors = (0.9, 0.8, 0.65, 0.5), the fractions of its drive a carried point which does not reconverge retreats to in turn, and a growth tries after the converged drive itself; and resumestep = s0/2, the drive step the walk climbs on with once a carried point has reconverged.
JosephsonCircuits.stagedtable! Method
stagedtable!(table, ds::DeviceSweep, i::Integer)Fill table with the values of the frequency dependent functions at the modes of frequency i of the batch staged by the last solvebatch!, a row per function and a column per mode, as stagefrequencydependent! evaluated them for its assembly. The form hblinsolve_inner! takes as presolvedtable.
JosephsonCircuits.stagefrequencydependent! Method
stagefrequencydependent!(st::DeviceFrequencyDependentStamps, w, lo, k,
wpumpmodes)Evaluate the functions of the frequency dependent components on the host at the mode frequencies of the batch of k signal frequencies of w beginning at lo, each distinct function once a mode frequency, and send the table to the backend. A short final batch repeats its last frequency, as its assembly does.
JosephsonCircuits.stagescatteringstamps! Method
stagescatteringstamps!(st::DeviceScatteringStamps, w, lo, k, wpumpmodes)Compute the scattering values of the batch beginning at lo on the host and send them to the backend.
JosephsonCircuits.stageweights! Method
stageweights!(rw::RationalWork, sys::TransientSystem, t1, t2)Set the weights of the output terms of the rational blocks at the two stage times t1 and t2 of the step about to be formed, which the reflected waves at the stages read; the weight of the unconverted response is one and those of the modulated outputs of the pumped blocks their modulation at the time. A circuit without a pumped block has only the first, and its weights never change.
JosephsonCircuits.stalled! Method
stalled!(pc::AbstractPreconditioner)Tell the preconditioner that the last linear solve reduced its residual slowly, by a factor worse than the slowrate of nlsolvekrylov! per Arnoldi step, and return pc. The default does nothing. A ModeCouplingPreconditioner with Clusters takes it as the sign that the coupling has outgrown its clusters and remeasures them at the next update. Called by nlsolvekrylov! after each slow linear solve, except under Never; wrappers forward it.
JosephsonCircuits.stallmessage Method
stallmessage(reason::Symbol)The sentence behind a reason of an IterationInfo, for the warning a solve which did not converge issues; a reason it does not know (:converged, :unspecified) is reported as reason <name>.
JosephsonCircuits.statednoise Method
statednoise(block)Whether a block states its noise with a NoiseCovariance, and so carries the channels of both kinds rather than those of its loss.
JosephsonCircuits.statednoisefactors! Method
statednoisefactors!(L, M, V, m, n)The factors of the channels of a block which states its noise: on entry the lower triangle of L holds K = I - S S' at mode m and V[:,:,m] the stated covariance there; on exit L holds the triangular factor of V + K/2 and M that of V - K/2, both by psdcholesky!, which are positive semidefinite for a covariance checkblockdeclarations has admitted or which is completed.
JosephsonCircuits.structureassemblerowkernel! Method
structureassemblerowkernel!(nzval, colptr, rowval, lin, phimatrix, ...)As structureassemblykernel!, one work item per stored column rather than per stored entry, which is how a host assembles a structure in the natural orientation (realjacobiancolumnitem!).
The two differ in what they amortize against what they lose. Per entry, the column has to be found by a binary search and both sides of the entry are decoded; per column, the search is paid once, the column is decoded once, and the rows are read from a table, but the entries a work item writes are contiguous rather than interleaved with its neighbours', which costs coalescing on a device and nothing on a host.
sourceJosephsonCircuits.structureassemblykernel! Method
structureassemblykernel!(nzval, colptr, rowval, lin, phimatrix, ...)Assemble one stored entry of the real Jacobian per work item, from the circuit's structure.
The work item decodes the entry it owns into the node pair and mode pair it belongs to, looks up the junctions incident on that node pair, and sums their contributions: per incident junction the difference frequency coupling ami and its conjugate partner amc, and the linear term last. Floating point addition is not associative, so that order is part of the result.
JosephsonCircuits.substitute! Method
substitute!(Y, lu::BlockLU, Z, Pw, backend; transposed = false)The substitutions through the factors: overwrite Y (n x W x nb, in factorization order) with the solution against Z (the right-hand side in factorization order, overwritten), with Pw a panel work array of at least (maxpanel, W, nb). Forward substitution through the scaled panels, back substitution through the panels and the inverses; for the transposed system the same factors read the other way round, (D ⊕ U)ᵀ first as a lower block triangular solve with the transposed inverses, then (I + L)ᵀ backward. The caller gathers into Z and scatters out of Y by perm.
JosephsonCircuits.substitutefreq Method
substitutefreq(value, w)Resolve a component value at the mode frequency w: the identity for a plain number, and for a FrequencyDependent value its function at the magnitude of w. A value states the element at positive frequencies, and a mode of negative frequency takes its conjugate where the value is placed (see modevalue), which is the value a real element has there. A value which does not resolve to a number is returned as it is, for the caller to diagnose. The Symbolics extension adds the Num method.
JosephsonCircuits.sumvalues Method
sumvalues(type::Symbol, value1, value2)Sum together two values in different ways depending on the circuit component type: capacitances and coupling coefficients add, and inductances and resistances combine in parallel.
Examples
julia> JosephsonCircuits.sumvalues(:L, 1.0, 4.0)
0.8
julia> JosephsonCircuits.sumvalues(:Lj, 1.0, 4.0)
0.8
julia> JosephsonCircuits.sumvalues(:R, 1.0, 4.0)
0.8
julia> JosephsonCircuits.sumvalues(:C, 1.0, 4.0)
5.0
julia> JosephsonCircuits.sumvalues(:K, 1.0, 4.0)
5.0JosephsonCircuits.supportsrecycling Method
supportsrecycling(ls)Whether the solver exposes an Arnoldi basis for harvestcycle!.
JosephsonCircuits.sweepdestinations Method
sweepdestinations(A::SparseMatrixCSC, Aindex, adjoint::Bool)The destination of each scattering contribution in the stored order a FrequencySweepPlan uses, given its destinations in the stored order of A.
A plan built for the transpose stores its values in A's own order, so the indices pass through; one built for the matrix itself stores them permuted into compressed sparse row order, so they must be permuted the same way.
JosephsonCircuits.sweepfrequencies Method
sweepfrequencies(ws)The signal frequencies ws as a Vector{Float64}: a real number, or any iterable of real numbers (a vector, a range), in radians per second.
JosephsonCircuits.sweepoutputs! Method
sweepoutputs!(QE, nbar, Vout, CM, QEideal, i, S, Cnoise, reduction,
portnoise, porttemperatures, wmodes, Nmodes, vout, comp, Sweighted)Write the outputs of the sweep at its i-th frequency which the noise at the ports enters, from the scattering matrix S, the noise the circuit adds Cnoise and its NoiseReduction reduction (zero for a circuit without noise channels): the quantum efficiency QE, the occupations nbar, the output covariance Vout, the commutation relations CM and the ideal amplifier's quantum efficiency QEideal, each skipped when its array is empty. portnoise receives the symmetrized noise of every input mode, at the temperature porttemperatures of its port's termination and the mode frequencies wmodes; vout the symmetrized noise at each output and comp its compensation; and Sweighted the scattering matrix weighted by the input noise.
hblinsolve_inner! calls it with the same argument types whatever the circuit and whichever outputs are stored, so it is compiled once rather than with every specialization of the sweep.
JosephsonCircuits.symbolicfill Method
symbolicfill(S::SparseMatrixCSC, perm::AbstractVector{<:Integer})The number of nonzeros of the Cholesky factor of the symmetric pattern S under the symmetric permutation perm (perm[k] is the original index of the kth pivot), and the flop count of that factorization, both from the elimination tree without forming anything: (fill, flops).
Only the pattern of S is read, and only its structural symmetry matters; for the pattern of an unsymmetric A use that of A + A'. The fill of an LU factorization with the same permutation on both sides is about twice this and its flops about the same, which is enough to rank two orderings. Cost O(fill): the column counts are accumulated by walking the row subtrees of the elimination tree, one step per nonzero of the factor.
JosephsonCircuits.symplectic_form_block Method
symplectic_form_block(n::Integer)Return the 2n x 2n matrix representing the symplectic form Ω for n modes in the real quadrature operator basis with block order r = [x_1,...,x_n,p_1,...,p_n] where Ω = [0_n 1_n;-1_n 0_n]. 0_n is an n by n matrix of zeros and 1_n is an n by n identity matrix.
Examples
julia> JosephsonCircuits.symplectic_form_block(2)
4×4 SparseArrays.SparseMatrixCSC{Int64, Int64} with 4 stored entries:
⋅ ⋅ 1 ⋅
⋅ ⋅ ⋅ 1
-1 ⋅ ⋅ ⋅
⋅ -1 ⋅ ⋅JosephsonCircuits.symplectic_form_pair Method
symplectic_form_pair(n::Integer)Return the 2n x 2n matrix representing the symplectic form Ω for n modes in the real quadrature operator basis with pair order r = [x_1,p_1,...,x_n,p_n] where Ω = direct sum of n of Ω1 where Ω1 = [0 1; -1 0].
Examples
julia> JosephsonCircuits.symplectic_form_pair(2)
4×4 SparseArrays.SparseMatrixCSC{Int64, Int64} with 4 stored entries:
⋅ 1 ⋅ ⋅
-1 ⋅ ⋅ ⋅
⋅ ⋅ ⋅ 1
⋅ ⋅ -1 ⋅JosephsonCircuits.symplectic_normal_form_block Method
symplectic_normal_form_block(A::AbstractMatrix{<:Real})The block ordered form of symplectic_normal_form_pair: A is in block order and Ω the block ordered symplectic form.
JosephsonCircuits.symplectic_normal_form_pair Method
symplectic_normal_form_pair(A::AbstractMatrix{<:Real})For a real skew-symmetric matrix A return Q such that A = Q Ω Q^T where Q is an invertible matrix and Ω is the pair symplectic form. If A is singular, the decomposition works, but Q is no longer invertible.
JosephsonCircuits.targetstampsystems Method
targetstampsystems(ssys, target::Integer, cs, dblock)The stamp system of the derivative of the block contribution with respect to a parameter of the block instance at ordinal target (its position among the compiled scattering blocks, which the stamped blocks follow), as (dsys, position, rows, cols). cs are the positions of that instance's contributions among those of ssys, in their order (blockcontributions). The contributions are affine in the block's S and no other instance's depend on the parameter, so dsys holds that instance's contributions alone, with dblock, the block whose S is dS/dtheta, in its place (see blockstampvals!). position places each contribution among the entries of the stamp, which are the pattern entries at rows and cols those contributions reach. The instance is selected by its ordinal and not by its definition, because two instances may share one definition object and a parameter belongs to one of them.
JosephsonCircuits.testshow Method
testshow(io::IO,S)Print S to io in a form which can be pasted back into a test as Julia source. The default show does not always produce such a form (a sparse vector, for example), and a parameterized struct would print its full type parameters, which are implementation details; this prints sparse vectors as sparsevec(...) calls and the solver result structs as their constructor applied to their fields.
Examples
julia> JosephsonCircuits.testshow(stdout,JosephsonCircuits.SparseArrays.sparsevec([1],[2],3))
sparsevec([1], [2], 3)
julia> JosephsonCircuits.testshow(stdout,JosephsonCircuits.SparseArrays.sparsevec([],Nothing[],3))
sparsevec(Int64[], Nothing[], 3)
julia> JosephsonCircuits.testshow(IOBuffer(),JosephsonCircuits.AxisKeys.KeyedArray(rand(Int8, 2,10), ([:a, :b], 10:10:100)))JosephsonCircuits.thermalnoise! Method
thermalnoise!(channelnoise, temperatures::AbstractVector, wmodes, Nmodes)Fill channelnoise with the symmetrized noise nbar + 1/2 of each row of the noise scattering matrix, whose rows run over the noise channels with the modes innermost, or of each port mode's input, whose rows run over the ports the same way.
This is the state of each channel. It weighs a channel's contribution where the noise is asked for, by calcqe! and by the noise covariance, and never enters Snoise itself, which is a scattering matrix and does not depend on temperature. The commutation relations, which are a statement about the transformation rather than about the state of anything, therefore do not see it at all.
temperatures is one temperature per noise channel, in the order noisechannelnames gives them, or one per port for the port modes; every temperature being zero gives the vacuum, 1/2 everywhere.
JosephsonCircuits.tobackend Method
tobackend(backend, v::AbstractArray)Move a host array to the given KernelAbstractions backend.
On a device backend this allocates there and copies. On CPU() the vector is already the type and in the memory the plan wants, so it is adopted as is rather than duplicated: allocate would return an ordinary Vector and the copy would leave the original as garbage, which for a plan of a large circuit is a transient copy of every index map. Only a dense Array is adopted, so any other AbstractArray (a view, a range) is still materialized.
The caller must therefore hand over arrays it does not retain, which every call site does: they are all freshly built.
sourceJosephsonCircuits.tohost Method
tohost(x::AbstractArray)The array on the host, for the host loops which cannot read a device array. Returns x itself when it is already an Array, so nothing about the CPU path changes; anything else is copied back with Array.
JosephsonCircuits.tonefrequencies Function
tonefrequencies(w, definitions = nothing)The tone frequencies w as a tuple of Float64, in radians per second. Each is a real number, or a name, as a component value may be, resolved at definitions to a real number; the solve checks that they are finite.
JosephsonCircuits.torelations Method
torelations(r, A::AbstractArray)The relations r, nothing or a host JunctionRelations, in the array types of A: the coefficients take the working precision of A and move to the backend it lives on, so that the solvers' broadcasts stay on one device and in one precision.
JosephsonCircuits.tracerestart! Method
tracerestart!(tr::NewtonTrace, F)Begin a second attempt at a point whose residual F holds, keeping the record of the first: the norm is appended to the history, the tolerance is the first attempt's, and the residual decides, as at the start, whether the iteration has ended (tracestart!), which is returned.
JosephsonCircuits.tracestalled Method
tracestalled(tr::NewtonTrace, start::Integer; remaining = nothing)residualstalled on the recorded history from start, against the tolerance in force and remaining further steps when a budget is given.
JosephsonCircuits.tracestart! Method
tracestart!(tr::NewtonTrace, F, atol, rtol)Begin the record at a point whose residual F holds: the history is emptied, the tolerance fixed at atol or rtol*norm(F), whichever is larger, and convergence decided on the residual before any Jacobian work. A norm which is not finite, from an entry which is not or from finite entries whose norm overflows, scales no relative tolerance and admits no step: the iteration ends there, not converged, with the reason :nonfinite, and the tolerance is atol. Returns whether the iteration has ended.
JosephsonCircuits.tracestep! Method
tracestep!(tr::NewtonTrace, F, accepted::Bool)Record the step taken to a point whose residual F holds: its norm is appended, convergence is decided on it, and the consecutive line searches which returned the best decreasing trial rather than an Armijo accepted step are counted, an accepted step resetting the count so that an isolated failure in an otherwise recovering solve is ignored. Returns :converged, :linesearch when the count reached maxbacktrackfailures, which is a stall recorded as the reason, or :continue.
JosephsonCircuits.tracetrial! Function
tracetrial!(tr::NewtonTrace, alpha, backtracks, anderson::Bool = false)Record the outcome of one line search: the step length it returned (zero when no trial decreased the merit, NaN for an accelerated candidate accepted outright), the trial evaluations after its first, and whether the step lies on the accelerated path. Recorded before it is known whether the step is taken, since a zero step is not.
JosephsonCircuits.transientinjection Method
transientinjection(problem, targets)The unscaled injection of a unit current at each of targets into the node equations, one sparse column per target: a port number injects into the port's first (positive) terminal, as a port source does, and a component name drives the current through the component from its first terminal to its second, as a named CurrentSource does, whatever the component is: it draws the current from the node at its first terminal and delivers it to the node at its second. The default targets of transienttangent and transientadjoint are the ports in the order of their numbers.
JosephsonCircuits.transientquantumdiagnostics Method
transientquantumdiagnostics(covariance, commutator, expected; rtol=1e-3)Check commutator closure and the Gaussian uncertainty inequality covariance + im*expected/2 >= 0. Small output matrices are inspected on the host. Passing is necessary, not sufficient: refine RF sampling, bath cutoff, frequency quadrature and solver tolerances independently.
JosephsonCircuits.transientsystem Method
transientsystem(problem, h, method, backend, factorization)The TransientSystem of problem at the step h under method on backend, factorizing with factorization.
JosephsonCircuits.transportcurrent! Method
transportcurrent!(d, t::TransportRows, v)The direct resistor current G0 P v each node carries, in place, indexed by node with ground dropped. This is the coupling Jpv applied to v, and it is the quantity a hand elimination would subtract from the source.
JosephsonCircuits.transportresidual! Method
transportresidual!(Fv, t::TransportRows, v)The transport row residual Y v - j, in place.
JosephsonCircuits.transportrows Method
transportrows(plan::DCConductancePlan, bnm, Nmodes)Build the TransportRows for a source bnm.
bnm must be the applied source, not one corrected for the resistor current: that current appears here as the coupling term, and taking it from a corrected source would count it twice.
JosephsonCircuits.transposedestinations Method
transposedestinations(st::DeviceScatteringStamps, Aindexcsr, backend)A view of the same scattering stamp values with different destinations, for the transposed (adjoint) system: the contribution of a block does not depend on the direction the system is assembled in, only on where in the stored order of that system each scalar lands. Sharing values is what lets the providers be evaluated once for both directions.
JosephsonCircuits.transposepattern Method
transposepattern(p::DeviceSparsePattern, backend)The transpose of a sparsity structure, on the same backend.
Compressed sparse columns of the transpose are compressed sparse rows of the original, so this is a stable counting sort of the stored entries by their row: segmentbydest! does exactly that, and its stability is what leaves the column indices ascending within each row, because a column major traversal meets them in that order.
JosephsonCircuits.truncfreqs Method
truncfreqs(frequencies::Frequencies; maxharmonics = frequencies.Nharmonics,
maxintermodorder = Inf, dc = true, odd = true, even = true,
w = nothing, frequencywindow = (0, Inf))Return a new Frequencies with the coordinates and modes truncated to those which satisfy the criteria: the zero frequency mode when dc, modes of odd or even total harmonic order when odd or even, modes which are a harmonic of a single tone or whose absolute harmonic indices sum to at most maxintermodorder, and modes whose absolute harmonic index in each tone is at most maxharmonics for that tone.
With the tone frequencies w given and a window other than the default (0, Inf), a mode is also required to lie in the frequencywindow: wmin <= abs(dot(w, mode)) <= wmax, in the units of w. The zero frequency mode is governed by dc alone. This is a truncation by frequency rather than by order: incommensurate tones scatter combination frequencies of high order arbitrarily close to zero, where a floating circuit's linear response is enormous although nothing excites those modes, and near the junction plasma frequency at the other end, at the edge of the sampled grid where their products alias. Such modes carry almost no flux at the operating point, and their nearly singular blocks are what a block diagonal preconditioner, and every preconditioner built from it, inverts badly: the ceiling can decide whether such a preconditioner converges a solve, while the retained modes barely change.
Examples
julia> JosephsonCircuits.truncfreqs(JosephsonCircuits.calcfreqsrdft((3,3));maxintermodorder=2).modes
12-element Vector{Tuple{Int64, Int64}}:
(0, 0)
(1, 0)
(2, 0)
(3, 0)
(0, 1)
(1, 1)
(0, 2)
(0, 3)
(0, -3)
(0, -2)
(0, -1)
(1, -1)
julia> JosephsonCircuits.truncfreqs(JosephsonCircuits.calcfreqsrdft((3,3));dc=false,even=false,maxintermodorder=3).modes
10-element Vector{Tuple{Int64, Int64}}:
(1, 0)
(3, 0)
(0, 1)
(2, 1)
(1, 2)
(0, 3)
(0, -3)
(1, -2)
(0, -1)
(2, -1)
julia> JosephsonCircuits.truncfreqs(JosephsonCircuits.calcfreqsrdft((3,3));maxintermodorder=2)
JosephsonCircuits.Frequencies{2}((3, 3), (4, 7), (7, 7), CartesianIndex{2}[CartesianIndex(1, 1), CartesianIndex(2, 1), CartesianIndex(3, 1), CartesianIndex(4, 1), CartesianIndex(1, 2), CartesianIndex(2, 2), CartesianIndex(1, 3), CartesianIndex(1, 4), CartesianIndex(1, 5), CartesianIndex(1, 6), CartesianIndex(1, 7), CartesianIndex(2, 7)], [(0, 0), (1, 0), (2, 0), (3, 0), (0, 1), (1, 1), (0, 2), (0, 3), (0, -3), (0, -2), (0, -1), (1, -1)])
julia> JosephsonCircuits.truncfreqs(JosephsonCircuits.calcfreqsrdft((3,3));dc=false,even=false,maxharmonics=(2,2),maxintermodorder=3).modes
7-element Vector{Tuple{Int64, Int64}}:
(1, 0)
(0, 1)
(2, 1)
(1, 2)
(1, -2)
(0, -1)
(2, -1)JosephsonCircuits.tryfactorize! Method
tryfactorize!(cache::FactorizationCache,
factorization::AbstractFactorization, A; kwargs...)Factorize A, a matrix or a BlockJacobian, with the method factorization and store the result in cache. When the cache already holds a factorization and the method supports refactorization, its symbolic analysis is reused; a SingularException during that refactorization falls back to a fresh factorization, since reusing the symbolic analysis can fail numerically where a fresh one succeeds. (KLU checks the pivots it reuses itself and repivots in place; see klurefactor!.) A fresh factorization by a method which is handed its fill reducing ordering (KLU) takes the ordering the cache holds for the pattern of A, choosing and keeping one when it holds none. kwargs are forwarded to factorize (the block size of a BlockFactorization of a sparse matrix).
JosephsonCircuits.trysolve! Method
trysolve!(x,factorization,b)Solve the linear system factorized by factorization for the right hand side b into x with ldiv!, and with \ for a factorization which has no ldiv! for these arguments: after a MethodError of ldiv! itself or an ArgumentError. Any other error is rethrown.
JosephsonCircuits.trysolvetranspose! Method
trysolvetranspose!(x,factorization,b)Solve the transposed linear system transpose(A)*x = b using an existing factorization of A, without refactorizing. The non-conjugating transpose is used, not the adjoint. Sparse LU factorizations support this directly with a pair of triangular solves against the stored factors (klu_tsolve for KLU), so an adjoint solve costs a solve rather than a factorization. As in trysolve!, fall back to \\ for factorizations which do not support ldiv! with a transposed factorization.
Used by hblinsolve to obtain the solutions of the transposed linearized system, which are the adjoint solutions required by the noise, quantum efficiency, and sensitivity calculations.
JosephsonCircuits.tuple2edge Method
tuple2edge(tuplevector::Vector{Tuple{Int, Int}})Convert a vector of (src, dst) tuples to a vector of Graphs edges.
Examples
julia> JosephsonCircuits.tuple2edge([(1,2),(3,4)])
2-element Vector{Graphs.SimpleGraphs.SimpleEdge{Int64}}:
Edge 1 => 2
Edge 3 => 4JosephsonCircuits.uniformbatchlimit Method
uniformbatchlimit(nrhs::Integer)The largest uniform batch of systems to hand cuDSS, whatever the number of right hand sides nrhs. Fifteen, for two independent reasons, one of correctness and one of speed.
A wrong answer above fifteen systems with six or more right hand sides
cuDSS 0.7 and 0.8 (through CUDSS.jl 0.8.0) return silently wrong solutions from a uniform batch of sixteen or more systems once each has six or more right hand sides. Every system of the batch comes back wrong, by order one, while cudss_get(solver, "info") reports success and "lu_nnz" is unchanged, so nothing downstream can detect it. A batch of fifteen is correct with twelve right hand sides and a batch of sixteen is wrong by order one.
A step in the cost at sixteen systems, at every right hand side count
cuDSS 0.8 takes several times as long per refactorization and solve for a batch of sixteen as for a batch of fifteen, at every number of right hand sides, and then the same time for every batch from sixteen to sixty four. Because the cost above the step does not grow with the batch, splitting into chunks of fifteen always wins.
The cap costs nothing on this path, since the speedup of batching a frequency sweep through cuDSS saturates by about a dozen systems. It applies only to the cuDSS batch, which a frequency sweep also holds to its memory budget (cudssbatchlimit): a SparseBlockFactorization sweep sizes its batch by memory alone (blocksystembytes) and profits from batches well past this. The nrhs argument is kept because the first bound depends on it and the second does not, so a cuDSS release which fixes one can be accommodated without changing the callers. Re-check both against newer releases before raising it.
JosephsonCircuits.unitaritybound Method
unitaritybound(provider)An upper bound on how far the data of provider is from unitary at any frequency, as the largest entry of I - S S', from what it stores: its samples (see unitaritydeviation), and between the knots of a table the bound of its interpolant. Inf where nothing stored bounds it: a callable or a realization, whose values are computed, a table extrapolated linearly, which is unbounded beyond its knots, and data which is zero somewhere, a table extrapolated by zero or a piecewise table, which absorbs everything there. A lossless line is unitary by construction. A rotation of unit phases on each side keeps the size of every entry of I - S S', so it is bounded as what it turns is.
JosephsonCircuits.unitaritydeviation Method
unitaritydeviation(S::AbstractMatrix)The largest absolute entry of I - S S', which is zero for a lossless (unitary) scattering matrix. Unlike passivitymargin this sees gain as well as loss, so it is the quantity a lossless test compares against a tolerance.
JosephsonCircuits.unscalesolution! Method
unscalesolution!(X::AbstractArray{<:Any,3}, eq::SweepEquilibration,
backend)Undo on the solutions of a batch the column scaling equilibrate! applied to its matrices; the row scaling changes the equations and not the unknowns, so it has nothing to undo.
JosephsonCircuits.unwrap! Method
unwrap!(y, m; dims = nothing, range = 2pi)Unwrap m storing the result in y, see unwrap. dims must be given for an array of more than one dimension.
JosephsonCircuits.unwrap Method
unwrap(m; dims = nothing, range = 2pi)Assumes m to be a sequence of real values, such as phases, that has been wrapped to be inside the given range (centered around zero), and undoes the wrapping by identifying discontinuities: each value is moved by a multiple of range to within half of range of the value before it. dims is the dimension along which to unwrap, required for an array of more than one dimension; the array is unwrapped along that dimension only. The result is of floating point type, for integer values as well. Complex values are not phases and are refused with an ArgumentError: unwrap angle.(z).
A common usage is a phase measured over time or over frequency, such as the phase of a scattering parameter, which angle wraps to stay within (-pi, pi].
Arguments
m::AbstractArray{T, N}: Array of real values to unwrap.dims=nothing: Dimension along which to unwrap.range=2pi: Range of wrapped array.
JosephsonCircuits.updatepreconditioner! Function
updatepreconditioner!(pc::AbstractPreconditioner, x::AbstractVector)Rebuild the preconditioner pc at the point x and return pc.
JosephsonCircuits.updatepreconditioner! Method
updatepreconditioner!(pc::ModeCouplingPreconditioner, x)Rebuild the preconditioner at the point x: set the system's point, let a MeasuredBand remeasure its per tone bandwidths there and grow its band when they have widened (never shrinking), let a Clusters request reprobe its couplings at the first point or after stalled! and grow its mask, then assemble and refactorize. A band or a mask grows only when its factors fit the memory budget an escalation keeps to (escalatepreconditioner!); one which would not keeps the set it has.
JosephsonCircuits.usescycleharvest Method
usescycleharvest(pc::AbstractPreconditioner)Whether pc reads the Arnoldi factorization of every restart cycle (harvestcycle!), so that the linear solve calls it back at the end of each. false by default, which leaves the callback out of the solves of a preconditioner that does not recycle.
JosephsonCircuits.valuemaps Method
valuemaps(sys::HBSystem)The ValueMaps of a system, for rebinding it without rebuilding the plan.
JosephsonCircuits.valuemaps Method
valuemaps(plan::NonlinearTermPlan, Knm, invLnm, Gnm, Cnm, Rbnm, Ljb,
layout, freqindexmap)The ValueMaps of a plan, found by probing.
Each conversion is linear and each of its output entries reads one input entry, so tagging the inputs with their own indices and reading the outputs gives the map, and does so for whatever rule the conversion follows. The conversions keep every stored entry whatever its value, so the structure under the tags is the plan's; one which is not is refused.
sourceJosephsonCircuits.valuetonumber Method
valuetonumber(value, circuitdefs)The component value value at the definitions circuitdefs. A name, written as a symbol or a string, is the definition of that name under whichever key gives it (see definitionsbyname), and a name the definitions do not give is returned as it is, for the check of the values to report naming its component (checkcomponentvaluesdefined). Any other value, a number or a frequency dependent value, is returned unchanged. The Symbolics extension adds the method for its symbolic values, which substitutes the definitions of their variables.
Examples
julia> JosephsonCircuits.valuetonumber(:Lj1,Dict(:Lj1=>1e-12,:Lj2=>2e-12))
1.0e-12
julia> JosephsonCircuits.valuetonumber("Lj1",Dict(:Lj1=>1e-12))
1.0e-12
julia> JosephsonCircuits.valuetonumber(1.0,Dict(:Lj1=>1e-12,:Lj2=>2e-12))
1.0JosephsonCircuits.warndeprecations Method
warndeprecations(messages::Vector{String}, caller::Symbol)Warn once, attributed to caller, with messages, the deprecations one call of caller met; nothing when there are none.
JosephsonCircuits.warnduplicatematchedload Method
warnduplicatematchedload(ports, componentnames, componenttypes,
componentvalues, nodeindices)Warn when a matched port has a device resistor of exactly its own reference impedance across the same two nodes.
Such a circuit is legal, and is what a user who wants two loads means, so it is not refused. It is far more often a circuit written in the tuple netlist style, where the resistor across a port was its termination, and now carries two loads instead of one. Only an exact match of the reference impedance is reported, because that is what makes the resistor a likely duplicate rather than a device.
sourceJosephsonCircuits.weightedrowpower! Method
weightedrowpower!(out, comp, A::AbstractMatrix, w)Overwrite out[i] with sum_j weight_j*abs2(A[i,j]), the weight of column j being the sign of the mode frequency w[(j-1) % length(w) + 1] of the column, which is the sum of the commutation relations (calccm!). The rows are accumulated column by column for cache efficiency, with a Kahan-Babuska-Neumaier compensated sum whose corrections live in comp, one per row: the row of a high gain amplifier is a cancellation between large signal and idler terms.
JosephsonCircuits.williamson_block Method
williamson_block(M::AbstractMatrix{<:Real}; atol = 0, rtol = ...)The block ordered form of williamson_pair: d is in block order and S is symplectic with respect to the block ordered symplectic form.
JosephsonCircuits.williamson_pair Method
williamson_pair(M::AbstractMatrix{<:Real}; atol = 0, rtol = ...)For a symmetric positive semi-definite matrix M, return a vector of values d and a real symplectic matrix S such that M = S Diagonal(d) S^T. S is symplectic with respect to the pair ordered symplectic form Ω.
Such a decomposition exists for a positive definite M, and for a positive semi-definite one on whose range the symplectic form is nondegenerate, which requires an even rank. Otherwise, as for Diagonal([1, 0]) of rank one or Diagonal([1, 0, 1, 0]), whose range holds the positions alone, an ArgumentError is thrown.
The values d are unique but the matrix S is not. S is computed from a Schur decomposition [2] rather than an eigendecomposition, which is robust to degenerate values.
M must be symmetric to the tolerances atol and rtol of isapprox (the default rtol is the square root of the machine epsilon of its element type, and zero when atol is given), and its symmetric part (M + transpose(M))/2 is decomposed, so that a covariance which rounding left slightly asymmetric, such as S*Diagonal(d)*transpose(S), is accepted.
References
[1] M. Idel, S. Soto Gaona, and M. M. Wolf, “Perturbation bounds for Williamson’s symplectic normal form,” Linear Algebra and its Applications, vol. 525, pp. 45–58, Jul. 2017, doi: 10.1016/j.laa.2017.03.013. [2] M. Houde, W. McCutcheon, and N. Quesada, “Matrix decompositions in Quantum Optics: Takagi/Autonne, Bloch-Messiah/Euler, Iwasawa, and Williamson,” Can. J. Phys., vol. 102, no. 10, pp. 497–507, Oct. 2024, doi: 10.1139/cjp-2024-0070.
sourceJosephsonCircuits.windowindex Method
windowindex(L::CompositeLayout, k)The canonical position of window entry k: a zero frequency entry of the internal state for k <= L.ndc, an explicit voltage after that.
JosephsonCircuits.windowindices Method
windowindices(L::CompositeLayout)The canonical positions of the whole window, in window order.
sourceJosephsonCircuits.with Method
with(k::KrylovSolveInfo; fields...)A copy of the record with the named fields replaced: the step outcome filled in after the line search, an escalation marked after the solve.
sourceJosephsonCircuits.withescalation Method
withescalation(m::AbstractHBNonlinearSolver, flag::Bool)The method with its escalate set to flag, for the interior stages of Staged; methods without escalation are returned unchanged.
JosephsonCircuits.withfactors Method
withfactors(bp::DeviceBlockNoisePlan)A copy of the plan with scratch of its own for the covariance factors, sharing everything else, so that several workers can form the noise channels of different signal frequencies at once. The factors are written by blocknoisefactorkernel! and read by blocknoisecontractkernel! at one frequency, so they cannot be shared; the tables which say where each block is can be.
JosephsonCircuits.withprecision Method
withprecision(f::AbstractFactorization, T)The factorization f holding its factors in T: a CUDSSFactorization or a BlockFactorization with its precision replaced, any other unchanged, since it factorizes in the precision of the matrix it is handed. This is how a preconditioner whose factors are held in less precision than its iteration is escalated.
JosephsonCircuits.wmatrix! Method
wmatrix!(w::AbstractMatrix, ws::AbstractVector, wp::Tuple,
modes::AbstractVector{<:Tuple})In place version of wmatrix, writing into w, of size (length(modes), length(ws)), and returning it.
JosephsonCircuits.wmatrix Method
wmatrix(ws::AbstractVector, wp::Tuple, modes::AbstractVector{<:Tuple})Return the Nmodes by Nfreqs matrix of frequencies for the signal, idlers, and sidebands given the signal frequencies ws, pump frequencies wp, and modes modes, each a tuple of as many integers as there are pumps: the frequency of mode modes[i] at signal frequency ws[j] is ws[j] + sum(modes[i] .* wp). The element type is that of ws and wp promoted.
Examples
julia> JosephsonCircuits.wmatrix(0.1:0.1:1.0,(1.0,),[(1,),(-1,)])
2×10 Matrix{Float64}:
1.1 1.2 1.3 1.4 1.5 1.6 1.7 1.8 1.9 2.0
-0.9 -0.8 -0.7 -0.6 -0.5 -0.4 -0.3 -0.2 -0.1 0.0JosephsonCircuits.workspacetwin Method
workspacetwin(sys::HBSystem)A system which shares with sys everything its evaluations only read – the linear term, the junction data, the source, the maps, the transform plans, the nonlinear term plan and the junction relations – and has a point and workspaces of its own, and no Jacobian assembly plans. Evaluating the twin writes nothing sys reads, so twins of one system serve calls which evaluate it at the same time; neither may be rebound (see rebind!), which would move the shared values under the other.
JosephsonCircuits.wrspice_calcS_paramp Method
wrspice_calcS_paramp(out, wswrspice, Nnodes; stepsperperiod = 80,
Is = 1e-13)The reflection S11 and transmission S21 of a parametric amplifier at the signal angular frequencies wswrspice, from the WRSPICE outputs out of the simulations generated by wrspice_input_paramp with the same Is. The traces v(1) and v(Nnodes-1), found by name, are taken as the input and the output port, both of 50 ohms, where Nnodes is the number of nodes including ground; so the nets must be named by the integers 0 to Nnodes-1, and an output without either trace is an error. The signal response at a node is the difference of its voltage with the signal and without it, the cosine and the sine responses combined as the real and imaginary parts of one complex response, which holds every mixing product, the idlers included, at the signal frequency shifted by a combination of the pump frequencies. It is demodulated at the signal frequency and averaged over the last stepsperperiod print points, over which the mixing products average to zero only if the window spans a common period of the pumps. With the stepsperperiod of the generation the window is one period of the fastest pump, which is that common period for a single pump; several pumps need a larger stepsperperiod, which spans theirs. The incident wave of the signal source is half its Thevenin voltage 50*Is.
Examples
# the voltages of a port which reflects S11 = 0.5*cis(pi/3) at the signal
# frequency, on the last pump period, with the pump's own response
ws = 2*pi*5e9
wp = 2*pi*6e9
stepsperperiod = 80
Is = 1e-13
t = collect(0:stepsperperiod - 1)*2*pi/(wp*stepsperperiod)
V = (1 + 0.5*cis(pi/3))*50*Is/2
Vpump = reshape(1e-6*cos.(wp*t), 1, :)
Vcos = Vpump .+ reshape(real.(V*cis.(ws*t)), 1, :)
Vsin = Vpump .+ reshape(real.(-im*V*cis.(ws*t)), 1, :)
variables = Dict("V" => ["v(1)"])
out = [(variables = variables, values = Dict("S" => t, "V" => Vpump)),
(variables = variables, values = Dict("S" => t, "V" => Vsin)),
(variables = variables, values = Dict("S" => t, "V" => Vcos))]
S = JosephsonCircuits.wrspice_calcS_paramp(out, [ws], 2;
stepsperperiod = stepsperperiod, Is = Is)
abs(only(S.S11) - 0.5*cis(pi/3)) < 1e-10
# output
trueJosephsonCircuits.wrspice_cmd Method
wrspice_cmd()The command which runs WRSPICE: the executable at WRSPICE's standard installation path if one is installed there, else the one a loaded provider registered, which loading the XicTools_jll package does on the platforms its artifact supports. Throws when neither is available; WRspice and spice_run take an executable directly for one installed elsewhere.
JosephsonCircuits.wrspice_input_ac Method
wrspice_input_ac(netlist, nsteps, wstart, wstop, portnodes, portcurrent;
maxdata = 2e9)
wrspice_input_ac(netlist, ws, portnodes, portcurrent; maxdata = 2e9)Generate the WRSPICE input for an AC small signal simulation of the circuit in netlist, driven by an AC current source of the complex amplitude portcurrent across the node pair portnodes, given as one-based node indices with ground as index 1: the source draws its current from portnodes[1] and injects it into portnodes[2], each decremented to its SPICE node label, so [1, 2] drives the SPICE node 1 from ground, with the magnitude and the phase of portcurrent, the phase written in degrees as SPICE reads it. The indices address the nets named by the integers 0 to N-1, index k the net k-1; a net named by a word cannot be driven. The analysis is .ac lin nsteps fstart fstop, over linearly spaced frequencies from the angular frequency wstart to wstop in radians per second, written in Hz as SPICE takes them, which WRSPICE answers with nsteps + 2 points when wstart < wstop. The second form takes the angular frequencies ws as a single number, or as a vector or range of uniformly spaced ones: one frequency is written from itself to itself, which WRSPICE answers with that one point, and more from the first to the last with length(ws) - 2 passed as nsteps, so that WRSPICE answers with length(ws) points, the frequencies of ws. A vector which is not uniformly spaced to the tolerance of isapprox is refused, since WRSPICE would answer at other frequencies, and so are two frequencies, since WRSPICE answers nsteps = 0 with three points. maxdata is the WRSPICE limit on the size of the data written, in kilobytes.
Examples
julia> println(JosephsonCircuits.wrspice_input_ac("* SPICE Simulation",100,2pi*4e9,2pi*5e9,[1,2],1e-6))
* SPICE Simulation
* AC current source into the port
isrc 0 1 ac 1.0e-6 0.0
* Set up the AC small signal simulation
.ac lin 100 4.0g 5.0g
* The control block
.control
* Maximum size of data to export in kilobytes from 1e3 to 2e9 with
* default 2.56e5. This has to come before the run command
set maxdata=2.0e9
* Run the simulation
run
* Binary files are faster to save and load.
set filetype=binary
* Leave filename empty so we can add that as a command line argument.
* Don't specify any variables so it saves everything.
write
.endcjulia> println(JosephsonCircuits.wrspice_input_ac("* SPICE Simulation",2pi*(4:0.01:5)*1e9,[1,2],1e-6))
* SPICE Simulation
* AC current source into the port
isrc 0 1 ac 1.0e-6 0.0
* Set up the AC small signal simulation
.ac lin 99 4.0g 5.0g
* The control block
.control
* Maximum size of data to export in kilobytes from 1e3 to 2e9 with
* default 2.56e5. This has to come before the run command
set maxdata=2.0e9
* Run the simulation
run
* Binary files are faster to save and load.
set filetype=binary
* Leave filename empty so we can add that as a command line argument.
* Don't specify any variables so it saves everything.
write
.endcJosephsonCircuits.wrspice_input_paramp Method
wrspice_input_paramp(netlist, ws, wp, Ip, sourcenodes, sourcenodep;
stepsperperiod = 80, Is = 1e-13, tstop = 200e-9, trise = 10e-9,
dphimax = 0.01, maxdata = 2e9)Generate the WRSPICE inputs for the time domain simulations of a parametric amplifier: one with the pump alone at angular frequency wp and current Ip, applied between the (src, dst) node pair sourcenodep, and then for each signal angular frequency in ws one with a small sine and one with a small cosine signal of amplitude Is added between the node pair sourcenodes. A source draws its current from src and injects it into dst, as SPICE orients a current source, so a drive into port node 1 is (0, 1). Returns the vector of input strings, pump first, which spice_run runs and wrspice_calcS_paramp turns into scattering parameters. stepsperperiod time steps per pump period are taken for tstop seconds with a rise time trise (see wrspice_input_transient).
Examples
using JosephsonCircuits
using Plots
circuit = Circuit(
[:p1 => Port(1; Z0 = :R),
:cc => Capacitor(:Cc),
:jj => JosephsonJunction(:Lj),
:cj => Capacitor(:Cj),
:gnd => Ground()],
[Net("1", [(:p1, 1), (:cc, 1)]),
Net("2", [(:cc, 2), (:jj, 1), (:cj, 1)]),
Net("0", [(:p1, 2), (:jj, 2), (:cj, 2), (:gnd, 1)])])
circuitdefs = Dict(
:Lj =>1000.0e-12,
:Cc => 100.0e-15,
:Cj => 1000.0e-15,
:R => 50.0)
ws = 2*pi*(4.5:0.001:5.0)*1e9
wp = (2*pi*4.75001*1e9,)
Ip = 0.00565e-6
sources = [(mode=(1,),port=1,current=Ip)]
Npumpharmonics = (16,)
Nmodulationharmonics = (8,)
@time jpa = hbsolve(ws, wp, sources, Nmodulationharmonics,
Npumpharmonics, circuit, circuitdefs)
wswrspice=2*pi*(4.5:0.01:5.0)*1e9
n = JosephsonCircuits.exportnetlist(circuit,circuitdefs);
input = JosephsonCircuits.wrspice_input_paramp(n.netlist,wswrspice,wp[1],2*Ip,(0,1),(0,1));
@time output = JosephsonCircuits.spice_run(input,JosephsonCircuits.wrspice_cmd());
S11,S21=JosephsonCircuits.wrspice_calcS_paramp(output,wswrspice,n.Nnodes);
plot(ws/(2*pi*1e9),
10*log10.(abs2.(jpa.linearized.S((0,),1,(0,),1,:))),
label="JosephsonCircuits.jl",
xlabel="Frequency (GHz)",
ylabel="S11 (dB)")
plot!(wswrspice/(2*pi*1e9),10*log10.(abs2.(S11)),
label="WRSPICE",
seriestype=:scatter)JosephsonCircuits.wrspice_input_transient Method
wrspice_input_transient(netlist::String, current, w, phase,
sourcenodes, tstep, tstop, trise; maxdata = 2e9, jjaccel = 1,
dphimax = 0.01, filetype = "binary")Generate the WRSPICE input for a transient simulation of the circuit in netlist, driven by one sinusoidal current source per entry of current, w, phase and sourcenodes, with the time step and stop time given. The output file name is left out of the write command so it can be given on the command line, and no variables are named so that every node is saved.
Arguments
netlist: String containing the circuit netlist, excluding sources.current: Vector of current source amplitudes in Ampere.w: Vector of current source angular frequencies in radians per second.phase: Vector of current source phases in radians.sourcenodes: Vector of tuples of nodes(src, dst)at which to place the current source(s). A source draws its current fromsrcand injects it intodst, as SPICE orients a current source, so(0, 1)drives node1from ground.tstep: Time step in seconds.tstop: Time for which to run the simulation in seconds.trise: The simulation ramps up the current source amplitude with a 1-sech(t/trise) envelope which reaches 35 percent of the peak in onetrise.
Keywords
maxdata = 2e9: Maximum size of data to export in kilobytes from 1e3 to 2e9 with WRspice default 2.56e5. This has to come before the run command.jjaccel = 1: Causes a faster convergence testing and iteration control algorithm to be used, rather than the standard more comprehensive algorithm suitable for all devices.dphimax = 0.01: The maximum allowed phase change per time step. Decreasing dphimax from the default of pi/5 to a smaller value is critical for matching the accuracy of the harmonic balance method simulations. This increases simulation time by pi/5/(dphimax).filetype = "binary": the format of the rawfile WRSPICE writes,"binary"or"ascii".spice_runandspice_raw_loadread the binary format only, so an ASCII rawfile must be read elsewhere.
Examples
julia> println(JosephsonCircuits.wrspice_input_transient("* SPICE Simulation",[1e-6,1e-3],2pi*[5e9,6e9],[3.14,6.28],[(1,0),(1,0)],1e-9,100e-9,10e-9))
* SPICE Simulation
* Current source
* 1-hyperbolic secant rise
isrc1 1 0 1.0u*cos(31.41592653589793g*x+3.14)*(1-2/(exp(x/1.0e-8)+exp(-x/1.0e-8)))
isrc2 1 0 1000.0u*cos(37.69911184307752g*x+6.28)*(1-2/(exp(x/1.0e-8)+exp(-x/1.0e-8)))
* Set up the transient simulation
* .tran 5p 10n
.tran 1000.0000000000001p 100.0n uic
* The control block
.control
set maxdata=2.0e9
set jjaccel=1
set dphimax=0.01
run
set filetype=binary
write
.endcLinearAlgebra.dot Method
dot(y::AbstractVector{<:BlasFloat}, A::DeviceValuedSparseMatrix,
x::AbstractVector)y' * A * x, the model slope the line search of nlsolve! needs.
LinearAlgebra.ldiv! Method
LinearAlgebra.ldiv!(z, pc::AbstractPreconditioner, r)
LinearAlgebra.ldiv!(pc::AbstractPreconditioner, r)
pc \ rApply the inverse of the preconditioner, forwarding to applypreconditioner!.
ldiv! is the de facto interface every external Krylov package consumes: Pl/Pr in LinearSolve.jl and IterativeSolvers.jl, M/N in Krylov.jl, Pl in BifurcationKit's linear solvers. The domain knowledge of this solver lives in the preconditioner, so defining ldiv! is what makes ModeCouplingPreconditioner and FloquetPreconditioner reusable outside the package without an adapter.
LinearAlgebra.mul! Method
LinearAlgebra.mul!(z, pc::AbstractPreconditioner, r)Apply the inverse of the preconditioner, spelled as a multiplication.
The two conventions in the ecosystem disagree. LinearSolve.jl and IterativeSolvers.jl take a preconditioner and divide by it, so they call ldiv!. Krylov.jl takes M and N to be operators which already represent the inverse and multiplies, so it calls mul!. Supporting both is what lets the same preconditioner object be handed to either without an adapter, which is the whole point of shipping it as an object.
LinearAlgebra.mul! Method
mul!(w::AbstractVector{<:BlasFloat}, A::DeviceValuedSparseMatrix,
x::AbstractVector)w = A*x on the backend A's values live on.
A stores its structure as the transpose, so a compressed column of that structure is a row of A and the product is a row wise contraction with no atomics.
The destination is restricted to the element types a device backend actually stores, which is also what keeps this from being ambiguous with the mul! methods packages define for their own scalar types.