diff options
Diffstat (limited to 'src/electronics/simulation/element.h')
-rw-r--r-- | src/electronics/simulation/element.h | 255 |
1 files changed, 255 insertions, 0 deletions
diff --git a/src/electronics/simulation/element.h b/src/electronics/simulation/element.h new file mode 100644 index 0000000..e05de46 --- /dev/null +++ b/src/electronics/simulation/element.h @@ -0,0 +1,255 @@ +/*************************************************************************** + * Copyright (C) 2003-2004 by David Saxton * + * [email protected] * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + ***************************************************************************/ + +#ifndef ELEMENT_H +#define ELEMENT_H + +#include "elementset.h" +#include "matrix.h" + +class ElementSet; +class Vector; +typedef unsigned int uint; + +const double T = 300.; // Temperature in Kelvin +const double K = 1.38e-23; // Boltzmann's constant +const double q = 1.602e-19; // Charge on an electron +const double V_T = K*T/q; // Thermal voltage +const double gmin = 1e-12; // Minimum parallel conductance used in dc domain + +class CNode +{ +public: + CNode(); + void set_n( const uint n ) { m_n=n; } + uint n() { return m_n; } + double v; // Voltage on node. This is set from the last calculated voltage. + bool isGround; // True for ground nodes. Obviously, you should ignore n and v if this is true +private: + uint m_n; // CNode number +}; + +class CBranch +{ +public: + CBranch(); + void set_n( const uint n ) { m_n=n; } + uint n() { return m_n; } + double i; // Current flowing through branch. This is set from the last calculated current. +private: + uint m_n; // CBranch number +}; + +const int MAX_CNODES = 4; + +// Default node number that represents no node (remember that +// Ground node is -1, and the rest are numbered from 0 to n-1 +const int noCNode = -2; +// Likewise for branch (although there is no "ground" branch; +// it is merely -2 for likeness with noCNode) +const int noBranch = -2; + +/** +@short Represents a circuit element (such as resistance) +@author David Saxton +*/ +class Element +{ +public: + enum Type + { + Element_BJT, + Element_Capacitance, + Element_CCCS, + Element_CCVS, + Element_CurrentSignal, + Element_CurrentSource, + Element_Diode, + Element_Inductance, + Element_LogicIn, + Element_LogicOut, + Element_OpAmp, + Element_Resistance, + Element_VCCS, + Element_VCVS, + Element_VoltagePoint, + Element_VoltageSignal, + Element_VoltageSource + }; + + Element(); + virtual ~Element(); + /** + * This must be called when the circuit is changed. The function will get + * all the required pointers from ElementSet + */ + virtual void setElementSet( ElementSet *c ); + /** + * Returns a pointer to the current element set + */ + ElementSet *elementSet() { return p_eSet; } + /** + * Tells the element which nodes to use. Remember that -1 is ground. You + * should refer to the individual elements for which nodes are used for what. + */ + void setCNodes( const int n0 = noCNode, const int n1 = noCNode, const int n2 = noCNode, const int n3 = noCNode ); + /** + * Tells the element it's branch numbers (if it should have one). Not + * all elements use this. + */ + void setCBranches( const int b0 = noBranch, const int b1 = noBranch, const int b2 = noBranch, const int b3 = noBranch ); + /** + * Returns a pointer to the given CNode + */ + CNode *cnode( const uint num ) { return p_cnode[num]; } + /** + * Returns a pointer to the given CNode + */ + CBranch *cbranch( const uint num ) { return p_cbranch[num]; } + /** + * Returns the number of branches used by the element + */ + int numCBranches() { return m_numCBranches; } + /** + * Returns the number of circuit nodes used by the element + */ + int numCNodes() { return m_numCNodes; } + /** + * Call this function to tell the element to calculate the + * current flowing *into* it's cnodes *from* the element. You + * can get the currents with m_cnodeI. Child class must implement this function. + */ + virtual void updateCurrents() = 0; + /** + * Returns true for reactive elements that need stepping for numerical-integration + * (such as capacitors) + */ + virtual bool isReactive() { return false; } + /** + * Returns true for NonLinear elements that need iteration to converge to a solution + * as the matrix A is a function of x. + */ + virtual bool isNonLinear() { return false; } + /** + * Returns the type of element + */ + virtual Type type() const = 0; + /** + * Call this function to tell the element to add its map to the matrix in use + */ + virtual void add_map() {}; + /** + * Does the required MNA stuff. This should be called from ElementSet when necessary. + */ + virtual void add_initial_dc() = 0; + /** + * This is called from the Component destructor. When elementSetDeleted has + * also been called, this class will delete itself. + */ + void componentDeleted(); + void elementSetDeleted(); + + double m_cnodeI[8]; ///< Current flowing into the cnodes from the element + double cbranchCurrent( const int branch ); + double cnodeVoltage( const int node ); + +protected: + /** + * Resets all calculated currents in the nodes to 0 + */ + void resetCurrents(); + + inline double & A_g( uint i, uint j ); + inline double & A_b( uint i, uint j ); + inline double & A_c( uint i, uint j ); + inline double & A_d( uint i, uint j ); + + inline double & b_i( uint i ); + inline double & b_v( uint i ); + + ElementSet *p_eSet; + Matrix *p_A; + Vector *p_b; + CNode *p_cnode[MAX_CNODES]; + CBranch *p_cbranch[4]; + + /** + * True when the element can do add_initial_dc(), i.e. when it has + * pointers to the circuit, and at least one of its nodes is not ground. + */ + bool b_status; + /** + * Update the status, returning b_status + */ + virtual bool updateStatus(); + /** + * Set by child class - the number of branches that the element uses + * Typically, this is 0, but could be 1 (e.g. independent voltage source) + * or 2 (e.g. cccs) + */ + int m_numCBranches; + /** + * Set by child class - the number of circuit nodes that the element uses + */ + int m_numCNodes; + +private: + bool b_componentDeleted; + bool b_eSetDeleted; + double m_temp; +}; + + +double & Element::A_g( uint i, uint j ) +{ + if ( p_cnode[i]->isGround || p_cnode[j]->isGround ) + return m_temp; + return p_A->g( p_cnode[i]->n(), p_cnode[j]->n() ); +} + + +double & Element::A_b( uint i, uint j ) +{ + if ( p_cnode[i]->isGround ) + return m_temp; + return p_A->b( p_cnode[i]->n(), p_cbranch[j]->n() ); +} + + +double & Element::A_c( uint i, uint j ) +{ + if ( p_cnode[j]->isGround ) + return m_temp; + return p_A->c( p_cbranch[i]->n(), p_cnode[j]->n() ); +} + + +double & Element::A_d( uint i, uint j ) +{ + return p_A->d( p_cbranch[i]->n(), p_cbranch[j]->n() ); +} + + + +double & Element::b_i( uint i ) +{ + if ( p_cnode[i]->isGround ) + return m_temp; + + return (*p_b)[ p_cnode[i]->n() ]; +} + + +double & Element::b_v( uint i ) +{ + return (*p_b)[ p_eSet->cnodeCount() + p_cbranch[i]->n() ]; +} + +#endif |