257 lines
8.1 KiB
C
257 lines
8.1 KiB
C
/**********
|
|
Copyright 1990 Regents of the University of California. All rights reserved.
|
|
Author: 1985 Wayne A. Christopher, U. C. Berkeley CAD Group
|
|
**********/
|
|
|
|
#include "ngspice/ngspice.h"
|
|
#include "ngspice/cpdefs.h"
|
|
#include "ngspice/ftedefs.h"
|
|
#include "ngspice/dvec.h"
|
|
|
|
#include "circuits.h"
|
|
#include "linear.h"
|
|
#include "interp.h"
|
|
|
|
|
|
/* Interpolate all the vectors in a plot to a linear time scale, which
|
|
* we determine by looking at the transient parameters in the CKT struct.
|
|
* If no circuit is loaded, e.g. because the 'load' command has been used
|
|
* to obtain data, try to get parameters from scale vector.
|
|
* Interpolation may be restricted to only a region of the input vector,
|
|
* thus creating a cutout of the original vector.
|
|
*/
|
|
void
|
|
com_linearize(wordlist *wl)
|
|
{
|
|
double tstart, tstop, tstep, d;
|
|
struct plot *new, *old;
|
|
struct dvec *newtime, *v;
|
|
struct dvec *oldtime;
|
|
struct dvec *lin;
|
|
int len, i;
|
|
|
|
if (!plot_cur || !plot_cur->pl_typename || !ciprefix("tran", plot_cur->pl_typename)) {
|
|
fprintf(cp_err, "Error: plot must be a transient analysis\n");
|
|
return;
|
|
}
|
|
if (!plot_cur->pl_dvecs || !plot_cur->pl_scale) {
|
|
fprintf(cp_err, "Error: no vectors available\n");
|
|
return;
|
|
}
|
|
if (!isreal(plot_cur->pl_scale)) {
|
|
fprintf(cp_err, "Error: non-real time scale for %s\n",
|
|
plot_cur->pl_typename);
|
|
return;
|
|
}
|
|
|
|
/* check if circuit is loaded and TSTART, TSTOP, TSTEP are available
|
|
if no circuit is loaded, but vectors are available, obtain
|
|
start, stop, step data from scale vector */
|
|
if (!ft_curckt || !ft_curckt->ci_ckt ||
|
|
!if_tranparams(ft_curckt, &tstart, &tstop, &tstep)) {
|
|
fprintf(cp_err,
|
|
"Warning: Can't get transient parameters from circuit.\n"
|
|
" Use transient analysis scale vector data instead.\n");
|
|
int length = plot_cur->pl_scale->v_length;
|
|
if (length < 1) {
|
|
fprintf(cp_err, "Error: no data in vector\n");
|
|
return;
|
|
}
|
|
tstart = plot_cur->pl_scale->v_realdata[0];
|
|
tstop = plot_cur->pl_scale->v_realdata[length - 1];
|
|
tstep = (tstop - tstart) / (double)length;
|
|
}
|
|
|
|
/* if this plot contains special vectors lin-tstart, lin-tstop or lin-tstep, use these instead */
|
|
lin = vec_fromplot("lin-tstart", plot_cur);
|
|
if (lin) {
|
|
fprintf(cp_out, "linearize tstart is set to: %8e\n", lin->v_realdata[0]);
|
|
tstart = lin->v_realdata[0];
|
|
}
|
|
|
|
lin = vec_fromplot("lin-tstop", plot_cur);
|
|
if (lin) {
|
|
fprintf(cp_out, "linearize tstop is set to: %8e\n", lin->v_realdata[0]);
|
|
tstop = lin->v_realdata[0];
|
|
}
|
|
|
|
lin = vec_fromplot("lin-tstep", plot_cur);
|
|
if (lin) {
|
|
fprintf(cp_out, "linearize tstep is set to: %8e\n", lin->v_realdata[0]);
|
|
tstep = lin->v_realdata[0];
|
|
}
|
|
|
|
/* finally check if tstart, tstop and tstep are reasonable */
|
|
if (((tstop - tstart) * tstep <= 0.0) || ((tstop - tstart) < tstep)) {
|
|
fprintf(cp_err,
|
|
"Error: bad parameters -- start = %G, stop = %G, step = %G\n",
|
|
tstart, tstop, tstep);
|
|
return;
|
|
}
|
|
old = plot_cur;
|
|
oldtime = old->pl_scale;
|
|
new = plot_alloc("transient");
|
|
new->pl_name = tprintf("%s (linearized)", old->pl_name);
|
|
new->pl_title = copy(old->pl_title);
|
|
new->pl_date = copy(old->pl_date);
|
|
new->pl_next = plot_list;
|
|
plot_new(new);
|
|
plot_setcur(new->pl_typename);
|
|
plot_list = new;
|
|
len = (int)((tstop - tstart) / tstep + 1.5);
|
|
newtime = dvec_alloc(copy(oldtime->v_name),
|
|
oldtime->v_type,
|
|
oldtime->v_flags | VF_PERMANENT,
|
|
len, NULL);
|
|
|
|
newtime->v_plot = new;
|
|
for (i = 0, d = tstart; i < len; i++, d += tstep)
|
|
newtime->v_realdata[i] = d;
|
|
new->pl_scale = new->pl_dvecs = newtime;
|
|
|
|
if (wl) {
|
|
while (wl) {
|
|
v = vec_fromplot(wl->wl_word, old);
|
|
if (!v) {
|
|
fprintf(cp_err, "Error: no such vector %s\n",
|
|
wl->wl_word);
|
|
wl = wl->wl_next;
|
|
continue;
|
|
}
|
|
lincopy(v, newtime->v_realdata, len, oldtime);
|
|
wl = wl->wl_next;
|
|
}
|
|
} else {
|
|
for (v = old->pl_dvecs; v; v = v->v_next) {
|
|
if (v == old->pl_scale)
|
|
continue;
|
|
lincopy(v, newtime->v_realdata, len, oldtime);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/* Cut out part of tran vectors from cut-tstart to cut-tstop and copy these
|
|
into a new plot. A new scale vector 'time' will be there as well. Vectors
|
|
that are shorter than the new scale vector will not be copied. */
|
|
void
|
|
com_cutout(wordlist* wl)
|
|
{
|
|
double tstart, tstop;
|
|
struct plot* new, * old;
|
|
struct dvec* newtime, * v, *nv;
|
|
struct dvec* oldtime;
|
|
struct dvec* sta, *sto;
|
|
int len, i, istart, istop;
|
|
|
|
if (!plot_cur || !plot_cur->pl_dvecs || !plot_cur->pl_scale) {
|
|
fprintf(cp_err, "Error: no vectors available\n");
|
|
return;
|
|
}
|
|
if (!isreal(plot_cur->pl_scale)) {
|
|
fprintf(cp_err, "Error: non-real time scale for %s\n",
|
|
plot_cur->pl_typename);
|
|
return;
|
|
}
|
|
if (!ciprefix("tran", plot_cur->pl_typename)) {
|
|
fprintf(cp_err, "Error: plot must be a transient analysis\n");
|
|
return;
|
|
}
|
|
|
|
int length = plot_cur->pl_scale->v_length;
|
|
if (length < 1) {
|
|
fprintf(cp_err, "Error: no data in vector\n");
|
|
return;
|
|
}
|
|
/* if this plot contains special vectors cut-tstart or cut-tstop, use these */
|
|
sta = vec_fromplot("cut-tstart", plot_cur);
|
|
if (sta) {
|
|
tstart = sta->v_realdata[0];
|
|
for (istart = 0; istart < length - 1; istart++) {
|
|
if (plot_cur->pl_scale->v_realdata[istart] > tstart) {
|
|
// istart--;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
tstart = plot_cur->pl_scale->v_realdata[0];
|
|
istart = 0;
|
|
}
|
|
sto = vec_fromplot("cut-tstop", plot_cur);
|
|
if (sto) {
|
|
tstop = sto->v_realdata[0];
|
|
for (istop = 0; istop < length - 1; istop++) {
|
|
if (plot_cur->pl_scale->v_realdata[istop] > tstop)
|
|
break;
|
|
}
|
|
}
|
|
else {
|
|
tstop = plot_cur->pl_scale->v_realdata[length - 1];
|
|
istop = length - 1;
|
|
}
|
|
|
|
|
|
/* finally check if tstart, tstop, istart and istop are reasonable */
|
|
if (((tstop - tstart) <= 0.0) || ((istop - istart) <= 0)) {
|
|
fprintf(cp_err,
|
|
"Error: bad parameters -- start = %G, stop = %G\n",
|
|
tstart, tstop);
|
|
return;
|
|
}
|
|
|
|
/* create a new plot */
|
|
old = plot_cur;
|
|
oldtime = old->pl_scale;
|
|
new = plot_alloc("transient");
|
|
if (!sta && !sto)
|
|
new->pl_name = tprintf("%s (copy)", old->pl_name);
|
|
else
|
|
new->pl_name = tprintf("%s (cut out)", old->pl_name);
|
|
new->pl_title = copy(old->pl_title);
|
|
new->pl_date = copy(old->pl_date);
|
|
new->pl_next = plot_list;
|
|
plot_new(new);
|
|
plot_setcur(new->pl_typename);
|
|
plot_list = new;
|
|
|
|
/* copy a new scale vector (time) */
|
|
len = istop - istart;
|
|
newtime = dvec_alloc(copy(oldtime->v_name),
|
|
oldtime->v_type,
|
|
oldtime->v_flags | VF_PERMANENT,
|
|
len, NULL);
|
|
|
|
newtime->v_plot = new;
|
|
for (i = 0; i < len; i++)
|
|
newtime->v_realdata[i] = oldtime->v_realdata[istart + i];
|
|
new->pl_scale = new->pl_dvecs = newtime;
|
|
|
|
/* copy the vectors from tstart to tstop */
|
|
if (wl) {
|
|
while (wl) {
|
|
v = vec_fromplot(wl->wl_word, old);
|
|
if (!v) {
|
|
fprintf(cp_err, "Error: no such vector %s\n",
|
|
wl->wl_word);
|
|
wl = wl->wl_next;
|
|
continue;
|
|
}
|
|
nv = copycut(v, newtime, istart, istop);
|
|
vec_new(nv);
|
|
wl = wl->wl_next;
|
|
}
|
|
}
|
|
else {
|
|
for (v = old->pl_dvecs; v; v = v->v_next) {
|
|
if (v == old->pl_scale)
|
|
continue;
|
|
/* Don't copy vectors that are too short */
|
|
if (v->v_length < istop)
|
|
continue;
|
|
nv = copycut(v, newtime, istart, istop);
|
|
vec_new(nv);
|
|
}
|
|
}
|
|
}
|