1805 lines
59 KiB
C
1805 lines
59 KiB
C
/* KLU to SMP Interface
|
|
* Francesco Lannutti
|
|
* July 2020
|
|
*/
|
|
|
|
#include "ngspice/config.h"
|
|
#include <assert.h>
|
|
#include <stdio.h>
|
|
#include <math.h>
|
|
#include "ngspice/spmatrix.h"
|
|
#include "../sparse/spdefs.h"
|
|
#include "ngspice/smpdefs.h"
|
|
|
|
#if defined (_MSC_VER)
|
|
extern double scalbn(double, int);
|
|
#define logb _logb
|
|
extern double logb(double);
|
|
#endif
|
|
|
|
static void LoadGmin_CSC (double **diag, unsigned int n, double Gmin) ;
|
|
static void LoadGmin (SMPmatrix *eMatrix, double Gmin) ;
|
|
|
|
typedef struct sElement {
|
|
unsigned int row ;
|
|
unsigned int col ;
|
|
double *pointer ;
|
|
unsigned int group ;
|
|
} Element ;
|
|
|
|
static int
|
|
CompareRow (const void *a, const void *b)
|
|
{
|
|
Element *A = (Element *) a ;
|
|
Element *B = (Element *) b ;
|
|
|
|
return
|
|
(A->row > B->row) ? 1 :
|
|
(A->row < B->row) ? -1 :
|
|
0 ;
|
|
}
|
|
|
|
static int
|
|
CompareColumn (const void *a, const void *b)
|
|
{
|
|
Element *A = (Element *) a ;
|
|
Element *B = (Element *) b ;
|
|
|
|
return
|
|
(A->col > B->col) ? 1 :
|
|
(A->col < B->col) ? -1 :
|
|
0 ;
|
|
}
|
|
|
|
static void
|
|
Compress (unsigned int *Ai, unsigned int *Bp, unsigned int n, unsigned int nz)
|
|
{
|
|
unsigned int i, j ;
|
|
|
|
for (i = 0 ; i <= Ai [0] ; i++)
|
|
Bp [i] = 0 ;
|
|
|
|
j = Ai [0] + 1 ;
|
|
for (i = 1 ; i < nz ; i++)
|
|
{
|
|
if (Ai [i] == Ai [i - 1] + 1)
|
|
{
|
|
Bp [j] = i ;
|
|
j++ ;
|
|
}
|
|
else if (Ai [i] > Ai [i - 1] + 1)
|
|
{
|
|
for ( ; j <= Ai [i] ; j++)
|
|
Bp [j] = i ;
|
|
}
|
|
}
|
|
|
|
for ( ; j <= n ; j++)
|
|
Bp [j] = i ;
|
|
}
|
|
|
|
int
|
|
BindCompare (const void *a, const void *b)
|
|
{
|
|
BindElement *A = (BindElement *) a ;
|
|
BindElement *B = (BindElement *) b ;
|
|
|
|
return
|
|
(A->COO > B->COO) ? 1 :
|
|
(A->COO < B->COO) ? -1 :
|
|
0 ;
|
|
}
|
|
|
|
#ifdef CIDER
|
|
int
|
|
BindCompareKLUforCIDER (const void *a, const void *b)
|
|
{
|
|
BindElementKLUforCIDER *A = (BindElementKLUforCIDER *) a ;
|
|
BindElementKLUforCIDER *B = (BindElementKLUforCIDER *) b ;
|
|
|
|
return
|
|
(A->COO > B->COO) ? 1 :
|
|
(A->COO < B->COO) ? -1 :
|
|
0 ;
|
|
}
|
|
|
|
int
|
|
BindKluCompareCSCKLUforCIDER (const void *a, const void *b)
|
|
{
|
|
BindElementKLUforCIDER *A = (BindElementKLUforCIDER *) a ;
|
|
BindElementKLUforCIDER *B = (BindElementKLUforCIDER *) b ;
|
|
|
|
return
|
|
(A->CSC_Complex > B->CSC_Complex) ? 1 :
|
|
(A->CSC_Complex < B->CSC_Complex) ? -1 :
|
|
0 ;
|
|
}
|
|
#endif
|
|
|
|
void SMPconvertCOOtoCSC (SMPmatrix *Matrix)
|
|
{
|
|
Element *MatrixCOO ;
|
|
KluLinkedListCOO *current, *temp ;
|
|
unsigned int *Ap_COO, current_group, i, j ;
|
|
|
|
/* Allocate the compressed COO elements */
|
|
MatrixCOO = (Element *) malloc (Matrix->SMPkluMatrix->KLUmatrixLinkedListNZ * sizeof (Element)) ;
|
|
|
|
/* Populate the compressed COO elements and COO value of Binding Table */
|
|
/* Delete the Linked List in the meantime */
|
|
i = 0 ;
|
|
temp = Matrix->SMPkluMatrix->KLUmatrixLinkedListCOO ;
|
|
while (temp != NULL) {
|
|
MatrixCOO [i].row = temp->row ;
|
|
MatrixCOO [i].col = temp->col ;
|
|
MatrixCOO [i].pointer = temp->pointer ;
|
|
MatrixCOO [i].group = 0 ;
|
|
current = temp ;
|
|
temp = temp->next ;
|
|
free (current) ;
|
|
current = NULL ;
|
|
i++ ;
|
|
}
|
|
|
|
/* Order the MatrixCOO along the columns */
|
|
qsort (MatrixCOO, Matrix->SMPkluMatrix->KLUmatrixLinkedListNZ, sizeof (Element), CompareColumn) ;
|
|
|
|
/* Order the MatrixCOO along the rows */
|
|
i = 0 ;
|
|
while (i < Matrix->SMPkluMatrix->KLUmatrixLinkedListNZ)
|
|
{
|
|
/* Look for the next column */
|
|
for (j = i + 1 ; j < Matrix->SMPkluMatrix->KLUmatrixLinkedListNZ ; j++)
|
|
{
|
|
if (MatrixCOO [j].col != MatrixCOO [i].col)
|
|
{
|
|
break ;
|
|
}
|
|
}
|
|
|
|
qsort (MatrixCOO + i, j - i, sizeof (Element), CompareRow) ;
|
|
|
|
i = j ;
|
|
}
|
|
|
|
/* Assign labels to avoid duplicates */
|
|
for (i = 0, j = 1 ; i < Matrix->SMPkluMatrix->KLUmatrixLinkedListNZ - 1 ; i++, j++) {
|
|
if ((MatrixCOO [i].col == MatrixCOO [j].col) && (MatrixCOO [i].row == MatrixCOO [j].row)) {
|
|
// If col and row are the same
|
|
MatrixCOO [j].group = MatrixCOO [i].group ;
|
|
} else if ((MatrixCOO [i].col != MatrixCOO [j].col) || (MatrixCOO [i].row != MatrixCOO [j].row)) {
|
|
// If or col either row are different, it isn't a duplicate, so assign the next label and store it in 'nz'
|
|
MatrixCOO [j].group = MatrixCOO [i].group + 1 ;
|
|
} else {
|
|
printf ("Error: Strange behavior during label assignment\n") ;
|
|
}
|
|
}
|
|
|
|
/* Assign N and NZ */
|
|
Matrix->SMPkluMatrix->KLUmatrixN = (unsigned int)MatrixCOO [Matrix->SMPkluMatrix->KLUmatrixLinkedListNZ - 1].col + 1 ;
|
|
Matrix->SMPkluMatrix->KLUmatrixNZ = MatrixCOO [Matrix->SMPkluMatrix->KLUmatrixLinkedListNZ - 1].group + 1 ;
|
|
|
|
/* Allocate Diag Gmin CSC Vector */
|
|
Matrix->SMPkluMatrix->KLUmatrixDiag = (double **) malloc (Matrix->SMPkluMatrix->KLUmatrixN * sizeof (double *)) ;
|
|
for (i = 0 ; i < Matrix->SMPkluMatrix->KLUmatrixN ; i++) {
|
|
Matrix->SMPkluMatrix->KLUmatrixDiag [i] = NULL ;
|
|
}
|
|
|
|
/* Allocate the temporary COO Column Index */
|
|
Ap_COO = (unsigned int *) malloc (Matrix->SMPkluMatrix->KLUmatrixNZ * sizeof (unsigned int)) ;
|
|
|
|
/* Allocate the needed KLU data structures */
|
|
Matrix->SMPkluMatrix->KLUmatrixAp = (int *) malloc ((Matrix->SMPkluMatrix->KLUmatrixN + 1) * sizeof (int)) ;
|
|
Matrix->SMPkluMatrix->KLUmatrixAi = (int *) malloc (Matrix->SMPkluMatrix->KLUmatrixNZ * sizeof (int)) ;
|
|
Matrix->SMPkluMatrix->KLUmatrixBindStructCOO = (BindElement *) malloc (Matrix->SMPkluMatrix->KLUmatrixLinkedListNZ * sizeof (BindElement)) ;
|
|
Matrix->SMPkluMatrix->KLUmatrixAx = (double *) malloc (Matrix->SMPkluMatrix->KLUmatrixNZ * sizeof (double)) ;
|
|
Matrix->SMPkluMatrix->KLUmatrixAxComplex = (double *) malloc (2 * Matrix->SMPkluMatrix->KLUmatrixNZ * sizeof (double)) ;
|
|
Matrix->SMPkluMatrix->KLUmatrixIntermediate = (double *) malloc (Matrix->SMPkluMatrix->KLUmatrixN * sizeof (double)) ;
|
|
Matrix->SMPkluMatrix->KLUmatrixIntermediateComplex = (double *) malloc (2 * Matrix->SMPkluMatrix->KLUmatrixN * sizeof (double)) ;
|
|
|
|
/* Copy back the Matrix in partial CSC */
|
|
for (i = 0, current_group = 0 ; i < Matrix->SMPkluMatrix->KLUmatrixLinkedListNZ ; i++)
|
|
{
|
|
if (MatrixCOO [i].group > current_group) {
|
|
current_group = MatrixCOO [i].group ;
|
|
}
|
|
|
|
Ap_COO [current_group] = MatrixCOO [i].col ;
|
|
Matrix->SMPkluMatrix->KLUmatrixAi [current_group] = (int)MatrixCOO [i].row ;
|
|
Matrix->SMPkluMatrix->KLUmatrixBindStructCOO [i].COO = MatrixCOO [i].pointer ;
|
|
Matrix->SMPkluMatrix->KLUmatrixBindStructCOO [i].CSC = &(Matrix->SMPkluMatrix->KLUmatrixAx [current_group]) ;
|
|
Matrix->SMPkluMatrix->KLUmatrixBindStructCOO [i].CSC_Complex = &(Matrix->SMPkluMatrix->KLUmatrixAxComplex [2 * current_group]) ;
|
|
if (MatrixCOO [i].col == MatrixCOO [i].row) {
|
|
Matrix->SMPkluMatrix->KLUmatrixDiag [MatrixCOO [i].col] = Matrix->SMPkluMatrix->KLUmatrixBindStructCOO [i].CSC ;
|
|
}
|
|
}
|
|
|
|
/* Compress the COO Column Index to CSC Column Index */
|
|
Compress (Ap_COO, (unsigned int *)Matrix->SMPkluMatrix->KLUmatrixAp, Matrix->SMPkluMatrix->KLUmatrixN, Matrix->SMPkluMatrix->KLUmatrixNZ) ;
|
|
|
|
/* Free the temporary stuff */
|
|
free (Ap_COO) ;
|
|
free (MatrixCOO) ;
|
|
|
|
/* Sort the Binding Table */
|
|
qsort (Matrix->SMPkluMatrix->KLUmatrixBindStructCOO, Matrix->SMPkluMatrix->KLUmatrixLinkedListNZ, sizeof (BindElement), BindCompare) ;
|
|
|
|
/* Set the Matrix as Real */
|
|
Matrix->SMPkluMatrix->KLUmatrixIsComplex = KLUmatrixReal ;
|
|
|
|
return ;
|
|
}
|
|
|
|
#ifdef CIDER
|
|
typedef struct sElementKLUforCIDER {
|
|
unsigned int row ;
|
|
unsigned int col ;
|
|
double *pointer ;
|
|
} ElementKLUforCIDER ;
|
|
|
|
void SMPconvertCOOtoCSCKLUforCIDER (SMPmatrix *Matrix)
|
|
{
|
|
ElementKLUforCIDER *MatrixCOO ;
|
|
unsigned int *Ap_COO, i, j, nz ;
|
|
|
|
/* Count the non-zero elements and store it */
|
|
nz = 0 ;
|
|
for (i = 0 ; i < Matrix->SMPkluMatrix->KLUmatrixN * Matrix->SMPkluMatrix->KLUmatrixN ; i++) {
|
|
if ((Matrix->SMPkluMatrix->KLUmatrixRowCOOforCIDER [i] != -1) && (Matrix->SMPkluMatrix->KLUmatrixColCOOforCIDER [i] != -1)) {
|
|
nz++ ;
|
|
}
|
|
}
|
|
Matrix->SMPkluMatrix->KLUmatrixNZ = nz ;
|
|
|
|
/* Allocate the compressed COO elements */
|
|
MatrixCOO = (ElementKLUforCIDER *) malloc (nz * sizeof (ElementKLUforCIDER)) ;
|
|
|
|
/* Allocate the temporary COO Column Index */
|
|
Ap_COO = (unsigned int *) malloc (nz * sizeof (unsigned int)) ;
|
|
|
|
/* Allocate the needed KLU data structures */
|
|
Matrix->SMPkluMatrix->KLUmatrixAp = (int *) malloc ((Matrix->SMPkluMatrix->KLUmatrixN + 1) * sizeof (int)) ;
|
|
Matrix->SMPkluMatrix->KLUmatrixAi = (int *) malloc (nz * sizeof (int)) ;
|
|
Matrix->SMPkluMatrix->KLUmatrixBindStructForCIDER = (BindElementKLUforCIDER *) malloc (nz * sizeof (BindElementKLUforCIDER)) ;
|
|
Matrix->SMPkluMatrix->KLUmatrixAxComplex = (double *) malloc (2 * nz * sizeof (double)) ;
|
|
Matrix->SMPkluMatrix->KLUmatrixIntermediateComplex = (double *) malloc (2 * Matrix->SMPkluMatrix->KLUmatrixN * sizeof (double)) ;
|
|
|
|
/* Populate the compressed COO elements and COO value of Binding Table */
|
|
j = 0 ;
|
|
for (i = 0 ; i < Matrix->SMPkluMatrix->KLUmatrixN * Matrix->SMPkluMatrix->KLUmatrixN ; i++) {
|
|
if ((Matrix->SMPkluMatrix->KLUmatrixRowCOOforCIDER [i] != -1) && (Matrix->SMPkluMatrix->KLUmatrixColCOOforCIDER [i] != -1)) {
|
|
MatrixCOO [j].row = (unsigned int)Matrix->SMPkluMatrix->KLUmatrixRowCOOforCIDER [i] ;
|
|
MatrixCOO [j].col = (unsigned int)Matrix->SMPkluMatrix->KLUmatrixColCOOforCIDER [i] ;
|
|
MatrixCOO [j].pointer = &(Matrix->SMPkluMatrix->KLUmatrixValueComplexCOOforCIDER [2 * i]) ;
|
|
j++ ;
|
|
}
|
|
}
|
|
|
|
/* Order the MatrixCOO along the columns */
|
|
qsort (MatrixCOO, nz, sizeof (ElementKLUforCIDER), CompareColumn) ;
|
|
|
|
/* Order the MatrixCOO along the rows */
|
|
i = 0 ;
|
|
while (i < nz)
|
|
{
|
|
/* Look for the next column */
|
|
for (j = i + 1 ; j < nz ; j++)
|
|
{
|
|
if (MatrixCOO [j].col != MatrixCOO [i].col)
|
|
{
|
|
break ;
|
|
}
|
|
}
|
|
|
|
qsort (MatrixCOO + i, j - i, sizeof (ElementKLUforCIDER), CompareRow) ;
|
|
|
|
i = j ;
|
|
}
|
|
|
|
/* Copy back the Matrix in partial CSC */
|
|
for (i = 0 ; i < nz ; i++)
|
|
{
|
|
Ap_COO [i] = MatrixCOO [i].col ;
|
|
Matrix->SMPkluMatrix->KLUmatrixAi [i] = (int)MatrixCOO [i].row ;
|
|
Matrix->SMPkluMatrix->KLUmatrixBindStructForCIDER [i].COO = MatrixCOO [i].pointer ;
|
|
Matrix->SMPkluMatrix->KLUmatrixBindStructForCIDER [i].CSC_Complex = &(Matrix->SMPkluMatrix->KLUmatrixAxComplex [2 * i]) ;
|
|
}
|
|
|
|
/* Compress the COO Column Index to CSC Column Index */
|
|
Compress (Ap_COO, (unsigned int *)Matrix->SMPkluMatrix->KLUmatrixAp, Matrix->SMPkluMatrix->KLUmatrixN, nz) ;
|
|
|
|
/* Free the temporary stuff */
|
|
free (Ap_COO) ;
|
|
free (MatrixCOO) ;
|
|
|
|
/* Sort the Binding Table */
|
|
qsort (Matrix->SMPkluMatrix->KLUmatrixBindStructForCIDER, nz, sizeof (BindElementKLUforCIDER), BindCompareKLUforCIDER) ;
|
|
|
|
return ;
|
|
}
|
|
#endif
|
|
|
|
/*
|
|
* SMPmakeElt()
|
|
*/
|
|
double *
|
|
SMPmakeElt (SMPmatrix *Matrix, int Row, int Col)
|
|
{
|
|
KluLinkedListCOO *temp ;
|
|
|
|
if (Matrix->CKTkluMODE) {
|
|
if ((Row > 0) && (Col > 0)) {
|
|
Row = Row - 1 ;
|
|
Col = Col - 1 ;
|
|
temp = (KluLinkedListCOO *) malloc (sizeof (KluLinkedListCOO)) ;
|
|
temp->row = (unsigned int)Row ;
|
|
temp->col = (unsigned int)Col ;
|
|
temp->pointer = (double *) malloc (sizeof (double)) ;
|
|
temp->next = Matrix->SMPkluMatrix->KLUmatrixLinkedListCOO ;
|
|
Matrix->SMPkluMatrix->KLUmatrixLinkedListCOO = temp ;
|
|
Matrix->SMPkluMatrix->KLUmatrixLinkedListNZ++ ;
|
|
return temp->pointer ;
|
|
} else {
|
|
return Matrix->SMPkluMatrix->KLUmatrixTrashCOO ;
|
|
}
|
|
} else {
|
|
return spGetElement (Matrix->SPmatrix, Row, Col) ;
|
|
}
|
|
}
|
|
|
|
#ifdef CIDER
|
|
double *
|
|
SMPmakeEltKLUforCIDER (SMPmatrix *Matrix, int Row, int Col)
|
|
{
|
|
if (Matrix->CKTkluMODE) {
|
|
if ((Row > 0) && (Col > 0)) {
|
|
Row = Row - 1 ;
|
|
Col = Col - 1 ;
|
|
Matrix->SMPkluMatrix->KLUmatrixRowCOOforCIDER [Row * (int)Matrix->SMPkluMatrix->KLUmatrixN + Col] = Row ;
|
|
Matrix->SMPkluMatrix->KLUmatrixColCOOforCIDER [Row * (int)Matrix->SMPkluMatrix->KLUmatrixN + Col] = Col ;
|
|
return &(Matrix->SMPkluMatrix->KLUmatrixValueComplexCOOforCIDER [2 * (Row * (int)Matrix->SMPkluMatrix->KLUmatrixN + Col)]) ;
|
|
} else {
|
|
return Matrix->SMPkluMatrix->KLUmatrixTrashCOO ;
|
|
}
|
|
} else {
|
|
return spGetElement (Matrix->SPmatrix, Row, Col) ;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
/*
|
|
* SMPcClear()
|
|
*/
|
|
|
|
void
|
|
SMPcClear (SMPmatrix *Matrix)
|
|
{
|
|
unsigned int i ;
|
|
|
|
if (Matrix->CKTkluMODE)
|
|
{
|
|
for (i = 0 ; i < 2 * Matrix->SMPkluMatrix->KLUmatrixNZ ; i++) {
|
|
Matrix->SMPkluMatrix->KLUmatrixAxComplex [i] = 0 ;
|
|
}
|
|
} else {
|
|
spClear (Matrix->SPmatrix) ;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* SMPclear()
|
|
*/
|
|
|
|
void
|
|
SMPclear (SMPmatrix *Matrix)
|
|
{
|
|
unsigned int i ;
|
|
|
|
if (Matrix->CKTkluMODE)
|
|
{
|
|
for (i = 0 ; i < Matrix->SMPkluMatrix->KLUmatrixNZ ; i++) {
|
|
Matrix->SMPkluMatrix->KLUmatrixAx [i] = 0 ;
|
|
}
|
|
} else {
|
|
spClear (Matrix->SPmatrix) ;
|
|
}
|
|
}
|
|
|
|
#ifdef CIDER
|
|
void
|
|
SMPclearKLUforCIDER (SMPmatrix *Matrix)
|
|
{
|
|
unsigned int i ;
|
|
|
|
for (i = 0 ; i < 2 * Matrix->SMPkluMatrix->KLUmatrixNZ ; i++) {
|
|
Matrix->SMPkluMatrix->KLUmatrixAxComplex [i] = 0 ;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
#define NG_IGNORE(x) (void)x
|
|
|
|
/*
|
|
* SMPcLUfac()
|
|
*/
|
|
/*ARGSUSED*/
|
|
|
|
int
|
|
SMPcLUfac (SMPmatrix *Matrix, double PivTol)
|
|
{
|
|
int ret ;
|
|
|
|
NG_IGNORE (PivTol) ;
|
|
|
|
if (Matrix->CKTkluMODE)
|
|
{
|
|
ret = klu_z_refactor (Matrix->SMPkluMatrix->KLUmatrixAp, Matrix->SMPkluMatrix->KLUmatrixAi, Matrix->SMPkluMatrix->KLUmatrixAxComplex,
|
|
Matrix->SMPkluMatrix->KLUmatrixSymbolic, Matrix->SMPkluMatrix->KLUmatrixNumeric, Matrix->SMPkluMatrix->KLUmatrixCommon) ;
|
|
|
|
if (ret == 0)
|
|
{
|
|
if (Matrix->SMPkluMatrix->KLUmatrixCommon->status == KLU_SINGULAR) {
|
|
fprintf (stderr, "Warning (ReFactor): KLU Matrix is SINGULAR\n") ;
|
|
return E_SINGULAR ;
|
|
}
|
|
if (Matrix->SMPkluMatrix->KLUmatrixCommon == NULL) {
|
|
fprintf (stderr, "Error (ReFactor): KLUcommon object is NULL. A problem occurred\n") ;
|
|
}
|
|
if (Matrix->SMPkluMatrix->KLUmatrixCommon->status == KLU_EMPTY_MATRIX)
|
|
{
|
|
fprintf (stderr, "Error (ReFactor): KLU Matrix is empty\n") ;
|
|
}
|
|
if (Matrix->SMPkluMatrix->KLUmatrixNumeric == NULL) {
|
|
fprintf (stderr, "Error (ReFactor): KLUnumeric object is NULL. A problem occurred\n") ;
|
|
}
|
|
return 1 ;
|
|
} else {
|
|
return 0 ;
|
|
}
|
|
} else {
|
|
spSetComplex (Matrix->SPmatrix) ;
|
|
return spFactor (Matrix->SPmatrix) ;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* SMPluFac()
|
|
*/
|
|
/*ARGSUSED*/
|
|
|
|
int
|
|
SMPluFac (SMPmatrix *Matrix, double PivTol, double Gmin)
|
|
{
|
|
int ret ;
|
|
|
|
NG_IGNORE (PivTol) ;
|
|
|
|
if (Matrix->CKTkluMODE)
|
|
{
|
|
LoadGmin_CSC (Matrix->SMPkluMatrix->KLUmatrixDiag, Matrix->SMPkluMatrix->KLUmatrixN, Gmin) ;
|
|
|
|
ret = klu_refactor (Matrix->SMPkluMatrix->KLUmatrixAp, Matrix->SMPkluMatrix->KLUmatrixAi, Matrix->SMPkluMatrix->KLUmatrixAx,
|
|
Matrix->SMPkluMatrix->KLUmatrixSymbolic, Matrix->SMPkluMatrix->KLUmatrixNumeric, Matrix->SMPkluMatrix->KLUmatrixCommon) ;
|
|
|
|
if (ret == 0)
|
|
{
|
|
if (Matrix->SMPkluMatrix->KLUmatrixCommon->status == KLU_SINGULAR) {
|
|
fprintf (stderr, "Warning (ReFactor): KLU Matrix is SINGULAR\n") ;
|
|
return E_SINGULAR ;
|
|
}
|
|
if (Matrix->SMPkluMatrix->KLUmatrixCommon == NULL) {
|
|
fprintf (stderr, "Error (ReFactor): KLUcommon object is NULL. A problem occurred\n") ;
|
|
}
|
|
if (Matrix->SMPkluMatrix->KLUmatrixCommon->status == KLU_EMPTY_MATRIX)
|
|
{
|
|
fprintf (stderr, "Error (ReFactor): KLU Matrix is empty\n") ;
|
|
}
|
|
if (Matrix->SMPkluMatrix->KLUmatrixNumeric == NULL) {
|
|
fprintf (stderr, "Error (ReFactor): KLUnumeric object is NULL. A problem occurred\n") ;
|
|
}
|
|
return 1 ;
|
|
} else {
|
|
return 0 ;
|
|
}
|
|
} else {
|
|
spSetReal (Matrix->SPmatrix) ;
|
|
LoadGmin (Matrix, Gmin) ;
|
|
return spFactor (Matrix->SPmatrix) ;
|
|
}
|
|
}
|
|
|
|
#ifdef CIDER
|
|
int
|
|
SMPluFacKLUforCIDER (SMPmatrix *Matrix)
|
|
{
|
|
unsigned int i ;
|
|
double *KLUmatrixAx ;
|
|
int ret ;
|
|
|
|
if (Matrix->CKTkluMODE)
|
|
{
|
|
if (Matrix->SMPkluMatrix->KLUmatrixIsComplex) {
|
|
ret = klu_z_refactor (Matrix->SMPkluMatrix->KLUmatrixAp, Matrix->SMPkluMatrix->KLUmatrixAi, Matrix->SMPkluMatrix->KLUmatrixAxComplex,
|
|
Matrix->SMPkluMatrix->KLUmatrixSymbolic, Matrix->SMPkluMatrix->KLUmatrixNumeric, Matrix->SMPkluMatrix->KLUmatrixCommon) ;
|
|
} else {
|
|
/* Allocate the Real Matrix */
|
|
KLUmatrixAx = (double *) malloc (Matrix->SMPkluMatrix->KLUmatrixNZ * sizeof(double)) ;
|
|
|
|
/* Copy the Complex Matrix into the Real Matrix */
|
|
for (i = 0 ; i < Matrix->SMPkluMatrix->KLUmatrixNZ ; i++) {
|
|
KLUmatrixAx [i] = Matrix->SMPkluMatrix->KLUmatrixAxComplex [2 * i] ;
|
|
}
|
|
|
|
/* Re-Factor the Real Matrix */
|
|
ret = klu_refactor (Matrix->SMPkluMatrix->KLUmatrixAp, Matrix->SMPkluMatrix->KLUmatrixAi, KLUmatrixAx,
|
|
Matrix->SMPkluMatrix->KLUmatrixSymbolic, Matrix->SMPkluMatrix->KLUmatrixNumeric, Matrix->SMPkluMatrix->KLUmatrixCommon) ;
|
|
|
|
/* Free the Real Matrix Storage */
|
|
free (KLUmatrixAx) ;
|
|
}
|
|
|
|
if (ret == 0)
|
|
{
|
|
if (Matrix->SMPkluMatrix->KLUmatrixCommon->status == KLU_SINGULAR) {
|
|
fprintf (stderr, "Warning (ReFactor): KLU Matrix is SINGULAR\n") ;
|
|
return E_SINGULAR ;
|
|
}
|
|
if (Matrix->SMPkluMatrix->KLUmatrixCommon == NULL) {
|
|
fprintf (stderr, "Error (ReFactor): KLUcommon object is NULL. A problem occurred\n") ;
|
|
}
|
|
if (Matrix->SMPkluMatrix->KLUmatrixCommon->status == KLU_EMPTY_MATRIX)
|
|
{
|
|
fprintf (stderr, "Error (ReFactor): KLU Matrix is empty\n") ;
|
|
}
|
|
if (Matrix->SMPkluMatrix->KLUmatrixNumeric == NULL) {
|
|
fprintf (stderr, "Error (ReFactor): KLUnumeric object is NULL. A problem occurred\n") ;
|
|
}
|
|
return 1 ;
|
|
} else {
|
|
return 0 ;
|
|
}
|
|
} else {
|
|
return spFactor (Matrix->SPmatrix) ;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
/*
|
|
* SMPcReorder()
|
|
*/
|
|
|
|
int
|
|
SMPcReorder (SMPmatrix *Matrix, double PivTol, double PivRel, int *NumSwaps)
|
|
{
|
|
if (Matrix->CKTkluMODE)
|
|
{
|
|
Matrix->SMPkluMatrix->KLUmatrixCommon->tol = PivTol ;
|
|
|
|
if (Matrix->SMPkluMatrix->KLUmatrixNumeric != NULL) {
|
|
klu_free_numeric (&(Matrix->SMPkluMatrix->KLUmatrixNumeric), Matrix->SMPkluMatrix->KLUmatrixCommon) ;
|
|
}
|
|
Matrix->SMPkluMatrix->KLUmatrixNumeric = klu_z_factor (Matrix->SMPkluMatrix->KLUmatrixAp, Matrix->SMPkluMatrix->KLUmatrixAi,
|
|
Matrix->SMPkluMatrix->KLUmatrixAxComplex, Matrix->SMPkluMatrix->KLUmatrixSymbolic,
|
|
Matrix->SMPkluMatrix->KLUmatrixCommon) ;
|
|
|
|
if (Matrix->SMPkluMatrix->KLUmatrixNumeric == NULL)
|
|
{
|
|
fprintf (stderr, "Error (Factor): KLUnumeric object is NULL. A problem occurred\n") ;
|
|
if (Matrix->SMPkluMatrix->KLUmatrixCommon->status == KLU_SINGULAR) {
|
|
fprintf (stderr, "Warning (Factor): KLU Matrix is SINGULAR\n") ;
|
|
return 0 ;
|
|
}
|
|
if (Matrix->SMPkluMatrix->KLUmatrixCommon == NULL) {
|
|
fprintf (stderr, "Error (Factor): KLUcommon object is NULL. A problem occurred\n") ;
|
|
}
|
|
if (Matrix->SMPkluMatrix->KLUmatrixCommon->status == KLU_EMPTY_MATRIX) {
|
|
fprintf (stderr, "Error (Factor): KLU Matrix is empty\n") ;
|
|
}
|
|
if (Matrix->SMPkluMatrix->KLUmatrixSymbolic == NULL) {
|
|
fprintf (stderr, "Error (Factor): KLUsymbolic object is NULL. A problem occurred\n") ;
|
|
}
|
|
return 1 ;
|
|
} else {
|
|
return 0 ;
|
|
}
|
|
} else {
|
|
*NumSwaps = 1 ;
|
|
spSetComplex (Matrix->SPmatrix) ;
|
|
return spOrderAndFactor (Matrix->SPmatrix, NULL, (spREAL)PivRel, (spREAL)PivTol, YES) ;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* SMPreorder()
|
|
*/
|
|
|
|
int
|
|
SMPreorder (SMPmatrix *Matrix, double PivTol, double PivRel, double Gmin)
|
|
{
|
|
if (Matrix->CKTkluMODE)
|
|
{
|
|
LoadGmin_CSC (Matrix->SMPkluMatrix->KLUmatrixDiag, Matrix->SMPkluMatrix->KLUmatrixN, Gmin) ;
|
|
Matrix->SMPkluMatrix->KLUmatrixCommon->tol = PivTol ;
|
|
|
|
if (Matrix->SMPkluMatrix->KLUmatrixNumeric != NULL) {
|
|
klu_free_numeric (&(Matrix->SMPkluMatrix->KLUmatrixNumeric), Matrix->SMPkluMatrix->KLUmatrixCommon) ;
|
|
}
|
|
|
|
Matrix->SMPkluMatrix->KLUmatrixNumeric = klu_factor (Matrix->SMPkluMatrix->KLUmatrixAp, Matrix->SMPkluMatrix->KLUmatrixAi,
|
|
Matrix->SMPkluMatrix->KLUmatrixAx, Matrix->SMPkluMatrix->KLUmatrixSymbolic,
|
|
Matrix->SMPkluMatrix->KLUmatrixCommon) ;
|
|
|
|
if (Matrix->SMPkluMatrix->KLUmatrixNumeric == NULL)
|
|
{
|
|
fprintf (stderr, "Error (Factor): KLUnumeric object is NULL. A problem occurred\n") ;
|
|
if (Matrix->SMPkluMatrix->KLUmatrixCommon->status == KLU_SINGULAR) {
|
|
fprintf (stderr, "Warning (Factor): KLU Matrix is SINGULAR\n") ;
|
|
return 0 ;
|
|
}
|
|
if (Matrix->SMPkluMatrix->KLUmatrixCommon == NULL) {
|
|
fprintf (stderr, "Error (Factor): KLUcommon object is NULL. A problem occurred\n") ;
|
|
}
|
|
if (Matrix->SMPkluMatrix->KLUmatrixCommon->status == KLU_EMPTY_MATRIX) {
|
|
fprintf (stderr, "Error (Factor): KLU Matrix is empty\n") ;
|
|
}
|
|
if (Matrix->SMPkluMatrix->KLUmatrixSymbolic == NULL) {
|
|
fprintf (stderr, "Error (Factor): KLUsymbolic object is NULL. A problem occurred\n") ;
|
|
}
|
|
return 1 ;
|
|
} else {
|
|
return 0 ;
|
|
}
|
|
} else {
|
|
spSetReal (Matrix->SPmatrix) ;
|
|
LoadGmin (Matrix, Gmin) ;
|
|
return spOrderAndFactor (Matrix->SPmatrix, NULL, (spREAL)PivRel, (spREAL)PivTol, YES) ;
|
|
}
|
|
}
|
|
|
|
#ifdef CIDER
|
|
int
|
|
SMPreorderKLUforCIDER (SMPmatrix *Matrix)
|
|
{
|
|
unsigned int i ;
|
|
double *KLUmatrixAx ;
|
|
|
|
if (Matrix->CKTkluMODE)
|
|
{
|
|
if (Matrix->SMPkluMatrix->KLUmatrixNumeric != NULL) {
|
|
klu_free_numeric (&(Matrix->SMPkluMatrix->KLUmatrixNumeric), Matrix->SMPkluMatrix->KLUmatrixCommon) ;
|
|
}
|
|
if (Matrix->SMPkluMatrix->KLUmatrixIsComplex) {
|
|
Matrix->SMPkluMatrix->KLUmatrixNumeric = klu_z_factor (Matrix->SMPkluMatrix->KLUmatrixAp, Matrix->SMPkluMatrix->KLUmatrixAi,
|
|
Matrix->SMPkluMatrix->KLUmatrixAxComplex, Matrix->SMPkluMatrix->KLUmatrixSymbolic,
|
|
Matrix->SMPkluMatrix->KLUmatrixCommon) ;
|
|
} else {
|
|
/* Allocate the Real Matrix */
|
|
KLUmatrixAx = (double *) malloc (Matrix->SMPkluMatrix->KLUmatrixNZ * sizeof(double)) ;
|
|
|
|
/* Copy the Complex Matrix into the Real Matrix */
|
|
for (i = 0 ; i < Matrix->SMPkluMatrix->KLUmatrixNZ ; i++) {
|
|
KLUmatrixAx [i] = Matrix->SMPkluMatrix->KLUmatrixAxComplex [2 * i] ;
|
|
}
|
|
|
|
/* Factor the Real Matrix */
|
|
Matrix->SMPkluMatrix->KLUmatrixNumeric = klu_factor (Matrix->SMPkluMatrix->KLUmatrixAp, Matrix->SMPkluMatrix->KLUmatrixAi,
|
|
KLUmatrixAx, Matrix->SMPkluMatrix->KLUmatrixSymbolic,
|
|
Matrix->SMPkluMatrix->KLUmatrixCommon) ;
|
|
|
|
/* Free the Real Matrix Storage */
|
|
free (KLUmatrixAx) ;
|
|
}
|
|
|
|
if (Matrix->SMPkluMatrix->KLUmatrixNumeric == NULL)
|
|
{
|
|
fprintf (stderr, "Error (Factor): KLUnumeric object is NULL. A problem occurred\n") ;
|
|
if (Matrix->SMPkluMatrix->KLUmatrixCommon->status == KLU_SINGULAR) {
|
|
fprintf (stderr, "Warning (Factor): KLU Matrix is SINGULAR\n") ;
|
|
return 0 ;
|
|
}
|
|
if (Matrix->SMPkluMatrix->KLUmatrixCommon == NULL) {
|
|
fprintf (stderr, "Error (Factor): KLUcommon object is NULL. A problem occurred\n") ;
|
|
}
|
|
if (Matrix->SMPkluMatrix->KLUmatrixCommon->status == KLU_EMPTY_MATRIX) {
|
|
fprintf (stderr, "Error (Factor): KLU Matrix is empty\n") ;
|
|
}
|
|
if (Matrix->SMPkluMatrix->KLUmatrixSymbolic == NULL) {
|
|
fprintf (stderr, "Error (Factor): KLUsymbolic object is NULL. A problem occurred\n") ;
|
|
}
|
|
return 1 ;
|
|
} else {
|
|
return 0 ;
|
|
}
|
|
} else {
|
|
return spFactor (Matrix->SPmatrix) ;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
/*
|
|
* SMPcaSolve()
|
|
*/
|
|
void
|
|
SMPcaSolve (SMPmatrix *Matrix, double RHS[], double iRHS[], double Spare[], double iSpare[])
|
|
{
|
|
int ret ;
|
|
unsigned int i ;
|
|
|
|
NG_IGNORE (iSpare) ;
|
|
NG_IGNORE (Spare) ;
|
|
|
|
if (Matrix->CKTkluMODE)
|
|
{
|
|
for (i = 0 ; i < Matrix->SMPkluMatrix->KLUmatrixN ; i++)
|
|
{
|
|
Matrix->SMPkluMatrix->KLUmatrixIntermediateComplex [2 * i] = RHS [i + 1] ;
|
|
Matrix->SMPkluMatrix->KLUmatrixIntermediateComplex [2 * i + 1] = iRHS [i + 1] ;
|
|
}
|
|
|
|
ret = klu_z_solve (Matrix->SMPkluMatrix->KLUmatrixSymbolic, Matrix->SMPkluMatrix->KLUmatrixNumeric, (int)Matrix->SMPkluMatrix->KLUmatrixN, 1,
|
|
Matrix->SMPkluMatrix->KLUmatrixIntermediateComplex, Matrix->SMPkluMatrix->KLUmatrixCommon) ;
|
|
|
|
for (i = 0 ; i < Matrix->SMPkluMatrix->KLUmatrixN ; i++)
|
|
{
|
|
RHS [i + 1] = Matrix->SMPkluMatrix->KLUmatrixIntermediateComplex [2 * i] ;
|
|
iRHS [i + 1] = Matrix->SMPkluMatrix->KLUmatrixIntermediateComplex [2 * i + 1] ;
|
|
}
|
|
} else {
|
|
spSolveTransposed (Matrix->SPmatrix, RHS, RHS, iRHS, iRHS) ;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* SMPcSolve()
|
|
*/
|
|
|
|
void
|
|
SMPcSolve (SMPmatrix *Matrix, double RHS[], double iRHS[], double Spare[], double iSpare[])
|
|
{
|
|
int ret ;
|
|
unsigned int i ;
|
|
|
|
NG_IGNORE (iSpare) ;
|
|
NG_IGNORE (Spare) ;
|
|
|
|
if (Matrix->CKTkluMODE)
|
|
{
|
|
for (i = 0 ; i < Matrix->SMPkluMatrix->KLUmatrixN ; i++)
|
|
{
|
|
Matrix->SMPkluMatrix->KLUmatrixIntermediateComplex [2 * i] = RHS [i + 1] ;
|
|
Matrix->SMPkluMatrix->KLUmatrixIntermediateComplex [2 * i + 1] = iRHS [i + 1] ;
|
|
}
|
|
|
|
ret = klu_z_solve (Matrix->SMPkluMatrix->KLUmatrixSymbolic, Matrix->SMPkluMatrix->KLUmatrixNumeric, (int)Matrix->SMPkluMatrix->KLUmatrixN, 1,
|
|
Matrix->SMPkluMatrix->KLUmatrixIntermediateComplex, Matrix->SMPkluMatrix->KLUmatrixCommon) ;
|
|
|
|
for (i = 0 ; i < Matrix->SMPkluMatrix->KLUmatrixN ; i++)
|
|
{
|
|
RHS [i + 1] = Matrix->SMPkluMatrix->KLUmatrixIntermediateComplex [2 * i] ;
|
|
iRHS [i + 1] = Matrix->SMPkluMatrix->KLUmatrixIntermediateComplex [2 * i + 1] ;
|
|
}
|
|
} else {
|
|
spSolve (Matrix->SPmatrix, RHS, RHS, iRHS, iRHS) ;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* SMPsolve()
|
|
*/
|
|
|
|
void
|
|
SMPsolve (SMPmatrix *Matrix, double RHS[], double Spare[])
|
|
{
|
|
int ret ;
|
|
unsigned int i ;
|
|
|
|
NG_IGNORE (Spare) ;
|
|
|
|
if (Matrix->CKTkluMODE)
|
|
{
|
|
for (i = 0 ; i < Matrix->SMPkluMatrix->KLUmatrixN ; i++) {
|
|
Matrix->SMPkluMatrix->KLUmatrixIntermediate [i] = RHS [i + 1] ;
|
|
}
|
|
|
|
ret = klu_solve (Matrix->SMPkluMatrix->KLUmatrixSymbolic, Matrix->SMPkluMatrix->KLUmatrixNumeric, (int)Matrix->SMPkluMatrix->KLUmatrixN, 1,
|
|
Matrix->SMPkluMatrix->KLUmatrixIntermediate, Matrix->SMPkluMatrix->KLUmatrixCommon) ;
|
|
|
|
if (ret == 0)
|
|
{
|
|
if (Matrix->SMPkluMatrix->KLUmatrixCommon->status == KLU_SINGULAR) {
|
|
fprintf (stderr, "Warning (Solve): KLU Matrix is SINGULAR\n") ;
|
|
}
|
|
if (Matrix->SMPkluMatrix->KLUmatrixCommon == NULL) {
|
|
fprintf (stderr, "Error (Solve): KLUcommon object is NULL. A problem occurred\n") ;
|
|
}
|
|
if (Matrix->SMPkluMatrix->KLUmatrixCommon->status == KLU_EMPTY_MATRIX)
|
|
{
|
|
fprintf (stderr, "Error (Solve): KLU Matrix is empty\n") ;
|
|
}
|
|
if (Matrix->SMPkluMatrix->KLUmatrixNumeric == NULL) {
|
|
fprintf (stderr, "Error (Solve): KLUnumeric object is NULL. A problem occurred\n") ;
|
|
}
|
|
if (Matrix->SMPkluMatrix->KLUmatrixSymbolic == NULL) {
|
|
fprintf (stderr, "Error (Solve): KLUsymbolic object is NULL. A problem occurred\n") ;
|
|
}
|
|
}
|
|
|
|
for (i = 0 ; i < Matrix->SMPkluMatrix->KLUmatrixN ; i++) {
|
|
RHS [i + 1] = Matrix->SMPkluMatrix->KLUmatrixIntermediate [i] ;
|
|
}
|
|
} else {
|
|
spSolve (Matrix->SPmatrix, RHS, RHS, NULL, NULL) ;
|
|
}
|
|
}
|
|
|
|
#ifdef CIDER
|
|
void
|
|
SMPsolveKLUforCIDER (SMPmatrix *Matrix, double RHS[], double RHSsolution[], double iRHS[], double iRHSsolution[])
|
|
{
|
|
int ret ;
|
|
unsigned int i ;
|
|
double *KLUmatrixIntermediate ;
|
|
|
|
if (Matrix->CKTkluMODE)
|
|
{
|
|
if (Matrix->SMPkluMatrix->KLUmatrixIsComplex) {
|
|
for (i = 0 ; i < Matrix->SMPkluMatrix->KLUmatrixN ; i++)
|
|
{
|
|
Matrix->SMPkluMatrix->KLUmatrixIntermediateComplex [2 * i] = RHS [i + 1] ;
|
|
Matrix->SMPkluMatrix->KLUmatrixIntermediateComplex [2 * i + 1] = iRHS [i + 1] ;
|
|
}
|
|
|
|
ret = klu_z_solve (Matrix->SMPkluMatrix->KLUmatrixSymbolic, Matrix->SMPkluMatrix->KLUmatrixNumeric, (int)Matrix->SMPkluMatrix->KLUmatrixN, 1,
|
|
Matrix->SMPkluMatrix->KLUmatrixIntermediateComplex, Matrix->SMPkluMatrix->KLUmatrixCommon) ;
|
|
|
|
for (i = 0 ; i < Matrix->SMPkluMatrix->KLUmatrixN ; i++)
|
|
{
|
|
RHSsolution [i + 1] = Matrix->SMPkluMatrix->KLUmatrixIntermediateComplex [2 * i] ;
|
|
iRHSsolution [i + 1] = Matrix->SMPkluMatrix->KLUmatrixIntermediateComplex [2 * i + 1] ;
|
|
}
|
|
} else {
|
|
/* Allocate the Intermediate Vector */
|
|
KLUmatrixIntermediate = (double *) malloc (Matrix->SMPkluMatrix->KLUmatrixN * sizeof(double)) ;
|
|
|
|
for (i = 0 ; i < Matrix->SMPkluMatrix->KLUmatrixN ; i++) {
|
|
KLUmatrixIntermediate [i] = RHS [i + 1] ;
|
|
}
|
|
|
|
ret = klu_solve (Matrix->SMPkluMatrix->KLUmatrixSymbolic, Matrix->SMPkluMatrix->KLUmatrixNumeric, (int)Matrix->SMPkluMatrix->KLUmatrixN, 1,
|
|
KLUmatrixIntermediate, Matrix->SMPkluMatrix->KLUmatrixCommon) ;
|
|
|
|
for (i = 0 ; i < Matrix->SMPkluMatrix->KLUmatrixN ; i++) {
|
|
RHSsolution [i + 1] = KLUmatrixIntermediate [i] ;
|
|
}
|
|
|
|
/* Free the Intermediate Vector */
|
|
free (KLUmatrixIntermediate) ;
|
|
}
|
|
|
|
} else {
|
|
|
|
spSolve (Matrix->SPmatrix, RHS, RHSsolution, iRHS, iRHSsolution) ;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
/*
|
|
* SMPmatSize()
|
|
*/
|
|
int
|
|
SMPmatSize (SMPmatrix *Matrix)
|
|
{
|
|
if (Matrix->CKTkluMODE) {
|
|
return (int)Matrix->SMPkluMatrix->KLUmatrixN ;
|
|
} else {
|
|
return spGetSize (Matrix->SPmatrix, 1) ;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* SMPnewMatrix()
|
|
*/
|
|
int
|
|
SMPnewMatrix (SMPmatrix *Matrix, int size)
|
|
{
|
|
int Error ;
|
|
|
|
if (Matrix->CKTkluMODE) {
|
|
/* Allocate the KLU Matrix Data Structure */
|
|
Matrix->SMPkluMatrix = (KLUmatrix *) malloc (sizeof (KLUmatrix)) ;
|
|
Matrix->SMPkluMatrix->KLUmatrixLinkedListNZ = 0 ;
|
|
Matrix->SMPkluMatrix->KLUmatrixLinkedListCOO = NULL ;
|
|
|
|
/* Initialize the KLU Matrix Internal Pointers */
|
|
Matrix->SMPkluMatrix->KLUmatrixCommon = (klu_common *) malloc (sizeof (klu_common)) ; ;
|
|
Matrix->SMPkluMatrix->KLUmatrixSymbolic = NULL ;
|
|
Matrix->SMPkluMatrix->KLUmatrixNumeric = NULL ;
|
|
Matrix->SMPkluMatrix->KLUmatrixAp = NULL ;
|
|
Matrix->SMPkluMatrix->KLUmatrixAi = NULL ;
|
|
Matrix->SMPkluMatrix->KLUmatrixAx = NULL ;
|
|
Matrix->SMPkluMatrix->KLUmatrixAxComplex = NULL ;
|
|
Matrix->SMPkluMatrix->KLUmatrixIsComplex = KLUmatrixReal ;
|
|
Matrix->SMPkluMatrix->KLUmatrixIntermediate = NULL ;
|
|
Matrix->SMPkluMatrix->KLUmatrixIntermediateComplex = NULL ;
|
|
Matrix->SMPkluMatrix->KLUmatrixNZ = 0 ;
|
|
Matrix->SMPkluMatrix->KLUmatrixBindStructCOO = NULL ;
|
|
Matrix->SMPkluMatrix->KLUmatrixDiag = NULL ;
|
|
|
|
/* Initialize the KLU Common Data Structure */
|
|
klu_defaults (Matrix->SMPkluMatrix->KLUmatrixCommon) ;
|
|
Matrix->SMPkluMatrix->KLUmatrixCommon->memgrow = Matrix->CKTkluMemGrowFactor ;
|
|
|
|
/* Allocate KLU data structures */
|
|
Matrix->SMPkluMatrix->KLUmatrixN = (unsigned int)size ;
|
|
Matrix->SMPkluMatrix->KLUmatrixTrashCOO = (double *) malloc (sizeof (double)) ;
|
|
|
|
return spOKAY ;
|
|
} else {
|
|
Matrix->SPmatrix = spCreate (size, 1, &Error) ;
|
|
return Error ;
|
|
}
|
|
}
|
|
|
|
#ifdef CIDER
|
|
int
|
|
SMPnewMatrixKLUforCIDER (SMPmatrix *Matrix, int size, unsigned int KLUmatrixIsComplex)
|
|
{
|
|
int Error ;
|
|
unsigned int i ;
|
|
|
|
if (Matrix->CKTkluMODE) {
|
|
/* Allocate the KLU Matrix Data Structure */
|
|
Matrix->SMPkluMatrix = (KLUmatrix *) malloc (sizeof (KLUmatrix)) ;
|
|
|
|
/* Initialize the KLU Matrix Internal Pointers */
|
|
Matrix->SMPkluMatrix->KLUmatrixCommon = (klu_common *) malloc (sizeof (klu_common)) ; ;
|
|
Matrix->SMPkluMatrix->KLUmatrixSymbolic = NULL ;
|
|
Matrix->SMPkluMatrix->KLUmatrixNumeric = NULL ;
|
|
Matrix->SMPkluMatrix->KLUmatrixAp = NULL ;
|
|
Matrix->SMPkluMatrix->KLUmatrixAi = NULL ;
|
|
Matrix->SMPkluMatrix->KLUmatrixAxComplex = NULL ;
|
|
if (KLUmatrixIsComplex) {
|
|
Matrix->SMPkluMatrix->KLUmatrixIsComplex = KLUMatrixComplex ;
|
|
} else {
|
|
Matrix->SMPkluMatrix->KLUmatrixIsComplex = KLUmatrixReal ;
|
|
}
|
|
Matrix->SMPkluMatrix->KLUmatrixIntermediateComplex = NULL ;
|
|
Matrix->SMPkluMatrix->KLUmatrixNZ = 0 ;
|
|
Matrix->SMPkluMatrix->KLUmatrixBindStructForCIDER = NULL ;
|
|
Matrix->SMPkluMatrix->KLUmatrixValueComplexCOOforCIDER = NULL ;
|
|
|
|
/* Initialize the KLU Common Data Structure */
|
|
klu_defaults (Matrix->SMPkluMatrix->KLUmatrixCommon) ;
|
|
|
|
/* Allocate KLU data structures */
|
|
Matrix->SMPkluMatrix->KLUmatrixN = (unsigned int)size ;
|
|
Matrix->SMPkluMatrix->KLUmatrixColCOOforCIDER = (int *) malloc (Matrix->SMPkluMatrix->KLUmatrixN * Matrix->SMPkluMatrix->KLUmatrixN * sizeof(int)) ;
|
|
Matrix->SMPkluMatrix->KLUmatrixRowCOOforCIDER = (int *) malloc (Matrix->SMPkluMatrix->KLUmatrixN * Matrix->SMPkluMatrix->KLUmatrixN * sizeof(int)) ;
|
|
Matrix->SMPkluMatrix->KLUmatrixTrashCOO = (double *) malloc (sizeof(double)) ;
|
|
Matrix->SMPkluMatrix->KLUmatrixValueComplexCOOforCIDER = (double *) malloc (2 * Matrix->SMPkluMatrix->KLUmatrixN * Matrix->SMPkluMatrix->KLUmatrixN * sizeof(double)) ;
|
|
|
|
/* Pre-set the values of Row and Col */
|
|
for (i = 0 ; i < Matrix->SMPkluMatrix->KLUmatrixN * Matrix->SMPkluMatrix->KLUmatrixN ; i++) {
|
|
Matrix->SMPkluMatrix->KLUmatrixRowCOOforCIDER [i] = -1 ;
|
|
Matrix->SMPkluMatrix->KLUmatrixColCOOforCIDER [i] = -1 ;
|
|
}
|
|
|
|
return spOKAY ;
|
|
} else {
|
|
Matrix->SPmatrix = spCreate (size, (int)KLUmatrixIsComplex, &Error) ;
|
|
return Error ;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
/*
|
|
* SMPdestroy()
|
|
*/
|
|
|
|
void
|
|
SMPdestroy (SMPmatrix *Matrix)
|
|
{
|
|
if (Matrix->CKTkluMODE)
|
|
{
|
|
klu_free_numeric (&(Matrix->SMPkluMatrix->KLUmatrixNumeric), Matrix->SMPkluMatrix->KLUmatrixCommon) ;
|
|
klu_free_symbolic (&(Matrix->SMPkluMatrix->KLUmatrixSymbolic), Matrix->SMPkluMatrix->KLUmatrixCommon) ;
|
|
free (Matrix->SMPkluMatrix->KLUmatrixAp) ;
|
|
free (Matrix->SMPkluMatrix->KLUmatrixAi) ;
|
|
free (Matrix->SMPkluMatrix->KLUmatrixAx) ;
|
|
free (Matrix->SMPkluMatrix->KLUmatrixAxComplex) ;
|
|
free (Matrix->SMPkluMatrix->KLUmatrixIntermediate) ;
|
|
free (Matrix->SMPkluMatrix->KLUmatrixIntermediateComplex) ;
|
|
free (Matrix->SMPkluMatrix->KLUmatrixBindStructCOO) ;
|
|
free (Matrix->SMPkluMatrix->KLUmatrixTrashCOO) ;
|
|
Matrix->SMPkluMatrix->KLUmatrixAp = NULL ;
|
|
Matrix->SMPkluMatrix->KLUmatrixAi = NULL ;
|
|
Matrix->SMPkluMatrix->KLUmatrixAx = NULL ;
|
|
Matrix->SMPkluMatrix->KLUmatrixAxComplex = NULL ;
|
|
Matrix->SMPkluMatrix->KLUmatrixIntermediate = NULL ;
|
|
Matrix->SMPkluMatrix->KLUmatrixIntermediateComplex = NULL ;
|
|
Matrix->SMPkluMatrix->KLUmatrixBindStructCOO = NULL ;
|
|
Matrix->SMPkluMatrix->KLUmatrixTrashCOO = NULL ;
|
|
} else {
|
|
spDestroy (Matrix->SPmatrix) ;
|
|
}
|
|
}
|
|
|
|
#ifdef CIDER
|
|
void
|
|
SMPdestroyKLUforCIDER (SMPmatrix *Matrix)
|
|
{
|
|
if (Matrix->CKTkluMODE)
|
|
{
|
|
klu_free_numeric (&(Matrix->SMPkluMatrix->KLUmatrixNumeric), Matrix->SMPkluMatrix->KLUmatrixCommon) ;
|
|
klu_free_symbolic (&(Matrix->SMPkluMatrix->KLUmatrixSymbolic), Matrix->SMPkluMatrix->KLUmatrixCommon) ;
|
|
free (Matrix->SMPkluMatrix->KLUmatrixAp) ;
|
|
free (Matrix->SMPkluMatrix->KLUmatrixAi) ;
|
|
free (Matrix->SMPkluMatrix->KLUmatrixAxComplex) ;
|
|
free (Matrix->SMPkluMatrix->KLUmatrixIntermediateComplex) ;
|
|
free (Matrix->SMPkluMatrix->KLUmatrixBindStructForCIDER) ;
|
|
free (Matrix->SMPkluMatrix->KLUmatrixColCOOforCIDER) ;
|
|
free (Matrix->SMPkluMatrix->KLUmatrixRowCOOforCIDER) ;
|
|
free (Matrix->SMPkluMatrix->KLUmatrixValueComplexCOOforCIDER) ;
|
|
free (Matrix->SMPkluMatrix->KLUmatrixTrashCOO) ;
|
|
Matrix->SMPkluMatrix->KLUmatrixAp = NULL ;
|
|
Matrix->SMPkluMatrix->KLUmatrixAi = NULL ;
|
|
Matrix->SMPkluMatrix->KLUmatrixAxComplex = NULL ;
|
|
Matrix->SMPkluMatrix->KLUmatrixIntermediateComplex = NULL ;
|
|
Matrix->SMPkluMatrix->KLUmatrixBindStructForCIDER = NULL ;
|
|
Matrix->SMPkluMatrix->KLUmatrixColCOOforCIDER = NULL ;
|
|
Matrix->SMPkluMatrix->KLUmatrixRowCOOforCIDER = NULL ;
|
|
Matrix->SMPkluMatrix->KLUmatrixValueComplexCOOforCIDER = NULL ;
|
|
Matrix->SMPkluMatrix->KLUmatrixTrashCOO = NULL ;
|
|
} else {
|
|
spDestroy (Matrix->SPmatrix) ;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
/*
|
|
* SMPpreOrder()
|
|
*/
|
|
|
|
int
|
|
SMPpreOrder (SMPmatrix *Matrix)
|
|
{
|
|
if (Matrix->CKTkluMODE)
|
|
{
|
|
Matrix->SMPkluMatrix->KLUmatrixSymbolic = klu_analyze ((int)Matrix->SMPkluMatrix->KLUmatrixN, Matrix->SMPkluMatrix->KLUmatrixAp,
|
|
Matrix->SMPkluMatrix->KLUmatrixAi, Matrix->SMPkluMatrix->KLUmatrixCommon) ;
|
|
|
|
if (Matrix->SMPkluMatrix->KLUmatrixSymbolic == NULL)
|
|
{
|
|
fprintf (stderr, "Error (PreOrder): KLUsymbolic object is NULL. A problem occurred\n") ;
|
|
if (Matrix->SMPkluMatrix->KLUmatrixCommon->status == KLU_EMPTY_MATRIX)
|
|
{
|
|
return 0 ;
|
|
}
|
|
return 1 ;
|
|
} else {
|
|
return 0 ;
|
|
}
|
|
} else {
|
|
spMNA_Preorder (Matrix->SPmatrix) ;
|
|
return spError (Matrix->SPmatrix) ;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* SMPprintRHS()
|
|
*/
|
|
|
|
void
|
|
SMPprintRHS (SMPmatrix *Matrix, char *Filename, RealVector RHS, RealVector iRHS)
|
|
{
|
|
if (!Matrix->CKTkluMODE)
|
|
spFileVector (Matrix->SPmatrix, Filename, RHS, iRHS) ;
|
|
}
|
|
|
|
/*
|
|
* SMPprint()
|
|
*/
|
|
|
|
void
|
|
SMPprint (SMPmatrix *Matrix, char *Filename)
|
|
{
|
|
if (Matrix->CKTkluMODE)
|
|
{
|
|
if (Matrix->SMPkluMatrix->KLUmatrixIsComplex)
|
|
{
|
|
klu_z_print (Matrix->SMPkluMatrix->KLUmatrixAp, Matrix->SMPkluMatrix->KLUmatrixAi, Matrix->SMPkluMatrix->KLUmatrixAxComplex,
|
|
(int)Matrix->SMPkluMatrix->KLUmatrixN, NULL, NULL) ;
|
|
} else {
|
|
klu_print (Matrix->SMPkluMatrix->KLUmatrixAp, Matrix->SMPkluMatrix->KLUmatrixAi, Matrix->SMPkluMatrix->KLUmatrixAx,
|
|
(int)Matrix->SMPkluMatrix->KLUmatrixN, NULL, NULL) ;
|
|
}
|
|
} else {
|
|
if (Filename)
|
|
spFileMatrix (Matrix->SPmatrix, Filename, "Circuit Matrix", 0, 1, 1) ;
|
|
else
|
|
spPrint (Matrix->SPmatrix, 0, 1, 1) ;
|
|
}
|
|
}
|
|
|
|
#ifdef CIDER
|
|
void
|
|
SMPprintKLUforCIDER (SMPmatrix *Matrix, char *Filename)
|
|
{
|
|
unsigned int i ;
|
|
double *KLUmatrixAx ;
|
|
|
|
if (Matrix->CKTkluMODE)
|
|
{
|
|
if (Matrix->SMPkluMatrix->KLUmatrixIsComplex)
|
|
{
|
|
klu_z_print (Matrix->SMPkluMatrix->KLUmatrixAp, Matrix->SMPkluMatrix->KLUmatrixAi, Matrix->SMPkluMatrix->KLUmatrixAxComplex,
|
|
(int)Matrix->SMPkluMatrix->KLUmatrixN, NULL, NULL) ;
|
|
} else {
|
|
/* Allocate the Real Matrix */
|
|
KLUmatrixAx = (double *) malloc (Matrix->SMPkluMatrix->KLUmatrixNZ * sizeof(double)) ;
|
|
|
|
/* Copy the Complex Matrix into the Real Matrix */
|
|
for (i = 0 ; i < Matrix->SMPkluMatrix->KLUmatrixNZ ; i++) {
|
|
KLUmatrixAx [i] = Matrix->SMPkluMatrix->KLUmatrixAxComplex [2 * i] ;
|
|
}
|
|
|
|
/* Print the Real Matrix */
|
|
klu_print (Matrix->SMPkluMatrix->KLUmatrixAp, Matrix->SMPkluMatrix->KLUmatrixAi, KLUmatrixAx, (int)Matrix->SMPkluMatrix->KLUmatrixN, NULL, NULL) ;
|
|
|
|
/* Free the Real Matrix Storage */
|
|
free (KLUmatrixAx) ;
|
|
}
|
|
} else {
|
|
if (Filename)
|
|
spFileMatrix (Matrix->SPmatrix, Filename, "Circuit Matrix", 0, 1, 1) ;
|
|
else
|
|
spPrint (Matrix->SPmatrix, 0, 1, 1) ;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
/*
|
|
* SMPgetError()
|
|
*/
|
|
void
|
|
SMPgetError (SMPmatrix *Matrix, int *Col, int *Row)
|
|
{
|
|
if (Matrix->CKTkluMODE)
|
|
{
|
|
*Row = Matrix->SMPkluMatrix->KLUmatrixCommon->singular_col + 1 ;
|
|
*Col = Matrix->SMPkluMatrix->KLUmatrixCommon->singular_col + 1 ;
|
|
} else {
|
|
spWhereSingular (Matrix->SPmatrix, Row, Col) ;
|
|
}
|
|
}
|
|
|
|
void
|
|
spDeterminant_KLU (SMPmatrix *Matrix, int *pExponent, RealNumber *pDeterminant, RealNumber *piDeterminant)
|
|
{
|
|
int I, Size ;
|
|
RealNumber Norm, nr, ni ;
|
|
ComplexNumber Pivot, cDeterminant, Udiag ;
|
|
|
|
int *P, *Q ;
|
|
double *Rs, *Ux, *Uz ;
|
|
unsigned int nSwap, nSwapP, nSwapQ ;
|
|
|
|
#define NORM(a) (nr = ABS((a).Real), ni = ABS((a).Imag), MAX (nr,ni))
|
|
|
|
*pExponent = 0 ;
|
|
|
|
if (Matrix->SMPkluMatrix->KLUmatrixCommon->status == KLU_SINGULAR)
|
|
{
|
|
*pDeterminant = 0.0 ;
|
|
if (Matrix->SMPkluMatrix->KLUmatrixIsComplex == KLUMatrixComplex)
|
|
{
|
|
*piDeterminant = 0.0 ;
|
|
}
|
|
return ;
|
|
}
|
|
|
|
Size = (int)Matrix->SMPkluMatrix->KLUmatrixN ;
|
|
I = 0 ;
|
|
|
|
P = (int *) malloc ((size_t)Matrix->SMPkluMatrix->KLUmatrixN * sizeof (int)) ;
|
|
Q = (int *) malloc ((size_t)Matrix->SMPkluMatrix->KLUmatrixN * sizeof (int)) ;
|
|
|
|
Ux = (double *) malloc ((size_t)Matrix->SMPkluMatrix->KLUmatrixN * sizeof (double)) ;
|
|
|
|
Rs = (double *) malloc ((size_t)Matrix->SMPkluMatrix->KLUmatrixN * sizeof (double)) ;
|
|
|
|
if (Matrix->SMPkluMatrix->KLUmatrixIsComplex == KLUMatrixComplex) /* Complex Case. */
|
|
{
|
|
cDeterminant.Real = 1.0 ;
|
|
cDeterminant.Imag = 0.0 ;
|
|
|
|
Uz = (double *) malloc ((size_t)Matrix->SMPkluMatrix->KLUmatrixN * sizeof (double)) ;
|
|
/*
|
|
int *Lp, *Li, *Up, *Ui, *Fp, *Fi, *P, *Q ;
|
|
double *Lx, *Lz, *Ux, *Uz, *Fx, *Fz, *Rs ;
|
|
Lp = (int *) malloc (((size_t)Matrix->CKTkluN + 1) * sizeof (int)) ;
|
|
Li = (int *) malloc ((size_t)Matrix->CKTkluNumeric->lnz * sizeof (int)) ;
|
|
Lx = (double *) malloc ((size_t)Matrix->CKTkluNumeric->lnz * sizeof (double)) ;
|
|
Lz = (double *) malloc ((size_t)Matrix->CKTkluNumeric->lnz * sizeof (double)) ;
|
|
Up = (int *) malloc (((size_t)Matrix->CKTkluN + 1) * sizeof (int)) ;
|
|
Ui = (int *) malloc ((size_t)Matrix->CKTkluNumeric->unz * sizeof (int)) ;
|
|
Ux = (double *) malloc ((size_t)Matrix->CKTkluNumeric->unz * sizeof (double)) ;
|
|
Uz = (double *) malloc ((size_t)Matrix->CKTkluNumeric->unz * sizeof (double)) ;
|
|
Fp = (int *) malloc (((size_t)Matrix->CKTkluN + 1) * sizeof (int)) ;
|
|
Fi = (int *) malloc ((size_t)Matrix->CKTkluNumeric->Offp [Matrix->CKTkluN] * sizeof (int)) ;
|
|
Fx = (double *) malloc ((size_t)Matrix->CKTkluNumeric->Offp [Matrix->CKTkluN] * sizeof (double)) ;
|
|
Fz = (double *) malloc ((size_t)Matrix->CKTkluNumeric->Offp [Matrix->CKTkluN] * sizeof (double)) ;
|
|
klu_z_extract (Matrix->CKTkluNumeric, Matrix->CKTkluSymbolic,
|
|
Lp, Li, Lx, Lz,
|
|
Up, Ui, Ux, Uz,
|
|
Fp, Fi, Fx, Fz,
|
|
P, Q, Rs, NULL,
|
|
Matrix->CKTkluCommon) ;
|
|
*/
|
|
klu_z_extract_Udiag (Matrix->SMPkluMatrix->KLUmatrixNumeric, Matrix->SMPkluMatrix->KLUmatrixSymbolic, Ux, Uz, P, Q, Rs, Matrix->SMPkluMatrix->KLUmatrixCommon) ;
|
|
/*
|
|
for (I = 0 ; I < Matrix->CKTkluNumeric->lnz ; I++)
|
|
{
|
|
printf ("L - Value: %-.9g\t%-.9g\n", Lx [I], Lz [I]) ;
|
|
}
|
|
for (I = 0 ; I < Matrix->CKTkluNumeric->unz ; I++)
|
|
{
|
|
printf ("U - Value: %-.9g\t%-.9g\n", Ux [I], Uz [I]) ;
|
|
}
|
|
for (I = 0 ; I < Matrix->CKTkluNumeric->Offp [Matrix->CKTkluN] ; I++)
|
|
{
|
|
printf ("F - Value: %-.9g\t%-.9g\n", Fx [I], Fz [I]) ;
|
|
}
|
|
|
|
for (I = 0 ; I < Matrix->CKTkluN ; I++)
|
|
{
|
|
printf ("U - Value: %-.9g\t%-.9g\n", Ux [I], Uz [I]) ;
|
|
}
|
|
*/
|
|
nSwapP = 0 ;
|
|
for (I = 0 ; I < (int)Matrix->SMPkluMatrix->KLUmatrixN ; I++)
|
|
{
|
|
if (P [I] != I)
|
|
{
|
|
nSwapP++ ;
|
|
}
|
|
}
|
|
nSwapP /= 2 ;
|
|
|
|
nSwapQ = 0 ;
|
|
for (I = 0 ; I < (int)Matrix->SMPkluMatrix->KLUmatrixN ; I++)
|
|
{
|
|
if (Q [I] != I)
|
|
{
|
|
nSwapQ++ ;
|
|
}
|
|
}
|
|
nSwapQ /= 2 ;
|
|
|
|
nSwap = nSwapP + nSwapQ ;
|
|
/*
|
|
free (Lp) ;
|
|
free (Li) ;
|
|
free (Lx) ;
|
|
free (Lz) ;
|
|
free (Up) ;
|
|
free (Ui) ;
|
|
free (Fp) ;
|
|
free (Fi) ;
|
|
free (Fx) ;
|
|
free (Fz) ;
|
|
*/
|
|
I = 0 ;
|
|
while (I < Size)
|
|
{
|
|
Udiag.Real = 1 / (Ux [I] * Rs [I]) ;
|
|
Udiag.Imag = Uz [I] * Rs [I] ;
|
|
|
|
// printf ("Udiag.Real: %-.9g\tUdiag.Imag %-.9g\n", Udiag.Real, Udiag.Imag) ;
|
|
|
|
CMPLX_RECIPROCAL (Pivot, Udiag) ;
|
|
CMPLX_MULT_ASSIGN (cDeterminant, Pivot) ;
|
|
|
|
// printf ("cDeterminant.Real: %-.9g\tcDeterminant.Imag %-.9g\n", cDeterminant.Real, cDeterminant.Imag) ;
|
|
|
|
/* Scale Determinant. */
|
|
Norm = NORM (cDeterminant) ;
|
|
if (Norm != 0.0)
|
|
{
|
|
while (Norm >= 1.0e12)
|
|
{
|
|
cDeterminant.Real *= 1.0e-12 ;
|
|
cDeterminant.Imag *= 1.0e-12 ;
|
|
*pExponent += 12 ;
|
|
Norm = NORM (cDeterminant) ;
|
|
}
|
|
while (Norm < 1.0e-12)
|
|
{
|
|
cDeterminant.Real *= 1.0e12 ;
|
|
cDeterminant.Imag *= 1.0e12 ;
|
|
*pExponent -= 12 ;
|
|
Norm = NORM (cDeterminant) ;
|
|
}
|
|
}
|
|
I++ ;
|
|
}
|
|
|
|
/* Scale Determinant again, this time to be between 1.0 <= x < 10.0. */
|
|
Norm = NORM (cDeterminant) ;
|
|
if (Norm != 0.0)
|
|
{
|
|
while (Norm >= 10.0)
|
|
{
|
|
cDeterminant.Real *= 0.1 ;
|
|
cDeterminant.Imag *= 0.1 ;
|
|
(*pExponent)++ ;
|
|
Norm = NORM (cDeterminant) ;
|
|
}
|
|
while (Norm < 1.0)
|
|
{
|
|
cDeterminant.Real *= 10.0 ;
|
|
cDeterminant.Imag *= 10.0 ;
|
|
(*pExponent)-- ;
|
|
Norm = NORM (cDeterminant) ;
|
|
}
|
|
}
|
|
if (nSwap % 2 != 0)
|
|
{
|
|
CMPLX_NEGATE (cDeterminant) ;
|
|
}
|
|
|
|
*pDeterminant = cDeterminant.Real ;
|
|
*piDeterminant = cDeterminant.Imag ;
|
|
|
|
free (Uz) ;
|
|
}
|
|
else
|
|
{
|
|
/* Real Case. */
|
|
*pDeterminant = 1.0 ;
|
|
|
|
klu_extract_Udiag (Matrix->SMPkluMatrix->KLUmatrixNumeric, Matrix->SMPkluMatrix->KLUmatrixSymbolic, Ux, P, Q, Rs, Matrix->SMPkluMatrix->KLUmatrixCommon) ;
|
|
|
|
nSwapP = 0 ;
|
|
for (I = 0 ; I < (int)Matrix->SMPkluMatrix->KLUmatrixN ; I++)
|
|
{
|
|
if (P [I] != I)
|
|
{
|
|
nSwapP++ ;
|
|
}
|
|
}
|
|
nSwapP /= 2 ;
|
|
|
|
nSwapQ = 0 ;
|
|
for (I = 0 ; I < (int)Matrix->SMPkluMatrix->KLUmatrixN ; I++)
|
|
{
|
|
if (Q [I] != I)
|
|
{
|
|
nSwapQ++ ;
|
|
}
|
|
}
|
|
nSwapQ /= 2 ;
|
|
|
|
nSwap = nSwapP + nSwapQ ;
|
|
|
|
while (I < Size)
|
|
{
|
|
*pDeterminant /= (Ux [I] * Rs [I]) ;
|
|
|
|
/* Scale Determinant. */
|
|
if (*pDeterminant != 0.0)
|
|
{
|
|
while (ABS(*pDeterminant) >= 1.0e12)
|
|
{
|
|
*pDeterminant *= 1.0e-12 ;
|
|
*pExponent += 12 ;
|
|
}
|
|
while (ABS(*pDeterminant) < 1.0e-12)
|
|
{
|
|
*pDeterminant *= 1.0e12 ;
|
|
*pExponent -= 12 ;
|
|
}
|
|
}
|
|
I++ ;
|
|
}
|
|
|
|
/* Scale Determinant again, this time to be between 1.0 <= x <
|
|
10.0. */
|
|
if (*pDeterminant != 0.0)
|
|
{
|
|
while (ABS(*pDeterminant) >= 10.0)
|
|
{
|
|
*pDeterminant *= 0.1 ;
|
|
(*pExponent)++ ;
|
|
}
|
|
while (ABS(*pDeterminant) < 1.0)
|
|
{
|
|
*pDeterminant *= 10.0 ;
|
|
(*pExponent)-- ;
|
|
}
|
|
}
|
|
if (nSwap % 2 != 0)
|
|
{
|
|
*pDeterminant = -*pDeterminant ;
|
|
}
|
|
}
|
|
|
|
free (P) ;
|
|
free (Q) ;
|
|
free (Ux) ;
|
|
free (Rs) ;
|
|
}
|
|
|
|
/*
|
|
* SMPcProdDiag()
|
|
* note: obsolete for Spice3d2 and later
|
|
*/
|
|
int
|
|
SMPcProdDiag (SMPmatrix *Matrix, SPcomplex *pMantissa, int *pExponent)
|
|
{
|
|
if (Matrix->CKTkluMODE)
|
|
{
|
|
spDeterminant_KLU (Matrix, pExponent, &(pMantissa->real), &(pMantissa->imag)) ;
|
|
} else {
|
|
spDeterminant (Matrix->SPmatrix, pExponent, &(pMantissa->real), &(pMantissa->imag)) ;
|
|
}
|
|
return spError (Matrix->SPmatrix) ;
|
|
}
|
|
|
|
/*
|
|
* SMPcDProd()
|
|
*/
|
|
int
|
|
SMPcDProd (SMPmatrix *Matrix, SPcomplex *pMantissa, int *pExponent)
|
|
{
|
|
double re, im, x, y, z;
|
|
int p;
|
|
|
|
if (Matrix->CKTkluMODE)
|
|
{
|
|
spDeterminant_KLU (Matrix, &p, &re, &im) ;
|
|
} else {
|
|
spDeterminant (Matrix->SPmatrix, &p, &re, &im) ;
|
|
}
|
|
|
|
#ifndef M_LN2
|
|
#define M_LN2 0.69314718055994530942
|
|
#endif
|
|
#ifndef M_LN10
|
|
#define M_LN10 2.30258509299404568402
|
|
#endif
|
|
|
|
#ifdef debug_print
|
|
printf ("Determinant 10: (%20g,%20g)^%d\n", re, im, p) ;
|
|
#endif
|
|
|
|
/* Convert base 10 numbers to base 2 numbers, for comparison */
|
|
y = p * M_LN10 / M_LN2;
|
|
x = (int) y;
|
|
y -= x;
|
|
|
|
/* ASSERT
|
|
* x = integral part of exponent, y = fraction part of exponent
|
|
*/
|
|
|
|
/* Fold in the fractional part */
|
|
#ifdef debug_print
|
|
printf (" ** base10 -> base2 int = %g, frac = %20g\n", x, y) ;
|
|
#endif
|
|
z = pow (2.0, y) ;
|
|
re *= z ;
|
|
im *= z ;
|
|
#ifdef debug_print
|
|
printf (" ** multiplier = %20g\n", z) ;
|
|
#endif
|
|
|
|
/* Re-normalize (re or im may be > 2.0 or both < 1.0 */
|
|
if (re != 0.0)
|
|
{
|
|
y = logb (re) ;
|
|
if (im != 0.0)
|
|
z = logb (im) ;
|
|
else
|
|
z = 0 ;
|
|
} else if (im != 0.0) {
|
|
z = logb (im) ;
|
|
y = 0 ;
|
|
} else {
|
|
/* Singular */
|
|
/*printf("10 -> singular\n");*/
|
|
y = 0 ;
|
|
z = 0 ;
|
|
}
|
|
|
|
#ifdef debug_print
|
|
printf (" ** renormalize changes = %g,%g\n", y, z) ;
|
|
#endif
|
|
if (y < z)
|
|
y = z ;
|
|
|
|
*pExponent = (int)(x + y) ;
|
|
x = scalbn (re, (int) -y) ;
|
|
z = scalbn (im, (int) -y) ;
|
|
#ifdef debug_print
|
|
printf (" ** values are: re %g, im %g, y %g, re' %g, im' %g\n", re, im, y, x, z) ;
|
|
#endif
|
|
pMantissa->real = scalbn (re, (int) -y) ;
|
|
pMantissa->imag = scalbn (im, (int) -y) ;
|
|
|
|
#ifdef debug_print
|
|
printf ("Determinant 10->2: (%20g,%20g)^%d\n", pMantissa->real, pMantissa->imag, *pExponent) ;
|
|
#endif
|
|
|
|
if (Matrix->CKTkluMODE)
|
|
{
|
|
return 0 ;
|
|
} else {
|
|
return spError (Matrix->SPmatrix) ;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
* The following routines need internal knowledge of the Sparse data
|
|
* structures.
|
|
*/
|
|
|
|
/*
|
|
* LOAD GMIN
|
|
*
|
|
* This routine adds Gmin to each diagonal element. Because Gmin is
|
|
* added to the current diagonal, which may bear little relation to
|
|
* what the outside world thinks is a diagonal, and because the
|
|
* elements that are diagonals may change after calling spOrderAndFactor,
|
|
* use of this routine is not recommended. It is included here simply
|
|
* for compatibility with Spice3.
|
|
*/
|
|
|
|
|
|
static void
|
|
LoadGmin_CSC (double **diag, unsigned int n, double Gmin)
|
|
{
|
|
unsigned int i ;
|
|
|
|
if (Gmin != 0.0) {
|
|
for (i = 0 ; i < n ; i++) {
|
|
if (diag [i] != NULL) {
|
|
// Not all the elements on the diagonal are present, when the circuit is parsed
|
|
*(diag [i]) += Gmin ;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
static void
|
|
LoadGmin (SMPmatrix *eMatrix, double Gmin)
|
|
{
|
|
MatrixPtr Matrix = eMatrix->SPmatrix ;
|
|
int I ;
|
|
ArrayOfElementPtrs Diag ;
|
|
ElementPtr diag ;
|
|
|
|
/* Begin `LoadGmin'. */
|
|
assert (IS_SPARSE (Matrix)) ;
|
|
|
|
if (Gmin != 0.0) {
|
|
Diag = Matrix->Diag ;
|
|
for (I = Matrix->Size ; I > 0 ; I--)
|
|
{
|
|
if ((diag = Diag [I]) != NULL)
|
|
diag->Real += Gmin ;
|
|
}
|
|
}
|
|
return ;
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
* FIND ELEMENT
|
|
*
|
|
* This routine finds an element in the matrix by row and column number.
|
|
* If the element exists, a pointer to it is returned. If not, then NULL
|
|
* is returned unless the CreateIfMissing flag is TRUE, in which case a
|
|
* pointer to the new element is returned.
|
|
*/
|
|
|
|
SMPelement *
|
|
SMPfindElt (SMPmatrix *eMatrix, int Row, int Col, int CreateIfMissing)
|
|
{
|
|
MatrixPtr Matrix = eMatrix->SPmatrix ;
|
|
|
|
if (eMatrix->CKTkluMODE)
|
|
{
|
|
int i ;
|
|
|
|
Row = Row - 1 ;
|
|
Col = Col - 1 ;
|
|
if ((Row < 0) || (Col < 0)) {
|
|
printf ("Error: Cannot find an element with row '%d' and column '%d' in the KLU matrix\n", Row, Col) ;
|
|
return NULL ;
|
|
}
|
|
for (i = eMatrix->SMPkluMatrix->KLUmatrixAp [Col] ; i < eMatrix->SMPkluMatrix->KLUmatrixAp [Col + 1] ; i++) {
|
|
if (eMatrix->SMPkluMatrix->KLUmatrixAi [i] == Row) {
|
|
if (eMatrix->SMPkluMatrix->KLUmatrixIsComplex == KLUmatrixReal) {
|
|
return (SMPelement *) &(eMatrix->SMPkluMatrix->KLUmatrixAx [i]) ;
|
|
} else if (eMatrix->SMPkluMatrix->KLUmatrixIsComplex == KLUMatrixComplex) {
|
|
return (SMPelement *) &(eMatrix->SMPkluMatrix->KLUmatrixAxComplex [2 * i]) ;
|
|
} else {
|
|
return NULL ;
|
|
}
|
|
}
|
|
}
|
|
return NULL ;
|
|
} else {
|
|
ElementPtr Element ;
|
|
|
|
/* Begin `SMPfindElt'. */
|
|
assert (IS_SPARSE (Matrix)) ;
|
|
Row = Matrix->ExtToIntRowMap [Row] ;
|
|
Col = Matrix->ExtToIntColMap [Col] ;
|
|
Element = Matrix->FirstInCol [Col] ;
|
|
Element = spcFindElementInCol (Matrix, &Element, Row, Col, CreateIfMissing) ;
|
|
return (SMPelement *)Element ;
|
|
}
|
|
}
|
|
|
|
/* XXX The following should probably be implemented in spUtils */
|
|
|
|
/*
|
|
* SMPcZeroCol()
|
|
*/
|
|
int
|
|
SMPcZeroCol (SMPmatrix *eMatrix, int Col)
|
|
{
|
|
MatrixPtr Matrix = eMatrix->SPmatrix ;
|
|
ElementPtr Element ;
|
|
|
|
if (eMatrix->CKTkluMODE)
|
|
{
|
|
int i ;
|
|
for (i = eMatrix->SMPkluMatrix->KLUmatrixAp [Col - 1] ; i < eMatrix->SMPkluMatrix->KLUmatrixAp [Col] ; i++)
|
|
{
|
|
eMatrix->SMPkluMatrix->KLUmatrixAxComplex [2 * i] = 0 ;
|
|
eMatrix->SMPkluMatrix->KLUmatrixAxComplex [2 * i + 1] = 0 ;
|
|
}
|
|
return 0 ;
|
|
} else {
|
|
Col = Matrix->ExtToIntColMap [Col] ;
|
|
for (Element = Matrix->FirstInCol [Col] ; Element != NULL ; Element = Element->NextInCol)
|
|
{
|
|
Element->Real = 0.0 ;
|
|
Element->Imag = 0.0 ;
|
|
}
|
|
return spError (Matrix) ;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* SMPcAddCol()
|
|
*/
|
|
int
|
|
SMPcAddCol (SMPmatrix *eMatrix, int Accum_Col, int Addend_Col)
|
|
{
|
|
MatrixPtr Matrix = eMatrix->SPmatrix ;
|
|
ElementPtr Accum, Addend, *Prev ;
|
|
|
|
Accum_Col = Matrix->ExtToIntColMap [Accum_Col] ;
|
|
Addend_Col = Matrix->ExtToIntColMap [Addend_Col] ;
|
|
|
|
Addend = Matrix->FirstInCol [Addend_Col] ;
|
|
Prev = &Matrix->FirstInCol [Accum_Col] ;
|
|
Accum = *Prev;
|
|
|
|
while (Addend != NULL)
|
|
{
|
|
while (Accum && Accum->Row < Addend->Row)
|
|
{
|
|
Prev = &Accum->NextInCol ;
|
|
Accum = *Prev ;
|
|
}
|
|
if (!Accum || Accum->Row > Addend->Row)
|
|
{
|
|
Accum = spcCreateElement (Matrix, Addend->Row, Accum_Col, Prev, 0) ;
|
|
}
|
|
Accum->Real += Addend->Real ;
|
|
Accum->Imag += Addend->Imag ;
|
|
Addend = Addend->NextInCol ;
|
|
}
|
|
|
|
return spError (Matrix) ;
|
|
}
|
|
|
|
/*
|
|
* SMPzeroRow()
|
|
*/
|
|
int
|
|
SMPzeroRow (SMPmatrix *eMatrix, int Row)
|
|
{
|
|
MatrixPtr Matrix = eMatrix->SPmatrix ;
|
|
ElementPtr Element ;
|
|
|
|
Row = Matrix->ExtToIntColMap [Row] ;
|
|
|
|
if (Matrix->RowsLinked == NO)
|
|
spcLinkRows (Matrix) ;
|
|
|
|
if (Matrix->PreviousMatrixWasComplex || Matrix->Complex)
|
|
{
|
|
for (Element = Matrix->FirstInRow[Row] ; Element != NULL; Element = Element->NextInRow)
|
|
{
|
|
Element->Real = 0.0 ;
|
|
Element->Imag = 0.0 ;
|
|
}
|
|
} else {
|
|
for (Element = Matrix->FirstInRow [Row] ; Element != NULL ; Element = Element->NextInRow)
|
|
{
|
|
Element->Real = 0.0 ;
|
|
}
|
|
}
|
|
|
|
return spError (Matrix) ;
|
|
}
|
|
|
|
/*
|
|
* SMPconstMult()
|
|
*/
|
|
void
|
|
SMPconstMult (SMPmatrix *Matrix, double constant)
|
|
{
|
|
if (Matrix->CKTkluMODE)
|
|
{
|
|
if (Matrix->SMPkluMatrix->KLUmatrixIsComplex)
|
|
{
|
|
klu_z_constant_multiply (Matrix->SMPkluMatrix->KLUmatrixAp, Matrix->SMPkluMatrix->KLUmatrixAxComplex,
|
|
(int)Matrix->SMPkluMatrix->KLUmatrixN, Matrix->SMPkluMatrix->KLUmatrixCommon, constant) ;
|
|
} else {
|
|
klu_constant_multiply (Matrix->SMPkluMatrix->KLUmatrixAp, Matrix->SMPkluMatrix->KLUmatrixAx,
|
|
(int)Matrix->SMPkluMatrix->KLUmatrixN, Matrix->SMPkluMatrix->KLUmatrixCommon, constant) ;
|
|
}
|
|
} else {
|
|
spConstMult (Matrix->SPmatrix, constant) ;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* SMPmultiply()
|
|
*/
|
|
void
|
|
SMPmultiply (SMPmatrix *Matrix, double *RHS, double *Solution, double *iRHS, double *iSolution)
|
|
{
|
|
if (Matrix->CKTkluMODE)
|
|
{
|
|
int *Ap_CSR, *Ai_CSR ;
|
|
double *Ax_CSR ;
|
|
|
|
Ap_CSR = (int *) malloc ((size_t)(Matrix->SMPkluMatrix->KLUmatrixN + 1) * sizeof (int)) ;
|
|
Ai_CSR = (int *) malloc ((size_t)Matrix->SMPkluMatrix->KLUmatrixNZ * sizeof (int)) ;
|
|
|
|
if (Matrix->SMPkluMatrix->KLUmatrixIsComplex)
|
|
{
|
|
Ax_CSR = (double *) malloc ((size_t)(2 * Matrix->SMPkluMatrix->KLUmatrixNZ) * sizeof (double)) ;
|
|
klu_z_convert_matrix_in_CSR (Matrix->SMPkluMatrix->KLUmatrixAp, Matrix->SMPkluMatrix->KLUmatrixAi, Matrix->SMPkluMatrix->KLUmatrixAxComplex, Ap_CSR,
|
|
Ai_CSR, Ax_CSR, (int)Matrix->SMPkluMatrix->KLUmatrixN, (int)Matrix->SMPkluMatrix->KLUmatrixNZ, Matrix->SMPkluMatrix->KLUmatrixCommon) ;
|
|
klu_z_matrix_vector_multiply (Ap_CSR, Ai_CSR, Ax_CSR, RHS, Solution, iRHS, iSolution, NULL, NULL,
|
|
(int)Matrix->SMPkluMatrix->KLUmatrixN, Matrix->SMPkluMatrix->KLUmatrixCommon) ;
|
|
} else {
|
|
Ax_CSR = (double *) malloc ((size_t)Matrix->SMPkluMatrix->KLUmatrixNZ * sizeof (double)) ;
|
|
klu_convert_matrix_in_CSR (Matrix->SMPkluMatrix->KLUmatrixAp, Matrix->SMPkluMatrix->KLUmatrixAi, Matrix->SMPkluMatrix->KLUmatrixAx, Ap_CSR, Ai_CSR,
|
|
Ax_CSR, (int)Matrix->SMPkluMatrix->KLUmatrixN, (int)Matrix->SMPkluMatrix->KLUmatrixNZ, Matrix->SMPkluMatrix->KLUmatrixCommon) ;
|
|
klu_matrix_vector_multiply (Ap_CSR, Ai_CSR, Ax_CSR, RHS, Solution, NULL, NULL,
|
|
(int)Matrix->SMPkluMatrix->KLUmatrixN, Matrix->SMPkluMatrix->KLUmatrixCommon) ;
|
|
iSolution = iRHS ;
|
|
}
|
|
|
|
free (Ap_CSR) ;
|
|
free (Ai_CSR) ;
|
|
free (Ax_CSR) ;
|
|
} else {
|
|
spMultiply (Matrix->SPmatrix, RHS, Solution, iRHS, iSolution) ;
|
|
}
|
|
}
|
|
|