outitf.c: new option interp to plot interpolated raw file data
during transient analysis
This commit is contained in:
parent
0609d231c0
commit
bdb54257c7
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue