//--------------------------------------------------------------------- //public AnnualClimate(IEcoregion ecoregion, int year, double latitude) public AnnualClimate(int ecoregionIndex, int year, double latitude) { IClimateRecord[] ecoClimate = new IClimateRecord[12]; this.Year = year; this.AnnualPrecip = 0.0; this.AnnualN = 0.0; for(int mo = 0; mo < 12; mo++) { ecoClimate[mo] = Climate.TimestepData[ecoregionIndex, mo]; double MonthlyAvgTemp = (ecoClimate[mo].AvgMinTemp + ecoClimate[mo].AvgMaxTemp) / 2.0; double standardDeviation = ecoClimate[mo].StdDevTemp * (Landis.Util.Random.GenerateUniform() * 2.0 - 1.0); this.MonthlyTemp[mo] = MonthlyAvgTemp + standardDeviation; this.MonthlyMinTemp[mo] = ecoClimate[mo].AvgMinTemp + standardDeviation; this.MonthlyMaxTemp[mo] = ecoClimate[mo].AvgMaxTemp + standardDeviation; this.MonthlyPrecip[mo] = Math.Max(0.0, ecoClimate[mo].AvgPpt + (ecoClimate[mo].StdDevPpt * (Landis.Util.Random.GenerateUniform()*2.0 - 1.0))); this.MonthlyPAR[mo] = ecoClimate[mo].PAR; this.AnnualPrecip += this.MonthlyPrecip[mo]; if (this.MonthlyPrecip[mo] < 0) this.MonthlyPrecip[mo] = 0; double hr = CalculateDayNightLength(mo, latitude); this.MonthlyDayLength[mo] = (60.0 * 60.0 * hr); // seconds of daylight/day this.MonthlyNightLength[mo] = (60.0 * 60.0 * (24 - hr)); // seconds of nighttime/day //this.DOY[mo] = DayOfYear(mo); } this.MonthlyPET = CalculatePotentialEvapotranspiration(ecoClimate); this.MonthlyVPD = CalculateVaporPressureDeficit(ecoClimate); this.MonthlyGDD = CalculatePnETGDD(this.MonthlyTemp, year); this.BeginGrowing = CalculateBeginGrowingSeason(ecoClimate); this.EndGrowing = CalculateEndGrowingSeason(ecoClimate); this.GrowingDegreeDays = GrowSeasonDegreeDays(year); for(int mo = 5; mo < 8; mo++) this.JJAtemperature += this.MonthlyTemp[mo]; this.JJAtemperature /= 3.0; }
//--------------------------------------------------------------------- //public AnnualClimate(IEcoregion ecoregion, int year, double latitude) public AnnualClimate(int ecoregionIndex, int year, double latitude) { IClimateRecord[] ecoClimate = new IClimateRecord[12]; this.Year = year; this.AnnualPrecip = 0.0; this.AnnualN = 0.0; for (int mo = 0; mo < 12; mo++) { ecoClimate[mo] = Climate.TimestepData[ecoregionIndex, mo]; double MonthlyAvgTemp = (ecoClimate[mo].AvgMinTemp + ecoClimate[mo].AvgMaxTemp) / 2.0; double standardDeviation = ecoClimate[mo].StdDevTemp * (Landis.Util.Random.GenerateUniform() * 2.0 - 1.0); this.MonthlyTemp[mo] = MonthlyAvgTemp + standardDeviation; this.MonthlyMinTemp[mo] = ecoClimate[mo].AvgMinTemp + standardDeviation; this.MonthlyMaxTemp[mo] = ecoClimate[mo].AvgMaxTemp + standardDeviation; this.MonthlyPrecip[mo] = Math.Max(0.0, ecoClimate[mo].AvgPpt + (ecoClimate[mo].StdDevPpt * (Landis.Util.Random.GenerateUniform() * 2.0 - 1.0))); this.MonthlyPAR[mo] = ecoClimate[mo].PAR; this.AnnualPrecip += this.MonthlyPrecip[mo]; if (this.MonthlyPrecip[mo] < 0) { this.MonthlyPrecip[mo] = 0; } double hr = CalculateDayNightLength(mo, latitude); this.MonthlyDayLength[mo] = (60.0 * 60.0 * hr); // seconds of daylight/day this.MonthlyNightLength[mo] = (60.0 * 60.0 * (24 - hr)); // seconds of nighttime/day //this.DOY[mo] = DayOfYear(mo); } this.MonthlyPET = CalculatePotentialEvapotranspiration(ecoClimate); this.MonthlyVPD = CalculateVaporPressureDeficit(ecoClimate); this.MonthlyGDD = CalculatePnETGDD(this.MonthlyTemp, year); this.BeginGrowing = CalculateBeginGrowingSeason(ecoClimate); this.EndGrowing = CalculateEndGrowingSeason(ecoClimate); this.GrowingDegreeDays = GrowSeasonDegreeDays(year); for (int mo = 5; mo < 8; mo++) { this.JJAtemperature += this.MonthlyTemp[mo]; } this.JJAtemperature /= 3.0; }
private void CalculateMonthlyData_NoVariance(IEcoregion ecoregion, IClimateRecord[,] timestepData, int actualYear, double latitude) { IClimateRecord[] ecoClimate = new IClimateRecord[12]; this.Year = actualYear; this.AnnualPrecip = 0.0; //if(timestepData[ecoregion.Index]. ADD MONTH CHECK HERE. for (int mo = 0; mo < 12; mo++) { //Climate.ModelCore.UI.WriteLine(" Calculating Monthly Climate (No Variance): Yr={0}, month={1}, Eco={2}, Phase={3}.", actualYear, mo, ecoregion.Name, this.climatePhase); ecoClimate[mo] = timestepData[ecoregion.Index, mo]; double MonthlyAvgTemp = (ecoClimate[mo].AvgMinTemp + ecoClimate[mo].AvgMaxTemp) / 2.0; //double standardDeviation = ecoClimate[mo].StdDevTemp * (Climate.ModelCore.GenerateUniform() * 2.0 - 1.0); this.MonthlyTemp[mo] = MonthlyAvgTemp; this.MonthlyMinTemp[mo] = ecoClimate[mo].AvgMinTemp; this.MonthlyMaxTemp[mo] = ecoClimate[mo].AvgMaxTemp; this.MonthlyPrecip[mo] = Math.Max(0.0, ecoClimate[mo].AvgPpt); this.MonthlyPAR[mo] = ecoClimate[mo].PAR; this.AnnualPrecip += this.MonthlyPrecip[mo]; if (this.MonthlyPrecip[mo] < 0) { this.MonthlyPrecip[mo] = 0; } double hr = CalculateDayNightLength(mo, latitude); this.MonthlyDayLength[mo] = (60.0 * 60.0 * hr); // seconds of daylight/day this.MonthlyNightLength[mo] = (60.0 * 60.0 * (24 - hr)); // seconds of nighttime/day } }
// ------------------------------------------------------------------------------------------------------ private void CalculateMonthlyData_AddVariance(IEcoregion ecoregion, IClimateRecord[,] timestepData, int actualYear, double latitude) { IClimateRecord[] ecoClimate = new IClimateRecord[12]; this.Year = actualYear; this.AnnualPrecip = 0.0; //if(timestepData[ecoregion.Index]. ADD MONTH CHECK HERE. for (int mo = 0; mo < 12; mo++) { ecoClimate[mo] = timestepData[ecoregion.Index, mo]; //Climate.TimestepData[ecoregion.Index, mo]; double MonthlyAvgTemp = (ecoClimate[mo].AvgMinTemp + ecoClimate[mo].AvgMaxTemp) / 2.0; double standardDeviation = ecoClimate[mo].StdDevTemp * (Climate.ModelCore.GenerateUniform() * 2.0 - 1.0); this.MonthlyTemp[mo] = MonthlyAvgTemp + standardDeviation; this.MonthlyMinTemp[mo] = ecoClimate[mo].AvgMinTemp + standardDeviation; this.MonthlyMaxTemp[mo] = ecoClimate[mo].AvgMaxTemp + standardDeviation; this.MonthlyPrecip[mo] = Math.Max(0.0, ecoClimate[mo].AvgPpt + (ecoClimate[mo].StdDevPpt * (Climate.ModelCore.GenerateUniform() * 2.0 - 1.0))); this.MonthlyPAR[mo] = ecoClimate[mo].PAR; this.AnnualPrecip += this.MonthlyPrecip[mo]; if (this.MonthlyPrecip[mo] < 0) { this.MonthlyPrecip[mo] = 0; } double hr = CalculateDayNightLength(mo, latitude); this.MonthlyDayLength[mo] = (60.0 * 60.0 * hr); // seconds of daylight/day this.MonthlyNightLength[mo] = (60.0 * 60.0 * (24 - hr)); // seconds of nighttime/day //this.DOY[mo] = DayOfYear(mo); } }
//--------------------------------------------------------------------- protected override Dictionary <int, IClimateRecord[, ]> Parse() { InputVar <string> landisData = new InputVar <string>("LandisData"); ReadVar(landisData); if (landisData.Value.Actual != LandisDataValue) { throw new InputValueException(landisData.Value.String, "The value is not \"{0}\"", LandisDataValue); } Dictionary <int, IClimateRecord[, ]> allData = new Dictionary <int, IClimateRecord[, ]>(); const string nextTableName = "ClimateTable"; //--------------------------------------------------------------------- //Read in climate data: ReadName(nextTableName); InputVar <string> ecoregionName = new InputVar <string>("Ecoregion"); //InputVar<int> ecoregionIndex = new InputVar<int>("Ecoregion Index"); InputVar <int> year = new InputVar <int>("Time step for updating the climate"); InputVar <int> month = new InputVar <int>("The Month"); InputVar <double> avgMinTemp = new InputVar <double>("Monthly Minimum Temperature Value"); InputVar <double> avgMaxTemp = new InputVar <double>("Monthly Maximum Temperature Value"); InputVar <double> stdDevTemp = new InputVar <double>("Monthly Std Deviation Temperature Value"); InputVar <double> avgPpt = new InputVar <double>("Monthly Precipitation Value"); InputVar <double> stdDevPpt = new InputVar <double>("Monthly Std Deviation Precipitation Value"); InputVar <double> par = new InputVar <double>("Monthly Photosynthetically Active Radiation Value"); InputVar <double> avgVarTemp = new InputVar <double>("Monthly Variance Temperature Value"); InputVar <double> avgPptVarTemp = new InputVar <double>("Monthly Precipitation Variance Temperature Value"); while (!AtEndOfInput) { StringReader currentLine = new StringReader(CurrentLine); ReadValue(ecoregionName, currentLine); //ReadValue(ecoregionIndex, currentLine); IEcoregion ecoregion = GetEcoregion(ecoregionName.Value); ReadValue(year, currentLine); int yr = year.Value.Actual; if (!allData.ContainsKey(yr)) { IClimateRecord[,] climateTable = new IClimateRecord[Climate.ModelCore.Ecoregions.Count, 12]; allData.Add(yr, climateTable); //UI.WriteLine(" Climate Parser: Add new year = {0}.", yr); } ReadValue(month, currentLine); int mo = month.Value.Actual; IClimateRecord climateRecord = new ClimateRecord(); ReadValue(avgMinTemp, currentLine); climateRecord.AvgMinTemp = avgMinTemp.Value; ReadValue(avgMaxTemp, currentLine); climateRecord.AvgMaxTemp = avgMaxTemp.Value; ReadValue(stdDevTemp, currentLine); climateRecord.StdDevTemp = stdDevTemp.Value; ReadValue(avgPpt, currentLine); climateRecord.AvgPpt = avgPpt.Value; ReadValue(stdDevPpt, currentLine); climateRecord.StdDevPpt = stdDevPpt.Value; ReadValue(par, currentLine); climateRecord.PAR = par.Value; //if (currentLine.ToString().ToLower().Contains("avgvartemp")) //{ //if(!Climate.ConfigParameters.ClimateFileFormat.ToLower().Contains("standard")) //{ try { ReadValue(avgVarTemp, currentLine); climateRecord.AvgVarTemp = avgVarTemp.Value; ReadValue(avgPptVarTemp, currentLine); climateRecord.AvgPptVarTemp = avgPptVarTemp.Value; allData[yr][ecoregion.Index, mo - 1] = climateRecord; CheckNoDataAfter("the " + avgPptVarTemp.Name + " column", currentLine); } catch (InputVariableException ex) { if (ex is InputVariableException) // This we know how to handle. { allData[yr][ecoregion.Index, mo - 1] = climateRecord; CheckNoDataAfter("the " + par.Name + " column", currentLine); } } //if(!Climate.ConfigParameters.ClimateFileFormat.ToLower().Contains("standard")) ////{ // ReadValue(avgVarTemp, currentLine); // climateRecord.AvgVarTemp = avgVarTemp.Value; // ReadValue(avgPptVarTemp, currentLine); // climateRecord.AvgPptVarTemp = avgPptVarTemp.Value; // allData[yr][ecoregion.Index, mo - 1] = climateRecord; // CheckNoDataAfter("the " + avgPptVarTemp.Name + " column", // currentLine); //} //else //{ // allData[yr][ecoregion.Index, mo - 1] = climateRecord; // CheckNoDataAfter("the " + par.Name + " column", // currentLine); //} GetNextLine(); } return(allData); }
public AnnualClimate_Monthly(IEcoregion ecoregion, int actualYear, double latitude, Climate.Phase spinupOrfuture = Climate.Phase.Future_Climate, int timeStep = Int32.MinValue) //For Hist and Random timeStep arg should be passed { this.climatePhase = spinupOrfuture; this.Latitude = latitude; // ------------------------------------------------------------------------------------------------------ // Case: Daily data used for future climate. Note: No need to ever use daily data with spinup climate //if (Climate.AllData_granularity == TemporalGranularity.Daily && spinupOrfuture == Climate.Phase.Future_Climate) //{ // //Climate.ModelCore.UI.WriteLine(" Processing Daily data into Monthly data. Ecoregion = {0}, Year = {1}, timestep = {2}.", ecoregion.Name, actualYear, timeStep); // this.AnnualClimate_From_AnnualClimate_Daily(ecoregion, actualYear, latitude, spinupOrfuture, timeStep); // return; //} IClimateRecord[,] timestepData = new IClimateRecord[Climate.ModelCore.Ecoregions.Count, 12]; // ------------------------------------------------------------------------------------------------------ // PossibleValues = "MonthlyRandom, MonthlyAverage, DailyHistRandom, DailyHistAverage, MonthlyStandard, DailyGCM"; string climateOption = Climate.ConfigParameters.ClimateTimeSeries; if (this.climatePhase == Climate.Phase.SpinUp_Climate) climateOption = Climate.ConfigParameters.SpinUpClimateTimeSeries; switch (climateOption) { case "Monthly_AverageAllYears": { //if (this.climatePhase == Climate.Phase.Future_Climate) //else if (this.climatePhase == Climate.Phase.SpinUp_Climate) // timestepData = AnnualClimate_Avg(ecoregion, actualYear, latitude); timestepData = AnnualClimate_AvgMonth(ecoregion, actualYear, latitude); break; } case "Monthly_AverageWithVariation": { timestepData = AnnualClimate_AvgMonth(ecoregion, actualYear, latitude); CalculateMonthlyData_AddVariance(ecoregion, timestepData, actualYear, latitude); break; } case "Monthly_RandomYear": { TimeStep = timeStep; try { if (this.climatePhase == Climate.Phase.Future_Climate) timestepData = Climate.Future_AllData[Climate.RandSelectedTimeSteps_future[TimeStep]]; else if (this.climatePhase == Climate.Phase.SpinUp_Climate) timestepData = Climate.Spinup_AllData[Climate.RandSelectedTimeSteps_spinup[TimeStep]]; CalculateMonthlyData_NoVariance(ecoregion, timestepData, actualYear, latitude); } catch (System.Collections.Generic.KeyNotFoundException ex) { throw new ClimateDataOutOfRangeException("Exception: The requested Time-step is out of range for " + this.climatePhase.ToString() + " input file.", ex); } break; } case "Monthly_SequencedYears": { TimeStep = timeStep; try { if (this.climatePhase == Climate.Phase.Future_Climate) timestepData = Climate.Future_AllData[TimeStep]; else if (this.climatePhase == Climate.Phase.SpinUp_Climate) timestepData = Climate.Spinup_AllData[TimeStep]; CalculateMonthlyData_NoVariance(ecoregion, timestepData, actualYear, latitude); } catch (System.Collections.Generic.KeyNotFoundException ex) { throw new ClimateDataOutOfRangeException("Exception: The requested Time-step is out of range for " + this.climatePhase.ToString() + " input file.", ex); } break; } case "Daily_RandomYear": { this.AnnualClimate_From_AnnualClimate_Daily(ecoregion, actualYear, latitude, spinupOrfuture, timeStep); break; } case "Daily_AverageAllYears": { this.AnnualClimate_From_AnnualClimate_Daily(ecoregion, actualYear, latitude, spinupOrfuture, timeStep); return; } //case "MonthlyStandard": // { // TimeStep = timeStep; // try // { // if (this.climatePhase == Climate.Phase.Future_Climate) // timestepData = Climate.Future_AllData[TimeStep]; // else if (this.climatePhase == Climate.Phase.SpinUp_Climate) // timestepData = Climate.Spinup_AllData[TimeStep]; // CalculateMonthlyData_AddVariance(ecoregion, timestepData, actualYear, latitude); // } // catch (System.Collections.Generic.KeyNotFoundException ex) // { // throw new ClimateDataOutOfRangeException("Exception: The requested Time-step is out of range for " + this.climatePhase.ToString() + " input file.", ex); // } // break; // } case "Daily_SequencedYears": { this.AnnualClimate_From_AnnualClimate_Daily(ecoregion, actualYear, latitude, spinupOrfuture, timeStep); return; } default: throw new ApplicationException(String.Format("Unknown Climate Time Series: {}", climateOption)); } this.MonthlyPET = CalculatePotentialEvapotranspiration(); this.MonthlyVPD = CalculateVaporPressureDeficit(); this.MonthlyGDD = CalculatePnETGDD(); this.beginGrowing = CalculateBeginGrowingSeason(); this.endGrowing = CalculateEndGrowingSeason(); this.growingDegreeDays = GrowSeasonDegreeDays(); for (int mo = 5; mo < 8; mo++) this.JJAtemperature += this.MonthlyTemp[mo]; this.JJAtemperature /= 3.0; }
//Daily will not come to here. the average in daily is calculated in the AnnualClimate_Daily private IClimateRecord[,] AnnualClimate_AvgMonth(IEcoregion ecoregion, int year, double latitude) { IClimateRecord[,] timestepData = new IClimateRecord[Climate.ModelCore.Ecoregions.Count, 12]; IClimateRecord[,] avgEcoClimate = new IClimateRecord[Climate.ModelCore.Ecoregions.Count, 12]; //IClimateRecord[,] ecoClimateT = new IClimateRecord[Climate.ModelCore.Ecoregions.Count, 12]; for (int i = 0; i < 12; i++) { this.MonthlyMinTemp[i] = 0.0; this.MonthlyMaxTemp[i] = 0.0; this.MonthlyVarTemp[i] = 0.0; this.MonthlyPptVarTemp[i] = 0.0; this.MonthlyPrecip[i] = 0.0; this.MonthlyPAR[i] = 0.0; } int allDataCount = 0; if (this.climatePhase == Climate.Phase.Future_Climate) allDataCount = Climate.Future_AllData.Count; else if (this.climatePhase == Climate.Phase.SpinUp_Climate) allDataCount = Climate.Spinup_AllData.Count; for (int mo = 0; mo < 12; mo++) { for (int stp = 0; stp < allDataCount; stp++) { if (this.climatePhase == Climate.Phase.Future_Climate) timestepData = Climate.Future_AllData.ElementAt(stp).Value; else if (this.climatePhase == Climate.Phase.SpinUp_Climate) timestepData = Climate.Spinup_AllData.ElementAt(stp).Value; //Climate.ModelCore.UI.WriteLine(" Calculating annual average climate: Yr={0}, month={1}, Eco={2}, Phase={3}.", Climate.Future_AllData.ElementAt(stp).Key, mo, ecoregion.Name, this.climatePhase); this.MonthlyMinTemp[mo] += timestepData[ecoregion.Index, mo].AvgMinTemp; this.MonthlyMaxTemp[mo] += timestepData[ecoregion.Index, mo].AvgMaxTemp; this.MonthlyVarTemp[mo] += timestepData[ecoregion.Index, mo].AvgVarTemp; this.MonthlyPptVarTemp[mo] += timestepData[ecoregion.Index, mo].AvgPptVarTemp; this.MonthlyPrecip[mo] += timestepData[ecoregion.Index, mo].AvgPpt; this.MonthlyPAR[mo] += timestepData[ecoregion.Index, mo].PAR; } this.MonthlyMinTemp[mo] = this.MonthlyMinTemp[mo] / allDataCount; this.MonthlyMaxTemp[mo] = this.MonthlyMaxTemp[mo] / allDataCount; this.MonthlyVarTemp[mo] = this.MonthlyVarTemp[mo] / allDataCount; this.MonthlyPptVarTemp[mo] = this.MonthlyPptVarTemp[mo] / allDataCount; this.MonthlyPrecip[mo] = this.MonthlyPrecip[mo] / allDataCount; this.MonthlyPAR[mo] = this.MonthlyPAR[mo] / allDataCount; avgEcoClimate[ecoregion.Index, mo] = new ClimateRecord(); avgEcoClimate[ecoregion.Index, mo].AvgMinTemp = this.MonthlyMinTemp[mo]; avgEcoClimate[ecoregion.Index, mo].AvgMaxTemp = this.MonthlyMaxTemp[mo]; avgEcoClimate[ecoregion.Index, mo].AvgVarTemp = this.MonthlyVarTemp[mo]; avgEcoClimate[ecoregion.Index, mo].StdDevTemp = Math.Sqrt(MonthlyVarTemp[mo]); avgEcoClimate[ecoregion.Index, mo].AvgPptVarTemp = this.MonthlyPptVarTemp[mo]; avgEcoClimate[ecoregion.Index, mo].AvgPpt = this.MonthlyPrecip[mo]; avgEcoClimate[ecoregion.Index, mo].StdDevPpt = Math.Sqrt(this.MonthlyPrecip[mo]); avgEcoClimate[ecoregion.Index, mo].PAR = this.MonthlyPAR[mo]; } IClimateRecord[] ecoClimate = new IClimateRecord[12]; this.Year = year; this.AnnualPrecip = 0.0; for (int mo = 0; mo < 12; mo++) { ecoClimate[mo] = timestepData[ecoregion.Index, mo]; double MonthlyAvgTemp = (ecoClimate[mo].AvgMinTemp + ecoClimate[mo].AvgMaxTemp) / 2.0; //double standardDeviation = ecoClimate[mo].StdDevTemp * (Climate.ModelCore.GenerateUniform() * 2.0 - 1.0); this.MonthlyTemp[mo] = MonthlyAvgTemp;// + standardDeviation; this.MonthlyMinTemp[mo] = ecoClimate[mo].AvgMinTemp; // + standardDeviation; this.MonthlyMaxTemp[mo] = ecoClimate[mo].AvgMaxTemp; // + standardDeviation; this.MonthlyPrecip[mo] = Math.Max(0.0, ecoClimate[mo].AvgPpt); // + (ecoClimate[mo].StdDevPpt * (Climate.ModelCore.GenerateUniform() * 2.0 - 1.0))); this.MonthlyPAR[mo] = ecoClimate[mo].PAR; this.AnnualPrecip += this.MonthlyPrecip[mo]; if (this.MonthlyPrecip[mo] < 0) this.MonthlyPrecip[mo] = 0; double hr = CalculateDayNightLength(mo, latitude); this.MonthlyDayLength[mo] = (60.0 * 60.0 * hr); // seconds of daylight/day this.MonthlyNightLength[mo] = (60.0 * 60.0 * (24 - hr)); // seconds of nighttime/day //this.DOY[mo] = DayOfYear(mo); } //Climate.ModelCore.UI.WriteLine(" Completed calculations for {0} from AVERAGE MONTHLY data... Ecoregion = {1}, Year = {2}, BeginGrow = {3}.", this.climatePhase, ecoregion.Name, year, this.beginGrowing); return avgEcoClimate; }
//--------------------------------------------------------------------- protected override Dictionary <int, IClimateRecord[, ]> Parse() { ReadLandisDataVar(); Dictionary <int, IClimateRecord[, ]> allData = new Dictionary <int, IClimateRecord[, ]>(); const string nextTableName = "ClimateTable"; //--------------------------------------------------------------------- //Read in climate data: ReadName(nextTableName); //InputVar<string> ecoregionName = new InputVar<string>("Ecoregion"); InputVar <int> ecoregionIndex = new InputVar <int>("Ecoregion Index"); InputVar <int> year = new InputVar <int>("Time step for updating the climate"); InputVar <int> month = new InputVar <int>("The Month"); InputVar <double> avgMinTemp = new InputVar <double>("Monthly Minimum Temperature Value"); InputVar <double> avgMaxTemp = new InputVar <double>("Monthly Maximum Temperature Value"); InputVar <double> stdDevTemp = new InputVar <double>("Monthly Std Deviation Temperature Value"); InputVar <double> avgPpt = new InputVar <double>("Monthly Precipitation Value"); InputVar <double> stdDevPpt = new InputVar <double>("Monthly Std Deviation Precipitation Value"); InputVar <double> par = new InputVar <double>("Monthly Photosynthetically Active Radiation Value"); while (!AtEndOfInput) { StringReader currentLine = new StringReader(CurrentLine); //ReadValue(ecoregionName, currentLine); ReadValue(ecoregionIndex, currentLine); //IEcoregion ecoregion = GetEcoregion(ecoregionName.Value); ReadValue(year, currentLine); int yr = year.Value.Actual; if (!allData.ContainsKey(yr)) { IClimateRecord[,] climateTable = new IClimateRecord[ecoregionDataset.Count, 12]; allData.Add(yr, climateTable); //UI.WriteLine(" Climate Parser: Add new year = {0}.", yr); } ReadValue(month, currentLine); int mo = month.Value.Actual; IClimateRecord climateRecord = new ClimateRecord(); ReadValue(avgMinTemp, currentLine); climateRecord.AvgMinTemp = avgMinTemp.Value; ReadValue(avgMaxTemp, currentLine); climateRecord.AvgMaxTemp = avgMaxTemp.Value; ReadValue(stdDevTemp, currentLine); climateRecord.StdDevTemp = stdDevTemp.Value; ReadValue(avgPpt, currentLine); climateRecord.AvgPpt = avgPpt.Value; ReadValue(stdDevPpt, currentLine); climateRecord.StdDevPpt = stdDevPpt.Value; ReadValue(par, currentLine); climateRecord.PAR = par.Value; allData[yr][ecoregionIndex.Value, mo - 1] = climateRecord; //UI.WriteLine(" climateTable avgPpt={0:0.0}.", climateTable[ecoregion.Index, mo-1].AvgPpt); //UI.WriteLine(" allData yr={0}, mo={1}, avgPpt={2:0.0}.", yr, mo, allData[yr][ecoregion.Index, mo-1].AvgPpt); CheckNoDataAfter("the " + par.Name + " column", currentLine); GetNextLine(); } return(allData); }
//--------------------------------------------------------------------------- private int CalculateEndGrowingDay_Daily(IClimateRecord[] annualClimate)//, Random autoRand) //Calculate End Growing Degree Day (First frost; Minimum = 0 degrees C): { double nightTemp = 0.0; //int beginGrowingDay = CalculateBeginGrowingDay_Daily(annualClimate); int endGrowingDay = MaxDayInYear; //int i = beginGrowingDay; for (int day = MaxDayInYear; day > this.BeginGrowing; day--) //Loop through all the days of the year from day 1 to day 162 { nightTemp = this.DailyMinTemp[day]; if (nightTemp > 0) { //this.endGrowing = i; //endGrowingDay = i; return day; } } return 0; }
//--------------------------------------------------------------------------- private static double[] CalculateVaporPressureDeficit(IClimateRecord[] annualClimate) { // From PnET //Estimation of saturated vapor pressure from daily average temperature. // calculates saturated vp and delta from temp // from Murray J Applied Meteorol 6:203 // ?? are the < 0 equations from there also // Tday average air temperature, degC // ES saturated vapor pressure at Tday, kPa // DELTA dES/dTA at TA, kPa/K which is the slope of the sat. vapor pressure curve // Saturation equations are from: // Murry, (1967). Journal of Applied Meteorology. 6:203. // // // double[] monthlyVPD = new double[12]; for(int month = 0; month < 12; month++) { double Tmin = annualClimate[month].AvgMinTemp; double Tday = (annualClimate[month].AvgMinTemp + annualClimate[month].AvgMaxTemp) / 2.0; double es = 0.61078 * Math.Exp(17.26939 * Tday / (Tday + 237.3)); //kPa //double delta = 4098 * es / (Tday + 237.3) ^ 2.0; if (Tday < 0) { es = 0.61078 * Math.Exp(21.87456 * Tday / (Tday + 265.5)); //kPa //delta = 5808 * es / (Tday + 265.5) ^ 2 } //Calculation of mean daily vapor pressure from minimum daily temperature. // Tmin = minimum daily air temperature //degrees C // emean = mean daily vapor pressure //kPa // Vapor pressure equations are from: // Murray (1967). Journal of Applied Meteorology. 6:203. double emean = 0.61078 * Math.Exp(17.26939 * Tmin / (Tmin + 237.3)); //kPa if (Tmin < 0) emean = 0.61078 * Math.Exp(21.87456 * Tmin / (Tmin + 265.5)); double VPD = es - emean; //if (VPD = 0) // VPD = VPD; monthlyVPD[month] = VPD; } return monthlyVPD; }
private IClimateRecord[,] AnnualClimate_AvgDaily(IEcoregion ecoregion, int year, double latitude) { IClimateRecord[,] timestepData = new IClimateRecord[Climate.ModelCore.Ecoregions.Count, 366]; IClimateRecord[,] avgEcoClimate = new IClimateRecord[Climate.ModelCore.Ecoregions.Count, MaxDayInYear]; IClimateRecord[,] ecoClimateT = new IClimateRecord[Climate.ModelCore.Ecoregions.Count, MaxDayInYear]; for (int i = 0; i < MaxDayInYear; i++) { this.DailyMinTemp[i] = 0.0; this.DailyMaxTemp[i] = 0.0; this.DailyVarTemp[i] = 0.0; this.DailyPptVarTemp[i] = 0.0; this.DailyPrecip[i] = 0.0; this.DailyPAR[i] = 0.0; } int allDataCount = 0; if (this.climatePhase == Climate.Phase.Future_Climate) { allDataCount = Climate.Future_AllData.Count; } else if (this.climatePhase == Climate.Phase.SpinUp_Climate) { allDataCount = Climate.Spinup_AllData.Count; } for (int day = 0; day < MaxDayInYear; day++) { for (int stp = 0; stp < allDataCount; stp++) { if (this.climatePhase == Climate.Phase.Future_Climate) { timestepData = Climate.Future_AllData.ElementAt(stp).Value; } else if (this.climatePhase == Climate.Phase.SpinUp_Climate) { timestepData = Climate.Spinup_AllData.ElementAt(stp).Value; } ecoClimateT[ecoregion.Index, day] = timestepData[ecoregion.Index, day]; //Climate.TimestepData[ecoregion.Index, day]; if (ecoClimateT[ecoregion.Index, day] != null) { this.DailyMinTemp[day] += ecoClimateT[ecoregion.Index, day].AvgMinTemp; this.DailyMaxTemp[day] += ecoClimateT[ecoregion.Index, day].AvgMaxTemp; this.DailyVarTemp[day] += ecoClimateT[ecoregion.Index, day].AvgVarTemp; this.DailyPptVarTemp[day] += ecoClimateT[ecoregion.Index, day].AvgPptVarTemp; this.DailyPrecip[day] += ecoClimateT[ecoregion.Index, day].AvgPpt; this.DailyPAR[day] += ecoClimateT[ecoregion.Index, day].PAR; } } this.DailyMinTemp[day] = this.DailyMinTemp[day] / allDataCount; this.DailyMaxTemp[day] = this.DailyMaxTemp[day] / allDataCount; this.DailyVarTemp[day] = this.DailyVarTemp[day] / allDataCount; this.DailyPptVarTemp[day] = this.DailyPptVarTemp[day] / allDataCount; this.DailyPrecip[day] = this.DailyPrecip[day] / allDataCount; //This DailyPrecip avg is the historic average so the average should be taken as opposed to summing that up. this.DailyPAR[day] = this.DailyPAR[day] / allDataCount; avgEcoClimate[ecoregion.Index, day] = new ClimateRecord(); avgEcoClimate[ecoregion.Index, day].AvgMinTemp = this.DailyMinTemp[day]; avgEcoClimate[ecoregion.Index, day].AvgMaxTemp = this.DailyMaxTemp[day]; avgEcoClimate[ecoregion.Index, day].AvgVarTemp = this.DailyVarTemp[day]; avgEcoClimate[ecoregion.Index, day].StdDevTemp = Math.Sqrt(DailyVarTemp[day]); avgEcoClimate[ecoregion.Index, day].AvgPptVarTemp = this.DailyPptVarTemp[day]; avgEcoClimate[ecoregion.Index, day].AvgPpt = this.DailyPrecip[day]; avgEcoClimate[ecoregion.Index, day].StdDevPpt = Math.Sqrt(this.DailyPrecip[day]); avgEcoClimate[ecoregion.Index, day].PAR = this.DailyPAR[day]; } return(avgEcoClimate); }
//-------------------------------------------------------------------- /// <summary> /// This function converts Monthly to Monthly and Daily to Monthly /// </summary> /// <returns>string: file name of the converted monthly file </returns> public static void Convert_USGS_to_ClimateData_FillAlldata(TemporalGranularity timeStep, string climateFile, string climateFileFormat, Climate.Phase climatePhase) { Dictionary<int, IClimateRecord[,]> allDataRef = null; //this dictionary is filled out either by Daily data or Monthly if (climatePhase == Climate.Phase.Future_Climate) allDataRef = Climate.Future_AllData; if (climatePhase == Climate.Phase.SpinUp_Climate) allDataRef = Climate.Spinup_AllData; //The Convert conversts the csv file data to a dictionary (of either daily or monthly data) //-------------------------------------------------------------------- //string resultingFileName = Convert_USGS_to_ClimateData(timeStep, climateFile, climateFileFormat); //-------------------------------------------------------------------- //Then read from the dictionary and convert it to IClimate records //if (timeStep == TimeStep.Daily) //{ //setIndexed(checkRHWindSpeed); IndexMaxT_Mean = 0; IndexMaxT_Var = 1; IndexMaxT_STD = 2; IndexMinT_Mean = 3; IndexMinT_Var = 4; IndexMinT_STD = 5; IndexPrcp_Mean = 6; IndexPrcp_Var = 7; IndexPrcp_STD = 8; IndexRH_Mean = 9; IndexRH_Var = 10; IndexRH_STD = 11; IndexwindSpeed_Mean = 12; IndexwindSpeed_Var = 13; IndexwindSpeed_STD = 14; for (int j = firstYear; j <= lastYear; j++)//for each year { currentYear = j.ToString(); //Dictionary<string, double[]> climate_Dic_currentYear = (Dictionary<string, double[]>)climate_Dic.Where(r => r.Key.Substring(0, 4).ToString() == currentYear); IEnumerable<KeyValuePair<string, double[]>> climate_Dic_currentYear = climate_Dic.Where(r => r.Key.Substring(0, 4).ToString() == currentYear); IClimateRecord[,] icrs = new IClimateRecord[Climate.ModelCore.Ecoregions.Count, climate_Dic_currentYear.Count()]; // climate_Dic_currentYear.Count: number of days/months in a year for (int i = 0; i < Climate.ModelCore.Ecoregions.Count; i++) //for each ecoregion either active or inactive { //IClimateRecord icr; List<IClimateRecord> icrList = new List<IClimateRecord>(); int icrCount = 0; foreach (KeyValuePair<string, double[]> row in climate_Dic_currentYear) // foreach day/month in a certain year-ecoregion { IClimateRecord icr = new ClimateRecord(row.Value[IndexMinT_Mean], row.Value[IndexMaxT_Mean], (row.Value[IndexMinT_STD] + row.Value[IndexMaxT_STD]) / 2, row.Value[IndexPrcp_Mean], row.Value[IndexPrcp_STD], 0, (row.Value[IndexMinT_Var] + row.Value[IndexMaxT_Var]) / 2, 0, row.Value[IndexRH_Mean], row.Value[IndexRH_Var], row.Value[IndexRH_STD], row.Value[IndexwindSpeed_Mean], row.Value[IndexwindSpeed_Var], row.Value[IndexwindSpeed_STD]); if (Climate.ModelCore.Ecoregions[i].Active) icrs[i, icrCount++] = icr;//new KeyValuePair<int, IClimateRecord>(i, icr); } } allDataRef.Add(j, icrs); } return;// resultingFileName; }
public AnnualClimate_Monthly(IEcoregion ecoregion, int actualYear, double latitude, Climate.Phase spinupOrfuture = Climate.Phase.Future_Climate, int timeStep = Int32.MinValue) //For Hist and Random timeStep arg should be passed { this.climatePhase = spinupOrfuture; this.Latitude = latitude; // ------------------------------------------------------------------------------------------------------ // Case: Daily data used for future climate. Note: No need to ever use daily data with spinup climate //if (Climate.AllData_granularity == TemporalGranularity.Daily && spinupOrfuture == Climate.Phase.Future_Climate) //{ // //Climate.ModelCore.UI.WriteLine(" Processing Daily data into Monthly data. Ecoregion = {0}, Year = {1}, timestep = {2}.", ecoregion.Name, actualYear, timeStep); // this.AnnualClimate_From_AnnualClimate_Daily(ecoregion, actualYear, latitude, spinupOrfuture, timeStep); // return; //} IClimateRecord[,] timestepData = new IClimateRecord[Climate.ModelCore.Ecoregions.Count, 12]; // ------------------------------------------------------------------------------------------------------ // PossibleValues = "MonthlyRandom, MonthlyAverage, DailyHistRandom, DailyHistAverage, MonthlyStandard, DailyGCM"; string climateOption = Climate.ConfigParameters.ClimateTimeSeries; if (this.climatePhase == Climate.Phase.SpinUp_Climate) { climateOption = Climate.ConfigParameters.SpinUpClimateTimeSeries; } switch (climateOption) { case "Monthly_AverageAllYears": { //if (this.climatePhase == Climate.Phase.Future_Climate) //else if (this.climatePhase == Climate.Phase.SpinUp_Climate) // timestepData = AnnualClimate_Avg(ecoregion, actualYear, latitude); timestepData = AnnualClimate_AvgMonth(ecoregion, actualYear, latitude); break; } case "Monthly_AverageWithVariation": { timestepData = AnnualClimate_AvgMonth(ecoregion, actualYear, latitude); CalculateMonthlyData_AddVariance(ecoregion, timestepData, actualYear, latitude); break; } case "Monthly_RandomYear": { TimeStep = timeStep; try { if (this.climatePhase == Climate.Phase.Future_Climate) { timestepData = Climate.Future_AllData[Climate.RandSelectedTimeSteps_future[TimeStep]]; } else if (this.climatePhase == Climate.Phase.SpinUp_Climate) { timestepData = Climate.Spinup_AllData[Climate.RandSelectedTimeSteps_spinup[TimeStep]]; } CalculateMonthlyData_NoVariance(ecoregion, timestepData, actualYear, latitude); } catch (System.Collections.Generic.KeyNotFoundException ex) { throw new ClimateDataOutOfRangeException("Exception: The requested Time-step is out of range for " + this.climatePhase.ToString() + " input file.", ex); } break; } case "Monthly_SequencedYears": { TimeStep = timeStep; try { if (this.climatePhase == Climate.Phase.Future_Climate) { timestepData = Climate.Future_AllData[TimeStep]; } else if (this.climatePhase == Climate.Phase.SpinUp_Climate) { timestepData = Climate.Spinup_AllData[TimeStep]; } CalculateMonthlyData_NoVariance(ecoregion, timestepData, actualYear, latitude); } catch (System.Collections.Generic.KeyNotFoundException ex) { throw new ClimateDataOutOfRangeException("Exception: The requested Time-step is out of range for " + this.climatePhase.ToString() + " input file.", ex); } break; } case "Daily_RandomYear": { this.AnnualClimate_From_AnnualClimate_Daily(ecoregion, actualYear, latitude, spinupOrfuture, timeStep); break; } case "Daily_AverageAllYears": { this.AnnualClimate_From_AnnualClimate_Daily(ecoregion, actualYear, latitude, spinupOrfuture, timeStep); return; } //case "MonthlyStandard": // { // TimeStep = timeStep; // try // { // if (this.climatePhase == Climate.Phase.Future_Climate) // timestepData = Climate.Future_AllData[TimeStep]; // else if (this.climatePhase == Climate.Phase.SpinUp_Climate) // timestepData = Climate.Spinup_AllData[TimeStep]; // CalculateMonthlyData_AddVariance(ecoregion, timestepData, actualYear, latitude); // } // catch (System.Collections.Generic.KeyNotFoundException ex) // { // throw new ClimateDataOutOfRangeException("Exception: The requested Time-step is out of range for " + this.climatePhase.ToString() + " input file.", ex); // } // break; // } case "Daily_SequencedYears": { this.AnnualClimate_From_AnnualClimate_Daily(ecoregion, actualYear, latitude, spinupOrfuture, timeStep); return; } default: throw new ApplicationException(String.Format("Unknown Climate Time Series: {}", climateOption)); } this.MonthlyPET = CalculatePotentialEvapotranspiration(); this.MonthlyVPD = CalculateVaporPressureDeficit(); this.MonthlyGDD = CalculatePnETGDD(); this.beginGrowing = CalculateBeginGrowingSeason(); this.endGrowing = CalculateEndGrowingSeason(); this.growingDegreeDays = GrowSeasonDegreeDays(); for (int mo = 5; mo < 8; mo++) { this.JJAtemperature += this.MonthlyTemp[mo]; } this.JJAtemperature /= 3.0; }
//Daily will not come to here. the average in daily is calculated in the AnnualClimate_Daily private IClimateRecord[,] AnnualClimate_AvgMonth(IEcoregion ecoregion, int year, double latitude) { IClimateRecord[,] timestepData = new IClimateRecord[Climate.ModelCore.Ecoregions.Count, 12]; IClimateRecord[,] avgEcoClimate = new IClimateRecord[Climate.ModelCore.Ecoregions.Count, 12]; //IClimateRecord[,] ecoClimateT = new IClimateRecord[Climate.ModelCore.Ecoregions.Count, 12]; for (int i = 0; i < 12; i++) { this.MonthlyMinTemp[i] = 0.0; this.MonthlyMaxTemp[i] = 0.0; this.MonthlyVarTemp[i] = 0.0; this.MonthlyPptVarTemp[i] = 0.0; this.MonthlyPrecip[i] = 0.0; this.MonthlyPAR[i] = 0.0; } int allDataCount = 0; if (this.climatePhase == Climate.Phase.Future_Climate) { allDataCount = Climate.Future_AllData.Count; } else if (this.climatePhase == Climate.Phase.SpinUp_Climate) { allDataCount = Climate.Spinup_AllData.Count; } for (int mo = 0; mo < 12; mo++) { for (int stp = 0; stp < allDataCount; stp++) { if (this.climatePhase == Climate.Phase.Future_Climate) { timestepData = Climate.Future_AllData.ElementAt(stp).Value; } else if (this.climatePhase == Climate.Phase.SpinUp_Climate) { timestepData = Climate.Spinup_AllData.ElementAt(stp).Value; } //Climate.ModelCore.UI.WriteLine(" Calculating annual average climate: Yr={0}, month={1}, Eco={2}, Phase={3}.", Climate.Future_AllData.ElementAt(stp).Key, mo, ecoregion.Name, this.climatePhase); this.MonthlyMinTemp[mo] += timestepData[ecoregion.Index, mo].AvgMinTemp; this.MonthlyMaxTemp[mo] += timestepData[ecoregion.Index, mo].AvgMaxTemp; this.MonthlyVarTemp[mo] += timestepData[ecoregion.Index, mo].AvgVarTemp; this.MonthlyPptVarTemp[mo] += timestepData[ecoregion.Index, mo].AvgPptVarTemp; this.MonthlyPrecip[mo] += timestepData[ecoregion.Index, mo].AvgPpt; this.MonthlyPAR[mo] += timestepData[ecoregion.Index, mo].PAR; } this.MonthlyMinTemp[mo] = this.MonthlyMinTemp[mo] / allDataCount; this.MonthlyMaxTemp[mo] = this.MonthlyMaxTemp[mo] / allDataCount; this.MonthlyVarTemp[mo] = this.MonthlyVarTemp[mo] / allDataCount; this.MonthlyPptVarTemp[mo] = this.MonthlyPptVarTemp[mo] / allDataCount; this.MonthlyPrecip[mo] = this.MonthlyPrecip[mo] / allDataCount; this.MonthlyPAR[mo] = this.MonthlyPAR[mo] / allDataCount; avgEcoClimate[ecoregion.Index, mo] = new ClimateRecord(); avgEcoClimate[ecoregion.Index, mo].AvgMinTemp = this.MonthlyMinTemp[mo]; avgEcoClimate[ecoregion.Index, mo].AvgMaxTemp = this.MonthlyMaxTemp[mo]; avgEcoClimate[ecoregion.Index, mo].AvgVarTemp = this.MonthlyVarTemp[mo]; avgEcoClimate[ecoregion.Index, mo].StdDevTemp = Math.Sqrt(MonthlyVarTemp[mo]); avgEcoClimate[ecoregion.Index, mo].AvgPptVarTemp = this.MonthlyPptVarTemp[mo]; avgEcoClimate[ecoregion.Index, mo].AvgPpt = this.MonthlyPrecip[mo]; avgEcoClimate[ecoregion.Index, mo].StdDevPpt = Math.Sqrt(this.MonthlyPrecip[mo]); avgEcoClimate[ecoregion.Index, mo].PAR = this.MonthlyPAR[mo]; } IClimateRecord[] ecoClimate = new IClimateRecord[12]; this.Year = year; this.AnnualPrecip = 0.0; for (int mo = 0; mo < 12; mo++) { ecoClimate[mo] = timestepData[ecoregion.Index, mo]; double MonthlyAvgTemp = (ecoClimate[mo].AvgMinTemp + ecoClimate[mo].AvgMaxTemp) / 2.0; //double standardDeviation = ecoClimate[mo].StdDevTemp * (Climate.ModelCore.GenerateUniform() * 2.0 - 1.0); this.MonthlyTemp[mo] = MonthlyAvgTemp; // + standardDeviation; this.MonthlyMinTemp[mo] = ecoClimate[mo].AvgMinTemp; // + standardDeviation; this.MonthlyMaxTemp[mo] = ecoClimate[mo].AvgMaxTemp; // + standardDeviation; this.MonthlyPrecip[mo] = Math.Max(0.0, ecoClimate[mo].AvgPpt); // + (ecoClimate[mo].StdDevPpt * (Climate.ModelCore.GenerateUniform() * 2.0 - 1.0))); this.MonthlyPAR[mo] = ecoClimate[mo].PAR; this.AnnualPrecip += this.MonthlyPrecip[mo]; if (this.MonthlyPrecip[mo] < 0) { this.MonthlyPrecip[mo] = 0; } double hr = CalculateDayNightLength(mo, latitude); this.MonthlyDayLength[mo] = (60.0 * 60.0 * hr); // seconds of daylight/day this.MonthlyNightLength[mo] = (60.0 * 60.0 * (24 - hr)); // seconds of nighttime/day //this.DOY[mo] = DayOfYear(mo); } //Climate.ModelCore.UI.WriteLine(" Completed calculations for {0} from AVERAGE MONTHLY data... Ecoregion = {1}, Year = {2}, BeginGrow = {3}.", this.climatePhase, ecoregion.Name, year, this.beginGrowing); return(avgEcoClimate); }
//--------------------------------------------------------------------------- private static int CalculateBeginGrowingSeason(IClimateRecord[] annualClimate) //Calculate Begin Growing Degree Day (Last Frost; Minimum = 0 degrees C): { NormalRandomVar randVar = new NormalRandomVar(0, 1); double lastMonthMinTemp = annualClimate[0].AvgMinTemp; int dayCnt = 15; //the middle of February int beginGrowingSeason = -1; for (int i = 1; i < 7; i++) //Begin looking in February (1). Should be safe for at least 100 years. { int totalDays = (DaysInMonth(i, 3) + DaysInMonth(i-1, 3)) / 2; double MonthlyMinTemp = annualClimate[i].AvgMinTemp;// + (monthlyTempSD[i] * randVar.GenerateNumber()); //Now interpolate between days: double degreeIncrement = System.Math.Abs(MonthlyMinTemp - lastMonthMinTemp) / (double) totalDays; double Tnight = MonthlyMinTemp; //start from warmer month double TnightRandom = Tnight + (annualClimate[i].StdDevTemp * (Landis.Util.Random.GenerateUniform() * 2 - 1)); for(int day = 1; day <= totalDays; day++) { if(TnightRandom <= 0) beginGrowingSeason = (dayCnt + day); Tnight += degreeIncrement; //work backwards to find last frost day. TnightRandom = Tnight + (annualClimate[i].StdDevTemp * (Landis.Util.Random.GenerateUniform() * 2 - 1)); } lastMonthMinTemp = MonthlyMinTemp; dayCnt += totalDays; //new monthly mid-point } return beginGrowingSeason; }
//--------------------------------------------------------------------------- private static int CalculateEndGrowingSeason(IClimateRecord[] annualClimate)//, Random autoRand) //Calculate End Growing Degree Day (First frost; Minimum = 0 degrees C): { NormalRandomVar randVar = new NormalRandomVar(0, 1); //Defaults for the middle of July: double lastMonthTemp = annualClimate[6].AvgMinTemp; int dayCnt = 198; //int endGrowingSeason = 198; for (int i = 7; i < 12; i++) //Begin looking in August. Should be safe for at least 100 years. { int totalDays = (DaysInMonth(i, 3) + DaysInMonth(i-1, 3)) / 2; double MonthlyMinTemp = annualClimate[i].AvgMinTemp; //Now interpolate between days: double degreeIncrement = System.Math.Abs(lastMonthTemp - MonthlyMinTemp) / (double) totalDays; double Tnight = lastMonthTemp; //start from warmer month //double randomT = (2 * annualClimate[i].StdDevTemp * randVar.GenerateNumber(autoRand)); //Console.WriteLine("Night Temp random offset = {0}.", randomT); double TnightRandom = Tnight + (annualClimate[i].StdDevTemp * (Landis.Util.Random.GenerateUniform() * 2 - 1)); for(int day = 1; day <= totalDays; day++) { if(TnightRandom <= 0) return (dayCnt + day); Tnight -= degreeIncrement; //work forwards to find first frost day. TnightRandom = Tnight + (annualClimate[i].StdDevTemp * (Landis.Util.Random.GenerateUniform() * 2 - 1)); //Console.WriteLine("Tnight = {0}.", TnightRandom); } lastMonthTemp = MonthlyMinTemp; dayCnt += totalDays; //new monthly mid-point } return 365; }
//For Sequenced and Random timeStep arg should be passed public AnnualClimate_Daily(IEcoregion ecoregion, int actualYear, double latitude, Climate.Phase spinupOrfuture = Climate.Phase.Future_Climate, int timeStep = Int32.MinValue) { this.climatePhase = spinupOrfuture; IClimateRecord[,] timestepData = new IClimateRecord[Climate.ModelCore.Ecoregions.Count, 366]; string climateOption = Climate.ConfigParameters.ClimateTimeSeries; if (this.climatePhase == Climate.Phase.SpinUp_Climate) { climateOption = Climate.ConfigParameters.SpinUpClimateTimeSeries; } //Climate.ModelCore.UI.WriteLine(" Calculating daily data ... Ecoregion = {0}, Year = {1}, timestep = {2}.", ecoregion.Name, actualYear, timeStep); switch (climateOption) { case "Daily_RandomYear": { TimeStep = timeStep; if (this.climatePhase == Climate.Phase.Future_Climate) { timestepData = Climate.Future_AllData[Climate.RandSelectedTimeSteps_future[TimeStep]]; } else if (this.climatePhase == Climate.Phase.SpinUp_Climate) { timestepData = Climate.Spinup_AllData[Climate.RandSelectedTimeSteps_future[TimeStep]]; } break; } case "Daily_AverageAllYears": { if (this.climatePhase == Climate.Phase.Future_Climate) { timestepData = AnnualClimate_AvgDaily(ecoregion, actualYear, latitude); } else if (this.climatePhase == Climate.Phase.SpinUp_Climate) { timestepData = AnnualClimate_AvgDaily(ecoregion, actualYear, latitude); } break; } case "Daily_SequencedYears": { TimeStep = timeStep; try { timestepData = Climate.Future_AllData[TimeStep]; } catch (System.Collections.Generic.KeyNotFoundException ex) { throw new ClimateDataOutOfRangeException("Exception: The requested Time-step or ecoregion is out of range of the provided " + this.climatePhase.ToString() + " input file. This may be because the number of input climate data is not devisable to the number of specified time-steps or there is not enough historic climate data to run the model for the specified duration.", ex); } break; } default: throw new ApplicationException(String.Format("Unknown Climate Time Series: {}", climateOption)); } IClimateRecord[] ecoClimate = new IClimateRecord[MaxDayInYear]; this.Year = actualYear; this.AnnualPrecip = 0.0; for (int day = 0; day < MaxDayInYear; day++) { ecoClimate[day] = timestepData[ecoregion.Index, day]; if (ecoClimate[day] != null) { double DailyAvgTemp = (ecoClimate[day].AvgMinTemp + ecoClimate[day].AvgMaxTemp) / 2.0; //Climate.ModelCore.UI.WriteLine("Timestep Data. PPt={0}, T={1}.", ecoClimate[day].AvgPpt, DailyAvgTemp); this.DailyTemp[day] = DailyAvgTemp; this.DailyMinTemp[day] = ecoClimate[day].AvgMinTemp; this.DailyMaxTemp[day] = ecoClimate[day].AvgMaxTemp; this.DailyPrecip[day] = Math.Max(0.0, ecoClimate[day].AvgPpt); this.DailyPAR[day] = ecoClimate[day].PAR; this.AnnualPrecip += this.DailyPrecip[day]; if (this.DailyPrecip[day] < 0) { this.DailyPrecip[day] = 0; } double hr = CalculateDayNightLength(day, latitude); this.DailyDayLength[day] = (60.0 * 60.0 * hr); // seconds of daylight/day this.DailyNightLength[day] = (60.0 * 60.0 * (24 - hr)); // seconds of nighttime/day //this.DOY[day] = DayOfYear(day); } else { Climate.ModelCore.UI.WriteLine("Daily data = null."); } } this.beginGrowing = CalculateBeginGrowingDay_Daily(); //ecoClimate); this.endGrowing = CalculateEndGrowingDay_Daily(ecoClimate); this.growingDegreeDays = GrowSeasonDegreeDays(actualYear); //if (Climate.TimestepData.GetLength(1) > 365) if (timestepData.GetLength(1) > 365) { this.isLeapYear = true; } }
//--------------------------------------------------------------------------- private static double[] CalculatePotentialEvapotranspiration(IClimateRecord[] annualClimate) { //Calculate potential evapotranspiration (pevap) //...Originally from pevap.f // FWLOSS(4) - Scaling factor for potential evapotranspiration (pevap). double waterLossFactor4 = 0.9; //from Century v4.5 // FINISH - from ecoregion data??? double elev = 1.0; //Definition?? Set elevation = 0??? double sitlat = 0.0; // Site latitude??? double highest = -40.0; double lowest = 100.0; for(int i = 0; i < 12; i++) { double avgTemp = (annualClimate[i].AvgMinTemp + annualClimate[i].AvgMaxTemp) / 2.0; highest = System.Math.Max(highest, avgTemp); lowest = System.Math.Min(lowest, avgTemp); } lowest = System.Math.Max(lowest, -10.0); //...Determine average temperature range double avgTempRange = System.Math.Abs(highest - lowest); double[] monthlyPET = new double[12]; for(int month = 0; month < 12; month++) { //...Temperature range calculation double tr = annualClimate[month].AvgMaxTemp - System.Math.Max(-10.0, annualClimate[month].AvgMinTemp); double t = tr / 2.0 + annualClimate[month].AvgMinTemp; double tm = t + 0.006 * elev; double td = (0.0023 * elev) + (0.37 * t) + (0.53 * tr) + (0.35 * avgTempRange) - 10.9; double e = ((700.0 * tm / (100.0 - System.Math.Abs(sitlat))) + 15.0 * td) / (80.0 - t); double monpet = (e * 30.0)/10.0; if (monpet < 0.5) monpet = 0.5; //...fwloss(4) is a modifier for PET loss. vek may90 monthlyPET[month] = monpet * waterLossFactor4; } return monthlyPET; }
// ------------------------------------------------------------------------------------------------------ private void CalculateMonthlyData_AddVariance(IEcoregion ecoregion, IClimateRecord[,] timestepData, int actualYear, double latitude) { IClimateRecord[] ecoClimate = new IClimateRecord[12]; this.Year = actualYear; this.AnnualPrecip = 0.0; //if(timestepData[ecoregion.Index]. ADD MONTH CHECK HERE. for (int mo = 0; mo < 12; mo++) { ecoClimate[mo] = timestepData[ecoregion.Index, mo]; //Climate.TimestepData[ecoregion.Index, mo]; double MonthlyAvgTemp = (ecoClimate[mo].AvgMinTemp + ecoClimate[mo].AvgMaxTemp) / 2.0; double standardDeviation = ecoClimate[mo].StdDevTemp * (Climate.ModelCore.GenerateUniform() * 2.0 - 1.0); this.MonthlyTemp[mo] = MonthlyAvgTemp + standardDeviation; this.MonthlyMinTemp[mo] = ecoClimate[mo].AvgMinTemp + standardDeviation; this.MonthlyMaxTemp[mo] = ecoClimate[mo].AvgMaxTemp + standardDeviation; this.MonthlyPrecip[mo] = Math.Max(0.0, ecoClimate[mo].AvgPpt + (ecoClimate[mo].StdDevPpt * (Climate.ModelCore.GenerateUniform() * 2.0 - 1.0))); this.MonthlyPAR[mo] = ecoClimate[mo].PAR; this.AnnualPrecip += this.MonthlyPrecip[mo]; if (this.MonthlyPrecip[mo] < 0) this.MonthlyPrecip[mo] = 0; double hr = CalculateDayNightLength(mo, latitude); this.MonthlyDayLength[mo] = (60.0 * 60.0 * hr); // seconds of daylight/day this.MonthlyNightLength[mo] = (60.0 * 60.0 * (24 - hr)); // seconds of nighttime/day //this.DOY[mo] = DayOfYear(mo); } }
private IClimateRecord[,] AnnualClimate_AvgDaily(IEcoregion ecoregion, int year, double latitude) { IClimateRecord[,] timestepData = new IClimateRecord[Climate.ModelCore.Ecoregions.Count, 366]; IClimateRecord[,] avgEcoClimate = new IClimateRecord[Climate.ModelCore.Ecoregions.Count, MaxDayInYear]; IClimateRecord[,] ecoClimateT = new IClimateRecord[Climate.ModelCore.Ecoregions.Count, MaxDayInYear]; for (int i = 0; i < MaxDayInYear; i++) { this.DailyMinTemp[i] = 0.0; this.DailyMaxTemp[i] = 0.0; this.DailyVarTemp[i] = 0.0; this.DailyPptVarTemp[i] = 0.0; this.DailyPrecip[i] = 0.0; this.DailyPAR[i] = 0.0; } int allDataCount = 0; if (this.climatePhase == Climate.Phase.Future_Climate) allDataCount = Climate.Future_AllData.Count; else if (this.climatePhase == Climate.Phase.SpinUp_Climate) allDataCount = Climate.Spinup_AllData.Count; for (int day = 0; day < MaxDayInYear; day++) { for (int stp = 0; stp < allDataCount; stp++) { if (this.climatePhase == Climate.Phase.Future_Climate) timestepData = Climate.Future_AllData.ElementAt(stp).Value; else if (this.climatePhase == Climate.Phase.SpinUp_Climate) timestepData = Climate.Spinup_AllData.ElementAt(stp).Value; ecoClimateT[ecoregion.Index, day] = timestepData[ecoregion.Index, day]; //Climate.TimestepData[ecoregion.Index, day]; if (ecoClimateT[ecoregion.Index, day] != null) { this.DailyMinTemp[day] += ecoClimateT[ecoregion.Index, day].AvgMinTemp; this.DailyMaxTemp[day] += ecoClimateT[ecoregion.Index, day].AvgMaxTemp; this.DailyVarTemp[day] += ecoClimateT[ecoregion.Index, day].AvgVarTemp; this.DailyPptVarTemp[day] += ecoClimateT[ecoregion.Index, day].AvgPptVarTemp; this.DailyPrecip[day] += ecoClimateT[ecoregion.Index, day].AvgPpt; this.DailyPAR[day] += ecoClimateT[ecoregion.Index, day].PAR; } } this.DailyMinTemp[day] = this.DailyMinTemp[day] / allDataCount; this.DailyMaxTemp[day] = this.DailyMaxTemp[day] / allDataCount; this.DailyVarTemp[day] = this.DailyVarTemp[day] / allDataCount; this.DailyPptVarTemp[day] = this.DailyPptVarTemp[day] / allDataCount; this.DailyPrecip[day] = this.DailyPrecip[day] / allDataCount; //This DailyPrecip avg is the historic average so the average should be taken as opposed to summing that up. this.DailyPAR[day] = this.DailyPAR[day] / allDataCount; avgEcoClimate[ecoregion.Index, day] = new ClimateRecord(); avgEcoClimate[ecoregion.Index, day].AvgMinTemp = this.DailyMinTemp[day]; avgEcoClimate[ecoregion.Index, day].AvgMaxTemp = this.DailyMaxTemp[day]; avgEcoClimate[ecoregion.Index, day].AvgVarTemp = this.DailyVarTemp[day]; avgEcoClimate[ecoregion.Index, day].StdDevTemp = Math.Sqrt(DailyVarTemp[day]); avgEcoClimate[ecoregion.Index, day].AvgPptVarTemp = this.DailyPptVarTemp[day]; avgEcoClimate[ecoregion.Index, day].AvgPpt = this.DailyPrecip[day]; avgEcoClimate[ecoregion.Index, day].StdDevPpt = Math.Sqrt(this.DailyPrecip[day]); avgEcoClimate[ecoregion.Index, day].PAR = this.DailyPAR[day]; } return avgEcoClimate; }
private void CalculateMonthlyData_NoVariance(IEcoregion ecoregion, IClimateRecord[,] timestepData, int actualYear, double latitude) { IClimateRecord[] ecoClimate = new IClimateRecord[12]; this.Year = actualYear; this.AnnualPrecip = 0.0; //if(timestepData[ecoregion.Index]. ADD MONTH CHECK HERE. for (int mo = 0; mo < 12; mo++) { //Climate.ModelCore.UI.WriteLine(" Calculating Monthly Climate (No Variance): Yr={0}, month={1}, Eco={2}, Phase={3}.", actualYear, mo, ecoregion.Name, this.climatePhase); ecoClimate[mo] = timestepData[ecoregion.Index, mo]; double MonthlyAvgTemp = (ecoClimate[mo].AvgMinTemp + ecoClimate[mo].AvgMaxTemp) / 2.0; //double standardDeviation = ecoClimate[mo].StdDevTemp * (Climate.ModelCore.GenerateUniform() * 2.0 - 1.0); this.MonthlyTemp[mo] = MonthlyAvgTemp; this.MonthlyMinTemp[mo] = ecoClimate[mo].AvgMinTemp; this.MonthlyMaxTemp[mo] = ecoClimate[mo].AvgMaxTemp; this.MonthlyPrecip[mo] = Math.Max(0.0, ecoClimate[mo].AvgPpt); this.MonthlyPAR[mo] = ecoClimate[mo].PAR; this.AnnualPrecip += this.MonthlyPrecip[mo]; if (this.MonthlyPrecip[mo] < 0) this.MonthlyPrecip[mo] = 0; double hr = CalculateDayNightLength(mo, latitude); this.MonthlyDayLength[mo] = (60.0 * 60.0 * hr); // seconds of daylight/day this.MonthlyNightLength[mo] = (60.0 * 60.0 * (24 - hr)); // seconds of nighttime/day } }
//For Sequenced and Random timeStep arg should be passed public AnnualClimate_Daily(IEcoregion ecoregion, int actualYear, double latitude, Climate.Phase spinupOrfuture = Climate.Phase.Future_Climate, int timeStep = Int32.MinValue) { this.climatePhase = spinupOrfuture; IClimateRecord[,] timestepData = new IClimateRecord[Climate.ModelCore.Ecoregions.Count, 366]; string climateOption = Climate.ConfigParameters.ClimateTimeSeries; if (this.climatePhase == Climate.Phase.SpinUp_Climate) climateOption = Climate.ConfigParameters.SpinUpClimateTimeSeries; //Climate.ModelCore.UI.WriteLine(" Calculating daily data ... Ecoregion = {0}, Year = {1}, timestep = {2}.", ecoregion.Name, actualYear, timeStep); switch (climateOption) { case "Daily_RandomYear": { TimeStep = timeStep; if (this.climatePhase == Climate.Phase.Future_Climate) timestepData = Climate.Future_AllData[Climate.RandSelectedTimeSteps_future[TimeStep]]; else if (this.climatePhase == Climate.Phase.SpinUp_Climate) timestepData = Climate.Spinup_AllData[Climate.RandSelectedTimeSteps_future[TimeStep]]; break; } case "Daily_AverageAllYears": { if (this.climatePhase == Climate.Phase.Future_Climate) timestepData = AnnualClimate_AvgDaily(ecoregion, actualYear, latitude); else if (this.climatePhase == Climate.Phase.SpinUp_Climate) timestepData = AnnualClimate_AvgDaily(ecoregion, actualYear, latitude); break; } case "Daily_SequencedYears": { TimeStep = timeStep; try { timestepData = Climate.Future_AllData[TimeStep]; } catch (System.Collections.Generic.KeyNotFoundException ex) { throw new ClimateDataOutOfRangeException("Exception: The requested Time-step or ecoregion is out of range of the provided " + this.climatePhase.ToString() + " input file. This may be because the number of input climate data is not devisable to the number of specified time-steps or there is not enough historic climate data to run the model for the specified duration.", ex); } break; } default: throw new ApplicationException(String.Format("Unknown Climate Time Series: {}", climateOption)); } IClimateRecord[] ecoClimate = new IClimateRecord[MaxDayInYear]; this.Year = actualYear; this.AnnualPrecip = 0.0; for (int day = 0; day < MaxDayInYear; day++) { ecoClimate[day] = timestepData[ecoregion.Index, day]; if (ecoClimate[day] != null) { double DailyAvgTemp = (ecoClimate[day].AvgMinTemp + ecoClimate[day].AvgMaxTemp) / 2.0; //Climate.ModelCore.UI.WriteLine("Timestep Data. PPt={0}, T={1}.", ecoClimate[day].AvgPpt, DailyAvgTemp); this.DailyTemp[day] = DailyAvgTemp; this.DailyMinTemp[day] = ecoClimate[day].AvgMinTemp; this.DailyMaxTemp[day] = ecoClimate[day].AvgMaxTemp; this.DailyPrecip[day] = Math.Max(0.0, ecoClimate[day].AvgPpt); this.DailyPAR[day] = ecoClimate[day].PAR; this.AnnualPrecip += this.DailyPrecip[day]; if (this.DailyPrecip[day] < 0) this.DailyPrecip[day] = 0; double hr = CalculateDayNightLength(day, latitude); this.DailyDayLength[day] = (60.0 * 60.0 * hr); // seconds of daylight/day this.DailyNightLength[day] = (60.0 * 60.0 * (24 - hr)); // seconds of nighttime/day //this.DOY[day] = DayOfYear(day); } else { Climate.ModelCore.UI.WriteLine("Daily data = null."); } } this.beginGrowing = CalculateBeginGrowingDay_Daily(); //ecoClimate); this.endGrowing = CalculateEndGrowingDay_Daily(ecoClimate); this.growingDegreeDays = GrowSeasonDegreeDays(actualYear); //if (Climate.TimestepData.GetLength(1) > 365) if (timestepData.GetLength(1) > 365) this.isLeapYear = true; }
//--------------------------------------------------------------------- private static void Write(IClimateRecord[,] TimestepData, int year, string period) { //spinup_allData. foreach (IEcoregion ecoregion in Climate.ModelCore.Ecoregions) { if (ecoregion.Active) { for (int month = 0; month < 12; month++) { MonthlyLog.Clear(); MonthlyLog ml = new MonthlyLog(); ml.SimulationPeriod = period; ml.Time = year; ml.Month = month + 1; ml.EcoregionName = ecoregion.Name; ml.EcoregionIndex = ecoregion.Index; ml.min_airtemp = TimestepData[ecoregion.Index, month].AvgMinTemp; ml.max_airtemp = TimestepData[ecoregion.Index, month].AvgMaxTemp; ml.std_temp = TimestepData[ecoregion.Index, month].StdDevTemp; ml.ppt = TimestepData[ecoregion.Index, month].AvgPpt; ml.std_ppt = TimestepData[ecoregion.Index, month].StdDevPpt; MonthlyLog.AddObject(ml); MonthlyLog.WriteToFile(); } } } }