Exemplo n.º 1
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);
        }
Exemplo n.º 2
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);
        }