📄 twopoiss.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**********/#include <math.h>#include "numglobs.h"#include "numenum.h"#include "nummacs.h"#include "twomesh.h"#include "twodev.h"/* functions to setup and solve the 2D poisson equation */void TWOQjacBuild(pDevice)TWOdevice *pDevice;{ char *matrix = pDevice->matrix; double *spGetElement(); TWOelem *pElem; TWOnode *pNode, *pNode1; int eIndex, nIndex; /* set up matrix pointers */ /* establish main diagonal first */ for ( eIndex = 1; eIndex <= pDevice->numElems; eIndex++ ) { pElem = pDevice->elements[ eIndex ]; for ( nIndex = 0; nIndex <= 3; nIndex++ ) { if ( pElem->evalNodes[ nIndex ] ) { pNode = pElem->pNodes[ nIndex ]; pNode->fPsiPsi = spGetElement( matrix, pNode->poiEqn, pNode->poiEqn ); } } } for ( eIndex = 1; eIndex <= pDevice->numElems; eIndex++ ) { pElem = pDevice->elements[ eIndex ]; pNode = pElem->pTLNode; pNode1 = pElem->pTRNode; pNode->fPsiPsiiP1 = spGetElement(matrix, pNode->poiEqn, pNode1->poiEqn ); pNode1 = pElem->pBLNode; pNode->fPsiPsijP1 = spGetElement(matrix, pNode->poiEqn, pNode1->poiEqn ); pNode = pElem->pTRNode; pNode1 = pElem->pTLNode; pNode->fPsiPsiiM1 = spGetElement(matrix, pNode->poiEqn, pNode1->poiEqn ); pNode1 = pElem->pBRNode; pNode->fPsiPsijP1 = spGetElement(matrix, pNode->poiEqn, pNode1->poiEqn ); pNode = pElem->pBRNode; pNode1 = pElem->pBLNode; pNode->fPsiPsiiM1 = spGetElement(matrix, pNode->poiEqn, pNode1->poiEqn ); pNode1 = pElem->pTRNode; pNode->fPsiPsijM1 = spGetElement(matrix, pNode->poiEqn, pNode1->poiEqn ); pNode = pElem->pBLNode; pNode1 = pElem->pBRNode; pNode->fPsiPsiiP1 = spGetElement(matrix, pNode->poiEqn, pNode1->poiEqn ); pNode1 = pElem->pTLNode; pNode->fPsiPsijM1 = spGetElement(matrix, pNode->poiEqn, pNode1->poiEqn ); } /* for ( eIndex = 1; eIndex <= pDevice->numElems; eIndex++ ) { pElem = pDevice->elements[ eIndex ]; pNode = pElem->pTLNode; pNode->fPsiPsi = spGetElement( matrix, pNode->poiEqn, pNode->poiEqn ); pNode1 = pElem->pTRNode; pNode->fPsiPsiiP1 = spGetElement(matrix, pNode->poiEqn, pNode1->poiEqn ); pNode1 = pElem->pBLNode; pNode->fPsiPsijP1 = spGetElement(matrix, pNode->poiEqn, pNode1->poiEqn ); pNode = pElem->pTRNode; pNode->fPsiPsi = spGetElement( matrix, pNode->poiEqn, pNode->poiEqn ); pNode1 = pElem->pTLNode; pNode->fPsiPsiiM1 = spGetElement(matrix, pNode->poiEqn, pNode1->poiEqn ); pNode1 = pElem->pBRNode; pNode->fPsiPsijP1 = spGetElement(matrix, pNode->poiEqn, pNode1->poiEqn ); pNode = pElem->pBRNode; pNode->fPsiPsi = spGetElement( matrix, pNode->poiEqn, pNode->poiEqn ); pNode1 = pElem->pBLNode; pNode->fPsiPsiiM1 = spGetElement(matrix, pNode->poiEqn, pNode1->poiEqn ); pNode1 = pElem->pTRNode; pNode->fPsiPsijM1 = spGetElement(matrix, pNode->poiEqn, pNode1->poiEqn ); pNode = pElem->pBLNode; pNode->fPsiPsi = spGetElement( matrix, pNode->poiEqn, pNode->poiEqn ); pNode1 = pElem->pBRNode; pNode->fPsiPsiiP1 = spGetElement(matrix, pNode->poiEqn, pNode1->poiEqn ); pNode1 = pElem->pTLNode; pNode->fPsiPsijM1 = spGetElement(matrix, pNode->poiEqn, pNode1->poiEqn ); } */}void TWOQsysLoad( pDevice ) TWOdevice *pDevice;{ TWOelem *pElem; TWOnode *pNode, *pNode1; TWOedge *pHEdge, *pVEdge; int index, eIndex; double *pRhs = pDevice->rhs; double dyOverDx, dxOverDy, dPsiT, dPsiB, dPsiL, dPsiR; void spClear(), TWOQcommonTerms(); TWOQcommonTerms( pDevice ); /* 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->numElems; eIndex++ ) { pElem = pDevice->elements[ eIndex ]; dxOverDy = 0.5 * pElem->epsRel * pElem->dxOverDy; dyOverDx = 0.5 * pElem->epsRel * pElem->dyOverDx; dPsiT = pElem->pTopEdge->dPsi; dPsiB = pElem->pBotEdge->dPsi; dPsiL = pElem->pLeftEdge->dPsi; dPsiR = pElem->pRightEdge->dPsi; /* load for all i,j */ for ( index = 0; index <= 3; index++ ) { pNode = pElem->pNodes[ index ]; if ( pNode->nodeType ISNOT CONTACT ) { *(pNode->fPsiPsi) += dyOverDx + dxOverDy; if ( index <= 1 ) { pHEdge = pElem->pTopEdge; } else { pHEdge = pElem->pBotEdge; } if ( index IS 0 OR index IS 3 ) { pVEdge = pElem->pLeftEdge; } else { pVEdge = pElem->pRightEdge; } /* add surface state charges */ pRhs[ pNode->poiEqn ] += 0.5 * pElem->dx * pHEdge->qf; pRhs[ pNode->poiEqn ] += 0.5 * pElem->dy * pVEdge->qf; if ( pElem->elemType IS SEMICON ) { *(pNode->fPsiPsi) += 0.25 * pElem->dx * pElem->dy * (pNode->nConc + pNode->pConc); pRhs[ pNode->poiEqn ] += 0.25 * pElem->dx * pElem->dy * (pNode->netConc + pNode->pConc - pNode->nConc); } } } pNode = pElem->pTLNode; pRhs[ pNode->poiEqn ] -= -dyOverDx * dPsiT - dxOverDy * dPsiL; *(pNode->fPsiPsiiP1) -= dyOverDx; *(pNode->fPsiPsijP1) -= dxOverDy; pNode = pElem->pTRNode; pRhs[ pNode->poiEqn ] -= dyOverDx * dPsiT - dxOverDy * dPsiR; *(pNode->fPsiPsiiM1) -= dyOverDx; *(pNode->fPsiPsijP1) -= dxOverDy; pNode = pElem->pBRNode; pRhs[ pNode->poiEqn ] -= dyOverDx * dPsiB + dxOverDy * dPsiR; *(pNode->fPsiPsiiM1) -= dyOverDx; *(pNode->fPsiPsijM1) -= dxOverDy; pNode = pElem->pBLNode; pRhs[ pNode->poiEqn ] -= -dyOverDx * dPsiB + dxOverDy * dPsiL; *(pNode->fPsiPsiiP1) -= dyOverDx; *(pNode->fPsiPsijM1) -= dxOverDy; }}void TWOQrhsLoad( pDevice ) TWOdevice *pDevice;{ TWOelem *pElem; TWOnode *pNode, *pNode1; TWOedge *pHEdge, *pVEdge; int index, eIndex; double *pRhs = pDevice->rhs; double dyOverDx, dxOverDy, dPsiT, dPsiB, dPsiL, dPsiR; void TWOQcommonTerms(); TWOQcommonTerms( pDevice ); /* zero the rhs vector */ for ( index = 1 ; index <= pDevice->numEqns ; index++ ) { pRhs[ index ] = 0.0; } for ( eIndex = 1; eIndex <= pDevice->numElems; eIndex++ ) { pElem = pDevice->elements[ eIndex ]; dxOverDy = 0.5 * pElem->epsRel * pElem->dxOverDy; dyOverDx = 0.5 * pElem->epsRel * pElem->dyOverDx; dPsiT = pElem->pTopEdge->dPsi; dPsiB = pElem->pBotEdge->dPsi; dPsiL = pElem->pLeftEdge->dPsi; dPsiR = pElem->pRightEdge->dPsi; /* load nodal terms */ for ( index = 0; index <= 3; index++ ) { pNode = pElem->pNodes[ index ]; if ( pNode->nodeType ISNOT CONTACT AND pElem->elemType IS SEMICON ) { pRhs[ pNode->poiEqn ] += 0.25 * pElem->dx * pElem->dy * (pNode->netConc + pNode->pConc - pNode->nConc); } if ( index <= 1 ) { pHEdge = pElem->pTopEdge; } else { pHEdge = pElem->pBotEdge; } if ( index IS 0 OR index IS 3 ) { pVEdge = pElem->pLeftEdge; } else { pVEdge = pElem->pRightEdge; } /* add surface state charges */ pRhs[ pNode->poiEqn ] += 0.5 * pElem->dx * pHEdge->qf; pRhs[ pNode->poiEqn ] += 0.5 * pElem->dy * pVEdge->qf; } /* load edge terms */ pNode = pElem->pTLNode; pRhs[ pNode->poiEqn ] -= -dyOverDx * dPsiT - dxOverDy * dPsiL; pNode = pElem->pTRNode; pRhs[ pNode->poiEqn ] -= dyOverDx * dPsiT - dxOverDy * dPsiR; pNode = pElem->pBRNode; pRhs[ pNode->poiEqn ] -= dyOverDx * dPsiB + dxOverDy * dPsiR; pNode = pElem->pBLNode; pRhs[ pNode->poiEqn ] -= -dyOverDx * dPsiB + dxOverDy * dPsiL; }}void TWOQcommonTerms(pDevice)TWOdevice *pDevice;{ TWOelem *pElem; TWOedge *pEdge; TWOnode *pNode, *pNode1; int index, eIndex; double psi1, psi2, refPsi; for ( eIndex = 1; eIndex <= pDevice->numElems; eIndex++ ) { pElem = pDevice->elements[ eIndex ]; refPsi = pElem->matlInfo->refPsi; for ( index = 0; index <= 3; index++ ) { if ( pElem->evalNodes[ index ] ) { pNode = pElem->pNodes[ index ]; if ( pNode->nodeType ISNOT CONTACT ) { pNode->psi = pDevice->dcSolution[ pNode->poiEqn ]; if ( pElem->elemType IS SEMICON ) { pNode->nConc = pNode->nie * exp( pNode->psi - refPsi ); pNode->pConc = pNode->nie * exp( - pNode->psi + refPsi ); } } } if ( pElem->evalEdges[ index ] ) { pEdge = pElem->pEdges[ index ]; pNode = pElem->pNodes[ index ]; if ( pNode->nodeType ISNOT CONTACT ) { psi1 = pDevice->dcSolution[pNode->poiEqn]; } else { psi1 = pNode->psi; } pNode = pElem->pNodes[ (index + 1) % 4 ]; if ( pNode->nodeType ISNOT CONTACT ) { psi2 = pDevice->dcSolution[pNode->poiEqn]; } else { psi2 = pNode->psi; } if ( index <= 1 ) { pEdge->dPsi = psi2 - psi1; } else { pEdge->dPsi = psi1 - psi2; } } } }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -