From 2c10c4aebd7f34551a32fc9287dc43d002306ad7 Mon Sep 17 00:00:00 2001 From: Alessio Cacciatori Date: Sat, 8 Jan 2022 15:39:47 +0100 Subject: [PATCH] S parameter simulation Command '.sp' arbitrary number of ports ports made with modified VSRC Patch provided by Alessio Cacciatori https://sourceforge.net/p/ngspice/discussion/127605/thread/7a2655c86f/ --- examples/sp/sp1.cir | 21 + src/frontend/commands.c | 8 + src/frontend/runcoms.c | 11 +- src/frontend/runcoms.h | 3 + src/frontend/shyu.c | 81 ++ src/frontend/spiceif.c | 9 +- src/include/ngspice/acdefs.h | 10 + src/include/ngspice/cktdefs.h | 41 +- src/include/ngspice/ipc.h | 3 + src/include/ngspice/spdefs.h | 51 + src/maths/dense/dense.c | 1325 ++++++++++++++++++++++++++ src/maths/dense/dense.h | 103 ++ src/maths/ni/niaciter.c | 76 ++ src/spicelib/analysis/analysis.c | 15 + src/spicelib/analysis/cktdest.c | 10 + src/spicelib/analysis/cktspdum.c | 108 +++ src/spicelib/analysis/span.c | 736 ++++++++++++++ src/spicelib/analysis/spaskq.c | 73 ++ src/spicelib/analysis/spsetp.c | 114 +++ src/spicelib/devices/cktinit.c | 9 + src/spicelib/devices/vsrc/vsrc.c | 7 + src/spicelib/devices/vsrc/vsrcacld.c | 136 ++- src/spicelib/devices/vsrc/vsrcask.c | 17 + src/spicelib/devices/vsrc/vsrcdefs.h | 44 +- src/spicelib/devices/vsrc/vsrcext.h | 4 + src/spicelib/devices/vsrc/vsrcload.c | 41 +- src/spicelib/devices/vsrc/vsrcpar.c | 45 + src/spicelib/devices/vsrc/vsrcset.c | 43 + src/spicelib/devices/vsrc/vsrctemp.c | 90 ++ src/spicelib/parser/inp2dot.c | 114 +++ visualc/vngspice.vcxproj | 19 +- 31 files changed, 3336 insertions(+), 31 deletions(-) create mode 100644 examples/sp/sp1.cir create mode 100644 src/include/ngspice/spdefs.h create mode 100644 src/maths/dense/dense.c create mode 100644 src/maths/dense/dense.h create mode 100644 src/spicelib/analysis/cktspdum.c create mode 100644 src/spicelib/analysis/span.c create mode 100644 src/spicelib/analysis/spaskq.c create mode 100644 src/spicelib/analysis/spsetp.c diff --git a/examples/sp/sp1.cir b/examples/sp/sp1.cir new file mode 100644 index 000000000..20e3064e1 --- /dev/null +++ b/examples/sp/sp1.cir @@ -0,0 +1,21 @@ +Example of VSRC as power ports +* +* +V1 in 0 dc 0 ac 1 portnum 1 z0 100 pwr 0.001 freq 2.3e9 +*V1 in 0 dc 1 ac 1 +Rpt in x 100 +C1 x 0 1e-9 +*Vx x 0 0 +R2 x out 10 +V2 out 0 dc 0 ac 0 portnum 2 z0 50 pwr 0.002 freq 3.2e9 +*V2 out 0 dc 0 ac 0 + +.sp lin 100 1e8 1e9 1 + +.control +run +plot S_1_1 S_1_2 S_2_1 +plot S_2_2 +.endc + +.end diff --git a/src/frontend/commands.c b/src/frontend/commands.c index 623ccf376..c18ef7fc8 100644 --- a/src/frontend/commands.c +++ b/src/frontend/commands.c @@ -305,6 +305,14 @@ struct comm spcp_coms[] = { NULL, "[.pss line args] : Do a periodic state analysis." } , /* SP */ +#endif +#ifdef RFSPICE +/* SP: S parameter Analysis */ + { "sp", com_sp, TRUE, TRUE, + { 0, 0, 0, 0 }, E_DEFHMASK, 0, LOTS, + NULL, + "[.sp line args] : Do a S parameter analysis." }, + /* SP */ #endif { "ac", com_ac, TRUE, TRUE, { 0, 0, 0, 0 }, E_DEFHMASK, 0, LOTS, diff --git a/src/frontend/runcoms.c b/src/frontend/runcoms.c index ecd74c570..c50cbb0b8 100644 --- a/src/frontend/runcoms.c +++ b/src/frontend/runcoms.c @@ -177,15 +177,22 @@ com_noise(wordlist *wl) #ifdef WITH_PSS -/* SP: Steady State Analysis */ +/* Steady State Analysis */ void com_pss(wordlist *wl) { dosim("pss", wl); } -/* SP */ #endif +#ifdef RFSPICE +/* S parameter Analysis*/ +void +com_sp(wordlist* wl) +{ + dosim("sp", wl); +} +#endif static int dosim( char *what, /* in: command diff --git a/src/frontend/runcoms.h b/src/frontend/runcoms.h index 714239e50..90ddb178c 100644 --- a/src/frontend/runcoms.h +++ b/src/frontend/runcoms.h @@ -20,6 +20,9 @@ void com_sens(wordlist *wl); void com_disto(wordlist *wl); void com_noise(wordlist *wl); void com_run(wordlist *wl); +#ifdef RFSPICE +void com_sp(wordlist* wl); +#endif extern FILE *rawfileFp; extern bool rawfileBinary; diff --git a/src/frontend/shyu.c b/src/frontend/shyu.c index 1afe5b965..c8436c64c 100644 --- a/src/frontend/shyu.c +++ b/src/frontend/shyu.c @@ -314,6 +314,87 @@ if_sens_run(CKTcircuit *ckt, wordlist *args, INPtables *tab) } #endif +#ifdef RFSPICE + if (strcmp(token, "sp") == 0) { + JOB* spJob; + which = ft_find_analysis("SP"); + if (which == -1) { + current->error = INPerrCat + (current->error, + INPmkTemp("S-Param analysis unsupported\n")); + return (0); /* temporary */ + } + err = ft_sim->newAnalysis(ft_curckt->ci_ckt, which, "span", + &spJob, ft_curckt->ci_specTask); + if (err) { + ft_sperror(err, "createSP"); /* or similar error message */ + return (0); /* temporary */ + } + + INPgetTok(&line, &steptype, 1); /* get DEC, OCT, or LIN */ + ptemp.iValue = 1; + error = INPapName(ckt, which, spJob, steptype, &ptemp); + if (error) + current->error = INPerrCat(current->error, INPerror(error)); + parm = INPgetValue(ckt, &line, IF_INTEGER, tab);/* number of points*/ + error = INPapName(ckt, which, spJob, "numsteps", parm); + if (error) + current->error = INPerrCat(current->error, INPerror(error)); + parm = INPgetValue(ckt, &line, IF_REAL, tab); /* fstart */ + error = INPapName(ckt, which, spJob, "start", parm); + if (error) + current->error = INPerrCat(current->error, INPerror(error)); + parm = INPgetValue(ckt, &line, IF_REAL, tab); /* fstop */ + error = INPapName(ckt, which, spJob, "stop", parm); + if (error) + current->error = INPerrCat(current->error, INPerror(error)); + parm = INPgetValue(ckt, &line, IF_INTEGER, tab); /* fstop */ + error = INPapName(ckt, which, spJob, "donoise", parm); + if (error) + current->error = INPerrCat(current->error, INPerror(error)); + } +#ifdef WITH_HB + if (strcmp(token, "hb") == 0) { + JOB* spJob; + which = ft_find_analysis("HB"); + if (which == -1) { + current->error = INPerrCat + (current->error, + INPmkTemp("S-Param analysis unsupported\n")); + return (0); /* temporary */ + } + err = ft_sim->newAnalysis(ft_curckt->ci_ckt, which, "hban", + &spJob, ft_curckt->ci_specTask); + if (err) { + ft_sperror(err, "createHB"); /* or similar error message */ + return (0); /* temporary */ + } + + INPgetTok(&line, &steptype, 1); /* get DEC, OCT, or LIN */ + ptemp.iValue = 1; + error = INPapName(ckt, which, spJob, steptype, &ptemp); + if (error) + current->error = INPerrCat(current->error, INPerror(error)); + parm = INPgetValue(ckt, &line, IF_INTEGER, tab);/* number of points*/ + error = INPapName(ckt, which, spJob, "numsteps", parm); + if (error) + current->error = INPerrCat(current->error, INPerror(error)); + parm = INPgetValue(ckt, &line, IF_REAL, tab); /* fstart */ + error = INPapName(ckt, which, spJob, "start", parm); + if (error) + current->error = INPerrCat(current->error, INPerror(error)); + parm = INPgetValue(ckt, &line, IF_REAL, tab); /* fstop */ + error = INPapName(ckt, which, spJob, "stop", parm); + if (error) + current->error = INPerrCat(current->error, INPerror(error)); + parm = INPgetValue(ckt, &line, IF_INTEGER, tab); /* fstop */ + error = INPapName(ckt, which, spJob, "donoise", parm); + if (error) + current->error = INPerrCat(current->error, INPerror(error)); + } +#endif +#endif + next: while (*line) { /* read the entire line */ diff --git a/src/frontend/spiceif.c b/src/frontend/spiceif.c index b6ac034db..dd6f1c51c 100644 --- a/src/frontend/spiceif.c +++ b/src/frontend/spiceif.c @@ -220,9 +220,14 @@ if_run(CKTcircuit *ckt, char *what, wordlist *args, INPtables *tab) eq(what, "tf") || eq(what, "noise") #ifdef WITH_PSS - /* SP: Steady State Analysis */ + /* Steady State Analysis */ || eq(what, "pss") - /* SP */ +#endif +#ifdef RFSPICE + || eq(what, "sp") +#ifdef WITH_HB + || eq(what, "hb") +#endif #endif ) { diff --git a/src/include/ngspice/acdefs.h b/src/include/ngspice/acdefs.h index 44519078b..d0db81897 100644 --- a/src/include/ngspice/acdefs.h +++ b/src/include/ngspice/acdefs.h @@ -25,11 +25,21 @@ typedef struct { /* available step types: XXX should be somewhere else */ +#ifdef RFSPICE +#ifndef ngspice_SPDEFS_H enum { DECADE = 1, OCTAVE, LINEAR, }; +#endif +#else +enum { + DECADE = 1, + OCTAVE, + LINEAR, +}; +#endif enum { AC_DEC = 1, diff --git a/src/include/ngspice/cktdefs.h b/src/include/ngspice/cktdefs.h index 2e5076cff..95d2ec6a8 100644 --- a/src/include/ngspice/cktdefs.h +++ b/src/include/ngspice/cktdefs.h @@ -32,6 +32,9 @@ #include "ngspice/noisedef.h" #include "ngspice/hash.h" +#ifdef RFSPICE +#include "../maths/dense/dense.h" +#endif struct CKTnode { @@ -187,6 +190,11 @@ struct CKTcircuit { #define MODEINITTRAN 0x1000 #define MODEINITPRED 0x2000 +#ifdef RFSPICE +#define MODESP 0x4000 +#define MODESPNOISE 0x8000 +#endif + /* old 'nosolv' paramater */ #define MODEUIC 0x10000l @@ -274,7 +282,17 @@ struct CKTcircuit { Enh_Ckt_Data_t *enh; /* data used by general enhancements */ #endif /* gtri - evt - wbk - 5/20/91 - add event-driven and enhancements data */ - +#ifdef RFSPICE + unsigned int CKTactivePort;/* Identify active port during S-Param analysis*/ + unsigned int CKTportCount; /* Number of RF ports */ + int CKTVSRCid; /* Place holder for VSRC Devices id*/ + GENinstance** CKTrfPorts; /* List of all RF ports (HB & SP) */ + CMat* CKTAmat; + CMat* CKTBmat; + CMat* CKTSmat; + CMat* CKTYmat; + CMat* CKTZmat; +#endif #ifdef WITH_PSS /* SP: Periodic Steady State Analysis - 100609 */ double CKTstabTime; /* PSS stab time */ @@ -356,6 +374,9 @@ extern int CKTmodAsk(CKTcircuit *, GENmodel *, int , IFvalue *, IFvalue *); extern int CKTmodCrt(CKTcircuit *, int , GENmodel **, IFuid); extern int CKTmodParam(CKTcircuit *, GENmodel *, int , IFvalue *, IFvalue *); extern int CKTnames(CKTcircuit *, int *, IFuid **); +#ifdef RFSPICE +extern int CKTSPnames(CKTcircuit*, int*, IFuid**); +#endif extern int CKTdnames(CKTcircuit *); extern int CKTnewAnal(CKTcircuit *, int , IFuid , JOB **, TSKtask *); extern int CKTnewEq(CKTcircuit *, CKTnode **, IFuid); @@ -423,12 +444,22 @@ extern int TRANsetParm(CKTcircuit *, JOB *, int , IFvalue *); extern int TRANinit(CKTcircuit *, JOB *); #ifdef WITH_PSS -/* SP: Steady State Analysis */ +/* Steady State Analysis */ extern int PSSaskQuest(CKTcircuit *, JOB *, int , IFvalue *); extern int PSSsetParm(CKTcircuit *, JOB *, int , IFvalue *); extern int PSSinit(CKTcircuit *, JOB *); extern int DCpss(CKTcircuit *, int); -/* SP */ +#endif + +#ifdef RFSPICE +extern int SPan(CKTcircuit*, int); +extern int SPaskQuest(CKTcircuit*, JOB*, int, IFvalue*); +extern int SPsetParm(CKTcircuit*, JOB*, int, IFvalue*); +extern int CKTspDump(CKTcircuit*, double, runDesc*); +extern int CKTspLoad(CKTcircuit*); +extern unsigned int CKTmatrixIndex(CKTcircuit*, unsigned int, unsigned int); +extern int CKTspCalcPowerWave(CKTcircuit* ckt); +extern int CKTspCalcSMatrix(CKTcircuit* ckt); #endif #ifdef __cplusplus @@ -452,6 +483,10 @@ extern int NIreinit(CKTcircuit *); extern int NIsenReinit(CKTcircuit *); extern int NIdIter (CKTcircuit *); extern void NInzIter(CKTcircuit *, int, int); +#ifdef RFSPICE +extern int NIspPreload(CKTcircuit*); +extern int NIspSolve(CKTcircuit*); +#endif #ifdef __cplusplus } #endif diff --git a/src/include/ngspice/ipc.h b/src/include/ngspice/ipc.h index ee3261797..7dd36621f 100644 --- a/src/include/ngspice/ipc.h +++ b/src/include/ngspice/ipc.h @@ -112,6 +112,9 @@ typedef enum { IPC_ANAL_DCTRCURVE, IPC_ANAL_AC, IPC_ANAL_TRAN, +#ifdef RFSPICE + IPC_ANAL_SP +#endif } Ipc_Anal_t; diff --git a/src/include/ngspice/spdefs.h b/src/include/ngspice/spdefs.h new file mode 100644 index 000000000..6fb878068 --- /dev/null +++ b/src/include/ngspice/spdefs.h @@ -0,0 +1,51 @@ +/********** +Copyright 1990 Regents of the University of California. All rights reserved. +Author: 1985 Thomas L. Quarles +**********/ + +#ifndef ngspice_SPDEFS_H +#define ngspice_SPDEFS_H + +#include "ngspice/jobdefs.h" + +#ifdef RFSPICE + /* structure used to describe an AC analysis to be performed */ + +typedef struct { + int JOBtype; + JOB *JOBnextJob; /* pointer to next thing to do */ + char *JOBname; /* name of this job */ + double SPstartFreq; + double SPstopFreq; + double SPfreqDelta; /* multiplier for decade/octave stepping, */ + /* step for linear steps. */ + double SPsaveFreq; /* frequency at which we left off last time*/ + int SPstepType; /* values described below */ + int SPnumberSteps; + + unsigned SPdoNoise : 1; /* Flag to indicate if SP noise must be calculated*/ + + unsigned int SPnoiseInput; + unsigned int SPnoiseOutput; +} SPAN; + +/* available step types: XXX should be somewhere else */ +#ifndef ngspice_ACDEFS_H +enum { + DECADE = 1, + OCTAVE, + LINEAR, +}; +#endif + +enum { + SP_DEC = 1, + SP_OCT, + SP_LIN, + SP_START, + SP_STOP, + SP_STEPS, + SP_DONOISE, +}; +#endif +#endif diff --git a/src/maths/dense/dense.c b/src/maths/dense/dense.c new file mode 100644 index 000000000..97da2d5ae --- /dev/null +++ b/src/maths/dense/dense.c @@ -0,0 +1,1325 @@ + +#include "dense.h" +#include +#include +#include +#include "ngspice/bool.h" +#include "ngspice/iferrmsg.h" + +inline void setcplx(cplx* d, double r, double i) +{ + d->re = r; d->im = i; +} + +inline void cmultc(cplx* res, cplx a, cplx b) +{ + res->re = a.re * b.re - a.im * b.im; + res->im = a.im * b.re + a.re * b.im; +} + +inline cplx cmultco(cplx a, cplx b) +{ + cplx res; + res.re = a.re * b.re - a.im * b.im; + res.im = a.im * b.re + a.re * b.im; + return res; +} + + +inline cplx cmultdo(cplx a, double d) +{ + cplx res; + res.re = a.re * d; + res.im = a.im * d; + return res; +} +inline void cmultd(cplx* res, cplx a, double d) +{ + res->re = a.re * d; + res->im = a.im * d; +} + +inline void caddc(cplx* res, cplx a, cplx b) +{ + res->re = a.re + b.re; + res->im = a.im + b.im; +} + +inline cplx caddco( cplx a, cplx b) +{ + cplx res; + res.re = a.re + b.re; + res.im = a.im + b.im; + return res; +} + + +inline void caddd(cplx* res, cplx a, double d) +{ + res->re = a.re + d; +} + +inline void csubc(cplx* res, cplx a, cplx b) +{ + res->re = a.re - b.re; + res->im = a.im - b.im; +} + +inline cplx csubco(cplx a, cplx b) +{ + cplx res; + res.re = a.re - b.re; + res.im = a.im - b.im; + return res; +} + +inline void csubd(cplx* res, cplx a, double d) +{ + res->re = a.re - d; +} + +inline double cmod(cplx a) +{ + return 1.0 / (a.re * a.re + a.im * a.im); +} + +inline int ciszero(cplx a) +{ + return (a.re == 0) && (a.im == 0); +} +inline cplx cinv(cplx a) +{ + cplx res; + double cpmod = cmod(a); + res.re = a.re * cpmod; + res.im = -a.im * cpmod; + return res; +} + +void showmat(Mat* A) { + if (A->row > 0 && A->col > 0) { + + printf("["); + for (int i = 0; i < A->row; i++) { + for (int j = 0; j < A->col; j++) { + if (j < A->col) { + printf("%f\t", A->d[i][j]); + } + else { + printf("%f", A->d[i][j]); + } + } + if (i < A->row) { + printf("\n"); + } + else { + printf("]\n"); + } + } + printf("\n"); + } + else { + printf("[]"); + } +} + +void showcmat(CMat* A) { + if (A->row > 0 && A->col > 0) { + + printf("["); + for (int i = 0; i < A->row; i++) { + for (int j = 0; j < A->col; j++) { + if (j < A->col) { + printf("%f+i%f\t", A->d[i][j].re, A->d[i][j].im); + } + else { + printf("%f+i%f\t", A->d[i][j].re, A->d[i][j].im); + } + } + if (i < A->row) { + printf("\n"); + } + else { + printf("]\n"); + } + } + printf("\n"); + } + else { + printf("[]"); + } +} + +CMat* newcmat(int r, int c, double dr, double di) { + CMat* M = (CMat*)malloc(sizeof(CMat)); + if (M == NULL) return NULL; + + M->row = r; M->col = c; + M->d = (cplx**)malloc(sizeof(cplx*) * r); + for (int i = 0; i < r; i++) + M->d[i] = (cplx*)malloc(sizeof(cplx) * c); + + for (int i = 0; i < M->row; i++) { + for (int j = 0; j < M->col; j++) { + M->d[i][j].re = dr; + M->d[i][j].im = di; + } + } + return M; +} + + + +CMat* newcmatnoinit(int r, int c) { + CMat* M = (CMat*)malloc(sizeof(CMat)); + if (M == NULL) return NULL; + M->row = r; M->col = c; + + M->d = (cplx**)malloc(sizeof(cplx*) * r); + for (int i = 0; i < r; i++) + M->d[i] = (cplx*)malloc(sizeof(cplx) * c); + return M; +} + +Mat* newmat(int r, int c, double d) { + Mat* M = (Mat*)malloc(sizeof(Mat)); + if (M == NULL) return NULL; + + M->row = r; M->col = c; + M->d = (double**)malloc(sizeof(double*) * r); + for (int i = 0; i < r; i++) + M->d[i] = (double*)malloc(sizeof(double) * c); + + for (int i = 0; i < M->row; i++) { + for (int j = 0; j < M->col; j++) { + M->d[i][j] = d; + } + } + return M; +} + +Mat* newmatnoinit(int r, int c) { + Mat* M = (Mat*)malloc(sizeof(Mat)); + if (M == NULL) return NULL; + + M->row = r; M->col = c; + M->d = (double**)malloc(sizeof(double*) * r); + for (int i = 0; i < r; i++) + M->d[i] = (double*)malloc(sizeof(double) * c); + + return M; +} + + +void resizemat(Mat* A, int r, int c) +{ + if (A == NULL) return; + if ((A->row == r) && (A->col == c)) + return; + + for (int r = 0; r < A->row; r++) + free(A->d[r]); + + if (A->d != NULL) + free(A->d); + + A->row = r; A->col = c; + A->d = (double**)malloc(sizeof(double*) * r); + for (int i = 0; i < r; i++) + A->d[i] = (double*)malloc(sizeof(double) * c); +} + +void resizecmat(CMat* A, int r, int c) +{ + if (A == NULL) return; + if ((A->row == r) && (A->col == c)) + return; + + for (int r = 0; r < A->row; r++) + free(A->d[r]); + + if (A->d != NULL) + free(A->d); + + A->row = r; A->col = c; + A->d = (cplx**)malloc(sizeof(cplx*) * r); + for (int i = 0; i < r; i++) + A->d[i] = (cplx*)malloc(sizeof(cplx) * c); +} + + +void freecmat(CMat* A) { + if (A == NULL) return; + + for (int r = 0; r < A->row; r++) + free(A->d[r]); + + if (A->d!=NULL) + free(A->d); + + free(A); +} + +void freemat(Mat* A) { + if (A == NULL) return; + + for (int r = 0; r < A->row; r++) + free(A->d[r]); + + if (A->d!=NULL) + free(A->d); + + free(A); +} + +CMat* ceye(int n) { + CMat* I = newcmat(n, n, 0,0); + for (int i = 0; i < n; i++) { + I->d[i][i].re = 1; + } + return I; +} + +Mat* eye(int n) { + Mat* I = newmat(n, n, 0); + for (int i = 0; i < n; i++) { + I->d[i][i] = 1; + } + return I; +} +Mat* zeros(int r, int c) { + Mat* Z = newmat(r, c, 0); + return Z; +} + +CMat* czeros(int r, int c) { + CMat* Z = newcmat(r, c, 0,0); + return Z; +} + + +Mat* ones(int r, int c) { + Mat* O = newmat(r, c, 1); + return O; +} + +CMat* cones(int r, int c) { + CMat* O = newcmat(r, c, 1,0); + return O; +} + +Mat* randm(int r, int c, double l, double u) { + Mat* R = newmatnoinit(r, c); + + for (int i = 0; i < r; i++) { + for (int j = 0; j < c; j++) { + double rx = ((double)rand()) / ((double)RAND_MAX); + R->d[i][j] = l + (u - l) * rx; + } + } + return R; +} + + +CMat* randcm(int r, int c, double l, double u) { + CMat* R = newcmatnoinit(r, c); + + double ks = u - l; + for (int i = 0; i < r; i++) { + for (int j = 0; j < c; j++) { + + setcplx(&(R->d[i][j]), + l + ks * ((double)rand()) / ((double)RAND_MAX), + l + ks * ((double)rand()) / ((double)RAND_MAX)); + } + } + return R; +} + + + +double get(Mat* M, int r, int c) { + double d = M->d[r][c]; + return d; +} + +cplx getcplx(CMat* M, int r, int c) +{ + return M->d[r][c]; +} + +void set(Mat* M, int r, int c, double d) { + M->d[r][c] = d; +} + +void setc(CMat* M, int r, int c, cplx d) +{ + M->d[r][c] = d; +} + +Mat* scalarmultiply(Mat* M, double c) { + Mat* B = newmatnoinit(M->row, M->col); + + for (int i = 0; i < M->row; i++) { + for (int j = 0; j < M->col; j++) { + B->d[i][j] = M->d[i][j] * c; + } + } + return B; +} + + +CMat* cscalarmultiply(CMat* M, double c) { + CMat* B = newcmatnoinit(M->row, M->col); + + for (int i = 0; i < M->row; i++) { + for (int j = 0; j < M->col; j++) { + cmultd(&(B->d[i][j]), M->d[i][j], c); + } + } + return B; +} + + +CMat* complexmultiply(CMat* M, cplx c) { + CMat* B = newcmatnoinit(M->row, M->col); + + for (int i = 0; i < M->row; i++) { + for (int j = 0; j < M->col; j++) { + cmultc(&(B->d[i][j]), M->d[i][j], c); + } + } + return B; +} + +int complexmultiplydest(CMat* M, cplx c, CMat* dest) { + + for (int i = 0; i < M->row; i++) { + for (int j = 0; j < M->col; j++) { + cmultc(&(dest->d[i][j]), M->d[i][j], c); + } + } + return (OK); +} + +Mat* sum(Mat* A, Mat* B) { + int r = A->row; + int c = A->col; + Mat* C = newmatnoinit(r, c); + int k = 0; + for (int i = 0; i < r; i++) { + for (int j = 0; j < c; j++) { + C->d[i][j] = A->d[i][j] + B->d[i][j]; + } + } + return C; +} + +CMat* csum(CMat* A, CMat* B) { + int r = A->row; + int c = A->col; + CMat* C = newcmatnoinit(r, c); + + for (int i = 0; i < r; i++) { + for (int j = 0; j < c; j++) { + caddc(&(C->d[i][j]), (A->d[i][j]), (B->d[i][j])); + } + } + return C; +} +Mat* minus(Mat* A, Mat* B) { + int r = A->row; + int c = A->col; + Mat* C = newmatnoinit(r, c); + + for (int i = 0; i < r; i++) { + for (int j = 0; j < c; j++) { + C->d[i][j] = A->d[i][j] - B->d[i][j]; + } + } + return C; +} + + +CMat* cminus(CMat* A, CMat* B) { + int r = A->row; + int c = A->col; + CMat* C = newcmatnoinit(r, c); + + for (int i = 0; i < r; i++) { + for (int j = 0; j < c; j++) { + csubc(&(C->d[i][j]), + A->d[i][j], + B->d[i][j]); + } + } + return C; +} + + +Mat* submat(Mat* A, int r1, int r2, int c1, int c2) { + Mat* B = newmatnoinit(r2 - r1 + 1, c2 - c1 + 1); + + for (int i = r1, id =0 ; i <= r2; i++, id++) { + for (int j = c1, jd=0; j <= c2; j++, jd++) { + B->d[id][jd] = A->d[i][j]; + } + } + return B; +} + + +void submat2(Mat* A, Mat* B, int r1, int r2, int c1, int c2) { + + for (int i = r1, id = 0; i <= r2; i++, id++) { + for (int j = c1, jd = 0; j <= c2; j++, jd++) { + B->d[id][jd] = A->d[i][j]; + } + } +} + +CMat* subcmat(CMat* A, int r1, int r2, int c1, int c2) { + CMat* B = newmatnoinit(r2 - r1 + 1, c2 - c1 + 1); + int k = 0; + for (int i = r1; i <= r2; i++) { + for (int j = c1; j <= c2; j++) { + B->d[k++] = A->d[i * A->col + j]; + } + } + return B; +} + + +void subcmat2(CMat* A, CMat* B, int r1, int r2, int c1, int c2) { + int k = 0; + for (int i = r1; i <= r2; i++) { + for (int j = c1; j <= c2; j++) { + + B->d[k++] = A->d[i* A->col + j]; + } + } +} + +Mat* multiply(Mat* A, Mat* B) { + int r1 = A->row; + int r2 = B->row; + int c1 = A->col; + int c2 = B->col; + if (r1 == 1 && c1 == 1) { + Mat* C = scalarmultiply(B, A->d[0][0]); + return C; + } + else if (r2 == 1 && c2 == 1) { + Mat* C = scalarmultiply(A, B->d[0][0]); + return C; + } + Mat* C = newmatnoinit(r1, c2); + for (int i = 0; i < r1; i++) { + for (int j = 0; j < c2; j++) { + double de = 0; + for (int k = 0; k < r2; k++) { + de += A->d[i][k] * B->d[k][j]; + } + C->d[i][j] = de; + } + } + return C; +} + + +CMat* cmultiply(CMat* A, CMat* B) { + int r1 = A->row; + int r2 = B->row; + int c1 = A->col; + int c2 = B->col; + if (r1 == 1 && c1 == 1) { + CMat* C = complexmultiply(B, A->d[0][0]); + return C; + } + else if (r2 == 1 && c2 == 1) { + CMat* C = complexmultiply(A, B->d[0][0]); + return C; + } + CMat* C = newcmatnoinit(r1, c2); + for (int i = 0; i < r1; i++) { + for (int j = 0; j < c2; j++) { + cplx de; + de.re = de.im = 0; + for (int k = 0; k < r2; k++) { + caddc(&de, de, cmultco(A->d[i][k], B->d[k][j])); + } + C->d[i][j] = de; + } + } + return C; +} + + +int cmultiplydest(CMat* A, CMat* B, CMat* dest) { + int r1 = A->row; + int r2 = B->row; + int c1 = A->col; + int c2 = B->col; + // r2 must be = c1 + if (r1 == 1 && c1 == 1) { + complexmultiplydest(B, A->d[0][0],dest); + return (OK); + } + else if (r2 == 1 && c2 == 1) { + complexmultiply(A, B->d[0][0],dest); + return (OK); + } + + for (int i = 0; i < r1; i++) { + for (int j = 0; j < c2; j++) { + cplx de; + de.re = de.im = 0; + for (int k = 0; k < r2; k++) { + caddc(&de, de, cmultco(A->d[i][k], B->d[k][j])); + } + dest->d[i][j] = de; + } + } + return (OK); +} +//----------------------------------------- +Mat* removerow(Mat* A, int r) { + Mat* B = newmatnoinit(A->row - 1, A->col); + int rowdest = 0; + for (int i = 0; i < A->row; i++) { + if (i!=r) + { + for (int j = 0; j < A->col; j++) + B->d[rowdest][j] = A->d[i][j]; + + rowdest++; + } + } + return B; +} +Mat* removecol(Mat* A, int c) { + Mat* B = newmatnoinit(A->row, A->col - 1); + int coldest = 0 ; + for (int i = 0; i < A->row; i++) { + for (int j = 0; j < A->col; j++) { + if (j != c) { + B->d[i][coldest] = A->d[i][j]; + coldest++; + } + } + } + return B; +} +void removerow2(Mat* A, Mat* B, int r) { + int rowdest = 0; + for (int i = 0; i < A->row; i++) { + if (i != r) + { + for (int j = 0; j < A->col; j++) + B->d[rowdest][j] = A->d[i][j]; + + rowdest++; + } + } + return; +} +void removecol2(Mat* A, Mat* B, int c) { + int coldest = 0; + for (int i = 0; i < A->row; i++) { + for (int j = 0; j < A->col; j++) { + if (j != c) { + B->d[i][coldest] = A->d[i][j]; + coldest++; + } + } + } + return; +} + + + + +CMat* cremoverow(CMat* A, int r) { + CMat* B = newcmatnoinit(A->row - 1, A->col); + + int rowdest = 0; + for (int i = 0; i < A->row; i++) { + if (i != r) + { + for (int j = 0; j < A->col; j++) + B->d[rowdest][j] = A->d[i][j]; + + rowdest++; + } + } + return B; +} +CMat* cremovecol(CMat* A, int c) { + CMat* B = newcmatnoinit(A->row, A->col - 1); + int coldest = 0; + for (int i = 0; i < A->row; i++) { + for (int j = 0; j < A->col; j++) { + if (j != c) { + B->d[i][coldest] = A->d[i][j]; + coldest++; + } + } + } + return B; +} +void cremoverow2(CMat* A, CMat* B, int r) { + int rowdest = 0; + for (int i = 0; i < A->row; i++) { + if (i != r) + { + for (int j = 0; j < A->col; j++) + B->d[rowdest][j] = A->d[i][j]; + + rowdest++; + } + } + return; +} +void cremovecol2(CMat* A, CMat* B, int c) { + int coldest = 0; + for (int i = 0; i < A->row; i++) { + for (int j = 0; j < A->col; j++) { + if (j != c) { + B->d[i][coldest] = A->d[i][j]; + coldest++; + } + } + } + return; +} + + + +Mat* transpose(Mat* A) { + Mat* B = newmatnoinit(A->col, A->row); + int k = 0; + for (int i = 0; i < A->col; i++) { + for (int j = 0; j < A->row; j++, k++) { + B->d[j][i] = A->d[i][j]; + } + } + return B; +} + +CMat* ctranspose(CMat* A) { + CMat* B = newcmatnoinit(A->col, A->row); + int k = 0; + for (int i = 0; i < A->col; i++) { + for (int j = 0; j < A->row; j++, k++) { + B->d[j][i] = A->d[i][j]; + } + } + return B; +} + + + + +double det(Mat* M) { + int r = M->row; + int c = M->col; + if (r == 1 && c == 1) { + double d = M->d[0][0]; + return d; + } + Mat* M1 = removerow(M, 1); + Mat* M2 = newmatnoinit(M->row - 1, M->col - 1); + double d = 0, si = +1; + for (int j = 0; j < M->col; j++) { + double cx = M->d[0][j]; + removecol2(M1, M2, j); + d += si * det(M2) * cx; + si *= -1; + } + freemat(M1); + freemat(M2); + return d; +} + + +cplx cdet(CMat* M) { + int r = M->row; + int c = M->col; + if (r == 1 && c == 1) { + cplx d = M->d[0][0]; + return d; + } + CMat* M1 = cremoverow(M, 0); + CMat* M2 = newcmatnoinit(M->row - 1, M->col - 1); + cplx d; double si = +1; + d.re = d.im = 0; + + for (int j = 0; j < M->col; j++) { + cplx cx = M->d[0][j]; + cremovecol2(M1, M2, j); + cplx d2 = cmultdo(cmultco(cdet(M2), cx), si); + caddc(&d, d, d2); + si = -si; + } + freecmat(M1); + freecmat(M2); + return d; +} + + +double trace(Mat* A) { + double d = 0; + for (int i = 0; i < A->row; i++) { + d += A->d[i][i]; + } + return d; +} + + +cplx ctrace(CMat* A) { + cplx d; + d.re = d.im = 0; + for (int i = 0; i < A->row; i++) { + d=caddco(d, A->d[i][i]); + } + return d; +} + + +Mat* adjoint(Mat* A) { + Mat* B = newmatnoinit(A->row, A->col); + Mat* A1 = newmatnoinit(A->row - 1, A->col); + Mat* A2 = newmatnoinit(A->row - 1, A->col - 1); + for (int i = 0; i < A->row; i++) { + removerow2(A, A1, i); + for (int j = 0; j < A->col; j++) { + removecol2(A1, A2, j); + double si = (i + j) % 2 ? -1.0 : 1.0; + B->d[i][j] = det(A2) * si; + } + } + Mat* C = transpose(B); + freemat(A1); + freemat(A2); + freemat(B); + return C; +} + + + + + +CMat* cadjoint(CMat* A) { + CMat* B = newcmatnoinit(A->row, A->col); + CMat* A1 = newcmatnoinit(A->row - 1, A->col); + CMat* A2 = newcmatnoinit(A->row - 1, A->col - 1); + for (int i = 0; i < A->row; i++) { + cremoverow2(A, A1, i); + for (int j = 0; j < A->col; j++) { + cremovecol2(A1, A2, j); + double si = (i + j) % 2 ? -1.0 : 1.0; + B->d[i][j] = cmultdo( cdet(A2) , si); + } + } + CMat* C = ctranspose(B); + freecmat(A1); + freecmat(A2); + freecmat(B); + return C; +} + +Mat* inverse(Mat* A) { + Mat* B = adjoint(A); + double de = det(A); + Mat* C = scalarmultiply(B, 1 / de); + freemat(B); + return C; +} + +CMat* cinverse(CMat* A) { + CMat* B = cadjoint(A); + cplx de = cinv(cdet(A)); + + CMat* C = complexmultiply(B, de); + freecmat(B); + return C; +} + +int cinversedest(CMat* A, CMat* dest) { + CMat* B = cadjoint(A); + cplx de = cinv(cdet(A)); + + complexmultiplydest(B, de, dest); + freecmat(B); + return (OK); +} + + +Mat* copyvalue(Mat* A) { + Mat* B = newmatnoinit(A->row, A->col); + + for (int i = 0; i < A->row; i++) { + for (int j = 0; j < A->col; j++) { + B->d[i][j] = A->d[i][j]; + } + } + return B; +} + + +CMat* copycvalue(CMat* A) { + CMat* B = newcmatnoinit(A->row, A->col); + + for (int i = 0; i < A->row; i++) { + for (int j = 0; j < A->col; j++) { + B->d[i][j] = A->d[i][j]; + } + } + return B; +} + +int copycvaluedest(CMat* A,CMat* dest) { + + for (int i = 0; i < A->row; i++) { + for (int j = 0; j < A->col; j++) { + dest->d[i][j] = A->d[i][j]; + } + } + return (OK); +} + + +Mat* triinverse(Mat* A) { + Mat* B = newmatnoinit(A->row, A->col); + for (int i = 0; i < B->row; i++) { + for (int j = i; j < B->col; j++) { + if (i == j) { + B->d[i][j] = 1 / A->d[i][j]; + } + else { + B->d[i][j] = -A->d[i][j] / A->d[j][j]; + } + } + } + return B; +} + +CMat* ctriinverse(CMat* A) { + CMat* B = newcmatnoinit(A->row, A->col); + for (int i = 0; i < B->row; i++) { + for (int j = i; j < B->col; j++) { + if (i == j) { + B->d[i][j] = cinv(A->d[i][j]); + } + else { + B->d[i][j] = cmultdo( cmultco(A->d[i][j], cinv( A->d[j][j])), -1.0); + } + } + } + return B; +} + + +Mat* rowechelon(Mat* A) { + if (A->row == 1) { + for (int j = 0; j < A->col; j++) { + if (A->d[j] != 0) { + Mat* B = scalarmultiply(A, 1 / A->d[0][j]); + return B; + } + } + Mat* B = newmat(1, A->col, 0); + return B; + } + + + Mat* B = copyvalue(A); + int ind1 = B->col; + int ind2 = 0; + for (int i = 0; i < B->row; i++) { + for (int j = 0; j < B->col; j++) { + if (B->d[i * B->col + j] != 0 && j < ind1) { + ind1 = j; + ind2 = i; + break; + } + } + }//TODOHERE + // Swap columns + if (ind2 > 0) { + for (int j = 0; j < B->col; j++) { + double temp = B->d[0][j]; + B->d[0][j] = B->d[ind2][j]; + B->d[ind2][j] = temp; + } + } + + if (B->d[0][0] != 0) { + double coeff = B->d[0][0]; + for (int j = 0; j < B->col; j++) { + B->d[0][j] /= coeff; + } + + for (int i = 1; i < B->row; i++) { + coeff = B->d[i][0]; + + for (int j = 0; j < B->col; j++) { + B->d[i][j] -= coeff * B->d[0][j]; + } + } + } + else { + double coeff = 0; + for (int j = 0; j < B->col; j++) { + if (B->d[0][j] != 0 && coeff == 0) { + coeff = B->d[0][j]; + B->d[0][j] = 1; + } + else if (B->d[0][j] != 0) { + B->d[0][j] /= coeff; + } + } + } + + Mat* B1 = removerow(B, 1); + Mat* B2 = removecol(B1, 1); + Mat* Be = rowechelon(B2); + + for (int i = 0, iB=1; i <= Be->row; i++, iB++) { + for (int j = 0, jB=1; j <= Be->col; j++, jB++) { + + B->d[iB][jB] = Be->d[i][j]; + } + } + freemat(B1); + freemat(B2); + freemat(Be); + return B; +} + + + +CMat* crowechelon(CMat* A) { + if (A->row == 1) { + for (int j = 0; j < A->col; j++) { + if (cmod(A->d[0][j]) != 0) { + CMat* B = complexmultiply(A,cinv(A->d[0][j])); + return B; + } + } + CMat* B = newcmat(1, A->col, 0,0); + return B; + } + + + CMat* B = copycvalue(A); + int ind1 = B->col; + int ind2 = 0; + + for (int i = 0; i < B->row; i++) { + for (int j = 0; j < B->col; j++) { + if (!ciszero(B->d[i][j]) && j < ind1) { + ind1 = j; + ind2 = i; + break; + } + } + } + // Swap columns + if (ind2 > 0) { + for (int j = 0; j < B->col; j++) { + cplx temp = B->d[0][j]; + B->d[0][j] = B->d[ind2][j]; + B->d[ind2][j] = temp; + } + } + + if (!ciszero(B->d[0][0])) { + cplx coeff = cinv(B->d[0][0]); + for (int j = 0; j < B->col; j++) { + B->d[0][j] = cmultco(B->d[0][j], coeff); + } + + for (int i = 1; i < B->row; i++) { + coeff = B->d[i][0]; + + for (int j = 0; j < B->col; j++) { + B->d[i][j] = csubco(B->d[i][j], cmultco(B->d[0][j], coeff)); + } + } + } + else { + cplx coeff; coeff.re = coeff.im = 0.0; + for (int j = 0; j < B->col; j++) { + if (!ciszero(B->d[0][j]) && ciszero(coeff)) { + coeff = cinv(B->d[0][j]); + B->d[0][j].re = 1; B->d[0][j].im = 0.0; + } + else + B->d[0][j] = cmultco(B->d[0][j], coeff); + } + } + + CMat* B1 = cremoverow(B, 0); + CMat* B2 = cremovecol(B1, 0); + CMat* Be = crowechelon(B2); + + for (int i = 0, iB = 1; i <= Be->row; i++, iB++) { + for (int j = 0, jB = 1; j <= Be->col; j++, jB++) { + + B->d[iB][jB] = Be->d[i][j]; + } + } + freecmat(B1); + freecmat(B2); + freecmat(Be); + return B; +} + + +Mat* hconcat(Mat* A, Mat* B) { + Mat* C = newmatnoinit(A->row, A->col + B->col); + for (int i = 0; i < A->row; i++) { + int k = 0; + for (int j = 0; j < A->col; j++, k++) { + C->d[i][k] = A->d[i][j]; + } + for (int j = 0; j < B->col; j++, k++) { + C->d[i][k] = B->d[i][j]; + } + } + return C; +} + +CMat* chconcat(CMat* A, CMat* B) { + CMat* C = newcmatnoinit(A->row, A->col + B->col); + int k = 0; + for (int i = 0; i < A->row; i++) { + int k = 0; + for (int j = 0; j < A->col; j++, k++) { + C->d[i][k] = A->d[i][j]; + } + for (int j = 0; j < B->col; j++, k++) { + C->d[i][k] = B->d[i][j]; + } + } + return C; +} +Mat* vconcat(Mat* A, Mat* B) { + Mat* C = newmatnoinit(A->row + B->row, A->col); + int k = 0; + for (int i = 0; i < A->row; i++, k++) { + for (int j = 0; j < A->col; j++) { + C->d[k][j] = A->d[i][j]; + } + } + for (int i = 0; i < B->row; i++, k++) { + for (int j = 0; j < B->col; j++) { + C->d[k][j] = B->d[i][j]; + } + } + return C; +} + +CMat* cvconcat(CMat* A, CMat* B) { + CMat* C = newcmatnoinit(A->row + B->row, A->col); + int k = 0; + for (int i = 0; i < A->row; i++, k++) { + for (int j = 0; j < A->col; j++) { + C->d[k][j] = A->d[i][j]; + } + } + for (int i = 0; i < B->row; i++, k++) { + for (int j = 0; j < B->col; j++) { + C->d[k][j] = B->d[i][j]; + } + } + return C; +} + +double norm(Mat* A) { + double d = 0; + + for (int i = 0; i < A->row; i++) { + for (int j = 0; j < A->col; j++) { + double d0 = A->d[i][j]; + d += d0*d0; + } + } + d = sqrt(d); + return d; +} + +double cnorm(CMat* A) { + double d = 0; + int k = 0; + for (int i = 0; i < A->row; i++) { + for (int j = 0; j < A->col; j++) { + d += cmod(A->d[i][j]); + } + } + d = sqrt(d); + return d; +} + + +Mat* nullmat(Mat* A) { + Mat* RM = rowechelon(A); + int k = RM->row; + for (int i = RM->row-1; i >= 0; i--) { + bool flag = FALSE; + for (int j = 0; j < RM->col; j++) { + if (RM->d[i][j] != 0) { + flag = TRUE; + break; + } + } + if (flag) { + k = i; + break; + } + } + Mat* RRM = submat(RM, 0, k-1, 0, RM->col-1); + freemat(RM); + int nn = RRM->col - RRM->row; + if (nn == 0) { + Mat* N = newmat(0, 0, 0); + return N; + } + Mat* R1 = submat(RRM, 0, RRM->row-1, 0, RRM->row-1); + Mat* R2 = submat(RRM, 0, RRM->row-1, RRM->row, RRM->col-1); + freemat(RRM); + Mat* I = eye(nn); + Mat* T1 = multiply(R2, I); + freemat(R2); + Mat* R3 = scalarmultiply(T1, -1); + freemat(T1); + Mat* T2 = triinverse(R1); + freemat(R1); + Mat* X = multiply(T2, R3); + freemat(T2); + freemat(R3); + Mat* N = vconcat(X, I); + freemat(I); + freemat(X); + for (int j = 0; j < N->col; j++) { + double de = 0; + for (int i = 0; i < N->row; i++) { + de += N->d[i][j] * N->d[i][j]; + } + de = sqrt(de); + for (int i = 1; i <= N->row; i++) { + N->d[i][j] /= de; + } + + } + return N; +} + +MatList* lu(Mat* A) { + if (A->row == 1) { + MatList* ml = (MatList*)malloc(sizeof(MatList)); + ml->mat = newmat(1, 1, A->d[0][0]); + ml->next = (MatList*)malloc(sizeof(MatList)); + ml->next->mat = newmat(1, 1, 1); + return ml; + } + double a = A->d[0][0]; + double c = 0; + if (a != 0) { + c = 1 / a; + } + Mat* w = submat(A, 0, 0, 1, A->col-1); + Mat* v = submat(A, 1, A->row-1, 0, 0); + Mat* Ab = submat(A, 1, A->row-1, 1, A->col-1); + Mat* T1 = multiply(v, w); + Mat* T2 = scalarmultiply(T1, -c); + Mat* T3 = sum(Ab, T2); + MatList* mlb = lu(T3); + freemat(T1); + freemat(T2); + freemat(T3); + freemat(Ab); + Mat* L = newmat(A->row, A->col, 0); + Mat* U = newmat(A->row, A->col, 0); + for (int i = 0; i < A->row; i++) { + for (int j = 0; j < A->col; j++) { + if (i == 0 && j == 0) { + L->d[i][j] = 1; + U->d[i][j] = a; + } + else if (i == 0 && j > 0) { + U->d[i][j] = w->d[0][j - 1]; + } + else if (i > 0 && j == 0) { + L->d[i][j] = c * v->d[0][i - 1]; + } + else { + L->d[i][j] = mlb->mat->d[i-1][j-1]; + U->d[i][j] = mlb->next->mat->d[i-1][j-1]; + } + } + } + MatList* ml = (MatList*)malloc(sizeof(MatList)); + ml->mat = L; + ml->next = (MatList*)malloc(sizeof(MatList));; + ml->next->mat = U; + freemat(w); + freemat(v); + free(mlb); + return ml; +} + +double innermultiply(Mat* a, Mat* b) { + double d = 0; + int n = a->row; + if (a->col > n) { + n = a->col; + } + for (int i = 0; i <= n; i++) { + d += a->d[0][i] * b->d[0][i]; + } + return d; +} + +MatList* qr(Mat* A) { + int r = A->row; + int c = A->col; + Mat* Q = newmat(r, r, 0); + Mat* R = newmat(r, c, 0); + Mat* ek = newmat(r, 1, 0); + Mat* uj = newmat(r, 1, 0); + Mat* aj = newmat(r, 1, 0); + + for (int j = 0; j < r; j++) { + submat2(A, aj, 0, r-1, j, j); + for (int k = 0; k < r; k++) { + uj->d[0][k] = aj->d[0][k]; + } + for (int k = 0; k < j - 1; k++) { + submat2(Q, ek, 0, r-1, k, k); + double proj = innermultiply(aj, ek); + for (int l = 0; l < ek->row; l++) { + ek->d[0][l] *= proj; + + } + uj = minus(uj, ek); + } + double nuj = norm(uj); + for (int i = 0; i < r; i++) { + Q->d[i][j] = uj->d[0][i] / nuj; + } + for (int j1 = j-1; j1 < c; j1++) { + R->d[j][j1] = innermultiply(uj, submat(A, 0, r-1, j1, j1)) / nuj; + } + } + MatList* ml = (MatList*)malloc(sizeof(MatList)); + ml->mat = Q; + ml->next = (MatList*)malloc(sizeof(MatList));; + ml->next->mat = R; + freemat(ek); + freemat(uj); + freemat(aj); + return ml; +} + diff --git a/src/maths/dense/dense.h b/src/maths/dense/dense.h new file mode 100644 index 000000000..a32366dac --- /dev/null +++ b/src/maths/dense/dense.h @@ -0,0 +1,103 @@ +#ifndef ngspice_DENSE_MATRIX_H +#define ngspice_DENSE_MATRIX_H + + +typedef struct cplx +{ + double re; + double im; +}cplx; + +typedef struct Mat{ + double** d; + int row; + int col; +}Mat; + +typedef struct CMat { + cplx** d; + int row; + int col; +}CMat; + + +typedef struct MatList{ + Mat* mat; + struct MatList* next; +}MatList; + +extern void showmat(Mat* A); +extern void showcmat(CMat* A); +extern CMat* newcmat(int r, int c, double dr, double di); +extern CMat* newcmatnoinit(int r, int c); +extern Mat* newmat(int r, int c, double d); +extern Mat* newmatnoinit(int r, int c); +extern void freecmat(CMat* A); +extern void freemat(Mat* A); +extern CMat* ceye(int n); +extern Mat* eye(int n); +extern Mat* zeros(int r, int c); +extern CMat* czeros(int r, int c); +extern Mat* ones(int r, int c); +extern CMat* cones(int r, int c); +extern Mat* randm(int r, int c, double l, double u); +extern CMat* randcm(int r, int c, double l, double u); +extern double get(Mat* M, int r, int c); +extern cplx getcplx(CMat* M, int r, int c); +extern void set(Mat* M, int r, int c, double d); +extern void setc(CMat* M, int r, int c, cplx d); +extern Mat* scalarmultiply(Mat* M, double c); +extern CMat* cscalarmultiply(CMat* M, double c); +extern CMat* complexmultiply(CMat* M, cplx c); +extern Mat* sum(Mat* A, Mat* B); +extern CMat* csum(CMat* A, CMat* B); +extern Mat* minus(Mat* A, Mat* B); +extern CMat* cminus(CMat* A, CMat* B); +extern Mat* submat(Mat* A, int r1, int r2, int c1, int c2); +extern void submat2(Mat* A, Mat* B, int r1, int r2, int c1, int c2); +extern CMat* subcmat(CMat* A, int r1, int r2, int c1, int c2); +extern void subcmat2(CMat* A, CMat* B, int r1, int r2, int c1, int c2); +extern Mat* multiply(Mat* A, Mat* B); +extern CMat* cmultiply(CMat* A, CMat* B); +extern Mat* removerow(Mat* A, int r); +extern Mat* removecol(Mat* A, int c); +extern void removerow2(Mat* A, Mat* B, int r); +extern void removecol2(Mat* A, Mat* B, int c); +extern CMat* cremoverow(CMat* A, int r); +extern CMat* cremovecol(CMat* A, int c); +extern void cremoverow2(CMat* A, CMat* B, int r); +extern void cremovecol2(CMat* A, CMat* B, int c); +extern Mat* transpose(Mat* A); +extern CMat* ctranspose(CMat* A); +extern double trace(Mat* A); +extern cplx ctrace(CMat* A); +extern Mat* adjoint(Mat* A); +extern CMat* cadjoint(CMat* A); +extern Mat* inverse(Mat* A); +extern CMat* cinverse(CMat* A); +extern Mat* copyvalue(Mat* A); +extern CMat* copycvalue(CMat* A); +extern Mat* copyvalue(Mat* A); +extern CMat* copycvalue(CMat* A); +extern Mat* triinverse(Mat* A); +extern CMat* ctriinverse(CMat* A); +extern Mat* rowechelon(Mat* A); +extern CMat* crowechelon(CMat* A); +extern Mat* hconcat(Mat* A, Mat* B); +extern CMat* chconcat(CMat* A, CMat* B); +extern Mat* vconcat(Mat* A, Mat* B); +extern CMat* cvconcat(CMat* A, CMat* B); +extern double norm(Mat* A); +extern double cnorm(CMat* A); +extern Mat* nullmat(Mat* A); +extern MatList* lu(Mat* A); +extern double innermultiply(Mat* a, Mat* b); +extern MatList* qr(Mat* A); +extern int complexmultiplydest(CMat* M, cplx c, CMat* dest); +extern int cinversedest(CMat* A, CMat* dest); +extern int copycvaluedest(CMat* A, CMat* dest); +extern int cmultiplydest(CMat* A, CMat* B, CMat* dest); + + + +#endif diff --git a/src/maths/ni/niaciter.c b/src/maths/ni/niaciter.c index 676d2cef9..5905aac56 100644 --- a/src/maths/ni/niaciter.c +++ b/src/maths/ni/niaciter.c @@ -19,6 +19,82 @@ Modified 1999 Emmanuel Rouat #include "ngspice/cktdefs.h" #include "ngspice/sperror.h" +#ifdef RFSPICE + // We don't need to reload the AC matrix for every port analysis + // So we split the NIacIter in two functions +int NIspPreload(CKTcircuit* ckt) +{ + + int error; + int ignore; + double startTime; + +retry: + ckt->CKTnoncon = 0; + + error = CKTacLoad(ckt); + + if (error) return(error); + + if (ckt->CKTniState & NIACSHOULDREORDER) { + startTime = SPfrontEnd->IFseconds(); + error = SMPcReorder(ckt->CKTmatrix, ckt->CKTpivotAbsTol, + ckt->CKTpivotRelTol, &ignore); + ckt->CKTstat->STATreorderTime += + SPfrontEnd->IFseconds() - startTime; + ckt->CKTniState &= ~NIACSHOULDREORDER; + if (error != 0) { + /* either singular equations or no memory, in either case, + * let caller handle problem + */ + return(error); + } + } + else { + startTime = SPfrontEnd->IFseconds(); + error = SMPcLUfac(ckt->CKTmatrix, ckt->CKTpivotAbsTol); + ckt->CKTstat->STATdecompTime += + SPfrontEnd->IFseconds() - startTime; + if (error != 0) { + if (error == E_SINGULAR) { + /* the problem is that the matrix can't be solved with the + * current LU factorization. Maybe if we reload and + * try to reorder again it will help... + */ + ckt->CKTniState |= NIACSHOULDREORDER; + goto retry; + } + return(error); /* can't handle E_BADMATRIX, so let caller */ + } + } + + return (OK); +}; + +int NIspSolve(CKTcircuit* ckt) +{ + double startTime; + startTime = SPfrontEnd->IFseconds(); + SMPcSolve(ckt->CKTmatrix, ckt->CKTrhs, + ckt->CKTirhs, ckt->CKTrhsSpare, + ckt->CKTirhsSpare); + ckt->CKTstat->STATsolveTime += SPfrontEnd->IFseconds() - startTime; + + ckt->CKTrhs[0] = 0; + ckt->CKTrhsSpare[0] = 0; + ckt->CKTrhsOld[0] = 0; + ckt->CKTirhs[0] = 0; + ckt->CKTirhsSpare[0] = 0; + ckt->CKTirhsOld[0] = 0; + + SWAP(double*, ckt->CKTirhs, ckt->CKTirhsOld); + + SWAP(double*, ckt->CKTrhs, ckt->CKTrhsOld); + return (OK); +}; + +#endif + int NIacIter(CKTcircuit *ckt) diff --git a/src/spicelib/analysis/analysis.c b/src/spicelib/analysis/analysis.c index ecb9279a6..8a4097bd8 100644 --- a/src/spicelib/analysis/analysis.c +++ b/src/spicelib/analysis/analysis.c @@ -16,6 +16,15 @@ extern SPICEanalysis DISTOinfo; extern SPICEanalysis NOISEinfo; extern SPICEanalysis SENSinfo; +#ifdef RFSPICE +extern SPICEanalysis SPinfo; + +#ifdef WITH_HB +extern SPICEanalysis HBinfo; +#endif + +#endif + #ifdef WITH_PSS extern SPICEanalysis PSSinfo; #endif @@ -41,6 +50,12 @@ SPICEanalysis *analInfo[] = { #ifdef WANT_SENSE2 &SEN2info, #endif +#ifdef RFSPICE + & SPinfo, +#ifdef WITH_HB + & HBinfo, +#endif +#endif }; diff --git a/src/spicelib/analysis/cktdest.c b/src/spicelib/analysis/cktdest.c index f9024209e..6c4fb82b4 100644 --- a/src/spicelib/analysis/cktdest.c +++ b/src/spicelib/analysis/cktdest.c @@ -104,6 +104,16 @@ CKTdestroy(CKTcircuit *ckt) nghash_free(ckt->DEVnameHash, NULL, NULL); nghash_free(ckt->MODnameHash, NULL, NULL); + +#ifdef RFSPICE + FREE(ckt->CKTrfPorts); + freecmat(ckt->CKTAmat); ckt->CKTAmat = NULL; + freecmat(ckt->CKTBmat); ckt->CKTBmat = NULL; + freecmat(ckt->CKTSmat); ckt->CKTSmat = NULL; + freecmat(ckt->CKTYmat); ckt->CKTYmat = NULL; + freecmat(ckt->CKTZmat); ckt->CKTZmat = NULL; +#endif + FREE(ckt); #ifdef XSPICE diff --git a/src/spicelib/analysis/cktspdum.c b/src/spicelib/analysis/cktspdum.c new file mode 100644 index 000000000..1e7d284d9 --- /dev/null +++ b/src/spicelib/analysis/cktspdum.c @@ -0,0 +1,108 @@ +/********** +Copyright 1990 Regents of the University of California. All rights reserved. +Author: 1985 Thomas L. Quarles +**********/ + + /* CKTspDump(ckt,freq,file) + * this is a simple program to dump the complex rhs vector + * into the rawfile. + */ + +#include "ngspice/ngspice.h" +#include "ngspice/smpdefs.h" +#include "ngspice/cktdefs.h" +#include "ngspice/iferrmsg.h" +#include "ngspice/ifsim.h" +#include "vsrc/vsrcdefs.h" + +unsigned int CKTmatrixIndex(CKTcircuit* ckt, unsigned int source, unsigned int dest) +{ + return source * ckt->CKTportCount + dest; +}; + +int CKTspCalcSMatrix(CKTcircuit* ckt) +{ + CMat* Ainv = cinverse(ckt->CKTAmat); + if (Ainv == NULL) return (E_NOMEM); + cmultiplydest(ckt->CKTBmat, Ainv, ckt->CKTSmat); + freecmat(Ainv); + return (OK); +} + +int CKTspCalcPowerWave(CKTcircuit* ckt) +{ + double* rhsold = ckt->CKTrhsOld; + double* irhsold = ckt->CKTirhsOld; + int col = ckt->CKTactivePort - 1; + for (int port = 0; port < ckt->CKTportCount; port++) + { + VSRCinstance* pSrc = (VSRCinstance*)(ckt->CKTrfPorts[port]); + int row = pSrc->VSRCportNum - 1; + double zi = pSrc->VSRCportZ0; + double iReal = -rhsold[pSrc->VSRCbranch]; + double iImag = -irhsold[pSrc->VSRCbranch]; + + double vReal = rhsold[pSrc->VSRCposNode] - rhsold[pSrc->VSRCnegNode]; + double vImag = irhsold[pSrc->VSRCposNode] - irhsold[pSrc->VSRCnegNode]; + // Forward wave (a) of i-th port, real (r) and imag (i) + cplx a; + a.re = pSrc->VSRCki * (vReal + zi * iReal); + a.im = pSrc->VSRCki * (vImag + zi * iImag); + + // Scattered wave (b) of i-th port, real (r) and imag (i) + cplx b; + b.re = pSrc->VSRCki * (vReal - zi * iReal); + b.im = pSrc->VSRCki * (vImag - zi * iImag); + + // fill in A and B matrices + setc(ckt->CKTAmat, row, col, a); + setc(ckt->CKTBmat, row, col, b); + + } + return (OK); +} + +int +CKTspDump(CKTcircuit *ckt, double freq, runDesc *plot) +{ + double *rhsold; + double *irhsold; + int i; + IFcomplex *data; + IFvalue freqData; + IFvalue valueData; + + rhsold = ckt->CKTrhsOld; + irhsold = ckt->CKTirhsOld; + freqData.rValue = freq; + unsigned int extraSPdataCount = ckt->CKTportCount * ckt->CKTportCount; + valueData.v.numValue = ckt->CKTmaxEqNum - 1 + extraSPdataCount; + + data = TMALLOC(IFcomplex, ckt->CKTmaxEqNum - 1 + extraSPdataCount); + valueData.v.vec.cVec = data; + for (i=0;iCKTmaxEqNum-1;i++) { + data[i].real = rhsold[i+1]; + data[i].imag = irhsold[i+1]; + } + + if (ckt->CKTrfPorts ) + { + // Cycle thru all ports + for (unsigned int pdest = 0; pdest < ckt->CKTportCount; pdest++) + { + for (unsigned int psource = 0; psource < ckt->CKTportCount; psource++) + { + unsigned int nPlot = ckt->CKTmaxEqNum - 1 + CKTmatrixIndex(ckt, pdest, psource); + cplx sij = ckt->CKTSmat->d[pdest][psource]; + data[nPlot].real = sij.re; + data[nPlot].imag = sij.im; + } + } + } + + + SPfrontEnd->OUTpData(plot, &freqData, &valueData); + + FREE(data); + return(OK); +} diff --git a/src/spicelib/analysis/span.c b/src/spicelib/analysis/span.c new file mode 100644 index 000000000..a0aa4db8a --- /dev/null +++ b/src/spicelib/analysis/span.c @@ -0,0 +1,736 @@ +/* +**** +* Alessio Cacciatori 2021 +**** +*/ +#include "ngspice/ngspice.h" +#include "ngspice/cktdefs.h" +#include "ngspice/spdefs.h" +#include "ngspice/devdefs.h" +#include "ngspice/sperror.h" + +#ifdef XSPICE +#include "ngspice/evt.h" +#include "ngspice/enh.h" +/* gtri - add - wbk - 12/19/90 - Add headers */ +#include "ngspice/mif.h" +#include "ngspice/evtproto.h" +#include "ngspice/ipctiein.h" +/* gtri - end - wbk */ +#endif + + + + +#ifdef RFSPICE +#include "vsrc/vsrcext.h" +#include "../maths/dense/dense.h" + +#define INIT_STATS() \ +do { \ + startTime = SPfrontEnd->IFseconds(); \ + startdTime = ckt->CKTstat->STATdecompTime; \ + startsTime = ckt->CKTstat->STATsolveTime; \ + startlTime = ckt->CKTstat->STATloadTime; \ + startkTime = ckt->CKTstat->STATsyncTime; \ +} while(0) + +#define UPDATE_STATS(analysis) \ +do { \ + ckt->CKTcurrentAnalysis = analysis; \ + ckt->CKTstat->STATacTime += SPfrontEnd->IFseconds() - startTime; \ + ckt->CKTstat->STATacDecompTime += ckt->CKTstat->STATdecompTime - startdTime; \ + ckt->CKTstat->STATacSolveTime += ckt->CKTstat->STATsolveTime - startsTime; \ + ckt->CKTstat->STATacLoadTime += ckt->CKTstat->STATloadTime - startlTime; \ + ckt->CKTstat->STATacSyncTime += ckt->CKTstat->STATsyncTime - startkTime; \ +} while(0) + + + +int +CKTspnoise(CKTcircuit * ckt, int mode, int operation, Ndata * data) +{ + NOISEAN* job = (NOISEAN*)ckt->CKTcurJob; + + double outNdens; + int i; + IFvalue outData; /* output variable (points to list of outputs)*/ + IFvalue refVal; /* reference variable (always 0)*/ + int error; + + outNdens = 0.0; + + /* let each device decide how many and what type of noise sources it has */ + + for (i = 0; i < DEVmaxnum; i++) { + if (DEVices[i] && DEVices[i]->DEVnoise && ckt->CKThead[i]) { + error = DEVices[i]->DEVnoise(mode, operation, ckt->CKThead[i], + ckt, data, &outNdens); + if (error) return (error); + } + } + + switch (operation) { + + case N_OPEN: + + /* take care of the noise for the circuit as a whole */ + + switch (mode) { + + case N_DENS: + + data->namelist = TREALLOC(IFuid, data->namelist, data->numPlots + 1); + + SPfrontEnd->IFnewUid(ckt, &(data->namelist[data->numPlots++]), + NULL, "onoise_spectrum", UID_OTHER, NULL); + + data->namelist = TREALLOC(IFuid, data->namelist, data->numPlots + 1); + + SPfrontEnd->IFnewUid(ckt, &(data->namelist[data->numPlots++]), + NULL, "inoise_spectrum", UID_OTHER, NULL); + + /* we've added two more plots */ + + data->outpVector = + TMALLOC(double, data->numPlots); + data->squared_value = + data->squared ? NULL : TMALLOC(char, data->numPlots); + break; + + case INT_NOIZ: + + data->namelist = TREALLOC(IFuid, data->namelist, data->numPlots + 1); + SPfrontEnd->IFnewUid(ckt, &(data->namelist[data->numPlots++]), + NULL, "onoise_total", UID_OTHER, NULL); + + data->namelist = TREALLOC(IFuid, data->namelist, data->numPlots + 1); + SPfrontEnd->IFnewUid(ckt, &(data->namelist[data->numPlots++]), + NULL, "inoise_total", UID_OTHER, NULL); + /* we've added two more plots */ + + data->outpVector = + TMALLOC(double, data->numPlots); + data->squared_value = + data->squared ? NULL : TMALLOC(char, data->numPlots); + break; + + default: + return (E_INTERN); + } + + break; + + case N_CALC: + + switch (mode) { + + case N_DENS: + if ((job->NStpsSm == 0) + || data->prtSummary) + { + data->outpVector[data->outNumber++] = outNdens; + data->outpVector[data->outNumber++] = + (outNdens * data->GainSqInv); + + refVal.rValue = data->freq; /* the reference is the freq */ + if (!data->squared) + for (i = 0; i < data->outNumber; i++) + if (data->squared_value[i]) + data->outpVector[i] = sqrt(data->outpVector[i]); + outData.v.numValue = data->outNumber; /* vector number */ + outData.v.vec.rVec = data->outpVector; /* vector of outputs */ + SPfrontEnd->OUTpData(data->NplotPtr, &refVal, &outData); + } + break; + + case INT_NOIZ: + data->outpVector[data->outNumber++] = data->outNoiz; + data->outpVector[data->outNumber++] = data->inNoise; + if (!data->squared) + for (i = 0; i < data->outNumber; i++) + if (data->squared_value[i]) + data->outpVector[i] = sqrt(data->outpVector[i]); + outData.v.vec.rVec = data->outpVector; /* vector of outputs */ + outData.v.numValue = data->outNumber; /* vector number */ + SPfrontEnd->OUTpData(data->NplotPtr, &refVal, &outData); + break; + + default: + return (E_INTERN); + } + break; + + case N_CLOSE: + SPfrontEnd->OUTendPlot(data->NplotPtr); + FREE(data->namelist); + FREE(data->outpVector); + FREE(data->squared_value); + break; + + default: + return (E_INTERN); + } + return (OK); +} + + +void +NInspIter(CKTcircuit * ckt, int posDrive, int negDrive) +{ + int i; + + /* clear out the right hand side vector */ + + for (i = 0; i <= SMPmatSize(ckt->CKTmatrix); i++) { + ckt->CKTrhs[i] = 0.0; + ckt->CKTirhs[i] = 0.0; + } + + ckt->CKTrhs[posDrive] = 1.0; /* apply unit current excitation */ + ckt->CKTrhs[negDrive] = -1.0; + SMPcaSolve(ckt->CKTmatrix, ckt->CKTrhs, ckt->CKTirhs, ckt->CKTrhsSpare, + ckt->CKTirhsSpare); + + ckt->CKTrhs[0] = 0.0; + ckt->CKTirhs[0] = 0.0; +} + + +int +SPan(CKTcircuit *ckt, int restart) +{ + + + SPAN *job = (SPAN *) ckt->CKTcurJob; + + double freq; + double freqTol; /* tolerence parameter for finding final frequency */ + double startdTime; + double startsTime; + double startlTime; + double startkTime; + double startTime; + int error; + int numNames; + int i; + IFuid *nameList; /* va: tmalloc'ed list of names */ + IFuid freqUid; + static runDesc *spPlot = NULL; + runDesc *plot = NULL; + + double* rhswoPorts = NULL; + double* irhswoPorts = NULL; + int* portPosNodes = NULL; + int* portNegNodes = NULL; + + + if (ckt->CKTportCount == 0) + { + fprintf(stderr, "No RF Port is present\n"); + return (E_PARMVAL); + } + + + + if (ckt->CKTAmat != NULL) freecmat(ckt->CKTAmat); + if (ckt->CKTBmat != NULL) freecmat(ckt->CKTBmat); + if (ckt->CKTSmat != NULL) freecmat(ckt->CKTSmat); + + ckt->CKTAmat = newcmat(ckt->CKTportCount, ckt->CKTportCount, 0.0, 0.0); + if (ckt->CKTAmat == NULL) + return (E_NOMEM); + ckt->CKTBmat = newcmat(ckt->CKTportCount, ckt->CKTportCount, 0.0, 0.0); + if (ckt->CKTBmat == NULL) + return (3); + + ckt->CKTSmat = newcmat(ckt->CKTportCount, ckt->CKTportCount, 0.0, 0.0); + if (ckt->CKTSmat == NULL) + return (E_NOMEM); + +#ifdef XSPICE +/* gtri - add - wbk - 12/19/90 - Add IPC stuff and anal_init and anal_type */ + + /* Tell the beginPlot routine what mode we're in */ + + // For now, let's keep this as IPC_ANAL_AC (TBD) + g_ipc.anal_type = IPC_ANAL_AC; + + /* Tell the code models what mode we're in */ + g_mif_info.circuit.anal_type = MIF_DC; + g_mif_info.circuit.anal_init = MIF_TRUE; + +/* gtri - end - wbk */ +#endif + + /* start at beginning */ + if (job->SPsaveFreq == 0 || restart) { + if (job->SPnumberSteps < 1) + job->SPnumberSteps = 1; + + switch (job->SPstepType) { + + case DECADE: + if (job->SPstartFreq <= 0) { + fprintf(stderr, "ERROR: AC startfreq <= 0\n"); + return E_PARMVAL; + } + job->SPfreqDelta = + exp(log(10.0)/job->SPnumberSteps); + break; + case OCTAVE: + if (job->SPstartFreq <= 0) { + fprintf(stderr, "ERROR: AC startfreq <= 0\n"); + return E_PARMVAL; + } + job->SPfreqDelta = + exp(log(2.0)/job->SPnumberSteps); + break; + case LINEAR: + if (job->SPnumberSteps-1 > 1) + job->SPfreqDelta = + (job->SPstopFreq - + job->SPstartFreq) / + (job->SPnumberSteps - 1); + else + /* Patch from: Richard McRoberts + * This patch is for a rather pathological case: + * a linear step with only one point */ + job->SPfreqDelta = 0; + break; + default: + return(E_BADPARM); + } +#ifdef XSPICE +/* gtri - begin - wbk - Call EVTop if event-driven instances exist */ + + if(ckt->evt->counts.num_insts != 0) { + error = EVTop(ckt, + (ckt->CKTmode & MODEUIC) | MODEDCOP | MODEINITJCT, + (ckt->CKTmode & MODEUIC) | MODEDCOP | MODEINITFLOAT, + ckt->CKTdcMaxIter, + MIF_TRUE); + EVTdump(ckt, IPC_ANAL_DCOP, 0.0); + EVTop_save(ckt, MIF_TRUE, 0.0); + } + else +#endif + /* 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); + } + } + else + fprintf(stdout,"\n Linear circuit, option noopac given: no OP analysis\n"); + +#ifdef XSPICE +/* gtri - add - wbk - 12/19/90 - Add IPC stuff */ + + /* Send the operating point results for Mspice compatibility */ + if(g_ipc.enabled) + { + /* Call CKTnames to get names of nodes/branches used by + BeginPlot */ + /* Probably should free nameList after this block since + called again... */ + error = CKTnames(ckt,&numNames,&nameList); + if(error) return(error); + + /* We have to do a beginPlot here since the data to return is + * different for the DCOP than it is for the AC analysis. + * Moreover the begin plot has not even been done yet at this + * point... + */ + SPfrontEnd->OUTpBeginPlot (ckt, ckt->CKTcurJob, + ckt->CKTcurJob->JOBname, + NULL, IF_REAL, + numNames, nameList, IF_REAL, + &spPlot); + txfree(nameList); + + ipc_send_dcop_prefix(); + CKTdump(ckt, 0.0, spPlot); + ipc_send_dcop_suffix(); + + SPfrontEnd->OUTendPlot (spPlot); + } +/* gtri - end - wbk */ +#endif + + ckt->CKTmode = (ckt->CKTmode & MODEUIC) | MODEDCOP | MODEINITSMSIG; + error = CKTload(ckt); + if(error) return(error); + + error = CKTnames(ckt,&numNames,&nameList); + if(error) return(error); + + if (ckt->CKTkeepOpInfo) { + /* Dump operating point. */ + error = SPfrontEnd->OUTpBeginPlot (ckt, ckt->CKTcurJob, + "AC Operating Point", + NULL, IF_REAL, + numNames, nameList, IF_REAL, + &plot); + if(error) return(error); + CKTdump(ckt, 0.0, plot); + SPfrontEnd->OUTendPlot (plot); + plot = NULL; + } + + unsigned int extraSPdataLength = ckt->CKTportCount * ckt->CKTportCount; + nameList = (IFuid*)TREALLOC(IFuid, nameList, numNames + extraSPdataLength); + + + // Create UIDs + for (unsigned int dest = 1; dest <= ckt->CKTportCount; dest++) + for (unsigned int j = 1; j <= ckt->CKTportCount; j++) + { + char tmpBuf[32]; + sprintf(tmpBuf, "S_%d_%d", dest, j); + + SPfrontEnd->IFnewUid(ckt, &(nameList[numNames++]), NULL, tmpBuf, UID_OTHER, NULL); + } + + SPfrontEnd->IFnewUid (ckt, &freqUid, NULL, "frequency", UID_OTHER, NULL); + error = SPfrontEnd->OUTpBeginPlot (ckt, ckt->CKTcurJob, + ckt->CKTcurJob->JOBname, + freqUid, IF_REAL, + numNames, nameList, IF_COMPLEX, + &spPlot); + + + + tfree(nameList); + if(error) return(error); + + if (job->SPstepType != LINEAR) { + SPfrontEnd->OUTattributes (spPlot, NULL, OUT_SCALE_LOG, NULL); + } + freq = job->SPstartFreq; + + } else { /* continue previous analysis */ + freq = job->SPsaveFreq; + job->SPsaveFreq = 0; /* clear the 'old' frequency */ + /* fix resume? saj, indeed !*/ + error = SPfrontEnd->OUTpBeginPlot (NULL, NULL, + NULL, + NULL, 0, + 666, NULL, 666, + &spPlot); + /* saj*/ + } + + switch (job->SPstepType) { + case DECADE: + case OCTAVE: + freqTol = job->SPfreqDelta * + job->SPstopFreq * ckt->CKTreltol; + break; + case LINEAR: + freqTol = job->SPfreqDelta * ckt->CKTreltol; + break; + default: + return(E_BADPARM); + } + + +#ifdef XSPICE +/* gtri - add - wbk - 12/19/90 - Set anal_init and anal_type */ + + g_mif_info.circuit.anal_init = MIF_TRUE; + + /* Tell the code models what mode we're in */ + g_mif_info.circuit.anal_type = MIF_AC; + +/* gtri - end - wbk */ +#endif + + INIT_STATS(); + + ckt->CKTcurrentAnalysis = DOING_AC; + + ckt->CKTactivePort = 0; + /* main loop through all scheduled frequencies */ + while (freq <= job->SPstopFreq + freqTol) { + + unsigned int activePort = 0; + // + if (SPfrontEnd->IFpauseTest()) { + /* user asked us to pause via an interrupt */ + job->SPsaveFreq = freq; + return(E_PAUSE); + } + ckt->CKTomega = 2.0 * M_PI * freq; + + /* Update opertating point, if variable 'hertz' is given */ + if (ckt->CKTvarHertz) { +#ifdef XSPICE + /* Call EVTop if event-driven instances exist */ + + if (ckt->evt->counts.num_insts != 0) { + error = EVTop(ckt, + (ckt->CKTmode & MODEUIC) | MODEDCOP | MODEINITJCT, + (ckt->CKTmode & MODEUIC) | MODEDCOP | MODEINITFLOAT, + ckt->CKTdcMaxIter, + MIF_TRUE); + EVTdump(ckt, IPC_ANAL_DCOP, 0.0); + EVTop_save(ckt, MIF_TRUE, 0.0); + } + 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 (error) { + fprintf(stdout, "\nAC operating point failed -\n"); + CKTncDump(ckt); + return(error); + } + ckt->CKTmode = (ckt->CKTmode & MODEUIC) | MODEDCOP | MODEINITSMSIG; + error = CKTload(ckt); + if (error) return(error); + } + // Let's sweep thru all available ports to build Y matrix + // Y_ij = I_i / V_j | V_k!=j = 0 + // (we have only to modify rhs) + + int vsrcLookupType = CKTtypelook("Vsource"); + int vsrcRoot = -1; + + // Get VSRCs root model + if (ckt->CKTVSRCid == -1) + { + for (i = 0; i < DEVmaxnum; i++) { + if (DEVices[i] && DEVices[i]->DEVacLoad && ckt->CKThead[i] && ckt->CKThead[i]->GENmodType == vsrcLookupType) { + + vsrcRoot = i; + break; + } + } + if (vsrcRoot == -1) + return (E_NOMOD); + + ckt->CKTVSRCid = vsrcRoot; + } + else + vsrcRoot = ckt->CKTVSRCid; + + if (rhswoPorts == NULL) + rhswoPorts = (double*)TREALLOC(double, rhswoPorts, ckt->CKTmaxEqNum); + if (irhswoPorts == NULL) + irhswoPorts = (double*)TREALLOC(double, irhswoPorts, ckt->CKTmaxEqNum); + + ckt->CKTmode = (ckt->CKTmode & MODEUIC) | MODESP; + // Pre-load everything but RF Ports (these will be updated in the next cycle). + error = NIspPreload(ckt); + if (error) return (error); + +// error = VSRCsaveNPData(ckt->CKThead[vsrcRoot]); +// if (error) return (error); + + //Keep a backup copy + memcpy(rhswoPorts, ckt->CKTrhs, ckt->CKTmaxEqNum * sizeof(double)); + memcpy(rhswoPorts, ckt->CKTirhs, ckt->CKTmaxEqNum * sizeof(double)); + + for (activePort = 1; activePort <= ckt->CKTportCount; activePort++) + { + // Copy the backup RHS into CKT's RHS + memcpy(ckt->CKTrhs, rhswoPorts, ckt->CKTmaxEqNum * sizeof(double)); + memcpy(ckt->CKTirhs, irhswoPorts, ckt->CKTmaxEqNum * sizeof(double)); + ckt->CKTactivePort = activePort; + + // Update only VSRCs + error = VSRCspupdate(ckt->CKThead[vsrcRoot], ckt); + if (error) + { + tfree(rhswoPorts); + tfree(irhswoPorts); + return(error); + } + + error = NIspSolve(ckt); + if (error) { + tfree(rhswoPorts); + tfree(irhswoPorts); + UPDATE_STATS(DOING_AC); + return(error); + } + + +#ifdef WANT_SENSE2 + if (ckt->CKTsenInfo && (ckt->CKTsenInfo->SENmode & ACSEN)) { + long save; + int save1; + + save = ckt->CKTmode; + ckt->CKTmode = (ckt->CKTmode & MODEUIC) | MODEDCOP | MODEINITSMSIG; + save1 = ckt->CKTsenInfo->SENmode; + ckt->CKTsenInfo->SENmode = ACSEN; + if (freq == job->SPstartFreq) { + ckt->CKTsenInfo->SENacpertflag = 1; + } + else { + ckt->CKTsenInfo->SENacpertflag = 0; + } + error = CKTsenAC(ckt); + if (error) + return (error); + ckt->CKTmode = save; + ckt->CKTsenInfo->SENmode = save1; + } +#endif + + // We have done 1 activated port. + error = CKTspCalcPowerWave(ckt); + + + } //active ports cycle + + // Now we can calculate the full S-Matrix + CKTspCalcSMatrix(ckt); + +#ifdef XSPICE + /* gtri - modify - wbk - 12/19/90 - Send IPC stuff */ + + if (g_ipc.enabled) + ipc_send_data_prefix(freq); + + error = CKTspDump(ckt, freq, spPlot); + + if (g_ipc.enabled) + ipc_send_data_suffix(); + + /* gtri - modify - wbk - 12/19/90 - Send IPC stuff */ +#else + error = CKTspDump(ckt, freq, acPlot); +#endif + if (error) { + UPDATE_STATS(DOING_AC); + tfree(rhswoPorts); + tfree(irhswoPorts); + return(error); + } + + + /* + * Now go with noise cycle, if required + */ + +#ifdef NOISE_AVAILABLE + + // To be completed + if (job->SPdoNoise) + { + if (portPosNodes == NULL) + { + portPosNodes = TMALLOC(int, ckt->CKTportCount); + portNegNodes = TMALLOC(int, ckt->CKTportCount); + VSRCgetActivePortNodes(ckt->CKThead[vsrcRoot], ckt, portPosNodes, portNegNodes); + } + + static Ndata* data; + + double realVal; + double imagVal; + int error; + int posOutNode; + int negOutNode; + //Keep a backup copy + memcpy(rhswoPorts, ckt->CKTrhs, ckt->CKTmaxEqNum * sizeof(double)); + memcpy(rhswoPorts, ckt->CKTirhs, ckt->CKTmaxEqNum * sizeof(double)); + + for (activePort = 0; activePort < ckt->CKTportCount; activePort++) + { + /* the frequency will NOT be stored in array[0] as before; instead, + * it will be given in refVal.rValue (see later) + */ + // Copy the backup RHS into CKT's RHS + memcpy(ckt->CKTrhs, rhswoPorts, ckt->CKTmaxEqNum * sizeof(double)); + memcpy(ckt->CKTirhs, irhswoPorts, ckt->CKTmaxEqNum * sizeof(double)); + ckt->CKTactivePort = activePort+1; + + posOutNode = portPosNodes[activePort]; + negOutNode = portNegNodes[activePort]; + NInspIter(ckt, posOutNode, negOutNode); /* solve the adjoint system */ + + /* now we use the adjoint system to calculate the noise + * contributions of each generator in the circuit + */ + + error = CKTspnoise(ckt, N_DENS, N_CALC, data); + if (error) + { + tfree(portPosNodes); tfree(portNegNodes); + return(error); + } + } + } +#endif + /* increment frequency */ + + switch (job->SPstepType) { + case DECADE: + case OCTAVE: + + /* inserted again 14.12.2001 */ +#ifdef HAS_PROGREP + { + double endfreq = job->SPstopFreq; + double startfreq = job->SPstartFreq; + endfreq = log(endfreq); + if (startfreq == 0.0) + startfreq = 1e-12; + startfreq = log(startfreq); + + if (freq > 0.0) + SetAnalyse("sp", (int)((log(freq) - startfreq) * 1000.0 / (endfreq - startfreq))); + } +#endif + + freq *= job->SPfreqDelta; + if (job->SPfreqDelta == 1) goto endsweep; + break; + case LINEAR: + +#ifdef HAS_PROGREP + { + double endfreq = job->SPstopFreq; + double startfreq = job->SPstartFreq; + SetAnalyse("sp", (int)((freq - startfreq) * 1000.0 / (endfreq - startfreq))); + } +#endif + + freq += job->SPfreqDelta; + if (job->SPfreqDelta == 0) goto endsweep; + break; + default: + tfree(rhswoPorts); + tfree(irhswoPorts); + tfree(portPosNodes); tfree(portNegNodes); + return(E_INTERN); + + } + } +endsweep: + SPfrontEnd->OUTendPlot (spPlot); + spPlot = NULL; + UPDATE_STATS(0); + tfree(rhswoPorts); + tfree(irhswoPorts); + tfree(portPosNodes); tfree(portNegNodes); + return(0); +} + + +#endif diff --git a/src/spicelib/analysis/spaskq.c b/src/spicelib/analysis/spaskq.c new file mode 100644 index 000000000..202b24a26 --- /dev/null +++ b/src/spicelib/analysis/spaskq.c @@ -0,0 +1,73 @@ +/********** +Copyright 1990 Regents of the University of California. All rights reserved. +Author: 1985 Thomas L. Quarles +**********/ +/* + */ + +#include "ngspice/ngspice.h" +#include "ngspice/ifsim.h" +#include "ngspice/iferrmsg.h" +#include "ngspice/spdefs.h" +#include "ngspice/cktdefs.h" + + +/* ARGSUSED */ +int +SPaskQuest(CKTcircuit *ckt, JOB *anal, int which, IFvalue *value) +{ + SPAN *job = (SPAN *) anal; + + NG_IGNORE(ckt); + + switch(which) { + + case SP_START: + value->rValue = job->SPstartFreq; + break; + + case SP_STOP: + value->rValue = job->SPstopFreq ; + break; + + case SP_STEPS: + value->iValue = job->SPnumberSteps; + break; + + case SP_DEC: + if (job->SPstepType == DECADE) { + value->iValue=1; + } else { + value->iValue=0; + } + break; + + case SP_OCT: + if (job->SPstepType == OCTAVE) { + value->iValue=1; + } else { + value->iValue=0; + } + break; + + case SP_LIN: + if (job->SPstepType == LINEAR) { + value->iValue=1; + } else { + value->iValue=0; + } + break; + + case SP_DONOISE: + if (job->SPdoNoise) + value->iValue = 1; + else + value->iValue = 0; + break; + + default: + return(E_BADPARM); + } + return(OK); +} + diff --git a/src/spicelib/analysis/spsetp.c b/src/spicelib/analysis/spsetp.c new file mode 100644 index 000000000..2f4b30a52 --- /dev/null +++ b/src/spicelib/analysis/spsetp.c @@ -0,0 +1,114 @@ +/********** +Copyright 1990 Regents of the University of California. All rights reserved. +Author: 1985 Thomas L. Quarles +**********/ + +#include "ngspice/ngspice.h" +#include "ngspice/ifsim.h" +#include "ngspice/iferrmsg.h" +#include "ngspice/spdefs.h" +#include "ngspice/cktdefs.h" + +#include "analysis.h" + +/* ARGSUSED */ +int +SPsetParm(CKTcircuit *ckt, JOB *anal, int which, IFvalue *value) +{ + SPAN *job = (SPAN *) anal; + + NG_IGNORE(ckt); + + switch(which) { + + case SP_START: + if (value->rValue < 0.0) { + errMsg = copy("Frequency of < 0 is invalid for AC start"); + job->SPstartFreq = 1.0; + return(E_PARMVAL); + } + + job->SPstartFreq = value->rValue; + break; + + case SP_STOP: + if (value->rValue < 0.0) { + errMsg = copy("Frequency of < 0 is invalid for AC stop"); + job->SPstartFreq = 1.0; + return(E_PARMVAL); + } + + job->SPstopFreq = value->rValue; + break; + + case SP_STEPS: + job->SPnumberSteps = value->iValue; + break; + + case SP_DEC: + if(value->iValue) { + job->SPstepType = DECADE; + } else { + if (job->SPstepType == DECADE) { + job->SPstepType = 0; + } + } + break; + + case SP_OCT: + if(value->iValue) { + job->SPstepType = OCTAVE; + } else { + if (job->SPstepType == OCTAVE) { + job->SPstepType = 0; + } + } + break; + + case SP_LIN: + if(value->iValue) { + job->SPstepType = LINEAR; + } else { + if (job->SPstepType == LINEAR) { + job->SPstepType = 0; + } + } + break; + + case SP_DONOISE: + job->SPdoNoise = value->iValue == 1; + break; + + default: + return(E_BADPARM); + } + return(OK); +} + + +static IFparm SPparms[] = { + { "start", SP_START, IF_SET|IF_ASK|IF_REAL, "starting frequency" }, + { "stop", SP_STOP, IF_SET|IF_ASK|IF_REAL, "ending frequency" }, + { "numsteps", SP_STEPS,IF_SET|IF_ASK|IF_INTEGER, "number of frequencies"}, + { "dec", SP_DEC, IF_SET|IF_FLAG, "step by decades" }, + { "oct", SP_OCT, IF_SET|IF_FLAG, "step by octaves" }, + { "lin", SP_LIN, IF_SET|IF_FLAG, "step linearly" }, + {"donoise", SP_DONOISE, IF_SET | IF_FLAG | IF_INTEGER, "do SP noise"} +}; + +SPICEanalysis SPinfo = { + { + "SP", + "S-Parameters analysis", + + NUMELEMS(SPparms), + SPparms + }, + sizeof(SPAN), + FREQUENCYDOMAIN, + 1, + SPsetParm, + SPaskQuest, + NULL, + SPan +}; diff --git a/src/spicelib/devices/cktinit.c b/src/spicelib/devices/cktinit.c index 0b5ae6d57..cc57200ad 100644 --- a/src/spicelib/devices/cktinit.c +++ b/src/spicelib/devices/cktinit.c @@ -134,5 +134,14 @@ CKTinit(CKTcircuit **ckt) /* new circuit to create */ g_mif_info.auto_partial.local = MIF_FALSE; /* gtri - end - wbk - 01/12/91 */ #endif + +#ifdef RFSPICE + sckt->CKTportCount = 0; + sckt->CKTactivePort = 0; + sckt->CKTVSRCid = -1; + sckt->CKTrfPorts = NULL; + sckt->CKTSmat = sckt->CKTAmat = sckt->CKTBmat = sckt->CKTYmat = sckt->CKTZmat = NULL; +#endif + return OK; } diff --git a/src/spicelib/devices/vsrc/vsrc.c b/src/spicelib/devices/vsrc/vsrc.c index f1c3913a9..c3e9872df 100644 --- a/src/spicelib/devices/vsrc/vsrc.c +++ b/src/spicelib/devices/vsrc/vsrc.c @@ -25,6 +25,13 @@ IFparm VSRCpTable[] = { /* parameters */ IOP ("trrandom", VSRC_TRRANDOM, IF_REALVEC,"random source description"), #ifdef SHARED_MODULE IOP ("external", VSRC_EXTERNAL, IF_STRING,"external source description"), +#endif + #ifdef RFSPICE + IOP("portnum", VSRC_PORTNUM, IF_INTEGER,"Port index"), + IOP("z0", VSRC_PORTZ0, IF_REAL, "Port impedance"), + IOP("pwr", VSRC_PORTPWR, IF_REAL, "Port Power"), + IOP("freq", VSRC_PORTFREQ, IF_REAL, "Port frequency"), + IOP("phase", VSRC_PORTPHASE, IF_REAL, "Phase of the source"), #endif OPU ("pos_node",VSRC_POS_NODE, IF_INTEGER,"Positive node of source"), OPU ("neg_node",VSRC_NEG_NODE, IF_INTEGER,"Negative node of source"), diff --git a/src/spicelib/devices/vsrc/vsrcacld.c b/src/spicelib/devices/vsrc/vsrcacld.c index 8ea4e345b..221bb8ef5 100644 --- a/src/spicelib/devices/vsrc/vsrcacld.c +++ b/src/spicelib/devices/vsrc/vsrcacld.c @@ -9,40 +9,150 @@ Author: 1985 Thomas L. Quarles #include "ngspice/sperror.h" #include "ngspice/suffix.h" +#ifdef RFSPICE + +int VSRCspupdate(GENmodel* inModel, CKTcircuit* ckt) +{ + if (!(ckt->CKTmode & MODESP)) + return (OK); + VSRCmodel* model = (VSRCmodel*)inModel; + VSRCinstance* here; + + for (; model != NULL; model = VSRCnextModel(model)) { + + /* loop through all the instances of the model */ + for (here = VSRCinstances(model); here != NULL; + here = VSRCnextInstance(here)) { + + if (here->VSRCisPort) + { + double acReal = here->VSRCportNum == ckt->CKTactivePort ? 1.0 : 0.0; + + *(ckt->CKTrhs + (here->VSRCbranch)) += acReal; + } + } + } + return (OK); +} + + +int VSRCgetActivePortNodes(GENmodel* inModel, CKTcircuit* ckt, int* posNodes, int* negNodes) +{ + if (!(ckt->CKTmode & MODESP)) + return (OK); + for (int n = 0; n < ckt->CKTportCount; n++) + posNodes[n] = negNodes[n] = 0; + VSRCmodel* model = (VSRCmodel*)inModel; + VSRCinstance* here; + + for (; model != NULL; model = VSRCnextModel(model)) { + + /* loop through all the instances of the model */ + for (here = VSRCinstances(model); here != NULL; + here = VSRCnextInstance(here)) { + + if (here->VSRCisPort) + { + int id = here->VSRCportNum - 1; + posNodes[id] = here->VSRCposNode; + negNodes[id] = here->VSRCnegNode; + + } + } + } + return (OK); +} +#endif int -VSRCacLoad(GENmodel *inModel, CKTcircuit *ckt) +VSRCacLoad(GENmodel* inModel, CKTcircuit* ckt) { - VSRCmodel *model = (VSRCmodel *) inModel; - VSRCinstance *here; + VSRCmodel* model = (VSRCmodel*)inModel; + VSRCinstance* here; - for( ; model != NULL; model = VSRCnextModel(model)) { + for (; model != NULL; model = VSRCnextModel(model)) { /* loop through all the instances of the model */ - for (here = VSRCinstances(model); here != NULL ; - here=VSRCnextInstance(here)) { + for (here = VSRCinstances(model); here != NULL; + here = VSRCnextInstance(here)) { double acReal, acImag; +#ifdef RFSPICE + double g0; + g0 = 0; + acReal = 0.0; + acImag = 0.0; + /* + * TBD: Verify that MODESPNOISE require also noise from source port + * In any case, activate only the required noise input to build + * noise matrix properly + */ + if ((ckt->CKTmode & MODEACNOISE) || (ckt->CKTmode & MODESPNOISE)) + { + if ((GENinstance*)here == ckt->noise_input) { + acReal = 1.0; + acImag = 0.0; + } + } + else + if (ckt->CKTmode & MODESP) // In SP Analysis, shut down all AC sources off except the current port + { + // During SP load, no port must excite the circuit before the SPAN procedure. + // They will be turned on & off in the inner cycle of SPAN. + // Also, AC Source must be switched off (<--- Check this against ADS). + { + acReal = 0.0; + acImag = 0.0; + } + } + else // AC Analysis + { + /* + * For AC analysis, AC mag is leading parameter for ports. + */ + 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)) += acReal; + *(ckt->CKTirhs + (here->VSRCbranch)) += acImag; + + if (here->VSRCisPort) + { + g0 = here->VSRCportY0; + *(here->VSRCposPosPtr) += g0; + *(here->VSRCnegNegPtr) += g0; + *(here->VSRCposNegPtr) -= g0; + *(here->VSRCnegPosPtr) -= g0; + } +#else if (ckt->CKTmode & MODEACNOISE) { - if ((GENinstance *) here == ckt->noise_input) { + if ((GENinstance*)here == ckt->noise_input) { acReal = 1.0; acImag = 0.0; - } else { + } + else { acReal = 0.0; acImag = 0.0; } - } else { + } + else { acReal = here->VSRCacReal; acImag = here->VSRCacImag; } - *(here->VSRCposIbrPtr) += 1.0 ; - *(here->VSRCnegIbrPtr) -= 1.0 ; - *(here->VSRCibrPosPtr) += 1.0 ; - *(here->VSRCibrNegPtr) -= 1.0 ; + *(here->VSRCposIbrPtr) += 1.0; + *(here->VSRCnegIbrPtr) -= 1.0; + *(here->VSRCibrPosPtr) += 1.0; + *(here->VSRCibrNegPtr) -= 1.0; *(ckt->CKTrhs + (here->VSRCbranch)) += acReal; *(ckt->CKTirhs + (here->VSRCbranch)) += acImag; +#endif } } diff --git a/src/spicelib/devices/vsrc/vsrcask.c b/src/spicelib/devices/vsrc/vsrcask.c index 5adee1dc9..54aa946cc 100644 --- a/src/spicelib/devices/vsrc/vsrcask.c +++ b/src/spicelib/devices/vsrc/vsrcask.c @@ -110,6 +110,23 @@ VSRCask(CKTcircuit *ckt, GENinstance *inst, int which, IFvalue *value, IFvalue * *(ckt->CKTrhsOld + here->VSRCbranch); } return(OK); +#ifdef RFSPICE + case VSRC_PORTNUM: + value->rValue = here->VSRCportNum; + return (OK); + case VSRC_PORTZ0: + value->rValue = here->VSRCportZ0; + return (OK); + case VSRC_PORTPWR: + value->rValue = here->VSRCportPower; + return (OK); + case VSRC_PORTFREQ: + value->rValue = here->VSRCportFreq; + return (OK); + case VSRC_PORTPHASE: + value->rValue = here->VSRCportPhase; + return (OK); +#endif #ifdef SHARED_MODULE case VSRC_EXTERNAL: /* Don't do anything */ diff --git a/src/spicelib/devices/vsrc/vsrcdefs.h b/src/spicelib/devices/vsrc/vsrcdefs.h index 784c7c05c..fa559be9d 100644 --- a/src/spicelib/devices/vsrc/vsrcdefs.h +++ b/src/spicelib/devices/vsrc/vsrcdefs.h @@ -32,6 +32,19 @@ typedef struct sVSRCinstance { const int VSRCposNode; /* number of positive node of source */ const int VSRCnegNode; /* number of negative node of source */ +#ifdef RFSPICE + int VSRCresNode; /* number of internal node of source (ZSeries) */ + + double* VSRCposPosPtr; /* pointer to sparse matrix diagonal at + * (positive,positive) */ + double* VSRCnegNegPtr; /* pointer to sparse matrix diagonal at + * (negative,negative) */ + double* VSRCposNegPtr; /* pointer to sparse matrix offdiagonal at + * (positive,negative) */ + double* VSRCnegPosPtr; /* pointer to sparse matrix offdiagonal at + * (negative,positive) */ +#endif + int VSRCbranch; /* equation number of branch equation added for source */ int VSRCfunctionType; /* code number of function type for source */ @@ -77,6 +90,24 @@ typedef struct sVSRCinstance { unsigned VSRCdF1given :1 ; /* flag to indicate source is an f1 distortion input */ unsigned VSRCdF2given :1 ; /* flag to indicate source is an f2 distortion input */ unsigned VSRCrGiven :1 ; /* flag to indicate repeating pwl */ +#ifdef RFSPICE + unsigned VSRCportNumGiven : 1; /* Flag to indicate Port Num is given */ + unsigned VSRCportZ0Given : 1; /* Flag to indicate Port Z0 is given */ + unsigned VSRCportPowerGiven : 1; /* Flag to indicate Port Power is given*/ + unsigned VSRCportFreqGiven : 1; /* Flag to indicate Port Frequency is given*/ + unsigned VSRCportPhaseGiven : 1; /* Flag to indicate Port Phase is given*/ + unsigned VSRCisPort : 1; /* Flag indicating if this is a port*/ + double VSRCVAmplitude; /* Support variable: Open Circuit Port Voltage */ + double VSRC2pifreq; /* Calculate 2*pi*freq once */ + unsigned int VSRCportNum; /* Port index*/ + double VSRCportZ0; /* Port internal impedance*/ + double VSRCportY0; /* Port internal admittance*/ + double VSRCportPower; /* Port power (W) for HB analysis */ + double VSRCportFreq; /* Port frequency */ + double VSRCportPhase; /* Port Initial Phase */ + double VSRCportPhaseRad; /* Port Initial Phase (rad) */ + double VSRCki; /* Normalization Factor for Kurosawa power wave*/ +#endif } VSRCinstance ; @@ -105,7 +136,11 @@ enum { AM, TRNOISE, TRRANDOM, - EXTERNAL, + EXTERNAL +#ifdef RFSPICE + , + PORT +#endif }; #endif @@ -136,6 +171,13 @@ enum { VSRC_AM, VSRC_R, VSRC_TD, +#ifdef RFSPICE + VSRC_PORTNUM, + VSRC_PORTZ0, + VSRC_PORTFREQ, + VSRC_PORTPWR, + VSRC_PORTPHASE, +#endif VSRC_TRNOISE, VSRC_TRRANDOM, VSRC_EXTERNAL, diff --git a/src/spicelib/devices/vsrc/vsrcext.h b/src/spicelib/devices/vsrc/vsrcext.h index 80c748a31..7761b867a 100644 --- a/src/spicelib/devices/vsrc/vsrcext.h +++ b/src/spicelib/devices/vsrc/vsrcext.h @@ -16,3 +16,7 @@ extern int VSRCsetup(SMPmatrix*,GENmodel*,CKTcircuit*,int*); extern int VSRCunsetup(GENmodel*,CKTcircuit*); extern int VSRCpzSetup(SMPmatrix*,GENmodel*,CKTcircuit*,int*); extern int VSRCtemp(GENmodel*,CKTcircuit*); +#ifdef RFSPICE +extern int VSRCspupdate(GENmodel*, CKTcircuit*); +extern int VSRCgetActivePortNodes(GENmodel* inModel, CKTcircuit* ckt, int* posNodes, int* negNodes); +#endif diff --git a/src/spicelib/devices/vsrc/vsrcload.c b/src/spicelib/devices/vsrc/vsrcload.c index 0987219c2..9c2bb52d3 100644 --- a/src/spicelib/devices/vsrc/vsrcload.c +++ b/src/spicelib/devices/vsrc/vsrcload.c @@ -40,10 +40,36 @@ VSRCload(GENmodel *inModel, CKTcircuit *ckt) for (here = VSRCinstances(model); here != NULL ; here=VSRCnextInstance(here)) { - *(here->VSRCposIbrPtr) += 1.0 ; - *(here->VSRCnegIbrPtr) -= 1.0 ; - *(here->VSRCibrPosPtr) += 1.0 ; - *(here->VSRCibrNegPtr) -= 1.0 ; +#ifndef RFSPICE + *(here->VSRCposIbrPtr) += 1.0; + *(here->VSRCnegIbrPtr) -= 1.0; + *(here->VSRCibrPosPtr) += 1.0; + *(here->VSRCibrNegPtr) -= 1.0; +#else + if (here->VSRCisPort) + { + // here->VSRCcurrent = (*(ckt->CKTrhs[Old] + (here->VSRCbranch)) + + *(here->VSRCposIbrPtr) += 1.0; + *(here->VSRCnegIbrPtr) -= 1.0; + *(here->VSRCibrPosPtr) += 1.0; + *(here->VSRCibrNegPtr) -= 1.0; + + double g0 = here->VSRCportY0; + *(here->VSRCposPosPtr) += g0; + *(here->VSRCnegNegPtr) += g0; + *(here->VSRCposNegPtr) -= g0; + *(here->VSRCnegPosPtr) -= g0; + } + else + { + *(here->VSRCposIbrPtr) += 1.0; + *(here->VSRCnegIbrPtr) -= 1.0; + *(here->VSRCibrPosPtr) += 1.0; + *(here->VSRCibrNegPtr) -= 1.0; + } +#endif + if( (ckt->CKTmode & (MODEDCOP | MODEDCTRANCURVE)) && here->VSRCdcGiven ) { /* load using DC value */ @@ -367,6 +393,13 @@ VNoi3 3 0 DC 0 TRNOISE(0 0 0 0 15m 22u 50u) : generate RTS noise } break; #endif +#ifdef RFSPICE + case PORT: + { + value += here->VSRCVAmplitude * cos(time * here->VSRC2pifreq); + + } +#endif } // switch } // else (line 48) diff --git a/src/spicelib/devices/vsrc/vsrcpar.c b/src/spicelib/devices/vsrc/vsrcpar.c index 66fa83036..b5957f943 100644 --- a/src/spicelib/devices/vsrc/vsrcpar.c +++ b/src/spicelib/devices/vsrc/vsrcpar.c @@ -288,7 +288,52 @@ VSRCparam(int param, IFvalue *value, GENinstance *inst, IFvalue *select) } break; #endif +#ifdef RFSPICE + /* + * NB If either Freq or Power are given, the Function type is overridden + * If not, we have a passive port: can be used for AC/SP/Noise but the time + * domain value is given by preceding Function definition (if present). + */ + case VSRC_PORTNUM: + { + here->VSRCportNum = value->iValue; + here->VSRCportNumGiven = TRUE; + here->VSRCisPort = ((here->VSRCportNumGiven) & (here->VSRCportNum > 0) & (here->VSRCportZ0 > 0.0)); + break; + } + case VSRC_PORTZ0: + { + here->VSRCportZ0 = value->rValue; + here->VSRCVAmplitude = sqrt(here->VSRCportPower * 4.0 * here->VSRCportZ0); + here->VSRCisPort = ((here->VSRCportNumGiven) & (here->VSRCportNum > 0) & (here->VSRCportZ0 > 0.0)); + here->VSRCportZ0Given = TRUE; + break; + } + case VSRC_PORTPWR: + { + here->VSRCportPower = value->rValue; + here->VSRCportPowerGiven = TRUE; + + here->VSRCfunctionType = PORT; + + break; + } + case VSRC_PORTFREQ: + { + here->VSRCportFreq = value->rValue; + here->VSRCportFreqGiven = TRUE; + + here->VSRCfunctionType = PORT; + break; + } + case VSRC_PORTPHASE: + { + here->VSRCportPhase = value->rValue; + here->VSRCportPhaseGiven = TRUE; + } + break; +#endif default: return(E_BADPARM); } diff --git a/src/spicelib/devices/vsrc/vsrcset.c b/src/spicelib/devices/vsrc/vsrcset.c index 7511acc3c..18d7764b7 100644 --- a/src/spicelib/devices/vsrc/vsrcset.c +++ b/src/spicelib/devices/vsrc/vsrcset.c @@ -49,10 +49,47 @@ do { if((here->ptr = SMPmakeElt(matrix, here->first, here->second)) == NULL){\ return(E_NOMEM);\ } } while(0) +#ifdef RFSPICE + if (here->VSRCisPort) + { + error = CKTmkVolt(ckt, &tmp, here->VSRCname, "res"); + if (error) return(error); + here->VSRCresNode = tmp->number; + if (ckt->CKTcopyNodesets) { + CKTnode* tmpNode; + IFuid tmpName; + if (CKTinst2Node(ckt, here, 1, &tmpNode, &tmpName) == OK) { + if (tmpNode->nsGiven) { + tmp->nodeset = tmpNode->nodeset; + tmp->nsGiven = tmpNode->nsGiven; + } + } + } + + TSTALLOC(VSRCposPosPtr, VSRCposNode, VSRCposNode); + TSTALLOC(VSRCnegNegPtr, VSRCresNode, VSRCresNode); + TSTALLOC(VSRCposNegPtr, VSRCposNode, VSRCresNode); + TSTALLOC(VSRCnegPosPtr, VSRCresNode, VSRCposNode); + + TSTALLOC(VSRCposIbrPtr, VSRCresNode, VSRCbranch); + TSTALLOC(VSRCnegIbrPtr, VSRCnegNode, VSRCbranch); + TSTALLOC(VSRCibrNegPtr, VSRCbranch, VSRCnegNode); + TSTALLOC(VSRCibrPosPtr, VSRCbranch, VSRCresNode); + } + else + { + TSTALLOC(VSRCposIbrPtr, VSRCposNode, VSRCbranch); + TSTALLOC(VSRCnegIbrPtr, VSRCnegNode, VSRCbranch); + TSTALLOC(VSRCibrNegPtr, VSRCbranch, VSRCnegNode); + TSTALLOC(VSRCibrPosPtr, VSRCbranch, VSRCposNode); + } +#else TSTALLOC(VSRCposIbrPtr, VSRCposNode, VSRCbranch); TSTALLOC(VSRCnegIbrPtr, VSRCnegNode, VSRCbranch); TSTALLOC(VSRCibrNegPtr, VSRCbranch, VSRCnegNode); TSTALLOC(VSRCibrPosPtr, VSRCbranch, VSRCposNode); +#endif + } } return(OK); @@ -73,6 +110,12 @@ VSRCunsetup(GENmodel *inModel, CKTcircuit *ckt) if (here->VSRCbranch > 0) CKTdltNNum(ckt, here->VSRCbranch); here->VSRCbranch = 0; +#ifdef RFSPICE + if ((here->VSRCresNode > 0) & (here->VSRCisPort)) + CKTdltNNum(ckt, here->VSRCresNode); + here->VSRCresNode = 0; + +#endif } } return OK; diff --git a/src/spicelib/devices/vsrc/vsrctemp.c b/src/spicelib/devices/vsrc/vsrctemp.c index 0a468e34f..2fb776bc4 100644 --- a/src/spicelib/devices/vsrc/vsrctemp.c +++ b/src/spicelib/devices/vsrc/vsrctemp.c @@ -22,6 +22,12 @@ VSRCtemp(GENmodel *inModel, CKTcircuit *ckt) NG_IGNORE(ckt); +#ifdef RFSPICE + ckt->CKTportCount = 0; + unsigned int* portIDs; + unsigned int prevPort; +#endif + /* loop through all the voltage source models */ for( ; model != NULL; model = VSRCnextModel(model)) { @@ -50,8 +56,92 @@ VSRCtemp(GENmodel *inModel, CKTcircuit *ckt) radians = here->VSRCacPhase * M_PI / 180.0; here->VSRCacReal = here->VSRCacMag * cos(radians); here->VSRCacImag = here->VSRCacMag * sin(radians); +#ifdef RFSPICE + // To have a power port, we need to define its index value + // AND a proper port impedance + if (here->VSRCportNumGiven) + { + if (!here->VSRCportZ0Given) + here->VSRCportZ0 = 50.0; + + here->VSRCisPort = here->VSRCportZ0 > 0.0; + } + else + here->VSRCisPort = FALSE; + + if (here->VSRCisPort) + { + if (!here->VSRCportFreqGiven) + here->VSRCportFreq = 1.0e9; + if (!here->VSRCportPowerGiven) + here->VSRCportPower = 0.001; // 1mW (0dBm) default RF power + if (!here->VSRCportPhaseGiven) + here->VSRCportPhase = 0.0; + + here->VSRC2pifreq = 2.0 * M_PI * here->VSRCportFreq; + here->VSRCVAmplitude = sqrt(here->VSRCportPower * 4.0 * here->VSRCportZ0); + here->VSRCportY0 = 1.0 / here->VSRCportZ0; + here->VSRCportPhaseRad = here->VSRCportPhase * M_PI / 180.0; + here->VSRCki = 0.5 / sqrt(here->VSRCportZ0); + + ckt->CKTportCount++; + ckt->CKTrfPorts = (GENinstance**)TREALLOC(GENinstance*, ckt->CKTrfPorts, ckt->CKTportCount); + ckt->CKTrfPorts[ckt->CKTportCount - 1] = (GENinstance*)here; + + + } +#endif + } + } + +#ifdef RFSPICE + portIDs = (unsigned int*)malloc(ckt->CKTportCount * sizeof(unsigned int)); + if (portIDs == NULL) + return (E_NOMEM); + + unsigned int curport = 0; + + // Sweep thru all ports to check for correct indexing + + /* loop through all the voltage source models */ + for (model = (VSRCmodel*)inModel; model != NULL; model = VSRCnextModel(model)) { + /* loop through all the instances of the model */ + for (here = VSRCinstances(model); here != NULL; + here = VSRCnextInstance(here)) { + + if (!here->VSRCisPort) continue; + + unsigned int curId = here->VSRCportNum; + // If port Index > port Count then we have either a duplicate number or a missing number + if (curId > ckt->CKTportCount) + { + SPfrontEnd->IFerrorf(ERR_FATAL, + "%s: incorrect port ordering", + here->VSRCname); + free(portIDs); + return (E_BADPARM); + } + + + // Check if we have already defined the "curId" + for (prevPort = 0; prevPort < curport; prevPort++) + { + if (portIDs[prevPort] == curId) + { + SPfrontEnd->IFerrorf(ERR_FATAL, + "%s: duplicate port Index", + here->VSRCname); + free(portIDs); + return (E_BADPARM); + } + } + + portIDs[curport++] = curId; } } + free(portIDs); + +#endif return(OK); } diff --git a/src/spicelib/parser/inp2dot.c b/src/spicelib/parser/inp2dot.c index 18be7ca2e..625372d11 100644 --- a/src/spicelib/parser/inp2dot.c +++ b/src/spicelib/parser/inp2dot.c @@ -614,6 +614,106 @@ dot_pss(char *line, void *ckt, INPtables *tab, struct card *current, /* SP */ #endif + +#ifdef RFSPICE +/* S Parameter Analyis */ +static int +dot_sp(char* line, void* ckt, INPtables* tab, struct card* current, + void* task, void* gnode, JOB* foo) +{ + int error; /* error code temporary */ + IFvalue ptemp; /* a value structure to package resistance into */ + IFvalue* parm; /* a pointer to a value struct for function returns */ + int which; /* which analysis we are performing */ + char* steptype; /* ac analysis, type of stepping function */ + + NG_IGNORE(gnode); + + /* .ac {DEC OCT LIN} NP FSTART FSTOP */ + which = ft_find_analysis("SP"); + if (which == -1) { + LITERR("S-Params analysis unsupported.\n"); + return (0); + } + IFC(newAnalysis, (ckt, which, "SP Analysis", &foo, task)); + INPgetTok(&line, &steptype, 1); /* get DEC, OCT, or LIN */ + ptemp.iValue = 1; + GCA(INPapName, (ckt, which, foo, steptype, &ptemp)); + tfree(steptype); + parm = INPgetValue(ckt, &line, IF_INTEGER, tab); /* number of points */ + GCA(INPapName, (ckt, which, foo, "numsteps", parm)); + parm = INPgetValue(ckt, &line, IF_REAL, tab); /* fstart */ + GCA(INPapName, (ckt, which, foo, "start", parm)); + parm = INPgetValue(ckt, &line, IF_REAL, tab); /* fstop */ + GCA(INPapName, (ckt, which, foo, "stop", parm)); + parm = INPgetValue(ckt, &line, IF_INTEGER, tab); /* fstop */ + GCA(INPapName, (ckt, which, foo, "donoise", parm)); + return (0); +} + +#ifdef WITH_HB +/* HB */ +static int +dot_hb(char* line, void* ckt, INPtables* tab, struct card* current, + void* task, void* gnode, JOB* foo) +{ + int error; /* error code temporary */ + IFvalue ptemp; /* a value structure to package resistance into */ + IFvalue* parm; /* a pointer to a value struct for function returns */ + char* nname; /* the oscNode name */ + CKTnode* nnode; /* the oscNode node */ + int which; /* which analysis we are performing */ + char* word; /* something to stick a word of input into */ + + NG_IGNORE(gnode); + + /* .pss Fguess StabTime OscNode */ + which = ft_find_analysis("PSS"); + if (which == -1) { + LITERR("Periodic steady state analysis unsupported.\n"); + return (0); + } + IFC(newAnalysis, (ckt, which, "Harmonic Balance State Analysis", &foo, task)); + + parm = INPgetValue(ckt, &line, IF_REALVEC, tab); /* Fguess */ + GCA(INPapName, (ckt, which, foo, "freq", parm)); + + parm = INPgetValue(ckt, &line, IF_INTVEC, tab); /* StabTime */ + GCA(INPapName, (ckt, which, foo, "harmonics", parm)); + + INPgetNetTok(&line, &nname, 0); + INPtermInsert(ckt, &nname, tab, &nnode); + ptemp.nValue = nnode; + GCA(INPapName, (ckt, which, foo, "oscnode", &ptemp)); /* OscNode given as string */ + + parm = INPgetValue(ckt, &line, IF_INTEGER, tab); /* PSS points */ + GCA(INPapName, (ckt, which, foo, "points", parm)); + + parm = INPgetValue(ckt, &line, IF_INTEGER, tab); /* PSS harmonics */ + GCA(INPapName, (ckt, which, foo, "harmonics", parm)); + + parm = INPgetValue(ckt, &line, IF_INTEGER, tab); /* SC iterations */ + GCA(INPapName, (ckt, which, foo, "sc_iter", parm)); + + parm = INPgetValue(ckt, &line, IF_REAL, tab); /* Steady coefficient */ + GCA(INPapName, (ckt, which, foo, "steady_coeff", parm)); + + if (*line) { + INPgetTok(&line, &word, 1); /* uic? */ + if (strcmp(word, "uic") == 0) { + ptemp.iValue = 1; + GCA(INPapName, (ckt, which, foo, "uic", &ptemp)); + } + else { + fprintf(stderr, "Error: unknown parameter %s on .pss - ignored\n", word); + } + } + return (0); +} +#endif + +#endif + static int dot_options(char *line, CKTcircuit *ckt, INPtables *tab, struct card *current, TSKtask *task, CKTnode *gnode, JOB *foo) @@ -699,6 +799,20 @@ INP2dot(CKTcircuit *ckt, INPtables *tab, struct card *current, TSKtask *task, CK rtn = dot_pss(line, ckt, tab, current, task, gnode, foo); goto quit; /* SP */ +#endif +#ifdef RFSPICE + } + else if ((strcmp(token, ".sp") == 0)) { + rtn = dot_sp(line, ckt, tab, current, task, gnode, foo); + goto quit; + /* SP */ +#ifdef WITH_HB + } + else if ((strcmp(token, ".hb") == 0)) { + rtn = dot_hb(line, ckt, tab, current, task, gnode, foo); + goto quit; + /* SP */ +#endif #endif } else if ((strcmp(token, ".subckt") == 0) || (strcmp(token, ".ends") == 0)) { diff --git a/visualc/vngspice.vcxproj b/visualc/vngspice.vcxproj index 155802e39..af6add978 100644 --- a/visualc/vngspice.vcxproj +++ b/visualc/vngspice.vcxproj @@ -311,7 +311,7 @@ Disabled ..\src\maths\poly;..\src\frontend;..\src\spicelib\devices;tmp-bison;src\include;..\src\spicelib\parser;..\src\include;..\src\include\cppduals;.;%(AdditionalIncludeDirectories) - _CRT_SECURE_NO_DEPRECATE;SIMULATOR;XSPICE;_MSC_PLATFORM_TOOLSET=$(PlatformToolsetVersion);NGDEBUG;CONFIG64;%(PreprocessorDefinitions) + RFSPICE;_CRT_SECURE_NO_DEPRECATE;SIMULATOR;XSPICE;_MSC_PLATFORM_TOOLSET=$(PlatformToolsetVersion);NGDEBUG;CONFIG64;%(PreprocessorDefinitions) false @@ -363,7 +363,7 @@ Speed true ..\src\maths\poly;..\src\frontend;..\src\spicelib\devices;tmp-bison;src\include;..\src\spicelib\parser;..\src\include;..\src\include\cppduals;.;%(AdditionalIncludeDirectories) - _CRT_SECURE_NO_DEPRECATE;SIMULATOR;XSPICE;_MSC_PLATFORM_TOOLSET=$(PlatformToolsetVersion);CONFIG64;%(PreprocessorDefinitions) + RFSPICE;_CRT_SECURE_NO_DEPRECATE;SIMULATOR;XSPICE;_MSC_PLATFORM_TOOLSET=$(PlatformToolsetVersion);CONFIG64;%(PreprocessorDefinitions) false @@ -511,7 +511,7 @@ Disabled ..\src\maths\poly;..\src\frontend;..\src\spicelib\devices;tmp-bison;src\include;..\src\spicelib\parser;..\src\include;..\src\include\cppduals;.;%(AdditionalIncludeDirectories) - _CRT_SECURE_NO_DEPRECATE;SIMULATOR;XSPICE;_MSC_PLATFORM_TOOLSET=$(PlatformToolsetVersion);NGDEBUG;CONSOLE;CONFIG64;%(PreprocessorDefinitions) + RFSPICE;_CRT_SECURE_NO_DEPRECATE;SIMULATOR;XSPICE;_MSC_PLATFORM_TOOLSET=$(PlatformToolsetVersion);NGDEBUG;CONSOLE;CONFIG64;%(PreprocessorDefinitions) false @@ -563,7 +563,7 @@ Speed true ..\src\maths\poly;..\src\frontend;..\src\spicelib\devices;tmp-bison;src\include;..\src\spicelib\parser;..\src\include;..\src\include\cppduals;.;%(AdditionalIncludeDirectories) - _CRT_SECURE_NO_DEPRECATE;SIMULATOR;XSPICE;_MSC_PLATFORM_TOOLSET=$(PlatformToolsetVersion);CONSOLE;CONFIG64;%(PreprocessorDefinitions) + RFSPICE;_CRT_SECURE_NO_DEPRECATE;SIMULATOR;XSPICE;_MSC_PLATFORM_TOOLSET=$(PlatformToolsetVersion);CONSOLE;CONFIG64;%(PreprocessorDefinitions) false @@ -669,7 +669,7 @@ Speed true ..\src\maths\poly;..\src\frontend;..\src\spicelib\devices;tmp-bison;src\include;..\src\spicelib\parser;..\src\include;..\src\include\cppduals;.;%(AdditionalIncludeDirectories) - _CRT_SECURE_NO_DEPRECATE;SIMULATOR;XSPICE;_MSC_PLATFORM_TOOLSET=$(PlatformToolsetVersion);USE_OMP;CONFIG64;%(PreprocessorDefinitions) + RFSPICE;_CRT_SECURE_NO_DEPRECATE;SIMULATOR;XSPICE;_MSC_PLATFORM_TOOLSET=$(PlatformToolsetVersion);USE_OMP;CONFIG64;%(PreprocessorDefinitions) false @@ -778,7 +778,7 @@ Speed true ..\src\maths\poly;..\src\frontend;..\src\spicelib\devices;tmp-bison;src\include;..\src\spicelib\parser;..\src\include;..\src\include\cppduals;.;%(AdditionalIncludeDirectories) - _CRT_SECURE_NO_DEPRECATE;SIMULATOR;XSPICE;_MSC_PLATFORM_TOOLSET=$(PlatformToolsetVersion);CONSOLE;CONFIG64;USE_OMP;%(PreprocessorDefinitions) + RFSPICE;_CRT_SECURE_NO_DEPRECATE;SIMULATOR;XSPICE;_MSC_PLATFORM_TOOLSET=$(PlatformToolsetVersion);CONSOLE;CONFIG64;USE_OMP;%(PreprocessorDefinitions) false @@ -952,6 +952,7 @@ + @@ -1065,6 +1066,7 @@ + @@ -1562,6 +1564,7 @@ + @@ -1682,6 +1685,7 @@ + @@ -1715,6 +1719,9 @@ + + +