⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sputils.c

📁 spice中支持多层次元件模型仿真的可单独运行的插件源码
💻 C
📖 第 1 页 / 共 5 页
字号:
/* *  MATRIX UTILITY MODULE * *  Author:                     Advising professor: *      Kenneth S. Kundert          Alberto Sangiovanni-Vincentelli *      UC Berkeley * *  This file contains various optional utility routines. * *  >>> User accessible functions contained in this file: *  spMNA_Preorder *  spScale *  spMultiply *  spMultTransposed *  spDeterminant *  spStripFills *  spDeleteRowAndCol *  spPseudoCondition *  spCondition *  spNorm *  spLargestElement *  spRoundoff *  spErrorMessage * *  >>> Other functions contained in this file: *  CountTwins *  SwapCols *  ScaleComplexMatrix *  ComplexMatrixMultiply *  ComplexCondition *//* *  Revision and copyright information. * *  Copyright (c) 1985,86,87,88,89,90 *  by Kenneth S. Kundert and the University of California. * *  Permission to use, copy, modify, and distribute this software and *  its documentation for any purpose and without fee is hereby granted, *  provided that the copyright notices appear in all copies and *  supporting documentation and that the authors and the University of *  California are properly credited.  The authors and the University of *  California make no representations as to the suitability of this *  software for any purpose.  It is provided `as is', without express *  or implied warranty. */#ifdef notdefstatic char copyright[] =    "Sparse1.3: Copyright (c) 1985,86,87,88,89,90 by Kenneth S. Kundert";static char RCSid[] =    "@(#)$Header: spUtils.c,v 1.3 88/06/24 05:03:37 kundert Exp $";#endif/* *  IMPORTS * *  >>> Import descriptions: *  spConfig.h *      Macros that customize the sparse matrix routines. *  spMatrix.h *      Macros and declarations to be imported by the user. *  spDefs.h *      Matrix type and macro definitions for the sparse matrix routines. */#define spINSIDE_SPARSE#include "spconfig.h"#include "spmatrix.h"#include "spdefs.h"/* *  Function declarations */#ifdef __STDC__static int CountTwins( MatrixPtr, int, ElementPtr*, ElementPtr* );static void SwapCols( MatrixPtr, ElementPtr, ElementPtr );static void ScaleComplexMatrix( MatrixPtr, RealVector, RealVector );#if spSEPARATED_COMPLEX_VECTORSstatic void ComplexMatrixMultiply( MatrixPtr, RealVector, RealVector,                                              RealVector, RealVector );static void ComplexTransposedMatrixMultiply( MatrixPtr, RealVector, RealVector,                                                        RealVector, RealVector);#elsestatic void ComplexMatrixMultiply( MatrixPtr, RealVector, RealVector );static void ComplexTransposedMatrixMultiply(MatrixPtr, RealVector, RealVector);#endifstatic RealNumber ComplexCondition( MatrixPtr, RealNumber, int* );#else /* __STDC__ */static int CountTwins();static void SwapCols();static void ScaleComplexMatrix();static void ComplexMatrixMultiply();static void ComplexTransposedMatrixMultiply();static RealNumber ComplexCondition();#endif /* __STDC__ */#if MODIFIED_NODAL/* *  PREORDER MODIFIED NODE ADMITTANCE MATRIX TO REMOVE ZEROS FROM DIAGONAL * *  This routine massages modified node admittance matrices to remove *  zeros from the diagonal.  It takes advantage of the fact that the *  row and column associated with a zero diagonal usually have *  structural ones placed symmetricly.  This routine should be used *  only on modified node admittance matrices and should be executed *  after the matrix has been built but before the factorization *  begins.  It should be executed for the initial factorization only *  and should be executed before the rows have been linked.  Thus it *  should be run before using spScale(), spMultiply(), *  spDeleteRowAndCol(), or spNorm(). * *  This routine exploits the fact that the structural ones are placed *  in the matrix in symmetric twins.  For example, the stamps for *  grounded and a floating voltage sources are *  grounded:              floating: *  [  x   x   1 ]         [  x   x   1 ] *  [  x   x     ]         [  x   x  -1 ] *  [  1         ]         [  1  -1     ] *  Notice for the grounded source, there is one set of twins, and for *  the floating, there are two sets.  We remove the zero from the diagonal *  by swapping the rows associated with a set of twins.  For example: *  grounded:              floating 1:            floating 2: *  [  1         ]         [  1  -1     ]         [  x   x   1 ] *  [  x   x     ]         [  x   x  -1 ]         [  1  -1     ] *  [  x   x   1 ]         [  x   x   1 ]         [  x   x  -1 ] * *  It is important to deal with any zero diagonals that only have one *  set of twins before dealing with those that have more than one because *  swapping row destroys the symmetry of any twins in the rows being *  swapped, which may limit future moves.  Consider *  [  x   x   1     ] *  [  x   x  -1   1 ] *  [  1  -1         ] *  [      1         ] *  There is one set of twins for diagonal 4 and two for diagonal 3. *  Dealing with diagonal 4 first requires swapping rows 2 and 4. *  [  x   x   1     ] *  [      1         ] *  [  1  -1         ] *  [  x   x  -1   1 ] *  We can now deal with diagonal 3 by swapping rows 1 and 3. *  [  1  -1         ] *  [      1         ] *  [  x   x   1     ] *  [  x   x  -1   1 ] *  And we are done, there are no zeros left on the diagonal.  However, if *  we originally dealt with diagonal 3 first, we could swap rows 2 and 3 *  [  x   x   1     ] *  [  1  -1         ] *  [  x   x  -1   1 ] *  [      1         ] *  Diagonal 4 no longer has a symmetric twin and we cannot continue. * *  So we always take care of lone twins first.  When none remain, we *  choose arbitrarily a set of twins for a diagonal with more than one set *  and swap the rows corresponding to that twin.  We then deal with any *  lone twins that were created and repeat the procedure until no *  zero diagonals with symmetric twins remain. * *  In this particular implementation, columns are swapped rather than rows. *  The algorithm used in this function was developed by Ken Kundert and *  Tom Quarles. * *  >>> Arguments: *  eMatrix  <input>  (char *) *      Pointer to the matrix to be preordered. * *  >>> Local variables; *  J  (int) *      Column with zero diagonal being currently considered. *  pTwin1  (ElementPtr) *      Pointer to the twin found in the column belonging to the zero diagonal. *  pTwin2  (ElementPtr) *      Pointer to the twin found in the row belonging to the zero diagonal. *      belonging to the zero diagonal. *  AnotherPassNeeded  (BOOLEAN) *      Flag indicating that at least one zero diagonal with symmetric twins *      remain. *  StartAt  (int) *      Column number of first zero diagonal with symmetric twins. *  Swapped  (BOOLEAN) *      Flag indicating that columns were swapped on this pass. *  Twins  (int) *      Number of symmetric twins corresponding to current zero diagonal. */voidspMNA_Preorder( eMatrix )char *eMatrix;{MatrixPtr  Matrix = (MatrixPtr)eMatrix;register  int  J, Size;ElementPtr  pTwin1, pTwin2;int  Twins, StartAt = 1;BOOLEAN  Swapped, AnotherPassNeeded;/* Begin `spMNA_Preorder'. */    ASSERT( IS_VALID(Matrix) AND NOT Matrix->Factored );    if (Matrix->RowsLinked) return;    Size = Matrix->Size;    Matrix->Reordered = YES;    do    {   AnotherPassNeeded = Swapped = NO;/* Search for zero diagonals with lone twins. */        for (J = StartAt; J <= Size; J++)        {   if (Matrix->Diag[J] == NULL)            {   Twins = CountTwins( Matrix, J, &pTwin1, &pTwin2 );                if (Twins == 1)                {   /* Lone twins found, swap rows. */                    SwapCols( Matrix, pTwin1, pTwin2 );                    Swapped = YES;                }                else if ((Twins > 1) AND NOT AnotherPassNeeded)                {   AnotherPassNeeded = YES;                    StartAt = J;                }            }        }/* All lone twins are gone, look for zero diagonals with multiple twins. */        if (AnotherPassNeeded)        {   for (J = StartAt; NOT Swapped AND (J <= Size); J++)            {   if (Matrix->Diag[J] == NULL)                {   Twins = CountTwins( Matrix, J, &pTwin1, &pTwin2 );                    SwapCols( Matrix, pTwin1, pTwin2 );                    Swapped = YES;                }            }        }    } while (AnotherPassNeeded);    return;}/* *  COUNT TWINS * *  This function counts the number of symmetric twins associated with *  a zero diagonal and returns one set of twins if any exist.  The *  count is terminated early at two. */static intCountTwins( Matrix, Col, ppTwin1, ppTwin2 )MatrixPtr Matrix;int Col;ElementPtr *ppTwin1, *ppTwin2;{int Row, Twins = 0;ElementPtr pTwin1, pTwin2;/* Begin `CountTwins'. */    pTwin1 = Matrix->FirstInCol[Col];    while (pTwin1 != NULL)    {   if (ABS(pTwin1->Real) == 1.0)        {   Row = pTwin1->Row;            pTwin2 = Matrix->FirstInCol[Row];            while ((pTwin2 != NULL) AND (pTwin2->Row != Col))                pTwin2 = pTwin2->NextInCol;            if ((pTwin2 != NULL) AND (ABS(pTwin2->Real) == 1.0))            {   /* Found symmetric twins. */                if (++Twins >= 2) return Twins;#ifdef notdef                (*ppTwin1 = pTwin1)/*->Col = Col XXX */;                (*ppTwin2 = pTwin2)/*->Col = Row XXX */;#else                (*ppTwin1 = pTwin1)->Col = Col;                (*ppTwin2 = pTwin2)->Col = Row;#endif            }        }        pTwin1 = pTwin1->NextInCol;    }    return Twins;}/* *  SWAP COLUMNS * *  This function swaps two columns and is applicable before the rows are *  linked. */static voidSwapCols( Matrix, pTwin1, pTwin2 )MatrixPtr Matrix;ElementPtr pTwin1, pTwin2;{int Col1 = pTwin1->Col, Col2 = pTwin2->Col;/* Begin `SwapCols'. */#ifdef notdefElementPtr e; /*XXX*/    /* XXX Update column numbers */    for (e = Matrix->FirstInCol[Col1]; e != NULL; e = e->NextInCol)	e->Col = Col2;    for (e = Matrix->FirstInCol[Col2]; e != NULL; e = e->NextInCol)	e->Col = Col1;#endif    SWAP (ElementPtr, Matrix->FirstInCol[Col1], Matrix->FirstInCol[Col2]);    SWAP (int, Matrix->IntToExtColMap[Col1], Matrix->IntToExtColMap[Col2]);#if TRANSLATE    Matrix->ExtToIntColMap[Matrix->IntToExtColMap[Col2]]=Col2;    Matrix->ExtToIntColMap[Matrix->IntToExtColMap[Col1]]=Col1;#endif    Matrix->Diag[Col1] = pTwin2;    Matrix->Diag[Col2] = pTwin1;    Matrix->NumberOfInterchangesIsOdd = NOT Matrix->NumberOfInterchangesIsOdd;    return;}#endif /* MODIFIED_NODAL */#if SCALING/* *  SCALE MATRIX * *  This function scales the matrix to enhance the possibility of *  finding a good pivoting order.  Note that scaling enhances accuracy *  of the solution only if it affects the pivoting order, so it makes *  no sense to scale the matrix before spFactor().  If scaling is *  desired it should be done before spOrderAndFactor().  There *  are several things to take into account when choosing the scale *  factors.  First, the scale factors are directly multiplied against *  the elements in the matrix.  To prevent roundoff, each scale factor *  should be equal to an integer power of the number base of the *  machine.  Since most machines operate in base two, scale factors *  should be a power of two.  Second, the matrix should be scaled such *  that the matrix of element uncertainties is equilibrated.  Third, *  this function multiplies the scale factors by the elements, so if *  one row tends to have uncertainties 1000 times smaller than the *  other rows, then its scale factor should be 1024, not 1/1024. *  Fourth, to save time, this function does not scale rows or columns *  if their scale factors are equal to one.  Thus, the scale factors *  should be normalized to the most common scale factor.  Rows and *  columns should be normalized separately.  For example, if the size *  of the matrix is 100 and 10 rows tend to have uncertainties near *  1e-6 and the remaining 90 have uncertainties near 1e-12, then the *  scale factor for the 10 should be 1/1,048,576 and the scale factors *  for the remaining 90 should be 1.  Fifth, since this routine *  directly operates on the matrix, it is necessary to apply the scale *  factors to the RHS and Solution vectors.  It may be easier to *  simply use spOrderAndFactor() on a scaled matrix to choose the *  pivoting order, and then throw away the matrix.  Subsequent *  factorizations, performed with spFactor(), will not need to have *  the RHS and Solution vectors descaled.  Lastly, this function *  should not be executed before the function spMNA_Preorder. * *  >>> Arguments: *  eMatrix  <input> (char *) *      Pointer to the matrix to be scaled. *  SolutionScaleFactors  <input>  (RealVector) *      The array of Solution scale factors.  These factors scale the columns. *      All scale factors are real valued. *  RHS_ScaleFactors  <input>  (RealVector) *      The array of RHS scale factors.  These factors scale the rows. *      All scale factors are real valued. * *  >>> Local variables: *  lSize  (int) *      Local version of the size of the matrix. *  pElement  (ElementPtr) *      Pointer to an element in the matrix. *  pExtOrder  (int *) *      Pointer into either IntToExtRowMap or IntToExtColMap vector. Used to *      compensate for any row or column swaps that have been performed. *  ScaleFactor  (RealNumber) *      The scale factor being used on the current row or column. */voidspScale( eMatrix, RHS_ScaleFactors, SolutionScaleFactors )char *eMatrix;register  RealVector  RHS_ScaleFactors, SolutionScaleFactors;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -