//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;
           

        }
        /// <summary>
        /// Converts USGS Data to Standard Input climate Data and fill out the Future_AllData and/or Spinup_AllData
        /// </summary>
        /// 
        public static void ConvertFileFormat_FillOutAllData(String timeSeries, string filePath, string fileFormat, Climate.Phase climatePhase)
        {
            if (climatePhase == Climate.Phase.Future_Climate && timeSeries.Contains("Daily"))
                future_allData_granularity = TemporalGranularity.Daily;

            else if (climatePhase == Climate.Phase.Future_Climate && timeSeries.Contains("Monthly"))
                future_allData_granularity = TemporalGranularity.Monthly;

            else if (climatePhase == Climate.Phase.SpinUp_Climate && timeSeries.Contains("Daily"))
                spinup_allData_granularity = TemporalGranularity.Daily;

            else if (climatePhase == Climate.Phase.SpinUp_Climate && timeSeries.Contains("Monthly"))
                spinup_allData_granularity = TemporalGranularity.Monthly;

            if (timeSeries.Contains("Daily"))
                ClimateDataConvertor.Convert_USGS_to_ClimateData_FillAlldata(TemporalGranularity.Daily, filePath, fileFormat, climatePhase);

            else if (timeSeries.Contains("Monthly"))
                ClimateDataConvertor.Convert_USGS_to_ClimateData_FillAlldata(TemporalGranularity.Monthly, filePath, fileFormat, climatePhase);

            return;
        }
Пример #3
0
        //---------------------------------------------------------------------
        public static void Initialize(string climateConfigFilename, bool writeOutput, ICore mCore)
        {
            InputParametersParser inParamsParser = new InputParametersParser();

            configParameters = Landis.Data.Load <IInputParameters>(climateConfigFilename, inParamsParser);

            modelCore = mCore;
            MetadataHandler.InitializeMetadata(1, modelCore);

            ModelCore.UI.WriteLine("   Loading weather data ...");
            Climate.future_allData = new Dictionary <int, IClimateRecord[, ]>();
            Climate.spinup_allData = new Dictionary <int, IClimateRecord[, ]>();

            Future_MonthlyData  = new Dictionary <int, AnnualClimate_Monthly[]>();
            Spinup_MonthlyData  = new Dictionary <int, AnnualClimate_Monthly[]>();
            Future_DailyData    = new Dictionary <int, AnnualClimate_Daily[]>();
            Spinup_DailyData    = new Dictionary <int, AnnualClimate_Daily[]>();
            LandscapeAnnualPDSI = new double[Climate.ModelCore.EndTime - Climate.ModelCore.StartTime + 1];

            ModelCore.UI.WriteLine("   Loading spin-up weather data from file {0} ...", configParameters.SpinUpClimateFile);
            Climate.ConvertFileFormat_FillOutAllData(configParameters.SpinUpClimateTimeSeries, configParameters.SpinUpClimateFile, configParameters.SpinUpClimateFileFormat, Climate.Phase.SpinUp_Climate);

            ModelCore.UI.WriteLine("   Loading future weather data from file {0} ...", configParameters.ClimateFile);
            Climate.ConvertFileFormat_FillOutAllData(configParameters.ClimateTimeSeries, configParameters.ClimateFile, configParameters.ClimateFileFormat, Climate.Phase.Future_Climate);


            //string climateOption = Climate.ConfigParameters.ClimateTimeSeries;
            //if (this.climatePhase == Climate.Phase.SpinUp_Climate)
            //    climateOption = Climate.ConfigParameters.SpinUpClimateTimeSeries;

            //switch (climateOption)
            //{
            //    case "MonthlyAverage":
            //        {
            //            break;
            //        }
            //    case "MonthlyRandom":
            //        {
            //            break;
            //        }
            //    case "DailyHistRandom":
            //        {
            //            break;
            //        }
            //    case "DailyHistAverage":
            //        {
            //            return;
            //        }
            //    case "MonthlyStandard":
            //        {
            //            break;
            //        }
            //    case "DailyGCM":
            //        {
            //        }
            //    case "MonthlyGCM":
            //        {
            //            break;
            //        }
            //    default:
            //        throw new ApplicationException(String.Format("Unknown Climate Time Series: {}", climateOption));

            //}


            if (Climate.ConfigParameters.ClimateTimeSeries.ToLower().Contains("random"))
            {
                Climate.randSelectedTimeSteps_future = new int[Climate.future_allData.Count];//should be future_allData.Count or it needs to be different?
                for (int i = 0; i < Climate.future_allData.Count; i++)
                {
                    Climate.randSelectedTimeSteps_future[i] = (int)Math.Round(Climate.ModelCore.GenerateUniform() * (Climate.future_allData.Count - 1));
                }
            }

            if (Climate.ConfigParameters.SpinUpClimateTimeSeries.ToLower().Contains("random"))
            {
                //int maxSpeciesAge = modelCore.Species.Max(sp => sp.Longevity);
                int maxSpeciesAge = 0;
                foreach (ISpecies sp in ModelCore.Species)
                {
                    if (sp.Longevity > maxSpeciesAge)
                    {
                        maxSpeciesAge = sp.Longevity;
                    }
                }

                Climate.randSelectedTimeSteps_spinup = new int[maxSpeciesAge];
                for (int i = 0; i < maxSpeciesAge; i++)
                {
                    Climate.randSelectedTimeSteps_spinup[i] = (int)Math.Round(Climate.ModelCore.GenerateUniform() * (Climate.spinup_allData.Count - 1));
                }
            }
            foreach (KeyValuePair <int, IClimateRecord[, ]> timeStep in spinup_allData)
            {
                //Climate.TimestepData = timeStep.Value;
                IClimateRecord[,] timestepData = timeStep.Value;
                int year = timeStep.Key;
                //Write(timestepData, year, "SpinUp");

                Spinup_MonthlyData.Add(timeStep.Key, new AnnualClimate_Monthly[modelCore.Ecoregions.Count]);
                Spinup_DailyData.Add(timeStep.Key, new AnnualClimate_Daily[modelCore.Ecoregions.Count]);
                Climate.Write(timestepData, timeStep.Key, Climate.Phase.SpinUp_Climate.ToString());
            }
            foreach (KeyValuePair <int, IClimateRecord[, ]> timeStep in future_allData)
            {
                //Climate.TimestepData = timeStep.Value;
                IClimateRecord[,] timestepData = timeStep.Value;
                int year = timeStep.Key;
                //Write(timestepData, year, "Future");

                Future_MonthlyData.Add(timeStep.Key, new AnnualClimate_Monthly[modelCore.Ecoregions.Count]);
                Future_DailyData.Add(timeStep.Key, new AnnualClimate_Daily[modelCore.Ecoregions.Count]);
                Climate.Write(timestepData, timeStep.Key, Climate.Phase.Future_Climate.ToString());
            }
        }
        //---------------------------------------------------------------------
        // Generates new climate parameters for a SINGLE ECOREGION at an annual time step.
        public static void SetSingleAnnualClimate(IEcoregion ecoregion, int year, Climate.Phase spinupOrfuture)
        {
            int actualYear = PlugIn.ModelCore.CurrentTime + year;

            if (spinupOrfuture == Climate.Phase.Future_Climate)
            {
                actualYear += Climate.Future_MonthlyData.First().Key;
                //PlugIn.ModelCore.UI.WriteLine("Retrieving {0} for year {1}.", spinupOrfuture.ToString(), actualYear);
                if (Climate.Future_MonthlyData.ContainsKey(actualYear))
                {
                    AnnualWeather[ecoregion] = Climate.Future_MonthlyData[actualYear][ecoregion.Index];
                    //AnnualWeather[ecoregion].WriteToLandisLogFile();
                }
                //else
                //    PlugIn.ModelCore.UI.WriteLine("Key is missing: Retrieving {0} for year {1}.", spinupOrfuture.ToString(), actualYear);
            }
            else
            {
                if (LastYearUpdated[ecoregion] == year+1)
                    return;

                actualYear += Climate.Spinup_MonthlyData.First().Key;
                //PlugIn.ModelCore.UI.WriteLine("Retrieving {0} for year {1}.", spinupOrfuture.ToString(), actualYear);
                if (Climate.Spinup_MonthlyData.ContainsKey(actualYear))
                {
                    AnnualWeather[ecoregion] = Climate.Spinup_MonthlyData[actualYear][ecoregion.Index];
                    LastYearUpdated[ecoregion] = year+1;
                }
            }
        }
Пример #5
0
        //---------------------------------------------------------------------
        public static void Initialize(string climateConfigFilename, bool writeOutput, ICore mCore)
        {
            InputParametersParser inParamsParser = new InputParametersParser();

            configParameters = Landis.Data.Load <IInputParameters>(climateConfigFilename, inParamsParser);

            modelCore = mCore;
            MetadataHandler.InitializeMetadata(1, modelCore);

            ModelCore.UI.WriteLine("   Loading weather data ...");
            Climate.future_allData = new Dictionary <int, ClimateRecord[][]>();
            Climate.spinup_allData = new Dictionary <int, ClimateRecord[][]>();

            Future_MonthlyData  = new Dictionary <int, AnnualClimate_Monthly[]>();
            Spinup_MonthlyData  = new Dictionary <int, AnnualClimate_Monthly[]>();
            Future_DailyData    = new Dictionary <int, AnnualClimate_Daily[]>();
            Spinup_DailyData    = new Dictionary <int, AnnualClimate_Daily[]>();
            LandscapeAnnualPDSI = new double[Climate.ModelCore.EndTime - Climate.ModelCore.StartTime + 1];

            ModelCore.UI.WriteLine("   Loading spin-up weather data from file {0} ...", configParameters.SpinUpClimateFile);
            Climate.ConvertFileFormat_FillOutAllData(configParameters.SpinUpClimateTimeSeries, configParameters.SpinUpClimateFile, configParameters.SpinUpClimateFileFormat, Climate.Phase.SpinUp_Climate);

            ModelCore.UI.WriteLine("   Loading future weather data from file {0} ...", configParameters.ClimateFile);
            Climate.ConvertFileFormat_FillOutAllData(configParameters.ClimateTimeSeries, configParameters.ClimateFile, configParameters.ClimateFileFormat, Climate.Phase.Future_Climate);


            // **
            // spinup

            // write input data to the log
            foreach (KeyValuePair <int, ClimateRecord[][]> timeStep in spinup_allData)
            {
                Climate.WriteSpinupInputLog(timeStep.Value, timeStep.Key); //, Climate.Phase.SpinUp_Climate.ToString());
            }

            // find maxSpeciesAge as the maximum possible time step count for spin up
            int maxSpeciesAge = 0;

            foreach (ISpecies sp in ModelCore.Species)
            {
                if (sp.Longevity > maxSpeciesAge)
                {
                    maxSpeciesAge = sp.Longevity;
                }
            }

            var spinupTimeStepKeys  = new List <int>();
            var spinupKeyList       = new List <int>(Climate.spinup_allData.Keys);
            var spinupStartYear     = spinupKeyList.Min();
            var spinupTimeStepCount = maxSpeciesAge;

            for (var i = 0; i < spinupTimeStepCount; ++i)
            {
                spinupTimeStepKeys.Add(spinupStartYear + i);
            }

            if (Climate.ConfigParameters.SpinUpClimateTimeSeries.ToLower().Contains("random"))
            {
                // generate random keys for the length of maxSpeciesAge
                Climate.randSelectedTimeKeys_spinup = new List <int>();

                // pick a random year key from allData
                for (var i = 0; i < spinupTimeStepCount; ++i)
                {
                    Climate.randSelectedTimeKeys_spinup.Add(spinupKeyList[(int)(spinupKeyList.Count * Climate.ModelCore.GenerateUniform())]);
                }
            }

            // initialize Spinup data arrays
            foreach (var timeStepKey in spinupTimeStepKeys)
            {
                Spinup_MonthlyData.Add(timeStepKey, new AnnualClimate_Monthly[modelCore.Ecoregions.Count]);
                Spinup_DailyData.Add(timeStepKey, new AnnualClimate_Daily[modelCore.Ecoregions.Count]);
            }


            // **
            // future

            // write input data to the log
            foreach (KeyValuePair <int, ClimateRecord[][]> timeStep in future_allData)
            {
                Climate.WriteFutureInputLog(timeStep.Value, timeStep.Key); //, future_allData_granularity);
            }

            var futureTimeStepKeys  = new List <int>();
            var futureKeyList       = new List <int>(Climate.future_allData.Keys);
            var futureStartYear     = futureKeyList.Min();
            var futureTimeStepCount = ModelCore.EndTime - ModelCore.StartTime;

            for (var i = 0; i < futureTimeStepCount; ++i)
            {
                futureTimeStepKeys.Add(futureStartYear + i);
            }

            if (Climate.ConfigParameters.ClimateTimeSeries.ToLower().Contains("random"))
            {
                // generate random keys for the length of the simulation
                Climate.randSelectedTimeKeys_future = new List <int>();

                // pick a random year key from allData
                for (var i = 0; i < futureTimeStepCount; ++i)
                {
                    Climate.randSelectedTimeKeys_future.Add(futureKeyList[(int)(futureKeyList.Count * Climate.ModelCore.GenerateUniform())]);
                }
            }

            // initialize Future data arrays
            foreach (var timeStepKey in futureTimeStepKeys)
            {
                Future_MonthlyData.Add(timeStepKey, new AnnualClimate_Monthly[modelCore.Ecoregions.Count]);
                Future_DailyData.Add(timeStepKey, new AnnualClimate_Daily[modelCore.Ecoregions.Count]);
            }
        }
        private ClimateRecord[] AnnualClimate_From_AnnualClimate_Daily(IEcoregion ecoregion, double latitude, Climate.Phase spinupOrfuture, int timeStep, int timeStepIndex)
        {
            var monthlyData = new ClimateRecord[12];

            int nDays;
            int dayOfYear = 0;
            AnnualClimate_Daily annDaily = new AnnualClimate_Daily(ecoregion, latitude, spinupOrfuture, timeStep, timeStepIndex); //for the same timeStep

            // if annDaily data come from averaging over years, it will always have 365 days, so I can't use the DaysInMonth() method based on the actualYear
            var daysInMonth = annDaily.DailyDataIsLeapYear ? new int[] { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 } : new int[] { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };

            if (spinupOrfuture == Climate.Phase.Future_Climate)
                Climate.Future_DailyData[timeStep][ecoregion.Index] = annDaily;
            else
                Climate.Spinup_DailyData[timeStep][ecoregion.Index] = annDaily;

            for (int mo = 0; mo < 12; mo++)
            {
                var monthlyMinTemp = 0.0;
                var monthlyMaxTemp = 0.0;
                var monthlyVarTemp = 0.0;
                var monthlyPptVarTemp = 0.0;
                var monthlyPrecip = 0.0;
                var monthlyPAR = 0.0;
                var monthlyWindDirection = 0.0;
                var monthlyWindSpeed = 0.0;
                var monthlyNDeposition = 0.0;
                var monthlyCO2 = 0.0;
                var monthlyRH = 0.0;

                nDays = daysInMonth[mo];
                for (int d = 0; d < nDays; d++)
                {
                    monthlyMinTemp += annDaily.DailyMinTemp[dayOfYear];
                    monthlyMaxTemp += annDaily.DailyMaxTemp[dayOfYear];
                    monthlyVarTemp += annDaily.DailyVarTemp[dayOfYear];
                    monthlyPptVarTemp += annDaily.DailyVarPpt[dayOfYear];
                    monthlyPrecip += annDaily.DailyPrecip[dayOfYear];
                    monthlyPAR += annDaily.DailyPAR[dayOfYear];
                    monthlyWindDirection += annDaily.DailyWindDirection[dayOfYear];
                    monthlyWindSpeed += annDaily.DailyWindSpeed[dayOfYear];
                    monthlyNDeposition += annDaily.DailyNDeposition[dayOfYear];
                    monthlyCO2 += annDaily.DailyCO2[dayOfYear];
                    monthlyRH += annDaily.DailyRH[dayOfYear];

                    dayOfYear++;
                }

                monthlyData[mo] = new ClimateRecord();

                monthlyData[mo].AvgMinTemp = monthlyMinTemp / nDays;
                monthlyData[mo].AvgMaxTemp = monthlyMaxTemp / nDays;
                monthlyData[mo].AvgVarTemp = monthlyVarTemp / nDays;
                monthlyData[mo].StdDevTemp = Math.Sqrt(monthlyVarTemp / nDays);
                monthlyData[mo].AvgVarPpt = monthlyPptVarTemp / nDays;
                monthlyData[mo].AvgPpt = monthlyPrecip;
                monthlyData[mo].StdDevPpt = Math.Sqrt(monthlyPrecip / nDays);
                monthlyData[mo].AvgPAR = monthlyPAR / nDays;
                monthlyData[mo].AvgWindDirection = monthlyWindDirection / nDays;
                monthlyData[mo].AvgWindSpeed = monthlyWindSpeed / nDays;
                monthlyData[mo].AvgNDeposition = monthlyNDeposition / nDays;
                monthlyData[mo].AvgCO2 = monthlyCO2 / nDays;
                monthlyData[mo].AvgRH = monthlyRH / nDays;
            }

            return monthlyData;
        }
        //---------------------------------------------------------------------
        // Generates new climate parameters for a SINGLE ECOREGION at an annual time step.
        public static void SetSingleAnnualClimate(IEcoregion ecoregion, int year, Climate.Phase spinupOrfuture)
        {
            int actualYear = Climate.Future_MonthlyData.Keys.Min() + year;

            if (spinupOrfuture == Climate.Phase.Future_Climate)
            {
                //PlugIn.ModelCore.UI.WriteLine("Retrieving {0} for year {1}.", spinupOrfuture.ToString(), actualYear);
                if (Climate.Future_MonthlyData.ContainsKey(actualYear))
                {
                    AnnualWeather[ecoregion] = Climate.Future_MonthlyData[actualYear][ecoregion.Index];
                }
                //else
                //    PlugIn.ModelCore.UI.WriteLine("Key is missing: Retrieving {0} for year {1}.", spinupOrfuture.ToString(), actualYear);
            }
            else
            {
                //PlugIn.ModelCore.UI.WriteLine("Retrieving {0} for year {1}.", spinupOrfuture.ToString(), actualYear);
                if (Climate.Spinup_MonthlyData.ContainsKey(actualYear))
                {
                    AnnualWeather[ecoregion] = Climate.Spinup_MonthlyData[actualYear][ecoregion.Index];
                }
            }
           
        }
        //private void AnnualClimate_Base(IEcoregion ecoregion, int year, double latitude)
        //{
        //    //Climate.ModelCore.Log.WriteLine("  Generate new annual climate:  Yr={0}, Eco={1}.", year, ecoregion.Name);
        //    Ecoregion = ecoregion;
        //    IClimateRecord[] ecoClimate = new IClimateRecord[12];

        //    this.Year = year;
        //    this.AnnualPrecip = 0.0;
        //    //this.AnnualN = 0.0;
        //    this.Latitude = latitude;

        //    for (int mo = 0; mo < 12; mo++)
        //    {
        //        ecoClimate[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);
        //    }


        //    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 AnnualClimate_From_AnnualClimate_Daily(IEcoregion ecoregion,  int actualYear, double latitude, Climate.Phase spinupOrfuture,  int timeStep)
        {

            //Climate.ModelCore.UI.WriteLine("  Retrieve Daily data... Ecoregion = {0}, Year = {1}.", ecoregion.Name, actualYear);
            //timestepData = Climate.Future_AllData[Climate.RandSelectedTimeSteps_future[TimeStep]];
            
            int nDays;
            int dayOfYear = 0;
            AnnualClimate_Daily annDaily = new AnnualClimate_Daily(ecoregion, actualYear, latitude, spinupOrfuture, timeStep); //for the same timeStep
            
            if (spinupOrfuture == Climate.Phase.Future_Climate)
                Climate.Future_DailyData[actualYear][ecoregion.Index] = annDaily;
            else
                Climate.Spinup_DailyData[actualYear][ecoregion.Index] = annDaily;  

            //IClimateRecord[] ecoClimate = new IClimateRecord[12];

            //----------------------------------------
            // Calculate precipitation and temperature 
            for (int mo = 0; mo < 12; mo++)
            {
                //ecoClimate[mo] = Climate.TimestepData[ecoregion.Index, mo];
                
                nDays = DaysInMonth(mo, actualYear);
                for (int d=1; d <= nDays; d++)
                {
                    

                    this.MonthlyTemp[mo]+= annDaily.DailyTemp[dayOfYear];
                    this.MonthlyMinTemp[mo] += annDaily.DailyMinTemp[dayOfYear];
                    this.MonthlyMaxTemp[mo] += annDaily.DailyMaxTemp[dayOfYear];
                    this.MonthlyPrecip[mo] += annDaily.DailyPrecip[dayOfYear];
                    this.MonthlyPAR[mo] += annDaily.DailyPAR[dayOfYear];
                    this.MonthlyVarTemp[mo] += annDaily.DailyVarTemp[dayOfYear];
                    this.MonthlyPptVarTemp[mo] += annDaily.DailyPptVarTemp[dayOfYear];

                    dayOfYear++;
                    //dayOfYear += nDays;
                }


                this.MonthlyTemp[mo] /= nDays;
                this.MonthlyMinTemp[mo] /= nDays;
                this.MonthlyMaxTemp[mo] /= nDays;
                //MonthlyPrecip[mo] /= nDays;
                this.MonthlyPAR[mo] /= nDays;
                this.MonthlyVarTemp[mo] /= nDays;
                this.MonthlyPptVarTemp[mo] /= nDays;
            }

            //------------------------------------------------------------
            // Calculate monthly data derived from precipitation and temperature

            this.Year = actualYear;
            this.AnnualPrecip = 0.0;
            for (int mo = 0; mo < 12; mo++)
            {
                //ecoClimate[mo] = Climate.TimestepData[ecoregion.Index, mo];

                this.AnnualPrecip += this.MonthlyPrecip[mo];

                if (this.MonthlyPrecip[mo] < 0)
                    throw new System.ApplicationException(String.Format("Error: Precipitation < 0.  Year={0}, Month={1}, Ppt={2}", this.Year, mo, this.MonthlyPrecip[mo]));

                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.MonthlyPET = CalculatePotentialEvapotranspiration();
            this.MonthlyVPD = CalculateVaporPressureDeficit(); 
            this.MonthlyGDD = CalculatePnETGDD(); 

            
            this.beginGrowing = annDaily.BeginGrowing; 
            this.endGrowing = annDaily.EndGrowing; 
            this.growingDegreeDays = annDaily.GrowingDegreeDays; 


            for (int mo = 5; mo < 8; mo++)
                this.JJAtemperature += this.MonthlyTemp[mo];
            this.JJAtemperature /= 3.0;

            //Climate.ModelCore.UI.WriteLine("  Completed calculations from daily data... Ecoregion = {0}, Year = {1}, BeginGrow = {2}.", ecoregion.Name, actualYear, this.beginGrowing);
            
        }
        public AnnualClimate_Monthly(IEcoregion ecoregion, double latitude, Climate.Phase spinupOrfuture, int timeStep, int timeStepIndex)
        {
            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, monthlyDataKey, timeStep);
            //    this.AnnualClimate_From_AnnualClimate_Daily(ecoregion, monthlyDataKey, latitude, spinupOrfuture, timeStep);
            //    return;
            //}

            ClimateRecord[][] timestepData = new ClimateRecord[Climate.ModelCore.Ecoregions.Count][];
            for (var i = 0; i < Climate.ModelCore.Ecoregions.Count; ++i)
                timestepData[i]= new ClimateRecord[12];

            // ------------------------------------------------------------------------------------------------------

            string climateOption = Climate.ConfigParameters.ClimateTimeSeries;
            if (this.climatePhase == Climate.Phase.SpinUp_Climate)
                climateOption = Climate.ConfigParameters.SpinUpClimateTimeSeries;

            ClimateRecord[] monthlyData;

            int actualTimeStep;

            switch (climateOption)
            {
                case "Monthly_AverageAllYears":
                    {
                        TimeStep = timeStep;
                        actualTimeStep = 0;
                        monthlyData = AnnualClimate_AvgMonth(ecoregion, latitude);
                        CalculateMonthlyData(ecoregion, monthlyData, actualTimeStep, latitude);
                        //Climate.ModelCore.UI.WriteLine("  Completed calculations for {0} using AVERAGE MONTHLY data. Ecoregion = {1}, SimulatedYear = AVERAGED.", this.climatePhase, ecoregion.Name, actualTimeStep);
                        break;
                    }

                case "Monthly_AverageWithVariation": //this case is not working as of 5/15/14
                    {
                        TimeStep = timeStep;
                        actualTimeStep = 0;
                        monthlyData = AnnualClimate_AvgMonth(ecoregion, latitude);
                        //Climate.ModelCore.UI.WriteLine("  Completed calculations for {0} from AVERAGE MONTHLY data. Ecoregion = {1}, SimulatedYear = AVERAGED.", this.climatePhase, ecoregion.Name, actualTimeStep);
                        //timestepData = AnnualClimate_AvgMonth(ecoregion, monthlyDataKey, latitude);
                        //CalculateMonthlyData_AddVariance(ecoregion, monthlyData, actualTimeStep, latitude);
                        break;
                    }
                case "Monthly_RandomYears":
                    {
                        TimeStep = timeStep;
                        Dictionary<int, ClimateRecord[][]> allData;
                        List<int> randomKeyList;

                        if (this.climatePhase == Climate.Phase.Future_Climate)
                        {
                            allData = Climate.Future_AllData;
                            randomKeyList = Climate.RandSelectedTimeKeys_future;
                        }
                        else
                        {
                            allData = Climate.Spinup_AllData;
                            randomKeyList = Climate.RandSelectedTimeKeys_spinup;
                        }

                        if (timeStepIndex >= randomKeyList.Count())
                        {
                            throw new ApplicationException(string.Format("Exception: the requested Time-step {0} is out-of-range for the {1} input file.", timeStep, this.climatePhase));
                        }
                        else
                            actualTimeStep = randomKeyList[timeStepIndex];

                        //Climate.ModelCore.UI.WriteLine("  AnnualClimate_Monthly: Monthly_RandomYear: timeStep = {0}, actualYear = {1}, phase = {2}.", timeStep, actualTimeStep, this.climatePhase);
                        //Climate.ModelCore.UI.WriteLine("  Completed calculations for FutureData using AnnualClimate_Monthly: SimulatedYear = {0}, actualYearSelected = {1}.", timeStep, actualTimeStep);
                        //Climate.ModelCore.UI.WriteLine("  Completed calculations for {0} using RandomYear_Monthly. Ecoregion = {1}, SimulatedYear = {2}, actualYearUsed={3}.", this.climatePhase, ecoregion.Name, timeStep, actualTimeStep);

                        monthlyData = allData[actualTimeStep][ecoregion.Index];
                        CalculateMonthlyData(ecoregion, monthlyData, actualTimeStep, latitude);
                        break;

                    }
                case "Monthly_SequencedYears":
                    {
                        TimeStep = timeStep;
                        actualTimeStep = timeStep;
                        Dictionary<int, ClimateRecord[][]> allData;

                        if (this.climatePhase == Climate.Phase.Future_Climate)
                            allData = Climate.Future_AllData;
                        else
                            allData = Climate.Spinup_AllData;

                        ClimateRecord[][] yearRecords;

                        // get the climate records for the requested year, or if the year is not found, get the records for the last year
                        if (!allData.TryGetValue(timeStep, out yearRecords))
                        {
                            actualTimeStep = allData.Keys.Max();
                            yearRecords = allData[actualTimeStep];
                        }

                        monthlyData = yearRecords[ecoregion.Index];
                        CalculateMonthlyData(ecoregion, monthlyData, actualTimeStep, latitude);

                        //Climate.ModelCore.UI.WriteLine("  Completed calculations for {0} using Monthly_SequencedYears. Ecoregion = {1}, SimulatedYear = {2}, actualYearUsed={3}.", this.climatePhase, ecoregion.Name, timeStep, actualTimeStep);
                        break;
                    }
                case "Daily_RandomYears":
                    {
                        TimeStep = timeStep;
                        Dictionary<int, ClimateRecord[][]> allData;
                        List<int> randomKeyList;

                        if (this.climatePhase == Climate.Phase.Future_Climate)
                        {
                            allData = Climate.Future_AllData;
                            randomKeyList = Climate.RandSelectedTimeKeys_future;
                        }
                        else
                        {
                            allData = Climate.Spinup_AllData;
                            randomKeyList = Climate.RandSelectedTimeKeys_spinup;
                        }

                        if (timeStepIndex >= randomKeyList.Count())
                        {
                            throw new ApplicationException(string.Format("Exception: the requested Time-step {0} is out-of-range for the {1} input file.", timeStep, this.climatePhase));
                        }
                        else
                            actualTimeStep = randomKeyList[timeStepIndex];

                        //Climate.ModelCore.UI.WriteLine("  Completed calculations for {0} using Daily_RandomYear. Ecoregion = {1}, SimulatedYear = {2}, actualYearUsed={3}.", this.climatePhase, ecoregion.Name, timeStep, actualTimeStep);

                        monthlyData = AnnualClimate_From_AnnualClimate_Daily(ecoregion, latitude, spinupOrfuture, timeStep, timeStepIndex);
                        CalculateMonthlyData(ecoregion, monthlyData, actualTimeStep, latitude);
                        break;

                    }
                case "Daily_AverageAllYears":
                    {
                        TimeStep = timeStep;
                        actualTimeStep = 0;
                        monthlyData = AnnualClimate_From_AnnualClimate_Daily(ecoregion, latitude, spinupOrfuture, timeStep, timeStepIndex);
                        CalculateMonthlyData(ecoregion, monthlyData, actualTimeStep, latitude);
                        //Climate.ModelCore.UI.WriteLine("  Completed calculations for {0} using Daily_AverageAllYears. Ecoregion = {1}, SimulatedYear = {2}.", this.climatePhase, ecoregion.Name, timeStep);
                        break;
                    }
                case "Daily_SequencedYears":
                    {
                        TimeStep = timeStep;
                        actualTimeStep = timeStep;
                        Dictionary<int, ClimateRecord[][]> allData;

                        if (this.climatePhase == Climate.Phase.Future_Climate)
                            allData = Climate.Future_AllData;
                        else
                            allData = Climate.Spinup_AllData;

                        if (!allData.ContainsKey(timeStep))
                            actualTimeStep = allData.Keys.Max();

                        monthlyData = AnnualClimate_From_AnnualClimate_Daily(ecoregion, latitude, spinupOrfuture, timeStep, timeStepIndex);
                        CalculateMonthlyData(ecoregion, monthlyData, actualTimeStep, latitude);
                        //Climate.ModelCore.UI.WriteLine("  Completed calculations for {0} using Daily_SequencedYears. Ecoregion = {1}, SimulatedYear = {2}, actualYearUsed={3}.", this.climatePhase, ecoregion.Name, timeStep, actualTimeStep);
                        break;
                    }

                default:
                    throw new ApplicationException(String.Format("Unknown Climate Time Series: {0}", climateOption));

            }

            //this.MonthlyPET = CalculatePotentialEvapotranspiration();
            this.MonthlyPET = CalculatePotentialEvapotranspirationThornwaite();
            this.MonthlyVPD = CalculateVaporPressureDeficit();
            this.MonthlyGDD = CalculatePnETGDD();

            this.beginGrowing = CalculateBeginGrowingSeason();
            this.endGrowing = CalculateEndGrowingSeason();
            this.growingDegreeDays = GrowSeasonDegreeDays();

            this.JJAtemperature = 0.0;
            for (int mo = 5; mo < 8; mo++)
                this.JJAtemperature += this.MonthlyTemp[mo];
            this.JJAtemperature /= 3.0;
        }
        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;
            

        }
        //--------------------------------------------------------------------
        /// <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 static void Convert_USGS_to_ClimateData_FillAlldata(TemporalGranularity timeStep, string climateFile, string climateFileFormat, Climate.Phase climatePhase)
        {
            //Dictionary<int, ClimateRecord[][]> 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;

            //// parse the input file into lists of timestamps and corresponding climate records arrays
            //List<string> timeStamps;
            //List<ClimateRecord>[] climateRecords;       // indexing: [ecoregion.Count][i]
            //Convert_USGS_to_ClimateData(timeStep, climateFile, climateFileFormat, out timeStamps, out climateRecords);

            //// break up the ecoregion lists into a dictionary by year based on timeStamp keys
            //var yearData = new Dictionary<int, List<ClimateRecord>[]>();    // indexing: [year][ecoregion][i]

            //var currentYear = -999;

            //List<ClimateRecord>[] yearRecords = null;

            //for (var j = 0; j < timeStamps.Count; ++j)
            //{
            //    var year = int.Parse(timeStamps[j].Substring(0, 4));

            //    // timestamps are grouped by year in the input files
            //    if (year != currentYear)
            //    {
            //        // make yearRecords instance for the new year
            //        yearRecords = new List<ClimateRecord>[Climate.ModelCore.Ecoregions.Count];
            //        for (var i = 0; i < Climate.ModelCore.Ecoregions.Count; ++i)
            //            yearRecords[i] = new List<ClimateRecord>();

            //        yearData[year] = yearRecords;
            //        currentYear = year;
            //    }

            //    // add the climate records onto the year records
            //    for (var i = 0; i < Climate.ModelCore.Ecoregions.Count; ++i)
            //        yearRecords[i].Add(climateRecords[i][j]);
            //}

            //// transfer the data to allDataRef and
            //// do some basic error checking

            //if (allDataRef == null)
            //    allDataRef = new Dictionary<int, ClimateRecord[][]>();
            //else
            //    allDataRef.Clear();

            //foreach (var key in yearData.Keys)
            //{
            //    allDataRef[key] = new ClimateRecord[Climate.ModelCore.Ecoregions.Count][];

            //    for (var i = 0; i < Climate.ModelCore.Ecoregions.Count; ++i)
            //    {
            //        if (timeStep == TemporalGranularity.Monthly && yearData[key][i].Count != 12)
            //            throw new ApplicationException(string.Format("Error in ClimateDataConvertor: Monthly data for year {0} in climate file '{1}' does not have 12 records.  It has {2} records.", key, climateFile, yearData[key][i].Count));

            //        if (timeStep == TemporalGranularity.Daily && yearData[key][i].Count != 365)
            //            throw new ApplicationException(string.Format("Error in ClimateDataConvertor: Daily data for year {0} in climate file '{1}' does not have 365 records.  It has {2} records.", key, climateFile, yearData[key][i].Count));

            //        // convert the yearRecords from List<ClimateRecord>[] to ClimateRecord[][]
            //        allDataRef[key][i] = yearData[key][i].ToArray();
            //    }
            //}

            // **
            // John McNabb:  new parsing code
            List<int> yearKeys;
            List<List<ClimateRecord>[]> climateRecords;

            Convert_USGS_to_ClimateData2(timeStep, climateFile, climateFileFormat, out yearKeys, out climateRecords);

            Dictionary<int, ClimateRecord[][]> 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;

            if (allDataRef == null)
                allDataRef = new Dictionary<int, ClimateRecord[][]>();
            else
                allDataRef.Clear();

            for (var i = 0; i < yearKeys.Count; ++i)
            {
                var ecoRecords = new ClimateRecord[Climate.ModelCore.Ecoregions.Count][];
                allDataRef[yearKeys[i]] = ecoRecords;

                for (var j = 0; j < Climate.ModelCore.Ecoregions.Count; ++j)
                {
                    // convert the parsed climateRecords for this year from List<ClimateRecord>[] to ClimateRecord[][]
                    ecoRecords[j] = climateRecords[i][j].ToArray();
                }
            }
        }
        //public int tempEcoIndex = -1;
        //public double[] DailyPET = new double[366];  // Potential Evapotranspiration
        //public double[] DailyVPD = new double[366];  // Vapor Pressure Deficit
        //public double[] DailyDayLength = new double[366];
        //public double[] DailyNightLength = new double[366];
        //public int[] DailyGDD = new int[366];
        //For Sequenced and Random timeStep arg should be passed
        public AnnualClimate_Daily(IEcoregion ecoregion, double latitude, Climate.Phase spinupOrfuture, int timeStep, int timeStepIndex)
        {
            this.climatePhase = spinupOrfuture;
            ClimateRecord[][] timestepData = new ClimateRecord[Climate.ModelCore.Ecoregions.Count][];
            for (var i = 0; i < Climate.ModelCore.Ecoregions.Count; ++i)
                timestepData[i] = new ClimateRecord[366];

            string climateOption = Climate.ConfigParameters.ClimateTimeSeries;
            if (this.climatePhase == Climate.Phase.SpinUp_Climate)
                climateOption = Climate.ConfigParameters.SpinUpClimateTimeSeries;

            ClimateRecord[] dailyData = null;

            int actualTimeStep;

            //Climate.TextLog.WriteLine("  Calculating daily data ...  Ecoregion = {0}, Year = {1}, timestep = {2}.", ecoregion.Name, actualYear, timeStep);
            switch (climateOption)
            {
                case "Daily_RandomYears":
                    {
                        // JM: this code assumes that the constructor for AnnualClimate_Daily is ONLY called from within
                        //  AnnualClimate_Monthly.AnnualClimate_From_AnnualClimate_Daily(), and, for Daily_RandomYear, the
                        //  actualYear contains the randomly-selected year.

                        TimeStep = timeStep;
                        Dictionary<int, ClimateRecord[][]> allData;
                        List<int> randomKeyList;

                        if (this.climatePhase == Climate.Phase.Future_Climate)
                        {
                            allData = Climate.Future_AllData;
                            randomKeyList = Climate.RandSelectedTimeKeys_future;
                        }
                        else
                        {
                            allData = Climate.Spinup_AllData;
                            randomKeyList = Climate.RandSelectedTimeKeys_spinup;
                        }

                        if (timeStepIndex >= randomKeyList.Count())
                        {
                            throw new ApplicationException(string.Format("Exception: the requested Time-step {0} is out-of-range for the {1} input file.", timeStep, this.climatePhase));
                        }
                        else
                            actualTimeStep = randomKeyList[timeStepIndex];

                        Climate.TextLog.WriteLine("  AnnualClimate_Daily: Daily_RandomYear: timeStep = {0}, actualYear = {1}, phase = {2}.", timeStep, actualTimeStep, this.climatePhase);

                        dailyData = allData[actualTimeStep][ecoregion.Index];
                        CalculateDailyData(ecoregion, dailyData, actualTimeStep, latitude);
                        break;

                    }
                case "Daily_AverageAllYears":
                    {
                        TimeStep = timeStep;
                        actualTimeStep = 0;

                        dailyData = AnnualClimate_AvgDaily(ecoregion, latitude);
                        CalculateDailyData(ecoregion, dailyData, actualTimeStep, latitude);
                        break;
                    }
                case "Daily_SequencedYears":
                    {
                        TimeStep = timeStep;
                        actualTimeStep = timeStep;
                        Dictionary<int, ClimateRecord[][]> allData;

                        if (this.climatePhase == Climate.Phase.Future_Climate)
                            allData = Climate.Future_AllData;
                        else
                            allData = Climate.Spinup_AllData;

                        ClimateRecord[][] yearRecords;

                        // get the climate records for the requested year, or if the year is not found, get the records for the last year
                        if (!allData.TryGetValue(timeStep, out yearRecords))
                        {
                            actualTimeStep = allData.Keys.Max();
                            yearRecords = allData[actualTimeStep];
                        }

                        dailyData = yearRecords[ecoregion.Index];
                        CalculateDailyData(ecoregion, dailyData, actualTimeStep, latitude);
                        break;
                    }
                default:
                    throw new ApplicationException(String.Format("Unknown Climate Time Series: {0}", climateOption));

            }

            this.beginGrowing = CalculateBeginGrowingDay_Daily(); //ecoClimate);
            this.endGrowing = CalculateEndGrowingDay_Daily(dailyData);
            this.growingDegreeDays = GrowSeasonDegreeDays();

            this.DailyDataIsLeapYear = dailyData.Length == 366;
        }
Пример #14
0
        //public static void GetPDSI_Test()
        //{
        //    IEcoregion ecoregion = Climate.ModelCore.Ecoregions[0];
        //    //here:
        //    string outputFilePath = @"C:\Program Files\LANDIS-II\v6\examples\base-BDA_1\PDSI_BaseBDA_Test2.csv";
        //    File.WriteAllText(outputFilePath, String.Empty);
        //    int startYear = 1893, endYear = 1897;
        //    AnnualClimate_Monthly[] acs;
        //    if (endYear > startYear)
        //    {
        //        int numOfYears = endYear - startYear + 1;
        //        acs = new AnnualClimate_Monthly[numOfYears];

        //        double[] mon_T_normal = new double[12] { 19.693, 23.849, 34.988, 49.082, 60.467, 70.074, 75.505, 73.478, 64.484, 52.634, 36.201, 24.267 };
        //        IClimateRecord[] climateRecs = new ClimateRecord[12];

        //        //Climate.TimestepData = allData[0];
        //        //for (int mo = 0; mo < 12; mo++)
        //        //{
        //        //    climateRecs[mo] = Climate.TimestepData[ecoregion.Index, mo];
        //        //    //mon_T_normal[mo] = (climateRecs[mo].AvgMinTemp + climateRecs[mo].AvgMinTemp) / 2;
        //        //}

        //        acs[0] = new AnnualClimate_Monthly(ecoregion, 1893, 0);
        //        ((AnnualClimate_Monthly)acs[0]).MonthlyTemp = new double[] { 14.371, 14.000, 26.435, 44.250, 54.645, 70.683, 73.355, 69.323, 63.600, 48.806, 32.867, 19.161 };
        //        //acs[0].MonthlyPrecip = new double[] { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 };
        //        ((AnnualClimate_Monthly)acs[0]).MonthlyPrecip = new double[] { 0.610, 1.500, 1.730, 4.050, 1.950, 0.790, 3.020, 2.570, 1.430, 0.850, 1.260, 2.350 };

        //        acs[1] = new AnnualClimate_Monthly(ecoregion, 1894, 0);
        //        ((AnnualClimate_Monthly)acs[1]).MonthlyTemp = new double[] { 12.705, 14.979, 37.984, 49.700, 61.209, 71.463, 77.935, 74.312, 65.283, 51.516, 34.767, 29.548 };
        //        ((AnnualClimate_Monthly)acs[1]).MonthlyPrecip = new double[] { 0.700, 0.550, 0.580, 4.240, 2.430, 1.150, 0.580, 1.480, 0.550, 1.760, 0.050, 1.000 };

        //        acs[2] = new AnnualClimate_Monthly(ecoregion, 1895, 0);
        //        ((AnnualClimate_Monthly)acs[2]).MonthlyTemp = new double[] { 12.519, 17.964, 33.994, 54.506, 60.411, 66.172, 70.548, 69.622, 65.288, 44.795, 32.433, 23.333 };
        //        ((AnnualClimate_Monthly)acs[2]).MonthlyPrecip = new double[] { 0.650, 0.540, 0.520, 3.980, 2.380, 6.240, 2.320, 3.920, 4.770, 0.060, 1.040, 0.000 };

        //        acs[3] = new AnnualClimate_Monthly(ecoregion, 1896, 0);
        //        ((AnnualClimate_Monthly)acs[3]).MonthlyTemp = new double[] { 23.258, 27.397, 26.425, 48.833, 62.790, 68.054, 71.365, 70.677, 57.991, 46.355, 21.154, 28.597 };
        //        ((AnnualClimate_Monthly)acs[3]).MonthlyPrecip = new double[] { 0.250, 0.270, 1.670, 5.680, 6.240, 7.740, 5.550, 1.660, 1.810, 3.230, 3.850, 0.230 };

        //        acs[4] = new AnnualClimate_Monthly(ecoregion, 1897, 0);
        //        ((AnnualClimate_Monthly)acs[4]).MonthlyTemp = new double[] { 13.758, 20.179, 26.613, 46.700, 59.016, 66.533, 74.032, 67.928, 71.617, 54.613, 32.450, 18.686 };
        //        ((AnnualClimate_Monthly)acs[4]).MonthlyPrecip = new double[] { 2.500, 0.540, 3.010, 4.480, 0.980, 5.820, 3.780, 1.600, 1.010, 1.940, 0.910, 2.950 };



        //        //for (int i = startYear; i <= endYear; i++)
        //        //{
        //        //    acs[i - startYear] = new AnnualClimate(ecoregion, i, 0); // Latitude should be given
        //        //    //Climate.ModelCore.UI.WriteLine(ac.MonthlyTemp[0].ToString() + "\n");
        //        //    //Climate.ModelCore.UI.WriteLine(ac.MonthlyPrecip[0].ToString() + "\n");
        //        //}



        //        //for (int mo = 0; mo < 12; mo++)
        //        //{
        //        //    climateRecs[mo] = Climate.TimestepData[ecoregion.Index, mo];
        //        //    mon_T_normal[mo] = (climateRecs[mo].AvgMinTemp + climateRecs[mo].AvgMinTemp) / 2;
        //        //}

        //        double AWC = 0.3;//Landis.Extension.Succession.Century.EcoregionData.FieldCapacity[ecoregion] - Landis.Extension.Succession.Century.EcoregionData.WiltingPoint[ecoregion];
        //        double latitude = 42.60;//Landis.Extension.Succession.Century.EcoregionData.Latitude[ecoregion];
        //        new PDSI_Calculator().CalculatePDSI(acs, mon_T_normal, AWC, latitude, /*outputFilePath,*/ UnitSystem.USCustomaryUnits);

        //    }


        /// <summary>
        /// Converts USGS Data to Standard Input climate Data and fill out the Future_AllData and/or Spinup_AllData
        /// </summary>
        /// 
        public static void ConvertFileFormat_FillOutAllData(String timeSeries, string filePath, string fileFormat, Climate.Phase climatePhase)
        {
            if (climatePhase == Climate.Phase.Future_Climate && timeSeries.Contains("Daily"))
                future_allData_granularity = TemporalGranularity.Daily;
                
            else if (climatePhase == Climate.Phase.Future_Climate && timeSeries.Contains("Monthly"))
                future_allData_granularity = TemporalGranularity.Monthly;

            else if (climatePhase == Climate.Phase.SpinUp_Climate && timeSeries.Contains("Daily"))
                spinup_allData_granularity = TemporalGranularity.Daily;

            else if (climatePhase == Climate.Phase.SpinUp_Climate && timeSeries.Contains("Monthly"))
                spinup_allData_granularity = TemporalGranularity.Monthly;

            if (timeSeries.Contains("Daily"))
                ClimateDataConvertor.Convert_USGS_to_ClimateData_FillAlldata(TemporalGranularity.Daily, filePath, fileFormat, climatePhase);
            
            else if (timeSeries.Contains("Monthly"))
                ClimateDataConvertor.Convert_USGS_to_ClimateData_FillAlldata(TemporalGranularity.Monthly, filePath, fileFormat, climatePhase);

                //string readableFile = "";
            //if (timeSeries.Contains("MonthlyStandard"))
            //{
            //    ModelCore.UI.WriteLine("Loading from file with Monthly Standard format...\n"); 
            //    if (future_allData_granularity == TemporalGranularity.Daily)
            //    {
            //        ClimateParser parser = new ClimateParser();
            //        future_allData = Landis.Data.Load<Dictionary<int, IClimateRecord[,]>>(filePath, parser);
            //    }
            //    else if (future_allData_granularity == TemporalGranularity.Monthly)
            //    {
            //        ClimateParser spinup_parser = new ClimateParser();
            //        spinup_allData = Landis.Data.Load<Dictionary<int, IClimateRecord[,]>>(filePath, spinup_parser);
            //    }
            //    return; // filePath;
            //}

            //else if (timeSeries.Contains("Average") || timeSeries.Contains("Random"))
            //{
            //    if (timeSeries.Contains("Daily"))
            //        //return readableFile = 
            //        ClimateDataConvertor.Convert_USGS_to_ClimateData_FillAlldata(TemporalGranularity.Daily, filePath, fileFormat, climatePhase);
            //    else if (timeSeries.Contains("Monthly"))
            //        //return readableFile = 
            //        ClimateDataConvertor.Convert_USGS_to_ClimateData_FillAlldata(TemporalGranularity.Monthly, filePath, fileFormat, climatePhase);

            //}

            //else if (timeSeries.Contains("MonthlyAverage"))//AverageMonthly
            //{
            //    //return readableFile = 
            //        ClimateDataConvertor.Convert_USGS_to_ClimateData_FillAlldata(TemporalGranularity.Monthly, filePath, fileFormat, climatePhase);
            //}

            ////else if (timeSeries.Contains("Random"))
            ////{
            ////    if (timeSeries.Contains("Daily"))
            ////        return readableFile = Landis.Library.Climate.ClimateDataConvertor.Convert_USGS_to_ClimateData_FillAlldata(TemporalGranularity.Daily, File, fileFormat, climatePhase);
            ////    else if (timeSeries.Contains("Monthly"))
            ////        return readableFile = Landis.Library.Climate.ClimateDataConvertor.Convert_USGS_to_ClimateData_FillAlldata(TemporalGranularity.Monthly, File, fileFormat, climatePhase);
            ////}

            //else if (timeSeries.Contains("DailyGCM"))
            //{
            //    //return readableFile = 
            //        ClimateDataConvertor.Convert_USGS_to_ClimateData_FillAlldata(TemporalGranularity.Daily, filePath, fileFormat, climatePhase);
            //}

            //else if (timeSeries.Contains("MonthlyGCM"))
            //{
            //    //return readableFile = 
            //        ClimateDataConvertor.Convert_USGS_to_ClimateData_FillAlldata(TemporalGranularity.Monthly, filePath, fileFormat, climatePhase);
            //}

            //else
            //{
            //    ModelCore.UI.WriteLine("Error in converting input-climate-file format: invalid ClimateTimeSeries value provided in cliamte-generator input file.");
            //    throw new Exception("Error in converting input-climate-file format: invalid ClimateTimeSeries value provided in cliamte-generator input file.");
            //}
            return;// readableFile;

        }