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