diff --git a/src/spicelib/analysis/cktop.c b/src/spicelib/analysis/cktop.c index 3f72162cf..b866b4336 100644 --- a/src/spicelib/analysis/cktop.c +++ b/src/spicelib/analysis/cktop.c @@ -9,6 +9,7 @@ Modified: 2005 Paolo Nenzi - Restructured #include "ngspice/cktdefs.h" #include "ngspice/devdefs.h" #include "ngspice/sperror.h" +#include "ngspice/cpextern.h" #ifdef XSPICE #include "ngspice/enh.h" @@ -17,6 +18,7 @@ Modified: 2005 Paolo Nenzi - Restructured static int dynamic_gmin(CKTcircuit *, long int, long int, int); static int spice3_gmin(CKTcircuit *, long int, long int, int); +static int new_gmin(CKTcircuit*, long int, long int, int); static int gillespie_src(CKTcircuit *, long int, long int, int); static int spice3_src(CKTcircuit *, long int, long int, int); @@ -51,10 +53,17 @@ CKTop (CKTcircuit *ckt, long int firstmode, long int continuemode, /* first, check if we should try gmin stepping */ if (ckt->CKTnumGminSteps >= 1) { - if (ckt->CKTnumGminSteps == 1) - converged = dynamic_gmin(ckt, firstmode, continuemode, iterlim); - else + if (ckt->CKTnumGminSteps == 1) { + if (cp_getvar("dyngmin", CP_BOOL, NULL, 0)) { + converged = dynamic_gmin(ckt, firstmode, continuemode, iterlim); + } + else { + converged = new_gmin(ckt, firstmode, continuemode, iterlim); + } + } + else { converged = spice3_gmin(ckt, firstmode, continuemode, iterlim); + } if (converged == 0) /* If gmin-stepping worked... move out */ return converged; } @@ -304,6 +313,185 @@ spice3_gmin (CKTcircuit *ckt, long int firstmode, return converged; } +/* just step the real gmin found in every device model */ +static int +new_gmin(CKTcircuit* ckt, long int firstmode, + long int continuemode, int iterlim) +{ + double OldGmin, gtarget, factor, startgmin; + int converged; + + int NumNodes, iters, i; + double* OldRhsOld, * OldCKTstate0; + CKTnode* n; + + ckt->CKTmode = firstmode; + SPfrontEnd->IFerrorf(ERR_INFO, "Starting true gmin stepping"); + + NumNodes = 0; + for (n = ckt->CKTnodes; n; n = n->next) + NumNodes++; + + OldRhsOld = TMALLOC(double, NumNodes + 1); + OldCKTstate0 = TMALLOC(double, ckt->CKTnumStates + 1); + + for (n = ckt->CKTnodes; n; n = n->next) + ckt->CKTrhsOld[n->number] = 0; + + for (i = 0; i < ckt->CKTnumStates; i++) + ckt->CKTstate0[i] = 0; + + startgmin = ckt->CKTgmin; + factor = ckt->CKTgminFactor; + OldGmin = 1e-2; + /*ckt->CKTdiagGmin = */ckt->CKTgmin = OldGmin / factor; + gtarget = MAX(startgmin, ckt->CKTgshunt); + + for (;;) { + fprintf(stderr, "Trying gmin = %12.4E ", ckt->CKTgmin); + + ckt->CKTnoncon = 1; + iters = ckt->CKTstat->STATnumIter; + converged = NIiter(ckt, ckt->CKTdcTrcvMaxIter); + iters = ckt->CKTstat->STATnumIter - iters; + + if (converged == 0) { + ckt->CKTmode = continuemode; + SPfrontEnd->IFerrorf(ERR_INFO, "One successful gmin step"); + + if (ckt->CKTgmin <= gtarget) + break; /* successfull */ + + for (i = 0, n = ckt->CKTnodes; n; n = n->next) + OldRhsOld[i++] = ckt->CKTrhsOld[n->number]; + + memcpy(OldCKTstate0, ckt->CKTstate0, + (size_t)ckt->CKTnumStates * sizeof(double)); + + if (iters <= (ckt->CKTdcTrcvMaxIter / 4)) { + factor *= sqrt(factor); + if (factor > ckt->CKTgminFactor) + factor = ckt->CKTgminFactor; + } + + if (iters > (3 * ckt->CKTdcTrcvMaxIter / 4)) + factor = MAX(sqrt(factor), 1.00005); + + OldGmin = ckt->CKTgmin; + + if (ckt->CKTgmin < factor * gtarget) { + factor = ckt->CKTgmin / gtarget; + /*ckt->CKTdiagGmin = */ckt->CKTgmin = gtarget; + } + else { + /*ckt->CKTdiagGmin = */ckt->CKTgmin /= factor; + } + } + else { + if (factor < 1.00005) { + SPfrontEnd->IFerrorf(ERR_WARNING, "Last gmin step failed"); + break; /* failed */ + } + SPfrontEnd->IFerrorf(ERR_WARNING, "Further gmin increment"); + factor = sqrt(sqrt(factor)); + /*ckt->CKTdiagGmin = */ckt->CKTgmin = OldGmin / factor; + + for (i = 0, n = ckt->CKTnodes; n; n = n->next) + ckt->CKTrhsOld[n->number] = OldRhsOld[i++]; + + memcpy(ckt->CKTstate0, OldCKTstate0, + (size_t)ckt->CKTnumStates * sizeof(double)); + } + } + + /*ckt->CKTdiagGmin = */ckt->CKTgmin = MAX(startgmin, ckt->CKTgshunt); + FREE(OldRhsOld); + FREE(OldCKTstate0); + +#ifdef XSPICE + /* gtri - wbk - add convergence problem reporting flags */ + ckt->enh->conv_debug.last_NIiter_call = (ckt->CKTnumSrcSteps <= 0); +#endif + + converged = NIiter(ckt, iterlim); + + if (converged != 0) { + SPfrontEnd->IFerrorf(ERR_WARNING, "True gmin stepping failed"); + } + else { + SPfrontEnd->IFerrorf(ERR_INFO, "True gmin stepping completed"); +#ifdef XSPICE + /* gtri - wbk - add convergence problem reporting flags */ + ckt->enh->conv_debug.last_NIiter_call = MIF_FALSE; +#endif + } + + return converged; +} + + + + + +static int +no_new_gmin(CKTcircuit* ckt, long int firstmode, + long int continuemode, int iterlim) +{ + int converged, i; + + ckt->CKTmode = firstmode; + SPfrontEnd->IFerrorf(ERR_INFO, "Starting new gmin stepping"); + + ckt->CKTgmin = 0.01; +// (ckt->CKTgshunt == 0) ? ckt->CKTgmin : ckt->CKTgshunt; + + for (i = 0; i < ckt->CKTnumGminSteps; i++) + ckt->CKTgmin *= ckt->CKTgminFactor; + + for (i = 0; i <= ckt->CKTnumGminSteps; i++) { + fprintf(stderr, "Trying gmin = %12.4E ", ckt->CKTgmin); + + ckt->CKTnoncon = 1; + converged = NIiter(ckt, ckt->CKTdcTrcvMaxIter); + + if (converged != 0) { + ckt->CKTgmin = ckt->CKTgshunt; + SPfrontEnd->IFerrorf(ERR_WARNING, "gmin step failed"); + break; + } + + ckt->CKTgmin /= ckt->CKTgminFactor; + ckt->CKTmode = continuemode; + + SPfrontEnd->IFerrorf(ERR_INFO, "One successful gmin step"); + } + + ckt->CKTgmin = ckt->CKTgshunt; + +#ifdef XSPICE + /* gtri - wbk - add convergence problem reporting flags */ + ckt->enh->conv_debug.last_NIiter_call = (ckt->CKTnumSrcSteps <= 0); +#endif + + converged = NIiter(ckt, iterlim); + + if (converged == 0) { + SPfrontEnd->IFerrorf(ERR_INFO, "gmin stepping completed"); + +#ifdef XSPICE + /* gtri - wbk - add convergence problem reporting flags */ + ckt->enh->conv_debug.last_NIiter_call = MIF_FALSE; +#endif + + } + else { + SPfrontEnd->IFerrorf(ERR_WARNING, "gmin stepping failed"); + } + + return converged; +} + + /* Gillespie's Source stepping * Modified 2005 - Paolo Nenzi (extracted from CKTop.c code) @@ -323,6 +511,7 @@ gillespie_src (CKTcircuit *ckt, long int firstmode, int converged, i, iters; double ConvFact; CKTnode *n; + double gminstart = ckt->CKTgmin; NG_IGNORE(iterlim); @@ -442,7 +631,13 @@ gillespie_src (CKTcircuit *ckt, long int firstmode, * raise = 0.01; */ - } else { + } +/* else if (ckt->CKTgmin < 1e-3){ + ckt->CKTdiagGmin = ckt->CKTgmin *= 10; + fprintf(stderr, + "gmin raised to %8.4e\n", ckt->CKTgmin); + }*/ + else { if (ckt->CKTsrcFact - ConvFact < 1e-8) break; @@ -459,7 +654,6 @@ gillespie_src (CKTcircuit *ckt, long int firstmode, memcpy(ckt->CKTstate0, OldCKTstate0, (size_t) ckt->CKTnumStates * sizeof(double)); - } if (ckt->CKTsrcFact > 1) @@ -467,6 +661,7 @@ gillespie_src (CKTcircuit *ckt, long int firstmode, } while ((raise >= 1e-7) && (ConvFact < 1)); + ckt->CKTdiagGmin = ckt->CKTgmin = gminstart; FREE (OldRhsOld); FREE (OldCKTstate0); }