Beispiel #1
0
/*ARGSUSED*/
int
MUTsetup(SMPmatrix *matrix, GENmodel *inModel, CKTcircuit *ckt, int *states)
{
    MUTmodel *model = (MUTmodel*)inModel;
    MUTinstance *here;
    int ktype;

    NG_IGNORE(states);

    /*  loop through all the inductor models */
    for( ; model != NULL; model = model->MUTnextModel ) {

        /* loop through all the instances of the model */
        for (here = model->MUTinstances; here != NULL ;
                here=here->MUTnextInstance) {
            
            ktype = CKTtypelook("Inductor");
            if(ktype <= 0) {
                SPfrontEnd->IFerror (ERR_PANIC,
                        "mutual inductor, but inductors not available!",
                        NULL);
                return(E_INTERN);
            }

            if (!here->MUTind1)
                here->MUTind1 = (INDinstance *) CKTfndDev(ckt, here->MUTindName1);
            if (!here->MUTind1) {
                IFuid namarray[2];
                namarray[0]=here->MUTname;
                namarray[1]=here->MUTindName1;
                SPfrontEnd->IFerror (ERR_WARNING,
                    "%s: coupling to non-existant inductor %s.",
                    namarray);
            }
            if (!here->MUTind2)
                here->MUTind2 = (INDinstance *) CKTfndDev(ckt, here->MUTindName2);
            if (!here->MUTind2) {
                IFuid namarray[2];
                namarray[0]=here->MUTname;
                namarray[1]=here->MUTindName2;
                SPfrontEnd->IFerror (ERR_WARNING,
                    "%s: coupling to non-existant inductor %s.",
                    namarray);
            }


/* macro to make elements with built in test for out of memory */
#define TSTALLOC(ptr,first,second) \
do { if((here->ptr = SMPmakeElt(matrix, here->first, here->second)) == NULL){\
    return(E_NOMEM);\
} } while(0)

            TSTALLOC(MUTbr1br2,MUTind1->INDbrEq,MUTind2->INDbrEq);
            TSTALLOC(MUTbr2br1,MUTind2->INDbrEq,MUTind1->INDbrEq);
        }
    }
    return(OK);
}
Beispiel #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);
}
Beispiel #3
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);
}