Try to speedup KCL (Part 1)
This commit is contained in:
parent
89d15214f3
commit
b2c663c61b
|
|
@ -122,6 +122,12 @@ struct CKTcircuit {
|
||||||
int *CKTnodeIsLinear ; /* Flag to indicate if a node is linear or non-linear */
|
int *CKTnodeIsLinear ; /* Flag to indicate if a node is linear or non-linear */
|
||||||
CKTmkCurKCLnode **CKTmkCurKCLarray ; /* Array of KCL Currents */
|
CKTmkCurKCLnode **CKTmkCurKCLarray ; /* Array of KCL Currents */
|
||||||
double **CKTdiag ;
|
double **CKTdiag ;
|
||||||
|
double **CKTrhsOrdered ;
|
||||||
|
double **CKTrhsOldOrdered ;
|
||||||
|
CKTmkCurKCLnode **CKTmkCurKCLarrayOrdered ;
|
||||||
|
double **CKTfvkOrdered ;
|
||||||
|
int CKTvoltageNonLinearNodes ;
|
||||||
|
int CKTcurrentNonLinearNodes ;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
double *CKTrhsSpare; /* spare rhs value for reordering */
|
double *CKTrhsSpare; /* spare rhs value for reordering */
|
||||||
|
|
|
||||||
|
|
@ -47,89 +47,93 @@ NIconvTest (CKTcircuit *ckt)
|
||||||
#endif /* STEPDEBUG */
|
#endif /* STEPDEBUG */
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef KIRCHHOFF
|
||||||
|
for (i = 0 ; i < ckt->CKTvoltageNonLinearNodes ; i++)
|
||||||
|
{
|
||||||
|
new = *(ckt->CKTrhsOrdered [i]) ;
|
||||||
|
old = *(ckt->CKTrhsOldOrdered [i]) ;
|
||||||
|
tol = ckt->CKTreltol * (MAX (fabs (old), fabs (new))) + ckt->CKTvoltTol ;
|
||||||
|
if (fabs (new - old) > tol)
|
||||||
|
{
|
||||||
|
|
||||||
|
#ifdef STEPDEBUG
|
||||||
|
fprintf (err, " non-convergence at node (type=%d) %s (fabs(new-old)>tol --> fabs(%g-%g)>%g)\n",
|
||||||
|
node->type, CKTnodName (ckt, i), new, old, tol) ;
|
||||||
|
fprintf (err, " 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 ;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* KCL Verification */
|
||||||
|
|
||||||
|
maximum = 0 ;
|
||||||
|
ptr = ckt->CKTmkCurKCLarrayOrdered [i] ;
|
||||||
|
|
||||||
|
#ifdef STEPDEBUG
|
||||||
|
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 ;
|
||||||
|
}
|
||||||
|
|
||||||
|
// if (maximum < fabs (ckt->CKTdiagGmin * ckt->CKTrhsOld [i]))
|
||||||
|
// maximum = fabs (ckt->CKTdiagGmin * ckt->CKTrhsOld [i]) ;
|
||||||
|
|
||||||
|
|
||||||
|
#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
|
||||||
|
|
||||||
|
/* Check Convergence */
|
||||||
|
// if (fabs (ckt->CKTfvk [i] + ckt->CKTdiagGmin * ckt->CKTrhsOld [i]) > (ckt->CKTreltol * maximum + ckt->CKTabstol))
|
||||||
|
if (fabs (*(ckt->CKTfvkOrdered [i])) > (ckt->CKTreltol * maximum + ckt->CKTabstol))
|
||||||
|
{
|
||||||
|
ckt->CKTtroubleNode = i ;
|
||||||
|
ckt->CKTtroubleElt = NULL ;
|
||||||
|
|
||||||
|
return 1 ;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = ckt->CKTvoltageNonLinearNodes ; i < ckt->CKTvoltageNonLinearNodes + ckt->CKTcurrentNonLinearNodes ; i++)
|
||||||
|
{
|
||||||
|
new = *(ckt->CKTrhsOrdered [i]) ;
|
||||||
|
old = *(ckt->CKTrhsOldOrdered [i]) ;
|
||||||
|
tol = ckt->CKTreltol * (MAX (fabs (old), fabs (new))) + ckt->CKTabstol ;
|
||||||
|
if (fabs (new - old) > tol)
|
||||||
|
{
|
||||||
|
|
||||||
|
#ifdef STEPDEBUG
|
||||||
|
fprintf (err, " non-convergence at node (type=%d) %s (fabs(new-old)>tol --> fabs(%g-%g)>%g)\n",
|
||||||
|
node->type, CKTnodName (ckt, i), new, old, tol) ;
|
||||||
|
fprintf (err, " 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 ;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#else
|
||||||
for (i = 1 ; i <= size ; i++)
|
for (i = 1 ; i <= size ; i++)
|
||||||
{
|
{
|
||||||
node = node->next ;
|
node = node->next ;
|
||||||
|
|
||||||
#ifdef KIRCHHOFF
|
|
||||||
if ((node->type == SP_VOLTAGE) && (!ckt->CKTnodeIsLinear [i]))
|
|
||||||
{
|
|
||||||
new = ckt->CKTrhs [i] ;
|
|
||||||
old = ckt->CKTrhsOld [i] ;
|
|
||||||
tol = ckt->CKTreltol * (MAX (fabs (old), fabs (new))) + ckt->CKTvoltTol ;
|
|
||||||
if (fabs (new - old) > tol)
|
|
||||||
{
|
|
||||||
|
|
||||||
#ifdef STEPDEBUG
|
|
||||||
fprintf (err, " non-convergence at node (type=%d) %s (fabs(new-old)>tol --> fabs(%g-%g)>%g)\n",
|
|
||||||
node->type, CKTnodName (ckt, i), new, old, tol) ;
|
|
||||||
fprintf (err, " 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 ;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* KCL Verification */
|
|
||||||
|
|
||||||
maximum = 0 ;
|
|
||||||
ptr = ckt->CKTmkCurKCLarray [i] ;
|
|
||||||
|
|
||||||
#ifdef STEPDEBUG
|
|
||||||
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 ;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (maximum < fabs (ckt->CKTdiagGmin * ckt->CKTrhsOld [i]))
|
|
||||||
maximum = fabs (ckt->CKTdiagGmin * ckt->CKTrhsOld [i]) ;
|
|
||||||
|
|
||||||
|
|
||||||
#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
|
|
||||||
|
|
||||||
/* Check Convergence */
|
|
||||||
if (fabs (ckt->CKTfvk [i] + ckt->CKTdiagGmin * ckt->CKTrhsOld [i]) > (ckt->CKTreltol * maximum + ckt->CKTabstol))
|
|
||||||
{
|
|
||||||
ckt->CKTtroubleNode = i ;
|
|
||||||
ckt->CKTtroubleElt = NULL ;
|
|
||||||
|
|
||||||
return 1 ;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
new = ckt->CKTrhs [i] ;
|
|
||||||
old = ckt->CKTrhsOld [i] ;
|
|
||||||
tol = ckt->CKTreltol * (MAX (fabs (old), fabs (new))) + ckt->CKTabstol ;
|
|
||||||
if (fabs (new - old) > tol)
|
|
||||||
{
|
|
||||||
|
|
||||||
#ifdef STEPDEBUG
|
|
||||||
fprintf (err, " non-convergence at node (type=%d) %s (fabs(new-old)>tol --> fabs(%g-%g)>%g)\n",
|
|
||||||
node->type, CKTnodName (ckt, i), new, old, tol) ;
|
|
||||||
fprintf (err, " 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 ;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
new = ckt->CKTrhs [i] ;
|
new = ckt->CKTrhs [i] ;
|
||||||
old = ckt->CKTrhsOld [i] ;
|
old = ckt->CKTrhsOld [i] ;
|
||||||
if (node->type == SP_VOLTAGE)
|
if (node->type == SP_VOLTAGE)
|
||||||
|
|
@ -164,9 +168,8 @@ NIconvTest (CKTcircuit *ckt)
|
||||||
return 1 ;
|
return 1 ;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif /* KIRCHHOFF */
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
#endif /* KIRCHHOFF */
|
||||||
|
|
||||||
#ifdef KIRCHHOFF
|
#ifdef KIRCHHOFF
|
||||||
return 0 ;
|
return 0 ;
|
||||||
|
|
|
||||||
|
|
@ -81,13 +81,13 @@ CKTload(CKTcircuit *ckt)
|
||||||
|
|
||||||
#ifdef KIRCHHOFF
|
#ifdef KIRCHHOFF
|
||||||
/* GMIN Stepping */
|
/* GMIN Stepping */
|
||||||
for (i = 1 ; i <= size ; i++)
|
// for (i = 1 ; i <= size ; i++)
|
||||||
{
|
// {
|
||||||
if (ckt->CKTdiag [i] != NULL)
|
// if (ckt->CKTdiag [i] != NULL)
|
||||||
{
|
// {
|
||||||
*(ckt->CKTdiag [i]) += ckt->CKTdiagGmin ;
|
// *(ckt->CKTdiag [i]) += ckt->CKTdiagGmin ;
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef XSPICE
|
#ifdef XSPICE
|
||||||
|
|
|
||||||
|
|
@ -155,11 +155,11 @@ dynamic_gmin (CKTcircuit * ckt, long int firstmode,
|
||||||
factor = ckt->CKTgminFactor;
|
factor = ckt->CKTgminFactor;
|
||||||
OldGmin = 1e-2;
|
OldGmin = 1e-2;
|
||||||
gtarget = MAX (ckt->CKTgmin, ckt->CKTgshunt);
|
gtarget = MAX (ckt->CKTgmin, ckt->CKTgshunt);
|
||||||
ckt->CKTdiagGmin = OldGmin / factor;
|
ckt->CKTgmin = OldGmin / factor;
|
||||||
success = failed = 0;
|
success = failed = 0;
|
||||||
|
|
||||||
while ((!success) && (!failed)) {
|
while ((!success) && (!failed)) {
|
||||||
fprintf (stderr, "Trying gmin = %12.4E ", ckt->CKTdiagGmin);
|
fprintf (stderr, "Trying gmin = %12.4E ", ckt->CKTgmin);
|
||||||
ckt->CKTnoncon = 1;
|
ckt->CKTnoncon = 1;
|
||||||
iters = ckt->CKTstat->STATnumIter;
|
iters = ckt->CKTstat->STATnumIter;
|
||||||
|
|
||||||
|
|
@ -171,7 +171,7 @@ dynamic_gmin (CKTcircuit * ckt, long int firstmode,
|
||||||
SPfrontEnd->IFerror (ERR_INFO,
|
SPfrontEnd->IFerror (ERR_INFO,
|
||||||
"One successful gmin step", NULL);
|
"One successful gmin step", NULL);
|
||||||
|
|
||||||
if (ckt->CKTdiagGmin <= gtarget) {
|
if (ckt->CKTgmin <= gtarget) {
|
||||||
success = 1;
|
success = 1;
|
||||||
} else {
|
} else {
|
||||||
i = 0;
|
i = 0;
|
||||||
|
|
@ -193,13 +193,13 @@ dynamic_gmin (CKTcircuit * ckt, long int firstmode,
|
||||||
if (iters > (3 * ckt->CKTdcTrcvMaxIter / 4))
|
if (iters > (3 * ckt->CKTdcTrcvMaxIter / 4))
|
||||||
factor = sqrt (factor);
|
factor = sqrt (factor);
|
||||||
|
|
||||||
OldGmin = ckt->CKTdiagGmin;
|
OldGmin = ckt->CKTgmin;
|
||||||
|
|
||||||
if ((ckt->CKTdiagGmin) < (factor * gtarget)) {
|
if ((ckt->CKTgmin) < (factor * gtarget)) {
|
||||||
factor = ckt->CKTdiagGmin / gtarget;
|
factor = ckt->CKTgmin / gtarget;
|
||||||
ckt->CKTdiagGmin = gtarget;
|
ckt->CKTgmin = gtarget;
|
||||||
} else {
|
} else {
|
||||||
ckt->CKTdiagGmin /= factor;
|
ckt->CKTgmin /= factor;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -213,7 +213,7 @@ dynamic_gmin (CKTcircuit * ckt, long int firstmode,
|
||||||
"Further gmin increment",
|
"Further gmin increment",
|
||||||
NULL);
|
NULL);
|
||||||
factor = sqrt (sqrt (factor));
|
factor = sqrt (sqrt (factor));
|
||||||
ckt->CKTdiagGmin = OldGmin / factor;
|
ckt->CKTgmin = OldGmin / factor;
|
||||||
|
|
||||||
i = 0;
|
i = 0;
|
||||||
for (n = ckt->CKTnodes; n; n = n->next) {
|
for (n = ckt->CKTnodes; n; n = n->next) {
|
||||||
|
|
@ -228,7 +228,7 @@ dynamic_gmin (CKTcircuit * ckt, long int firstmode,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ckt->CKTdiagGmin = ckt->CKTgshunt;
|
// ckt->CKTdiagGmin = ckt->CKTgshunt;
|
||||||
FREE (OldRhsOld);
|
FREE (OldRhsOld);
|
||||||
FREE (OldCKTstate0);
|
FREE (OldCKTstate0);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -129,18 +129,21 @@ CKTsetup(CKTcircuit *ckt)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef KIRCHHOFF
|
#ifdef KIRCHHOFF
|
||||||
CKTnode *node ;
|
/**
|
||||||
|
* Gmin Stepping
|
||||||
|
*/
|
||||||
|
// CKTnode *node ;
|
||||||
|
|
||||||
node = ckt->CKTnodes ;
|
// node = ckt->CKTnodes ;
|
||||||
for (i = 1 ; i <= SMPmatSize (ckt->CKTmatrix) ; i++)
|
// for (i = 1 ; i <= SMPmatSize (ckt->CKTmatrix) ; i++)
|
||||||
{
|
// {
|
||||||
node = node->next ;
|
// node = node->next ;
|
||||||
|
|
||||||
if (node->type == SP_VOLTAGE)
|
// if (node->type == SP_VOLTAGE)
|
||||||
{
|
// {
|
||||||
ckt->CKTdiag [i] = SMPmakeElt (ckt->CKTmatrix, i, i) ;
|
// ckt->CKTdiag [i] = SMPmakeElt (ckt->CKTmatrix, i, i) ;
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
/** Marking node as Non-Linear when needed
|
/** Marking node as Non-Linear when needed
|
||||||
* By default every node is Linear
|
* By default every node is Linear
|
||||||
|
|
@ -154,6 +157,56 @@ CKTsetup(CKTcircuit *ckt)
|
||||||
return (error) ;
|
return (error) ;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reordering nodes for convergence tests
|
||||||
|
*/
|
||||||
|
int j, non_linear_nodes ;
|
||||||
|
non_linear_nodes = 0 ;
|
||||||
|
for (i = 1 ; i <= SMPmatSize (ckt->CKTmatrix) ; i++)
|
||||||
|
{
|
||||||
|
if (!ckt->CKTnodeIsLinear [i])
|
||||||
|
{
|
||||||
|
non_linear_nodes++ ;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
CKALLOC (ckt->CKTrhsOrdered, non_linear_nodes, double*) ;
|
||||||
|
CKALLOC (ckt->CKTrhsOldOrdered, non_linear_nodes, double*) ;
|
||||||
|
CKALLOC (ckt->CKTmkCurKCLarrayOrdered, non_linear_nodes, CKTmkCurKCLnode*) ;
|
||||||
|
CKALLOC (ckt->CKTfvkOrdered, non_linear_nodes, double*) ;
|
||||||
|
j = 0 ;
|
||||||
|
node = ckt->CKTnodes ;
|
||||||
|
for (i = 1 ; i <= SMPmatSize (ckt->CKTmatrix) ; i++)
|
||||||
|
{
|
||||||
|
node = node->next ;
|
||||||
|
|
||||||
|
if ((node->type == SP_VOLTAGE) && (!ckt->CKTnodeIsLinear [i]))
|
||||||
|
{
|
||||||
|
ckt->CKTrhsOrdered [j] = &(ckt->CKTrhs [i]) ;
|
||||||
|
ckt->CKTrhsOldOrdered [j] = &(ckt->CKTrhsOld [i]) ;
|
||||||
|
ckt->CKTmkCurKCLarrayOrdered [j] = ckt->CKTmkCurKCLarray [i] ;
|
||||||
|
ckt->CKTfvkOrdered [j] = &(ckt->CKTfvk [i]) ;
|
||||||
|
j++ ;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ckt->CKTvoltageNonLinearNodes = j ;
|
||||||
|
|
||||||
|
node = ckt->CKTnodes ;
|
||||||
|
for (i = 1 ; i <= SMPmatSize (ckt->CKTmatrix) ; i++)
|
||||||
|
{
|
||||||
|
node = node->next ;
|
||||||
|
|
||||||
|
if ((node->type == SP_CURRENT) && (!ckt->CKTnodeIsLinear [i]))
|
||||||
|
{
|
||||||
|
ckt->CKTrhsOrdered [j] = &(ckt->CKTrhs [i]) ;
|
||||||
|
ckt->CKTrhsOldOrdered [j] = &(ckt->CKTrhsOld [i]) ;
|
||||||
|
j++ ;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ckt->CKTcurrentNonLinearNodes = j - ckt->CKTvoltageNonLinearNodes ;
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return(OK);
|
return(OK);
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue