public void Save(string title) { FileSupport.Save(TE, title, "T_TE_MAP"); FileSupport.Save(TW, title, "T_TW_MAP"); FileSupport.Save(TL, title, "T_TL_MAP"); FileSupport.Save(TS, title, "T_TS_MAP"); FileSupport.Save(SNOW, title, "N_00_MAP"); FileSupport.Save(RAIN, title, "R_00_MAP"); FileSupport.Save(BLIZZARD, title, "B_00_MAP"); FileSupport.Save(ALBEDO, title, "A_00_MAP"); FileSupport.Save(Precip, title, "C_00_MAP"); FileSupport.Save(TLow, title, "T_SL_MAP"); FileSupport.Save(THigh, title, "T_SH_MAP"); FileSupport.Save(LIDX, title, "L_00_MAP"); FileSupport.Save(FOG, title, "F_SI_MAP"); FileSupport.Save(TNormLow, title, "T_NL_MAP"); FileSupport.Save(TNormHigh, title, "T_NH_MAP"); FileSupport.Save(TLow - TNormLow, title, "T_DL_MAP"); FileSupport.Save(THigh - TNormHigh, title, "T_DH_MAP"); FileSupport.Save(0.5f * (TLow - TNormLow + THigh - TNormHigh).EQ(), title, "T_DA_MAP"); FileSupport.Save((1000 * WL - MatrixFactory.Init(500)), title, "E_00_MAP"); }
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 DenseMatrix LoadMatrixFromFile(string filePath) { try { return(new MatrixFile(filePath, true).Matrix); } catch { return(MatrixFactory.Init()); } }
private DenseMatrix ImportLevelData(string dataFile, string paramName, int levelIdx, Func <float, float> conversionFunc) { if (string.IsNullOrEmpty(dataFile) == false) { if (File.Exists(dataFile)) { File.Delete(dataFile); } } int level = (levelIdx < 0) ? 0 : _levels[levelIdx]; var messages = _messages.Where(m => m.Name.Contains(paramName) && m.Level == level).First(); var nodes = messages.GeoSpatialValues.Where(gs => gs.IsMissing == false && (gs.Latitude >= EarthModel.MinLat && gs.Latitude <= EarthModel.MaxLat) && (gs.Longitude >= 180 + EarthModel.MinLon && gs.Longitude <= 180 + EarthModel.MaxLon) && (gs.Latitude == Math.Truncate(gs.Latitude)) && gs.Longitude == Math.Truncate(gs.Longitude)) .ToArray(); if (!time) { DateTime dt = messages.ReferenceTime; SimDateTime sdt = new SimDateTime(dt); string timeSeedFile = "timeSeed.thd"; CorrectFilePath(ref timeSeedFile); File.WriteAllText(timeSeedFile, sdt.Title); time = true; } DenseMatrix mat = MatrixFactory.Init(); foreach (var node in nodes) { int r = EarthModel.MaxLat - (int)node.Latitude; int c = ((int)node.Longitude - EarthModel.MinLon) % 360; mat[r, c] = conversionFunc((float)node.Value); } if (string.IsNullOrEmpty(dataFile) == false) { FileSupport.SaveMatrixToFile(mat, dataFile, false); } return(mat); }
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); } }
protected virtual void ApplyCyclogenesys(DenseMatrix[] applyDevs, DenseMatrix T0, DenseMatrix P0) { DenseMatrix rawP = P0.Clone() as DenseMatrix; DenseMatrix deltaT = null; DenseMatrix deltaP = null; float thickness = 0; float levelPressure = 0; switch (_levelType) { case LevelType.TopLevel: deltaT = (Earth.ATM.TopLevel.T - MatrixFactory.Init(-55)); deltaP = (Earth.ATM.TopLevel.P - MatrixFactory.Init(300)); thickness = -4.5f; levelPressure = LevelPressure.TopLevelPressure; break; case LevelType.MidLevel: deltaT = (Earth.ATM.MidLevel.T - Earth.ATM.TopLevel.T); deltaP = (Earth.ATM.MidLevel.P - Earth.ATM.TopLevel.P); thickness = -4f; levelPressure = LevelPressure.MidLevelPressure; break; case LevelType.SeaLevel: deltaT = (Earth.ATM.SeaLevel.T - Earth.ATM.MidLevel.T); deltaP = (Earth.ATM.SeaLevel.P - Earth.ATM.MidLevel.P); thickness = -1.5f; levelPressure = LevelPressure.SeaLevelPressure; break; } var weakBlock = Earth.ATM.JetLevel.WeakBlockTH; var strongBlock = Earth.ATM.JetLevel.StrongBlockTH; var DIV = (10 * Earth.ATM.JetLevel.P.Divergence()).EQ(4); rawP.Assign((r, c) => { var front = Earth.ATM.Fronts[r, c]; var pJetLevel = Earth.ATM.JetLevel.P[r, c]; var t = T[r, c] + AbsoluteConstants.WaterFreezePoint; var t0 = T0[r, c] + AbsoluteConstants.WaterFreezePoint; var p0 = P0[r, c]; var lapseRate = Math.Abs(deltaT[r, c] / thickness); var unitDp = levelPressure * Math.Abs((t - t0) / AbsoluteConstants.WaterFreezePoint); var cf = -SimulationParameters.Instance.CyclogeneticFactor; var acf = SimulationParameters.Instance.AntiCyclogeneticFactor; var div = DIV[r, c]; const float strong = 2.5f; const float weak = 0.5f; const float pseudoStationary = 0.1f; //bool stable = ((lapseRate > SimulationParameters.Instance.HumidLapseRate) || (pJetLevel > strongBlock)); //bool unstable = ((lapseRate < SimulationParameters.Instance.HumidLapseRate) || (pJetLevel < weakBlock)); //bool stable = ((pJetLevel >= strongBlock)); //bool unstable = ((pJetLevel <= weakBlock)); bool stable = ((div <= -1)); bool unstable = ((div >= 1)); float actualDp = 0; if (front < 0) { if (stable) { actualDp = cf * pseudoStationary * unitDp; } else if (unstable) { actualDp = cf * strong * unitDp; } else { actualDp = cf * weak * unitDp; } } else if (front > 0) { actualDp = acf * pseudoStationary * unitDp; } else { if (stable) { actualDp = acf * strong * unitDp; } else if (unstable) { actualDp = acf * pseudoStationary * unitDp; } else { actualDp = acf * weak * unitDp; } } var p = p0 + Earth.SnapshotDivFactor * actualDp; if (p < PressureExtremes[0]) { p = PressureExtremes[0]; } if (p > PressureExtremes[1]) { p = PressureExtremes[1]; } return(p); }); var pNorth = rawP.RegionSubMatrix(-180, 179, 0, 89); var pSouth = rawP.RegionSubMatrix(-180, 179, -89, -1); var projPNorth = pNorth.Divide(pNorth.Mean()).Multiply(levelPressure) as DenseMatrix; var projPSouth = pSouth.Divide(pSouth.Mean()).Multiply(levelPressure) as DenseMatrix; var projP = MatrixFactory.Init(); projP.SetSubMatrix(0, pNorth.RowCount, 0, pNorth.ColumnCount, projPNorth); projP.SetSubMatrix(pNorth.RowCount, pSouth.RowCount, 0, pSouth.ColumnCount, projPSouth); P = projP.EQ(4).ApplyDeviations(applyDevs, null).EQ(4); }
public SurfaceLevel(EarthModel earth, bool loadFromStateFiles, float defaultValue = 0) { this.Earth = earth; InitGeographicalParams(); if (loadFromStateFiles == false) { if (defaultValue == 0) { // ------------ // Soil temperature where applicable string filePath = Path.Combine(SimulationData.WorkFolder, "SOIL.thd"); if (File.Exists(filePath)) { var tl = FileSupport.LoadMatrixFromFile(filePath); TL.Assign((r, c) => { if (WL[r, c] == 0) { return(tl[r, c]); } return(0); }); } // ------------ // Sea temperature where applicable filePath = Path.Combine(SimulationData.WorkFolder, "SST.thd"); if (File.Exists(filePath)) { var tw = FileSupport.LoadMatrixFromFile(filePath); TW.Assign((r, c) => { if (WL[r, c] != 0) { return(tw[r, c]); } return(0); }); } // Combined surface temperature TS.Assign((r, c) => { if (WL[r, c] != 0) { return(TW[r, c]); } return(TL[r, c]); }); // ------------ // Snow cover filePath = Path.Combine(SimulationData.WorkFolder, "SNOW.thd"); if (File.Exists(filePath)) { this.SNOW = FileSupport.LoadMatrixFromFile(filePath); } } else { TE = MatrixFactory.Init(defaultValue); TW = MatrixFactory.Init(defaultValue); TL = MatrixFactory.Init(defaultValue); TS = MatrixFactory.Init(defaultValue); SNOW = MatrixFactory.Init(defaultValue); RAIN = MatrixFactory.Init(defaultValue); BLIZZARD = MatrixFactory.Init(defaultValue); ALBEDO = MatrixFactory.Init(defaultValue); Precip = MatrixFactory.Init(defaultValue); TLow = MatrixFactory.Init(defaultValue); THigh = MatrixFactory.Init(defaultValue); LIDX = MatrixFactory.Init(defaultValue); FOG = MatrixFactory.Init(defaultValue); TNormLow = MatrixFactory.Init(defaultValue); TNormHigh = MatrixFactory.Init(defaultValue); } } else { TE = FileSupport.Load(Earth.UTC.Title, "T_TE_MAP"); TW = FileSupport.Load(Earth.UTC.Title, "T_TW_MAP"); TL = FileSupport.Load(Earth.UTC.Title, "T_TL_MAP"); TS = FileSupport.Load(Earth.UTC.Title, "T_TS_MAP"); SNOW = FileSupport.Load(Earth.UTC.Title, "N_00_MAP"); RAIN = FileSupport.Load(Earth.UTC.Title, "R_00_MAP"); BLIZZARD = FileSupport.Load(Earth.UTC.Title, "B_00_MAP"); ALBEDO = FileSupport.Load(Earth.UTC.Title, "A_00_MAP"); Precip = FileSupport.Load(Earth.UTC.Title, "C_00_MAP"); TLow = FileSupport.Load(Earth.UTC.Title, "T_SL_MAP"); THigh = FileSupport.Load(Earth.UTC.Title, "T_SH_MAP"); LIDX = FileSupport.Load(Earth.UTC.Title, "L_00_MAP"); FOG = FileSupport.Load(Earth.UTC.Title, "F_SI_MAP"); TNormLow = FileSupport.Load(Earth.UTC.Title, "T_NL_MAP"); TNormHigh = FileSupport.Load(Earth.UTC.Title, "T_NH_MAP"); } }
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; }); }