* commands.c: Use fourier.h.
* dotcards.c: Update to prevent segfault. * fourier.c, fourier.h: com_fourier is now calling fourier(), a function with more parameters. * dotcards.c: Added assertions to guard a double indirection, now ngspice will bomb out on an assertion instead of a segfault.
This commit is contained in:
parent
7a3a17a5b9
commit
508fee7d4b
|
|
@ -1,5 +1,12 @@
|
|||
2000-09-09 Arno W. Peters <A.W.Peters@ieee.org>
|
||||
|
||||
* commands.c: Use fourier.h.
|
||||
|
||||
* dotcards.c: Update to prevent segfault.
|
||||
|
||||
* fourier.c, fourier.h: com_fourier is now calling fourier(), a
|
||||
function with more parameters.
|
||||
|
||||
* dotcards.c: Added assertions to guard a double indirection, now
|
||||
ngspice will bomb out on an assertion instead of a segfault.
|
||||
|
||||
|
|
|
|||
|
|
@ -47,7 +47,7 @@
|
|||
#include "com_plot.h"
|
||||
#include "com_setscale.h"
|
||||
#include "com_xgraph.h"
|
||||
|
||||
#include "fourier.h"
|
||||
|
||||
/* FIXME: Integrate spcp_coms and nutcp_coms into one variable. */
|
||||
|
||||
|
|
|
|||
|
|
@ -20,19 +20,35 @@ Modified: 2000 AlansFixes
|
|||
#include "circuits.h"
|
||||
#include "dotcards.h"
|
||||
#include "variable.h"
|
||||
|
||||
#include "fourier.h"
|
||||
|
||||
/* Extract all the .save lines */
|
||||
|
||||
static void fixdotplot(wordlist *wl);
|
||||
static void fixdotprint(wordlist *wl);
|
||||
static char * fixem(char *string);
|
||||
static bool setcplot(char *name);
|
||||
static wordlist * gettoks(char *s);
|
||||
|
||||
|
||||
extern void com_save2 (wordlist *wl, char *name);
|
||||
|
||||
|
||||
|
||||
static struct plot *
|
||||
setcplot(char *name)
|
||||
{
|
||||
struct plot *pl;
|
||||
|
||||
for (pl = plot_list; pl; pl = pl->pl_next) {
|
||||
if (ciprefix(name, pl->pl_typename)) {
|
||||
return pl;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
ft_dotsaves(void)
|
||||
{
|
||||
|
|
@ -157,7 +173,9 @@ ft_cktcoms(bool terse)
|
|||
|
||||
if (!ft_curckt)
|
||||
return 1;
|
||||
if (!ft_curckt->ci_commands && !setcplot("op"))
|
||||
|
||||
plot_cur = setcplot("op");
|
||||
if (!ft_curckt->ci_commands && !plot_cur)
|
||||
goto nocmds;
|
||||
coms = ft_curckt->ci_commands;
|
||||
cp_interactive = FALSE;
|
||||
|
|
@ -168,41 +186,43 @@ ft_cktcoms(bool terse)
|
|||
fprintf(cp_err, ".options: no listing, rawfile was generated.\n");
|
||||
else
|
||||
inp_list(cp_out, ft_curckt->ci_deck, ft_curckt->ci_options,
|
||||
LS_DECK);
|
||||
LS_DECK);
|
||||
}
|
||||
|
||||
/* If there was a .op line, then we have to do the .op output. */
|
||||
assert(plot_cur != NULL);
|
||||
assert(plot_cur->pl_dvecs != NULL);
|
||||
if (setcplot("op") && (plot_cur->pl_dvecs->v_realdata!=NULL)) {
|
||||
if (terse) {
|
||||
fprintf(cp_out, "OP information in rawfile.\n");
|
||||
} else {
|
||||
fprintf(cp_out, "\t%-30s%15s\n", "Node", "Voltage");
|
||||
fprintf(cp_out, "\t%-30s%15s\n", "----", "-------");
|
||||
fprintf(cp_out, "\t----\t-------\n");
|
||||
for (v = plot_cur->pl_dvecs; v; v = v->v_next) {
|
||||
if (!isreal(v)) {
|
||||
fprintf(cp_err,
|
||||
"Internal error: op vector %s not real\n",
|
||||
v->v_name);
|
||||
continue;
|
||||
plot_cur = setcplot("op");
|
||||
if (plot_cur != NULL) {
|
||||
assert(plot_cur->pl_dvecs != NULL);
|
||||
if (plot_cur->pl_dvecs->v_realdata!=NULL) {
|
||||
if (terse) {
|
||||
fprintf(cp_out, "OP information in rawfile.\n");
|
||||
} else {
|
||||
fprintf(cp_out, "\t%-30s%15s\n", "Node", "Voltage");
|
||||
fprintf(cp_out, "\t%-30s%15s\n", "----", "-------");
|
||||
fprintf(cp_out, "\t----\t-------\n");
|
||||
for (v = plot_cur->pl_dvecs; v; v = v->v_next) {
|
||||
if (!isreal(v)) {
|
||||
fprintf(cp_err,
|
||||
"Internal error: op vector %s not real\n",
|
||||
v->v_name);
|
||||
continue;
|
||||
}
|
||||
if ((v->v_type == SV_VOLTAGE) && (*(v->v_name)!='@'))
|
||||
fprintf(cp_out, "\t%-30s%15s\n", v->v_name,
|
||||
printnum(v->v_realdata[0]));
|
||||
}
|
||||
if ((v->v_type == SV_VOLTAGE) && (*(v->v_name)!='@'))
|
||||
fprintf(cp_out, "\t%-30s%15s\n", v->v_name,
|
||||
printnum(v->v_realdata[0]));
|
||||
}
|
||||
fprintf(cp_out, "\n\tSource\tCurrent\n");
|
||||
fprintf(cp_out, "\t------\t-------\n\n");
|
||||
for (v = plot_cur->pl_dvecs; v; v = v->v_next)
|
||||
if (v->v_type == SV_CURRENT)
|
||||
fprintf(cp_out, "\t%-30s%15s\n", v->v_name,
|
||||
printnum(v->v_realdata[0]));
|
||||
fprintf(cp_out, "\n");
|
||||
fprintf(cp_out, "\n\tSource\tCurrent\n");
|
||||
fprintf(cp_out, "\t------\t-------\n\n");
|
||||
for (v = plot_cur->pl_dvecs; v; v = v->v_next)
|
||||
if (v->v_type == SV_CURRENT)
|
||||
fprintf(cp_out, "\t%-30s%15s\n", v->v_name,
|
||||
printnum(v->v_realdata[0]));
|
||||
fprintf(cp_out, "\n");
|
||||
|
||||
if (!ft_nomod)
|
||||
com_showmod(&all);
|
||||
com_show(&all);
|
||||
if (!ft_nomod)
|
||||
com_showmod(&all);
|
||||
com_show(&all);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -264,7 +284,7 @@ ft_cktcoms(bool terse)
|
|||
}
|
||||
if (!found)
|
||||
fprintf(cp_err, "Error: .print: no %s analysis found.\n",
|
||||
plottype);
|
||||
plottype);
|
||||
}
|
||||
} else if (eq(command->wl_word, ".plot")) {
|
||||
if (terse) {
|
||||
|
|
@ -298,22 +318,27 @@ ft_cktcoms(bool terse)
|
|||
if (terse) {
|
||||
fprintf(cp_out,
|
||||
".fourier line ignored since rawfile was produced.\n");
|
||||
} else if (setcplot("tran")) {
|
||||
com_fourier(command->wl_next);
|
||||
fprintf(cp_out, "\n\n");
|
||||
} else
|
||||
fprintf(cp_err,
|
||||
"No transient data available for fourier analysis");
|
||||
} else {
|
||||
int err;
|
||||
|
||||
plot_cur = setcplot("tran");
|
||||
err = fourier(command->wl_next, plot_cur);
|
||||
if (!err)
|
||||
fprintf(cp_out, "\n\n");
|
||||
else
|
||||
fprintf(cp_err, "No transient data available for "
|
||||
"fourier analysis");
|
||||
}
|
||||
} else if (!eq(command->wl_word, ".save")
|
||||
&& !eq(command->wl_word, ".op")
|
||||
&& !eq(command->wl_word, ".tf"))
|
||||
&& !eq(command->wl_word, ".op")
|
||||
&& !eq(command->wl_word, ".tf"))
|
||||
{
|
||||
goto bad;
|
||||
}
|
||||
coms = coms->wl_next;
|
||||
}
|
||||
|
||||
nocmds:
|
||||
nocmds:
|
||||
/* Now the node table */
|
||||
if (ft_nodesprint)
|
||||
;
|
||||
|
|
@ -335,7 +360,7 @@ nocmds:
|
|||
putc('\n', cp_out);
|
||||
return 0;
|
||||
|
||||
bad:
|
||||
bad:
|
||||
fprintf(cp_err, "Internal Error: ft_cktcoms: bad commands\n");
|
||||
return 1;
|
||||
}
|
||||
|
|
@ -473,22 +498,6 @@ fixem(char *string)
|
|||
return (string);
|
||||
}
|
||||
|
||||
/* Don't bother with ccom strangeness here. */
|
||||
|
||||
static bool
|
||||
setcplot(char *name)
|
||||
{
|
||||
struct plot *pl;
|
||||
|
||||
for (pl = plot_list; pl; pl = pl->pl_next) {
|
||||
if (ciprefix(name, pl->pl_typename)) {
|
||||
plot_cur = pl;
|
||||
return (TRUE);
|
||||
}
|
||||
}
|
||||
return (FALSE);
|
||||
}
|
||||
|
||||
static wordlist *
|
||||
gettoks(char *s)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -31,12 +31,15 @@ static int CKTfour(int ndata, int numFreq, double *thd, double *Time, double *Va
|
|||
|
||||
#define DEF_FOURGRIDSIZE 200
|
||||
|
||||
|
||||
/* CKTfour(ndata,numFreq,thd,Time,Value,FundFreq,Freq,Mag,Phase,nMag,nPhase)
|
||||
* len 10 ? inp inp inp out out out out out
|
||||
*/
|
||||
|
||||
void
|
||||
com_fourier(wordlist *wl)
|
||||
/* FIXME: This function leaks memory due to non local exit bypassing
|
||||
freeing of memory at the end of the function. */
|
||||
int
|
||||
fourier(wordlist *wl, struct plot *current_plot)
|
||||
{
|
||||
struct dvec *time, *vec;
|
||||
struct pnode *names, *first_name;
|
||||
|
|
@ -49,11 +52,14 @@ com_fourier(wordlist *wl)
|
|||
char xbuf[20];
|
||||
int shift;
|
||||
|
||||
if (!current_plot)
|
||||
return 1;
|
||||
|
||||
sprintf(xbuf, "%1.1e", 0.0);
|
||||
shift = strlen(xbuf) - 7;
|
||||
if (!plot_cur || !plot_cur->pl_scale) {
|
||||
if (!current_plot || !current_plot->pl_scale) {
|
||||
fprintf(cp_err, "Error: no vectors loaded.\n");
|
||||
return;
|
||||
return 1;
|
||||
}
|
||||
|
||||
if ((!cp_getvar("nfreqs", VT_NUM, (char *) &nfreqs)) || (nfreqs < 1))
|
||||
|
|
@ -65,15 +71,15 @@ com_fourier(wordlist *wl)
|
|||
(fourgridsize < 1))
|
||||
fourgridsize = DEF_FOURGRIDSIZE;
|
||||
|
||||
time = plot_cur->pl_scale;
|
||||
time = current_plot->pl_scale;
|
||||
if (!isreal(time)) {
|
||||
fprintf(cp_err, "Error: fourier needs real time scale\n");
|
||||
return;
|
||||
return 1;
|
||||
}
|
||||
s = wl->wl_word;
|
||||
if (!(ff = ft_numparse(&s, FALSE)) || (*ff <= 0.0)) {
|
||||
fprintf(cp_err, "Error: bad fund freq %s\n", wl->wl_word);
|
||||
return;
|
||||
return 1;
|
||||
}
|
||||
fundfreq = *ff;
|
||||
|
||||
|
|
@ -114,8 +120,8 @@ com_fourier(wordlist *wl)
|
|||
d = 1 / fundfreq; /* The wavelength... */
|
||||
if (dp[1] - dp[0] < d) {
|
||||
fprintf(cp_err,
|
||||
"Error: wavelength longer than time span\n");
|
||||
return;
|
||||
"Error: wavelength longer than time span\n");
|
||||
return 1;
|
||||
} else if (dp[1] - dp[0] > d) {
|
||||
dp[0] = dp[1] - d;
|
||||
}
|
||||
|
|
@ -131,7 +137,7 @@ com_fourier(wordlist *wl)
|
|||
polydegree)) {
|
||||
fprintf(cp_err,
|
||||
"Error: can't interpolate\n");
|
||||
return;
|
||||
return 1;
|
||||
}
|
||||
timescale = grid;
|
||||
} else {
|
||||
|
|
@ -145,7 +151,7 @@ com_fourier(wordlist *wl)
|
|||
nphase);
|
||||
if (err != OK) {
|
||||
ft_sperror(err, "fourier");
|
||||
return;
|
||||
return 1;
|
||||
}
|
||||
|
||||
fprintf(cp_out, "Fourier analysis for %s:\n",
|
||||
|
|
@ -185,9 +191,18 @@ com_fourier(wordlist *wl)
|
|||
tfree(phase);
|
||||
tfree(nmag);
|
||||
tfree(nphase);
|
||||
return;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
com_fourier(wordlist *wl)
|
||||
{
|
||||
fourier(wl, plot_cur);
|
||||
}
|
||||
|
||||
|
||||
|
||||
static char *
|
||||
pn(double num)
|
||||
{
|
||||
|
|
@ -198,50 +213,54 @@ pn(double num)
|
|||
i = 6;
|
||||
|
||||
if (num < 0.0)
|
||||
(void) sprintf(buf, "%.*g", i - 1, num);
|
||||
sprintf(buf, "%.*g", i - 1, num);
|
||||
else
|
||||
(void) sprintf(buf, "%.*g", i, num);
|
||||
sprintf(buf, "%.*g", i, num);
|
||||
return (copy(buf));
|
||||
}
|
||||
|
||||
/*
|
||||
* CKTfour() - perform fourier analysis of an output vector.
|
||||
* Due to the construction of the program which places all the
|
||||
* output data in the post-processor, the fourier analysis can not
|
||||
* be done directly. This function allows the post processor to
|
||||
* hand back vectors of time and data values to have the fourier analysis
|
||||
* performed on them.
|
||||
|
||||
/* CKTfour() - perform fourier analysis of an output vector.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
* Due to the construction of the program which places all the output
|
||||
* data in the post-processor, the fourier analysis can not be done
|
||||
* directly. This function allows the post processor to hand back
|
||||
* vectors of time and data values to have the fourier analysis
|
||||
* performed on them. */
|
||||
static int
|
||||
CKTfour(int ndata, int numFreq, double *thd, double *Time, double *Value, double FundFreq, double *Freq, double *Mag, double *Phase, double *nMag, double *nPhase)
|
||||
/* number of entries in the Time and Value arrays */
|
||||
/* number of harmonics to calculate */
|
||||
/* total harmonic distortion (percent) to be returned */
|
||||
/* times at which the voltage/current values were measured*/
|
||||
/* voltage or current vector whose transform is desired */
|
||||
/* the fundamental frequency of the analysis */
|
||||
/* the frequency value of the various harmonics */
|
||||
/* the Magnitude of the fourier transform */
|
||||
/* the Phase of the fourier transform */
|
||||
/* the normalized magnitude of the transform: nMag(fund)=1*/
|
||||
/* the normalized phase of the transform: Nphase(fund)=0 */
|
||||
/* note we can consider these as a set of arrays: The sizes are:
|
||||
* Time[ndata], Value[ndata]
|
||||
* Freq[numFreq],Mag[numfreq],Phase[numfreq],nMag[numfreq],nPhase[numfreq]
|
||||
CKTfour(int ndata, /* number of entries in the Time and
|
||||
Value arrays */
|
||||
int numFreq, /* number of harmonics to calculate */
|
||||
double *thd, /* total harmonic distortion (percent)
|
||||
to be returned */
|
||||
double *Time, /* times at which the voltage/current
|
||||
values were measured*/
|
||||
double *Value, /* voltage or current vector whose
|
||||
transform is desired */
|
||||
double FundFreq, /* the fundamental frequency of the
|
||||
analysis */
|
||||
double *Freq, /* the frequency value of the various
|
||||
harmonics */
|
||||
double *Mag, /* the Magnitude of the fourier
|
||||
transform */
|
||||
double *Phase, /* the Phase of the fourier transform */
|
||||
double *nMag, /* the normalized magnitude of the
|
||||
transform: nMag(fund)=1*/
|
||||
double *nPhase) /* the normalized phase of the
|
||||
transform: Nphase(fund)=0 */
|
||||
{
|
||||
/* Note: we can consider these as a set of arrays. The sizes are:
|
||||
* Time[ndata], Value[ndata], Freq[numFreq], Mag[numfreq],
|
||||
* Phase[numfreq], nMag[numfreq], nPhase[numfreq]
|
||||
*
|
||||
* The arrays must all be allocated by the caller.
|
||||
* The Time and Value array must be reasonably distributed over at
|
||||
* least one full period of the fundamental Frequency for the
|
||||
* fourier transform to be useful. The function will take the
|
||||
* last period of the frequency as data for the transform.
|
||||
*/
|
||||
|
||||
{
|
||||
/* we are assuming that the caller has provided exactly one period
|
||||
* of the fundamental frequency.
|
||||
*/
|
||||
*
|
||||
* We are assuming that the caller has provided exactly one period
|
||||
* of the fundamental frequency. */
|
||||
int i;
|
||||
int j;
|
||||
double tmp;
|
||||
|
|
|
|||
|
|
@ -7,7 +7,6 @@
|
|||
#define FOURIER_H_INCLUDED
|
||||
|
||||
void com_fourier(wordlist *wl);
|
||||
|
||||
|
||||
int fourier(wordlist *wl, struct plot *current);
|
||||
|
||||
#endif
|
||||
|
|
|
|||
Loading…
Reference in New Issue