public static float GetRefTemp(EarthModel earth, SimDateTime sdt, int r, int c)
        {
            string key = string.Format("{0}_{1}_{2}", sdt.DayOfYear, r, c);

            lock (_refTemp)
            {
                if (_refTemp.ContainsKey(key) == false)
                {
                    int lat = EarthModel.MaxLat - r;

                    float rt = GetRefTemp_ByLatitude_MidLevel(sdt, lat) + AbsoluteConstants.WaterFreezePoint;

                    float dt = rt - AbsoluteConstants.WaterFreezePoint;
                    float f  = 1.2f;

                    var wl = earth.SFC.WL[r, c];
                    if (wl == 0)
                    {
                        rt = AbsoluteConstants.WaterFreezePoint + dt * f;
                    }
                    else
                    {
                        rt = AbsoluteConstants.WaterFreezePoint + dt / f;
                    }

                    _refTemp.Add(key, rt - AbsoluteConstants.WaterFreezePoint);
                }

                return(_refTemp[key]);
            }
        }
Example #2
0
        public Atmosphere(EarthModel earth, bool loadFromStateFiles, float defaultValue = 0)
        {
            this.Earth = earth;

            SeaLevel = new SeaLevel(earth, loadFromStateFiles, defaultValue);
            MidLevel = new MidLevel(earth, loadFromStateFiles, defaultValue);
            TopLevel = new TopLevel(earth, loadFromStateFiles, defaultValue);
            JetLevel = new JetLevel(earth, loadFromStateFiles, defaultValue);

            if (loadFromStateFiles == false)
            {
                if (defaultValue == 0)
                {
                    TopLevel.LoadInitialConditions();

                    MidLevel.LoadInitialConditions();
                    CalculateAirMassType();

                    SeaLevel.LoadInitialConditions();
                }
                else
                {
                    AirMass = MatrixFactory.Init(defaultValue);
                }
            }
            else
            {
                AirMass = FileSupport.Load(Earth.UTC.Title, "M_00_MAP");
            }
        }
        public static float GetRefTempYearlyDelta_MidLevel(EarthModel earth, int r, int c)
        {
            string key = string.Format("{0}_{1}", r, c);

            lock (_refTempYearlyDelta)
            {
                if (_refTempYearlyDelta.ContainsKey(key) == false)
                {
                    float tRefMin = 100;
                    float tRefMax = -100;

                    SimDateTime sdtStart = earth.UTC;

                    for (int i = 0; i < 365; i += 5)
                    {
                        SimDateTime sdt  = sdtStart.AddHours((int)AbsoluteConstants.HoursPerDay * i);
                        float       tRef = GetRefTemp(earth, sdt, r, c);
                        tRefMin = Math.Min(tRefMin, tRef);
                        tRefMax = Math.Max(tRefMax, tRef);
                    }

                    float delta = (tRefMax - tRefMin);
                    _refTempYearlyDelta.Add(key, delta);
                }
            }

            return(_refTempYearlyDelta[key]);
        }
Example #4
0
        public Simulation(SimDateTime sdtStart, SimDateTime sdtEnd, int snaphotLength, bool loadFromStateFiles)
        {
            Start = sdtStart;
            End   = sdtEnd;

            _earth = new EarthModel(sdtStart, loadFromStateFiles, snaphotLength);
            _earth.Save(sdtStart.Title);
        }
        public SimDateTimeRangeStats(EarthModel earth)
        {
            MeanValues = new Atmosphere(earth, false, float.Epsilon);
            MinValues  = new Atmosphere(earth, false, float.MaxValue);
            MaxValues  = new Atmosphere(earth, false, float.MinValue);

            MeanValuesSFC = new SurfaceLevel(earth, false, float.Epsilon);
            MinValuesSFC  = new SurfaceLevel(earth, false, float.MaxValue);
            MaxValuesSFC  = new SurfaceLevel(earth, false, float.MinValue);
        }
Example #6
0
        public static bool SimBreakPoint(int r, int c, EarthModel model = null)
        {
            SimDateTime compareTo = new SimDateTime("2019-06-20_00");

#if HAVE_TESTSIMBREAKPOINT
            if (model == null || model.UTC.GetHoursOffset(compareTo) >= 0)
            {
                return(r == EarthModel.MaxLat - (int)SimConstants.TEST_Lat &&
                       c == EarthModel.MaxLon + (int)SimConstants.TEST_Lon);
            }
#endif
            return(false);
        }
Example #7
0
        /// <summary>
        /// найти все метеостанции из списка mts, которые находятся в радиусе radius от заданной точки coordinates
        /// </summary>
        /// <param name="coordinates"></param>
        /// <param name="radius"></param>
        /// <param name="addOwn">Если истина, то если точно в точке coordinates есть МС, то она тоже будет добавлена</param>
        /// <returns></returns>
        protected virtual List <BaseMeteostationInfo> GetNearestMS(PointLatLng coordinates, double radius, bool addOwn = false)
        {
            List <BaseMeteostationInfo> res = new List <BaseMeteostationInfo>();

            foreach (var ms in this.List.Cast <BaseMeteostationInfo>())
            {
                double dist = EarthModel.CalculateDistance(ms.Position, coordinates);
                if ((dist < radius && dist > COORDINATES_OVERLAP) || (dist < COORDINATES_OVERLAP && addOwn)) // если попадает в радиус и не совпадает или совпадает и надо добавлять
                {
                    res.Add(ms);
                }
            }
            return(res);
        }
Example #8
0
        /// <summary>
        /// найти ближайшую точку в словаре к заданной
        /// </summary>
        /// <param name="coordinates">заданная точка</param>
        /// <returns></returns>
        private PointLatLng getNearest(PointLatLng coordinates)
        {
            double      min = double.MaxValue;
            PointLatLng res = PointLatLng.Empty;

            foreach (var p in this.limits.Keys)
            {
                double f = EarthModel.CalculateDistance(p, coordinates);
                if (f < min)
                {
                    min = f;
                    res = p;
                }
            }
            return(res);
        }
        public static SimDateTimeRange BuildRange(SimDateTime dtStart, int rangeSize)
        {
            EarthModel earth = new EarthModel(dtStart, true, (int)AbsoluteConstants.HoursPerDay);

            if (SimulationData.AvailableSnapshots.Contains(dtStart))
            {
                SimDateTime sdt   = dtStart.AddHours((rangeSize - 1) * earth.SnapshotLength);
                SimDateTime dtEnd = SimulationData.SelectNearestSnapshot(sdt);

                if (dtEnd != null)
                {
                    return(new SimDateTimeRange(earth, dtStart, dtEnd));
                }
            }

            return(null);
        }
Example #10
0
        /// <summary>
        /// на основе ряда наблюдений на высоте 10м подобрать АМС и выбрать ряд коэффициентов m для поднятия скорости на высоту
        /// </summary>
        /// <param name="range">ряд наблюдений на МС</param>
        /// <param name="coordinates">координаты ряда</param>
        /// <param name="MSMeteostations">БД АМС</param>
        /// <param name="searchRadius">расстояние для фильтрации АМС в метрах. Если задано NaN, то фильтрация по расстоянию проводить не будет</param>
        /// <param name="maximalRelativeSpeedDeviation">максимальное среднеквадратичное отклонение относительной скорости. NaN, если не надо учитывать</param>
        /// <returns></returns>
        public static SuitAMSResult GetSuitAMS(RawRange range, PointLatLng coordinates, AMSMeteostationDatabase MSMeteostations, double searchRadius, double maximalRelativeSpeedDeviation)
        {
            //посчитать среднемесячные относительные скорости для МС
            //выбрать АМС из заданного радиуса
            //посчитать относительные скорости на всех АМС
            //найти наиболее подходящую АМС по наименьшему среднеквадратичному отклонению относительных скоростей

            //относительные среднемесячные скорости на МС
            Dictionary <Months, double> msRelatives = getRelativeAverageMonthSpeeds(range, out bool allMonth);

            //выбор АМС в заданном радиусе
            List <AMSMeteostationInfo> amss = double.IsNaN(searchRadius) ? MSMeteostations.List : MSMeteostations.GetNearestMS(coordinates, searchRadius, true); //выбираем все АМС в радиусе

            if (amss == null)
            {
                return(null);
            }

            //поиск АМС с минимальным среднеквадр отклонением относительных скоростей
            SuitAMSResult     res     = new SuitAMSResult();
            double            minDev  = double.MaxValue;
            SuitAMSResultItem minItem = null;

            foreach (AMSMeteostationInfo ams in amss)
            {
                SuitAMSResultItem item = new SuitAMSResultItem();
                item.Deviation         = Math.Sqrt(msRelatives.Average((kv) => { return(Math.Pow(kv.Value - ams.RelativeSpeeds[kv.Key], 2)); })); //корень(среднее ((KjМС - KjАМС)^2)), j - номер месяца
                item.AMS               = ams;
                item.AllMonthInRange   = allMonth;
                item.IsDeviationFailed = !double.IsNaN(maximalRelativeSpeedDeviation) && item.Deviation > maximalRelativeSpeedDeviation;
                item.Distance          = EarthModel.CalculateDistance(coordinates, ams.Position);
                res.Add(item);

                //ищем минимальный элемент
                if (minDev > item.Deviation)
                {
                    minDev  = item.Deviation;
                    minItem = item;
                }
            }

            res.AllMonthInRange          = allMonth;
            res.RangeRelativeSpeeds      = msRelatives;
            res.ItemWithMinimalDeviation = minItem;
            return(res);
        }
        public AtmosphericLevel(EarthModel earth, int levelType, bool loadFromStateFiles, float defaultValue = 0)
        {
            this.Earth = earth;
            _levelType = levelType;

            if (loadFromStateFiles)
            {
                P = FileSupport.Load(Earth.UTC.Title, string.Format("P_{0:d2}_MAP", _levelType));
                T = FileSupport.Load(Earth.UTC.Title, string.Format("T_{0:d2}_MAP", _levelType));
                H = FileSupport.Load(Earth.UTC.Title, string.Format("H_{0:d2}_MAP", _levelType));
            }
            else if (defaultValue != 0)
            {
                P = MatrixFactory.Init(defaultValue);
                T = MatrixFactory.Init(defaultValue);
                H = MatrixFactory.Init(defaultValue);
            }
        }
Example #12
0
        /// <summary>
        /// найти ближайшую МС для заданных координат и в заданном радиусе от точки
        /// </summary>
        /// <param name="coordinates"></param>
        /// <param name="maxRadius">радиус поиска в метрах</param>
        /// <returns></returns>
        protected virtual BaseMeteostationInfo GetNearestMS(PointLatLng coordinates, double maxRadius = double.MaxValue)
        {
            if (coordinates.IsEmpty)
            {
                return(null);
            }
            BaseMeteostationInfo res = null;
            bool   useMaxRadius      = maxRadius != double.MaxValue;
            double min = double.MaxValue;

            foreach (var p in this.List.Cast <BaseMeteostationInfo>())
            {
                double f = EarthModel.CalculateDistance(p.Position, coordinates);
                if (f < COORDINATES_OVERLAP)
                {
                    // ближайшая метеостанция не должна быть той же самой
                    continue;
                }
                if (useMaxRadius)
                {
                    if (f < min && f > COORDINATES_OVERLAP && f < maxRadius)
                    {
                        min = f;
                        res = p;
                    }
                }
                else
                {
                    if (f < min)
                    {
                        min = f;
                        res = p;
                    }
                }
            }
            if (min == double.MaxValue)
            {
                return(null);
            }
            return(res);
        }
        public SimDateTimeRange(EarthModel earth, SimDateTime dtStart, SimDateTime dtEnd)
        {
            this.Start = dtStart;
            this.End   = dtEnd;
            this.Earth = earth;

            AtmList = new List <Atmosphere>();
            SfcList = new List <SurfaceLevel>();

            for (SimDateTime sdt = dtStart; sdt.CompareTo(dtEnd) <= 0; sdt = sdt.AddHours(earth.SnapshotLength))
            {
                Atmosphere   atm = null;
                SurfaceLevel sfc = null;

                try
                {
                    earth.SetUTC(sdt);
                    atm = new Atmosphere(earth, true);
                    sfc = new SurfaceLevel(earth, true);
                }
                catch
                {
                    atm = null;
                    sfc = null;
                }

                if (atm != null)
                {
                    AtmList.Add(atm);
                }
                if (sfc != null)
                {
                    SfcList.Add(sfc);
                }
            }
        }
 public static DenseMatrix GetRefTemp(EarthModel earth)
 {
     return(MatrixFactory.New((r, c) => GetRefTemp(earth, r, c)));
 }
Example #15
0
        /// <summary>
        /// ищет наиболее подходящую к заданной точке МС и получает её ряд. Если ряд не найден, то возвращает null
        /// </summary>
        /// <param name="coordinates"></param>
        /// <param name="r"></param>
        /// <param name="actionPercent"></param>
        /// <param name="Range">ряд, для которого подбирается функция</param>
        /// <exception cref="GetBaseRangeException">Возвращает иснформацию о параметрах, мешающих получить ближайшую МС</exception>
        /// <returns></returns>
        internal static RawRange TryGetBaseRange(RawRange Range, PointLatLng coordinates, out double r, Action <int, string> actionPercent)
        {
            bool nlaw = CheckNormalLaw(Range, Vars.Options.NormalLawPirsonCoefficientDiapason);

            if (!nlaw)
            {
                throw new WindEnergyException("Исходный ряд не подчиняется нормальному закону распределения");
            }

            DateTime from = Range.Min((ri) => ri.Date).Date, to = Range.Max((ri) => ri.Date).Date;

            List <RP5MeteostationInfo>  mts = Vars.RP5Meteostations.GetNearestMS(coordinates, Vars.Options.NearestMSRadius, false);
            Dictionary <double, double> funcSpeed = Range.GetFunction(MeteorologyParameters.Speed); //функция скорости на заданном ряде
            RawRange res = null;
            double   rmax = double.MinValue, total_rmax = double.MinValue;
            RP5ru    provider = new RP5ru(Vars.Options.CacheFolder + "\\rp5.ru");

            for (int i = 0; i < mts.Count; i++)
            {
                if (actionPercent != null)
                {
                    actionPercent.Invoke((int)((i * 1d / mts.Count) * 100d), "Поиск подходящей МС...");
                }

                RP5MeteostationInfo m = mts[i];

                //если нет диапазона измерений в БД, то загружаем с сайта
                if (m.MonitoringFrom == DateTime.MinValue)
                {
                    provider.GetMeteostationExtInfo(ref m);
                }

                //если для этой МС нет наблюдений в этом периоде, то переходим на другую
                if (m.MonitoringFrom > from)
                {
                    continue;
                }

                //загрузка ряда с очередной МС
                RawRange curRange = null;
                try
                { curRange = provider.GetRange(from, to, m); }
                catch (WindEnergyException wex) // если не удалось получить ряд этой МС, то переходим к следующей
                { continue; }


                curRange = new Checker().ProcessRange(curRange, new CheckerParameters(LimitsProviders.StaticLimits, curRange.Position), out CheckerInfo info, null); //исправляем ошибки


                //СКОРОСТЬ
                MeteorologyParameters parameter = MeteorologyParameters.Speed;

                Dictionary <double, double> funcSpeedCurrentNearest = curRange.GetFunction(parameter); //функция скорости на текущей МС

                //проверка на нормальный закон распределения
                bool normal = CheckNormalLaw(curRange, Vars.Options.NormalLawPirsonCoefficientDiapason);
                if (!normal)
                {
                    continue;
                }

                //расчёт и проверка коэфф корреляции
                List <double>[] table     = calcTableCoeff(funcSpeed, funcSpeedCurrentNearest); //таблица для расчет коэффициентов
                double          current_r = getParameterR(table);                               //коэффициент корреляции

                //общий максимальный коэфф корреляции
                if (current_r > total_rmax)
                {
                    total_rmax = current_r;
                }

                //проверяем, можно ли взять эту МС
                if (current_r > rmax)
                {
                    //истина, если надо проверять этот параметр на допустимый диапазон корреляции
                    bool needCheck = Vars.Options.MinimalCorrelationControlParametres.Contains(parameter);
                    if ((needCheck && current_r >= Vars.Options.MinimalCorrelationCoeff) || !needCheck)
                    {
                        rmax = current_r;
                        res  = curRange;
                    }
                }
            }
            r = rmax;
            if (res == null)
            {
                RP5MeteostationInfo mi = Vars.RP5Meteostations.GetNearestMS(coordinates);
                double l = EarthModel.CalculateDistance(mi.Position, coordinates);
                throw new GetBaseRangeException(total_rmax, Vars.Options.MinimalCorrelationCoeff, l, mts.Count, Vars.Options.NearestMSRadius, coordinates);
            }
            return(res);
        }
Example #16
0
        /// <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);
        }
 public static DenseMatrix GetRefTempYearlyDelta_MidLevel(EarthModel earth)
 {
     return(MatrixFactory.New((r, c) => GetRefTempYearlyDelta_MidLevel(earth, r, c)));
 }
 public static float GetRefTemp(EarthModel earth, int r, int c)
 {
     return(GetRefTemp(earth, earth.UTC, r, c));
 }