public void Process(SimulationTimeStepRecord record) { var actors = Simulation.Actors; for (var i = 0; i < record.ActorPositionRecords.Count; i++) { foreach (var t in record.ActorPositionRecords[i].Exposures) Scatterplot.Expose(actors[i], t); } }
public void Process(SimulationTimeStepRecord record) { var actors = Simulation.Actors; for (var i = 0; i < record.ActorPositionRecords.Count; i++) { foreach (var t in record.ActorPositionRecords[actors[i].ID].Exposures) ModeBinnedExposureDictionary.Expose(actors[i], t); } }
void Run(TimeSpan timeStepSize, CancellationToken token) { Geo<float> firstAnimatPosition = null; Task<bool> processTask = null; var timeStepCount = (int)Math.Round(((TimeSpan)Scenario.Duration).TotalSeconds / timeStepSize.TotalSeconds); if (MovingAnimats) Initialize3MB(); PercentProgress = new PercentProgress<Simulation>(this) { MinimumValue = 0, MaximumValue = timeStepCount - 1 }; Actors = new List<Actor>(); foreach (var platform in Scenario.Platforms) { platform.PlatformBehavior = new PlatformBehavior(platform, timeStepSize, timeStepCount); var behaviors = platform.PlatformBehavior.PlatformStates.ToArray(); _platformStates.Add(behaviors); var curPlatform = platform; Globals.Dispatcher.InvokeIfRequired(() => { curPlatform.RemoveMapLayers(); curPlatform.UpdateMapLayers(); var mapLayers = CreateFootprintMapLayers(curPlatform, behaviors[0]).ToArray(); _modeFootprintMapLayers.Add(mapLayers); foreach (var layer in mapLayers) { MediatorMessage.Send(MediatorMessage.AddMapLayer, layer); MediatorMessage.Send(MediatorMessage.HideMapLayer, layer); } }); var actor = new Actor { ID = platform.ActorID, Platform = platform }; Actors.Add(actor); } _exposuresBySpecies = new int[Scenario.ScenarioSpecies.Count]; _speciesActorIDStart = new int[Scenario.ScenarioSpecies.Count]; _speciesActorIDEnd = new int[Scenario.ScenarioSpecies.Count]; for (var j = 0; j < Scenario.ScenarioSpecies.Count; j++) { var species = Scenario.ScenarioSpecies[j]; _speciesActorIDStart[j] = species.StartActorID; _speciesActorIDEnd[j] = species.StartActorID + species.Animat.Locations.Count - 1; if (firstAnimatPosition == null) firstAnimatPosition = new Geo<float>(species.Animat.Locations[0].Latitude, species.Animat.Locations[0].Longitude) { Data = species.Animat.Locations[0].Data }; for (var i = 0; i < species.Animat.Locations.Count; i++) Actors.Add(new Actor { ID = species.StartActorID + i, Species = species }); } var actorCount = Scenario.ScenarioSpecies.Last().StartActorID + Scenario.ScenarioSpecies.Last().Animat.Locations.Count; var logBlock = new ActionBlock<SimulationTimeStepRecord>(block => SimulationLog.Add(block), new ExecutionDataflowBlockOptions { BoundedCapacity = 1, MaxDegreeOfParallelism = 1 }); logBlock.Completion.ContinueWith(t => SimulationLog.Close()); var logBuffer = new BufferBlock<SimulationTimeStepRecord>(); logBuffer.LinkTo(logBlock); logBuffer.Completion.ContinueWith(t => logBlock.Complete()); Task moveTask = null; for (var timeStepIndex = 0; timeStepIndex < timeStepCount; timeStepIndex++) { if (MovingAnimats) moveTask = MoveAnimatsAsync(); var actorPositionRecords = new ActorPositionRecord[actorCount]; var actionBlockCompletions = new List<Task>(); var bufferBlocks = new List<BufferBlock<int>>(); foreach (var platform in Scenario.Platforms) { var platformState = _platformStates[platform.ActorID][timeStepIndex]; actorPositionRecords[platform.ActorID] = new ActorPositionRecord(platformState.PlatformLocation.Location, platformState.PlatformLocation.Depth); foreach (var activeMode in platformState.ModeActiveTimes.Keys) { var platformModeLayers = _modeFootprintMapLayers[Scenario.Platforms.IndexOf(platform)]; var activeModeLayerName = string.Format("{0}-footprint", activeMode.Guid); var curModeLayer = (from l in platformModeLayers where l.Name == activeModeLayerName select l).FirstOrDefault(); if (curModeLayer != null) { UpdateFootprintMapLayer(activeMode, platformState, curModeLayer); var isActive = platformState.ModeActiveTimes[activeMode].Ticks > 0; Globals.Dispatcher.InvokeIfRequired(() => { MediatorMessage.Send(AnimateSimulation && isActive ? MediatorMessage.ShowMapLayer : MediatorMessage.HideMapLayer, curModeLayer); MediatorMessage.Send(MediatorMessage.RefreshMapLayer, curModeLayer); }); } var mode = activeMode; var platformLocation = platformState.PlatformLocation.Location; var thisPlatform = platform; var scenario = Scenario; var geoArc = new GeoArc(platformLocation, Geo.DegreesToRadians(platformState.PlatformLocation.Course + mode.RelativeBeamAngle), Geo.DegreesToRadians(mode.HorizontalBeamWidth), Geo.MetersToRadians(mode.MaxPropagationRadius)); var actionBlock = new ActionBlock<int>(async index => { // Don't expose a platform to itself if (thisPlatform.ActorID == index) return; var record = actorPositionRecords[index]; var actorGeo = new Geo(record.Latitude, record.Longitude); var radiansToActor = platformLocation.DistanceRadians(actorGeo); var azimuthToActor = platformLocation.Azimuth(actorGeo); if (!geoArc.Contains(radiansToActor, azimuthToActor)) return; // At this point we know the actor will be exposed to this mode // Find the nearest radial var closestRadial = scenario.ClosestTransmissionLoss(platformLocation, mode) .ClosestRadial(Geo.RadiansToDegrees(azimuthToActor)); // Load it into the cache if it's not already there var tlTask = _transmissionLossCache[closestRadial]; await tlTask; // Look up the TL value at the actor's range and depth var transmissionLoss = tlTask.Result.ShadeFile[Geo.RadiansToMeters(radiansToActor), -record.Depth]; // Only generate an exposure record if the appropriate transmissionLoss is not NaN if (!float.IsNaN(transmissionLoss)) { var peakSPL = mode.SourceLevel - transmissionLoss; //Debug.Assert(platformState != null, "platformState != null"); //Debug.Assert(platformState.ModeActiveTimes != null, "platformState.ModeActiveTimes != null"); //Debug.Assert(platformState.ModeActiveTimes.ContainsKey(mode), "platformState.ModeActiveTimes does not contain key"); //Debug.Assert(record != null, "record != null"); //Debug.Assert(record.Exposures != null, "record.Exposures != null"); var energy = (float)(peakSPL + (10 * Math.Log10(platformState.ModeActiveTimes[mode].TotalSeconds))); record.Expose(new ActorExposureRecord(index, mode, peakSPL, energy)); Interlocked.Increment(ref _totalExposureCount); for (var i = 0; i < Scenario.ScenarioSpecies.Count; i++) if (_speciesActorIDStart[i] <= index && index <= _speciesActorIDEnd[i]) Interlocked.Increment(ref _exposuresBySpecies[i]); //var actorRecord = SimulationLog.RecordFromActorID(index) as SpeciesNameGuid; //if (actorRecord != null) Interlocked.Increment(ref _exposuresBySpecies[SimulationLog.SpeciesRecords.IndexOf(actorRecord)]); } }, new ExecutionDataflowBlockOptions { BoundedCapacity = -1, MaxDegreeOfParallelism = -1 }); var bufferBlock = new BufferBlock<int>(); bufferBlock.LinkTo(actionBlock); bufferBlocks.Add(bufferBlock); actionBlockCompletions.Add(actionBlock.Completion); bufferBlock.Completion.ContinueWith(t => actionBlock.Complete()); } } foreach (var species in Scenario.ScenarioSpecies) { for (var animatIndex = 0; animatIndex < species.Animat.Locations.Count; animatIndex++) { var actorID = species.StartActorID + animatIndex; actorPositionRecords[actorID] = new ActorPositionRecord(species.Animat.Locations[animatIndex]); } } foreach (var bufferBlock in bufferBlocks) { //Debug.WriteLine("Sending actor IDs to an active mode"); for (var actorID = 0; actorID < actorCount; actorID++) bufferBlock.Post(actorID); bufferBlock.Complete(); } //Debug.WriteLine("Actor IDs sent. Waiting for completion."); Task.WhenAll(actionBlockCompletions).Wait(); PercentProgress.Report(timeStepIndex); var timeStepRecord = new SimulationTimeStepRecord(); timeStepRecord.ActorPositionRecords.AddRange(actorPositionRecords); if (processTask != null) processTask.Wait(); processTask = ModeThresholdHistogram.Process(timeStepRecord, Globals.Dispatcher); if (timeStepIndex % 10 == 0) { processTask.Wait(); Globals.Dispatcher.InvokeIfRequired(UpdateHistogramDisplay); } //SpeciesThresholdHistogram.Process(timeStepRecord); logBuffer.Post(timeStepRecord); if (moveTask != null) { // Wait for 3MB to finish moving the animats moveTask.Wait(); // Pull in updated animat positions from 3MB for the next time step UpdateAnimatPositions(); } //var distance = Scenario.ScenarioSpecies[0].Animat.Locations[0].DistanceKilometers(firstAnimatPosition); //if (distance > 0.01) Debug.WriteLine(string.Format("{0}: First animat has moved {1:0.##} km from initial location", DateTime.Now, distance)); //Debug.WriteLine(string.Format("{0}: Finished time step {1} of {2}: {3:0%} complete", DateTime.Now, timeStepIndex, timeStepCount, Math.Round((float)timeStepIndex / timeStepCount, 3))); if (MovingAnimats & AnimateSimulation) Globals.Dispatcher.InvokeIfRequired(() => { foreach (var species in Scenario.ScenarioSpecies) species.UpdateMapLayers(); }); if (token.IsCancellationRequested) break; } if (processTask != null) processTask.Wait(); Globals.Dispatcher.InvokeIfRequired(UpdateHistogramDisplay); foreach (var layer in _modeFootprintMapLayers.SelectMany(layerSet => layerSet)) { var curLayer = layer; Globals.Dispatcher.InvokeIfRequired(() => MediatorMessage.Send(MediatorMessage.RemoveMapLayer, curLayer)); } Globals.Dispatcher.InvokeIfRequired(() => MediatorMessage.Send(MediatorMessage.RefreshMap, true)); logBuffer.Complete(); logBlock.Completion.Wait(); if (MovingAnimats) Shutdown3MB(); Debug.WriteLine("{0}: Simulation complete. Exposure count: {1}", DateTime.Now, _totalExposureCount); Debug.WriteLine("{0}: Exposures by species:", DateTime.Now); for (var i = 0; i < _exposuresBySpecies.Length; i++) Debug.WriteLine("{0}: Species: {1}, Exposures: {2}", DateTime.Now, Scenario.ScenarioSpecies[i].LatinName, _exposuresBySpecies[i]); //SpeciesThresholdHistogram.Display(); //NewModeThresholdHistogram.DebugDisplay(); }