My Project
0.0.16
QUCS Mapping
Main Page
Related Pages
Namespaces
Classes
Files
File List
File Members
All
Classes
Namespaces
Files
Functions
Variables
Typedefs
Enumerations
Enumerator
Friends
Macros
Pages
DownLoad
QUCS-src
qucs-0.0.16
qucs-core
src
acsolver.cpp
Go to the documentation of this file.
1
/*
2
* acsolver.cpp - AC solver class implementation
3
*
4
* Copyright (C) 2004, 2005, 2007, 2008 Stefan Jahn <stefan@lkcc.org>
5
*
6
* This is free software; you can redistribute it and/or modify
7
* it under the terms of the GNU General Public License as published by
8
* the Free Software Foundation; either version 2, or (at your option)
9
* any later version.
10
*
11
* This software is distributed in the hope that it will be useful,
12
* but WITHOUT ANY WARRANTY; without even the implied warranty of
13
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
* GNU General Public License for more details.
15
*
16
* You should have received a copy of the GNU General Public License
17
* along with this package; see the file COPYING. If not, write to
18
* the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
19
* Boston, MA 02110-1301, USA.
20
*
21
* $Id: acsolver.cpp 1825 2011-03-11 20:42:14Z ela $
22
*
23
*/
24
25
#if HAVE_CONFIG_H
26
# include <config.h>
27
#endif
28
29
#include <stdio.h>
30
#include <math.h>
31
32
#include "
object.h
"
33
#include "
complex.h
"
34
#include "
circuit.h
"
35
#include "
sweep.h
"
36
#include "
net.h
"
37
#include "
netdefs.h
"
38
#include "
analysis.h
"
39
#include "
nasolver.h
"
40
#include "
acsolver.h
"
41
42
// Constructor creates an unnamed instance of the acsolver class.
43
acsolver::acsolver
() :
nasolver
<
nr_complex_t
> () {
44
swp = NULL;
45
type =
ANALYSIS_AC
;
46
setDescription (
"AC"
);
47
xn = NULL;
48
noise = 0;
49
}
50
51
// Constructor creates a named instance of the acsolver class.
52
acsolver::acsolver
(
char
*
n
) :
nasolver
<
nr_complex_t
> (n) {
53
swp = NULL;
54
type
=
ANALYSIS_AC
;
55
setDescription
(
"AC"
);
56
xn = NULL;
57
noise = 0;
58
}
59
60
// Destructor deletes the acsolver class object.
61
acsolver::~acsolver
() {
62
if
(swp)
delete
swp;
63
if
(xn)
delete
xn;
64
}
65
66
/* The copy constructor creates a new instance of the acsolver class
67
based on the given acsolver object. */
68
acsolver::acsolver
(
acsolver
& o) :
nasolver
<
nr_complex_t
> (o) {
69
swp = o.swp ?
new
sweep
(*(o.swp)) : NULL;
70
xn = o.xn ?
new
tvector<nr_double_t>
(*(o.xn)) : NULL;
71
noise = o.noise;
72
}
73
74
/* This is the AC netlist solver. It prepares the circuit list for
75
each requested frequency and solves it then. */
76
int
acsolver::solve
(
void
) {
77
runs
++;
78
79
// run additional noise analysis ?
80
noise = !strcmp (
getPropertyString
(
"Noise"
),
"yes"
) ? 1 : 0;
81
82
// create frequency sweep if necessary
83
if
(swp == NULL) {
84
swp =
createSweep
(
"acfrequency"
);
85
}
86
87
// initialize node voltages, first guess for non-linear circuits and
88
// generate extra circuits if necessary
89
init
();
90
setCalculation
((
calculate_func_t
) &
calc
);
91
solve_pre
();
92
93
swp->
reset
();
94
for
(
int
i
= 0;
i
< swp->
getSize
();
i
++) {
95
freq = swp->
next
();
96
if
(
progress
)
logprogressbar
(
i
, swp->
getSize
(), 40);
97
98
#if DEBUG && 0
99
logprint
(
LOG_STATUS
,
"NOTIFY: %s: solving netlist for f = %e\n"
,
100
getName
(), (
double
) freq);
101
#endif
102
103
// start the linear solver
104
eqnAlgo
=
ALGO_LU_DECOMPOSITION
;
105
solve_linear
();
106
107
// compute noise if requested
108
if
(noise)
solve_noise
();
109
110
// save results
111
saveAllResults
(freq);
112
}
113
solve_post
();
114
if
(
progress
)
logprogressclear
(40);
115
return
0;
116
}
117
118
/* Goes through the list of circuit objects and runs its calcAC()
119
function. */
120
void
acsolver::calc
(
acsolver
*
self
) {
121
circuit
* root =
self
->
getNet
()->
getRoot
();
122
for
(
circuit
*
c
= root;
c
!= NULL;
c
= (
circuit
*)
c
->getNext ()) {
123
c
->calcAC (self->freq);
124
if
(self->noise)
c
->calcNoiseAC (self->freq);
125
}
126
}
127
128
/* Goes through the list of circuit objects and runs its initAC()
129
function. */
130
void
acsolver::init
(
void
) {
131
circuit
* root =
subnet
->
getRoot
();
132
for
(
circuit
*
c
= root;
c
!= NULL;
c
= (
circuit
*)
c
->getNext ()) {
133
if
(
c
->isNonLinear ())
c
->calcOperatingPoints ();
134
c
->initAC ();
135
if
(noise)
c
->initNoiseAC ();
136
}
137
}
138
139
/* This function saves the results of a single solve() functionality
140
(for the given frequency) into the output dataset. */
141
void
acsolver::saveAllResults
(nr_double_t freq) {
142
vector
* f;
143
// add current frequency to the dependency of the output dataset
144
if
((f =
data
->
findDependency
(
"acfrequency"
)) == NULL) {
145
f =
new
vector
(
"acfrequency"
);
146
data
->
addDependency
(f);
147
}
148
if
(
runs
== 1) f->
add
(freq);
149
saveResults
(
"v"
,
"i"
, 0, f);
150
151
// additionally save noise results if requested
152
if
(noise) {
153
saveNoiseResults
(f);
154
}
155
}
156
157
/* The function computes the final noise results and puts them into
158
the output dataset. */
159
void
acsolver::saveNoiseResults
(
vector
* f) {
160
int
N
=
countNodes
();
161
int
M
=
countVoltageSources
();
162
for
(
int
r = 0; r < N +
M
; r++) {
163
// renormalise the results
164
x
->
set
(r, fabs (xn->
get
(r) *
sqrt
(
kB
*
T0
)));
165
}
166
167
// apply probe data
168
circuit
* root =
subnet
->
getRoot
();
169
for
(
circuit
*
c
= root;
c
!= NULL;
c
= (
circuit
*)
c
->getNext ()) {
170
if
(!
c
->isProbe ())
continue
;
171
int
np, nn;
172
nr_double_t vp, vn;
173
np =
getNodeNr
(
c
->getNode (
NODE_1
)->getName ());
174
vp = np > 0 ? xn->
get
(np - 1) : 0.0;
175
nn =
getNodeNr
(
c
->getNode (
NODE_2
)->getName ());
176
vn = nn > 0 ? xn->
get
(nn - 1) : 0.0;
177
c
->setOperatingPoint (
"Vr"
, fabs ((vp - vn) *
sqrt
(
kB
*
T0
)));
178
c
->setOperatingPoint (
"Vi"
, 0.0);
179
}
180
181
saveResults
(
"vn"
,
"in"
, 0, f);
182
}
183
184
/* This function runs the AC noise analysis. It saves its results in
185
the 'xn' vector. */
186
void
acsolver::solve_noise
(
void
) {
187
int
N
=
countNodes
();
188
int
M
=
countVoltageSources
();
189
190
// save usual AC results
191
tvector<nr_complex_t>
xsave = *
x
;
192
193
// create the Cy matrix
194
createNoiseMatrix
();
195
// create noise result vector if necessary
196
if
(xn == NULL) xn =
new
tvector<nr_double_t>
(N +
M
);
197
198
// temporary result vector for transimpedances
199
tvector<nr_complex_t>
zn =
tvector<nr_complex_t>
(N +
M
);
200
201
// create the MNA matrix once again and LU decompose the adjoint matrix
202
createMatrix
();
203
A
->
transpose
();
204
eqnAlgo
=
ALGO_LU_FACTORIZATION_CROUT
;
205
runMNA
();
206
207
// ensure skipping LU decomposition
208
updateMatrix
= 0;
209
convHelper
=
CONV_None
;
210
eqnAlgo
=
ALGO_LU_SUBSTITUTION_CROUT
;
211
212
// compute noise voltage for each node (and voltage source)
213
for
(
int
i
= 0;
i
< N +
M
;
i
++) {
214
z
->
set
(0);
z
->
set
(
i
, -1);
// modify right hand side appropriately
215
runMNA
();
// solve
216
zn = *
x
;
// save transimpedance vector
217
218
// compute actual noise voltage
219
xn->
set
(
i
,
sqrt
(
real
(
scalar
(zn * (*
C
),
conj
(zn)))));
220
}
221
222
// restore usual AC results
223
*
x
= xsave;
224
}
225
226
// properties
227
PROP_REQ
[] = {
228
{
"Type"
,
PROP_STR
, {
PROP_NO_VAL
,
"lin"
},
PROP_RNG_TYP
},
229
PROP_NO_PROP
};
230
PROP_OPT
[] = {
231
{
"Noise"
,
PROP_STR
, {
PROP_NO_VAL
,
"no"
},
PROP_RNG_YESNO
},
232
{
"Start"
,
PROP_REAL
, { 1e9,
PROP_NO_STR
},
PROP_POS_RANGE
},
233
{
"Stop"
,
PROP_REAL
, { 10e9,
PROP_NO_STR
},
PROP_POS_RANGE
},
234
{
"Points"
,
PROP_INT
, { 10,
PROP_NO_STR
},
PROP_MIN_VAL
(2) },
235
{
"Values"
,
PROP_LIST
, { 10,
PROP_NO_STR
},
PROP_POS_RANGE
},
236
PROP_NO_PROP
};
237
struct
define_t
acsolver
::anadef =
238
{
"AC"
, 0,
PROP_ACTION
,
PROP_NO_SUBSTRATE
,
PROP_LINEAR
,
PROP_DEF
};
Generated on Tue Dec 25 2012 14:28:05 for My Project by
1.8.2