📄 onesetup.c
字号:
/**********Copyright 1991 Regents of the University of California. All rights reserved.Author: 1987 Kartikeya Mayaram, U. C. Berkeley CAD GroupAuthor: 1991 David A. Gates, U. C. Berkeley CAD Group**********//**********One-Dimensional Numerical Device Setup Routines**********/#include <math.h>#include "numglobs.h"#include "numconst.h"#include "numenum.h"#include "nummacs.h"#include "onemesh.h"#include "onedev.h"#include "carddefs.h" /* XXX Not really modular if we need this. *//* compute node parameters */voidONEsetup(pDevice) ONEdevice *pDevice;{ double temp1, deltaEg, avgConc, totalConc, absNetConc; double ncv0, dBand, dNie, psiBand[2]; int index, eIndex; int numContactNodes; ONEnode *pNode; ONEelem *pElem; ONEedge *pEdge; ONEmaterial *info; for (eIndex = 1; eIndex < pDevice->numNodes; eIndex++) { pElem = pDevice->elemArray[eIndex]; info = pElem->matlInfo; pElem->dx = pElem->pRightNode->x - pElem->pLeftNode->x; pElem->epsRel = info->eps; if (pElem->elemType IS INSULATOR) { for (index = 0; index <= 1; index++) { if (pElem->evalNodes[index]) { pNode = pElem->pNodes[index]; if (pNode->nodeType IS CONTACT) { pNode->eaff = PHI_METAL; pNode->eg = 0.0; } else { pNode->eaff = info->affin; pNode->eg = info->eg0; } } } } else if (pElem->elemType IS SEMICON) { ncv0 = sqrt(info->nc0) * sqrt(info->nv0); for (index = 0; index <= 1; index++) { if (pElem->evalNodes[index]) { pNode = pElem->pNodes[index]; /* Fixed Interface Charge */ pNode->qf = 0.0; /* Narrowing of Energy Band-Gap */ if (BandGapNarrowing) { absNetConc = ABS(pNode->netConc); if (pNode->netConc > 0.0) { temp1 = log(absNetConc / info->nrefBGN[ELEC]); deltaEg = -info->dEgDn[ELEC] * (temp1 + sqrt(temp1 * temp1 + 0.5)); pNode->eg = info->eg0 + deltaEg; } else if (pNode->netConc < 0.0) { temp1 = log(absNetConc / info->nrefBGN[HOLE]); deltaEg = -info->dEgDn[HOLE] * (temp1 + sqrt(temp1 * temp1 + 0.5)); pNode->eg = info->eg0 + deltaEg; } else { pNode->eg = info->eg0; } } else { pNode->eg = info->eg0; } pNode->nie = ncv0 * exp(-0.5 * pNode->eg / Vt); pNode->eaff = info->affin; /* Save band structure parameter. */ psiBand[index] = -info->refPsi; /* Ionized-Impurity-Scattering Reduction of Carrier Lifetime */ if (ConcDepLifetime) { totalConc = pNode->totalConc; temp1 = 1.0 / (1.0 + totalConc / info->nrefSRH[ELEC]); pNode->tn = info->tau0[ELEC] * temp1; temp1 = 1.0 / (1.0 + totalConc / info->nrefSRH[HOLE]); pNode->tp = info->tau0[HOLE] * temp1; } else { pNode->tn = info->tau0[ELEC]; pNode->tp = info->tau0[HOLE]; } } } pEdge = pElem->pEdge; /* Variable Band Built-In Potential */ dBand = psiBand[1] - psiBand[0]; dNie = log(pElem->pNodes[1]->nie / pElem->pNodes[0]->nie); pEdge->dCBand = dBand + dNie; pEdge->dVBand = -dBand + dNie; /* Evaluate conc.-dep. mobility. */ avgConc = 0.5 * (pElem->pRightNode->totalConc + pElem->pLeftNode->totalConc); MOBconcDep(info, avgConc, &pEdge->mun, &pEdge->mup); } }}/* Transfer BC info from bdry to nodes and edges. */static voidONEcopyBCinfo(pDevice, pElem, bdry, index) ONEdevice *pDevice; ONEelem *pElem; BDRYcard *bdry; int index;{ ONEnode *pNode; ONEelem *pNElem; int eIndex, nIndex; double length; /* First add fixed charge. */ pNode = pElem->pNodes[index]; pNode->qf += bdry->BDRYqf; /* Now add surface recombination. */ /* Compute semiconductor length around this node. */ length = 0.0; for (eIndex = 0; eIndex <= 3; eIndex++) { pNElem = pNode->pElems[eIndex]; if (pNElem ISNOT NIL(ONEelem) && pElem->elemType IS SEMICON) { length += 0.5 * pElem->dx; } } if (bdry->BDRYsnGiven) { pNode->tn = pNode->tn / (1.0 + ((bdry->BDRYsn * TNorm) * pNode->tn) / length); } if (bdry->BDRYspGiven) { pNode->tp = pNode->tp / (1.0 + ((bdry->BDRYsp * TNorm) * pNode->tp) / length); } /* Finally, surface layer is irrelevant for 1d devices. */}/* Compute boundary condition parameters. */voidONEsetBCparams(pDevice, bdryList, contList) ONEdevice *pDevice; BDRYcard *bdryList; CONTcard *contList;{ int index, xIndex; ONEnode *pNode; ONEelem *pElem, *pNElem; BDRYcard *bdry; CONTcard *cont; for (bdry = bdryList; bdry != NIL(BDRYcard); bdry = bdry->BDRYnextCard) { for (xIndex = bdry->BDRYixLow; xIndex < bdry->BDRYixHigh; xIndex++) { pElem = pDevice->elemArray[xIndex]; if (pElem ISNOT NIL(ONEelem)) { if (pElem->domain == bdry->BDRYdomain) { for (index = 0; index <= 1; index++) { if (pElem->evalNodes[index]) { pNElem = pElem->pElems[index]; if (bdry->BDRYneighborGiven) { if (pNElem && pNElem->domain == bdry->BDRYneighbor) { /* Found an interface node. */ ONEcopyBCinfo(pDevice, pElem, bdry, index); } } else { if (!pNElem || pNElem->domain != pElem->domain) { /* Found a boundary node. */ ONEcopyBCinfo(pDevice, pElem, bdry, index); } } } } } } } } for (cont = contList; cont != NIL(CONTcard); cont = cont->CONTnextCard) { if (!cont->CONTworkfunGiven) { cont->CONTworkfun = PHI_METAL; } /* * XXX This won't work right if someone tries to change the 1d BJT base * contact workfunction and doesn't want to change the emitter. But no * one will probably try to do that. */ if (cont->CONTnumber == 1) { pDevice->elemArray[1]->pNodes[0]->eaff = cont->CONTworkfun; } else if (cont->CONTnumber == 2 || cont->CONTnumber == 3) { pDevice->elemArray[pDevice->numNodes - 1]->pNodes[1]->eaff = cont->CONTworkfun; } }}voidONEnormalize(pDevice) ONEdevice *pDevice;{ int index, eIndex; ONEelem *pElem; ONEnode *pNode; for (eIndex = 1; eIndex < pDevice->numNodes; eIndex++) { pElem = pDevice->elemArray[eIndex]; pElem->dx /= LNorm; pElem->rDx = 1.0 / pElem->dx; pElem->epsRel /= EpsNorm; for (index = 0; index <= 1; index++) { if (pElem->evalNodes[index]) { pNode = pElem->pNodes[index]; pNode->netConc /= NNorm; pNode->nd /= NNorm; pNode->na /= NNorm; pNode->qf /= (NNorm * LNorm); pNode->nie /= NNorm; pNode->eg /= VNorm; pNode->eaff /= VNorm; } } }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -