/* Spice3 Source stepping * Modified 2005 - Paolo Nenzi (extracted from CKTop.c code) * * return value: * 0 -> method converged * 1 -> method failed * * Note that no path out of this code allows ckt->CKTsrcFact to be * anything but 1.00000. */ static int spice3_src (CKTcircuit * ckt, long int firstmode, long int continuemode, int iterlim) { int converged, i; ckt->CKTmode = firstmode; (*(SPfrontEnd->IFerror)) (ERR_INFO, "Starting source stepping", (IFuid *) NULL); for (i = 0; i <= ckt->CKTnumSrcSteps; i++) { ckt->CKTsrcFact = ((double) i) / ((double) ckt->CKTnumSrcSteps); #ifdef XSPICE /* gtri - begin - wbk - add convergence problem reporting flags */ ckt->enh->conv_debug.last_NIiter_call = MIF_TRUE; /* gtri - end - wbk - add convergence problem reporting flags */ #endif converged = NIiter (ckt, ckt->CKTdcTrcvMaxIter); ckt->CKTmode = continuemode; if (converged != 0) { ckt->CKTsrcFact = 1; ckt->CKTcurrentAnalysis = DOING_TRAN; (*(SPfrontEnd->IFerror)) (ERR_WARNING, "source stepping failed", (IFuid *) NULL); #ifdef XSPICE /* gtri - begin - wbk - add convergence problem reporting flags */ ckt->enh->conv_debug.last_NIiter_call = MIF_FALSE; /* gtri - end - wbk - add convergence problem reporting flags */ #endif return (converged); } (*(SPfrontEnd->IFerror)) (ERR_INFO, "One successful source step", (IFuid *) NULL); } (*(SPfrontEnd->IFerror)) (ERR_INFO, "Source stepping completed", (IFuid *) NULL); ckt->CKTsrcFact = 1; #ifdef XSPICE /* gtri - begin - wbk - add convergence problem reporting flags */ ckt->enh->conv_debug.last_NIiter_call = MIF_FALSE; /* gtri - end - wbk - add convergence problem reporting flags */ #endif return (0); }
int DCtrCurv(CKTcircuit *ckt, int restart) { TRCV *job = (TRCV *) ckt->CKTcurJob; int i; double *temp; int converged; int rcode; int vcode; int icode; int j; int error; IFuid varUid; IFuid *nameList; int numNames; int firstTime = 1; static runDesc *plot = NULL; #ifdef WANT_SENSE2 long save; #ifdef SENSDEBUG if (ckt->CKTsenInfo && (ckt->CKTsenInfo->SENmode & DCSEN)) { printf("\nDC Sensitivity Results\n\n"); CKTsenPrint(ckt); } #endif #endif rcode = CKTtypelook("Resistor"); vcode = CKTtypelook("Vsource"); icode = CKTtypelook("Isource"); if (!restart && job->TRCVnestState >= 0) { /* continuing */ i = job->TRCVnestState; /* resume to work? saj*/ error = SPfrontEnd->OUTpBeginPlot (NULL, NULL, NULL, NULL, 0, 666, NULL, 666, &plot); goto resume; } ckt->CKTtime = 0; ckt->CKTdelta = job->TRCVvStep[0]; ckt->CKTmode = (ckt->CKTmode & MODEUIC) | MODEDCTRANCURVE | MODEINITJCT; ckt->CKTorder = 1; /* Save the state of the circuit */ for (j = 0; j < 7; j++) ckt->CKTdeltaOld[j] = ckt->CKTdelta; for (i = 0; i <= job->TRCVnestLevel; i++) { if (rcode >= 0) { /* resistances are in this version, so use them */ RESinstance *here; RESmodel *model; for (model = (RESmodel *)ckt->CKThead[rcode]; model; model = model->RESnextModel) for (here = model->RESinstances; here; here = here->RESnextInstance) if (here->RESname == job->TRCVvName[i]) { job->TRCVvElt[i] = (GENinstance *)here; job->TRCVvSave[i] = here->RESresist; job->TRCVgSave[i] = here->RESresGiven; job->TRCVvType[i] = rcode; here->RESresist = job->TRCVvStart[i]; here->RESresGiven = 1; CKTtemp(ckt); goto found; } } if (vcode >= 0) { /* voltage sources are in this version, so use them */ VSRCinstance *here; VSRCmodel *model; for (model = (VSRCmodel *)ckt->CKThead[vcode]; model; model = model->VSRCnextModel) for (here = model->VSRCinstances; here; here = here->VSRCnextInstance) if (here->VSRCname == job->TRCVvName[i]) { job->TRCVvElt[i] = (GENinstance *)here; job->TRCVvSave[i] = here->VSRCdcValue; job->TRCVgSave[i] = here->VSRCdcGiven; job->TRCVvType[i] = vcode; here->VSRCdcValue = job->TRCVvStart[i]; here->VSRCdcGiven = 1; goto found; } } if (icode >= 0) { /* current sources are in this version, so use them */ ISRCinstance *here; ISRCmodel *model; for (model = (ISRCmodel *)ckt->CKThead[icode]; model; model = model->ISRCnextModel) for (here = model->ISRCinstances; here; here = here->ISRCnextInstance) if (here->ISRCname == job->TRCVvName[i]) { job->TRCVvElt[i] = (GENinstance *)here; job->TRCVvSave[i] = here->ISRCdcValue; job->TRCVgSave[i] = here->ISRCdcGiven; job->TRCVvType[i] = icode; here->ISRCdcValue = job->TRCVvStart[i]; here->ISRCdcGiven = 1; goto found; } } if (!strcmp(job->TRCVvName[i], "temp")) { job->TRCVvSave[i] = ckt->CKTtemp; /* Saves the old circuit temperature */ job->TRCVvType[i] = TEMP_CODE; /* Set the sweep type code */ ckt->CKTtemp = job->TRCVvStart[i] + CONSTCtoK; /* Set the new circuit temp */ if (expr_w_temper) inp_evaluate_temper(); CKTtemp(ckt); goto found; } SPfrontEnd->IFerrorf (ERR_FATAL, "DCtrCurv: source / resistor %s not in circuit", job->TRCVvName[i]); return(E_NODEV); found:; } #ifdef HAS_PROGREP actval = job->TRCVvStart[job->TRCVnestLevel]; actdiff = job->TRCVvStart[job->TRCVnestLevel] - job->TRCVvStop[job->TRCVnestLevel]; #endif #ifdef XSPICE /* gtri - add - wbk - 12/19/90 - Add IPC stuff and anal_init and anal_type */ /* Tell the beginPlot routine what mode we're in */ g_ipc.anal_type = IPC_ANAL_DCTRCURVE; /* Tell the code models what mode we're in */ g_mif_info.circuit.anal_type = MIF_DC; g_mif_info.circuit.anal_init = MIF_TRUE; /* gtri - end - wbk */ #endif error = CKTnames(ckt, &numNames, &nameList); if (error) return(error); i = job->TRCVnestLevel; if (job->TRCVvType[i] == vcode) SPfrontEnd->IFnewUid (ckt, &varUid, NULL, "v-sweep", UID_OTHER, NULL); else if (job->TRCVvType[i] == icode) SPfrontEnd->IFnewUid (ckt, &varUid, NULL, "i-sweep", UID_OTHER, NULL); else if (job->TRCVvType[i] == TEMP_CODE) SPfrontEnd->IFnewUid (ckt, &varUid, NULL, "temp-sweep", UID_OTHER, NULL); else if (job->TRCVvType[i] == rcode) SPfrontEnd->IFnewUid (ckt, &varUid, NULL, "res-sweep", UID_OTHER, NULL); else SPfrontEnd->IFnewUid (ckt, &varUid, NULL, "?-sweep", UID_OTHER, NULL); error = SPfrontEnd->OUTpBeginPlot (ckt, ckt->CKTcurJob, ckt->CKTcurJob->JOBname, varUid, IF_REAL, numNames, nameList, IF_REAL, &plot); tfree(nameList); if (error) return(error); /* initialize CKTsoaCheck `warn' counters */ if (ckt->CKTsoaCheck) error = CKTsoaInit(); /* now have finished the initialization - can start doing hard part */ i = 0; resume: for (;;) { if (job->TRCVvType[i] == vcode) { /* voltage source */ if (SGN(job->TRCVvStep[i]) * (((VSRCinstance*)(job->TRCVvElt[i]))->VSRCdcValue - job->TRCVvStop[i]) > DBL_EPSILON * 1e+03) { i++; firstTime = 1; ckt->CKTmode = (ckt->CKTmode & MODEUIC) | MODEDCTRANCURVE | MODEINITJCT; if (i > job->TRCVnestLevel) break; goto nextstep; } } else if (job->TRCVvType[i] == icode) { /* current source */ if (SGN(job->TRCVvStep[i]) * (((ISRCinstance*)(job->TRCVvElt[i]))->ISRCdcValue - job->TRCVvStop[i]) > DBL_EPSILON * 1e+03) { i++; firstTime = 1; ckt->CKTmode = (ckt->CKTmode & MODEUIC) | MODEDCTRANCURVE | MODEINITJCT; if (i > job->TRCVnestLevel) break; goto nextstep; } } else if (job->TRCVvType[i] == rcode) { /* resistance */ if (SGN(job->TRCVvStep[i]) * (((RESinstance*)(job->TRCVvElt[i]))->RESresist - job->TRCVvStop[i]) > DBL_EPSILON * 1e+03) { i++; firstTime = 1; ckt->CKTmode = (ckt->CKTmode & MODEUIC) | MODEDCTRANCURVE | MODEINITJCT; if (i > job->TRCVnestLevel) break; goto nextstep; } } else if (job->TRCVvType[i] == TEMP_CODE) { /* temp sweep */ if (SGN(job->TRCVvStep[i]) * ((ckt->CKTtemp - CONSTCtoK) - job->TRCVvStop[i]) > DBL_EPSILON * 1e+03) { i++; firstTime = 1; ckt->CKTmode = (ckt->CKTmode & MODEUIC) | MODEDCTRANCURVE | MODEINITJCT; if (i > job->TRCVnestLevel) break; goto nextstep; } } while (--i >= 0) if (job->TRCVvType[i] == vcode) { /* voltage source */ ((VSRCinstance *)(job->TRCVvElt[i]))->VSRCdcValue = job->TRCVvStart[i]; } else if (job->TRCVvType[i] == icode) { /* current source */ ((ISRCinstance *)(job->TRCVvElt[i]))->ISRCdcValue = job->TRCVvStart[i]; } else if (job->TRCVvType[i] == TEMP_CODE) { ckt->CKTtemp = job->TRCVvStart[i] + CONSTCtoK; if (expr_w_temper) inp_evaluate_temper(); CKTtemp(ckt); } else if (job->TRCVvType[i] == rcode) { ((RESinstance *)(job->TRCVvElt[i]))->RESresist = job->TRCVvStart[i]; /* RESload() needs conductance as well */ ((RESinstance *)(job->TRCVvElt[i]))->RESconduct = 1 / (((RESinstance *)(job->TRCVvElt[i]))->RESresist); DEVices[rcode]->DEVload(job->TRCVvElt[i]->GENmodPtr, ckt); } /* Rotate state vectors. */ temp = ckt->CKTstates[ckt->CKTmaxOrder + 1]; for (j = ckt->CKTmaxOrder; j >= 0; j--) ckt->CKTstates[j + 1] = ckt->CKTstates[j]; ckt->CKTstate0 = temp; /* do operation */ #ifdef XSPICE /* gtri - begin - wbk - Do EVTop if event instances exist */ if (ckt->evt->counts.num_insts == 0) { /* If no event-driven instances, do what SPICE normally does */ #endif converged = NIiter(ckt, ckt->CKTdcTrcvMaxIter); if (converged != 0) { converged = CKTop(ckt, (ckt->CKTmode & MODEUIC) | MODEDCTRANCURVE | MODEINITJCT, (ckt->CKTmode & MODEUIC) | MODEDCTRANCURVE | MODEINITFLOAT, ckt->CKTdcMaxIter); if (converged != 0) return(converged); } #ifdef XSPICE } else { /* else do new algorithm */ /* first get the current step in the analysis */ if (job->TRCVvType[0] == vcode) { g_mif_info.circuit.evt_step = ((VSRCinstance *)(job->TRCVvElt[0]))->VSRCdcValue; } else if (job->TRCVvType[0] == icode) { g_mif_info.circuit.evt_step = ((ISRCinstance *)(job->TRCVvElt[0]))->ISRCdcValue; } else if (job->TRCVvType[0] == rcode) { g_mif_info.circuit.evt_step = ((RESinstance*)(job->TRCVvElt[0]->GENmodPtr))->RESresist; } else if (job->TRCVvType[0] == TEMP_CODE) { g_mif_info.circuit.evt_step = ckt->CKTtemp - CONSTCtoK; } /* if first time through, call EVTop immediately and save event results */ if (firstTime) { converged = EVTop(ckt, (ckt->CKTmode & MODEUIC) | MODEDCTRANCURVE | MODEINITJCT, (ckt->CKTmode & MODEUIC) | MODEDCTRANCURVE | MODEINITFLOAT, ckt->CKTdcMaxIter, MIF_TRUE); EVTdump(ckt, IPC_ANAL_DCOP, g_mif_info.circuit.evt_step); EVTop_save(ckt, MIF_FALSE, g_mif_info.circuit.evt_step); if (converged != 0) return(converged); } /* else, call NIiter first with mode = MODEINITPRED */ /* to attempt quick analog solution. Then call all hybrids and call */ /* EVTop only if event outputs have changed, or if non-converged */ else { converged = NIiter(ckt, ckt->CKTdcTrcvMaxIter); EVTcall_hybrids(ckt); if ((converged != 0) || (ckt->evt->queue.output.num_changed != 0)) { converged = EVTop(ckt, (ckt->CKTmode & MODEUIC) | MODEDCTRANCURVE | MODEINITJCT, (ckt->CKTmode & MODEUIC) | MODEDCTRANCURVE | MODEINITFLOAT, ckt->CKTdcMaxIter, MIF_FALSE); EVTdump(ckt, IPC_ANAL_DCTRCURVE, g_mif_info.circuit.evt_step); EVTop_save(ckt, MIF_FALSE, g_mif_info.circuit.evt_step); if (converged != 0) return(converged); } } } /* gtri - end - wbk - Do EVTop if event instances exist */ #endif ckt->CKTmode = (ckt->CKTmode & MODEUIC) | MODEDCTRANCURVE | MODEINITPRED; if (job->TRCVvType[0] == vcode) ckt->CKTtime = ((VSRCinstance *)(job->TRCVvElt[0]))->VSRCdcValue; else if (job->TRCVvType[0] == icode) ckt->CKTtime = ((ISRCinstance *)(job->TRCVvElt[0]))->ISRCdcValue; else if (job->TRCVvType[0] == rcode) ckt->CKTtime = ((RESinstance *)(job->TRCVvElt[0]))->RESresist; else if (job->TRCVvType[0] == TEMP_CODE) ckt->CKTtime = ckt->CKTtemp - CONSTCtoK; #ifdef XSPICE /* gtri - add - wbk - 12/19/90 - Add IPC stuff */ /* If first time through, call CKTdump to output Operating Point info */ /* for Mspice compatibility */ if (g_ipc.enabled && firstTime) { ipc_send_dcop_prefix(); CKTdump(ckt, 0.0, plot); ipc_send_dcop_suffix(); } /* gtri - end - wbk */ #endif #ifdef WANT_SENSE2 /* if (!ckt->CKTsenInfo) printf("sensitivity structure does not exist\n"); */ if (ckt->CKTsenInfo && (ckt->CKTsenInfo->SENmode & DCSEN)) { int senmode; #ifdef SENSDEBUG if (job->TRCVvType[0] == vcode) { /* voltage source */ printf("Voltage Source Value : %.5e V\n", ((VSRCinstance*) (job->TRCVvElt[0]))->VSRCdcValue); } if (job->TRCVvType[0] == icode) { /* current source */ printf("Current Source Value : %.5e A\n", ((ISRCinstance*)(job->TRCVvElt[0]))->ISRCdcValue); } if (job->TRCVvType[0] == rcode) { /* resistance */ printf("Current Resistance Value : %.5e Ohm\n", ((RESinstance*)(job->TRCVvElt[0]->GENmodPtr))->RESresist); } if (job->TRCVvType[0] == TEMP_CODE) { /* Temperature */ printf("Current Circuit Temperature : %.5e C\n", ckt->CKTtemp - CONSTCtoK); } #endif senmode = ckt->CKTsenInfo->SENmode; save = ckt->CKTmode; ckt->CKTsenInfo->SENmode = DCSEN; error = CKTsenDCtran(ckt); if (error) return(error); ckt->CKTmode = save; ckt->CKTsenInfo->SENmode = senmode; } #endif #ifdef XSPICE /* gtri - modify - wbk - 12/19/90 - Send IPC delimiters */ if (g_ipc.enabled) ipc_send_data_prefix(ckt->CKTtime); #endif CKTdump(ckt,ckt->CKTtime,plot); if (ckt->CKTsoaCheck) error = CKTsoaCheck(ckt); #ifdef XSPICE if (g_ipc.enabled) ipc_send_data_suffix(); /* gtri - end - wbk */ #endif if (firstTime) { firstTime = 0; memcpy(ckt->CKTstate1, ckt->CKTstate0, (size_t) ckt->CKTnumStates * sizeof(double)); } i = 0; nextstep:; if (job->TRCVvType[i] == vcode) { /* voltage source */ ((VSRCinstance*)(job->TRCVvElt[i]))->VSRCdcValue += job->TRCVvStep[i]; } else if (job->TRCVvType[i] == icode) { /* current source */ ((ISRCinstance*)(job->TRCVvElt[i]))->ISRCdcValue += job->TRCVvStep[i]; } else if (job->TRCVvType[i] == rcode) { /* resistance */ ((RESinstance*)(job->TRCVvElt[i]))->RESresist += job->TRCVvStep[i]; /* RESload() needs conductance as well */ ((RESinstance*)(job->TRCVvElt[i]))->RESconduct = 1 / (((RESinstance*)(job->TRCVvElt[i]))->RESresist); DEVices[rcode]->DEVload(job->TRCVvElt[i]->GENmodPtr, ckt); } else if (job->TRCVvType[i] == TEMP_CODE) { /* temperature */ ckt->CKTtemp += job->TRCVvStep[i]; if (expr_w_temper) inp_evaluate_temper(); CKTtemp(ckt); } if (SPfrontEnd->IFpauseTest()) { /* user asked us to pause, so save state */ job->TRCVnestState = i; return(E_PAUSE); } #ifdef HAS_PROGREP if (i == job->TRCVnestLevel) { actval += job->TRCVvStep[job->TRCVnestLevel]; SetAnalyse("dc", abs((int)(actval * 1000. / actdiff))); } #endif } /* all done, lets put everything back */ for (i = 0; i <= job->TRCVnestLevel; i++) if (job->TRCVvType[i] == vcode) { /* voltage source */ ((VSRCinstance*)(job->TRCVvElt[i]))->VSRCdcValue = job->TRCVvSave[i]; ((VSRCinstance*)(job->TRCVvElt[i]))->VSRCdcGiven = (job->TRCVgSave[i] != 0); } else if (job->TRCVvType[i] == icode) { /*current source */ ((ISRCinstance*)(job->TRCVvElt[i]))->ISRCdcValue = job->TRCVvSave[i]; ((ISRCinstance*)(job->TRCVvElt[i]))->ISRCdcGiven = (job->TRCVgSave[i] != 0); } else if (job->TRCVvType[i] == rcode) { /* Resistance */ ((RESinstance*)(job->TRCVvElt[i]))->RESresist = job->TRCVvSave[i]; /* RESload() needs conductance as well */ ((RESinstance*)(job->TRCVvElt[i]))->RESconduct = 1 / (((RESinstance*)(job->TRCVvElt[i]))->RESresist); ((RESinstance*)(job->TRCVvElt[i]))->RESresGiven = (job->TRCVgSave[i] != 0); DEVices[rcode]->DEVload(job->TRCVvElt[i]->GENmodPtr, ckt); } else if (job->TRCVvType[i] == TEMP_CODE) { ckt->CKTtemp = job->TRCVvSave[i]; if (expr_w_temper) inp_evaluate_temper(); CKTtemp(ckt); } SPfrontEnd->OUTendPlot (plot); return(OK); }
/* Gillespie's Source stepping * Modified 2005 - Paolo Nenzi (extracted from CKTop.c code) * * return value: * 0 -> method converged * 1 -> method failed * * Note that no path out of this code allows ckt->CKTsrcFact to be * anything but 1.00000. */ static int gillespie_src (CKTcircuit * ckt, long int firstmode, long int continuemode, int iterlim) { int converged, NumNodes, i, iters; double raise, ConvFact; double *OldRhsOld, *OldCKTstate0; CKTnode *n; ckt->CKTmode = firstmode; (*(SPfrontEnd->IFerror)) (ERR_INFO, "Starting source stepping", (IFuid *) NULL); ckt->CKTsrcFact = 0; raise = 0.001; ConvFact = 0; NumNodes = 0; for (n = ckt->CKTnodes; n; n = n->next){ NumNodes++; } OldRhsOld = (double *) MALLOC ((NumNodes + 1) * sizeof (double)); OldCKTstate0 = (double *) MALLOC ((ckt->CKTnumStates + 1) * sizeof (double)); for (n = ckt->CKTnodes; n; n = n->next) *(ckt->CKTrhsOld + n->number) = 0; for (i = 0; i < ckt->CKTnumStates; i++) *(ckt->CKTstate0 + i) = 0; /* First, try a straight solution with all sources at zero */ fprintf (stderr, "Supplies reduced to %8.4f%% ", ckt->CKTsrcFact * 100); converged = NIiter (ckt, ckt->CKTdcTrcvMaxIter); /* If this doesn't work, try gmin stepping as well for the first solution */ if (converged != 0){ fprintf (stderr, "\n"); if (ckt->CKTgshunt <= 0){ ckt->CKTdiagGmin = ckt->CKTgmin; } else { ckt->CKTdiagGmin = ckt->CKTgshunt; } for (i = 0; i < 10; i++) ckt->CKTdiagGmin *= 10; for (i = 0; i <= 10; i++){ fprintf (stderr, "Trying gmin = %12.4E ", ckt->CKTdiagGmin); ckt->CKTnoncon = 1; #ifdef XSPICE /* gtri - begin - wbk - add convergence problem reporting flags */ ckt->enh->conv_debug.last_NIiter_call = MIF_TRUE; /* gtri - end - wbk - add convergence problem reporting flags */ #endif converged = NIiter (ckt, ckt->CKTdcTrcvMaxIter); if (converged != 0){ ckt->CKTdiagGmin = ckt->CKTgshunt; (*(SPfrontEnd->IFerror)) (ERR_WARNING, "gmin step failed", (IFuid *) NULL); #ifdef XSPICE /* gtri - begin - wbk - add convergence problem reporting flags */ ckt->enh->conv_debug.last_NIiter_call = MIF_FALSE; /* gtri - end - wbk - add convergence problem reporting flags */ #endif break; } ckt->CKTdiagGmin /= 10; ckt->CKTmode = continuemode; (*(SPfrontEnd->IFerror)) (ERR_INFO, "One successful gmin step", (IFuid *) NULL); } ckt->CKTdiagGmin = ckt->CKTgshunt; } /* If we've got convergence, then try stepping up the sources */ if (converged == 0){ i = 0; for (n = ckt->CKTnodes; n; n = n->next){ OldRhsOld[i] = *(ckt->CKTrhsOld + n->number); i++; } for (i = 0; i < ckt->CKTnumStates; i++) *(OldCKTstate0 + i) = *(ckt->CKTstate0 + i); (*(SPfrontEnd->IFerror)) (ERR_INFO, "One successful source step", (IFuid *) NULL); ckt->CKTsrcFact = ConvFact + raise; } if (converged == 0) do { fprintf (stderr, "Supplies reduced to %8.4f%% ", ckt->CKTsrcFact * 100); iters = ckt->CKTstat->STATnumIter; #ifdef XSPICE /* gtri - begin - wbk - add convergence problem reporting flags */ ckt->enh->conv_debug.last_NIiter_call = MIF_TRUE; /* gtri - end - wbk - add convergence problem reporting flags */ #endif converged = NIiter (ckt, ckt->CKTdcTrcvMaxIter); iters = (ckt->CKTstat->STATnumIter) - iters; ckt->CKTmode = continuemode; if (converged == 0){ ConvFact = ckt->CKTsrcFact; i = 0; for (n = ckt->CKTnodes; n; n = n->next){ OldRhsOld[i] = *(ckt->CKTrhsOld + n->number); i++; } for (i = 0; i < ckt->CKTnumStates; i++) *(OldCKTstate0 + i) = *(ckt->CKTstate0 + i); (*(SPfrontEnd->IFerror)) (ERR_INFO, "One successful source step", (IFuid *) NULL); ckt->CKTsrcFact = ConvFact + raise; if (iters <= (ckt->CKTdcTrcvMaxIter / 4)){ raise = raise * 1.5; } if (iters > (3 * ckt->CKTdcTrcvMaxIter / 4)){ raise = raise * 0.5; } /* if (raise>0.01) raise=0.01; */ } else { if ((ckt->CKTsrcFact - ConvFact) < 1e-8) break; raise = raise / 10; if (raise > 0.01) raise = 0.01; ckt->CKTsrcFact = ConvFact; i = 0; for (n = ckt->CKTnodes; n; n = n->next){ *(ckt->CKTrhsOld + n->number) = OldRhsOld[i]; i++; } for (i = 0; i < ckt->CKTnumStates; i++) *(ckt->CKTstate0 + i) = *(OldCKTstate0 + i); } if ((ckt->CKTsrcFact) > 1) ckt->CKTsrcFact = 1; } while ((raise >= 1e-7) && (ConvFact < 1)); FREE (OldRhsOld); FREE (OldCKTstate0); ckt->CKTsrcFact = 1; if (ConvFact != 1) { ckt->CKTsrcFact = 1; ckt->CKTcurrentAnalysis = DOING_TRAN; (*(SPfrontEnd->IFerror)) (ERR_WARNING, "source stepping failed", (IFuid *) NULL); return (E_ITERLIM); } else { (*(SPfrontEnd->IFerror)) (ERR_INFO, "Source stepping completed", (IFuid *) NULL); return (0); } }
static int spice3_gmin (CKTcircuit * ckt, long int firstmode, long int continuemode, int iterlim) { int converged, i; ckt->CKTmode = firstmode; (*(SPfrontEnd->IFerror)) (ERR_INFO, "Starting gmin stepping", (IFuid *) NULL); if (ckt->CKTgshunt == 0) ckt->CKTdiagGmin = ckt->CKTgmin; else ckt->CKTdiagGmin = ckt->CKTgshunt; for (i = 0; i < ckt->CKTnumGminSteps; i++) ckt->CKTdiagGmin *= ckt->CKTgminFactor; for (i = 0; i <= ckt->CKTnumGminSteps; i++){ fprintf (stderr, "Trying gmin = %12.4E ", ckt->CKTdiagGmin); ckt->CKTnoncon = 1; converged = NIiter (ckt, ckt->CKTdcTrcvMaxIter); if (converged != 0){ ckt->CKTdiagGmin = ckt->CKTgshunt; (*(SPfrontEnd->IFerror)) (ERR_WARNING, "gmin step failed", (IFuid *) NULL); break; } ckt->CKTdiagGmin /= ckt->CKTgminFactor; ckt->CKTmode = continuemode; (*(SPfrontEnd->IFerror)) (ERR_INFO, "One successful gmin step", (IFuid *) NULL); } ckt->CKTdiagGmin = ckt->CKTgshunt; #ifdef XSPICE /* gtri - begin - wbk - add convergence problem reporting flags */ if (ckt->CKTnumSrcSteps <= 0) ckt->enh->conv_debug.last_NIiter_call = MIF_TRUE; else ckt->enh->conv_debug.last_NIiter_call = MIF_FALSE; /* gtri - end - wbk - add convergence problem reporting flags */ #endif converged = NIiter (ckt, iterlim); if (converged == 0){ (*(SPfrontEnd->IFerror)) (ERR_INFO, "gmin stepping completed", (IFuid *) NULL); #ifdef XSPICE /* gtri - begin - wbk - add convergence problem reporting flags */ ckt->enh->conv_debug.last_NIiter_call = MIF_FALSE; /* gtri - end - wbk - add convergence problem reporting flags */ #endif } else { (*(SPfrontEnd->IFerror)) (ERR_WARNING, "gmin stepping failed", (IFuid *) NULL); } return (converged); }
int CKTop (CKTcircuit * ckt, long int firstmode, long int continuemode, int iterlim) { int converged; #ifdef HAS_WINDOWS SetAnalyse("op", 0); #endif ckt->CKTmode = firstmode; if (!ckt->CKTnoOpIter){ #ifdef XSPICE /* gtri - begin - wbk - add convergence problem reporting flags */ if ((ckt->CKTnumGminSteps <= 0) && (ckt->CKTnumSrcSteps <= 0)) ckt->enh->conv_debug.last_NIiter_call = MIF_TRUE; else ckt->enh->conv_debug.last_NIiter_call = MIF_FALSE; /* gtri - end - wbk - add convergence problem reporting flags */ #endif converged = NIiter (ckt, iterlim); } else { converged = 1; /* the 'go directly to gmin stepping' option */ } if (converged != 0) { /* no convergence on the first try, so we do something else */ /* first, check if we should try gmin stepping */ if (ckt->CKTnumGminSteps >= 1){ if (ckt->CKTnumGminSteps == 1) converged = dynamic_gmin(ckt, firstmode, continuemode, iterlim); else converged = spice3_gmin(ckt, firstmode, continuemode, iterlim); } if (!converged) /* If gmin-stepping worked... move out */ return (0); /* ... otherwise try stepping sources ... * now, we'll try source stepping - we scale the sources * to 0, converge, then start stepping them up until they * are at their normal values */ if (ckt->CKTnumSrcSteps >= 1){ if (ckt->CKTnumSrcSteps == 1) converged = gillespie_src(ckt, firstmode, continuemode, iterlim); else converged = spice3_src(ckt, firstmode, continuemode, iterlim); } #ifdef XSPICE /* gtri - begin - wbk - add convergence problem reporting flags */ ckt->enh->conv_debug.last_NIiter_call = MIF_FALSE; /* gtri - end - wbk - add convergence problem reporting flags */ #endif } return (converged); }
static int dynamic_gmin (CKTcircuit * ckt, long int firstmode, long int continuemode, int iterlim) { double OldGmin, gtarget, factor; int success, failed, converged; int NumNodes, iters, i; double *OldRhsOld, *OldCKTstate0; CKTnode *n; ckt->CKTmode = firstmode; (*(SPfrontEnd->IFerror)) (ERR_INFO, "Starting dynamic gmin stepping", (IFuid *) NULL); NumNodes = 0; for (n = ckt->CKTnodes; n; n = n->next) NumNodes++; OldRhsOld = (double *) MALLOC ((NumNodes + 1) * sizeof (double)); OldCKTstate0 = (double *) MALLOC ((ckt->CKTnumStates + 1) * sizeof (double)); for (n = ckt->CKTnodes; n; n = n->next) *(ckt->CKTrhsOld + n->number) = 0; for (i = 0; i < ckt->CKTnumStates; i++) *(ckt->CKTstate0 + i) = 0; factor = ckt->CKTgminFactor; OldGmin = 1e-2; ckt->CKTdiagGmin = OldGmin / factor; gtarget = MAX (ckt->CKTgmin, ckt->CKTgshunt); success = failed = 0; while ((!success) && (!failed)){ fprintf (stderr, "Trying gmin = %12.4E ", ckt->CKTdiagGmin); ckt->CKTnoncon = 1; iters = ckt->CKTstat->STATnumIter; converged = NIiter (ckt, ckt->CKTdcTrcvMaxIter); iters = (ckt->CKTstat->STATnumIter) - iters; if (converged == 0){ ckt->CKTmode = continuemode; (*(SPfrontEnd->IFerror)) (ERR_INFO, "One successful gmin step", (IFuid *) NULL); if (ckt->CKTdiagGmin <= gtarget){ success = 1; } else { i = 0; for (n = ckt->CKTnodes; n; n = n->next){ OldRhsOld[i] = *(ckt->CKTrhsOld + n->number); i++; } for (i = 0; i < ckt->CKTnumStates; i++){ *(OldCKTstate0 + i) = *(ckt->CKTstate0 + i); } if (iters <= (ckt->CKTdcTrcvMaxIter / 4)){ factor *= sqrt (factor); if (factor > ckt->CKTgminFactor) factor = ckt->CKTgminFactor; } if (iters > (3 * ckt->CKTdcTrcvMaxIter / 4)) factor = sqrt (factor); OldGmin = ckt->CKTdiagGmin; if ((ckt->CKTdiagGmin) < (factor * gtarget)){ factor = ckt->CKTdiagGmin / gtarget; ckt->CKTdiagGmin = gtarget; } else { ckt->CKTdiagGmin /= factor; } } } else { if (factor < 1.00005){ failed = 1; (*(SPfrontEnd->IFerror)) (ERR_WARNING, "Last gmin step failed", (IFuid *) NULL); } else { (*(SPfrontEnd->IFerror)) (ERR_WARNING, "Further gmin increment", (IFuid *) NULL); factor = sqrt (sqrt (factor)); ckt->CKTdiagGmin = OldGmin / factor; i = 0; for (n = ckt->CKTnodes; n; n = n->next){ *(ckt->CKTrhsOld + n->number) = OldRhsOld[i]; i++; } for (i = 0; i < ckt->CKTnumStates; i++){ *(ckt->CKTstate0 + i) = *(OldCKTstate0 + i); } } } } ckt->CKTdiagGmin = ckt->CKTgshunt; FREE (OldRhsOld); FREE (OldCKTstate0); #ifdef XSPICE /* gtri - begin - wbk - add convergence problem reporting flags */ if (ckt->CKTnumSrcSteps <= 0) ckt->enh->conv_debug.last_NIiter_call = MIF_TRUE; else ckt->enh->conv_debug.last_NIiter_call = MIF_FALSE; /* gtri - end - wbk - add convergence problem reporting flags */ #endif converged = NIiter (ckt, iterlim); if (converged != 0){ (*(SPfrontEnd->IFerror)) (ERR_WARNING, "Dynamic gmin stepping failed", (IFuid *) NULL); } else { (*(SPfrontEnd->IFerror)) (ERR_INFO, "Dynamic gmin stepping completed", (IFuid *) NULL); #ifdef XSPICE /* gtri - begin - wbk - add convergence problem reporting flags */ ckt->enh->conv_debug.last_NIiter_call = MIF_FALSE; /* gtri - end - wbk - add convergence problem reporting flags */ #endif } return (converged); }