ahkab.dc_analysis¶
This module provides the functions needed to perform OP and DC simulations.
The principal are:
dc_analysis()
- which performs a dc sweep,op_analysis()
- which does an operation point analysis or
Notice that internally, dc_analysis()
calls op_analysis()
,
since a DC sweep is nothing but a series of OP analyses..
The actual circuit solution is done by mdn_solver()
, that uses a
modified version of the Newton Rhapson method.
Module reference¶
-
build_gmin_matrix
(circ, gmin, mna_size, verbose)[source]¶ Build a Gmin matrix
Parameters:
- circ : circuit instance
- The circuit for which the matrix is built.
- gmin : scalar float
- The value of the minimum conductance to ground to be used.
- mna_size : int
- The size of the MNA matrix associated with the GMIN matrix being built.
- verbose : int
- The verbosity level, from 0 (silent) to 6 (debug).
Returns:
- Gmin : ndarray of size (mna_size, mna_size)
- The Gmin matrix itself.
-
build_x0_from_user_supplied_ic
(circ, icdict)[source]¶ Builds a vector of appropriate (reduced!) size from the values supplied in
icdict
.Supplying a custom x0 can be useful: - To aid convergence in tough circuits, - To start a transient simulation from a particular x0.
Parameters:
- circ: circuit instance
- The circuit the \(x_0\) is being assembled for
- icdict: dict
icdict
is a a dictionary assembled as follows:- to specify a nodal voltage:
{'V(node)':<voltage value>}
Eg.{'V(n1)':2.3, 'V(n2)':0.45, ...}
. All unspecified voltages default to 0. - to specify a branch current:
'I(<element>)':<current value>}
ie. the elements names are sorrounded byI(...)
. Eg.{'I(L1)':1.03e-3, I(V4):2.3e-6, ...}
All unspecified currents default to 0.
- to specify a nodal voltage:
Notes: this simulator uses the standard convention.
Returns:
- x0 : ndarray
- The x0 matrix assembled according to
icdict
.
Raises: ValueError – whenever a malformed icdict
is supplied.
-
dc_analysis
(circ, start, stop, step, source, sweep_type=u'LINEAR', guess=True, x0=None, outfile=u'stdout', verbose=3)[source]¶ Performs a sweep of the value of V or I of a independent source from start value to stop value using the provided step.
For every circuit generated, computes the OP. This function relays on
dc_analysis.op_analysis()
to actually solve each circuit.Parameters:
- circ : Circuit instance
- The circuit instance to be simulated.
- start : float
- Start value of the sweep source
- stop : float
- Stop value of the sweep source
- step : float
- The step size in the sweep
- source : string
- The part ID of the source to be swept, eg.
'V1'
. - sweep_type : string, optional
- Either options.dc_lin_step (default) or options.dc_log_step
- guess : boolean, optional
- op_analysis will guess to start the first NR iteration for the first point,
the previsious OP is used from then on. Defaults to
True
. - outfile : string, optional
- Filename of the output file. If set to
'stdout'
(default), prints to screen. - verbose : int
- The verbosity level, from 0 (silent) to 6 (debug).
Returns:
- rstdc : results.dc_solution instance or None
- A
results.dc_solution
instance is returned, if a solution was found for at least one sweep value. orNone
, if an error occurred (eg invalid start/stop/step values) or there was no solution for any sweep value.
-
dc_solve
(mna, Ndc, circ, Ntran=None, Gmin=None, x0=None, time=None, MAXIT=None, locked_nodes=None, skip_Tt=False, verbose=3)[source]¶ Low-level method to perform a DC solution of the circuit
Note
Typically the user calls
dc_analysis.op_analysis()
ordc_analysis.dc_analysis()
, which in turn will setup all matrices and call this method on their behalf.The system we want to solve is:
\[(mna + G_{min}) \cdot x + N(t) + T(x, t) = 0\]Where:
- \(mna\) is the reduced MNA matrix with the required KVL/KCL rows
- \(N\) is composed by a DC part, \(N_{dc}\), and a dynamic time-dependent part \(N_{tran}(t)\) and a time-dependent part \(T_t(t)\).
- \(T(x, t)\) is both time-dependent and non-linear with respect to the circuit solution \(x\), and it will be built at each iteration over \(t\) and \(x\).
Parameters:
- mna : ndarray
- The MNA matrix described above. It can be built calling
generate_mna_and_N()
. This matrix will contain the dynamic component due to a Differetiation Formula (DF) when this method is called from a transient analysis. - Ndc : ndarray
- The DC part of \(N\). Also this vector may be built calling
generate_mna_and_N()
. - circ : Circuit instance
- The circuit instance from which
mna
andN
were built. - Ntran : ndarray, optional
- The linear time-dependent and dynamic part of \(N\), if available. Notice this is typically set when a DF being applied and the method is being called from a transient analysis.
- Gmin : ndarray, optional
- A matrix of the same size of
mna
, containing the minimum transconductances to ground. It can be built withbuild_gmin_matrix()
. If not set, no Gmin matrix is used. - x0 : ndarray or results.op_solution instance, optional
- The initial guess for the Newthon-Rhapson algorithm. If not specified, the all-zeros vector will be used.
- time : float scalar, optional
- The time at which any matrix evaluation done by this method will be performed. Do not set for DC or OP analysis, must be set for a transisent analysis. Notice that \(t=0\) is not the same as DC!
- MAXIT : int, optional
- The maximum number of Newton Rhapson iterations to be performed before
giving up. If unset,
options.dc_max_nr_iter
is used. - locked_nodes : list of tuples, optional
- The nodes that need to have a well behaved, slowly varying voltage
applied. Typically they control non-linear elements. This is generated
by
ahkab.circuit.Circuit.get_locked_nodes()
and it will be generated for you if left unset. However, if you are doing many simulations of the same circuit (as it happens in a transient analysis), it’s a good idea to generate it only once. - skip_Tt : boolean, optional
- Do not build the \(T_t(t)\) vector. Defaults to
False
. - verbose : int, optional
- The verbosity level. From 0 (silent) to 6 (debug). Defaults to 3.
Returns:
- x : ndarray
- The solution, if found.
- error : ndarray
- The error associated with each solution item, if it was found.
- converged : boolean
- A flag set to True when convergence was detected.
- tot_iterations : int
- Total number of NR iterations run.
-
generate_mna_and_N
(circ, verbose=3)[source]¶ Generate the full unreduced MNA and N matrices required for an MNA analysis
We wish to solve the linear stationary MNA problem:
\[MNA \cdot x + N = 0\]If
nv
is the number of nodes in the circuit,MNA
is a square matrix composed by:MNA[:nv, :]
, KCLs ordered by node, from node 0 up to node nv.
In the above submatrix, we have a voltage part:
MNA[:nv, :nv]
, where each termMNA[i, j]
is due to the (trans-)conductances in between the nodes and a current part,MNA[:nv, nv:]
, where each term is due to a current variable introduced by elements whose current flow is not univocally defined by the voltage applied to their port(s).MNA[nv:, :]
are the KVL equations introduced by the above terms.
N
is similarly partitioned, but it is a vector of size(nv,)
.Parameters:
- circ : circuit instance
- The circuit for which the matrices are to be computed.
- verbose : int, optional
- The verbosity, from 0 (silent) to 6 (debug).
Returns:
- MNA, N : ndarrays
- The MNA matrix and constant term vector computed as per above.
-
get_solve_methods
()[source]¶ Get all the available solving methods
We have the standard solving method and two homotopies available. The homotopies are \(G_{min}\) stepping and source stepping.
Solving methods may be enabled and disabled through the options values:
options.use_standard_solve_method
,options.use_gmin_stepping
,options.use_source_stepping
.
Returns:
- standard_solving, gmin_stepping, source_stepping : dict
- The dictionaries contain the options and the status of the methods.
-
get_td
(dx, locked_nodes, n=-1)[source]¶ Calculates the damping coefficient for the Newthon method.
The damping coefficient is choosen as the lowest between:
- the damping required for the first NR iterations, a parameter which is set
through the integer
options.nr_damp_first_iters
. - If
options.nl_voltages_lock
evaluates toTrue
, the biggest damping factor that keeps the change in voltage across the locked nodes pairs less than the maximum variation allowed, set by:(options.nl_voltages_lock_factor * Vth)
- Unity.
Parameters:
- dx : ndarray
- The undamped increment returned by the NR solver.
- locked_nodes : list
- A vector of tuples of (internal) nodes that are a port of a non-linear component.
- n : int, optional
- The NR iteration counter
Note
If
n
is set to-1
(or any negative value),td
is independent from the iteration number andoptions.nr_damp_first_iters
is ignored.Returns:
- td : float
- The damping coefficient.
- the damping required for the first NR iterations, a parameter which is set
through the integer
-
mdn_solver
(x, mna, circ, T, MAXIT, nv, locked_nodes, time=None, print_steps=False, vector_norm=<function <lambda>>, debug=True)[source]¶ Solves a problem like F(x) = 0 using the Newton Algorithm with a variable damping.
Where:
\[F(x) = mna*x + T + T(x)\]- \(mna\) is the Modified Network Analysis matrix of the circuit
- \(T(x)\) is the contribute of nonlinear elements to KCL
- \(T\) contains the contributions of the independent sources, time
- invariant and linear
If \(x(0)\) is the initial guess, every \(x(n+1)\) is given by:
\[x(n+1) = x(n) + td \cdot dx\]Where \(td\) is a damping coefficient to avoid overflow in non-linear components and excessive oscillation in the very first iteration. Afterwards \(td=1\) To calculate \(td\), an array of locked nodes is needed.
The convergence check is done this way:
Parameters:
- x : ndarray
- The initial guess. If set to
None
, it will be initialized to all zeros. Specifying a initial guess may improve the convergence time of the algorithm and determine which solution (if any) is found if there are more than one. - mna : ndarray
- The Modified Network Analysis matrix of the circuit, reduced, see above.
- circ : circuit instance
- The circuit instance.
- T : ndarray,
- The \(T\) vector described above.
- MAXIT : int
- The maximum iterations that the method may perform.
- nv : int
- Number of nodes in the circuit (counting the ref, 0)
- locked_nodes : list of tuples
- A list of ports driving non-linear elements, generated by
circ.get_locked_nodes()
- time : float or None, optional
- The value of time to be passed to non_linear _and_ time variant elements.
- print_steps : boolean, optional
- Show a progress indicator, very verbose. Defaults to
False
. - vector_norm : function, optional
- An R^N -> R^1 function returning the norm of a vector, for convergence checking. Defaults to the maximum norm, ie \(f(x) = max(|x|)\),
- debug : int, optional
- Debug flag that will result in an array being returned containing node-by-node convergence information.
Returns:
- sol : ndarray
- The solution.
- err : ndarray
- The remaining error.
- converged : boolean
- A boolean that is set to
True
whenever the method exits because of a successful convergence check.False
whenever convergence problems where found. - N : int
- The number of NR iterations performed.
- convergence_by_node : list
- If
debug
was set toTrue
, this list has the same size of the MNA matrix and contains the information regarding which nodes fail to converge in the circuit. Ie.if convergence_by_node[j] == False
, nodej
has a convergence problem. This may significantly help debugging non-convergent circuits.
-
modify_x0_for_ic
(circ, x0)[source]¶ Modifies a supplied x0.
Several circut elements allow the user to set their own Initial Conditions (IC) for either voltage or current, depending on what is appropriate for the element considered.
This method, receives a preliminary
x0
value, typically computed by an OP analysis and goes through the circuit, looking for ICs and setting them inx0
.Notice it is possible to require ICs that are incompatible with each other – for example supplying different ICs to two parallel caps. In that case we try to accommodate the user’s requirements in a non-strict best-effort kind of way: for this reason, whenever multiple ICs are specified, it is best to visually inspect
x0
to check that what you would have expected is indeed what you got.Parameters
- circ : circuit instance
- The circuit in which the ICs are specified.
- x0 : ndarray or results.op_solution
- The initial value to be modified
Returns:
- x0p : ndarray or results.op_solution
- The modified
x0
. Notice that we return the same kind of object as it was supplied. Additionally, theresults.op_solution
is a new instance, while thendarray
is simply the original array modified.
-
more_solve_methods_available
(standard_solving, gmin_stepping, source_stepping)[source]¶ Are there more solving methods available?
Parameters:
- standard_solving, gmin_stepping, source_stepping : dict
- The dictionaries contain the options and the status of the methods.
Returns:
- rsp : boolean
- The answer.
-
op_analysis
(circ, x0=None, guess=True, outfile=None, verbose=3)[source]¶ Runs an Operating Point (OP) analysis
Parameters:
- circ : Circuit instance
- The circuit instance on which the simulation is run
- x0 : op_solution instance or ndarray, optional
- The initial guess to be used to start the NR
mdn_solver()
. - guess : boolean, optional
- If set to
True
(default) andx0
isNone
, it will generate a ‘smart’ guess to use asx0
. - verbose : int
- The verbosity level from 0 (silent) to 6 (debug).
Returns:
A
result.op_solution
instance, if successful,None
otherwise.
-
set_next_solve_method
(standard_solving, gmin_stepping, source_stepping, verbose=3)[source]¶ Select the next solving method.
We have the standard solving method and two homotopies available. The homotopies are \(G_{min}\) stepping and source stepping.
They will be selected and enabled when failures occur according to the options values:
options.use_standard_solve_method
,options.use_gmin_stepping
,options.use_source_stepping
.
The methods will be used in the order above.
The inputs to this method are three dictionaries that keep track of which method is currently enabled and which ones has failed in the past.
Parameters:
- standard_solving, gmin_stepping, source_stepping : dict
- The dictionaries contain the options and the status of the methods, they
should be the values provided by
get_solve_methods()
. - verbose : int, optional
- The verbosity level, from 0 (silent) to 6 (debug).
Returns:
- standard_solving, gmin_stepping, source_stepping : dict
- The updated dictionaries.