diff --git a/src/spicelib/devices/cpl/Makefile.am b/src/spicelib/devices/cpl/Makefile.am index efb1e3376..9c053cad7 100644 --- a/src/spicelib/devices/cpl/Makefile.am +++ b/src/spicelib/devices/cpl/Makefile.am @@ -20,6 +20,10 @@ libcpl_la_SOURCES = \ cpldelete.c \ cplinit.c +if KLU_WANTED +libcpl_la_SOURCES += cplbindCSC.c +endif + AM_CPPFLAGS = @AM_CPPFLAGS@ -I$(top_srcdir)/src/include AM_CFLAGS = $(STATIC) diff --git a/src/spicelib/devices/cpl/cplbindCSC.c b/src/spicelib/devices/cpl/cplbindCSC.c new file mode 100644 index 000000000..87896bef2 --- /dev/null +++ b/src/spicelib/devices/cpl/cplbindCSC.c @@ -0,0 +1,147 @@ +/********** +Author: 2013 Francesco Lannutti +**********/ + +#include "ngspice/ngspice.h" +#include "ngspice/cktdefs.h" +#include "cpldefs.h" +#include "ngspice/sperror.h" +#include "ngspice/klu-binding.h" + +#include + + +static +int +BindCompare (const void *a, const void *b) +{ + BindElement *A, *B ; + A = (BindElement *)a ; + B = (BindElement *)b ; + + return ((int)(A->Sparse - B->Sparse)) ; +} + +int +CPLbindCSC (GENmodel *inModel, CKTcircuit *ckt) +{ + CPLmodel *model = (CPLmodel *)inModel ; + CPLinstance *here ; + double *i ; + BindElement *matched, *BindStruct ; + size_t nz ; + int m, p ; + + BindStruct = ckt->CKTmatrix->CKTbindStruct ; + nz = (size_t)ckt->CKTmatrix->CKTklunz ; + + /* loop through all the CPL models */ + for ( ; model != NULL ; model = CPLnextModel(model)) + { + /* loop through all the instances of the model */ + for (here = CPLinstances(model); here != NULL ; here = CPLnextInstance(here)) + { + for (m = 0; m < here->dimension; m++) { + CREATE_KLU_BINDING_TABLE(CPLibr1Ibr1Ptr[m], CPLibr1Ibr1Binding[m], CPLibr1[m], CPLibr1[m]); + CREATE_KLU_BINDING_TABLE(CPLibr2Ibr2Ptr[m], CPLibr2Ibr2Binding[m], CPLibr2[m], CPLibr2[m]); + CREATE_KLU_BINDING_TABLE(CPLposIbr1Ptr[m], CPLposIbr1Binding[m], CPLposNodes[m], CPLibr1[m]); + CREATE_KLU_BINDING_TABLE(CPLnegIbr2Ptr[m], CPLnegIbr2Binding[m], CPLnegNodes[m], CPLibr2[m]); + CREATE_KLU_BINDING_TABLE(CPLposPosPtr[m], CPLposPosBinding[m], CPLposNodes[m], CPLposNodes[m]); + CREATE_KLU_BINDING_TABLE(CPLnegNegPtr[m], CPLnegNegBinding[m], CPLnegNodes[m], CPLnegNodes[m]); + CREATE_KLU_BINDING_TABLE(CPLnegPosPtr[m], CPLnegPosBinding[m], CPLnegNodes[m], CPLposNodes[m]); + CREATE_KLU_BINDING_TABLE(CPLposNegPtr[m], CPLposNegBinding[m], CPLposNodes[m], CPLnegNodes[m]); + + for (p = 0; p < here->dimension; p++) { + CREATE_KLU_BINDING_TABLE(CPLibr1PosPtr[m][p], CPLibr1PosBinding[m][p], CPLibr1[m], CPLposNodes[p]); + CREATE_KLU_BINDING_TABLE(CPLibr2NegPtr[m][p], CPLibr2NegBinding[m][p], CPLibr2[m], CPLnegNodes[p]); + CREATE_KLU_BINDING_TABLE(CPLibr1NegPtr[m][p], CPLibr1NegBinding[m][p], CPLibr1[m], CPLnegNodes[p]); + CREATE_KLU_BINDING_TABLE(CPLibr2PosPtr[m][p], CPLibr2PosBinding[m][p], CPLibr2[m], CPLposNodes[p]); + CREATE_KLU_BINDING_TABLE(CPLibr1Ibr2Ptr[m][p], CPLibr1Ibr2Binding[m][p], CPLibr1[m], CPLibr2[p]); + CREATE_KLU_BINDING_TABLE(CPLibr2Ibr1Ptr[m][p], CPLibr2Ibr1Binding[m][p], CPLibr2[m], CPLibr1[p]); + } + } + } + } + + return (OK) ; +} + +int +CPLbindCSCComplex (GENmodel *inModel, CKTcircuit *ckt) +{ + CPLmodel *model = (CPLmodel *)inModel ; + CPLinstance *here ; + int m, p; + + NG_IGNORE (ckt) ; + + /* loop through all the CPL models */ + for ( ; model != NULL ; model = CPLnextModel(model)) + { + /* loop through all the instances of the model */ + for (here = CPLinstances(model); here != NULL ; here = CPLnextInstance(here)) + { + for (m = 0; m < here->dimension; m++) { + CONVERT_KLU_BINDING_TABLE_TO_COMPLEX(CPLibr1Ibr1Ptr[m], CPLibr1Ibr1Binding[m], CPLibr1[m], CPLibr1[m]); + CONVERT_KLU_BINDING_TABLE_TO_COMPLEX(CPLibr2Ibr2Ptr[m], CPLibr2Ibr2Binding[m], CPLibr2[m], CPLibr2[m]); + CONVERT_KLU_BINDING_TABLE_TO_COMPLEX(CPLposIbr1Ptr[m], CPLposIbr1Binding[m], CPLposNodes[m], CPLibr1[m]); + CONVERT_KLU_BINDING_TABLE_TO_COMPLEX(CPLnegIbr2Ptr[m], CPLnegIbr2Binding[m], CPLnegNodes[m], CPLibr2[m]); + CONVERT_KLU_BINDING_TABLE_TO_COMPLEX(CPLposPosPtr[m], CPLposPosBinding[m], CPLposNodes[m], CPLposNodes[m]); + CONVERT_KLU_BINDING_TABLE_TO_COMPLEX(CPLnegNegPtr[m], CPLnegNegBinding[m], CPLnegNodes[m], CPLnegNodes[m]); + CONVERT_KLU_BINDING_TABLE_TO_COMPLEX(CPLnegPosPtr[m], CPLnegPosBinding[m], CPLnegNodes[m], CPLposNodes[m]); + CONVERT_KLU_BINDING_TABLE_TO_COMPLEX(CPLposNegPtr[m], CPLposNegBinding[m], CPLposNodes[m], CPLnegNodes[m]); + + for (p = 0; p < here->dimension; p++) { + CONVERT_KLU_BINDING_TABLE_TO_COMPLEX(CPLibr1PosPtr[m][p], CPLibr1PosBinding[m][p], CPLibr1[m], CPLposNodes[p]); + CONVERT_KLU_BINDING_TABLE_TO_COMPLEX(CPLibr2NegPtr[m][p], CPLibr2NegBinding[m][p], CPLibr2[m], CPLnegNodes[p]); + CONVERT_KLU_BINDING_TABLE_TO_COMPLEX(CPLibr1NegPtr[m][p], CPLibr1NegBinding[m][p], CPLibr1[m], CPLnegNodes[p]); + CONVERT_KLU_BINDING_TABLE_TO_COMPLEX(CPLibr2PosPtr[m][p], CPLibr2PosBinding[m][p], CPLibr2[m], CPLposNodes[p]); + CONVERT_KLU_BINDING_TABLE_TO_COMPLEX(CPLibr1Ibr2Ptr[m][p], CPLibr1Ibr2Binding[m][p], CPLibr1[m], CPLibr2[p]); + CONVERT_KLU_BINDING_TABLE_TO_COMPLEX(CPLibr2Ibr1Ptr[m][p], CPLibr2Ibr1Binding[m][p], CPLibr2[m], CPLibr1[p]); + } + } + } + } + + return (OK) ; +} + +int +CPLbindCSCComplexToReal (GENmodel *inModel, CKTcircuit *ckt) +{ + CPLmodel *model = (CPLmodel *)inModel ; + CPLinstance *here ; + int m, p; + + NG_IGNORE (ckt) ; + + /* loop through all the CPL models */ + for ( ; model != NULL ; model = CPLnextModel(model)) + { + /* loop through all the instances of the model */ + for (here = CPLinstances(model); here != NULL ; here = CPLnextInstance(here)) + { + for (m = 0; m < here->dimension; m++) { + CONVERT_KLU_BINDING_TABLE_TO_REAL(CPLibr1Ibr1Ptr[m], CPLibr1Ibr1Binding[m], CPLibr1[m], CPLibr1[m]); + CONVERT_KLU_BINDING_TABLE_TO_REAL(CPLibr2Ibr2Ptr[m], CPLibr2Ibr2Binding[m], CPLibr2[m], CPLibr2[m]); + CONVERT_KLU_BINDING_TABLE_TO_REAL(CPLposIbr1Ptr[m], CPLposIbr1Binding[m], CPLposNodes[m], CPLibr1[m]); + CONVERT_KLU_BINDING_TABLE_TO_REAL(CPLnegIbr2Ptr[m], CPLnegIbr2Binding[m], CPLnegNodes[m], CPLibr2[m]); + CONVERT_KLU_BINDING_TABLE_TO_REAL(CPLposPosPtr[m], CPLposPosBinding[m], CPLposNodes[m], CPLposNodes[m]); + CONVERT_KLU_BINDING_TABLE_TO_REAL(CPLnegNegPtr[m], CPLnegNegBinding[m], CPLnegNodes[m], CPLnegNodes[m]); + CONVERT_KLU_BINDING_TABLE_TO_REAL(CPLnegPosPtr[m], CPLnegPosBinding[m], CPLnegNodes[m], CPLposNodes[m]); + CONVERT_KLU_BINDING_TABLE_TO_REAL(CPLposNegPtr[m], CPLposNegBinding[m], CPLposNodes[m], CPLnegNodes[m]); + + for (p = 0; p < here->dimension; p++) { + CONVERT_KLU_BINDING_TABLE_TO_REAL(CPLibr1PosPtr[m][p], CPLibr1PosBinding[m][p], CPLibr1[m], CPLposNodes[p]); + CONVERT_KLU_BINDING_TABLE_TO_REAL(CPLibr2NegPtr[m][p], CPLibr2NegBinding[m][p], CPLibr2[m], CPLnegNodes[p]); + CONVERT_KLU_BINDING_TABLE_TO_REAL(CPLibr1NegPtr[m][p], CPLibr1NegBinding[m][p], CPLibr1[m], CPLnegNodes[p]); + CONVERT_KLU_BINDING_TABLE_TO_REAL(CPLibr2PosPtr[m][p], CPLibr2PosBinding[m][p], CPLibr2[m], CPLposNodes[p]); + CONVERT_KLU_BINDING_TABLE_TO_REAL(CPLibr1Ibr2Ptr[m][p], CPLibr1Ibr2Binding[m][p], CPLibr1[m], CPLibr2[p]); + CONVERT_KLU_BINDING_TABLE_TO_REAL(CPLibr2Ibr1Ptr[m][p], CPLibr2Ibr1Binding[m][p], CPLibr2[m], CPLibr1[p]); + } + } + } + } + + return (OK) ; +} diff --git a/src/spicelib/devices/cpl/cpldefs.h b/src/spicelib/devices/cpl/cpldefs.h index fb981a926..983ac00c2 100644 --- a/src/spicelib/devices/cpl/cpldefs.h +++ b/src/spicelib/devices/cpl/cpldefs.h @@ -58,6 +58,25 @@ typedef struct sCPLinstance { unsigned CPLdcGiven : 1; unsigned CPLlengthGiven : 1; +#ifdef KLU + BindElement **CPLibr1Ibr1Binding; + BindElement **CPLibr2Ibr2Binding; + BindElement **CPLposIbr1Binding; + BindElement **CPLnegIbr2Binding; + /* trial */ + BindElement **CPLposPosBinding; + BindElement **CPLnegNegBinding; + BindElement **CPLposNegBinding; + BindElement **CPLnegPosBinding; + + BindElement ***CPLibr1PosBinding; + BindElement ***CPLibr2NegBinding; + BindElement ***CPLibr1NegBinding; + BindElement ***CPLibr2PosBinding; + BindElement ***CPLibr1Ibr2Binding; + BindElement ***CPLibr2Ibr1Binding; +#endif + } CPLinstance ; diff --git a/src/spicelib/devices/cpl/cplext.h b/src/spicelib/devices/cpl/cplext.h index 4c28a93a6..bfebe6c5f 100644 --- a/src/spicelib/devices/cpl/cplext.h +++ b/src/spicelib/devices/cpl/cplext.h @@ -13,3 +13,9 @@ extern int CPLsetup(SMPmatrix*, GENmodel*, CKTcircuit*, int*); extern int CPLunsetup(GENmodel*, CKTcircuit*); extern int CPLmDelete(GENmodel*); extern int CPLDelete(GENinstance*); + +#ifdef KLU +extern int CPLbindCSC (GENmodel *, CKTcircuit *) ; +extern int CPLbindCSCComplex (GENmodel *, CKTcircuit *) ; +extern int CPLbindCSCComplexToReal (GENmodel *, CKTcircuit *) ; +#endif diff --git a/src/spicelib/devices/cpl/cplinit.c b/src/spicelib/devices/cpl/cplinit.c index 1882c5613..075988856 100644 --- a/src/spicelib/devices/cpl/cplinit.c +++ b/src/spicelib/devices/cpl/cplinit.c @@ -68,9 +68,9 @@ SPICEdev CPLinfo = { #endif #ifdef KLU - .DEVbindCSC = NULL, - .DEVbindCSCComplex = NULL, - .DEVbindCSCComplexToReal = NULL, + .DEVbindCSC = CPLbindCSC, + .DEVbindCSCComplex = CPLbindCSCComplex, + .DEVbindCSCComplexToReal = CPLbindCSCComplexToReal, #endif }; diff --git a/src/spicelib/devices/cpl/cplsetup.c b/src/spicelib/devices/cpl/cplsetup.c index 351eaf28a..1c55efc43 100644 --- a/src/spicelib/devices/cpl/cplsetup.c +++ b/src/spicelib/devices/cpl/cplsetup.c @@ -233,6 +233,23 @@ do { if((here->ptr = SMPmakeElt(matrix, here->first, here->second)) == NULL){\ MATRIX_ALLOC(double, here->CPLibr1Ibr2Ptr, noL, noL); MATRIX_ALLOC(double, here->CPLibr2Ibr1Ptr, noL, noL); +#ifdef KLU + VECTOR_ALLOC(here->CPLibr1Ibr1Binding, BindElement, noL); + VECTOR_ALLOC(here->CPLibr2Ibr2Binding, BindElement, noL); + VECTOR_ALLOC(here->CPLposIbr1Binding, BindElement, noL); + VECTOR_ALLOC(here->CPLnegIbr2Binding, BindElement, noL); + VECTOR_ALLOC(here->CPLposPosBinding, BindElement, noL); + VECTOR_ALLOC(here->CPLnegNegBinding, BindElement, noL); + VECTOR_ALLOC(here->CPLnegPosBinding, BindElement, noL); + VECTOR_ALLOC(here->CPLposNegBinding, BindElement, noL); + + MATRIX_ALLOC(here->CPLibr1PosBinding, BindElement, noL, noL); + MATRIX_ALLOC(here->CPLibr2NegBinding, BindElement, noL, noL); + MATRIX_ALLOC(here->CPLibr1NegBinding, BindElement, noL, noL); + MATRIX_ALLOC(here->CPLibr2PosBinding, BindElement, noL, noL); + MATRIX_ALLOC(here->CPLibr1Ibr2Binding, BindElement, noL, noL); + MATRIX_ALLOC(here->CPLibr2Ibr1Binding, BindElement, noL, noL); +#endif branchname = TMALLOC(char*, here->dimension); memsaved(branchname); @@ -312,6 +329,7 @@ do { if((here->ptr = SMPmakeElt(matrix, here->first, here->second)) == NULL){\ } return(OK); + } }