This module provides the functionality needed to perform a small-signal symbolic simulation.

The principal method is symbolic_analysis(), which performs the symbolic circuit solution.


This module is geared towards setting up and running the symbolic simulation. Typically, it should be used in conjunction with ahkab.results.symbolic_solution, the symbolic solution class, which holds several convenience methods to extensively manipulate, simplify, post-process and analyze the simulation results, complementing the functionality offered by the Sympy module itself.


calculate_gains(sol, xin, optimize=True)[source]

Calculate low-frequency gain and roots of a transfer function.


sol : dict
the circuit solution
xin : Sympy symbol
the input variable
optimize : boolean, optional
If optimize is set to False, no algebraic simplification will be attempted on the results. The default (optimize=True) results in sympy.together being called on each expression.


gs : dict
A dictionary with as keys the strings <key>/<xin> and as values dictionaries with keys 'gain', 'gain0', 'poles', 'zeros'.
generate_mna_and_N(circ, opts, ac=False, subs=None, verbose=3)[source]

Generate a symbolic Modified Nodal Analysis matrix and N vector.

Only elements that have an is_symbolic attribute set to True (the default) are considered symbolically. Simply set the attribute to False to employ the numeric value. This allows to simplify and speed up the work of the symbolic solver.

The formulation can be performed using conductances or resistances. The choice is made setting the global options.symb_formulate_with_gs value to True. A formulation done in terms of resistors, may result in many separate \(1/R\) terms in the matrices. Historically, sympy choked on those, because of a long-standing bug in polys. Now the issue seems to have been solved and the two computations should be symbolically equivalent albeit computationally different (as expected). The option value options.symb_formulate_with_gs is provided to restore the old functionality in case you use an old version of sympy.


circ : circuit instance
The circuit.
opts : dict
The options to be used for the generation of the matrices. As of now, the only supported option is 'r0s' which can be set to either True or False, and selects whether the equivalent output resistance of the transistors should be taken into account or not.
ac : bool, optional
Flag to trigger the inclusion of frequency-dependent elements. Defaults to False currently (but may change).
subs : dict, optional
The substitution dictionary, composed by mappings of <symbol>:<sympy expression>.
verbose : int, optional
Verbosity flag, from 0 (silent) to 6 (very logorrhoic). Defaults to 3.


mna, N : Sympy matrices
The MNA matrix and the contant term of symbolic type.
subs_gs : dict of symbols
In case the formulation of the MNA is performed in terms of conducatances, this dictionary is to be used to substitute away the conducatances for the resistor symbols, after the circuit is solved but before the results are shown to the user. sympy‘s sub() can take care of that for you. If not necessary, this dictionary is empty.


Setting opts['r0s'] = True, ie considering all the transistors output resistances, can significantly slow down – or even prevent by consuming all available memory – the solution of complex circuits with several active elements.

We recommend a combination of the following:

  • setting the above option in simple circuits only,
  • inserting explicitely the \(r_0\) you wish to consider at circuit level,
  • beefing up your machine with extra RAM and extra computing power,
  • being patient.

Given the transfer function expr, returns poles, zeros.


Get a sympy matrix containing the circuit variables to be solved for.


circ : circuit instance
The circuit


vars : sympy matrix, shape (n, 1)
The variables in a column vector.
s = s

the Laplace variable

symbolic_analysis(circ, source=None, ac_enable=True, r0s=False, subs=None, outfile=None, verbose=3)[source]

Attempt a symbolic, small-signal solution of the circuit.


circ : circuit instance
the circuit instance to be simulated.
source : string, optional
the part_id of the source to be used as input for the transfer
function. If None, no transfer function is evaluated.
ac_enable : bool, optional
take frequency dependency into consideration (default: True).
r0s : bool, optional
take transistors’ output impedance into consideration (default: False)
subs: dict, optional
a dictionary of part IDs to be substituted. It makes solving the circuit easier. Eg. subs={'R1':'R2'} - replace the resistor R1 with R2.
outfile : string, optional
output filename - 'stdout' means print to stdout, the default.
verbose: int, optional
verbosity level 0 (silent) to 6 (painful).


sol : symbolic solution
The solutions.
tfs : symbolic solution
The transfer functions, only if requested. Otherwise tfs is a None object.