Re: [ng-spice-devel] Some questions about circuit simulation
---"Paolo" == Paolo Nenzi <pnenzi@ieee.ing.uniroma1.it> writes:
Paolo> There are "direct" methods and "iterative" ones. What are the
Paolo> differences between the two and what are the peculiarities and
Paolo> drawbacks ? Are there alternative solutions to the tho classes
Paolo> of methods stated above ?
Sorry if I'm being too basic or too long-winded in my explanation,
but...
These terms refer to the matrix solution; of course spice uses Newton
iterations for the nonlinear solution.
So, in solving linear systems, direct methods calculate the solution
more-or-less directly; iterative methods use some iterative process to
get successively closer solutions. We are solving Ax=b, where "A" is
the Jacobian matrix, G+wC, where "w" is the leading term of the
implicit integrator in the time domain, or j*omega in the frequency
domain. C can be singular, while G+wC is typically almost
structurally symmetric, not positive definite, but could be nearly
singular depending on the values in G and C.
Of the direct methods, some variation on LU decomposition is generally
used (Crout or Doolittle), where the original system, Ax=b, is
decomposed into LUx=b where L is lower-triangular and U is upper
triangular. The solution is then a simple two step process: solve Lz=b
to get z, which is an easy forward-substitution process because L is
lower-triangular, then Ux=z is solved for x, which is an easy backward
substitution process.
Direct method solutions can be done "in place" and store the
decomposed matrix in the same space as the original matrix, which
saves memory. Also, the LU factors can be re-used on successive
right-hand side vectors, which is a plus for things like sensitivity
analysis.
Direct methods work well most of the time. Two error mechanisms exist,
through roundoff and ill-conditioning. Roundoff can be mitigated
through reordering the equations to maximize the pivot terms in the LU
decomposition. Of course, since we're talking about sparse matrices, a
bad reordering could fill in the matrix with decomposition terms which
would make things very slow, so there is a tradeoff between accuracy
and speed.
Ill-conditioning, on the other hand, is intrinsic to the equations. A
poorly conditioned matrix has a large condition number. Condition
number is defined by kappa = norm(A)*norm(A^(-1)). The matrix
approaches being singular as kappa approaches infinity. An
ill-conditioned matrix is sensitive, such that small differences in
the b vector can produce large differences in the answer. To mitigate
ill-conditioning, it is best to look at the equations being generated
and see if they can be written differently, perhaps in terms of other
quantities.
For direct method solutions, there has been a lot of work on different
methods for different problems, optimization of the solution with
respect to cache performance, optimal storage schemes, reordering
schemes, etc. etc. Most of this work, with respect to circuit
simulation, is not available, as it was done at Bell Labs, etc. I
don't know of a really good sparse matrix package for circuit
simulation that is readily available. If someone knows of one, I would
be very interested.
Iterative methods are interesting for a number of reasons, especially
for large problems. The basic idea is to solve Ax=b through a process
of guessing a series of x vectors, such that r=b-Ax is minimized. The
hope is that the work per iteration is much less than the LU
decomposition of the matrix, so that if only a few iterations are
required, the iterative method will be faster. The convergence rate of
many iterative methods depends on the condition number of the matrix.
To converge well, one typically needs a "good" preconditioner matrix,
Q, such that Q^(-1)Ax=Q^(-1)b is better conditioned than the original
problem.
For very large problems, iterative methods are interesting because
many of these methods do not require the matrix be stored -- they only
require the result of a matrix-vector product, which can be
accumulated without actually forming the matrix.
For circuit simulation, I don't know of anyone using iterative methods
for transient analysis, unless perhaps TI is after some work 10 years
ago by Ping Yang. Circuit simulation matrices need preconditioners
which will change over time; forming a preconditioner can be
expensive, so as simple a preconditioner as possible should be
used. But for most circuits, solving the matrix is typicically 20% or
less of the transient time, which hardly makes a lot of work on an
iterative method worth the effort. Of course, if the rest of your
simulator is already parallel, then it gets more interesting.
For DC operating point solutions, it would be very difficult to
successfully use an interative method. DC matrices are very badly
condidtioned, especially during the first few iterations, and the
preconditioner would need to change dramatically on each iteration,
which would cause more work to be done. Ugly problem.
Harmonic balance, on the other hand, generates matrices which are N
times larger than system matrix, where N is the number of harmonics,
and getting a good preconditioner is not that difficult. So any
practical harmonic balance implementation (or time-domain steady-state
method, for that matter) will use an iterative method.
One thing I've wanted to try, but haven't, is iterative refinement.
First one does the direct solution to get an answer, then a few
iterations of iterative refinement to "clean up" the solution,
assuming that roundoff and/or ill-conditioning has influenced the
initial solution. This might help with a few really nasty cases we've
seen. Unfortunately, using this requires saving a copy of the original
matrix, which negates the memory advantage of in-place decomposition.
Sorry, that was probably much more than you wanted to know. :)
--Steve
Partial thread listing: