Пример #1
0
        private void buttonElevate_Click(object sender, EventArgs e)
        {
            Cursor = Cursors.WaitCursor;

            if (!double.TryParse(textBoxToHeight.Text.Trim().Replace('.', Constants.DecimalSeparator), out double new_height))
            {
                _ = MessageBox.Show(this, $"Не удалось распознать {textBoxToHeight.Text} как число", "Расчет скорости ветра на высоте башни ВЭУ", MessageBoxButtons.OK, MessageBoxIcon.Warning); return;
            }
            if (!double.TryParse(textBoxFromHeight.Text.Trim().Replace('.', Constants.DecimalSeparator), out double old_height))
            {
                _ = MessageBox.Show(this, $"Не удалось распознать {textBoxFromHeight.Text} как число", "Расчет скорости ветра на высоте башни ВЭУ", MessageBoxButtons.OK, MessageBoxIcon.Warning); return;
            }
            if (!double.TryParse(textBoxRadius.Text.Trim().Replace('.', Constants.DecimalSeparator), out double radius))
            {
                _ = MessageBox.Show(this, $"Не удалось распознать {textBoxRadius.Text} как число", "Расчет скорости ветра на высоте башни ВЭУ", MessageBoxButtons.OK, MessageBoxIcon.Warning); return;
            }
            if (!double.TryParse(textBoxCoeffM.Text.Trim().Replace('.', Constants.DecimalSeparator), out double m))
            {
                _ = MessageBox.Show(this, $"Не удалось распознать {textBoxCoeffM.Text} как число", "Расчет скорости ветра на высоте башни ВЭУ", MessageBoxButtons.OK, MessageBoxIcon.Warning); return;
            }

            radius *= 1000; //перевод км в метры

            if (hellmanCoeffSource == HellmanCoefficientSource.None)
            {
                _ = MessageBox.Show(this, "Что-то пошло не так, попробуйте другие настройки", "Расчет скорости ветра на высоте башни ВЭУ", MessageBoxButtons.OK, MessageBoxIcon.Warning);
            }

            Action <int> action = new Action <int>((percent) =>
            {
                try
                {
                    if (this.InvokeRequired)
                    {
                        _ = Invoke(new Action(() => { progressBar1.Value = percent; }));
                    }
                    else
                    {
                        progressBar1.Value = percent;
                    }
                }
                catch (Exception) { }
            });

            Action <RawRange, SuitAMSResultItem> actionAfter = new Action <RawRange, SuitAMSResultItem>((rawRange, selectedAMS) =>
            {
                _ = this.Invoke(new Action(() =>
                {
                    string AMStext = selectedAMS != null ? $"На основе данных АМС {selectedAMS.AMS.Name} {selectedAMS.AMS.Position}\r\nОтклонение среднемесячных скоростей: {selectedAMS.Deviation:0.000} {(selectedAMS.AllMonthInRange ? "" : "\r\nВНИМАНИЕ!! В исходном ряде представлены не все месяцы. Поэтому подбор подходящей АМС может быть неточным")}" : "";
                    rawRange.Name  = "Ряд на высоте " + new_height + " м";
                    _ = MessageBox.Show(this, $"Скорости ветра пересчитаны на высоту {new_height} м\r\n{((!string.IsNullOrWhiteSpace(AMStext)) ? AMStext : "")}", "Расчет скорости ветра на высоте башни ВЭУ", MessageBoxButtons.OK, MessageBoxIcon.Information);

                    if (rawRange == null)
                    {
                        DialogResult = DialogResult.Cancel;
                    }
                    else
                    {
                        DialogResult = DialogResult.OK;
                        Result       = rawRange;
                    }
                    Cursor = Cursors.Arrow;
                    Result = rawRange;
                    Close();
                }));
            });

            try
            {
                //если в ряде нет координат и надо искать АМС-аналог, то выбираем (для подбора подходящей АМС)
                if (range.Position.IsEmpty && hellmanCoeffSource == HellmanCoefficientSource.AMSAnalog)
                {
                    FormSelectMapPointDialog fsp = new FormSelectMapPointDialog("Выберите координаты ряда " + range.Name, PointLatLng.Empty, Vars.Options.CacheFolder, Resources.rp5_marker, Vars.Options.MapProvider);
                    if (fsp.ShowDialog(this) == DialogResult.OK)
                    {
                        range.Position = fsp.Result;
                    }
                    else
                    {
                        Cursor = Cursors.Arrow;
                        return;
                    }
                }

                //основные параметры пересчета ряда на высоту
                ElevatorParameters parameters = new ElevatorParameters()
                {
                    FromHeight   = old_height,
                    ToHeight     = new_height,
                    Coordinates  = range.Position,
                    SearchRaduis = checkBoxUseRadius.Checked ? radius : double.NaN,
                    MaximalRelativeSpeedDeviation = Vars.Options.UseSuitAMSMaximalRelativeSpeedDeviation ? Vars.Options.SuitAMSMaximalRelativeSpeedDeviation : double.NaN,
                    CustomMCoefficient            = checkBoxCustomCoeffM.Checked ? m : double.NaN,
                    CustomMCoefficientMonths      = MonthsHellmanValues,
                    HellmanCoefficientSource      = hellmanCoeffSource
                };

                //если способ пересчета АМС-аналог, то надо предоставить выбор АМС для расчетов
                if (hellmanCoeffSource == HellmanCoefficientSource.AMSAnalog)
                {
                    //находим все подходящие АМС
                    SuitAMSResult suitAMSList = AMSSupport.GetSuitAMS(
                        range,
                        range.Position,
                        Vars.AMSMeteostations,
                        checkBoxUseRadius.Checked ? radius : double.NaN,
                        Vars.Options.UseSuitAMSMaximalRelativeSpeedDeviation ? Vars.Options.SuitAMSMaximalRelativeSpeedDeviation : double.NaN
                        );

                    //открывам диалоговое окно списка АМС
                    FormRangeElevatorConfirmation frec = new FormRangeElevatorConfirmation(suitAMSList);
                    if (frec.ShowDialog(this) == DialogResult.OK)
                    {
                        parameters.SelectedAMS = frec.Result;
                    }
                    else //если ничего не выбрали, то выходим
                    {
                        Cursor = Cursors.Arrow;
                        return;
                    }
                }

                RangeElevator.ProcessRange(range, parameters, action, actionAfter); //запускаем обработку ряда
            }
            catch (WebException exc)
            {
                Cursor       = Cursors.Arrow;
                _            = MessageBox.Show(this, exc.Message, "Расчет скорости ветра на высоте башни ВЭУ", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                DialogResult = DialogResult.Cancel;
            }
            catch (WindEnergyException wex)
            {
                Cursor = Cursors.Arrow;
                _      = MessageBox.Show(this, wex.Message, "Расчет скорости ветра на высоте башни ВЭУ", MessageBoxButtons.OK, MessageBoxIcon.Warning);
            }
            catch (ApplicationException exc)
            {
                Cursor       = Cursors.Arrow;
                _            = MessageBox.Show(this, exc.Message + "\r\nПопробуйте уменьшить длину ряда", "Расчет скорости ветра на высоте башни ВЭУ", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                DialogResult = DialogResult.Cancel;
            }
            catch (Exception ex)
            {
                Cursor       = Cursors.Arrow;
                _            = MessageBox.Show(this, "Произошла ошибка:\r\n" + ex.Message, this.Text, MessageBoxButtons.OK, MessageBoxIcon.Warning);
                DialogResult = DialogResult.Cancel;
            }
        }
Пример #2
0
        /// <summary>
        /// основной расчет для ВЭУ по заданному ряду
        /// </summary>
        /// <param name="range"></param>
        /// <param name="equipment"></param>
        /// <param name="h"></param>
        /// <param name="startHeight"></param>
        /// <param name="ams">выбранная АМС для пересчета на высоту или null, если не надо проводить пересчет</param>
        /// <param name="needRecalcWithAirDensity"></param>
        /// <returns></returns>
        public async static Task <PowerCalculatorResult> Calculate(RawRange range, EquipmentItemInfo equipment, double h, double startHeight, SuitAMSResultItem ams, bool needRecalcWithAirDensity)
        {
            //пересчитать ряд на высоту h (считаем, что ряд на высоте startHeight)
            //расчитать  Ni для каждого наблюдения
            //расчитать основные показатели Э, kиум, Эуд, hиум
            //расчитать кривую обеспеченности

            //проверка, надо ли пересчитывать скорости ветра на высоту
            RawRange altedRange;

            if (ams != null)
            {
                altedRange = await RangeElevator.ProcessRange(range, new ElevatorParameters()
                {
                    ToHeight    = h,
                    Coordinates = range.Position,
                    HellmanCoefficientSource = HellmanCoefficientSource.AMSAnalog,
                    SelectedAMS = ams,
                    FromHeight  = startHeight
                });
            }
            else
            {
                altedRange = range;
            }

            //если надо, то пересчитываем мощностную характеристику с учетом плотности воздуха
            Dictionary <double, double> characteristic;

            if (needRecalcWithAirDensity)
            {
                characteristic = RecalcPerfomanceCharacteristicWithAirDensity(range.AirDensity, equipment.PerformanceCharacteristic, equipment);
            }
            else
            {
                characteristic = equipment.PerformanceCharacteristic;
            }

            //расчет мощности для каждого наблюдения и годовой выработки
            LinearInterpolateMethod       interpolator    = new LinearInterpolateMethod(characteristic);
            Dictionary <double, double>   production      = new Dictionary <double, double>();
            Dictionary <DateTime, double> productionRange = new Dictionary <DateTime, double>();
            Dictionary <Months, double>   energyByMonth   = new Dictionary <Months, double>();
            double totalE = 0;

            for (int i = 0; i < altedRange.Count; i++)
            {
                RawItem item = altedRange[i];
                double  N;
                if (!interpolator.InBounds(item.Speed))
                {
                    N = 0; //мощность в кВт
                }
                else
                {
                    N = interpolator.GetValue(item.Speed); //мощность в кВт
                }
                production.Add(item.DateArgument, N);
                productionRange.Add(item.Date, N);

                //расчет выработки
                if (i > 0)
                {
                    double energyBit = N * (item.DateArgument - altedRange[i - 1].DateArgument) / 60; //перевод в часы (DateArgumet в минутах)
                    totalE += energyBit;                                                              //суммарная выработка в кВт*ч

                    //выработка по месяцам
                    Months month = (Months)item.Date.Month;
                    if (energyByMonth.ContainsKey(month))
                    {
                        energyByMonth[month] += energyBit;
                    }
                    else
                    {
                        energyByMonth.Add(month, energyBit);
                    }
                }
            }

            //поскольку ряд мб произвольной длины, то надо привести выработку к среднегодовой
            //коэффициент пересчета к одному году
            double yearKoeff = 8760 / ((altedRange.Last().Date - altedRange.First().Date).TotalHours);
            double E         = totalE * yearKoeff;

            //коэфф использования установленной мощности
            double kium = E / (equipment.Power * 8760); //выработка уже приведена к году, используем как есть

            //удельная выработка
            double Edensity = E / (Math.PI * Math.Pow(equipment.Diameter, 2) / 4); // Эгод/Fом

            //число часов использования установленной мощности
            double hium = E / equipment.Power; //выработка уже приведена к году, используем как есть

            PowerCalculatorResult result = new PowerCalculatorResult()
            {
                YearEnergy      = E,
                TotalEnergy     = totalE,
                EnergyByMonth   = energyByMonth,
                EDensity        = Edensity,
                Kium            = kium,
                Hium            = hium,
                SupportingPower = calculateSupportingPower(production),
                Production      = productionRange,
                Equipment       = equipment,
                TowerHeight     = h,
                Range           = range
            };

            return(result);
        }