📄 sputils.c
字号:
/* * 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 + -