File indexing completed on 2024-04-28 05:43:15

0001 /***************************************************************************
0002  *   Copyright (C) 2003-2005 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 CIRCUIT_H
0012 #define CIRCUIT_H
0013 
0014 #include <QList>
0015 #include <QPointer>
0016 
0017 #include "elementset.h"
0018 
0019 class CircuitDocument;
0020 class Wire;
0021 class Pin;
0022 class Element;
0023 class LogicOut;
0024 
0025 typedef QList<QPointer<Pin>> PinList;
0026 typedef QList<Element *> ElementList;
0027 
0028 class LogicCacheNode
0029 {
0030 public:
0031     LogicCacheNode();
0032     ~LogicCacheNode();
0033 
0034     LogicCacheNode *high;
0035     LogicCacheNode *low;
0036     QuickVector *data;
0037 };
0038 
0039 /**
0040 Usage of this class (usually invoked from CircuitDocument):
0041 (1) Add Wires, Pins and Elements to the class as appropriate
0042 (2) Call init to initialize the simulation
0043 (3) Control the simulation with step()
0044 
0045 This class can be considered a bridge between the gui-tainted CircuitDocument - specific
0046 to this implementation, and the pure untainted ElementSet. Please keep it that way.
0047 
0048 @short Simulates a collection of components
0049 @author David Saxton
0050 */
0051 class Circuit
0052 {
0053 public:
0054     Circuit();
0055     ~Circuit();
0056 
0057     void addPin(Pin *node);
0058     void addElement(Element *element);
0059 
0060     bool contains(Pin *node);
0061     bool containsNonLinear() const
0062     {
0063         return m_elementSet->containsNonLinear();
0064     }
0065 
0066     void init();
0067     /**
0068      * Called after everything else has been setup - before doNonLogic or
0069      * doLogic are called for the first time. Preps the circuit.
0070      */
0071     void initCache();
0072     /**
0073      * Marks all cached results as invalidated and removes them.
0074      */
0075     void setCacheInvalidated();
0076     /**
0077      * Solves for non-logic elements
0078      */
0079     void doNonLogic();
0080     /**
0081      * Solves for logic elements (i.e just does fbSub)
0082      */
0083     void doLogic()
0084     {
0085         m_elementSet->doLinear(false);
0086     }
0087 
0088     void displayEquations();
0089     void updateCurrents();
0090 
0091     void createMatrixMap();
0092     /**
0093         * This will identify the ground node and non-ground nodes in the given set.
0094         * Ground will be given the eqId -1, non-ground of 0.
0095         * @param highest The highest ground type of the groundnodes found. If no
0096         ground nodes were found, this will be (gt_never-1).
0097         * @returns the number of ground nodes. If all nodes are at or below the
0098         *           gt_never threshold, then this will be zero.
0099         */
0100     static int identifyGround(PinList nodeList, int *highest = nullptr);
0101 
0102     void setNextChanged(Circuit *circuit, unsigned char chain)
0103     {
0104         m_pNextChanged[chain] = circuit;
0105     }
0106     Circuit *nextChanged(unsigned char chain) const
0107     {
0108         return m_pNextChanged[chain];
0109     }
0110     void setCanAddChanged(bool canAdd)
0111     {
0112         m_bCanAddChanged = canAdd;
0113     }
0114     bool canAddChanged() const
0115     {
0116         return m_bCanAddChanged;
0117     }
0118 
0119 protected:
0120     void cacheAndUpdate();
0121     /**
0122      * Update the nodal voltages from those calculated in ElementSet
0123      */
0124     void updateNodalVoltages();
0125     /**
0126      * Step the reactive elements.
0127      */
0128     void stepReactive();
0129     /**
0130      * Returns true if any of the nodes are ground
0131      */
0132     static bool recursivePinAdd(Pin *node, PinList *unassignedNodes, PinList *associated, PinList *nodes);
0133 
0134     int m_cnodeCount;
0135     int m_branchCount;
0136     int m_prepNLCount; // Count until next m_elementSet->prepareNonLinear() is called
0137 
0138     PinList m_pinList;
0139     ElementList m_elementList;
0140     ElementSet *m_elementSet;
0141 
0142     // Stuff for caching
0143     bool m_bCanCache;
0144     LogicCacheNode *m_pLogicCacheBase;
0145     unsigned m_logicOutCount;
0146     LogicOut **m_pLogicOut;
0147 
0148     bool m_bCanAddChanged;
0149     Circuit *m_pNextChanged[2];
0150 };
0151 
0152 #endif