Exemple #1
0
        public const double NOMINAL_AIR_DENSITY = 1.2041; //  кг/м3

        /// <summary>
        /// расчет мощностной характеристики на основе основных параметров ВЭУ
        /// </summary>
        /// <param name="selectedEquipment"></param>
        /// <returns></returns>
        public static Dictionary <double, double> CalculatePerformanceCharacteristic(EquipmentItemInfo selectedEquipment)
        {
            if (!selectedEquipment.EnoughDataToCalculateCharacteristic)
            {
                throw new WindEnergyException("Недостаточно данных для расчета мощностной характеристики");
            }

            LinearInterpolateMethod interpolator = new LinearInterpolateMethod(new Dictionary <double, double>()
            {
                { 0, 0 },
                { selectedEquipment.MinWindSpeed, 0 },
                { selectedEquipment.NomWindSpeed, selectedEquipment.Power },
                { selectedEquipment.MaxWindSpeed, selectedEquipment.Power },
                { selectedEquipment.MaxWindSpeed + MIN_WIND_SPEED_STEP, 0 },
                { 31, 0 },
            });

            Dictionary <double, double> res = new Dictionary <double, double>();

            for (double speed = 1; speed <= 30; speed++)
            {
                res.Add(speed, interpolator.GetValue(speed));
            }
            return(res);
        }
Exemple #2
0
        /// <summary>
        /// выбор микроклиматического коэффициента рельефа по средней скорости и стратификации атмосферы
        /// </summary>
        /// <param name="speed">скорость ветра </param>
        /// <param name="microclimateCoefficient"></param>
        /// <param name="atmosphereStratification"></param>
        /// <returns></returns>
        private static double selectMicroclimateCoefficient(double speed, MicroclimateItemInfo microclimateCoefficient, AtmosphereStratification atmosphereStratification)
        {
            Diapason <double> diap;
            double            res;

            if (speed <= 5)
            {
                diap = atmosphereStratification == AtmosphereStratification.Stable ? microclimateCoefficient.Stable_3_5 : microclimateCoefficient.Unstable_3_5;
                res  = LinearInterpolateMethod.LinearInterpolation(3, 5, diap.From, diap.To, speed);
            }
            else
            {
                diap = atmosphereStratification == AtmosphereStratification.Stable ? microclimateCoefficient.Stable_6_20 : microclimateCoefficient.Unstable_6_20;
                res  = LinearInterpolateMethod.LinearInterpolation(6, 20, diap.From, diap.To, speed);
            }

            if (res < 0)
            {
                throw new Exception("Отрицательный коэффициент после интерполяции");
            }
            return(res);
        }
        private void buttonSave_Click(object sender, EventArgs e)
        {
            if (Result.Count == 0)
            {
                _ = MessageBox.Show(this, "Для сохранения надо добавить хотя бы одну точку в характеристику", "Редактирование мощностной характеристики", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                return;
            }

            Result[0]            = 0;
            Result[maxSpeed + 1] = 0;
            LinearInterpolateMethod interpolator = new LinearInterpolateMethod(Result);

            for (int i = 1; i <= maxSpeed; i++)
            {
                Result[i] = interpolator.GetValue(i);
            }

            _ = Result.Remove(0);
            _ = Result.Remove(maxSpeed + 1);

            this.DialogResult = DialogResult.OK;
            Close();
        }
Exemple #4
0
        /// <summary>
        /// подготовка функций для интерполирования
        /// </summary>
        private void prepareIterpolators()
        {
            if (param.Method == InterpolateMethods.NearestMeteostation && param.Coordinates.IsEmpty)
            {
                throw new Exception("Для этого метода интерполяции необходимо указать расчетную точку на карте");
            }

            //ПОДГОТОВКА ФУНКЦИЙ

            Dictionary <double, double>
            speedFunc       = new Dictionary <double, double>(), //функция скорости
                directsFunc = new Dictionary <double, double>(), //функция направления
                wetFunc     = new Dictionary <double, double>(), //функция влажности
                tempFunc    = new Dictionary <double, double>(), //функция температуры
                pressFunc   = new Dictionary <double, double>(); //функция давления



            //заполнение известными значениями функции
            foreach (var item in Range)
            {
                double timeStamp = item.DateArgument;
                if (speedFunc.ContainsKey(timeStamp))
                {
                    throw new ApplicationException("В ряде наблюдений есть повторяющиеся даты. Восстановление невозможно, попробуйте проверить ряд на ошибки.");
                }
                if (!double.IsNaN(item.Speed))
                {
                    speedFunc.Add(timeStamp, item.Speed);
                }
                if (!double.IsNaN(item.Direction) && item.Direction > 0)
                {
                    directsFunc.Add(timeStamp, item.Direction);
                }
                if (!double.IsNaN(item.Wetness))
                {
                    wetFunc.Add(timeStamp, item.Wetness);
                }
                if (!double.IsNaN(item.Temperature))
                {
                    tempFunc.Add(timeStamp, item.Temperature);
                }
                if (!double.IsNaN(item.Pressure))
                {
                    pressFunc.Add(timeStamp, item.Pressure);
                }
            }

            //ПОДГОТОВКА ИНТЕРПОЛЯТОРОВ
            //создание интерполяторов функций скорости, направления, температуры, влажности

            switch (param.Method)
            {
            case InterpolateMethods.Linear:
                methodSpeeds  = new LinearInterpolateMethod(speedFunc);
                methodDirects = new LinearInterpolateMethod(directsFunc);
                methodTemp    = new LinearInterpolateMethod(tempFunc);
                methodWet     = new LinearInterpolateMethod(wetFunc);
                methodPress   = new LinearInterpolateMethod(pressFunc);
                break;

            case InterpolateMethods.Stepwise:
                methodSpeeds  = new StepwiseInterpolateMethod(speedFunc);
                methodDirects = new StepwiseInterpolateMethod(directsFunc);
                methodTemp    = new StepwiseInterpolateMethod(tempFunc);
                methodWet     = new StepwiseInterpolateMethod(wetFunc);
                methodPress   = new StepwiseInterpolateMethod(pressFunc);
                break;

            case InterpolateMethods.NearestMeteostation:
                if (param.BaseRange != null)
                {
                    //проверяем заданный ряд на возможность восстановления с помощью него
                    bool f = NearestMSInterpolateMethod.CheckNormalLaw(param.BaseRange, Vars.Options.NormalLawPirsonCoefficientDiapason);
                    if (f)
                    {
                        baseRange = param.BaseRange;
                    }
                    else
                    {
                        throw new WindEnergyException("Этот ряд не может быть использован так как он не подчиняется нормальному закону распределения");
                    }
                }
                else
                {
                    //ищем подходящую МС из ближайших и получаем её ряд. Если подходит, то ошибки нет
                    baseRange = NearestMSInterpolateMethod.TryGetBaseRange(Range, param.Coordinates, out r, null);
                }

                methodSpeeds  = new NearestMSInterpolateMethod(speedFunc, baseRange, MeteorologyParameters.Speed, param.ReplaceExistMeasurements);
                methodDirects = new LinearInterpolateMethod(directsFunc);
                methodTemp    = new LinearInterpolateMethod(tempFunc);
                methodWet     = new LinearInterpolateMethod(wetFunc);
                methodPress   = new LinearInterpolateMethod(pressFunc);
                break;

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

            //новый интервал наблюдений в минутах
            int newInterval = (int)param.Interval;

            //метки времени для нового ряда
            newRangeX = new List <double>();
            double start = speedFunc.Keys.Min();
            double end   = speedFunc.Keys.Max();

            for (double i = start; i <= end; i += newInterval)
            {
                newRangeX.Add(i);
            }
        }
Exemple #5
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);
        }