diff --git a/src/spicelib/devices/sw/swload.c b/src/spicelib/devices/sw/swload.c index a492b4a77..b146219d5 100644 --- a/src/spicelib/devices/sw/swload.c +++ b/src/spicelib/devices/sw/swload.c @@ -12,56 +12,51 @@ Modified: 2001 Jon Engelbert #include "ngspice/sperror.h" #include "ngspice/suffix.h" + int SWload(GENmodel *inModel, CKTcircuit *ckt) - /* actually load the current values into the - * sparse matrix previously provided - */ { SWmodel *model = (SWmodel *) inModel; SWinstance *here; double g_now; double v_ctrl; - double previous_state = -1; + double previous_state = -1; double current_state = -1; - double old_current_state = -1; - double REALLY_OFF = 0, REALLY_ON = 1; // switch is on or off, not in hysteresis region. - double HYST_OFF = 2, HYST_ON = 3; // switch is on or off while control value is in hysteresis region. -// double previous_region = -1; + double old_current_state = -1; + double REALLY_OFF = 0, REALLY_ON = 1; // switch is on or off, not in hysteresis region. + double HYST_OFF = 2, HYST_ON = 3; // switch is on or off while control value is in hysteresis region. +// double previous_region = -1; // double current_region = -1; - /* loop through all the switch models */ - for( ; model != NULL; model = SWnextModel(model)) { + for (; model; model = SWnextModel(model)) { + for (here = SWinstances(model); here; here=SWnextInstance(here)) { - /* loop through all the instances of the model */ - for (here = SWinstances(model); here != NULL ; - here=SWnextInstance(here)) { - - old_current_state = *(ckt->CKTstates[0] + here->SWstate); - previous_state = *(ckt->CKTstates[1] + here->SWstate); + old_current_state = ckt->CKTstates[0][here->SWstate + 0]; + previous_state = ckt->CKTstates[1][here->SWstate + 0]; - v_ctrl = *(ckt->CKTrhsOld + here->SWposCntrlNode) - - *(ckt->CKTrhsOld + here->SWnegCntrlNode); - - /* decide the state of the switch */ - - if(ckt->CKTmode & (MODEINITFIX|MODEINITJCT)) { + v_ctrl = + ckt->CKTrhsOld [here->SWposCntrlNode] - + ckt->CKTrhsOld [here->SWnegCntrlNode]; - if(here->SWzero_stateGiven) { - /* switch specified "on" */ - if ((model->SWvHysteresis >= 0) && (v_ctrl > (model->SWvThreshold + model->SWvHysteresis))) - current_state = REALLY_ON; - else if ((model->SWvHysteresis < 0) && (v_ctrl > (model->SWvThreshold - model->SWvHysteresis))) - current_state = REALLY_ON; - else - current_state = HYST_ON; + /* decide the state of the switch */ + + if (ckt->CKTmode & (MODEINITFIX | MODEINITJCT)) { + + if (here->SWzero_stateGiven) { + /* switch specified "on" */ + if ((model->SWvHysteresis >= 0) && (v_ctrl > (model->SWvThreshold + model->SWvHysteresis))) + current_state = REALLY_ON; + else if ((model->SWvHysteresis < 0) && (v_ctrl > (model->SWvThreshold - model->SWvHysteresis))) + current_state = REALLY_ON; + else + current_state = HYST_ON; } else { - if ((model->SWvHysteresis >= 0) && (v_ctrl < (model->SWvThreshold - model->SWvHysteresis))) - current_state = REALLY_OFF; - else if ((model->SWvHysteresis < 0) && (v_ctrl < (model->SWvThreshold + model->SWvHysteresis))) - current_state = REALLY_OFF; - else - current_state = HYST_OFF; + if ((model->SWvHysteresis >= 0) && (v_ctrl < (model->SWvThreshold - model->SWvHysteresis))) + current_state = REALLY_OFF; + else if ((model->SWvHysteresis < 0) && (v_ctrl < (model->SWvThreshold + model->SWvHysteresis))) + current_state = REALLY_OFF; + else + current_state = HYST_OFF; } } else if (ckt->CKTmode & (MODEINITSMSIG)) { @@ -71,79 +66,80 @@ SWload(GENmodel *inModel, CKTcircuit *ckt) } else if (ckt->CKTmode & (MODEINITFLOAT)) { /* use state0 since INITTRAN or INITPRED already called */ - if (model->SWvHysteresis > 0) { - if (v_ctrl > (model->SWvThreshold + model->SWvHysteresis)) { - current_state = REALLY_ON; - } else if (v_ctrl < (model->SWvThreshold - model->SWvHysteresis)) { - current_state = REALLY_OFF; - } else { - current_state = old_current_state; - } - } else { // negative hysteresis case. - if (v_ctrl > (model->SWvThreshold - model->SWvHysteresis)) - { - current_state = REALLY_ON; - } else if (v_ctrl < (model->SWvThreshold + model->SWvHysteresis)) - { - current_state = REALLY_OFF; - } else { // in hysteresis... change value if going from low to hysteresis, or from hi to hysteresis. - // if previous state was in hysteresis, then don't change the state.. - if ((previous_state == HYST_OFF) || (previous_state == HYST_ON)) { - current_state = previous_state; - } else if (previous_state == REALLY_ON) { - current_state = HYST_OFF; - } else if (previous_state == REALLY_OFF) { - current_state = HYST_ON; - } else - internalerror("bad value for previous state in swload"); - } - } - - if(current_state != old_current_state) { - ckt->CKTnoncon++; /* ensure one more iteration */ - ckt->CKTtroubleElt = (GENinstance *) here; + if (model->SWvHysteresis > 0) { + if (v_ctrl > (model->SWvThreshold + model->SWvHysteresis)) { + current_state = REALLY_ON; + } else if (v_ctrl < (model->SWvThreshold - model->SWvHysteresis)) { + current_state = REALLY_OFF; + } else { + current_state = old_current_state; + } + } else { // negative hysteresis case. + if (v_ctrl > (model->SWvThreshold - model->SWvHysteresis)) { + current_state = REALLY_ON; + } else if (v_ctrl < (model->SWvThreshold + model->SWvHysteresis)) { + current_state = REALLY_OFF; + } else { // in hysteresis... change value if going from low to hysteresis, or from hi to hysteresis. + // if previous state was in hysteresis, then don't change the state.. + if ((previous_state == HYST_OFF) || (previous_state == HYST_ON)) { + current_state = previous_state; + } else if (previous_state == REALLY_ON) { + current_state = HYST_OFF; + } else if (previous_state == REALLY_OFF) { + current_state = HYST_ON; + } else { + internalerror("bad value for previous state in swload"); + } + } } + if (current_state != old_current_state) { + ckt->CKTnoncon++; /* ensure one more iteration */ + ckt->CKTtroubleElt = (GENinstance *) here; + } - } else if(ckt->CKTmode & (MODEINITTRAN|MODEINITPRED) ) { + } else if (ckt->CKTmode & (MODEINITTRAN | MODEINITPRED)) { + + if (model->SWvHysteresis > 0) { + if (v_ctrl > (model->SWvThreshold + model->SWvHysteresis)) + current_state = REALLY_ON; + else if (v_ctrl < (model->SWvThreshold - model->SWvHysteresis)) + current_state = REALLY_OFF; + else + current_state = previous_state; + } else { // negative hysteresis case. + if (v_ctrl > (model->SWvThreshold - model->SWvHysteresis)) + current_state = REALLY_ON; + else if (v_ctrl < (model->SWvThreshold + model->SWvHysteresis)) + current_state = REALLY_OFF; + else { + if ((previous_state == HYST_ON) || (previous_state == HYST_OFF)) + current_state = previous_state; + else if (previous_state == REALLY_ON) + current_state = REALLY_OFF; + else if (previous_state == REALLY_OFF) + current_state = REALLY_ON; + else + current_state = 0.0; + } + } + } - if (model->SWvHysteresis > 0) { - if (v_ctrl > (model->SWvThreshold + model->SWvHysteresis)) - current_state = REALLY_ON; - else if (v_ctrl < (model->SWvThreshold - model->SWvHysteresis)) - current_state = REALLY_OFF; - else - current_state = previous_state; - } else { // negative hysteresis case. - if (v_ctrl > (model->SWvThreshold - model->SWvHysteresis)) - current_state = REALLY_ON; - else if (v_ctrl < (model->SWvThreshold + model->SWvHysteresis)) - current_state = REALLY_OFF; - else { - current_state = 0.0; - if ((previous_state == HYST_ON) || (previous_state == HYST_OFF)) { - current_state = previous_state; - } else if (previous_state == REALLY_ON) { - current_state = REALLY_OFF; - } else if (previous_state == REALLY_OFF) { - current_state = REALLY_ON; - } - } - } - } // code added to force the state to be updated. // there is a possible problem. What if, during the transient analysis, the time is stepped // forward enough to change the switch's state, but that time point is rejected as being too -// distant and then the time is pushed back to a time before the switch changed states. +// distant and then the time is pushed back to a time before the switch changed states. // After analyzing the transient code, it seems that this is not a problem because state updating // occurs before the convergence loop in transient processing. - *(ckt->CKTstates[0] + here->SWstate) = current_state; - *(ckt->CKTstates[0] + here->SWstate + 1) = v_ctrl; - if ((current_state == REALLY_ON) || (current_state == HYST_ON)) - g_now = model->SWonConduct; - else - g_now = model->SWoffConduct; + ckt->CKTstates[0][here->SWstate + 0] = current_state; + ckt->CKTstates[0][here->SWstate + 1] = v_ctrl; + + if ((current_state == REALLY_ON) || (current_state == HYST_ON)) + g_now = model->SWonConduct; + else + g_now = model->SWoffConduct; + here->SWcond = g_now; *(here->SWposPosPtr) += g_now; @@ -152,5 +148,6 @@ SWload(GENmodel *inModel, CKTcircuit *ckt) *(here->SWnegNegPtr) += g_now; } } - return(OK); + + return OK; } diff --git a/src/spicelib/devices/sw/swtrunc.c b/src/spicelib/devices/sw/swtrunc.c index 9b40e3098..ed19a0f1b 100644 --- a/src/spicelib/devices/sw/swtrunc.c +++ b/src/spicelib/devices/sw/swtrunc.c @@ -3,8 +3,6 @@ Copyright 1990 Regents of the University of California. All rights reserved. Author: 1985 Thomas L. Quarles Modified: 2000 AlansFixes **********/ -/* - */ #include "ngspice/ngspice.h" #include "ngspice/cktdefs.h" @@ -12,36 +10,44 @@ Modified: 2000 AlansFixes #include "ngspice/suffix.h" #include "swdefs.h" + int SWtrunc(GENmodel *inModel, CKTcircuit *ckt, double *timeStep) { - SWmodel *model = (SWmodel*)inModel; + SWmodel *model = (SWmodel *) inModel; SWinstance *here; double lastChange, maxChange, maxStep, ref; - for( ; model!= NULL; model = SWnextModel(model)) { - for(here = SWinstances(model); here != NULL ; - here = SWnextInstance(here)) { - lastChange = *(ckt->CKTstate0+(here->SWstate+1)) - - *(ckt->CKTstate1+(here->SWstate+1)); - if (*(ckt->CKTstate0+(here->SWstate))==0) { - ref = (model->SWvThreshold + model->SWvHysteresis); - if ((*(ckt->CKTstate0+(here->SWstate+1))0)) { - maxChange = (ref - *(ckt->CKTstate0+(here->SWstate+1))) * - 0.75 + 0.05; - maxStep = maxChange/lastChange * ckt->CKTdeltaOld[0]; - if (*timeStep > maxStep) { *timeStep = maxStep; } - } + for (; model; model = SWnextModel(model)) { + for (here = SWinstances(model); here; here = SWnextInstance(here)) { + lastChange = + ckt->CKTstates[0][here->SWstate + 1] - + ckt->CKTstates[1][here->SWstate + 1]; + if (ckt->CKTstates[0][here->SWstate + 0] == 0) { + ref = (model->SWvThreshold + model->SWvHysteresis); + if (ckt->CKTstates[0][here->SWstate + 1] < ref && lastChange > 0) + { + maxChange = + (ref - ckt->CKTstates[0][here->SWstate + 1]) * 0.75 + + 0.05; + maxStep = maxChange / lastChange * ckt->CKTdeltaOld[0]; + if (*timeStep > maxStep) + *timeStep = maxStep; + } } else { - ref = (model->SWvThreshold - model->SWvHysteresis); - if ((*(ckt->CKTstate0+(here->SWstate+1))>ref) && (lastChange<0)) { - maxChange = (ref - *(ckt->CKTstate0+(here->SWstate+1))) * - 0.75 - 0.05; - maxStep = maxChange/lastChange * ckt->CKTdeltaOld[0]; - if (*timeStep > maxStep) { *timeStep = maxStep; } - } + ref = model->SWvThreshold - model->SWvHysteresis; + if (ckt->CKTstates[0][here->SWstate + 1] > ref && lastChange < 0) + { + maxChange = + (ref - ckt->CKTstates[0][here->SWstate + 1]) * 0.75 + - 0.05; + maxStep = maxChange / lastChange * ckt->CKTdeltaOld[0]; + if (*timeStep > maxStep) + *timeStep = maxStep; + } } } } - return(OK); + + return OK; }