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

📄 twoadmit.c

📁 ngspice又一个电子CAD仿真软件代码.功能更全
💻 C
📖 第 1 页 / 共 3 页
字号:
	    omega / (TWO_PI * TNorm) );	CMPLX_ASSIGN_VALUE(yAc->yIdVdb, 0.0, 0.0);	CMPLX_ASSIGN_VALUE(yAc->yIdVsb, 0.0, 0.0);	CMPLX_ASSIGN_VALUE(yAc->yIdVgb, 0.0, 0.0);	CMPLX_ASSIGN_VALUE(yAc->yIsVdb, 0.0, 0.0);	CMPLX_ASSIGN_VALUE(yAc->yIsVsb, 0.0, 0.0);	CMPLX_ASSIGN_VALUE(yAc->yIsVgb, 0.0, 0.0);	CMPLX_ASSIGN_VALUE(yAc->yIgVdb, 0.0, 0.0);	CMPLX_ASSIGN_VALUE(yAc->yIgVsb, 0.0, 0.0);	CMPLX_ASSIGN_VALUE(yAc->yIgVgb, 0.0, 0.0);	return (AcAnalysisMethod);      } else {	/* MISC */	startTime = SPfrontEnd->IFseconds();	y = contactAdmittance(pDevice, pDContact, FALSE,	    solnReal, solnImag, &cOmega);	CMPLX_ASSIGN_VALUE(yAc->yIdVsb, y->real, y->imag);	y = contactAdmittance(pDevice, pSContact, TRUE,	    solnReal, solnImag, &cOmega);	CMPLX_ASSIGN_VALUE(yAc->yIsVsb, y->real, y->imag);	y = GateTypeAdmittance(pDevice, pGContact, FALSE,	    solnReal, solnImag, &cOmega);	CMPLX_ASSIGN_VALUE(yAc->yIgVsb, y->real, y->imag);	pDevice->pStats->miscTime[STAT_AC] +=	    SPfrontEnd->IFseconds() - startTime;	/* LOAD */	startTime = SPfrontEnd->IFseconds();	/* load in the gate contribution to the rhs */	for (index = 1; index <= pDevice->numEqns; index++) {	  rhsImag[index] = 0.0;	}	storeNewRhs(pDevice, pGContact);	pDevice->pStats->loadTime[STAT_AC] +=	    SPfrontEnd->IFseconds() - startTime;	/* SOLVE */	startTime = SPfrontEnd->IFseconds();	SORFailed = TWOsorSolve(pDevice, solnReal, solnImag, omega);	pDevice->pStats->solveTime[STAT_AC] +=	    SPfrontEnd->IFseconds() - startTime;	if (SORFailed && AcAnalysisMethod == SOR) {	  AcAnalysisMethod = DIRECT;	  printf("SOR failed at %g Hz, switching to direct-method ac analysis.\n",	      omega / (TWO_PI * TNorm) );	} else if (SORFailed) {	/* Told to only do SOR, so give up. */	  printf("SOR failed at %g Hz, returning null admittance.\n",	      omega / (TWO_PI * TNorm) );	  CMPLX_ASSIGN_VALUE(yAc->yIdVdb, 0.0, 0.0);	  CMPLX_ASSIGN_VALUE(yAc->yIdVsb, 0.0, 0.0);	  CMPLX_ASSIGN_VALUE(yAc->yIdVgb, 0.0, 0.0);	  CMPLX_ASSIGN_VALUE(yAc->yIsVdb, 0.0, 0.0);	  CMPLX_ASSIGN_VALUE(yAc->yIsVsb, 0.0, 0.0);	  CMPLX_ASSIGN_VALUE(yAc->yIsVgb, 0.0, 0.0);	  CMPLX_ASSIGN_VALUE(yAc->yIgVdb, 0.0, 0.0);	  CMPLX_ASSIGN_VALUE(yAc->yIgVsb, 0.0, 0.0);	  CMPLX_ASSIGN_VALUE(yAc->yIgVgb, 0.0, 0.0);	  return (AcAnalysisMethod);	}      }    }  }  if (AcAnalysisMethod == DIRECT) {    /* solve the system of equations directly */    /* LOAD */    startTime = SPfrontEnd->IFseconds();    for (index = 1; index <= pDevice->numEqns; index++) {      rhsImag[index] = 0.0;    }    storeNewRhs(pDevice, pDContact);    /* Need to load & factor jacobian once. */    if (!OneCarrier) {      TWO_jacLoad(pDevice);    } else if (OneCarrier == N_TYPE) {      TWONjacLoad(pDevice);    } else if (OneCarrier == P_TYPE) {      TWOPjacLoad(pDevice);    }    spSetComplex(pDevice->matrix);    for (eIndex = 1; eIndex <= pDevice->numElems; eIndex++) {      pElem = pDevice->elements[eIndex];      if (pElem->elemType == SEMICON) {	dxdy = 0.25 * pElem->dx * pElem->dy;	for (index = 0; index <= 3; index++) {	  pNode = pElem->pNodes[index];	  if (pNode->nodeType != CONTACT) {	    if (!OneCarrier) {	      spADD_COMPLEX_ELEMENT(pNode->fNN, 0.0, -dxdy * omega);	      spADD_COMPLEX_ELEMENT(pNode->fPP, 0.0, dxdy * omega);	    } else if (OneCarrier == N_TYPE) {	      spADD_COMPLEX_ELEMENT(pNode->fNN, 0.0, -dxdy * omega);	    } else if (OneCarrier == P_TYPE) {	      spADD_COMPLEX_ELEMENT(pNode->fPP, 0.0, dxdy * omega);	    }	  }	}      }    }    pDevice->pStats->loadTime[STAT_AC] += SPfrontEnd->IFseconds() - startTime;    /* FACTOR */    startTime = SPfrontEnd->IFseconds();    spFactor(pDevice->matrix);    pDevice->pStats->factorTime[STAT_AC] += SPfrontEnd->IFseconds() - startTime;    /* SOLVE */    startTime = SPfrontEnd->IFseconds();    spSolve(pDevice->matrix, rhsReal, solnReal, rhsImag, solnImag);    pDevice->pStats->solveTime[STAT_AC] += SPfrontEnd->IFseconds() - startTime;    /* MISC */    startTime = SPfrontEnd->IFseconds();    y = contactAdmittance(pDevice, pDContact, TRUE,	solnReal, solnImag, &cOmega);    CMPLX_ASSIGN_VALUE(yAc->yIdVdb, y->real, y->imag);    y = contactAdmittance(pDevice, pSContact, FALSE,	solnReal, solnImag, &cOmega);    CMPLX_ASSIGN_VALUE(yAc->yIsVdb, y->real, y->imag);    y = GateTypeAdmittance(pDevice, pGContact, FALSE,	solnReal, solnImag, &cOmega);    CMPLX_ASSIGN_VALUE(yAc->yIgVdb, y->real, y->imag);    pDevice->pStats->miscTime[STAT_AC] += SPfrontEnd->IFseconds() - startTime;    /* LOAD */    startTime = SPfrontEnd->IFseconds();    for (index = 1; index <= pDevice->numEqns; index++) {      rhsImag[index] = 0.0;    }    storeNewRhs(pDevice, pSContact);    pDevice->pStats->loadTime[STAT_AC] += SPfrontEnd->IFseconds() - startTime;    /* FACTOR: already done, no need to repeat. */    /* SOLVE */    startTime = SPfrontEnd->IFseconds();    spSolve(pDevice->matrix, rhsReal, solnReal, rhsImag, solnImag);    pDevice->pStats->solveTime[STAT_AC] += SPfrontEnd->IFseconds() - startTime;    /* MISC */    startTime = SPfrontEnd->IFseconds();    y = contactAdmittance(pDevice, pDContact, FALSE,	solnReal, solnImag, &cOmega);    CMPLX_ASSIGN_VALUE(yAc->yIdVsb, y->real, y->imag);    y = contactAdmittance(pDevice, pSContact, TRUE,	solnReal, solnImag, &cOmega);    CMPLX_ASSIGN_VALUE(yAc->yIsVsb, y->real, y->imag);    y = GateTypeAdmittance(pDevice, pGContact, FALSE,	solnReal, solnImag, &cOmega);    CMPLX_ASSIGN_VALUE(yAc->yIgVsb, y->real, y->imag);    pDevice->pStats->miscTime[STAT_AC] += SPfrontEnd->IFseconds() - startTime;    /* LOAD */    startTime = SPfrontEnd->IFseconds();    for (index = 1; index <= pDevice->numEqns; index++) {      rhsImag[index] = 0.0;    }    storeNewRhs(pDevice, pGContact);    pDevice->pStats->loadTime[STAT_AC] += SPfrontEnd->IFseconds() - startTime;    /* FACTOR: already done, no need to repeat. */    /* SOLVE */    startTime = SPfrontEnd->IFseconds();    spSolve(pDevice->matrix, rhsReal, solnReal, rhsImag, solnImag);    pDevice->pStats->solveTime[STAT_AC] += SPfrontEnd->IFseconds() - startTime;  }  /* MISC */  startTime = SPfrontEnd->IFseconds();  y = contactAdmittance(pDevice, pDContact, FALSE,      solnReal, solnImag, &cOmega);  CMPLX_ASSIGN_VALUE(yAc->yIdVgb, y->real, y->imag);  y = contactAdmittance(pDevice, pSContact, FALSE,      solnReal, solnImag, &cOmega);  CMPLX_ASSIGN_VALUE(yAc->yIsVgb, y->real, y->imag);  y = GateTypeAdmittance(pDevice, pGContact, TRUE,      solnReal, solnImag, &cOmega);  CMPLX_ASSIGN_VALUE(yAc->yIgVgb, y->real, y->imag);  CMPLX_MULT_SELF_SCALAR(yAc->yIdVdb, GNorm * width * LNorm);  CMPLX_MULT_SELF_SCALAR(yAc->yIdVsb, GNorm * width * LNorm);  CMPLX_MULT_SELF_SCALAR(yAc->yIdVgb, GNorm * width * LNorm);  CMPLX_MULT_SELF_SCALAR(yAc->yIsVdb, GNorm * width * LNorm);  CMPLX_MULT_SELF_SCALAR(yAc->yIsVsb, GNorm * width * LNorm);  CMPLX_MULT_SELF_SCALAR(yAc->yIsVgb, GNorm * width * LNorm);  CMPLX_MULT_SELF_SCALAR(yAc->yIgVdb, GNorm * width * LNorm);  CMPLX_MULT_SELF_SCALAR(yAc->yIgVsb, GNorm * width * LNorm);  CMPLX_MULT_SELF_SCALAR(yAc->yIgVgb, GNorm * width * LNorm);  pDevice->pStats->miscTime[STAT_AC] += SPfrontEnd->IFseconds() - startTime;  return (AcAnalysisMethod);}BOOLEAN TWOsorSolve(TWOdevice *pDevice, double *xReal, double *xImag,             double omega){  double dxdy;  double wRelax = 1.0;		/* SOR relaxation parameter */  double *rhsReal = pDevice->rhs;  double *rhsSOR = pDevice->rhsImag;  BOOLEAN SORConverged = FALSE;  BOOLEAN SORFailed = FALSE;  int numEqns = pDevice->numEqns;  int iterationNum;  int indexN, indexP;  int index, eIndex;  TWOnode *pNode;  TWOelem *pElem;  /* clear xReal and xImag arrays */  for (index = 1; index <= numEqns; index++) {    xReal[index] = 0.0;    xImag[index] = 0.0;  }  iterationNum = 1;  for (; (!SORConverged) &&(!SORFailed); iterationNum++) {    for (index = 1; index <= numEqns; index++) {      rhsSOR[index] = 0.0;    }    for (eIndex = 1; eIndex <= pDevice->numElems; eIndex++) {      pElem = pDevice->elements[eIndex];      dxdy = 0.25 * pElem->dx * pElem->dy;      for (index = 0; index <= 3; index++) {	pNode = pElem->pNodes[index];	if ((pNode->nodeType != CONTACT) && (pElem->elemType == SEMICON)) {	  if (!OneCarrier) {	    indexN = pNode->nEqn;	    indexP = pNode->pEqn;	    rhsSOR[indexN] -= dxdy * omega * xImag[indexN];	    rhsSOR[indexP] += dxdy * omega * xImag[indexP];	  } else if (OneCarrier == N_TYPE) {	    indexN = pNode->nEqn;	    rhsSOR[indexN] -= dxdy * omega * xImag[indexN];	  } else if (OneCarrier == P_TYPE) {	    indexP = pNode->pEqn;	    rhsSOR[indexP] += dxdy * omega * xImag[indexP];	  }	}      }    }    /* now add the terms from rhs to rhsImag */    for (index = 1; index <= numEqns; index++) {      rhsSOR[index] += rhsReal[index];    }    /* compute xReal(k+1). solution stored in rhsImag */    spSolve(pDevice->matrix, rhsSOR, rhsSOR, NIL(spREAL), NIL(spREAL));    /* modify solution when wRelax is not 1 */    if (wRelax != 1) {      for (index = 1; index <= numEqns; index++) {	rhsSOR[index] = (1 - wRelax) * xReal[index] +	    wRelax * rhsSOR[index];      }    }    if (iterationNum > 1) {      SORConverged = hasSORConverged(xReal, rhsSOR, numEqns);    }    /* copy real solution into xReal */    for (index = 1; index <= numEqns; index++) {      xReal[index] = rhsSOR[index];    }    /* now compute the imaginary part of the solution xImag */    for (index = 1; index <= numEqns; index++) {      rhsSOR[index] = 0.0;    }    for (eIndex = 1; eIndex <= pDevice->numElems; eIndex++) {      pElem = pDevice->elements[eIndex];      dxdy = 0.25 * pElem->dx * pElem->dy;      for (index = 0; index <= 3; index++) {	pNode = pElem->pNodes[index];	if ((pNode->nodeType != CONTACT) && (pElem->elemType == SEMICON)) {	  if (!OneCarrier) {	    indexN = pNode->nEqn;	    indexP = pNode->pEqn;	    rhsSOR[indexN] += dxdy * omega * xReal[indexN];	    rhsSOR[indexP] -= dxdy * omega * xReal[indexP];	  } else if (OneCarrier == N_TYPE) {	    indexN = pNode->nEqn;	    rhsSOR[indexN] += dxdy * omega * xReal[indexN];	  } else if (OneCarrier ==  P_TYPE) {	    indexP = pNode->pEqn;	    rhsSOR[indexP] -= dxdy * omega * xReal[indexP];	  }	}      }    }    /* compute xImag(k+1) */    spSolve(pDevice->matrix, rhsSOR, rhsSOR, NIL(spREAL), NIL(spREAL));    /* modify solution when wRelax is not 1 */    if (wRelax != 1) {      for (index = 1; index <= numEqns; index++) {	rhsSOR[index] = (1 - wRelax) * xImag[index] +	    wRelax * rhsSOR[index];      }    }    if (iterationNum > 1) {      SORConverged = SORConverged && hasSORConverged(xImag, rhsSOR, numEqns);    }    /* copy imag solution into xImag */    for (index = 1; index <= numEqns; index++) {      xImag[index] = rhsSOR[index];    }    if ((iterationNum > 4) && !SORConverged) {      SORFailed = TRUE;    }    if (TWOacDebug)      printf("SOR iteration number = %d\n", iterationNum);  }  return (SORFailed);}SPcomplex *contactAdmittance(TWOdevice *pDevice, TWOcontact *pContact, BOOLEAN delVContact,                  double *xReal, double *xImag, SPcomplex *cOmega){  TWOnode *pNode, *pHNode = NULL, *pVNode = NULL;  TWOedge *pHEdge = NULL, *pVEdge = NULL;  int index, i, indexPsi, indexN, indexP, numContactNodes;  TWOelem *pElem;  SPcomplex psiAc, nAc, pAc;  SPcomplex prod1, prod2, sum;  double temp;  CMPLX_ASSIGN_VALUE(yTotal, 0.0, 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 != NIL(TWOelem)) {	switch (i) {	case 0:	  /* the TL element */	  pHNode = pElem->pBLNode;	  pVNode = pElem->pTRNode;	  pHEdge = pElem->pBotEdge;	  pVEdge = pElem->pRightEdge;	  if (pElem->elemType == SEMICON) {	    /* compute the derivatives with n,p */	    if (pHNode->nodeType != CONTACT) {	      indexN = pHNode->nEqn;	      indexP = pHNode->pEqn;	      CMPLX_ASSIGN_VALUE(nAc, xReal[indexN], xImag[indexN]);	      CMPLX_ASSIGN_VALUE(pAc, xReal[indexP], xImag[indexP]);	      CMPLX_MULT_SCALAR(prod1, nAc, pHEdge->dJnDn);	      CMPLX_MULT_SCALAR(prod2, pAc, pHEdge->dJpDp);	      CMPLX_ADD(sum, prod1, prod2);	      CMPLX_MULT_SCALAR(prod1, sum, 0.5 * pElem->dy);	      CMPLX_SUBT_ASSIGN(yTotal, prod1);	    }	    if (pVNode->nodeType != CONTACT) {	      indexN = pVNode->nEqn;	      indexP = pVNode->pEqn;	      CMPLX_ASSIGN_VALUE(nAc, xReal[indexN], xImag[indexN]);	      CMPLX_ASSIGN_VALUE(pAc, xReal[indexP], xImag[indexP]);	      CMPLX_MULT_SCALAR(prod1, nAc, pVEdge->dJnDn);	      CMPLX_MULT_SCALAR(prod2, pAc, pVEdge->dJpDp);	      CMPLX_ADD(sum, prod1, prod2);	      CMPLX_MULT_SCALAR(prod1, sum, 0.5 * pElem->dx);	      CMPLX_SUBT_ASSIGN(yTotal, prod1);	    }	  }	  break;	case 1:	  /* the TR element */	  pHNode = pElem->pBRNode;	  pVNode = pElem->pTLNode;	  pHEdge = pElem->pBotEdge;	  pVEdge = pElem->pLeftEdge;	  if (pElem->elemType == SEMICON) {	    /* compute the derivatives with n,p */	    if (pHNode->nodeType != CONTACT) {	      indexN = pHNode->nEqn;	      indexP = pHNode->pEqn;	      CMPLX_ASSIGN_VALUE(nAc, xReal[indexN], xImag[indexN]);	      CMPLX_ASSIGN_VALUE(pAc, xReal[indexP], xImag[indexP]);	      CMPLX_MULT_SCALAR(prod1, nAc, pHEdge->dJnDnP1);	      CMPLX_MULT_SCALAR(prod2, pAc, pHEdge->dJpDpP1);	      CMPLX_ADD(sum, prod1, prod2);	      CMPLX_MULT_SCALAR(prod1, sum, 0.5 * pElem->dy);	      CMPLX_ADD_ASSIGN(yTotal, prod1);	    }	    if (pVNode->nodeType != CONTACT) {	      indexN = pVNode->nEqn;	      indexP = pVNode->pEqn;	      CMPLX_ASSIGN_VALUE(nAc, xReal[indexN], xImag[indexN]);	      CMPLX_ASSIGN_VALUE(pAc, xReal[indexP], xImag[indexP]);	      CMPLX_MULT_SCALAR(prod1, nAc, pVEdge->dJnDn);	      CMPLX_MULT_SCALAR(prod2, pAc, pVEdge->dJpDp);	      CMPLX_ADD(sum, prod1, prod2);	      CMPLX_MULT_SCALAR(prod1, sum, 0.5 * pElem->dx);	      CMPLX_SUBT_ASSIGN(yTotal, prod1);	    }	  }	  break;	case 2:	  /* the BR element */	  pHNode = pElem->pTRNode;	  pVNode = pElem->pBLNode;	  pHEdge = pElem->pTopEdge;	  pVEdge = pElem->pLeftEdge;	  if (pElem->elemType == SEMICON) {	    /* compute the derivatives with n,p */	    if (pHNode->nodeType != CONTACT) {	      indexN = pHNode->nEqn;	      indexP = pHNode->pEqn;	      CMPLX_ASSIGN_VALUE(nAc, xReal[indexN], xImag[indexN]);	      CMPLX_ASSIGN_VALUE(pAc, xReal[indexP], xImag[indexP]);	      CMPLX_MULT_SCALAR(prod1, nAc, pHEdge->dJnDnP1);	      CMPLX_MULT_SCALAR(prod2, pAc, pHEdge->dJpDpP1);	      CMPLX_ADD(sum, prod1, prod2);	      CMPLX_MULT_SCALAR(prod1, sum, 0.5 * pElem->dy);	      CMPLX_ADD_ASSIGN(yTotal, prod1);	    }	    if (pVNode->nodeType != CONTACT) {	      indexN = pVNode->nEqn;	      indexP = pVNode->pEqn;	      CMPLX_ASSIGN_VALUE(nAc, xReal[indexN], xImag[indexN]);	      CMPLX_ASSIGN_VALUE(pAc, xReal[indexP], xImag[indexP]);	      CMPLX_MULT_SCALAR(prod1, nAc, pVEdge->dJnDnP1);	      CMPLX_MULT_SCALAR(prod2, pAc, pVEdge->dJpDpP1);	      CMPLX_ADD(sum, prod1, prod2);	      CMPLX_MULT_SCALAR(prod1, sum, 0.5 * pElem->dx);	      CMPLX_ADD_ASSIGN(yTotal, prod1);	    }	  }	  break;	case 3:	  /* the BL element */	  pHNode = pElem->pTLNode;	  pVNode = pElem->pBRNode;	  pHEdge = pElem->pTopEdge;	  pVEdge = pElem->pRightEdge;

⌨️ 快捷键说明

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