Nodal Analyses Reference
========================
Introduction
------------
In the following discussion we assume that :math:`x` is the vector of
nodal variables. We denote matrices and frequency-domain quantities
with uppercase letters.
This section documents the formulation used for nodal-based
analyses. For all analyses there are four types of devices to
consider:
Linear VCCS/QS
Contribute the :math:`G` and :math:`C` matrices,
respectively. Elements provide the following attributes to build
these matrices: ``linearVCCS`` and ``linearVCQS``.
Nonlinear VCCS/QS
Contribute :math:`i(v, v_T)` and :math:`q(v, v_T)` vector
functions. Here :math:`v` is a vector with controlling port
voltages and :math:`v_T` is a vector with time-delayed control
voltages. For the :math:`j^{th}` nonlinear device, vector
:math:`[i_j , q_j]^T` and its Jacobian are returned by
``eval_and_deriv()``. The Jacobian is returned in a single matrix
with the following format:
.. math::
\left[ \begin{array}{cc} di_j/dv & di_j/dv_T \\
dq_j/dv & dq_j/dv_T
\end{array} \right]
In nodal analyses, controlling port voltages (:math:`v`) are
obtained as differences between elements of the nodal variables
vector (:math:`x`). In compact form this can be denoted as:
.. math::
v = T_{cv} x \; ,
where :math:`T_{cv}` is an incidence matrix. All nonzero entries
in :math:`T_{dv}` are either equal to 1 or -1 and there are at
most two nonzero entries per row. This matrix is implicitly stored
in the simulator with the control port definitions in each
element. Samples of time-delayed control voltages can be
calculated in a similar way using a :math:`T_{dv}` incident matrix
but the effect of time delays depends on the analysis type.
Vector functions :math:`i(v, v_T)` and :math:`q(v, v_T)` are
mapped into the nodal equations using incidence matrices
:math:`T_i` and :math:`T_q`, which have the same properties as
the transpose of :math:`T_{cv}`.
Frequency-defined devices
Contribute the complex, frequency-dependent :math:`Y(f)`
matrix. The corresponding impulse-response matrix is denoted
:math:`Y(t)`. The following methods are used to build this
matrix: ``get_Y_matrix()`` for :math:`f \neq 0` and
``get_G_matrix()`` for :math:`f = 0`. More details will be
provided when time-domain support for this kind of device is
implemented.
Sources
Contribute a source vector. There are 3 types of source: DC
(:math:`s_{DC}`), time-domain (:math:`s(t)`) and frequency-domain
(:math:`S(f)`). The following element methods are used:
``get_DCsource()``, ``get_TDsource()``, ``get_FDsource()`` and
``get_AC()``.
OP/DC Equations
---------------
For DC analysis, time-delayed control voltages are calculated as
regular control voltages; :math:`C` and :math:`q(v, v_T)` are ignored
and only the DC component of sources (:math:`s_{DC}`) and the DC
conductance matrix of frequency-defined elements (:math:`G_0`) are
considered.
The analysis solves the following nonlinear equation iteratively
using Newton's method:
.. math::
(G + G_0) x + T_i i(T_{cv} x, T_{dv} x) = s_{DC} \; .
Let :math:`G_1 = G + G_0`. The iteration is defined by linearizing
:math:`i(T_{cv} x, T_{dv} x)` as follows:
.. math::
G_1 x^{k+1} + i^k + J^k_i \, (x^{k+1} - x^k) = s_{DC} \; ,
where the :math:`k` superscript indicates the iteration number and
.. math::
i^k = T_i i \left(T_{cv} x^k, T_{dv} x^k \right)
J^k_i = \left(
\frac{di^k}{dv} T_{cv} + \frac{di^k}{dv_T} T_{dv}
\right) \; .
The :math:`x^k` vector is assumed to be known for each iteration and
:math:`x^{k+1}` is the unknown to solve for. The initial guess
(:math:`x_0`) is set to the values suggested by the nonlinear devices,
if any, or otherwise to zero. The previous equation can be re-arranged
as as the following system of linear equations:
.. math::
(G_1 + J^k_i) \, \Delta x^{k+1} =
s_{DC} - G_1 x^k - i^k \; ,
with :math:`\Delta x^{k+1} = x^{k+1} - x^k`. This equation can be
seen as the nodal equation of a linearized circuit obtained by
substituting all devices by transconductances in parallel with current
sources that are dependent of the current approximation for the nodal
voltages (:math:`x^k`).
The condition to stop Newton iterations is:
.. math::
| \Delta x^{k+1}_j | <
\mbox{reltol} \; \max(|x^{k+1}_j|, |x^k_j|) + \mbox{abstol}
for each nodal variable (:math:`j`). In addition, if ``errfunc`` is
set to ``True``, nodal equations are also checked:
.. math::
|(G + G_0) x^{k+1} + i^{k+1} - s_{DC}| < \mbox{abstol} \; ,
and iterations stop when both conditions are satisfied. Normally the
first condition is enough to obtain an acceptable solution and that is
why by default the second check is not enabled to save the CPU time
required to re-evaluate the nodal equations.
AC Formulation
--------------
Here :math:`X(f)` is the nodal vector in frequency domain. A DC
operating point analysis is performed first to obtain the incremental
conductances and capacitances given by :math:`di/dx` and
:math:`dq/dx`, respectively. The analysis solves for :math:`X(f)` for
all requested frequencies using the following equation:
.. math::
\left[ (G + J_i + j 2 \pi f (C + J_q)
+ Y(f) \right] \, X(f) = S(f)
The :math:`J_i` and :math:`J_q` Jacobian matrices are calculated as
follows:
.. math::
J_i = T_i \left(
\frac{di}{dv} T_{cv} + \frac{di}{dv_T} E_{\tau} T_{dv}
\right) \; ,
J_q = T_q \left(
\frac{dq}{dv} T_{cv} + \frac{dq}{dv_T} E_{\tau} T_{dv}
\right) \; ,
where :math:`E_{\tau}` is a diagonal matrix that includes the effect
of time delays in each control port:
.. math::
E_{\tau} = \mbox{diag}\left( [\exp(-j \omega \tau_1),
\exp(-j \omega \tau_2), \dots , \exp(-j \omega \tau_m)]
\right)
Transient Analysis Equations
----------------------------
Transient analysis solves the following nonlinear
algebraic-integral-differential equation given an initial condition,
:math:`x(0) = x_0`:
.. math::
G x + C \dot{x} + T_i i(T_{cv} x, d(T_{dv} x)) +
T_q \dot{q}(T_{cv} x, d(T_{dv} x)) +
\int_{0}^\infty Y(\tau) x(t - \tau) d\tau
= s_{DC} + s(t) \; ,
where dotted quantities indicate derivative with respect to time and
:math:`d()` is a vector function that applies a (possibly different)
time delay to each control voltage. The delay function (:math:`d()`)
is implemented by storing all time-delayed control port voltages and
using an interpolation function to find the voltage at the desired
time in the past.
The initial condition (:math:`x(0)`) is usually obtained by
calculating the operating point of the circuit using the OP analysis.
An integration method such as Backward Euler (BE) or trapezoidal rule
is applied to transform the differential equation into a difference
equation by discretizing time and approximating derivatives with
respect to time. Here we assume the time step (:math:`h`) is constant.
For example, using the BE rule:
.. math::
\dot{q}(t_n) = \dot{q}_n \approx \frac{q_n - q_{n-1}}{h} \; ,
here, the subscript :math:`n` denotes the time sample number. For
implicit methods in general,
.. math::
\dot{q_n} \approx a_0 q_n - f_{n-1}(q) \; ,
with :math:`f_{n-1}(x)` being a function that depends on the previous
samples of :math:`q`:
.. math::
f_{n-1}(q) = a_1 q_{n-1} + a_2 q_{n-2} + \dots \; .
The :math:`a_i; i=0,1,\dots` coefficients depend on the time step size
and the integration method. Substituting dotted variables and
discretizing the convolution operation the resulting circuit equation
is the following:
.. math::
G' x_n + i'(x_n) = s' \; ,
with
.. math::
G' = G + Y_0 + a_0 C
i'(x_n) = T_i i(T_{cv} x_n, d(T_{dv} x_n)) +
a_0 T_q q(T_{cv} x_n, d(T_{dv} x_n))
s' = s_n - \sum_{m=1}^\infty \textbf{Y}_m x_{n-m}
+ f_{n-1}(C x + T_q q) \; ,
where :math:`Y_m = Y(t_m)` and :math:`Y_0 = Y(0)`. Note that
:math:`s'` is a known vector at the :math:`n^{th}` time step. This is
the equation of a DC circuit with a conductance matrix equal to
:math:`G'`, a set of nonlinear currents given by the :math:`i'(x_n)`
function and a source vector given by :math:`s'`. The unknown
(:math:`x_n`) is iteratively solved using Newton's Method (similarly
as in OP/DC analysis). Iterations are defined by linearizing
:math:`i'(x)` as follows:
.. math::
G' x^{k+1}_n + i'(x^k_n) + J^k_n \Delta x^{k+1}_n
= s' \; ,
where the :math:`k` subscript denotes the Newton iteration number,
:math:`\Delta x^{k+1}_n = x^{k+1}_n - x^k_n` and :math:`J^k_n =
di'(x^k_n)/dx`. This equation is re-arranged as follows:
.. math::
( G' + J^k_n ) \Delta x^{k+1}_n =
s' - G' x^k_n - i'(x^k_n) \; ,
as the right-hand side of this equation is known at the :math:`k^{th}`
iteration, :math:`x^{k+1}_n` can be found by solving a linear system
of equations.
The criterion to stop iterations is the same as in the DC analysis.