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.
112 lines
3.5 KiB
112 lines
3.5 KiB
/**********
|
|
Copyright 1990 Regents of the University of California. All rights reserved.
|
|
Author: 1985 Thomas L. Quarles
|
|
**********/
|
|
|
|
#include "ngspice/ngspice.h"
|
|
#include "ngspice/cktdefs.h"
|
|
#include "vdmosdefs.h"
|
|
#include "ngspice/sperror.h"
|
|
#include "ngspice/suffix.h"
|
|
|
|
int
|
|
VDMOSconvTest(GENmodel *inModel, CKTcircuit *ckt)
|
|
{
|
|
VDMOSmodel *model = (VDMOSmodel*)inModel;
|
|
VDMOSinstance *here;
|
|
double delvgs;
|
|
double delvds;
|
|
double delvgd;
|
|
double cdhat;
|
|
double vgs;
|
|
double vds;
|
|
double vgd;
|
|
double vgdo;
|
|
double tol;
|
|
double delvd,vd,cd;
|
|
int selfheat;
|
|
double delTemp, deldelTemp;
|
|
|
|
for( ; model != NULL; model = VDMOSnextModel(model)) {
|
|
for(here = VDMOSinstances(model); here!= NULL;
|
|
here = VDMOSnextInstance(here)) {
|
|
|
|
vgs = model->VDMOStype * (
|
|
*(ckt->CKTrhs+here->VDMOSgNode) -
|
|
*(ckt->CKTrhs+here->VDMOSsNodePrime));
|
|
vds = model->VDMOStype * (
|
|
*(ckt->CKTrhs+here->VDMOSdNodePrime) -
|
|
*(ckt->CKTrhs+here->VDMOSsNodePrime));
|
|
vgd=vgs-vds;
|
|
vgdo = *(ckt->CKTstate0 + here->VDMOSvgs) -
|
|
*(ckt->CKTstate0 + here->VDMOSvds);
|
|
delvgs = vgs - *(ckt->CKTstate0 + here->VDMOSvgs);
|
|
delvds = vds - *(ckt->CKTstate0 + here->VDMOSvds);
|
|
delvgd = vgd-vgdo;
|
|
|
|
selfheat = (here->VDMOSthermalGiven) && (model->VDMOSrthjcGiven);
|
|
if (selfheat) {
|
|
delTemp = *(ckt->CKTrhs + here->VDMOStempNode);
|
|
deldelTemp = delTemp - *(ckt->CKTstate0 + here->VDMOSdelTemp);
|
|
} else {
|
|
delTemp = 0.0;
|
|
deldelTemp = 0.0;
|
|
}
|
|
|
|
/* these are needed for convergence testing */
|
|
|
|
if (here->VDMOSmode >= 0) {
|
|
cdhat=
|
|
here->VDMOScd -
|
|
here->VDMOSgm * delvgs +
|
|
here->VDMOSgds * delvds +
|
|
here->VDMOSgmT * deldelTemp;
|
|
} else {
|
|
cdhat=
|
|
here->VDMOScd -
|
|
here->VDMOSgm * delvgd +
|
|
here->VDMOSgds * delvds +
|
|
here->VDMOSgmT * deldelTemp;
|
|
}
|
|
/*
|
|
* check convergence
|
|
*/
|
|
tol=ckt->CKTreltol*MAX(fabs(cdhat),fabs(here->VDMOScd))+
|
|
ckt->CKTabstol;
|
|
if (fabs(cdhat-here->VDMOScd) >= tol) {
|
|
ckt->CKTnoncon++;
|
|
ckt->CKTtroubleElt = (GENinstance *) here;
|
|
return(OK); /* no reason to continue, we haven't converged */
|
|
}
|
|
|
|
/*
|
|
* initialization
|
|
*/
|
|
|
|
vd = *(ckt->CKTrhsOld+here->VDIOposPrimeNode)-
|
|
*(ckt->CKTrhsOld + here->VDMOSdNode);
|
|
|
|
delvd=vd- *(ckt->CKTstate0 + here->VDIOvoltage);
|
|
|
|
cdhat= *(ckt->CKTstate0 + here->VDIOcurrent) +
|
|
*(ckt->CKTstate0 + here->VDIOconduct) * delvd +
|
|
*(ckt->CKTstate0 + here->VDIOdIdio_dT) * deldelTemp;
|
|
|
|
cd= *(ckt->CKTstate0 + here->VDIOcurrent);
|
|
|
|
/*
|
|
* check convergence
|
|
*/
|
|
tol=ckt->CKTreltol*
|
|
MAX(fabs(cdhat),fabs(cd))+ckt->CKTabstol;
|
|
if (fabs(cdhat-cd) > tol) {
|
|
ckt->CKTnoncon++;
|
|
ckt->CKTtroubleElt = (GENinstance *) here;
|
|
return(OK); /* don't need to check any more device */
|
|
}
|
|
|
|
|
|
}
|
|
}
|
|
return(OK);
|
|
}
|