28 #include "qucs_typedefs.h"
62 template <
class nr_type_t>
79 template <
class nr_type_t>
96 template <
class nr_type_t>
99 if (nlist)
delete nlist;
111 template <
class nr_type_t>
137 template <
class nr_type_t>
162 if (
d >= countNodes ())
165 e->
setText (
"voltage source `%s' conflicts with some other voltage "
166 "source", findVoltageSource(
d)->getName ());
170 e->
setText (
"circuit admittance matrix in %s solver is singular at "
171 "node `%s' connected to [%s]", desc, nlist->get (
d),
172 nlist->getNodeString (
d));
182 if (
d < countNodes ())
185 "node `%s' connected to [%s]\n", getName (), nlist->get (
d),
186 nlist->getNodeString (
d));
198 if (!error) saveSolution ();
204 template <
class nr_type_t>
212 template <
class nr_type_t>
221 nlist->assignNodes ();
222 assignVoltageSources ();
228 int M = countVoltageSources ();
229 int N = countNodes ();
230 if (
A != NULL)
delete A;
232 if (z != NULL)
delete z;
234 if (
x != NULL)
delete x;
246 template <
class nr_type_t>
249 if (
x == NULL || nlist == NULL)
return;
252 if (nokeep)
for (
int i = 0;
i <
x->getSize ();
i++)
x->set (
i, 0);
255 for (
nodeset *
n = subnet->getNodeset ();
n;
n =
n->getNext ())
257 struct nodelist_t * nl = nlist->getNode (
n->getName ());
260 x->set (nl->
n,
n->getValue ());
265 "initialize node\n", getName (),
n->getName ());
268 if (xprev != NULL) *xprev = *
x;
274 template <
class nr_type_t>
278 int convergence, run = 0, MaxIterations, error = 0;
279 nr_double_t gStep, gPrev;
282 MaxIterations = getPropertyInteger (
"MaxIter") / 4 + 1;
297 error = solve_once ();
301 convergence = (run > 0) ? checkConvergence () : 0;
302 savePreviousIteration ();
307 while (!convergence && run < MaxIterations);
311 if (run >= MaxIterations || error)
319 e->
setText (
"no convergence in %s analysis after %d gMinStepping "
320 "iterations", desc, iterations);
324 gMin =
MAX (gPrev - gStep, 0);
330 gMin =
MAX (gMin - gStep, 0);
342 template <
class nr_type_t>
346 int convergence, run = 0, MaxIterations, error = 0;
347 nr_double_t sStep, sPrev;
350 MaxIterations = getPropertyInteger (
"MaxIter") / 4 + 1;
355 sPrev = srcFactor = 0;
365 subnet->setSrcFactor (srcFactor);
366 error = solve_once ();
370 convergence = (run > 0) ? checkConvergence () : 0;
371 savePreviousIteration ();
376 while (!convergence && run < MaxIterations);
380 if (run >= MaxIterations || error)
386 restorePreviousIteration ();
393 e->
setText (
"no convergence in %s analysis after %d sourceStepping "
394 "iterations", desc, iterations);
398 srcFactor =
MIN (sPrev + sStep, 1);
401 else if (run < MaxIterations / 4)
404 srcFactor =
MIN (srcFactor + sStep, 1);
409 srcFactor =
MIN (srcFactor + sStep, 1);
415 subnet->setSrcFactor (1);
421 template <
class nr_type_t>
426 return "RHS attenuation";
430 return "line search";
434 return "steepest descent";
438 return "gMin stepping";
442 return "source stepping";
448 template <
class nr_type_t>
452 int convergence, run = 0, MaxIterations, error = 0;
455 MaxIterations = getPropertyInteger (
"MaxIter");
456 reltol = getPropertyDouble (
"reltol");
457 abstol = getPropertyDouble (
"abstol");
458 vntol = getPropertyDouble (
"vntol");
466 error = solve_nonlinear_continuation_gMin ();
474 error = solve_nonlinear_continuation_Source ();
481 error = solve_once ();
485 convergence = (run > 0) ? checkConvergence () : 0;
486 savePreviousIteration ();
491 if (convergence && !updateMatrix)
507 while (!convergence &&
508 run < MaxIterations * (1 + convHelper ? 1 : 0));
510 if (run >= MaxIterations || error)
513 e->
setText (
"no convergence in %s analysis after %d iterations",
524 template <
class nr_type_t>
528 return solve_once ();
535 template <
class nr_type_t>
556 int N = countNodes ();
557 int M = countVoltageSources ();
558 for (
int n = 0;
n < N +
M;
n++)
560 A->set (
n,
n,
A->get (
n,
n) + gMin);
577 #define MatVal(x) MatValX (x, (nr_type_t *) 0)
579 template <
class nr_type_t>
585 template <
class nr_type_t>
599 template <
class nr_type_t>
602 int N = countNodes ();
603 int M = countVoltageSources ();
609 for (
int c = 0;
c <
M;
c++)
611 vs = findVoltageSource (
c);
613 for (
int r = 0;
r <
N;
r++)
616 n = nlist->getNode (
r);
620 if (n->
nodes[
i]->getCircuit () == vs)
626 A->set (
r,
c + N, val);
639 template <
class nr_type_t>
642 int N = countNodes ();
643 int M = countVoltageSources ();
649 for (
int r = 0;
r <
M;
r++)
651 vs = findVoltageSource (
r);
653 for (
int c = 0;
c <
N;
c++)
656 n = nlist->getNode (
c);
660 if (n->
nodes[
i]->getCircuit () == vs)
666 A->set (
r + N,
c, val);
673 template <
class nr_type_t>
676 int M = countVoltageSources ();
677 int N = countNodes ();
680 for (
int r = 0;
r <
M;
r++)
682 vsr = findVoltageSource (
r);
683 for (
int c = 0;
c <
M;
c++)
685 vsc = findVoltageSource (
c);
691 A->set (
r + N,
c + N, val);
705 template <
class nr_type_t>
708 int pr, pc,
N = countNodes ();
714 for (
int c = 0;
c <
N;
c++)
716 nc = nlist->getNode (
c);
718 for (
int r = 0;
r <
N;
r++)
720 nr = nlist->getNode (
r);
723 for (
int a = 0; a < nc->
nNodes; a++)
724 for (
int b = 0; b < nr->
nNodes; b++)
725 if (nc->
nodes[a]->getCircuit () == nr->
nodes[b]->getCircuit ())
727 ct = nc->
nodes[a]->getCircuit ();
728 pc = nc->
nodes[a]->getPort ();
729 pr = nr->
nodes[b]->getPort ();
740 template <
class nr_type_t>
743 int pr, pc,
N = countNodes ();
744 int M = countVoltageSources ();
747 int r,
c, a, b, ri, ci,
i;
752 if (
C != NULL)
delete C;
756 for (c = 0; c <
N; c++)
758 nc = nlist->getNode (c);
760 for (r = 0; r <
N; r++)
762 nr = nlist->getNode (r);
765 for (a = 0; a < nc->
nNodes; a++)
766 for (b = 0; b < nr->
nNodes; b++)
767 if (nc->
nodes[a]->getCircuit () == nr->
nodes[b]->getCircuit ())
769 ct = nc->
nodes[a]->getCircuit ();
770 pc = nc->
nodes[a]->getPort ();
771 pr = nr->
nodes[b]->getPort ();
782 for (r = 0; r <
M; r++)
784 vsr = findVoltageSource (r);
785 for (c = 0; c <
M; c++)
787 vsc = findVoltageSource (c);
795 C->set (r + N, c + N, val);
800 for (r = 0; r <
M; r++)
802 vsr = findVoltageSource (r);
804 for (c = 0; c <
N; c++)
807 n = nlist->getNode (c);
808 for (i = 0; i < n->
nNodes; i++)
811 if (n->
nodes[i]->getCircuit () == vsr)
814 ci = n->
nodes[
i]->getPort ();
819 C->set (r + N, c, val);
824 for (c = 0; c <
M; c++)
826 vsc = findVoltageSource (c);
828 for (r = 0; r <
N; r++)
831 n = nlist->getNode (r);
832 for (i = 0; i < n->
nNodes; i++)
835 if (n->
nodes[i]->getCircuit () == vsc)
838 ri = n->
nodes[
i]->getPort ();
843 C->set (r, c + N, val);
854 template <
class nr_type_t>
857 int N = countNodes ();
863 for (
int r = 0;
r <
N;
r++)
866 n = nlist->getNode (
r);
870 is = n->
nodes[
i]->getCircuit ();
884 template <
class nr_type_t>
887 int N = countNodes ();
888 int M = countVoltageSources ();
893 for (
int r = 0;
r <
M;
r++)
895 vs = findVoltageSource (
r);
903 template <
class nr_type_t>
911 template <
class nr_type_t>
914 return nlist->length () - 1;
918 template <
class nr_type_t>
921 return nlist->getNodeNr (str);
926 template <
class nr_type_t>
929 int N = countNodes ();
931 for (
int r = 0;
r <
N;
r++)
933 n = nlist->getNode (
r);
935 if (c == n->
nodes[
i]->getCircuit ())
936 if (port == n->
nodes[
i]->getPort ())
943 template <
class nr_type_t>
946 return subnet->getVoltageSources ();
952 template <
class nr_type_t>
955 circuit * root = subnet->getRoot ();
958 if (n >=
c->getVoltageSource () &&
959 n <=
c->getVoltageSource () +
c->getVoltageSources () - 1)
968 template <
class nr_type_t>
971 circuit * root = subnet->getRoot ();
975 if (
c->getVoltageSources () > 0)
977 c->setVoltageSource (nSources);
978 nSources +=
c->getVoltageSources ();
981 subnet->setVoltageSources (nSources);
986 template <
class nr_type_t>
991 eqns->setAlgo (eqnAlgo);
992 eqns->passEquationSys (updateMatrix ?
A : NULL,
x, z);
1000 applyAttenuation ();
1016 template <
class nr_type_t>
1019 nr_double_t alpha = 1.0, nMax;
1028 nr_double_t g = 1.0;
1029 alpha =
MIN (0.9, g / nMax);
1030 if (alpha < 0.1) alpha = 0.1;
1034 *
x = *xprev + alpha * dx;
1043 template <
class nr_type_t>
1046 nr_double_t alpha = 0.5,
n, nMin, aprev = 1.0, astep = 0.5, adiff;
1056 *
x = *xprev + alpha * dx;
1068 adiff = fabs (alpha - aprev);
1075 if (alpha == 1) dir = -dir;
1076 alpha += astep * dir;
1081 alpha += 1.5 * astep * dir;
1085 while (adiff > 0.005);
1088 assert (alpha > 0 && alpha <= 1);
1089 *
x = *xprev + alpha * dx;
1096 template <
class nr_type_t>
1099 nr_double_t alpha = 1.0, sl,
n;
1109 *
x = *xprev + alpha * dx;
1119 if (
norm (*z) < n + alpha * sl)
break;
1122 while (alpha > 0.001);
1125 *
x = *xprev + alpha * dx;
1131 template <
class nr_type_t>
1135 int N = countNodes ();
1136 int M = countVoltageSources ();
1137 nr_double_t v_abs, v_rel, i_abs, i_rel;
1142 for (r = 0; r <
N; r++)
1144 v_abs =
abs (
x->get (r) - xprev->get (r));
1145 v_rel =
abs (
x->get (r));
1146 if (v_abs >= vntol + reltol * v_rel)
return 0;
1149 i_abs =
abs (z->get (r) - zprev->get (r));
1150 i_rel =
abs (z->get (r));
1151 if (i_abs >= abstol + reltol * i_rel)
return 0;
1155 for (r = 0; r <
M; r++)
1157 i_abs =
abs (
x->get (r + N) - xprev->get (r + N));
1158 i_rel =
abs (
x->get (r + N));
1159 if (i_abs >= abstol + reltol * i_rel)
return 0;
1162 v_abs =
abs (z->get (r + N) - zprev->get (r + N));
1163 v_rel =
abs (z->get (r + N));
1164 if (v_abs >= vntol + reltol * v_rel)
return 0;
1172 template <
class nr_type_t>
1187 template <
class nr_type_t>
1190 if (xprev != NULL) *
x = *xprev;
1191 if (zprev != NULL) *z = *zprev;
1196 template <
class nr_type_t>
1199 circuit * root = subnet->getRoot ();
1202 if (
c->isNonLinear ())
c->restartDC ();
1209 template <
class nr_type_t>
1212 int N = countNodes ();
1215 for (
int r = 0;
r <
N;
r++)
1217 n = nlist->getNode (
r);
1220 n->
nodes[
i]->getCircuit()->setV (n->
nodes[
i]->getPort (),
x->get (
r));
1224 n = nlist->getNode (-1);
1227 n->
nodes[
i]->getCircuit()->setV (n->
nodes[
i]->getPort (), 0.0);
1234 template <
class nr_type_t>
1237 int N = countNodes ();
1238 int M = countVoltageSources ();
1241 for (
int r = 0;
r <
M;
r++)
1243 vs = findVoltageSource (
r);
1249 template <
class nr_type_t>
1252 saveNodeVoltages ();
1253 saveBranchCurrents ();
1257 template <
class nr_type_t>
1263 int N = countNodes ();
1264 int M = countVoltageSources ();
1266 for (r = 0; r <
N; r++)
1269 solution.add (n->
name,
x->get (r), 0);
1272 for (r = 0; r <
M; r++)
1274 circuit * vs = findVoltageSource (r);
1276 solution.add (vs->
getName (),
x->get (r + N), vn);
1281 template <
class nr_type_t>
1285 int N = countNodes ();
1286 int M = countVoltageSources ();
1289 for (r = 0; r <
N; r++)
1292 if ((na = solution.find (n->
name, 0)) != NULL)
1296 for (r = 0; r <
M; r++)
1298 circuit * vs = findVoltageSource (r);
1300 if ((na = solution.find (vs->
getName (), vn)) != NULL)
1301 x->set (r + N, na->
value);
1307 template <
class nr_type_t>
1311 int N = countNodes ();
1312 int M = countVoltageSources ();
1318 for (
int r = 0;
r <
N;
r++)
1320 if ((n = createV (
r, volts, saveOPs)) != NULL)
1322 saveVariable (n,
x->get (
r), f);
1331 for (
int r = 0;
r <
M;
r++)
1333 if ((n = createI (
r, amps, saveOPs)) != NULL)
1335 saveVariable (n,
x->get (
r + N), f);
1344 circuit * root = subnet->getRoot ();
1347 if (!
c->isProbe ())
continue;
1348 if (
c->getSubcircuit () && !(saveOPs &
SAVE_ALL))
continue;
1349 if (strcmp (volts,
"vn"))
1350 c->saveOperatingPoints ();
1351 n = createOP (
c->getName (), volts);
1353 c->getOperatingPoint (
"Vi")), f);
1361 circuit * root = subnet->getRoot ();
1364 if (!
c->isNonLinear ())
continue;
1365 if (
c->getSubcircuit () && !(saveOPs &
SAVE_ALL))
continue;
1366 c->calcOperatingPoints ();
1371 n = createOP (
c->getName (), p->
getName ());
1372 saveVariable (n, p->
getValue (), f);
1381 template <
class nr_type_t>
1384 char * text = (
char *) malloc (strlen (c) + strlen (n) + 2);
1385 sprintf (text,
"%s.%s", c, n);
1391 template <
class nr_type_t>
1394 if (nlist->isInternal (n))
return NULL;
1395 char *
node = nlist->get (n);
1397 char * text = (
char *) malloc (strlen (node) + 2 + strlen (volts));
1398 sprintf (text,
"%s.%s", node, volts);
1404 template <
class nr_type_t>
1407 circuit * vs = findVoltageSource (n);
1424 char * text = (
char *) malloc (strlen (name) + 4 + strlen (amps));
1428 sprintf (text,
"%s.%s", name, amps);
1434 template <
class nr_type_t>
1437 return countNodes ();
1441 template <
class nr_type_t>
1444 return countVoltageSources ();
std::complex< nr_double_t > nr_complex_t
matrix real(matrix a)
Real part matrix.
matrix abs(matrix a)
Computes magnitude of each matrix element.
void recallSolution(void)
int getN()
Returns the number of node voltages in the circuit.
void applyNodeset(bool nokeep=true)
#define CONV_GMinStepping
int solve_nonlinear_continuation_gMin(void)
void restorePreviousIteration(void)
char * createV(int, const char *, int)
bool isInternalVoltageSource(void)
Global physical constants header file.
int getVoltageSource(void)
eqnsys< nr_type_t > * eqns
#define catch_exception()
nr_complex_t getN(int, int)
void setJ(int, nr_complex_t)
int getSize(void)
Get the number of ports the circuit element has.
#define throw_exception(e)
nr_double_t maxnorm(tvector< nr_type_t > a)
nr_type_t MatValX(nr_complex_t, nr_complex_t *)
int getVoltageSources(void)
nr_complex_t getC(int, int)
base class for qucs circuit elements.
char * getSubcircuit(void)
tvector< nr_type_t > * zprev
nasolution< nr_type_t > solution
void saveResults(const char *, const char *, int, qucs::vector *f=NULL)
The analysis class header file.
void applyAttenuation(void)
circuit * findVoltageSource(int)
void print(const char *prefix=NULL)
The circuit class header file.
int solve_nonlinear(void)
nr_complex_t getD(int, int)
#define CONV_SourceStepping
calculate_func_t calculate_func
tvector< nr_type_t > * xprev
int countVoltageSources(void)
#define MIN(x, y)
Minimum of x and y.
void saveNodeVoltages(void)
const char * getHelperDescription(void)
nr_complex_t getB(int, int)
nr_double_t norm(const nr_complex_t z)
Compute euclidian norm of complex number.
void saveBranchCurrents(void)
nr_double_t getValue(void)
void setText(const char *,...)
void createNoiseMatrix(void)
char * createI(int, const char *, int)
int checkConvergence(void)
void assignVoltageSources(void)
char * createOP(const char *, const char *)
int getM()
Returns the number of branch currents in the circuit.
nr_complex_t getY(int, int)
#define CONV_SteepestDescent
void savePreviousIteration(void)
void logprint(int level, const char *format,...)
int findAssignedNode(circuit *, int)
void steepestDescent(void)
int solve_nonlinear_continuation_Source(void)
#define MAX(x, y)
Maximum of x and y.