From 07ee771a96263eeaa3501362038bde5632f03bde Mon Sep 17 00:00:00 2001 From: rlar Date: Tue, 3 Mar 2015 21:27:29 +0100 Subject: [PATCH] noise analysis, bug fix, override ac magnitude of all vsrc/isrc devices Bug report due to Hartmut Henkel in >> [Ngspice-users] Noise analysis depends on ac parameter The noise analysis internally depends on an ac analysis to derive "inoise" from "onoise" ("onoise" is multiplied with the inverse ac gain from input to output) This AC analysis used all the given ac magnitudes for all vsrc/isrc devices in the deck. This fix overrides all ac magnitudes with zero, except for the given input device, whose magnitude is set to one. --- src/include/ngspice/cktdefs.h | 5 +++++ src/spicelib/analysis/noisean.c | 5 +++-- src/spicelib/devices/isrc/isrcacld.c | 18 ++++++++++++++---- src/spicelib/devices/vsrc/vsrcacld.c | 14 ++++++++++++-- 4 files changed, 34 insertions(+), 8 deletions(-) diff --git a/src/include/ngspice/cktdefs.h b/src/include/ngspice/cktdefs.h index f129016a9..451b4dc51 100644 --- a/src/include/ngspice/cktdefs.h +++ b/src/include/ngspice/cktdefs.h @@ -165,6 +165,9 @@ struct CKTcircuit { #define MODETRAN 0x1 #define MODEAC 0x2 +/* for noise analysis */ +#define MODEACNOISE 0x8 + /* old 'modedc' parameters */ #define MODEDC 0x70 #define MODEDCOP 0x10 @@ -288,6 +291,8 @@ struct CKTcircuit { NGHASHPTR DEVnameHash; NGHASHPTR MODnameHash; + + GENinstance *noise_input; /* identify the input vsrc/isrc during noise analysis */ }; diff --git a/src/spicelib/analysis/noisean.c b/src/spicelib/analysis/noisean.c index 48345d9a3..340184b02 100644 --- a/src/spicelib/analysis/noisean.c +++ b/src/spicelib/analysis/noisean.c @@ -37,13 +37,13 @@ NOISEan (CKTcircuit *ckt, int restart) double freqTol; /* tolerence parameter for finding final frequency; hack */ NOISEAN *job = (NOISEAN *) ckt->CKTcurJob; + GENinstance *inst = CKTfndDev(ckt, job->input); posOutNode = (job->output) -> number; negOutNode = (job->outputRef) -> number; /* see if the source specified is AC */ { - GENinstance *inst = CKTfndDev(ckt, job->input); bool ac_given = FALSE; if (!inst || inst->GENmodPtr->GENmodType < 0) { @@ -194,7 +194,8 @@ NOISEan (CKTcircuit *ckt, int restart) return (E_PAUSE); } ckt->CKTomega = 2.0 * M_PI * data->freq; - ckt->CKTmode = (ckt->CKTmode & MODEUIC) | MODEAC; + ckt->CKTmode = (ckt->CKTmode & MODEUIC) | MODEAC | MODEACNOISE; + ckt->noise_input = inst; /* * solve the original AC system to get the transfer diff --git a/src/spicelib/devices/isrc/isrcacld.c b/src/spicelib/devices/isrc/isrcacld.c index 5ddbec373..2a8cefff1 100644 --- a/src/spicelib/devices/isrc/isrcacld.c +++ b/src/spicelib/devices/isrc/isrcacld.c @@ -23,16 +23,26 @@ ISRCacLoad(GENmodel *inModel, CKTcircuit *ckt) for (here = model->ISRCinstances; here != NULL ; here=here->ISRCnextInstance) { + double acReal, acImag; + + if ((ckt->CKTmode & MODEACNOISE) && (here == ckt->noise_input)) { + acReal = 1.0; + acImag = 0.0; + } else { + acReal = here->ISRCacReal; + acImag = here->ISRCacImag; + } + m = here->ISRCmValue; *(ckt->CKTrhs + (here->ISRCposNode)) += - m * here->ISRCacReal; + m * acReal; *(ckt->CKTrhs + (here->ISRCnegNode)) -= - m * here->ISRCacReal; + m * acReal; *(ckt->CKTirhs + (here->ISRCposNode)) += - m * here->ISRCacImag; + m * acImag; *(ckt->CKTirhs + (here->ISRCnegNode)) -= - m * here->ISRCacImag; + m * acImag; } } diff --git a/src/spicelib/devices/vsrc/vsrcacld.c b/src/spicelib/devices/vsrc/vsrcacld.c index 5b7b9058b..8229bb842 100644 --- a/src/spicelib/devices/vsrc/vsrcacld.c +++ b/src/spicelib/devices/vsrc/vsrcacld.c @@ -22,12 +22,22 @@ VSRCacLoad(GENmodel *inModel, CKTcircuit *ckt) for (here = model->VSRCinstances; here != NULL ; here=here->VSRCnextInstance) { + double acReal, acImag; + + if ((ckt->CKTmode & MODEACNOISE) && (here == ckt->noise_input)) { + acReal = 1.0; + acImag = 0.0; + } else { + acReal = here->VSRCacReal; + acImag = here->VSRCacImag; + } + *(here->VSRCposIbrptr) += 1.0 ; *(here->VSRCnegIbrptr) -= 1.0 ; *(here->VSRCibrPosptr) += 1.0 ; *(here->VSRCibrNegptr) -= 1.0 ; - *(ckt->CKTrhs + (here->VSRCbranch)) += here->VSRCacReal; - *(ckt->CKTirhs + (here->VSRCbranch)) += here->VSRCacImag; + *(ckt->CKTrhs + (here->VSRCbranch)) += acReal; + *(ckt->CKTirhs + (here->VSRCbranch)) += acImag; } }