outitf.c: new option interp to plot interpolated raw file data

during transient analysis
This commit is contained in:
h_vogt 2014-02-01 14:24:04 +01:00
parent 0609d231c0
commit bdb54257c7
1 changed files with 336 additions and 3 deletions

View File

@ -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);
}