From 04507a637d745136bd8b238e68e68c1b559d852c Mon Sep 17 00:00:00 2001 From: Enrique Date: Thu, 26 Feb 2026 22:39:34 +0100 Subject: [PATCH] Added parameter numPeriod so that the user can select the number of fundamental frequency periods used in the detection of the fundamental frequency and its harmonics. This is usefull when trying to recover the fundamental frequency and its harmonics from a noisy signal, like the output of a DCDC converter --- src/frontend/fourier.c | 36 +++++++++++++++++++++--------------- 1 file changed, 21 insertions(+), 15 deletions(-) diff --git a/src/frontend/fourier.c b/src/frontend/fourier.c index d66efe3ee..5754700a3 100644 --- a/src/frontend/fourier.c +++ b/src/frontend/fourier.c @@ -23,7 +23,7 @@ Author: 1985 Wayne A. Christopher, U. C. Berkeley CAD Group static char *pnum(double num); -static int CKTfour(int ndata, int numFreq, double *thd, double *Time, double *Value, +static int CKTfour(int ndata, int numFreq, int numPeriod, double *thd, double *Time, double *Value, double FundFreq, double *Freq, double *Mag, double *Phase, double *nMag, double *nPhase); @@ -32,8 +32,8 @@ 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 +/* CKTfour(ndata, numFreq, numPeriod, thd, Time, Value, FundFreq, Freq, Mag, Phase, nMag, nPhase) + * len 10 1 ? inp inp inp out out out out out */ int @@ -42,7 +42,7 @@ fourier(wordlist *wl, struct plot *current_plot) struct dvec *time, *vec; struct pnode *pn, *names; double fundfreq, *data = NULL; - int nfreqs, fourgridsize, polydegree; + int nfreqs, nperiods, fourgridsize, polydegree; double *freq, *mag, *phase, *nmag, *nphase; /* Outputs from CKTfour */ double thd, *timescale = NULL; char *s; @@ -68,6 +68,8 @@ fourier(wordlist *wl, struct plot *current_plot) if (!cp_getvar("nfreqs", CP_NUM, &nfreqs, 0) || nfreqs < 1) nfreqs = 10; + if (!cp_getvar("nperiods", CP_NUM, &nperiods, 0) || nperiods < 1) + nperiods = 1; if (!cp_getvar("polydegree", CP_NUM, &polydegree, 0) || polydegree < 0) polydegree = 1; if (!cp_getvar("fourgridsize", CP_NUM, &fourgridsize, 0) || fourgridsize < 1) @@ -112,14 +114,16 @@ fourier(wordlist *wl, struct plot *current_plot) if (polydegree) { double *dp, d; + /* Get fourgridsize points per period */ + fourgridsize = fourgridsize * nperiods; /* Build the grid... */ timescale = TMALLOC(double, fourgridsize); data = TMALLOC(double, fourgridsize); dp = ft_minmax(time, TRUE); /* Now get the last fund freq... */ - d = 1 / fundfreq; /* The wavelength... */ + d = nperiods / fundfreq; /* The wavelength... */ if (dp[1] - dp[0] < d) { - fprintf(cp_err, "Error: wavelength longer than time span\n"); + fprintf(cp_err, "Error: (%d * wavelength) longer than time span\n", nperiods); goto done; } else if (dp[1] - dp[0] > d) { dp[0] = dp[1] - d; @@ -143,7 +147,7 @@ fourier(wordlist *wl, struct plot *current_plot) timescale = time->v_realdata; } - err = CKTfour(fourgridsize, nfreqs, &thd, timescale, + err = CKTfour(fourgridsize, nfreqs, nperiods, &thd, timescale, data, fundfreq, freq, mag, phase, nmag, nphase); if (err != OK) { @@ -153,9 +157,10 @@ fourier(wordlist *wl, struct plot *current_plot) fprintf(cp_out, "Fourier analysis for %s:\n", vec->v_name); fprintf(cp_out, - " No. Harmonics: %d, THD: %g %%, Gridsize: %d, Interpolation Degree: %d\n\n", + " No. Harmonics: %d, THD: %g %%, Gridsize: %d, Interpolation Degree: %d," + " No. Periods: %d\n\n", nfreqs, thd, fourgridsize, - polydegree); + polydegree, nperiods); /* Each field will have width cp_numdgt + 6 (or 7 * with HP-UX) + 1 if there is a - sign. */ @@ -288,6 +293,7 @@ static int CKTfour(int ndata, /* number of entries in the Time and Value arrays */ int numFreq, /* number of harmonics to calculate */ + int numPeriod, /* number of periods for detection */ double *thd, /* total harmonic distortion (percent) to be returned */ double *Time, /* times at which the voltage/current @@ -313,10 +319,10 @@ CKTfour(int ndata, /* number of entries in the Time and * 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. + * fourier transform to be useful. The function will take + * numPeriod periods of the frequency as data for the transform. * - * We are assuming that the caller has provided exactly one period + * We are assuming that the caller has provided exactly numPeriod periods * of the fundamental frequency. */ int i; int j; @@ -331,10 +337,10 @@ CKTfour(int ndata, /* number of entries in the Time and Phase[i] = 0; } - for (i = 0; i < ndata; i++) + for (i = 0; i < ndata ; i++) for (j = 0; j < numFreq; j++) { - Mag[j] += Value[i] * sin(j*2.0*M_PI*i/((double)ndata)); - Phase[j] += Value[i] * cos(j*2.0*M_PI*i/((double)ndata)); + Mag[j] += Value[i] * sin(j*2.0*M_PI*numPeriod*i/((double)ndata)); + Phase[j] += Value[i] * cos(j*2.0*M_PI*numPeriod*i/((double)ndata)); } Mag[0] = Phase[0]/ndata;