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

📄 onesolve.c

📁 spice中支持多层次元件模型仿真的可单独运行的插件源码
💻 C
📖 第 1 页 / 共 3 页
字号:
	    *(pDevice->devState0 + pNode->nodePsi) = pNode->psi;	    if (pElem->elemType IS SEMICON) {	      pNode->nConc = solution[pNode->nEqn];	      pNode->pConc = solution[pNode->pEqn];	      *(pDevice->devState0 + pNode->nodeN) = pNode->nConc;	      *(pDevice->devState0 + pNode->nodeP) = pNode->pConc;	    }	  }	}      }    }  }  miscTime += SPfrontEnd->IFseconds() - startTime;  if (tranAnalysis) {    pDevice->pStats->setupTime[STAT_TRAN] += setupTime;    pDevice->pStats->miscTime[STAT_TRAN] += miscTime;  } else {    pDevice->pStats->setupTime[STAT_DC] += setupTime;    pDevice->pStats->miscTime[STAT_DC] += miscTime;  }}/* Copy the device's equilibrium state into the solution vector. */voidONEstoreEquilibGuess(pDevice)  ONEdevice *pDevice;{  int nIndex, eIndex;  double *solution = pDevice->dcSolution;  double refPsi;  ONEelem *pElem;  ONEnode *pNode;  for (eIndex = 1; eIndex < pDevice->numNodes; eIndex++) {    pElem = pDevice->elemArray[eIndex];    refPsi = pElem->matlInfo->refPsi;    for (nIndex = 0; nIndex <= 1; nIndex++) {      if (pElem->evalNodes[nIndex]) {	pNode = pElem->pNodes[nIndex];	if (pNode->nodeType ISNOT CONTACT) {	  solution[pNode->psiEqn] = pNode->psi0;	  if (pElem->elemType IS SEMICON) {	    solution[pNode->nEqn] = pNode->nie * exp(pNode->psi0 - refPsi);	    solution[pNode->pEqn] = pNode->nie * exp(-pNode->psi0 + refPsi);	  }	}      }    }  }}/* Copy the device's internal state into the solution vector. */voidONEstoreInitialGuess(pDevice)  ONEdevice *pDevice;{  int nIndex, eIndex;  double *solution = pDevice->dcSolution;  ONEelem *pElem;  ONEnode *pNode;  for (eIndex = 1; eIndex < pDevice->numNodes; eIndex++) {    pElem = pDevice->elemArray[eIndex];    for (nIndex = 0; nIndex <= 1; nIndex++) {      if (pElem->evalNodes[nIndex]) {	pNode = pElem->pNodes[nIndex];	if (pNode->nodeType ISNOT CONTACT) {	  solution[pNode->psiEqn] = pNode->psi;	  if (pElem->elemType IS SEMICON) {	    solution[pNode->nEqn] = pNode->nConc;	    solution[pNode->pEqn] = pNode->pConc;	  }	}      }    }  }}#define NORM_RED_MAXITERS 10intONEnewDelta(pDevice, tranAnalysis, info)  ONEdevice *pDevice;  BOOLEAN tranAnalysis;  ONEtranInfo *info;{  int index, iterNum;  double newNorm, fib, lambda, fibn, fibp;  BOOLEAN acceptable = FALSE, error = FALSE;  iterNum = 0;  lambda = 1.0;  fibn = 1.0;  fibp = 1.0;  /*   * Copy the contents of dcSolution into copiedSolution and modify   * dcSolution by adding the deltaSolution.   */  for (index = 1; index <= pDevice->numEqns; index++) {    pDevice->copiedSolution[index] = pDevice->dcSolution[index];    pDevice->dcSolution[index] += pDevice->dcDeltaSolution[index];  }  if (pDevice->poissonOnly) {    ONEQrhsLoad(pDevice);  } else {    ONE_rhsLoad(pDevice, tranAnalysis, info);  }  newNorm = maxNorm(pDevice->rhs, pDevice->numEqns);  if (pDevice->rhsNorm <= pDevice->abstol) {    lambda = 0.0;    newNorm = pDevice->rhsNorm;  } else if (newNorm < pDevice->rhsNorm) {    acceptable = TRUE;  } else {    /* chop the step size so that deltax is acceptable */    if (ONEdcDebug) {      fprintf(stdout, "          %11.4e  %11.4e\n",	  newNorm, lambda);    }    while (NOT acceptable) {      iterNum++;      if (iterNum > NORM_RED_MAXITERS) {	error = TRUE;	lambda = 0.0;	/* Don't break out until after we've reset the device. */      }      fib = fibp;      fibp = fibn;      fibn += fib;      lambda *= (fibp / fibn);      for (index = 1; index <= pDevice->numEqns; index++) {	pDevice->dcSolution[index] = pDevice->copiedSolution[index]	    + lambda * pDevice->dcDeltaSolution[index];      }      if (pDevice->poissonOnly) {	ONEQrhsLoad(pDevice);      } else {	ONE_rhsLoad(pDevice, tranAnalysis, info);      }      newNorm = maxNorm(pDevice->rhs, pDevice->numEqns);      if (error) {	break;      }      if (newNorm <= pDevice->rhsNorm) {	acceptable = TRUE;      }      if (ONEdcDebug) {	fprintf(stdout, "          %11.4e  %11.4e\n",	    newNorm, lambda);      }    }  }  /* Restore the previous dcSolution and store the new deltaSolution. */  pDevice->rhsNorm = newNorm;  for (index = 1; index <= pDevice->numEqns; index++) {    pDevice->dcSolution[index] = pDevice->copiedSolution[index];    pDevice->dcDeltaSolution[index] *= lambda;  }  return(error);}/* Predict the values of the internal variables at the next timepoint. *//* Needed for Predictor-Corrector LTE estimation */voidONEpredict(pDevice, info)  ONEdevice *pDevice;  ONEtranInfo *info;{  int nIndex, eIndex;  ONEnode *pNode;  ONEelem *pElem;  double startTime, miscTime = 0.0;  /* TRANSIENT MISC */  startTime = SPfrontEnd->IFseconds();  for (eIndex = 1; eIndex < pDevice->numNodes; eIndex++) {    pElem = pDevice->elemArray[eIndex];    for (nIndex = 0; nIndex <= 1; nIndex++) {      if (pElem->evalNodes[nIndex]) {	pNode = pElem->pNodes[nIndex];	pNode->psi = *(pDevice->devState1 + pNode->nodePsi);	if (pElem->elemType IS SEMICON AND pNode->nodeType ISNOT CONTACT) {	  pNode->nPred = predict(pDevice->devStates, info, pNode->nodeN);	  pNode->pPred = predict(pDevice->devStates, info, pNode->nodeP);	  pNode->nConc = pNode->nPred;	  pNode->pConc = pNode->pPred;	}      }    }  }  miscTime += SPfrontEnd->IFseconds() - startTime;  pDevice->pStats->miscTime[STAT_TRAN] += miscTime;}/* Estimate the device's overall truncation error. */doubleONEtrunc(pDevice, info, delta)  ONEdevice *pDevice;  ONEtranInfo *info;  double delta;{  int nIndex, eIndex;  ONEelem *pElem;  ONEnode *pNode;  double tolN, tolP, lte, relError, temp, relLTE;  double lteCoeff = info->lteCoeff;  double mult = 10.0;  double reltol;  double startTime, lteTime = 0.0;  /* TRANSIENT LTE */  startTime = SPfrontEnd->IFseconds();  relError = 0.0;  reltol = pDevice->reltol * mult;  /* Need to get the predictor for the current order. */  /* The scheme currently used is very dumb. Need to fix later. */  /* XXX Why is the scheme dumb?  Never understood this. */  computePredCoeff(info->method, info->order, info->predCoeff, info->delta);  for (eIndex = 1; eIndex < pDevice->numNodes; eIndex++) {    pElem = pDevice->elemArray[eIndex];    for (nIndex = 0; nIndex <= 1; nIndex++) {      if (pElem->evalNodes[nIndex]) {	pNode = pElem->pNodes[nIndex];	if (pElem->elemType IS SEMICON AND pNode->nodeType ISNOT CONTACT) {	  tolN = pDevice->abstol + reltol * ABS(pNode->nConc);	  tolP = pDevice->abstol + reltol * ABS(pNode->pConc);	  pNode->nPred = predict(pDevice->devStates, info, pNode->nodeN);	  pNode->pPred = predict(pDevice->devStates, info, pNode->nodeP);	  lte = lteCoeff * (pNode->nConc - pNode->nPred);	  temp = lte / tolN;	  relError += temp * temp;	  lte = lteCoeff * (pNode->pConc - pNode->pPred);	  temp = lte / tolP;	  relError += temp * temp;	}      }    }  }  /* Make sure error is non-zero. */  relError = MAX(pDevice->abstol, relError);  /* The total relative error has been calculated norm-2 squared. */  relError = sqrt(relError / pDevice->numEqns);  /* Use the order of the integration method to compute new delta. */  temp = delta / pow(relError, 1.0 / (info->order + 1));  lteTime += SPfrontEnd->IFseconds() - startTime;  pDevice->pStats->lteTime += lteTime;  return (temp);}/* Save info from state table into the internal state. */voidONEsaveState(pDevice)  ONEdevice *pDevice;{  int nIndex, eIndex;  ONEnode *pNode;  ONEelem *pElem;  for (eIndex = 1; eIndex < pDevice->numNodes; eIndex++) {    pElem = pDevice->elemArray[eIndex];    for (nIndex = 0; nIndex <= 1; nIndex++) {      if (pElem->evalNodes[nIndex]) {	pNode = pElem->pNodes[nIndex];	pNode->psi = *(pDevice->devState1 + pNode->nodePsi);	if (pElem->elemType IS SEMICON AND pNode->nodeType ISNOT CONTACT) {	  pNode->nConc = *(pDevice->devState1 + pNode->nodeN);	  pNode->pConc = *(pDevice->devState1 + pNode->nodeP);	}      }    }  }}/* Function to compute Nu norm of the rhs vector. *//* Nu-norm calculation based upon work done at Stanford. */doubleONEnuNorm(pDevice)  ONEdevice *pDevice;{  double norm = 0.0;  double temp;  int index;  /* The LU Decomposed matrix is available.  Use it to calculate x. */  spSolve(pDevice->matrix, pDevice->rhs, pDevice->rhsImag,      NIL(spREAL), NIL(spREAL));  /* Compute L2-norm of the solution vector (stored in rhsImag) */  return (l2Norm(pDevice->rhsImag, pDevice->numEqns));}/* * Check for numerical errors in the Jacobian.  Useful debugging aid when new * models are being incorporated. */voidONEjacCheck(pDevice, tranAnalysis, info)  ONEdevice *pDevice;  BOOLEAN tranAnalysis;  ONEtranInfo *info;{  int index, rIndex;  double del, diff, tol, *dptr;  double *spFindElement();  if (ONEjacDebug) {    ONE_sysLoad(pDevice, tranAnalysis, info);    /*     * spPrint( pDevice->matrix, 0, 1, 1 );     */    pDevice->rhsNorm = maxNorm(pDevice->rhs, pDevice->numEqns);    for (index = 1; index <= pDevice->numEqns; index++) {      if (1e3 * ABS(pDevice->rhs[index]) > pDevice->rhsNorm) {	fprintf(stderr, "eqn %d: res %11.4e, norm %11.4e\n",	    index, pDevice->rhs[index], pDevice->rhsNorm);      }    }    for (index = 1; index <= pDevice->numEqns; index++) {      pDevice->rhsImag[index] = pDevice->rhs[index];    }    for (index = 1; index <= pDevice->numEqns; index++) {      pDevice->copiedSolution[index] = pDevice->dcSolution[index];      del = 1e-4 * pDevice->abstol + 1e-6 * ABS(pDevice->dcSolution[index]);      pDevice->dcSolution[index] += del;      ONE_rhsLoad(pDevice, tranAnalysis, info);      pDevice->dcSolution[index] = pDevice->copiedSolution[index];      for (rIndex = 1; rIndex <= pDevice->numEqns; rIndex++) {	diff = (pDevice->rhsImag[rIndex] - pDevice->rhs[rIndex]) / del;	dptr = spFindElement(pDevice->matrix, rIndex, index);	/*	 * if ( dptr ISNOT NIL(double) ) { fprintf( stderr, "[%d][%d]: FD =	 * %11.4e, AJ = %11.4e\n", rIndex, index, diff, *dptr ); } else {	 * fprintf( stderr, "[%d][%d]: FD = %11.4e, AJ = %11.4e\n", rIndex,	 * index, diff, 0.0 ); }	 */	if (dptr ISNOT NIL(double)) {	  tol = (1e-4 * pDevice->abstol) + (1e-2 * MAX(ABS(diff), ABS(*dptr)));	  if ((diff != 0.0) && (ABS(diff - *dptr) > tol)) {	    fprintf(stderr, "Mismatch[%d][%d]: FD = %11.4e, AJ = %11.4e\n\t FD-AJ = %11.4e vs. %11.4e\n",		rIndex, index, diff, *dptr,		ABS(diff - *dptr), tol);	  }	} else {	  if (diff != 0.0) {	    fprintf(stderr, "Missing [%d][%d]: FD = %11.4e, AJ = 0.0\n",		rIndex, index, diff);	  }	}      }    }  }}

⌨️ 快捷键说明

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