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.
146 lines
4.7 KiB
146 lines
4.7 KiB
/**********
|
|
Copyright 1990 Regents of the University of California. All rights reserved.
|
|
Author: 1985 Thomas L. Quarles
|
|
**********/
|
|
|
|
#include "ngspice.h"
|
|
#include <stdio.h>
|
|
#include "cktdefs.h"
|
|
#include "devdefs.h"
|
|
#include "sperror.h"
|
|
|
|
|
|
int
|
|
CKTop(CKTcircuit *ckt, long int firstmode, long int continuemode, int iterlim)
|
|
{
|
|
int converged;
|
|
int i;
|
|
|
|
ckt->CKTmode = firstmode;
|
|
if(!ckt->CKTnoOpIter) {
|
|
converged = NIiter(ckt,iterlim);
|
|
} else {
|
|
converged = 1; /* the 'go directly to gmin stepping' option */
|
|
}
|
|
if(converged != 0) {
|
|
/* no convergence on the first try, so we do something else */
|
|
/* first, check if we should try gmin stepping */
|
|
/* note that no path out of this code allows ckt->CKTdiagGmin to be
|
|
* anything but 0.000000000
|
|
*/
|
|
if(ckt->CKTnumGminSteps >1) {
|
|
ckt->CKTmode = firstmode;
|
|
(*(SPfrontEnd->IFerror))(ERR_INFO,
|
|
"starting Gmin stepping",(IFuid *)NULL);
|
|
ckt->CKTdiagGmin = ckt->CKTgmin;
|
|
for(i=0;i<ckt->CKTnumGminSteps;i++) {
|
|
ckt->CKTdiagGmin *= 10;
|
|
}
|
|
for(i=0;i<=ckt->CKTnumGminSteps;i++) {
|
|
ckt->CKTnoncon =1;
|
|
converged = NIiter(ckt,iterlim);
|
|
if(converged != 0) {
|
|
ckt->CKTdiagGmin = 0;
|
|
(*(SPfrontEnd->IFerror))(ERR_WARNING,
|
|
"Gmin step failed",(IFuid *)NULL);
|
|
break;
|
|
}
|
|
ckt->CKTdiagGmin /= 10;
|
|
ckt->CKTmode=continuemode;
|
|
(*(SPfrontEnd->IFerror))(ERR_INFO,
|
|
"One successful Gmin step",(IFuid *)NULL);
|
|
}
|
|
ckt->CKTdiagGmin = 0;
|
|
converged = NIiter(ckt,iterlim);
|
|
if(converged == 0) {
|
|
(*(SPfrontEnd->IFerror))(ERR_INFO,
|
|
"Gmin stepping completed",(IFuid *)NULL);
|
|
return(0);
|
|
}
|
|
(*(SPfrontEnd->IFerror))(ERR_WARNING,
|
|
"Gmin stepping failed",(IFuid *)NULL);
|
|
|
|
}
|
|
/* 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
|
|
*
|
|
* note that no path out of this code allows ckt->CKTsrcFact to be
|
|
* anything but 1.000000000
|
|
*/
|
|
if(ckt->CKTnumSrcSteps >1) {
|
|
ckt->CKTmode = firstmode;
|
|
(*(SPfrontEnd->IFerror))(ERR_INFO,
|
|
"starting source stepping",(IFuid *)NULL);
|
|
for(i=0;i<=ckt->CKTnumSrcSteps;i++) {
|
|
ckt->CKTsrcFact = ((double)i)/((double)ckt->CKTnumSrcSteps);
|
|
converged = NIiter(ckt,iterlim);
|
|
ckt->CKTmode = continuemode;
|
|
if(converged != 0) {
|
|
ckt->CKTsrcFact = 1;
|
|
ckt->CKTcurrentAnalysis = DOING_TRAN;
|
|
(*(SPfrontEnd->IFerror))(ERR_WARNING,
|
|
"source stepping failed",(IFuid *)NULL);
|
|
return(converged);
|
|
}
|
|
(*(SPfrontEnd->IFerror))(ERR_INFO,
|
|
"One successful source step",(IFuid *)NULL);
|
|
}
|
|
(*(SPfrontEnd->IFerror))(ERR_INFO,
|
|
"Source stepping completed",(IFuid *)NULL);
|
|
ckt->CKTsrcFact = 1;
|
|
return(0);
|
|
} else {
|
|
return(converged);
|
|
}
|
|
}
|
|
return(0);
|
|
}
|
|
|
|
/* 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)
|
|
{
|
|
extern SPICEdev *DEVices[];
|
|
int i;
|
|
int error = OK;
|
|
#ifdef PARALLEL_ARCH
|
|
int ibuf[2];
|
|
long type = MT_CONV, length = 2;
|
|
#endif /* PARALLEL_ARCH */
|
|
|
|
for (i=0;i<DEVmaxnum;i++) {
|
|
if (((*DEVices[i]).DEVconvTest != NULL) && (ckt->CKThead[i] != NULL)) {
|
|
error = (*((*DEVices[i]).DEVconvTest))(ckt->CKThead[i],ckt);
|
|
}
|
|
#ifdef PARALLEL_ARCH
|
|
if (error || ckt->CKTnoncon) goto combine;
|
|
#else
|
|
if (error) return(error);
|
|
if (ckt->CKTnoncon) {
|
|
/* printf("convTest: device %s failed\n",
|
|
(*DEVices[i]).DEVpublic.name); */
|
|
return(OK);
|
|
}
|
|
#endif /* PARALLEL_ARCH */
|
|
}
|
|
#ifdef PARALLEL_ARCH
|
|
combine:
|
|
/* See if any of the DEVconvTest functions bailed. If not, proceed. */
|
|
ibuf[0] = error;
|
|
ibuf[1] = ckt->CKTnoncon;
|
|
IGOP_( &type, ibuf, &length, "+" );
|
|
ckt->CKTnoncon = ibuf[1];
|
|
if ( ibuf[0] != error ) {
|
|
error = E_MULTIERR;
|
|
}
|
|
return (error);
|
|
#else
|
|
return(OK);
|
|
#endif /* PARALLEL_ARCH */
|
|
}
|