Esempio n. 1
0
        /// <summary>
        ///   Verifies that current subcircuit with given nodes as terminals represents valid SPICE circuit. That is: there
        ///   are no floating nodes and there is a DC path between any two nodes not going through ground.
        /// </summary>
        private CircuitTopologyException ValidateCircuit_Internal()
        {
            if (validatedCircuit)
            {
                return(circuitException);
            }
            // every node must be transitively connected to 0 (ground)
            var neighbourghs = CircuitBuilderHelpers.GetNeighbourghs(NodeCount, Devices);

            var visited = CircuitBuilderHelpers.GetIdsInSameComponent(0, neighbourghs);

            // some nodes are not reachable from ground
            if (visited.Count != NodeCount)
            {
                return(new NoDcPathToGroundException(Enumerable.Range(0, NodeCount).Except(visited)));
            }

            var branches = devices.SelectMany(e => e.GetBranchMetadata()).ToArray();

            var cycle = GetVoltageCicrle(branches);

            if (cycle != null)
            {
                return(new VoltageBranchCycleException(cycle));
            }

            var cutset = GetCurrentCutset(branches);

            return(cutset != null ? new CurrentBranchCutsetException(cutset) : null);
        }
Esempio n. 2
0
        /// <summary>
        ///   Verifies that current subcircuit with given nodes as terminals represents valid SPICE subcircuit. That is:
        ///   there are no floating nodes and there is a DC path between any two nodes not going through ground.
        /// </summary>
        /// <param name="terminals"></param>
        private CircuitTopologyException ValidateSubcircuit_Internal(int[] terminals)
        {
            // ground node must not be external terminal
            if (terminals == null)
            {
                throw new ArgumentNullException(nameof(terminals));
            }
            if (terminals.Length == 0)
            {
                throw new ArgumentException("Subcircuit must have at least one terminal node.");
            }
            if (terminals.Any(n => n <= 0))
            {
                throw new ArgumentOutOfRangeException("Terminals of Subcircuit must have positive ids.");
            }
            if (terminals.Any(n => n >= NodeCount))
            {
                throw new ArgumentOutOfRangeException("There is no node with given id.");
            }

            if (validatedCircuit)
            {
                return(circuitException);
            }

            var neighbourghs = CircuitBuilderHelpers.GetNeighbourghs(NodeCount, Devices);

            neighbourghs[0].Clear();             // ignore connections to the ground node

            var components = CircuitBuilderHelpers.GetComponents(neighbourghs);

            components.RemoveAll(c => c[0] == 0);  // remove ground component

            if (components.Count != 1)             // incorrectly connected
            {
                return(new NotConnectedSubcircuitException(components));
            }

            var branches = devices.SelectMany(e => e.GetBranchMetadata()).ToArray();

            var cycle = GetVoltageCicrle(branches);

            return(cycle != null ? new VoltageBranchCycleException(cycle) : null);
        }
Esempio n. 3
0
        private IEnumerable <ICircuitDefinitionDevice> GetCurrentCutset(CircuitBranchMetadata[] branches)
        {
            var currentBranches = branches.Where(b => b.BranchType == BranchType.CurrentDefined).ToArray();

            var neighbourghs = CircuitBuilderHelpers.GetNeighbourghs(NodeCount, devices);

            // remove current defined branches from the graph
            var nonCurrentElems = new HashSet <ICircuitDefinitionDevice>(devices);

            foreach (var e in currentBranches.Select(b => b.Device))
            {
                nonCurrentElems.Remove(e);
            }
            foreach (var branch in currentBranches)
            {
                if (nonCurrentElems.Any(e =>
                                        e.ConnectedNodes.Contains(branch.N1) && e.ConnectedNodes.Contains(branch.N2)))
                {
                    continue;                     // some node bridges the same connection as this branch
                }
                neighbourghs[branch.N1].Remove(branch.N2);
                neighbourghs[branch.N2].Remove(branch.N1);
            }

            var components = CircuitBuilderHelpers.GetComponents(neighbourghs);

            // get indexes of components for faster lookup
            var componentIndexes = new int[NodeCount];

            for (var i = 0; i < components.Count; i++)
            {
                foreach (var n in components[i])
                {
                    componentIndexes[n] = i;
                }
            }

            // throw away branches that do not connect nodes from different components
            var result = currentBranches
                         .Where(b => componentIndexes[b.N1] != componentIndexes[b.N2]).Select(b => b.Device).ToArray();

            return(result.Length > 0 ? result : null);
        }