diff --git a/src/frontend/inp.c b/src/frontend/inp.c index ad5d9f33f..4d6de50df 100644 --- a/src/frontend/inp.c +++ b/src/frontend/inp.c @@ -10,6 +10,7 @@ Author: 1985 Wayne A. Christopher #include "ngspice/ngspice.h" +#include "ngspice/cktdefs.h" #include "ngspice/cpdefs.h" #include "ngspice/inpdefs.h" #include "ngspice/ftedefs.h" @@ -49,6 +50,7 @@ static char *upper(register char *string); static bool doedit(char *filename); static struct line *com_options = NULL; static void consaves(wordlist *wl); +static void cktislinear(CKTcircuit *ckt, struct line *deck); void line_free_x(struct line *deck, bool recurse); @@ -796,6 +798,7 @@ inp_dodeck( ckt = NULL; } + cktislinear(ckt, deck); out_init(); ft_curckt->FTEstats->FTESTATdeckNumLines = 0; @@ -1138,3 +1141,40 @@ consaves(wordlist *wl_control) com_save(wl); } + + +/* check the input deck (after inpcom and numparam extensions) + for linear elements. If only linear elements are found, + ckt->CKTisLinear is set to 1. Return immediately if a first + non-linear element is found. */ +static void +cktislinear(CKTcircuit *ckt, struct line *deck) +{ + struct line *dd; + char firstchar; + + if (deck->li_next) + for (dd = deck->li_next; dd; dd = dd->li_next) { + firstchar = *dd->li_line; + switch (firstchar) { + case 'r': + case 'l': + case 'c': + case 'i': + case 'v': + case '*': + case '.': + case 'e': + case 'g': + case 'f': + case 'h': + continue; + break; + default: + ckt->CKTisLinear = 0; + return; + } + } + + ckt->CKTisLinear = 1; +} diff --git a/src/include/ngspice/cktdefs.h b/src/include/ngspice/cktdefs.h index d6f478849..abd5f64bf 100644 --- a/src/include/ngspice/cktdefs.h +++ b/src/include/ngspice/cktdefs.h @@ -275,7 +275,10 @@ struct CKTcircuit { int CKTsc_iter; /* SP: 100609 */ #endif - + unsigned int CKTisLinear:1; /* flag to indicate that the circuit + contains only linear elements */ + unsigned int CKTnoopac:1; /* flag to indicate that OP will not be evaluated + during AC simulation */ }; diff --git a/src/include/ngspice/optdefs.h b/src/include/ngspice/optdefs.h index e3948b626..95c577db2 100644 --- a/src/include/ngspice/optdefs.h +++ b/src/include/ngspice/optdefs.h @@ -124,6 +124,8 @@ typedef struct { #define OPT_ABSDV 66 /* Original: 51 (Node_Damping) */ #define OPT_RELDV 67 /* Original: 52 (Node_Damping) */ +#define OPT_NOOPAC 68 + #ifdef XSPICE /* gtri - begin - wbk - add new options */ #define OPT_ENH_NOOPALTER 100 diff --git a/src/include/ngspice/tskdefs.h b/src/include/ngspice/tskdefs.h index db2fc5147..fb4953c6e 100644 --- a/src/include/ngspice/tskdefs.h +++ b/src/include/ngspice/tskdefs.h @@ -65,6 +65,7 @@ struct TSKtask { unsigned int TSKnodeDamping:1; /* flag for node damping */ double TSKabsDv; /* abs limit for iter-iter voltage change */ double TSKrelDv; /* rel limit for iter-iter voltage change */ + unsigned int TSKnoopac:1; /* flag for no OP calculation before AC */ }; #endif /*TSK*/ diff --git a/src/spicelib/analysis/acan.c b/src/spicelib/analysis/acan.c index ca19b7557..f6f58d01b 100644 --- a/src/spicelib/analysis/acan.c +++ b/src/spicelib/analysis/acan.c @@ -123,17 +123,21 @@ ACan(CKTcircuit *ckt, int restart) } else #endif -/* If no event-driven instances, do what SPICE normally does */ - error = CKTop(ckt, - (ckt->CKTmode & MODEUIC) | MODEDCOP | MODEINITJCT, - (ckt->CKTmode & MODEUIC) | MODEDCOP | MODEINITFLOAT, - ckt->CKTdcMaxIter); + /* If no event-driven instances, do what SPICE normally does */ + if (!ckt->CKTnoopac) { /* skip OP if option NOOPAC is set and circuit is linear */ + error = CKTop(ckt, + (ckt->CKTmode & MODEUIC) | MODEDCOP | MODEINITJCT, + (ckt->CKTmode & MODEUIC) | MODEDCOP | MODEINITFLOAT, + ckt->CKTdcMaxIter); - if(error){ - fprintf(stdout,"\nAC operating point failed -\n"); - CKTncDump(ckt); - return(error); - } + if(error){ + fprintf(stdout,"\nAC operating point failed -\n"); + CKTncDump(ckt); + return(error); + } + } + else + fprintf(stdout,"\n Linear circuit, option noopac given: no OP analysis\n"); #ifdef XSPICE /* gtri - add - wbk - 12/19/90 - Add IPC stuff */ diff --git a/src/spicelib/analysis/cktdojob.c b/src/spicelib/analysis/cktdojob.c index fe0e2f026..9e57f130b 100644 --- a/src/spicelib/analysis/cktdojob.c +++ b/src/spicelib/analysis/cktdojob.c @@ -103,6 +103,7 @@ CKTdoJob(CKTcircuit *ckt, int reset, TSKtask *task) ckt->CKTrelDv = task->TSKrelDv; ckt->CKTtroubleNode = 0; ckt->CKTtroubleElt = NULL; + ckt->CKTnoopac = task->TSKnoopac && ckt->CKTisLinear; #ifdef NEWTRUNC ckt->CKTlteReltol = task->TSKlteReltol; ckt->CKTlteAbstol = task->TSKlteAbstol; diff --git a/src/spicelib/analysis/cktntask.c b/src/spicelib/analysis/cktntask.c index 19f2b4aa3..beded0d52 100644 --- a/src/spicelib/analysis/cktntask.c +++ b/src/spicelib/analysis/cktntask.c @@ -70,6 +70,7 @@ CKTnewTask(CKTcircuit *ckt, TSKtask **taskPtr, IFuid taskName, TSKtask **defPtr) tsk->TSKnodeDamping = def->TSKnodeDamping; tsk->TSKabsDv = def->TSKabsDv; tsk->TSKrelDv = def->TSKrelDv; + tsk->TSKnoopac = def->TSKnoopac; #ifdef NEWTRUNC tsk->TSKlteReltol = def->TSKlteReltol; tsk->TSKlteAbstol = def->TSKlteAbstol; diff --git a/src/spicelib/analysis/cktsopt.c b/src/spicelib/analysis/cktsopt.c index e9d80e998..1d557a1c9 100644 --- a/src/spicelib/analysis/cktsopt.c +++ b/src/spicelib/analysis/cktsopt.c @@ -158,6 +158,9 @@ CKTsetOpt(CKTcircuit *ckt, JOB *anal, int opt, IFvalue *val) case OPT_RELDV: task->TSKrelDv = val->rValue; break; + case OPT_NOOPAC: + task->TSKnoopac = (val->iValue != 0); + break; /* gtri - begin - wbk - add new options */ #ifdef XSPICE case OPT_EVT_MAX_OP_ALTER: @@ -311,7 +314,9 @@ static IFparm OPTtbl[] = { { "absdv", OPT_ABSDV, IF_SET|IF_REAL, "Maximum absolute iter-iter node voltage change" }, { "reldv", OPT_RELDV, IF_SET|IF_REAL, - "Maximum relative iter-iter node voltage change" } + "Maximum relative iter-iter node voltage change" }, + { "noopac", OPT_NOOPAC, IF_SET|IF_FLAG, + "No op calculation in ac if circuit is linear" } }; int OPTcount = NUMELEMS(OPTtbl);