From b36221996bfcf073065429e13313a42865378fe8 Mon Sep 17 00:00:00 2001 From: Francesco Lannutti Date: Thu, 6 Jun 2013 08:16:43 +0200 Subject: [PATCH] Implemented a new check for the KCL Verification, based on the maximum of the unknown current branches at each voltage node. Please note that this check introduces the theoretically correct check, but, since achieving this target involves the perfect knowledge of every model, we can use this suboptimal and practical check (to be extended with the other possible unknown current branches) --- src/include/ngspice/cktdefs.h | 14 +++++- src/maths/ni/niconv.c | 63 ++++++++++++++++++--------- src/maths/ni/nireinit.c | 6 +++ src/spicelib/analysis/Makefile.am | 4 ++ src/spicelib/devices/cpl/cplinit.c | 2 +- src/spicelib/devices/csw/cswinit.c | 2 +- src/spicelib/devices/ind/Makefile.am | 3 ++ src/spicelib/devices/ind/inddefs.h | 5 +++ src/spicelib/devices/ind/indext.h | 4 ++ src/spicelib/devices/ind/indinit.c | 2 +- src/spicelib/devices/ind/indload.c | 6 +++ src/spicelib/devices/vsrc/Makefile.am | 3 ++ src/spicelib/devices/vsrc/vsrcdefs.h | 6 +++ src/spicelib/devices/vsrc/vsrcext.h | 4 ++ src/spicelib/devices/vsrc/vsrcinit.c | 2 +- src/spicelib/devices/vsrc/vsrcload.c | 6 +++ 16 files changed, 107 insertions(+), 25 deletions(-) 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)) &&