⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 diotemp.c

📁 ngspice又一个电子CAD仿真软件代码.功能更全
💻 C
字号:
/**********Copyright 1990 Regents of the University of California.  All rights reserved.Author: 1985 Thomas L. QuarlesModified: 2000 AlansFixesModified by Dietmar Warning 2003 and Paolo Nenzi 2003**********/    /* perform the temperature update to the diode */#include "ngspice.h"#include "cktdefs.h"#include "diodefs.h"#include "const.h"#include "sperror.h"#include "suffix.h"intDIOtemp(GENmodel *inModel, CKTcircuit *ckt){    DIOmodel *model = (DIOmodel*)inModel;    double xfc, xfcs;    double vte;    double cbv;    double xbv;    double xcbv;    double tol;    double vt;    double vtnom;    double difference;    double factor;    DIOinstance *here;    int iter;    char *emsg;    /*  loop through all the diode models */    for( ; model != NULL; model = model->DIOnextModel ) {        if(!model->DIOnomTempGiven) {            model->DIOnomTemp = ckt->CKTnomTemp;        }        vtnom = CONSTKoverQ * model->DIOnomTemp;        /* limit grading coeff to max of .9 */        if(model->DIOgradingCoeff>.9) {            (*(SPfrontEnd->IFerror))(ERR_WARNING,                    "%s: grading coefficient too large, limited to 0.9",                    &(model->DIOmodName));            model->DIOgradingCoeff=.9;        }        /* limit activation energy to min of .1 */        if(model->DIOactivationEnergy<.1) {            (*(SPfrontEnd->IFerror))(ERR_WARNING,                    "%s: activation energy too small, limited to 0.1",                    &(model->DIOmodName));            model->DIOactivationEnergy=.1;        }        /* limit depletion cap coeff to max of .95 */        if(model->DIOdepletionCapCoeff>.95) {            (*(SPfrontEnd->IFerror))(ERR_WARNING,                    "%s: coefficient Fc too large, limited to 0.95",                    &(model->DIOmodName));            model->DIOdepletionCapCoeff=.95;        }	/* limit sidewall depletion cap coeff to max of .95 */        if(model->DIOdepletionSWcapCoeff>.95) {            (*(SPfrontEnd->IFerror))(ERR_WARNING,                    "%s: coefficient Fcs too large, limited to 0.95",                    &(model->DIOmodName));            model->DIOdepletionSWcapCoeff=.95;        }        if((!model->DIOresistGiven) || (model->DIOresist==0)) {            model->DIOconductance = 0.0;        } else {            model->DIOconductance = 1/model->DIOresist;        }        xfc=log(1-model->DIOdepletionCapCoeff);	xfcs=log(1-model->DIOdepletionSWcapCoeff);	        for(here=model->DIOinstances;here;here=here->DIOnextInstance) {            double egfet1,arg1,fact1,pbfact1,pbo,gmaold,pboSW,gmaSWold;            double fact2,pbfact,arg,egfet,gmanew,gmaSWnew;	    	    if (here->DIOowner != ARCHme) continue;            /* loop through all the instances */            	    if(!here->DIOdtempGiven) here->DIOdtemp = 0.0;	    	    if(!here->DIOtempGiven) 	        here->DIOtemp = ckt->CKTtemp + here->DIOdtemp;				           /* Junction grading temperature adjust */	   difference = here->DIOtemp - model->DIOnomTemp;	   factor = 1.0 + (model->DIOgradCoeffTemp1 * difference)                        + (model->DIOgradCoeffTemp2 * difference * difference);           here->DIOtGradingCoeff = model->DIOgradingCoeff * factor;	   	   /* limit temperature adjusted grading coeff 	* to max of .9 	*/          if(here->DIOtGradingCoeff>.9) {              (*(SPfrontEnd->IFerror))(ERR_WARNING,                    "%s: temperature adjusted grading coefficient too large, limited to 0.9",                    &(here->DIOname));              here->DIOtGradingCoeff=.9;              }				            vt = CONSTKoverQ * here->DIOtemp;            /* this part gets really ugly - I won't even try to         * explain these equations */            fact2 = here->DIOtemp/REFTEMP;            egfet = 1.16-(7.02e-4*here->DIOtemp*here->DIOtemp)/                    (here->DIOtemp+1108);            arg = -egfet/(2*CONSTboltz*here->DIOtemp) +                    1.1150877/(CONSTboltz*(REFTEMP+REFTEMP));            pbfact = -2*vt*(1.5*log(fact2)+CHARGE*arg);            egfet1 = 1.16 - (7.02e-4*model->DIOnomTemp*model->DIOnomTemp)/                    (model->DIOnomTemp+1108);            arg1 = -egfet1/(CONSTboltz*2*model->DIOnomTemp) +                     1.1150877/(2*CONSTboltz*REFTEMP);            fact1 = model->DIOnomTemp/REFTEMP;            pbfact1 = -2 * vtnom*(1.5*log(fact1)+CHARGE*arg1);            pbo = (model->DIOjunctionPot-pbfact1)/fact1;            gmaold = (model->DIOjunctionPot -pbo)/pbo;            here->DIOtJctCap = model->DIOjunctionCap/                    (1+here->DIOtGradingCoeff*                    (400e-6*(model->DIOnomTemp-REFTEMP)-gmaold) );            here->DIOtJctPot = pbfact+fact2*pbo;            gmanew = (here->DIOtJctPot-pbo)/pbo;            here->DIOtJctCap *= 1+here->DIOtGradingCoeff*                    (400e-6*(here->DIOtemp-REFTEMP)-gmanew);            pboSW = (model->DIOjunctionSWPot-pbfact1)/fact1;            gmaSWold = (model->DIOjunctionSWPot -pboSW)/pboSW;            here->DIOtJctSWCap = model->DIOjunctionSWCap/                    (1+model->DIOgradingSWCoeff*                    (400e-6*(model->DIOnomTemp-REFTEMP)-gmaSWold) );            here->DIOtJctSWPot = pbfact+fact2*pboSW;            gmaSWnew = (here->DIOtJctSWPot-pboSW)/pboSW;            here->DIOtJctSWCap *= 1+model->DIOgradingSWCoeff*                    (400e-6*(here->DIOtemp-REFTEMP)-gmaSWnew);            here->DIOtSatCur = model->DIOsatCur *  exp(                     ((here->DIOtemp/model->DIOnomTemp)-1) *                    model->DIOactivationEnergy/(model->DIOemissionCoeff*vt) +                    model->DIOsaturationCurrentExp/model->DIOemissionCoeff*                    log(here->DIOtemp/model->DIOnomTemp) );            here->DIOtSatSWCur = model->DIOsatSWCur *  exp(                     ((here->DIOtemp/model->DIOnomTemp)-1) *                    model->DIOactivationEnergy/(model->DIOemissionCoeff*vt) +                    model->DIOsaturationCurrentExp/model->DIOemissionCoeff*                    log(here->DIOtemp/model->DIOnomTemp) );            /* the defintion of f1, just recompute after temperature adjusting             * all the variables used in it */            here->DIOtF1=here->DIOtJctPot*                    (1-exp((1-here->DIOtGradingCoeff)*xfc))/                    (1-here->DIOtGradingCoeff);            /* same for Depletion Capacitance */            here->DIOtDepCap=model->DIOdepletionCapCoeff*                    here->DIOtJctPot;            /* and Vcrit */            vte=model->DIOemissionCoeff*vt;                        here->DIOtVcrit=vte*                          log(vte/(CONSTroot2*here->DIOtSatCur*here->DIOarea));                        /* and now to copute the breakdown voltage, again, using             * temperature adjusted basic parameters */            if (model->DIObreakdownVoltageGiven){                cbv=model->DIObreakdownCurrent*here->DIOarea*here->DIOm;                if (cbv < here->DIOtSatCur*here->DIOarea*here->DIOm *                          model->DIObreakdownVoltage/vt) {                    cbv=here->DIOtSatCur*here->DIOarea*here->DIOm *                         model->DIObreakdownVoltage/vt;                    emsg = MALLOC(100);                    if(emsg == (char *)NULL) return(E_NOMEM);                    (void)sprintf(emsg,                    "%%s: breakdown current increased to %g to resolve",                            cbv);                    (*(SPfrontEnd->IFerror))(ERR_WARNING,emsg,&(here->DIOname));                    FREE(emsg);                    (*(SPfrontEnd->IFerror))(ERR_WARNING,                    "incompatibility with specified saturation current",(IFuid*)NULL);                    xbv=model->DIObreakdownVoltage;                } else {                    tol=ckt->CKTreltol*cbv;                    xbv=model->DIObreakdownVoltage-vt*log(1+cbv/                            (here->DIOtSatCur*here->DIOarea*here->DIOm));                    iter=0;                    for(iter=0 ; iter < 25 ; iter++) {                        xbv=model->DIObreakdownVoltage-vt*log(cbv/                                (here->DIOtSatCur*here->DIOarea*here->DIOm)+1-xbv/vt);                        xcbv=here->DIOtSatCur*here->DIOarea*here->DIOm *                              (exp((model->DIObreakdownVoltage-xbv)/vt)-1+xbv/vt);                        if (fabs(xcbv-cbv) <= tol) goto matched;                    }                    emsg = MALLOC(100);                    if(emsg == (char *)NULL) return(E_NOMEM);                    (void)sprintf(emsg,                    "%%s: unable to match forward and reverse diode regions: bv = %g, ibv = %g",                            xbv,xcbv);                    (*(SPfrontEnd->IFerror))(ERR_WARNING,emsg,&here->DIOname);                    FREE(emsg);                }                matched:                here->DIOtBrkdwnV = xbv;            }	    	    /* transit time temperature adjust */	    difference = here->DIOtemp - model->DIOnomTemp;	    factor = 1.0 + (model->DIOtranTimeTemp1 * difference) 	                 + (model->DIOtranTimeTemp2 * difference * difference);	    here->DIOtTransitTime = model->DIOtransitTime * factor;			    /* Series resistance temperature adjust */	    here->DIOtConductance = model->DIOconductance;	    if(model->DIOresistGiven && model->DIOresist!=0.0) {                difference = here->DIOtemp - model->DIOnomTemp;	        factor = 1.0 + (model->DIOresistTemp1) * difference		             + (model->DIOresistTemp2 * difference * difference);	        here->DIOtConductance = model->DIOconductance / factor;            }	                here->DIOtF2=exp((1+here->DIOtGradingCoeff)*xfc);            here->DIOtF3=1-model->DIOdepletionCapCoeff*                    (1+here->DIOtGradingCoeff);            here->DIOtF2SW=exp((1+model->DIOgradingSWCoeff)*xfcs);            here->DIOtF3SW=1-model->DIOdepletionSWcapCoeff*                    (1+model->DIOgradingSWCoeff);		} /* instance */       		    } /* model */    return(OK);}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -