Пример #1
0
        private int GetPhaseID(GSF.PQDIF.Logical.Phase phase)
        {
            if ((object)m_phaseLookup == null)
            {
                m_phaseLookup = new DataContextLookup <string, Phase>(m_dbAdapterContainer.GetAdapter <MeterInfoDataContext>(), ph => ph.Name);
            }

            return(m_phaseLookup.GetOrAdd(phase.ToString(), name => new Phase()
            {
                Name = name, Description = name
            }).ID);
        }
Пример #2
0
        private double GetLineVoltage(Line line, PQDPhase phase)
        {
            PQDPhase[] lnPhases    = { PQDPhase.AN, PQDPhase.BN, PQDPhase.CN, PQDPhase.LineToNeutralAverage };
            double     lineVoltage = line.VoltageKV;

            if (lnPhases.Contains(phase))
            {
                lineVoltage /= Math.Sqrt(3.0D);
            }

            return(lineVoltage * 1000.0D);
        }
Пример #3
0
        private Disturbance ToDisturbance(DataSeries rms, Range <int> range, Phase phase)
        {
            Disturbance disturbance = new Disturbance();

            disturbance.EventType        = m_eventType;
            disturbance.Phase            = phase;
            disturbance.StartIndex       = range.Start;
            disturbance.EndIndex         = range.End;
            disturbance.StartTime        = rms[range.Start].Time;
            disturbance.EndTime          = rms[range.End].Time;
            disturbance.Magnitude        = GetMagnitude(rms.ToSubSeries(range.Start, range.End));
            disturbance.PerUnitMagnitude = disturbance.Magnitude / rms.SeriesInfo.Channel.PerUnitValue.GetValueOrDefault();

            return(disturbance);
        }
Пример #4
0
        private Disturbance ToDisturbance(DataSeries rms, Range <int> range, Phase phase)
        {
            double      nominalValue = rms.SeriesInfo.Channel.PerUnitValue ?? GetLineVoltage(rms);
            Disturbance disturbance  = new Disturbance();

            disturbance.EventType        = m_eventType;
            disturbance.Phase            = phase;
            disturbance.StartIndex       = range.Start;
            disturbance.EndIndex         = range.End;
            disturbance.StartTime        = rms[range.Start].Time;
            disturbance.EndTime          = rms[range.End].Time;
            disturbance.Magnitude        = GetMagnitude(rms.ToSubSeries(range.Start, range.End));
            disturbance.PerUnitMagnitude = disturbance.Magnitude / nominalValue;

            return(disturbance);
        }
Пример #5
0
        private void ProcessSnapshots(double systemFrequency, DataSeries waveForm, Phase phase)
        {
            if (waveForm == null)
            {
                return;
            }

            waveForm.SeriesInfo.ConnectionFactory = () => new AdoDataConnection("systemSettings");
            int samplesPerCycle = Transform.CalculateSamplesPerCycle(waveForm.SampleRate, systemFrequency);
            int numCycles       = (int)Math.Floor((double)waveForm.DataPoints.Count / samplesPerCycle);
            int numPoints       = numCycles * samplesPerCycle;

            double[] points         = waveForm.DataPoints.Select(x => x.Value / numPoints).Take(numPoints).ToArray();
            double[] frequencyScale = Fourier.FrequencyScale(points.Length, systemFrequency * samplesPerCycle);

            Complex[] result = FFT(points);

            Dictionary <string, PhasorResult> dict = new Dictionary <string, PhasorResult>();

            for (int i = 0; i < result.Length; i++)
            {
                if (frequencyScale[i] <= 0 || frequencyScale[i] % systemFrequency != 0)
                {
                    continue;
                }

                int harmonic = (int)frequencyScale[i] / (int)systemFrequency;
                if (harmonic <= 0)
                {
                    continue;
                }

                dict.Add($"H{harmonic}", new PhasorResult()
                {
                    Angle = result[i].Phase * 180 / Math.PI, Magnitude = result[i].Magnitude * 2 / Math.Sqrt(2)
                });
            }

            Snapshots.Add(waveForm.SeriesInfo.Channel, JsonConvert.SerializeObject(dict, Formatting.None));

            //using (StreamWriter sw = new StreamWriter(waveForm.SeriesInfo.Channel.Meter.Name + waveForm.SeriesInfo.Channel.MeasurementType.Name + phase.ToString() + "snapshottest.txt"))
            //{
            //    sw.Write(JsonConvert.SerializeObject(dict, Formatting.Indented));
            //}
        }
        private Disturbance ToDisturbance(DataSeries rms, Range<int> range, Phase phase)
        {
            Disturbance disturbance = new Disturbance();

            disturbance.EventType = m_eventType;
            disturbance.Phase = phase;
            disturbance.StartIndex = range.Start;
            disturbance.EndIndex = range.End;
            disturbance.StartTime = rms[range.Start].Time;
            disturbance.EndTime = rms[range.End].Time;
            disturbance.Magnitude = GetMagnitude(rms.ToSubSeries(range.Start, range.End));
            disturbance.PerUnitMagnitude = disturbance.Magnitude / rms.SeriesInfo.Channel.PerUnitValue.GetValueOrDefault();

            return disturbance;
        }
Пример #7
0
        private IEnumerable <Disturbance> DetectTransients(DataSeries waveform, Phase phase)
        {
            if (waveform == null)
            {
                return(Enumerable.Empty <Disturbance>());
            }

            // Obtain a list of time gaps in the waveform
            List <int> gapIndexes = Enumerable.Range(0, waveform.DataPoints.Count - 1)
                                    .Where(index =>
            {
                DataPoint p1     = waveform[index];
                DataPoint p2     = waveform[index + 1];
                double cycleDiff = (p2.Time - p1.Time).TotalSeconds * SystemFrequency;

                // Detect gaps larger than a quarter cycle.
                // Tolerance of 0.000062 calculated
                // assuming 3.999 samples per cycle
                return(cycleDiff > 0.250062);
            })
                                    .ToList();

            double sampleRate      = waveform.SampleRate;
            int    samplesPerCycle = Transform.CalculateSamplesPerCycle(waveform.SampleRate, SystemFrequency);
            double nominalVoltage  = waveform.SeriesInfo.Channel.Line.VoltageKV * 1000.0D;

            if (IsLineToNeutral(waveform.SeriesInfo.Channel.Phase.Name))
            {
                nominalVoltage /= Math.Sqrt(3.0D);
            }

            double             thresholdValue = nominalVoltage * TransientThreshold / 100;
            List <Disturbance> disturbances   = new List <Disturbance>();

            List <int> detections = Enumerable.Range(0, waveform.DataPoints.Count)
                                    .Select(index => new { P1 = index - samplesPerCycle, P2 = index, P3 = index + samplesPerCycle })
                                    .Where(obj => obj.P1 >= 0 && obj.P3 < waveform.DataPoints.Count)
                                    .Where(obj => !gapIndexes.Any(index => obj.P1 <= index && index < obj.P3))
                                    .Where(obj =>
            {
                double p1     = waveform[obj.P1].Value;
                double p2     = waveform[obj.P2].Value;
                double p3     = waveform[obj.P3].Value;
                double p1Diff = Math.Abs(p2 - p1);
                double p3Diff = Math.Abs(p2 - p3);
                return(p1Diff >= thresholdValue && p3Diff >= thresholdValue);
            })
                                    .Select(obj => obj.P2)
                                    .ToList();

            IEnumerable <Range <int> > ranges = detections
                                                .Zip(detections.Skip(1), (p1, p2) => new Range <int>(p1, p2))
                                                .Where(range => range.End - range.Start < samplesPerCycle);

            return(Range <int> .MergeAllOverlapping(ranges)
                   .Select(range =>
            {
                DataSeries subSeries = waveform.ToSubSeries(range.Start, range.End);
                double max = Math.Abs(subSeries.Maximum);
                double min = Math.Abs(subSeries.Minimum);
                double peak = Math.Max(max, min);

                return new Disturbance()
                {
                    EventType = EventClassification.Transient,
                    Phase = phase,
                    StartIndex = range.Start,
                    EndIndex = range.End,
                    StartTime = waveform[range.Start].Time,
                    EndTime = waveform[range.End].Time,
                    Magnitude = peak,
                    PerUnitMagnitude = peak / nominalVoltage
                };
            })
                   .ToList());
        }