📄 onecont.c
字号:
/**********Copyright 1991 Regents of the University of California. All rights reserved.Author: 1987 Kartikeya Mayaram, U. C. Berkeley CAD Group**********/#include <math.h>#include "numglobs.h"#include "numenum.h"#include "nummacs.h"#include "onemesh.h"#include "onedev.h"#include "spmatrix.h"/* functions to setup and solve the continuity equations *//* Both continuity equations are solved */extern double integrate();extern double ONEavalanche();void ONE_commonTerms();void ONE_jacBuild(pDevice) ONEdevice *pDevice;{ char *matrix = pDevice->matrix; ONEelem *pElem; ONEnode *pNode, *pNode1; int index, eIndex; int psiEqn, nEqn, pEqn; /* scratch for deref'd eqn numbers */ int psiEqnL, nEqnL, pEqnL; int psiEqnR, nEqnR, pEqnR; for (eIndex = 1; eIndex < pDevice->numNodes; eIndex++) { pElem = pDevice->elemArray[eIndex]; /* first the self terms */ for (index = 0; index <= 1; index++) { pNode = pElem->pNodes[index]; /* get poisson pointer */ psiEqn = pNode->psiEqn; pNode->fPsiPsi = spGetElement(matrix, psiEqn, psiEqn); if (pElem->elemType IS SEMICON) { /* get continuity-coupling terms */ nEqn = pNode->nEqn; pEqn = pNode->pEqn; /* pointers for additional terms */ pNode->fPsiN = spGetElement(matrix, psiEqn, nEqn); pNode->fPsiP = spGetElement(matrix, psiEqn, pEqn); pNode->fNPsi = spGetElement(matrix, nEqn, psiEqn); pNode->fNN = spGetElement(matrix, nEqn, nEqn); pNode->fNP = spGetElement(matrix, nEqn, pEqn); pNode->fPPsi = spGetElement(matrix, pEqn, psiEqn); pNode->fPP = spGetElement(matrix, pEqn, pEqn); pNode->fPN = spGetElement(matrix, pEqn, nEqn); } else { nEqn = 0; pEqn = 0; } /* save indices */ if (index == 0) { /* left node */ psiEqnL = psiEqn; nEqnL = nEqn; pEqnL = pEqn; } else { psiEqnR = psiEqn; nEqnR = nEqn; pEqnR = pEqn; } } /* now terms to couple to adjacent nodes */ pNode = pElem->pLeftNode; pNode->fPsiPsiiP1 = spGetElement(matrix, psiEqnL, psiEqnR); if (pElem->elemType IS SEMICON) { /* pointers for additional terms */ pNode->fNPsiiP1 = spGetElement(matrix, nEqnL, psiEqnR); pNode->fNNiP1 = spGetElement(matrix, nEqnL, nEqnR); pNode->fPPsiiP1 = spGetElement(matrix, pEqnL, psiEqnR); pNode->fPPiP1 = spGetElement(matrix, pEqnL, pEqnR); if (AvalancheGen) { pNode->fNPiP1 = spGetElement(matrix, nEqnL, pEqnR); pNode->fPNiP1 = spGetElement(matrix, pEqnL, nEqnR); } } pNode = pElem->pRightNode; pNode->fPsiPsiiM1 = spGetElement(matrix, psiEqnR, psiEqnL); if (pElem->elemType IS SEMICON) { /* pointers for additional terms */ pNode->fNPsiiM1 = spGetElement(matrix, nEqnR, psiEqnL); pNode->fNNiM1 = spGetElement(matrix, nEqnR, nEqnL); pNode->fPPsiiM1 = spGetElement(matrix, pEqnR, psiEqnL); pNode->fPPiM1 = spGetElement(matrix, pEqnR, pEqnL); if (AvalancheGen) { pNode->fNPiM1 = spGetElement(matrix, nEqnR, pEqnL); pNode->fPNiM1 = spGetElement(matrix, pEqnR, nEqnL); } } }}void ONE_sysLoad(pDevice, tranAnalysis, info) ONEdevice *pDevice; BOOLEAN tranAnalysis; ONEtranInfo *info;{ ONEelem *pElem; ONEnode *pNode, *pNode1; ONEedge *pEdge; int index, eIndex; double *pRhs = pDevice->rhs; double dx, rDx, dPsi; double rhsN, rhsP, generation; double perTime; double fNd, fNa, fdNd, fdNa; double netConc, dNd, dNa, psi, nConc, pConc; /* first compute the currents and their derivatives */ ONE_commonTerms(pDevice, FALSE, tranAnalysis, info); /* find reciprocal timestep */ if (tranAnalysis) { perTime = info->intCoeff[0]; } /* zero the rhs vector */ for (index = 1; index <= pDevice->numEqns; index++) { pRhs[index] = 0.0; } /* zero the matrix */ spClear(pDevice->matrix); for (eIndex = 1; eIndex < pDevice->numNodes; eIndex++) { pElem = pDevice->elemArray[eIndex]; dx = 0.5 * pElem->dx; rDx = pElem->epsRel * pElem->rDx; /* load for all i */ for (index = 0; index <= 1; index++) { pNode = pElem->pNodes[index]; if (pNode->nodeType ISNOT CONTACT) { *(pNode->fPsiPsi) += rDx; pRhs[pNode->psiEqn] += pNode->qf; if (pElem->elemType IS SEMICON) { pEdge = pElem->pEdge; netConc = pNode->netConc; dNd = 0.0; dNa = 0.0; psi = *(pDevice->devState0 + pNode->nodePsi); nConc = *(pDevice->devState0 + pNode->nodeN); pConc = *(pDevice->devState0 + pNode->nodeP); if (FreezeOut) { ONE_freezeOut(pNode, nConc, pConc, &fNd, &fNa, &fdNd, &fdNa); netConc = pNode->nd * fNd - pNode->na * fNa; dNd = pNode->nd * fdNd; dNa = pNode->na * fdNa; } *(pNode->fPsiN) += dx * (1.0 - dNd); *(pNode->fPsiP) -= dx * (1.0 - dNa); *(pNode->fNPsi) -= pEdge->dJnDpsiP1; *(pNode->fPPsi) -= pEdge->dJpDpsiP1; pRhs[pNode->psiEqn] += dx * (netConc + pConc - nConc); /* Handle generation terms */ *(pNode->fNN) -= dx * pNode->dUdN; *(pNode->fNP) -= dx * pNode->dUdP; *(pNode->fPP) += dx * pNode->dUdP; *(pNode->fPN) += dx * pNode->dUdN; pRhs[pNode->nEqn] -= -dx * pNode->uNet; pRhs[pNode->pEqn] -= dx * pNode->uNet; /* Handle dXdT continuity terms */ if (tranAnalysis) { *(pNode->fNN) -= dx * perTime; *(pNode->fPP) += dx * perTime; pRhs[pNode->nEqn] += dx * pNode->dNdT; pRhs[pNode->pEqn] -= dx * pNode->dPdT; } /* Take care of base contact if necessary */ /* eg holds the base edge mu/dx */ if (pNode->baseType IS N_TYPE) { pRhs[pNode->nEqn] += 0.5 * pNode->eg * nConc * (pNode->vbe - psi + log(nConc / pNode->nie)); *(pNode->fNPsi) += 0.5 * pNode->eg * nConc; *(pNode->fNN) -= 0.5 * pNode->eg * (pNode->vbe - psi + log(nConc / pNode->nie) + 1.0); } else if (pNode->baseType IS P_TYPE) { pRhs[pNode->pEqn] += 0.5 * pNode->eg * pConc * (pNode->vbe - psi - log(pConc / pNode->nie)); *(pNode->fPPsi) += 0.5 * pNode->eg * pConc; *(pNode->fPP) -= 0.5 * pNode->eg * (pNode->vbe - psi - log(pConc / pNode->nie) - 1.0); } } } } pEdge = pElem->pEdge; dPsi = pEdge->dPsi; pNode = pElem->pLeftNode; if (pNode->nodeType ISNOT CONTACT) { pRhs[pNode->psiEqn] += rDx * dPsi; *(pNode->fPsiPsiiP1) -= rDx; if (pElem->elemType IS SEMICON) { pRhs[pNode->nEqn] -= pEdge->jn; pRhs[pNode->pEqn] -= pEdge->jp; *(pNode->fNN) += pEdge->dJnDn; *(pNode->fPP) += pEdge->dJpDp; *(pNode->fNPsiiP1) += pEdge->dJnDpsiP1; *(pNode->fNNiP1) += pEdge->dJnDnP1; *(pNode->fPPsiiP1) += pEdge->dJpDpsiP1; *(pNode->fPPiP1) += pEdge->dJpDpP1; } } pNode = pElem->pRightNode; if (pNode->nodeType ISNOT CONTACT) { pRhs[pNode->psiEqn] -= rDx * dPsi; *(pNode->fPsiPsiiM1) -= rDx; if (pElem->elemType IS SEMICON) { pRhs[pNode->nEqn] += pEdge->jn; pRhs[pNode->pEqn] += pEdge->jp; *(pNode->fNN) -= pEdge->dJnDnP1; *(pNode->fPP) -= pEdge->dJpDpP1; *(pNode->fNPsiiM1) += pEdge->dJnDpsiP1; *(pNode->fNNiM1) -= pEdge->dJnDn; *(pNode->fPPsiiM1) += pEdge->dJpDpsiP1; *(pNode->fPPiM1) -= pEdge->dJpDp; } } } if (AvalancheGen) { /* add the generation terms */ for (eIndex = 1; eIndex < pDevice->numNodes; eIndex++) { pElem = pDevice->elemArray[eIndex]; for (index = 0; index <= 1; index++) { if (pElem->evalNodes[index]) { pNode = pElem->pNodes[index]; if (pNode->nodeType ISNOT CONTACT AND pElem->elemType IS SEMICON) { generation = ONEavalanche(FALSE, pDevice, pNode); pRhs[pNode->nEqn] -= generation; pRhs[pNode->pEqn] += generation; } } } } }}void ONE_jacLoad(pDevice) ONEdevice *pDevice;{ /* used only for ac analysis */ ONEelem *pElem; ONEnode *pNode, *pNode1; ONEedge *pEdge; int index, eIndex; double dx, rDx, dPsi; double rhsN, rhsP, generation; double fNd, fNa, fdNd, fdNa; double netConc, dNd, dNa, psi, nConc, pConc; /* first compute the currents and their derivatives */ ONE_commonTerms(pDevice, FALSE, FALSE, NIL(ONEtranInfo)); /* zero the matrix */ spClear(pDevice->matrix); for (eIndex = 1; eIndex < pDevice->numNodes; eIndex++) { pElem = pDevice->elemArray[eIndex]; dx = 0.5 * pElem->dx; rDx = pElem->epsRel * pElem->rDx; /* load for all i */ for (index = 0; index <= 1; index++) { pNode = pElem->pNodes[index]; if (pNode->nodeType ISNOT CONTACT) { *(pNode->fPsiPsi) += rDx; if (pElem->elemType IS SEMICON) { pEdge = pElem->pEdge; dNd = 0.0; dNa = 0.0; psi = *(pDevice->devState0 + pNode->nodePsi); nConc = *(pDevice->devState0 + pNode->nodeN); pConc = *(pDevice->devState0 + pNode->nodeP); if (FreezeOut) { ONE_freezeOut(pNode, nConc, pConc, &fNd, &fNa, &fdNd, &fdNa); dNd = pNode->nd * fdNd; dNa = pNode->na * fdNa; } *(pNode->fPsiN) += dx * (1.0 - dNd); *(pNode->fPsiP) -= dx * (1.0 - dNa); *(pNode->fNPsi) -= pEdge->dJnDpsiP1; *(pNode->fPPsi) -= pEdge->dJpDpsiP1; if (pNode->baseType IS N_TYPE) { *(pNode->fNPsi) += 0.5 * nConc * pNode->eg; *(pNode->fNN) -= 0.5 * pNode->eg * (pNode->vbe - psi + log(nConc / pNode->nie) + 1.0); } if (pNode->baseType IS P_TYPE) { *(pNode->fPPsi) += 0.5 * pConc * pNode->eg; *(pNode->fPP) -= 0.5 * pNode->eg * (pNode->vbe - psi - log(pConc / pNode->nie) - 1.0); } } } } pNode = pElem->pLeftNode; if (pNode->nodeType ISNOT CONTACT) { pEdge = pElem->pEdge; dPsi = pEdge->dPsi; if (pElem->elemType IS SEMICON) { *(pNode->fNN) += pEdge->dJnDn - dx * pNode->dUdN; *(pNode->fNP) -= dx * pNode->dUdP; *(pNode->fPP) += pEdge->dJpDp + dx * pNode->dUdP;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -