Neew pswitch with patch 0001-pswitch-fix.patch from Jube 3rd, 21 at
https://sourceforge.net/p/ngspice/discussion/127605/thread/d55d2322f2/#c966/b802/4764/2540/3b3f/04a4/bc51/3a68 Input resistance, numerically computed derivatives with auto-partial, reasonable limits.
This commit is contained in:
parent
5cc5e351f1
commit
d36fcaf34c
|
|
@ -139,6 +139,7 @@ void cm_pswitch(ARGS) /* structure holding parms,
|
||||||
double cntl_off; /* voltage below the switch has resistance roff */
|
double cntl_off; /* voltage below the switch has resistance roff */
|
||||||
double r_on; /* on resistance */
|
double r_on; /* on resistance */
|
||||||
double r_off; /* off resistance */
|
double r_off; /* off resistance */
|
||||||
|
double r_cntl_in; /* input resistance for control terminal */
|
||||||
double logmean; /* log-mean of resistor values */
|
double logmean; /* log-mean of resistor values */
|
||||||
double logratio; /* log-ratio of resistor values */
|
double logratio; /* log-ratio of resistor values */
|
||||||
double cntl_mean; /* mean of control values */
|
double cntl_mean; /* mean of control values */
|
||||||
|
|
@ -153,7 +154,7 @@ void cm_pswitch(ARGS) /* structure holding parms,
|
||||||
|
|
||||||
Mif_Complex_t ac_gain;
|
Mif_Complex_t ac_gain;
|
||||||
|
|
||||||
char *cntl_error = "\n*****ERROR*****\nPSWITCH: CONTROL voltage delta less than 1.0e-12\n";
|
|
||||||
|
|
||||||
Local_Data_t *loc; /* Pointer to local static data, not to be included
|
Local_Data_t *loc; /* Pointer to local static data, not to be included
|
||||||
in the state vector */
|
in the state vector */
|
||||||
|
|
@ -165,15 +166,19 @@ void cm_pswitch(ARGS) /* structure holding parms,
|
||||||
cntl_off = PARAM(cntl_off);
|
cntl_off = PARAM(cntl_off);
|
||||||
r_on = PARAM(r_on);
|
r_on = PARAM(r_on);
|
||||||
r_off = PARAM(r_off);
|
r_off = PARAM(r_off);
|
||||||
|
r_cntl_in = PARAM(r_cntl_in);
|
||||||
|
|
||||||
if( r_on < 1.0e-3 ) r_on = 1.0e-3; /* Set minimum 'ON' resistance */
|
r_on = (r_on < 1.0e-3) ? 1.0e-3 : r_on; /* Set minimum 'ON' resistance */
|
||||||
|
r_off = (r_off > 1.0e12) ? 1.0e12 : r_off; /* Set maximum 'OFF' resistance */
|
||||||
|
|
||||||
if( (fabs(cntl_on - cntl_off) < 1.0e-12) ) {
|
|
||||||
cm_message_send(cntl_error);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(INIT == 1) { /* first time through, allocate memory, set static parameters */
|
if(INIT == 1) { /* first time through, allocate memory, set static parameters */
|
||||||
|
char *cntl_error = "\n*****ERROR*****\nPSWITCH: CONTROL voltage delta less than 1.0e-12\n";
|
||||||
|
|
||||||
|
if( (fabs(cntl_on - cntl_off) < 1.0e-12) ) {
|
||||||
|
cm_message_send(cntl_error);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
CALLBACK = cm_pswitch_callback;
|
CALLBACK = cm_pswitch_callback;
|
||||||
|
|
||||||
|
|
@ -182,13 +187,24 @@ void cm_pswitch(ARGS) /* structure holding parms,
|
||||||
loc = STATIC_VAR (locdata);
|
loc = STATIC_VAR (locdata);
|
||||||
|
|
||||||
if ( PARAM(log) == MIF_TRUE ) { /* Logarithmic Variation in 'R' */
|
if ( PARAM(log) == MIF_TRUE ) { /* Logarithmic Variation in 'R' */
|
||||||
|
if (cntl_on > cntl_off)
|
||||||
|
{
|
||||||
|
cntl_on = 1;
|
||||||
|
cntl_off = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
cntl_on = 0;
|
||||||
|
cntl_off = 1;
|
||||||
|
}
|
||||||
|
|
||||||
loc->logmean = log(sqrt(r_on * r_off));
|
loc->logmean = log(sqrt(r_on * r_off));
|
||||||
loc->logratio = log(r_on / r_off);
|
loc->logratio = log(r_on / r_off);
|
||||||
loc->cntl_mean = (cntl_on + cntl_off) / 2.;
|
loc->cntl_mean = 0.5;
|
||||||
loc->cntl_diff = cntl_on - cntl_off;
|
loc->cntl_diff = cntl_on - cntl_off;
|
||||||
loc->intermediate = loc->logratio / loc->cntl_diff;
|
loc->intermediate = loc->logratio / loc->cntl_diff;
|
||||||
loc->c1 = 1.5 * loc->logratio / loc->cntl_diff;
|
loc->c1 = 1.5 * loc->logratio / loc->cntl_diff;
|
||||||
loc->c3 = 2. * loc->logratio / pow(loc->cntl_diff, 3);
|
loc->c3 = 2. * loc->logratio / (loc->cntl_diff * loc->cntl_diff * loc->cntl_diff); //pow(loc->cntl_diff, 3);
|
||||||
loc->c2 = 3 * loc->c3;
|
loc->c2 = 3 * loc->c3;
|
||||||
} else {
|
} else {
|
||||||
loc->cntl_diff = cntl_on - cntl_off;
|
loc->cntl_diff = cntl_on - cntl_off;
|
||||||
|
|
@ -204,37 +220,42 @@ void cm_pswitch(ARGS) /* structure holding parms,
|
||||||
cntl_mean = loc->cntl_mean;
|
cntl_mean = loc->cntl_mean;
|
||||||
cntl_diff = loc->cntl_diff;
|
cntl_diff = loc->cntl_diff;
|
||||||
intermediate = loc->intermediate;
|
intermediate = loc->intermediate;
|
||||||
double inmean = INPUT(cntl_in) - cntl_mean;
|
double inmean;// = INPUT(cntl_in) - cntl_mean;
|
||||||
if (cntl_on >= cntl_off) {
|
int outOfLimit = 0;
|
||||||
if (INPUT(cntl_in) >= cntl_on) {
|
if (cntl_on > cntl_off) {
|
||||||
|
inmean = ((INPUT(cntl_in) - PARAM(cntl_off)) / (PARAM(cntl_on) - PARAM(cntl_off))) - cntl_mean;
|
||||||
|
if (INPUT(cntl_in) > cntl_on) {
|
||||||
r = r_on;
|
r = r_on;
|
||||||
|
outOfLimit = 1;
|
||||||
}
|
}
|
||||||
else if (INPUT(cntl_in) <= cntl_off) {
|
else if (INPUT(cntl_in) < cntl_off) {
|
||||||
r = r_off;
|
r = r_off;
|
||||||
|
outOfLimit = 1;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
r = exp(logmean + 3 * logratio * inmean / (2 * cntl_diff) - loc->c3 * pow(inmean, 3));
|
r = exp(logmean + loc->c1 * inmean - loc->c3 * inmean * inmean * inmean);
|
||||||
if(r<r_on) r=r_on;/* minimum resistance limiter */
|
if(r<r_on) r=r_on;/* minimum resistance limiter */
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (INPUT(cntl_in) <= cntl_on) {
|
inmean = (PARAM(cntl_on) - (INPUT(cntl_in)) / (PARAM(cntl_off) - PARAM(cntl_on))) - cntl_mean;
|
||||||
|
if (INPUT(cntl_in) < cntl_on) {
|
||||||
r = r_on;
|
r = r_on;
|
||||||
|
outOfLimit = 1;
|
||||||
}
|
}
|
||||||
else if (INPUT(cntl_in) >= cntl_off) {
|
else if (INPUT(cntl_in) > cntl_off) {
|
||||||
r = r_off;
|
r = r_off;
|
||||||
|
outOfLimit = 1;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
r = exp(logmean + 3 * logratio * inmean / (2 * cntl_diff) - loc->c3 * pow(inmean, 3));
|
r = exp(logmean + loc->c1 * inmean - loc->c3 * inmean * inmean * inmean);
|
||||||
// r = exp(logmean + 3 * logratio * (INPUT(cntl_in) - cntl_mean) / (2 * cntl_diff) - 2 * logratio * pow((INPUT(cntl_in) - cntl_mean), 3) / pow(cntl_diff, 3));
|
|
||||||
if(r<r_on) r=r_on;/* minimum resistance limiter */
|
if(r<r_on) r=r_on;/* minimum resistance limiter */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pi_pcntl = INPUT(out) / r * (loc->c2 * inmean * inmean - loc->c1);
|
pi_pcntl = INPUT(out) / r * (loc->c2 * inmean * inmean - loc->c1);
|
||||||
if(r == r_on)
|
if(1 == outOfLimit){
|
||||||
pi_pcntl = 0;
|
|
||||||
if(r == r_off)
|
|
||||||
pi_pcntl = 0;
|
pi_pcntl = 0;
|
||||||
|
}
|
||||||
pi_pvout = 1.0 / r;
|
pi_pvout = 1.0 / r;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
@ -249,10 +270,14 @@ void cm_pswitch(ARGS) /* structure holding parms,
|
||||||
}
|
}
|
||||||
|
|
||||||
if(ANALYSIS != MIF_AC) { /* Output DC & Transient Values */
|
if(ANALYSIS != MIF_AC) { /* Output DC & Transient Values */
|
||||||
OUTPUT(out) = INPUT(out) / r;
|
OUTPUT(out) = INPUT(out) / r;
|
||||||
PARTIAL(out,out) = pi_pvout;
|
OUTPUT(cntl_in) = INPUT(cntl_in) / r_cntl_in;
|
||||||
PARTIAL(out,cntl_in) = pi_pcntl;
|
// PARTIAL(out,out) = pi_pvout;
|
||||||
// cm_analog_auto_partial();
|
// PARTIAL(out,cntl_in) = pi_pcntl;
|
||||||
|
// PARTIAL(cntl_in,cntl_in) = 1 / r_cntl_in;
|
||||||
|
// PARTIAL(cntl_in,out) = 0; /* cntl input resistance is
|
||||||
|
// independent to out port */
|
||||||
|
cm_analog_auto_partial();
|
||||||
|
|
||||||
/* Note that the minus signs are required because current is positive
|
/* Note that the minus signs are required because current is positive
|
||||||
flowing INTO rather than OUT OF a component node. */
|
flowing INTO rather than OUT OF a component node. */
|
||||||
|
|
|
||||||
|
|
@ -30,11 +30,11 @@ PORT_TABLE:
|
||||||
|
|
||||||
Port_Name: cntl_in out
|
Port_Name: cntl_in out
|
||||||
Description: "input" "resistive output"
|
Description: "input" "resistive output"
|
||||||
Direction: in inout
|
Direction: inout inout
|
||||||
Default_Type: v gd
|
Default_Type: gd gd
|
||||||
Allowed_Types: [v,vd,i,id,vnam] [gd]
|
Allowed_Types: [g,gd] [gd]
|
||||||
Vector: no no
|
Vector: no no
|
||||||
Vector_Bounds: - -
|
Vector_Bounds: - -
|
||||||
Null_Allowed: no no
|
Null_Allowed: no no
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -66,14 +66,14 @@ Null_Allowed: yes yes
|
||||||
|
|
||||||
PARAMETER_TABLE:
|
PARAMETER_TABLE:
|
||||||
|
|
||||||
Parameter_Name: r_on
|
Parameter_Name: r_on r_cntl_in
|
||||||
Description: "on resistance"
|
Description: "on resistance" "input resistance for control terminal"
|
||||||
Data_Type: real
|
Data_Type: real real
|
||||||
Default_Value: 1.0
|
Default_Value: 1.0 1.0e12
|
||||||
Limits: -
|
Limits: - -
|
||||||
Vector: no
|
Vector: no no
|
||||||
Vector_Bounds: -
|
Vector_Bounds: - -
|
||||||
Null_Allowed: yes
|
Null_Allowed: yes yes
|
||||||
|
|
||||||
|
|
||||||
STATIC_VAR_TABLE:
|
STATIC_VAR_TABLE:
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue