ahkab.circuit¶
Introduction¶
A circuit is described in the ahkab simulator by an instance of the
Circuit
class.
This class holds everything is needed to simulate the circuit, except the specification of the analyses to be performed.
To rewrite a netlist from a Circuit instance see the
ahkab.printing
module.
The Circuit¶
A circuit is derived from a list which contains all its elements.
Conceptually, every time an element is to be inserted in the circuit, two operations have to be performed:
- The element must be appended to the
Circuit
instance. - Its connections should be ensure checking that the nodes the element refers to are indeed existing circuit nodes.
To simplify the operation of adding a component to a Circuit
,
the following convenience methods are provided to the user to add and
remove most elements to the circuit:
Circuit.add_resistor()
Circuit.add_capacitor()
Circuit.add_inductor()
Circuit.add_vsource()
Circuit.add_isource()
Circuit.add_diode()
Circuit.add_mos()
Circuit.add_cccs()
Circuit.add_vcvs()
Circuit.add_vccs()
Circuit.add_user_defined()
Circuit.remove_elem()
Example:
mycircuit = circuit.Circuit(title="Example circuit", filename=None)
# no filename since there will be no deck associated with this circuit.
# get the ref node (gnd)
gnd = mycircuit.get_ground_node()
# add a node named n1 and a 600 ohm resistor connected between n1 and gnd
mycircuit.add_resistor(part_id="R1", n1="n1", n2=gnd, R=600)
Refer to the methods help for additional information.
Nodes¶
The nodes are internally stored in the following way: we assign to each node an internal ID, independetly from its external identifier used in the netlist. Those IDs are integers.
The simulator uses always the internal names. When the results are presented to the user, the internal node is not showed, the external identifier (or external node name) is printed instead.
This is done through:
my_circuit = Circuit()
...
[ init code ]
...
print "This is a node" + my_circuit.nodes_dict[int_node]
Internal only nodes
The number of internal only nodes (added automatically by the simulator)
is held in Circuit.internal_nodes
. That value shouldn’t be changed by
hand.
Device models¶
Non-linear elements have their operation described by specialized routines held in their module.
They are stored in Circuit.models
(of type dict), the following methods
are provided to add and remove device models to a Circuit instance.
Reference¶
-
class
Circuit
(title, filename=None)[source]¶ The circuit class.
Parameters:
- title : string
- The circuit title.
filename : string, optional
Deprecated since version 0.09.
If the circuit instance corresponds to a netlist file on disk, set this to the netlist filename.
-
add_capacitor
(part_id, n1, n2, value, ic=None)[source]¶ Adds a capacitor to the circuit.
The capacitor instance is added to the circuit elements and connected to the provided nodes. If the nodes are not found in the circuit, they are created and added as well.
Parameters:
- part_id : string
- The capacitor part_id (eg “C1”). The first letter is always C.
- n1, n2 : string
- The nodes to which the element is connected.
- value : float
- The capacitance value.
- ic : float, optional
- The initial condition, if any. See the simulation docs for how this affects the results.
-
add_cccs
(part_id, n1, n2, source_id, value)[source]¶ Adds a current-controlled current source (CCCS) to the circuit
This method takes care that its nodes are added as well.
Parameters:
- part_id : string
- The cccs ID (eg
'F1'
). The first letter is always'F'
. - n1, n2 : strings
- The output port nodes, where the output current is forced. Eg. “outp”, “outm” or “out_a”, “out_b”.
- source_id : string
- The voltage source to be used to sense the current that drives
the output. Eg.
'V1'
. - value : float
The proportionality factor between input (\(I_s\)) and output (\(I_o\)) currents. Mathematically:
\[I_o = \alpha I_s\]
See also
ahkab.components.sources.FISource
-
add_ccvs
(part_id, n1, n2, source_id, value)[source]¶ Adds a current-controlled voltage source (CCCS) to the circuit
This method takes care that its nodes are added as well.
Parameters:
- part_id : string
- The cccs ID (eg
'H1'
). The first letter is always'H'
. - n1, n2 : strings
- The output port nodes, where the output current is forced. Eg. “outp”, “outm” or “out_a”, “out_b”.
- source_id : string
- The voltage source to be used to sense the current that drives
the output voltage. Eg.
'V1'
. - value : float
The proportionality factor between the sense current \(I_s\) flowing into the
source_id
voltage source (input) and output voltage. Mathematically:\[Vn_1 - Vn_2 = \alpha I_s\]
See also
ahkab.components.sources.EVSource
,ahkab.components.sources.FISource
-
add_diode
(part_id, n1, n2, model_label, models=None, Area=None, T=None, ic=None, off=False)[source]¶ Adds a diode to the circuit (also takes care that the nodes are added as well).
Parameters:
- part_id : string
- The diode ID (eg “D1”). The first letter is always D.
- n1, n2 : string
- the nodes to which the element is connected. eg.
"in"
or"out_a"
- model_label : string
- The diode model identifier. The model needs to be added first, then the elements using it.
- models : dict, optional
- List of available model instances. If not set or
None
, the circuit models will be used (recommended). - Area : float, optional
- Scaled device area (optional, defaults to 1.0)
- T : float, optional
- Operating temperature (no temperature dependence yet)
- ic : float, optional
- Initial condition (not really implemented yet)
- off : bool, optional
- Consider the diode to be initially off.
-
add_inductor
(part_id, n1, n2, value, ic=None)[source]¶ Adds an inductor to the circuit.
The inductor instance is added to the circuit elements and connected to the provided nodes. If the nodes are not found in the circuit, they are created and added as well.
Parameters:
- part_id : string
- The inductor part_id (eg “Lfilter”). The first letter is always L.
- n1, n2 : string
- The nodes to which the element is connected. Eg.
"in"
or"out_a"
. - value : float
- The inductance value.
- ic : float, optional
- Initial condition, see simulation types for how this affects the results.
-
add_inductor_coupling
(part_id, L1, L2, value)[source]¶ Add a coupling between two inductors.
Parameters:
- part_id : string
- The part ID for the inductor coupling device. Eg.
'K1'
, the first letter is always'K'
. - L1 : string
- The part ID of the first inductor to be coupled.
- L2 : string
- The part ID of the second inductor to be coupled.
- value : float
- The
k
value of the mutual coupling coefficient. Its value must be greater than zero and lesser or equal to``1`` or instability ensues.
-
add_isource
(part_id, n1, n2, dc_value, ac_value=0, function=None)[source]¶ Adds a current source to the circuit (also takes care that the nodes are added as well).
Parameters:
- part_id : string
- The current source ID (eg
"IA"
or"I3"
). The first letter is always I. - n1, n2 : string
- The nodes to which the element is connected, eg.
"in"
or"out1"
. - dc_value : float
- DC current value.
- ac_value :float, optional
- AC current value, defaults to 0.
- function : function, optional
- Time function. See devices.py for built-in options.
-
add_model
(model_type, model_label, model_parameters)[source]¶ Add a model to the available circuit models.
Parameters:
- model_type : string
- the model type (eg “ekv”). Right now, the possible values are:
"mosq"
,"ekv"
,"diode"
,"sw"
. - model_label : string
- a unique identifier for the model being added (eg.
"nch1"
). - model_parameters: dict
- a dictionary holding the parameters to be supplied to the model to instantiate it.
-
add_mos
(part_id, nd, ng, ns, nb, w, l, model_label, models=None, m=1, n=1)[source]¶ Adds a mosfet to the circuit (also takes care that the nodes are added as well).
Parameters:
- part_id : string
- The mos part_id (eg “M1”). The first letter is always M.
- nd : string
- The drain node.
- ng : string
- The gate node.
- ns : string
- The source node.
- nb : string
- The bulk node.
- w : float
- The gate width.
- l : float
- The gate length.
- model_label : string
- The model identifier.
- models : dict, optional
- The circuit models.
- m : int, optional
- Shunt multiplier value. Defaults to 1.
- n : int, optional
- Series multiplier value, not always supported. Defaults to 1.
-
add_node
(ext_name)[source]¶ Adds the supplied node to the circuit, if needed.
When a ‘normal’ (not the reference) node is added, a internal name (or label) is assigned to it.
The nodes labels are stored in
Circuit.nodes_dict
, as a dictionary of pairs like{int_node:ext_node}
.Those internal names are integers, by definition, and are generated starting from 1, then 2, 3, 4, 5... The integer
0
is reserved for the reference node (gnd), which is required for the circuit to be non-pathological and hasext_name=str(int_name)='0'
.Notice that this method doesn’t halt or print errors if the node is already been added previsiously. It simply returns the internal node name assigned to it.
Parameters:
- ext_name : string
- The unique identifier of the node.
Returns:
- int_name : string
- the unique internal ciecuit identifier of the node.
Raises: TypeError – if the parameter ext_name
is not of “text” type (what that means exactly depends on which version of Python you are using.)
-
add_resistor
(part_id, n1, n2, value)[source]¶ Adds a resistor to the circuit.
The resistor instance is added to the circuit elements and connected to the provided nodes. If the nodes are not found in the circuit, they are created and added as well.
Parameters:
- part_id : string
- the resistor part_id (eg “R1”). The first letter is replaced by an R
- n1, n2 : string
- the nodes to which the resistor is connected.
- value : float,
- The resistance between
n1
andn2
in Ohm.
-
add_switch
(part_id, n1, n2, sn1, sn2, ic, model_label, models=None)[source]¶ Adds a voltage-controlled or current-controlled switch to the circuit
This method also takes care that its nodes are added to the circuit as well, if necessary.
Notice:
- Current-controlled switches are not yet implemented. If you try to add one, you’ll trigger an error. If you got a bit of time to spare, patches are welcome.
- The switches
part_id
should begin with'S'
for voltage-controlled switches and with'W'
for current-controlled switches. - The actual behavior is set by the model. Make sure you supply a voltage-controlled switch model for a voltage-controlled switch and the appropriate type of model for the current-controlled switch. Mixing them up will go undetected.
Parameters:
- part_id : string
- the switch ID (eg
"S1"
- voltage-controlled - or"Wa"
- current-controlled). The first letter is alwaysS
orW
. - n1, n2 : string
- the output port nodes, where the switch is connected. Eg.
"out1"
,"out2"
or"n_a"
,"n_b"
. - sn1, sn2 : string
- The input port nodes, where the input voltage is read. Eg. “inp”, “inm” or “in_a”, “in_b”.
- ic : boolean
- The initial conditions for transient simulation. Not currently implemented!
- model_label : string
- The switch model identifier. The model needs to be added first, then the elements using it.
- models : dict, optional
- A dictionary assembled as (identifier:instance), containing all the available model
instances. If not set or
None
, the circuit models will be used (recommended).
-
add_user_defined
(module, label, param_dict)[source]¶ Adds a user defined element.
In order for this to work, you should write a module that supplies the elem class.
XXX WRITE DOC
-
add_vccs
(part_id, n1, n2, sn1, sn2, value)[source]¶ Adds a voltage-controlled current source (VCCS) to the circuit
This method also takes care that its nodes are added as well.
Parameters:
- part_id : string
- The VCCS ID (eg
"G1"
). The first letter is always'G'
. - n1, n2 : string
- The output port nodes, where the output current is
forced. Eg. “outp”, “outm” or “out_a”, “out_b”.
The passive convention is used as everywhere else in the simulator:
a positive current flows into
n1
and out ofn2
. - sn1, sn2 : string
- The input port nodes, where the input voltage is sensed. Eg. “inp”, “inm” or “in_a”, “in_b”.
- value : float
The proportionality factor between input and output voltages, which are related by the equality:
\[I_o = alpha * \left[V(inp) - V(inn)\right]\]
-
add_vcvs
(part_id, n1, n2, sn1, sn2, value)[source]¶ Adds a voltage-controlled voltage source (vcvs) to the circuit
This method also takes care that its nodes are added as well.
Parameters:
- part_id : string
- The vcvs ID (eg “E1”). The first letter is always E.
- n1, n2 : string
- The output port nodes, where the output voltage is forced. Eg. “outp”, “outm” or “out_a”, “out_b”.
- sn1, sn2 : string
- The input port nodes, where the input voltage is read. Eg. “inp”, “inm” or “in_a”, “in_b”.
- alpha : float
The proportionality factor between input and output voltages is given by the relationship:
\[V(out_p) - V(out_n) = \alpha \cdot (V(in_p) - V(in_n))\]
-
add_vsource
(part_id, n1, n2, dc_value, ac_value=0, function=None)[source]¶ Adds a voltage source to the circuit (also takes care that the nodes are added as well).
Parameters:
- part_id : string
- The voltage source part_id (eg “VA”). The first letter is always V.
- n1, n2 : string
- The nodes to which the element is connected. Eg.
"in"
or"out_a"
. - dc_value : float
- DC voltage value
- ac_value : float, optional
- AC voltage value, defaults to 0.
- function : function, optional
- Time function. See devices.py for built-in options.
-
create_node
(name)[source]¶ Creates a new circuit node
If there is a node in the circuit with the same name, ValueError is raised.
Parameters:
- name : string
- the _unique_ identifier of the node.
Returns:
- node : string
- the _unique_ identifier of the node, to be used for subsequent element declarations, for example.
Raises: - ValueError – if a new node with the given id cannot be created,
for example because a node with the same name already exists in the
circuit. The only exception is the ground node, which has the
reserved id
'0'
, and for which this method won’t raise any exception. - TypeError – if the parameter
name
is not of “text” type (what that means exactly depends on which version of Python you are using.)
-
ext_node_to_int
(ext_node)[source]¶ This function returns the integer id associated with an external node id.
Parameters:
- ext_node : string
- The external node id to be converted.
Returns:
- int_node : int
- The internal node associated.
-
find_vde
(index)[source]¶ Finds a voltage-defined element from its MNA KVL index
Parameters:
- index : int
- The element index in the KVL equations.
Returns:
- e : circuit element (an instance of a subclass of Component)
- The element corresponding to
index
.
Raises: IndexError – if no element corresponds to such an index.
-
find_vde_index
(elem_or_id, verbose=3)[source]¶ Finds a voltage-defined element MNA index.
Parameters:
- elem_or_id : string or circuit element
- You may pass as first element, alternatively, either the
part_id
of the element whose index is being requested (eg. ‘V1’) or the element itself. Notice thepart_id
includes both the id letter (eg. ‘V’) and the description (eg. ‘1’). - verbose : int
- The verbosity level, from 0 (silent) to 6 (debug).
Returns:
- indx : int
- The index.
Raises: ValueError – if no such element is in the circuit.
-
get_elem_by_name
(part_id)[source]¶ Get a circuit element from its
part_id
value.If no matching element is found, the method returns
None
. This may change in the future.Parameters:
- part_id : string
- The
part_id
of the element
Returns:
- elem : circuit element
- Depending whether a matching element was found or not.
Raises: ValueError – if the element is not found.
-
get_locked_nodes
()[source]¶ Get all nodes connected to non-linear elements.
This list is meant to be passed to
dc_solve
ormdn_solver
to be used inget_td
to evaluate the damping coefficient in a Newton-Rhapson iteration.Returns:
- locked_nodes : list
- A list of internal nodes.
-
has_duplicate_elem
()[source]¶ Self-check for duplicate elements.
No circuit should ever have duplicate elements (ie elements with the same
part_id
).Returns:
- chk : boolean
- The result of the check.
-
int_node_to_ext
(int_node)[source]¶ This function returns the string id associated with the integer internal node id
int_node
.Parameters:
- int_node : int
- The internal node id to be converted.
Returns:
- ext_node : string
- the string id associated with
int_node
.
-
is_int_node_internal_only
(int_node)[source]¶ Check whether an internal node is an “internal only node” or not.
Parameters:
- int_node : int
- The internal only node to be checked.
Returns:
- chk : boolean
- The result of the check.
Raises: TypeError – if the supplied node is not an int
. Typically this happens when the method is called with an external name.
-
is_nonlinear
()[source]¶ Check whether the circuit is non-linear or not.
Returns:
- chk : boolean
- The result of the check.
-
new_internal_node
()[source]¶ Generate implicit internal nodes.
Some devices are made of a group of other devices, connected by “internal only” nodes, which have the prefix
'INT'
and the simulator treats specially, hiding them from the user if not explicitly asked about them.This method generates the external names for such nodes and inserts them in the circuit.
Returns:
- ext_node : string
- The corresponding external node id.
-
remove_elem
(elem_or_id)[source]¶ Removes an element from the circuit and takes care that no “orphan” nodes are left.
Note
Support for removing elements is experimental.
Parameters:
- elem_or_id : string or circuit element
- You may pass as first element, alternatively, either the
part_id
of the element to be removed or the element itself.
The method will also take care of purging from the circuit nodes that are left orphan, ie with no elements connected.
Raises: ValueError – if no such element is found in the circuit.
-
is_elem_voltage_defined
(elem)[source]¶ Check if an element needs its own KCL equation
Parameters:
- elem : Component
- The element to be checked.
Returns:
- chk : bool
True
ifelem
is a voltage source, an inductor, a voltage-controlled voltage source or a current-controlled voltage source.False
otherwise.
-
class
subckt
(name, code, connected_nodes_list)[source]¶ This class holds the necessary information about a circuit.
An instance of this class is returned by:
ahkab.netlist_parser.parse_sub_declaration()
Parameters:
- name : string
- The subcircuit definition label.
- code : string
- The netlist code that can be instantiated have a circuit instance.
- connected_nodes_list : list
- A list of nodes that are used in the circuit and that are meant to be connected to the external circuit.
Notice that in the current implementation, the GND node (0) is always global.