예제 #1
0
        //---------------------------------------------------------------------

        public static Event Initiate(ActiveSite site,
                                     int currentTime,
                                     int timestep)
        {
            IFireRegion ecoregion = SiteVars.FireRegion[site];

            //Adjust ignition probability (measured on an annual basis) for the
            //user determined fire time step.
            double ignitionProb = ecoregion.IgnitionProbability * timestep;

            //The initial site must exceed the probability of initiation and
            //have a severity > 0 and exceed the ignition threshold:

            if (PlugIn.ModelCore.GenerateUniform() <= ignitionProb &&
                PlugIn.ModelCore.GenerateUniform() <= ComputeFireInitSpreadProb(site, currentTime) &&
                CalcSeverity(site, currentTime) > 0)
            {
                Event FireEvent = new Event(site);
                FireEvent.Spread(currentTime);
                return(FireEvent);
            }
            else
            {
                return(null);
            }
        }
예제 #2
0
        //---------------------------------------------------------------------

        public static int ComputeSize(IFireRegion ecoregion)
        {
            if (ecoregion.MeanSize <= 0)
            {
                return(0);
            }

            PlugIn.ModelCore.ExponentialDistribution.Lambda = 1.0 / ecoregion.MeanSize;
            double sizeGenerated = PlugIn.ModelCore.ExponentialDistribution.NextDouble();

            int finalSize;

            if (sizeGenerated < ecoregion.MinSize)
            {
                finalSize = (int)(ecoregion.MinSize / PlugIn.ModelCore.CellArea);
            }
            else if (sizeGenerated > ecoregion.MaxSize)
            {
                finalSize = (int)(ecoregion.MaxSize / PlugIn.ModelCore.CellArea);
            }
            else
            {
                finalSize = (int)(sizeGenerated / PlugIn.ModelCore.CellArea);
            }

            return(finalSize);
        }
예제 #3
0
        //---------------------------------------------------------------------

        private IFireRegion GetFireRegion(InputValue <string> ecoregionName,
                                          Dictionary <string, int> lineNumbers)
        {
            //IFireRegion ecoregion = FireRegions.Dataset[ecoregionName.Actual];
            IFireRegion ecoregion = FireRegions.FindName(ecoregionName.Actual);

            if (ecoregion == null)
            {
                throw new InputValueException(ecoregionName.String,
                                              "{0} is not an ecoregion name.",
                                              ecoregionName.String);
            }
            int lineNumber;

            if (lineNumbers.TryGetValue(ecoregion.Name, out lineNumber))
            {
                throw new InputValueException(ecoregionName.String,
                                              "The ecoregion {0} was previously used on line {1}",
                                              ecoregionName.String, lineNumber);
            }
            else
            {
                lineNumbers[ecoregion.Name] = LineNumber;
            }

            return(ecoregion);
        }
예제 #4
0
        //---------------------------------------------------------------------

        // The probability of fire initiation (different from ignition)
        // and spread.  Formula from Jian Yang, University of Missouri-Columbia,
        // personal communication.

        public static double ComputeFireInitSpreadProb(ActiveSite site, int currentTime)
        {
            IFireRegion ecoregion = SiteVars.FireRegion[site];

            int    timeSinceLastFire  = currentTime - SiteVars.TimeOfLastFire[site];
            double fireInitSpreadProb =
                1.0 - System.Math.Exp(timeSinceLastFire * (-1.0 / (double)ecoregion.FireSpreadAge));

            return(fireInitSpreadProb);
        }
        //---------------------------------------------------------------------

        public static void ReadMap(string path)
        {
            IInputRaster <IntPixel> map;

            try
            {
                map = PlugIn.ModelCore.OpenRaster <IntPixel>(path);
            }
            catch (FileNotFoundException)
            {
                string mesg = string.Format("Error: The file {0} does not exist", path);
                throw new System.ApplicationException(mesg);
            }

            if (map.Dimensions != PlugIn.ModelCore.Landscape.Dimensions)
            {
                string mesg = string.Format("Error: The input map {0} does not have the same dimension (row, column) as the ecoregions map", path);
                throw new System.ApplicationException(mesg);
            }

            using (map) {
                IntPixel pixel = map.BufferPixel;
                foreach (Site site in PlugIn.ModelCore.Landscape.AllSites)
                {
                    map.ReadBufferPixel();
                    int mapCode = pixel.MapCode.Value;
                    if (site.IsActive)
                    {
                        if (Dataset == null)
                        {
                            PlugIn.ModelCore.UI.WriteLine("FireRegion.Dataset not set correctly.");
                        }
                        IFireRegion fire_region = Find(mapCode);

                        if (fire_region == null)
                        {
                            string mesg = string.Format("Unknown map code = {0}, Row/Column = {1}/{2}", mapCode, site.Location.Row, site.Location.Column);
                            throw new System.ApplicationException(mesg);
                        }
                        SiteVars.FireRegion[site] = fire_region;
                        fire_region.FireRegionSites.Add(site.Location);
                    }
                }
            }
        }
예제 #6
0
        //---------------------------------------------------------------------

        private Event(ActiveSite initiationSite, ISeasonParameters fireSeason, SizeType fireSizeType)
        {
            this.initiationSite = initiationSite;
            this.sitesInEvent   = new int[FireRegions.Dataset.Count];
            //PlugIn.ModelCore.UI.WriteLine("   initialzing siteInEvent ...");

            foreach (IFireRegion fire_region in FireRegions.Dataset)
            {
                this.sitesInEvent[fire_region.Index] = 0;
            }
            this.cohortsKilled     = 0;
            this.eventSeverity     = 0;
            this.totalSitesDamaged = 0;
            this.lengthB           = 0.0;
            this.lengthA           = 0.0;
            this.lengthD           = 0.0;
            IFireRegion eco = SiteVars.FireRegion[initiationSite];

            this.initiationFireRegion = eco;
            this.maxFireParameter     = ComputeSize(eco.MeanSize, eco.StandardDeviation, eco.MaxSize); //fireSizeType);
            this.sizeBin    = ComputeSizeBin(eco.MeanSize, eco.StandardDeviation, this.maxFireParameter);
            this.fireSeason = fireSeason;                                                              //Weather.GenerateSeason(seasons);
            System.Data.DataRow weatherRow = Weather.GenerateDataRow(this.fireSeason, eco, this.sizeBin);

            this.windSpeed            = Weather.GenerateWindSpeed(weatherRow);
            this.fineFuelMoistureCode = Weather.GenerateFineFuelMoistureCode(weatherRow);
            this.buildUpIndex         = Weather.GenerateBuildUpIndex(weatherRow);
            this.windDirection        = Weather.GenerateWindDirection(weatherRow);
            this.foliarMC             = Weather.GenerateFMC(this.fireSeason, eco);


            //PlugIn.ModelCore.UI.WriteLine();

            /*PlugIn.ModelCore.UI.WriteLine("   New Fire Event Data:  WSV={0}, FFMC={1}, BUI={2}, foliarMC={3}, windDirection={4}, Season={5}, FireRegion={6}, SizeBin = {7}.",
             *              this.windSpeed,
             *              this.fineFuelMoistureCode,
             *              this.buildUpIndex,
             *              this.foliarMC,
             *              this.windDirection,
             *              this.fireSeason.NameOfSeason,
             *              this.initiationFireRegion.Name,
             *              this.sizeBin
             *              );*/
        }
예제 #7
0
        //---------------------------------------------------------------------

        public static int GenerateFMC(ISeasonParameters season, IFireRegion fire_region)
        {
            int FMC = 0;

            if (season.NameOfSeason == SeasonName.Spring)
            {
                if (PlugIn.ModelCore.GenerateUniform() < fire_region.SpringFMCHiProp)
                {
                    FMC = fire_region.SpringFMCHi;
                }
                else
                {
                    FMC = fire_region.SpringFMCLo;
                }
            }
            if (season.NameOfSeason == SeasonName.Summer)
            {
                if (PlugIn.ModelCore.GenerateUniform() < fire_region.SummerFMCHiProp)
                {
                    FMC = fire_region.SummerFMCHi;
                }
                else
                {
                    FMC = fire_region.SummerFMCLo;
                }
            }
            if (season.NameOfSeason == SeasonName.Fall)
            {
                if (PlugIn.ModelCore.GenerateUniform() < fire_region.FallFMCHiProp)
                {
                    FMC = fire_region.FallFMCHi;
                }
                else
                {
                    FMC = fire_region.FallFMCLo;
                }
            }
            return(FMC);
        }
예제 #8
0
        //---------------------------------------------------------------------
        private bool Spread(ActiveSite initiationSite, SizeType fireSizeType, bool BUI, double severityCalibrate)
        {
            //First, check for fire overlap:
            if (SiteVars.Event[initiationSite] != null)
            {
                return(false);
            }

            if (isDebugEnabled)
            {
                PlugIn.ModelCore.UI.WriteLine("   Spreading fire event started at {0} ...", initiationSite.Location);
            }

            IFireRegion fire_region = SiteVars.FireRegion[initiationSite];

            int totalSiteSeverities = 0;
            int siteCohortsKilled   = 0;
            int totalISI            = 0;

            totalSitesDamaged = 1;

            this.initiationFuel           = SiteVars.CFSFuelType[initiationSite];
            this.initiationPercentConifer = SiteVars.PercentConifer[initiationSite];

            //PlugIn.ModelCore.UI.WriteLine("      Calculated max fire size or duration = {0:0.0}", maxFireParameter);
            //PlugIn.ModelCore.UI.WriteLine("      Fuel Type = {0}", activeFT.ToString());

            //Next, calculate the fire area:
            List <Site> FireLocations = new List <Site>();

            if (isDebugEnabled)
            {
                PlugIn.ModelCore.UI.WriteLine("  Calling SizeFireCostSurface ...");
            }

            FireLocations = EventRegion.SizeFireCostSurface(this, fireSizeType, BUI);

            if (isDebugEnabled)
            {
                PlugIn.ModelCore.UI.WriteLine("    FireLocations.Count = {0}", FireLocations.Count);
            }

            if (FireLocations.Count == 0)
            {
                return(false);
            }

            //Attach travel time weights here
            if (isDebugEnabled)
            {
                PlugIn.ModelCore.UI.WriteLine("  Computing SizeFireCostSurface ...");
            }
            List <WeightedSite> FireCostSurface = new List <WeightedSite>(0);

            foreach (Site site in FireLocations)
            {
                double myWeight = SiteVars.TravelTime[site];
                if ((Double.IsNaN(myWeight)) || (Double.IsInfinity(myWeight)))
                {
                }
                else
                {
                    FireCostSurface.Add(new WeightedSite(site, myWeight));
                }
            }
            WeightComparer weightComp = new WeightComparer();

            FireCostSurface.Sort(weightComp);
            FireLocations = new List <Site>();

            double cellArea  = (PlugIn.ModelCore.CellLength * PlugIn.ModelCore.CellLength) / 10000; //convert to ha
            double totalArea = 0.0;
            int    cellCnt   = 0;
            double durMax    = 0;

            if (isDebugEnabled)
            {
                PlugIn.ModelCore.UI.WriteLine("  Determining cells burned ...");
            }
            if (fireSizeType == SizeType.size_based)
            {
                foreach (WeightedSite weighted in FireCostSurface)
                {
                    //weightCnt++;
                    cellCnt++;
                    if (totalArea > this.maxFireParameter)
                    {
                        SiteVars.Event[weighted.Site] = null;
                    }
                    else
                    {
                        totalArea += cellArea;
                        FireLocations.Add(weighted.Site);
                        if (SiteVars.TravelTime[weighted.Site] > durMax)
                        {
                            durMax = SiteVars.TravelTime[weighted.Site];
                        }
                    }
                }
                this.maxDuration = durMax;
                //PlugIn.ModelCore.UI.WriteLine("   Fire Summary:  Cells Checked={0}, BurnedArea={1:0.0} (ha), Target Area={2:0.0} (ha).", cellCnt, totalArea, this.maxFireParameter);
                //if(totalArea < this.maxFireParameter)
                //    PlugIn.ModelCore.UI.WriteLine("      NOTE:  Partial fire burn; fire may have spread to the edge of the active area.");
            }
            else if (fireSizeType == SizeType.duration_based)
            {
                double durationAdj = this.maxFireParameter;
                if (durationAdj >= 1440)
                {
                    durationAdj = durationAdj * this.FireSeason.DayLengthProp;
                }


                foreach (WeightedSite weighted in FireCostSurface)
                {
                    cellCnt++;
                    if (weighted.Site == this.initiationSite)
                    {
                        totalArea += cellArea;
                        FireLocations.Add(weighted.Site);
                        if (SiteVars.TravelTime[weighted.Site] > durMax)
                        {
                            durMax = SiteVars.TravelTime[weighted.Site];
                        }
                    }
                    else
                    {
                        if (weighted.Weight > durationAdj)
                        {
                            SiteVars.Event[weighted.Site] = null;
                        }
                        else
                        {
                            totalArea += cellArea;
                            FireLocations.Add(weighted.Site);
                            //-----Added by BRM-----
                            if (SiteVars.TravelTime[weighted.Site] > durMax)
                            {
                                durMax = SiteVars.TravelTime[weighted.Site];
                            }
                            //----------
                        }
                    }
                }
                this.maxDuration = durMax;

                //PlugIn.ModelCore.UI.WriteLine("   Fire Summary:  Cells Checked={0}, BurnedArea={1:0.0} (ha), Target Duration={2:0.0}, Adjusted Duration = {3:0.0}.", cellCnt, totalArea, this.maxFireParameter, durationAdj);
                //if(durationAdj - durMax > 5.0)
                //    PlugIn.ModelCore.UI.WriteLine("      NOTE:  Partial fire burn; fire may have spread to the edge of the active area.");
            }
            if (isDebugEnabled)
            {
                PlugIn.ModelCore.UI.WriteLine("  FireLocations.Count = {0}", FireLocations.Count);
            }
            int FMC = this.FMC;  //Foliar Moisture Content

            if (FireLocations.Count == 0)
            {
                return(false);
            }

            if (isDebugEnabled)
            {
                PlugIn.ModelCore.UI.WriteLine("  Damaging cohorts at burned sites ...");
            }
            foreach (Site site in FireLocations)
            {
                currentSite = (ActiveSite)site;
                if (site.IsActive)
                {
                    this.numSitesChecked++;

                    this.siteSeverity = FireSeverity.CalcFireSeverity(currentSite, this, severityCalibrate, FMC);
                    SiteVars.Severity[currentSite] = (byte)siteSeverity;
                    siteCohortsKilled = Damage(currentSite);

                    this.totalSitesDamaged++;
                    totalSiteSeverities += this.siteSeverity;
                    totalISI            += (int)SiteVars.ISI[site];

                    IFireRegion siteFireRegion = SiteVars.FireRegion[site];
                    sitesInEvent[siteFireRegion.Index]++;

                    SiteVars.Disturbed[currentSite] = true;


                    if (siteSeverity > 0)
                    {
                        SiteVars.LastSeverity[currentSite] = (byte)siteSeverity;
                    }
                }
            }

            if (this.totalSitesDamaged == 0)
            {
                this.eventSeverity = 0;
            }
            else
            {
                this.eventSeverity = ((double)totalSiteSeverities) / (double)this.totalSitesDamaged;
            }

            this.isi = (int)((double)totalISI / (double)this.totalSitesDamaged);

            if (isDebugEnabled)
            {
                PlugIn.ModelCore.UI.WriteLine("  Done spreading");
            }
            return(true);
        }
        //---------------------------------------------------------------------

        public static int ComputeSize(IFireRegion ecoregion)
        {
            if (ecoregion.MeanSize <= 0)
                return 0;
            
            PlugIn.ModelCore.ExponentialDistribution.Lambda = 1.0 / ecoregion.MeanSize;
            double sizeGenerated = PlugIn.ModelCore.ExponentialDistribution.NextDouble();
            
            int finalSize;

            if (sizeGenerated < ecoregion.MinSize)
                finalSize = (int)(ecoregion.MinSize / PlugIn.ModelCore.CellArea);
            else if (sizeGenerated > ecoregion.MaxSize)
            {
                finalSize = (int)(ecoregion.MaxSize / PlugIn.ModelCore.CellArea);
            }    
            else
                finalSize = (int)(sizeGenerated / PlugIn.ModelCore.CellArea);

            return finalSize;
        }
예제 #10
0
        //---------------------------------------------------------------------

        public static byte CalcSeverity(ActiveSite site,
                                        int currentTime)
        {
            IFireRegion ecoregion = SiteVars.FireRegion[site];
            IFuelCurve  fuelCurve = ecoregion.FuelCurve;
            IWindCurve  windCurve = ecoregion.WindCurve;
            int         severity  = 0;

            int timeSinceLastFire = currentTime - SiteVars.TimeOfLastFire[site];

            if (fuelCurve.Severity1 != -1 && timeSinceLastFire >= fuelCurve.Severity1)
            {
                severity = 1;
            }
            if (fuelCurve.Severity2 != -1 && timeSinceLastFire >= fuelCurve.Severity2)
            {
                severity = 2;
            }
            if (fuelCurve.Severity3 != -1 && timeSinceLastFire >= fuelCurve.Severity3)
            {
                severity = 3;
            }
            if (fuelCurve.Severity4 != -1 && timeSinceLastFire >= fuelCurve.Severity4)
            {
                severity = 4;
            }
            if (fuelCurve.Severity5 != -1 && timeSinceLastFire >= fuelCurve.Severity5)
            {
                severity = 5;
            }

            int windSeverity      = 0;
            int timeSinceLastWind = 0;

            if (SiteVars.TimeOfLastWind != null)
            {
                timeSinceLastWind = currentTime - SiteVars.TimeOfLastWind[site];
                if (windCurve.Severity1 != -1 && timeSinceLastWind <= windCurve.Severity1)
                {
                    windSeverity = 1;
                }
                if (windCurve.Severity2 != -1 && timeSinceLastWind <= windCurve.Severity2)
                {
                    windSeverity = 2;
                }
                if (windCurve.Severity3 != -1 && timeSinceLastWind <= windCurve.Severity3)
                {
                    windSeverity = 3;
                }
                if (windCurve.Severity4 != -1 && timeSinceLastWind <= windCurve.Severity4)
                {
                    windSeverity = 4;
                }
                if (windCurve.Severity5 != -1 && timeSinceLastWind <= windCurve.Severity5)
                {
                    windSeverity = 5;
                }
            }

            if (windSeverity > severity)
            {
                severity = windSeverity;
            }
            return((byte)severity);
        }
예제 #11
0
        //---------------------------------------------------------------------

        private void Spread(int currentTime)
        {
            int    windDirection = (int)(PlugIn.ModelCore.GenerateUniform() * 8);
            double windSpeed     = PlugIn.ModelCore.GenerateUniform();

            int[] size = new int[FireRegions.Dataset.Count]; // in # of sites

            int  totalSitesInEvent   = 0;
            long totalSiteSeverities = 0;
            int  maxFireRegionSize   = 0;
            int  siteCohortsKilled   = 0;

            IFireRegion ecoregion = SiteVars.FireRegion[initiationSite];
            int         ecoIndex  = ecoregion.Index;

            size[ecoIndex] = ComputeSize(ecoregion);

            if (size[ecoIndex] > maxFireRegionSize)
            {
                maxFireRegionSize = size[ecoIndex];
            }

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

            sitesToConsider.Enqueue(initiationSite);

            //Fire size cannot be larger than the size calculated for each ecoregion.
            //Fire size cannot be larger than the largest size for any ecoregion.
            while (sitesToConsider.Count > 0 &&
                   this.sitesInEvent[ecoIndex] < size[ecoIndex] &&
                   totalSitesInEvent < maxFireRegionSize)
            {
                this.numSiteChecked++;
                Site site = sitesToConsider.Dequeue();
                currentSite = (ActiveSite)site;  //site as ActiveSite;

                ecoregion = SiteVars.FireRegion[site];
                if (ecoregion.Index != ecoIndex)
                {
                    ecoIndex = ecoregion.Index;
                    if (size[ecoIndex] < 1)
                    {
                        size[ecoIndex] = ComputeSize(ecoregion);
                        if (size[ecoIndex] > maxFireRegionSize)
                        {
                            maxFireRegionSize = size[ecoIndex];
                        }
                    }
                }

                SiteVars.Event[site] = this;

                if (currentSite != null)
                {
                    siteSeverity = CalcSeverity(currentSite, currentTime);
                }
                else
                {
                    siteSeverity = 0;
                }

                if (siteSeverity > 0)
                {
                    this.sitesInEvent[ecoIndex]++;
                    totalSitesInEvent++;

                    SiteVars.Severity[currentSite]       = siteSeverity;
                    SiteVars.TimeOfLastFire[currentSite] = currentTime;

                    totalSiteSeverities            += siteSeverity;
                    SiteVars.Disturbed[currentSite] = true;

                    siteCohortsKilled = KillSiteCohorts(currentSite);
                    if (siteCohortsKilled > 0)
                    {
                        totalSitesDamaged++;
                    }

                    //Next, add site's neighbors in random order 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.

                    //Fire can burn into neighbors only if the
                    //spread probability is exceeded.
                    List <Site> neighbors = GetNeighbors(site, windDirection, windSpeed);
                    if (neighbors.Count > 0)
                    {
                        neighbors = PlugIn.ModelCore.shuffle(neighbors);

                        foreach (Site neighbor in neighbors)
                        {
                            if (!neighbor.IsActive)
                            {
                                continue;
                            }
                            if (SiteVars.Event[neighbor] != null)
                            {
                                continue;
                            }
                            if (sitesToConsider.Contains(neighbor))
                            {
                                continue;
                            }
                            if (PlugIn.ModelCore.GenerateUniform() <= ComputeFireInitSpreadProb((ActiveSite)neighbor, currentTime)) //(neighbor as ActiveSite, currentTime))
                            {
                                sitesToConsider.Enqueue(neighbor);
                            }
                        }
                    }
                }
            }

            if (this.totalSitesDamaged == 0)
            {
                this.severity = 0;
            }
            else
            {
                this.severity = ((double)totalSiteSeverities) / totalSitesInEvent;
            }
        }
예제 #12
0
        //---------------------------------------------------------------------

        public static int ComputeSize(IFireRegion ecoregion)
        {
            if (ecoregion.MeanSize <= 0)
                return 0;
            double sizeGenerated = Random.GenerateExponential(ecoregion.MeanSize);
            //UI.WriteLine("Max={0}, Min={1}, Mean={2}, Eco={3}.", ecoregion.MaxSize, ecoregion.MinSize, ecoregion.MeanSize, ecoregion.Name);
            //double sizeGenerated = Random.GenerateLogNormal(ecoregion.MeanSize);
            if (sizeGenerated < ecoregion.MinSize)
                return (int) (ecoregion.MinSize/Model.Core.CellArea);
            else if (sizeGenerated > ecoregion.MaxSize)
            {
                return (int) (ecoregion.MaxSize / Model.Core.CellArea);
            }    
            else
                return (int) (sizeGenerated/Model.Core.CellArea);
        }
예제 #13
0
        private static double CalculateTravelTime(Site site, Site firesource, Event fireEvent, bool buildUp)
        {
            if (!site.IsActive || !firesource.IsActive)
            {
                throw new ApplicationException("Either site or fire source are not active.");
            }

            //Calculate Fire regime size adjustment:
            IFireRegion fire_region = SiteVars.FireRegion[site];
            double      FRUA        = fire_region.MeanSize;

            fire_region = SiteVars.FireRegion[firesource];
            FRUA        = FRUA / fire_region.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;

            //PlugIn.ModelCore.UI.WriteLine("         Fuel Type Code = {0}.", temp.ToString());

            ISeasonParameters season = fireEvent.FireSeason;

            double f_F = Weather.CalculateFuelMoistureEffect(fireEvent.FFMC);
            double ISZ = 0.208 * f_F;  //No wind
            double RSZ = FuelEffects.InitialRateOfSpread(ISZ, season, site);

            if (Event.FuelTypeParms[fuelIndex].BaseFuel == BaseFuelType.ConiferPlantation)//SurfaceFuel == SurfaceFuelType.C6)
            {
                double FME = (Math.Pow((1.5 - (0.00275 * fireEvent.FMC)), 4) / (460 + (25.9 * fireEvent.FMC))) * 1000;
                double RSC = FuelEffects.CalculateRSI(60, 0.0497, 1, ISZ) * (FME / 0.778);
                double CSI = 0.001 * Math.Pow(7, 1.5) * Math.Pow((460 + 25.9 * fireEvent.FMC), 1.5);
                double SFC = FireSeverity.SurfaceFuelConsumption(fuelIndex, fireEvent.FFMC, fireEvent.BuildUpIndex, percentHardwood, percentDeadFir);
                double RSO = CSI / (300 * SFC);
                double CFB = 0;
                if (RSZ > RSO)
                {
                    CFB = 1 - Math.Exp(-0.23 * (RSZ - RSO));
                }
                RSZ = RSZ + (CFB * (RSC - RSZ));
            }
            double BE = 0;

            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;

            SiteVars.ISI[site] = ISI;

            double BISI = 0.208 * f_F * f_backW;

            double BROSi = FuelEffects.InitialRateOfSpread(BISI, season, site);
            double ROSi  = FuelEffects.InitialRateOfSpread(ISI, season, site);

            if (ROSi == 0)
            {
                SiteVars.RateOfSpread[site] = 0;
                SiteVars.AdjROS[site]       = 0;
                return(Double.PositiveInfinity);
            }
            else
            {
                BROSi *= FRUA;
                ROSi  *= FRUA;

                if (buildUp)
                {
                    if (SiteVars.PercentDeadFir[site] > 0) //either criteria indicates a DEAD FIR type
                    {
                        BE = Math.Exp(50 * Math.Log(0.80) * ((1 / (double)fireEvent.BuildUpIndex) - (1 / (double)50)));
                    }
                    else
                    {
                        BE = Math.Exp(50.0 * Math.Log(Event.FuelTypeParms[fuelIndex].Q) * ((1.0 / (double)fireEvent.BuildUpIndex) - (1 / (double)Event.FuelTypeParms[fuelIndex].BUI)));
                    }
                }
                else
                {
                    BE = 1;
                }
                ROSi  *= BE;
                BROSi *= BE;
                SiteVars.RateOfSpread[site] = ROSi;

                double LB = CalculateLengthBreadthRatio(siteWindSpeed, fuelIndex);

                double FROSi = (ROSi + BROSi) / (LB * 2.0);//        (FBP; 89)

                double alpha = siteWindDirection * (-1);
                double A     = FROSi;
                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
                //  Note that a and b are switched from those defined in these equations
                //  so that they will fit in Finney's equation below

                double e     = Math.Sqrt((double)1 - (Math.Pow(((double)1 / LB), 2)));                   //e = Eccentricity
                double dist  = CellDistanceBetweenSites(site, firesource) * PlugIn.ModelCore.CellLength; //dist = r in Calvert's equation
                double r     = ROSi;
                double time  = 0;
                double index = 1;

                if (dist != 0)
                {
                    double beta = BetaRand(firesource, site, alpha);         // Beta = angle between wind direction, site
                    double p    = dist * (1 + e * Math.Cos(Math.PI - beta)); // p = semi-latus rectum = dist from focus to ellipse perimeter perpendicular to major axis
                    double b    = p / (1 - (e * e));                         // b = half major axis (a in Calvert's equations)
                    double a    = b * Math.Sqrt(1 - (e * e));                // a = half minor axis (b in Calvert's equations)
                    double c    = e * b;                                     // c = dist between focus and center

                    // New (10/22/2007) equations to get r
                    // a, b, c, and dist are real distances in m
                    time = (b + c) / ROSi;  // Calculate the time it would take to travel the distance of b+c if ROSi was the rate
                    r    = dist / time;     // Calculate the ROS given the distance to the cell and the time

                    //++++++++++
                    // This is a better way to make adjustments to account for randomization of angles
                    // These equations were derived in MathCad (Beta_Adjust.xmcd)
                    // See rationale for adjustments in Randomization Summary.doc

                    index = 1;
                    if (beta < 0)
                    {
                        beta = (Math.PI * 2) + beta;
                    }
                    double L2 = LB * LB;

                    double partA = L2 * Math.Pow(((L2 - 1) / L2), 0.5);

                    double partB = (-2) * (Math.Atan(Math.Tan(((0.5) * beta) + ((0.0625) * (Math.PI))) * Math.Pow((2 * L2 + 2 * L2 * Math.Pow(((LB - 1) * ((LB + 1) / L2)), (0.5)) - 1), (0.5))));

                    double partC = (((-1) * (L2)) + (partA * Math.Cos(beta)) - (partA) + (Math.Cos(beta) * L2) - (Math.Cos(beta))) / (Math.Pow(((2 * L2) + (2 * partA) - 1), (0.5)));

                    double partD = (2) * (Math.Atan(((double)1 / (Math.Tan(((0.5) * beta) + ((0.4375) * (Math.PI))))) * Math.Pow((2 * L2 + 2 * L2 * Math.Pow(((LB - 1) * ((LB + 1) / L2)), (0.5)) - 1), (0.5))));
                    if ((((beta + 0.125 * Math.PI) >= Math.PI) && ((beta - 0.125 * Math.PI) >= Math.PI)) || (((beta + 0.125 * Math.PI) <= Math.PI) && ((beta - 0.125 * Math.PI) <= Math.PI)))
                    {
                        index = 4 * (partB * partC - partD * partC) / Math.PI;

                        //Console.WriteLine("Beta = {0}; LB = {1}; partA = {2}; partB = {3}, partC = {4}, partD = {5}; Index = {6}", Beta, LB, partA, partB, partC, partD, index);
                    }
                    else
                    {
                        double indexA  = ((-1) * Math.PI * partC - partD * partC) / (Math.PI * ((double)9 / (double)8) - beta);
                        double indexB  = (partB * partC - Math.PI * partC) / (beta - Math.PI * ((double)7 / (double)8));
                        double weightA = (Math.PI - (beta - 0.125 * Math.PI)) / (0.25 * Math.PI);
                        double weightB = ((beta + 0.125 * Math.PI) - Math.PI) / (0.25 * Math.PI);
                        index = indexA * weightA + indexB * weightB;
                        //Console.WriteLine("Beta = {0}; IndexA = {1}; weightA = {2}; IndexB = {3}; weightB = {4}; Index = {5}", Beta, indexA, weightA, indexB, weightB, index);
                    }
                    r = r * (1 / index);
                    //++++++++++
                }
                if (Event.FuelTypeParms[fuelIndex].BaseFuel == BaseFuelType.ConiferPlantation) //(int)FuelTypeCode.C6)
                {
                    double FME = (Math.Pow((1.5 - (0.00275 * fireEvent.FMC)), 4) / (460 + (25.9 * fireEvent.FMC))) * 1000;
                    double RSC = FuelEffects.CalculateRSI(60, 0.0497, 1, ISI) * (FME / 0.778);
                    double CSI = 0.001 * Math.Pow(7, 1.5) * Math.Pow((460 + 25.9 * fireEvent.FMC), 1.5);
                    double SFC = FireSeverity.SurfaceFuelConsumption(fuelIndex, fireEvent.FFMC, fireEvent.BuildUpIndex, percentHardwood, percentDeadFir);
                    double RSO = CSI / (300 * SFC);
                    double CFB = 0;
                    if (r > RSO)
                    {
                        CFB = 1 - Math.Exp(-0.23 * (r - RSO));
                    }
                    r = r + (CFB * (RSC - r));
                }


                //-----Added by BRM-----
                SiteVars.AdjROS[site] = r;
                //----------

                //PlugIn.ModelCore.UI.WriteLine("      FROSi = {0}, BROSi = {1}.", FROSi, BROSi);
                //PlugIn.ModelCore.UI.WriteLine("      beta = {0:0.00}, theta = {1:0.00}, alpha = {2:0.00}, Travel time = {3:0.000000}.", beta, theta, alpha, 1/r);
                //PlugIn.ModelCore.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 * PlugIn.ModelCore.CellLength / 2.0; //units = minutes
                    return(cost);
                }
                else
                {
                    double rate = 1.0 / r;                            //units = minutes / meter
                    double cost = rate * PlugIn.ModelCore.CellLength; //units = minutes
                    //if (cost < 1)
                    //   PlugIn.ModelCore.UI.WriteLine("Travel time < 1 min");
                    return(cost);
                }
            }
        }
        //---------------------------------------------------------------------

        public static DataRow GenerateDataRow(ISeasonParameters season, IFireRegion fire_region, int sizeBin)
        {

            int weatherRandomizer = PlugIn.WeatherRandomizer;
            string seasonName = season.NameOfSeason.ToString();
            string ecoName = fire_region.Name;
            int weatherBin = 0;

            if(weatherRandomizer == 0)
                weatherBin = sizeBin;
            else
            {
                // First, tally the available bins and assign a probability based on their size
                // (number of records).
                // Bins can only be 1 - 5.

                int minBin = (int) System.Math.Max(1, sizeBin - weatherRandomizer);
                int maxBin = (int) System.Math.Min(5, sizeBin + weatherRandomizer);

                double[] binProbability = new double[maxBin - minBin + 1];
                int[] binCount = new int[maxBin - minBin + 1];
                int binSum = 0;

                for(int bin = minBin; bin <= maxBin; bin++)
                {
                    string selectString = "FWIBin = '" + bin + "' AND Season = '" + seasonName + "' AND Ecoregion = '" + ecoName + "'";
                    DataRow[] rows = PlugIn.WeatherDataTable.Select(selectString);
                    if (rows.Length == 0)
                    {
                        selectString = "FWIBin = '" + bin + "' AND Season = '" + seasonName + "' AND Ecoregion = 'All'";
                        rows = PlugIn.WeatherDataTable.Select(selectString);
                    }

                    int numRecs = rows.Length;

                    binCount[bin - minBin] = numRecs;
                    binSum += numRecs;
                }

                for(int bin = minBin; bin <= maxBin; bin++)
                    binProbability[bin-minBin] = (double) binCount[bin-minBin] / (double) binSum;

                // Now randomly select from the available bins:
                double randomBinNum = Util.Random.GenerateUniform();

                double minProb = 0.0;
                double maxProb = 0.0;

                for(int bin = minBin; bin <= maxBin; bin++)
                {
                    maxProb += binProbability[bin-minBin];
                    if(randomBinNum >= minProb && randomBinNum < maxProb)
                    {
                        weatherBin = bin;
                        break;
                    }
                    else
                    {
                        minProb = binProbability[bin-minBin];
                    }
                }

            }
            if(weatherBin == 0)
                weatherBin = sizeBin;
                //throw new System.ApplicationException("No Weather Bin randomly selected. FireRegion = "+ecoName+", Season = "+seasonName+", sizeBin = "+sizeBin);

            int rowCount = 0;
            int loopCount = 0;
            int firstDir = 0;
            DataRow[] foundRows = null;

            if (Util.Random.GenerateUniform() >= 0.5)
                firstDir = 1;  // Direction (+ or -) to check first if target bin is not available (+1 or -1)
            else
                firstDir = -1;
            while (rowCount == 0)
            {
                string selectString = "FWIBin = '" + weatherBin + "' AND Season = '" + seasonName + "' AND Ecoregion = '" + ecoName + "'";
                foundRows = PlugIn.WeatherDataTable.Select(selectString);
                rowCount = foundRows.Length;

                if (rowCount == 0)
                {
                    selectString = "FWIBin = '" + weatherBin + "' AND Season = '" + seasonName + "' AND Ecoregion = 'All'";
                    foundRows = PlugIn.WeatherDataTable.Select(selectString);
                    rowCount = foundRows.Length;
                }

                if (rowCount == 0)
                {
                    //UI.WriteLine("   weatherBin "+weatherBin+" Not Found.  Using alternate weatherBin.");
                    if (sizeBin == 5)
                        weatherBin = weatherBin - 1;
                    else if (sizeBin == 1)
                        weatherBin = weatherBin + 1;
                    else
                    {
                        if (loopCount == 0)
                            weatherBin = sizeBin + firstDir;
                        else if (loopCount == 1)
                            weatherBin = sizeBin - firstDir;
                        else if (loopCount == 2)
                            weatherBin = sizeBin + (firstDir * 2);
                        else if (loopCount == 3)
                            weatherBin = sizeBin - (firstDir * 2);
                        else if (loopCount == 4)
                            weatherBin = sizeBin + (firstDir * 3);
                        else if (loopCount == 5)
                            weatherBin = sizeBin - (firstDir * 3);
                        else if (loopCount == 6)
                            weatherBin = sizeBin + (firstDir * 4);
                        else
                            weatherBin = sizeBin - (firstDir * 4);
                    }
                    loopCount ++;
                    if (loopCount > 100)
                    {

                        UI.WriteLine("   No Weather Rows Selected");
                        throw new System.ApplicationException("No Weather Row could be selected. Ecoregion = "+ecoName+", Season = "+seasonName+", sizeBin = "+sizeBin);

                    }

                }
            }
            int newRandNum = (int)(Math.Round(Util.Random.GenerateUniform() * (rowCount - 1)));
            DataRow weatherRow = foundRows[newRandNum];

            return weatherRow;
        }
예제 #15
0
        //---------------------------------------------------------------------

        ///<summary>
        /// Run the plug-in at a particular timestep.
        ///</summary>
        public override void Run()
        {
            SiteVars.InitializeFuelType();
            modelCore.UI.WriteLine("   Processing landscape for Fire events ...");

            if (FireRegions.Dataset.Count == 0)
            {
                throw new ApplicationException("Fire region data set is empty.");
            }

            SiteVars.Event.SiteValues                       = null;
            SiteVars.Severity.ActiveSiteValues              = 0;
            SiteVars.Disturbed.ActiveSiteValues             = false;
            SiteVars.TravelTime.ActiveSiteValues            = Double.PositiveInfinity;
            SiteVars.MinNeighborTravelTime.ActiveSiteValues = Double.PositiveInfinity;
            SiteVars.RateOfSpread.ActiveSiteValues          = 0.0;

            foreach (IFireRegion fire_region in FireRegions.Dataset)
            {
                summaryFireRegionEventCount[fire_region.Index] = 0;
            }

            summaryTotalSites = 0;
            summaryEventCount = 0;

            // Update the FireRegions Map as necessary:
            //modelCore.UI.WriteLine("    Dynamic Fire:  Loading Dynamic Fire Regions...");
            foreach (IDynamicFireRegion dyneco in dynamicEcos)
            {
                if (dyneco.Year == modelCore.CurrentTime)
                {
                    modelCore.UI.WriteLine("   Reading in new Fire FireRegions Map {0}.", dyneco.MapName);
                    foreach (IFireRegion fire_region in FireRegions.Dataset)
                    {
                        fire_region.FireRegionSites.Clear(); // = new List<Location>();
                    }
                    FireRegions.ReadMap(dyneco.MapName);     //Sites added to their respective fire_region lists
                }
            }

            //Update the weather table as necessary:
            foreach (IDynamicWeather dynweather in dynamicWeather)
            {
                if (dynweather.Year == modelCore.CurrentTime)
                {
                    modelCore.UI.WriteLine("  Reading in new Weather Table {0}", dynweather.FileName);
                    WeatherDataTable = Weather.ReadWeatherFile(dynweather.FileName, FireRegions.Dataset, seasonParameters);
                }
            }

            // Fill in open types as needed:
            modelCore.UI.WriteLine("   Dynamic Fire:  Filling open types as needed ...");
            foreach (ActiveSite site in modelCore.Landscape)
            {
                IFireRegion fire_region = SiteVars.FireRegion[site];

                if (fire_region == null)
                {
                    throw new System.ApplicationException("Error: SiteVars.FireRegion is empty.");
                }

                //if(SiteVars.CFSFuelType[site] == 0)
                //    throw new System.ApplicationException("Error: SiteVars.CFSFuelType is empty.");


                if (Event.FuelTypeParms[SiteVars.CFSFuelType[site]] == null)
                {
                    modelCore.UI.WriteLine("Error:  SiteVars.CFSFuelType[site]={0}.", SiteVars.CFSFuelType[site]);
                    throw new System.ApplicationException("Error: Event BaseFuel Empty.");
                }

                if (Event.FuelTypeParms[SiteVars.CFSFuelType[site]].BaseFuel == BaseFuelType.NoFuel)
                {
                    if (SiteVars.PercentDeadFir[site] == 0)
                    {
                        SiteVars.CFSFuelType[site] = fire_region.OpenFuelType;
                    }
                }
            }
            if (isDebugEnabled)
            {
                modelCore.UI.WriteLine("Done filling open types");
            }

            modelCore.UI.WriteLine("   Dynamic Fire:  Igniting Fires ...");
            foreach (IFireRegion fire_region in FireRegions.Dataset)
            {
                if (isDebugEnabled)
                {
                    modelCore.UI.WriteLine("   There are {0} site locations in fire region {1}", fire_region.FireRegionSites.Count, fire_region.Name);
                }
                if (fire_region.EcoIgnitionNum > 0)
                {
                    //PoissonDistribution randVar = new PoissonDistribution(RandomNumberGenerator.Singleton);
                    double doubleLambda;
                    int    ignGenerated = 0;

                    if (isDebugEnabled)
                    {
                        modelCore.UI.WriteLine("{0}: EcoIgnitionNum = {1}, computing ignGenerated ...", fire_region.Name, fire_region.EcoIgnitionNum);
                    }
                    if (fire_region.EcoIgnitionNum < 1)
                    {
                        // Adjust ignition probability for multiple years
                        // (The inverse of the probability of NOT having any ignition for the time period.)
                        // P = 1 - (1-Pignition)^timestep
                        //doubleLambda = 1 - System.Math.Pow(1.0 - fire_region.EcoIgnitionNum, Timestep);

                        for (int i = 1; i <= Timestep; i++)
                        {
                            int annualFires = 0;
                            if (modelCore.GenerateUniform() <= fire_region.EcoIgnitionNum)
                            {
                                annualFires = 1;
                            }
                            ignGenerated += annualFires;
                        }
                    }
                    else
                    {
                        doubleLambda = fire_region.EcoIgnitionNum;
                        bool boolLarge = false;

                        // 745 is the upper limit for valid Poisson lambdas.  If greater than
                        // 745, divide by 10 and readjust back up below.
                        if (doubleLambda > 745)
                        {
                            doubleLambda = doubleLambda / 10;
                            boolLarge    = true;
                        }
                        PlugIn.ModelCore.PoissonDistribution.Lambda = doubleLambda;
                        //randVar.Lambda = doubleLambda;

                        for (int i = 1; i <= Timestep; i++)
                        {
                            int annualFires = PlugIn.ModelCore.PoissonDistribution.Next();
                            if (boolLarge)
                            {
                                annualFires = annualFires * 10;  //readjust if necessary.
                            }
                            ignGenerated += annualFires;
                        }
                    }
                    if (isDebugEnabled)
                    {
                        modelCore.UI.WriteLine("  Ignitions generated = {0}; Shuffling {0} cells ...", ignGenerated, fire_region.FireRegionSites.Count);
                    }

                    List <Location> cellsPerFireRegion = new List <Location>(0);
                    foreach (Location location in fire_region.FireRegionSites)
                    {
                        cellsPerFireRegion.Add(location);
                    }

                    cellsPerFireRegion = Shuffle(cellsPerFireRegion);
                    int fireCount = 0;

                    //Try to create poissonNumber of fires in each fire_region.
                    //Fires should only initiate if a fire event has not previously occurred
                    //at that site.

                    foreach (Location siteLocation in cellsPerFireRegion)
                    {
                        Site site = modelCore.Landscape.GetSite(siteLocation);

                        ActiveSite asite = (ActiveSite)site;

                        if (fireCount >= ignGenerated)
                        {
                            continue;                             //exit loop if the required number of fires has occurred.
                        }
                        if (SiteVars.Event[asite] == null)
                        {
                            fireCount++;
                            if (isDebugEnabled)
                            {
                                modelCore.UI.WriteLine("    fireCount = {0}", fireCount);
                            }
                            Event FireEvent = Event.Initiate(asite, Timestep, fireSizeType, bui, seasonParameters, severityCalibrate);
                            if (isDebugEnabled)
                            {
                                modelCore.UI.WriteLine("    fire event {0} started at {1}",
                                                       FireEvent == null ? "not ": "",
                                                       asite.Location);
                            }
                            if (FireEvent != null)
                            {
                                LogEvent(modelCore.CurrentTime, FireEvent);
                                summaryEventCount++;
                                //fireCount++;  //RMS test
                            }
                        }
                    }
                }
            }

            // Track the time of last fire; registered in SiteVars.cs for other extensions to access.
            if (isDebugEnabled)
            {
                modelCore.UI.WriteLine("Assigning TimeOfLastFire site var ...");
            }
            foreach (Site site in modelCore.Landscape.AllSites)
            {
                if (SiteVars.Disturbed[site])
                {
                    SiteVars.TimeOfLastFire[site] = modelCore.CurrentTime;
                }
            }


            //  Write Fire severity map
            string path = MapNames.ReplaceTemplateVars(mapNameTemplate, modelCore.CurrentTime);

            modelCore.UI.WriteLine("   Writing Fire severity map to {0} ...", path);
            using (IOutputRaster <BytePixel> outputRaster = modelCore.CreateRaster <BytePixel>(path, modelCore.Landscape.Dimensions))
            {
                BytePixel pixel = outputRaster.BufferPixel;
                foreach (Site site in modelCore.Landscape.AllSites)
                {
                    if (site.IsActive)
                    {
                        if (SiteVars.Disturbed[site])
                        {
                            pixel.MapCode.Value = (byte)(SiteVars.Severity[site] + 2);
                        }
                        else
                        {
                            pixel.MapCode.Value = 1;
                        }
                    }
                    else
                    {
                        //  Inactive site
                        pixel.MapCode.Value = 0;
                    }
                    outputRaster.WriteBufferPixel();
                }
            }

            path = MapNames.ReplaceTemplateVars("./DFFS-output/TimeOfLastFire-{timestep}.img", modelCore.CurrentTime);
            modelCore.UI.WriteLine("   Writing Travel Time output map to {0} ...", path);
            using (IOutputRaster <ShortPixel> outputRaster = modelCore.CreateRaster <ShortPixel>(path, modelCore.Landscape.Dimensions))
            {
                ShortPixel pixel = outputRaster.BufferPixel;
                foreach (Site site in modelCore.Landscape.AllSites)
                {
                    if (site.IsActive)
                    {
                        pixel.MapCode.Value = (short)(SiteVars.TimeOfLastFire[site]);
                    }
                    else
                    {
                        pixel.MapCode.Value = 0;
                    }
                    outputRaster.WriteBufferPixel();
                }
            }

            WriteSummaryLog(modelCore.CurrentTime);

            if (isDebugEnabled)
            {
                modelCore.UI.WriteLine("Done running extension");
            }
        }
예제 #16
0
        //---------------------------------------------------------------------

        protected override IInputParameters Parse()
        {
            InputVar <string> landisData = new InputVar <string>("LandisData");

            ReadVar(landisData);
            if (landisData.Value.Actual != PlugIn.ExtensionName)
            {
                throw new InputValueException(landisData.Value.String, "The value is not \"{0}\"", PlugIn.ExtensionName);
            }

            InputParameters parameters = new InputParameters();

            InputVar <int> timestep = new InputVar <int>("Timestep");

            ReadVar(timestep);
            parameters.Timestep = timestep.Value;

            //----------------------------------------------------------
            // First, read table of additional parameters for ecoregions
            PlugIn.ModelCore.UI.WriteLine("   Loading FireRegion data...");

            //IEditableFireRegionDataset dataset = new EditableFireRegionDataset();
            List <IFireRegion> dataset = new List <IFireRegion>(0);

            Dictionary <string, int> nameLineNumbers    = new Dictionary <string, int>();
            Dictionary <ushort, int> mapCodeLineNumbers = new Dictionary <ushort, int>();

            InputVar <string> name          = new InputVar <string>("Fire Region Name");
            InputVar <ushort> mapCode       = new InputVar <ushort>("Map Code");
            InputVar <double> meanSize      = new InputVar <double>("Mean Fire Size");
            InputVar <double> maxSize       = new InputVar <double>("Maximum Fire Size");
            InputVar <double> minSize       = new InputVar <double>("Minimum Fire Size");
            InputVar <double> ignitionProb  = new InputVar <double>("Ignition Probability");
            InputVar <int>    fireSpreadAge = new InputVar <int>("Fire Spread Age");

            Dictionary <string, int> lineNumbers               = new Dictionary <string, int>();
            const string             DynamicFireRegionTable    = "DynamicFireRegionTable";
            const string             InitialFireFireRegionsMap = "InitialFireRegionsMap";


            int fireRegionIndex = 0;

            while (!AtEndOfInput && CurrentName != InitialFireFireRegionsMap)
            {
                //IEditableFireRegionParameters ecoparameters = new EditableFireRegionParameters();
                IFireRegion ecoparameters = new FireRegion(fireRegionIndex);

                dataset.Add(ecoparameters);

                StringReader currentLine = new StringReader(CurrentLine);

                int lineNumber;

                ReadValue(name, currentLine);
                if (nameLineNumbers.TryGetValue(name.Value.Actual, out lineNumber))
                {
                    throw new InputValueException(name.Value.String,
                                                  "The name \"{0}\" was previously used on line {1}",
                                                  name.Value.Actual, lineNumber);
                }
                else
                {
                    nameLineNumbers[name.Value.Actual] = LineNumber;
                }
                ecoparameters.Name = name.Value;

                ReadValue(mapCode, currentLine);
                if (mapCodeLineNumbers.TryGetValue(mapCode.Value.Actual, out lineNumber))
                {
                    throw new InputValueException(mapCode.Value.String,
                                                  "The map code {0} was previously used on line {1}",
                                                  mapCode.Value.Actual, lineNumber);
                }
                else
                {
                    mapCodeLineNumbers[mapCode.Value.Actual] = LineNumber;
                }
                ecoparameters.MapCode = mapCode.Value;

                ReadValue(meanSize, currentLine);
                ecoparameters.MeanSize = meanSize.Value;

                ReadValue(minSize, currentLine);
                ecoparameters.MinSize = minSize.Value;

                ReadValue(maxSize, currentLine);
                ecoparameters.MaxSize = maxSize.Value;

                ReadValue(ignitionProb, currentLine);
                ecoparameters.IgnitionProbability = ignitionProb.Value;

                ReadValue(fireSpreadAge, currentLine);
                ecoparameters.FireSpreadAge = fireSpreadAge.Value;

                //UI.WriteLine("Max={0}, Min={1}, Mean={2}, Eco={3}.", ecoparameters.MaxSize, ecoparameters.MinSize, ecoparameters.MeanSize, ecoparameters.Name);
                fireRegionIndex++;

                CheckNoDataAfter("the " + fireSpreadAge.Name + " column",
                                 currentLine);

                GetNextLine();
            }

            FireRegions.Dataset = dataset;


            //----------------------------------------------------------
            // Read in the initial fire ecoregions map:


            InputVar <string> ecoregionsMap = new InputVar <string>("InitialFireRegionsMap");

            ReadVar(ecoregionsMap);
            FireRegions.ReadMap(ecoregionsMap.Value);

            //----------------------------------------------------------
            // Read in the table of dynamic ecoregions:

            const string FuelCurves = "FuelCurveTable";

            if (ReadOptionalName(DynamicFireRegionTable))
            {
                //ReadName(DynamicFireRegionTable);

                InputVar <string> mapName = new InputVar <string>("Dynamic Map Name");
                InputVar <int>    year    = new InputVar <int>("Year to read in new FireRegion Map");

                double previousYear = 0;

                while (!AtEndOfInput && CurrentName != FuelCurves)
                {
                    StringReader currentLine = new StringReader(CurrentLine);

                    IDynamicFireRegion dynEco = new DynamicFireRegion();
                    parameters.DynamicFireRegions.Add(dynEco);

                    ReadValue(year, currentLine);
                    dynEco.Year = year.Value;

                    if (year.Value.Actual <= previousYear)
                    {
                        throw new InputValueException(year.Value.String,
                                                      "Year must > the year ({0}) of the preceeding ecoregion map",
                                                      previousYear);
                    }

                    previousYear = year.Value.Actual;

                    ReadValue(mapName, currentLine);
                    dynEco.MapName = mapName.Value;

                    CheckNoDataAfter("the " + mapName.Name + " column",
                                     currentLine);
                    GetNextLine();
                }
            }

            //-------------------------------------------------------------
            // Second, read table of Fire curve parameters for ecoregions
            ReadName(FuelCurves);

            InputVar <string> fireRegionName = new InputVar <string>("Fire Region Name");
            InputVar <int>    severity1      = new InputVar <int>("Fire Severity1 Age");
            InputVar <int>    severity2      = new InputVar <int>("Fire Severity2 Age");
            InputVar <int>    severity3      = new InputVar <int>("Fire Severity3 Age");
            InputVar <int>    severity4      = new InputVar <int>("Fire Severity4 Age");
            InputVar <int>    severity5      = new InputVar <int>("Fire Severity5 Age");

            lineNumbers.Clear();
            const string WindCurves = "WindCurveTable";

            while (!AtEndOfInput && CurrentName != WindCurves)
            {
                StringReader currentLine = new StringReader(CurrentLine);

                ReadValue(fireRegionName, currentLine);
                IFireRegion ecoregion = GetFireRegion(fireRegionName.Value,
                                                      lineNumbers);

                IFuelCurve fuelCurve = new FuelCurve();

                ReadValue(severity1, currentLine);
                fuelCurve.Severity1 = severity1.Value;

                ReadValue(severity2, currentLine);
                fuelCurve.Severity2 = severity2.Value;

                ReadValue(severity3, currentLine);
                fuelCurve.Severity3 = severity3.Value;

                ReadValue(severity4, currentLine);
                fuelCurve.Severity4 = severity4.Value;

                ReadValue(severity5, currentLine);
                fuelCurve.Severity5 = severity5.Value;

                ecoregion.FuelCurve = fuelCurve; //.GetComplete();

                CheckNoDataAfter("the " + severity1.Name + " column",
                                 currentLine);
                GetNextLine();
            }

            //----------------------------------------------------------
            // Third, read table of wind curve parameters for ecoregions
            ReadName(WindCurves);

            InputVar <int> wseverity1 = new InputVar <int>("Wind Severity1 Age");
            InputVar <int> wseverity2 = new InputVar <int>("Wind Severity2 Age");
            InputVar <int> wseverity3 = new InputVar <int>("Wind Severity3 Age");
            InputVar <int> wseverity4 = new InputVar <int>("Wind Severity4 Age");
            InputVar <int> wseverity5 = new InputVar <int>("Wind Severity5 Age");

            lineNumbers.Clear();
            const string FireDamage = "FireDamageTable";

            while (!AtEndOfInput && CurrentName != FireDamage)
            {
                StringReader currentLine = new StringReader(CurrentLine);

                ReadValue(fireRegionName, currentLine);
                IFireRegion ecoregion = GetFireRegion(fireRegionName.Value,
                                                      lineNumbers);

                IWindCurve windCurve = new WindCurve();

                ReadValue(wseverity5, currentLine);
                windCurve.Severity5 = wseverity5.Value;

                ReadValue(wseverity4, currentLine);
                windCurve.Severity4 = wseverity4.Value;

                ReadValue(wseverity3, currentLine);
                windCurve.Severity3 = wseverity3.Value;

                ReadValue(wseverity2, currentLine);
                windCurve.Severity2 = wseverity2.Value;

                ReadValue(wseverity1, currentLine);
                windCurve.Severity1 = wseverity1.Value;

                ecoregion.WindCurve = windCurve; //.GetComplete();

                CheckNoDataAfter("the " + wseverity1.Name + " column",
                                 currentLine);
                GetNextLine();
            }

            //-------------------------------------------------------------------
            //  Read table of Fire Damage classes.
            //  Damages are in increasing order.
            ReadName(FireDamage);

            InputVar <Percentage> maxAge = new InputVar <Percentage>("Max Survival Age");
            InputVar <int>        severTolerDifference = new InputVar <int>("Severity Tolerance Diff");

            const string MapNames       = "MapNames";
            int          previousNumber = -4;
            double       previousMaxAge = 0.0;

            while (!AtEndOfInput && CurrentName != MapNames &&
                   previousNumber != 4)
            {
                StringReader currentLine = new StringReader(CurrentLine);

                IDamageTable damage = new DamageTable();
                parameters.FireDamages.Add(damage);

                ReadValue(maxAge, currentLine);
                damage.MaxAge = maxAge.Value;
                if (maxAge.Value.Actual <= 0)
                {
                    //  Maximum age for damage must be > 0%
                    throw new InputValueException(maxAge.Value.String,
                                                  "Must be > 0% for the all damage classes");
                }
                if (maxAge.Value.Actual > 1)
                {
                    //  Maximum age for damage must be <= 100%
                    throw new InputValueException(maxAge.Value.String,
                                                  "Must be <= 100% for the all damage classes");
                }
                //  Maximum age for every damage must be >
                //  maximum age of previous damage.
                if (maxAge.Value.Actual <= previousMaxAge)
                {
                    throw new InputValueException(maxAge.Value.String,
                                                  "MaxAge must > the maximum age ({0}) of the preceeding damage class",
                                                  previousMaxAge);
                }

                previousMaxAge = (double)maxAge.Value.Actual;

                ReadValue(severTolerDifference, currentLine);
                damage.SeverTolerDifference = severTolerDifference.Value;

                //Check that the current damage number is > than
                //the previous number (numbers are must be in increasing
                //order).
                if (severTolerDifference.Value.Actual <= previousNumber)
                {
                    throw new InputValueException(severTolerDifference.Value.String,
                                                  "Expected the damage number {0} to be greater than previous {1}",
                                                  damage.SeverTolerDifference, previousNumber);
                }
                if (severTolerDifference.Value.Actual > 4)
                {
                    throw new InputValueException(severTolerDifference.Value.String,
                                                  "Expected the damage number {0} to be less than 5",
                                                  damage.SeverTolerDifference);
                }

                previousNumber = severTolerDifference.Value.Actual;

                CheckNoDataAfter("the " + severTolerDifference.Name + " column",
                                 currentLine);
                GetNextLine();
            }

            if (parameters.FireDamages.Count == 0)
            {
                throw NewParseException("No damage classes defined.");
            }

            InputVar <string> mapNames = new InputVar <string>(MapNames);

            ReadVar(mapNames);
            parameters.MapNamesTemplate = mapNames.Value;

            InputVar <string> logFile = new InputVar <string>("LogFile");

            ReadVar(logFile);
            parameters.LogFileName = logFile.Value;

            InputVar <string> summaryLogFile = new InputVar <string>("SummaryLogFile");

            ReadVar(summaryLogFile);
            parameters.SummaryLogFileName = summaryLogFile.Value;

            CheckNoDataAfter(string.Format("the {0} parameter", summaryLogFile.Name));

            return(parameters); //.GetComplete();
        }
        //---------------------------------------------------------------------

        public static int GenerateFMC(ISeasonParameters season, IFireRegion fire_region)
        {

            int FMC = 0;
            if (season.NameOfSeason == SeasonName.Spring)
            {
                if (Util.Random.GenerateUniform() < fire_region.SpringFMCHiProp)
                    FMC = fire_region.SpringFMCHi;
                else
                    FMC = fire_region.SpringFMCLo;
            }
            if (season.NameOfSeason == SeasonName.Summer)
            {
                if (Util.Random.GenerateUniform() < fire_region.SummerFMCHiProp)
                    FMC = fire_region.SummerFMCHi;
                else
                    FMC = fire_region.SummerFMCLo;
            }
            if (season.NameOfSeason == SeasonName.Fall)
            {
                if (Util.Random.GenerateUniform() < fire_region.FallFMCHiProp)
                    FMC = fire_region.FallFMCHi;
                else
                    FMC = fire_region.FallFMCLo;
            }
            return FMC;
        }
예제 #18
0
        //---------------------------------------------------------------------

        public override void Initialize()
        {
            Timestep          = parameters.Timestep;
            fireSizeType      = parameters.FireSizeType;
            bui               = parameters.BUI;
            mapNameTemplate   = parameters.MapNamesTemplate;
            dynamicWeather    = parameters.DynamicWeather;
            severityCalibrate = parameters.SeverityCalibrate;


            modelCore.UI.WriteLine("   Initializing Fire Events...");
            Event.Initialize(parameters.SeasonParameters, parameters.FuelTypeParameters, parameters.FireDamages);


            seasonParameters = parameters.SeasonParameters;

            dynamicEcos = parameters.DynamicFireRegions;

            summaryFireRegionEventCount = new int[FireRegions.Dataset.Count];
            ecoregionSitesCount         = new int[FireRegions.Dataset.Count];

            //foreach (IFireRegion fire_region in FireRegions.Dataset)
            //modelCore.UI.WriteLine("   FireSize={0}, SD={1}", fire_region.MeanSize, fire_region.StandardDeviation);

            // Count the number of sites per fire_region:
            foreach (Site site in modelCore.Landscape)
            {
                if (site.IsActive)
                {
                    IFireRegion fire_region = SiteVars.FireRegion[site];
                    ecoregionSitesCount[fire_region.Index]++;
                }
            }

            modelCore.UI.WriteLine("   Opening and Initializing Fire log files \"{0}\" and \"{1}\"...", parameters.LogFileName, parameters.SummaryLogFileName);

            List <string> colnames = new List <string>();

            foreach (IFireRegion fire_region in FireRegions.Dataset)
            {
                colnames.Add(fire_region.MapCode.ToString());
            }
            ExtensionMetadata.ColumnNames = colnames;

            MetadataHandler.InitializeMetadata(mapNameTemplate, parameters.LogFileName, parameters.SummaryLogFileName);



            summaryLog.Clear();
            SummaryLog sl = new SummaryLog();

            sl.Time             = 0;
            sl.TotalSitesBurned = 0;
            sl.NumberFires      = 0;
            sl.EcoMaps_         = new double[FireRegions.Dataset.Count];
            int i = 0;

            foreach (IFireRegion fire_region in FireRegions.Dataset)
            {
                sl.EcoMaps_[i] = ecoregionSitesCount[fire_region.Index];
                i = i + 1;
            }
            summaryLog.AddObject(sl);
            summaryLog.WriteToFile();

            if (isDebugEnabled)
            {
                modelCore.UI.WriteLine("Initialization done");
            }
        }
예제 #19
0
        //---------------------------------------------------------------------

        public static DataRow GenerateDataRow(ISeasonParameters season, IFireRegion fire_region, int sizeBin)
        {
            int    weatherRandomizer = PlugIn.WeatherRandomizer;
            string seasonName        = season.NameOfSeason.ToString();
            string ecoName           = fire_region.Name;
            int    weatherBin        = 0;

            if (weatherRandomizer == 0)
            {
                weatherBin = sizeBin;
            }
            else
            {
                // First, tally the available bins and assign a probability based on their size
                // (number of records).
                // Bins can only be 1 - 5.

                int minBin = (int)System.Math.Max(1, sizeBin - weatherRandomizer);
                int maxBin = (int)System.Math.Min(5, sizeBin + weatherRandomizer);

                double[] binProbability = new double[maxBin - minBin + 1];
                int[]    binCount       = new int[maxBin - minBin + 1];
                int      binSum         = 0;

                for (int bin = minBin; bin <= maxBin; bin++)
                {
                    string    selectString = "FWIBin = '" + bin + "' AND Season = '" + seasonName + "' AND Ecoregion = '" + ecoName + "'";
                    DataRow[] rows         = PlugIn.WeatherDataTable.Select(selectString);
                    if (rows.Length == 0)
                    {
                        selectString = "FWIBin = '" + bin + "' AND Season = '" + seasonName + "' AND Ecoregion = 'All'";
                        rows         = PlugIn.WeatherDataTable.Select(selectString);
                    }

                    int numRecs = rows.Length;

                    binCount[bin - minBin] = numRecs;
                    binSum += numRecs;
                }

                for (int bin = minBin; bin <= maxBin; bin++)
                {
                    binProbability[bin - minBin] = (double)binCount[bin - minBin] / (double)binSum;
                }

                // Now randomly select from the available bins:
                double randomBinNum = PlugIn.ModelCore.GenerateUniform();

                double minProb = 0.0;
                double maxProb = 0.0;

                for (int bin = minBin; bin <= maxBin; bin++)
                {
                    maxProb += binProbability[bin - minBin];
                    if (randomBinNum >= minProb && randomBinNum < maxProb)
                    {
                        weatherBin = bin;
                        break;
                    }
                    else
                    {
                        minProb = binProbability[bin - minBin];
                    }
                }
            }
            if (weatherBin == 0)
            {
                weatherBin = sizeBin;
            }
            //throw new System.ApplicationException("No Weather Bin randomly selected. FireRegion = "+ecoName+", Season = "+seasonName+", sizeBin = "+sizeBin);

            int rowCount  = 0;
            int loopCount = 0;
            int firstDir  = 0;

            DataRow[] foundRows = null;

            if (PlugIn.ModelCore.GenerateUniform() >= 0.5)
            {
                firstDir = 1;  // Direction (+ or -) to check first if target bin is not available (+1 or -1)
            }
            else
            {
                firstDir = -1;
            }
            while (rowCount == 0)
            {
                string selectString = "FWIBin = '" + weatherBin + "' AND Season = '" + seasonName + "' AND Ecoregion = '" + ecoName + "'";
                foundRows = PlugIn.WeatherDataTable.Select(selectString);
                rowCount  = foundRows.Length;

                if (rowCount == 0)
                {
                    selectString = "FWIBin = '" + weatherBin + "' AND Season = '" + seasonName + "' AND Ecoregion = 'All'";
                    foundRows    = PlugIn.WeatherDataTable.Select(selectString);
                    rowCount     = foundRows.Length;
                }

                if (rowCount == 0)
                {
                    //PlugIn.ModelCore.UI.WriteLine("   weatherBin "+weatherBin+" Not Found.  Using alternate weatherBin.");
                    if (sizeBin == 5)
                    {
                        weatherBin = weatherBin - 1;
                    }
                    else if (sizeBin == 1)
                    {
                        weatherBin = weatherBin + 1;
                    }
                    else
                    {
                        if (loopCount == 0)
                        {
                            weatherBin = sizeBin + firstDir;
                        }
                        else if (loopCount == 1)
                        {
                            weatherBin = sizeBin - firstDir;
                        }
                        else if (loopCount == 2)
                        {
                            weatherBin = sizeBin + (firstDir * 2);
                        }
                        else if (loopCount == 3)
                        {
                            weatherBin = sizeBin - (firstDir * 2);
                        }
                        else if (loopCount == 4)
                        {
                            weatherBin = sizeBin + (firstDir * 3);
                        }
                        else if (loopCount == 5)
                        {
                            weatherBin = sizeBin - (firstDir * 3);
                        }
                        else if (loopCount == 6)
                        {
                            weatherBin = sizeBin + (firstDir * 4);
                        }
                        else
                        {
                            weatherBin = sizeBin - (firstDir * 4);
                        }
                    }
                    loopCount++;
                    if (loopCount > 100)
                    {
                        PlugIn.ModelCore.UI.WriteLine("   No Weather Rows Selected");
                        throw new System.ApplicationException("No Weather Row could be selected. Ecoregion = " + ecoName + ", Season = " + seasonName + ", sizeBin = " + sizeBin);
                    }
                }
            }
            int     newRandNum = (int)(Math.Round(PlugIn.ModelCore.GenerateUniform() * (rowCount - 1)));
            DataRow weatherRow = foundRows[newRandNum];

            return(weatherRow);
        }