diff --git a/src/frontend/outitf.c b/src/frontend/outitf.c index 3f47b3720..0ccff5867 100644 --- a/src/frontend/outitf.c +++ b/src/frontend/outitf.c @@ -56,6 +56,8 @@ static bool parseSpecial(char *name, char *dev, char *param, char *ind); static bool name_eq(char *n1, char *n2); static bool getSpecial(dataDesc *desc, runDesc *run, IFvalue *val); static void freeRun(runDesc *run); +static int InterpFileAdd(runDesc *plotPtr, IFvalue *refValue, IFvalue *valuePtr); +static int InterpPlotAdd(runDesc *plotPtr, IFvalue *refValue, IFvalue *valuePtr); /*Output data to spice module*/ #ifdef TCL_MODULE @@ -80,6 +82,8 @@ static size_t column, rowbuflen; static bool shouldstop = FALSE; /* Tell simulator to stop next time it asks. */ +static bool interpolated = FALSE; +static double *valueold, *valuenew; /* The two "begin plot" routines share all their internals... */ @@ -145,6 +149,12 @@ beginPlot(JOB *analysisPtr, CKTcircuit *circuitPtr, char *cktName, char *analNam if (cp_getvar("printinfo", CP_BOOL, NULL)) fprintf(cp_err, "(debug printing enabled)\n"); + /* Check to see if we want to save only interpolated data. */ + if (cp_getvar("interp", CP_BOOL, NULL)) { + interpolated = TRUE; + fprintf(cp_out, "Warning: Interpolated raw file data!\n\n"); + } + *runp = run = alloc(struct runDesc); /* First fill in some general information. */ @@ -365,6 +375,14 @@ beginPlot(JOB *analysisPtr, CKTcircuit *circuitPtr, char *cktName, char *analNam } } + /* define storage for old and new data, to allow interpolation */ + if (interpolated && run->circuit->CKTcurJob->JOBtype == 4) { + valueold = TMALLOC(double, run->numData); + for (i = 0; i < run->numData; i++) + valueold[i] = 0.0; + valuenew = TMALLOC(double, run->numData); + } + /*Start BLT, initilises the blt vectors saj*/ #ifdef TCL_MODULE blt_init(run); @@ -453,8 +471,18 @@ OUTpData(runDesc *plotPtr, IFvalue *refValue, IFvalue *valuePtr) #ifdef TCL_MODULE steps_completed = run->pointCount; #endif - - if (run->writeOut) { + /* interpolated batch mode output to file in transient analysis */ + if (interpolated && run->circuit->CKTcurJob->JOBtype == 4 && run->writeOut) { + InterpFileAdd(run, refValue, valuePtr); + return (OK); + } + /* interpolated interactive or control mode output to plot in transient analysis */ + else if (interpolated && run->circuit->CKTcurJob->JOBtype == 4 && !(run->writeOut)) { + InterpPlotAdd(run, refValue, valuePtr); + return (OK); + } + /* standard batch mode output to file */ + else if (run->writeOut) { if (run->pointCount == 1) fileInit_pass2(run); @@ -677,7 +705,12 @@ OUTendPlot(runDesc *plotPtr) { runDesc *run = plotPtr; // FIXME - if (run->writeOut) { + if (interpolated && run->circuit->CKTcurJob->JOBtype == 4 && run->writeOut) { + tfree(valueold); + tfree(valuenew); + fileEnd(run); + } + else if (run->writeOut) { fileEnd(run); } else { gr_end_iplot(); @@ -1251,3 +1284,303 @@ OUTerror(int flags, char *format, IFuid *names) fprintf(cp_err, "%s\n", buf); fflush(cp_err); } + +static int +InterpFileAdd(runDesc *run, IFvalue *refValue, IFvalue *valuePtr) +{ + int i; + static double timeold = 0.0, timenew = 0.0, timestep = 0.0; + bool nodata = FALSE; + bool interpolatenow = FALSE; + + if (run->pointCount == 1) { + fileInit_pass2(run); + timestep = run->circuit->CKTinitTime + run->circuit->CKTstep; + } + + if (run->refIndex != -1) { + /* Save first time step */ + if (refValue->rValue == run->circuit->CKTinitTime) { + timeold = refValue->rValue; + fileStartPoint(run->fp, run->binary, run->pointCount); + fileAddRealValue(run->fp, run->binary, run->circuit->CKTinitTime); + interpolatenow = nodata = FALSE; + } + /* Save last time step */ + else if (refValue->rValue == run->circuit->CKTfinalTime) { + timeold = refValue->rValue; + fileStartPoint(run->fp, run->binary, run->pointCount); + fileAddRealValue(run->fp, run->binary, run->circuit->CKTfinalTime); + interpolatenow = nodata = FALSE; + } + /* Save exact point */ + else if (refValue->rValue == timestep) { + timeold = refValue->rValue; + fileStartPoint(run->fp, run->binary, run->pointCount); + fileAddRealValue(run->fp, run->binary, timestep); + timestep += run->circuit->CKTstep; + interpolatenow = nodata = FALSE; + } + else if (refValue->rValue > timestep) { + /* add the next time step value to the vector */ + fileStartPoint(run->fp, run->binary, run->pointCount); + timenew = refValue->rValue; + fileAddRealValue(run->fp, run->binary, timestep); + timestep += run->circuit->CKTstep; + nodata = FALSE; + interpolatenow = TRUE; + } + else { + /* Do not save this step */ + run->pointCount--; + timeold = refValue->rValue; + nodata = TRUE; + interpolatenow = FALSE; + } +#ifndef HAS_WINGUI + if (!orflag) { + currclock = clock(); + if ((currclock-lastclock) > (0.25*CLOCKS_PER_SEC)) { + fprintf(stderr, " Reference value : % 12.5e\r", + refValue->rValue); + lastclock = currclock; + } + } +#endif + + } + + for (i = 0; i < run->numData; i++) { + /* we've already printed reference vec first */ + if (run->data[i].outIndex == -1) + continue; + +#ifdef TCL_MODULE + blt_add(i, refValue ? refValue->rValue : NAN); +#endif + + if (run->data[i].regular) { + /* Store value or interpolate and store or do not store any value to file */ + if (!interpolatenow && !nodata) { + /* store the first or last value */ + valueold[i] = valuePtr->v.vec.rVec [run->data[i].outIndex]; + fileAddRealValue(run->fp, run->binary, valueold[i]); + } + else if (interpolatenow) { + /* Interpolate time if actual time is greater than proposed next time step */ + double newval; + valuenew[i] = valuePtr->v.vec.rVec [run->data[i].outIndex]; + newval = (timestep - run->circuit->CKTstep - timeold)/(timenew - timeold) * (valuenew[i] - valueold[i]) + valueold[i]; + fileAddRealValue(run->fp, run->binary, newval); + valueold[i] = valuenew[i]; + } + else if (nodata) + /* Just keep the transient output value corresponding to timeold, + but do not store to file */ + valueold[i] = valuePtr->v.vec.rVec [run->data[i].outIndex]; + } else { + IFvalue val; + /* should pre-check instance */ + if (!getSpecial(&run->data[i], run, &val)) { + + /* If this is the first data point, print a warning for any unrecognized + variables, since this has not already been checked */ + if (run->pointCount == 1) + fprintf(stderr, "Warning: unrecognized variable - %s\n", + run->data[i].name); + val.rValue = 0; + fileAddRealValue(run->fp, run->binary, val.rValue); + continue; + } + if (!interpolatenow && !nodata) { + /* store the first or last value */ + valueold[i] = val.rValue; + fileAddRealValue(run->fp, run->binary, valueold[i]); + } + else if (interpolatenow) { + /* Interpolate time if actual time is greater than proposed next time step */ + double newval; + valuenew[i] = val.rValue; + newval = (timestep - run->circuit->CKTstep - timeold)/(timenew - timeold) * (valuenew[i] - valueold[i]) + valueold[i]; + fileAddRealValue(run->fp, run->binary, newval); + valueold[i] = valuenew[i]; + } + else if (nodata) + /* Just keep the transient output value corresponding to timeold, + but do not store to file */ + valueold[i] = val.rValue; + } + +#ifdef TCL_MODULE + blt_add(i, valuePtr->v.vec.rVec [run->data[i].outIndex]); +#endif + + } + + fileEndPoint(run->fp, run->binary); + + /* Check that the write to disk completed successfully, otherwise abort */ + if (ferror(run->fp)) { + fprintf(stderr, "Warning: rawfile write error !!\n"); + shouldstop = TRUE; + } + + if (ft_bpcheck(run->runPlot, run->pointCount) == FALSE) + shouldstop = TRUE; + +#ifdef TCL_MODULE + Tcl_ExecutePerLoop(); +#elif defined SHARED_MODULE + sh_ExecutePerLoop(); +#endif + return(OK); +} + +static int +InterpPlotAdd(runDesc *run, IFvalue *refValue, IFvalue *valuePtr) +{ + int i, iscale = -1; + static double timeold = 0.0, timenew = 0.0, timestep = 0.0; + bool nodata = FALSE; + bool interpolatenow = FALSE; + + if (run->pointCount == 1) + timestep = run->circuit->CKTinitTime + run->circuit->CKTstep; + + /* find the scale vector */ + for (i = 0; i < run->numData; i++) + if (run->data[i].outIndex == -1) { + iscale = i; + break; + } + if (iscale == -1) + fprintf(stderr, "Error: no scale vector found\n"); + +#ifdef TCL_MODULE + /*Locks the blt vector to stop access*/ + blt_lockvec(iscale); +#endif + + /* Save first time step */ + if (refValue->rValue == run->circuit->CKTinitTime) { + timeold = refValue->rValue; + plotAddRealValue(&run->data[iscale], refValue->rValue); + interpolatenow = nodata = FALSE; + } + /* Save last time step */ + else if (refValue->rValue == run->circuit->CKTfinalTime) { + timeold = refValue->rValue; + plotAddRealValue(&run->data[iscale], run->circuit->CKTfinalTime); + interpolatenow = nodata = FALSE; + } + /* Save exact point */ + else if (refValue->rValue == timestep) { + timeold = refValue->rValue; + plotAddRealValue(&run->data[iscale], timestep); + timestep += run->circuit->CKTstep; + interpolatenow = nodata = FALSE; + } + else if (refValue->rValue > timestep) { + /* add the next time step value to the vector */ + timenew = refValue->rValue; + plotAddRealValue(&run->data[iscale], timestep); + timestep += run->circuit->CKTstep; + nodata = FALSE; + interpolatenow = TRUE; + } + else { + /* Do not save this step */ + run->pointCount--; + timeold = refValue->rValue; + nodata = TRUE; + interpolatenow = FALSE; + } + +#ifdef TCL_MODULE + /*relinks and unlocks vector*/ + blt_relink(iscale, (run->data[iscale]).vec); +#endif + +#ifndef HAS_WINGUI + if (!orflag) { + currclock = clock(); + if ((currclock-lastclock) > (0.25*CLOCKS_PER_SEC)) { + fprintf(stderr, " Reference value : % 12.5e\r", + refValue->rValue); + lastclock = currclock; + } + } +#endif + + for (i = 0; i < run->numData; i++) { + if (i == iscale) + continue; + +#ifdef TCL_MODULE + /*Locks the blt vector to stop access*/ + blt_lockvec(i); +#endif + + if (run->data[i].regular) { + /* Store value or interpolate and store or do not store any value to file */ + if (!interpolatenow && !nodata) { + /* store the first or last value */ + valueold[i] = valuePtr->v.vec.rVec [run->data[i].outIndex]; + plotAddRealValue(&run->data[i], valueold[i]); + } + else if (interpolatenow) { + /* Interpolate time if actual time is greater than proposed next time step */ + double newval; + valuenew[i] = valuePtr->v.vec.rVec [run->data[i].outIndex]; + newval = (timestep - run->circuit->CKTstep - timeold)/(timenew - timeold) * (valuenew[i] - valueold[i]) + valueold[i]; + plotAddRealValue(&run->data[i], newval); + valueold[i] = valuenew[i]; + } + else if (nodata) + /* Just keep the transient output value corresponding to timeold, + but do not store to file */ + valueold[i] = valuePtr->v.vec.rVec [run->data[i].outIndex]; + } else { + IFvalue val; + /* should pre-check instance */ + if (!getSpecial(&run->data[i], run, &val)) + continue; + if (!interpolatenow && !nodata) { + /* store the first or last value */ + valueold[i] = val.rValue; + plotAddRealValue(&run->data[i], valueold[i]); + } + else if (interpolatenow) { + /* Interpolate time if actual time is greater than proposed next time step */ + double newval; + valuenew[i] = val.rValue; + newval = (timestep - run->circuit->CKTstep - timeold)/(timenew - timeold) * (valuenew[i] - valueold[i]) + valueold[i]; + plotAddRealValue(&run->data[i], newval); + valueold[i] = valuenew[i]; + } + else if (nodata) + /* Just keep the transient output value corresponding to timeold, + but do not store to file */ + valueold[i] = val.rValue; + } + +#ifdef TCL_MODULE + /*relinks and unlocks vector*/ + blt_relink(i, (run->data[i]).vec); +#endif + + } + + gr_iplot(run->runPlot); + + if (ft_bpcheck(run->runPlot, run->pointCount) == FALSE) + shouldstop = TRUE; + +#ifdef TCL_MODULE + Tcl_ExecutePerLoop(); +#elif defined SHARED_MODULE + sh_ExecutePerLoop(); +#endif + + return(OK); +}