parent
4005a956a8
commit
80a9eb3909
|
|
@ -26,6 +26,20 @@ typedef struct {
|
|||
runDesc *PSSplot_fd;
|
||||
int sc_iter;
|
||||
double steady_coeff;
|
||||
|
||||
/* Enhancement-119: the converged periodic operating point, retained past the
|
||||
* analysis as the substrate the periodic small-signal analyses (PAC / pnoise
|
||||
* / PXF) linearize around. PSS already samples the node voltages over one
|
||||
* period for its DFT but frees them; here they -- and the device states,
|
||||
* which the reactive Jacobian C(t) needs -- are kept on the job. Row-major
|
||||
* per sample: [unknown + sample*PSSopMsize] and [state + sample*PSSopNumStates]. */
|
||||
long PSSopPoints; /* number of time samples over one period */
|
||||
int PSSopMsize; /* matrix size (nodes + branch currents) */
|
||||
int PSSopNumStates; /* CKTnumStates captured per sample */
|
||||
double PSSopFreq; /* converged fundamental frequency (Hz) */
|
||||
double *PSSopTimes; /* [PSSopPoints] sample times across the period */
|
||||
double *PSSopVoltages; /* [PSSopMsize * PSSopPoints] node voltages per sample */
|
||||
double *PSSopStates; /* [PSSopNumStates * PSSopPoints] device states per sample */
|
||||
} PSSan;
|
||||
|
||||
enum {
|
||||
|
|
|
|||
|
|
@ -114,6 +114,7 @@ DCpss(CKTcircuit *ckt,
|
|||
double gf_last_0 = HUGE_VAL, gf_last_1 = GF_LAST ;
|
||||
double thd = 0 ;
|
||||
double *psstimes, *pssvalues;
|
||||
double *pssstates; /* Enhancement-119: device states captured per PSS sample */
|
||||
double *RHS_max, *RHS_min, *err_conv ;
|
||||
|
||||
/* Francesco Lannutti's MOD */
|
||||
|
|
@ -175,6 +176,9 @@ DCpss(CKTcircuit *ckt,
|
|||
|
||||
psstimes = TMALLOC (double, ckt->CKTpsspoints + 1) ;
|
||||
pssvalues = TMALLOC (double, msize * (ckt->CKTpsspoints + 1)) ;
|
||||
/* Enhancement-119: also capture the device states (charges/fluxes) per
|
||||
* sample -- CKTstate0 holds the accepted state alongside CKTrhsOld. */
|
||||
pssstates = TMALLOC (double, ckt->CKTnumStates * (ckt->CKTpsspoints + 1)) ;
|
||||
|
||||
for (i = 0 ; i < ckt->CKTpsspoints + 1 ; i++)
|
||||
psstimes [i] = 0.0 ;
|
||||
|
|
@ -182,6 +186,9 @@ DCpss(CKTcircuit *ckt,
|
|||
for (i = 0 ; i < msize * (ckt->CKTpsspoints + 1) ; i++)
|
||||
pssvalues [i] = 0.0 ;
|
||||
|
||||
for (i = 0 ; i < ckt->CKTnumStates * (ckt->CKTpsspoints + 1) ; i++)
|
||||
pssstates [i] = 0.0 ;
|
||||
|
||||
/* Delta timestep and circuit time setup */
|
||||
delta = ckt->CKTstep ;
|
||||
ckt->CKTtime = 0;
|
||||
|
|
@ -463,6 +470,10 @@ DCpss(CKTcircuit *ckt,
|
|||
for (i = 1 ; i <= msize ; i++)
|
||||
pssvalues [i - 1 + pss_points_cycle * msize] = ckt->CKTrhsOld [i] ;
|
||||
|
||||
/* Enhancement-119: capture the device states at this sample */
|
||||
memcpy (pssstates + (size_t)pss_points_cycle * ckt->CKTnumStates,
|
||||
ckt->CKTstate0, (size_t)ckt->CKTnumStates * sizeof(double)) ;
|
||||
|
||||
/* Update PSS counter cycle, used to stop the entire algorithm */
|
||||
pss_points_cycle++ ;
|
||||
|
||||
|
|
@ -759,7 +770,8 @@ DCpss(CKTcircuit *ckt,
|
|||
FREE (err_conv) ;
|
||||
FREE (psstimes) ;
|
||||
FREE (pssvalues) ;
|
||||
return (E_ERR_PSS) ; /* error macro in iferrmsg.h */
|
||||
FREE (pssstates) ;
|
||||
return (E_PANIC) ; /* error macro in iferrmsg.h */
|
||||
}
|
||||
else if ((time_err_min_0 - time_temp) < 0)
|
||||
{
|
||||
|
|
@ -775,6 +787,7 @@ DCpss(CKTcircuit *ckt,
|
|||
FREE (err_conv) ;
|
||||
FREE (psstimes) ;
|
||||
FREE (pssvalues) ;
|
||||
FREE (pssstates) ;
|
||||
return (E_PANIC) ; /* to be corrected with definition of new error macro in iferrmsg.h */
|
||||
}
|
||||
|
||||
|
|
@ -902,6 +915,10 @@ shootingexit:
|
|||
for (i = 1 ; i <= msize ; i++)
|
||||
pssvalues [i - 1 + pss_points_cycle * msize] = ckt->CKTrhsOld [i] ;
|
||||
|
||||
/* Enhancement-119: capture the device states at the first sample */
|
||||
memcpy (pssstates + (size_t)pss_points_cycle * ckt->CKTnumStates,
|
||||
ckt->CKTstate0, (size_t)ckt->CKTnumStates * sizeof(double)) ;
|
||||
|
||||
/* Update the PSS points counter and set the next Breakpoint */
|
||||
pss_points_cycle++ ;
|
||||
CKTsetBreak (ckt, time_temp + (1 / ckt->CKTguessedFreq) * ((double)pss_points_cycle / (double)ckt->CKTpsspoints)) ;
|
||||
|
|
@ -1018,6 +1035,49 @@ shootingexit:
|
|||
PSSDBG( "The predicted fundamental frequency is incorrect.\nRelaunching the analysis...\n\n") ;
|
||||
PSSDBG( "The new guessed fundamental frequency is: %.6g\n\n", ckt->CKTguessedFreq) ;
|
||||
DCpss (ckt, 1) ;
|
||||
/* the relaunched run retained its own (correct) operating point;
|
||||
* this run's samples are stale -- fall through and free them. */
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Enhancement-119: frequency confirmed -- retain this converged
|
||||
* periodic operating point on the job for periodic small-signal
|
||||
* reuse (PAC/pnoise/PXF). Ownership of the sample arrays is
|
||||
* transferred to the job (set local ptrs NULL so the FREE below
|
||||
* is a no-op); the DFT that produced the harmonic output above
|
||||
* was taken from exactly these samples, so they are self-consistent. */
|
||||
FREE (job->PSSopTimes) ;
|
||||
FREE (job->PSSopVoltages) ;
|
||||
FREE (job->PSSopStates) ;
|
||||
job->PSSopPoints = ckt->CKTpsspoints ;
|
||||
job->PSSopMsize = msize ;
|
||||
job->PSSopNumStates = ckt->CKTnumStates ;
|
||||
job->PSSopFreq = ckt->CKTguessedFreq ;
|
||||
job->PSSopTimes = psstimes ; psstimes = NULL ;
|
||||
job->PSSopVoltages = pssvalues ; pssvalues = NULL ;
|
||||
job->PSSopStates = pssstates ; pssstates = NULL ;
|
||||
fprintf (stderr, "PSS periodic operating point retained: %ld samples x "
|
||||
"%d unknowns x %d states at f = %.10g Hz\n",
|
||||
job->PSSopPoints, job->PSSopMsize, job->PSSopNumStates,
|
||||
job->PSSopFreq) ;
|
||||
|
||||
/* Self-check: report the osc-node voltage swing straight from the
|
||||
* retained samples, so the retained data can be validated without
|
||||
* a consumer yet (a periodic node must swing over the period). */
|
||||
{
|
||||
int onode = job->PSSoscNode ? job->PSSoscNode->number : 0 ;
|
||||
if (onode > 0 && onode <= job->PSSopMsize) {
|
||||
double vmin = HUGE_VAL, vmax = -HUGE_VAL ;
|
||||
long s ;
|
||||
for (s = 0 ; s < job->PSSopPoints ; s++) {
|
||||
double v = job->PSSopVoltages [(onode - 1) + s * job->PSSopMsize] ;
|
||||
if (v < vmin) vmin = v ;
|
||||
if (v > vmax) vmax = v ;
|
||||
}
|
||||
fprintf (stderr, " retained op-point self-check: osc-node swing "
|
||||
"[%.6g, %.6g] over the period\n", vmin, vmax) ;
|
||||
}
|
||||
}
|
||||
}
|
||||
/****************************/
|
||||
|
||||
|
|
@ -1037,6 +1097,7 @@ shootingexit:
|
|||
FREE (err_conv) ;
|
||||
FREE (psstimes) ;
|
||||
FREE (pssvalues) ;
|
||||
FREE (pssstates) ;
|
||||
ckt->CKTag[0] = ckt->CKTag[1] = 0.;
|
||||
return (OK) ;
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue