angefangene vsrc baustelle

wip, versuch eines PWL vsrc rewrites
This commit is contained in:
Robert Larice 2012-12-17 20:58:02 +01:00 committed by rlar
parent a8619e1756
commit 53a0963632
4 changed files with 136 additions and 43 deletions

View File

@ -165,22 +165,75 @@ VSRCaccept(CKTcircuit *ckt, GENmodel *inModel)
break;
case PWL: {
int i;
if(ckt->CKTtime < *(here->VSRCcoeffs)) {
double td = here->VSRCrdelay;
double tp = here->VSRCrperiod;
volatile double bp;
if (ckt->CKTtime < here->VSRCcoeffs [0] + td) {
here->nxt = 0;
here->rpt = 0;
if(ckt->CKTbreak) {
error = CKTsetBreak(ckt,*(here->VSRCcoeffs));
error = CKTsetBreak(ckt, here->VSRCcoeffs [0] + td);
break;
}
}
for(i=0;i<(here->VSRCfunctionOrder/2)-1;i++) {
if ( ckt->CKTbreak && AlmostEqualUlps(*(here->VSRCcoeffs+2*i), ckt->CKTtime, 3 ) ) {
error = CKTsetBreak(ckt, *(here->VSRCcoeffs+2*i+2));
if(error) return(error);
goto bkptset;
/* check td + first >= 0 */
/*
* Postition:
* nxt = [0, order[
* rpt = [0.. [
* with
* time == arr[nxt] + rpt*period + td
*
* (fixme, no thats inclusive see above)
*
* evtl ==order als Ende Kriterium, !!! must
*/
/* (libc) Remainder Functions, `same sign ...' and magnitude ... */
#if 0
if (repeat && (time > tstart))
rest = tstart + fmod(time - tstart, period);
else
rest = time;
#endif
if (!ckt->CKTbreak || here->nxt >= here->VSRCfunctionOrder)
break;
bp = here->VSRCcoeffs[here->nxt] + td + (here->rpt * tp);
if (!AlmostEqualUlps(bp, ckt->CKTtime, 3))
break;
for (;;) {
volatile double t;
here->nxt += 2;
if (here->nxt >= here->VSRCfunctionOrder) {
if (!here->VSRCrGiven)
break;
here->nxt = here->VSRCrBreakpt;
here->rpt++;
}
t = here->VSRCcoeffs[here->nxt] + td + (here->rpt * tp);
/* CKTtime isn't exactly identical to bp, thus ... */
if (t <= ckt->CKTtime || t <= bp)
continue;
bp = t;
error = CKTsetBreak(ckt, bp);
if (error)
return(error);
break;
}
break;
}
break;
/**** tansient noise routines:
VNoi2 2 0 DC 0 TRNOISE(10n 0.5n 0 0n) : generate gaussian distributed noise
@ -289,7 +342,6 @@ VSRCaccept(CKTcircuit *ckt, GENmodel *inModel)
} // switch
} // if ... else
bkptset: ;
} // for
} // for

View File

@ -52,9 +52,12 @@ typedef struct sVSRCinstance {
struct trnoise_state *VSRCtrnoise_state; /* transient noise */
struct trrandom_state *VSRCtrrandom_state; /* transient random source */
struct pwl_state *VSRC_state;
int nxt, rpt;
double VSRCr; /* pwl repeat */
double VSRCrdelay; /* pwl delay period */
double VSRCrperiod;
double *VSRCposIbrptr; /* pointer to sparse matrix element at
* (positive node, branch equation) */
double *VSRCnegIbrptr; /* pointer to sparse matrix element at
@ -78,6 +81,15 @@ typedef struct sVSRCinstance {
} VSRCinstance ;
struct pwl_state
{
double *arr;
int len;
int position;
int bpoint;
};
/* per model data */
typedef struct sVSRCmodel {

View File

@ -18,6 +18,55 @@ Modified: 2000 AlansFixes
/* gtri - end - wbk - modify for supply ramping option */
#endif
static double
pwl_state_get(struct pwl_state *this, double time)
{
for (;;) {
double t1 = this->arr[this->position + 0];
double t2 = this->arr[this->position + 2];
double v1, v2;
if (time >= t2) {
if (this->position+4 >= this->len)
return this->arr[this->len-1];
this->position += 2;
continue;
}
if (time < t1) {
if (this->position == 0)
return this->arr[1];
this->position = 0;
continue;
}
/* invariant: t1 <= time < t2 ==> t1 != t2 */
v1 = this->arr[this->position + 1];
v2 = this->arr[this->position + 3];
return v1 + ((v2-v1)/(t2-t1)) * (time - t1);
}
}
static void
pwl_state_init(struct pwl_state *this, VSRCinstance *here)
{
this->len = here->VSRCfunctionOrder;
this->arr = here->VSRCcoeffs;
this->position = 0;
this->bpoint = 0;
}
/*-----------------------------------------------------------------------------*/
int
VSRCload(GENmodel *inModel, CKTcircuit *ckt)
/* actually load the current value into the
@ -289,45 +338,22 @@ VSRCload(GENmodel *inModel, CKTcircuit *ckt)
break;
case PWL: {
int i = 0, num_repeat = 0, ii = 0;
double foo, repeat_time = 0, end_time, breakpt_time, itime;
time -= here->VSRCrdelay;
struct pwl_state *state;
if(time < *(here->VSRCcoeffs)) {
foo = *(here->VSRCcoeffs + 1) ;
value = foo;
goto loadDone;
if (!here->VSRC_state) {
here->VSRC_state = TMALLOC(struct pwl_state, 1);
pwl_state_init((struct pwl_state *) here->VSRC_state, here);
}
do {
for(i=ii ; i<(here->VSRCfunctionOrder/2)-1; i++ ) {
itime = *(here->VSRCcoeffs+2*i);
if ( AlmostEqualUlps(itime+repeat_time, time, 3 )) {
foo = *(here->VSRCcoeffs+2*i+1);
value = foo;
goto loadDone;
} else if ( (*(here->VSRCcoeffs+2*i)+repeat_time < time)
&& (*(here->VSRCcoeffs+2*(i+1))+repeat_time > time) ) {
foo = *(here->VSRCcoeffs+2*i+1) + (((time-(*(here->VSRCcoeffs+2*i)+repeat_time))/
(*(here->VSRCcoeffs+2*(i+1)) - *(here->VSRCcoeffs+2*i))) *
(*(here->VSRCcoeffs+2*i+3) - *(here->VSRCcoeffs+2*i+1)));
value = foo;
goto loadDone;
}
}
foo = *(here->VSRCcoeffs+ here->VSRCfunctionOrder-1) ;
value = foo;
state = (struct pwl_state *) here -> VSRC_state;
if ( !here->VSRCrGiven ) goto loadDone;
/* fixme repeat value ignored */
value = pwl_state_get(state, time - here->VSRCrdelay);
end_time = *(here->VSRCcoeffs + here->VSRCfunctionOrder-2);
breakpt_time = *(here->VSRCcoeffs + here->VSRCrBreakpt);
repeat_time = end_time + (end_time - breakpt_time)*num_repeat++ - breakpt_time;
ii = here->VSRCrBreakpt/2;
} while ( here->VSRCrGiven );
break;
goto loadDone;
}
break;
/**** tansient noise routines:
VNoi2 2 0 DC 0 TRNOISE(10n 0.5n 0 0n) : generate gaussian distributed noise

View File

@ -105,6 +105,7 @@ VSRCparam(int param, IFvalue *value, GENinstance *inst, IFvalue *select)
copy_coeffs(here, value);
for (i=0; i<(here->VSRCfunctionOrder/2)-1; i++) {
/* fixme identical soll erlaubt werden */
if (*(here->VSRCcoeffs+2*(i+1))<=*(here->VSRCcoeffs+2*i)) {
fprintf(stderr, "Warning : voltage source %s",
here->VSRCname);
@ -129,6 +130,7 @@ VSRCparam(int param, IFvalue *value, GENinstance *inst, IFvalue *select)
}
end_time = *(here->VSRCcoeffs + here->VSRCfunctionOrder-2);
/* actually ok, würde stationaer bedeuten ... und ist so gut wie no repeat */
if ( here->VSRCr > end_time ) {
fprintf(stderr, "ERROR: repeat start time value %g for pwl voltage source must be smaller than final time point given!\n", here->VSRCr );
return ( E_PARMVAL );
@ -139,8 +141,9 @@ VSRCparam(int param, IFvalue *value, GENinstance *inst, IFvalue *select)
return ( E_PARMVAL );
}
break;
here ->VSRCrperiod = end_time - here->VSRCcoeffs[here->VSRCrBreakpt];
}
break;
case VSRC_SFFM:
if(value->v.numValue < 2)