//--------------------------------------------------------------------- /// <summary> /// Computes the rank for a stand. /// </summary> protected override double ComputeRank(Stand stand, int i) { double standEconImportance = 0.0; //Model.Core.UI.WriteLine("Base Harvest: EconomicRank.cs: ComputeRank: there are {0} sites in this stand.", stand.SiteCount); foreach (ActiveSite site in stand) { double siteEconImportance = 0.0; foreach (ISpeciesCohorts speciesCohorts in SiteVars.Cohorts[site]) { EconomicRankParameters rankingParameters = rankTable[speciesCohorts.Species]; foreach (ICohort cohort in speciesCohorts) { if (rankingParameters.MinimumAge > 0 && rankingParameters.MinimumAge <= cohort.Age) { siteEconImportance += (double)rankingParameters.Rank / rankingParameters.MinimumAge * cohort.Age; } } } standEconImportance += siteEconImportance; } standEconImportance /= stand.SiteCount; return(standEconImportance); }
//--------------------------------------------------------------------- /// <summary> /// Harvests the highest-ranked stand which hasn't been harvested yet /// during the current timestep. /// </summary> public virtual void HarvestHighestRankedStand() { //Model.Core.UI.WriteLine(" Standard Harvest Highest Ranked Stand."); //get the highest ranked unharvested stand Stand stand = rankings[highestUnharvestedStand].Stand; if (rankings[highestUnharvestedStand].Rank > 0) { if (!stand.IsSetAside) { // set the global current rank so it can be taken by // Prescription.Harvest and applied // to this harvest event currentRank = rankings[highestUnharvestedStand].Rank; prescription.Harvest(stand); this.HighestRankedStand = stand; double harvestedArea = stand.LastAreaHarvested; areaHarvested += harvestedArea; //if all (or more ??) is harvested, set areaRemainingToHarvest to 0 if (harvestedArea >= areaRemainingToHarvest) { areaRemainingToHarvest = 0; } else { areaRemainingToHarvest -= harvestedArea; } areaRemainingRatio = areaRemainingToHarvest / areaToHarvest; } } }
//--------------------------------------------------------------------- /// <summary> /// Adds a stand to the management area. /// </summary> public void Add(Stand stand) { stands.Add(stand); area += stand.ActiveArea; //Model.Core.UI.WriteLine("ma {0} now has area {1}", mapCode, area); stand.ManagementArea = this; }
//--------------------------------------------------------------------- /// <summary> /// Harvests a stand (and possibly its neighbors) according to the /// repeat-harvest's site-selection method. /// </summary> /// <returns> /// The area that was harvested (units: hectares). /// </returns> public override void Harvest(Stand stand) { if (stand.IsSetAside) { CohortCutter = additionalCohortCutter; SpeciesToPlant = additionalSpeciesToPlant; // //if(this.SiteSelectionMethod.GetType() == Landis.Extension.BiomassHarvest.PartialStandSpreading) // SiteSelector = BiomassHarvest.WrapSiteSelector(SiteSelector); this.IsSingleRepeatStep = true; } else { CohortCutter = initialCohortCutter; SpeciesToPlant = initialSpeciesToPlant; } base.Harvest(stand); // Unmark specific cells that were set aside if (stand.IsSetAside) { stand.ClearSetAsideSites(this.Name); this.IsSingleRepeatStep = false; } return; }
//--------------------------------------------------------------------- bool IRequirement.MetBy(Stand stand) { //Model.Core.UI.WriteLine("checking stand {0}", stand.MapCode); //get list of neighboring stands (must cast from enum) List <Stand> neighbor_stands = new List <Stand>(); neighbor_stands = (List <Stand>)stand.Neighbors; //add ma_neighbors to this list as well, to check with all the neighboring stands that are in a different management area foreach (Stand n_stand in stand.MaNeighbors) { neighbor_stands.Add(n_stand); } //loop through neighbor stands (including ma_neighbors), if one is too young then return false foreach (Stand n_stand in neighbor_stands) { //if n_stand is too young, return false (breaking out of loop as soon as one neighbor fails) if (type == "StandAge") { if (n_stand.Age < time) { return(false); } } //if type was mintimesincelastharvest else { if (n_stand.TimeSinceLastHarvested < time) { //Model.Core.UI.WriteLine("stand {0} NOT ranked.", stand.MapCode); return(false); } } } return(true); }
//--------------------------------------------------------------------- /// <summary> /// Computes the rank for a stand. /// </summary> protected override double ComputeRank(Stand stand, int i) { SiteVars.GetExternalVars(); //if (SiteVars.CFSFuelType == null) // throw new System.ApplicationException("Error: CFS Fuel Type NOT Initialized. Fuel extension MUST be active."); double standFireRisk = 0.0; //Model.Core.UI.WriteLine("Base Harvest: EconomicRank.cs: ComputeRank: there are {0} sites in this stand.", stand.SiteCount); foreach (ActiveSite site in stand) { //double siteFireRisk = 0.0; int fuelType = SiteVars.CFSFuelType[site]; //Model.Core.UI.WriteLine("Base Harvest: ComputeRank: FuelType = {0}.", fuelType); FireRiskParameters rankingParameters = rankTable[fuelType]; standFireRisk = (double)rankingParameters.Rank; //foreach (ISpeciesCohorts speciesCohorts in SiteVars.Cohorts[site]) //{ // FireRiskParameters rankingParameters = rankTable[speciesCohorts.Species]; // foreach (ICohort cohort in speciesCohorts) { // if (rankingParameters.MinimumAge > 0 && // rankingParameters.MinimumAge <= cohort.Age) // siteEconImportance += (double) rankingParameters.Rank / rankingParameters.MinimumAge * cohort.Age; // } //} //standEconImportance += siteEconImportance; } standFireRisk /= stand.SiteCount; return(standFireRisk); }
/// <summary> /// Reads the input map of stands. /// </summary> /// <param name="path"> /// Path to the map. /// </param> public static void ReadMap(string path) { Stand stand; Dictionary <uint, Stand> stands = new Dictionary <uint, Stand>(); IInputRaster <UIntPixel> map; try { map = Model.Core.OpenRaster <UIntPixel>(path); } catch (FileNotFoundException) { string mesg = string.Format("Error: The file {0} does not exist", path); throw new System.ApplicationException(mesg); } if (map.Dimensions != Model.Core.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) { UIntPixel pixel = map.BufferPixel; foreach (Site site in Model.Core.Landscape.AllSites) { map.ReadBufferPixel(); uint mapCode = pixel.MapCode.Value; if (site.IsActive && SiteVars.ManagementArea[site] != null) { if (stands.TryGetValue(mapCode, out stand)) { //if the stand is already in the dictionary, check if it is in the same management area. //if it's not in the same MA, throw exception. if (SiteVars.ManagementArea[site] != stand.ManagementArea) { string mesg = string.Format("Stand {0} is in management areas {1} and {2}", stand.MapCode, stand.ManagementArea.MapCode, SiteVars.ManagementArea[site].MapCode); throw new System.ApplicationException(mesg); } } //valid site location which has not been keyed by the dictionary. else { //assign stand (trygetvalue set it to null when it wasn't found in the dictionary) stand = new Stand(mapCode); //add this stand to the correct management area (pointed to by the site) SiteVars.ManagementArea[site].Add(stand); stands[mapCode] = stand; } //add this site to this stand stand.Add((ActiveSite)site); } } } }
//--------------------------------------------------------------------- protected void AddMaNeighbor(Stand neighbor) { Require.ArgumentNotNull(neighbor); if (!ma_neighbors.Contains(neighbor)) { ma_neighbors.Add(neighbor); } }
//--------------------------------------------------------------------- /// <summary> /// Schedules the next harvest for a stand that's been set aside /// (reserved). /// </summary> protected void ScheduleNextHarvest(Stand stand) { int nextTimeToHarvest = Model.Core.CurrentTime + repeatHarvest.Interval; if (nextTimeToHarvest <= EndTime) { reservedStands.Enqueue(new ReservedStand(stand, nextTimeToHarvest)); } }
/// <summary> /// Signals that a stand has been harvested in a repeat step /// </summary> public static void OnRepeatStandHarvest(object sender, Stand stand, uint repeatNumber) { if (RepeatStandHarvestedEvent != null) { RepeatStandHarvestedEvent(sender, new RepeatHarvestStandHarvestedEvent.Args(stand, repeatNumber)); } }
//--------------------------------------------------------------------- //mark the whole area selected as harvested IEnumerable <ActiveSite> ISiteSelector.SelectSites(Stand stand) { areaSelected = stand.ActiveArea; stand.MarkAsHarvested(); //mark this stand's event id stand.EventId = EventId.MakeNewId(); return(stand); }
//--------------------------------------------------------------------- /// <summary> /// Harvests a stand (and possibly its neighbors) according to the /// prescription's site-selection method. /// </summary> /// <returns> /// The area that was harvested (units: hectares). /// </returns> // This is called by AppliedPrescription public virtual void Harvest(Stand stand) { if (isDebugEnabled) { log.DebugFormat(" Harvesting stand {0} by {1} ...", stand.MapCode, Name); } //set prescription name for stand stand.PrescriptionName = this.Name; stand.HarvestedRank = AppliedPrescription.CurrentRank; stand.LastPrescription = this; stand.MinTimeSinceDamage = this.minTimeSinceDamage; //set current stand currentStand = stand; currentStand.ClearDamageTable(); // SelectSites(stand) is where either complete, complete stand spreading, or partial stand // spreading are activated. // tjs - This is what gets the sites that will be harvested if (isSingleRepeatStep) { foreach (ActiveSite site in stand) { // Check if this was previously harvested in the last step if (stand.IsSiteSetAside(site, this.Name)) { HarvestSite(site, stand); } } } else { foreach (ActiveSite site in SiteSelector.SelectSites(stand)) { HarvestSite(site, stand); // Only queue up for a repeat harvest if cohorts were cut if (this.isSingleRepeatPrescription && cohortCounts.AllSpecies > 0) { stand.SetSiteAside(site, this.Name); } } } return; }
//--------------------------------------------------------------------- /// <summary> /// Schedules the next harvest for a stand that's been set aside /// (reserved). /// </summary> protected void ScheduleNextHarvest(Stand stand) { int nextTimeToHarvest = Model.Core.CurrentTime + repeatHarvest.Interval; if (nextTimeToHarvest <= Model.Core.EndTime && stand.RepeatNumber < this.repeatHarvest.TimesToRepeat) { reservedStands.Enqueue(new ReservedStand(stand, nextTimeToHarvest)); } else { if (stand.RepeatNumber >= this.repeatHarvest.TimesToRepeat) { stand.SetAsideUntil(Model.Core.CurrentTime); } stand.ResetRepeatNumber(); } }
//--------------------------------------------------------------------- /// <summary> /// Computes the rank for a stand. /// </summary> protected override double ComputeRank(Stand stand, int i) { SiteVars.GetExternalVars(); foreach (IRequirement req in Requirements) { //check for fire or wind requirements if (req is TimeSinceLastFire || req is TimeSinceLastWind) { if (req.MetBy(stand)) { return(1); } } } return(0); //if we are still here, stand does not meet requirements }
//--------------------------------------------------------------------- /// <summary> /// Gets the ranking for an unharvested stand from among the whole set /// of stand rankings. /// </summary> public StandRanking GetRanking(Stand stand) { // Search backward through the stand rankings because unharvested // stands are at the end of the list. for (int i = rankings.Length - 1; i >= 0; i--) { if (rankings[i].Stand == stand) { return(rankings[i]); } } //throw new System.ApplicationException("ERROR: Stand not found in rankings"); //instead of throwing an exception, just return 0 rankings[0].Stand = stand; rankings[0].Rank = 0; return(rankings[0]); }
//--------------------------------------------------------------------- /// <summary> /// Harvests the stands that have repeat harvests scheduled for the /// current time step. /// </summary> public void HarvestReservedStands() { while (reservedStands.Count > 0 && reservedStands.Peek().NextTimeToHarvest <= Model.Core.CurrentTime) { //Stand stand = reservedStands.Dequeue().Stand; Stand stand = reservedStands.Peek().Stand; repeatHarvest.Harvest(stand); stand = reservedStands.Dequeue().Stand; if (isMultipleRepeatHarvest) { ScheduleNextHarvest(stand); } } }
//--------------------------------------------------------------------- void IStandRankingMethod.RankStands(List <Stand> stands, StandRanking[] rankings) { InitializeForRanking(stands, stands.Count); for (int i = 0; i < stands.Count; i++) { Stand stand = stands[i]; double rank = 0; if (!stand.IsSetAside) { //check if stand meets all the ranking requirements bool meetsAllRequirements = true; foreach (IRequirement requirement in requirements) { if (!requirement.MetBy(stand)) { meetsAllRequirements = false; //set stand rank to 0 rankings[i].Rank = 0; break; } } //if the stand meets all the requirements and is not set-aside,, get its rank if (meetsAllRequirements) { rank = ComputeRank(stand, i); } //otherwise, rank it 0 (so it will not be harvested.) else { rank = 0; //Model.Core.UI.WriteLine(" Stand {0} did not meet its requirements.", stand.MapCode); } } else { rankings[i].Rank = 0; } rankings[i].Stand = stand; rankings[i].Rank = rank; //assign rank to stand //Model.Core.UI.WriteLine(" Stand {0} rank = {1}.", rankings[i].Stand.MapCode, rankings[i].Rank); } }
//--------------------------------------------------------------------- public void Add(ActiveSite site) { AllLocations.Add(site.Location); this.activeArea = AllLocations.Count * Model.Core.CellArea; //set site var SiteVars.Stand[site] = this; //loop- really just 2 locations, relative (-1, 0) and relative (0, -1) foreach (RelativeLocation neighbor_loc in neighborsAboveAndLeft) { //check this site for neighbors that are different Site neighbor = site.GetNeighbor(neighbor_loc); if (neighbor != null && neighbor.IsActive) { //declare a stand with this site as its index. Stand neighbor_stand = SiteVars.Stand[neighbor]; //check for non-null stand //also, only allow stands in same management area to be called neighbors if (neighbor_stand != null && this.ManagementArea == neighbor_stand.ManagementArea) { //if neighbor_stand is different than this stand, then it is a true //neighbor. add it as a neighbor and add 'this' as a neighbor of that. if (this != neighbor_stand) { //add neighbor_stand as a neighboring stand to this AddNeighbor(neighbor_stand); //add this as a neighboring stand to neighbor_stand neighbor_stand.AddNeighbor(this); } } //take into account other management areas just for stand-adjacency issue else if (neighbor_stand != null && this.ManagementArea != neighbor_stand.ManagementArea) { if (this != neighbor_stand) { //add neighbor_stand as a ma-neighboring stand to this AddMaNeighbor(neighbor_stand); //add this as a ma-neighbor stand to neighbor_stand neighbor_stand.AddMaNeighbor(this); } } } } }
/// <summary> /// Does the actual work of harvesting individual sites /// </summary> public void HarvestSite(ActiveSite site, Stand stand) { // Site selection may have spread to other stands beyond the // original stand. Stand standForCurrentSite = SiteVars.Stand[site]; // Always record the prescription even if nothing harvested; Supports plantOnly prescriptions SiteVars.Prescription[site] = this; SiteVars.PrescriptionName[site] = this.Name; if (isDebugEnabled) { log.DebugFormat(" Cutting cohorts at {0} in stand {1}{2}", site, SiteVars.Stand[site].MapCode, (standForCurrentSite == stand) ? "" : string.Format(" (initial stand {0})", stand.MapCode)); } cohortCutter.Cut(site, cohortCounts); if (cohortCounts.AllSpecies > 0) { SiteVars.CohortsDamaged[site] = cohortCounts.AllSpecies; standForCurrentSite.DamageTable.IncrementCounts(cohortCounts); stand.LastAreaHarvested += Model.Core.CellArea; if (isDebugEnabled) { log.DebugFormat(" # of cohorts damaged = {0}; stand.LastAreaHarvested = {1}", SiteVars.CohortsDamaged[site], stand.LastAreaHarvested); } HarvestExtensionMain.OnSiteHarvest(this, site); } if (speciesToPlant != null) { if (isDebugEnabled) { Model.Core.UI.WriteLine(" {0} {1}", speciesToPlant.ToString(), site.ToString()); } Reproduction.ScheduleForPlanting(speciesToPlant, site); } }
//--------------------------------------------------------------------- /// <summary> /// Harvests a stand (and possibly its neighbors) according to the /// repeat-harvest's site-selection method. /// </summary> /// <returns> /// The area that was harvested (units: hectares). /// </returns> public override void Harvest(Stand stand) { base.Harvest(stand); harvestedStands.Clear(); // Add stand to list only if actually harvested if (stand.LastAreaHarvested > 0) { harvestedStands.Add(stand); } if (spreadingSiteSelector != null) { harvestedStands.AddRange(spreadingSiteSelector.HarvestedNeighbors); } return; // areaHarvested; }
//--------------------------------------------------------------------- /// <summary> /// Computes the rank for a stand. /// </summary> /// <remarks> /// Stands are ranked by age class so that over time harvesting will /// result in an even distribution of sites by age classes. /// </remarks> protected override double ComputeRank(Stand stand, int i) { double freq = 0.0; //find where the stands of this age are in the array //and return that frequency from the freq_array int k = 0; for (k = 0; k < age_count; k++) { if (stand.Age == age_array[k]) { freq = freq_array[k]; //Model.Core.UI.WriteLine("stand {0}.\nreturning age = {1} and freq = {2}", stand.MapCode, age_array[k], freq); //break loop when freq for this stand has been found break; } } //rank = freq * e^(age / 10) <-- using age / 10 to get a smaller number return(freq * (System.Math.Exp(stand.Age / 10))); }
//--------------------------------------------------------------------- /// <summary> /// Harvests a stand (and possibly its neighbors) according to the /// repeat-harvest's site-selection method. /// </summary> /// <returns> /// The area that was harvested (units: hectares). /// </returns> public override void Harvest(Stand stand) { if (stand.IsSetAside) { CohortCutter = additionalCohortCutter; SpeciesToPlant = additionalSpeciesToPlant; SiteSelector = additionalSiteSelector; // new CompleteStand(); // //if(this.SiteSelectionMethod.GetType() == Landis.Extension.BiomassHarvest.PartialStandSpreading) // SiteSelector = BiomassHarvest.WrapSiteSelector(SiteSelector); } else { CohortCutter = initialCohortSelector; SpeciesToPlant = initialSpeciesToPlant; } base.Harvest(stand); return; }
//--------------------------------------------------------------------- /// <summary> /// Harvests the stands that have repeat harvests scheduled for the /// current time step. /// </summary> public void HarvestReservedStands() { while (reservedStands.Count > 0 && reservedStands.Peek().NextTimeToHarvest <= Model.Core.CurrentTime) { //Stand stand = reservedStands.Dequeue().Stand; Stand stand = reservedStands.Peek().Stand; uint repeat = stand.RepeatNumber; repeatHarvest.Harvest(stand); stand.SetRepeatHarvested(); stand.IncrementRepeat(); HarvestExtensionMain.OnRepeatStandHarvest(this, stand, stand.RepeatNumber); stand = reservedStands.Dequeue().Stand; // Record every instance of a repeat harvest if (reservedStands.Count > 0 && reservedStands.Peek().Stand.RepeatNumber != repeat) { HarvestExtensionMain.OnRepeatHarvestFinished(this, this, this.ActiveMgmtArea, repeat + 1, false); } else if (reservedStands.Count == 0 || reservedStands.Peek().NextTimeToHarvest > Model.Core.CurrentTime) { HarvestExtensionMain.OnRepeatHarvestFinished(this, this, this.ActiveMgmtArea, repeat + 1, true); } if (isMultipleRepeatHarvest) { ScheduleNextHarvest(stand); } else { stand.ResetRepeatNumber(); } } }
//--------------------------------------------------------------------- /// <summary> /// Adds a stand's unharvested neighbors and their rankings to a /// sorted list of stand rankings. /// </summary> /// <remarks> /// The stand rankings are in highest to lowest order. A neighbor is /// only added to the list if its rank is > 0 and it isn't already in /// the list. /// </remarks> public void AddUnharvestedNeighbors(Stand stand, List <StandRanking> neighborRankings) { foreach (Stand neighbor in stand.Neighbors) { if (!neighbor.Harvested) { bool inList = false; foreach (StandRanking ranking in neighborRankings) { if (ranking.Stand == neighbor) { inList = true; break; } } if (inList) { continue; } StandRanking neighborRanking = GetRanking(neighbor); if (neighborRanking.Rank <= 0) { continue; } int i; for (i = 0; i < neighborRankings.Count; i++) { if (neighborRankings[i].Rank < neighborRanking.Rank) { break; } } //Model.Core.UI.WriteLine(" place={0}, rank={1}.", i, neighborRanking.Rank); neighborRankings.Insert(i, neighborRanking); } } }
} // private bool spreadFromStand() { //-------------------------------------------------------------- // For the current stand, enqueue all the eligible sites onto // the harvestableSites queue private bool EnqueueEligibleSites(Stand crntStand) { bool rtrnVal = false; int sitesHarvested = 0, sitesChecked = 0; foreach (ActiveSite crntSite in crntStand) { sitesChecked++; if (SiteVars.TimeSinceLastDamage(crntSite) >= minTimeSinceDamage) { sitesHarvested++; harvestableSites.Enqueue(crntSite); areaSelected += Model.Core.CellArea; rtrnVal = true; } } return(rtrnVal); } // private void EnqueueEligibleSites() {
//--------------------------------------------------------------------- bool IRequirement.MetBy(Stand stand) { int sumTimeOfNext = 0; int siteCount = 0; if (SiteVars.NextBDA == null) { return(false); } else { foreach (ActiveSite site in stand) { int timeOfNext = SiteVars.NextBDA[site]; siteCount += 1; sumTimeOfNext += timeOfNext; } double avgTimeOfNext = (double)sumTimeOfNext / (double)siteCount; return(avgTimeOfNext <= (Model.Core.CurrentTime + presalvYears)); } }
//--------------------------------------------------------------------- bool IRequirement.MetBy(Stand stand) { double avgtime = 0; int num = 0; if (SiteVars.TimeOfLastWind != null) { foreach (ActiveSite site in stand) { avgtime = avgtime + SiteVars.TimeOfLastWind[(Site)site]; num = num + 1; } } avgtime = avgtime / num; if (num == 0) { return(false); } return(avgtime >= timeSinceWind); }
//--------------------------------------------------------------------- IEnumerable <ActiveSite> ISiteSelector.SelectSites(Stand stand) { this.stand = stand; return(this); }
//--------------------------------------------------------------------- /// <summary> /// Harvest the area's stands according to its prescriptions. /// </summary> public void HarvestStands() { //Model.Core.UI.WriteLine("BaseHarvest: ManagementArea.cs: HarvestStands: Harvesting management area {0} ...", mapCode); //initialize each stand for harvesting (setting harvested = false) foreach (Stand stand in stands) { stand.InitializeForHarvesting(); } // Determine which are prescriptions are active. List <AppliedPrescription> activePrescriptions = new List <AppliedPrescription>(); foreach (AppliedPrescription prescription in prescriptions) { // Decide whether or not to apply prescription // tjs 2009.01.10 - prescription application // This has been modified so that if the prescription is AppliedRepeatHarvest // AND has not been harvested once, it is set to harvest. If it has been set // to harvest the first time, it will automatically be harvested by the logic // having to do with the setAside member variable (see AppliedRepeatHarvest.cs) prescription.ApplyPrescription = false; if (prescription.BeginTime <= Model.Core.CurrentTime && prescription.EndTime >= Model.Core.CurrentTime) { if (!(prescription is AppliedRepeatHarvest) || prescription.Prescription is SingleRepeatHarvest) { prescription.ApplyPrescription = true; } else if (prescription is AppliedRepeatHarvest && Model.Core.CurrentTime > 0 && ((AppliedRepeatHarvest)prescription).IsMultipleRepeatHarvest) { prescription.ApplyPrescription = true; ((AppliedRepeatHarvest)prescription).HasBeenHarvested = true; } } // if(prescription.BeginTime <= Model.Core.CurrentTime... if (prescription.ApplyPrescription) { //Model.Core.UI.WriteLine(" Applying Prescription: {0} Model.Core.CurrentTime: {1}", prescription.Prescription.Name, Model.Core.CurrentTime); if (isDebugEnabled) { log.DebugFormat(" Initializing prescription {0} ...", prescription.Prescription.Name); } //Model.Core.UI.WriteLine(" Initializing prescription {0} ...", prescription.Prescription.Name); //set harvesting areas, rank stands (by user choice method) prescription.InitializeForHarvest(stands); if (prescription.AnyUnharvestedStandsRankedAbove0) { //Model.Core.UI.WriteLine(" Adding {0}", prescription.Prescription.Name); foreach (StandRanking sr in prescription.Rankings) { //Model.Core.UI.WriteLine(" Stand {0} ranked {1}", sr.Stand.MapCode, sr.Rank); } activePrescriptions.Add(prescription); } } } if (isDebugEnabled) { Model.Core.UI.WriteLine(" Number of active prescriptions: {0}", activePrescriptions.Count); for (int i = 0; i < activePrescriptions.Count; i++) { Model.Core.UI.WriteLine(" {0}) {1}", i + 1, activePrescriptions[i].Prescription.Name); } } foreach (AppliedPrescription prescription in prescriptions) { //Model.Core.UI.WriteLine(" Looping through prescriptions... {0}.", prescription.Prescription.Name); if (prescription is AppliedRepeatHarvest) { //prescription.Prescription.SiteSelectionMethod = new CompleteStand(); //Model.Core.UI.WriteLine(" Attempting to Re-Harvest {0}.", prescription.Prescription.Name); ((AppliedRepeatHarvest)prescription).ActiveMgmtArea = this; ((AppliedRepeatHarvest)prescription).HarvestReservedStands(); ((AppliedRepeatHarvest)prescription).ActiveMgmtArea = null; } } // Loop while there are still active prescriptions that haven't // reached their target harvest areas and that still have // at least one unharvested stand ranked above 0. while (activePrescriptions.Count > 0) { double[] endProbability = new double[activePrescriptions.Count + 1]; // Assign a part of the probability interval [0, 1) to each // prescription based on how the ratio of the area remaining to // be harvested to the total area to be harvested double ratioTotal = 0.0; foreach (AppliedPrescription prescription in activePrescriptions) { ratioTotal += Math.Min(prescription.AreaRemainingRatio, prescription.StandsRemainingRatio); } if (ratioTotal > 0) { for (int i = 0; i < activePrescriptions.Count; ++i) { AppliedPrescription prescription = activePrescriptions[i]; //first prescription, start at 0 if (i == 0) { endProbability[i] = Math.Min(prescription.AreaRemainingRatio, prescription.StandsRemainingRatio) / ratioTotal; } //last prescription, end at 1.0 else if (i == activePrescriptions.Count - 1) { endProbability[i] = 1.0; } // else { double startProbability = endProbability[i - 1]; double intervalWidth = Math.Min(prescription.AreaRemainingRatio, prescription.StandsRemainingRatio) / ratioTotal; endProbability[i] = startProbability + intervalWidth; } } // for (int i = 0; i < activePrescriptions.Count; ++i) // Randomly select one of the active prescriptions and harvest the stand ranked highest by that prescription. AppliedPrescription selectedPrescription = null; double randomNum = Model.Core.GenerateUniform(); for (int i = 0; i < activePrescriptions.Count; ++i) { if (randomNum < endProbability[i]) { selectedPrescription = activePrescriptions[i]; //Model.Core.UI.WriteLine("\nSELECTED PRESCRIPTION = {0}\n", selectedPrescription.Prescription.Name); break; } } //actually harvest the stands: starting with highest ranked if (selectedPrescription is AppliedRepeatHarvest) { ((AppliedRepeatHarvest)selectedPrescription).HarvestHighestRankedStand(); } else { selectedPrescription.HarvestHighestRankedStand(); } //Model.Core.UI.WriteLine("\nSELECTED PRESCRIPTION = {0}\n", selectedPrescription.Prescription.Name); Stand stand = selectedPrescription.HighestRankedStand; if (stand != null) { //if there was a stand-adjacency constraint on this stand, enforce: foreach (IRequirement r in selectedPrescription.Prescription.StandRankingMethod.Requirements) { //look for stand-adacency constraint in list r ranking methods if (r.ToString() == "Landis.Harvest.StandAdjacency") { StandAdjacency sa = (StandAdjacency)r; //set-aside every stand in this stand's neighbor-list for the specified number of years //IF siteselection = some type of spreading, freeze the spread-list of neighbors if (selectedPrescription.Prescription.SiteSelectionMethod.ToString() == "Landis.Harvest.CompleteStandSpreading" || selectedPrescription.Prescription.SiteSelectionMethod.ToString() == "Landis.Harvest.PartialStandSpreading") { //freeze every stand in the neighbor list StandSpreading ss = (StandSpreading)selectedPrescription.Prescription.SiteSelectionMethod; //if it's spreading, go through the UnharvestedNeighbors list that was built during the site-selection spread foreach (Stand n_stand in ss.UnharvestedNeighbors) { //Model.Core.UI.WriteLine("SPREAD setting aside {0}", n_stand.MapCode); n_stand.SetAsideUntil(Model.Core.CurrentTime + sa.SetAside); } } else { //if it's not a spreading, just take all of the stand's neighbors foreach (Stand n_stand in stand.Neighbors) { //Model.Core.UI.WriteLine("NON-SPREAD setting aside {0}", n_stand.MapCode); n_stand.SetAsideUntil(Model.Core.CurrentTime + sa.SetAside); } } //found and implemented the stand adjacency, so break out of the requirements list break; } } } else { //Model.Core.UI.WriteLine("returned a null stand"); } // Check each prescription to see if there's at least one unharvested stand that the prescription ranks higher than 0. // The list is traversed in reverse order, so that the removal of items doesn't mess up the traversal. for (int i = activePrescriptions.Count - 1; i >= 0; --i) { if (!activePrescriptions[i].AnyUnharvestedStandsRankedAbove0) { //Model.Core.UI.WriteLine("removing1 {0}", activePrescriptions[i].Prescription.Name); activePrescriptions.RemoveAt(i); } } } else { for (int i = activePrescriptions.Count - 1; i >= 0; --i) { //Model.Core.UI.WriteLine("removing2 {0}", activePrescriptions[i].Prescription.Name); activePrescriptions.RemoveAt(i); } } } //endwhile }
//--------------------------------------------------------------------- /// <summary> /// Computes the rank for a stand. /// </summary> /// <remarks> /// The stand's rank is a random number. /// </remarks> protected override double ComputeRank(Stand stand, int i) { //just return current rank from the list return(rank_array[i]); }