Пример #1
0
        public void CalculateTotalPrecipitation()
        {
            var GP = Earth.ATM.MidLevel.P.Gradient2().Rescale(new float[] { 0, 100 });
            var GT = Earth.ATM.MidLevel.T.Gradient2().Rescale(new float[] { 0, 100 });
            var TS = Earth.SFC.TS;
            var TE = Earth.SFC.TE;

            DenseMatrix WIND = MatrixFactory.Init();

            if (Earth.ATM.SeaLevel.P != null)
            {
                WIND = Earth.ATM.SeaLevel.P.Gradient2();
            }

            var HMid = Earth.ATM.MidLevel.H;
            var HSea = Earth.ATM.SeaLevel.H;

            if (HSea == null)
            {
                HSea = HMid;
            }

            var eqFronts = Earth.ATM.Fronts;//.EQ();

            // Calculate convective precipitation (thunderstorms)
            CalculateInstabilityIndex(eqFronts);

            var FP = Earth.ATM.JetLevel.FP;

            Precip.Assign((r, c) =>
            {
                var hgt = Earth.SFC.Height[r, c];
                float h = 0;

                var hTop = Earth.ATM.TopLevel.H[r, c];
                var hMid = Earth.ATM.MidLevel.H[r, c];
                var hSea = Earth.ATM.SeaLevel.H[r, c];

                if (hgt > SimConstants.LevelHeights[LevelType.TopLevel])
                {
                    h = 0.5f * hTop;
                }
                else if (hgt > SimConstants.LevelHeights[LevelType.MidLevel])
                {
                    h = 0.5f * (hTop + hMid);
                }
                else
                {
                    h = 0.5f * (hSea + hMid);
                }

                var lidx = LIDX[r, c];
                var gp   = GP[r, c];
                var gt   = GT[r, c];
                var fp   = FP[r, c];

                // Baric gradient precipitation
                var pRate = 0.5f * Math.Abs(gp);

                // Frontal precipitation
                var f     = eqFronts[r, c];
                var dx    = (f > 0) ? 0.75f : 1.5f;
                var fRate = dx * 20 * Math.Abs(f);

                // Orographic precipitation
                var oRate = 0.3f * ((hgt >= 900) ? h : 0);

                // Convective precipitation
                var cRate = 0f;
                if (lidx < 0)
                {
                    var lidxRate = Math.Abs(lidx);

                    var mul = 1;
                    if (lidx > 3)
                    {
                        mul = 2;
                    }
                    if (lidx > 5)
                    {
                        mul = 3;
                    }
                    if (lidx > 7)
                    {
                        mul = 4;
                    }
                    if (lidx > 9)
                    {
                        mul = 5;
                    }

                    cRate = fp * mul * Math.Abs(lidxRate);
                }

                var totalRate = (pRate + fRate + oRate + cRate) * h / 100;

                return(Math.Min(300, totalRate));
            });


            DenseMatrix SolidPrecip = MatrixFactory.Init();

            for (int r = 0; r < SolidPrecip.RowCount; r++)
            {
                for (int c = 0; c < SolidPrecip.ColumnCount; c++)
                {
                    var wl  = WL[r, c];
                    var ts  = TS[r, c];
                    var te  = TE[r, c];
                    var cl  = Precip[r, c];
                    var t01 = Earth.ATM.MidLevel.T[r, c];

                    var totalRain = RAIN[r, c];
                    var totalSnow = SNOW[r, c];

                    var fogMeltFactor = Math.Min(1, 1 - FOG[r, c] / 100);

                    const float precipClThreshold = 10f;

                    if (te >= -10f || cl <= precipClThreshold)
                    {
                        if (te >= 0)
                        {
                            // Accumulated soil moisture evaporation
                            totalRain -= 0.5f * te * Earth.SnapshotLength;
                            if (totalRain < 0)
                            {
                                totalRain = 0;
                            }

                            // Old snow cover is melting and transforming into water
                            // OBS: Snow melts faster when we have fog
                            var meltedSnow = Math.Min(totalSnow, 0.2f * (1 + fogMeltFactor) * te * Earth.SnapshotLength);
                            totalSnow -= meltedSnow;
                            if (totalSnow < 0)
                            {
                                totalSnow = 0;
                            }

                            // Consider melted snow as rain because it contributes to the total soil moisture
                            totalRain += meltedSnow;
                        }
                        else
                        {
                            // Old snow cover is slowly compacting due to daytime melt / night time freeze
                            totalSnow -= 0.025f * (1 + fogMeltFactor) * Earth.SnapshotLength;

                            if (totalSnow < 0)
                            {
                                totalSnow = 0;
                            }
                        }
                    }

                    DaysSinceLastRainFall[r, c] = (DaysSinceLastRainFall[r, c] + Earth.SnapshotDivFactor);
                    DaysSinceLastSnowFall[r, c] = (DaysSinceLastSnowFall[r, c] + Earth.SnapshotDivFactor);

                    float actualPrecipRate = (cl - precipClThreshold);
                    if (actualPrecipRate > 0)
                    {
                        var unitPrecipFall = actualPrecipRate * Earth.SnapshotDivFactor;

                        PrecipTypeComputer <float> .Compute(

                            // Actual temperatures
                            te, ts, t01,

                            // Boundary temperatures as read from simulation parameters
                            SimulationParameters.Instance,

                            // Computed precip type: snow
                            () =>
                        {
                            totalSnow                  += 0.3f * unitPrecipFall;
                            SolidPrecip[r, c]           = 1;
                            DaysSinceLastSnowFall[r, c] = 0;
                            return(0);
                        },

                            // Computed precip type: rain
                            () =>
                        {
                            totalRain += unitPrecipFall;
                            DaysSinceLastRainFall[r, c] = 0;
                            return(0);
                        },

                            // Computed precip type: freezing rain
                            () =>
                        {
                            totalSnow                  += 0.1f * unitPrecipFall;
                            totalRain                  += 0.9f * unitPrecipFall;
                            SolidPrecip[r, c]           = 1;
                            DaysSinceLastSnowFall[r, c] = 0;
                            return(0);
                        },

                            // Computed precip type: sleet
                            () =>
                        {
                            totalSnow                  += 0.2f * unitPrecipFall;
                            totalRain                  += 0.8f * unitPrecipFall;
                            SolidPrecip[r, c]           = 1;
                            DaysSinceLastSnowFall[r, c] = 0;
                            return(0);
                        }
                            );
                    }

                    if (totalSnow < 0 ||
                        // Snow does not accumulate on a water surface if water is not frozen
                        (wl != 0 && ts > 0))
                    {
                        totalSnow = 0;
                    }

                    if (totalRain < 0 ||
                        // Rain water does not accumulate on a water surface
                        wl != 0)
                    {
                        totalRain = 0;
                    }

                    RAIN[r, c] = totalRain;
                    SNOW[r, c] = totalSnow;
                }
            }
            ;

            Earth.SFC.BLIZZARD.Assign((r, c) =>
            {
                var wind         = WIND[r, c];
                var cl           = Precip[r, c] / 20f;
                bool solidPrecip = (SolidPrecip[r, c] != 0);

                if (solidPrecip)
                {
                    return(Math.Abs(cl * wind));
                }

                return(0);
            });

            Earth.SFC.ALBEDO.Assign((r, c) =>
            {
                var wl        = WL[r, c];
                var defAlbedo = DEF_ALBEDO[r, c];

                //if (wl == 0)
                {
                    var snowAlbedo = 0f;
                    var rainAlbedo = 0f;

                    if (SNOW[r, c] > 3f)
                    {
                        snowAlbedo = SNOW[r, c] + 20f * Math.Max(0, 5 - DaysSinceLastSnowFall[r, c]);
                    }

                    if (RAIN[r, c] >= 10f)
                    {
                        rainAlbedo = 0.5f * RAIN[r, c] + 10f * Math.Max(0, 3 - DaysSinceLastRainFall[r, c]);
                    }

                    var total = Math.Min(100f, defAlbedo + snowAlbedo + rainAlbedo);

                    return(total);

                    //return Math.Max(total, defAlbedo);
                }

                //return defAlbedo;
            });
        }
Пример #2
0
        private void DoReloadModel(string fieldDataFile, bool isWindMap)
        {
            // Create the plot model
            PlotModel model = this.Model;

            model.PlotMargins = new OxyThickness(30, 0, 60, 30);

            model.Axes.Clear();
            model.Series.Clear();
            model.Annotations.Clear();

            string fileTitle = Path.GetFileNameWithoutExtension(fieldDataFile);

            this.FileTitle = fileTitle;

            WeatherDataPalette wdp = WeatherDataPaletteFactory.GetPaletteForDataFile(fieldDataFile);
            bool contours          = wdp.ShowContours;
            bool heatmap           = wdp.ShowHeatmap;
            bool precipitationMap  = false;

            model.Title = string.Format("{0}: {1} [{2}]{3}",
                                        App.ControlPanelModel.SelectedViewport.Name,
                                        App.ControlPanelModel.SelectedDataType.Value,
                                        fileTitle,
                                        App.ControlPanelModel.SelectedDataType.Comments);

            DenseMatrix m = null;

            int minLon = App.ControlPanelModel.SelectedViewport.MinLon.Round();
            int maxLon = App.ControlPanelModel.SelectedViewport.MaxLon.Round();
            int minLat = App.ControlPanelModel.SelectedViewport.MinLat.Round();
            int maxLat = App.ControlPanelModel.SelectedViewport.MaxLat.Round();

            var fieldMatrix = FileSupport.LoadSubMatrixFromFile(fieldDataFile, minLon, maxLon, minLat, maxLat);

            bool interpolate = (fieldMatrix.RowCount < 10);

            if (interpolate)
            {
                fieldMatrix = fieldMatrix.Interpolate();
            }

            float[,] data  = null;
            float[,] data2 = null;

            float actualOffset = 0;

            if (wdp.ShowHeatmap)
            {
                float fOffset = (float)App.ControlPanelModel.Offset / 100;
                float delta   = wdp.MinMax.Delta;

                if (wdp.GetType() == typeof(C_00_Palette))
                {
                    delta = 100;
                }

                actualOffset = delta * fOffset;
            }

            if (wdp.GetType() == typeof(C_00_Palette))
            {
                // It's a map of the precipitation
                precipitationMap = true;

                string t01File = fieldDataFile.Replace("C_00", "T_01");
                string teFile  = fieldDataFile.Replace("C_00", "T_TE");
                string tsFile  = fieldDataFile.Replace("C_00", "T_TS");

                DenseMatrix T01 = FileSupport.LoadSubMatrixFromFile(t01File, minLon, maxLon, minLat, maxLat);
                DenseMatrix TE  = FileSupport.LoadSubMatrixFromFile(teFile, minLon, maxLon, minLat, maxLat);
                DenseMatrix TS  = FileSupport.LoadSubMatrixFromFile(tsFile, minLon, maxLon, minLat, maxLat);
                DenseMatrix C00 = fieldMatrix;

                if (interpolate)
                {
                    T01 = T01.Interpolate();
                    TE  = TE.Interpolate();
                    TS  = TS.Interpolate();
                }

                float sRain         = 0;
                float sSnow         = 300;
                float sSleet        = 600;
                float sFreezingRain = 900;

                data2 = C00.Transpose().ToArray();

                m = DenseMatrix.Create(C00.RowCount, C00.ColumnCount, (r, c) =>
                {
                    float cl = Math.Abs(C00[r, c]) + actualOffset;

                    if (cl <= 0)
                    {
                        cl = 0;
                    }
                    if (cl >= 100)
                    {
                        cl = 100;
                    }


                    float t01 = T01[r, c];
                    float te  = TE[r, c];
                    float ts  = TS[r, c];

                    float precipClThreshold = 10f;
                    float actualPrecipRate  = (cl - precipClThreshold);
                    if (actualPrecipRate >= 0)
                    {
                        return(PrecipTypeComputer <float> .Compute(

                                   // Actual temperatures
                                   te, ts, t01,

                                   // Boundary temperatures as read from simulation parameters
                                   SimulationParameters.Instance,

                                   // Computed precip type: snow
                                   () => (cl + sSnow),

                                   // Computed precip type: rain
                                   () => (cl + sRain),

                                   // Computed precip type: freezing rain
                                   () => (cl + sFreezingRain),

                                   // Computed precip type: sleet
                                   () => (cl + sSleet)
                                   ));
                    }
                    else if (cl > 5)
                    {
                        // Cloudy but without precipitation.
                        return(5);
                    }

                    // Sunny
                    return(0);
                });
            }
            else
            {
                m = DenseMatrix.Create(fieldMatrix.RowCount, fieldMatrix.ColumnCount, (r, c) =>
                                       fieldMatrix[r, c]);

                m.ADD(actualOffset);
            }

            Range <float> minMax      = wdp.MinMax;
            float         lineSpacing = wdp.LineSpacing;

            m    = m.MIN(minMax.Max).MAX(minMax.Min);
            data = m.Transpose().ToArray();

            float step = interpolate ? 0.5f : 1;

            List <float> cols = new List <float>();

            for (float i = minLon; i <= maxLon; i += step)
            {
                cols.Add(i);
            }

            List <float> rows = new List <float>();

            for (float i = maxLat; i >= minLat; i -= step)
            {
                rows.Add(i);
            }


            List <float> levels = new List <float>();

            for (float i = wdp.MinMax.Min; i <= wdp.MinMax.Max; i += wdp.LineSpacing)
            {
                levels.Add(i);
            }

            var pal = OxyPalette.Interpolate(levels.Count, wdp.ColorSteps.ToArray());

            List <OxyColor> lineColors = new List <OxyColor>();

            foreach (OxyColor c in wdp.ColorSteps)
            {
                if (heatmap)
                {
                    switch (wdp.LineColor.ColorMode)
                    {
                    case Views.LineColorMode.FixedColor:
                        lineColors.Add(wdp.LineColor.Color);
                        break;

                    case Views.LineColorMode.Best_Contrast:
                        lineColors.Add(c.Complementary());
                        break;

                    case Views.LineColorMode.Black_And_White:
                    {
                        System.Drawing.Color cw = System.Drawing.Color.FromArgb(c.R, c.G, c.B);
                        float br = cw.GetBrightness();

                        if (br < 0.5f)
                        {
                            lineColors.Add(OxyColors.White);
                        }
                        else
                        {
                            lineColors.Add(OxyColors.Black);
                        }
                    }
                    break;
                    }
                }
                else
                {
                    lineColors.Add(c);
                }
            }

            if (isWindMap)
            {
                this.FileTitle += "_WINDMAP";

                var D = (App.ControlPanelModel.SelectedViewport.MaxLon -
                         App.ControlPanelModel.SelectedViewport.MinLon);

                float hf = 1;
                if (D > 200)
                {
                    hf = 0.45f;
                }
                else if (D > 20)
                {
                    hf = 0.55f;
                }
                else
                {
                    hf = 1;
                }

                float sf = 0.9f * hf;

                DenseMatrix[] gr = fieldMatrix.ToWindComponents();
                float[,] dataX = gr[Direction.X].ToArray();
                float[,] dataY = gr[Direction.Y].ToArray();

                int rowCount = dataX.GetLength(0);
                int colCount = dataX.GetLength(1);

                for (int r = 0; r < rowCount; r++)
                {
                    for (int c = 0; c < colCount; c++)
                    {
                        float x = c + App.ControlPanelModel.SelectedViewport.MinLon;
                        float y = App.ControlPanelModel.SelectedViewport.MaxLat - r;

                        float dx = dataX[r, c];
                        float dy = -dataY[r, c];

                        int mod = (int)Math.Sqrt(dx * dx + dy * dy);

                        LineSeries line = new LineSeries();
                        line.Points.Add(new DataPoint(x, y));
                        line.Points.Add(new DataPoint(x + dx, y + dy));
                        line.StrokeThickness = 1;


                        if (mod < 2)
                        {
                            line.Color           = OxyColors.Green;
                            line.StrokeThickness = 2 * hf;
                        }
                        else if (mod < 5)
                        {
                            line.Color           = OxyColors.Red;
                            line.StrokeThickness = 2.5 * hf;
                        }
                        else
                        {
                            line.Color           = OxyColors.Magenta;
                            line.StrokeThickness = 3 * hf;
                        }

                        model.Series.Add(line);

                        ArrowAnnotation arrow = new ArrowAnnotation();
                        var             edy   = Math.Min(dy, 2);
                        arrow.StartPoint      = new DataPoint(x + sf * dx, y + sf * edy);
                        arrow.EndPoint        = new DataPoint(x + dx, y + edy);
                        arrow.Color           = line.Color;
                        arrow.StrokeThickness = line.StrokeThickness;
                        arrow.HeadWidth       = 1.5 * line.StrokeThickness;
                        arrow.HeadLength      = 3 * line.StrokeThickness;

                        model.Annotations.Add(arrow);

                        //goto MapFeatures;
                    }
                }
            }
            else
            {
                if (heatmap)
                {
                    if (precipitationMap)
                    {
                        HeatMapSeriesEx cloudMapSeries = new HeatMapSeriesEx
                        {
                            Data = data.ToDoubleArray(),
                            X0   = cols[0],
                            X1   = cols[cols.Count - 1],
                            Y0   = rows[0],
                            Y1   = rows[rows.Count - 1],
                        };
                        model.Series.Add(cloudMapSeries);
                    }
                    else
                    {
                        OxyPlot.Series.HeatMapSeries heatmapSeries = new OxyPlot.Series.HeatMapSeries
                        {
                            Data = data.ToDoubleArray(),
                            X0   = cols[0],
                            X1   = cols[cols.Count - 1],
                            Y0   = rows[0],
                            Y1   = rows[rows.Count - 1],
                        };
                        model.Series.Add(heatmapSeries);
                    }
                }

                if (contours)
                {
                    OxyPlot.Series.ContourSeries contour = new OxyPlot.Series.ContourSeries
                    {
                        ColumnCoordinates = cols.ToArray().ToDoubleArray(),
                        RowCoordinates    = rows.ToArray().ToDoubleArray(),
                        ContourLevels     = levels.ToArray().ToDoubleArray(),

                        ContourColors = lineColors.ToArray(), // Same # elements as the levels' array

                        Data = (data2 == null) ? data.ToDoubleArray() : data2.ToDoubleArray(),

                        LabelBackground  = OxyColors.Transparent,
                        ContourLevelStep = wdp.LineSpacing,
                        StrokeThickness  = wdp.LineWidth,
                        FontSize         = 15,
                        FontWeight       = 500,
                    };


                    model.Series.Add(contour);
                }
            }

MapFeatures:

            // Always do this last.
            AddMapFeatures(model, wdp, pal, isWindMap);
        }