Exemple #1
0
        /// <summary>
        /// Initialise the population with an initial set of cohorts, iterating each one
        /// every time a new one is added so they are all appropriately "decayed"
        /// </summary>
        /// <param name="SpinUpTemps"></param>
        public unsafe void Initialise(double[] SpinUpTemps)
        {
            if (SpinUpTemps.Length != m_LifespanSlices)
            {
                throw new ArgumentException("Population must be initialised with one temp for each slice in a lifespan");
            }
            // initialise the population arrays (all values will be set to 0)
            m_Contribs = new double[m_LifespanSlices];
            m_DegDays  = new double[m_LifespanSlices];
            double[] localContribs = m_Contribs;
            double[] localDegDays  = m_DegDays;

            for (int i = 0; i < m_LifespanSlices; i++)
            {
                double minTemp      = SpinUpTemps[i];
                double survivalRate = MossieMethods.GetSurvivingFraction(minTemp, m_SliceLengthDays, m_UpperTempLimit);
                double degreeDays   = Math.Max(((minTemp - m_TempThreshold) * m_SliceLengthDays), 0);

                // decrease all the living cohorts by the survival fraction and
                // we don't care what the actual result of the sum is at this point
                for (int cohPos = 0; cohPos < i; cohPos++)
                {
                    localContribs[cohPos] *= survivalRate;
                    localDegDays[cohPos]  += degreeDays;
                }
                // "hatch" the next cohort
                localContribs[i] = 1;
                localDegDays[i]  = 0;
            }
            m_Contribs    = localContribs;
            m_DegDays     = localDegDays;
            IsInitialised = true;
        }
Exemple #2
0
        /// <summary>
        /// Initialise the population with an initial set of cohorts, iterating each one
        /// every time a new one is added so they are all appropriately "decayed"
        /// </summary>
        /// <param name="SpinUpTemps"></param>
        public void Initialise(double[] SpinUpTemps)
        {
            if (SpinUpTemps.Length != m_LifespanSlices)
            {
                throw new ArgumentException("Population must be initialised with one temp for each slice in a lifespan");
            }

            m_Contribs = new double[m_LifespanSlices];
            m_DegDays  = new double[m_LifespanSlices];
            double[] localContribs = m_Contribs;
            double[] localDegDays  = m_DegDays;

            for (int i = 0; i < m_LifespanSlices; i++)
            {
                double minTemp = SpinUpTemps[i];
                // survival rate is zero if the upper temp threshold is exceeded, meaning all cohorts will die
                double survivalRate = MossieMethods.GetSurvivingFraction(minTemp, m_SliceLengthDays, m_UpperTempLimit);
                double degreeDays   = Math.Max(((minTemp - m_TempThreshold) * m_SliceLengthDays), 0);

                // we don't care what the actual result of the sum is at this point
                for (int cohPos = 0; cohPos < i; cohPos++)
                {
                    localContribs[cohPos] *= survivalRate;
                    localDegDays[cohPos]  += degreeDays;
                }
                localContribs[i] = 1;
                localDegDays[i]  = 0;
            }
            m_Contribs    = localContribs;
            m_DegDays     = localDegDays;
            IsInitialised = true;
        }
Exemple #3
0
        public double Iterate(double minTemp)
        {
            if (!IsInitialised)
            {
                throw new InvalidOperationException("Population has not yet been initialised");
            }
            // Calculate degree days once here rather than in every Cohort.
            double degreeDays = Math.Max(((minTemp - m_TempThreshold) * m_SliceLengthDays), 0);
            // Calculate survival fraction once here rather than in every Cohort
            double survivalRate = MossieMethods.GetSurvivingFraction(minTemp, m_SliceLengthDays, m_UpperTempLimit);
            // Temperature suitability at this slice is simply the sum of Contributions from every Cohort.
            // This is given before applying the death / decay of this timeslice.
            // So all we have to do is this time-slice's temperature to all currently living cohorts and
            // summarise the return values.
            double tsAtSlice = 0;

            // It would be sweeter to say:
            // double tsAtSLice = m_Population.Sum(coh => coh.Iterate(degreeDays, survivalRate));
            // But that's substantially slower thanks to the linq overhead, given the tightness of this loop.
            foreach (Cohort coh in m_Population)
            {
                tsAtSlice += coh.Iterate(degreeDays, survivalRate);
            }

            // Remove the oldest cohort, which should now be dead anyway
            Cohort tDeadCohort = m_Population.Dequeue();

            //Debug.Assert(tDeadCohort.IsDead);
            // Add the new cohort
            m_Population.Enqueue(new Cohort(m_InfectionThreshold, m_LifespanSlices));
            return(tsAtSlice);
        }
Exemple #4
0
        /// Initialise the population with an initial set of cohorts, iterating each one
        /// every time a new one is added so they are all appropriately "decayed"
        /// </summary>
        /// <param name="SpinUpTemps"></param>
        public void Initialise(double[] SpinUpTemps)
        {
            if (SpinUpTemps.Length != m_LifespanSlices)
            {
                throw new ArgumentException("Population must be initialised with one temp for each slice in a lifespan");
            }

            for (int i = 0; i < m_LifespanSlices; i++)
            {
                double minTemp      = SpinUpTemps[i];
                double survivalRate = MossieMethods.GetSurvivingFraction(minTemp, m_SliceLengthDays, m_UpperTempLimit);
                double degreeDays   = Math.Max(((minTemp - m_TempThreshold) * m_SliceLengthDays), 0);

                // we don't care what the actual result of the sum is at this point
                // It's much neater to say:
                //m_Population.Sum(coh => coh.Iterate(degreeDays, survivalRate));
                // But also much slower! Use ye olde loop instead.
                foreach (Cohort coh in m_Population)
                {
                    coh.Iterate(degreeDays, survivalRate);
                }
                m_Population.Enqueue(new Cohort(m_InfectionThreshold, m_LifespanSlices));
            }
            IsInitialised = true;
        }
Exemple #5
0
        public double Iterate(double minTemp)
        {
            if (!IsInitialised)
            {
                throw new InvalidOperationException("Population has not yet been initialised");
            }
            // work on a local copy rather than referencing the fields in the tight loop;
            // this saves approx 10% of overall program runtime!
            double[] localContribs  = m_Contribs;
            double[] localDegDays   = m_DegDays;
            double   localThreshold = m_InfectionThreshold;

            // Calculate degree days once here rather than in every Cohort.
            double degreeDays = Math.Max(((minTemp - m_TempThreshold) * m_SliceLengthDays), 0);
            // Calculate survival fraction once here rather than in every Cohort
            double survivalRate = MossieMethods.GetSurvivingFraction(minTemp, m_SliceLengthDays, m_UpperTempLimit);
            // Temperature suitability at this slice is simply the sum of Contributions from every Cohort.
            // This is given before applying the death / decay of this timeslice.
            // So all we have to do is apply this time-slice's temperature to all currently living cohorts and
            // summarise the return values.
            double tsAtSlice = 0;

            // calculate and summarise the contribution of all living cohorts first...
            for (int cohPos = 0; cohPos < localContribs.Length; cohPos++)
            {
                if (localDegDays[cohPos] > localThreshold)
                {
                    tsAtSlice += localContribs[cohPos];
                }
                // ... BEFORE applying the decay function
                localContribs[cohPos] *= survivalRate;
                localDegDays[cohPos]  += degreeDays;
            }
            // ... and BEFORE replacing the oldest dead cohort with a new one
            localContribs[m_NextToDie] = 1;
            localDegDays[m_NextToDie]  = 0;

            m_Contribs  = localContribs;
            m_DegDays   = localDegDays;
            m_NextToDie = (m_NextToDie + 1) % m_LifespanSlices;

            return(tsAtSlice);
        }
Exemple #6
0
        public unsafe double Iterate(double SliceTemp)
        {
            if (!IsInitialised)
            {
                throw new InvalidOperationException("Population has not yet been initialised");
            }
            // Calculate degree days once here rather than in every Cohort.
            double degreeDays = (SliceTemp - m_TempThreshold) * m_SliceLengthDays;

            if (degreeDays < 0)
            {
                degreeDays = 0;
            }
            // Calculate survival fraction once here rather than in every Cohort. It may be interesting at some stage
            // to investigate calculating a survival rate that varies with age to reflect different acceptable temp
            // ranges at different stages of the lifecycle.
            double survivalRate = MossieMethods.GetSurvivingFraction(SliceTemp, m_SliceLengthDays, m_UpperTempLimit);
            // Temperature suitability at this slice is simply the sum of Contributions from every Cohort.
            // This is given before applying the death / decay of this timeslice.
            // So all we have to do is apply this time-slice's temperature to all currently living cohorts and
            // summarise the return values.
            double tsAtSlice = 0;

            // work on a local copy rather than referencing the fields in the tight loop;
            // this single step saves approx 10% of overall program runtime in the array-based implementation.
            double[] localContribs  = m_Contribs;
            double[] localDegDays   = m_DegDays;
            double   localThreshold = m_InfectionThreshold;
            int      count          = m_LifespanSlices;

            fixed(double *pContribs = localContribs, pDegDays = localDegDays)
            {
                double *pContrib = pContribs, pDegDay = pDegDays;

                for (int i = 0; i < count; i++)
                {
                    // go through each cohort of the current population, based on pointers
                    if (*pDegDay > localThreshold)
                    {
                        // this cohort has reached sporogenesis threshold, it contributes to the temperature suitability
                        // of this timeslice based on the surviving fraction _before_ this timeslice's die-off
                        tsAtSlice += *pContrib;
                    }
                    // reduce the surviving fraction of this cohort (possibly to zero if mosoquito-baking temp was exceeded)
                    *pContrib *= survivalRate;
                    // add the degree-days of this slice to the total degree days experienced by this cohort (probably quicker
                    // just to do it rather than only conditionally doing it if baking didn't occur)
                    *pDegDay += degreeDays;
                    // move pointer for contribution and degree day onto next value
                    pContrib++;
                    pDegDay++;
                }
            }

            // spawn a new one (replacing the previous value at this position, the cohort which is now dead)
            localContribs[m_NextToDie] = 1;
            localDegDays[m_NextToDie]  = 0;
            // copy local variables back to field
            m_Contribs  = localContribs;
            m_DegDays   = localDegDays;
            m_NextToDie = (m_NextToDie + 1) % m_LifespanSlices;
            return(tsAtSlice);
        }