Warning, file /sdk/ktechlab/src/electronics/simulation/element.h was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).
0001 /*************************************************************************** 0002 * Copyright (C) 2003-2006 by David Saxton * 0003 * david@bluehaze.org * 0004 * * 0005 * This program is free software; you can redistribute it and/or modify * 0006 * it under the terms of the GNU General Public License as published by * 0007 * the Free Software Foundation; either version 2 of the License, or * 0008 * (at your option) any later version. * 0009 ***************************************************************************/ 0010 0011 #ifndef ELEMENT_H 0012 #define ELEMENT_H 0013 0014 #include "elementset.h" 0015 #include "matrix.h" 0016 0017 #include <stdint.h> 0018 0019 class ElementSet; 0020 typedef unsigned int uint; 0021 0022 const double T = 300.; ///< Temperature in Kelvin 0023 const double K = 1.3806503e-23; ///< Boltzmann's constant 0024 const double q = 1.602176462e-19; ///< Charge on an electron 0025 const double V_T = K * T / q; ///< Thermal voltage 0026 0027 class CNode 0028 { 0029 public: 0030 CNode() 0031 : v(0.0) 0032 , isGround(false) 0033 , m_n(0) 0034 { 0035 } 0036 CNode(const uint32_t n) 0037 : v(0.0) 0038 , isGround(false) 0039 , m_n(n) 0040 { 0041 } 0042 void set_n(const uint n) 0043 { 0044 m_n = n; 0045 } 0046 uint n() const 0047 { 0048 return m_n; 0049 } 0050 0051 /// Voltage on node. This is set from the last calculated voltage. 0052 double v; 0053 0054 /// True for ground nodes. Obviously, you should ignore n and v if this is true 0055 bool isGround; 0056 0057 private: 0058 /// CNode number 0059 uint m_n; 0060 }; 0061 0062 class CBranch 0063 { 0064 public: 0065 CBranch() 0066 : i(0.0) 0067 , m_n(0) 0068 { 0069 } 0070 CBranch(const uint32_t n) 0071 : i(0.0) 0072 , m_n(n) 0073 { 0074 } 0075 void set_n(const uint n) 0076 { 0077 m_n = n; 0078 } 0079 uint n() const 0080 { 0081 return m_n; 0082 } 0083 0084 /// Current flowing through branch. This is set from the last calculated current. 0085 double i; 0086 0087 private: 0088 /// CBranch number 0089 uint m_n; 0090 }; 0091 0092 const int MAX_CNODES = 4; 0093 const int MAX_CBRANCHES = 4; 0094 0095 /// Default node number that represents no node (remember that 0096 /// Ground node is -1, and the rest are numbered from 0 to n-1 0097 const int noCNode = -2; 0098 0099 /// Likewise for branch (although there is no "ground" branch; 0100 /// it is merely -2 for likeness with noCNode) 0101 const int noBranch = -2; 0102 0103 /** 0104 @short Represents a circuit element (such as resistance) 0105 @author David Saxton 0106 */ 0107 class Element 0108 { 0109 public: 0110 enum Type { 0111 Element_BJT, 0112 Element_Capacitance, 0113 Element_CCCS, 0114 Element_CCVS, 0115 Element_CurrentSignal, 0116 Element_CurrentSource, 0117 Element_Diode, 0118 Element_JFET, 0119 Element_Inductance, 0120 Element_LogicIn, 0121 Element_LogicOut, 0122 Element_MOSFET, 0123 Element_OpAmp, 0124 Element_Resistance, 0125 Element_VCCS, 0126 Element_VCVS, 0127 Element_VoltagePoint, 0128 Element_VoltageSignal, 0129 Element_VoltageSource 0130 }; 0131 0132 Element(); 0133 virtual ~Element(); 0134 /** 0135 * This must be called when the circuit is changed. The function will get 0136 * all the required pointers from ElementSet 0137 */ 0138 virtual void setElementSet(ElementSet *c); 0139 /** 0140 * Returns a pointer to the current element set 0141 */ 0142 ElementSet *elementSet() const 0143 { 0144 return p_eSet; 0145 } 0146 /** 0147 * Tells the element which nodes to use. Remember that -1 is ground. You 0148 * should refer to the individual elements for which nodes are used for what. 0149 */ 0150 void setCNodes(const int n0 = noCNode, const int n1 = noCNode, const int n2 = noCNode, const int n3 = noCNode); 0151 /** 0152 * Tells the element it's branch numbers (if it should have one). Not 0153 * all elements use this. 0154 */ 0155 void setCBranches(const int b0 = noBranch, const int b1 = noBranch, const int b2 = noBranch, const int b3 = noBranch); 0156 /** 0157 * Returns a pointer to the given CNode 0158 */ 0159 CNode *cnode(const uint num) 0160 { 0161 return p_cnode[num]; 0162 } 0163 /** 0164 * Returns a pointer to the given CNode 0165 */ 0166 CBranch *cbranch(const uint num) 0167 { 0168 return p_cbranch[num]; 0169 } 0170 /** 0171 * Returns the number of branches used by the element 0172 */ 0173 int numCBranches() const 0174 { 0175 return m_numCBranches; 0176 } 0177 /** 0178 * Returns the number of circuit nodes used by the element 0179 */ 0180 int numCNodes() const 0181 { 0182 return m_numCNodes; 0183 } 0184 /** 0185 * Call this function to tell the element to calculate the 0186 * current flowing *into* it's cnodes *from* the element. You 0187 * can get the currents with m_cnodeI. Child class must implement this function. 0188 */ 0189 virtual void updateCurrents() = 0; 0190 /** 0191 * Returns true for reactive elements that need stepping for numerical-integration 0192 * (such as capacitors) 0193 */ 0194 virtual bool isReactive() const 0195 { 0196 return false; 0197 } 0198 /** 0199 * Returns true for NonLinear elements that need iteration to converge to a solution 0200 * as the matrix A is a function of x. 0201 */ 0202 virtual bool isNonLinear() const 0203 { 0204 return false; 0205 } 0206 /** 0207 * Returns the type of element 0208 */ 0209 virtual Type type() const = 0; 0210 0211 /** 0212 * Does the required MNA stuff. This should be called from ElementSet when necessary. 0213 */ 0214 virtual void add_initial_dc() = 0; 0215 /** 0216 * This is called from the Component destructor. When elementSetDeleted has 0217 * also been called, this class will delete itself. 0218 */ 0219 void componentDeleted(); 0220 void elementSetDeleted(); 0221 0222 double m_cnodeI[8]; ///< Current flowing into the cnodes from the element 0223 double cbranchCurrent(const int branch); 0224 double cnodeVoltage(const int node); 0225 0226 protected: 0227 /** 0228 * Update the status, returning b_status 0229 */ 0230 virtual bool updateStatus(); 0231 /** 0232 * Resets all calculated currents in the nodes to 0 0233 */ 0234 void resetCurrents(); 0235 0236 inline double &A_g(uint i, uint j); 0237 inline double &A_b(uint i, uint j); 0238 inline double &A_c(uint i, uint j); 0239 inline double &A_d(uint i, uint j); 0240 0241 inline double &b_i(uint i); 0242 inline double &b_v(uint i); 0243 0244 ElementSet *p_eSet; 0245 0246 /** 0247 * Set by child class - the number of circuit nodes that the element uses 0248 */ 0249 int m_numCNodes; 0250 CNode *p_cnode[MAX_CNODES]; 0251 0252 /** 0253 * Set by child class - the number of branches that the element uses 0254 * Typically, this is 0, but could be 1 (e.g. independent voltage source) 0255 * or 2 (e.g. cccs) 0256 */ 0257 int m_numCBranches; 0258 CBranch *p_cbranch[MAX_CBRANCHES]; 0259 0260 /** 0261 * True when the element can do add_initial_dc(), i.e. when it has 0262 * pointers to the circuit, and at least one of its nodes is not ground. 0263 */ 0264 bool b_status; 0265 0266 private: 0267 bool b_componentDeleted; 0268 double m_temp; 0269 }; 0270 0271 double &Element::A_g(uint i, uint j) 0272 { 0273 if (p_cnode[i]->isGround || p_cnode[j]->isGround) 0274 return m_temp; 0275 return p_eSet->matrix()->g(p_cnode[i]->n(), p_cnode[j]->n()); 0276 } 0277 0278 double &Element::A_b(uint i, uint j) 0279 { 0280 if (p_cnode[i]->isGround) 0281 return m_temp; 0282 return p_eSet->matrix()->b(p_cnode[i]->n(), p_cbranch[j]->n()); 0283 } 0284 0285 double &Element::A_c(uint i, uint j) 0286 { 0287 if (p_cnode[j]->isGround) 0288 return m_temp; 0289 return p_eSet->matrix()->c(p_cbranch[i]->n(), p_cnode[j]->n()); 0290 } 0291 0292 double &Element::A_d(uint i, uint j) 0293 { 0294 return p_eSet->matrix()->d(p_cbranch[i]->n(), p_cbranch[j]->n()); 0295 } 0296 0297 double &Element::b_i(uint i) 0298 { 0299 if (p_cnode[i]->isGround) 0300 return m_temp; 0301 0302 return (*(p_eSet->b()))[p_cnode[i]->n()]; 0303 } 0304 0305 double &Element::b_v(uint i) 0306 { 0307 return (*(p_eSet->b()))[p_eSet->cnodeCount() + p_cbranch[i]->n()]; 0308 } 0309 0310 #endif