///<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*/ }
/* 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); }
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; }