⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 twopoiss.c

📁 spice中支持多层次元件模型仿真的可单独运行的插件源码
💻 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 + -