示例#1
0
int
CKTaccept(CKTcircuit *ckt)
{
    int i;
    int error;
    SPICEdev **devs;

#ifdef PREDICTOR
    double *temp;
    int size;
#endif

    devs = devices();
    for (i = 0; i < DEVmaxnum; i++) {
        if ( devs[i] && devs[i]->DEVaccept && ckt->CKThead[i] ) {
            error = devs[i]->DEVaccept (ckt, ckt->CKThead[i]);
            if (error)
		return(error);
        }
    }
#ifdef PREDICTOR
    /* now, move the sols vectors around */
    temp = ckt->CKTsols[7];
    for ( i=7;i>0;i--) {
        ckt->CKTsols[i] = ckt->CKTsols[i-1];
    }
    ckt->CKTsols[0]=temp;
    size = SMPmatSize(ckt->CKTmatrix);
    for(i=0;i<=size;i++) {
        ckt->CKTsols[0][i]=ckt->CKTrhs[i];
    }
#endif /* PREDICTOR */
    return(OK);
}
示例#2
0
文件: acan.c 项目: Anastien/ngspice
int
CKTacLoad(CKTcircuit *ckt)
{
    int i;
    int size;
    int error;
    double startTime;

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

    for (i=0;i<DEVmaxnum;i++) {
        if ( DEVices[i] && DEVices[i]->DEVacLoad && ckt->CKThead[i] ) {
            error = DEVices[i]->DEVacLoad (ckt->CKThead[i], ckt);
            if(error) return(error);
        }
    }
    
#ifdef XSPICE
   /* gtri - begin - Put resistors to ground at all nodes. */
    /* Value of resistor is set by new "rshunt" option.     */

    if(ckt->enh->rshunt_data.enabled) {
       for(i = 0; i < ckt->enh->rshunt_data.num_nodes; i++) {
          *(ckt->enh->rshunt_data.diag[i]) +=
                               ckt->enh->rshunt_data.gshunt;
       }
    }

    /* gtri - end - Put resistors to ground at all nodes */



    /* gtri - add - wbk - 11/26/90 - reset the MIF init flags */

    /* init is set by CKTinit and should be true only for first load call */
    g_mif_info.circuit.init = MIF_FALSE;

    /* anal_init is set by CKTdoJob and is true for first call */
    /* of a particular analysis type */
    g_mif_info.circuit.anal_init = MIF_FALSE;

    /* gtri - end - wbk - 11/26/90 */
#endif

    
    ckt->CKTstat->STATloadTime += SPfrontEnd->IFseconds() - startTime;
    return(OK);
}
示例#3
0
int
NIsenReinit(CKTcircuit *ckt)
{
    int size;
    int senparms;
    int i;

#ifdef SENSDEBUG
    printf("NIsenReinit \n");
    printf("senflag = %d\n",ckt->CKTsenInfo->SENinitflag);
    if(ckt->CKTniState & NIUNINITIALIZED) {
        printf("circuit uninitialized\n");
    }
    else{
        printf("circuit already initialized\n");
    }
#endif /* SENSDEBUG */
    size = SMPmatSize(ckt->CKTmatrix);
    if(ckt->CKTsenInfo->SENinitflag){
        if(!(ckt->CKTniState & NIUNINITIALIZED)) {
#ifdef SENSDEBUG
            printf("NIsenReinit1\n");
#endif /* SENSDEBUG */
            if(ckt->CKTrhsOp) FREE(ckt->CKTrhsOp);
            if(ckt->CKTsenRhs) FREE(ckt->CKTsenRhs);
            if(ckt->CKTseniRhs) FREE(ckt->CKTseniRhs);
        }
        senparms = ckt->CKTsenInfo->SENparms;
#ifdef SENSDEBUG
        printf("NIsenReinit2\n");
#endif /* SENSDEBUG */
        /*
                   CKALLOC(CKTsenInfo->SEN_parmVal,senparms+1,double);
            */
        ckt->CKTsenInfo->SENsize = size;
        CKALLOC(CKTrhsOp,size+1,double);
        CKALLOC(CKTsenRhs,size+1,double);
        CKALLOC(CKTseniRhs,size+1,double);
        CKALLOC(CKTsenInfo->SEN_Sap,size+1,double*);
        CKALLOC(CKTsenInfo->SEN_RHS,size+1,double*);
        CKALLOC(CKTsenInfo->SEN_iRHS,size+1,double*);
        for(i=0;i<=(size);i++){
            CKALLOC(CKTsenInfo->SEN_Sap[i],senparms+1,double);
            CKALLOC(CKTsenInfo->SEN_RHS[i],senparms+1,double);
            CKALLOC(CKTsenInfo->SEN_iRHS[i],senparms+1,double);
        }
#ifdef SENSDEBUG
        printf("NIsenReinit3\n");
#endif /* SENSDEBUG */
        ckt->CKTsenInfo->SENinitflag = OFF;
    }
    return(0);
}
示例#4
0
int
CKTic(CKTcircuit *ckt)
{
    int error;
    int size;
    int i;
    CKTnode *node;

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

    for(node = ckt->CKTnodes;node != NULL; node = node->next) {
        if(node->nsGiven) {
            node->ptr = SMPmakeElt(ckt->CKTmatrix,node->number,node->number);
            if(node->ptr == (double *)NULL) return(E_NOMEM);
            ckt->CKThadNodeset = 1;
            *(ckt->CKTrhs+node->number) = node->nodeset;
        }
        if(node->icGiven) {
            if(! ( node->ptr)) {
                node->ptr = SMPmakeElt(ckt->CKTmatrix,node->number,
                        node->number);
                if(node->ptr == (double *)NULL) return(E_NOMEM);
            }
            *(ckt->CKTrhs+node->number) = node->ic;
        }
    }

    if(ckt->CKTmode & MODEUIC) {
        for (i=0;i<DEVmaxnum;i++) {
            if( DEVices[i] && ((*DEVices[i]).DEVsetic != NULL) && (ckt->CKThead[i] != NULL) ){
                error = (*((*DEVices[i]).DEVsetic))(ckt->CKThead[i],ckt);
                if(error) return(error);
            }
        }
    }

    return(OK);
}
示例#5
0
文件: cktic.c 项目: Anastien/ngspice
int
CKTic(CKTcircuit *ckt)
{
    int error;
    int size;
    int i;
    CKTnode *node;

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

    for(node = ckt->CKTnodes;node != NULL; node = node->next) {
        if(node->nsGiven) {
            node->ptr = SMPmakeElt(ckt->CKTmatrix,node->number,node->number);
            if(node->ptr == NULL) return(E_NOMEM);
            ckt->CKThadNodeset = 1;
            ckt->CKTrhs[node->number] = node->nodeset;
        }
        if(node->icGiven) {
            if(! ( node->ptr)) {
                node->ptr = SMPmakeElt(ckt->CKTmatrix,node->number,
                        node->number);
                if(node->ptr == NULL) return(E_NOMEM);
            }
            ckt->CKTrhs[node->number] = node->ic;
        }
    }

    if(ckt->CKTmode & MODEUIC) {
        for (i=0;i<DEVmaxnum;i++) {
            if( DEVices[i] && DEVices[i]->DEVsetic && ckt->CKThead[i] ) {
                error = DEVices[i]->DEVsetic (ckt->CKThead[i], ckt);
                if(error) return(error);
            }
        }
    }

    return(OK);
}
示例#6
0
int
CKTpzLoad(CKTcircuit *ckt, SPcomplex *s)
{
    PZAN *job = (PZAN *) ckt->CKTcurJob;

    int error;
    int i;

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

    SMPcClear(ckt->CKTmatrix);
    for (i = 0; i < DEVmaxnum; i++) {
        if (DEVices[i] && DEVices[i]->DEVpzLoad != NULL && ckt->CKThead[i] != NULL) {
            error = DEVices[i]->DEVpzLoad (ckt->CKThead[i], ckt, s);
            if(error) return(error);
        }
    }

    if (job->PZbalance_col && job->PZsolution_col) {
	SMPcAddCol(ckt->CKTmatrix, job->PZbalance_col, job->PZsolution_col);
	/* AC sources ?? XXX */
    }

    if (job->PZsolution_col) {
	SMPcZeroCol(ckt->CKTmatrix, job->PZsolution_col);
    }

    /* Driving function (current source) */
    if (job->PZdrive_pptr)
	*job->PZdrive_pptr = 1.0;
    if (job->PZdrive_nptr)
	*job->PZdrive_nptr = -1.0;

    return(OK);
}
示例#7
0
int
NIreinit( CKTcircuit *ckt)
{
    int size;
#ifdef PREDICTOR
    int i;
#endif    

    size = SMPmatSize(ckt->CKTmatrix);
    CKALLOC(CKTrhs,size+1,double);
    CKALLOC(CKTrhsOld,size+1,double);
    CKALLOC(CKTrhsSpare,size+1,double);
    CKALLOC(CKTirhs,size+1,double);
    CKALLOC(CKTirhsOld,size+1,double);
    CKALLOC(CKTirhsSpare,size+1,double);
#ifdef PREDICTOR
    CKALLOC(CKTpred,size+1,double);
    for( i=0;i<8;i++) {
        CKALLOC(CKTsols[i],size+1,double);
    }
#endif /* PREDICTOR */
    ckt->CKTniState = NISHOULDREORDER | NIACSHOULDREORDER | NIPZSHOULDREORDER;
    return(0);
}
示例#8
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);
}
示例#9
0
int
CKTdisto (CKTcircuit *ckt, int mode)
{
    DISTOAN* cv = (DISTOAN*) (ckt->CKTcurJob);
    int i;
    int error=0;
    int size;

    switch(mode) {

    case D_SETUP:

	    for (i=0;i<DEVmaxnum;i++) {
		if ( DEVices[i] && ((*DEVices[i]).DEVdisto != NULL) && (ckt->CKThead[i] != NULL) ){
		    error = (*((*DEVices[i]).DEVdisto))(mode,ckt->CKThead[i],ckt);
		    if(error) return(error);
		}
	    }
	    break;

    case D_TWOF1:
    case D_THRF1:
    case D_F1PF2:
    case D_F1MF2:
    case D_2F1MF2:

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

	    for (i=0;i<DEVmaxnum;i++) {
		if ( DEVices[i] && ((*DEVices[i]).DEVdisto != NULL) && (ckt->CKThead[i] != NULL) ){
		    error = (*((*DEVices[i]).DEVdisto))(mode,ckt->CKThead[i],ckt);
		    if(error) return(error);
		}
	    }
	    break;

    case D_RHSF1:

 	   cv->Df2given = 0; /* will change if any F2 source is found */

    case D_RHSF2:



{
    int vcode;
    int icode;
    double mag=0.0;
    double phase=0.0;
    int size;

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

    vcode = CKTtypelook("Vsource");
    icode = CKTtypelook("Isource");


        if(vcode >= 0) {
            /* voltage sources are in this version, so use them */
            VSRCinstance *here;
            VSRCmodel *model;
            for(model = (VSRCmodel *)ckt->CKThead[vcode];model != NULL;
                    model=model->VSRCnextModel){
                for(here=model->VSRCinstances;here!=NULL;
                        here=here->VSRCnextInstance) {

/* check if the source has a distortion input*/

if (here->VSRCdGiven) {
  if (here->VSRCdF2given) cv->Df2given = 1;
  if ((here->VSRCdF1given) && (mode == D_RHSF1)) {
 
     mag = here->VSRCdF1mag;
     phase = here->VSRCdF1phase;
}
else if ((here->VSRCdF2given) && (mode == D_RHSF2)) {

     mag = here->VSRCdF2mag;
     phase = here->VSRCdF2phase;
}
if (((here->VSRCdF1given) && (mode == D_RHSF1)) || 
	((here->VSRCdF2given) && (mode == D_RHSF2))) {
   
	*(ckt->CKTrhs + here->VSRCbranch) = 0.5*mag* cos(M_PI*phase/180.0);
	*(ckt->CKTirhs + here->VSRCbranch) = 0.5*mag*sin(M_PI*phase/180.0); 
}


                    }
                }
            }
        }
        if(icode >= 0 ) {
            /* current sources are in this version, so use them */
            ISRCinstance *here;
            ISRCmodel *model;

            for(model= (ISRCmodel *)ckt->CKThead[icode];model != NULL;
                    model=model->ISRCnextModel){
                for(here=model->ISRCinstances;here!=NULL;
                        here=here->ISRCnextInstance) {

/* check if the source has a distortion input*/

if (here->ISRCdGiven) {
  if (here->ISRCdF2given) cv->Df2given = 1;
  if ((here->ISRCdF1given) && (mode == D_RHSF1)) {
 
     mag = here->ISRCdF1mag;
     phase = here->ISRCdF1phase;
}
else if ((here->ISRCdF2given) && (mode == D_RHSF2)) {

     mag = here->ISRCdF2mag;
     phase = here->ISRCdF2phase;
}
if (((here->ISRCdF1given) && (mode == D_RHSF1)) || 
	((here->ISRCdF2given) && (mode == D_RHSF2))) {
   
	*(ckt->CKTrhs + here->ISRCposNode) = - 0.5 * mag
		* cos(M_PI*phase/180.0);
        *(ckt->CKTrhs + here->ISRCnegNode) =   0.5 * mag * cos(
		M_PI*phase/180.0);
	*(ckt->CKTirhs + here->ISRCposNode) = - 0.5 * mag * sin(
		M_PI*phase/180.0);
	*(ckt->CKTirhs + here->ISRCnegNode) = 0.5 * mag * sin(
		M_PI*phase/180.0); 
}
                    }
                }
            }
        }
}
error = 0;
break;

    default: 

	    error = E_BADPARM;
	    break;
    }

    return(error);

}
示例#10
0
int
CKTacLoad(CKTcircuit *ckt)
{
    int i;
    int size;
    int error;
#ifdef PARALLEL_ARCH
    long type = MT_ACLOAD, length = 1;
#endif /* PARALLEL_ARCH */
    double startTime;

    startTime  = SPfrontEnd->IFseconds();
    size = SMPmatSize(ckt->CKTmatrix);
    for (i=0;i<=size;i++) {
        *(ckt->CKTrhs+i)=0;
        *(ckt->CKTirhs+i)=0;
    }
    SMPcClear(ckt->CKTmatrix);

    for (i=0;i<DEVmaxnum;i++) {
        if ( DEVices[i] && ((*DEVices[i]).DEVacLoad != NULL) && (ckt->CKThead[i] != NULL) ){
            error = (*((*DEVices[i]).DEVacLoad))(ckt->CKThead[i],ckt);
#ifdef PARALLEL_ARCH
	    if (error) goto combine;
#else
            if(error) return(error);
#endif /* PARALLEL_ARCH */
        }
    }
    
#ifdef XSPICE
   /* gtri - begin - Put resistors to ground at all nodes. */
    /* Value of resistor is set by new "rshunt" option.     */

    if(ckt->enh->rshunt_data.enabled) {
       for(i = 0; i < ckt->enh->rshunt_data.num_nodes; i++) {
          *(ckt->enh->rshunt_data.diag[i]) +=
                               ckt->enh->rshunt_data.gshunt;
       }
    }

    /* gtri - end - Put resistors to ground at all nodes */



    /* gtri - add - wbk - 11/26/90 - reset the MIF init flags */

    /* init is set by CKTinit and should be true only for first load call */
    g_mif_info.circuit.init = MIF_FALSE;

    /* anal_init is set by CKTdoJob and is true for first call */
    /* of a particular analysis type */
    g_mif_info.circuit.anal_init = MIF_FALSE;

    /* gtri - end - wbk - 11/26/90 */
#endif

    
#ifdef PARALLEL_ARCH
combine:
    ckt->CKTstat->STATloadTime += SPfrontEnd->IFseconds() - startTime;
    startTime  = SPfrontEnd->IFseconds();
    /* See if any of the DEVload functions bailed. If not, proceed. */
    IGOP_( &type, &error, &length, "max" );
    ckt->CKTstat->STATsyncTime += SPfrontEnd->IFseconds() - startTime;
    if (error == OK) {
      startTime  = SPfrontEnd->IFseconds();
      SMPcCombine( ckt->CKTmatrix, ckt->CKTrhs, ckt->CKTrhsSpare,
	  ckt->CKTirhs, ckt->CKTirhsSpare );
      ckt->CKTstat->STATcombineTime += SPfrontEnd->IFseconds() - startTime;
      return(OK);
    } else {
      return(error);
    }
#else
    ckt->CKTstat->STATloadTime += SPfrontEnd->IFseconds() - startTime;
    return(OK);
#endif /* PARALLEL_ARCH */
}
示例#11
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;
}