void CalculateLoadFlowForSubGraph(Node source, List <KeyValuePair <long, LoadFlowResult> > result) { Dictionary <long, LoadFlowResult> lf = new Dictionary <long, LoadFlowResult>(); EnergySource es = source.IO as EnergySource; if (es == null) { return; } Complex u1 = GetVoltageFromEnergySource(es); if (u1.IsNaN()) { return; } Dictionary <long, Complex> currents = new Dictionary <long, Complex>(); for (int iteration = 0; iteration < maxIterations; ++iteration) { double maxVoltageRelativeDelta = 0; Stack <Triple <Node, int, List <Complex> > > stack = new Stack <Triple <Node, int, List <Complex> > >(); stack.Push(new Triple <Node, int, List <Complex> >(source, 0, new List <Complex>(source.AdjacentCount - 1))); HashSet <long> visited = new HashSet <long>(); while (stack.Count > 0) { Triple <Node, int, List <Complex> > triple = stack.Pop(); Node node = triple.First; int childrenPos = triple.Second; Func <Node, IEnumerable <Complex>, Dictionary <long, LoadFlowResult>, Complex> currentFunction = CalculateCurrentDefault; visited.Add(node.IO.GID); DMSType type = ModelCodeHelper.GetTypeFromGID(node.IO.GID); switch (type) { case DMSType.Recloser: continue; case DMSType.ConnectivityNode: { LoadFlowResult lfr; if (!lf.TryGetValue(node.IO.GID, out lfr)) { lfr = new LoadFlowResult(); lfr.Add(new LoadFlowResultItem(u1.X, LoadFlowResultType.UR)); lfr.Add(new LoadFlowResultItem(u1.Y, LoadFlowResultType.UI)); lf[node.IO.GID] = lfr; } } break; case DMSType.EnergyConsumer: { currentFunction = CalculateCurrentForEnergyConsumer; LoadFlowResult lfr; if (!lf.TryGetValue(node.IO.GID, out lfr)) { Complex s = GetPowerForEnergyConsumer(node.IO as EnergyConsumer); lfr = new LoadFlowResult(); lfr.Add(new LoadFlowResultItem(s.X, LoadFlowResultType.SR)); lfr.Add(new LoadFlowResultItem(s.Y, LoadFlowResultType.SI)); lf[node.IO.GID] = lfr; } } break; case DMSType.Breaker: case DMSType.Disconnector: { currentFunction = CalculateCurrentForSwitch; if (childrenPos == 0) { double maxDelta = CalculateVoltageForSwitch(node, lf, currents); if (maxDelta > maxVoltageRelativeDelta) { maxVoltageRelativeDelta = maxDelta; } } } break; case DMSType.DistributionGenerator: { currentFunction = CalculateCurrentForDistributionGenerator; } break; case DMSType.TransformerWinding: { currentFunction = CalculateCurrentForTransformerWinding; if (childrenPos == 0) { double maxDelta = CalculateVoltageForTransformerWinding(node, lf, currents); if (maxDelta > maxVoltageRelativeDelta) { maxVoltageRelativeDelta = maxDelta; } } } break; case DMSType.ACLineSegment: { currentFunction = CalculateCurrentForACLineSegment; if (childrenPos == 0) { double maxDelta = CalculateVoltageForACLineSegment(node, lf, currents); if (maxDelta > maxVoltageRelativeDelta) { maxVoltageRelativeDelta = maxDelta; } } } break; } Node childNode = null; for (int i = node.AdjacentOffset + childrenPos; i < node.AdjacentOffset + node.AdjacentCount; ++i) { Node adjacentNode = adjacency[i]; if (adjacentNode == null || visited.Contains(adjacentNode.IO.GID)) { continue; } childNode = adjacentNode; break; } if (childNode != null) { stack.Push(new Triple <Node, int, List <Complex> >(node, childrenPos + 1, triple.Third)); stack.Push(new Triple <Node, int, List <Complex> >(childNode, 0, new List <Complex>(childNode.AdjacentCount - 1))); continue; } if (stack.Count > 0) { Complex current = currentFunction(node, triple.Third, lf); stack.Peek().Third.Add(current); currents[node.IO.GID] = current; } } if (maxVoltageRelativeDelta < voltageRelativeDelta) { break; } } result.AddRange(lf); }