Esempio n. 1
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);
}
Esempio n. 2
0
/* ARGSUSED */
int
TFanal(CKTcircuit *ckt, int restart) 
                    
                    /* forced restart flag */
{
    int size;
    int insrc = 0, outsrc = 0;
    double outputs[3];
    IFvalue outdata;    /* structure for output data vector, will point to 
                         * outputs vector above */
    IFvalue refval;     /* structure for 'reference' value (not used here) */
    int error;
    int converged;
    int i;
    void *plotptr = NULL;   /* pointer to out plot */
    GENinstance *ptr = NULL;
    IFuid uids[3];
    int Itype;
    int Vtype;
    char *name;
#define tfuid (uids[0]) /* unique id for the transfer function output */
#define inuid (uids[1]) /* unique id for the transfer function input imp. */
#define outuid (uids[2]) /* unique id for the transfer function out. imp. */


    /* first, find the operating point */
    converged = CKTop(ckt,
            (ckt->CKTmode & MODEUIC) | MODEDCOP | MODEINITJCT,
            (ckt->CKTmode & MODEUIC) | MODEDCOP | MODEINITFLOAT,
            ckt->CKTdcMaxIter);

    Itype = CKTtypelook("Isource");
    Vtype = CKTtypelook("Vsource");
    if(Itype != -1) {
        error = CKTfndDev(ckt,&Itype,&ptr,
                ((TFan*)ckt->CKTcurJob)->TFinSrc, (GENmodel *)NULL, (IFuid)NULL);
        if(error ==0) {
            ((TFan*)ckt->CKTcurJob)->TFinIsI = 1;
            ((TFan*)ckt->CKTcurJob)->TFinIsV = 0;
        } else {
            ptr = NULL;
        }
    }

    if( (Vtype != -1) && (ptr==NULL) ) {
        error = CKTfndDev(ckt,&Vtype,&ptr,
                ((TFan*)ckt->CKTcurJob)->TFinSrc, (GENmodel *)NULL,
                (IFuid)NULL);
        ((TFan*)ckt->CKTcurJob)->TFinIsV = 1;
        ((TFan*)ckt->CKTcurJob)->TFinIsI = 0;
        if(error !=0) {
            (*(SPfrontEnd->IFerror))(ERR_WARNING,
                    "Transfer function source %s not in circuit",
                    &(((TFan*)ckt->CKTcurJob)->TFinSrc));
            ((TFan*)ckt->CKTcurJob)->TFinIsV = 0;
            return(E_NOTFOUND);
        }
    }

    size = SMPmatSize(ckt->CKTmatrix);
    for(i=0;i<=size;i++) {
        ckt->CKTrhs[i] = 0;
    }

    if(((TFan*)ckt->CKTcurJob)->TFinIsI) {
        ckt->CKTrhs[ptr->GENnode1] -= 1;
        ckt->CKTrhs[ptr->GENnode2] += 1;
    } else {
        insrc = CKTfndBranch(ckt,((TFan*)ckt->CKTcurJob)->TFinSrc);
        ckt->CKTrhs[insrc] += 1;
    }


    SMPsolve(ckt->CKTmatrix,ckt->CKTrhs,ckt->CKTrhsSpare);
    ckt->CKTrhs[0]=0;

    /* make a UID for the transfer function output */
    (*(SPfrontEnd->IFnewUid))(ckt,&tfuid,(IFuid)NULL,"Transfer_function",
            UID_OTHER, NULL);

    /* make a UID for the input impedance */
    (*(SPfrontEnd->IFnewUid))(ckt,&inuid,((TFan*)ckt->CKTcurJob)->TFinSrc,
            "Input_impedance", UID_OTHER, NULL);

    /* make a UID for the output impedance */
    if(((TFan*)ckt->CKTcurJob)->TFoutIsI) {
        (*(SPfrontEnd->IFnewUid))(ckt,&outuid,((TFan*)ckt->CKTcurJob)->TFoutSrc
                ,"Output_impedance", UID_OTHER, NULL);
    } else {
        name = (char *)
    MALLOC(sizeof(char)*(strlen(((TFan*)ckt->CKTcurJob)->TFoutName)+22));
        (void)sprintf(name,"output_impedance_at_%s",
                ((TFan*)ckt->CKTcurJob)->TFoutName);
        (*(SPfrontEnd->IFnewUid))(ckt,&outuid,(IFuid)NULL,
                name, UID_OTHER, NULL);
    }

    error = (*(SPfrontEnd->OUTpBeginPlot))(ckt,(void *)(ckt->CKTcurJob),
            ((TFan*)(ckt->CKTcurJob))->JOBname,(IFuid)NULL,(int)0,3,
            uids,IF_REAL,&plotptr);
    if(error) return(error);

    /*find transfer function */
    if(((TFan*)ckt->CKTcurJob)->TFoutIsV) {
        outputs[0] = ckt->CKTrhs[((TFan*)ckt->CKTcurJob)->TFoutPos->number] -
                ckt->CKTrhs[((TFan*)ckt->CKTcurJob)->TFoutNeg->number] ;
    } else {
        outsrc = CKTfndBranch(ckt,((TFan*)ckt->CKTcurJob)->TFoutSrc);
        outputs[0] = ckt->CKTrhs[outsrc];
    }

    /* now for input resistance */
    if(((TFan*)ckt->CKTcurJob)->TFinIsI) {
        outputs[1] = ckt->CKTrhs[ptr->GENnode2] -
                ckt->CKTrhs[ptr->GENnode1];
    } else {
        if(fabs(ckt->CKTrhs[insrc])<1e-20) {
            outputs[1]=1e20;
        } else {
            outputs[1] = -1/ckt->CKTrhs[insrc];
        }
    }

    if(((TFan*)ckt->CKTcurJob)->TFoutIsI && 
            (((TFan*)ckt->CKTcurJob)->TFoutSrc == 
            ((TFan*)ckt->CKTcurJob)->TFinSrc)) {
        outputs[2]=outputs[1];
        goto done;
        /* no need to compute output resistance when it is the same as 
           the input  */
    }
    /* now for output resistance */
    for(i=0;i<=size;i++) {
        ckt->CKTrhs[i] = 0;
    }
    if(((TFan*)ckt->CKTcurJob)->TFoutIsV) {
        ckt->CKTrhs[((TFan*)ckt->CKTcurJob)->TFoutPos->number] -= 1;
        ckt->CKTrhs[((TFan*)ckt->CKTcurJob)->TFoutNeg->number] += 1;
    } else {
        ckt->CKTrhs[outsrc] += 1;
    }
    SMPsolve(ckt->CKTmatrix,ckt->CKTrhs,ckt->CKTrhsSpare);
    ckt->CKTrhs[0]=0;
    if(((TFan*)ckt->CKTcurJob)->TFoutIsV) {
        outputs[2]= ckt->CKTrhs[((TFan*)ckt->CKTcurJob)->TFoutNeg->number] -
                ckt->CKTrhs[((TFan*)ckt->CKTcurJob)->TFoutPos->number];
    } else {
        outputs[2] = 1/MAX(1e-20,ckt->CKTrhs[outsrc]);
    }
done:
    outdata.v.numValue=3;
    outdata.v.vec.rVec=outputs;
    refval.rValue = 0;
    (*(SPfrontEnd->OUTpData))(plotptr,&refval,&outdata);
    (*(SPfrontEnd->OUTendPlot))(plotptr);
    return(OK);
}
Esempio n. 3
0
int sens_sens(CKTcircuit *ckt, int restart)
{
    SENS_AN	*sen_info = ((SENS_AN *) ckt->CKTcurJob);
    static int	size;
    static double	*delta_I, *delta_iI,
             *delta_I_delta_Y, *delta_iI_delta_Y;
    sgen		*sg;
    static double	freq;
    static int	nfreqs;
    static int	i;
    static SMPmatrix	*delta_Y = NULL, *Y;
    static double	step_size;
    double		*E, *iE;
    IFvalue		value, nvalue;
    double		*output_values;
    IFcomplex	*output_cvalues;
    double		delta_var;
    int		(*fn)( );
    static int	is_dc;
    int		k, j, n;
    int		num_vars, branch_eq;
    char		*sen_data;
    char		namebuf[513];
    IFuid		*output_names, freq_name;
    int		bypass;
    int		type;

#ifndef notdef
    double		*save_states[8];
#ifdef notdef
    for (sg = sgen_init(ckt, 0); sg; sgen_next(&sg)) {
        if (sg->is_instparam)
            printf("%s:%s:%s -> param %s\n",
                   DEVices[sg->dev]->DEVpublic.name,
                   sg->model->GENmodName,
                   sg->instance->GENname,
                   sg->ptable[sg->param].keyword);
        else
            printf("%s:%s:%s -> mparam %s\n",
                   DEVices[sg->dev]->DEVpublic.name,
                   sg->model->GENmodName,
                   sg->instance->GENname,
                   sg->ptable[sg->param].keyword);
    }
#endif
#ifdef ASDEBUG
    DEBUG(1)
    printf(">>> restart : %d\n", restart);
#endif

    /* get to work */

    restart = 1;
    if (restart) {

        freq = 0.0;
        is_dc = (sen_info->step_type == SENS_DC);
        nfreqs = count_steps(sen_info->step_type, sen_info->start_freq,
                             sen_info->stop_freq, sen_info->n_freq_steps,
                             &step_size);

        if (!is_dc)
            freq = sen_info->start_freq;

        error = CKTop(ckt,
                      (ckt->CKTmode & MODEUIC) | MODEDCOP | MODEINITJCT,
                      (ckt->CKTmode & MODEUIC) | MODEDCOP | MODEINITFLOAT,
                      ckt->CKTdcMaxIter);

#ifdef notdef
        ckt->CKTmode = (ckt->CKTmode & MODEUIC)
                       | MODEDCOP | MODEINITSMSIG;
#endif
        if (error)
            return error;

        size = spGetSize(ckt->CKTmatrix, 1);

        /* Create the perturbation matrix */
        /* XXX check error return, '1' is complex -- necessary?
         * only in ac */
        delta_Y = spCreate(size, !is_dc, &error);

        size += 1;

        /* Create an extra rhs */
        delta_I = NEWN(double, size);
        delta_iI = NEWN(double, size);

        delta_I_delta_Y = NEWN(double, size);
        delta_iI_delta_Y = NEWN(double, size);


        num_vars = 0;
        for (sg = sgen_init(ckt, is_dc); sg; sgen_next(&sg)) {
            num_vars += 1;
        }

        if (!num_vars)
            return OK;	/* XXXX Should be E_ something */

        k = 0;
        output_names = NEWN(IFuid, num_vars);
        for (sg = sgen_init(ckt, is_dc); sg; sgen_next(&sg)) {
            if (!sg->is_instparam) {
                sprintf(namebuf, "%s:%s",
                        sg->instance->GENname,
                        sg->ptable[sg->param].keyword);
            } else if ((sg->ptable[sg->param].dataType
                        & IF_PRINCIPAL) && sg->is_principle == 1)
            {
                sprintf(namebuf, "%s", sg->instance->GENname);
            } else {
                sprintf(namebuf, "%s_%s",
                        sg->instance->GENname,
                        sg->ptable[sg->param].keyword);
            }

            (*SPfrontEnd->IFnewUid)((GENERIC *) ckt,
                                    output_names + k, NULL,
                                    namebuf, UID_OTHER, NULL);
            k += 1;
        }

        if (is_dc) {
            type = IF_REAL;
            freq_name = NULL;
        } else {
            type = IF_COMPLEX;
            (*SPfrontEnd->IFnewUid)((GENERIC *) ckt,
                                    &freq_name, NULL,
                                    "frequency", UID_OTHER, NULL);
        }

        error = (*SPfrontEnd->OUTpBeginPlot)((GENERIC *) ckt,
                                             (GENERIC *) ckt->CKTcurJob,
                                             ckt->CKTcurJob->JOBname, freq_name, IF_REAL, num_vars,
                                             output_names, type, (GENERIC **) &sen_data);
        if (error)
            return error;

        FREE(output_names);
        if (is_dc) {
            output_values = NEWN(double, num_vars);
            output_cvalues = NULL;
        } else {
            output_values = NULL;
            output_cvalues = NEWN(IFcomplex, num_vars);
            if (sen_info->step_type != SENS_LINEAR)
                (*(SPfrontEnd->OUTattributes))((GENERIC *)sen_data,
                                               NULL, OUT_SCALE_LOG, NULL);

        }

    } else {
Esempio n. 4
0
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);
}
Esempio n. 5
0
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);
}