public void Dispose() { if (!m_disposed) { try { lock (FaultSummaryIDLock) { foreach (MappingNode node in m_processedMappingNodes) { FaultSummaryIDs.Remove(node.Fault.ID); } } } finally { m_disposed = true; } } }
public override void Execute(MeterDataSet meterDataSet) { MeterInfoDataContext meterInfo; DoubleEndedFaultDistanceTableAdapter doubleEndedFaultDistanceAdapter; List <SystemEventResource.SystemEvent> systemEvents; MeterData.EventDataTable systemEventTable; double lineLength; ComplexNumber nominalImpedance; List <Mapping> mappings; int leftEventID; int rightEventID; VICycleDataGroup leftCycleDataGroup; VICycleDataGroup rightCycleDataGroup; meterInfo = m_dbAdapterContainer.GetAdapter <MeterInfoDataContext>(); doubleEndedFaultDistanceAdapter = m_dbAdapterContainer.GetAdapter <DoubleEndedFaultDistanceTableAdapter>(); // Get a time range for querying each system event that contains events in this meter data set systemEvents = SystemEventResource.GetResource(meterDataSet, m_dbAdapterContainer).SystemEvents; foreach (SystemEventResource.SystemEvent systemEvent in systemEvents) { // Get the full collection of events from the database that comprise the system event that overlaps this time range systemEventTable = m_dbAdapterContainer.GetAdapter <EventTableAdapter>().GetSystemEvent(systemEvent.StartTime, systemEvent.EndTime, m_timeTolerance); foreach (IGrouping <int, MeterData.EventRow> lineGrouping in systemEventTable.GroupBy(evt => evt.LineID)) { // Make sure this line connects two known meter locations if (meterInfo.MeterLocationLines.Count(mll => mll.LineID == lineGrouping.Key) != 2) { continue; } // Determine the length of the line lineLength = meterInfo.Lines .Where(line => line.ID == lineGrouping.Key) .Select(line => (double?)line.Length) .FirstOrDefault() ?? double.NaN; if (double.IsNaN(lineLength)) { continue; } // Determine the nominal impedance of the line nominalImpedance = m_dbAdapterContainer.GetAdapter <FaultLocationInfoDataContext>().LineImpedances .Where(lineImpedance => lineImpedance.LineID == lineGrouping.Key) .Select(lineImpedance => new ComplexNumber(lineImpedance.R1, lineImpedance.X1)) .FirstOrDefault(); if (!nominalImpedance.AllAssigned) { continue; } leftEventID = 0; rightEventID = 0; leftCycleDataGroup = null; rightCycleDataGroup = null; // Attempt to match faults during this system event that occurred // on one end of the line with faults that occurred during this // system even on the other end of the line mappings = GetMappings(lineGrouping); foreach (Mapping mapping in mappings) { if (mapping.Left.FaultType == FaultType.None || mapping.Right.FaultType == FaultType.None) { continue; } // Get the cycle data for each of the two mapped faults if (mapping.Left.Fault.EventID != leftEventID) { leftEventID = mapping.Left.Fault.EventID; leftCycleDataGroup = GetCycleData(leftEventID); } if (mapping.Right.Fault.EventID != rightEventID) { rightEventID = mapping.Right.Fault.EventID; rightCycleDataGroup = GetCycleData(rightEventID); } if ((object)leftCycleDataGroup == null || (object)rightCycleDataGroup == null) { continue; } // Make sure there are no other threads calculating double-ended fault distance for this mapping, // and that double-ended distance has not already been calculated and entered into the database lock (FaultSummaryIDLock) { if (FaultSummaryIDs.Contains(mapping.Left.Fault.ID)) { continue; } if (FaultSummaryIDs.Contains(mapping.Right.Fault.ID)) { continue; } if (doubleEndedFaultDistanceAdapter.GetCountBy(mapping.Left.Fault.ID) > 0) { continue; } if (doubleEndedFaultDistanceAdapter.GetCountBy(mapping.Right.Fault.ID) > 0) { continue; } FaultSummaryIDs.Add(mapping.Left.Fault.ID); FaultSummaryIDs.Add(mapping.Right.Fault.ID); } // Initialize the mappings with additional data needed for double-ended fault location mapping.Left.Initialize(m_dbAdapterContainer, leftCycleDataGroup, m_systemFrequency); mapping.Right.Initialize(m_dbAdapterContainer, rightCycleDataGroup, m_systemFrequency); // Execute the double-ended fault location algorithm ExecuteFaultLocationAlgorithm(lineLength, nominalImpedance, mapping.Left, mapping.Right); ExecuteFaultLocationAlgorithm(lineLength, nominalImpedance, mapping.Right, mapping.Left); // Create rows in the DoubleEndedFaultDistance table CreateFaultDistanceRow(lineLength, mapping.Left, mapping.Right); CreateFaultDistanceRow(lineLength, mapping.Right, mapping.Left); // Add these nodes to the collection of processed mapping nodes m_processedMappingNodes.Add(mapping.Left); m_processedMappingNodes.Add(mapping.Right); } } } // Create a row in the FaultCurve table for every event that now has double-ended fault distance curves foreach (IGrouping <int, MappingNode> grouping in m_processedMappingNodes.GroupBy(node => node.Fault.EventID)) { CreateFaultCurveRow(grouping); } }