int NIiter(CKTcircuit *ckt, int maxIter) { double startTime, *OldCKTstate0 = NULL; int error, i, j; int iterno = 0; int ipass = 0; /* some convergence issues that get resolved by increasing max iter */ if (maxIter < 100) maxIter = 100; if ((ckt->CKTmode & MODETRANOP) && (ckt->CKTmode & MODEUIC)) { SWAP(double *, ckt->CKTrhs, ckt->CKTrhsOld); error = CKTload(ckt); if (error) return(error); return(OK); }
int ACan(CKTcircuit *ckt, int restart) { double freq; double freqTol; /* tolerence parameter for finding final frequency */ double startdTime; double startsTime; double startlTime; double startcTime; double startkTime; double startTime; int error; int numNames; IFuid *nameList; /* va: tmalloc'ed list of names */ IFuid freqUid; static void *acPlot = NULL; void *plot = NULL; #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_AC; /* 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 /* start at beginning */ if(((ACAN*)ckt->CKTcurJob)->ACsaveFreq == 0 || restart) { if (((ACAN*)ckt->CKTcurJob)->ACnumberSteps < 1) ((ACAN*)ckt->CKTcurJob)->ACnumberSteps = 1; switch(((ACAN*)ckt->CKTcurJob)->ACstepType) { case DECADE: ((ACAN*)ckt->CKTcurJob)->ACfreqDelta = exp(log(10.0)/((ACAN*)ckt->CKTcurJob)->ACnumberSteps); break; case OCTAVE: ((ACAN*)ckt->CKTcurJob)->ACfreqDelta = exp(log(2.0)/((ACAN*)ckt->CKTcurJob)->ACnumberSteps); break; case LINEAR: if (((ACAN*)ckt->CKTcurJob)->ACnumberSteps-1 > 1) ((ACAN*)ckt->CKTcurJob)->ACfreqDelta = (((ACAN*)ckt->CKTcurJob)->ACstopFreq - ((ACAN*)ckt->CKTcurJob)->ACstartFreq)/ (((ACAN*)ckt->CKTcurJob)->ACnumberSteps-1); else /* Patch from: Richard McRoberts * This patch is for a rather pathological case: * a linear step with only one point */ ((ACAN*)ckt->CKTcurJob)->ACfreqDelta = 0; break; default: return(E_BADPARM); } #ifdef XSPICE /* gtri - begin - wbk - Call EVTop if event-driven instances exist */ if(ckt->evt->counts.num_insts != 0) { error = EVTop(ckt, (ckt->CKTmode & MODEUIC) | MODEDCOP | MODEINITJCT, (ckt->CKTmode & MODEUIC) | MODEDCOP | MODEINITFLOAT, ckt->CKTdcMaxIter, MIF_TRUE); EVTdump(ckt, IPC_ANAL_DCOP, 0.0); EVTop_save(ckt, MIF_TRUE, 0.0); } else #endif /* If no event-driven instances, do what SPICE normally does */ error = CKTop(ckt, (ckt->CKTmode & MODEUIC) | MODEDCOP | MODEINITJCT, (ckt->CKTmode & MODEUIC) | MODEDCOP | MODEINITFLOAT, ckt->CKTdcMaxIter); if(error){ fprintf(stdout,"\nAC operating point failed -\n"); CKTncDump(ckt); return(error); } #ifdef XSPICE /* gtri - add - wbk - 12/19/90 - Add IPC stuff */ /* Send the operating point results for Mspice compatibility */ if(g_ipc.enabled) { /* Call CKTnames to get names of nodes/branches used by BeginPlot */ /* Probably should free nameList after this block since called again... */ error = CKTnames(ckt,&numNames,&nameList); if(error) return(error); /* We have to do a beginPlot here since the data to return is * different for the DCOP than it is for the AC analysis. * Moreover the begin plot has not even been done yet at this * point... */ (*(SPfrontEnd->OUTpBeginPlot))(ckt,(void*)ckt->CKTcurJob, ckt->CKTcurJob->JOBname,(IFuid)NULL,IF_REAL,numNames,nameList, IF_REAL,&acPlot); tfree(nameList); ipc_send_dcop_prefix(); CKTdump(ckt,(double)0,acPlot); ipc_send_dcop_suffix(); (*(SPfrontEnd->OUTendPlot))(acPlot); } /* gtri - end - wbk */ #endif ckt->CKTmode = (ckt->CKTmode & MODEUIC) | MODEDCOP | MODEINITSMSIG; error = CKTload(ckt); if(error) return(error); error = CKTnames(ckt,&numNames,&nameList); if(error) return(error); if (ckt->CKTkeepOpInfo) { /* Dump operating point. */ error = (*(SPfrontEnd->OUTpBeginPlot))(ckt, (void*)ckt->CKTcurJob, "AC Operating Point", (IFuid)NULL,IF_REAL,numNames,nameList, IF_REAL,&plot); if(error) return(error); CKTdump(ckt,(double)0,plot); (*(SPfrontEnd->OUTendPlot))(plot); plot = NULL; } (*(SPfrontEnd->IFnewUid))(ckt,&freqUid,(IFuid)NULL, "frequency", UID_OTHER, NULL); error = (*(SPfrontEnd->OUTpBeginPlot))(ckt, (void*)ckt->CKTcurJob, ckt->CKTcurJob->JOBname,freqUid,IF_REAL,numNames,nameList, IF_COMPLEX,&acPlot); tfree(nameList); if(error) return(error); if (((ACAN*)ckt->CKTcurJob)->ACstepType != LINEAR) { (*(SPfrontEnd->OUTattributes))((void *)acPlot,NULL, OUT_SCALE_LOG, NULL); } freq = ((ACAN*)ckt->CKTcurJob)->ACstartFreq; } else { /* continue previous analysis */ freq = ((ACAN*)ckt->CKTcurJob)->ACsaveFreq; ((ACAN*)ckt->CKTcurJob)->ACsaveFreq = 0; /* clear the 'old' frequency */ /* fix resume? saj*/ error = (*(SPfrontEnd->OUTpBeginPlot))(ckt, (void*)ckt->CKTcurJob, ckt->CKTcurJob->JOBname,freqUid,IF_REAL,numNames,nameList, IF_COMPLEX,&acPlot); /* saj*/ } switch(((ACAN*)ckt->CKTcurJob)->ACstepType) { case DECADE: case OCTAVE: freqTol = ((ACAN*)ckt->CKTcurJob)->ACfreqDelta * ((ACAN*)ckt->CKTcurJob)->ACstopFreq * ckt->CKTreltol; break; case LINEAR: freqTol = ((ACAN*)ckt->CKTcurJob)->ACfreqDelta * ckt->CKTreltol; break; default: return(E_BADPARM); } #ifdef XSPICE /* gtri - add - wbk - 12/19/90 - Set anal_init and anal_type */ g_mif_info.circuit.anal_init = MIF_TRUE; /* Tell the code models what mode we're in */ g_mif_info.circuit.anal_type = MIF_AC; /* gtri - end - wbk */ #endif startTime = SPfrontEnd->IFseconds(); startdTime = ckt->CKTstat->STATdecompTime; startsTime = ckt->CKTstat->STATsolveTime; startlTime = ckt->CKTstat->STATloadTime; startcTime = ckt->CKTstat->STATcombineTime; startkTime = ckt->CKTstat->STATsyncTime; /* main loop through all scheduled frequencies */ while(freq <= ((ACAN*)ckt->CKTcurJob)->ACstopFreq+freqTol) { if( (*(SPfrontEnd->IFpauseTest))() ) { /* user asked us to pause via an interrupt */ ((ACAN*)ckt->CKTcurJob)->ACsaveFreq = freq; return(E_PAUSE); } ckt->CKTomega = 2.0 * M_PI *freq; /* Update opertating point, if variable 'hertz' is given */ if (ckt->CKTvarHertz) { #ifdef XSPICE /* Call EVTop if event-driven instances exist */ if(ckt->evt->counts.num_insts != 0) { error = EVTop(ckt, (ckt->CKTmode & MODEUIC) | MODEDCOP | MODEINITJCT, (ckt->CKTmode & MODEUIC) | MODEDCOP | MODEINITFLOAT, ckt->CKTdcMaxIter, MIF_TRUE); EVTdump(ckt, IPC_ANAL_DCOP, 0.0); EVTop_save(ckt, MIF_TRUE, 0.0); } else #endif // If no event-driven instances, do what SPICE normally does error = CKTop(ckt, (ckt->CKTmode & MODEUIC) | MODEDCOP | MODEINITJCT, (ckt->CKTmode & MODEUIC) | MODEDCOP | MODEINITFLOAT, ckt->CKTdcMaxIter); if(error){ fprintf(stdout,"\nAC operating point failed -\n"); CKTncDump(ckt); return(error); } ckt->CKTmode = (ckt->CKTmode & MODEUIC) | MODEDCOP | MODEINITSMSIG; error = CKTload(ckt); if(error) return(error); } ckt->CKTmode = (ckt->CKTmode&MODEUIC) | MODEAC; error = NIacIter(ckt); if (error) { ckt->CKTcurrentAnalysis = DOING_AC; ckt->CKTstat->STATacTime += SPfrontEnd->IFseconds() - startTime; ckt->CKTstat->STATacDecompTime += ckt->CKTstat->STATdecompTime - startdTime; ckt->CKTstat->STATacSolveTime += ckt->CKTstat->STATsolveTime - startsTime; ckt->CKTstat->STATacLoadTime += ckt->CKTstat->STATloadTime - startlTime; ckt->CKTstat->STATacCombTime += ckt->CKTstat->STATcombineTime - startcTime; ckt->CKTstat->STATacSyncTime += ckt->CKTstat->STATsyncTime - startkTime; return(error); } #ifdef WANT_SENSE2 if(ckt->CKTsenInfo && (ckt->CKTsenInfo->SENmode&ACSEN) ){ save = ckt->CKTmode; ckt->CKTmode=(ckt->CKTmode&MODEUIC)|MODEDCOP|MODEINITSMSIG; save1 = ckt->CKTsenInfo->SENmode; ckt->CKTsenInfo->SENmode = ACSEN; if(freq == ((ACAN*)ckt->CKTcurJob)->ACstartFreq){ ckt->CKTsenInfo->SENacpertflag = 1; } else{ ckt->CKTsenInfo->SENacpertflag = 0; } if(error = CKTsenAC(ckt)) return (error); ckt->CKTmode = save; ckt->CKTsenInfo->SENmode = save1; } #endif #ifdef XSPICE /* gtri - modify - wbk - 12/19/90 - Send IPC stuff */ if(g_ipc.enabled) ipc_send_data_prefix(freq); error = CKTacDump(ckt,freq,acPlot); if(g_ipc.enabled) ipc_send_data_suffix(); /* gtri - modify - wbk - 12/19/90 - Send IPC stuff */ #else error = CKTacDump(ckt,freq,acPlot); #endif if (error) { ckt->CKTcurrentAnalysis = DOING_AC; ckt->CKTstat->STATacTime += SPfrontEnd->IFseconds() - startTime; ckt->CKTstat->STATacDecompTime += ckt->CKTstat->STATdecompTime - startdTime; ckt->CKTstat->STATacSolveTime += ckt->CKTstat->STATsolveTime - startsTime; ckt->CKTstat->STATacLoadTime += ckt->CKTstat->STATloadTime - startlTime; ckt->CKTstat->STATacCombTime += ckt->CKTstat->STATcombineTime - startcTime; ckt->CKTstat->STATacSyncTime += ckt->CKTstat->STATsyncTime - startkTime; return(error); } /* increment frequency */ switch(((ACAN*)ckt->CKTcurJob)->ACstepType) { case DECADE: case OCTAVE: /* inserted again 14.12.2001 */ #ifdef HAS_WINDOWS { double endfreq = ((ACAN*)ckt->CKTcurJob)->ACstopFreq; double startfreq = ((ACAN*)ckt->CKTcurJob)->ACstartFreq; endfreq = log(endfreq); if (startfreq == 0.0) startfreq = 1e-12; startfreq = log(startfreq); if (freq > 0.0) SetAnalyse( "ac", (log(freq)-startfreq) * 1000.0 / (endfreq-startfreq)); } #endif freq *= ((ACAN*)ckt->CKTcurJob)->ACfreqDelta; if(((ACAN*)ckt->CKTcurJob)->ACfreqDelta==1) goto endsweep; break; case LINEAR: #ifdef HAS_WINDOWS { double endfreq = ((ACAN*)ckt->CKTcurJob)->ACstopFreq; double startfreq = ((ACAN*)ckt->CKTcurJob)->ACstartFreq; SetAnalyse( "ac", (freq - startfreq)* 1000.0 / (endfreq-startfreq)); } #endif freq += ((ACAN*)ckt->CKTcurJob)->ACfreqDelta; if(((ACAN*)ckt->CKTcurJob)->ACfreqDelta==0) goto endsweep; break; default: return(E_INTERN); } } endsweep: (*(SPfrontEnd->OUTendPlot))(acPlot); acPlot = NULL; ckt->CKTcurrentAnalysis = 0; ckt->CKTstat->STATacTime += SPfrontEnd->IFseconds() - startTime; ckt->CKTstat->STATacDecompTime += ckt->CKTstat->STATdecompTime - startdTime; ckt->CKTstat->STATacSolveTime += ckt->CKTstat->STATsolveTime - startsTime; ckt->CKTstat->STATacLoadTime += ckt->CKTstat->STATloadTime - startlTime; ckt->CKTstat->STATacCombTime += ckt->CKTstat->STATcombineTime - startcTime; ckt->CKTstat->STATacSyncTime += ckt->CKTstat->STATsyncTime - startkTime; return(0); }
///<param name = "*ckt"> Circuit to operate on </param> ///<param name = "maxIter"> Maximum number of iterations to attempt </param> int NIiter(register CKTcircuit *ckt, int maxIter) { int iterno; int ipass; int error; int i, j; /* temporaries for finding error location */ char *message; /* temporary message buffer */ double *temp; double startTime; static char *msg = "Too many iterations without convergence"; iterno = 0; ipass = 0; if ((ckt->CKTmode & MODETRANOP) && (ckt->CKTmode & MODEUIC)) { temp = ckt->CKTrhsOld; ckt->CKTrhsOld = ckt->CKTrhs; ckt->CKTrhs = temp; error = CKTload(ckt); if (error) { return(error); } return(OK); } #ifdef HAS_SENSE2 if (ckt->CKTsenInfo) { error = NIsenReinit(ckt); if (error) return(error); } #endif if (ckt->CKTniState & NIUNINITIALIZED) { error = NIreinit(ckt); if (error) { #ifdef STEPDEBUG printf("re-init returned error \n"); #endif return(error); } } while (1) { ckt->CKTnoncon = 0; #ifdef NEWPRED if (!(ckt->CKTmode & MODEINITPRED)) { #else /* NEWPRED */ if (1) { /* } */ #endif /* NEWPRED */ error = CKTload(ckt); /*printf("loaded, noncon is %d\n",ckt->CKTnoncon);*/ /*fflush(stdout);*/ iterno++; if (error) { ckt->CKTstat->STATnumIter += iterno; #ifdef STEPDEBUG printf("load returned error \n"); #endif return(error); } /*printf("after loading, before solving\n");*/ /*CKTdump(ckt);*/ if (!(ckt->CKTniState & NIDIDPREORDER)) { error = SMPpreOrder(ckt->CKTmatrix); if (error) { ckt->CKTstat->STATnumIter += iterno; #ifdef STEPDEBUG printf("pre-order returned error \n"); #endif return(error); /* badly formed matrix */ } ckt->CKTniState |= NIDIDPREORDER; } if ((ckt->CKTmode & MODEINITJCT) || ((ckt->CKTmode & MODEINITTRAN) && (iterno == 1))) { ckt->CKTniState |= NISHOULDREORDER; } if (ckt->CKTniState & NISHOULDREORDER) { startTime = (*(SPfrontEnd->IFseconds))(); error = SMPreorder(ckt->CKTmatrix, ckt->CKTpivotAbsTol, ckt->CKTpivotRelTol, ckt->CKTdiagGmin); ckt->CKTstat->STATreorderTime += (*(SPfrontEnd->IFseconds))() - startTime; if (error) { /* new feature - we can now find out something about what is * wrong - so we ask for the troublesome entry */ SMPgetError(ckt->CKTmatrix, &i, &j); message = (char *)MALLOC(1000); /* should be enough */ (void)sprintf(message, "singular matrix: check nodes %s and %s\n", NODENAME(ckt, i), NODENAME(ckt, j)); (*(SPfrontEnd->IFerror))(ERR_WARNING, message, (IFuid *)NULL); FREE(message); ckt->CKTstat->STATnumIter += iterno; #ifdef STEPDEBUG printf("reorder returned error \n"); #endif return(error); /* can't handle these errors - pass up! */ } ckt->CKTniState &= ~NISHOULDREORDER; } else { startTime = (*(SPfrontEnd->IFseconds))(); error = SMPluFac(ckt->CKTmatrix, ckt->CKTpivotAbsTol, ckt->CKTdiagGmin); ckt->CKTstat->STATdecompTime += (*(SPfrontEnd->IFseconds))() - startTime; if (error) { if (error == E_SINGULAR) { ckt->CKTniState |= NISHOULDREORDER; DEBUGMSG(" forced reordering....\n"); continue; } /*CKTload(ckt);*/ /*SMPprint(ckt->CKTmatrix,stdout);*/ /* seems to be singular - pass the bad news up */ ckt->CKTstat->STATnumIter += iterno; #ifdef STEPDEBUG printf("lufac returned error \n"); #endif return(error); } } startTime = (*(SPfrontEnd->IFseconds))(); SMPsolve(ckt->CKTmatrix, ckt->CKTrhs, ckt->CKTrhsSpare); ckt->CKTstat->STATsolveTime += (*(SPfrontEnd->IFseconds))() - startTime; #ifdef STEPDEBUG /*XXXX*/ if (*ckt->CKTrhs != 0.0) printf("NIiter: CKTrhs[0] = %g\n", *ckt->CKTrhs); if (*ckt->CKTrhsSpare != 0.0) printf("NIiter: CKTrhsSpare[0] = %g\n", *ckt->CKTrhsSpare); if (*ckt->CKTrhsOld != 0.0) printf("NIiter: CKTrhsOld[0] = %g\n", *ckt->CKTrhsOld); /*XXXX*/ #endif *ckt->CKTrhs = 0; *ckt->CKTrhsSpare = 0; *ckt->CKTrhsOld = 0; if (iterno > maxIter) { /*printf("too many iterations without convergence: %d iter's\n", iterno);*/ ckt->CKTstat->STATnumIter += iterno; errMsg = MALLOC(strlen(msg) + 1); strcpy(errMsg, msg); #ifdef STEPDEBUG printf("iterlim exceeded \n"); #endif return(E_ITERLIM); } if (ckt->CKTnoncon == 0 && iterno != 1) { ckt->CKTnoncon = NIconvTest(ckt); } else { ckt->CKTnoncon = 1; } } if (ckt->CKTmode & MODEINITFLOAT) { if ((ckt->CKTmode & MODEDC) && (ckt->CKThadNodeset)) { if (ipass) { ckt->CKTnoncon = ipass; } ipass = 0; } if (ckt->CKTnoncon == 0) { ckt->CKTstat->STATnumIter += iterno; return(OK); } } else if (ckt->CKTmode & MODEINITJCT) { ckt->CKTmode = (ckt->CKTmode&(~INITF)) | MODEINITFIX; ckt->CKTniState |= NISHOULDREORDER; } else if (ckt->CKTmode & MODEINITFIX) { if (ckt->CKTnoncon == 0) ckt->CKTmode = (ckt->CKTmode&(~INITF)) | MODEINITFLOAT; ipass = 1; } else if (ckt->CKTmode & MODEINITSMSIG) { ckt->CKTmode = (ckt->CKTmode&(~INITF)) | MODEINITFLOAT; } else if (ckt->CKTmode & MODEINITTRAN) { if (iterno <= 1) ckt->CKTniState |= NISHOULDREORDER; ckt->CKTmode = (ckt->CKTmode&(~INITF)) | MODEINITFLOAT; } else if (ckt->CKTmode & MODEINITPRED) { ckt->CKTmode = (ckt->CKTmode&(~INITF)) | MODEINITFLOAT; } else { ckt->CKTstat->STATnumIter += iterno; #ifdef STEPDEBUG printf("bad initf state \n"); #endif return(E_INTERN); /* impossible - no such INITF flag! */ } /* build up the lvnim1 array from the lvn array */ temp = ckt->CKTrhsOld; ckt->CKTrhsOld = ckt->CKTrhs; ckt->CKTrhs = temp; /*printf("after loading, after solving\n");*/ /*CKTdump(ckt);*/ } /*NOTREACHED*/ }
int NOISEan (CKTcircuit *ckt, int restart) { static Ndata *data; /* va, must be static, for continuation of * interrupted(Ctrl-C), longer lasting noise * analysis */ double realVal; double imagVal; int error; int posOutNode; int negOutNode; int step; IFuid freqUid; double freqTol; /* tolerence parameter for finding final frequency; hack */ int i, src_type; NOISEAN *job = (NOISEAN *) ckt->CKTcurJob; GENinstance *inst = CKTfndDev(ckt, job->input); posOutNode = (job->output) -> number; negOutNode = (job->outputRef) -> number; /* see if the source specified is AC */ { //bool ac_given = FALSE; int ac_given = FALSE; if (!inst || inst->GENmodPtr->GENmodType < 0) { SPfrontEnd->IFerrorf (ERR_WARNING, "Noise input source %s not in circuit", job->input); return E_NOTFOUND; } if (inst->GENmodPtr->GENmodType == CKTtypelook("Vsource")) { ac_given = ((VSRCinstance *)inst) -> VSRCacGiven; src_type = SV_VOLTAGE; } else if(inst->GENmodPtr->GENmodType == CKTtypelook("Isource")) { ac_given = ((ISRCinstance *)inst) -> ISRCacGiven; src_type = SV_CURRENT; } else { SPfrontEnd->IFerrorf (ERR_WARNING, "Noise input source %s is not of proper type", job->input); return E_NOTFOUND; } if (!ac_given) { SPfrontEnd->IFerrorf (ERR_WARNING, "Noise input source %s has no AC value", job->input); return E_NOACINPUT; } } if ( (job->NsavFstp == 0.0) || restart) { /* va, NsavFstp is double */ switch (job->NstpType) { case DECADE: job->NfreqDelta = exp(log(10.0)/ job->NnumSteps); break; case OCTAVE: job->NfreqDelta = exp(log(2.0)/ job->NnumSteps); break; case LINEAR: job->NfreqDelta = (job->NstopFreq - job->NstartFreq)/ (job->NnumSteps - 1); break; default: return(E_BADPARM); } /* error = DCop(ckt); */ error = CKTop(ckt, (ckt->CKTmode & MODEUIC) | MODEDCOP | MODEINITJCT, (ckt->CKTmode & MODEUIC) | MODEDCOP | MODEINITFLOAT, ckt->CKTdcMaxIter); if (error) return(error); /* Patch to noisean.c by Richard D. McRoberts. */ ckt->CKTmode = (ckt->CKTmode & MODEUIC) | MODEDCOP | MODEINITSMSIG; error = CKTload(ckt); if(error) return(error); data = TMALLOC(Ndata, 1); step = 0; data->freq = job->NstartFreq; data->outNoiz = 0.0; data->inNoise = 0.0; data->squared = cp_getvar("sqrnoise", CP_BOOL, NULL) ? 1 : 0; /* the current front-end needs the namelist to be fully declared before an OUTpBeginplot */ SPfrontEnd->IFnewUid (ckt, &freqUid, NULL, "frequency", UID_OTHER, NULL); data->numPlots = 0; /* we don't have any plots yet */ error = CKTnoise(ckt,N_DENS,N_OPEN,data); if (error) return(error); /* * all names in the namelist have been declared. now start the * plot */ if (src_type == SV_VOLTAGE) fixme_inoise_type = data->squared ? SV_SQR_VOLTAGE_DENSITY : SV_VOLTAGE_DENSITY; else fixme_inoise_type = data->squared ? SV_SQR_CURRENT_DENSITY : SV_CURRENT_DENSITY; fixme_onoise_type = data->squared ? SV_SQR_VOLTAGE_DENSITY : SV_VOLTAGE_DENSITY; if (!data->squared) for (i = 0; i < data->numPlots; i++) data->squared_value[i] = ciprefix("inoise", data->namelist[i]) || ciprefix("onoise", data->namelist[i]); error = SPfrontEnd->OUTpBeginPlot (ckt, ckt->CKTcurJob, data->squared ? "Noise Spectral Density Curves - (V^2 or A^2)/Hz" : "Noise Spectral Density Curves", freqUid, IF_REAL, data->numPlots, data->namelist, IF_REAL, &(data->NplotPtr)); if (error) return(error); if (job->NstpType != LINEAR) { SPfrontEnd->OUTattributes (data->NplotPtr, NULL, OUT_SCALE_LOG, NULL); } } else { /* we must have paused before. pick up where we left off */ step = (int)(job->NsavFstp); switch (job->NstpType) { case DECADE: case OCTAVE: data->freq = job->NstartFreq * exp (step * log (job->NfreqDelta)); break; case LINEAR: data->freq = job->NstartFreq + step * job->NfreqDelta; break; default: return(E_BADPARM); } job->NsavFstp = 0; data->outNoiz = job->NsavOnoise; data->inNoise = job->NsavInoise; /* saj resume rawfile fix*/ error = SPfrontEnd->OUTpBeginPlot (NULL, NULL, NULL, NULL, 0, 666, NULL, 666, &(data->NplotPtr)); /*saj*/ } switch (job->NstpType) { case DECADE: case OCTAVE: freqTol = job->NfreqDelta * job->NstopFreq * ckt->CKTreltol; break; case LINEAR: freqTol = job->NfreqDelta * ckt->CKTreltol; break; default: return(E_BADPARM); } data->lstFreq = data->freq; /* do the noise analysis over all frequencies */ while (data->freq <= job->NstopFreq + freqTol) { if(SPfrontEnd->IFpauseTest()) { job->NsavFstp = step; /* save our results */ job->NsavOnoise = data->outNoiz; /* up until now */ job->NsavInoise = data->inNoise; return (E_PAUSE); } ckt->CKTomega = 2.0 * M_PI * data->freq; ckt->CKTmode = (ckt->CKTmode & MODEUIC) | MODEAC | MODEACNOISE; ckt->noise_input = inst; /* * solve the original AC system to get the transfer * function between the input and output */ NIacIter(ckt); realVal = ckt->CKTrhsOld [posOutNode] - ckt->CKTrhsOld [negOutNode]; imagVal = ckt->CKTirhsOld [posOutNode] - ckt->CKTirhsOld [negOutNode]; data->GainSqInv = 1.0 / MAX(((realVal*realVal) + (imagVal*imagVal)),N_MINGAIN); data->lnGainInv = log(data->GainSqInv); /* set up a block of "common" data so we don't have to * recalculate it for every device */ data->delFreq = data->freq - data->lstFreq; data->lnFreq = log(MAX(data->freq,N_MINLOG)); data->lnLastFreq = log(MAX(data->lstFreq,N_MINLOG)); data->delLnFreq = data->lnFreq - data->lnLastFreq; if ((job->NStpsSm != 0) && ((step % (job->NStpsSm)) == 0)) { data->prtSummary = TRUE; } else { data->prtSummary = FALSE; } /* data->outNumber = 1; */ data->outNumber = 0; /* the frequency will NOT be stored in array[0] as before; instead, * it will be given in refVal.rValue (see later) */ NInzIter(ckt,posOutNode,negOutNode); /* solve the adjoint system */ /* now we use the adjoint system to calculate the noise * contributions of each generator in the circuit */ error = CKTnoise(ckt,N_DENS,N_CALC,data); if (error) return(error); data->lstFreq = data->freq; /* update the frequency */ switch (job->NstpType) { case DECADE: case OCTAVE: data->freq *= job->NfreqDelta; break; case LINEAR: data->freq += job->NfreqDelta; break; default: return(E_INTERN); } step++; } error = CKTnoise(ckt,N_DENS,N_CLOSE,data); if (error) return(error); data->numPlots = 0; data->outNumber = 0; if (job->NstartFreq != job->NstopFreq) { error = CKTnoise(ckt,INT_NOIZ,N_OPEN,data); if (error) return(error); if (src_type == SV_VOLTAGE) fixme_inoise_type = data->squared ? SV_SQR_VOLTAGE : SV_VOLTAGE; else fixme_inoise_type = data->squared ? SV_SQR_CURRENT : SV_CURRENT; fixme_onoise_type = data->squared ? SV_SQR_VOLTAGE : SV_VOLTAGE; if (!data->squared) for (i = 0; i < data->numPlots; i++) data->squared_value[i] = ciprefix("inoise", data->namelist[i]) || ciprefix("onoise", data->namelist[i]); SPfrontEnd->OUTpBeginPlot (ckt, ckt->CKTcurJob, data->squared ? "Integrated Noise - V^2 or A^2" : "Integrated Noise", NULL, 0, data->numPlots, data->namelist, IF_REAL, &(data->NplotPtr)); error = CKTnoise(ckt,INT_NOIZ,N_CALC,data); if (error) return(error); error = CKTnoise(ckt,INT_NOIZ,N_CLOSE,data); if (error) return(error); } FREE(data); return(OK); }