//---------------------------------------------------------------------
        private static void WriteAnnualLog(IEcoregion ecoregion, int year, AnnualClimate_Monthly annualClimateMonthly)
        {
            AnnualLog.Clear();
            AnnualLog al = new AnnualLog();

            //al.SimulationPeriod = TBD
            al.Time = year;
            al.EcoregionName = ecoregion.Name;
            al.EcoregionIndex = ecoregion.Index;
            al.BeginGrow = annualClimateMonthly.BeginGrowing;
            al.EndGrow = annualClimateMonthly.EndGrowing;
            al.TAP = annualClimateMonthly.TotalAnnualPrecip;
            al.MAT = annualClimateMonthly.MeanAnnualTemperature;
            al.PDSI = Future_MonthlyData[year][ecoregion.Index].PDSI;

            AnnualLog.AddObject(al);
            AnnualLog.WriteToFile();
        }
        //---------------------------------------------------------------------------
        public static double CalculateAnnualActualEvapotranspiration(AnnualClimate_Monthly annualClimate, double fieldCapacity)
        {
            //I don't think this method is every called.

            // field capacity input as cm
            // variable with xVariableName indicate conversion to mm

            double xFieldCap = fieldCapacity * 10.0;

            double waterAvail = 0.0;
            double actualET = 0.0;
            double oldWaterAvail = 0.0;
            double accPotWaterLoss = 0.0;

            for (int month = 0; month < 12; month++)
            {

                double monthlyRain = annualClimate.MonthlyPrecip[month];
                double potentialET = annualClimate.MonthlyPET[month];

                //Calc potential water loss this month
                double potWaterLoss = monthlyRain - potentialET;

                //If monthlyRain doesn't satisfy potentialET, add this month's potential
                //water loss to accumulated water loss from soil
                if (potWaterLoss < 0.0)
                {
                    accPotWaterLoss += potWaterLoss;
                    double xAccPotWaterLoss = accPotWaterLoss * 10.0;

                    //Calc water retained in soil given so much accumulated potential
                    //water loss Pastor and Post. 1984.  Can. J. For. Res. 14:466:467.

                    waterAvail = fieldCapacity *
                                 System.Math.Exp((.000461 - 1.10559 / xFieldCap) * (-1.0 * xAccPotWaterLoss));

                    if (waterAvail < 0.0)
                        waterAvail = 0.0;

                    //changeSoilMoisture - during this month
                    double changeSoilMoisture = waterAvail - oldWaterAvail;

                    //Calc actual evapotranspiration (AET) if soil water is drawn down
                    actualET += (monthlyRain - changeSoilMoisture);
                }

                //If monthlyRain satisfies potentialET, don't draw down soil water
                else
                {
                    waterAvail = oldWaterAvail + potWaterLoss;
                    if (waterAvail >= fieldCapacity)
                        waterAvail = fieldCapacity;

                    double changeSoilMoisture = waterAvail - oldWaterAvail;

                    //If soil partially recharged, reduce accumulated potential
                    //water loss accordingly
                    accPotWaterLoss += changeSoilMoisture;

                    //If soil completely recharged, reset accumulated potential
                    //water loss to zero
                    if (waterAvail >= fieldCapacity)
                        accPotWaterLoss = 0.0;

                    //If soil water is not drawn upon, add potentialET to AET
                    actualET += potentialET;
                }

                oldWaterAvail = waterAvail;

                //Climate.ModelCore.UI.WriteLine("Actual ET Calcs. Rain={0},PET={1}, potWaterLoss={2:0.0},,fieldcapacity={3:0.000}, oldwaterAvail={4:0.000}, actualET={5:0.000}", monthlyRain, potentialET, potWaterLoss, fieldCapacity, oldWaterAvail, actualET);
            }

            return actualET;
        }
        public static void GenerateEcoregionClimateData(IEcoregion ecoregion, int startYear, double latitude, double fieldCapacity, double wiltingPoint)
        {
            // JM:  these next three lines are not currently used, but may need to be modified if used:
            //int numberOftimeSteps = Climate.ModelCore.EndTime - Climate.ModelCore.StartTime;
            //annualPDSI = new double[Climate.ModelCore.Ecoregions.Count, future_allData.Count];
            //landscapeAnnualPDSI = new double[future_allData.Count];
            double[] temperature_normals = new double[12];
            double[] precip_normals = new double[12];

            double availableWaterCapacity = fieldCapacity - wiltingPoint;

            Climate.TextLog.WriteLine("Core.StartTime = {0}, Core.EndTime = {1}.", ModelCore.StartTime, ModelCore.EndTime);
            //Climate.TextLog.WriteLine("   Climate.LandscapeAnnualPDSI.Length = {0}.", Climate.LandscapeAnnualPDSI.Length);

            //First Calculate Climate Normals from Spin-up data
            int timeStepIndex = 0;
            foreach (KeyValuePair<int, AnnualClimate_Monthly[]> timeStep in Spinup_MonthlyData)
            {

                //Climate.TextLog.WriteLine("  Calculating Weather for SPINUP: timeStep = {0}, actualYear = {1}", timeStep.Key, startYear + timeStep.Key);
                AnnualClimate_Monthly annualClimateMonthly = new AnnualClimate_Monthly(ecoregion, latitude, Climate.Phase.SpinUp_Climate, timeStep.Key, timeStepIndex);
                Spinup_MonthlyData[startYear + timeStep.Key][ecoregion.Index] = annualClimateMonthly;

                for (int mo = 0; mo < 12; mo++)
                {
                    temperature_normals[mo] += annualClimateMonthly.MonthlyTemp[mo];
                    precip_normals[mo] += annualClimateMonthly.MonthlyPrecip[mo];
                }

                timeStepIndex++;
            }

            // Calculate AVERAGE T normal.
            for (int mo = 0; mo < 12; mo++)
            {
                temperature_normals[mo] /= (double)Spinup_MonthlyData.Count;
                precip_normals[mo] /= (double)Spinup_MonthlyData.Count;
                //Climate.TextLog.WriteLine("Month = {0}, Original Monthly T normal = {1}", mo, month_Temp_normal[mo]);

            }

            timeStepIndex = 0;

            //PDSI_Calculator.InitializeEcoregion_PDSI(temperature_normals, precip_normals, availableWaterCapacity, latitude, UnitSystem.metrics, ecoregion);

            foreach (KeyValuePair<int, AnnualClimate_Monthly[]> timeStep in Future_MonthlyData)
            {
                //Climate.TextLog.WriteLine("  Completed calculations for Future_Climate: TimeStepYear = {0}, actualYear = {1}", timeStep.Key, startYear + timeStep.Key);
                AnnualClimate_Monthly annualClimateMonthly = new AnnualClimate_Monthly(ecoregion, latitude, Climate.Phase.Future_Climate, timeStep.Key, timeStepIndex);
                Future_MonthlyData[startYear + timeStep.Key][ecoregion.Index] = annualClimateMonthly;

                // Next calculate PSDI for the future data
                //Future_MonthlyData[startYear + timeStep.Key][ecoregion.Index].PDSI = PDSI_Calculator.CalculateEcoregion_PDSI(annualClimateMonthly, temperature_normals, precip_normals, availableWaterCapacity, latitude, UnitSystem.metrics, ecoregion);
                //Future_MonthlyData[startYear + timeStep.Key][ecoregion.Index].PDSI = PDSI_Calculator.CalculateEcoregion_PDSI(annualClimateMonthly, temperature_normals, precip_normals, latitude, UnitSystem.metrics, ecoregion);
                // Climate.LandscapeAnnualPDSI[timeStepIndex] += (Future_MonthlyData[startYear + timeStep.Key][ecoregion.Index].PDSI / Climate.ModelCore.Ecoregions.Count);

                //Climate.TextLog.WriteLine("Calculated PDSI for Ecoregion {0}, timestep {1}, PDSI Year {2}; PDSI={3:0.00}.", ecoregion.Name, timeStepIndex, timeStep.Key, Future_MonthlyData[startYear + timeStep.Key][ecoregion.Index].PDSI);
                timeStepIndex++;

                WriteAnnualLog(ecoregion, startYear + timeStep.Key, annualClimateMonthly);
            }
        }
        //public static void GenerateClimate_GetPDSI(int startYear, int endYear, int latitude, double fieldCapacity, double wiltingPoint)
        //{
        //    string outputFilePath = @"PDSI_BaseBDA_Genrated_Climate.csv";
        //    File.WriteAllText(outputFilePath, String.Empty);

        //    foreach (IEcoregion ecoregion in Climate.ModelCore.Ecoregions)
        //    {
        //        AnnualClimate_Monthly[] acs;
        //        int numOfYears = endYear - startYear + 1;
        //        acs = new AnnualClimate_Monthly[numOfYears];

        //        //foreach time step it should be called

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



        //        double[] mon_T_normal = new double[12];//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];

        //        //If timestep is 0 then calculate otherwise get the mon_T_normal for timestep 0

        //        Climate.TimestepData = future_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;
        //        }
        //        double AWC = fieldCapacity - wiltingPoint;
        //        //double latitude = Landis.Extension.Succession.Century.EcoregionData.Latitude[ecoregion];
        //        new PDSI_Calculator().CalculatePDSI(acs, mon_T_normal, AWC, latitude, /*outputFilePath,*/ UnitSystem.metrics);
        //    }
        //}
        //public static void GenerateEcoregionClimateData()
        //{
        //}

        public static void GenerateEcoregionClimateData(IEcoregion ecoregion, int startYear, double latitude, double fieldCapacity, double wiltingPoint)
        {

            Climate.ModelCore.UI.WriteLine("  Generating Ecoregion Climate Data for ecoregion = {0}.", ecoregion.Name);
            
            int numberOftimeSteps = Climate.ModelCore.EndTime - Climate.ModelCore.StartTime;
            annualPDSI = new double[Climate.ModelCore.Ecoregions.Count, future_allData.Count]; //numberOftimeSteps + 1];
            landscapeAnnualPDSI = new double[future_allData.Count]; //numberOftimeSteps+1];
            double[] temperature_normals = new double[12];
            
            double availableWaterCapacity = fieldCapacity - wiltingPoint;


            //Climate.ModelCore.UI.WriteLine("   Latitude = {0}, Available Water = {1}.", latitude, availableWaterCapacity);

            //IClimateRecord[] climateRecs = new ClimateRecord[12];
            //int minimumTime = 5000;
            
            
            //Firt Calculate Climate Normals from Spin-up data
            foreach (KeyValuePair<int, IClimateRecord[,]> timeStep in spinup_allData)
            {

                //Climate.ModelCore.UI.WriteLine("  Calculating Weather for SPINUP Year = {0}.", timeStep.Key);
                AnnualClimate_Monthly annualClimateMonthly = new AnnualClimate_Monthly(ecoregion, startYear + timeStep.Key, latitude, Climate.Phase.SpinUp_Climate, timeStep.Key); 
                Spinup_MonthlyData[startYear + timeStep.Key][ecoregion.Index] = annualClimateMonthly;

                for (int mo = 0; mo < 12; mo++)
                {
                    temperature_normals[mo] += annualClimateMonthly.MonthlyTemp[mo]; 
                }
            }

            // Calculate AVERAGE T normal.
            for (int mo = 0; mo < 12; mo++)
            {
                temperature_normals[mo] /= (double)spinup_allData.Count;
                //Climate.ModelCore.UI.WriteLine("Month = {0}, Original Monthly T normal = {1}", mo, month_Temp_normal[mo]);

            }
            
            int timestepIndex = 0;

            // Next calculate PSDI for the future data
            foreach (KeyValuePair<int, AnnualClimate_Monthly[]> timeStep in Future_MonthlyData)
            //foreach (KeyValuePair<int, IClimateRecord[,]> timeStep in future_allData)
            {
                //if (timeStep.Key < minimumTime)
                //    minimumTime = timeStep.Key;

                //if (timestepIndex > numberOftimeSteps)
                //    break;

                //Climate.ModelCore.UI.WriteLine("  Calculating Weather for FUTURE Year = {0}.", timeStep.Key);
                AnnualClimate_Monthly annualClimateMonthly = new AnnualClimate_Monthly(ecoregion, startYear + timeStep.Key, latitude, Climate.Phase.Future_Climate, timeStep.Key);
                Future_MonthlyData[startYear + timeStep.Key][ecoregion.Index] = annualClimateMonthly;

                Future_MonthlyData[startYear + timeStep.Key][ecoregion.Index].PDSI = PDSI_Calculator.CalculatePDSI(annualClimateMonthly, temperature_normals, availableWaterCapacity, latitude, UnitSystem.metrics, ecoregion);
                Climate.LandscapeAnnualPDSI[timestepIndex] += (Future_MonthlyData[startYear + timeStep.Key][ecoregion.Index].PDSI / Climate.ModelCore.Ecoregions.Count);

                //Climate.ModelCore.UI.WriteLine("Calculated PDSI for Ecoregion {0}, timestep {1}, PDSI Year {2}; PDSI={3:0.00}.", ecoregion.Name, timestepIndex, timeStep.Key, PDSI);
                timestepIndex++;
            }

        }