Inheritance: AgeCohort.ICohortDisturbance
        public static int CalcFireSeverity(ActiveSite site, Event fireEvent, double severityCalibrate, int FMC)
        {

            //IFireRegion ecoregion = SiteVars.FireRegion[site];
            int PH = SiteVars.PercentHardwood[site];  //Percent Hardwood
            int PDF = SiteVars.PercentDeadFir[site];
            int PC = SiteVars.PercentConifer[site];

            int fuelIndex = SiteVars.CFSFuelType[site];
            int CBH = Event.FuelTypeParms[fuelIndex].CBH;
            //If M3 or M4 type (PDF >0) assign appropriate fuel index
            if (PDF > 0)
            {

                    if (fireEvent.FireSeason.LeafStatus == LeafOnOff.LeafOff)
                    {
                        foreach (FuelType listFuel in Event.FuelTypeParms)
                        {
                            if (listFuel.SurfaceFuel == SurfaceFuelType.M3)
                                fuelIndex = listFuel.FuelIndex;
                            if (Event.FuelTypeParms[fuelIndex].CBH < CBH)
                                CBH = Event.FuelTypeParms[fuelIndex].CBH;
                        }
                    }
                    else
                    {
                        foreach (FuelType listFuel in Event.FuelTypeParms)
                        {
                            if (listFuel.SurfaceFuel == SurfaceFuelType.M4)
                                fuelIndex = listFuel.FuelIndex;
                            if (Event.FuelTypeParms[fuelIndex].CBH < CBH)
                                CBH = Event.FuelTypeParms[fuelIndex].CBH;
                        }
                    }
                }


            //If mixed, use weighted average CBH
            if(PH > 0 && PC > 0 && PDF <= 0)
            {
                int decidIndex = SiteVars.DecidFuelType[site];
                if (decidIndex > 0)
                {
                    int decidCBH = Event.FuelTypeParms[decidIndex].CBH;
                    CBH = ((CBH * PC) + (decidCBH * PH)) / 100;
                }

            }
            int FFMC = fireEvent.FFMC;
            int BUI = fireEvent.BuildUpIndex;
            double SFC = SurfaceFuelConsumption(fuelIndex, FFMC, BUI, PH, PDF);
            if (PH > 0 && PC > 0 && PDF <= 0)
            {
                int decidIndex = SiteVars.DecidFuelType[site];
                double decidSFC = SurfaceFuelConsumption(decidIndex, FFMC, BUI, PH, PDF);
                SFC = ((SFC * PC) + (decidSFC * PH)) / 100;
            }
            int severity = 0;

            //-----Edited by BRM-----
            //double ROS = SiteVars.RateOfSpread[site];
            //double ROS = SiteVars.AdjROS[site];

            double ROS = (SiteVars.AdjROS[site] + (SiteVars.RateOfSpread[site] * severityCalibrate)) / (1 + severityCalibrate);
            //----------
            double CSI = 0.001 * Math.Pow(CBH,1.5) * Math.Pow((460 + 25.9 * FMC),1.5);
            double RSO = CSI / (300 * SFC);
            double CFB = 1 - Math.Exp(-0.23 * (ROS - RSO));


            // Finally, calculate SEVERITY:
            double lowThreshold = (RSO + 0.458)/2.0;

            // TEMPORARY?  This seems to help adjust severities 1 and 2 so that there isn't so much of 1 and little of 2.
            lowThreshold *= severityCalibrate;

            if (CFB >= 0.9) severity = 5;
            if (CFB < 0.9 && CFB >= 0.495) severity = 4;
            if (CFB < 0.495 && CFB >= 0.1) severity = 3;
            if (CFB < 0.1 && ROS >= lowThreshold) severity = 2;
            if (CFB < 0.1 && ROS < lowThreshold) severity = 1;

            //UI.WriteLine("      Severity = {0}.  CSI={1}, RSO={2}, ROS={3}, CFB={4}.", severity, CSI, RSO, ROS, CFB);

            return severity;
        }
		//---------------------------------------------------------------------

		public static Event Initiate(ActiveSite site,
		                             int  currentTime, int timestep)
		{

			IEcoregion ecoregion = Model.SiteVars.Ecoregion[site];
			IFireParameters eventParms = FireEventParms[ecoregion.Index];
			double ignitionProb = eventParms.IgnitionProb * timestep;

			//The initial site must exceed the probability of initiation and
			//have a severity > 0 and exceed the ignition threshold:
			if (	Random.GenerateUniform() <= ignitionProb
				&& Random.GenerateUniform() <= ComputeFireInitSpreadProb(site, currentTime)
				&& calcSeverity(site, currentTime) > 0) 
			{
				Event FireEvent = new Event(site);
				FireEvent.Spread(currentTime);
				return FireEvent;
			}
			else
			return null;
		}
        //---------------------------------------------------------------------

        private void LogEvent(int   currentTime,
                              Event FireEvent)
        {
            int totalSitesInEvent = 0;
            if (FireEvent.Severity > 0)
            {
                log.Write("{0},{1},{2},{3},{4},{5:0.0}",
                          currentTime,
                          FireEvent.StartLocation.Row,
                          FireEvent.StartLocation.Column,
                          FireEvent.NumSiteChecked,
                          FireEvent.CohortsKilled,
                          FireEvent.Severity);

                foreach (IFireRegion fireregion in FireRegions.Dataset)
                {
                    log.Write(",{0}", FireEvent.SitesInEvent[fireregion.Index]);
                    totalSitesInEvent += FireEvent.SitesInEvent[fireregion.Index];
                    summaryFireRegionEventCount[fireregion.Index] += FireEvent.SitesInEvent[fireregion.Index];
                }
                summaryTotalSites += totalSitesInEvent;
                log.Write(", {0}", totalSitesInEvent);
                log.WriteLine("");
            }
        }
        public static int CalcFireSeverity(ActiveSite site, Event fireEvent)
        {

            IEcoregion ecoregion = SiteVars.Ecoregion[site];
            IMoreEcoregionParameters fireParms = ecoregion.MoreEcoregionParameters;
            int PH = SiteVars.PercentHardwood[site];  //Percent Hardwood
            int PDF = SiteVars.PercentDeadFir[site];
            
            int fuelIndex = SiteVars.CFSFuelType[site];
            
            int CBH = fireEvent.FuelTypeParms[fuelIndex].CBH;
            int FFMC = fireEvent.FFMC;
            int BUI = fireEvent.BuildUpIndex;
            double SFC = SurfaceFuelConsumption(fuelIndex, FFMC, BUI, PH, PDF);
            int severity = 0;
        
            int FMC = 0;  //Foliar Moisture Content
            if(fireEvent.FireSeason.NameOfSeason == SeasonName.Spring)
            {
                if (Util.Random.GenerateUniform() < fireParms.SpringFMCHiProp)
                    FMC = fireParms.SpringFMCHi;
                else
                    FMC = fireParms.SpringFMCLo;
            }
            if(fireEvent.FireSeason.NameOfSeason == SeasonName.Summer)
            {
                if (Util.Random.GenerateUniform() < fireParms.SummerFMCHiProp)
                    FMC = fireParms.SummerFMCHi;
                else
                    FMC = fireParms.SummerFMCLo;
            }
            if(fireEvent.FireSeason.NameOfSeason == SeasonName.Fall)
            {
                if (Util.Random.GenerateUniform() < fireParms.FallFMCHiProp)
                    FMC = fireParms.FallFMCHi;
                else
                    FMC = fireParms.FallFMCLo;
            }

            //-----Edited by BRM-----
            //double ROS = SiteVars.RateOfSpread[site];
            double ROS = SiteVars.AdjROS[site];
            //----------
            double CSI = 0.001 * Math.Pow(CBH,1.5) * Math.Pow((460 + 25.9 * FMC),1.5);
            double RSO = CSI / 300 * SFC;
            double CFB = 1 - Math.Exp(-0.23 * (ROS - RSO));
            
            
            // Finally, calculate SEVERITY:
            double lowThreshold = (RSO + 0.458)/2.0;
            
            if (CFB >= 0.9) severity = 5;
            if (CFB < 0.9 && CFB >= 0.495) severity = 4;
            if (CFB < 0.495 && CFB >= 0.1) severity = 3;
            if (CFB < 0.1 && ROS >= lowThreshold) severity = 2;
            if (CFB < 0.1 && ROS < lowThreshold) severity = 1;
            
            //UI.WriteLine("      Severity = {0}.  CSI={1}, RSO={2}, ROS={3}, CFB={4}.", severity, CSI, RSO, ROS, CFB);

            return severity;
        }
        //---------------------------------------------------------------------

        private void LogEvent(int   currentTime,
                              Event FireEvent)
        {
            int totalSitesInEvent = 0;
            if (FireEvent.Severity > 0) 
            {
                log.Write("{0},\"{1}\",{2},{3},{4:0.0}",
                          currentTime,
                          FireEvent.StartLocation,
                          FireEvent.NumSiteChecked,
                          FireEvent.CohortsKilled,
                          FireEvent.Severity);
                foreach (IEcoregion ecoregion in Model.Core.Ecoregions)
                {
                    if (ecoregion.Active)
                    {
                        log.Write(",{0}", FireEvent.SitesInEvent[ecoregion.Index]);
                        totalSitesInEvent += FireEvent.SitesInEvent[ecoregion.Index];
                        summaryEcoregionEventCount[ecoregion.Index] += FireEvent.SitesInEvent[ecoregion.Index];
                    }
                }
                summaryTotalSites += totalSitesInEvent;
                log.Write(", {0}", totalSitesInEvent);
                log.WriteLine("");
            }
        }
        //---------------------------------------------------------------------

        public static Event Initiate(ActiveSite site,
                                     int        currentTime,
                                     int        timestep)
        {
            IEcoregion ecoregion = SiteVars.Ecoregion[site];
            IFireParameters eventParms = ecoregion.FireParameters;
            
            //Adjust ignition probability (measured on an annual basis) for the 
            //user determined fire time step.
            double ignitionProb = eventParms.IgnitionProb * timestep;

            //The initial site must exceed the probability of initiation and
            //have a severity > 0 and exceed the ignition threshold:
            if (Random.GenerateUniform() <= ignitionProb
                && Random.GenerateUniform() <= ComputeFireInitSpreadProb(site, currentTime)
                && CalcSeverity(site, currentTime) > 0) 
            {
                Event FireEvent = new Event(site);
                FireEvent.Spread(currentTime);
                return FireEvent;
            }
            else
                return null;
        }
        //---------------------------------------------------------------------

        private void LogEvent(int   currentTime,
                              Event fireEvent)
        {
        
        //HEADER:  Time,Initiation Site,Sites Checked,Cohorts Killed,Mean Severity,
            int totalSitesInEvent = 0;
            if (fireEvent.EventSeverity > 0) 
            {
                //-----Edited by BRM-----
                //-----to include MaxDuration
                log.Write("{0},\"{1}\",{2},{3},{4},{5:0.00},{6:0.00},{7},{8},{9},{10},{11},{12},{13},{14},{15:0.00}",
                          currentTime,
                          fireEvent.StartLocation,
                          fireEvent.InitiationEcoregion,
                          fireEvent.InitiationFuel,
                          fireEvent.InitiationPercentConifer,
                          fireEvent.MaxFireParameter,
                          fireEvent.MaxDuration,
                          fireEvent.FireSeason.NameOfSeason,
                          fireEvent.WindSpeed,
                          fireEvent.WindDirection,
                          fireEvent.FFMC,
                          fireEvent.BuildUpIndex,
                          fireEvent.FireSeason.PercentCuring,
                          fireEvent.NumSitesChecked,
                          fireEvent.CohortsKilled,
                          fireEvent.EventSeverity);
                //----------
                foreach (IEcoregion ecoregion in Ecoregions.Dataset)
                {
//                    if (ecoregion.Active)
//                    {
                        log.Write(",{0}", fireEvent.SitesInEvent[ecoregion.Index]);
                        totalSitesInEvent += fireEvent.SitesInEvent[ecoregion.Index];
                        summaryEcoregionEventCount[ecoregion.Index] += fireEvent.SitesInEvent[ecoregion.Index];
//                    }
                }
                summaryTotalSites += totalSitesInEvent;
                log.Write(", {0}", totalSitesInEvent);
                log.WriteLine("");
            }
        }
        //---------------------------------------------------------------------

        private void LogEvent(int   currentTime,
                              Event fireEvent)
        {

        //HEADER:  Time,Initiation Site,Sites Checked,Cohorts Killed,Mean Severity,
            int totalSitesInEvent = 0;
            if (fireEvent.EventSeverity > 0)
            {
                log.Write("{0},\"{1}\",{2},{3},{4},{5:0.00},{6},{7:0.00},{8},{9},{10},{11},{12},{13},{14},{15},{16},{17:0.00}",
                          currentTime,
                          fireEvent.StartLocation,
                          fireEvent.InitiationFireRegion.Name,
                          fireEvent.InitiationFuel,
                          fireEvent.InitiationPercentConifer,
                          fireEvent.MaxFireParameter,
                          fireEvent.SizeBin,
                          fireEvent.MaxDuration,
                          fireEvent.FireSeason.NameOfSeason,
                          fireEvent.WindSpeed,
                          fireEvent.WindDirection,
                          fireEvent.FFMC,
                          fireEvent.BuildUpIndex,
                          fireEvent.FireSeason.PercentCuring,
                          fireEvent.ISI,
                          fireEvent.NumSitesChecked,
                          fireEvent.CohortsKilled,
                          fireEvent.EventSeverity);
                //----------
                foreach (IFireRegion fire_region in FireRegions.Dataset)
                {
                        log.Write(",{0}", fireEvent.SitesInEvent[fire_region.Index]);
                        totalSitesInEvent += fireEvent.SitesInEvent[fire_region.Index];
                        summaryFireRegionEventCount[fire_region.Index] += fireEvent.SitesInEvent[fire_region.Index];
                }
                summaryTotalSites += totalSitesInEvent;
                log.Write(", {0}", totalSitesInEvent);
                log.WriteLine("");
            }
        }
        //---------------------------------------------------------------------
        public static Event Initiate(ActiveSite site,
                                     int        timestep,
                                     SizeType   fireSizeType, 
                                     bool       bui,
                                     ISeasonParameters[] seasons, 
                                     IWindDirectionParameters[] windDirs)
        {

            
            //Adjust ignition probability (measured on an annual basis) for the 
            //user determined fire time step.
            int fuelIndex = SiteVars.CFSFuelType[site];
            //-----Edited by BRM-----
            //double initProb = fuelTypeParms[fuelIndex].InitiationProbability * timestep;
            double initProb = fuelTypeParms[fuelIndex].InitiationProbability;
            //---------

            //The initial site must exceed the probability of initiation and
            //have a severity > 0 and exceed the ignition threshold:
            if (Util.Random.GenerateUniform() <= initProb)
            {
                Event FireEvent = new Event(site, seasons, windDirs);
                
                if(!FireEvent.Spread(site, fireSizeType, bui))
                    return null;
                else 
                    return FireEvent;
            }
            
            return null;
        }
        private static void MaximumFuelDistance(Event fireEvent)
        {
            UI.WriteLine("      Calculating maximum RSI...");
            IFuelTypeParameters[] fuelTypeParms = fireEvent.FuelTypeParms;

            ISeasonParameters season = fireEvent.FireSeason;
            ushort tempSlope, maxSlope = 0;
            foreach (Site site in Model.Core.Landscape.AllSites)
            {
                if (site.IsActive)
                {
                    tempSlope = SiteVars.GroundSlope[site];
                    if (tempSlope > maxSlope)
                        maxSlope = tempSlope;
                }
            }
            
            double f_F = Weather.CalculateFuelMoistureEffect(fireEvent.FFMC);
            double SF = CalculateSF(maxSlope);
            double f_WZero = Weather.CalculateWindEffect(0);

            double ISZ = 0.208 * f_F * f_WZero;

            double ISI = 0;
            double f_backW = Weather.CalculateBackWindEffect(fireEvent.WindSpeed);
            double BISI = 0.208 * f_F * f_backW;
            double RSZ = 0;
            double RSF = 0;
            double WSE = 0;
            double WSV = 0;
            double f_W = 0;

            
            //M2 and M4 (leaf on) not included in maximum list because they will always be lower
            //than M1 and M3 (leaf off), respectively.
            double ROS = 0.0;
            double ROSmax = 0.0;
            double BROSmax = 0.0;
            double FROSmax = 0.0;
            int maxfuelIndex = -1; 

            int fuelIndex = (int) FuelTypeCode.C1;
            RSZ = FuelEffects.InitialRateOfSpread(fuelIndex, ISZ, 100, 0, 0, season);
            RSF = RSZ * SF;
            WSE = CalculateWSE(fuelIndex, RSF, f_F, 100, season);
            WSV = WSE + fireEvent.WindSpeed;
            f_W = Weather.CalculateWindEffect(WSV);
            ISI = 0.208 * f_F * f_W;
            ROS = FuelEffects.InitialRateOfSpread(fuelIndex, ISI, 100, 0, 0, season) * fuelTypeParms[fuelIndex].MaxBE;
            if(ROS >= ROSmax)
            {
                ROSmax = ROS;
                maxfuelIndex = fuelIndex;
                BROSmax = FuelEffects.InitialRateOfSpread(fuelIndex, BISI, 100, 0, 0, season);
                fireEvent.LB = CalculateLengthBreadthRatio(fireEvent.WindSpeed, fuelIndex);
                FROSmax = (ROSmax + BROSmax) / (fireEvent.LB * 2);
                //FROSmax = FuelEffects.InitialRateOfSpread(fuelIndex, RSZ, 100, 0, 0, season);
                maxfuelIndex = fuelIndex;
            }
            fuelIndex = (int) FuelTypeCode.C2;
            RSZ = FuelEffects.InitialRateOfSpread(fuelIndex, ISZ, 100, 0, 0, season);
            RSF = RSZ * SF;
            WSE = CalculateWSE(fuelIndex, RSF, f_F, 100, season);
            WSV = WSE + fireEvent.WindSpeed;
            f_W = Weather.CalculateWindEffect(WSV);
            ISI = 0.208 * f_F * f_W;
            ROS = FuelEffects.InitialRateOfSpread(fuelIndex, ISI, 100, 0, 0, season) * fuelTypeParms[fuelIndex].MaxBE;
            if(ROS >= ROSmax)
            {
                ROSmax = ROS;
                maxfuelIndex = fuelIndex;
                BROSmax = FuelEffects.InitialRateOfSpread(fuelIndex, BISI, 100, 0, 0, season);
                fireEvent.LB = CalculateLengthBreadthRatio(fireEvent.WindSpeed, fuelIndex);
                FROSmax = (ROSmax + BROSmax) / (fireEvent.LB * 2);
                //FROSmax = FuelEffects.InitialRateOfSpread(fuelIndex, RSZ, 100, 0, 0, season);
                maxfuelIndex = fuelIndex;
            }
            fuelIndex = (int) FuelTypeCode.C3;
            RSZ = FuelEffects.InitialRateOfSpread(fuelIndex, ISZ, 100, 0, 0, season);
            RSF = RSZ * SF;
            WSE = CalculateWSE(fuelIndex, RSF, f_F, 100, season);
            WSV = WSE + fireEvent.WindSpeed;
            f_W = Weather.CalculateWindEffect(WSV);
            ISI = 0.208 * f_F * f_W;
            ROS = FuelEffects.InitialRateOfSpread(fuelIndex, ISI, 100, 0, 0, season) * fuelTypeParms[fuelIndex].MaxBE;
            if(ROS >= ROSmax)
            {
                ROSmax = ROS;
                maxfuelIndex = fuelIndex;
                BROSmax = FuelEffects.InitialRateOfSpread(fuelIndex, BISI, 100, 0, 0, season);
                fireEvent.LB = CalculateLengthBreadthRatio(fireEvent.WindSpeed, fuelIndex);
                FROSmax = (ROSmax + BROSmax) / (fireEvent.LB * 2);
                //FROSmax = FuelEffects.InitialRateOfSpread(fuelIndex, RSZ, 100, 0, 0, season);
                maxfuelIndex = fuelIndex;
            }
            fuelIndex = (int) FuelTypeCode.C4;
            RSZ = FuelEffects.InitialRateOfSpread(fuelIndex, ISZ, 100, 0, 0, season);
            RSF = RSZ * SF;
            WSE = CalculateWSE(fuelIndex, RSF, f_F, 100, season);
            WSV = WSE + fireEvent.WindSpeed;
            f_W = Weather.CalculateWindEffect(WSV);
            ISI = 0.208 * f_F * f_W;
            ROS = FuelEffects.InitialRateOfSpread(fuelIndex, ISI, 100, 0, 0, season) * fuelTypeParms[fuelIndex].MaxBE;
            if(ROS >= ROSmax)
            {
                ROSmax = ROS;
                BROSmax = FuelEffects.InitialRateOfSpread(fuelIndex, BISI, 100, 0, 0, season);
                fireEvent.LB = CalculateLengthBreadthRatio(fireEvent.WindSpeed, fuelIndex);
                FROSmax = (ROSmax + BROSmax) / (fireEvent.LB * 2);
                //FROSmax = FuelEffects.InitialRateOfSpread(fuelIndex, RSZ, 100, 0, 0, season);
                maxfuelIndex = fuelIndex;
            }
            fuelIndex = (int) FuelTypeCode.C5;
            RSZ = FuelEffects.InitialRateOfSpread(fuelIndex, ISZ, 100, 0, 0, season);
            RSF = RSZ * SF;
            WSE = CalculateWSE(fuelIndex, RSF, f_F, 100, season);
            WSV = WSE + fireEvent.WindSpeed;
            f_W = Weather.CalculateWindEffect(WSV);
            ISI = 0.208 * f_F * f_W;
            ROS = FuelEffects.InitialRateOfSpread(fuelIndex, ISI, 100, 0, 0, season) * fuelTypeParms[fuelIndex].MaxBE;
            if(ROS >= ROSmax)
            {
                ROSmax = ROS;
                BROSmax = FuelEffects.InitialRateOfSpread(fuelIndex, BISI, 100, 0, 0, season);
                fireEvent.LB = CalculateLengthBreadthRatio(fireEvent.WindSpeed, fuelIndex);
                FROSmax = (ROSmax + BROSmax) / (fireEvent.LB * 2);
                //FROSmax = FuelEffects.InitialRateOfSpread(fuelIndex, RSZ, 100, 0, 0, season);
                maxfuelIndex = fuelIndex;
            }
            fuelIndex = (int) FuelTypeCode.C6;
            RSZ = FuelEffects.InitialRateOfSpread(fuelIndex, ISZ, 100, 0, 0, season);
            RSF = RSZ * SF;
            WSE = CalculateWSE(fuelIndex, RSF, f_F, 100, season);
            WSV = WSE + fireEvent.WindSpeed;
            f_W = Weather.CalculateWindEffect(WSV);
            ISI = 0.208 * f_F * f_W;
            ROS = FuelEffects.InitialRateOfSpread(fuelIndex, ISI, 100, 0, 0, season) * fuelTypeParms[fuelIndex].MaxBE;
            if(ROS >= ROSmax)
            {
                ROSmax = ROS;
                BROSmax = FuelEffects.InitialRateOfSpread(fuelIndex, BISI, 100, 0, 0, season);
                fireEvent.LB = CalculateLengthBreadthRatio(fireEvent.WindSpeed, fuelIndex);
                FROSmax = (ROSmax + BROSmax) / (fireEvent.LB * 2);
                //FROSmax = FuelEffects.InitialRateOfSpread(fuelIndex, RSZ, 100, 0, 0, season);
                maxfuelIndex = fuelIndex;
            }
            fuelIndex = (int) FuelTypeCode.C7;
            RSZ = FuelEffects.InitialRateOfSpread(fuelIndex, ISZ, 100, 0, 0, season);
            RSF = RSZ * SF;
            WSE = CalculateWSE(fuelIndex, RSF, f_F, 100, season);
            WSV = WSE + fireEvent.WindSpeed;
            f_W = Weather.CalculateWindEffect(WSV);
            ISI = 0.208 * f_F * f_W;
            ROS = FuelEffects.InitialRateOfSpread(fuelIndex, ISI, 100, 0, 0, season) * fuelTypeParms[fuelIndex].MaxBE;
            if(ROS >= ROSmax)
            {
                ROSmax = ROS;
                BROSmax = FuelEffects.InitialRateOfSpread(fuelIndex, BISI, 100, 0, 0, season);
                fireEvent.LB = CalculateLengthBreadthRatio(fireEvent.WindSpeed, fuelIndex);
                FROSmax = (ROSmax + BROSmax) / (fireEvent.LB * 2);
                //FROSmax = FuelEffects.InitialRateOfSpread(fuelIndex, RSZ, 100, 0, 0, season);
                maxfuelIndex = fuelIndex;
            }
            fuelIndex = (int) FuelTypeCode.D1;
            RSZ = FuelEffects.InitialRateOfSpread(fuelIndex, ISZ, 0, 0, 0, season);
            RSF = RSZ * SF;
            WSE = CalculateWSE(fuelIndex, RSF, f_F, 100, season);
            WSV = WSE + fireEvent.WindSpeed;
            f_W = Weather.CalculateWindEffect(WSV);
            ISI = 0.208 * f_F * f_W;
            ROS = FuelEffects.InitialRateOfSpread(fuelIndex, ISI, 0, 100, 0, season) * fuelTypeParms[fuelIndex].MaxBE;
            if(ROS >= ROSmax)
            {
                ROSmax = ROS;
                BROSmax = FuelEffects.InitialRateOfSpread(fuelIndex, BISI, 0, 100, 0, season);
                fireEvent.LB = CalculateLengthBreadthRatio(fireEvent.WindSpeed, fuelIndex);
                FROSmax = (ROSmax + BROSmax) / (fireEvent.LB * 2);
                //FROSmax = FuelEffects.InitialRateOfSpread(fuelIndex, RSZ, 0, 100, 0, season);
                maxfuelIndex = fuelIndex;
            }
            fuelIndex = (int) FuelTypeCode.S1;
            RSZ = FuelEffects.InitialRateOfSpread(fuelIndex, ISZ, 0, 0, 0, season);
            RSF = RSZ * SF;
            WSE = CalculateWSE(fuelIndex, RSF, f_F, 100, season);
            WSV = WSE + fireEvent.WindSpeed;
            f_W = Weather.CalculateWindEffect(WSV);
            ISI = 0.208 * f_F * f_W;
            ROS = FuelEffects.InitialRateOfSpread(fuelIndex, ISI, 0, 0, 0, season) * fuelTypeParms[fuelIndex].MaxBE;
            if(ROS >= ROSmax)
            {
                ROSmax = ROS;
                BROSmax = FuelEffects.InitialRateOfSpread(fuelIndex, BISI, 0, 0, 0, season);
                fireEvent.LB = CalculateLengthBreadthRatio(fireEvent.WindSpeed, fuelIndex);
                FROSmax = (ROSmax + BROSmax) / (fireEvent.LB * 2);
                //FROSmax = FuelEffects.InitialRateOfSpread(fuelIndex, RSZ, 0, 0, 0, season);
                maxfuelIndex = fuelIndex;
            }
            fuelIndex = (int) FuelTypeCode.S2;
            RSZ = FuelEffects.InitialRateOfSpread(fuelIndex, ISZ, 0, 0, 0, season);
            RSF = RSZ * SF;
            WSE = CalculateWSE(fuelIndex, RSF, f_F, 100, season);
            WSV = WSE + fireEvent.WindSpeed;
            f_W = Weather.CalculateWindEffect(WSV);
            ISI = 0.208 * f_F * f_W;
            ROS = FuelEffects.InitialRateOfSpread(fuelIndex, ISI, 0, 0, 0, season) * fuelTypeParms[fuelIndex].MaxBE;
            if(ROS >= ROSmax)
            {
                ROSmax = ROS;
                BROSmax = FuelEffects.InitialRateOfSpread(fuelIndex, BISI, 0, 0, 0, season);
                fireEvent.LB = CalculateLengthBreadthRatio(fireEvent.WindSpeed, fuelIndex);
                FROSmax = (ROSmax + BROSmax) / (fireEvent.LB * 2);
                //FROSmax = FuelEffects.InitialRateOfSpread(fuelIndex, RSZ, 0, 0, 0, season);
                maxfuelIndex = fuelIndex;
            }
            fuelIndex = (int) FuelTypeCode.S3;
            RSZ = FuelEffects.InitialRateOfSpread(fuelIndex, ISZ, 0, 0, 0, season);
            RSF = RSZ * SF;
            WSE = CalculateWSE(fuelIndex, RSF, f_F, 100, season);
            WSV = WSE + fireEvent.WindSpeed;
            f_W = Weather.CalculateWindEffect(WSV);
            ISI = 0.208 * f_F * f_W;
            ROS = FuelEffects.InitialRateOfSpread(fuelIndex, ISI, 0, 0, 0, season) * fuelTypeParms[fuelIndex].MaxBE;
            if(ROS >= ROSmax)
            {
                ROSmax = ROS;
                BROSmax = FuelEffects.InitialRateOfSpread(fuelIndex, BISI, 0, 0, 0, season);
                fireEvent.LB = CalculateLengthBreadthRatio(fireEvent.WindSpeed, fuelIndex);
                FROSmax = (ROSmax + BROSmax) / (fireEvent.LB * 2);
                //FROSmax = FuelEffects.InitialRateOfSpread(fuelIndex, RSZ, 0, 0, 0, season);
                maxfuelIndex = fuelIndex;
            }
            /*fuelIndex = (int) FuelTypeCode.M1;
            ROS = FuelEffects.InitialRateOfSpread(fuelIndex, ISI, 100, 0, 0, season) * fuelTypeParms[fuelIndex].MaxBE;
            if(ROS >= ROSmax)
            {
                ROSmax = ROS;
                BROSmax = FuelEffects.InitialRateOfSpread(fuelIndex, BISI, 100, 0, 0, season);
                FROSmax = FuelEffects.InitialRateOfSpread(fuelIndex, RSZ, 100, 0, 0, season);
                maxfuelIndex = fuelIndex;
            }
            fuelIndex = (int) FuelTypeCode.M3;
            ROS = FuelEffects.InitialRateOfSpread(fuelIndex, ISI, 0, 0, 100, season) * fuelTypeParms[fuelIndex].MaxBE;
            if(ROS >= ROSmax)
            {
                ROSmax = ROS;
                BROSmax = FuelEffects.InitialRateOfSpread(fuelIndex, BISI, 0, 0, 100, season);
                FROSmax = FuelEffects.InitialRateOfSpread(fuelIndex, RSZ, 0, 0, 100, season);
                maxfuelIndex = fuelIndex;
            }*/
            fuelIndex = (int) FuelTypeCode.O1a;
            RSZ = FuelEffects.InitialRateOfSpread(fuelIndex, ISZ, 0, 0, 0, season);
            RSF = RSZ * SF;
            WSE = CalculateWSE(fuelIndex, RSF, f_F, 100, season);
            WSV = WSE + fireEvent.WindSpeed;
            f_W = Weather.CalculateWindEffect(WSV);
            ISI = 0.208 * f_F * f_W;
            ROS = FuelEffects.InitialRateOfSpread(fuelIndex, ISI, 0, 0, 0, season) * fuelTypeParms[fuelIndex].MaxBE;
            if(ROS >= ROSmax)
            {
                ROSmax = ROS;
                BROSmax = FuelEffects.InitialRateOfSpread(fuelIndex, BISI, 0, 0, 0, season);
                //Open fuel types have narrow LB, so to make sure max ellipse covers enough area we force it
                // to use the wider LB of the other types
                fireEvent.LB = CalculateLengthBreadthRatio(fireEvent.WindSpeed, (int) FuelTypeCode.D1);  
                FROSmax = (ROSmax + BROSmax) / (fireEvent.LB * 2);
                //FROSmax = FuelEffects.InitialRateOfSpread(fuelIndex, RSZ, 0, 0, 0, season);
                maxfuelIndex = fuelIndex;
            }
           /* fuelIndex = (int) FuelTypeCode.O1b;
            ROS = FuelEffects.InitialRateOfSpread(fuelIndex, ISI, 0, 0, 0, season) * fuelTypeParms[fuelIndex].MaxBE;
            if(ROS >= ROSmax)
            {
                ROSmax = ROS;
                BROSmax = FuelEffects.InitialRateOfSpread(fuelIndex, BISI, 0, 0, 0, season);
                FROSmax = FuelEffects.InitialRateOfSpread(fuelIndex, RSZ, 0, 0, 0, season);
                maxfuelIndex = fuelIndex;
            }*/
            
            if(maxfuelIndex == -1)
                UI.WriteLine("   Error:  FFMC={0}, WSV={1}.", fireEvent.FFMC, fireEvent.WindSpeed);
            
            
            BROSmax *= fuelTypeParms[maxfuelIndex].MaxBE;

            // Use the Length to Breadth ratio to determine the FLANK rate of spread (FROS).
            //double LB = CalculateLengthBreadthRatio(fireEvent.WindSpeed, maxfuelIndex);
            //FROSmax = (ROSmax + BROSmax)/(LB * 2.0);//        (FBP; 89)
            FROSmax *= fuelTypeParms[maxfuelIndex].MaxBE;
            
            fireEvent.LengthA = FROSmax;
            //fireEvent.LengthB = FROSmax * LB; //((ROSmax + BROSmax) / 2);
            fireEvent.LengthB = ((ROSmax + BROSmax) / 2);
            fireEvent.LengthD = BROSmax;
            //fireEvent.LB = fireEvent.LengthB / fireEvent.LengthA;
            
            UI.WriteLine("      ROSmax = {0:0.000}, FROSmax = {1:0.000}, BROSmax = {2:0.000}.", ROSmax, FROSmax, BROSmax);
            UI.WriteLine("      LBmax = {0:0.000}, WSV = {1}, maxfuelType = {2}", fireEvent.LB, fireEvent.WindSpeed, (FuelTypeCode) maxfuelIndex);
            UI.WriteLine("      LengthA = {0:0.000}, LengthB = {1:0.000}, LengthD = {2:0.000}.", fireEvent.LengthA, fireEvent.LengthB, fireEvent.LengthD);
            UI.WriteLine("      BISI = {0:0.000}, ISI = {1:0.000}, RSZ = {2:0.000}, f(F) = {3:0.000}, f(W) = {4:0.000}.", BISI, ISI, RSZ, f_F, f_W);

            return; 
        }
        //---------------------------------------------------------------------
        //-----Edited by BRM-----
        //-----To pass fireSizeType
        public static List<Site> SizeFireCostSurface(Event fireEvent, SizeType fireSizeType)
        //----------
        {
            
            Site initiationSite = Model.Core.Landscape.GetSite(fireEvent.StartLocation);
            
            MaximumFuelDistance(fireEvent);
            
            //Adjusted for SIZE or DURATION-----BRM-----
            if (fireSizeType == SizeType.size_based)
            {
                double ellipseAdjust = ((fireEvent.LengthB * 2) - fireEvent.LengthD) / fireEvent.LengthD;
                if (ellipseAdjust < 2)
                    ellipseAdjust = 2;
                double ratioBD = fireEvent.LengthB/fireEvent.LengthD;
                double ellipseArea = fireEvent.MaxFireParameter * Model.Core.CellLength * Model.Core.CellLength * ellipseAdjust;
                fireEvent.LengthA = Math.Sqrt(ellipseArea / (Math.PI * fireEvent.LB));
                fireEvent.LengthB = fireEvent.LengthA * fireEvent.LB;
                fireEvent.LengthD = fireEvent.LengthB/ratioBD;
            }
            else
            {
                //FBP 86;  Area in ha
                double ellipseArea = (((Math.PI) / (4 * fireEvent.LB)) * Math.Pow(fireEvent.LengthB * 2 * fireEvent.MaxFireParameter, 2) / 10000);
                fireEvent.LengthD = fireEvent.LengthD * fireEvent.MaxFireParameter;
                fireEvent.LengthB = fireEvent.LengthB * fireEvent.MaxFireParameter;
                fireEvent.LengthA = fireEvent.LengthA * fireEvent.MaxFireParameter;              
             }
             //double ellipseArea = fireEvent.LengthB * fireEvent.LengthA * Math.PI;
            //double ellipseAdjust = 2 * Math.Sqrt((double) fireEvent.MaxFireParameter / ellipseArea);

            //These are the parameters necessary for the calculating eliptical lengths:
            //double lengthD = fireEvent.LengthD * Model.Core.CellLength * ellipseAdjust;
            double lengthC = (fireEvent.LengthB - fireEvent.LengthD);
            
            //UI.WriteLine("      Max Distance = {0:0.0}.  Calculating burn area...", maxDistance);
            UI.WriteLine("      Ellipse: LengthD = {0:0.0} (m).  LengthC = {1:0.0} (m).", fireEvent.LengthD, lengthC);
            
            List<Site> newFireList = new List<Site>();
            SiteVars.TravelTime[initiationSite] = 0.0;
            SiteVars.MinNeighborTravelTime[initiationSite] = 0.0;
            SiteVars.Event[initiationSite] = fireEvent;
            
            //Assign a ROS to the initiation site:
            double initiationTravelTime = CalculateTravelTime(initiationSite, initiationSite, fireEvent);
            SiteVars.TravelTime[initiationSite] = initiationTravelTime;

            //Create a queue of neighboring sites to which the fire will spread:
            Queue<Site> sitesToConsider = new Queue<Site>();
            sitesToConsider.Enqueue(initiationSite);

            while (sitesToConsider.Count > 0) 
            {
                
                //UI.WriteLine("      SiteToConsider = {0}.", sitesToConsider.Count);
                Site srcSite = sitesToConsider.Dequeue();  //Source site
                newFireList.Add(srcSite);

                //Next, add site's neighbors to the list of
                //sites to consider.  The neighbors cannot be part of
                //any other Fire event in the current timestep, and
                //cannot already be on the list.

                List<Site> destinations = Get8Neighbors(srcSite);
                if (destinations.Count > 0)
                {
                    foreach (Site destSite in destinations) 
                    {
                        if (SiteVars.Event[destSite] != null)
                            continue;
                        if (sitesToConsider.Contains(destSite))
                            continue;
                        if(ElipseDistanceBetweenSites(initiationSite, destSite, lengthC, fireEvent.LengthD, fireEvent.WindDirection))
                        {
                            //Complex Cost Surface (Scheller's algorithm)
                            SiteVars.CostTime[destSite] = CalculateTravelTime(destSite, srcSite, fireEvent);
                            if (srcSite == initiationSite)
                            {
                                SiteVars.TravelTime[destSite] = (SiteVars.CostTime[destSite] / 2) * CellDistanceBetweenSites(destSite, srcSite)
                                                           + SiteVars.TravelTime[srcSite];
                            }
                            else
                            {
                                SiteVars.TravelTime[destSite] = (SiteVars.CostTime[destSite] / 2 + SiteVars.CostTime[srcSite] / 2) * CellDistanceBetweenSites(destSite, srcSite)
                                                               + SiteVars.TravelTime[srcSite];
                                //SiteVars.TravelTime[destSite] = SiteVars.CostTime[destSite] * CellDistanceBetweenSites(destSite, srcSite) 
                                //                                + SiteVars.TravelTime[srcSite];
                            }
                            SiteVars.MinNeighborTravelTime[destSite] = SiteVars.TravelTime[srcSite];
                            sitesToConsider.Enqueue(destSite);
                            SiteVars.Event[destSite] = fireEvent;
                        }
                    }
                }
            }
            
            //Finally,  check neighbor travel 10 times to optimize the shortest travel
            //distance.
            
            bool finished = false;
            int count = 1;

            while (!finished)
            {
                UI.WriteLine("      Re-Calculating optimal travel time:  {0} times.", count++);
                finished = true;
                
                // Loop through list and check each for a new, shorter travel time.
                foreach (Site destSite in newFireList)  //Fire destination
                {
                    Site srcSite = CalculateMinNeighbor(destSite, fireEvent);  // Where is the fire coming from?
                    if(srcSite != null)
                    {
                        double oldTravelTime = SiteVars.TravelTime[destSite];
                        //double newTravelTime = (CalculateTravelTime(destSite, srcSite, fireEvent)
                        //                        * CellDistanceBetweenSites(destSite, srcSite))
                        //                        + SiteVars.TravelTime[srcSite];
                        double newCostTime = CalculateTravelTime(destSite, srcSite, fireEvent);
                        double newTravelTime = ((newCostTime / 2 + SiteVars.CostTime[srcSite] / 2) *
                                                    CellDistanceBetweenSites(destSite, srcSite)) + SiteVars.TravelTime[srcSite];
                        if(newTravelTime < oldTravelTime)
                        {
                            SiteVars.CostTime[destSite] = newCostTime;
                            SiteVars.TravelTime[destSite] = newTravelTime;
                            //UI.WriteLine("      OldTT = {0:0.00}, NewTT = {1:0.00}, OldMinNeighborTT = {2:0.00}, MinNeighborTT = {3:0.00}.", 
                            //oldTravelTime, SiteVars.TravelTime[destSite], 
                            SiteVars.MinNeighborTravelTime[destSite]= SiteVars.TravelTime[srcSite];
                            if ((oldTravelTime - newTravelTime) > 0.5)
                            finished = false;
                        }
                    }

                }
                
                if(count > 2000) finished = true;
            }

            return newFireList;
        }
        private static double CalculateTravelTime(Site site, Site firesource, Event fireEvent)
        {

            //Calculate Fire regime size adjustment:
            IEcoregion ecoregion = SiteVars.Ecoregion[site];
            IMoreEcoregionParameters eventParms = ecoregion.MoreEcoregionParameters;
            double FRUA = eventParms.MeanSize;
            
            ecoregion = SiteVars.Ecoregion[firesource];
            eventParms = ecoregion.MoreEcoregionParameters;
            FRUA = FRUA / eventParms.MeanSize;
            
            
            int fuelIndex = SiteVars.CFSFuelType[site];
            int percentConifer = SiteVars.PercentConifer[site];
            int percentHardwood = SiteVars.PercentHardwood[site];
            int percentDeadFir = SiteVars.PercentDeadFir[site];
            List<int> siteWindList = new List<int>();
            int siteWindSpeed, siteWindDirection;

            FuelTypeCode temp = (FuelTypeCode) fuelIndex;
            //UI.WriteLine("         Fuel Type Code = {0}.", temp.ToString());
            
            IFuelTypeParameters[] fuelTypeParms = fireEvent.FuelTypeParms;
            ISeasonParameters season = fireEvent.FireSeason;

            double f_F = Weather.CalculateFuelMoistureEffect(fireEvent.FFMC);
            double ISZ = 0.208 * f_F;  //No wind
            double RSZ = FuelEffects.InitialRateOfSpread(fuelIndex, ISZ,
                                                        percentConifer,
                                                        percentHardwood,
                                                        percentDeadFir,
                                                        season);
            
            siteWindList = CalculateSlopeEffect(fireEvent.WindSpeed, fireEvent.WindDirection, site, RSZ, f_F, season);
            if (siteWindList.Count > 0)
            {
                siteWindSpeed = siteWindList[0];
                siteWindDirection = siteWindList[1];
            }
            else
            {
                siteWindSpeed = fireEvent.WindSpeed;
                siteWindDirection = fireEvent.WindDirection;
            }

            double f_backW = Weather.CalculateBackWindEffect(siteWindSpeed);
            double f_W = Weather.CalculateWindEffect(siteWindSpeed);

            double ISI = 0.208 * f_F * f_W;
            double BISI = 0.208 * f_F * f_backW;

            double BROSi = FuelEffects.InitialRateOfSpread(fuelIndex, BISI, 
                                                        percentConifer,
                                                        percentHardwood,
                                                        percentDeadFir,
                                                        season);
           
            double ROSi = FuelEffects.InitialRateOfSpread(fuelIndex, ISI, 
                                                        percentConifer,
                                                        percentHardwood,
                                                        percentDeadFir,
                                                        season );
            
            BROSi *= FRUA;
            ROSi  *= FRUA;
            SiteVars.RateOfSpread[site] = ROSi;

            double LB = CalculateLengthBreadthRatio(siteWindSpeed, fuelIndex);
            
            double FROSi = (ROSi + BROSi)/(LB * 2.0);//        (FBP; 89)

            double alpha = siteWindDirection;
            double A = FROSi;
            double beta = Beta(firesource, site, alpha);

            //Randomize around 8 neighbor directions
            //int wiggle = (int)((Util.Random.GenerateUniform() * 45.0) - 22.5);
            //beta = beta + wiggle;
            

            double B = A * LB; //fireEvent.LB; 
            double C = B - BROSi;

            //  Equations below for e, p, b, c, a utlize the polar equation
            //  for an ellipse, given at:
            //  http://www.du.edu/~jcalvert/math/ellipse.htm

            double e = C / B;
            double dist = CellDistanceBetweenSites(site, firesource) * Model.Core.CellLength;
            double r = ROSi;
            if (dist != 0)
            {
                double p = dist * (1 + e * Math.Cos(Math.PI - beta));
                double b = p / (1 - e * e);
                double c = e * b;
                r = (dist / (b + c)) * ROSi;
             
            //double a = (1 / LB) * b;           

            //Equations below for theta, r come from Finney 2002, eq [3], [5]

            //double cosSqBeta = CosSquared(beta);
            //double sinSqBeta = SinSquared(beta);
            //double termA = a * Math.Cos(beta) * Math.Pow(((a*a * cosSqBeta) + ((b*b)-(c*c)) * sinSqBeta),0.5);
            //double termB = b * c * sinSqBeta;
            //double termC = ((a*a) * cosSqBeta) + ((b*b) * sinSqBeta);
            //double theta = Math.Acos((termA - termB) / termC);
            
            //r = (a * ((c * Math.Cos(theta)) + b)) /
            //            Math.Sqrt((a * a * CosSquared(theta)) + (b * b * SinSquared(theta)));
            }
                        
            //-----Added by BRM-----
            SiteVars.AdjROS[site] = r;
            //----------      
            
            //UI.WriteLine("      FROSi = {0}, BROSi = {1}.", FROSi, BROSi);
            //UI.WriteLine("      beta = {0:0.00}, theta = {1:0.00}, alpha = {2:0.00}, Travel time = {3:0.000000}.", beta, theta, alpha, 1/r);
            //UI.WriteLine("      Travel time = {0:0.000000}.  R = {1}.", 1/r, r);
            if (site == firesource)
            {
                double rate = 1.0 / r;  //units = minutes / meter
                double cost = rate * Model.Core.CellLength / 2;     //units = minutes
                return cost;
            }
            else
            {
                double rate = 1.0 / r;  //units = minutes / meter
                double cost = rate * Model.Core.CellLength;     //units = minutes
                return cost;
            }
        }
        //-------------------------------------------------------
        private static Site CalculateMinNeighbor(Site site, Event fireEvent)
        {
            List<Site> neighborhood = Get8Neighbors(site);

            Site lowestNeighbor = null;
            
            double minNeighborTravelTime = SiteVars.MinNeighborTravelTime[site]; 
            
            foreach (Site relneighbor in neighborhood) 
            {
                if( //relneighbor != null && 
                    SiteVars.Event[relneighbor] == fireEvent &&
                    !Double.IsPositiveInfinity(SiteVars.TravelTime[relneighbor]) && 
                    SiteVars.TravelTime[relneighbor] < minNeighborTravelTime)
                {
                    lowestNeighbor = relneighbor;
                    SiteVars.MinNeighborTravelTime[site] = SiteVars.TravelTime[relneighbor];
                    //UI.WriteLine("Location = {0},{1}.  MinTravelTime = {2}.", lowestNeighbor.Row, lowestNeighbor.Column, SiteVars.TravelTime[relneighbor]);
                }
            }
            
            return lowestNeighbor;

        }