Beispiel #1
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*/
}
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
CKTsenComp(CKTcircuit *ckt)
{
    int size;
    int row;
    int col;
    SENstruct *info;

#ifdef SENSDEBUG
    char *rowe;
    SMPelement *elt;
#endif

#ifdef SENSDEBUG
    printf("CKTsenComp\n");
#endif

    size = SMPmatSize(ckt->CKTmatrix);
    info = ckt->CKTsenInfo;

    if ((info->SENmode == DCSEN) || (info->SENmode == TRANSEN)) {

        /*  loop throgh all the columns of RHS
            matrix - each column corresponding to a design
            parameter */

        for (col = 1; col <= info->SENparms; col++) {

            for (row = 1; row <= size; row++) {
                ckt->CKTsenRhs[row] = info->SEN_RHS[row][col];
            }

            /* solve for the sensitivity values */
            SMPsolve(ckt->CKTmatrix, ckt->CKTsenRhs, ckt->CKTrhsSpare);

            /* store the sensitivity values */
            for (row = 1; row <= size; row++) {
                info->SEN_Sap[row][col] = ckt->CKTsenRhs[row];
                info->SEN_RHS[row][col] = ckt->CKTsenRhs[row];
            }
        }

#ifdef SENSDEBUG
        printf("\n");
        printf("Sensitivity matrix :\n");

        for (row = 1; row <= size; row++) {
            rowe = CKTnodName(ckt, row);
//          if (strcmp("4", rowe) == 0) {
                for (col = 1; col <= info->SENparms; col++) {
                    printf("\t");
                    printf("Sap(%s,%d) = %.5e\t", rowe, col,
                           info->SEN_Sap[row][col]);
                }
                printf("\n\n");
//          }
        }

        printf("  RHS matrix   :\n");
        for (row = 1; row <= size; row++) {
            for (col = 1; col <= info->SENparms; col++) {
                printf("  ");
                printf("RHS(%d,%d) = %.7e ", row, col,
                       info->SEN_RHS[row][col]);
            }
            printf("\n");
        }

        printf("      Jacobian  matrix :\n");
        for (row = 1; row <= size; row++) {
            for (col = 1; col <= size; col++) {
                elt = SMPfindElt(ckt->CKTmatrix, row , col , 0);
                if (elt)
                    printf("%.7e ", elt->Real);
                else
                    printf("0.0000000e+00 ");
            }
            printf("\n");
        }
#endif

    }

    if (info->SENmode == ACSEN) {

        /*  loop throgh all the columns of RHS
            matrix - each column corresponding to a design
            parameter */

        for (col = 1; col <= info->SENparms; col++) {

            for (row = 1; row <= size; row++) {
                ckt->CKTsenRhs[row]  = info->SEN_RHS[row][col];
                ckt->CKTseniRhs[row] = info->SEN_iRHS[row][col];
            }

            /* solve for the sensitivity values ( both real and imag parts)*/
            SMPcSolve(ckt->CKTmatrix, ckt->CKTsenRhs, ckt->CKTseniRhs,
                      ckt->CKTrhsSpare, ckt->CKTirhsSpare);

            /* store the sensitivity values ( both real and imag parts)*/
            for (row = 1; row <= size; row++) {
                info->SEN_RHS[row][col]  = ckt->CKTsenRhs[row];
                info->SEN_iRHS[row][col] = ckt->CKTseniRhs[row];
            }
        }

#ifdef SENSDEBUG
        printf("\n");
        printf("CKTomega = %.7e rad/sec\t\n", ckt->CKTomega);
        printf("Sensitivity matrix :\n");
        for (row = 1; row <= size; row++) {
            rowe = CKTnodName(ckt, row);
            for (col = 1; col <= info->SENparms; col++) {
                printf("\t");
                printf("RHS(%s,%d) = %.5e", rowe, col,
                       info->SEN_RHS[row][col]);
                printf(" + j %.5e\t", info->SEN_iRHS[row][col]);
                printf("\n\n");
            }
            printf("\n");
        }

        printf("CKTomega = %.7e rad/sec\t\n", ckt->CKTomega);
        printf("  RHS matrix   :\n");
        for (row = 1; row <= size; row++) {
            for (col = 1; col <= info->SENparms; col++) {
                printf("  ");
                printf("RHS(%d,%d) = %.7e ", row, col,
                       info->SEN_RHS[row][col]);
                printf("+j %.7e ", info->SEN_iRHS[row][col]);
            }
            printf("\n");
        }

        printf("      Jacobian  matrix for AC :\n");
        for (row = 1; row <= size; row++) {
            for (col = 1; col <= size; col++) {
                elt = SMPfindElt(ckt->CKTmatrix, row , col , 0);
                if (elt) {
                    printf("%.7e ", elt->Real);
                    printf("+j%.7e\t", elt->Imag);
                } else{
                    printf("0.0000000e+00 ");
                    printf("+j0.0000000e+00\t");
                }
            }
            printf("\n\n");
        }
#endif

    }

    return OK;
}