📄 twocond.c
字号:
/**********Copyright 1991 Regents of the University of California. All rights reserved.Author: 1987 Kartikeya Mayaram, U. C. Berkeley CAD Group$Id: twocond.c,v 1.3 2005/05/21 12:37:24 sjborley Exp $**********//* Functions to compute terminal conductances & currents. */#include "ngspice.h"#include "numglobs.h"#include "numenum.h"#include "twomesh.h"#include "twodev.h"#include "bool.h"#include "spmatrix.h"#include "twoddefs.h"#include "twodext.h"void NUMD2conductance(TWOdevice *pDevice, BOOLEAN tranAnalysis, double *intCoeff, double *gd){ TWOcontact *pContact = pDevice->pFirstContact; 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, NIL(spREAL), NIL(spREAL)); incVpn = pDevice->dcDeltaSolution; *gd = contactConductance( pDevice, pContact, deltaVContact, incVpn, tranAnalysis, intCoeff ); *gd *= - GNorm * pDevice->width * LNorm;}void NBJT2conductance(TWOdevice *pDevice, BOOLEAN tranAnalysis, double *intCoeff, double *dIeDVce, double *dIcDVce, double *dIeDVbe, double *dIcDVbe){ TWOcontact *pEmitContact = pDevice->pLastContact; TWOcontact *pColContact = pDevice->pFirstContact; TWOcontact *pBaseContact = pDevice->pFirstContact->next; 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, NIL(spREAL), NIL(spREAL)); storeNewRhs( pDevice, pBaseContact ); spSolve( pDevice->matrix, pDevice->rhs, incVbe, NIL(spREAL), NIL(spREAL)); *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(TWOdevice *pDevice, BOOLEAN tranAnalysis, double *intCoeff, struct mosConductances *dIdV){ TWOcontact *pDContact = pDevice->pFirstContact; TWOcontact *pGContact = pDevice->pFirstContact->next; TWOcontact *pSContact = pDevice->pFirstContact->next->next; 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, NIL(spREAL), NIL(spREAL)); storeNewRhs( pDevice, pSContact ); spSolve( pDevice->matrix, pDevice->rhs, incVsb, NIL(spREAL), NIL(spREAL)); storeNewRhs( pDevice, pGContact ); spSolve( pDevice->matrix, pDevice->rhs, incVgb, NIL(spREAL), NIL(spREAL)); 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(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 != 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 == 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 == 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 == 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 == SEMICON ) { jTotal += -dy * (pHEdge->jn + pHEdge->jp) + dx * (pVEdge->jn + pVEdge->jp); } break; } } } } return( jTotal * pDevice->width * LNorm * JNorm );}double oxideCurrent(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 ( !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 != 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(TWOdevice *pDevice, TWOcontact *pContact, BOOLEAN delVContact, double *dxDv, BOOLEAN tranAnalysis, double *intCoeff){ /* computes the conductance of the contact given in pContact */ int index, i, numContactNodes; TWOnode *pNode, *pHNode = NULL, *pVNode = NULL; TWOelem *pElem; TWOedge *pHEdge = NULL, *pVEdge = NULL; 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 ( !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 ]; if ( pElem != NIL(TWOelem) ) { switch ( i ) { case 0: /* the TL element */ pHNode = pElem->pBLNode; pVNode = pElem->pTRNode; pHEdge = pElem->pBotEdge; pVEdge = pElem->pRightEdge; if ( pElem->elemType == SEMICON ) { /* compute the derivatives with n,p */ if ( pHNode->nodeType != CONTACT ) { dnDv = dxDv[ pHNode->nEqn ]; dpDv = dxDv[ pHNode->pEqn ]; gTotal -= 0.5 * pElem->dy * (pHEdge->dJnDn * dnDv
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -