📄 twocond.c
字号:
/**********Copyright 1991 Regents of the University of California. All rights reserved.Author: 1987 Kartikeya Mayaram, U. C. Berkeley CAD Group**********//* Functions to compute terminal conductances & currents. */#include <math.h>#include "numglobs.h"#include "numenum.h"#include "nummacs.h"#include "twomesh.h"#include "twodev.h"/* Forward declarations. */double contactConductance();double oxideConductance();double contactCurrent();double oxideCurrent();void storeNewRhs();/* Temporary hack to remove NUMOS gate special case */#ifdef NORMAL_GATE#define GateTypeConductance oxideConductance#define GateTypeCurrent oxideCurrent#else#define GateTypeConductance contactConductance#define GateTypeCurrent contactCurrent#endif /* NORMAL_GATE */void NUMD2conductance( pDevice, tranAnalysis, intCoeff, gd ) TWOdevice *pDevice; BOOLEAN tranAnalysis; double *intCoeff; double *gd;{ TWOcontact *pContact = pDevice->pFirstContact; int index; double *incVpn; BOOLEAN deltaVContact = FALSE; /* * store the new rhs for computing the incremental quantities * with the second to last node. solve the system of equations */ incVpn = pDevice->dcDeltaSolution; storeNewRhs( pDevice, pDevice->pLastContact ); spSolve( pDevice->matrix, pDevice->rhs, incVpn); incVpn = pDevice->dcDeltaSolution; *gd = contactConductance( pDevice, pContact, deltaVContact, incVpn, tranAnalysis, intCoeff ); *gd *= - GNorm * pDevice->width * LNorm;}void NBJT2conductance( pDevice, tranAnalysis, intCoeff, dIeDVce, dIcDVce, dIeDVbe, dIcDVbe ) TWOdevice *pDevice; BOOLEAN tranAnalysis; double *intCoeff; double *dIeDVce, *dIcDVce, *dIeDVbe, *dIcDVbe;{ TWOcontact *pEmitContact = pDevice->pLastContact; TWOcontact *pColContact = pDevice->pFirstContact; TWOcontact *pBaseContact = pDevice->pFirstContact->next; int index; double width = pDevice->width; double *incVce, *incVbe; /* * store the new rhs for computing the incremental quantities * incVce (dcDeltaSolution) and incVbe (copiedSolution) are used to * store the incremental quantities associated with Vce and Vbe */ incVce = pDevice->dcDeltaSolution; incVbe = pDevice->copiedSolution; storeNewRhs( pDevice, pColContact ); spSolve( pDevice->matrix, pDevice->rhs, incVce); storeNewRhs( pDevice, pBaseContact ); spSolve( pDevice->matrix, pDevice->rhs, incVbe); *dIeDVce = contactConductance( pDevice, pEmitContact, FALSE, incVce, tranAnalysis, intCoeff ); *dIeDVbe = contactConductance( pDevice, pEmitContact, FALSE, incVbe, tranAnalysis, intCoeff ); *dIcDVce = contactConductance( pDevice, pColContact, TRUE, incVce, tranAnalysis, intCoeff ); *dIcDVbe = contactConductance( pDevice, pColContact, FALSE, incVbe, tranAnalysis, intCoeff ); *dIeDVce *= GNorm * width * LNorm; *dIcDVce *= GNorm * width * LNorm; *dIeDVbe *= GNorm * width * LNorm; *dIcDVbe *= GNorm * width * LNorm;}void NUMOSconductance( pDevice, tranAnalysis, intCoeff, dIdV ) TWOdevice *pDevice; BOOLEAN tranAnalysis; double *intCoeff; struct mosConductances *dIdV;{ TWOcontact *pDContact = pDevice->pFirstContact; TWOcontact *pGContact = pDevice->pFirstContact->next; TWOcontact *pSContact = pDevice->pFirstContact->next->next; TWOcontact *pBContact = pDevice->pLastContact; int index; double width = pDevice->width; double *incVdb, *incVsb, *incVgb; /* * store the new rhs for computing the incremental quantities * incVdb (dcDeltaSolution) */ incVdb = pDevice->dcDeltaSolution; incVsb = pDevice->copiedSolution; incVgb = pDevice->rhsImag; storeNewRhs( pDevice, pDContact ); spSolve( pDevice->matrix, pDevice->rhs, incVdb); storeNewRhs( pDevice, pSContact ); spSolve( pDevice->matrix, pDevice->rhs, incVsb); storeNewRhs( pDevice, pGContact ); spSolve( pDevice->matrix, pDevice->rhs, incVgb); dIdV->dIdDVdb = contactConductance( pDevice, pDContact, TRUE, incVdb, tranAnalysis, intCoeff ); dIdV->dIsDVdb = contactConductance( pDevice, pSContact, FALSE, incVdb, tranAnalysis, intCoeff ); dIdV->dIgDVdb = GateTypeConductance( pDevice, pGContact, FALSE, incVdb, tranAnalysis, intCoeff ); dIdV->dIdDVsb = contactConductance( pDevice, pDContact, FALSE, incVsb, tranAnalysis, intCoeff ); dIdV->dIsDVsb = contactConductance( pDevice, pSContact, TRUE, incVsb, tranAnalysis, intCoeff ); dIdV->dIgDVsb = GateTypeConductance( pDevice, pGContact, FALSE, incVsb, tranAnalysis, intCoeff ); dIdV->dIdDVgb = contactConductance( pDevice, pDContact, FALSE, incVgb, tranAnalysis, intCoeff ); dIdV->dIsDVgb = contactConductance( pDevice, pSContact, FALSE, incVgb, tranAnalysis, intCoeff ); dIdV->dIgDVgb = GateTypeConductance( pDevice, pGContact, TRUE, incVgb, tranAnalysis, intCoeff ); dIdV->dIdDVdb *= GNorm * width * LNorm; dIdV->dIdDVsb *= GNorm * width * LNorm; dIdV->dIdDVgb *= GNorm * width * LNorm; dIdV->dIsDVdb *= GNorm * width * LNorm; dIdV->dIsDVsb *= GNorm * width * LNorm; dIdV->dIsDVgb *= GNorm * width * LNorm; dIdV->dIgDVdb *= GNorm * width * LNorm; dIdV->dIgDVsb *= GNorm * width * LNorm; dIdV->dIgDVgb *= GNorm * width * LNorm; }double contactCurrent( pDevice, pContact )TWOdevice *pDevice;TWOcontact *pContact;{ /* computes the current through the contact given in pContact */ int index, i, numContactNodes; TWOnode *pNode; TWOelem *pElem; TWOedge *pHEdge, *pVEdge; double dx, dy; double jTotal = 0.0; numContactNodes = pContact->numNodes; for ( index = 0; index < numContactNodes; index++ ) { pNode = pContact->pNodes[ index ]; for ( i = 0; i <= 3; i++ ) { pElem = pNode->pElems[ i ]; if ( pElem ISNOT NIL(TWOelem) ) { dx = 0.5 * pElem->dx; dy = 0.5 * pElem->dy; switch ( i ) { case 0: /* Bottom Right node */ pHEdge = pElem->pBotEdge; pVEdge = pElem->pRightEdge; jTotal += pElem->epsRel * ( -dy * pHEdge->jd - dx * pVEdge->jd ); if ( pElem->elemType IS SEMICON ) { jTotal += -dy * (pHEdge->jn + pHEdge->jp) -dx * (pVEdge->jn + pVEdge->jp); } break; case 1: /* Bottom Left node */ pHEdge = pElem->pBotEdge; pVEdge = pElem->pLeftEdge; jTotal += pElem->epsRel * ( dy * pHEdge->jd - dx * pVEdge->jd ); if ( pElem->elemType IS SEMICON ) { jTotal += dy * (pHEdge->jn + pHEdge->jp) -dx * (pVEdge->jn + pVEdge->jp); } break; case 2: /* Top Left node */ pHEdge = pElem->pTopEdge; pVEdge = pElem->pLeftEdge; jTotal += pElem->epsRel * ( dy * pHEdge->jd + dx * pVEdge->jd ); if ( pElem->elemType IS SEMICON ) { jTotal += dy * (pHEdge->jn + pHEdge->jp) + dx * (pVEdge->jn + pVEdge->jp); } break; case 3: /* Top Right Node */ pHEdge = pElem->pTopEdge; pVEdge = pElem->pRightEdge; jTotal += pElem->epsRel * ( -dy * pHEdge->jd + dx * pVEdge->jd ); if ( pElem->elemType IS SEMICON ) { jTotal += -dy * (pHEdge->jn + pHEdge->jp) + dx * (pVEdge->jn + pVEdge->jp); } break; } } } } return( jTotal * pDevice->width * LNorm * JNorm );}double oxideCurrent( pDevice, pContact, tranAnalysis )TWOdevice *pDevice;TWOcontact *pContact;BOOLEAN tranAnalysis;{ /* computes the current through the contact given in pContact */ int index, i, numContactNodes; TWOnode *pNode; TWOelem *pElem; TWOedge *pHEdge, *pVEdge; double dx, dy; double jTotal = 0.0; if ( NOT tranAnalysis ) { return( jTotal ); } numContactNodes = pContact->numNodes; for ( index = 0; index < numContactNodes; index++ ) { pNode = pContact->pNodes[ index ]; for ( i = 0; i <= 3; i++ ) { pElem = pNode->pElems[ i ]; if ( pElem ISNOT NIL(TWOelem) ) { dx = 0.5 * pElem->dx; dy = 0.5 * pElem->dy; switch ( i ) { case 0: /* Bottom Right node */ pHEdge = pElem->pBotEdge; pVEdge = pElem->pRightEdge; jTotal += pElem->epsRel * ( -dy * pHEdge->jd - dx * pVEdge->jd ); break; case 1: /* Bottom Left node */ pHEdge = pElem->pBotEdge; pVEdge = pElem->pLeftEdge; jTotal += pElem->epsRel * ( dy * pHEdge->jd - dx * pVEdge->jd ); break; case 2: /* Top Left node */ pHEdge = pElem->pTopEdge; pVEdge = pElem->pLeftEdge; jTotal += pElem->epsRel * ( dy * pHEdge->jd + dx * pVEdge->jd ); break; case 3: /* Top Right Node */ pHEdge = pElem->pTopEdge; pVEdge = pElem->pRightEdge; jTotal += pElem->epsRel * ( -dy * pHEdge->jd + dx * pVEdge->jd ); break; } } } } return( jTotal * pDevice->width * LNorm * JNorm );}double contactConductance( pDevice, pContact, delVContact, dxDv, tranAnalysis, intCoeff ) TWOdevice *pDevice; TWOcontact *pContact; BOOLEAN delVContact, tranAnalysis; double *dxDv, *intCoeff;{ /* computes the conductance of the contact given in pContact */ int index, i, numContactNodes; TWOnode *pNode, *pHNode, *pVNode; TWOelem *pElem; TWOedge *pHEdge, *pVEdge; double dPsiDv, dnDv, dpDv; double gTotal = 0.0; int nInc, pInc; /* for one carrier the rest of this code relies on appropriate current derivative term to be zero */ if ( NOT OneCarrier ) { nInc = 1; pInc = 2; } else { nInc = 1; pInc = 1; } numContactNodes = pContact->numNodes; for ( index = 0; index < numContactNodes; index++ ) { pNode = pContact->pNodes[ index ]; for ( i = 0; i <= 3; i++ ) { pElem = pNode->pElems[ i ];
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -