Qucs-core
0.0.19
|
00001 /* 00002 * circuit.cpp - circuit class implementation 00003 * 00004 * Copyright (C) 2003, 2004, 2005, 2006, 2008 Stefan Jahn <stefan@lkcc.org> 00005 * 00006 * This is free software; you can redistribute it and/or modify 00007 * it under the terms of the GNU General Public License as published by 00008 * the Free Software Foundation; either version 2, or (at your option) 00009 * any later version. 00010 * 00011 * This software is distributed in the hope that it will be useful, 00012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00014 * GNU General Public License for more details. 00015 * 00016 * You should have received a copy of the GNU General Public License 00017 * along with this package; see the file COPYING. If not, write to 00018 * the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor, 00019 * Boston, MA 02110-1301, USA. 00020 * 00021 * $Id$ 00022 * 00023 */ 00024 00025 #if HAVE_CONFIG_H 00026 # include <config.h> 00027 #endif 00028 00029 #include <stdio.h> 00030 #include <stdlib.h> 00031 #include <string.h> 00032 #include <assert.h> 00033 00034 #include "logging.h" 00035 #include "complex.h" 00036 #include "object.h" 00037 #include "matrix.h" 00038 #include "node.h" 00039 #include "property.h" 00040 #include "valuelist.h" 00041 #include "tvector.h" 00042 #include "history.h" 00043 #include "circuit.h" 00044 #include "microstrip/substrate.h" 00045 #include "operatingpoint.h" 00046 #include "characteristic.h" 00047 #include "component_id.h" 00048 00049 namespace qucs { 00050 00051 // normalising impedance 00052 const nr_double_t circuit::z0 = 50.0; 00053 00054 // Constructor creates an unnamed instance of the circuit class. 00055 circuit::circuit () : object (), integrator () { 00056 next = prev = NULL; 00057 size = 0; 00058 MatrixN = MatrixS = MatrixY = NULL; 00059 MatrixB = MatrixC = MatrixD = NULL; 00060 VectorQ = VectorE = VectorI = VectorV = VectorJ = NULL; 00061 MatrixQV = NULL; 00062 VectorCV = VectorGV = NULL; 00063 nodes = NULL; 00064 pacport = 0; 00065 pol = 1; 00066 flag = CIRCUIT_ORIGINAL | CIRCUIT_LINEAR; 00067 subst = NULL; 00068 vsource = -1; 00069 vsources = 0; 00070 nsources = 0; 00071 inserted = -1; 00072 subcircuit = std::string(); 00073 subnet = NULL; 00074 deltas = NULL; 00075 histories = NULL; 00076 nHistories = 0; 00077 type = CIR_UNKNOWN; 00078 } 00079 00080 /* Constructor creates an unnamed instance of the circuit class with a 00081 certain number of ports. */ 00082 circuit::circuit (int s) : object (), integrator () { 00083 next = prev = NULL; 00084 assert (s >= 0); 00085 size = s; 00086 if (size > 0) nodes = new node[s]; 00087 MatrixN = MatrixS = MatrixY = NULL; 00088 MatrixB = MatrixC = MatrixD = NULL; 00089 VectorQ = VectorE = VectorI = VectorV = VectorJ = NULL; 00090 MatrixQV = NULL; 00091 VectorCV = VectorGV = NULL; 00092 pacport = 0; 00093 pol = 1; 00094 flag = CIRCUIT_ORIGINAL | CIRCUIT_LINEAR; 00095 subst = NULL; 00096 vsource = -1; 00097 vsources = 0; 00098 nsources = 0; 00099 inserted = -1; 00100 subcircuit = std::string(); 00101 subnet = NULL; 00102 deltas = NULL; 00103 histories = NULL; 00104 nHistories = 0; 00105 type = CIR_UNKNOWN; 00106 } 00107 00108 /* The copy constructor creates a new instance based on the given 00109 circuit object. */ 00110 circuit::circuit (const circuit & c) : object (c), integrator (c) { 00111 next = c.next; 00112 prev = c.prev; 00113 size = c.size; 00114 pol = c.pol; 00115 pacport = c.pacport; 00116 flag = c.flag; 00117 type = c.type; 00118 subst = c.subst; 00119 vsource = c.vsource; 00120 vsources = c.vsources; 00121 nsources = c.nsources; 00122 inserted = c.inserted; 00123 subnet = c.subnet; 00124 deltas = c.deltas; 00125 nHistories = c.nHistories; 00126 histories = NULL; 00127 subcircuit = c.subcircuit; 00128 00129 if (size > 0) { 00130 // copy each node and set its circuit to the current circuit object 00131 nodes = new node[size]; 00132 for (int i = 0; i < size; i++) { 00133 nodes[i] = node (c.nodes[i]);; 00134 nodes[i].setCircuit (this); 00135 } 00136 // copy each s-parameter 00137 if (c.MatrixS) { 00138 allocMatrixS (); 00139 memcpy (MatrixS, c.MatrixS, size * size * sizeof (nr_complex_t)); 00140 } 00141 // copy each noise-correlation parameter 00142 if (c.MatrixN) { 00143 allocMatrixN (nsources); 00144 int i = size + nsources; 00145 memcpy (MatrixN, c.MatrixN, i * i * sizeof (nr_complex_t)); 00146 } 00147 // copy each HB-matrix entry 00148 if (c.MatrixQV) { 00149 allocMatrixHB (); 00150 memcpy (MatrixQV, c.MatrixQV, size * size * sizeof (nr_complex_t)); 00151 memcpy (VectorGV, c.VectorGV, size * sizeof (nr_complex_t)); 00152 memcpy (VectorCV, c.VectorCV, size * sizeof (nr_complex_t)); 00153 memcpy (VectorQ, c.VectorQ, size * sizeof (nr_complex_t)); 00154 } 00155 // copy each G-MNA matrix entry 00156 if (c.MatrixY) { 00157 allocMatrixMNA (); 00158 memcpy (MatrixY, c.MatrixY, size * size * sizeof (nr_complex_t)); 00159 memcpy (VectorI, c.VectorI, size * sizeof (nr_complex_t)); 00160 memcpy (VectorV, c.VectorV, size * sizeof (nr_complex_t)); 00161 if (vsources > 0) { 00162 memcpy (MatrixB, c.MatrixB, vsources * size * sizeof (nr_complex_t)); 00163 memcpy (MatrixC, c.MatrixC, vsources * size * sizeof (nr_complex_t)); 00164 memcpy (MatrixD, c.MatrixD, vsources * vsources * sizeof (nr_complex_t)); 00165 memcpy (VectorE, c.VectorE, vsources * sizeof (nr_complex_t)); 00166 memcpy (VectorJ, c.VectorJ, vsources * sizeof (nr_complex_t)); 00167 } 00168 } 00169 } 00170 else { 00171 nodes = NULL; 00172 MatrixS = MatrixN = MatrixY = NULL; 00173 MatrixB = MatrixC = MatrixD = NULL; 00174 VectorQ = VectorE = VectorI = VectorV = VectorJ = NULL; 00175 MatrixQV = NULL; 00176 VectorCV = VectorGV = NULL; 00177 } 00178 00179 // copy operating points 00180 oper = valuelist<operatingpoint> (c.oper); 00181 } 00182 00183 // Destructor deletes a circuit object. 00184 circuit::~circuit () { 00185 if (size > 0) { 00186 delete[] MatrixS; 00187 delete[] MatrixN; 00188 freeMatrixMNA (); 00189 freeMatrixHB (); 00190 delete[] nodes; 00191 } 00192 deleteHistory (); 00193 } 00194 00195 /* With this function the number of ports of the circuit object can be 00196 changed. Previously stored node and matrix information gets 00197 completely lost except the current size equals the given size. */ 00198 void circuit::setSize (int s) { 00199 // nothing to do here 00200 if (size == s) return; 00201 assert (s >= 0); 00202 00203 if (size > 0) { 00204 // destroy any matrix and node information 00205 delete[] MatrixS; 00206 delete[] MatrixN; 00207 MatrixS = MatrixN = NULL; 00208 freeMatrixMNA (); 00209 delete[] nodes; nodes = NULL; 00210 } 00211 00212 if ((size = s) > 0) { 00213 // re-create matrix and node information space 00214 nodes = new node[size]; 00215 allocMatrixS (); 00216 allocMatrixN (nsources); 00217 allocMatrixMNA (); 00218 } 00219 } 00220 00221 /* Destroys the HB-matrix memory. */ 00222 void circuit::freeMatrixHB (void) { 00223 if (VectorQ) { delete[] VectorQ; VectorQ = NULL; } 00224 if (MatrixQV) { delete[] MatrixQV; MatrixQV = NULL; } 00225 if (VectorCV) { delete[] VectorCV; VectorCV = NULL; } 00226 if (VectorGV) { delete[] VectorGV; VectorGV = NULL; } 00227 } 00228 00229 /* Allocates the HB-matrix memory. */ 00230 void circuit::allocMatrixHB (void) { 00231 if (VectorQ) { 00232 memset (VectorQ, 0, size * sizeof (nr_complex_t)); 00233 } else { 00234 VectorQ = new nr_complex_t[size]; 00235 } 00236 if (MatrixQV) { 00237 memset (MatrixQV, 0, size * size * sizeof (nr_complex_t)); 00238 } else { 00239 MatrixQV = new nr_complex_t[size * size]; 00240 } 00241 if (VectorCV) { 00242 memset (VectorCV, 0, size * sizeof (nr_complex_t)); 00243 } else { 00244 VectorCV = new nr_complex_t[size]; 00245 } 00246 if (VectorGV) { 00247 memset (VectorGV, 0, size * sizeof (nr_complex_t)); 00248 } else { 00249 VectorGV = new nr_complex_t[size]; 00250 } 00251 } 00252 00253 /* Allocates the S-parameter matrix memory. */ 00254 void circuit::allocMatrixS (void) { 00255 if (MatrixS) { 00256 memset (MatrixS, 0, size * size * sizeof (nr_complex_t)); 00257 } else { 00258 MatrixS = new nr_complex_t[size * size]; 00259 } 00260 } 00261 00262 /* Allocates the noise correlation matrix memory. */ 00263 void circuit::allocMatrixN (int sources) { 00264 nsources = sources; 00265 delete[] MatrixN; 00266 MatrixN = new nr_complex_t[(size + sources) * (size + sources)]; 00267 } 00268 00269 /* Allocates the matrix memory for the MNA matrices. */ 00270 void circuit::allocMatrixMNA (void) { 00271 freeMatrixMNA (); 00272 if (size > 0) { 00273 MatrixY = new nr_complex_t[size * size]; 00274 VectorI = new nr_complex_t[size]; 00275 VectorV = new nr_complex_t[size]; 00276 if (vsources > 0) { 00277 MatrixB = new nr_complex_t[vsources * size]; 00278 MatrixC = new nr_complex_t[vsources * size]; 00279 MatrixD = new nr_complex_t[vsources * vsources]; 00280 VectorE = new nr_complex_t[vsources]; 00281 VectorJ = new nr_complex_t[vsources]; 00282 } 00283 } 00284 } 00285 00286 /* Free()'s all memory used by the MNA matrices. */ 00287 void circuit::freeMatrixMNA (void) { 00288 if (MatrixY) { delete[] MatrixY; MatrixY = NULL; } 00289 if (MatrixB) { delete[] MatrixB; MatrixB = NULL; } 00290 if (MatrixC) { delete[] MatrixC; MatrixC = NULL; } 00291 if (MatrixD) { delete[] MatrixD; MatrixD = NULL; } 00292 if (VectorE) { delete[] VectorE; VectorE = NULL; } 00293 if (VectorI) { delete[] VectorI; VectorI = NULL; } 00294 if (VectorV) { delete[] VectorV; VectorV = NULL; } 00295 if (VectorJ) { delete[] VectorJ; VectorJ = NULL; } 00296 } 00297 00298 /* This function sets the name and port number of one of the circuit's 00299 nodes. It also tells the appropriate node about the circuit it 00300 belongs to. The optional 'intern' argument is used to mark a node 00301 to be for internal use only. */ 00302 void circuit::setNode (int i, const std::string &n, int intern) { 00303 nodes[i].setName (n); 00304 nodes[i].setCircuit (this); 00305 nodes[i].setPort (i); 00306 nodes[i].setInternal (intern); 00307 } 00308 00309 // Returns one of the circuit's nodes. 00310 node * circuit::getNode (int i) { 00311 return &nodes[i]; 00312 } 00313 00314 // Sets the subcircuit reference for the circuit object. 00315 void circuit::setSubcircuit (const std::string &n) { 00316 subcircuit = n; 00317 } 00318 00319 #if DEBUG 00320 // DEBUG function: Prints the S parameters of this circuit object. 00321 void circuit::print (void) { 00322 for (int i = 0; i < getSize (); i++) { 00323 for (int j = 0; j < getSize (); j++) { 00324 logprint (LOG_STATUS, "%s S%d%d(%+.3e,%+.3e) ", getName (), i, j, 00325 (double) real (getS (i, j)), (double) imag (getS (i, j))); 00326 } 00327 logprint (LOG_STATUS, "\n"); 00328 } 00329 } 00330 #endif /* DEBUG */ 00331 00332 /* Returns the current substrate of the circuit object. Used for 00333 microstrip components only. */ 00334 substrate * circuit::getSubstrate (void) { 00335 return subst; 00336 } 00337 00338 // Sets the substrate of the circuit object. 00339 void circuit::setSubstrate (substrate * s) { 00340 subst = s; 00341 } 00342 00343 /* Returns the circuits B-MNA matrix value of the given voltage source 00344 built in the circuit depending on the port number. */ 00345 nr_complex_t circuit::getB (int port, int nr) { 00346 return MatrixB[(nr - vsource) * size + port]; 00347 } 00348 00349 /* Sets the circuits B-MNA matrix value of the given voltage source 00350 built in the circuit depending on the port number. */ 00351 void circuit::setB (int port, int nr, nr_complex_t z) { 00352 MatrixB[nr * size + port] = z; 00353 } 00354 00355 /* Returns the circuits C-MNA matrix value of the given voltage source 00356 built in the circuit depending on the port number. */ 00357 nr_complex_t circuit::getC (int nr, int port) { 00358 return MatrixC[(nr - vsource) * size + port]; 00359 } 00360 00361 /* Sets the circuits C-MNA matrix value of the given voltage source 00362 built in the circuit depending on the port number. */ 00363 void circuit::setC (int nr, int port, nr_complex_t z) { 00364 MatrixC[nr * size + port] = z; 00365 } 00366 00367 /* Returns the circuits D-MNA matrix value of the given voltage source 00368 built in the circuit. */ 00369 nr_complex_t circuit::getD (int r, int c) { 00370 return MatrixD[(r - vsource) * vsources + c - vsource]; 00371 } 00372 00373 /* Sets the circuits D-MNA matrix value of the given voltage source 00374 built in the circuit. */ 00375 void circuit::setD (int r, int c, nr_complex_t z) { 00376 MatrixD[r * vsources + c] = z; 00377 } 00378 00379 /* Returns the circuits E-MNA matrix value of the given voltage source 00380 built in the circuit. */ 00381 nr_complex_t circuit::getE (int nr) { 00382 return VectorE[nr - vsource]; 00383 } 00384 00385 /* Sets the circuits E-MNA matrix value of the given voltage source 00386 built in the circuit. */ 00387 void circuit::setE (int nr, nr_complex_t z) { 00388 VectorE[nr] = z; 00389 } 00390 00391 /* Returns the circuits I-MNA matrix value of the current source built 00392 in the circuit. */ 00393 nr_complex_t circuit::getI (int port) { 00394 return VectorI[port]; 00395 } 00396 00397 /* Sets the circuits I-MNA matrix value of the current source built in 00398 the circuit depending on the port number. */ 00399 void circuit::setI (int port, nr_complex_t z) { 00400 VectorI[port] = z; 00401 } 00402 00403 /* Modifies the circuits I-MNA matrix value of the current source 00404 built in the circuit depending on the port number. */ 00405 void circuit::addI (int port, nr_complex_t i) { 00406 VectorI[port] += i; 00407 } 00408 00409 /* Same as above with different argument type. */ 00410 void circuit::addI (int port, nr_double_t i) { 00411 VectorI[port] += i; 00412 } 00413 00414 /* Returns the circuits Q-HB vector value. */ 00415 nr_complex_t circuit::getQ (int port) { 00416 return VectorQ[port]; 00417 } 00418 00419 /* Sets the circuits Q-HB vector value. */ 00420 void circuit::setQ (int port, nr_complex_t q) { 00421 VectorQ[port] = q; 00422 } 00423 00424 /* Returns the circuits J-MNA matrix value of the given voltage source 00425 built in the circuit. */ 00426 nr_complex_t circuit::getJ (int nr) { 00427 return VectorJ[nr]; 00428 } 00429 00430 /* Sets the circuits J-MNA matrix value of the given voltage source 00431 built in the circuit. */ 00432 void circuit::setJ (int nr, nr_complex_t z) { 00433 VectorJ[nr - vsource] = z; 00434 } 00435 00436 // Returns the circuits voltage value at the given port. 00437 nr_complex_t circuit::getV (int port) { 00438 return VectorV[port]; 00439 } 00440 00441 // Sets the circuits voltage value at the given port. 00442 void circuit::setV (int port, nr_complex_t z) { 00443 VectorV[port] = z; 00444 } 00445 00446 /* Returns the circuits G-MNA matrix value depending on the port 00447 numbers. */ 00448 nr_complex_t circuit::getY (int r, int c) { 00449 return MatrixY[r * size + c]; 00450 } 00451 00452 /* Sets the circuits G-MNA matrix value depending on the port 00453 numbers. */ 00454 void circuit::setY (int r, int c, nr_complex_t y) { 00455 MatrixY[r * size + c] = y; 00456 } 00457 00458 /* Modifies the circuits G-MNA matrix value depending on the port 00459 numbers. */ 00460 void circuit::addY (int r, int c, nr_complex_t y) { 00461 MatrixY[r * size + c] += y; 00462 } 00463 00464 /* Same as above with different argument type. */ 00465 void circuit::addY (int r, int c, nr_double_t y) { 00466 MatrixY[r * size + c] += y; 00467 } 00468 00469 /* Returns the circuits G-MNA matrix value depending on the port 00470 numbers. */ 00471 nr_double_t circuit::getG (int r, int c) { 00472 return real (MatrixY[r * size + c]); 00473 } 00474 00475 /* Sets the circuits G-MNA matrix value depending on the port 00476 numbers. */ 00477 void circuit::setG (int r, int c, nr_double_t y) { 00478 MatrixY[r * size + c] = y; 00479 } 00480 00481 /* Returns the circuits C-HB matrix value depending on the port 00482 numbers. */ 00483 nr_complex_t circuit::getQV (int r, int c) { 00484 return MatrixQV[r * size + c]; 00485 } 00486 00487 /* Sets the circuits C-HB matrix value depending on the port 00488 numbers. */ 00489 void circuit::setQV (int r, int c, nr_complex_t qv) { 00490 MatrixQV[r * size + c] = qv; 00491 } 00492 00493 /* Returns the circuits GV-HB vector value depending on the port 00494 number. */ 00495 nr_complex_t circuit::getGV (int port) { 00496 return VectorGV[port]; 00497 } 00498 00499 /* Sets the circuits GV-HB matrix value depending on the port 00500 number. */ 00501 void circuit::setGV (int port, nr_complex_t gv) { 00502 VectorGV[port] = gv; 00503 } 00504 00505 /* Returns the circuits CV-HB vector value depending on the port 00506 number. */ 00507 nr_complex_t circuit::getCV (int port) { 00508 return VectorCV[port]; 00509 } 00510 00511 /* Sets the circuits CV-HB matrix value depending on the port 00512 number. */ 00513 void circuit::setCV (int port, nr_complex_t cv) { 00514 VectorCV[port] = cv; 00515 } 00516 00517 /* This function adds a operating point consisting of a key and a 00518 value to the circuit. */ 00519 void circuit::addOperatingPoint (const std::string &n, nr_double_t val) { 00520 operatingpoint p(n, val); 00521 oper.insert ({{n,p}}); 00522 } 00523 00524 /* Returns the requested operating point value which has been 00525 previously added as its double representation. If there is no such 00526 operating point the function returns zero. */ 00527 nr_double_t circuit::getOperatingPoint (const std::string &n) { 00528 const auto it = oper.find(n); 00529 if (it != oper.end()) 00530 return (*it).second.getValue(); 00531 return 0.0; 00532 } 00533 00534 /* This function sets the operating point specified by the given name 00535 to the value passed to the function. */ 00536 void circuit::setOperatingPoint (const std::string& n, nr_double_t val) { 00537 auto it = oper.find(n); 00538 if (it != oper.end()) 00539 (*it).second.setValue (val); 00540 else 00541 addOperatingPoint (n, val); 00542 } 00543 00544 /* The function checks whether the circuit has got a certain operating 00545 point value. If so it returns non-zero, otherwise it returns 00546 zero. */ 00547 int circuit::hasOperatingPoint (const std::string& n) { 00548 return oper.find(n) != oper.end(); 00549 } 00550 00551 /* This function adds a characteristic point consisting of a key and a 00552 value to the circuit. */ 00553 void circuit::addCharacteristic (const std::string &n, nr_double_t val) { 00554 characteristic p(n, val); 00555 charac.insert({{n, p}}); 00556 } 00557 00558 /* Returns the requested characteristic value which has been 00559 previously added as its double representation. If there is no such 00560 characteristic value the function returns zero. */ 00561 nr_double_t circuit::getCharacteristic (const std::string &n) { 00562 const auto it = charac.find(n); 00563 if (it != charac.end()) 00564 return (*it).second.getValue (); 00565 return 0.0; 00566 } 00567 00568 /* This function sets the characteristic value specified by the given 00569 name to the value passed to the function. */ 00570 void circuit::setCharacteristic (const std::string &n, nr_double_t val) { 00571 auto it = charac.find(n); 00572 if (it != charac.end()) 00573 (*it).second.setValue (val); 00574 else 00575 addCharacteristic (n, val); 00576 } 00577 00578 /* The function checks whether the circuit has got a certain 00579 characteristic value. If so it returns non-zero, otherwise it 00580 returns zero. */ 00581 int circuit::hasCharacteristic (const std::string & n) { 00582 return charac.find (n) != charac.end(); 00583 } 00584 00585 // Returns the S-parameter at the given matrix position. 00586 nr_complex_t circuit::getS (int x, int y) { 00587 return MatrixS[y + x * size]; 00588 } 00589 00590 // Sets the S-parameter at the given matrix position. 00591 void circuit::setS (int x, int y, nr_complex_t z) { 00592 MatrixS[y + x * size] = z; 00593 } 00594 00595 // Returns the noise-correlation-parameter at the given matrix position. 00596 nr_complex_t circuit::getN (int r, int c) { 00597 return MatrixN[c + r * (size + nsources)]; 00598 } 00599 00600 // Sets the noise-correlation-parameter at the given matrix position. 00601 void circuit::setN (int r, int c, nr_complex_t z) { 00602 MatrixN[c + r * (size + nsources)] = z; 00603 } 00604 00605 // Returns the number of internal voltage sources for DC analysis. 00606 int circuit::getVoltageSources (void) { 00607 return vsources; 00608 } 00609 00610 // Sets the number of internal voltage sources for DC analysis. 00611 void circuit::setVoltageSources (int s) { 00612 assert (s >= 0); 00613 vsources = s; 00614 } 00615 00616 // Returns the number of internal noise sources for AC analysis. 00617 int circuit::getNoiseSources (void) { 00618 return nsources; 00619 } 00620 00621 // Sets the number of internal noise voltage sources for AC analysis. 00622 void circuit::setNoiseSources (int s) { 00623 assert (s >= 0); 00624 nsources = s; 00625 } 00626 00627 /* The function returns an internal node or circuit name with the 00628 given prefix and based on the given circuits name. The caller is 00629 responsible to free() the returned string. */ 00630 std::string circuit::createInternal (const std::string &prefix, const std::string &obj) { 00631 return "_"+prefix+"#"+obj; 00632 } 00633 00634 /* Creates an internal node given the node number as well as the name 00635 suffix. An appropriate node name is constructed from the circuits 00636 name and the suffix. */ 00637 void circuit::setInternalNode (int node, const std::string &suffix) { 00638 const std::string &n = createInternal (getName (), suffix); 00639 setNode (node, n, 1); 00640 } 00641 00642 /* This function copies the matrix elements inside the given matrix to 00643 the internal S-parameter matrix of the circuit. */ 00644 void circuit::setMatrixS (matrix s) { 00645 int r = s.getRows (); 00646 int c = s.getCols (); 00647 // copy matrix elements 00648 if (r > 0 && c > 0 && r * c == size * size) { 00649 memcpy (MatrixS, s.getData (), sizeof (nr_complex_t) * r * c); 00650 } 00651 } 00652 00653 /* The function return a matrix containing the S-parameters of the 00654 circuit. */ 00655 matrix circuit::getMatrixS (void) { 00656 matrix res (size); 00657 for(unsigned int i=0; i < size; ++i) 00658 for(unsigned int j=0; j < size; ++j) 00659 res(i,j) = MatrixS[i*size + j]; 00660 return res; 00661 } 00662 00663 /* This function copies the matrix elements inside the given matrix to 00664 the internal noise correlation matrix of the circuit. */ 00665 void circuit::setMatrixN (matrix n) { 00666 int r = n.getRows (); 00667 int c = n.getCols (); 00668 // copy matrix elements 00669 if (r > 0 && c > 0 && r * c == size * size) { 00670 memcpy (MatrixN, n.getData (), sizeof (nr_complex_t) * r * c); 00671 } 00672 } 00673 00674 /* The function return a matrix containing the noise correlation 00675 matrix of the circuit. */ 00676 matrix circuit::getMatrixN (void) { 00677 matrix res (size); 00678 for(unsigned int i=0; i < size; ++i) 00679 for(unsigned int j=0; j < size; ++j) 00680 res(i,j) = MatrixN[i*size + j]; 00681 return res; 00682 } 00683 00684 /* This function copies the matrix elements inside the given matrix to 00685 the internal G-MNA matrix of the circuit. */ 00686 void circuit::setMatrixY (matrix y) { 00687 int r = y.getRows (); 00688 int c = y.getCols (); 00689 // copy matrix elements 00690 if (r > 0 && c > 0 && r * c == size * size) { 00691 memcpy (MatrixY, y.getData (), sizeof (nr_complex_t) * r * c); 00692 } 00693 } 00694 00695 /* The function return a matrix containing the G-MNA matrix of the 00696 circuit. */ 00697 matrix circuit::getMatrixY (void) { 00698 matrix res (size); 00699 for(unsigned int i=0; i < size; ++i) 00700 for(unsigned int j=0; j < size; ++j) 00701 res(i,j) = MatrixY[i*size + j]; 00702 return res; 00703 } 00704 00705 // The function cleans up the B-MNA matrix entries. 00706 void circuit::clearB (void) { 00707 memset (MatrixB, 0, sizeof (nr_complex_t) * size * vsources); 00708 } 00709 00710 // The function cleans up the C-MNA matrix entries. 00711 void circuit::clearC (void) { 00712 memset (MatrixC, 0, sizeof (nr_complex_t) * size * vsources); 00713 } 00714 00715 // The function cleans up the D-MNA matrix entries. 00716 void circuit::clearD (void) { 00717 memset (MatrixD, 0, sizeof (nr_complex_t) * vsources * vsources); 00718 } 00719 00720 // The function cleans up the E-MNA matrix entries. 00721 void circuit::clearE (void) { 00722 memset (VectorE, 0, sizeof (nr_complex_t) * vsources); 00723 } 00724 00725 // The function cleans up the J-MNA matrix entries. 00726 void circuit::clearJ (void) { 00727 memset (VectorJ, 0, sizeof (nr_complex_t) * vsources); 00728 } 00729 00730 // The function cleans up the I-MNA matrix entries. 00731 void circuit::clearI (void) { 00732 memset (VectorI, 0, sizeof (nr_complex_t) * size); 00733 } 00734 00735 // The function cleans up the V-MNA matrix entries. 00736 void circuit::clearV (void) { 00737 memset (VectorV, 0, sizeof (nr_complex_t) * size); 00738 } 00739 00740 // The function cleans up the G-MNA matrix entries. 00741 void circuit::clearY (void) { 00742 memset (MatrixY, 0, sizeof (nr_complex_t) * size * size); 00743 } 00744 00745 /* This function can be used by several components in order to place 00746 the n-th voltage source between node 'pos' and node 'neg' with the 00747 given value. Remember to indicate this voltage source using the 00748 function setVoltageSources(). */ 00749 void circuit::voltageSource (int n, int pos, int neg, nr_double_t value) { 00750 setC (n, pos, +1.0); setC (n, neg, -1.0); 00751 setB (pos, n, +1.0); setB (neg, n, -1.0); 00752 setD (n, n, 0.0); 00753 setE (n, value); 00754 } 00755 00756 /* The function runs the necessary calculation in order to perform a 00757 single integration step of a voltage controlled capacitance placed 00758 in between the given nodes. It is assumed that the appropiate 00759 charge only depends on the voltage between these nodes. */ 00760 void circuit::transientCapacitance (int qstate, int pos, int neg, 00761 nr_double_t cap, nr_double_t voltage, 00762 nr_double_t charge) { 00763 nr_double_t g, i; 00764 int cstate = qstate + 1; 00765 setState (qstate, charge); 00766 integrate (qstate, cap, g, i); 00767 addY (pos, pos, +g); addY (neg, neg, +g); 00768 addY (pos, neg, -g); addY (neg, pos, -g); 00769 i = pol * (getState (cstate) - g * voltage); 00770 addI (pos , -i); 00771 addI (neg , +i); 00772 } 00773 00774 /* This is the one-node variant of the above function. It performs 00775 the same steps for a single node related to ground. */ 00776 void circuit::transientCapacitance (int qstate, int node, nr_double_t cap, 00777 nr_double_t voltage, nr_double_t charge) { 00778 nr_double_t g, i; 00779 int cstate = qstate + 1; 00780 setState (qstate, charge); 00781 integrate (qstate, cap, g, i); 00782 addY (node, node, +g); 00783 i = pol * (getState (cstate) - g * voltage); 00784 addI (node , -i); 00785 } 00786 00787 /* The function performs a single integration step of the given charge 00788 located between the given nodes. It saves the current 00789 contributions of the charge itself and considers the polarity of 00790 the circuit. */ 00791 void circuit::transientCapacitanceQ (int qstate, int qpos, int qneg, 00792 nr_double_t charge) { 00793 nr_double_t unused, i; 00794 int cstate = qstate + 1; 00795 setState (qstate, charge); 00796 integrate (qstate, 0, unused, unused); 00797 i = pol * getState (cstate); 00798 addI (qpos , -i); 00799 addI (qneg , +i); 00800 } 00801 00802 /* This is the one-node variant of the above function. It performs 00803 the same steps for a single node related to ground. */ 00804 void circuit::transientCapacitanceQ (int qstate, int qpos, 00805 nr_double_t charge) { 00806 nr_double_t unused, i; 00807 int cstate = qstate + 1; 00808 setState (qstate, charge); 00809 integrate (qstate, 0, unused, unused); 00810 i = pol * getState (cstate); 00811 addI (qpos , -i); 00812 } 00813 00814 /* This function stores the Jacobian entries due to the C = dQ/dV 00815 value. The nodes where the charge is located as well as those of 00816 the voltage dependency, the appropiate capacitance value and the 00817 voltage across the the controlling branch must be given. It also 00818 saves the current contributions which are necessary for the NR 00819 iteration and considers the polarity of the circuit. */ 00820 void circuit::transientCapacitanceC (int qpos, int qneg, int vpos, int vneg, 00821 nr_double_t cap, nr_double_t voltage) { 00822 nr_double_t g, i; 00823 conductor (cap, g); 00824 addY (qpos, vpos, +g); addY (qneg, vneg, +g); 00825 addY (qpos, vneg, -g); addY (qneg, vpos, -g); 00826 i = pol * (g * voltage); 00827 addI (qpos , +i); 00828 addI (qneg , -i); 00829 } 00830 00831 /* This is the one-node variant of the transientCapacitanceC() 00832 function. It performs the same steps for a single charge node 00833 related to ground. */ 00834 void circuit::transientCapacitanceC2V (int qpos, int vpos, int vneg, 00835 nr_double_t cap, nr_double_t voltage) { 00836 nr_double_t g, i; 00837 conductor (cap, g); 00838 addY (qpos, vpos, +g); 00839 addY (qpos, vneg, -g); 00840 i = pol * (g * voltage); 00841 addI (qpos , +i); 00842 } 00843 00844 /* This is the one-node variant of the transientCapacitanceC() 00845 function. It performs the same steps for a single voltage node 00846 related to ground. */ 00847 void circuit::transientCapacitanceC2Q (int qpos, int qneg, int vpos, 00848 nr_double_t cap, nr_double_t voltage) { 00849 nr_double_t g, i; 00850 conductor (cap, g); 00851 addY (qpos, vpos, +g); addY (qneg, vpos, -g); 00852 i = pol * (g * voltage); 00853 addI (qpos , +i); 00854 addI (qneg , -i); 00855 } 00856 00857 /* This is the one-node variant of the transientCapacitanceC() 00858 function. It performs the same steps for a single voltage node and 00859 charge node related to ground. */ 00860 void circuit::transientCapacitanceC (int qpos, int vpos, 00861 nr_double_t cap, nr_double_t voltage) { 00862 nr_double_t g, i; 00863 conductor (cap, g); 00864 addY (qpos, vpos, +g); 00865 i = pol * (g * voltage); 00866 addI (qpos , +i); 00867 } 00868 00869 // The function initializes the histories of a circuit having the given age. 00870 void circuit::initHistory (nr_double_t age) { 00871 nHistories = getSize () + getVoltageSources (); 00872 histories = new history[nHistories]; 00873 setHistoryAge (age); 00874 } 00875 00876 // Sets the age of all circuit histories 00877 void circuit::setHistoryAge (nr_double_t age) { 00878 for (int i = 0; i < nHistories; i++) 00879 { 00880 histories[i].setAge (age); 00881 } 00882 } 00883 00884 00885 00886 // The function deletes the histories for the transient analysis. 00887 void circuit::deleteHistory (void) { 00888 if (histories != NULL) { 00889 delete[] histories; 00890 histories = NULL; 00891 } 00892 setHistory (false); 00893 } 00894 00895 // Truncates the transient analysis history (i.e. removes values newer 00896 // newer than time tcut). 00897 void circuit::truncateHistory (nr_double_t tcut) { 00898 if (histories != NULL) { 00899 for (int i = 0; i < nHistories; i++) 00900 { 00901 histories[i].truncate (tcut); 00902 } 00903 } 00904 } 00905 00906 // Appends a history value. 00907 void circuit::appendHistory (int n, nr_double_t val) { 00908 histories[n].push_back (val); 00909 } 00910 00911 // Returns the required age of the history. 00912 nr_double_t circuit::getHistoryAge (void) { 00913 if (histories) return histories[0].getAge (); 00914 return 0.0; 00915 } 00916 00917 // Returns size of the history 00918 int circuit::getHistorySize (void) { 00919 return histories[0].size (); 00920 } 00921 00922 // Returns the time with the specified index 00923 nr_double_t circuit::getHistoryTFromIndex (int idx) 00924 { 00925 return histories[0].getTfromidx (idx); 00926 } 00927 00928 /* This function should be used to apply the time vector history to 00929 the value histories of a circuit. */ 00930 void circuit::applyHistory (history * h) { 00931 for (int i = 0; i < nHistories; i++) 00932 { 00933 histories[i].apply(*h); 00934 } 00935 00936 } 00937 00938 // Returns voltage at the given time for the given node. 00939 nr_double_t circuit::getV (int port, nr_double_t t) { 00940 return histories[port].nearest (t); 00941 } 00942 00943 // Returns voltage at the given index from the history for the given node. 00944 nr_double_t circuit::getV (int port, int idx) { 00945 return histories[port].getValfromidx (idx); 00946 } 00947 00948 // Returns current at the given time for the given voltage source. 00949 nr_double_t circuit::getJ (int nr, nr_double_t t) { 00950 return histories[nr + getSize ()].nearest (t); 00951 } 00952 00953 } // namespace qucs