pa-176
This commit is contained in:
parent
f506e53546
commit
5887fb8dff
|
|
@ -17,6 +17,7 @@
|
|||
#include "ngspice/fteext.h"
|
||||
#ifdef RFSPICE
|
||||
#include "vsrc/vsrcdefs.h" /* Enhancement-132: RF port fields (z0, ki, branch) */
|
||||
#include "isrc/isrcdefs.h" /* Enhancement-176: driven-mode source detection */
|
||||
#include "../maths/dense/dense.h" /* Enhancement-132: complex S = B*A^-1 */
|
||||
#include "../maths/dense/denseinlines.h"
|
||||
#endif
|
||||
|
|
@ -527,7 +528,11 @@ static int
|
|||
pac_choose_M(CKTcircuit *ckt, PSSan *job)
|
||||
{
|
||||
int K = ckt->CKTharms, N = job->PSSopMsize, M;
|
||||
M = (K - 1 < 3) ? (K - 1) : 3;
|
||||
/* Enhancement-176: honor the requested harmonic count (the old hard cap of
|
||||
* 3 sidebands silently truncated the conversion basis -- the +-2 sidebands
|
||||
* carried ~10% error with no way to buy accuracy). The dense-solve guard
|
||||
* below still bounds the matrix size. */
|
||||
M = K - 1;
|
||||
if (M < 1)
|
||||
return 0;
|
||||
while (M > 1 && (2*M + 1) * N > 400) /* dense-solve guard */
|
||||
|
|
@ -2955,6 +2960,7 @@ DCpss(CKTcircuit *ckt,
|
|||
double time_err_min_1 = 0, time_err_min_0 = 0, err_min_0 = HUGE_VAL, err_min_1 = 0 ;
|
||||
double err_1 = 0, err_max = HUGE_VAL ;
|
||||
int pss_points_cycle = 0, dynamic_test = 0 ;
|
||||
int pss_driven = 0 ; /* Enhancement-176: driven (non-autonomous) circuit */
|
||||
double gf_last_0 = HUGE_VAL, gf_last_1 = GF_LAST ;
|
||||
double thd = 0 ;
|
||||
double *psstimes, *pssvalues;
|
||||
|
|
@ -2990,6 +2996,52 @@ DCpss(CKTcircuit *ckt,
|
|||
PSSDBG( "PSS Stabilization Time %g\n", ckt->CKTstabTime) ;
|
||||
|
||||
|
||||
/* Enhancement-176: DRIVEN-mode detection. The Lannutti shooting was built
|
||||
* for autonomous oscillators: it hunts the fundamental frequency through a
|
||||
* fine forced-breakpoint grid whose spacing is proportional to
|
||||
* steady_coeff -- on a driven circuit at steady_coeff = 5e-6 that is a
|
||||
* sub-picosecond grid, i.e. millions of forced timesteps per shooting
|
||||
* cycle. But when the circuit contains a time-varying independent source
|
||||
* (a SIN/PULSE/... V or I source) the period is EXACTLY the source period:
|
||||
* no frequency estimation is needed, so the grid (and the estimator) is
|
||||
* skipped entirely and each shooting cycle runs at plain-transient speed.
|
||||
* The autonomous (oscillator) path is untouched. */
|
||||
{
|
||||
int vt = CKTtypelook("Vsource") ;
|
||||
int itk = CKTtypelook("Isource") ;
|
||||
if (vt >= 0 && ckt->CKThead [vt]) {
|
||||
VSRCmodel *vm ;
|
||||
VSRCinstance *vi ;
|
||||
for (vm = (VSRCmodel *) ckt->CKThead [vt] ; vm && !pss_driven ; vm = VSRCnextModel (vm))
|
||||
for (vi = VSRCinstances (vm) ; vi ; vi = VSRCnextInstance (vi))
|
||||
if (vi->VSRCfuncTGiven) { pss_driven = 1 ; break ; }
|
||||
}
|
||||
if (itk >= 0 && ckt->CKThead [itk] && !pss_driven) {
|
||||
ISRCmodel *im ;
|
||||
ISRCinstance *ii ;
|
||||
for (im = (ISRCmodel *) ckt->CKThead [itk] ; im && !pss_driven ; im = ISRCnextModel (im))
|
||||
for (ii = ISRCinstances (im) ; ii ; ii = ISRCnextInstance (ii))
|
||||
if (ii->ISRCfuncTGiven) { pss_driven = 1 ; break ; }
|
||||
}
|
||||
if (pss_driven) {
|
||||
/* Match the shooting-phase integration resolution to the sampling
|
||||
* resolution the user asked for (psspoints samples per period).
|
||||
* Without the (removed) breakpoint flood the LTE control would let
|
||||
* steps grow to CKTmaxStep = T/2, and the shooting then converges
|
||||
* to the fixed point of that COARSE discretization -- several
|
||||
* percent off the true orbit -- which the fine-stepped sampling
|
||||
* pass afterwards drifts away from (an inconsistent retained
|
||||
* period). One clamp keeps orbit and samples on the same
|
||||
* discretization; the cycle count is unchanged, so this is still
|
||||
* orders of magnitude faster than the grid flood. */
|
||||
double h_samp = (1.0 / ckt->CKTguessedFreq) / (double) ckt->CKTpsspoints ;
|
||||
if (ckt->CKTmaxStep > h_samp)
|
||||
ckt->CKTmaxStep = h_samp ;
|
||||
fprintf (stderr, "PSS: driven circuit detected -- shooting at the fixed source period (%g Hz), frequency estimation off\n",
|
||||
ckt->CKTguessedFreq) ;
|
||||
}
|
||||
}
|
||||
|
||||
oscnNode = job->PSSoscNode->number ;
|
||||
|
||||
|
||||
|
|
@ -3424,8 +3476,9 @@ DCpss(CKTcircuit *ckt,
|
|||
}
|
||||
err = sqrt (err) ;
|
||||
|
||||
/* Start frequency estimation */
|
||||
if ((err < err_0) && (ckt->CKTtime >= time_temp + 0.5 / ckt->CKTguessedFreq)) /* far enough from time temp... */
|
||||
/* Start frequency estimation (autonomous mode only) */
|
||||
if (!pss_driven &&
|
||||
(err < err_0) && (ckt->CKTtime >= time_temp + 0.5 / ckt->CKTguessedFreq)) /* far enough from time temp... */
|
||||
{
|
||||
if (err < err_min_0)
|
||||
{
|
||||
|
|
@ -3452,7 +3505,15 @@ DCpss(CKTcircuit *ckt,
|
|||
/* Force the tran analysis to evaluate requested breakpoints. Breakpoints are even more closer as
|
||||
the next occurence of guessed period is approaching. La lunga notte dei robot viventi... */
|
||||
|
||||
if ((ckt->CKTtime > time_temp + (1 / ckt->CKTguessedFreq) * 0.995) && (ckt->CKTtime <= time_temp + (1 / ckt->CKTguessedFreq)))
|
||||
|
||||
if (pss_driven)
|
||||
{
|
||||
/* Enhancement-176: the period is the exact source period; no
|
||||
* frequency estimation, so no mid-period breakpoint grid is
|
||||
* needed -- the cycle-end breakpoint is set by the shooting
|
||||
* logic below and the LTE control resolves the waveform. */
|
||||
}
|
||||
else if ((ckt->CKTtime > time_temp + (1 / ckt->CKTguessedFreq) * 0.995) && (ckt->CKTtime <= time_temp + (1 / ckt->CKTguessedFreq)))
|
||||
{
|
||||
offset = time_temp + (1 / ckt->CKTguessedFreq) * 0.995 ;
|
||||
interval = (1 / ckt->CKTguessedFreq) * (1 - 0.995) * (ckt->CKTsteady_coeff / 10) ;
|
||||
|
|
@ -3617,7 +3678,7 @@ DCpss(CKTcircuit *ckt,
|
|||
FREE (pssstates) ;
|
||||
return (E_PANIC) ; /* error macro in iferrmsg.h */
|
||||
}
|
||||
else if ((time_err_min_0 - time_temp) < 0)
|
||||
else if (!pss_driven && (time_err_min_0 - time_temp) < 0)
|
||||
{
|
||||
/* Something has gone wrong... */
|
||||
fprintf(stderr, "Error: Cannot find a minimum for error vector in estimated period. Try to adjust tstab! PSS analysis aborted\n") ;
|
||||
|
|
@ -3649,7 +3710,15 @@ DCpss(CKTcircuit *ckt,
|
|||
/***********************************/
|
||||
/*** FREQUENCY ESTIMATION UPDATE ***/
|
||||
/***********************************/
|
||||
if ((err_min_0 == err) || (err_min_0 == HUGE_VAL))
|
||||
if (pss_driven)
|
||||
{
|
||||
/* Enhancement-176: driven circuit -- the fundamental IS the
|
||||
* source frequency; no estimation. Rank the iteration history
|
||||
* by the period residual instead of the (meaningless here)
|
||||
* period-correction prediction. */
|
||||
predsum_history [shooting_cycle_counter] = err ;
|
||||
}
|
||||
else if ((err_min_0 == err) || (err_min_0 == HUGE_VAL))
|
||||
{
|
||||
/* Enters here if guessed frequency is higher than the 'real' value */
|
||||
ckt->CKTguessedFreq = 1 / (1 / ckt->CKTguessedFreq + fabs (predsum)) ;
|
||||
|
|
@ -3681,6 +3750,13 @@ DCpss(CKTcircuit *ckt,
|
|||
rr_history [shooting_cycle_counter] = err ;
|
||||
gf_history [shooting_cycle_counter] = ckt->CKTguessedFreq ;
|
||||
shooting_cycle_counter++ ;
|
||||
if (getenv("PSSTRACE"))
|
||||
fprintf(stderr, "[pss] cyc=%-3d t=%.6g gf=%.10g err=%.3e badnodes=%d predsum=%.3e pts=%d rej=%d nit=%d\n",
|
||||
shooting_cycle_counter - 1, ckt->CKTtime, ckt->CKTguessedFreq,
|
||||
err, excessive_err_nodes, predsum,
|
||||
ckt->CKTstat->STATtimePts, ckt->CKTstat->STATrejected,
|
||||
ckt->CKTstat->STATnumIter) ;
|
||||
|
||||
freq = eng(ckt->CKTguessedFreq, 10, TRUE, FALSE);
|
||||
PSSDBG( "Updated guessed frequency: %s Hz.\n", freq) ;
|
||||
tfree(freq);
|
||||
|
|
@ -3873,8 +3949,12 @@ shootingexit:
|
|||
}
|
||||
}
|
||||
|
||||
if (pssfreqs [position] != ckt->CKTguessedFreq)
|
||||
if (!pss_driven && pssfreqs [position] != ckt->CKTguessedFreq)
|
||||
{
|
||||
/* autonomous only: for a driven circuit the fundamental IS the
|
||||
* source frequency -- relaunching at the strongest spectral
|
||||
* line (e.g. a rectifier's dominant 2nd harmonic) would retain
|
||||
* the wrong period (Enhancement-176). */
|
||||
ckt->CKTguessedFreq = pssfreqs [position] ;
|
||||
fprintf(stdout, "\nThe predicted fundamental frequency is incorrect.\nRelaunching the analysis ") ;
|
||||
fprintf(stdout, "with new guessed fundamental frequency %.6g Hz\n\n", ckt->CKTguessedFreq) ;
|
||||
|
|
|
|||
Loading…
Reference in New Issue