/*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); }
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); }
/* 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 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); }
int INDload(GENmodel *inModel, CKTcircuit *ckt) { INDmodel *model = (INDmodel*)inModel; INDinstance *here; double veq; double req; double m; int error; #ifdef MUTUAL MUTinstance *muthere; MUTmodel *mutmodel; int ktype; int itype; #endif /* loop through all the inductor models */ for( ; model != NULL; model = model->INDnextModel ) { /* loop through all the instances of the model */ for (here = model->INDinstances; here != NULL ; here=here->INDnextInstance) { m = (here->INDm); if(!(ckt->CKTmode & (MODEDC|MODEINITPRED))) { if(ckt->CKTmode & MODEUIC && ckt->CKTmode & MODEINITTRAN) { *(ckt->CKTstate0 + here->INDflux) = here->INDinduct / m * here->INDinitCond; } else { *(ckt->CKTstate0 + here->INDflux) = here->INDinduct / m * *(ckt->CKTrhsOld + here->INDbrEq); } } #ifdef MUTUAL } } ktype = CKTtypelook("mutual"); mutmodel = (MUTmodel *)(ckt->CKThead[ktype]); /* loop through all the mutual inductor models */ for( ; mutmodel != NULL; mutmodel = mutmodel->MUTnextModel ) { /* loop through all the instances of the model */ for (muthere = mutmodel->MUTinstances; muthere != NULL ; muthere=muthere->MUTnextInstance) { if(!(ckt->CKTmode& (MODEDC|MODEINITPRED))) { *(ckt->CKTstate0 + muthere->MUTind1->INDflux) += muthere->MUTfactor * *(ckt->CKTrhsOld + muthere->MUTind2->INDbrEq); *(ckt->CKTstate0 + muthere->MUTind2->INDflux) += muthere->MUTfactor * *(ckt->CKTrhsOld + muthere->MUTind1->INDbrEq); } *(muthere->MUTbr1br2) -= muthere->MUTfactor*ckt->CKTag[0]; *(muthere->MUTbr2br1) -= muthere->MUTfactor*ckt->CKTag[0]; } } itype = CKTtypelook("Inductor"); model = (INDmodel *)(ckt->CKThead[itype]); /* loop through all the inductor models */ for( ; model != NULL; model = model->INDnextModel ) { /* loop through all the instances of the model */ for (here = model->INDinstances; here != NULL ; here=here->INDnextInstance) { #endif /*MUTUAL*/ if(ckt->CKTmode & MODEDC) { req = 0.0; veq = 0.0; } else { double newmind; #ifndef PREDICTOR if(ckt->CKTmode & MODEINITPRED) { *(ckt->CKTstate0 + here->INDflux) = *(ckt->CKTstate1 + here->INDflux); } else { #endif /*PREDICTOR*/ if (ckt->CKTmode & MODEINITTRAN) { *(ckt->CKTstate1 + here->INDflux) = *(ckt->CKTstate0 + here->INDflux); } #ifndef PREDICTOR } #endif /*PREDICTOR*/ m = (here->INDm); newmind = here->INDinduct/m; error=NIintegrate(ckt,&req,&veq,newmind,here->INDflux); if(error) return(error); } *(ckt->CKTrhs+here->INDbrEq) += veq; if(ckt->CKTmode & MODEINITTRAN) { *(ckt->CKTstate1+here->INDvolt) = *(ckt->CKTstate0+here->INDvolt); } *(here->INDposIbrptr) += 1; *(here->INDnegIbrptr) -= 1; *(here->INDibrPosptr) += 1; *(here->INDibrNegptr) -= 1; *(here->INDibrIbrptr) -= req; } } return(OK); }
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); }