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

📄 spfactor.c

📁 spice中支持多层次元件模型仿真的可单独运行的插件源码
💻 C
📖 第 1 页 / 共 5 页
字号:
 *      Pointer to matrix. * *  >>> Local variables: *  SizePlusOne  (unsigned) *      Size of the arrays to be allocated. * *  >>> Possible errors: *  spNO_MEMORY */voidspcCreateInternalVectors( Matrix )MatrixPtr  Matrix;{int  Size;/* Begin `spcCreateInternalVectors'. *//* Create Markowitz arrays. */    Size= Matrix->Size;    if (Matrix->MarkowitzRow == NULL)    {   if (( Matrix->MarkowitzRow = ALLOC(int, Size+1)) == NULL)            Matrix->Error = spNO_MEMORY;    }    if (Matrix->MarkowitzCol == NULL)    {   if (( Matrix->MarkowitzCol = ALLOC(int, Size+1)) == NULL)            Matrix->Error = spNO_MEMORY;    }    if (Matrix->MarkowitzProd == NULL)    {   if (( Matrix->MarkowitzProd = ALLOC(long, Size+2)) == NULL)            Matrix->Error = spNO_MEMORY;    }/* Create DoDirect vectors for use in spFactor(). */#if REAL    if (Matrix->DoRealDirect == NULL)    {   if (( Matrix->DoRealDirect = ALLOC(BOOLEAN, Size+1)) == NULL)            Matrix->Error = spNO_MEMORY;    }#endif#if spCOMPLEX    if (Matrix->DoCmplxDirect == NULL)    {   if (( Matrix->DoCmplxDirect = ALLOC(BOOLEAN, Size+1)) == NULL)            Matrix->Error = spNO_MEMORY;    }#endif/* Create Intermediate vectors for use in MatrixSolve. */#if spCOMPLEX    if (Matrix->Intermediate == NULL)    {   if ((Matrix->Intermediate = ALLOC(RealNumber,2*(Size+1))) == NULL)            Matrix->Error = spNO_MEMORY;    }#else    if (Matrix->Intermediate == NULL)    {   if ((Matrix->Intermediate = ALLOC(RealNumber, Size+1)) == NULL)            Matrix->Error = spNO_MEMORY;    }#endif    if (Matrix->Error != spNO_MEMORY)        Matrix->InternalVectorsAllocated = YES;    return;}/* *  COUNT MARKOWITZ * *  Scans Matrix to determine the Markowitz counts for each row and column. * *  >>> Arguments: *  Matrix  <input>  (MatrixPtr) *      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. *  Step  <input>  (int) *     Index of the diagonal currently being eliminated. * *  >>> Local variables: *  Count  (int) *     Temporary counting variable. *  ExtRow  (int) *     The external row number that corresponds to I. *  pElement  (ElementPtr) *     Pointer to matrix elements. *  Size  (int) *     The size of the matrix. */static voidCountMarkowitz( Matrix, RHS, Step )MatrixPtr Matrix;register RealVector  RHS;int Step;{register int  Count, I, Size = Matrix->Size;register ElementPtr  pElement;int  ExtRow;/* Begin `CountMarkowitz'. *//* Correct array pointer for ARRAY_OFFSET. */#if NOT ARRAY_OFFSET#if spSEPARATED_COMPLEX_VECTORS OR NOT spCOMPLEX        if (RHS != NULL) --RHS;#else        if (RHS != NULL)        {   if (Matrix->Complex) RHS -= 2;            else --RHS;        }#endif#endif/* Generate MarkowitzRow Count for each row. */    for (I = Step; I <= Size; I++)    {/* Set Count to -1 initially to remove count due to pivot element. */        Count = -1;        pElement = Matrix->FirstInRow[I];        while (pElement != NULL AND pElement->Col < Step)            pElement = pElement->NextInRow;        while (pElement != NULL)        {   Count++;            pElement = pElement->NextInRow;        }/* Include nonzero elements in the RHS vector. */        ExtRow = Matrix->IntToExtRowMap[I];#if spSEPARATED_COMPLEX_VECTORS OR NOT spCOMPLEX        if (RHS != NULL)            if (RHS[ExtRow] != 0.0)  Count++;#else        if (RHS != NULL)        {   if (Matrix->Complex)            {   if ((RHS[2*ExtRow] != 0.0) OR (RHS[2*ExtRow+1] != 0.0))                    Count++;            }            else if (RHS[I] != 0.0) Count++;        }#endif        Matrix->MarkowitzRow[I] = Count;    }/* Generate the MarkowitzCol count for each column. */    for (I = Step; I <= Size; I++)    {/* Set Count to -1 initially to remove count due to pivot element. */        Count = -1;        pElement = Matrix->FirstInCol[I];        while (pElement != NULL AND pElement->Row < Step)            pElement = pElement->NextInCol;        while (pElement != NULL)        {   Count++;            pElement = pElement->NextInCol;        }        Matrix->MarkowitzCol[I] = Count;    }    return;}/* *  MARKOWITZ PRODUCTS * *  Calculates MarkowitzProduct for each diagonal element from the Markowitz *  counts. * *  >>> Arguments: *  Matrix  <input>  (MatrixPtr) *      Pointer to matrix. *  Step  <input>  (int) *      Index of the diagonal currently being eliminated. * *  >>> Local Variables: *  pMarkowitzProduct  (long *) *      Pointer that points into MarkowitzProduct array. Is used to *      sequentially access entries quickly. *  pMarkowitzRow  (int *) *      Pointer that points into MarkowitzRow array. Is used to sequentially *      access entries quickly. *  pMarkowitzCol  (int *) *      Pointer that points into MarkowitzCol array. Is used to sequentially *      access entries quickly. *  Product  (long) *      Temporary storage for Markowitz product./ *  Size  (int) *      The size of the matrix. */static voidMarkowitzProducts( Matrix, Step )MatrixPtr Matrix;int Step;{register  int  I, *pMarkowitzRow, *pMarkowitzCol;register  long  Product, *pMarkowitzProduct;register  int  Size = Matrix->Size;double fProduct;/* Begin `MarkowitzProducts'. */    Matrix->Singletons = 0;    pMarkowitzProduct = &(Matrix->MarkowitzProd[Step]);    pMarkowitzRow = &(Matrix->MarkowitzRow[Step]);    pMarkowitzCol = &(Matrix->MarkowitzCol[Step]);    for (I = Step; I <= Size; I++)    {/* If chance of overflow, use real numbers. */        if ((*pMarkowitzRow > LARGEST_SHORT_INTEGER AND *pMarkowitzCol != 0) OR            (*pMarkowitzCol > LARGEST_SHORT_INTEGER AND *pMarkowitzRow != 0))        {   fProduct = (double)(*pMarkowitzRow++) * (double)(*pMarkowitzCol++);            if (fProduct >= LARGEST_LONG_INTEGER)                *pMarkowitzProduct++ = LARGEST_LONG_INTEGER;            else                *pMarkowitzProduct++ = fProduct;        }        else        {   Product = *pMarkowitzRow++ * *pMarkowitzCol++;            if ((*pMarkowitzProduct++ = Product) == 0)                Matrix->Singletons++;        }    }    return;}/* *  SEARCH FOR BEST PIVOT * *  Performs a search to determine the element with the lowest Markowitz *  Product that is also acceptable.  An acceptable element is one that is *  larger than the AbsThreshold and at least as large as RelThreshold times *  the largest element in the same column.  The first step is to look for *  singletons if any exist.  If none are found, then all the diagonals are *  searched. The diagonal is searched once quickly using the assumption that *  elements on the diagonal are large compared to other elements in their *  column, and so the pivot can be chosen only on the basis of the Markowitz *  criterion.  After a element has been chosen to be pivot on the basis of *  its Markowitz product, it is checked to see if it is large enough. *  Waiting to the end of the Markowitz search to check the size of a pivot *  candidate saves considerable time, but is not guaranteed to find an *  acceptable pivot.  Thus if unsuccessful a second pass of the diagonal is *  made.  This second pass checks to see if an element is large enough during *  the search, not after it.  If still no acceptable pivot candidate has *  been found, the search expands to cover the entire matrix. * *  >>> Returned: *  A pointer to the element chosen to be pivot.  If every element in the *  matrix is zero, then NULL is returned. * *  >>> Arguments: *  Matrix  <input>  (MatrixPtr) *      Pointer to matrix. *  Step  <input>  (int) *      The row and column number of the beginning of the reduced submatrix. * *  >>> Local variables: *  ChosenPivot  (ElementPtr) *      Pointer to element that has been chosen to be the pivot. * *  >>> Possible errors: *  spSINGULAR *  spSMALL_PIVOT */static ElementPtrSearchForPivot( Matrix, Step, DiagPivoting )MatrixPtr Matrix;int Step, DiagPivoting;{register ElementPtr  ChosenPivot;ElementPtr  SearchForSingleton();ElementPtr  QuicklySearchDiagonal();ElementPtr  SearchDiagonal();ElementPtr  SearchEntireMatrix();/* Begin `SearchForPivot'. *//* If singletons exist, look for an acceptable one to use as pivot. */    if (Matrix->Singletons)    {   ChosenPivot = SearchForSingleton( Matrix, Step );        if (ChosenPivot != NULL)        {   Matrix->PivotSelectionMethod = 's';            return ChosenPivot;        }    }#if DIAGONAL_PIVOTING    if (DiagPivoting)    {/* * Either no singletons exist or they weren't acceptable.  Take quick first * pass at searching diagonal.  First search for element on diagonal of  * remaining submatrix with smallest Markowitz product, then check to see * if it okay numerically.  If not, QuicklySearchDiagonal fails. */        ChosenPivot = QuicklySearchDiagonal( Matrix, Step );        if (ChosenPivot != NULL)        {   Matrix->PivotSelectionMethod = 'q';            return ChosenPivot;        }/* * Quick search of diagonal failed, carefully search diagonal and check each * pivot candidate numerically before even tentatively accepting it. */        ChosenPivot = SearchDiagonal( Matrix, Step );        if (ChosenPivot != NULL)        {   Matrix->PivotSelectionMethod = 'd';            return ChosenPivot;        }    }#endif /* DIAGONAL_PIVOTING *//* No acceptable pivot found yet, search entire matrix. */    ChosenPivot = SearchEntireMatrix( Matrix, Step );    Matrix->PivotSelectionMethod = 'e';    return ChosenPivot;}/* *  SEARCH FOR SINGLETON TO USE AS PIVOT * *  Performs a search to find a singleton to use as the pivot.  The *  first acceptable singleton is used.  A singleton is acceptable if *  it is larger in magnitude than the AbsThreshold and larger *  than RelThreshold times the largest of any other elements in the same *  column.  It may seem that a singleton need not satisfy the *  relative threshold criterion, however it is necessary to prevent *  excessive growth in the RHS from resulting in overflow during the *  forward and backward substitution.  A singleton does not need to *  be on the diagonal to be selected. * *  >>> Returned: *  A pointer to the singleton chosen to be pivot.  In no singleton is *  acceptable, return NULL. * *  >>> Arguments: *  Matrix  <input>  (MatrixPtr) *      Pointer to matrix. *  Step  <input>  (int)

⌨️ 快捷键说明

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