You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
681 lines
20 KiB
681 lines
20 KiB
/**********
|
|
Copyright 1990 Regents of the University of California. All rights reserved.
|
|
Author: 1985 Thomas L. Quarles
|
|
Modified: 2000 AlansFixes
|
|
Modified: 2005 Paolo Nenzi - Restructured
|
|
**********/
|
|
|
|
#include "ngspice/ngspice.h"
|
|
#include "ngspice/cktdefs.h"
|
|
#include "ngspice/devdefs.h"
|
|
#include "ngspice/sperror.h"
|
|
#include "ngspice/cpextern.h"
|
|
|
|
#ifdef XSPICE
|
|
#include "ngspice/enh.h"
|
|
#endif
|
|
|
|
|
|
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);
|
|
|
|
|
|
int
|
|
CKTop (CKTcircuit *ckt, long int firstmode, long int continuemode,
|
|
int iterlim)
|
|
{
|
|
int converged;
|
|
|
|
#ifdef HAS_PROGREP
|
|
SetAnalyse("op", 0);
|
|
#endif
|
|
|
|
ckt->CKTmode = firstmode;
|
|
|
|
if (!ckt->CKTnoOpIter) {
|
|
#ifdef XSPICE
|
|
/* gtri - wbk - add convergence problem reporting flags */
|
|
ckt->enh->conv_debug.last_NIiter_call =
|
|
(ckt->CKTnumGminSteps <= 0) && (ckt->CKTnumSrcSteps <= 0);
|
|
#endif
|
|
converged = NIiter (ckt, iterlim);
|
|
if (converged == 0)
|
|
return converged; /* successfull */
|
|
} else {
|
|
converged = 1; /* the 'go directly to gmin stepping' option */
|
|
}
|
|
|
|
|
|
/* no convergence on the first try, so we do something else */
|
|
/* first, check if we should try gmin stepping */
|
|
|
|
if (ckt->CKTnumGminSteps >= 1) {
|
|
if (ckt->CKTnumGminSteps == 1) {
|
|
/* only the old gmin */
|
|
if (cp_getvar("dyngmin", CP_BOOL, NULL, 0)) {
|
|
converged = dynamic_gmin(ckt, firstmode, continuemode, iterlim);
|
|
}
|
|
/* first the new gmin, then the old gmin */
|
|
else {
|
|
converged = new_gmin(ckt, firstmode, continuemode, iterlim);
|
|
if(converged != 0) {
|
|
converged = dynamic_gmin(ckt, firstmode, continuemode, iterlim);
|
|
}
|
|
|
|
}
|
|
}
|
|
else {
|
|
converged = spice3_gmin(ckt, firstmode, continuemode, iterlim);
|
|
}
|
|
if (converged == 0) /* If gmin-stepping worked... move out */
|
|
return converged;
|
|
}
|
|
|
|
/* ... otherwise try stepping sources ...
|
|
* now, we'll try source stepping - we scale the sources
|
|
* to 0, converge, then start stepping them up until they
|
|
* are at their normal values
|
|
*/
|
|
|
|
if (ckt->CKTnumSrcSteps >= 1) {
|
|
if (ckt->CKTnumSrcSteps == 1)
|
|
converged = gillespie_src(ckt, firstmode, continuemode, iterlim);
|
|
else
|
|
converged = spice3_src(ckt, firstmode, continuemode, iterlim);
|
|
if (converged == 0) /* If gmin-stepping worked... move out */
|
|
return converged;
|
|
}
|
|
|
|
converged = OPtran(ckt);
|
|
|
|
#ifdef XSPICE
|
|
/* gtri - wbk - add convergence problem reporting flags */
|
|
ckt->enh->conv_debug.last_NIiter_call = MIF_FALSE;
|
|
#endif
|
|
|
|
return converged;
|
|
}
|
|
|
|
|
|
/* CKTconvTest(ckt)
|
|
* this is a driver program to iterate through all the various
|
|
* convTest functions provided for the circuit elements in the
|
|
* given circuit
|
|
*/
|
|
|
|
int
|
|
CKTconvTest (CKTcircuit *ckt)
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; i < DEVmaxnum; i++) {
|
|
|
|
if (DEVices[i] && DEVices[i]->DEVconvTest && ckt->CKThead[i]) {
|
|
int error = DEVices[i]->DEVconvTest (ckt->CKThead[i], ckt);
|
|
if (error)
|
|
return error;
|
|
}
|
|
|
|
if (ckt->CKTnoncon) {
|
|
/* printf("convTest: device %s failed\n",
|
|
* DEVices[i]->DEVpublic.name); */
|
|
return OK;
|
|
}
|
|
}
|
|
|
|
return OK;
|
|
}
|
|
|
|
|
|
/* Dynamic gmin stepping
|
|
* Algorithm by Alan Gillespie
|
|
* Modified 2005 - Paolo Nenzi (extracted from CKTop.c code)
|
|
*
|
|
* return value:
|
|
* 0 -> method converged
|
|
* 1 -> method failed
|
|
*
|
|
* Note that no path out of this code allows ckt->CKTdiagGmin to be
|
|
* anything but CKTgshunt.
|
|
*/
|
|
|
|
static int
|
|
dynamic_gmin (CKTcircuit *ckt, long int firstmode,
|
|
long int continuemode, int iterlim)
|
|
{
|
|
double OldGmin, gtarget, factor;
|
|
int converged;
|
|
|
|
int NumNodes, iters, i;
|
|
double *OldRhsOld, *OldCKTstate0;
|
|
CKTnode *n;
|
|
|
|
ckt->CKTmode = firstmode;
|
|
SPfrontEnd->IFerrorf (ERR_INFO, "Starting dynamic 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;
|
|
|
|
factor = ckt->CKTgminFactor;
|
|
OldGmin = 1e-2;
|
|
ckt->CKTdiagGmin = OldGmin / factor;
|
|
gtarget = MAX (ckt->CKTgmin, ckt->CKTgshunt);
|
|
|
|
for (;;) {
|
|
fprintf (stderr, "Trying gmin = %12.4E ", ckt->CKTdiagGmin);
|
|
|
|
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->CKTdiagGmin <= 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->CKTdiagGmin;
|
|
|
|
if (ckt->CKTdiagGmin < factor * gtarget) {
|
|
factor = ckt->CKTdiagGmin / gtarget;
|
|
ckt->CKTdiagGmin = gtarget;
|
|
} else {
|
|
ckt->CKTdiagGmin /= 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 = 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->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, "Dynamic gmin stepping failed");
|
|
} else {
|
|
SPfrontEnd->IFerrorf (ERR_INFO, "Dynamic gmin stepping completed");
|
|
#ifdef XSPICE
|
|
/* gtri - wbk - add convergence problem reporting flags */
|
|
ckt->enh->conv_debug.last_NIiter_call = MIF_FALSE;
|
|
#endif
|
|
}
|
|
|
|
return converged;
|
|
}
|
|
|
|
|
|
/* Spice3 gmin stepping
|
|
* Modified 2000 - Alan Gillespie (added gshunt)
|
|
* Modified 2005 - Paolo Nenzi (extracted from CKTop.c code)
|
|
*
|
|
* return value:
|
|
* 0 -> method converged
|
|
* 1 -> method failed
|
|
*
|
|
* Note that no path out of this code allows ckt->CKTdiagGmin to be
|
|
* anything but CKTgshunt.
|
|
*/
|
|
|
|
static int
|
|
spice3_gmin (CKTcircuit *ckt, long int firstmode,
|
|
long int continuemode, int iterlim)
|
|
{
|
|
int converged, i;
|
|
|
|
ckt->CKTmode = firstmode;
|
|
SPfrontEnd->IFerrorf (ERR_INFO, "Starting gmin stepping");
|
|
|
|
ckt->CKTdiagGmin =
|
|
(ckt->CKTgshunt == 0) ? ckt->CKTgmin : ckt->CKTgshunt;
|
|
|
|
for (i = 0; i < ckt->CKTnumGminSteps; i++)
|
|
ckt->CKTdiagGmin *= ckt->CKTgminFactor;
|
|
|
|
for (i = 0; i <= ckt->CKTnumGminSteps; i++) {
|
|
fprintf (stderr, "Trying gmin = %12.4E ", ckt->CKTdiagGmin);
|
|
|
|
ckt->CKTnoncon = 1;
|
|
converged = NIiter (ckt, ckt->CKTdcTrcvMaxIter);
|
|
|
|
if (converged != 0) {
|
|
ckt->CKTdiagGmin = ckt->CKTgshunt;
|
|
SPfrontEnd->IFerrorf (ERR_WARNING, "gmin step failed");
|
|
break;
|
|
}
|
|
|
|
ckt->CKTdiagGmin /= ckt->CKTgminFactor;
|
|
ckt->CKTmode = continuemode;
|
|
|
|
SPfrontEnd->IFerrorf (ERR_INFO, "One successful gmin step");
|
|
}
|
|
|
|
ckt->CKTdiagGmin = 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;
|
|
}
|
|
|
|
/* 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;
|
|
}
|
|
|
|
|
|
/* Gillespie's Source stepping
|
|
* Modified 2005 - Paolo Nenzi (extracted from CKTop.c code)
|
|
*
|
|
* return value:
|
|
* 0 -> method converged
|
|
* 1 -> method failed
|
|
*
|
|
* Note that no path out of this code allows ckt->CKTsrcFact to be
|
|
* anything but 1.00000.
|
|
*/
|
|
|
|
static int
|
|
gillespie_src (CKTcircuit *ckt, long int firstmode,
|
|
long int continuemode, int iterlim)
|
|
{
|
|
int converged, i, iters;
|
|
double ConvFact;
|
|
CKTnode *n;
|
|
double gminstart = ckt->CKTgmin;
|
|
|
|
NG_IGNORE(iterlim);
|
|
|
|
ckt->CKTmode = firstmode;
|
|
SPfrontEnd->IFerrorf (ERR_INFO, "Starting source stepping");
|
|
|
|
ckt->CKTsrcFact = 0;
|
|
ConvFact = 0;
|
|
|
|
for (n = ckt->CKTnodes; n; n = n->next)
|
|
ckt->CKTrhsOld[n->number] = 0;
|
|
|
|
for (i = 0; i < ckt->CKTnumStates; i++)
|
|
ckt->CKTstate0[i] = 0;
|
|
|
|
/* First, try a straight solution with all sources at zero */
|
|
|
|
fprintf (stderr, "Supplies reduced to %8.4f%% ", ckt->CKTsrcFact * 100);
|
|
converged = NIiter (ckt, ckt->CKTdcTrcvMaxIter);
|
|
|
|
/* If this doesn't work, try gmin stepping as well for the first solution */
|
|
|
|
if (converged != 0) {
|
|
fprintf (stderr, "\n");
|
|
|
|
ckt->CKTdiagGmin =
|
|
(ckt->CKTgshunt <= 0) ? ckt->CKTgmin : ckt->CKTgshunt;
|
|
|
|
for (i = 0; i < 10; i++)
|
|
ckt->CKTdiagGmin *= 10;
|
|
|
|
for (i = 0; i <= 10; i++) {
|
|
fprintf (stderr, "Trying gmin = %12.4E ", ckt->CKTdiagGmin);
|
|
|
|
#ifdef XSPICE
|
|
/* gtri - wbk - add convergence problem reporting flags */
|
|
ckt->enh->conv_debug.last_NIiter_call = MIF_TRUE;
|
|
#endif
|
|
|
|
ckt->CKTnoncon = 1;
|
|
converged = NIiter (ckt, ckt->CKTdcTrcvMaxIter);
|
|
|
|
if (converged != 0) {
|
|
ckt->CKTdiagGmin = ckt->CKTgshunt;
|
|
SPfrontEnd->IFerrorf (ERR_WARNING, "gmin step failed");
|
|
#ifdef XSPICE
|
|
/* gtri - wbk - add convergence problem reporting flags */
|
|
ckt->enh->conv_debug.last_NIiter_call = MIF_FALSE;
|
|
#endif
|
|
break;
|
|
}
|
|
|
|
ckt->CKTdiagGmin /= 10;
|
|
ckt->CKTmode = continuemode;
|
|
SPfrontEnd->IFerrorf (ERR_INFO, "One successful gmin step");
|
|
}
|
|
ckt->CKTdiagGmin = ckt->CKTgshunt;
|
|
}
|
|
|
|
/* If we've got convergence, then try stepping up the sources */
|
|
|
|
if (converged == 0) {
|
|
|
|
double *OldRhsOld, *OldCKTstate0, raise = 0.001;
|
|
|
|
int NumNodes = 0;
|
|
for (n = ckt->CKTnodes; n; n = n->next)
|
|
NumNodes++;
|
|
|
|
OldRhsOld = TMALLOC(double, NumNodes + 1);
|
|
OldCKTstate0 = TMALLOC(double, ckt->CKTnumStates + 1);
|
|
|
|
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));
|
|
|
|
SPfrontEnd->IFerrorf (ERR_INFO, "One successful source step");
|
|
ckt->CKTsrcFact = ConvFact + raise;
|
|
|
|
do {
|
|
fprintf (stderr,
|
|
"Supplies reduced to %8.4f%% ", ckt->CKTsrcFact * 100);
|
|
|
|
#ifdef XSPICE
|
|
/* gtri - wbk - add convergence problem reporting flags */
|
|
ckt->enh->conv_debug.last_NIiter_call = MIF_TRUE;
|
|
#endif
|
|
|
|
iters = ckt->CKTstat->STATnumIter;
|
|
converged = NIiter (ckt, ckt->CKTdcTrcvMaxIter);
|
|
iters = ckt->CKTstat->STATnumIter - iters;
|
|
|
|
ckt->CKTmode = continuemode;
|
|
|
|
if (converged == 0) {
|
|
ConvFact = ckt->CKTsrcFact;
|
|
|
|
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));
|
|
|
|
SPfrontEnd->IFerrorf (ERR_INFO, "One successful source step");
|
|
|
|
ckt->CKTsrcFact = ConvFact + raise;
|
|
|
|
if (iters <= (ckt->CKTdcTrcvMaxIter / 4))
|
|
raise *= 1.5;
|
|
|
|
if (iters > (3 * ckt->CKTdcTrcvMaxIter / 4))
|
|
raise *= 0.5;
|
|
|
|
/* if (raise > 0.01)
|
|
* raise = 0.01;
|
|
*/
|
|
|
|
}
|
|
/* 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;
|
|
|
|
raise /= 10;
|
|
|
|
if (raise > 0.01)
|
|
raise = 0.01;
|
|
|
|
ckt->CKTsrcFact = ConvFact;
|
|
|
|
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));
|
|
}
|
|
|
|
if (ckt->CKTsrcFact > 1)
|
|
ckt->CKTsrcFact = 1;
|
|
|
|
} while ((raise >= 1e-7) && (ConvFact < 1));
|
|
|
|
ckt->CKTdiagGmin = ckt->CKTgmin = gminstart;
|
|
FREE (OldRhsOld);
|
|
FREE (OldCKTstate0);
|
|
}
|
|
|
|
ckt->CKTsrcFact = 1;
|
|
|
|
if (ConvFact != 1) {
|
|
ckt->CKTcurrentAnalysis = DOING_TRAN;
|
|
SPfrontEnd->IFerrorf (ERR_WARNING, "source stepping failed");
|
|
return E_ITERLIM;
|
|
} else {
|
|
SPfrontEnd->IFerrorf (ERR_INFO, "Source stepping completed");
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
|
|
/* Spice3 Source stepping
|
|
* Modified 2005 - Paolo Nenzi (extracted from CKTop.c code)
|
|
*
|
|
* return value:
|
|
* 0 -> method converged
|
|
* 1 -> method failed
|
|
*
|
|
* Note that no path out of this code allows ckt->CKTsrcFact to be
|
|
* anything but 1.00000.
|
|
*/
|
|
|
|
static int
|
|
spice3_src (CKTcircuit *ckt, long int firstmode,
|
|
long int continuemode, int iterlim)
|
|
{
|
|
int converged, i;
|
|
|
|
NG_IGNORE(iterlim);
|
|
|
|
ckt->CKTmode = firstmode;
|
|
SPfrontEnd->IFerrorf (ERR_INFO, "Starting source stepping");
|
|
|
|
for (i = 0; i <= ckt->CKTnumSrcSteps; i++) {
|
|
ckt->CKTsrcFact = ((double) i) / ((double) ckt->CKTnumSrcSteps);
|
|
#ifdef XSPICE
|
|
/* gtri - wbk - add convergence problem reporting flags */
|
|
ckt->enh->conv_debug.last_NIiter_call = MIF_TRUE;
|
|
#endif
|
|
converged = NIiter (ckt, ckt->CKTdcTrcvMaxIter);
|
|
ckt->CKTmode = continuemode;
|
|
if (converged != 0) {
|
|
ckt->CKTsrcFact = 1;
|
|
ckt->CKTcurrentAnalysis = DOING_TRAN;
|
|
SPfrontEnd->IFerrorf (ERR_WARNING, "source stepping failed");
|
|
#ifdef XSPICE
|
|
/* gtri - wbk - add convergence problem reporting flags */
|
|
ckt->enh->conv_debug.last_NIiter_call = MIF_FALSE;
|
|
#endif
|
|
return converged;
|
|
}
|
|
SPfrontEnd->IFerrorf (ERR_INFO, "One successful source step");
|
|
}
|
|
|
|
SPfrontEnd->IFerrorf (ERR_INFO, "Source stepping completed");
|
|
ckt->CKTsrcFact = 1;
|
|
|
|
#ifdef XSPICE
|
|
/* gtri - wbk - add convergence problem reporting flags */
|
|
ckt->enh->conv_debug.last_NIiter_call = MIF_FALSE;
|
|
#endif
|
|
|
|
return 0;
|
|
}
|