private void DistributePopulation(DemographicCategoryGeneration cat, float[] ageProbability, float[][] assignedPersons, int catIndex, float[][] ret)
        {
            var timeOfDayRate         = CurrentTimeOfDayRates.GiveData();
            var dailyRates            = CurrentDailyRates.GiveData();
            var zones                 = Root.ZoneSystem.ZoneArray.GetFlatData();
            var numberOfMobilityTypes = GetMobilityTypeTotal();
            var currentMobilityType   = catIndex % numberOfMobilityTypes;

            ModeSplit.StartNewInteractiveModeSplit(NumberOfGenerations);
            // Setup the mode choice function, since each zone is the same, we only need to do this once
            cat.InitializeDemographicCategory();
            var age = cat.AgeCategoryRange[0].Start;
            //ageOfffset = foreach each OD Pair, for each mobility category multiplied by the age - 2 (workrs start at 2).
            var ageOffset = (5 * zones.Length * zones.Length) * (age - 2);

            // for each origin zone
            Parallel.For(0, zones.Length, i =>
            {
                var pdI = zones[i].PlanningDistrict;
                // Offset of the origin
                var iOffset = i * zones.Length * numberOfMobilityTypes;
                // offset by the age category plus the mobility category offset
                iOffset += ageOffset + currentMobilityType * zones.Length;
                // for each destination
                var row = ret[i];
                var assignedPersonRow = assignedPersons[i];
                if (ageProbability[i] == 0)
                {
                    for (int j = 0; j < zones.Length; j++)
                    {
                        row[j] = 0;
                    }
                }
                else
                {
                    int currentJIndex = 0;
                    for (int j = 0; j < zones.Length; j++)
                    {
                        if (assignedPersonRow[j] <= 0)
                        {
                            row[j] = 0;
                        }
                        else if (j == i)
                        {
                            throw new XTMFRuntimeException(this, "We found assigned persons for an intra-zonal work trip!");
                        }
                        else
                        {
                            var pdJ = zones[j].PlanningDistrict;
                            // compute the mode choice
                            var util = ModeSplit.ComputeUtility(zones[i], zones[j]);
                            if (float.IsNaN(util) | float.IsInfinity(util))
                            {
                                throw new XTMFRuntimeException(this, "We came across an invalid utility! Age = " + age + " origin = " + zones[i].ZoneNumber + " destination = " + zones[j].ZoneNumber
                                                               + " demographic category = '" + cat.ToString() + "'");
                            }
                            // Process how many persons go here
                            // probabilities contains the probability of being in that age category already
                            var rate    = timeOfDayRate[pdI, pdJ, age] * dailyRates[pdI, pdJ, age];
                            var persons = ageProbability[i] * assignedPersonRow[j];
                            if ((rate == 0) & (persons > 0))
                            {
                                throw new XTMFRuntimeException(this, "We lost generation for " + zones[i].ZoneNumber + " to " + zones[j].ZoneNumber + ". " + persons
                                                               + " persons in category " + catIndex + ".");
                            }
                            row[j] = persons * rate * MobilityCache[iOffset + currentJIndex];
                        }
                        currentJIndex++;
                    }
                }
            });
        }
 private void DistributePopulation(DemographicCategoryGeneration cat, float[] ageProbability, float[][] assignedPersons, int catIndex, float[][] ret)
 {
     var timeOfDayRate = this.CurrentTimeOfDayRates.GiveData();
     var dailyRates = this.CurrentDailyRates.GiveData();
     var zones = this.Root.ZoneSystem.ZoneArray.GetFlatData();
     var numberOfMobilityTypes = GetMobilityTypeTotal();
     var currentMobilityType = catIndex % numberOfMobilityTypes;
     this.ModeSplit.StartNewInteractiveModeSplit( this.NumberOfGenerations );
     // Setup the mode choice function, since each zone is the same, we only need to do this once
     cat.InitializeDemographicCategory();
     var age = cat.AgeCategoryRange[0].Start;
     //ageOfffset = foreach each OD Pair, for each mobility category multiplied by the age - 2 (workrs start at 2).
     var ageOffset = ( 5 * zones.Length * zones.Length ) * ( age - 2 );
     // for each origin zone
     Parallel.For( 0, zones.Length, (int i) =>
         {
             var pdI = zones[i].PlanningDistrict;
             // Offset of the origin
             var iOffset = i * zones.Length * numberOfMobilityTypes;
             // offset by the age category plus the mobility category offset
             iOffset += ageOffset + currentMobilityType * zones.Length;
             // for each destination
             var row = ret[i];
             var assignedPersonRow = assignedPersons[i];
             if ( ageProbability[i] == 0 )
             {
                 for ( int j = 0; j < zones.Length; j++ )
                 {
                     row[j] = 0;
                 }
             }
             else
             {
                 int currentJIndex = 0;
                 for ( int j = 0; j < zones.Length; j++ )
                 {
                     if ( assignedPersonRow[j] <= 0 )
                     {
                         row[j] = 0;
                     }
                     else if ( j == i )
                     {
                         throw new XTMFRuntimeException( "We found assigned persons for an intra-zonal work trip!" );
                     }
                     else
                     {
                         var pdJ = zones[j].PlanningDistrict;
                         // compute the mode choice
                         var util = this.ModeSplit.ComputeUtility( zones[i], zones[j] );
                         if ( float.IsNaN( util ) | float.IsInfinity( util ) )
                         {
                             throw new XTMFRuntimeException( "We came across an invalid utility! Age = " + age + " origin = " + zones[i].ZoneNumber + " destination = " + zones[j].ZoneNumber
                                 + " demographic category = '" + cat.ToString() + "'" );
                         }
                         // Process how many persons go here
                         // probabilities contains the probability of being in that age category already
                         var rate = timeOfDayRate[pdI, pdJ, age] * dailyRates[pdI, pdJ, age];
                         var persons = ageProbability[i] * assignedPersonRow[j];
                         if ( ( rate == 0 ) & ( persons > 0 ) )
                         {
                             throw new XTMFRuntimeException( "We lost generation for " + zones[i].ZoneNumber + " to " + zones[j].ZoneNumber + ". " + persons
                                 + " persons in category " + catIndex + "." );
                         }
                         row[j] = persons * rate * this.MobilityCache[iOffset + currentJIndex];
                     }
                     currentJIndex++;
                 }
             }
         } );
 }