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:
parent
7345c3d032
commit
b36221996b
|
|
@ -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 *);
|
||||
|
|
|
|||
|
|
@ -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))
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -75,7 +75,7 @@ SPICEdev CPLinfo = {
|
|||
/* DEVmodSize */ &CPLmSize,
|
||||
|
||||
#ifdef KIRCHHOFF
|
||||
/* DEVnodeIsLinear */ NULL
|
||||
/* DEVnodeIsNonLinear */ NULL
|
||||
#endif
|
||||
|
||||
};
|
||||
|
|
|
|||
|
|
@ -77,7 +77,7 @@ SPICEdev CSWinfo = {
|
|||
/* DEVmodSize */ &CSWmSize,
|
||||
|
||||
#ifdef KIRCHHOFF
|
||||
/* DEVnodeIsLinear */ NULL
|
||||
/* DEVnodeIsNonLinear */ NULL
|
||||
#endif
|
||||
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
|
|
|||
|
|
@ -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**);
|
||||
|
|
|
|||
|
|
@ -74,7 +74,7 @@ SPICEdev INDinfo = {
|
|||
/* DEVmodSize */ &INDmSize,
|
||||
|
||||
#ifdef KIRCHHOFF
|
||||
/* DEVnodeIsNonLinear */ NULL
|
||||
/* DEVnodeIsNonLinear */ INDnodeIsNonLinear
|
||||
#endif
|
||||
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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 ;
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -75,7 +75,7 @@ SPICEdev VSRCinfo = {
|
|||
/* DEVmodSize */ &VSRCmSize,
|
||||
|
||||
#ifdef KIRCHHOFF
|
||||
/* DEVnodeIsNonLinear */ NULL
|
||||
/* DEVnodeIsNonLinear */ VSRCnodeIsNonLinear
|
||||
#endif
|
||||
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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)) &&
|
||||
|
|
|
|||
Loading…
Reference in New Issue