public async static Task<Animat> SeedAsync(ScenarioSpecies species, GeoRect geoRect, Bathymetry bathymetry)
        {
            var yxzFileName = Path.Combine(Path.GetTempPath(), Path.GetFileNameWithoutExtension(Path.GetRandomFileName()) + ".txt");
            bathymetry.ToYXZ(yxzFileName, -1);
            var mbs = new C3mbs();
            mbsRESULT mbsResult;
            if (mbsRESULT.OK != (mbsResult = mbs.SetOutputDirectory(Path.GetTempPath())))
                throw new AnimatInterfaceMMBSException("SetOutputDirectory Error:" + mbs.ResultToTc(mbsResult));
            var config = mbs.GetConfiguration();
            config.enabled = false;             // binary output enabled/disabled
            config.durationLess = true;         // make sure we're in durationless mode.
            mbs.SetConfiguration(config);
            mbsResult = mbs.LoadBathymetryFromTextFile(yxzFileName);
            if (mbsRESULT.OK != mbsResult) throw new AnimatInterfaceMMBSException("Bathymetry failed to load: " + mbs.ResultToTc(mbsResult));
            mbsResult = mbs.AddSpecies(species.SpeciesDefinitionFilePath);
            if (mbsRESULT.OK != mbsResult) throw new AnimatInterfaceMMBSException(string.Format("C3mbs::AddSpecies FATAL error {0} for species {1}", mbs.ResultToTc(mbsResult), species.SpeciesDefinitionFilePath));

            var bounds = new GeoArray(geoRect.NorthWest, geoRect.NorthEast, geoRect.SouthEast, geoRect.SouthWest, geoRect.NorthWest);
            var result = new Animat { ScenarioSpecies = species };
            
            var area = bounds.Area;
            //Debug.WriteLine("Area: {0}",area);
            var transformManyBlock = new TransformManyBlock<int, Geo<float>>(count =>
            {
                var geos = new List<Geo<float>>();
                for (var i = 0; i < count; i++)
                {
                    var location = bounds.RandomLocationWithinPerimeter();
                    var depth = bathymetry.Samples.GetNearestPointAsync(location).Result.Data;
                    mbsRESULT retval;
                    lock (mbs) retval = mbs.AddIndividualAnimat(0, new mbsPosition { latitude = location.Latitude, longitude = location.Longitude, depth = 0 });
                    if (mbsRESULT.OK == retval) geos.Add(new Geo<float>(location.Latitude, location.Longitude, (float)(depth * Random.NextDouble())));
                }
                return geos;
            }, new ExecutionDataflowBlockOptions
            {
                TaskScheduler = TaskScheduler.Default,
                BoundedCapacity = -1,
                MaxDegreeOfParallelism = -1,
            });
            var bufferBlock = new BufferBlock<Geo<float>>();
            transformManyBlock.LinkTo(bufferBlock);
            var population = (int)Math.Round(area * species.PopulationDensity);
            result.TotalAnimats = population;
            const int blockSize = 100;
            while (population > 0)
            {
                transformManyBlock.Post(population > blockSize ? blockSize : population);
                population -= blockSize;
            }
            transformManyBlock.Complete();
            await transformManyBlock.Completion;
            //mbsResult = mbs.InitializeRun();
            //if (mbsRESULT.OK == mbsResult) while (mbsRUNSTATE.INITIALIZING == mbs.GetRunState()) Thread.Sleep(1);
            //else throw new AnimatInterfaceMMBSException("C3mbs::Initialize FATAL error " + mbs.ResultToTc(mbsResult));
            mbsResult = mbs.FinishRun();
            if (mbsRESULT.OK != mbsResult) throw new AnimatInterfaceMMBSException("C3mbs::FinishRun FATAL error " + mbs.ResultToTc(mbsResult));

            IList<Geo<float>> animatGeos;
            if (bufferBlock.TryReceiveAll(out animatGeos))
                result.Locations.AddRange(animatGeos);
            return result;
        }
        //double[] _animatSoundExposure;
        void Initialize3MB()
        {
            var nextSpeciesIndex = 0;
            var yxzFileName = Path.Combine(Path.GetTempPath(), Path.GetFileNameWithoutExtension(Path.GetRandomFileName()) + ".txt");
            Scenario.BathymetryData.ToYXZ(yxzFileName, -1);
            var contexts = new List<AnimatContext>();
            foreach (var species in Scenario.ScenarioSpecies)
            {
                if (!_speciesNameToIndex.ContainsKey(species.SpeciesDefinitionFilePath))
                    _speciesNameToIndex.Add(species.SpeciesDefinitionFilePath, nextSpeciesIndex++);
                var speciesInstanceIndex = _speciesNameToIndex[species.SpeciesDefinitionFilePath];
                var curSpecies = species;
                species.ReloadOrReseedAnimats();
                contexts.AddRange(species.Animat.Locations.Select((t, speciesIndex) => new AnimatContext
                {
                    Species = curSpecies,
                    SpeciesInstanceIndex = speciesInstanceIndex,
                    SpeciesAnimatIndex = speciesIndex
                }));
            }
            //var splitContext = contexts.Split(System.Environment.ProcessorCount).ToList();
            var splitContext = contexts.Split(1).ToList();
            _mbs = new C3mbs[splitContext.Count];
            _animatContext = new AnimatContext[splitContext.Count][];
            for (var mbsIndex = 0; mbsIndex < splitContext.Count; mbsIndex++)
            {
                mbsRESULT result;
                var mbs = new C3mbs();
                _mbs[mbsIndex] = mbs;

                // set the output directory
                if (mbsRESULT.OK != (result = mbs.SetOutputDirectory(_simulationDirectory)))
                    throw new AnimatInterfaceMMBSException("SetOutputDirectory Error:" + mbs.ResultToTc(result));

                var config = mbs.GetConfiguration();
                config.seedValue = (uint)mbsIndex;  // Probably wise to set each 3mb instance to a unique randomizer seed value.
                config.enabled = false;             // binary output enabled/disabled
                config.durationLess = true;         // make sure we're in durationless mode.
                mbs.SetConfiguration(config);
                result = mbs.LoadBathymetryFromTextFile(yxzFileName);
                if (mbsRESULT.OK != result) throw new AnimatInterfaceMMBSException("Bathymetry failed to load: " + mbs.ResultToTc(result));

                foreach (var speciesFilePath in _speciesNameToIndex.Keys)
                {
                    result = mbs.AddSpecies(speciesFilePath);
                    if (mbsRESULT.OK != result) throw new AnimatInterfaceMMBSException(string.Format("C3mbs::AddSpecies FATAL error {0} for species {1}", mbs.ResultToTc(result), speciesFilePath));
                }
                var context = splitContext[mbsIndex].ToList();
                _animatContext[mbsIndex] = new AnimatContext[context.Count];
                //_animatPositions[mbsIndex] = new mbsPosition[context.Count];
                //Debug.WriteLine("Thread {0} contains {1} animats", mbsIndex, context.Count);
                for (var animatIndex = 0; animatIndex < context.Count; animatIndex++)
                {
                    var species = context[animatIndex].Species;
                    var geo = species.Animat.Locations[context[animatIndex].SpeciesAnimatIndex];
                    _animatContext[mbsIndex][animatIndex] = new AnimatContext { Species = species, SpeciesAnimatIndex = context[animatIndex].SpeciesAnimatIndex };
                    result = mbs.AddIndividualAnimat(context[animatIndex].SpeciesInstanceIndex, new mbsPosition { latitude = geo.Latitude, longitude = geo.Longitude, depth = 0 });
                    if (mbsRESULT.OK != result) throw new AnimatInterfaceMMBSException(string.Format("An error was found with animat species {0}. Please verify that this species is appropriate for use in the location \"{1}\".C3mbs::AddIndividualAnimat FATAL error {2}", species.LatinName, Scenario.Location.Name,mbs.ResultToTc(result)));
                    //throw new AnimatInterfaceMMBSException("this is a test error.");
                    
                    //Debug.WriteLine("Animat {0} lat: {1:0.####} lon: {2:0.####} depth: {3:0.#}, bathy: {4:0.#}", animatIndex, geo.Latitude, geo.Longitude, geo.Data, Scenario.BathymetryData.Samples.GetNearestPoint(geo).Data);
                }
                mbs.SetDuration((int)((TimeSpan)Scenario.Duration).TotalSeconds);
                result = mbs.SaveScenario(Path.Combine(_simulationDirectory, "test.sce"));
                if (mbsRESULT.OK != result) throw new AnimatInterfaceMMBSException(string.Format("C3mbs::SaveScenario FATAL error {0}", mbs.ResultToTc(result)));
                //----------------------------------------------------------------------//
                // Initialize the scenario.
                //----------------------------//
                if (mbsRESULT.OK == result) while (mbsRUNSTATE.INITIALIZING == mbs.GetRunState()) Thread.Sleep(1);
                else throw new AnimatInterfaceMMBSException("C3mbs::Initialize FATAL error " + mbs.ResultToTc(result));
            }
            UpdateAnimatPositions();
        }