📄 spbuild.c
字号:
#if NOT EXPANDABLE
vASSERT( IntRow <= Matrix->Size, "Matrix size fixed" );
#endif
#if EXPANDABLE
/* Re-size Matrix if necessary. */
if (IntRow > Matrix->Size)
EnlargeMatrix( Matrix, IntRow );
if (Matrix->Error == spNO_MEMORY) return;
#endif
Matrix->IntToExtRowMap[IntRow] = ExtRow;
Matrix->IntToExtColMap[IntRow] = ExtRow;
}
/* Translate external column or node number to internal column or node number.*/
if ((IntCol = Matrix->ExtToIntColMap[ExtCol]) == -1)
{ Matrix->ExtToIntRowMap[ExtCol] = ++Matrix->CurrentSize;
Matrix->ExtToIntColMap[ExtCol] = Matrix->CurrentSize;
IntCol = Matrix->CurrentSize;
#if NOT EXPANDABLE
vASSERT( IntCol <= Matrix->Size, "Matrix size fixed" );
#endif
#if EXPANDABLE
/* Re-size Matrix if necessary. */
if (IntCol > Matrix->Size)
EnlargeMatrix( Matrix, IntCol );
if (Matrix->Error == spNO_MEMORY) return;
#endif
Matrix->IntToExtRowMap[IntCol] = ExtCol;
Matrix->IntToExtColMap[IntCol] = ExtCol;
}
*Row = IntRow;
*Col = IntCol;
return;
}
#endif
#if QUAD_ELEMENT
/*!
* Performs same function as spGetElement() except rather than one
* element, all four matrix elements for a floating two terminal
* admittance component are added. This routine also works if component
* is grounded. Positive elements are placed at [Node1,Node2] and
* [Node2,Node1]. This routine is only to be used after spCreate()
* and before spMNA_Preorder(), spFactor() or spOrderAndFactor().
*
* \return
* Error code. Possible errors include \a spNO_MEMORY.
* Error is not cleared in this routine.
*
* \param Matrix
* Pointer to the matrix that component is to be entered in.
* \param Node1
* Row and column indices for elements. Must be in the range of [0..Size]
* unless the options \a EXPANDABLE or \a TRANSLATE are used. Node zero is the
* ground node. In no case may \a Node1 be less than zero.
* \param Node2
* Row and column indices for elements. Must be in the range of [0..Size]
* unless the options \a EXPANDABLE or \a TRANSLATE are used. Node zero is the
* ground node. In no case may \a Node2 be less than zero.
* \param Template
* Collection of pointers to four elements that are later used to directly
* address elements. User must supply the template, this routine will
* fill it.
*/
spError
spGetAdmittance(
spMatrix Matrix,
int Node1,
int Node2,
struct spTemplate *Template
)
{
/* Begin `spGetAdmittance'. */
Template->Element1 = spGetElement(Matrix, Node1, Node1 );
Template->Element2 = spGetElement(Matrix, Node2, Node2 );
Template->Element3Negated = spGetElement( Matrix, Node2, Node1 );
Template->Element4Negated = spGetElement( Matrix, Node1, Node2 );
if
( (Template->Element1 == NULL)
OR (Template->Element2 == NULL)
OR (Template->Element3Negated == NULL)
OR (Template->Element4Negated == NULL)
) return spNO_MEMORY;
if (Node1 == 0)
SWAP( RealNumber*, Template->Element1, Template->Element2 );
return spOKAY;
}
#endif /* QUAD_ELEMENT */
#if QUAD_ELEMENT
/*!
* Similar to spGetAdmittance(), except that spGetAdmittance() only
* handles 2-terminal components, whereas spGetQuad() handles simple
* 4-terminals as well. These 4-terminals are simply generalized
* 2-terminals with the option of having the sense terminals different
* from the source and sink terminals. spGetQuad() adds four
* elements to the matrix. Positive elements occur at [Row1,Col1]
* [Row2,Col2] while negative elements occur at [Row1,Col2] and [Row2,Col1].
* The routine works fine if any of the rows and columns are zero.
* This routine is only to be used after spCreate() and before
* spMNA_Preorder(), spFactor() or spOrderAndFactor()
* unless \a TRANSLATE is set true.
*
* \return
* Error code. Possible errors include \a spNO_MEMORY.
* Error is not cleared in this routine.
*
* \param Matrix
* Pointer to the matrix that component is to be entered in.
* \param Row1
* First row index for elements. Must be in the range of [0..Size]
* unless the options \a EXPANDABLE or \a TRANSLATE are used. Zero is the
* ground row. In no case may Row1 be less than zero.
* \param Row2
* Second row index for elements. Must be in the range of [0..Size]
* unless the options \a EXPANDABLE or \a TRANSLATE are used. Zero is the
* ground row. In no case may Row2 be less than zero.
* \param Col1
* First column index for elements. Must be in the range of [0..Size]
* unless the options \a EXPANDABLE or \a TRANSLATE are used. Zero is the
* ground column. In no case may Col1 be less than zero.
* \param Col2
* Second column index for elements. Must be in the range of [0..Size]
* unless the options \a EXPANDABLE or \a TRANSLATE are used. Zero is the
* ground column. In no case may Col2 be less than zero.
* \param Template
* Collection of pointers to four elements that are later used to directly
* address elements. User must supply the template, this routine will
* fill it.
*/
spError
spGetQuad(
spMatrix Matrix,
int Row1,
int Row2,
int Col1,
int Col2,
struct spTemplate *Template
)
{
/* Begin `spGetQuad'. */
Template->Element1 = spGetElement( Matrix, Row1, Col1);
Template->Element2 = spGetElement( Matrix, Row2, Col2 );
Template->Element3Negated = spGetElement( Matrix, Row2, Col1 );
Template->Element4Negated = spGetElement( Matrix, Row1, Col2 );
if
( (Template->Element1 == NULL)
OR (Template->Element2 == NULL)
OR (Template->Element3Negated == NULL)
OR (Template->Element4Negated == NULL)
) return spNO_MEMORY;
if (Template->Element1 == &((MatrixPtr)Matrix)->TrashCan.Real)
SWAP( RealNumber *, Template->Element1, Template->Element2 );
return spOKAY;
}
#endif /* QUAD_ELEMENT */
#if QUAD_ELEMENT
/*!
* Addition of four structural ones to matrix by index.
* Performs similar function to spGetQuad() except this routine is
* meant for components that do not have an admittance representation.
*
* The following stamp is used: \code
* Pos Neg Eqn
* Pos [ . . 1 ]
* Neg [ . . -1 ]
* Eqn [ 1 -1 . ]
* \endcode
*
* \return
* Error code. Possible errors include \a spNO_MEMORY.
* Error is not cleared in this routine.
*
* \param Matrix
* Pointer to the matrix that component is to be entered in.
* \param Pos
* See stamp above. Must be in the range of [0..Size]
* unless the options \a EXPANDABLE or \a TRANSLATE are used. Zero is the
* ground row. In no case may \a Pos be less than zero.
* \param Neg
* See stamp above. Must be in the range of [0..Size]
* unless the options \a EXPANDABLE or \a TRANSLATE are used. Zero is the
* ground row. In no case may \a Neg be less than zero.
* \param Eqn
* See stamp above. Must be in the range of [0..Size]
* unless the options \a EXPANDABLE or \a TRANSLATE are used. Zero is the
* ground row. In no case may \a Eqn be less than zero.
* \param Template
* Collection of pointers to four elements that are later used to directly
* address elements. User must supply the template, this routine will
* fill it.
*/
spError
spGetOnes(
spMatrix Matrix,
int Pos,
int Neg,
int Eqn,
struct spTemplate *Template
)
{
/* Begin `spGetOnes'. */
Template->Element4Negated = spGetElement( Matrix, Neg, Eqn );
Template->Element3Negated = spGetElement( Matrix, Eqn, Neg );
Template->Element2 = spGetElement( Matrix, Pos, Eqn );
Template->Element1 = spGetElement( Matrix, Eqn, Pos );
if
( (Template->Element1 == NULL)
OR (Template->Element2 == NULL)
OR (Template->Element3Negated == NULL)
OR (Template->Element4Negated == NULL)
) return spNO_MEMORY;
spADD_REAL_QUAD( *Template, 1.0 );
return spOKAY;
}
#endif /* QUAD_ELEMENT */
/*
* FIND DIAGONAL
*
* This routine is used to find a diagonal element. It will not
* create it if it does not exist.
*
* >>> Returned:
* A pointer to the desired element, or NULL if it does not exist.
*
* >>> Arguments:
* Matrix <input> (MatrixPtr)
* Pointer to matrix.
* Index <input> (int)
* Row, Col index for diagonal element.
*
* >>> Local variables:
* pElement (ElementPtr)
* Pointer to an element in the matrix.
*/
ElementPtr
spcFindDiag(
MatrixPtr Matrix,
register int Index
)
{
register ElementPtr pElement;
/* Begin `spcFindDiag'. */
pElement = Matrix->FirstInCol[Index];
/* Search column for element. */
while ((pElement != NULL) AND (pElement->Row < Index))
pElement = pElement->NextInCol;
if (pElement AND (pElement->Row == Index))
return pElement;
else
return NULL;
}
/*
* CREATE AND SPLICE ELEMENT INTO MATRIX
*
* This routine is used to create new matrix elements and splice them into the
* matrix.
*
* >>> Returned:
* A pointer to the element that was created is returned.
*
* >>> Arguments:
* Matrix <input> (MatrixPtr)
* Pointer to matrix.
* Row <input> (int)
* Row index for element.
* Col <input> (int)
* Column index for element.
* ppToLeft <input-output> (ElementPtr *)
* This contains the address of the pointer to an element to the left
* of the one being created. It is used to speed the search and if it
* is immediately to the left, it is updated with address of the
* created element.
* ppAbove <input-output> (ElementPtr *)
* This contains the address of the pointer to an element above the
* one being created. It is used to speed the search and it if it
* is immediatley above, it is updated with address of the created
* element.
* Fillin <input> (BOOLEAN)
* Flag that indicates if created element is to be a fill-in.
*
* >>> Local variables:
* pElement (ElementPtr)
* Pointer to an element in the matrix.
* pCreatedElement (ElementPtr)
* Pointer to the desired element, the one that was just created.
*
* >>> Possible errors:
* spNO_MEMORY
*/
ElementPtr
spcCreateElement(
MatrixPtr Matrix,
int Row,
register int Col,
register ElementPtr *ppToLeft,
register ElementPtr *ppAbove,
BOOLEAN Fillin
)
{
register ElementPtr pElement, pCreatedElement;
/* Begin `spcCreateElement'. */
/* Find element immediately above the desired element. */
pElement = *ppAbove;
while ((pElement != NULL) AND (pElement->Row < Row))
{ ppAbove = &pElement->NextInCol;
pElement = *ppAbove;
}
if ((pElement != NULL) AND (pElement->Row == Row))
return pElement;
/* The desired element does not exist, create it. */
if (Fillin)
{ pCreatedElement = spcGetFillin( Matrix );
Matrix->Fillins++;
/* Update Markowitz counts and products. */
++Matrix->MarkowitzRow[Row];
spcMarkoProd( Matrix->MarkowitzProd[Row],
Matrix->MarkowitzRow[Row],
Matrix->MarkowitzCol[Row] );
if ((Matrix->MarkowitzRow[Row] == 1) AND
(Matrix->MarkowitzCol[Row] != 0))
{
Matrix->Singletons--;
}
++Matrix->MarkowitzCol[Col];
spcMarkoProd( Matrix->MarkowitzProd[Col],
Matrix->MarkowitzCol[Col],
Matrix->MarkowitzRow[Col] );
if ((Matrix->MarkowitzRow[Col] != 0) AND
(Matrix->MarkowitzCol[Col] == 1))
{
Matrix->Singletons--;
}
}
else
{ pCreatedElement = spcGetElement( Matrix );
Matrix->NeedsOrdering = YES;
}
if (pCreatedElement == NULL) return NULL;
Matrix->Elements++;
/* Initialize Element. */
pCreatedElement->Row = Row;
pCreatedElement->Col = Col;
pCreatedElement->Real = 0.0;
#if spCOMPLEX
pCreatedElement->Imag = 0.0;
#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -