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

📄 spfactor.c

📁 spice中支持多层次元件模型仿真的可单独运行的插件源码
💻 C
📖 第 1 页 / 共 5 页
字号:
/* *  MATRIX FACTORIZATION MODULE * *  Author:                     Advising Professor: *      Kenneth S. Kundert          Alberto Sangiovanni-Vincentelli *      UC Berkeley * *  This file contains the routines to factor the matrix into LU form. * *  >>> User accessible functions contained in this file: *  spOrderAndFactor *  spFactor *  spPartition * *  >>> Other functions contained in this file: *  FactorComplexMatrix         spcCreateInternalVectors *  CountMarkowitz              MarkowitzProducts *  SearchForPivot              SearchForSingleton *  QuicklySearchDiagonal       SearchDiagonal *  SearchEntireMatrix          FindLargestInCol *  FindBiggestInColExclude     ExchangeRowsAndCols *  spcRowExchange              spcColExchange *  ExchangeColElements         ExchangeRowElements *  RealRowColElimination       ComplexRowColElimination *  UpdateMarkowitzNumbers      CreateFillin *  MatrixIsSingular            ZeroPivot *  WriteStatus *//* *  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: spFactor.c,v 1.3 88/06/24 05:01:12 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  FactorComplexMatrix( MatrixPtr );static void CountMarkowitz( MatrixPtr, RealVector, int );static void MarkowitzProducts( MatrixPtr, int );static ElementPtr SearchForPivot( MatrixPtr, int, int );static ElementPtr SearchForSingleton( MatrixPtr, int );static ElementPtr QuicklySearchDiagonal( MatrixPtr, int );static ElementPtr SearchDiagonal( MatrixPtr, int );static ElementPtr SearchEntireMatrix( MatrixPtr, int );static RealNumber FindLargestInCol( ElementPtr );static RealNumber FindBiggestInColExclude( MatrixPtr, ElementPtr, int );static void ExchangeRowsAndCols( MatrixPtr, ElementPtr, int );static void ExchangeColElements( MatrixPtr, int, ElementPtr, int,                                 ElementPtr, int );static void ExchangeRowElements( MatrixPtr, int, ElementPtr, int,                                 ElementPtr, int );static void RealRowColElimination( MatrixPtr, ElementPtr );static void ComplexRowColElimination( MatrixPtr, ElementPtr );static void UpdateMarkowitzNumbers( MatrixPtr, ElementPtr );static ElementPtr CreateFillin( MatrixPtr, int, int );static int  MatrixIsSingular( MatrixPtr, int );static int  ZeroPivot( MatrixPtr, int );static void WriteStatus( MatrixPtr, int );#else /* __STDC__ */static int  FactorComplexMatrix();static void CountMarkowitz();static void MarkowitzProducts();static ElementPtr SearchForPivot();static ElementPtr SearchForSingleton();static ElementPtr QuicklySearchDiagonal();static ElementPtr SearchDiagonal();static ElementPtr SearchEntireMatrix();static RealNumber FindLargestInCol();static RealNumber FindBiggestInColExclude();static void ExchangeRowsAndCols();static void ExchangeColElements();static void ExchangeRowElements();static void RealRowColElimination();static void ComplexRowColElimination();static void UpdateMarkowitzNumbers();static ElementPtr CreateFillin();static int  MatrixIsSingular();static int  ZeroPivot();static void WriteStatus();#endif /* __STDC__ *//* *  ORDER AND FACTOR MATRIX * *  This routine chooses a pivot order for the matrix and factors it *  into LU form.  It handles both the initial factorization and subsequent *  factorizations when a reordering is desired.  This is handled in a manner *  that is transparent to the user.  The routine uses a variation of *  Gauss's method where the pivots are associated with L and the *  diagonal terms of U are one. * *  >>> Returned: *  The error code is returned.  Possible errors are listed below. * *  >>> Arguments: *  Matrix  <input>  (char *) *      Pointer to matrix. *  RHS  <input>  (RealVector) *      Representative right-hand side vector that is used to determine *      pivoting order when the right hand side vector is sparse.  If *      RHS is a NULL pointer then the RHS vector is assumed to *      be full and it is not used when determining the pivoting *      order. *  RelThreshold  <input>  (RealNumber) *      This number determines what the pivot relative threshold will *      be.  It should be between zero and one.  If it is one then the *      pivoting method becomes complete pivoting, which is very slow *      and tends to fill up the matrix.  If it is set close to zero *      the pivoting method becomes strict Markowitz with no *      threshold.  The pivot threshold is used to eliminate pivot *      candidates that would cause excessive element growth if they *      were used.  Element growth is the cause of roundoff error. *      Element growth occurs even in well-conditioned matrices. *      Setting the RelThreshold large will reduce element growth and *      roundoff error, but setting it too large will cause execution *      time to be excessive and will result in a large number of *      fill-ins.  If this occurs, accuracy can actually be degraded *      because of the large number of operations required on the *      matrix due to the large number of fill-ins.  A good value seems *      to be 0.001.  The default is chosen by giving a value larger *      than one or less than or equal to zero.  This value should be *      increased and the matrix resolved if growth is found to be *      excessive.  Changing the pivot threshold does not improve *      performance on matrices where growth is low, as is often the *      case with ill-conditioned matrices.  Once a valid threshold is *      given, it becomes the new default.  The default value of *      RelThreshold was choosen for use with nearly diagonally *      dominant matrices such as node- and modified-node admittance *      matrices.  For these matrices it is usually best to use *      diagonal pivoting.  For matrices without a strong diagonal, it *      is usually best to use a larger threshold, such as 0.01 or *      0.1. *  AbsThreshold  <input>  (RealNumber) *      The absolute magnitude an element must have to be considered *      as a pivot candidate, except as a last resort.  This number *      should be set significantly smaller than the smallest diagonal *      element that is is expected to be placed in the matrix.  If *      there is no reasonable prediction for the lower bound on these *      elements, then AbsThreshold should be set to zero. *      AbsThreshold is used to reduce the possibility of choosing as a *      pivot an element that has suffered heavy cancellation and as a *      result mainly consists of roundoff error.  Once a valid *      threshold is given, it becomes the new default. *  DiagPivoting  <input>  (BOOLEAN) *      A flag indicating that pivot selection should be confined to the *      diagonal if possible.  If DiagPivoting is nonzero and if *      DIAGONAL_PIVOTING is enabled pivots will be chosen only from *      the diagonal unless there are no diagonal elements that satisfy *      the threshold criteria.  Otherwise, the entire reduced *      submatrix is searched when looking for a pivot.  The diagonal *      pivoting in Sparse is efficient and well refined, while the *      off-diagonal pivoting is not.  For symmetric and near symmetric *      matrices, it is best to use diagonal pivoting because it *      results in the best performance when reordering the matrix and *      when factoring the matrix without ordering.  If there is a *      considerable amount of nonsymmetry in the matrix, then *      off-diagonal pivoting may result in a better equation ordering *      simply because there are more pivot candidates to choose from. *      A better ordering results in faster subsequent factorizations. *      However, the initial pivot selection process takes considerably *      longer for off-diagonal pivoting. * *  >>> Local variables: *  pPivot  (ElementPtr) *      Pointer to the element being used as a pivot. *  ReorderingRequired  (BOOLEAN) *      Flag that indicates whether reordering is required. * *  >>> Possible errors: *  spNO_MEMORY *  spSINGULAR *  spSMALL_PIVOT *  Error is cleared in this function. */intspOrderAndFactor( eMatrix, RHS, RelThreshold, AbsThreshold, DiagPivoting )char *eMatrix;RealNumber  RHS[], RelThreshold, AbsThreshold;BOOLEAN DiagPivoting;{MatrixPtr  Matrix = (MatrixPtr)eMatrix;ElementPtr  pPivot;int  Step, Size, ReorderingRequired;ElementPtr SearchForPivot();RealNumber LargestInCol, FindLargestInCol();/* Begin `spOrderAndFactor'. */    ASSERT( IS_VALID(Matrix) AND NOT Matrix->Factored);    Matrix->Error = spOKAY;    Size = Matrix->Size;    if (RelThreshold <= 0.0) RelThreshold = Matrix->RelThreshold;    if (RelThreshold > 1.0) RelThreshold = Matrix->RelThreshold;    Matrix->RelThreshold = RelThreshold;    if (AbsThreshold < 0.0) AbsThreshold = Matrix->AbsThreshold;    Matrix->AbsThreshold = AbsThreshold;    ReorderingRequired = NO;    if (NOT Matrix->NeedsOrdering)    {/* Matrix has been factored before and reordering is not required. */        for (Step = 1; Step <= Size; Step++)        {   pPivot = Matrix->Diag[Step];            LargestInCol = FindLargestInCol(pPivot->NextInCol);            if ((LargestInCol * RelThreshold < ELEMENT_MAG(pPivot)))            {   if (Matrix->Complex)                    ComplexRowColElimination( Matrix, pPivot );                else                    RealRowColElimination( Matrix, pPivot );            }            else            {   ReorderingRequired = YES;                break; /* for loop */            }        }        if (NOT ReorderingRequired)            goto Done;        else        {/* * A pivot was not large enough to maintain accuracy, * so a partial reordering is required. */#if (ANNOTATE >= ON_STRANGE_BEHAVIOR)            printf("Reordering,  Step = %1d\n", Step);#endif        }    } /* End of if(NOT Matrix->NeedsOrdering) */    else    {/* * This is the first time the matrix has been factored.  These few statements * indicate to the rest of the code that a full reodering is required rather * than a partial reordering, which occurs during a failure of a fast * factorization. */        Step = 1;        if (NOT Matrix->RowsLinked)            spcLinkRows( Matrix );        if (NOT Matrix->InternalVectorsAllocated)            spcCreateInternalVectors( Matrix );        if (Matrix->Error >= spFATAL)            return Matrix->Error;    }/* Form initial Markowitz products. */    CountMarkowitz( Matrix, RHS, Step );    MarkowitzProducts( Matrix, Step );    Matrix->MaxRowCountInLowerTri = -1;/* Perform reordering and factorization. */    for (; Step <= Size; Step++)    {   pPivot = SearchForPivot( Matrix, Step, DiagPivoting );        if (pPivot == NULL) return MatrixIsSingular( Matrix, Step );        ExchangeRowsAndCols( Matrix, pPivot, Step );        if (Matrix->Complex)            ComplexRowColElimination( Matrix, pPivot );        else            RealRowColElimination( Matrix, pPivot );        if (Matrix->Error >= spFATAL) return Matrix->Error;        UpdateMarkowitzNumbers( Matrix, pPivot );#if (ANNOTATE == FULL)        WriteStatus( Matrix, Step );#endif    }Done:    Matrix->NeedsOrdering = NO;    Matrix->Reordered = YES;    Matrix->Factored = YES;    return Matrix->Error;}/* *  FACTOR MATRIX * *  This routine is the companion routine to spOrderAndFactor(). *  Unlike spOrderAndFactor(), spFactor() cannot change the ordering. *  It is also faster than spOrderAndFactor().  The standard way of *  using these two routines is to first use spOrderAndFactor() for the *  initial factorization.  For subsequent factorizations, spFactor() *  is used if there is some assurance that little growth will occur *  (say for example, that the matrix is diagonally dominant).  If *  spFactor() is called for the initial factorization of the matrix, *  then spOrderAndFactor() is automatically called with the default *  threshold.  This routine uses "row at a time" LU factorization. *  Pivots are associated with the lower triangular matrix and the *  diagonals of the upper triangular matrix are ones. * *  >>> Returned: *  The error code is returned.  Possible errors are listed below. * *  >>> Arguments: *  Matrix  <input>  (char *) *      Pointer to matrix. * *  >>> Possible errors: *  spNO_MEMORY *  spSINGULAR *  spZERO_DIAG *  spSMALL_PIVOT *  Error is cleared in this function. */intspFactor( eMatrix )char *eMatrix;{MatrixPtr  Matrix = (MatrixPtr)eMatrix;register  ElementPtr  pElement;register  ElementPtr  pColumn;register  int  Step, Size;RealNumber Mult;/* Begin `spFactor'. */    ASSERT( IS_VALID(Matrix) AND NOT Matrix->Factored);    if (Matrix->NeedsOrdering)    {   return spOrderAndFactor( eMatrix, (RealVector)NULL,

⌨️ 快捷键说明

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