From 68c4de76b773cedf86eb4843bb2de5a8740279eb Mon Sep 17 00:00:00 2001 From: h_vogt Date: Wed, 26 Sep 2012 16:59:59 +0200 Subject: [PATCH] new option noopac, don't do op simulation before ac if circuit is linear May simplify ac simulation of passive RLC networks (No need to add series resistors in Ls, allows to C inseries) --- src/frontend/inp.c | 40 ++++++++++++++++++++++++++++++++ src/include/ngspice/cktdefs.h | 5 +++- src/include/ngspice/optdefs.h | 2 ++ src/include/ngspice/tskdefs.h | 1 + src/spicelib/analysis/acan.c | 24 +++++++++++-------- src/spicelib/analysis/cktdojob.c | 1 + src/spicelib/analysis/cktntask.c | 1 + src/spicelib/analysis/cktsopt.c | 7 +++++- 8 files changed, 69 insertions(+), 12 deletions(-) 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);