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)
This commit is contained in:
Francesco Lannutti 2013-06-06 08:16:43 +02:00
parent 7345c3d032
commit b36221996b
16 changed files with 107 additions and 25 deletions

View File

@ -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 *);

View File

@ -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))

View File

@ -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

View File

@ -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

View File

@ -75,7 +75,7 @@ SPICEdev CPLinfo = {
/* DEVmodSize */ &CPLmSize,
#ifdef KIRCHHOFF
/* DEVnodeIsLinear */ NULL
/* DEVnodeIsNonLinear */ NULL
#endif
};

View File

@ -77,7 +77,7 @@ SPICEdev CSWinfo = {
/* DEVmodSize */ &CSWmSize,
#ifdef KIRCHHOFF
/* DEVnodeIsLinear */ NULL
/* DEVnodeIsNonLinear */ NULL
#endif
};

View File

@ -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)

View File

@ -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 */

View File

@ -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**);

View File

@ -74,7 +74,7 @@ SPICEdev INDinfo = {
/* DEVmodSize */ &INDmSize,
#ifdef KIRCHHOFF
/* DEVnodeIsNonLinear */ NULL
/* DEVnodeIsNonLinear */ INDnodeIsNonLinear
#endif
};

View File

@ -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
}

View File

@ -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)

View File

@ -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 ;

View File

@ -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

View File

@ -75,7 +75,7 @@ SPICEdev VSRCinfo = {
/* DEVmodSize */ &VSRCmSize,
#ifdef KIRCHHOFF
/* DEVnodeIsNonLinear */ NULL
/* DEVnodeIsNonLinear */ VSRCnodeIsNonLinear
#endif
};

View File

@ -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)) &&