コード例 #1
0
ファイル: RangeTerrain.cs プロジェクト: vasichmen/WindEnergy
        /// <summary>
        /// приведение ряда к условиям плоской местности
        /// </summary>
        /// <param name="ms_range">ряд</param>
        /// <param name="expectancy">повторяемости направлений ветра</param>
        /// <param name="ms_classes">классы открытости МС</param>
        /// <param name="water_type">расстояние до водной поверхности</param>
        /// <returns></returns>
        public static RawRange ToFlatTerrain(RawRange ms_range, StatisticalRange <WindDirections8> expectancy, Dictionary <WindDirections8, double> ms_classes, WaterDistanceType water_type)
        {
            //1. найти Кмс
            //2. пересчитать ряд

            RawRange result = new RawRange();
            double   K0     = (int)water_type;

            //средневзвешенный коэффициент открытости метеостанции
            double Kms = 0;

            foreach (WindDirections8 dir in WindDirections8.N.GetEnumItems())
            {
                if (dir != WindDirections8.Calm && dir != WindDirections8.Undefined && dir != WindDirections8.Variable)
                {
                    Kms += expectancy[dir] * ms_classes[dir];
                }
            }

            double k0 = K0 / Kms;

            result.BeginChange();
            foreach (RawItem item in ms_range)
            {
                RawItem ni = item.Clone();
                ni.Speed = item.Speed * k0;
                result.Add(ni);
            }
            result.EndChange();
            return(result);
        }
コード例 #2
0
 /// <summary>
 /// перераспределяет штиль по румбам в пропорциях их вероятностей
 /// </summary>
 /// <typeparam name="T">тип градаций направления</typeparam>
 /// <param name="rawDirectionExpectancy">базовое распределение new StatisticalRange(...)</param>
 /// <returns></returns>
 private static StatisticalRange <T> reorganizeCalm <T>(StatisticalRange <T> rawDirectionExpectancy)
 {
     if (typeof(T) == typeof(WindDirections16))
     {
         double dirs = rawDirectionExpectancy.Values.Sum() - rawDirectionExpectancy[WindDirections16.Calm];
         for (int i = 0; i < 16; i++)
         {
             rawDirectionExpectancy[(WindDirections16)i] /= dirs;
         }
         return(rawDirectionExpectancy);
     }
     else if (typeof(T) == typeof(WindDirections8))
     {
         double dirs = rawDirectionExpectancy.Values.Sum() - rawDirectionExpectancy[WindDirections8.Calm];
         for (int i = 0; i < 8; i++)
         {
             rawDirectionExpectancy[(WindDirections8)i] /= dirs;
         }
         return(rawDirectionExpectancy);
     }
     else
     {
         throw new ArgumentException("Тип должен быть одним из типов румбов", nameof(T));
     }
 }
コード例 #3
0
        /// <summary>
        /// проверка на соответствие нормальному закону распределния ряда. озвращая критерий согласия Пирсона для этого ряда
        /// http://www.ekonomstat.ru/kurs-lektsij-po-teorii-statistiki/403-proverka-sootvetstvija-rjada-raspredelenija.html
        /// https://life-prog.ru/2_84515_proverka-po-kriteriyu-hi-kvadrat.html критерий пирсона
        /// https://math.semestr.ru/group/example-normal-distribution.php для нормального распределения
        /// </summary>
        /// <param name="range">ряд</param>
        /// <param name="parameter">проверяемый параметр</param>
        /// <returns></returns>
        private static double checkNormalLaw(RawRange range, MeteorologyParameters parameter)
        {
            GradationInfo <GradationItem> grads;

            switch (parameter)
            {
            case MeteorologyParameters.Speed:
                grads = new GradationInfo <GradationItem>(0, SPEED_GRADATION_STEP, range.Max((item) => { return(item.Speed); }));   //градации скорости
                break;

            case MeteorologyParameters.Direction:
                StatisticalRange <WindDirections16> srwd = StatisticEngine.GetDirectionExpectancy(range, GradationInfo <WindDirections16> .Rhumb16Gradations);

                return(0);

            case MeteorologyParameters.Temperature:
                grads = new GradationInfo <GradationItem>(0, TEMPERATURE_GRADATION_STEP, range.Max((item) => { return(item.Temperature); }));   //градации температуры
                break;

            case MeteorologyParameters.Wetness:
                grads = new GradationInfo <GradationItem>(0, WETNESS_GRADATION_STEP, range.Max((item) => { return(item.Wetness); }));   //градации влажности
                break;

            default: throw new WindEnergyException("Этот параметр не реализован");
            }

            //РАСЧЕТ ДЛЯ ВСЕХ, КРОМЕ НАПРАВЛЕНИЙ
            StatisticalRange <GradationItem> stat_range = StatisticEngine.GetExpectancy(range, grads, parameter); //статистический ряд

            // TODO: расчет критерия пирсона для ряда

            return(0);
        }
コード例 #4
0
        /// <summary>
        /// получить статистический ряд по заданным значениям и заданным градациям
        /// </summary>
        /// <param name="tempr"></param>
        /// <param name="rhumb8Gradations"></param>
        /// <returns></returns>
        public static StatisticalRange <WindDirections8> GetDirectionExpectancy(RawRange tempr, GradationInfo <WindDirections8> rhumb8Gradations)
        {
            List <double> spds = new List <double>(from t in tempr select t.Direction);
            StatisticalRange <WindDirections8> r = new StatisticalRange <WindDirections8>(spds, rhumb8Gradations);

            return(reorganizeCalm(r));
        }
コード例 #5
0
        /// <summary>
        /// получить статистический ряд по заданным значениям и заданным градациям
        /// </summary>
        /// <param name="range"></param>
        /// <param name="gradations"></param>
        /// <param name="parameter"></param>
        /// <returns></returns>
        public static StatisticalRange <GradationItem> GetExpectancy(IList <RawItem> range, GradationInfo <GradationItem> gradations, MeteorologyParameters parameter = MeteorologyParameters.Speed)
        {
            List <double> rang;

            switch (parameter)
            {
            case MeteorologyParameters.Speed:
                rang = new List <double>(from t in range select t.Speed);
                break;

            case MeteorologyParameters.Direction:
                rang = new List <double>(from t in range select t.Direction);
                break;

            case MeteorologyParameters.Temperature:
                rang = new List <double>(from t in range select t.Temperature);
                break;

            case MeteorologyParameters.Wetness:
                rang = new List <double>(from t in range select t.Wetness);
                break;

            default: throw new WindEnergyException("Этот параметр не реализован");
            }
            StatisticalRange <GradationItem> r = new StatisticalRange <GradationItem>(rang, gradations);

            return(r);
        }
コード例 #6
0
        /// <summary>
        /// возвращает отклонение повторямости скорости от среднемноголетней
        /// </summary>
        /// <param name="range"></param>
        /// <param name="totalRange"></param>
        /// <returns></returns>
        private static double getExpectancyDeviation(RawRange range, RawRange totalRange)
        {
            StatisticalRange <GradationItem> exp = GetExpectancy(totalRange, Vars.Options.CurrentSpeedGradation);
            double         averSpeed             = totalRange.Average((t) => t.Speed);
            DeviationsInfo dinfo = ProcessRangeDeviations(range, averSpeed, exp);

            return(dinfo.ExpDeviation);
        }
コード例 #7
0
        /// <summary>
        /// сохранить энергетические характеристики в файл csv
        /// </summary>
        /// <param name="fileName">имя файла</param>
        /// <param name="range_info">характеристики по ряду наблюдений</param>
        /// <param name="ext_info">характеристики по градациям</param>
        /// <param name="stat_directions">повторяемость направлений</param>
        /// <param name="stat_speeds">повторяемость скоростей</param>
        /// <param name="append">если истина, то файл будет дописан</param>
        /// <param name="caption">заголовок, который будет записан в начале</param>
        /// <param name="month">значение графы месяц</param>
        /// <param name="year">значение графы год</param>
        /// <param name="amount">количество измерений в ряде</param>
        private void saveEnergyInfoLine(
            string fileName,
            EnergyInfo range_info,
            EnergyInfo ext_info,
            StatisticalRange <WindDirections16> stat_directions,
            StatisticalRange <GradationItem> stat_speeds,
            string caption,
            string year,
            string month,
            int amount,
            bool append
            )
        {
            StreamWriter sw = new StreamWriter(fileName, append, Encoding.UTF8);

            //запись заголовка
            if (!string.IsNullOrEmpty(caption))
            {
                sw.WriteLine(caption);
            }

            if (range_info == null || ext_info == null || stat_directions == null || stat_speeds == null)
            {
                sw.Close();
                return;
            }

            //  "Год;Месяц;кол-во изм;0.75;2.5;4.5;6.5;8.5;10.5;12.5;14.5;16.5;19;22.5;26.5;31.5;37.5;43.5;Vmin;Vmax;Vср.год;Vэкст50,м/с;δ(P);Cv(V);Nвал уд.;Эвал уд.;С;СВ;В;ЮВ;Ю;ЮЗ;З;СЗ;штиль";
            string line = $"{year};{month};{amount}";

            //повторяемости скоростей ветра
            for (int j = 0; j < stat_speeds.Keys.Count; j++)
            {
                line += ";" + (stat_speeds.Values[j] * 100).ToString("0.00");
            }

            //по ряду наблюдений
            line += string.Format(";{0:f2};{1:f2};{2:f2};{3:f2};{4:f2};{5:f2};{6:f2};{7:f2};{8:f2};{9:f2};{10:f2}",
                                  range_info.Vmin, range_info.Vmax, range_info.V0, range_info.ExtremalSpeed, range_info.ExpectancyDeviation, range_info.Cv,
                                  range_info.StandardDeviationSpeed, range_info.VeybullGamma, range_info.VeybullBeta, range_info.PowerDensity, range_info.EnergyDensity);

            //повторяемости направлений ветра
            List <Enum> rs = WindDirections16.Calm.GetEnumItems().GetRange(0, 17);

            for (int j = 0; j < rs.Count; j++)
            {
                WindDirections16 rhumb = (WindDirections16)rs[j];
                int index = stat_directions.Keys.IndexOf(rhumb);
                if (index == -1)
                {
                    continue;
                }
                line += ";" + (stat_directions.Values[index] * 100).ToString("0.00");
            }
            sw.WriteLine(line);
            sw.Close();
        }
コード例 #8
0
        /// <summary>
        /// обновление всех элементов в соответствии с выбранными параметрами
        /// </summary>
        private void refreshInfo()
        {
            RawRange tempr = range.GetRange(
                radioButtonSelectPeriod.Checked,
                radioButtonSelectYearMonth.Checked,
                dateTimePickerFrom.Value,
                dateTimePickerTo.Value,
                comboBoxYear.SelectedItem,
                comboBoxMonth.SelectedItem
                );

            if (tempr == null)
            {
                throw new Exception("что-то совсем не так!!");
            }

            //расчет параметров
            try
            {
                range_info      = StatisticEngine.ProcessRange(tempr, range);
                stat_speeds     = StatisticEngine.GetExpectancy(tempr, Vars.Options.CurrentSpeedGradation);
                stat_directions = StatisticEngine.GetDirectionExpectancy(tempr, GradationInfo <WindDirections16> .Rhumb16Gradations);
                exp_info        = StatisticEngine.ProcessRange(stat_speeds);
            }
            catch (Exception ex)
            {
                _ = MessageBox.Show(this, ex.Message, "Расчёт энергетических характеристик", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                return;
            }

            if (range_info == null || exp_info == null)
            {
                _ = MessageBox.Show(this, "Для заданного ряда невозможно расчитать характеристики на выбранном интервале", "Расчёт энергетических характеристик", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                return;
            }

            //вывод параметров
            labelEnergyDensity.Text          = (range_info.EnergyDensity / 1000).ToString("0.00") + " кВт*ч/м^2";
            labelPowerDensity.Text           = range_info.PowerDensity.ToString("0.00") + " Вт/м^2";
            labelCv.Text                     = range_info.Cv.ToString("0.000");
            labelV0.Text                     = range_info.V0.ToString("0.0") + " м/с";
            labelExtremalSpeed.Text          = range_info.ExtremalSpeed.ToString("0.0") + " м/с";
            labelVmax.Text                   = range_info.Vmax.ToString("0.0") + " м/с";
            labelVmin.Text                   = range_info.Vmin.ToString("0.0") + " м/с";
            labelStandardDeviationSpeed.Text = range_info.StandardDeviationSpeed.ToString("0.000") + " м/с";
            labelGamma.Text                  = range_info.VeybullGamma.ToString("0.000");
            labelBeta.Text                   = range_info.VeybullBeta.ToString("0.000") + " м/с";
            labelAirDensity.Text             = tempr.AirDensity.ToString("0.000") + " кг/м^3" + (Vars.Options.CalculateAirDensity ? " (расчёт)" : "");

            labelEnergyDensityTV.Text = (exp_info.EnergyDensity / 1000).ToString("0.00") + " кВт*ч/м^2";
            labelPowerDensityTV.Text  = exp_info.PowerDensity.ToString("0.00") + " Вт/м^2";
            labelCvTV.Text            = exp_info.Cv.ToString("0.000");
            labelV0TV.Text            = exp_info.V0.ToString("0.0") + " м/с";
            labelGammaTV.Text         = exp_info.VeybullGamma.ToString("0.000");
            labelBetaTV.Text          = exp_info.VeybullBeta.ToString("0.000") + " м/с";
        }
コード例 #9
0
        /// <summary>
        /// расчёт отклонений от заданных многолетних значений
        /// </summary>
        /// <param name="r">ряд за небольшой промежуток (год)</param>
        /// <param name="averSpeed">среднемноголетняя скорость</param>
        /// <param name="exp">многолетняя повторяемость скорости ветра</param>
        /// <returns></returns>
        internal static DeviationsInfo ProcessRangeDeviations(RawRange r, double averSpeed, StatisticalRange <GradationItem> exp)
        {
            DeviationsInfo res = new DeviationsInfo();

            double aver = r.Average((t) => t.Speed);

            res.SpeedDeviation = Math.Abs(aver - averSpeed);

            StatisticalRange <GradationItem> th = GetExpectancy(r, Vars.Options.CurrentSpeedGradation);

            res.ExpDeviation = Math.Sqrt(exp.Values.Zip(th.Values, (a, b) => Math.Pow(a - b, 2)).Aggregate((x, y) => x + y)); //корень из суммы квадратов разностей повторяемостей многолетней и этого промежутка
            return(res);
        }
コード例 #10
0
ファイル: RangeTerrain.cs プロジェクト: vasichmen/WindEnergy
        /// <summary>
        /// получить преобладающие направления ветра
        /// </summary>
        /// <param name="ms_range"></param>
        /// <param name="expectancy"></param>
        /// <returns></returns>
        public static List <WindDirections8> GetRhumbsDominants(RawRange ms_range, StatisticalRange <WindDirections8> expectancy = null)
        {
            List <WindDirections8> res = new List <WindDirections8>();

            expectancy = expectancy ?? StatisticEngine.GetDirectionExpectancy(ms_range, GradationInfo <WindDirections8> .Rhumb8Gradations); //повторяемости скорости ветра по 8 румбам
            var maxes = expectancy.Values.OrderByDescending((d) => d).ToList();

            res.Add((WindDirections8)expectancy.Keys[expectancy.Values.IndexOf(maxes[0])]); //первый всегда добавляем
            if (maxes[0] > 0.3 && maxes[0] - maxes[1] < 0.1)                                //второй добавляем если первый больше 30% и у второго отрыв меньше 10%
            {
                res.Add((WindDirections8)expectancy.Keys[expectancy.Values.IndexOf(maxes[1])]);
            }
            return(res);
        }
コード例 #11
0
        /// <summary>
        /// получить характеристики по заданным градациям
        /// </summary>
        /// <param name="speeds"></param>
        /// <returns></returns>
        public static EnergyInfo ProcessRange(StatisticalRange <GradationItem> speeds)
        {
            List <GradationItem> grads  = speeds.Gradation.Items.ConvertAll((r) => (GradationItem)r);
            List <double>        expect = speeds.Values;

            if (grads.Count != expect.Count)
            {
                throw new Exception("что-то опять не так");
            }


            //средняя скорость:  сумма произведений скорости градации на вероятность
            IEnumerable <double> en = grads.Zip(expect, (g, e) => g.Average * e);
            double V0 = en.Aggregate(0d, (x, y) => x + (double.IsNaN(y) ? 0 : y));

            //удельная энергия
            double EDensity = (grads.Zip(expect, (g, e) => Math.Pow(g.Average, 3) * 0.5 * e * 8760 * Vars.Options.AirDensity)).Aggregate((x, y) => x + (double.IsNaN(y) ? 0 : y));

            //удельная мощность
            double PDensity = EDensity / 8760d;

            //среднеквадратическое отклонение
            double sigm = Math.Sqrt((grads.Zip(expect, (g, e) => Math.Pow((g.Average - V0), 2) * e)).Aggregate((x, y) => x + (double.IsNaN(y) ? 0 : y)));

            //Cv
            double Cv = sigm / V0;

            double VeyGamma = getVeybullGamma(Cv);
            double VeyBeta  = getVeybullBeta(V0, VeyGamma);

            return(new EnergyInfo()
            {
                Cv = Cv,
                EnergyDensity = EDensity,
                PowerDensity = PDensity,
                StandardDeviationSpeed = sigm,
                V0 = V0,
                VeybullBeta = VeyBeta,
                VeybullGamma = VeyGamma,
            });
        }
コード例 #12
0
        /// <summary>
        /// запись одной строки в лист ВЭК. Возвращет число элементов в этой строке
        /// </summary>
        /// <param name="worksheet">страница для записи</param>
        /// <param name="line">строка</param>
        /// <param name="range_info">характеристики по ряду наблюдений</param>
        /// <param name="ext_info">характеристики по градациям</param>
        /// <param name="stat_directions">повторяемость направлений</param>
        /// <param name="stat_speeds">повторяемость скоростей</param>
        /// <param name="year">год</param>
        /// <param name="month">месяц</param>
        /// <param name="amount">число измерений</param>
        /// <returns>количество добавленных ячеек</returns>
        private int saveEnergyInfoLine(ExcelWorksheet worksheet,
                                       int line,
                                       EnergyInfo range_info,
                                       EnergyInfo ext_info,
                                       StatisticalRange <WindDirections16> stat_directions,
                                       StatisticalRange <GradationItem> stat_speeds,
                                       string year,
                                       string month,
                                       int amount)
        {
            if (range_info == null || ext_info == null || stat_directions == null || stat_speeds == null)
            {
                return(0);
            }

            //  "Год;Месяц;кол-во изм;0.75;2.5;4.5;6.5;8.5;10.5;12.5;14.5;16.5;19;22.5;26.5;31.5;37.5;43.5;Vmin;Vmax;Vср.год;Vэкстр.50, м/с;δ(P);Cv(V);Nвал уд.;Эвал уд.;С;СВ;В;ЮВ;Ю;ЮЗ;З;СЗ;штиль";
            List <object> values = new List <object>()
            {
                year, month, amount
            };

            //повторяемости скоростей ветра
            for (int j = 0; j < stat_speeds.Keys.Count; j++)
            {
                values.Add(Math.Round((stat_speeds.Values[j] * 100), 2));
            }

            //по ряду наблюдений
            values.AddRange(new List <object>()
            {
                Math.Round(range_info.Vmin, 2),
                Math.Round(range_info.Vmax, 2),
                Math.Round(range_info.V0, 2),
                Math.Round(range_info.ExtremalSpeed, 2),
                Math.Round(range_info.ExpectancyDeviation, 2),
                Math.Round(range_info.Cv, 2),
                Math.Round(range_info.StandardDeviationSpeed, 2),
                Math.Round(range_info.VeybullGamma, 2),
                Math.Round(range_info.VeybullBeta, 2),
                Math.Round(range_info.PowerDensity, 2),
                Math.Round(range_info.EnergyDensity, 2)
            });

            //повторяемости направлений ветра
            List <Enum> rs = WindDirections16.Calm.GetEnumItems().GetRange(0, 17);

            for (int j = 0; j < rs.Count; j++)
            {
                WindDirections16 rhumb = (WindDirections16)rs[j];
                int index = stat_directions.Keys.IndexOf(rhumb);
                if (index == -1)
                {
                    continue;
                }
                values.Add(Math.Round((stat_directions.Values[index] * 100), 2));
            }

            //запись всех значений
            for (int j = 1; j <= values.Count; j++)
            {
                worksheet.Cells[line, j].Value = values[j - 1];
            }

            return(values.Count);
        }
コード例 #13
0
        /// <summary>
        /// сохранение ВЭК
        /// </summary>
        /// <param name="filename"></param>
        /// <param name="range"></param>
        public override void SaveEnergyInfo(string filename, RawRange range)
        {
            using (ExcelPackage excelPackage = new ExcelPackage())
            {
                //Set some properties of the Excel document
                excelPackage.Workbook.Properties.Author  = "Wind Energy";
                excelPackage.Workbook.Properties.Title   = range.Name;
                excelPackage.Workbook.Properties.Created = DateTime.Now;
                //Create the WorkSheet
                ExcelWorksheet worksheet = excelPackage.Workbook.Worksheets.Add("Лист 1");

                List <object> years = new List <object>();
                foreach (RawItem item in range)
                {
                    if (!years.Contains(item.Date.Year))
                    {
                        years.Add(item.Date.Year);
                    }
                }

                double totalAverageSpeed = range.Average((t) => t.Speed);

                //формирование заголовка
                List <string> cap = new List <string>()
                {
                    "Год", "Месяц", "Кол-во измерений"
                };
                foreach (GradationItem grad in Vars.Options.CurrentSpeedGradation.Items)
                {
                    cap.Add(grad.Average.ToString("0.00"));
                }
                cap.AddRange(new string[] { "Vmin, м/с", "Vmax, м/с", "Vср, м/с", "Vэкстр.50, м/с", "δ(P)", "Cv(V)", "𝜎(V)", "γ", "β", "Nвал уд., Вт/м^2", "Эвал уд., Вт*ч/м^2" });
                foreach (WindDirections16 wd in WindDirections16.Calm.GetEnumItems().GetRange(0, 17))
                {
                    cap.Add(wd.Description());
                }


                //ЗАПИСЬ ФАЙЛА
                //запись заголовка
                for (int j = 1; j <= cap.Count; j++)
                {
                    worksheet.Cells[1, j].Value = cap[j - 1];
                }
                worksheet.Cells[1, 1, 1, cap.Count].Style.Font.Bold        = true;
                worksheet.Cells[1, 1, 1, cap.Count].Style.Fill.PatternType = ExcelFillStyle.Solid;
                worksheet.Cells[1, 1, 1, cap.Count].Style.Fill.BackgroundColor.SetColor(Color.Gray);
                worksheet.View.FreezePanes(2, 3);

                //запись данных обо всём периоде
                EnergyInfo ri1 = StatisticEngine.ProcessRange(range);
                StatisticalRange <WindDirections16> sd1 = StatisticEngine.GetDirectionExpectancy(range, GradationInfo <WindDirections16> .Rhumb16Gradations);
                StatisticalRange <GradationItem>    ss1 = StatisticEngine.GetExpectancy(range, Vars.Options.CurrentSpeedGradation);
                EnergyInfo ei1   = StatisticEngine.ProcessRange(ss1);
                int        cells = saveEnergyInfoLine(worksheet, 2, ri1, ei1, sd1, ss1, "Все года", "Все месяцы", range.Count);
                worksheet.Cells[2, 1, 2, cells].Style.Font.Bold        = true;
                worksheet.Cells[2, 1, 2, cells].Style.Fill.PatternType = ExcelFillStyle.Solid;
                worksheet.Cells[2, 1, 2, cells].Style.Fill.BackgroundColor.SetColor(Color.LightGray);

                //запись данных для каждого года
                int line = 3;
                foreach (int year in years) //цикл по годам
                {
                    //для каждого месяца в году
                    for (int mt = 0; mt <= 12; mt++) //по месяцам, начиная со всех
                    {
                        Months   month = (Months)mt;
                        RawRange rn    = range.GetRange(false, true, DateTime.Now, DateTime.Now, year, month.Description());
                        if (rn == null || rn.Count == 0)
                        {
                            continue;
                        }
                        EnergyInfo ri = StatisticEngine.ProcessRange(rn, range);
                        StatisticalRange <WindDirections16> sd = StatisticEngine.GetDirectionExpectancy(rn, GradationInfo <WindDirections16> .Rhumb16Gradations);
                        StatisticalRange <GradationItem>    ss = StatisticEngine.GetExpectancy(rn, Vars.Options.CurrentSpeedGradation);
                        EnergyInfo ei = StatisticEngine.ProcessRange(ss);
                        cells = saveEnergyInfoLine(worksheet, line, ri, ei, sd, ss, year.ToString(), month.Description(), rn.Count);
                        if (Math.IEEERemainder(mt + 1, 2) == 0 || mt == 0) //на нечетных строках добавляем серый фон
                        {
                            worksheet.Cells[line, 1, line, cells].Style.Fill.PatternType = ExcelFillStyle.Solid;
                            worksheet.Cells[line, 1, line, cells].Style.Fill.BackgroundColor.SetColor(Color.LightGray);
                        }
                        if (month == Months.All) //для суммарной информации по году выделение жирным
                        {
                            worksheet.Cells[line, 1, line, cells].Style.Font.Bold = true;
                        }
                        line++;
                    }
                }

                //запись данных для каждого месяца отдельно
                line += 3;
                //для каждого месяца в году
                for (int mt = 1; mt <= 12; mt++) //по месяцам
                {
                    Months   month = (Months)mt;
                    RawRange rn    = range.GetRange(false, true, DateTime.Now, DateTime.Now, "Все", month.Description());
                    if (rn == null || rn.Count == 0)
                    {
                        continue;
                    }
                    EnergyInfo ri = StatisticEngine.ProcessRange(rn, range);
                    StatisticalRange <WindDirections16> sd = StatisticEngine.GetDirectionExpectancy(rn, GradationInfo <WindDirections16> .Rhumb16Gradations);
                    StatisticalRange <GradationItem>    ss = StatisticEngine.GetExpectancy(rn, Vars.Options.CurrentSpeedGradation);
                    EnergyInfo ei = StatisticEngine.ProcessRange(ss);
                    cells = saveEnergyInfoLine(worksheet, line, ri, ei, sd, ss, "Все года", month.Description(), rn.Count);
                    if (Math.IEEERemainder(mt + 1, 2) == 0 || mt == 0) //на нечетных строках добавляем серый фон
                    {
                        worksheet.Cells[line, 1, line, cells].Style.Fill.PatternType = ExcelFillStyle.Solid;
                        worksheet.Cells[line, 1, line, cells].Style.Fill.BackgroundColor.SetColor(Color.LightGray);
                    }
                    line++;
                }


                //Save your file
                FileInfo fi = new FileInfo(filename);
                excelPackage.SaveAs(fi);
            }
        }
コード例 #14
0
        /// <summary>
        /// обработка ряда и получение расчётного года
        /// </summary>
        /// <param name="Range"></param>
        /// <returns></returns>
        public static CalculateYearInfo ProcessRange(RawRange Range)
        {
            if (Range == null || Range.Count < 3)
            {
                throw new ArgumentException("Ряд не может быть null или длиной меньше трёх наблюдений");
            }
            List <RawItem> range = new List <RawItem>(Range);

            range.Sort(new DateTimeComparerRawItem());
            if (range[range.Count - 1].Date - range[0].Date < TimeSpan.FromDays(366))
            {
                throw new ArgumentException("Ряд должен быть длиной больше одного года");
            }


            //среднемноголетняя скорость
            double averSpeed = range.Average((i) => i.Speed);

            if (double.IsNaN(averSpeed))
            {
                throw new WindEnergyException("Ряд содержит недопустимые для расчета значения скорости");
            }

            //разделяем исходный ряд по годам
            var years = range.GroupBy((i) => i.Date.Year).ToList().ConvertAll((gr) => new RawRange(gr.ToList()));

            //ОБРАБОТКА ВСЕХ РЯДОВ И ПОЛУЧЕНИЕ ИНФОРМАЦИИ
            CalculateYearInfo res = new CalculateYearInfo();

            res.AverageSpeed = averSpeed;
            res.Range        = Range;
            foreach (RawRange r in years)
            {
                QualityInfo qinfo = Qualifier.ProcessRange(r);

                //если null, то ряд очень маленький или не удалось расчитать параметры
                if (r == null || r[r.Count - 1].Date - r[0].Date < TimeSpan.FromDays(364))
                {
                    continue;
                }

                StatisticalRange <GradationItem> exp = StatisticEngine.GetExpectancy(range, Vars.Options.CurrentSpeedGradation);
                DeviationsInfo dinfo = StatisticEngine.ProcessRangeDeviations(r, averSpeed, exp);

                double           aver  = r.Average((t) => t.Speed);
                SinglePeriodInfo spinf = new SinglePeriodInfo()
                {
                    Interval              = qinfo.Intervals.Count == 1 ? qinfo.Intervals[0].Interval : StandartIntervals.Variable,
                    Completness           = qinfo.Completeness * 100,
                    Vmax                  = r.Max((t) => t.Speed),
                    Year                  = r[0].Date.Year,
                    From                  = r[0].Date,
                    To                    = r[r.Count - 1].Date,
                    SpeedDeviation        = dinfo.SpeedDeviation,
                    ExpectancyDeviation   = dinfo.ExpDeviation,
                    AverageSpeed          = aver,
                    SpeedDeviationPercent = (dinfo.SpeedDeviation / averSpeed) * 100d
                };
                res.Years.Add(spinf);
            }

            //ВЫБОР РАСЧЕТНОГО ГОДА
            //получаем года с одинаковым интервалом и полнотой больше 95%
            List <SinglePeriodInfo> accepts = (from t in res.Years where t.Interval != StandartIntervals.Variable && t.Interval != StandartIntervals.Missing && t.Completness > 95 select t).ToList();

            //если даже таких годов не нашлось, то выходим
            if (accepts.Count == 0)
            {
                return(res);
            }

            //если только один год остался, то его и оставляем
            if (accepts.Count == 1)
            {
                res.RecomendedYear = accepts[0];
                return(res);
            }

            //проверка по отклонению скорости
            var    ac        = accepts.OrderBy((t) => t.SpeedDeviation).ToList();                                             //в начале ряда остаются минимальные отклонения скорости
            double startsDev = ac[0].SpeedDeviation;                                                                          //запоминаем сааамое мальнкое отклонение (с ним сравниваем остальные, чтоб найти похожие)
            var    ac2       = ac.TakeWhile(e => e.SpeedDeviation - startsDev < Vars.Options.MinimalSpeedDeviation).ToList(); //остаются только ряды с очень похожим отклонением скоростей


            if (ac2.Count == 1) //если остался только один, то его оставляем
            {
                res.RecomendedYear = ac2[0];
                return(res);
            }

            //проверка по отклонению повторяемости
            var ac3 = ac2.OrderBy((t) => t.ExpectancyDeviation); //выбираем минимальное отклонение по повторяемости

            res.RecomendedYear = ac3.ToList()[0];

            return(res);
        }
コード例 #15
0
ファイル: RangeTerrain.cs プロジェクト: vasichmen/WindEnergy
        /// <summary>
        /// выбор текста для рекомендаций, какой тип рельефа лучше использовать
        /// </summary>
        /// <param name="range"></param>
        /// <param name="pointCoordinates"></param>
        /// <param name="geoinfo"></param>
        /// <returns></returns>
        public static Dictionary <string, Color> GetRecommendation(RawRange range, PointLatLng pointCoordinates, IGeoInfoProvider geoinfo)
        {
            if (range.Position.IsEmpty)
            {
                throw new WindEnergyException("Не заданы координаты метеостанции");
            }
            if (pointCoordinates.IsEmpty)
            {
                throw new WindEnergyException("Не заданы координаты точки ВЭС");
            }
            if (geoinfo == null)
            {
                throw new ArgumentNullException(nameof(geoinfo));
            }

            Dictionary <string, Color> result = new Dictionary <string, Color>();
            double L      = EarthModel.CalculateDistance(range.Position, pointCoordinates) / 1000;                                                            //расстояние вкилометрах между МС и точкой ВЭС
            double Hms    = geoinfo.GetElevation(range.Position);                                                                                             //высота точки МС
            double Hpoint = geoinfo.GetElevation(pointCoordinates);                                                                                           //высота точки ВЭС
            double Habs   = Math.Max(Hms, Hpoint);                                                                                                            //максимальная высота на у.м.
            double dH     = Math.Abs(Hpoint - Habs);                                                                                                          //перепад высот между МС и ВЭС
            StatisticalRange <WindDirections8> expectancy = StatisticEngine.GetDirectionExpectancy(range, GradationInfo <WindDirections8> .Rhumb8Gradations); //повторяемости скорости ветра по 8 румбам
            var maxes = expectancy.Values.OrderByDescending((d) => d).ToList();

            if (maxes[0] < 0.2) //если все румбы меньше 20%, то нет преобладающего направления
            {
                result.Add("Нет преобладающего направления ветра", Color.Black);
            }
            else//выбор преобладающих направлений ветра
            {
                var    dirs = GetRhumbsDominants(range, expectancy);
                string ln   = dirs.Aggregate("", (str, dir) => str + $"{dir.Description()} ({Math.Round(expectancy[dir] * 100, 2)}%), ").Trim(new char[] { ' ', ',' });
                result.Add("Преобладающие направления ветра: " + ln, Color.Black);
            }

            if (Hms > 750)
            {
                result.Add($"Высота точки МС больше 750 м над у. м. ({Hms:0.0} м), не рекомендуеся выполнять преобразование", Color.Red);
            }
            else if (Hpoint > 750)
            {
                result.Add($"Высота точки ВЭС больше 750 м над у. м. ({Hpoint:0.0} м), не рекомендуеся выполнять преобразование", Color.Red);
            }
            else
            {
                if (L > 50 && dH <= 750 && Habs <= 750) //макрорельеф
                {
                    result.Add($"Рекомендуется выбрать макрорельеф (L={L:0.0} км, Δh={dH:0.0} м)", Color.Green);
                }
                if (L > 3 && L <= 50 && dH <= 750 && Habs <= 750) //мезорельеф
                {
                    result.Add($"Рекомендуется выбрать мезорельеф (L={L:0.0} км, Δh={dH:0.0} м)", Color.Green);
                }
                if (L <= 3 && dH <= 80 && Habs <= 750) //микрорельеф
                {
                    result.Add($"Рекомендуется выбрать микрорельеф (L={L:0.0} км, Δh={dH:0.0} м)", Color.Green);
                }
            }

            return(result);
        }
コード例 #16
0
        /// <summary>
        /// Сохранение ВЭК в формате CSV
        /// </summary>
        /// <param name="filename"></param>
        /// <param name="range"></param>
        public override void SaveEnergyInfo(string filename, RawRange range)
        {
            List <object> years = new List <object>();

            foreach (RawItem item in range)
            {
                if (!years.Contains(item.Date.Year))
                {
                    years.Add(item.Date.Year);
                }
            }

            //формирование заголовка
            string cap = "Год;Месяц;кол-во изм";

            foreach (GradationItem grad in Vars.Options.CurrentSpeedGradation.Items)
            {
                cap += ";" + grad.Average.ToString("0.00");
            }
            cap += ";Vmin, м/с;Vmax, м/с;Vср, м/с;Vэкст50,м/с;Cv(V);𝜎(V);параметр γ;параметр β;Nвал уд., Вт/м^2;Эвал уд., Вт*ч/м^2";
            foreach (WindDirections16 wd in WindDirections16.Calm.GetEnumItems().GetRange(0, 17))
            {
                cap += ";" + wd.Description();
            }

            //запись в файл
            saveEnergyInfoLine(filename, null, null, null, null, cap, "", "", 0, false); //запись заголовка

            //запись данных обо всём периоде
            EnergyInfo ri1 = StatisticEngine.ProcessRange(range);
            StatisticalRange <WindDirections16> sd1 = StatisticEngine.GetDirectionExpectancy(range, GradationInfo <WindDirections16> .Rhumb16Gradations);
            StatisticalRange <GradationItem>    ss1 = StatisticEngine.GetExpectancy(range, Vars.Options.CurrentSpeedGradation);
            EnergyInfo ei1 = StatisticEngine.ProcessRange(ss1);

            saveEnergyInfoLine(filename, ri1, ei1, sd1, ss1, null, "Все года", "Все месяцы", range.Count, true);

            //запись данных для каждого года
            foreach (int year in years) //цикл по годам
            {
                //для каждого месяца в году
                for (int mt = 0; mt <= 12; mt++)//по месяцам, начиная со всех
                {
                    Months   month = (Months)mt;
                    RawRange rn    = range.GetRange(false, true, DateTime.Now, DateTime.Now, year, month.Description());
                    if (rn == null || rn.Count == 0)
                    {
                        continue;
                    }
                    EnergyInfo ri = StatisticEngine.ProcessRange(rn, range);
                    StatisticalRange <WindDirections16> sd = StatisticEngine.GetDirectionExpectancy(rn, GradationInfo <WindDirections16> .Rhumb16Gradations);
                    StatisticalRange <GradationItem>    ss = StatisticEngine.GetExpectancy(rn, Vars.Options.CurrentSpeedGradation);
                    EnergyInfo ei = StatisticEngine.ProcessRange(ss);
                    saveEnergyInfoLine(filename, ri, ei, sd, ss, null, year.ToString(), month.Description(), rn.Count, true);
                }
            }

            //запись данных по месяцам
            saveEnergyInfoLine(filename, null, null, null, null, ";", "", "", 0, true);
            saveEnergyInfoLine(filename, null, null, null, null, ";", "", "", 0, true);
            saveEnergyInfoLine(filename, null, null, null, null, ";", "", "", 0, true);
            for (int mt = 1; mt <= 12; mt++)//по месяцам, начиная со всех
            {
                Months   month = (Months)mt;
                RawRange rn    = range.GetRange(false, true, DateTime.Now, DateTime.Now, "Все", month.Description());
                if (rn == null || rn.Count == 0)
                {
                    continue;
                }
                EnergyInfo ri = StatisticEngine.ProcessRange(rn, range);
                StatisticalRange <WindDirections16> sd = StatisticEngine.GetDirectionExpectancy(rn, GradationInfo <WindDirections16> .Rhumb16Gradations);
                StatisticalRange <GradationItem>    ss = StatisticEngine.GetExpectancy(rn, Vars.Options.CurrentSpeedGradation);
                EnergyInfo ei = StatisticEngine.ProcessRange(ss);
                saveEnergyInfoLine(filename, ri, ei, sd, ss, null, "Все года", month.Description(), rn.Count, true);
            }
        }