📄 twocont.c
字号:
if ( index IS 0 OR index IS 3 ) { pVEdge = pLEdge; } else { pVEdge = pREdge; } /* Add surface state charges. */ pRhs[ pNode->psiEqn ] += dx * pHEdge->qf; pRhs[ pNode->psiEqn ] += dy * pVEdge->qf; if ( pElem->elemType IS SEMICON ) { *(pNode->fPsiN) += dxdy; *(pNode->fPsiP) -= dxdy; *(pNode->fNPsi) -= dy * pHEdge->dJnDpsiP1 + dx * pVEdge->dJnDpsiP1; *(pNode->fPPsi) -= dy * pHEdge->dJpDpsiP1 + dx * pVEdge->dJpDpsiP1; nConc = *(pDevice->devState0 + pNode->nodeN); pConc = *(pDevice->devState0 + pNode->nodeP); pRhs[ pNode->psiEqn ] += dxdy * (pNode->netConc + pConc - nConc); /* Handle generation terms */ *(pNode->fNN) -= dxdy * pNode->dUdN; *(pNode->fNP) -= dxdy * pNode->dUdP; *(pNode->fPP) += dxdy * pNode->dUdP; *(pNode->fPN) += dxdy * pNode->dUdN; rhsN = - dxdy * pNode->uNet; rhsP = dxdy * pNode->uNet; if ( AvalancheGen ) { generation = TWOavalanche( pElem, pNode ); rhsN += dxdy * generation; rhsP -= dxdy * generation; } pRhs[ pNode->nEqn ] -= rhsN; pRhs[ pNode->pEqn ] -= rhsP; /* Handle dXdT continuity terms */ if ( tranAnalysis ) { *(pNode->fNN) -= dxdy * perTime; *(pNode->fPP) += dxdy * perTime; pRhs[ pNode->nEqn ] += dxdy * pNode->dNdT; pRhs[ pNode->pEqn ] -= dxdy * pNode->dPdT; } } } } /* Handle neighbor and edge dependent terms */ pNode = pElem->pTLNode; if ( pNode->nodeType ISNOT CONTACT ) { pRhs[ pNode->psiEqn ] -= -dyOverDx * dPsiT - dxOverDy * dPsiL; *(pNode->fPsiPsiiP1) -= dyOverDx; *(pNode->fPsiPsijP1) -= dxOverDy; if ( pElem->elemType IS SEMICON ) { pRhs[ pNode->nEqn ] -= dy * pTEdge->jn + dx * pLEdge->jn; pRhs[ pNode->pEqn ] -= dy * pTEdge->jp + dx * pLEdge->jp; *(pNode->fNN) += dy * pTEdge->dJnDn + dx * pLEdge->dJnDn; *(pNode->fPP) += dy * pTEdge->dJpDp + dx * pLEdge->dJpDp; *(pNode->fNPsiiP1) += dy * pTEdge->dJnDpsiP1; *(pNode->fNNiP1) += dy * pTEdge->dJnDnP1; *(pNode->fPPsiiP1) += dy * pTEdge->dJpDpsiP1; *(pNode->fPPiP1) += dy * pTEdge->dJpDpP1; *(pNode->fNPsijP1) += dx * pLEdge->dJnDpsiP1; *(pNode->fNNjP1) += dx * pLEdge->dJnDnP1; *(pNode->fPPsijP1) += dx * pLEdge->dJpDpsiP1; *(pNode->fPPjP1) += dx * pLEdge->dJpDpP1; } } pNode = pElem->pTRNode; if ( pNode->nodeType ISNOT CONTACT ) { pRhs[ pNode->psiEqn ] -= dyOverDx * dPsiT - dxOverDy * dPsiR; *(pNode->fPsiPsiiM1) -= dyOverDx; *(pNode->fPsiPsijP1) -= dxOverDy; if ( pElem->elemType IS SEMICON ) { pRhs[ pNode->nEqn ] -= -dy * pTEdge->jn + dx * pREdge->jn; pRhs[ pNode->pEqn ] -= -dy * pTEdge->jp + dx * pREdge->jp; *(pNode->fNN) += -dy * pTEdge->dJnDnP1 + dx * pREdge->dJnDn; *(pNode->fPP) += -dy * pTEdge->dJpDpP1 + dx * pREdge->dJpDp; *(pNode->fNPsiiM1) += dy * pTEdge->dJnDpsiP1; *(pNode->fNNiM1) -= dy * pTEdge->dJnDn; *(pNode->fPPsiiM1) += dy * pTEdge->dJpDpsiP1; *(pNode->fPPiM1) -= dy * pTEdge->dJpDp; *(pNode->fNPsijP1) += dx * pREdge->dJnDpsiP1; *(pNode->fNNjP1) += dx * pREdge->dJnDnP1; *(pNode->fPPsijP1) += dx * pREdge->dJpDpsiP1; *(pNode->fPPjP1) += dx * pREdge->dJpDpP1; } } pNode = pElem->pBRNode; if ( pNode->nodeType ISNOT CONTACT ) { pRhs[ pNode->psiEqn ] -= dyOverDx * dPsiB + dxOverDy * dPsiR; *(pNode->fPsiPsiiM1) -= dyOverDx; *(pNode->fPsiPsijM1) -= dxOverDy; if ( pElem->elemType IS SEMICON ) { pRhs[ pNode->nEqn ] -= -dy * pBEdge->jn - dx * pREdge->jn; pRhs[ pNode->pEqn ] -= -dy * pBEdge->jp - dx * pREdge->jp; *(pNode->fNN) += -dy * pBEdge->dJnDnP1 - dx * pREdge->dJnDnP1; *(pNode->fPP) += -dy * pBEdge->dJpDpP1 - dx * pREdge->dJpDpP1; *(pNode->fNPsiiM1) += dy * pBEdge->dJnDpsiP1; *(pNode->fNNiM1) -= dy * pBEdge->dJnDn; *(pNode->fPPsiiM1) += dy * pBEdge->dJpDpsiP1; *(pNode->fPPiM1) -= dy * pBEdge->dJpDp; *(pNode->fNPsijM1) += dx * pREdge->dJnDpsiP1; *(pNode->fNNjM1) -= dx * pREdge->dJnDn; *(pNode->fPPsijM1) += dx * pREdge->dJpDpsiP1; *(pNode->fPPjM1) -= dx * pREdge->dJpDp; } } pNode = pElem->pBLNode; if ( pNode->nodeType ISNOT CONTACT ) { pRhs[ pNode->psiEqn ] -= -dyOverDx * dPsiB + dxOverDy * dPsiL; *(pNode->fPsiPsiiP1) -= dyOverDx; *(pNode->fPsiPsijM1) -= dxOverDy; if ( pElem->elemType IS SEMICON ) { pRhs[ pNode->nEqn ] -= dy * pBEdge->jn - dx * pLEdge->jn; pRhs[ pNode->pEqn ] -= dy * pBEdge->jp - dx * pLEdge->jp; *(pNode->fNN) += dy * pBEdge->dJnDn - dx * pLEdge->dJnDnP1; *(pNode->fPP) += dy * pBEdge->dJpDp - dx * pLEdge->dJpDpP1; *(pNode->fNPsiiP1) += dy * pBEdge->dJnDpsiP1; *(pNode->fNNiP1) += dy * pBEdge->dJnDnP1; *(pNode->fPPsiiP1) += dy * pBEdge->dJpDpsiP1; *(pNode->fPPiP1) += dy * pBEdge->dJpDpP1; *(pNode->fNPsijM1) += dx * pLEdge->dJnDpsiP1; *(pNode->fNNjM1) -= dx * pLEdge->dJnDn; *(pNode->fPPsijM1) += dx * pLEdge->dJpDpsiP1; *(pNode->fPPjM1) -= dx * pLEdge->dJpDp; } } } /* Calculate the Inversion-Layer Mobility Dependent Terms in Jac. */ if ( MobDeriv AND SurfaceMobility ) { for ( pCh = pDevice->pChannel; pCh ISNOT NIL(TWOchannel); pCh = pCh->next ) { /* Find effective height of oxide element at interface. */ if ( pCh->type%2 == 0 ) { /* Vertical slice */ ds = pCh->pNElem->dy / pCh->pNElem->epsRel; } else { /* Horizontal slice */ ds = pCh->pNElem->dx / pCh->pNElem->epsRel; } pElem = pCh->pSeed; nextIndex = (pCh->type + 2)%4; while (pElem && pElem->channel == pCh->id) { TWO_mobDeriv( pElem, pCh->type, ds ); pElem = pElem->pElems[ nextIndex ]; } } /* endfor pCh ISNOT NIL */ } /* endif MobDeriv and SurfaceMobility */}/* this function used only for direct method ac analysis Used to load only the dc Jacobian matrix. Rhs is unaffected */void TWO_jacLoad( pDevice ) TWOdevice *pDevice;{ TWOelem *pElem; TWOnode *pNode; TWOedge *pHEdge, *pVEdge; TWOedge *pTEdge, *pBEdge, *pLEdge, *pREdge; TWOchannel *pCh; int index, eIndex; int nextIndex; /* index of node to find next element */ double dx, dy, dxdy, dyOverDx, dxOverDy; double ds; void spClear(), TWO_commonTerms(); /* first compute the currents and derivatives */ TWO_commonTerms( pDevice, FALSE, FALSE, NIL(TWOtranInfo) ); /* zero the matrix */ spClear( pDevice->matrix ); for ( eIndex = 1; eIndex <= pDevice->numElems; eIndex++ ) { pElem = pDevice->elements[ eIndex ]; dx = 0.5 * pElem->dx; dy = 0.5 * pElem->dy; dxdy = dx * dy; dxOverDy = 0.5 * pElem->epsRel * pElem->dxOverDy; dyOverDx = 0.5 * pElem->epsRel * pElem->dyOverDx; pTEdge = pElem->pTopEdge; pBEdge = pElem->pBotEdge; pLEdge = pElem->pLeftEdge; pREdge = pElem->pRightEdge; /* load for all i,j */ for ( index = 0; index <= 3; index++ ) { pNode = pElem->pNodes[ index ]; if ( pNode->nodeType ISNOT CONTACT ) { *(pNode->fPsiPsi) += dyOverDx + dxOverDy; if ( pElem->elemType IS SEMICON ) { if ( index <= 1 ) { pHEdge = pTEdge; } else { pHEdge = pBEdge; } if ( index IS 0 OR index IS 3 ) { pVEdge = pLEdge; } else { pVEdge = pREdge; } *(pNode->fPsiN) += dxdy; *(pNode->fPsiP) -= dxdy; *(pNode->fNPsi) -= dy * pHEdge->dJnDpsiP1 + dx * pVEdge->dJnDpsiP1; *(pNode->fPPsi) -= dy * pHEdge->dJpDpsiP1 + dx * pVEdge->dJpDpsiP1; /* Handle generation terms */ *(pNode->fNN) -= dxdy * pNode->dUdN; *(pNode->fNP) -= dxdy * pNode->dUdP; *(pNode->fPP) += dxdy * pNode->dUdP; *(pNode->fPN) += dxdy * pNode->dUdN; } } } /* Handle neighbor and edge dependent terms */ pNode = pElem->pTLNode; if ( pNode->nodeType ISNOT CONTACT ) { *(pNode->fPsiPsiiP1) -= dyOverDx; *(pNode->fPsiPsijP1) -= dxOverDy; if ( pElem->elemType IS SEMICON ) { *(pNode->fNN) += dy * pTEdge->dJnDn + dx * pLEdge->dJnDn; *(pNode->fPP) += dy * pTEdge->dJpDp + dx * pLEdge->dJpDp; *(pNode->fNPsiiP1) += dy * pTEdge->dJnDpsiP1; *(pNode->fNNiP1) += dy * pTEdge->dJnDnP1; *(pNode->fPPsiiP1) += dy * pTEdge->dJpDpsiP1; *(pNode->fPPiP1) += dy * pTEdge->dJpDpP1; *(pNode->fNPsijP1) += dx * pLEdge->dJnDpsiP1; *(pNode->fNNjP1) += dx * pLEdge->dJnDnP1; *(pNode->fPPsijP1) += dx * pLEdge->dJpDpsiP1; *(pNode->fPPjP1) += dx * pLEdge->dJpDpP1; } } pNode = pElem->pTRNode; if ( pNode->nodeType ISNOT CONTACT ) { *(pNode->fPsiPsiiM1) -= dyOverDx; *(pNode->fPsiPsijP1) -= dxOverDy; if ( pElem->elemType IS SEMICON ) { *(pNode->fNN) += -dy * pTEdge->dJnDnP1 + dx * pREdge->dJnDn; *(pNode->fPP) += -dy * pTEdge->dJpDpP1 + dx * pREdge->dJpDp; *(pNode->fNPsiiM1) += dy * pTEdge->dJnDpsiP1; *(pNode->fNNiM1) -= dy * pTEdge->dJnDn; *(pNode->fPPsiiM1) += dy * pTEdge->dJpDpsiP1; *(pNode->fPPiM1) -= dy * pTEdge->dJpDp; *(pNode->fNPsijP1) += dx * pREdge->dJnDpsiP1; *(pNode->fNNjP1) += dx * pREdge->dJnDnP1; *(pNode->fPPsijP1) += dx * pREdge->dJpDpsiP1; *(pNode->fPPjP1) += dx * pREdge->dJpDpP1; } } pNode = pElem->pBRNode; if ( pNode->nodeType ISNOT CONTACT ) { *(pNode->fPsiPsiiM1) -= dyOverDx; *(pNode->fPsiPsijM1) -= dxOverDy; if ( pElem->elemType IS SEMICON ) { *(pNode->fNN) += -dy * pBEdge->dJnDnP1 - dx * pREdge->dJnDnP1; *(pNode->fPP) += -dy * pBEdge->dJpDpP1 - dx * pREdge->dJpDpP1; *(pNode->fNPsiiM1) += dy * pBEdge->dJnDpsiP1; *(pNode->fNNiM1) -= dy * pBEdge->dJnDn; *(pNode->fPPsiiM1) += dy * pBEdge->dJpDpsiP1; *(pNode->fPPiM1) -= dy * pBEdge->dJpDp; *(pNode->fNPsijM1) += dx * pREdge->dJnDpsiP1; *(pNode->fNNjM1) -= dx * pREdge->dJnDn; *(pNode->fPPsijM1) += dx * pREdge->dJpDpsiP1; *(pNode->fPPjM1) -= dx * pREdge->dJpDp; } } pNode = pElem->pBLNode; if ( pNode->nodeType ISNOT CONTACT ) { *(pNode->fPsiPsiiP1) -= dyOverDx; *(pNode->fPsiPsijM1) -= dxOverDy; if ( pElem->elemType IS SEMICON ) { *(pNode->fNN) += dy * pBEdge->dJnDn - dx * pLEdge->dJnDnP1; *(pNode->fPP) += dy * pBEdge->dJpDp - dx * pLEdge->dJpDpP1; *(pNode->fNPsiiP1) += dy * pBEdge->dJnDpsiP1; *(pNode->fNNiP1) += dy * pBEdge->dJnDnP1; *(pNode->fPPsiiP1) += dy * pBEdge->dJpDpsiP1; *(pNode->fPPiP1) += dy * pBEdge->dJpDpP1; *(pNode->fNPsijM1) += dx * pLEdge->dJnDpsiP1; *(pNode->fNNjM1) -= dx * pLEdge->dJnDn; *(pNode->fPPsijM1) += dx * pLEdge->dJpDpsiP1; *(pNode->fPPjM1) -= dx * pLEdge->dJpDp; } } } /* Calculate the Inversion-Layer Mobility Dependent Terms in Jac. */ if ( MobDeriv AND SurfaceMobility ) { for ( pCh = pDevice->pChannel; pCh ISNOT NIL(TWOchannel); pCh = pCh->next ) { /* Find effective height of oxide element at interface. */ if ( pCh->type%2 == 0 ) { /* Vertical slice */ ds = pCh->pNElem->dy / pCh->pNElem->epsRel; } else { /* Horizontal slice */ ds = pCh->pNElem->dx / pCh->pNElem->epsRel; } pElem = pCh->pSeed; nextIndex = (pCh->type + 2)%4; while (pElem && pElem->channel == pCh->id) { TWO_mobDeriv( pElem, pCh->type, ds ); pElem = pElem->pElems[ nextIndex ]; } } /* endfor pCh ISNOT NIL */ } /* endif MobDeriv and SurfaceMobility */}/* load only the Rhs vector */void TWO_rhsLoad( pDevice, tranAnalysis, info ) TWOdevice *pDevice;BOOLEAN tranAnalysis;TWOtranInfo *info;{ TWOelem *pElem; TWOnode *pNode; TWOedge *pHEdge, *pVEdge; TWOedge *pTEdge, *pBEdge, *pLEdge, *pREdge; TWOchannel *pCh; int index, eIndex; double *pRhs = pDevice->rhs; double dx, dy, dxdy, dyOverDx, dxOverDy; double dPsiT, dPsiB, dPsiL, dPsiR; double rhsN, rhsP; double generation, TWOavalanche(); double nConc, pConc; double perTime; void TWO_commonTerms(); /* first compute the currents */ TWO_commonTerms( pDevice, TRUE, 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; } for ( eIndex = 1; eIndex <= pDevice->numElems; eIndex++ ) { pElem = pDevice->elements[ eIndex ]; dx = 0.5 * pElem->dx; dy = 0.5 * pElem->dy; dxdy = dx * dy; dxOverDy = 0.5 * pElem->epsRel * pElem->dxOverDy; dyOverDx = 0.5 * pElem->epsRel * pElem->dyOverDx;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -