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

📄 oneproj.c

📁 spice中支持多层次元件模型仿真的可单独运行的插件源码
💻 C
字号:
/**********Copyright 1992 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"#define MIN_DELV 1e-3/* * Functions for projecting the next solution point for modified two-level * newton scheme */void NUMDproject(pDevice, delV)  ONEdevice *pDevice;  double delV;{  ONEelem *pElem = pDevice->elemArray[pDevice->numNodes - 1];  ONEnode *pNode;  ONEedge *pEdge;  double delPsi, delN, delP, newN, newP, guessNewConc();  double *incVpn;  void ONEstoreInitialGuess();  int i, index;  delV = - delV / VNorm;  pElem->pRightNode->psi += delV;  if (ABS(delV) < MIN_DELV) {    ONEstoreInitialGuess(pDevice);    return;  }  /* zero the rhs before loading in the new rhs */  for (index = 1; index <= pDevice->numEqns; index++) {    pDevice->rhs[index] = 0.0;  }  /* compute incremental changes due to N contact */  pNode = pElem->pLeftNode;  pDevice->rhs[pNode->psiEqn] = pElem->epsRel * pElem->rDx;  if (pElem->elemType IS SEMICON) {    pEdge = pElem->pEdge;    pDevice->rhs[pNode->nEqn] = -pEdge->dJnDpsiP1;    pDevice->rhs[pNode->pEqn] = -pEdge->dJpDpsiP1;  }  incVpn = pDevice->dcDeltaSolution;  spSolve(pDevice->matrix, pDevice->rhs, incVpn);  for (index = 1; index < pDevice->numNodes; index++) {    pElem = pDevice->elemArray[index];    for (i = 0; i <= 1; i++) {      if (pElem->evalNodes[i]) {	pNode = pElem->pNodes[i];	if (pNode->nodeType ISNOT CONTACT) {	  delPsi = incVpn[pNode->psiEqn] * delV;	  pDevice->dcSolution[pNode->psiEqn] = pNode->psi + delPsi;	  if (pElem->elemType IS SEMICON) {	    delN = incVpn[pNode->nEqn] * delV;	    delP = incVpn[pNode->pEqn] * delV;	    newN = pNode->nConc + delN;	    newP = pNode->pConc + delP;	    /* if new conc less than 0.0 then use a fraction of the guess */	    if (newN <= 0.0) {	      pDevice->dcSolution[pNode->nEqn] =		  guessNewConc(pNode->nConc, delN);	    } else {	      pDevice->dcSolution[pNode->nEqn] = newN;	    }	    if (newP <= 0.0) {	      pDevice->dcSolution[pNode->pEqn] =		  guessNewConc(pNode->pConc, delP);	    } else {	      pDevice->dcSolution[pNode->pEqn] = newP;	    }	  }	}      }    }  }}void NBJTproject(pDevice, delVce, delVbe, vbe)  ONEdevice *pDevice;  double delVce, delVbe, vbe;{  ONEelem *pLastElem = pDevice->elemArray[pDevice->numNodes - 1];  ONEelem *pBaseElem = pDevice->elemArray[pDevice->baseIndex - 1];  ONEelem *pElem;  ONEnode *pNode;  ONEedge *pEdge;  double delPsi, delN, delP, newN, newP, guessNewConc(), *incVce, *incVbe;  double baseConc;  int i, index;  double nConc, pConc;  void ONEstoreInitialGuess();  /* normalize the voltages for calculations */  delVce = delVce / VNorm;  delVbe = delVbe / VNorm;  pLastElem->pRightNode->psi += delVce;  pBaseElem->pRightNode->vbe = vbe / VNorm + pBaseElem->matlInfo->refPsi;  pNode = pBaseElem->pRightNode;  if (pNode->baseType IS N_TYPE) {    baseConc = pNode->nConc;  } else if (pNode->baseType IS P_TYPE) {    baseConc = pNode->pConc;  }  if (ABS(delVce) > MIN_DELV) {    /* zero the rhs before loading in the new rhs */    for (index = 1; index <= pDevice->numEqns; index++) {      pDevice->rhs[index] = 0.0;    }    /* store the new rhs for computing the incremental quantities */    pNode = pLastElem->pLeftNode;    pDevice->rhs[pNode->psiEqn] = pLastElem->epsRel * pLastElem->rDx;    if (pLastElem->elemType IS SEMICON) {      pEdge = pLastElem->pEdge;      pDevice->rhs[pNode->nEqn] = -pEdge->dJnDpsiP1;      pDevice->rhs[pNode->pEqn] = -pEdge->dJpDpsiP1;    }    incVce = pDevice->dcDeltaSolution;    spSolve(pDevice->matrix, pDevice->rhs, incVce);    for (index = 1; index < pDevice->numNodes; index++) {      pElem = pDevice->elemArray[index];      for (i = 0; i <= 1; i++) {	if (pElem->evalNodes[i]) {	  pNode = pElem->pNodes[i];	  if (pNode->nodeType ISNOT CONTACT) {	    delPsi = incVce[pNode->psiEqn] * delVce;	    pDevice->dcSolution[pNode->psiEqn] = pNode->psi + delPsi;	    if (pElem->elemType IS SEMICON) {	      delN = incVce[pNode->nEqn] * delVce;	      delP = incVce[pNode->pEqn] * delVce;	      newN = pNode->nConc + delN;	      newP = pNode->pConc + delP;	      /* if new conc less than 0.0 then use a fraction of the guess */	      if (newN <= 0.0) {		pDevice->dcSolution[pNode->nEqn] =		    guessNewConc(pNode->nConc, delN);	      } else {		pDevice->dcSolution[pNode->nEqn] = newN;	      }	      if (newP <= 0.0) {		pDevice->dcSolution[pNode->pEqn] =		    guessNewConc(pNode->pConc, delP);	      } else {		pDevice->dcSolution[pNode->pEqn] = newP;	      }	    }	  }	}      }    }  } else {    ONEstoreInitialGuess(pDevice);  }  if (ABS(delVbe) > MIN_DELV) {    /* zero the rhs before loading in the new rhs base contribution */    for (index = 1; index <= pDevice->numEqns; index++) {      pDevice->rhs[index] = 0.0;    }    pNode = pBaseElem->pRightNode;    if (pNode->baseType IS N_TYPE) {      pDevice->rhs[pNode->nEqn] = baseConc * pNode->eg;    } else if (pNode->baseType IS P_TYPE) {      pDevice->rhs[pNode->pEqn] = baseConc * pNode->eg;    }    incVbe = pDevice->copiedSolution;    spSolve(pDevice->matrix, pDevice->rhs, incVbe);    for (index = 1; index < pDevice->numNodes; index++) {      pElem = pDevice->elemArray[index];      for (i = 0; i <= 1; i++) {	if (pElem->evalNodes[i]) {	  pNode = pElem->pNodes[i];	  if (pNode->nodeType ISNOT CONTACT) {	    delPsi = incVbe[pNode->psiEqn] * delVbe;	    pDevice->dcSolution[pNode->psiEqn] += delPsi;	    if (pElem->elemType IS SEMICON) {	      delN = incVbe[pNode->nEqn] * delVbe;	      delP = incVbe[pNode->pEqn] * delVbe;	      nConc = pDevice->dcSolution[pNode->nEqn];	      pConc = pDevice->dcSolution[pNode->pEqn];	      newN = nConc + delN;	      newP = pConc + delP;	      /* if new conc less than 0.0 then use a fraction of the guess */	      if (newN <= 0.0) {		pDevice->dcSolution[pNode->nEqn] =		    guessNewConc(nConc, delN);	      } else {		pDevice->dcSolution[pNode->nEqn] = newN;	      }	      if (newP <= 0.0) {		pDevice->dcSolution[pNode->pEqn] =		    guessNewConc(pConc, delP);	      } else {		pDevice->dcSolution[pNode->pEqn] = newP;	      }	    }	  }	}      }    }  }}/* functions to update device states for full-LU algorithm */void NUMDupdate(pDevice, delV, updateBoundary)  ONEdevice *pDevice;  double delV;  BOOLEAN updateBoundary;{  ONEelem *pElem = pDevice->elemArray[pDevice->numNodes - 1];  ONEnode *pNode;  ONEedge *pEdge;  double delPsi, delN, delP;  int i, index;  delV = - delV / VNorm;  if (updateBoundary) {    pElem->pRightNode->psi += delV;  }  for (index = 1; index < pDevice->numNodes; index++) {    pElem = pDevice->elemArray[index];    for (i = 0; i <= 1; i++) {      if (pElem->evalNodes[i]) {	pNode = pElem->pNodes[i];	if (pNode->nodeType ISNOT CONTACT) {	  delPsi = pDevice->dcDeltaSolution[pNode->psiEqn] * delV;	  pDevice->dcSolution[pNode->psiEqn] = pNode->psi + delPsi;	  if (pElem->elemType IS SEMICON) {	    delN = pDevice->dcDeltaSolution[pNode->nEqn] * delV;	    delP = pDevice->dcDeltaSolution[pNode->pEqn] * delV;	    pDevice->dcSolution[pNode->nEqn] = pNode->nConc + delN;	    pDevice->dcSolution[pNode->pEqn] = pNode->pConc + delP;	  }	}      }    }  }}void NBJTupdate(pDevice, delVce, delVbe, vbe, updateBoundary)  ONEdevice *pDevice;  double delVce, delVbe, vbe;  BOOLEAN updateBoundary;{  ONEelem *pLastElem = pDevice->elemArray[pDevice->numNodes - 1];  ONEelem *pBaseElem = pDevice->elemArray[pDevice->baseIndex - 1];  ONEelem *pElem;  ONEnode *pNode;  double delPsi, delN, delP, *incVce, *incVbe;  int i, index;  /* normalize the voltages for calculations */  delVce = delVce / VNorm;  delVbe = delVbe / VNorm;  if (updateBoundary) {    pLastElem->pRightNode->psi += delVce;    pBaseElem->pRightNode->vbe = vbe / VNorm + pBaseElem->matlInfo->refPsi;  }  /*   * The incremental quantities are available from NBJTconductance. incVce   * (dcDeltaSolution) and incVbe (copiedSolution) are used to store the   * incremental quantities associated with Vce and Vbe   */  /* set incVce = dcDeltaSolution; incVbe = copiedSolution */  incVce = pDevice->dcDeltaSolution;  incVbe = pDevice->copiedSolution;  for (index = 1; index < pDevice->numNodes; index++) {    pElem = pDevice->elemArray[index];    for (i = 0; i <= 1; i++) {      if (pElem->evalNodes[i]) {	pNode = pElem->pNodes[i];	if (pNode->nodeType ISNOT CONTACT) {	  delPsi = incVce[pNode->psiEqn] * delVce	      + incVbe[pNode->psiEqn] * delVbe;	  pDevice->dcSolution[pNode->psiEqn] = pNode->psi + delPsi;	  if (pElem->elemType IS SEMICON) {	    delN = incVce[pNode->nEqn] * delVce		+ incVbe[pNode->nEqn] * delVbe;	    delP = incVce[pNode->pEqn] * delVce		+ incVbe[pNode->pEqn] * delVbe;	    pDevice->dcSolution[pNode->nEqn] = pNode->nConc + delN;	    pDevice->dcSolution[pNode->pEqn] = pNode->pConc + delP;	  }	}      }    }  }}void NUMDsetBCs(pDevice, vpn)  ONEdevice *pDevice;  double vpn;{  ONEelem *pElem = pDevice->elemArray[pDevice->numNodes - 1];  /* normalize the voltage */  vpn =  - vpn / VNorm;  /* set the boundary conditions */  pElem->pRightNode->psi = vpn + pElem->pRightNode->psi0;}void NBJTsetBCs(pDevice, vce, vbe)  ONEdevice *pDevice;  double vce, vbe;{  ONEelem *pLastElem = pDevice->elemArray[pDevice->numNodes - 1];  ONEelem *pBaseElem = pDevice->elemArray[pDevice->baseIndex - 1];  ONEnode *pNode;  double psi, conc, sign, absConc;  double nie, ni, pi;  /* normalize the voltages */  vce = vce / VNorm;  vbe = vbe / VNorm;  /* set the boundary conditions */  pBaseElem->pRightNode->vbe = vbe + pBaseElem->matlInfo->refPsi;  pLastElem->pRightNode->psi = vce + pLastElem->pRightNode->psi0;  /*   * if (pLastElem->elemType IS INSULATOR) { pNode->psi = RefPsi -   * pNode->eaff; pNode->nConc = 0.0; pNode->pConc = 0.0; } else if   * (pLastElem->elemType IS SEMICON) { nie = pNode->nie; conc =   * pNode->netConc / pNode->nie; psi = 0.0; ni = nie; pi = nie; sign = SGN(   * conc ); absConc = ABS( conc ); if ( conc ISNOT 0.0 ) { psi = sign * log(   * 0.5 * absConc + sqrt( 1.0 + 0.25*absConc*absConc )); ni = nie * exp( psi   * ); pi = nie * exp( -psi ); } pNode->psi = pLastElem->matlInfo->refPsi +   * psi; pNode->nConc = ni; pNode->pConc = pi; } pNode->psi = pNode->psi0;   * pNode->psi += vce;   */}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -