bool IsSwitchWithoutSCADA(long switchGID) { if (!ModelCodeHelper.ModelCodeClassIsSubClassOf(typeToModelCode[ModelCodeHelper.GetTypeFromGID(switchGID)], ModelCode.SWITCH)) { return(false); } Switch s = Get(switchGID) as Switch; if (s == null) { return(false); } for (int i = 0; i < s.Measurements.Count; ++i) { Measurement m = Get(s.Measurements[i]) as Measurement; if (m == null) { continue; } if (m.MeasurementType == MeasurementType.SwitchState) { return(false); } } return(true); }
bool TryGetEntity(long gid, out IdentifiedObject io) { Container container; io = null; return(containers.TryGetValue(ModelCodeHelper.GetTypeFromGID(gid), out container) && container.Get(gid, out io)); }
IdentifiedObject Get(long gid) { IdentifiedObject io; Dictionary <long, IdentifiedObject> container; return(containers.TryGetValue(ModelCodeHelper.GetTypeFromGID(gid), out container) && container.TryGetValue(gid, out io) ? io : null); }
ElementView InitView() { DMSType type = ModelCodeHelper.GetTypeFromGID(GID); ModelCode mc = dmsTypeToModelCodeMap[type]; ElementView v; if (ModelCodeHelper.ModelCodeClassIsSubClassOf(mc, ModelCode.SWITCH)) { v = new SwitchView(GID, PubSub); } else if (ModelCodeHelper.ModelCodeClassIsSubClassOf(mc, ModelCode.POWERSYSTEMRESOURCE)) { v = new PowerSystemResourceView(GID, PubSub); } else if (type == DMSType.ConnectivityNode) { v = new ConnectivityNodeView(GID, PubSub); } else if (type == DMSType.Discrete || type == DMSType.Analog) { v = new MeasurementView(GID, PubSub); } else { v = new IdentifiedObjectView(GID, PubSub); } return(v); }
double CalculateVoltageForACLineSegment(Node node, Dictionary <long, LoadFlowResult> lf, Dictionary <long, Complex> currents) { Complex current; if (!currents.TryGetValue(node.IO.GID, out current)) { return(double.MaxValue); } ACLineSegment segment = node.IO as ACLineSegment; List <Node> nodes = new List <Node>(2); for (int i = node.AdjacentOffset; i < node.AdjacentOffset + node.AdjacentCount; ++i) { Node n = adjacency[i]; if (!nodes.Contains(n) && ModelCodeHelper.GetTypeFromGID(n.IO.GID) == DMSType.ConnectivityNode) { nodes.Add(n); } } if (nodes.Count != 2) { return(0); } LoadFlowResult lfr1; if (!lf.TryGetValue(nodes[0].IO.GID, out lfr1)) { return(0); } Complex u1 = new Complex(lfr1.Get(LoadFlowResultType.UR), lfr1.Get(LoadFlowResultType.UI)); Complex u2 = u1.Subtract(new Complex(segment.PerLengthPhaseResistance * segment.Length, segment.PerLengthPhaseReactance * segment.Length).Multiply(current)); LoadFlowResult lfr2; double relDelta = double.MaxValue; if (!lf.TryGetValue(nodes[1].IO.GID, out lfr2)) { lfr2 = new LoadFlowResult(); lf[nodes[1].IO.GID] = lfr2; } else { relDelta = GetVoltageRelativeDifference(new Complex(lfr2.Get(LoadFlowResultType.UR), lfr2.Get(LoadFlowResultType.UI)), u2); } lfr2.Remove(LoadFlowResultType.UR); lfr2.Remove(LoadFlowResultType.UI); lfr2.Add(new LoadFlowResultItem(u2.X, LoadFlowResultType.UR)); lfr2.Add(new LoadFlowResultItem(u2.Y, LoadFlowResultType.UI)); return(relDelta); }
public bool PersistDelta(List <IdentifiedObject> inserted, List <IdentifiedObject> updatedNew, List <IdentifiedObject> deleted, Dictionary <DMSType, int> newCounters) { try { using (DBContext context = new DBContext()) { for (int i = 0; i < inserted.Count; ++i) { IdentifiedObject io = inserted[i]; IEFTable table = tables[(int)ModelCodeHelper.GetTypeFromGID(io.GID)]; object entity = io.ToDBEntity(); table.Insert(context, entity); } for (int i = 0; i < updatedNew.Count; ++i) { IdentifiedObject io = updatedNew[i]; IEFTable table = tables[(int)ModelCodeHelper.GetTypeFromGID(io.GID)]; object entity = io.ToDBEntity(); table.Update(context, entity); } for (int i = 0; i < deleted.Count; ++i) { IdentifiedObject io = deleted[i]; IEFTable table = tables[(int)ModelCodeHelper.GetTypeFromGID(io.GID)]; object entity = io.ToDBEntity(); table.Delete(context, entity); } foreach (KeyValuePair <DMSType, int> pair in newCounters) { IEFTable table = tables[0]; ModelCounterDBModel oldCounter = (ModelCounterDBModel)table.Get(context, pair.Key); if (oldCounter != null) { oldCounter.Counter = pair.Value; } else { table.Insert(context, new ModelCounterDBModel() { Type = pair.Key, Counter = pair.Value }); } } context.SaveChanges(); } } catch (Exception e) { return(false); } return(true); }
Complex CalculateCurrentForACLineSegment(Node node, IEnumerable <Complex> childCurrents, Dictionary <long, LoadFlowResult> lf) { Complex result = CalculateCurrentDefault(node, childCurrents, lf); LoadFlowResult lfr; if (!lf.TryGetValue(node.IO.GID, out lfr)) { lfr = new LoadFlowResult(); lf[node.IO.GID] = lfr; } lfr.Remove(LoadFlowResultType.IR); lfr.Remove(LoadFlowResultType.II); lfr.Add(new LoadFlowResultItem(result.X, LoadFlowResultType.IR)); lfr.Add(new LoadFlowResultItem(result.Y, LoadFlowResultType.II)); List <Node> nodes = new List <Node>(2); for (int i = node.AdjacentOffset; i < node.AdjacentOffset + node.AdjacentCount; ++i) { Node n = adjacency[i]; if (!nodes.Contains(n) && ModelCodeHelper.GetTypeFromGID(n.IO.GID) == DMSType.ConnectivityNode) { nodes.Add(n); } } if (nodes.Count != 2) { return(result); } LoadFlowResult lfr1; LoadFlowResult lfr2; if (!lf.TryGetValue(nodes[0].IO.GID, out lfr1) || !lf.TryGetValue(nodes[1].IO.GID, out lfr2)) { return(result); } ACLineSegment segment = node.IO as ACLineSegment; Complex u1 = new Complex(lfr1.Get(LoadFlowResultType.UR), lfr1.Get(LoadFlowResultType.UI)); Complex u2 = new Complex(lfr2.Get(LoadFlowResultType.UR), lfr2.Get(LoadFlowResultType.UI)); Complex s = u1.Subtract(u2).Multiply(new Complex(result.X, -result.Y)); lfr.Remove(LoadFlowResultType.SR); lfr.Remove(LoadFlowResultType.SI); lfr.Add(new LoadFlowResultItem(s.X, LoadFlowResultType.SR)); lfr.Add(new LoadFlowResultItem(s.Y, LoadFlowResultType.SI)); return(result); }
double CalculateVoltageForSwitch(Node node, Dictionary <long, LoadFlowResult> lf, Dictionary <long, Complex> currents) { if (!currents.ContainsKey(node.IO.GID)) { return(double.MaxValue); } List <Node> nodes = new List <Node>(2); for (int i = node.AdjacentOffset; i < node.AdjacentOffset + node.AdjacentCount; ++i) { Node n = adjacency[i]; if (!nodes.Contains(n) && ModelCodeHelper.GetTypeFromGID(n.IO.GID) == DMSType.ConnectivityNode) { nodes.Add(n); } } if (nodes.Count != 2) { return(0); } LoadFlowResult lfr1; if (!lf.TryGetValue(nodes[0].IO.GID, out lfr1)) { return(0); } Complex u1 = new Complex(lfr1.Get(LoadFlowResultType.UR), lfr1.Get(LoadFlowResultType.UI)); Complex u2 = GetSwitchState(node.IO as Switch) ? new Complex(0, 0) : u1; LoadFlowResult lfr2; double relDelta = double.MaxValue; if (!lf.TryGetValue(nodes[1].IO.GID, out lfr2)) { lfr2 = new LoadFlowResult(); lf[nodes[1].IO.GID] = lfr2; } else { relDelta = GetVoltageRelativeDifference(new Complex(lfr2.Get(LoadFlowResultType.UR), lfr2.Get(LoadFlowResultType.UI)), u2); } lfr2.Remove(LoadFlowResultType.UR); lfr2.Remove(LoadFlowResultType.UI); lfr2.Add(new LoadFlowResultItem(u2.X, LoadFlowResultType.UR)); lfr2.Add(new LoadFlowResultItem(u2.Y, LoadFlowResultType.UI)); return(relDelta); }
public ElementWindow(long gid, PubSubClient pubSub) { GID = gid; this.pubSub = pubSub; pubSub.Subscribe(this); InitializeComponent(); Title = ModelCodeHelper.GetTypeFromGID(gid) + " " + gid; view = new MaybeElementView(gid, pubSub); panel.Children.Add(view.Element); }
void ExecuteCommand(string text) { Measurement m = measurementGetter(); if (m == null) { return; } DMSType type = ModelCodeHelper.GetTypeFromGID(m.GID); if (type == DMSType.Analog) { float value; if (!float.TryParse(text, out value)) { return; } Client <ISCADAServiceContract> client = new Client <ISCADAServiceContract>("endpointSCADA"); client.Connect(); client.Call <bool>(scada => { scada.CommandAnalog(new List <long>(1) { m.GID }, new List <float>(1) { value }); return(true); }, out _); client.Disconnect(); } else if (type == DMSType.Discrete) { int value; if (!int.TryParse(text, out value)) { return; } Client <ISCADAServiceContract> client = new Client <ISCADAServiceContract>("endpointSCADA"); client.Connect(); client.Call <bool>(scada => { scada.CommandDiscrete(new List <long>(1) { m.GID }, new List <int>(1) { value }); return(true); }, out _); client.Disconnect(); } }
IdentifiedObject InsertEntity(ResourceDescription rd) { if (rd == null) { return(null); } DMSType type = ModelCodeHelper.GetTypeFromGID(rd.Id); Container container; if (!containers.TryGetValue(type, out container) || container.Contains(rd.Id)) { return(null); } IdentifiedObject io = IdentifiedObject.Create(rd); if (io == null) { return(null); } foreach (Property prop in rd.Properties.Values) { if (prop.Type == PropertyType.Reference) { long targetGID = ((ReferenceProperty)prop).Value; if (targetGID == 0) { continue; } IdentifiedObject target; Container targetContainer; if (!TryGetEntity(targetGID, out target, out targetContainer)) { return(null); } target = target.Clone(); target.AddTargetReference(prop.Id, io.GID); targetContainer.Set(target); } } containers[type].Add(io); return(io); }
Brush GetNodeColor(IdentifiedObject io) { ModelCode mc; if (!dmsTypeToModelCodeMap.TryGetValue(ModelCodeHelper.GetTypeFromGID(io.GID), out mc)) { return(Brushes.SlateGray); } if (!ModelCodeHelper.ModelCodeClassIsSubClassOf(mc, ModelCode.SWITCH)) { return(GetColor(topology.GetNodeEnergization(io.GID))); } Switch s = (Switch)io; foreach (long measGID in s.Measurements) { Measurement m = (Measurement)networkModel.Get(measGID); if (m == null) { continue; } if (m.MeasurementType == MeasurementType.SwitchState) { int value; if (!measurements.GetDiscreteInput(m.GID, out value)) { continue; } if (value == 0) { return(Brushes.Green); //closed } else { return(Brushes.Blue); //open } } } return(Brushes.SlateGray); }
public GraphicsModel GetGraphicsModel(IdentifiedObject io) { DMSType type = ModelCodeHelper.GetTypeFromGID(io.GID); object model; if (!typeToGE.TryGetValue(type, out model)) { return(null); } if (type == DMSType.EnergyConsumer) { model = ((Dictionary <ConsumerClass, GraphicsModel>)model)[((EnergyConsumer)io).ConsumerClass]; } return((GraphicsModel)model); }
void FilterGIDs(List <long> gids) { int wi = 0; for (int ri = 0; ri < gids.Count; ++ri) { long gid = gids[ri]; DMSType type = ModelCodeHelper.GetTypeFromGID(gid); if (type == DMSType.Analog || type == DMSType.Discrete) { gids[wi] = gid; ++wi; } } gids.RemoveRange(wi, gids.Count - wi); gids.TrimExcess(); }
public List <ResourceDescription> Next(int n, NetworkModel model) { if (n < 0) { return(null); } int left = ResourcesLeft(); int count = n < left ? n : left; List <ResourceDescription> result = new List <ResourceDescription>(count); int i; for (i = position; i < position + count; ++i) { long gid = gids[i]; result.Add(model.GetValues(gid, properties[ModelCodeHelper.GetTypeFromGID(gid)])); } position = i; return(result); }
void UpdateGIDsForHoldingRegister(ushort address, Dictionary <long, float> updatedAnalogInputs, Dictionary <long, float> updatedAnalogOutputs, Dictionary <long, int> updatedDiscreteInputs, Dictionary <long, int> updatedDiscreteOutputs) { address -= (ushort)(address % 2); ushort high, low; if (!holdingRegisters.TryGetValue(address, out high) || !holdingRegisters.TryGetValue((ushort)(address + 1), out low)) { return; } float analogValue; int discreteValue; GetValues(high, low, out analogValue, out discreteValue); int baseAddress = address / 2; List <long> gids; if (!byAddress.TryGetValue(baseAddress, out gids)) { return; } foreach (long gid in gids) { DMSType type = ModelCodeHelper.GetTypeFromGID(gid); if (type == DMSType.Analog) { Analog a = model.GetAnalog(gid); if (a == null) { continue; } switch (a.Direction) { case SignalDirection.Write: case SignalDirection.ReadWrite: updatedAnalogOutputs[gid] = analogValue; break; case SignalDirection.Read: default: continue; } } else if (type == DMSType.Discrete) { Discrete d = model.GetDiscrete(gid); if (d == null) { continue; } switch (d.Direction) { case SignalDirection.Write: case SignalDirection.ReadWrite: updatedDiscreteOutputs[gid] = discreteValue; break; case SignalDirection.Read: default: continue; } } } }
public void UpdateModel() { SCADAModel model = SCADAModel.Instance; if (model == null) { return; } Dictionary <int, List <long> > byAddress = new Dictionary <int, List <long> >(); List <ushort> inputAddresses = new List <ushort>(); foreach (Analog a in model.GetAllAnalogs()) { if (a == null || !IsValidAddress(a.BaseAddress)) { continue; } List <long> gids; if (byAddress.TryGetValue(a.BaseAddress, out gids)) { gids.Add(a.GID); } else { byAddress[a.BaseAddress] = new List <long>(1) { a.GID }; } if (a.Direction == SignalDirection.Write) { continue; } ushort address = GetAddress(a.BaseAddress); inputAddresses.Add(address); } foreach (Discrete d in model.GetAllDiscretes()) { if (d == null || !IsValidAddress(d.BaseAddress)) { continue; } List <long> gids; if (byAddress.TryGetValue(d.BaseAddress, out gids)) { gids.Add(d.GID); } else { byAddress[d.BaseAddress] = new List <long>(1) { d.GID }; } if (d.Direction == SignalDirection.Write) { continue; } ushort address = GetAddress(d.BaseAddress); inputAddresses.Add(address); } List <IModbusFunction> acquisitionFunctions = new List <IModbusFunction>(); if (inputAddresses.Count <= 0) { return; } inputAddresses.Sort(); int runStart = inputAddresses[0]; int runCount = 0; for (int i = 0; i < inputAddresses.Count; ++i) { int address = inputAddresses[i]; if (runCount < 124 && address == runStart + runCount) { runCount += 2; } else if (runCount > 0) { acquisitionFunctions.Add(new ReadInputRegistersFunction(new ModbusReadCommandParameters(6, (byte)EModbusFunctionCode.READ_INPUT_REGISTERS, (ushort)runStart, (ushort)runCount, 0, 1))); runCount = 2; runStart = address; } } if (runCount > 0) { acquisitionFunctions.Add(new ReadInputRegistersFunction(new ModbusReadCommandParameters(6, (byte)EModbusFunctionCode.READ_INPUT_REGISTERS, (ushort)runStart, (ushort)runCount, 0, 1))); } modelLock.EnterWriteLock(); { this.model = model; this.acquisitionFunctions = acquisitionFunctions; this.byAddress = byAddress; } modelLock.ExitWriteLock(); List <KeyValuePair <long, float> > analogInputs = new List <KeyValuePair <long, float> >(); List <KeyValuePair <long, float> > analogOutputs = new List <KeyValuePair <long, float> >(); List <KeyValuePair <long, int> > discreteInputs = new List <KeyValuePair <long, int> >(); List <KeyValuePair <long, int> > discreteOutputs = new List <KeyValuePair <long, int> >(); foreach (KeyValuePair <int, List <long> > addressEntry in byAddress) { ushort address = GetAddress(addressEntry.Key); ushort high, low; float analogIn; int discreteIn; float analogOut; int discreteOut; inputRegisters.TryGetValue(address, out high); inputRegisters.TryGetValue((ushort)(address + 1), out low); GetValues(high, low, out analogIn, out discreteIn); holdingRegisters.TryGetValue(address, out high); holdingRegisters.TryGetValue((ushort)(address + 1), out low); GetValues(high, low, out analogOut, out discreteOut); for (int i = 0; i < addressEntry.Value.Count; ++i) { long gid = addressEntry.Value[i]; switch (ModelCodeHelper.GetTypeFromGID(gid)) { case DMSType.Analog: Analog a = model.GetAnalog(gid); if (a == null) { continue; } switch (a.Direction) { case SignalDirection.Read: analogInputs.Add(new KeyValuePair <long, float>(gid, analogIn)); break; case SignalDirection.Write: analogOutputs.Add(new KeyValuePair <long, float>(gid, analogOut)); break; case SignalDirection.ReadWrite: analogInputs.Add(new KeyValuePair <long, float>(gid, analogIn)); analogOutputs.Add(new KeyValuePair <long, float>(gid, analogOut)); break; default: continue; } break; case DMSType.Discrete: Discrete d = model.GetDiscrete(gid); if (d == null) { continue; } switch (d.Direction) { case SignalDirection.Read: discreteInputs.Add(new KeyValuePair <long, int>(gid, discreteIn)); break; case SignalDirection.Write: discreteOutputs.Add(new KeyValuePair <long, int>(gid, discreteOut)); break; case SignalDirection.ReadWrite: discreteInputs.Add(new KeyValuePair <long, int>(gid, discreteIn)); discreteOutputs.Add(new KeyValuePair <long, int>(gid, discreteOut)); break; default: continue; } break; default: continue; } } } PublishMeasurementValues(analogInputs, analogOutputs, discreteInputs, discreteOutputs); }
Node BuildSubGraph(EnergySource source) { Dictionary <long, IdentifiedObject> terminals = containers[DMSType.Terminal]; Dictionary <long, IdentifiedObject> cNodes = containers[DMSType.ConnectivityNode]; Node sourceNode = new Node(source, 0, 0); Queue <Tuple <Node, Node> > queue = new Queue <Tuple <Node, Node> >(); queue.Enqueue(new Tuple <Node, Node>(null, sourceNode)); Dictionary <long, Node> visited = new Dictionary <long, Node>(); visited.Add(source.GID, sourceNode); while (queue.Count > 0) { Tuple <Node, Node> tuple = queue.Dequeue(); Node node = tuple.Item2; node.AdjacentOffset = adjacency.Count; adjacency.Add(tuple.Item1); ++node.AdjacentCount; DMSType type = ModelCodeHelper.GetTypeFromGID(node.IO.GID); if (type == DMSType.ConnectivityNode) { foreach (long tGID in ((ConnectivityNode)node.IO).Terminals) { IdentifiedObject terminal; if (!terminals.TryGetValue(tGID, out terminal)) { continue; } long ceGID = ((Terminal)terminal).ConductingEquipment; if (ceGID == 0) { continue; } Node adjacentNode; if (!visited.TryGetValue(ceGID, out adjacentNode)) { DMSType ceType = ModelCodeHelper.GetTypeFromGID(ceGID); IdentifiedObject ce; if (!containers[ceType].TryGetValue(ceGID, out ce)) { continue; } adjacentNode = new Node(ce, 0, 0); queue.Enqueue(new Tuple <Node, Node>(node, adjacentNode)); visited.Add(ceGID, adjacentNode); } adjacency.Add(adjacentNode); ++node.AdjacentCount; } } else if (type == DMSType.TransformerWinding) { TransformerWinding tw = node.IO as TransformerWinding; PowerTransformer pt = Get(tw.PowerTransformer) as PowerTransformer; if (pt == null) { continue; } foreach (long twGID in pt.TransformerWindings) { if (twGID == tw.GID) { continue; } Node adjacentNode; if (!visited.TryGetValue(twGID, out adjacentNode)) { TransformerWinding twAdjacent = Get(twGID) as TransformerWinding; if (twAdjacent == null) { continue; } adjacentNode = new Node(twAdjacent, 0, 0); queue.Enqueue(new Tuple <Node, Node>(node, adjacentNode)); visited.Add(twGID, adjacentNode); } adjacency.Add(adjacentNode); ++node.AdjacentCount; break; } foreach (long tGID in tw.Terminals) { IdentifiedObject terminal; if (!terminals.TryGetValue(tGID, out terminal)) { continue; } long cNodeGID = ((Terminal)terminal).ConnectivityNode; if (cNodeGID == 0) { continue; } Node adjacentNode; if (!visited.TryGetValue(cNodeGID, out adjacentNode)) { IdentifiedObject cNode; if (!cNodes.TryGetValue(cNodeGID, out cNode)) { continue; } adjacentNode = new Node(cNode, 0, 0); queue.Enqueue(new Tuple <Node, Node>(node, adjacentNode)); visited.Add(cNodeGID, adjacentNode); } adjacency.Add(adjacentNode); ++node.AdjacentCount; } } else { foreach (long tGID in ((ConductingEquipment)node.IO).Terminals) { IdentifiedObject terminal; if (!terminals.TryGetValue(tGID, out terminal)) { continue; } long cNodeGID = ((Terminal)terminal).ConnectivityNode; if (cNodeGID == 0) { continue; } Node adjacentNode; if (!visited.TryGetValue(cNodeGID, out adjacentNode)) { IdentifiedObject cNode; if (!cNodes.TryGetValue(cNodeGID, out cNode)) { continue; } adjacentNode = new Node(cNode, 0, 0); queue.Enqueue(new Tuple <Node, Node>(node, adjacentNode)); visited.Add(cNodeGID, adjacentNode); } adjacency.Add(adjacentNode); ++node.AdjacentCount; } } } return(sourceNode); }
public override void Update() { Grid grid = (Grid)((Border)((StackPanel)panel.Children[1]).Children[0]).Child; if (grid.Children.Count > 3) { grid.Children.RemoveRange(3, grid.Children.Count - 3); } if (grid.RowDefinitions.Count > 1) { grid.RowDefinitions.RemoveRange(1, grid.RowDefinitions.Count - 1); } IdentifiedObject io = ioGetter(); List <ModelCode> props; if (io == null || !typeToProps.TryGetValue(ModelCodeHelper.GetTypeFromGID(io.GID), out props)) { Grid.SetColumnSpan(AddToGrid(grid, new TextBlock() { Text = "No properties." }, 1, 0), int.MaxValue); Grid.SetRowSpan(grid.Children[2], 1); return; } List <KeyValuePair <string, UIElement> > rows = new List <KeyValuePair <string, UIElement> >(); foreach (ModelCode prop in props) { Property p = io.GetProperty(prop); if (p == null) { continue; } UIElement element; switch (p.Type) { case PropertyType.Bool: element = new TextBlock() { Text = ((BoolProperty)p).Value.ToString(), TextAlignment = TextAlignment.Right }; break; case PropertyType.Enum: element = new TextBlock() { Text = ((EnumProperty)p).Value.ToString(), TextAlignment = TextAlignment.Right }; break; case PropertyType.Float: element = new TextBlock() { Text = ((FloatProperty)p).Value.ToString(), TextAlignment = TextAlignment.Right }; break; case PropertyType.Int32: element = new TextBlock() { Text = ((Int32Property)p).Value.ToString(), TextAlignment = TextAlignment.Right }; break; case PropertyType.Int64: element = new TextBlock() { Text = ((Int64Property)p).Value.ToString(), TextAlignment = TextAlignment.Right }; break; case PropertyType.Reference: { long value = ((ReferenceProperty)p).Value; if (value != 0) { TextBlock tb = CreateHyperlink(value.ToString(), () => new ElementWindow(value, pubSub) { Owner = Application.Current.MainWindow }.Show()); tb.TextAlignment = TextAlignment.Right; element = tb; } else { element = new TextBlock() { Text = value.ToString(), TextAlignment = TextAlignment.Right }; } } break; case PropertyType.String: element = new TextBlock() { Text = ((StringProperty)p).Value.ToString(), TextAlignment = TextAlignment.Right }; break; case PropertyType.ReferenceVector: { List <long> values = ((ReferencesProperty)p).Value; StackPanel sp = new StackPanel(); for (int j = 0; j < values.Count; ++j) { long value = values[j]; TextBlock tb = CreateHyperlink(value.ToString(), () => new ElementWindow(value, pubSub) { Owner = Application.Current.MainWindow }.Show()); tb.TextAlignment = TextAlignment.Right; sp.Children.Add(tb); } element = new ScrollViewer() { MaxHeight = 100, Content = sp, VerticalScrollBarVisibility = ScrollBarVisibility.Auto }; } break; default: continue; } rows.Add(new KeyValuePair <string, UIElement>(prop.ToString(), element)); } rows.Sort((x, y) => { return(x.Key.CompareTo(y.Key)); }); int i; for (i = 0; i < rows.Count; ++i) { var row = rows[i]; grid.RowDefinitions.Add(new RowDefinition()); AddToGrid(grid, new TextBlock() { Text = row.Key }, i + 1, 0); AddToGrid(grid, row.Value, i + 1, 2); } if (i == 0) { Grid.SetColumnSpan(AddToGrid(grid, new TextBlock() { Text = "No properties." }, 1, 0), int.MaxValue); Grid.SetRowSpan(grid.Children[2], 1); } else { Grid.SetRowSpan(grid.Children[2], int.MaxValue); } initialized = true; }
void Layout() { if (!networkModelChanged || networkModel == null) { return; } networkModelChanged = false; Tuple <List <Node>, List <RecloserNode> > model = networkModel.GetTreesAndReclosers(); Dictionary <Node, NodeLayout> recloserConNodes = new Dictionary <Node, NodeLayout>(model.Item2.Count * 2); foreach (RecloserNode rn in model.Item2) { recloserConNodes[rn.node1] = null; recloserConNodes[rn.node2] = null; } NodeLayout root = new NodeLayout(null, null); foreach (Node tree in model.Item1) { NodeLayout treeRoot = new NodeLayout(root, tree); NodeLayout node = treeRoot; uint y = 0; do { node.Y = y; if (recloserConNodes.ContainsKey(node.Node)) { recloserConNodes[node.Node] = node; } if (node.Children.Count < node.Node.children.Count) { node = new NodeLayout(node, node.Node.children[node.Children.Count]); ++y; continue; } node.Parent.Children.Add(node); node = node.Parent; --y; }while(node != root); } List <RecloserLayout> reclosers = new List <RecloserLayout>(model.Item2.Count); List <RecloserState> recloserStates = new List <RecloserState>(model.Item2.Count); foreach (RecloserNode rn in model.Item2) { RecloserLayout r = new RecloserLayout(rn, recloserConNodes[rn.node1], recloserConNodes[rn.node2]); reclosers.Add(r); recloserStates.Add(new RecloserState(r)); } recloserStates.Sort(); { NodeLayout node = root; Stack <int> stack = new Stack <int>(); stack.Push(0); uint x = 0; do { int i = stack.Pop(); if (i == 0) { ReorderChildren(node, recloserStates); } if (i < node.Children.Count) { node = node.Children[i]; stack.Push(i + 1); stack.Push(0); continue; } if (node.Children.Count > 0) { foreach (NodeLayout child in node.Children) { node.X += child.X; } node.X /= (uint)node.Children.Count; } else { node.X = x += (node.IO != null && ModelCodeHelper.GetTypeFromGID(node.IO.GID) == DMSType.EnergyConsumer) ? 2 : 1; } node = node.Parent; }while(node != null); } this.root = root; this.reclosers = reclosers; topologyChanged = true; }
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); }
void RedrawLoadFlow() { if (!loadFlowChanged || topology == null) { return; } loadFlowChanged = false; List <GraphicsText> loadFlows = new List <GraphicsText>(); for (int i = 0; i < elements.Count; ++i) { GraphicsElement element = elements[i]; if (element.IO == null) { continue; } LoadFlowResult lfResult = topology.GetLoadFlow(element.IO.GID); if (lfResult == null) { continue; } switch (ModelCodeHelper.GetTypeFromGID(element.IO.GID)) { case DMSType.ConnectivityNode: { double ur = lfResult.Get(LoadFlowResultType.UR); double ui = lfResult.Get(LoadFlowResultType.UI); if (double.IsNaN(ur) || double.IsNaN(ui)) { break; } GraphicsText gtu = new GraphicsText(element.X + loadFlowXOffset, 0, GetLoadFlowItemText(ur, ui, "V"), Brushes.Black, Brushes.Transparent, element, loadFlowFontSize); gtu.Y = element.Y - gtu.CalculateSize().Height / 2; loadFlows.Add(gtu); } break; case DMSType.ACLineSegment: { double ir = lfResult.Get(LoadFlowResultType.IR); double ii = lfResult.Get(LoadFlowResultType.II); double sr = lfResult.Get(LoadFlowResultType.SR); double si = lfResult.Get(LoadFlowResultType.SI); if (double.IsNaN(ir) || double.IsNaN(ii) || double.IsNaN(sr) || double.IsNaN(si)) { break; } bool abnormalCurrent = ComplexLength(ir, ii) > ((ACLineSegment)element.IO).RatedCurrent; GraphicsText gti = new GraphicsText(element.X + loadFlowXOffset, 0, GetLoadFlowItemText(ir, ii, "A"), abnormalCurrent ? Brushes.White : Brushes.Black, abnormalCurrent ? Brushes.DarkRed : Brushes.Transparent, element, loadFlowFontSize); GraphicsText gts = new GraphicsText(element.X + loadFlowXOffset, 0, GetLoadFlowItemText(sr, si, "VA"), Brushes.Black, Brushes.Transparent, element, loadFlowFontSize); Size gtiSize = gti.CalculateSize(); Size gtsSize = gts.CalculateSize(); gti.Y = element.Y - (gtiSize.Height + gtsSize.Height) / 2; gts.Y = gti.Y + gtiSize.Height; loadFlows.Add(gti); loadFlows.Add(gts); } break; case DMSType.EnergyConsumer: { double sr = lfResult.Get(LoadFlowResultType.SR); double si = lfResult.Get(LoadFlowResultType.SI); if (double.IsNaN(sr) || double.IsNaN(si)) { break; } GraphicsText gts = new GraphicsText(0, element.Y + loadFlowYOffset, GetLoadFlowItemText(sr, si, "VA"), Brushes.Black, Brushes.Transparent, element, loadFlowFontSize); gts.X = element.X - gts.CalculateSize().Width / 2; loadFlows.Add(gts); } break; } } this.loadFlows = loadFlows; }
public List <Tuple <long, List <Tuple <long, long> >, List <Tuple <long, long> > > > CalculateLineEnergization() { List <Tuple <long, List <Tuple <long, long> >, List <Tuple <long, long> > > > sourcesEnergization = new List <Tuple <long, List <Tuple <long, long> >, List <Tuple <long, long> > > >(subGraphs.Count); for (int i = 0; i < subGraphs.Count; ++i) { Stack <Tuple <Node, EEnergization> > stack = new Stack <Tuple <Node, EEnergization> >(); stack.Push(new Tuple <Node, EEnergization>(subGraphs[i], EEnergization.Energized)); HashSet <Tuple <long, long> > visitedEnergized = new HashSet <Tuple <long, long> >(); HashSet <Tuple <long, long> > visitedUnknown = new HashSet <Tuple <long, long> >(); while (stack.Count > 0) { Tuple <Node, EEnergization> node = stack.Pop(); EEnergization energization = node.Item2; long gid = node.Item1.IO.GID; if (energization != EEnergization.NotEnergized && ModelCodeHelper.ModelCodeClassIsSubClassOf(dmsTypeToModelCodeMap[ModelCodeHelper.GetTypeFromGID(gid)], ModelCode.SWITCH) && GetSwitchState((Switch)node.Item1.IO)) { energization = EEnergization.NotEnergized; } if (energization == EEnergization.NotEnergized) { continue; } if (energization == EEnergization.Energized) { for (int j = node.Item1.AdjacentOffset; j < node.Item1.AdjacentOffset + node.Item1.AdjacentCount; ++j) { Node adjacentNode = adjacency[j]; if (adjacentNode == null) { continue; } long adjacentGID = adjacentNode.IO.GID; Tuple <long, long> line = gid <= adjacentGID ? new Tuple <long, long>(gid, adjacentGID) : new Tuple <long, long>(adjacentGID, gid); if (visitedEnergized.Contains(line)) { continue; } stack.Push(new Tuple <Node, EEnergization>(adjacentNode, EEnergization.Energized)); visitedEnergized.Add(line); visitedUnknown.Remove(line); } } else { for (int j = node.Item1.AdjacentOffset; j < node.Item1.AdjacentOffset + node.Item1.AdjacentCount; ++j) { Node adjacentNode = adjacency[j]; if (adjacentNode == null) { continue; } long adjacentGID = adjacentNode.IO.GID; Tuple <long, long> line = gid <= adjacentGID ? new Tuple <long, long>(gid, adjacentGID) : new Tuple <long, long>(adjacentGID, gid); if (visitedEnergized.Contains(line) || visitedUnknown.Contains(line)) { continue; } stack.Push(new Tuple <Node, EEnergization>(adjacentNode, EEnergization.Unknown)); visitedUnknown.Add(line); } } } sourcesEnergization.Add(new Tuple <long, List <Tuple <long, long> >, List <Tuple <long, long> > >(subGraphs[i].IO.GID, new List <Tuple <long, long> >(visitedEnergized), new List <Tuple <long, long> >(visitedUnknown))); } return(sourcesEnergization); }
public override void Update() { Grid measGrid = (Grid)((Border)((StackPanel)panel.Children[1]).Children[0]).Child; if (measGrid.Children.Count > 5) { measGrid.Children.RemoveRange(5, measGrid.Children.Count - 5); } if (measGrid.RowDefinitions.Count > 1) { measGrid.RowDefinitions.RemoveRange(1, measGrid.RowDefinitions.Count - 1); } int row = 0; NetworkModel nm = pubSub.Model; IEnumerable <long> measGIDs = measurementsGetter(); if (measGIDs == null) { measGIDs = new long[0]; } foreach (long measGID in measurementsGetter()) { ++row; Measurement meas = (Measurement)nm.Get(measGID); if (meas == null) { continue; } measGrid.RowDefinitions.Add(new RowDefinition()); TextBlock mridTextBlock = CreateHyperlink(meas.MRID, () => new ElementWindow(measGID, pubSub) { Owner = Application.Current.MainWindow }.Show()); AddToGrid(measGrid, mridTextBlock, row, 0); AddToGrid(measGrid, new TextBlock() { Text = meas.MeasurementType.ToString() }, row, 2); string valueText; bool isNormal; if (ModelCodeHelper.GetTypeFromGID(measGID) == DMSType.Analog) { float value; bool available = pubSub.Measurements.GetAnalogInput(measGID, out value); Analog a = (Analog)meas; isNormal = !available || (value <= a.MaxValue && value >= a.MinValue); valueText = available ? value.ToString() : "N/A"; } else { int value; bool available = pubSub.Measurements.GetDiscreteInput(measGID, out value); Discrete d = (Discrete)meas; isNormal = !available || (value <= d.MaxValue && value >= d.MinValue); valueText = available ? value.ToString() : "N/A"; } AddToGrid(measGrid, new TextBlock() { Text = valueText, Foreground = isNormal ? Brushes.Black : Brushes.White, Background = isNormal ? Brushes.White : Brushes.Red, FontWeight = isNormal ? FontWeights.Regular : FontWeights.Bold, TextAlignment = TextAlignment.Right }, row, 4); } int splitterRowSpan = int.MaxValue; if (row == 0) { measGrid.RowDefinitions.Add(new RowDefinition()); Grid.SetColumnSpan(AddToGrid(measGrid, new TextBlock() { Text = "No measurements.", HorizontalAlignment = HorizontalAlignment.Center }, 1, 0), 5); splitterRowSpan = 1; } Grid.SetRowSpan(measGrid.Children[3], splitterRowSpan); Grid.SetRowSpan(measGrid.Children[4], splitterRowSpan); measGrid.RowDefinitions.Last().Height = new GridLength(1, GridUnitType.Star); initialized = true; }
public bool ApplyUpdate(TopologyModelDownload download) { rwLock.EnterWriteLock(); try { foreach (IdentifiedObject io in download.Inserted) { DMSType type = ModelCodeHelper.GetTypeFromGID(io.GID); Dictionary <long, IdentifiedObject> container; if (!containers.TryGetValue(type, out container)) { continue; } int oldCount = container.Count; container[io.GID] = io; if (container.Count != oldCount + 1) { return(false); } measurementsOfInterest.Add(io.GID); } foreach (IdentifiedObject io in download.Updated) { DMSType type = ModelCodeHelper.GetTypeFromGID(io.GID); Dictionary <long, IdentifiedObject> container; if (!containers.TryGetValue(type, out container)) { continue; } int oldCount = container.Count; container[io.GID] = io; if (container.Count != oldCount) { return(false); } measurementsOfInterest.Add(io.GID); } foreach (long gid in download.Deleted) { DMSType type = ModelCodeHelper.GetTypeFromGID(gid); Dictionary <long, IdentifiedObject> container; if (!containers.TryGetValue(type, out container)) { continue; } if (!container.Remove(gid)) { return(false); } measurementsOfInterest.Remove(gid); markedSwitchStates.TryRemove(gid, out _); } foreach (long switchGID in markedSwitchStates.Keys) { if (!IsSwitchWithoutSCADA(switchGID)) { markedSwitchStates.TryRemove(switchGID, out _); } } graph = new TopologyGraph(containers, analogInputs, discreteInputs, markedSwitchStates, loadProfiles); return(true); } finally { rwLock.ExitWriteLock(); } }
bool IsMeasurementOfInterest(IdentifiedObject io) { Discrete d; return(ModelCodeHelper.GetTypeFromGID(io.GID) == DMSType.Discrete && (d = io as Discrete) != null && d.MeasurementType == MeasurementType.SwitchState); }
void Simulation() { Random r = new Random(); while (!stopSignal.WaitOne(1000)) { Dictionary <long, Analog> analogs; Dictionary <long, Discrete> discretes; HashSet <int> readWriteMeasurementAddresses; modelLock.EnterReadLock(); { analogs = this.analogs; discretes = this.discretes; readWriteMeasurementAddresses = this.readWriteMeasurementAddresses; } modelLock.ExitReadLock(); CommandParams command; while (commands.TryDequeue(out command)) { for (ushort address = command.offset; address < command.offset + command.count; ++address) { if (!readWriteMeasurementAddresses.Contains(address / 2)) { continue; } modbusServer.SetInputRegister(address, modbusServer.GetHoldingRegister(address)); } } DateTime now = DateTime.Now; foreach (Analog a in analogs.Values) { if (a.Direction != SignalDirection.Read) { continue; } float newValue = float.NaN; if (ModelCodeHelper.GetTypeFromGID(a.PowerSystemResource) == DMSType.EnergyConsumer) { newValue = GetConsumerPowerValue(now, a); } if (float.IsNaN(newValue)) { newValue = a.NormalValue; } SetAnalogInput(a.BaseAddress, newValue); } foreach (Discrete d in discretes.Values) { if (d.Direction != SignalDirection.Read) { continue; } int newValue = d.NormalValue + (r.Next(11) - 5); SetDiscreteInput(d.BaseAddress, newValue); } } }
public static IdentifiedObject Create(ResourceDescription rd, bool forceProperties = false) { IdentifiedObject io = null; switch (ModelCodeHelper.GetTypeFromGID(rd.Id)) { case DMSType.ACLineSegment: io = new ACLineSegment(); break; case DMSType.Analog: io = new Analog(); break; case DMSType.BaseVoltage: io = new BaseVoltage(); break; case DMSType.Breaker: io = new Breaker(); break; case DMSType.ConnectivityNode: io = new ConnectivityNode(); break; case DMSType.Disconnector: io = new Disconnector(); break; case DMSType.Discrete: io = new Discrete(); break; case DMSType.DistributionGenerator: io = new DistributionGenerator(); break; case DMSType.EnergyConsumer: io = new EnergyConsumer(); break; case DMSType.EnergySource: io = new EnergySource(); break; case DMSType.PowerTransformer: io = new PowerTransformer(); break; case DMSType.RatioTapChanger: io = new RatioTapChanger(); break; case DMSType.Recloser: io = new Recloser(); break; case DMSType.Terminal: io = new Terminal(); break; case DMSType.TransformerWinding: io = new TransformerWinding(); break; default: return(null); } io.GID = rd.Id; foreach (Property p in rd.Properties.Values) { io.SetProperty(p, forceProperties); } return(io); }
public override void Update() { Switch io = switchGetter(); if (io == null) { panel.Children.Clear(); return; } bool hasSCADA = false; bool marked = false; bool defaulted = false; bool open = false; for (int i = 0; i < io.Measurements.Count; ++i) { long gid = io.Measurements[i]; if (ModelCodeHelper.GetTypeFromGID(gid) != DMSType.Discrete) { continue; } Discrete d = pubSub.Model.Get(gid) as Discrete; if (d == null || d.MeasurementType != MeasurementType.SwitchState) { continue; } int state; if (pubSub.Measurements.GetDiscreteInput(gid, out state)) { hasSCADA = true; open = state != 0; break; } } if (!hasSCADA && !(marked = pubSub.Topology.TryGetMarkedSwitch(io.GID, out open))) { open = io.NormalOpen; defaulted = true; } TextBlock tbState = new TextBlock() { Margin = new Thickness(2), Text = (open ? "Open" : "Closed") + (hasSCADA ? " (Measured)" : (marked ? " (Marked)" : " (Default)")), VerticalAlignment = VerticalAlignment.Center }; Button markOpenButton = new Button() { Margin = new Thickness(2), Content = "Mark as open", IsEnabled = defaulted || (marked && !open), VerticalAlignment = VerticalAlignment.Center }; markOpenButton.Click += (x, y) => MarkSwitch(true); Button markClosedButton = new Button() { Margin = new Thickness(2), Content = "Mark as closed", IsEnabled = defaulted || (marked && open), VerticalAlignment = VerticalAlignment.Center }; markClosedButton.Click += (x, y) => MarkSwitch(false); Button unmarkButton = new Button() { Margin = new Thickness(2), Content = "Unmark", IsEnabled = marked, VerticalAlignment = VerticalAlignment.Center }; unmarkButton.Click += (x, y) => UnmarkSwitch(); StackPanel sp = new StackPanel() { Margin = new Thickness(1, 0, 1, 0), Orientation = Orientation.Horizontal }; sp.Children.Add(tbState); sp.Children.Add(markOpenButton); sp.Children.Add(markClosedButton); sp.Children.Add(unmarkButton); panel.Children.Clear(); panel.Children.Add(new TextBlock() { Margin = new Thickness(2), Text = "Switch state", FontWeight = FontWeights.Bold, FontSize = 14 }); panel.Children.Add(sp); initialized = true; }
public void DownloadMeasurements(List <long> gids) { bool publish = false; rwLock.EnterUpgradeableReadLock(); try { List <long> analogs; List <long> discretes; bool update = false; if (gids == null) { analogs = GetAnalogGIDsOfInterest(); discretes = GetDiscreteGIDsOfInterest(); } else { analogs = new List <long>(); discretes = new List <long>(); for (int i = 0; i < gids.Count; ++i) { long gid = gids[i]; switch (ModelCodeHelper.GetTypeFromGID(gid)) { case DMSType.Analog: { analogs.Add(gid); IdentifiedObject io; containers[DMSType.Analog].TryGetValue(gid, out io); if (IsMeasurementOfInterest(io)) { update = true; } } break; case DMSType.Discrete: { discretes.Add(gid); IdentifiedObject io; containers[DMSType.Discrete].TryGetValue(gid, out io); if (IsMeasurementOfInterest(io)) { update = true; } } break; } } } if (analogs.Count <= 0 && discretes.Count <= 0) { return; } List <KeyValuePair <long, float> > analogValues = null; List <KeyValuePair <long, int> > discreteValues = null; Client <ISCADAServiceContract> client = new Client <ISCADAServiceContract>("endpointSCADA"); client.Connect(); if (!client.Call <bool>(scada => { analogValues = scada.ReadAnalog(analogs); discreteValues = scada.ReadDiscrete(discretes); return(true); }, out _)) { client.Disconnect(); return; } client.Disconnect(); for (int i = 0; i < analogValues.Count; ++i) { KeyValuePair <long, float> tuple = analogValues[i]; analogInputs[tuple.Key] = tuple.Value; } for (int i = 0; i < discreteValues.Count; ++i) { KeyValuePair <long, int> tuple = discreteValues[i]; discreteInputs[tuple.Key] = tuple.Value; } rwLock.EnterWriteLock(); try { lineEnergization = graph.CalculateLineEnergization(); loadFlowResults = graph.CalculateLoadFlow(); publish = true; } catch (Exception e) { } finally { rwLock.ExitWriteLock(); } } finally { rwLock.ExitUpgradeableReadLock(); } if (publish) { Publish(new TopologyChanged()); Publish(new LoadFlowChanged()); } }