summaryrefslogtreecommitdiffstats
path: root/src/electronics/simulation/element.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/electronics/simulation/element.h')
-rw-r--r--src/electronics/simulation/element.h255
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 *
+ * david@bluehaze.org *
+ * *
+ * 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