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

📄 twoproj.c

📁 spice中支持多层次元件模型仿真的可单独运行的插件源码
💻 C
📖 第 1 页 / 共 2 页
字号:
		solution[ pNode->pEqn ] = newP;	      }	    }	  }	}      }    }  }    if ( ABS( delVgb ) > MIN_DELV ) {        incVgb = pDevice->dcDeltaSolution;    storeNewRhs( pDevice, pGContact );    spSolve( pDevice->matrix, pDevice->rhs, incVgb);        for ( eIndex = 1; eIndex <= pDevice->numElems; eIndex++ ) {      pElem = pDevice->elements[ eIndex ];      for ( index = 0; index <= 3; index++ ) {	if ( pElem->evalNodes[ index ] ) {	  pNode = pElem->pNodes[ index ];	  if ( pNode->nodeType ISNOT CONTACT ) {	    delPsi = incVgb[ pNode->psiEqn ] * delVgb;	    solution[ pNode->psiEqn ] += delPsi;	    if ( pElem->elemType IS SEMICON		AND (NOT OneCarrier OR OneCarrier IS N_TYPE) ) {	      delN = incVgb[ pNode->nEqn ] * delVgb;	      nConc = solution[ pNode->nEqn ];	      newN = nConc + delN;	      if ( newN <= 0.0 ) {		solution[ pNode->nEqn ] = guessNewConc( nConc, delN );	      }	      else {		solution[ pNode->nEqn ] = newN;	      }	    }	    if ( pElem->elemType IS SEMICON		AND (NOT OneCarrier OR OneCarrier IS P_TYPE) ) {	      delP = incVgb[ pNode->pEqn ] * delVgb;	      pConc = solution[ pNode->pEqn ];	      newP = pConc + delP;	      if ( newP <= 0.0 ) {		solution[ pNode->pEqn ] = guessNewConc( pConc, delP );	      }	      else {		solution[ pNode->pEqn ] = newP;	      }	    }	  }	}      }    }  }}/* functions to update the solution for the full-LU and   modified two-level Newton methods   */void NUMD2update( pDevice, delV, updateBoundary )     TWOdevice *pDevice;     double delV;     BOOLEAN updateBoundary;{  TWOnode *pNode;  TWOelem *pElem;  int index, eIndex, numContactNodes;  TWOcontact *pContact = pDevice->pLastContact;  double delPsi, delN, delP, *incVpn, *solution = pDevice->dcSolution;    delV = -delV / VNorm;  if ( updateBoundary ) {    /* update the boundary condition for the last contact */    numContactNodes = pContact->numNodes;    for ( index = 0; index < numContactNodes; index++ ) {      pNode = pContact->pNodes[ index ];      pNode->psi += delV;    }  }    /* the equations have been solved while computing the conductances */  /* solution is in dcDeltaSolution, so use it */  incVpn = pDevice->dcDeltaSolution;  for ( eIndex = 1; eIndex <= pDevice->numElems; eIndex++ ) {    pElem = pDevice->elements[ eIndex ];    for ( index = 0; index <= 3; index++ ) {      if ( pElem->evalNodes[ index ] ) {	pNode = pElem->pNodes[ index ];	if ( pNode->nodeType ISNOT CONTACT ) {	  delPsi = incVpn[ pNode->psiEqn ] * delV;	  solution[ pNode->psiEqn ] = pNode->psi + delPsi;	  if ( pElem->elemType IS SEMICON	      AND (NOT OneCarrier OR OneCarrier IS N_TYPE) ) {	    delN = incVpn[ pNode->nEqn ] * delV;	    solution[ pNode->nEqn ] = pNode->nConc + delN;	  }	  if ( pElem->elemType IS SEMICON	      AND (NOT OneCarrier OR OneCarrier IS P_TYPE) ) {	    delP = incVpn[ pNode->pEqn ] * delV;	    solution[ pNode->pEqn ] = pNode->pConc + delP;	  }	}      }    }  }}void NBJT2update( pDevice, delVce, delVbe, updateBoundary )     TWOdevice *pDevice;     double delVce, delVbe;     BOOLEAN updateBoundary;{  TWOnode *pNode;  TWOelem *pElem;  int index, eIndex, numContactNodes;  TWOcontact *pColContact = pDevice->pFirstContact;  TWOcontact *pBaseContact = pDevice->pFirstContact->next;  double delPsi, delN, delP, *incVce, *incVbe, *solution = pDevice->dcSolution;    /* normalize the voltages for calculations */    if ( delVce ISNOT 0.0 ) {    delVce = delVce / VNorm;    if ( updateBoundary ) {      numContactNodes = pColContact->numNodes;      for ( index = 0; index < numContactNodes; index++ ) {	pNode = pColContact->pNodes[ index ];	pNode->psi += delVce;      }    }  }  if ( delVbe ISNOT 0.0 ) {    delVbe = delVbe / VNorm;    if ( updateBoundary ) {      numContactNodes = pBaseContact->numNodes;      for ( index = 0; index < numContactNodes; index++ ) {	pNode = pBaseContact->pNodes[ index ];	pNode->psi += delVbe;      }    }  }    /* use solution from computeConductance to do update */  /* set incVce = dcDeltaSolution; incVbe = copiedSolution */    incVce = pDevice->dcDeltaSolution;  incVbe = pDevice->copiedSolution;  for ( eIndex = 1; eIndex <= pDevice->numElems; eIndex++ ) {    pElem = pDevice->elements[ eIndex ];    for ( index = 0; index <= 3; index++ ) {      if ( pElem->evalNodes[ index ] ) {	pNode = pElem->pNodes[ index ];	if ( pNode->nodeType ISNOT CONTACT ) {	  delPsi = (incVce[ pNode->psiEqn ] * delVce		    + incVbe[ pNode->psiEqn ] * delVbe);	  solution[ pNode->psiEqn ] = pNode->psi + delPsi;	  if ( pElem->elemType IS SEMICON	      AND (NOT OneCarrier OR OneCarrier IS N_TYPE) ) {	    delN = (incVce[ pNode->nEqn ] * delVce		    + incVbe[ pNode->nEqn ] * delVbe);	    solution[ pNode->nEqn ] = pNode->nConc + delN;	  }	  if ( pElem->elemType IS SEMICON	      AND (NOT OneCarrier OR OneCarrier IS P_TYPE) ) {	    delP = (incVce[ pNode->pEqn ] * delVce		    + incVbe[ pNode->pEqn ] * delVbe);	    solution[ pNode->pEqn ] = pNode->pConc + delP;	  }	}      }    }  }}void NUMOSupdate( pDevice, delVdb, delVsb, delVgb, updateBoundary )     TWOdevice *pDevice;     double delVdb, delVsb, delVgb;     BOOLEAN updateBoundary;{  TWOnode *pNode;  TWOelem *pElem;  int index, eIndex, numContactNodes;  TWOcontact *pDContact = pDevice->pFirstContact;  TWOcontact *pGContact = pDevice->pFirstContact->next;  TWOcontact *pSContact = pDevice->pFirstContact->next->next;  double delPsi, delN, delP;  double *incVdb, *incVsb, *incVgb, *solution = pDevice->dcSolution;    /* normalize the voltages for calculations */  if ( delVdb ISNOT 0.0 ) {    delVdb = delVdb / VNorm;    if ( updateBoundary ) {      numContactNodes = pDContact->numNodes;      for ( index = 0; index < numContactNodes; index++ ) {	pNode = pDContact->pNodes[ index ];	pNode->psi += delVdb;      }    }  }  if ( delVsb ISNOT 0.0 ) {    delVsb = delVsb / VNorm;    if ( updateBoundary ) {      numContactNodes = pSContact->numNodes;      for ( index = 0; index < numContactNodes; index++ ) {	pNode = pSContact->pNodes[ index ];	pNode->psi += delVsb;      }    }  }  if ( delVgb ISNOT 0.0 ) {    delVgb = delVgb / VNorm;    if ( updateBoundary ) {      numContactNodes = pGContact->numNodes;      for ( index = 0; index < numContactNodes; index++ ) {	pNode = pGContact->pNodes[ index ];	pNode->psi += delVgb;      }    }  }    /* use solution from computeConductance to do update */    incVdb = pDevice->dcDeltaSolution;  incVsb = pDevice->copiedSolution;  incVgb = pDevice->rhsImag;  for ( eIndex = 1; eIndex <= pDevice->numElems; eIndex++ ) {    pElem = pDevice->elements[ eIndex ];    for ( index = 0; index <= 3; index++ ) {      if ( pElem->evalNodes[ index ] ) {	pNode = pElem->pNodes[ index ];	if ( pNode->nodeType ISNOT CONTACT ) {	  delPsi = (incVdb[ pNode->psiEqn ] * delVdb		    + incVsb[ pNode->psiEqn ] * delVsb		    + incVgb[ pNode->psiEqn ] * delVgb);	  solution[ pNode->psiEqn ] = pNode->psi + delPsi;	  if ( pElem->elemType IS SEMICON	      AND (NOT OneCarrier OR OneCarrier IS N_TYPE) ) {	    delN = (incVdb[ pNode->nEqn ] * delVdb		    + incVsb[ pNode->nEqn ] * delVsb		    + incVgb[ pNode->nEqn ] * delVgb);	    solution[ pNode->nEqn ] = pNode->nConc + delN;	  }	  if ( pElem->elemType IS SEMICON	      AND (NOT OneCarrier OR OneCarrier IS P_TYPE) ) {	    delP = (incVdb[ pNode->pEqn ] * delVdb		    + incVsb[ pNode->pEqn ] * delVsb		    + incVgb[ pNode->pEqn ] * delVgb);	    solution[ pNode->pEqn ] = pNode->pConc + delP;	  }	}      }    }  }}void storeNewRhs( pDevice, pContact )     TWOdevice *pDevice;     TWOcontact *pContact;{  int index, i, numContactNodes;  TWOelem *pElem;  TWOnode *pNode, *pHNode, *pVNode;  TWOedge *pHEdge, *pVEdge;  double *rhs = pDevice->rhs;    /* zero the rhs before loading in the new rhs */  for ( index = 1; index <= pDevice->numEqns ; index++ ) {    rhs[ index ] = 0.0;  }    numContactNodes = pContact->numNodes;  for ( index = 0; index < numContactNodes; index++ ) {    pNode = pContact->pNodes[ index ];    for ( i = 0; i <= 3; i++ ) {      pElem = pNode->pElems[ i ];      if ( pElem ISNOT NIL(TWOelem)) {	/* found an element to which this node belongs */	switch ( i ) {	case 0:	  /* the TL element of this node */	  pHNode = pElem->pBLNode;	  pVNode = pElem->pTRNode;	  pHEdge = pElem->pBotEdge;	  pVEdge = pElem->pRightEdge;	  break;	case 1:	  /* the TR element */	  pHNode = pElem->pBRNode;	  pVNode = pElem->pTLNode;	  pHEdge = pElem->pBotEdge;	  pVEdge = pElem->pLeftEdge;	  break;	case 2:	  /* the BR element */	  pHNode = pElem->pTRNode;	  pVNode = pElem->pBLNode;	  pHEdge = pElem->pTopEdge;	  pVEdge = pElem->pLeftEdge;	  break;	case 3:	  /* the BL element */	  pHNode = pElem->pTLNode;	  pVNode = pElem->pBRNode;	  pHEdge = pElem->pTopEdge;	  pVEdge = pElem->pRightEdge;	  break;	default:	  printf( "storeNewRhs: shouldn't be here\n");	  break;	}	if ( pHNode->nodeType ISNOT CONTACT ) {	  /* contribution to the x nodes */	  rhs[ pHNode->psiEqn ] += pElem->epsRel * 0.5 * pElem->dyOverDx;	  if ( pElem->elemType IS SEMICON ) {	    if ( NOT OneCarrier ) {	      rhs[ pHNode->nEqn ] -= 0.5 * pElem->dy * pHEdge->dJnDpsiP1;	      rhs[ pHNode->pEqn ] -= 0.5 * pElem->dy * pHEdge->dJpDpsiP1;	    } else if ( OneCarrier IS N_TYPE ) {	      rhs[ pHNode->nEqn ] -= 0.5 * pElem->dy * pHEdge->dJnDpsiP1;	    } else if ( OneCarrier IS P_TYPE ) {	      rhs[ pHNode->pEqn ] -= 0.5 * pElem->dy * pHEdge->dJpDpsiP1;	    }	  }	}	if ( pVNode->nodeType ISNOT CONTACT ) {	  /* contribution to the y nodes */	  rhs[ pVNode->psiEqn ] += pElem->epsRel * 0.5 * pElem->dxOverDy;	  if ( pElem->elemType IS SEMICON ) {	    if ( NOT OneCarrier ) {	      rhs[ pVNode->nEqn ] -= 0.5 * pElem->dx * pVEdge->dJnDpsiP1;	      rhs[ pVNode->pEqn ] -= 0.5 * pElem->dx * pVEdge->dJpDpsiP1;	    } else if ( OneCarrier IS N_TYPE ) {	      rhs[ pVNode->nEqn ] -= 0.5 * pElem->dx * pVEdge->dJnDpsiP1;	    } else if ( OneCarrier IS P_TYPE ) {	      rhs[ pVNode->pEqn ] -= 0.5 * pElem->dx * pVEdge->dJpDpsiP1;	    }	  }	}      }    }  }}

⌨️ 快捷键说明

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