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

        //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);
            }
        }
Beispiel #5
0
        //---------------------------------------------------------------------

        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();

                    }
                }
            }

        }