Ejemplo n.º 1
0
    // Circuit error 1
    public static void CircuitError(ICircuitElement element)
    {
        Whisp whisp = FindObjectOfType <Whisp>();            // tuna je ta chyba niekde,, bez tohto nevyhadzuje nikde chybu

        /*string path = element.ToString();
         * int pos = path.LastIndexOf(".", StringComparison.Ordinal) + 1;
         * string componentName = path.Substring(pos, path.Length - pos);
         *
         * string toFindInRes = path.Substring(pos, path.Length - pos);
         * string resComponentName = ResourceReader.Instance.GetResource("ComponentText" + componentName);
         * string resCircuitErrorMsg = ResourceReader.Instance.GetResource("CircuitErrorMSG1");
         * resCircuitErrorMsg = resCircuitErrorMsg.Replace("{COMPONENTNAME}", resComponentName);
         *
         * string windowName = "ERRORMSG_" + componentName;
         *
         * if (GameObject.Find(windowName))
         * {
         *  bool currentlyEnabled = GameObject.Find(windowName).GetComponent<Canvas>().enabled;
         *  if (currentlyEnabled == false)
         *  {
         *      currentlyEnabled = true;
         *      GameObject.Find(windowName).GetComponent<Canvas>().enabled = true;
         *  }
         *  else
         *  {
         *      currentlyEnabled = false;
         *      GameObject.Find(windowName).GetComponent<Canvas>().enabled = false;
         *  }
         * }
         * else
         * {
         *  whisp.Say(ResourceReader.Instance.GetResource("CircuitErrorMissingErrorBox") + "{" + resComponentName + "}");
         * }
         * whisp.Say(resCircuitErrorMsg);*/
    }
Ejemplo n.º 2
0
 public FindPathInfo(Circuit r, PathType t, ICircuitElement e, int d)
 {
     sim      = r;
     dest     = d;
     type     = t;
     firstElm = e;
     used     = new bool[sim.nodeList.Count];
 }
Ejemplo n.º 3
0
        public void Connect(ICircuitElement left, int leftLeadNdx, ICircuitElement right, int rightLeadNdx)
        {
            int leftNdx  = elements.IndexOf(left);
            int rightNdx = elements.IndexOf(right);

            Connect(leftNdx, leftLeadNdx, rightNdx, rightLeadNdx);
            needAnalyze();
        }
Ejemplo n.º 4
0
 public static ScopeFrame GetScopeFrame(this ICircuitElement elem, double time)
 {
     return(new ScopeFrame {
         time = time,
         current = elem.getCurrent(),
         voltage = elem.getVoltageDelta(),
     });
 }
        public CircuitElementDrawingVisual(ICircuitElement circuitElement)
        {
            CircuitElement = circuitElement;

            this.Offset = circuitElement.Location;

            circuitElement.Updated += (o, e) =>
            {
                this.Offset = circuitElement.Location;
            };
        }
        public CircuitElementDrawingVisual(ICircuitElement circuitElement)
        {
            CircuitElement = circuitElement;

            this.Offset = circuitElement.Location;

            circuitElement.Updated += (o, e) =>
                {
                    this.Offset = circuitElement.Location;
                };
        }
Ejemplo n.º 7
0
        private Wire CreateWire(string operation, ICircuitElement input1, ICircuitElement input2, string output)
        {
            Wire wire = null;

            switch (operation)
            {
            case "NOT":
                if (input2 != null)
                {
                    wire = new Wire(output, new NotGate(input2));
                }
                break;

            case "AND":
                if (input1 != null && input2 != null)
                {
                    wire = new Wire(output, new AndGate(input1, input2));
                }
                break;

            case "OR":
                if (input1 != null && input2 != null)
                {
                    wire = new Wire(output, new OrGate(input1, input2));
                }
                break;

            case "LSHIFT":
                if (input1 != null && input2 != null)
                {
                    wire = new Wire(output, new LeftShiftGate(input1, input2));
                }
                break;

            case "RSHIFT":
                if (input1 != null && input2 != null)
                {
                    wire = new Wire(output, new RightShiftGate(input1, input2));
                }
                break;

            case "":
                if (input1 != null || input2 != null)
                {
                    wire = new Wire(output, input1 ?? input2);
                }
                break;

            default:
                throw new ApplicationException("Unsupported operation " + operation);
            }
            return(wire);
        }
        public void Update(ICircuitElement element)
        {
            SpotLoad   spotLoad   = element as SpotLoad;
            MainWindow mainWindow = GetMainWindow();

            if (mainWindow.GlobalSpotLoads.ContainsKey(spotLoad.Element_id))
            {
                mainWindow.GlobalSpotLoads.Remove(spotLoad.Element_id);
            }

            mainWindow.DeleteSpotLoad(spotLoad.Element_id);
        }
Ejemplo n.º 9
0
 public List <ScopeFrame> Watch(ICircuitElement component)
 {
     if (!scopeMap.ContainsKey(component))
     {
         List <ScopeFrame> scope = new List <ScopeFrame>();
         scopeMap.Add(component, scope);
         return(scope);
     }
     else
     {
         return(scopeMap[component]);
     }
 }
Ejemplo n.º 10
0
 private Wire CreateWire(string operation, ICircuitElement input1, ICircuitElement input2, string output)
 {
     Wire wire = null;
     switch (operation)
     {
         case "NOT":
             if (input2 != null)
             {
                 wire = new Wire(output, new NotGate(input2));
             }
             break;
         case "AND":
             if (input1 != null && input2 != null)
             {
                 wire = new Wire(output, new AndGate(input1, input2));
             }
             break;
         case "OR":
             if (input1 != null && input2 != null)
             {
                 wire = new Wire(output, new OrGate(input1, input2));
             }
             break;
         case "LSHIFT":
             if (input1 != null && input2 != null)
             {
                 wire = new Wire(output, new LeftShiftGate(input1, input2));
             }
             break;
         case "RSHIFT":
             if (input1 != null && input2 != null)
             {
                 wire = new Wire(output, new RightShiftGate(input1, input2));
             }
             break;
         case "":
             if (input1 != null || input2 != null)
             {
                 wire = new Wire(output, input1 ?? input2);
             }
             break;
         default:
             throw new ApplicationException("Unsupported operation " + operation);
     }
     return wire;
 }
        public void Create(ICircuitElement element)
        {
            SpotLoad   spotLoad   = element as SpotLoad;
            MainWindow mainWindow = GetMainWindow();

            if (mainWindow.GlobalSpotLoads.ContainsKey(spotLoad.Element_id) == false)
            {
                mainWindow.GlobalSpotLoads.Add(spotLoad.Element_id, spotLoad);
            }
            else
            {
                mainWindow.GlobalSpotLoads[spotLoad.Element_id] = spotLoad;
            }

            mainWindow.CloseAllWindows();

            mainWindow.spotLoadTab._globalSpotLoads = mainWindow.GlobalSpotLoads;
            mainWindow.spotLoadTab.populateListView();
        }
Ejemplo n.º 12
0
        public void AddElement(ICircuitElement elm)
        {
            if (!elements.Contains(elm))
            {
                elements.Add(elm);

                nodeMesh.Add(new long[elm.getLeadCount()]);
                for (int x = 0; x < elm.getLeadCount(); x++)
                {
                    nodeMesh[nodeMesh.Count - 1][x] = -1;
                }

                int e_ndx = elements.Count - 1;
                int m_ndx = nodeMesh.Count - 1;
                if (e_ndx != m_ndx)
                {
                    throw new System.Exception("AddElement array length mismatch");
                }
            }
        }
Ejemplo n.º 13
0
 public OrGate(ICircuitElement input1, ICircuitElement input2)
     : base(input1, input2)
 {
 }
Ejemplo n.º 14
0
 public NotGate(ICircuitElement input)
 {
     _input = input;
 }
Ejemplo n.º 15
0
            public bool findPath(int n1, int depth)
            {
                if (n1 == dest)
                {
                    return(true);
                }

                if (depth-- == 0)
                {
                    return(false);
                }

                if (used[n1])
                {
                    return(false);
                }

                used[n1] = true;
                for (int i = 0; i != sim.elements.Count; i++)
                {
                    ICircuitElement ce = sim.getElm(i);
                    if (ce == firstElm)
                    {
                        continue;
                    }

                    if (type == PathType.INDUCT)
                    {
                        if (ce is CurrentSource)
                        {
                            continue;
                        }
                    }

                    if (type == PathType.VOLTAGE)
                    {
                        if (!(ce.isWire() || ce is Voltage))
                        {
                            continue;
                        }
                    }

                    if (type == PathType.SHORT && !ce.isWire())
                    {
                        continue;
                    }

                    if (type == PathType.CAP_V)
                    {
                        if (!(ce.isWire() || ce is CapacitorElm || ce is Voltage))
                        {
                            continue;
                        }
                    }

                    if (n1 == 0)
                    {
                        // look for posts which have a ground connection;
                        // our path can go through ground
                        for (int z = 0; z != ce.getLeadCount(); z++)
                        {
                            if (ce.leadIsGround(z) && findPath(ce.getLeadNode(z), depth))
                            {
                                used[n1] = false;
                                return(true);
                            }
                        }
                    }

                    int j;
                    for (j = 0; j != ce.getLeadCount(); j++)
                    {
                        if (ce.getLeadNode(j) == n1)
                        {
                            break;
                        }
                    }

                    if (j == ce.getLeadCount())
                    {
                        continue;
                    }

                    if (ce.leadIsGround(j) && findPath(0, depth))
                    {
                        // System.out.println(ce + " has ground");
                        used[n1] = false;
                        return(true);
                    }

                    if (type == PathType.INDUCT && ce is InductorElm)
                    {
                        double c = ce.getCurrent();
                        if (j == 0)
                        {
                            c = -c;
                        }

                        // System.out.println("matching " + c + " to " + firstElm.getCurrent());
                        // System.out.println(ce + " " + firstElm);
                        if (Math.Abs(c - firstElm.getCurrent()) > 1e-10)
                        {
                            continue;
                        }
                    }

                    for (int k = 0; k != ce.getLeadCount(); k++)
                    {
                        if (j == k)
                        {
                            continue;
                        }

                        // System.out.println(ce + " " + ce.getNode(j) + "-" + ce.getNode(k));
                        if (ce.leadsAreConnected(j, k) && findPath(ce.getLeadNode(k), depth))
                        {
                            // System.out.println("got findpath " + n1);
                            used[n1] = false;
                            return(true);
                        }
                        // System.out.println("back on findpath " + n1);
                    }
                }

                used[n1] = false;
                // System.out.println(n1 + " failed");
                return(false);
            }
Ejemplo n.º 16
0
 public LeftShiftGate(ICircuitElement input, ICircuitElement shift)
     : base(input, shift)
 {
 }
Ejemplo n.º 17
0
 public Lead(ICircuitElement e, Int32 i)
 {
     elem = e; ndx = i;
 }
Ejemplo n.º 18
0
 protected ShiftGate(ICircuitElement input, ICircuitElement shift)
 {
     Input = input;
     Shift = shift;
 }
Ejemplo n.º 19
0
 public Wire(string identifier, ICircuitElement input)
 {
     Identifier = identifier;
     _input     = input;
 }
Ejemplo n.º 20
0
 public void panic(String why, ICircuitElement elem)
 {
     circuitMatrix = null;
     _analyze      = true;
     throw new Exception(why, elem);
 }
Ejemplo n.º 21
0
 public static string GetCurrentString(this ICircuitElement elem)
 {
     return(SIUnits.Current(elem.getCurrent()));
 }
Ejemplo n.º 22
0
 public static string GetVoltageString(this ICircuitElement elem)
 {
     return(SIUnits.Voltage(elem.getVoltageDelta()));
 }
Ejemplo n.º 23
0
 public Exception(string why, ICircuitElement elem) : base(why)
 {
     element = elem;
 }
Ejemplo n.º 24
0
 public RightShiftGate(ICircuitElement input, ICircuitElement shift)
     : base(input, shift)
 {
 }
Ejemplo n.º 25
0
 protected BinaryGate(ICircuitElement input1, ICircuitElement input2)
 {
     Input1 = input1;
     Input2 = input2;
 }
Ejemplo n.º 26
0
 public AndGate(ICircuitElement input1, ICircuitElement input2)
     : base(input1, input2)
 {
 }
Ejemplo n.º 27
0
 public NotGate(ICircuitElement input)
 {
     _input = input;
 }
Ejemplo n.º 28
0
 protected ShiftGate(ICircuitElement input, ICircuitElement shift)
 {
     Input = input;
     Shift = shift;
 }
Ejemplo n.º 29
0
 protected BinaryGate(ICircuitElement input1, ICircuitElement input2)
 {
     Input1 = input1;
     Input2 = input2;
 }
Ejemplo n.º 30
0
 public Wire(string identifier, ICircuitElement input)
 {
     Identifier = identifier;
     _input = input;
 }
Ejemplo n.º 31
0
        public void analyze()
        {
            if (elements.Count == 0)
            {
                return;
            }

            nodeList.Clear();
            List <bool>         internalList = new List <bool>();
            Action <long, bool> pushNode     = (id, isInternal) => {
                if (!nodeList.Contains(id))
                {
                    nodeList.Add(id);
                    internalList.Add(isInternal);
                }
            };

            #region             //// Look for Voltage or Ground element ////
            // Search the circuit for a Ground, or Voltage sourcre
            ICircuitElement voltageElm = null;
            bool            gotGround  = false;
            bool            gotRail    = false;
            for (int i = 0; i != elements.Count; i++)
            {
                ICircuitElement elem = elements[i];
                if (elem is Ground)
                {
                    gotGround = true;
                    break;
                }

                if (elem is VoltageInput)
                {
                    gotRail = true;
                }

                if (elem is Voltage && voltageElm == null)
                {
                    voltageElm = elem;
                }
            }

            // If no ground and no rails, then the voltage elm's first terminal is ground.
            if (!gotGround && !gotRail && voltageElm != null)
            {
                int    elm_ndx = elements.IndexOf(voltageElm);
                long[] ndxs    = nodeMesh[elm_ndx];
                pushNode(ndxs[0], false);
            }
            else
            {
                // If the circuit contains a ground, rail, or voltage
                // element, push a temporary node to the node list.
                pushNode(snowflake.NextId(), false);
            }
            #endregion

            // At this point, there is 1 node in the list, the special `global ground` node.

            #region             //// Nodes and Voltage Sources ////
            int vscount = 0;    // Number of voltage sources
            for (int i = 0; i != elements.Count; i++)
            {
                ICircuitElement elm   = elements[i];
                int             leads = elm.getLeadCount();

                // If the leadCount reported by the element does
                // not match the number of leads allocated,
                // resize the array.
                if (leads != nodeMesh[i].Length)
                {
                    long[] leadMap = nodeMesh[i];
                    Array.Resize(ref leadMap, leads);
                    nodeMesh[i] = leadMap;
                }

                // For each lead in the element
                for (int leadX = 0; leadX != leads; leadX++)
                {
                    long leadNode = nodeMesh[i][leadX];                            // Id of the node leadX is connected too
                    int  node_ndx = nodeList.IndexOf(leadNode);                    // Index of the leadNode in the nodeList
                    if (node_ndx == -1)
                    {
                        // If the nodeList doesn't contain the node, push it
                        // onto the list and assign it's new index to the lead.
                        elm.setLeadNode(leadX, nodeList.Count);
                        pushNode(leadNode, false);
                    }
                    else
                    {
                        // Otherwise, assign the lead the index of
                        // the node in the nodeList.
                        elm.setLeadNode(leadX, node_ndx);

                        if (leadNode == 0)
                        {
                            // if it's the ground node, make sure the
                            // node voltage is 0, cause it may not get set later
                            elm.setLeadVoltage(leadX, 0);                             // TODO: ??
                        }
                    }
                }

                // Push an internal node onto the list for
                // each internal lead on the element.
                int internalLeads = elm.getInternalLeadCount();
                for (int x = 0; x != internalLeads; x++)
                {
                    elm.setLeadNode(leads + x, nodeList.Count);
                    pushNode(snowflake.NextId(), true);
                }

                vscount += elm.getVoltageSourceCount();
            }
            #endregion

            // == Creeate the voltageSources array.
            // Also determine if circuit is nonlinear.

            // VoltageSourceId -> ICircuitElement map
            voltageSources = new ICircuitElement[vscount];
            vscount        = 0;

            circuitNonLinear = false;
            //for(int i = 0; i != elements.Count; i++) {
            //	ICircuitElement elem = elements[i];
            foreach (ICircuitElement elem in elements)
            {
                if (elem.nonLinear())
                {
                    circuitNonLinear = true;
                }

                // Assign each votage source in the element a globally unique id,
                // (the index of the next open slot in voltageSources)
                for (int leadX = 0; leadX != elem.getVoltageSourceCount(); leadX++)
                {
                    voltageSources[vscount] = elem;
                    elem.setVoltageSource(leadX, vscount++);
                }
            }

            #region             //// Matrix setup ////
            int matrixSize = nodeList.Count - 1 + vscount;

            // setup circuitMatrix
            circuitMatrix = new double[matrixSize][];
            for (int z = 0; z < matrixSize; z++)
            {
                circuitMatrix[z] = new double[matrixSize];
            }

            circuitRightSide = new double[matrixSize];

            // setup origMatrix
            origMatrix = new double[matrixSize][];
            for (int z = 0; z < matrixSize; z++)
            {
                origMatrix[z] = new double[matrixSize];
            }

            origRightSide = new double[matrixSize];

            // setup circuitRowInfo
            circuitRowInfo = new RowInfo[matrixSize];
            for (int i = 0; i != matrixSize; i++)
            {
                circuitRowInfo[i] = new RowInfo();
            }

            circuitPermute    = new int[matrixSize];
            circuitMatrixSize = circuitMatrixFullSize = matrixSize;
            circuitNeedsMap   = false;
            #endregion

            // Stamp linear circuit elements.
            for (int i = 0; i != elements.Count; i++)
            {
                elements[i].stamp(this);
            }

            #region             //// Determine nodes that are unconnected ////
            bool[] closure = new bool[nodeList.Count];
            bool   changed = true;
            closure[0] = true;
            while (changed)
            {
                changed = false;
                for (int i = 0; i != elements.Count; i++)
                {
                    ICircuitElement ce = elements[i];
                    // loop through all ce's nodes to see if they are connected
                    // to other nodes not in closure
                    for (int leadX = 0; leadX < ce.getLeadCount(); leadX++)
                    {
                        if (!closure[ce.getLeadNode(leadX)])
                        {
                            if (ce.leadIsGround(leadX))
                            {
                                closure[ce.getLeadNode(leadX)] = changed = true;
                            }
                            continue;
                        }
                        for (int k = 0; k != ce.getLeadCount(); k++)
                        {
                            if (leadX == k)
                            {
                                continue;
                            }
                            int kn = ce.getLeadNode(k);
                            if (ce.leadsAreConnected(leadX, k) && !closure[kn])
                            {
                                closure[kn] = true;
                                changed     = true;
                            }
                        }
                    }
                }

                if (changed)
                {
                    continue;
                }

                // connect unconnected nodes
                for (int i = 0; i != nodeList.Count; i++)
                {
                    if (!closure[i] && !internalList[i])
                    {
                        //System.out.println("node " + i + " unconnected");
                        stampResistor(0, i, 1E8);
                        closure[i] = true;
                        changed    = true;
                        break;
                    }
                }
            }
            #endregion

            #region             //// Sanity checks ////
            for (int i = 0; i != elements.Count; i++)
            {
                ICircuitElement ce = elements[i];

                // look for inductors with no current path
                if (ce is InductorElm)
                {
                    FindPathInfo fpi = new FindPathInfo(this, FindPathInfo.PathType.INDUCT, ce, ce.getLeadNode(1));
                    // first try findPath with maximum depth of 5, to avoid slowdowns
                    if (!fpi.findPath(ce.getLeadNode(0), 5) && !fpi.findPath(ce.getLeadNode(0)))
                    {
                        //System.out.println(ce + " no path");
                        ce.reset();
                    }
                }

                // look for current sources with no current path
                if (ce is CurrentSource)
                {
                    FindPathInfo fpi = new FindPathInfo(this, FindPathInfo.PathType.INDUCT, ce, ce.getLeadNode(1));
                    if (!fpi.findPath(ce.getLeadNode(0)))
                    {
                        panic("No path for current source!", ce);
                    }
                }

                // look for voltage source loops
                if ((ce is Voltage && ce.getLeadCount() == 2) || ce is Wire)
                {
                    FindPathInfo fpi = new FindPathInfo(this, FindPathInfo.PathType.VOLTAGE, ce, ce.getLeadNode(1));
                    if (fpi.findPath(ce.getLeadNode(0)))
                    {
                        panic("Voltage source/wire loop with no resistance!", ce);
                    }
                }

                // look for shorted caps, or caps w/ voltage but no R
                if (ce is CapacitorElm)
                {
                    FindPathInfo fpi = new FindPathInfo(this, FindPathInfo.PathType.SHORT, ce, ce.getLeadNode(1));
                    if (fpi.findPath(ce.getLeadNode(0)))
                    {
                        //System.out.println(ce + " shorted");
                        ce.reset();
                    }
                    else
                    {
                        fpi = new FindPathInfo(this, FindPathInfo.PathType.CAP_V, ce, ce.getLeadNode(1));
                        if (fpi.findPath(ce.getLeadNode(0)))
                        {
                            panic("Capacitor loop with no resistance!", ce);
                        }
                    }
                }
            }
            #endregion

            #region             //// Simplify the matrix //// =D
            for (int i = 0; i != matrixSize; i++)
            {
                int     qm = -1, qp = -1;
                double  qv = 0;
                RowInfo re = circuitRowInfo[i];

                if (re.lsChanges || re.dropRow || re.rsChanges)
                {
                    continue;
                }

                double rsadd = 0;

                // look for rows that can be removed
                int leadX = 0;
                for (; leadX != matrixSize; leadX++)
                {
                    double q = circuitMatrix[i][leadX];
                    if (circuitRowInfo[leadX].type == RowInfo.ROW_CONST)
                    {
                        // keep a running total of const values that have been removed already
                        rsadd -= circuitRowInfo[leadX].value * q;
                        continue;
                    }

                    if (q == 0)
                    {
                        continue;
                    }

                    if (qp == -1)
                    {
                        qp = leadX;
                        qv = q;
                        continue;
                    }

                    if (qm == -1 && q == -qv)
                    {
                        qm = leadX;
                        continue;
                    }

                    break;
                }

                if (leadX == matrixSize)
                {
                    if (qp == -1)
                    {
                        panic("Matrix error", null);
                    }

                    RowInfo elt = circuitRowInfo[qp];
                    if (qm == -1)
                    {
                        // we found a row with only one nonzero entry;
                        // that value is a constant
                        for (int k = 0; elt.type == RowInfo.ROW_EQUAL && k < 100; k++)
                        {
                            // follow the chain
                            // System.out.println("following equal chain from " + i + " " + qp + " to " + elt.nodeEq);
                            qp  = elt.nodeEq;
                            elt = circuitRowInfo[qp];
                        }

                        if (elt.type == RowInfo.ROW_EQUAL)
                        {
                            // break equal chains
                            // System.out.println("Break equal chain");
                            elt.type = RowInfo.ROW_NORMAL;
                            continue;
                        }

                        if (elt.type != RowInfo.ROW_NORMAL)
                        {
                            //System.out.println("type already " + elt.type + " for " + qp + "!");
                            continue;
                        }

                        elt.type  = RowInfo.ROW_CONST;
                        elt.value = (circuitRightSide[i] + rsadd) / qv;
                        circuitRowInfo[i].dropRow = true;
                        // System.out.println(qp + " * " + qv + " = const " + elt.value);
                        i = -1;                         // start over from scratch
                    }
                    else if (circuitRightSide[i] + rsadd == 0)
                    {
                        // we found a row with only two nonzero entries, and one
                        // is the negative of the other; the values are equal
                        if (elt.type != RowInfo.ROW_NORMAL)
                        {
                            // System.out.println("swapping");
                            int qq = qm;
                            qm  = qp;
                            qp  = qq;
                            elt = circuitRowInfo[qp];
                            if (elt.type != RowInfo.ROW_NORMAL)
                            {
                                // we should follow the chain here, but this hardly
                                // ever happens so it's not worth worrying about
                                //System.out.println("swap failed");
                                continue;
                            }
                        }
                        elt.type   = RowInfo.ROW_EQUAL;
                        elt.nodeEq = qm;
                        circuitRowInfo[i].dropRow = true;
                        // System.out.println(qp + " = " + qm);
                    }
                }
            }

            // == Find size of new matrix
            int nn = 0;
            for (int i = 0; i != matrixSize; i++)
            {
                RowInfo elt = circuitRowInfo[i];
                if (elt.type == RowInfo.ROW_NORMAL)
                {
                    elt.mapCol = nn++;
                    // System.out.println("col " + i + " maps to " + elt.mapCol);
                    continue;
                }
                if (elt.type == RowInfo.ROW_EQUAL)
                {
                    RowInfo e2 = null;
                    // resolve chains of equality; 100 max steps to avoid loops
                    for (int leadX = 0; leadX != 100; leadX++)
                    {
                        e2 = circuitRowInfo[elt.nodeEq];
                        if (e2.type != RowInfo.ROW_EQUAL)
                        {
                            break;
                        }

                        if (i == e2.nodeEq)
                        {
                            break;
                        }

                        elt.nodeEq = e2.nodeEq;
                    }
                }
                if (elt.type == RowInfo.ROW_CONST)
                {
                    elt.mapCol = -1;
                }
            }

            for (int i = 0; i != matrixSize; i++)
            {
                RowInfo elt = circuitRowInfo[i];
                if (elt.type == RowInfo.ROW_EQUAL)
                {
                    RowInfo e2 = circuitRowInfo[elt.nodeEq];
                    if (e2.type == RowInfo.ROW_CONST)
                    {
                        // if something is equal to a const, it's a const
                        elt.type   = e2.type;
                        elt.value  = e2.value;
                        elt.mapCol = -1;
                    }
                    else
                    {
                        elt.mapCol = e2.mapCol;
                    }
                }
            }

            // == Make the new, simplified matrix.
            int        newsize = nn;
            double[][] newmatx = new double[newsize][];
            for (int z = 0; z < newsize; z++)
            {
                newmatx[z] = new double[newsize];
            }

            double[] newrs = new double[newsize];
            int      ii    = 0;
            for (int i = 0; i != matrixSize; i++)
            {
                RowInfo rri = circuitRowInfo[i];
                if (rri.dropRow)
                {
                    rri.mapRow = -1;
                    continue;
                }
                newrs[ii]  = circuitRightSide[i];
                rri.mapRow = ii;
                // System.out.println("Row " + i + " maps to " + ii);
                for (int leadX = 0; leadX != matrixSize; leadX++)
                {
                    RowInfo ri = circuitRowInfo[leadX];
                    if (ri.type == RowInfo.ROW_CONST)
                    {
                        newrs[ii] -= ri.value * circuitMatrix[i][leadX];
                    }
                    else
                    {
                        newmatx[ii][ri.mapCol] += circuitMatrix[i][leadX];
                    }
                }
                ii++;
            }
            #endregion

            #region             //// Copy matrix to orig ////
            circuitMatrix    = newmatx;
            circuitRightSide = newrs;
            matrixSize       = circuitMatrixSize = newsize;

            // copy `rightSide` to `origRightSide`
            for (int i = 0; i != matrixSize; i++)
            {
                origRightSide[i] = circuitRightSide[i];
            }

            // copy `matrix` to `origMatrix`
            for (int i = 0; i != matrixSize; i++)
            {
                for (int leadX = 0; leadX != matrixSize; leadX++)
                {
                    origMatrix[i][leadX] = circuitMatrix[i][leadX];
                }
            }
            #endregion

            circuitNeedsMap = true;
            _analyze        = false;

            // If the matrix is linear, we can do the lu_factor
            // here instead of needing to do it every frame.
            if (!circuitNonLinear)
            {
                if (!lu_factor(circuitMatrix, circuitMatrixSize, circuitPermute))
                {
                    panic("Singular matrix!", null);
                }
            }
        }