/// <summary> /// Clears the transition patches for the specified transition group /// </summary> /// <param name="transitionGroup"></param> /// <remarks></remarks> private void ClearTransitionPatches(TransitionGroup transitionGroup) { Debug.Assert(this.IsSpatial); if (transitionGroup.PatchPrioritization != null) { transitionGroup.PatchPrioritization.TransitionPatches.Clear(); } }
/// <summary> /// Calculates the spread distance for the specified criteria /// </summary> /// <param name="contagionCell"></param> /// <param name="tstValue"></param> /// <param name="spreadGroup"></param> /// <returns></returns> /// <remarks></remarks> private double CalculateSpreadDistance(Cell contagionCell, int tstValue, TransitionGroup spreadGroup, int iteration, int timestep) { Debug.Assert(tstValue > 0); Debug.Assert(this.IsSpatial); double SpreadDistance = 0.0; for (int tstval = 1; tstval <= tstValue; tstval++) { double rand = this.m_RandomGenerator.GetNextDouble(); double PreviousCumulativeProportion = 0.0; double CumulativeProportion = 0.0; List <TransitionSpreadDistribution> lst = spreadGroup.TransitionSpreadDistributionMap.GetDistributionList(contagionCell.StratumId, contagionCell.StateClassId, iteration, timestep); if (lst == null) { continue; } foreach (TransitionSpreadDistribution tsd in lst) { PreviousCumulativeProportion = CumulativeProportion; CumulativeProportion += tsd.Proportion; if (CumulativeProportion > rand) { double diff1 = (rand - PreviousCumulativeProportion); if (diff1 == 0.0) { SpreadDistance += tsd.MinimumDistance; } else { double diff2 = (CumulativeProportion - PreviousCumulativeProportion); Debug.Assert(diff2 >= diff1); if (diff1 == diff2) { SpreadDistance += tsd.MaximumDistance; } else { double diff3 = (tsd.MaximumDistance - tsd.MinimumDistance); SpreadDistance += (tsd.MinimumDistance + ((diff1 / diff2) * diff3)); } } break; } } } return(SpreadDistance); }
private int GetMaxOrderIndex(double order) { for (int Index = this.m_ShufflableTransitionGroups.Count - 1; Index >= 0; Index--) { TransitionGroup tg = this.m_ShufflableTransitionGroups[Index]; if (tg.Order == order) { return(Index); } } throw new InvalidOperationException("Cannot find maximum transition order!"); }
/// <summary> /// Grows a transition patch /// </summary> /// <param name="transitionedCells"></param> /// <param name="patchCells"></param> /// <param name="initiationCell"></param> /// <param name="patch"></param> /// <param name="transitionGroup"></param> /// <param name="iteration"></param> /// <param name="timestep"></param> /// <remarks></remarks> private void GrowTransitionPatch( Dictionary <int, Cell> transitionedCells, Dictionary <int, Cell> patchCells, Cell initiationCell, TransitionPatch patch, TransitionGroup transitionGroup, int iteration, int timestep) { double PatchSize = 0.0; Queue <Cell> PatchQueue = new Queue <Cell>(); Dictionary <int, Cell> QueuedCells = new Dictionary <int, Cell>(); PatchQueue.Enqueue(initiationCell); QueuedCells.Add(initiationCell.CellId, initiationCell); while (PatchQueue.Count > 0) { Cell CurrentCell = PatchQueue.Dequeue(); Debug.Assert(!patchCells.ContainsKey(CurrentCell.CellId)); Debug.Assert(!patch.AllCells.ContainsKey(CurrentCell.CellId)); patchCells.Add(CurrentCell.CellId, CurrentCell); patch.AllCells.Add(CurrentCell.CellId, CurrentCell); PatchSize += this.m_AmountPerCell; this.AddNeighboringPatchCell(transitionedCells, patchCells, QueuedCells, PatchQueue, this.GetCellNorth(CurrentCell), transitionGroup, iteration, timestep); this.AddNeighboringPatchCell(transitionedCells, patchCells, QueuedCells, PatchQueue, this.GetCellNortheast(CurrentCell), transitionGroup, iteration, timestep); this.AddNeighboringPatchCell(transitionedCells, patchCells, QueuedCells, PatchQueue, this.GetCellEast(CurrentCell), transitionGroup, iteration, timestep); this.AddNeighboringPatchCell(transitionedCells, patchCells, QueuedCells, PatchQueue, this.GetCellSoutheast(CurrentCell), transitionGroup, iteration, timestep); this.AddNeighboringPatchCell(transitionedCells, patchCells, QueuedCells, PatchQueue, this.GetCellSouth(CurrentCell), transitionGroup, iteration, timestep); this.AddNeighboringPatchCell(transitionedCells, patchCells, QueuedCells, PatchQueue, this.GetCellSouthwest(CurrentCell), transitionGroup, iteration, timestep); this.AddNeighboringPatchCell(transitionedCells, patchCells, QueuedCells, PatchQueue, this.GetCellWest(CurrentCell), transitionGroup, iteration, timestep); this.AddNeighboringPatchCell(transitionedCells, patchCells, QueuedCells, PatchQueue, this.GetCellNorthwest(CurrentCell), transitionGroup, iteration, timestep); } patch.Size = PatchSize; foreach (var PatchCell in patch.AllCells.Values) { if (this.IsPatchEdgeCell(PatchCell, patch)) { patch.EdgeCells.Add(PatchCell.CellId, PatchCell); } } Debug.Assert(patch.EdgeCells.Count() > 0); Debug.Assert(patch.AllCells.Count() > 0); Debug.Assert(patch.AllCells.Count() >= patch.EdgeCells.Count()); }
/// <summary> /// Updates the patch membership for the specified transition group and cell /// </summary> /// <param name="transitionGroupId"></param> /// <param name="cell"></param> /// <remarks> /// This function will also remove a patch if its cell collection becomes empty. /// </remarks> private void UpdateCellPatchMembership(int transitionGroupId, Cell cell) { TransitionGroup TransitionGroup = this.m_TransitionGroups[transitionGroupId]; if (TransitionGroup.PatchPrioritization != null) { TransitionPatch Patch = null; if ( TransitionGroup.PatchPrioritization.PatchPrioritizationType == PatchPrioritizationType.Smallest || TransitionGroup.PatchPrioritization.PatchPrioritizationType == PatchPrioritizationType.SmallestEdgesOnly) { Patch = TransitionGroup.PatchPrioritization.TransitionPatches.First(); } else { Patch = TransitionGroup.PatchPrioritization.TransitionPatches.Last(); } if (Patch.AllCells.ContainsKey(cell.CellId)) { Patch.AllCells.Remove(cell.CellId); } if (Patch.EdgeCells.ContainsKey(cell.CellId)) { Patch.EdgeCells.Remove(cell.CellId); } if ( TransitionGroup.PatchPrioritization.PatchPrioritizationType == PatchPrioritizationType.LargestEdgesOnly || TransitionGroup.PatchPrioritization.PatchPrioritizationType == PatchPrioritizationType.SmallestEdgesOnly) { if (Patch.EdgeCells.Count() == 0) { TransitionGroup.PatchPrioritization.TransitionPatches.Remove(Patch); } } else if (Patch.AllCells.Count() == 0) { Debug.Assert(Patch.EdgeCells.Count() == 0); TransitionGroup.PatchPrioritization.TransitionPatches.Remove(Patch); } } }
/// <summary> /// Selects a patch initiation cell /// </summary> /// <param name="transitionGroup"></param> /// <returns></returns> /// <remarks></remarks> private Cell SelectPatchInitiationCell(TransitionGroup transitionGroup) { Debug.Assert(this.IsSpatial); PatchPrioritization pp = transitionGroup.PatchPrioritization; List <TransitionPatch> patches = pp.TransitionPatches; if (patches.Count == 0) { return(null); } TransitionPatch Patch = patches[0]; if (pp.PatchPrioritizationType == PatchPrioritizationType.Largest || pp.PatchPrioritizationType == PatchPrioritizationType.LargestEdgesOnly) { Patch = patches[patches.Count - 1]; } if (pp.PatchPrioritizationType == PatchPrioritizationType.SmallestEdgesOnly || pp.PatchPrioritizationType == PatchPrioritizationType.LargestEdgesOnly) { if (Patch.EdgeCells.ContainsKey(Patch.SeedCell.CellId)) { return(Patch.SeedCell); } else { return(Patch.EdgeCells.Values.ElementAt(0)); } } else { if (Patch.AllCells.ContainsKey(Patch.SeedCell.CellId)) { return(Patch.SeedCell); } else { return(Patch.AllCells.Values.ElementAt(0)); } } }
/// <summary> /// Fills the transition patches for the specified transition group /// </summary> /// <param name="transitionedCells"></param> /// <param name="stratum"></param> /// <param name="transitionGroup"></param> /// <param name="iteration"></param> /// <param name="timestep"></param> /// <remarks></remarks> private void FillTransitionPatches( Dictionary <int, Cell> transitionedCells, Stratum stratum, TransitionGroup transitionGroup, int iteration, int timestep) { Debug.Assert(this.IsSpatial); if (transitionGroup.PatchPrioritization == null) { return; } Debug.Assert(transitionGroup.PatchPrioritization.TransitionPatches.Count == 0); Dictionary <int, Cell> patchCells = new Dictionary <int, Cell>(); foreach (Cell SimulationCell in stratum.Cells.Values) { Debug.Assert(SimulationCell.StratumId != 0); Debug.Assert(SimulationCell.StateClassId != 0); if (patchCells.ContainsKey(SimulationCell.CellId) | transitionedCells.ContainsKey(SimulationCell.CellId)) { continue; } if (this.SelectTransitionPathway(SimulationCell, transitionGroup.TransitionGroupId, iteration, timestep) == null) { continue; } TransitionPatch Patch = new TransitionPatch(SimulationCell); this.GrowTransitionPatch(transitionedCells, patchCells, SimulationCell, Patch, transitionGroup, iteration, timestep); transitionGroup.PatchPrioritization.TransitionPatches.Add(Patch); } transitionGroup.PatchPrioritization.TransitionPatches.Sort((TransitionPatch p1, TransitionPatch p2) => { return(p1.Size.CompareTo(p2.Size)); }); }
/// <summary> /// Initializes the transition spread groups /// </summary> /// <remarks></remarks> private void InitializeTransitionSpreadGroups() { #if DEBUG Debug.Assert(this.IsSpatial); Debug.Assert(this.m_TransitionSpreadGroups.Count == 0); foreach (TransitionGroup t in this.m_TransitionGroups) { Debug.Assert(t.TransitionSpreadCells.Count == 0); } #endif //Get a unique list of transition groups from the spread distribution records Dictionary <int, TransitionSpreadDistribution> dict = new Dictionary <int, TransitionSpreadDistribution>(); foreach (TransitionSpreadDistribution t in this.m_TransitionSpreadDistributions) { if (!dict.ContainsKey(t.TransitionGroupId)) { dict.Add(t.TransitionGroupId, t); } } foreach (TransitionSpreadDistribution t in dict.Values) { this.m_TransitionSpreadGroups.Add(this.m_TransitionGroups[t.TransitionGroupId]); } //Associate each spread distribution with its transition spread group foreach (TransitionSpreadDistribution t in this.m_TransitionSpreadDistributions) { TransitionGroup tg = this.m_TransitionGroups[t.TransitionGroupId]; tg.TransitionSpreadDistributionMap.AddItem(t); } foreach (TransitionGroup tg in this.m_TransitionSpreadGroups) { tg.TransitionSpreadDistributionMap.Normalize(); } }
/// <summary> /// Adds a neighboring patch cell /// </summary> /// <param name="transitionedCells"></param> /// <param name="patchCells"></param> /// <param name="queuedCells"></param> /// <param name="patchQueue"></param> /// <param name="neighborCell"></param> /// <param name="transitionGroup"></param> /// <param name="iteration"></param> /// <param name="timestep"></param> /// <remarks></remarks> private void AddNeighboringPatchCell (Dictionary <int, Cell> transitionedCells, Dictionary <int, Cell> patchCells, Dictionary <int, Cell> queuedCells, Queue <Cell> patchQueue, Cell neighborCell, TransitionGroup transitionGroup, int iteration, int timestep) { if (neighborCell != null) { if ( queuedCells.ContainsKey(neighborCell.CellId) || patchCells.ContainsKey(neighborCell.CellId) || transitionedCells.ContainsKey(neighborCell.CellId)) { return; } if (this.SelectTransitionPathway(neighborCell, transitionGroup.TransitionGroupId, iteration, timestep) == null) { return; } queuedCells.Add(neighborCell.CellId, neighborCell); patchQueue.Enqueue(neighborCell); } }
private void ApplyTransitionSpread(Cell contagionCell, Cell neighboringCell, TransitionGroup spreadGroup, int iteration, int timestep, bool isDiagonal, CardinalDirection direction, Dictionary <int, double[]> rasterTransitionAttrValues, Dictionary <int, int[]> dictTransitionedPixels) { Debug.Assert(this.IsSpatial); //Get the cell probability. If it is less than or equal to zero we don't need to continue //DEVTODO: LEO, is this OK with the new Transition Prioritization Code? double CellProbability = this.SpatialCalculateCellProbability(neighboringCell, spreadGroup.TransitionGroupId, iteration, timestep); if (CellProbability <= 0.0) { return; } //Get the transition pathway. If there isn't one we don't need to continue Transition tr = this.SelectTransitionPathway(neighboringCell, spreadGroup.TransitionGroupId, iteration, timestep); if (tr == null) { return; } //Prepare a TST value with a default of 1. If we can find a TST group for the contagion cell's stratum and transition type, and //the the contagion cells TST values contains that group, then use that TST value. int tstvalue = 1; TstTransitionGroup tstgroup = this.m_TstTransitionGroupMap.GetGroup( tr.TransitionTypeId, contagionCell.StratumId, contagionCell.SecondaryStratumId, contagionCell.TertiaryStratumId); if (tstgroup != null) { if (contagionCell.TstValues.Contains(tstgroup.TSTGroupId)) { tstvalue = contagionCell.TstValues[tstgroup.TSTGroupId].TstValue; } } if (tstvalue > 0) { double MinThreshold = 0; double MaxThreshold = 0; double SpreadDistance = this.CalculateSpreadDistance(contagionCell, tstvalue, spreadGroup, iteration, timestep); double NeighborDistance = this.GetNeighborCellDistance(direction); double Slope = GetSlope(contagionCell, neighboringCell, NeighborDistance); SpreadDistance *= this.m_TransitionDirectionMultiplierMap.GetDirectionMultiplier(spreadGroup.TransitionGroupId, contagionCell.StratumId, contagionCell.SecondaryStratumId, contagionCell.TertiaryStratumId, direction, iteration, timestep); SpreadDistance *= this.m_TransitionSlopeMultiplierMap.GetSlopeMultiplier(spreadGroup.TransitionGroupId, contagionCell.StratumId, contagionCell.SecondaryStratumId, contagionCell.TertiaryStratumId, iteration, timestep, Slope); if (isDiagonal) { MinThreshold = this.m_InputRasters.GetCellSizeDiagonalMeters() / 2; MaxThreshold = this.m_InputRasters.GetCellSizeDiagonalMeters() * 1.5; } else { MinThreshold = this.m_InputRasters.GetCellSizeMeters() / 2; MaxThreshold = this.m_InputRasters.GetCellSizeMeters() * 1.5; } if (SpreadDistance >= MinThreshold && SpreadDistance <= MaxThreshold) { this.RecordSummaryTransitionOutput(neighboringCell, tr, iteration, timestep, null); this.RecordSummaryTransitionByStateClassOutput(neighboringCell, tr, iteration, timestep); this.ChangeCellForProbabilisticTransition(neighboringCell, tr, iteration, timestep, rasterTransitionAttrValues); this.UpdateTransitionedPixels(neighboringCell, tr.TransitionTypeId, dictTransitionedPixels[spreadGroup.TransitionGroupId]); this.FillProbabilisticTransitionsForCell(neighboringCell, iteration, timestep); } else if (SpreadDistance > MaxThreshold) { int randdirection = this.m_RandomGenerator.GetNextInteger(0, 360); Cell DistantCell = GetCellByDistanceAndDirection(contagionCell, randdirection, SpreadDistance); if (DistantCell != null) { Transition DistantTransition = this.SelectTransitionPathway(DistantCell, spreadGroup.TransitionGroupId, iteration, timestep); if (DistantTransition != null) { this.RecordSummaryTransitionOutput(DistantCell, DistantTransition, iteration, timestep, null); this.RecordSummaryTransitionByStateClassOutput(DistantCell, DistantTransition, iteration, timestep); this.ChangeCellForProbabilisticTransition(DistantCell, DistantTransition, iteration, timestep, rasterTransitionAttrValues); this.UpdateTransitionedPixels(DistantCell, DistantTransition.TransitionTypeId, dictTransitionedPixels[spreadGroup.TransitionGroupId]); this.FillProbabilisticTransitionsForCell(DistantCell, iteration, timestep); } } } } }
/// <summary> /// Resets the transition target multipliers for this cell, iteration, timestep and explicit transition group /// </summary> /// <param name="iteration">The current iteration</param> /// <param name="timestep">The current timestep</param> /// <param name="explicitGroup">transition group must be provided if spatial - should be null if non spatial</param> /// <remarks></remarks> private void ResetTransitionTargetMultipliers(int iteration, int timestep, TransitionGroup explicitGroup) { Debug.Assert(explicitGroup != null); if (this.m_TransitionTargets.Count == 0) { return; } foreach (TransitionTarget tt in this.m_TransitionTargets) { if (!tt.IsDisabled) { tt.Multiplier = 1.0; tt.ExpectedAmount = 0.0; if (tt.HasPrioritizations) { List <TransitionTargetPrioritization> pl = tt.GetPrioritizations(iteration, timestep); if (pl != null) { foreach (TransitionTargetPrioritization pri in pl) { pri.PossibleAmount = 0.0; pri.ExpectedAmount = 0.0; pri.DesiredAmount = null; pri.CumulativePossibleAmount = 0.0; pri.ProbabilityMultiplier = 1.0; pri.ProbabilityOverride = null; } } } } } foreach (Cell simulationCell in this.m_Cells) { foreach (Transition tr in simulationCell.Transitions) { TransitionType ttype = this.m_TransitionTypes[tr.TransitionTypeId]; if (this.IsSpatial) { if (!ttype.PrimaryTransitionGroups.Contains(explicitGroup.TransitionGroupId)) { continue; } } if (ttype.TransitionGroups.Count == 0) { continue; } double TransMult = this.GetTransitionMultiplier(tr.TransitionTypeId, iteration, timestep, simulationCell); TransMult *= this.GetExternalTransitionMultipliers(tr.TransitionTypeId, iteration, timestep, simulationCell); if (this.IsSpatial) { TransMult *= this.GetTransitionSpatialMultiplier(simulationCell, tr.TransitionTypeId, iteration, timestep); foreach (TransitionGroup tg in ttype.TransitionGroups) { TransMult *= this.GetTransitionAdjacencyMultiplier(tg.TransitionGroupId, iteration, timestep, simulationCell); TransMult *= this.GetExternalSpatialMultipliers(simulationCell, iteration, timestep, tg.TransitionGroupId); } Debug.Assert(TransMult >= 0.0); } if (TransMult == 0.0) { continue; } foreach (TransitionGroup tgroup in ttype.TransitionGroups) { TransitionTarget tt = this.m_TransitionTargetMap.GetTransitionTarget( tgroup.TransitionGroupId, simulationCell.StratumId, simulationCell.SecondaryStratumId, simulationCell.TertiaryStratumId, iteration, timestep); if (tt != null && !tt.IsDisabled) { tt.ExpectedAmount += (tr.Probability * tr.Proportion * this.m_AmountPerCell * TransMult); Debug.Assert(tt.ExpectedAmount >= 0.0); if (tt.HasPrioritizations) { TransitionTargetPrioritization pri = tt.GetPrioritization( simulationCell.StratumId, simulationCell.SecondaryStratumId, simulationCell.TertiaryStratumId, simulationCell.StateClassId, iteration, timestep); if (pri != null) { pri.PossibleAmount += this.m_AmountPerCell; pri.ExpectedAmount += (tr.Probability * tr.Proportion * this.m_AmountPerCell * TransMult); } } } } } } foreach (TransitionTarget ttarg in this.m_TransitionTargets) { if (!ttarg.IsDisabled && ttarg.ExpectedAmount != 0) { ttarg.Multiplier = ttarg.CurrentValue.Value / ttarg.ExpectedAmount; Debug.Assert(ttarg.Multiplier >= 0.0); if (ttarg.HasPrioritizations) { double PreviousCumulativeAmount = 0.0; double TotalCumulativePossibleAmount = 0.0; List <TransitionTargetPrioritization> pl = ttarg.GetPrioritizations(iteration, timestep); if (pl != null) { foreach (TransitionTargetPrioritization pri in pl) { TotalCumulativePossibleAmount += pri.PossibleAmount; pri.CumulativePossibleAmount = TotalCumulativePossibleAmount; if (ttarg.CurrentValue >= pri.CumulativePossibleAmount) { pri.ProbabilityOverride = 1.0; } else { if (ttarg.CurrentValue > PreviousCumulativeAmount) { pri.DesiredAmount = ttarg.CurrentValue - PreviousCumulativeAmount; pri.ProbabilityMultiplier = pri.DesiredAmount.Value / pri.ExpectedAmount; } else { pri.ProbabilityOverride = 0.0; } } PreviousCumulativeAmount = pri.CumulativePossibleAmount; } } } } } }
private void ResetTransitionAttributeTargetMultipliers( int iteration, int timestep, Dictionary <int, TransitionGroup> remainingTransitionGroups, MultiLevelKeyMap1 <Dictionary <int, TransitionAttributeTarget> > tatMap, TransitionGroup currentTransitionGroup) { if (this.m_TransitionAttributeTargets.Count == 0) { return; } foreach (TransitionAttributeTarget tat in this.m_TransitionAttributeTargets) { if (!tat.IsDisabled) { tat.Multiplier = 1.0; tat.ExpectedAmount = 0.0; if (tat.HasPrioritizations) { List <TransitionAttributeTargetPrioritization> pl = tat.GetPrioritizations(iteration, timestep); if (pl != null) { foreach (TransitionAttributeTargetPrioritization pri in pl) { pri.PossibleAmount = 0.0; pri.ExpectedAmount = 0.0; pri.DesiredAmount = null; pri.CumulativePossibleAmount = 0.0; pri.ProbabilityMultiplier = 1.0; pri.ProbabilityOverride = null; } } } } } foreach (Cell simulationCell in this.m_Cells) { //Only iterate over the transition attribute types that have a target associated with them in this timestep. foreach (int tatId in this.m_TransitionAttributeTypesWithTarget.Keys) { TransitionAttributeType ta = this.m_TransitionAttributeTypes[tatId]; TransitionAttributeTarget Target = this.m_TransitionAttributeTargetMap.GetAttributeTarget( ta.TransitionAttributeId, simulationCell.StratumId, simulationCell.SecondaryStratumId, simulationCell.TertiaryStratumId, iteration, timestep); if (Target == null || Target.IsDisabled) { continue; } foreach (Transition tr in simulationCell.Transitions) { TransitionType tt = this.m_TransitionTypes[tr.TransitionTypeId]; bool Found = false; foreach (TransitionGroup rtg in remainingTransitionGroups.Values) { if (tt.PrimaryTransitionGroups.Contains(rtg.TransitionGroupId)) { Found = true; break; } } if (!Found) { continue; } if (tt.TransitionGroups.Count == 0) { continue; } if ((tatMap != null) && (currentTransitionGroup != null)) { if (tt.TransitionGroups.Contains(currentTransitionGroup.TransitionGroupId)) { Dictionary <int, TransitionAttributeTarget> d = tatMap.GetItemExact(Target.StratumId); if (d == null) { d = new Dictionary <int, TransitionAttributeTarget>(); tatMap.AddItem(Target.StratumId, d); } if (!d.ContainsKey(Target.TransitionAttributeTargetId)) { d.Add(Target.TransitionAttributeTargetId, Target); } } } double TransMult = this.GetTransitionMultiplier(tr.TransitionTypeId, iteration, timestep, simulationCell); TransMult *= this.GetExternalTransitionMultipliers(tr.TransitionTypeId, iteration, timestep, simulationCell); if (this.IsSpatial) { TransMult *= this.GetTransitionSpatialMultiplier(simulationCell, tr.TransitionTypeId, iteration, timestep); foreach (TransitionGroup tg in tt.TransitionGroups) { TransMult *= this.GetTransitionAdjacencyMultiplier(tg.TransitionGroupId, iteration, timestep, simulationCell); TransMult *= this.GetExternalSpatialMultipliers(simulationCell, iteration, timestep, tg.TransitionGroupId); } Debug.Assert(TransMult >= 0.0); } if (TransMult == 0.0) { continue; } foreach (TransitionGroup tg in tt.TransitionGroups) { if (this.IsSpatial) { if (!remainingTransitionGroups.ContainsKey(tg.TransitionGroupId)) { continue; } } double?AttrValue = this.m_TransitionAttributeValueMap.GetAttributeValue( ta.TransitionAttributeId, tg.TransitionGroupId, simulationCell.StratumId, simulationCell.SecondaryStratumId, simulationCell.TertiaryStratumId, simulationCell.StateClassId, iteration, timestep, simulationCell.Age, simulationCell.TstValues); if (AttrValue.HasValue) { double Expectation = tr.Probability * tr.Proportion * this.m_AmountPerCell * AttrValue.Value * TransMult; Target.ExpectedAmount += Expectation; Debug.Assert(Expectation >= 0.0); Debug.Assert(Target.ExpectedAmount >= 0.0); if (Target.HasPrioritizations) { TransitionAttributeTargetPrioritization pri = Target.GetPrioritization( simulationCell.StratumId, simulationCell.SecondaryStratumId, simulationCell.TertiaryStratumId, tg.TransitionGroupId, simulationCell.StateClassId, iteration, timestep); if (pri != null) { pri.PossibleAmount += this.m_AmountPerCell * AttrValue.Value; pri.ExpectedAmount += Expectation; } } } } } } } foreach (TransitionAttributeTarget tat in this.m_TransitionAttributeTargets) { if (!tat.IsDisabled && tat.ExpectedAmount != 0.0) { tat.Multiplier = tat.TargetRemaining / tat.ExpectedAmount; Debug.Assert(tat.Multiplier >= 0.0); if (tat.HasPrioritizations) { double PreviousCumulativeAmount = 0.0; double TotalCumulativePossibleAmount = 0.0; List <TransitionAttributeTargetPrioritization> pl = tat.GetPrioritizations(iteration, timestep); if (pl != null) { foreach (TransitionAttributeTargetPrioritization pri in pl) { TotalCumulativePossibleAmount += pri.PossibleAmount; pri.CumulativePossibleAmount = TotalCumulativePossibleAmount; if (tat.TargetRemaining >= pri.CumulativePossibleAmount) { pri.ProbabilityOverride = 1.0; } else { if (tat.TargetRemaining > PreviousCumulativeAmount) { pri.DesiredAmount = tat.TargetRemaining - PreviousCumulativeAmount; pri.ProbabilityMultiplier = pri.DesiredAmount.Value / pri.ExpectedAmount; } else { pri.ProbabilityOverride = 0.0; } } PreviousCumulativeAmount = pri.CumulativePossibleAmount; } } } } } }