diff --git a/src/include/ngspice/cktdefs.h b/src/include/ngspice/cktdefs.h index 86f58fab2..f85d8b2a6 100644 --- a/src/include/ngspice/cktdefs.h +++ b/src/include/ngspice/cktdefs.h @@ -122,6 +122,12 @@ struct CKTcircuit { int *CKTnodeIsLinear ; /* Flag to indicate if a node is linear or non-linear */ CKTmkCurKCLnode **CKTmkCurKCLarray ; /* Array of KCL Currents */ double **CKTdiag ; + double **CKTrhsOrdered ; + double **CKTrhsOldOrdered ; + CKTmkCurKCLnode **CKTmkCurKCLarrayOrdered ; + double **CKTfvkOrdered ; + int CKTvoltageNonLinearNodes ; + int CKTcurrentNonLinearNodes ; #endif double *CKTrhsSpare; /* spare rhs value for reordering */ diff --git a/src/maths/ni/niconv.c b/src/maths/ni/niconv.c index 30dbcf31a..16b665442 100644 --- a/src/maths/ni/niconv.c +++ b/src/maths/ni/niconv.c @@ -47,89 +47,93 @@ NIconvTest (CKTcircuit *ckt) #endif /* STEPDEBUG */ #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++) { 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] ; old = ckt->CKTrhsOld [i] ; if (node->type == SP_VOLTAGE) @@ -164,9 +168,8 @@ NIconvTest (CKTcircuit *ckt) return 1 ; } } -#endif /* KIRCHHOFF */ - } +#endif /* KIRCHHOFF */ #ifdef KIRCHHOFF return 0 ; diff --git a/src/spicelib/analysis/cktload.c b/src/spicelib/analysis/cktload.c index 8de8c7749..a33d7d1f5 100644 --- a/src/spicelib/analysis/cktload.c +++ b/src/spicelib/analysis/cktload.c @@ -81,13 +81,13 @@ CKTload(CKTcircuit *ckt) #ifdef KIRCHHOFF /* GMIN Stepping */ - for (i = 1 ; i <= size ; i++) - { - if (ckt->CKTdiag [i] != NULL) - { - *(ckt->CKTdiag [i]) += ckt->CKTdiagGmin ; - } - } +// for (i = 1 ; i <= size ; i++) +// { +// if (ckt->CKTdiag [i] != NULL) +// { +// *(ckt->CKTdiag [i]) += ckt->CKTdiagGmin ; +// } +// } #endif #ifdef XSPICE diff --git a/src/spicelib/analysis/cktop.c b/src/spicelib/analysis/cktop.c index 90549af90..cfd07a422 100644 --- a/src/spicelib/analysis/cktop.c +++ b/src/spicelib/analysis/cktop.c @@ -155,11 +155,11 @@ dynamic_gmin (CKTcircuit * ckt, long int firstmode, factor = ckt->CKTgminFactor; OldGmin = 1e-2; gtarget = MAX (ckt->CKTgmin, ckt->CKTgshunt); - ckt->CKTdiagGmin = OldGmin / factor; + ckt->CKTgmin = OldGmin / factor; success = failed = 0; while ((!success) && (!failed)) { - fprintf (stderr, "Trying gmin = %12.4E ", ckt->CKTdiagGmin); + fprintf (stderr, "Trying gmin = %12.4E ", ckt->CKTgmin); ckt->CKTnoncon = 1; iters = ckt->CKTstat->STATnumIter; @@ -171,7 +171,7 @@ dynamic_gmin (CKTcircuit * ckt, long int firstmode, SPfrontEnd->IFerror (ERR_INFO, "One successful gmin step", NULL); - if (ckt->CKTdiagGmin <= gtarget) { + if (ckt->CKTgmin <= gtarget) { success = 1; } else { i = 0; @@ -193,13 +193,13 @@ dynamic_gmin (CKTcircuit * ckt, long int firstmode, if (iters > (3 * ckt->CKTdcTrcvMaxIter / 4)) factor = sqrt (factor); - OldGmin = ckt->CKTdiagGmin; + OldGmin = ckt->CKTgmin; - if ((ckt->CKTdiagGmin) < (factor * gtarget)) { - factor = ckt->CKTdiagGmin / gtarget; - ckt->CKTdiagGmin = gtarget; + if ((ckt->CKTgmin) < (factor * gtarget)) { + factor = ckt->CKTgmin / gtarget; + ckt->CKTgmin = gtarget; } else { - ckt->CKTdiagGmin /= factor; + ckt->CKTgmin /= factor; } } } else { @@ -213,7 +213,7 @@ dynamic_gmin (CKTcircuit * ckt, long int firstmode, "Further gmin increment", NULL); factor = sqrt (sqrt (factor)); - ckt->CKTdiagGmin = OldGmin / factor; + ckt->CKTgmin = OldGmin / factor; i = 0; 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 (OldCKTstate0); diff --git a/src/spicelib/analysis/cktsetup.c b/src/spicelib/analysis/cktsetup.c index 36409186b..7a964d4a2 100644 --- a/src/spicelib/analysis/cktsetup.c +++ b/src/spicelib/analysis/cktsetup.c @@ -129,18 +129,21 @@ CKTsetup(CKTcircuit *ckt) #endif #ifdef KIRCHHOFF - CKTnode *node ; + /** + * Gmin Stepping + */ +// CKTnode *node ; - node = ckt->CKTnodes ; - for (i = 1 ; i <= SMPmatSize (ckt->CKTmatrix) ; i++) - { - node = node->next ; +// node = ckt->CKTnodes ; +// for (i = 1 ; i <= SMPmatSize (ckt->CKTmatrix) ; i++) +// { +// node = node->next ; - if (node->type == SP_VOLTAGE) - { - ckt->CKTdiag [i] = SMPmakeElt (ckt->CKTmatrix, i, i) ; - } - } +// if (node->type == SP_VOLTAGE) +// { +// ckt->CKTdiag [i] = SMPmakeElt (ckt->CKTmatrix, i, i) ; +// } +// } /** Marking node as Non-Linear when needed * By default every node is Linear @@ -154,6 +157,56 @@ CKTsetup(CKTcircuit *ckt) 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 return(OK);