//--------------------------------------------------------------------- public override void LoadParameters(string dataFile, ICore mCore) { modelCore = mCore; SiteVars.Initialize(); InputParameterParser parser = new InputParameterParser(); Parameters = Landis.Data.Load <IInputParameters>(dataFile, parser); }
//--------------------------------------------------------------------- ///<summary> /// Run the plug-in at a particular timestep. ///</summary> public override void Run() { if (PlugIn.ModelCore.CurrentTime > 0) { SiteVars.InitializeDisturbances(); } SiteVars.Disturbed.ActiveSiteValues = false; SiteVars.Intensity.ActiveSiteValues = 0; SiteVars.SpreadProbability.ActiveSiteValues = 0.0; SiteVars.DayOfFire.ActiveSiteValues = 0; SiteVars.TypeOfIginition.ActiveSiteValues = 0; SiteVars.SpecialDeadWood.ActiveSiteValues = 0; SiteVars.EventID.ActiveSiteValues = 0; foreach (IDynamicIgnitionMap dynamicIgnitions in dynamicRxIgns) { if (dynamicIgnitions.Year == PlugIn.modelCore.CurrentTime) { PlugIn.ModelCore.UI.WriteLine(" Reading in new Fire Regions Map {0}.", dynamicIgnitions.MapName); MapUtility.ReadMap(dynamicIgnitions.MapName, SiteVars.RxFireWeight); } } AnnualClimate_Daily weatherData = null; totalBurnedSites = new int[3]; numberOfFire = new int[3]; totalBiomassMortality = new int[3]; numCellsSeverity1 = 0; numCellsSeverity2 = 0; numCellsSeverity3 = 0; modelCore.UI.WriteLine(" Processing landscape for Fire events ..."); ActualYear = 0; try { ActualYear = (PlugIn.ModelCore.CurrentTime - 1) + Climate.Future_AllData.First().Key; } catch { throw new UninitializedClimateData(string.Format("Could not initilize the actual year {0} from climate data", ActualYear)); } // Get the active sites from the landscape and shuffle them // Sites are weighted for ignition in the Shuffle method, based on the respective inputs maps. List <ActiveSite> shuffledLightningFireSites = Shuffle(SiteVars.LightningFireWeight); List <ActiveSite> shuffledRxFireSites = Shuffle(SiteVars.RxFireWeight); List <ActiveSite> shuffledAccidentalFireSites = Shuffle(SiteVars.AccidentalFireWeight); int numRxFires = Parameters.NumberRxAnnualFires; for (int day = 0; day < DaysPerYear; ++day) { double ecoregionAverageFireWeatherIndex = 0.0; double ecoregionNumSites = 0.0; // number of fires get initilized to 0 every timestep foreach (IEcoregion ecoregion in PlugIn.ModelCore.Ecoregions) { if (ecoregion.Active) { if (sitesPerEcoregions.ContainsKey(ecoregion.Index)) { ecoregionNumSites = (double)sitesPerEcoregions[ecoregion.Index]; } try { weatherData = Climate.Future_DailyData[ActualYear][ecoregion.Index]; } catch { throw new UninitializedClimateData(string.Format("Climate data could not be found in Run(). Year: {0} in ecoregion: {1}", ActualYear, ecoregion.Name)); } try { ecoregionAverageFireWeatherIndex += weatherData.DailyFireWeatherIndex[day] * ecoregionNumSites; } catch { throw new UninitializedClimateData(string.Format("Fire Weather Index could not be found in Run(). Year: {0}, day: {1}, ecoregion: {2}, NumSites={3}", ActualYear, day, ecoregion.Name, sitesPerEcoregions[ecoregion.Index])); } } } double landscapeAverageFireWeatherIndex = ecoregionAverageFireWeatherIndex / (double)modelCore.Landscape.ActiveSiteCount; //modelCore.UI.WriteLine(" Processing landscape for Fire events. Day={0}, FWI={1}", day, landscapeAverageFireWeatherIndex); // FWI must be > .10 if (landscapeAverageFireWeatherIndex >= 10.0) { // Ignite Accidental Fires. if (shuffledAccidentalFireSites.Count > 0) { int numLFires = NumberOfIgnitions(Ignition.Accidental, landscapeAverageFireWeatherIndex); for (int i = 0; i < numLFires; ++i) { Ignite(Ignition.Accidental, shuffledAccidentalFireSites, day, landscapeAverageFireWeatherIndex); LogIgnition(ModelCore.CurrentTime, landscapeAverageFireWeatherIndex, Ignition.Accidental.ToString(), numLFires, day); } } // Ignite Lightning Fires if (shuffledLightningFireSites.Count > 0) { int numAFires = NumberOfIgnitions(Ignition.Lightning, landscapeAverageFireWeatherIndex); for (int i = 0; i < numAFires; ++i) { Ignite(Ignition.Lightning, shuffledLightningFireSites, day, landscapeAverageFireWeatherIndex); LogIgnition(ModelCore.CurrentTime, landscapeAverageFireWeatherIndex, Ignition.Lightning.ToString(), numAFires, day); } } // Ignite a single Rx fire per day if (shuffledRxFireSites.Count > 0 && numRxFires > 0 && landscapeAverageFireWeatherIndex > Parameters.RxMinFireWeatherIndex && landscapeAverageFireWeatherIndex < Parameters.RxMaxFireWeatherIndex && weatherData.DailyWindSpeed[day] < Parameters.RxMaxWindSpeed && day >= Parameters.FirstDayRxFire) { Ignite(Ignition.Rx, shuffledRxFireSites, day, landscapeAverageFireWeatherIndex); LogIgnition(ModelCore.CurrentTime, landscapeAverageFireWeatherIndex, Ignition.Rx.ToString(), 1, day); numRxFires--; } } } WriteMaps(PlugIn.ModelCore.CurrentTime); WriteSummaryLog(modelCore.CurrentTime); if (isDebugEnabled) { modelCore.UI.WriteLine("Done running extension"); } }
//--------------------------------------------------------------------- ///<summary> /// Run the plug-in at a particular timestep. ///</summary> public override void Run() { if (PlugIn.ModelCore.CurrentTime > 0) { SiteVars.InitializeDisturbances(); } SiteVars.Disturbed.ActiveSiteValues = false; SiteVars.Intensity.ActiveSiteValues = 0; SiteVars.SpreadProbability.ActiveSiteValues = 0.0; SiteVars.DayOfFire.ActiveSiteValues = 0; SiteVars.TypeOfIginition.ActiveSiteValues = 0; SiteVars.SpecialDeadWood.ActiveSiteValues = 0; SiteVars.EventID.ActiveSiteValues = 0; foreach (IDynamicIgnitionMap dynamicRxIgnitions in dynamicRxIgns) { if (dynamicRxIgnitions.Year == PlugIn.modelCore.CurrentTime) { PlugIn.ModelCore.UI.WriteLine(" Reading in new Ignitions Maps {0}.", dynamicRxIgnitions.MapName); MapUtility.ReadMap(dynamicRxIgnitions.MapName, SiteVars.RxFireWeight); double totalWeight = 0.0; activeRxSites = PreShuffle(SiteVars.RxFireWeight, out totalWeight); rxTotalWeight = totalWeight; } } foreach (IDynamicIgnitionMap dynamicLxIgns in dynamicLightningIgns) { if (dynamicLxIgns.Year == PlugIn.modelCore.CurrentTime) { PlugIn.ModelCore.UI.WriteLine(" Reading in new Ignitions Maps {0}.", dynamicLxIgns.MapName); MapUtility.ReadMap(dynamicLxIgns.MapName, SiteVars.LightningFireWeight); double totalWeight = 0.0; activeLightningSites = PreShuffle(SiteVars.LightningFireWeight, out totalWeight); lightningTotalWeight = totalWeight; } } foreach (IDynamicIgnitionMap dynamicAxIgns in dynamicAccidentalIgns) { if (dynamicAxIgns.Year == PlugIn.modelCore.CurrentTime) { PlugIn.ModelCore.UI.WriteLine(" Reading in new Ignitions Maps {0}.", dynamicAxIgns.MapName); MapUtility.ReadMap(dynamicAxIgns.MapName, SiteVars.AccidentalFireWeight); double totalWeight = 0.0; activeAccidentalSites = PreShuffle(SiteVars.AccidentalFireWeight, out totalWeight); accidentalTotalWeight = totalWeight; } } foreach (IDynamicSuppressionMap dynamicSuppressMaps in dynamicSuppress) { if (dynamicSuppressMaps.Year == PlugIn.modelCore.CurrentTime) { PlugIn.ModelCore.UI.WriteLine(" Reading in new Fire Suppression Map {0}.", dynamicSuppressMaps.MapName); MapUtility.ReadMap(dynamicSuppressMaps.MapName, SiteVars.AccidentalSuppressionIndex); } } AnnualClimate_Daily weatherData = null; dNBR = new int[3]; totalBurnedSites = new int[3]; numberOfFire = new int[3]; totalBiomassMortality = new int[3]; modelCore.UI.WriteLine(" Processing landscape for Fire events ..."); ActualYear = 0; try { ActualYear = (PlugIn.ModelCore.CurrentTime - 1) + Climate.Future_AllData.First().Key; } catch { throw new UninitializedClimateData(string.Format("Could not initilize the actual year {0} from climate data", ActualYear)); } // modelCore.UI.WriteLine(" Next, shuffle ignition sites..."); // Get the active sites from the landscape and shuffle them // Sites are weighted for ignition in the Ether.WeightedSelector Shuffle method, based on the respective inputs maps. int numSites = 0; weightedRxSites = PreShuffleEther(SiteVars.RxFireWeight, out numSites); int numRxSites = numSites; //modelCore.UI.WriteLine(" Number Rx sites = {0}", numRxSites); weightedAccidentalSites = PreShuffleEther(SiteVars.AccidentalFireWeight, out numSites); int numAccidentalSites = numSites; weightedLightningSites = PreShuffleEther(SiteVars.LightningFireWeight, out numSites); int numLightningSites = numSites; //modelCore.UI.WriteLine(" Next, loop through each day to start fires..."); int numAnnualRxFires = Parameters.RxNumberAnnualFires; for (int day = 0; day < DaysPerYear; ++day) { double landscapeAverageFireWeatherIndex = 0.0; double landscapeAverageTemperature = 0.0; double landscapeAverageRelHumidity = 0.0; // number of fires get initilized to 0 every timestep foreach (IEcoregion climateRegion in PlugIn.ModelCore.Ecoregions) { if (sitesPerClimateRegion.ContainsKey(climateRegion.Index)) { double climateRegionFractionSites = (double)fractionSitesPerClimateRegion[climateRegion.Index]; try { weatherData = Climate.Future_DailyData[ActualYear][climateRegion.Index]; } catch { throw new UninitializedClimateData(string.Format("Climate data could not be found in Run(). Year: {0} in ecoregion: {1}", ActualYear, climateRegion.Name)); } try { // modelCore.UI.WriteLine(" Fire Weather Check Daily={0}, Average={1}", weatherData.DailyFireWeatherIndex[day], landscapeAverageFireWeatherIndex); landscapeAverageFireWeatherIndex += weatherData.DailyFireWeatherIndex[day] * climateRegionFractionSites; landscapeAverageTemperature += weatherData.DailyMaxTemp[day] * climateRegionFractionSites; if (weatherData.DailyMinRH[day] == -99.0) { double relativeHumidity = AnnualClimate_Daily.ConvertSHtoRH(weatherData.DailySpecificHumidity[day], weatherData.DailyTemp[day]); if (relativeHumidity > 100) { relativeHumidity = 100.0; } landscapeAverageRelHumidity += relativeHumidity * climateRegionFractionSites; } else { landscapeAverageRelHumidity += weatherData.DailyMinRH[day] * climateRegionFractionSites; } //landscapeAverageRelHumidity += weatherData.DailyMinRH[day] * climateRegionFractionSites; // modelCore.UI.WriteLine(" Fire Weather Check Daily={0}, Average={1}", weatherData.DailyFireWeatherIndex[day], landscapeAverageFireWeatherIndex); } catch { throw new UninitializedClimateData(string.Format("Fire Weather Index could not be found in Run(). Year: {0}, day: {1}, climate region: {2}, NumSites={3}", ActualYear, day, climateRegion.Name, sitesPerClimateRegion[climateRegion.Index])); } if (Climate.Future_DailyData[PlugIn.ActualYear][climateRegion.Index].DailyRH[day] < 0) { string mesg = string.Format("Relative Humidity not included in the climate data. (RH is required to calculate FWI.) Year: {0}, day: {1}, climate region: {2}, NumSites={3}", ActualYear, day, climateRegion.Name, sitesPerClimateRegion[climateRegion.Index]); throw new System.ApplicationException(mesg); } } } //PlugIn.ModelCore.UI.WriteLine(" Generating accidental fires..."); if (numAccidentalSites > 0) { bool fire = false; int maxNumAccidentalFires = NumberOfIgnitions(IgnitionType.Accidental, landscapeAverageFireWeatherIndex); int logMaxNumAccidentalFires = maxNumAccidentalFires; int actualNumAccidentalFires = 0; while (maxNumAccidentalFires > 0) { //Ignite(Ignition.Accidental, shuffledAccidentalFireSites, day, landscapeAverageFireWeatherIndex); fire = Ignite(IgnitionType.Accidental, weightedAccidentalSites.Select(), day, landscapeAverageFireWeatherIndex); if (fire) { maxNumAccidentalFires--; actualNumAccidentalFires++; } } if (fire) { LogIgnition(ModelCore.CurrentTime, landscapeAverageFireWeatherIndex, IgnitionType.Accidental.ToString(), logMaxNumAccidentalFires, actualNumAccidentalFires, day); } } /// Removed FWI threshold ZR 11-12-20 //PlugIn.ModelCore.UI.WriteLine(" Generating lightning fires..."); if (numLightningSites > 0) { bool fire = false; int maxNumLightningFires = NumberOfIgnitions(IgnitionType.Lightning, landscapeAverageFireWeatherIndex); int logMaxNumLightningFires = maxNumLightningFires; int actualNumLightningFires = 0; while (maxNumLightningFires > 0) { //Ignite(Ignition.Lightning, shuffledLightningFireSites, day, landscapeAverageFireWeatherIndex); fire = Ignite(IgnitionType.Lightning, weightedLightningSites.Select(), day, landscapeAverageFireWeatherIndex); if (fire) { maxNumLightningFires--; actualNumLightningFires++; } } if (fire) { LogIgnition(ModelCore.CurrentTime, landscapeAverageFireWeatherIndex, IgnitionType.Lightning.ToString(), logMaxNumLightningFires, actualNumLightningFires, day); } } // Ignite a single Rx fire per day //PlugIn.ModelCore.UI.WriteLine(" Generating prescribed fires..."); if (numRxSites > 0 && numAnnualRxFires > 0 && landscapeAverageFireWeatherIndex > Parameters.RxMinFireWeatherIndex && landscapeAverageFireWeatherIndex < Parameters.RxMaxFireWeatherIndex && landscapeAverageTemperature < Parameters.RxMaxTemperature && landscapeAverageRelHumidity > Parameters.RxMinRelativeHumidity && weatherData.DailyWindSpeed[day] < Parameters.RxMaxWindSpeed && day >= Parameters.RxFirstDayFire && day < Parameters.RxLastDayFire) { int maxNumDailyRxFires = Parameters.RxNumberDailyFires; int actualNumRxFires = 0; bool fire = false; int maxIgnitionFailures = 20; int actualIgnitionFailures = 0; while (numAnnualRxFires > 0 && maxNumDailyRxFires > 0) { ActiveSite site = weightedRxSites.Select(); if (SiteVars.Disturbed[site]) { actualIgnitionFailures++; } if (actualIgnitionFailures > maxIgnitionFailures) { break; } //PlugIn.ModelCore.UI.WriteLine(" Ignite prescribed fires..."); fire = Ignite(IgnitionType.Rx, site, day, landscapeAverageFireWeatherIndex); if (fire) { numAnnualRxFires--; maxNumDailyRxFires--; actualNumRxFires++; } } if (fire) { LogIgnition(ModelCore.CurrentTime, landscapeAverageFireWeatherIndex, IgnitionType.Rx.ToString(), Parameters.RxNumberDailyFires, actualNumRxFires, day); } } } modelCore.UI.WriteLine(" Fire for the year completed. Next, write fire maps and summary fire files. ..."); WriteMaps(PlugIn.ModelCore.CurrentTime); WriteSummaryLog(PlugIn.ModelCore.CurrentTime); if (isDebugEnabled) { modelCore.UI.WriteLine("Done running extension"); } }