This commit is contained in:
rlar 2012-12-17 20:53:12 +01:00
parent 41379c5aa4
commit c9cd174761
5 changed files with 99 additions and 65 deletions

View File

@ -6,8 +6,9 @@ struct pwl_state
double *arr;
int len;
int position;
int XrBreakpt;
int rBreakpt;
int rpt_cnt;
double td, tp;
};
#endif

View File

@ -22,33 +22,61 @@ Modified: 2000 Alansfixes
static double
pwl_state_get(struct pwl_state *this, double time)
{
double td = this->td;
double tp = this->tp;
int rBreakpt = this->rBreakpt;
/* fixme, enter mehrmals im sägezahn ...
* 1) optimier dafür
* 2) stelle sicher, dass das jeweils höchste timestamp zum zug kommt
* (allow step antwort *)
* invariant bei repeat:
* enter time < timof(last-point)
* this->position < indexof(last-point) (fixme really ? wenn es nur 2 points sind zB )
*/
/* fixme, einen warp einbauen wenns nicht passt ? */
for (;;) {
double t1 = this->arr[this->position + 0];
double t2 = this->arr[this->position + 2];
/* carefully exactly duplicate the math in vsrcacct .. */
volatile double t1 = this->arr[this->position + 0] + td + (this->rpt_cnt * tp);
volatile double t2 = this->arr[this->position + 2] + td + (this->rpt_cnt * tp);
double v1, v2;
if (time >= t2) {
if (this->position+4 >= this->len)
if (this->position+4 < this->len) {
this->position += 2;
continue;
}
if (tp == 0.0)
return this->arr[this->len-1];
this->position += 2;
/* actually a += 4 step, but the intermediate
* suffices t1 == t2
*/
this->position = rBreakpt;
this->rpt_cnt++;
continue;
}
if (time < t1) {
if (this->position == 0)
if (this->position > rBreakpt) { /*fixme must be 0 !! vfor non repeat*/
this->position -= 2;
continue;
}
if (tp == 0.0 || this->rpt_cnt == 0)
return this->arr[1];
this->position = 0;
/* actually a -= 4 step, but ... */
this->position = this->len - 4;
this->rpt_cnt--;
continue;
}
@ -66,10 +94,21 @@ static void
pwl_state_init(struct pwl_state *this, ISRCinstance *here)
{
#if 0
assert
( here->ISRCrGiven
? here->ISRCr >= 0 && here->ISRCrperiod > 0 && here->ISRCrBreakpt >= 0
: here->ISRCr == 0 && here->ISRCrperiod == 0 && here->ISRCrBreakpt == 0 );
#endif
this->len = here->ISRCfunctionOrder;
this->arr = here->ISRCcoeffs;
this->position = 0;
#warning "Baustelle, ..."
this->rpt_cnt = 0;
this->td = here->ISRCrdelay;
this->tp = here->ISRCrperiod;
this->rBreakpt = here->ISRCrBreakpt;
}
@ -348,26 +387,12 @@ ISRCload(GENmodel *inModel, CKTcircuit *ckt)
case PWL: {
struct pwl_state *state;
double td = here->ISRCrdelay;
double tp = here->ISRCrperiod;
double r = here->ISRCr;
if (!here->ISRC_state) {
here->ISRC_state = TMALLOC(struct pwl_state, 1);
pwl_state_init((struct pwl_state *) here->ISRC_state, here);
}
state = (struct pwl_state *) here -> ISRC_state;
/* fixme repeat value ignored */
if (here->ISRCrGiven && time - td - r >= 0) {
double t = fmod(time - td - r, tp) + r;
value = pwl_state_get(state, t);
} else {
value = pwl_state_get(state, time - td);
}
value = pwl_state_get((struct pwl_state *) here -> ISRC_state, time);
}
break;

View File

@ -105,12 +105,13 @@ ISRCparam(int param, IFvalue *value, GENinstance *inst, IFvalue *select)
copy_coeffs(here, value);
for (i=0; i<(here->ISRCfunctionOrder/2)-1; i++) {
/* fixme identical soll erlaubt werden */
if (*(here->ISRCcoeffs+2*(i+1))<=*(here->ISRCcoeffs+2*i)) {
fprintf(stderr, "Warning : current source %s",
here->ISRCname);
fprintf(stderr, " has non-increasing PWL time points.\n");
}
if (here->ISRCcoeffs[2*i + 2] < here->ISRCcoeffs[2*i]) {
fprintf(stderr,
"ERROR: current source %s,"
" PWL time stamps are not allowed to decrease.\n",
here->ISRCname);
return(E_PARMVAL);
}
}
break;
@ -120,28 +121,30 @@ ISRCparam(int param, IFvalue *value, GENinstance *inst, IFvalue *select)
break;
case ISRC_R: {
double end_time;
here->ISRCr = value->rValue;
here->ISRCrGiven = TRUE;
double Tr = value->rValue;
double Tperiod;
for ( i = 0; i < here->ISRCfunctionOrder; i += 2 ) {
here->ISRCrBreakpt = i;
if ( here->ISRCr == *(here->ISRCcoeffs+i) ) break;
for ( i = 0; i < here->ISRCfunctionOrder; i += 2 )
if ( Tr == here->ISRCcoeffs[i] )
break;
if (i == here->ISRCfunctionOrder) {
fprintf(stderr, "ERROR: repeat start time value %g for pwl current source does not match any time point given!\n", Tr );
return ( E_PARMVAL );
}
end_time = *(here->ISRCcoeffs + here->ISRCfunctionOrder-2);
/* actually ok, würde stationaer bedeuten ... und ist so gut wie no repeat */
if ( here->ISRCr > end_time ) {
fprintf(stderr, "ERROR: repeat start time value %g for pwl voltage source must be smaller than final time point given!\n", here->ISRCr );
return ( E_PARMVAL );
Tperiod =
here->ISRCcoeffs[here->ISRCfunctionOrder-2] - Tr;
if (Tperiod == 0.0) {
fprintf(stderr, "ERROR: repeat start time value %g for pwl voltage source would cause a period of 0\n", Tr );
return ( E_PARMVAL );
}
if ( here->ISRCr != *(here->ISRCcoeffs+here->ISRCrBreakpt) ) {
fprintf(stderr, "ERROR: repeat start time value %g for pwl voltage source does not match any time point given!\n", here->ISRCr );
return ( E_PARMVAL );
}
here ->ISRCrperiod = end_time - here->ISRCcoeffs[here->ISRCrBreakpt];
here->ISRCrGiven = TRUE;
here->ISRCr = Tr;
here->ISRCrperiod = Tperiod;
here->ISRCrBreakpt = i;
}
break;

View File

@ -20,8 +20,13 @@ Modified: 2000 AlansFixes
static double
pwl_state_get(struct pwl_state *this, double time, double td, double tp, int XrBreakpt)
pwl_state_get(struct pwl_state *this, double time)
{
double td = this->td;
double tp = this->tp;
int rBreakpt = this->rBreakpt;
/* fixme, enter mehrmals im sägezahn ...
* 1) optimier dafür
* 2) stelle sicher, dass das jeweils höchste timestamp zum zug kommt
@ -54,13 +59,13 @@ pwl_state_get(struct pwl_state *this, double time, double td, double tp, int XrB
* suffices t1 == t2
*/
this->position = XrBreakpt;
this->position = rBreakpt;
this->rpt_cnt++;
continue;
}
if (time < t1) {
if (this->position > XrBreakpt) { /*fixme must be 0 !! vfor non repeat*/
if (this->position > rBreakpt) {
this->position -= 2;
continue;
}
@ -89,10 +94,21 @@ static void
pwl_state_init(struct pwl_state *this, VSRCinstance *here)
{
#if 0
assert
( here->VSRCrGiven
? here->VSRCr >= 0 && here->VSRCrperiod > 0 && here->VSRCrBreakpt >= 0
: here->VSRCr == 0 && here->VSRCrperiod == 0 && here->VSRCrBreakpt == 0 );
#endif
this->len = here->VSRCfunctionOrder;
this->arr = here->VSRCcoeffs;
this->position = 0;
this->rpt_cnt = 0;
this->td = here->VSRCrdelay;
this->tp = here->VSRCrperiod;
this->rBreakpt = here->VSRCrBreakpt;
}
@ -371,23 +387,12 @@ VSRCload(GENmodel *inModel, CKTcircuit *ckt)
case PWL: {
struct pwl_state *state;
double td = here->VSRCrdelay;
double tp = here->VSRCrperiod;
if (!here->VSRC_state) {
here->VSRC_state = TMALLOC(struct pwl_state, 1);
pwl_state_init((struct pwl_state *) here->VSRC_state, here);
}
state = (struct pwl_state *) here -> VSRC_state;
if (here->VSRCrGiven) {
value = pwl_state_get(state, time, td, tp, here->VSRCrBreakpt);
} else {
value = pwl_state_get(state, time, td, 0.0, 0);
}
value = pwl_state_get((struct pwl_state *) here -> VSRC_state, time);
}
break;

View File

@ -107,10 +107,10 @@ VSRCparam(int param, IFvalue *value, GENinstance *inst, IFvalue *select)
for (i=0; i<(here->VSRCfunctionOrder/2)-1; i++) {
if (here->VSRCcoeffs[2*i + 2] < here->VSRCcoeffs[2*i]) {
fprintf(stderr,
"Warning : voltage source %s"
" has non-increasing PWL time points.\n",
"ERROR: voltage source %s,"
" PWL time stamps are not allowed to decrease.\n",
here->VSRCname);
break;
return(E_PARMVAL);
}
}