📄 nummload.c
字号:
ig = *(ckt->CKTstate0 + inst->NUMOSig); g.dIdDVdb = *(ckt->CKTstate0 + inst->NUMOSdIdDVdb); g.dIdDVsb = *(ckt->CKTstate0 + inst->NUMOSdIdDVsb); g.dIdDVgb = *(ckt->CKTstate0 + inst->NUMOSdIdDVgb); g.dIsDVdb = *(ckt->CKTstate0 + inst->NUMOSdIsDVdb); g.dIsDVsb = *(ckt->CKTstate0 + inst->NUMOSdIsDVsb); g.dIsDVgb = *(ckt->CKTstate0 + inst->NUMOSdIsDVgb); g.dIgDVdb = *(ckt->CKTstate0 + inst->NUMOSdIgDVdb); g.dIgDVsb = *(ckt->CKTstate0 + inst->NUMOSdIgDVsb); g.dIgDVgb = *(ckt->CKTstate0 + inst->NUMOSdIgDVgb); goto load; }#endif /* NOBYPASS */ /* * limit nonlinear branch voltages */ icheck1 = 1; if (deviceType == OPTN_BIPOLAR) { double vbe, vbe0; double vce, vce0; vdb = -inst->NUMOStype * limitJunctionVoltage(-inst->NUMOStype * vdb, -inst->NUMOStype * *(ckt->CKTstate0 + inst->NUMOSvdb), &icheck); vce = vdb - vsb; vce0 = *(ckt->CKTstate0 + inst->NUMOSvdb) - *(ckt->CKTstate0 + inst->NUMOSvsb); vce = inst->NUMOStype * limitVce(inst->NUMOStype * vce, inst->NUMOStype * vce0, &icheck1); if (icheck1 == 1) icheck = 1; vsb = vdb - vce; vbe = vgb - vsb; vbe0 = *(ckt->CKTstate0 + inst->NUMOSvgb) - *(ckt->CKTstate0 + inst->NUMOSvsb); vbe = inst->NUMOStype * limitVbe(inst->NUMOStype * vbe, inst->NUMOStype * vbe0, &icheck1); if (icheck1 == 1) icheck = 1; vgb = vbe + vsb; } else { vdb = -inst->NUMOStype * limitJunctionVoltage(-inst->NUMOStype * vdb, -inst->NUMOStype * *(ckt->CKTstate0 + inst->NUMOSvdb), &icheck); vsb = -inst->NUMOStype * limitJunctionVoltage(-inst->NUMOStype * vsb, -inst->NUMOStype * *(ckt->CKTstate0 + inst->NUMOSvsb), &icheck1); if (icheck1 == 1) icheck = 1; vgb = inst->NUMOStype * limitVgb(inst->NUMOStype * vgb, inst->NUMOStype * *(ckt->CKTstate0 + inst->NUMOSvgb), &icheck1); if (icheck1 == 1) icheck = 1; } delVdb = vdb - *(ckt->CKTstate0 + inst->NUMOSvdb); delVsb = vsb - *(ckt->CKTstate0 + inst->NUMOSvsb); delVgb = vgb - *(ckt->CKTstate0 + inst->NUMOSvgb); NUMOSsetBCs(pDevice, vdb - delVdb, vsb - delVsb, vgb - delVgb); } if (doInitSolve) { if (TWOdcDebug) { printVoltages(stdout, model->NUMOSmodName, inst->NUMOSname, deviceType, 3, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0); } startTime2 = SPfrontEnd->IFseconds(); TWOequilSolve(pDevice); totalTime2 = SPfrontEnd->IFseconds() - startTime2; pDevice->pStats->totalTime[STAT_SETUP] += totalTime2; pDevice->pStats->totalTime[STAT_DC] -= totalTime2; TWObiasSolve(pDevice, MaxIterations, FALSE, NULL); *(ckt->CKTstate0 + inst->NUMOSvdb) = 0.0; *(ckt->CKTstate0 + inst->NUMOSvsb) = 0.0; *(ckt->CKTstate0 + inst->NUMOSvgb) = 0.0; if (initStateName != NULL) { if (TWOreadState(pDevice, initStateName, 3, &vdb, &vgb, &vsb ) < 0) { fprintf(stderr, "NUMOSload: trouble reading state-file %s\n", initStateName); } else { NUMOSsetBCs(pDevice, vdb, vsb, vgb); delVdb = delVsb = delVgb = 0.0; } } } /* * determine dc current and derivatives using the numerical routines */ if (ckt->CKTmode & (MODEDCOP | MODETRANOP | MODEDCTRANCURVE | MODEINITSMSIG)) { numDevNonCon = 0; inst->NUMOSc11 = inst->NUMOSy11r = inst->NUMOSy11i = 0.0; inst->NUMOSc12 = inst->NUMOSy12r = inst->NUMOSy12i = 0.0; inst->NUMOSc13 = inst->NUMOSy13r = inst->NUMOSy13i = 0.0; inst->NUMOSc21 = inst->NUMOSy21r = inst->NUMOSy21i = 0.0; inst->NUMOSc22 = inst->NUMOSy22r = inst->NUMOSy22i = 0.0; inst->NUMOSc23 = inst->NUMOSy23r = inst->NUMOSy23i = 0.0; inst->NUMOSc31 = inst->NUMOSy31r = inst->NUMOSy31i = 0.0; inst->NUMOSc32 = inst->NUMOSy32r = inst->NUMOSy32i = 0.0; inst->NUMOSc33 = inst->NUMOSy33r = inst->NUMOSy33i = 0.0; inst->NUMOSsmSigAvail = FALSE; devNonCon: NUMOSproject(pDevice, delVdb, delVsb, delVgb); if (TWOdcDebug) { printVoltages(stdout, model->NUMOSmodName, inst->NUMOSname, deviceType, 3, vdb, delVdb, vgb, delVgb, vsb, delVsb); } TWObiasSolve(pDevice, MaxIterations, FALSE, model->NUMOSpInfo); devConverged = pDevice->converged; if (devConverged && finite(pDevice->rhsNorm)) { /* compute the currents */ NUMOScurrent(pDevice, FALSE, (double *) NULL, &id, &is, &ig); NUMOSconductance(pDevice, FALSE, (double *) NULL, &g); /* * Add gmin to the gate conductance terms since they will be zero. * XXX This messes up the gXY output values, but we choose not to * correct this error, because it shouldn't cause practical problems. */ g.dIgDVdb += ckt->CKTgmin; g.dIgDVsb += ckt->CKTgmin; g.dIgDVgb += ckt->CKTgmin; } else { /* reduce the voltage step until converged */ /* restore boundary nodes to previous potential */ NUMOSsetBCs(pDevice, vdb - delVdb, vsb - delVsb, vgb - delVgb); TWOstoreInitialGuess(pDevice); TWOresetJacobian(pDevice); delVdb *= 0.5; delVsb *= 0.5; delVgb *= 0.5; vdb = delVdb + *(ckt->CKTstate0 + inst->NUMOSvdb); vsb = delVsb + *(ckt->CKTstate0 + inst->NUMOSvsb); vgb = delVgb + *(ckt->CKTstate0 + inst->NUMOSvgb); numDevNonCon++; icheck = 1; if (numDevNonCon > 10) { printVoltages(stderr, model->NUMOSmodName, inst->NUMOSname, deviceType, 3, vdb, delVdb, vgb, delVgb, vsb, delVsb); fprintf(stderr, "*** Non-convergence during load ***\n"); totalTime += SPfrontEnd->IFseconds() - startTime; pDevice->pStats->totalTime[STAT_DC] += totalTime; ckt->CKTtroubleElt = (GENinstance *) inst; return (E_BADMATRIX); } else { goto devNonCon; } } } if ((ckt->CKTmode & (MODETRAN | MODEAC)) || ((ckt->CKTmode & MODETRANOP) && (ckt->CKTmode & MODEUIC)) || (ckt->CKTmode & MODEINITSMSIG)) { /* * store small-signal parameters */ if ((!(ckt->CKTmode & MODETRANOP)) || (!(ckt->CKTmode & MODEUIC))) { if (ckt->CKTmode & MODEINITSMSIG) { totalTime += SPfrontEnd->IFseconds() - startTime; pDevice->pStats->totalTime[STAT_DC] += totalTime; startTime2 = SPfrontEnd->IFseconds(); NUMOSinitSmSig(inst); pDevice->pStats->totalTime[STAT_AC] += SPfrontEnd->IFseconds() - startTime2; continue; } else { inst->NUMOSsmSigAvail = FALSE; } /* * transient analysis */ if (ckt->CKTmode & MODEINITPRED) { NUMOSsetBCs(pDevice, vdb, vsb, vgb); TWOstoreInitialGuess(pDevice); } else { NUMOSupdate(pDevice, delVdb, delVsb, delVgb, TRUE); } if (TWOtranDebug) { printVoltages(stdout, model->NUMOSmodName, inst->NUMOSname, deviceType, 3, vdb, delVdb, vgb, delVgb, vsb, delVsb); } TWObiasSolve(pDevice, 0, TRUE, model->NUMOSpInfo); if (!finite(pDevice->rhsNorm)) { totalTime += SPfrontEnd->IFseconds() - startTime; pDevice->pStats->totalTime[STAT_TRAN] += totalTime; ckt->CKTtroubleElt = (GENinstance *) inst; return (E_BADMATRIX); } devConverged = TWOdeviceConverged(pDevice); pDevice->converged = devConverged; /* compute the currents and conductances */ NUMOScurrent(pDevice, TRUE, model->NUMOSpInfo->intCoeff, &id, &is, &ig); NUMOSconductance(pDevice, TRUE, model->NUMOSpInfo->intCoeff, &g); } } /* * check convergence */ if ((!(ckt->CKTmode & MODEINITFIX)) || (!(inst->NUMOSoff))) { if (icheck == 1 || !devConverged) { ckt->CKTnoncon++; ckt->CKTtroubleElt = (GENinstance *) inst; } else { tol = ckt->CKTreltol * MAX(FABS(idhat), FABS(id)) + ckt->CKTabstol; if (FABS(idhat - id) > tol) { ckt->CKTnoncon++; ckt->CKTtroubleElt = (GENinstance *) inst; } else { tol = ckt->CKTreltol * MAX(FABS(ishat), FABS(is)) + ckt->CKTabstol; if (FABS(ishat - is) > tol) { ckt->CKTnoncon++; ckt->CKTtroubleElt = (GENinstance *) inst; } else { tol = ckt->CKTreltol * MAX(FABS(ighat), FABS(ig)) + ckt->CKTabstol; if (FABS(ighat - ig) > tol) { ckt->CKTnoncon++; ckt->CKTtroubleElt = (GENinstance *) inst; } } } } } *(ckt->CKTstate0 + inst->NUMOSvdb) = vdb; *(ckt->CKTstate0 + inst->NUMOSvsb) = vsb; *(ckt->CKTstate0 + inst->NUMOSvgb) = vgb; *(ckt->CKTstate0 + inst->NUMOSid) = id; *(ckt->CKTstate0 + inst->NUMOSis) = is; *(ckt->CKTstate0 + inst->NUMOSig) = ig; *(ckt->CKTstate0 + inst->NUMOSdIdDVdb) = g.dIdDVdb; *(ckt->CKTstate0 + inst->NUMOSdIdDVsb) = g.dIdDVsb; *(ckt->CKTstate0 + inst->NUMOSdIdDVgb) = g.dIdDVgb; *(ckt->CKTstate0 + inst->NUMOSdIsDVdb) = g.dIsDVdb; *(ckt->CKTstate0 + inst->NUMOSdIsDVsb) = g.dIsDVsb; *(ckt->CKTstate0 + inst->NUMOSdIsDVgb) = g.dIsDVgb; *(ckt->CKTstate0 + inst->NUMOSdIgDVdb) = g.dIgDVdb; *(ckt->CKTstate0 + inst->NUMOSdIgDVsb) = g.dIgDVsb; *(ckt->CKTstate0 + inst->NUMOSdIgDVgb) = g.dIgDVgb; load: /* * load current excitation vector */ ideq = id - g.dIdDVdb * vdb - g.dIdDVsb * vsb - g.dIdDVgb * vgb; iseq = is - g.dIsDVdb * vdb - g.dIsDVsb * vsb - g.dIsDVgb * vgb; igeq = ig - g.dIgDVdb * vdb - g.dIgDVsb * vsb - g.dIgDVgb * vgb; *(ckt->CKTrhs + inst->NUMOSdrainNode) -= ideq; *(ckt->CKTrhs + inst->NUMOSsourceNode) -= iseq; *(ckt->CKTrhs + inst->NUMOSgateNode) -= igeq; *(ckt->CKTrhs + inst->NUMOSbulkNode) += ideq + iseq + igeq; /* * load y matrix */ *(inst->NUMOSdrainDrainPtr) += g.dIdDVdb; *(inst->NUMOSdrainSourcePtr) += g.dIdDVsb; *(inst->NUMOSdrainGatePtr) += g.dIdDVgb; *(inst->NUMOSdrainBulkPtr) -= g.dIdDVdb + g.dIdDVsb + g.dIdDVgb; *(inst->NUMOSsourceDrainPtr) += g.dIsDVdb; *(inst->NUMOSsourceSourcePtr) += g.dIsDVsb; *(inst->NUMOSsourceGatePtr) += g.dIsDVgb; *(inst->NUMOSsourceBulkPtr) -= g.dIsDVdb + g.dIsDVsb + g.dIsDVgb; *(inst->NUMOSgateDrainPtr) += g.dIgDVdb; *(inst->NUMOSgateSourcePtr) += g.dIgDVsb; *(inst->NUMOSgateGatePtr) += g.dIgDVgb; *(inst->NUMOSgateBulkPtr) -= g.dIgDVdb + g.dIgDVsb + g.dIgDVgb; *(inst->NUMOSbulkDrainPtr) -= g.dIdDVdb + g.dIsDVdb + g.dIgDVdb; *(inst->NUMOSbulkSourcePtr) -= g.dIdDVsb + g.dIsDVsb + g.dIgDVsb; *(inst->NUMOSbulkGatePtr) -= g.dIdDVgb + g.dIsDVgb + g.dIgDVgb; *(inst->NUMOSbulkBulkPtr) += g.dIdDVdb + g.dIdDVsb + g.dIdDVgb + g.dIsDVdb + g.dIsDVsb + g.dIsDVgb + g.dIgDVdb + g.dIgDVsb + g.dIgDVgb; totalTime += SPfrontEnd->IFseconds() - startTime; if (ckt->CKTmode & MODETRAN) { pDevice->pStats->totalTime[STAT_TRAN] += totalTime; } else { pDevice->pStats->totalTime[STAT_DC] += totalTime; } } } return (OK);}intNUMOSinitSmSig(inst) NUMOSinstance *inst;{ struct mosAdmittances yAc; double omega = inst->NUMOSmodPtr->NUMOSmethods->METHomega; AcAnalysisMethod = SOR_ONLY; (void) NUMOSadmittance(inst->NUMOSpDevice, omega, &yAc); inst->NUMOSc11 = yAc.yIdVdb.imag / omega; inst->NUMOSc12 = yAc.yIdVgb.imag / omega; inst->NUMOSc13 = yAc.yIdVsb.imag / omega; inst->NUMOSc21 = yAc.yIgVdb.imag / omega; inst->NUMOSc22 = yAc.yIgVgb.imag / omega; inst->NUMOSc23 = yAc.yIgVsb.imag / omega; inst->NUMOSc31 = yAc.yIsVdb.imag / omega; inst->NUMOSc32 = yAc.yIsVgb.imag / omega; inst->NUMOSc33 = yAc.yIsVsb.imag / omega; inst->NUMOSy11r = yAc.yIdVdb.real; inst->NUMOSy11i = yAc.yIdVdb.imag; inst->NUMOSy12r = yAc.yIdVgb.real; inst->NUMOSy12i = yAc.yIdVgb.imag; inst->NUMOSy13r = yAc.yIdVsb.real; inst->NUMOSy13i = yAc.yIdVsb.imag; inst->NUMOSy21r = yAc.yIgVdb.real; inst->NUMOSy21i = yAc.yIgVdb.imag; inst->NUMOSy22r = yAc.yIgVgb.real; inst->NUMOSy22i = yAc.yIgVgb.imag; inst->NUMOSy23r = yAc.yIgVsb.real; inst->NUMOSy23i = yAc.yIgVsb.imag; inst->NUMOSy31r = yAc.yIsVdb.real; inst->NUMOSy31i = yAc.yIsVdb.imag; inst->NUMOSy32r = yAc.yIsVgb.real; inst->NUMOSy32i = yAc.yIsVgb.imag; inst->NUMOSy33r = yAc.yIsVsb.real; inst->NUMOSy33i = yAc.yIsVsb.imag; inst->NUMOSsmSigAvail = TRUE; return (OK);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -