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

📄 onecont.c

📁 spice中支持多层次元件模型仿真的可单独运行的插件源码
💻 C
📖 第 1 页 / 共 2 页
字号:
/**********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 + -