diff --git a/src/include/ngspice/cktdefs.h b/src/include/ngspice/cktdefs.h index 7a42a12cb..548fcde01 100644 --- a/src/include/ngspice/cktdefs.h +++ b/src/include/ngspice/cktdefs.h @@ -56,6 +56,12 @@ struct CKTnode { #define PARM_IC 2 #define PARM_NODETYPE 3 +#ifdef KIRCHHOFF +typedef struct sCKTmkCurKCLnode { + double KCLcurrent ; + struct sCKTmkCurKCLnode *next ; +} CKTmkCurKCLnode ; +#endif struct CKTcircuit { @@ -114,6 +120,8 @@ struct CKTcircuit { #ifdef KIRCHHOFF double *CKTfvk ; /* KCL Verification array */ int *CKTnodeIsLinear ; /* Flag to indicate if a node is linear or non-linear */ + int *CKTvoltCurNode ; /* Flag to indicate if a node contains some direct unknown currents */ + CKTmkCurKCLnode **CKTmkCurKCLarray ; /* Array of KCL Currents */ #endif double *CKTrhsSpare; /* spare rhs value for reordering */ @@ -290,7 +298,11 @@ struct CKTcircuit { }; -/* Now function prottypes */ +/* Now function prototypes */ + +#ifdef KIRCHHOFF +extern int CKTmkCurKCL (CKTcircuit *, int, double **) ; +#endif extern int ACan(CKTcircuit *, int); extern int ACaskQuest(CKTcircuit *, JOB *, int , IFvalue *); diff --git a/src/maths/ni/niconv.c b/src/maths/ni/niconv.c index 48ed9a577..cf1097999 100644 --- a/src/maths/ni/niconv.c +++ b/src/maths/ni/niconv.c @@ -21,17 +21,23 @@ NIconvTest(CKTcircuit *ckt) int i; /* generic loop variable */ int size; /* size of the matrix */ CKTnode *node; /* current matrix entry */ - -#ifndef KIRCHHOFF double old; double new; double tol; + +#ifdef KIRCHHOFF +#ifdef STEPDEBUG + int j ; +#endif + + double maximum ; + CKTmkCurKCLnode *ptr ; + #endif size = SMPmatSize(ckt->CKTmatrix); - -#ifndef KIRCHHOFF node = ckt->CKTnodes; + #ifdef STEPDEBUG for (i=1;i<=size;i++) { new = ckt->CKTrhs [i] ; @@ -39,6 +45,7 @@ NIconvTest(CKTcircuit *ckt) printf("chk for convergence: %s new: %g old: %g\n",CKTnodName(ckt,i),new,old); } #endif /* STEPDEBUG */ + for (i=1;i<=size;i++) { node = node->next; new = ckt->CKTrhs [i] ; @@ -47,54 +54,70 @@ NIconvTest(CKTcircuit *ckt) tol = ckt->CKTreltol * (MAX(fabs(old),fabs(new))) + ckt->CKTvoltTol; if (fabs(new-old) >tol ) { + #ifdef STEPDEBUG printf(" non-convergence at node (type=3) %s (fabs(new-old)>tol --> fabs(%g-%g)>%g)\n",CKTnodName(ckt,i),new,old,tol); printf(" reltol: %g voltTol: %g (tol=reltol*(MAX(fabs(old),fabs(new))) + voltTol)\n",ckt->CKTreltol,ckt->CKTvoltTol); #endif /* STEPDEBUG */ + ckt->CKTtroubleNode = i; ckt->CKTtroubleElt = NULL; return(1); } + +#ifndef KIRCHHOFF } else { tol = ckt->CKTreltol * (MAX(fabs(old),fabs(new))) + ckt->CKTabstol; if (fabs(new-old) >tol ) { + #ifdef STEPDEBUG printf(" non-convergence at node (type=%d) %s (fabs(new-old)>tol --> fabs(%g-%g)>%g)\n",node->type,CKTnodName(ckt,i),new,old,tol); printf(" reltol: %g abstol: %g (tol=reltol*(MAX(fabs(old),fabs(new))) + abstol)\n",ckt->CKTreltol,ckt->CKTabstol); #endif /* STEPDEBUG */ + ckt->CKTtroubleNode = i; ckt->CKTtroubleElt = NULL; return(1); } +#endif + } } -#else +#ifdef KIRCHHOFF + node = ckt->CKTnodes; /* KCL Verification */ - double maximum = 0 ; - node = ckt->CKTnodes ; for (i = 1 ; i <= size ; i++) { node = node->next ; - if (node->type == SP_CURRENT) - { - if (maximum < fabs (ckt->CKTrhs [i])) - maximum = fabs (ckt->CKTrhs [i]) ; - } - } - - node = ckt->CKTnodes ; - for (i = 1 ; i <= size ; i++) - { - node = node->next ; - if ((node->type == SP_VOLTAGE) && (!ckt->CKTnodeIsLinear [i])) + if ((node->type == SP_VOLTAGE) && (!ckt->CKTnodeIsLinear [i]) && (ckt->CKTvoltCurNode [i])) { + maximum = 0 ; + ptr = ckt->CKTmkCurKCLarray [i] ; #ifdef STEPDEBUG - fprintf (stderr, "Index: %d\tValue: %-.9g\tThreshold: %-.9g\n", i, fabs (ckt->CKTfvk [i]), ckt->CKTreltol * maximum + ckt->CKTabstol) ; + j = 0 ; +#endif + + while (ptr != NULL) + { + if (maximum < fabs (ptr->KCLcurrent)) + maximum = fabs (ptr->KCLcurrent) ; + +#ifdef STEPDEBUG + fprintf (stderr, "Index KCL Array: %d\tValue: %-.9g\tMaximum: %-.9g\n", j, fabs(ptr->KCLcurrent), maximum) ; + j++ ; +#endif + + ptr = ptr->next ; + } + +#ifdef STEPDEBUG + fprintf (stderr, "Index: %d\tValue: %-.9g\tThreshold: %-.9g\tMaximum: %-.9g\n", i, fabs (ckt->CKTfvk [i]), + ckt->CKTreltol * maximum + ckt->CKTabstol, maximum) ; #endif if (fabs (ckt->CKTfvk [i]) > (ckt->CKTreltol * maximum + ckt->CKTabstol)) diff --git a/src/maths/ni/nireinit.c b/src/maths/ni/nireinit.c index 30dce7b1f..805e2ea5f 100644 --- a/src/maths/ni/nireinit.c +++ b/src/maths/ni/nireinit.c @@ -40,6 +40,12 @@ NIreinit( CKTcircuit *ckt) CKALLOC(CKTnodeIsLinear,size+1,int); for (i = 0 ; i <= size ; i++) ckt->CKTnodeIsLinear [i] = 1 ; + CKALLOC(CKTvoltCurNode,size+1,int); + for (i = 0 ; i <= size ; i++) + ckt->CKTvoltCurNode [i] = 0 ; + CKALLOC(CKTmkCurKCLarray,size+1,CKTmkCurKCLnode*); + for (i = 0 ; i <= size ; i++) + ckt->CKTmkCurKCLarray [i] = NULL ; #endif #ifdef PREDICTOR diff --git a/src/spicelib/analysis/Makefile.am b/src/spicelib/analysis/Makefile.am index 86d6b7371..03d8f1ab0 100644 --- a/src/spicelib/analysis/Makefile.am +++ b/src/spicelib/analysis/Makefile.am @@ -107,6 +107,10 @@ libckt_la_SOURCES += \ endif +if KIRCHHOFF_WANTED +libckt_la_SOURCES += cktmkcurKCL.c +endif + AM_CPPFLAGS = @AM_CPPFLAGS@ -I$(top_srcdir)/src/include -I$(top_srcdir)/src/spicelib/devices AM_CFLAGS = $(STATIC) MAINTAINERCLEANFILES = Makefile.in diff --git a/src/spicelib/devices/cpl/cplinit.c b/src/spicelib/devices/cpl/cplinit.c index 576972a45..be0bd922c 100644 --- a/src/spicelib/devices/cpl/cplinit.c +++ b/src/spicelib/devices/cpl/cplinit.c @@ -75,7 +75,7 @@ SPICEdev CPLinfo = { /* DEVmodSize */ &CPLmSize, #ifdef KIRCHHOFF -/* DEVnodeIsLinear */ NULL +/* DEVnodeIsNonLinear */ NULL #endif }; diff --git a/src/spicelib/devices/csw/cswinit.c b/src/spicelib/devices/csw/cswinit.c index 89d61bc48..b2fbe4dc4 100644 --- a/src/spicelib/devices/csw/cswinit.c +++ b/src/spicelib/devices/csw/cswinit.c @@ -77,7 +77,7 @@ SPICEdev CSWinfo = { /* DEVmodSize */ &CSWmSize, #ifdef KIRCHHOFF - /* DEVnodeIsLinear */ NULL + /* DEVnodeIsNonLinear */ NULL #endif }; diff --git a/src/spicelib/devices/ind/Makefile.am b/src/spicelib/devices/ind/Makefile.am index 5a05ee97b..5bf3c7871 100644 --- a/src/spicelib/devices/ind/Makefile.am +++ b/src/spicelib/devices/ind/Makefile.am @@ -40,6 +40,9 @@ libind_la_SOURCES = \ muttemp.c +if KIRCHHOFF_WANTED +libind_la_SOURCES += indnode.c +endif AM_CPPFLAGS = @AM_CPPFLAGS@ -I$(top_srcdir)/src/include AM_CFLAGS = $(STATIC) diff --git a/src/spicelib/devices/ind/inddefs.h b/src/spicelib/devices/ind/inddefs.h index f024d1490..b91d3fb1f 100644 --- a/src/spicelib/devices/ind/inddefs.h +++ b/src/spicelib/devices/ind/inddefs.h @@ -63,6 +63,11 @@ typedef struct sINDinstance { int INDsenParmNo; /* parameter # for sensitivity use; set equal to 0 if not a design parameter*/ +#ifdef KIRCHHOFF + double *KCLcurrentPos ; + double *KCLcurrentNeg ; +#endif + } INDinstance ; #define INDflux INDstate /* flux in the inductor */ diff --git a/src/spicelib/devices/ind/indext.h b/src/spicelib/devices/ind/indext.h index 8d2fa035c..56bfe0e7a 100644 --- a/src/spicelib/devices/ind/indext.h +++ b/src/spicelib/devices/ind/indext.h @@ -25,6 +25,10 @@ extern int INDunsetup(GENmodel*,CKTcircuit*); extern int INDtemp(GENmodel*, CKTcircuit*); extern int INDtrunc(GENmodel*,CKTcircuit*,double*); +#ifdef KIRCHHOFF +extern int INDnodeIsNonLinear (GENmodel *, CKTcircuit *) ; +#endif + extern int MUTacLoad(GENmodel*,CKTcircuit*); extern int MUTask(CKTcircuit*,GENinstance*,int,IFvalue*,IFvalue*); extern int MUTdelete(GENmodel*,IFuid,GENinstance**); diff --git a/src/spicelib/devices/ind/indinit.c b/src/spicelib/devices/ind/indinit.c index fb8cfa296..0513f2750 100644 --- a/src/spicelib/devices/ind/indinit.c +++ b/src/spicelib/devices/ind/indinit.c @@ -74,7 +74,7 @@ SPICEdev INDinfo = { /* DEVmodSize */ &INDmSize, #ifdef KIRCHHOFF - /* DEVnodeIsNonLinear */ NULL + /* DEVnodeIsNonLinear */ INDnodeIsNonLinear #endif }; diff --git a/src/spicelib/devices/ind/indload.c b/src/spicelib/devices/ind/indload.c index 7eed3a9dc..e763cf4a7 100644 --- a/src/spicelib/devices/ind/indload.c +++ b/src/spicelib/devices/ind/indload.c @@ -125,6 +125,12 @@ INDload(GENmodel *inModel, CKTcircuit *ckt) #ifdef KIRCHHOFF *(ckt->CKTfvk+here->INDposNode) += *(ckt->CKTrhsOld+here->INDbrEq) ; *(ckt->CKTfvk+here->INDnegNode) -= *(ckt->CKTrhsOld+here->INDbrEq) ; + + *(ckt->CKTvoltCurNode+here->INDposNode) = 1 ; + *(ckt->CKTvoltCurNode+here->INDnegNode) = 1 ; + + *(here->KCLcurrentPos) = *(ckt->CKTrhsOld+here->INDbrEq) ; + *(here->KCLcurrentNeg) = -(*(ckt->CKTrhsOld+here->INDbrEq)) ; #endif } diff --git a/src/spicelib/devices/vsrc/Makefile.am b/src/spicelib/devices/vsrc/Makefile.am index 28d5fb38b..5d6495b03 100644 --- a/src/spicelib/devices/vsrc/Makefile.am +++ b/src/spicelib/devices/vsrc/Makefile.am @@ -24,6 +24,9 @@ libvsrc_la_SOURCES = \ vsrctemp.c +if KIRCHHOFF_WANTED +libvsrc_la_SOURCES += vsrcnode.c +endif AM_CPPFLAGS = @AM_CPPFLAGS@ -I$(top_srcdir)/src/include AM_CFLAGS = $(STATIC) diff --git a/src/spicelib/devices/vsrc/vsrcdefs.h b/src/spicelib/devices/vsrc/vsrcdefs.h index d8f71ec5e..4d1be2a2c 100644 --- a/src/spicelib/devices/vsrc/vsrcdefs.h +++ b/src/spicelib/devices/vsrc/vsrcdefs.h @@ -75,6 +75,12 @@ typedef struct sVSRCinstance { unsigned VSRCdF1given :1 ; /* flag to indicate source is an f1 distortion input */ unsigned VSRCdF2given :1 ; /* flag to indicate source is an f2 distortion input */ unsigned VSRCrGiven :1 ; /* flag to indicate repeating pwl */ + +#ifdef KIRCHHOFF + double *KCLcurrentPos ; + double *KCLcurrentNeg ; +#endif + } VSRCinstance ; diff --git a/src/spicelib/devices/vsrc/vsrcext.h b/src/spicelib/devices/vsrc/vsrcext.h index 980efbf8e..a0eca1408 100644 --- a/src/spicelib/devices/vsrc/vsrcext.h +++ b/src/spicelib/devices/vsrc/vsrcext.h @@ -18,3 +18,7 @@ extern int VSRCsetup(SMPmatrix*,GENmodel*,CKTcircuit*,int*); extern int VSRCunsetup(GENmodel*,CKTcircuit*); extern int VSRCpzSetup(SMPmatrix*,GENmodel*,CKTcircuit*,int*); extern int VSRCtemp(GENmodel*,CKTcircuit*); + +#ifdef KIRCHHOFF +extern int VSRCnodeIsNonLinear (GENmodel *, CKTcircuit *) ; +#endif diff --git a/src/spicelib/devices/vsrc/vsrcinit.c b/src/spicelib/devices/vsrc/vsrcinit.c index a2e973efb..7e75c7b4d 100644 --- a/src/spicelib/devices/vsrc/vsrcinit.c +++ b/src/spicelib/devices/vsrc/vsrcinit.c @@ -75,7 +75,7 @@ SPICEdev VSRCinfo = { /* DEVmodSize */ &VSRCmSize, #ifdef KIRCHHOFF - /* DEVnodeIsNonLinear */ NULL + /* DEVnodeIsNonLinear */ VSRCnodeIsNonLinear #endif }; diff --git a/src/spicelib/devices/vsrc/vsrcload.c b/src/spicelib/devices/vsrc/vsrcload.c index 53f164f9a..61e7aa635 100644 --- a/src/spicelib/devices/vsrc/vsrcload.c +++ b/src/spicelib/devices/vsrc/vsrcload.c @@ -44,6 +44,12 @@ VSRCload(GENmodel *inModel, CKTcircuit *ckt) #ifdef KIRCHHOFF *(ckt->CKTfvk+here->VSRCposNode) += *(ckt->CKTrhsOld+here->VSRCbranch) ; *(ckt->CKTfvk+here->VSRCnegNode) -= *(ckt->CKTrhsOld+here->VSRCbranch) ; + + *(ckt->CKTvoltCurNode+here->VSRCposNode) = 1 ; + *(ckt->CKTvoltCurNode+here->VSRCnegNode) = 1 ; + + *(here->KCLcurrentPos) = *(ckt->CKTrhsOld+here->VSRCbranch) ; + *(here->KCLcurrentNeg) = -(*(ckt->CKTrhsOld+here->VSRCbranch)) ; #endif if( (ckt->CKTmode & (MODEDCOP | MODEDCTRANCURVE)) &&