Ejemplo n.º 1
0
        private void Muster()
        {
            foreach (Ruminant ind in this.CurrentHerd(false))
            {
                // set new location ID
                ind.Location = Pasture.Name;

                this.SetStatusSuccess();

                // check if sucklings are to be moved with mother
                if (MoveSucklings)
                {
                    // if female
                    if (ind.GetType() == typeof(RuminantFemale))
                    {
                        RuminantFemale female = ind as RuminantFemale;
                        // check if mother with sucklings
                        if (female.SucklingOffspring.Count > 0)
                        {
                            foreach (var suckling in female.SucklingOffspring)
                            {
                                suckling.Location = Pasture.Name;
                            }
                        }
                    }
                }
            }
        }
Ejemplo n.º 2
0
 /// <summary>
 /// A method to add the male attributes to the female attribute store at mating
 /// </summary>
 /// <param name="female">The female breeder successfully mated</param>
 /// <param name="male">The mated male</param>
 private void AddMalesAttributeDetails(RuminantFemale female, Ruminant male)
 {
     if (male != null)
     {
         foreach (var attribute in female.Attributes)
         {
             var maleAttribute = male.GetAttributeValue(attribute.Key);
             if (maleAttribute != null)
             {
                 if (attribute.Value.InheritanceStyle != maleAttribute.InheritanceStyle)
                 {
                     throw new ApsimXException(this, $"The inheritance style for attribute [{attribute.Key}] differs between the breeder and breeding male from the herd in [a={this.Name}]");
                 }
                 attribute.Value.storedMateValue = maleAttribute.storedValue;
             }
             else
             {
                 attribute.Value.storedMateValue = null;
                 if (female.BreedParams.IsMandatoryAttribute(attribute.Key))
                 {
                     throw new ApsimXException(this, $"The attributes provided with the breeding male from the herd does not include the madatory attribute [{attribute.Key}] in [a={this.Name}]");
                 }
             }
         }
     }
 }
        /// <summary>
        /// Constructor
        /// </summary>
        /// <param name="status">Change status</param>
        /// <param name="female">Individual being reported</param>
        /// <param name="dateTime">Current clock</param>
        /// <param name="offspring">The offspring related to</param>
        public ConceptionStatusChangedEventArgs(ConceptionStatus status, RuminantFemale female, DateTime dateTime, Ruminant offspring = null)
        {
            Status = status;
            Female = female;

            // Calculate conception date
            switch (Status)
            {
            case ConceptionStatus.Conceived:
            case ConceptionStatus.Failed:
            case ConceptionStatus.Birth:
                ConceptionDate = dateTime.AddMonths(-1 * Convert.ToInt32(female.Age - female.AgeAtLastConception, CultureInfo.InvariantCulture));
                ConceptionDate = new DateTime(ConceptionDate.Year, ConceptionDate.Month, DateTime.DaysInMonth(ConceptionDate.Year, ConceptionDate.Month));
                break;

            case ConceptionStatus.Weaned:
                if (offspring is null)
                {
                    throw new ArgumentException("Code logice error: An offspring must be supplied in ConceptionStatusChangedEventArgs when status is Weaned");
                }
                ConceptionDate = dateTime.AddMonths(-1 * Convert.ToInt32(offspring.Age + female.BreedParams.GestationLength, CultureInfo.InvariantCulture));
                ConceptionDate = new DateTime(ConceptionDate.Year, ConceptionDate.Month, DateTime.DaysInMonth(ConceptionDate.Year, ConceptionDate.Month));
                break;

            case ConceptionStatus.Unsuccessful:
            case ConceptionStatus.NotMated:
            case ConceptionStatus.NotReady:
                ConceptionDate = dateTime;
                break;

            default:
                break;
            }
        }
Ejemplo n.º 4
0
        private void Move()
        {
            Status = ActivityStatus.NotNeeded;
            // allow multiple filter groups for moving.
            var filterGroups = FindAllChildren <RuminantGroup>();

            foreach (RuminantGroup item in filterGroups)
            {
                foreach (Ruminant ind in item.Filter(CurrentHerd(false)))
                {
                    // set new location ID
                    if (ind.Location != pastureName)
                    {
                        this.Status  = ActivityStatus.Success;
                        ind.Location = pastureName;

                        // check if sucklings are to be moved with mother
                        if (MoveSucklings)
                        {
                            // if female
                            if (ind is RuminantFemale)
                            {
                                RuminantFemale female = ind as RuminantFemale;
                                // check if mother with sucklings
                                foreach (var suckling in female.SucklingOffspringList)
                                {
                                    suckling.Location = pastureName;
                                }
                            }
                        }
                    }
                }
            }
        }
Ejemplo n.º 5
0
        /// <summary>
        /// Set the milk production of the selected female given diet drymatter digesibility
        /// </summary>
        /// <param name="ind">Female individual</param>
        /// <returns>energy of milk</returns>
        private double CalculateMilkProduction(RuminantFemale ind)
        {
            double energyMetabolic = EnergyGross * (((ind.DietDryMatterDigestibility == 0)?50:ind.DietDryMatterDigestibility) / 100.0) * 0.81;
            // Reference: SCA p.
            double kl        = ind.BreedParams.ELactationEfficiencyCoefficient * energyMetabolic / EnergyGross + ind.BreedParams.ELactationEfficiencyIntercept;
            double milkTime  = ind.DaysLactating;
            double milkCurve = 0;

            if (ind.SucklingOffspring.Count == 0 && ind.MilkingPerformed) // no suckling calf and milking has been performed
            {
                milkCurve = ind.BreedParams.MilkCurveNonSuckling;
            }
            else // suckling calf
            {
                milkCurve = ind.BreedParams.MilkCurveSuckling;
            }
            double milkProduction = ind.BreedParams.MilkPeakYield * ind.Weight / ind.NormalisedAnimalWeight * (Math.Pow(((milkTime + ind.BreedParams.MilkOffsetDay) / ind.BreedParams.MilkPeakDay), milkCurve)) * Math.Exp(milkCurve * (1 - (milkTime + ind.BreedParams.MilkOffsetDay) / ind.BreedParams.MilkPeakDay));

            milkProduction = Math.Max(milkProduction, 0.0);
            // Reference: Potential milk prodn, 3.2 MJ/kg milk - Jouven et al 2008
            double energyMilk = milkProduction * 3.2 / kl;

            // adjust last time step's energy balance
            if (ind.EnergyBalance < (-0.5936 / 0.322 * energyMilk))
            {
                ind.EnergyBalance = (-0.5936 / 0.322 * energyMilk);
            }
            milkProduction = Math.Max(0.0, milkProduction * (0.5936 + 0.322 * ind.EnergyBalance / energyMilk));

            // set milk production in lactating females for consumption.
            ind.MilkProduction = milkProduction;
            ind.MilkAmount     = ind.MilkProduction * 30.4;

            return(milkProduction * 3.2 / kl);
        }
Ejemplo n.º 6
0
        /// <summary>
        /// Calculate conception rate for a female
        /// </summary>
        /// <param name="female">Female to calculate conception rate for</param>
        /// <returns></returns>
        private double ConceptionRate(RuminantFemale female)
        {
            double rate = 0;

            bool isConceptionReady = false;

            if (female.Age >= female.BreedParams.MinimumAge1stMating && female.NumberOfBirths == 0)
            {
                isConceptionReady = true;
            }
            else
            {
                double currentIPI = female.BreedParams.InterParturitionIntervalIntercept * Math.Pow((female.Weight / female.StandardReferenceWeight), female.BreedParams.InterParturitionIntervalCoefficient) * 30.64;
                // calculate inter-parturition interval
                currentIPI = Math.Max(currentIPI, female.BreedParams.GestationLength * 30.4 + female.BreedParams.MinimumDaysBirthToConception); // 2nd param was 61
                double ageNextConception = female.AgeAtLastConception + (currentIPI / 30.4);
                isConceptionReady = (female.Age >= ageNextConception);
            }

            // if first mating and of age or suffcient time since last birth/conception
            if (isConceptionReady)
            {
                // Get conception rate from conception model associated with the Ruminant Type parameters
                if (female.BreedParams.ConceptionModel == null)
                {
                    throw new ApsimXException(this, String.Format("No conception details were found for [r={0}]\nPlease add a conception component below the [r=RuminantType]", female.BreedParams.Name));
                }
                return(female.BreedParams.ConceptionModel.ConceptionRate(female));
            }
            return(rate / 100);
        }
Ejemplo n.º 7
0
        /// <summary>
        /// Constructor
        /// </summary>
        /// <param name="status">Change status</param>
        /// <param name="female">Individual being reported</param>
        /// <param name="dateTime">Current clock</param>
        public ConceptionStatusChangedEventArgs(ConceptionStatus status, RuminantFemale female, DateTime dateTime)
        {
            Status = status;
            Female = female;

            // Calculate conception date
            switch (Status)
            {
            case ConceptionStatus.Conceived:
            case ConceptionStatus.Failed:
            case ConceptionStatus.Birth:
            case ConceptionStatus.Weaned:
                ConceptionDate = dateTime.AddMonths(-1 * Convert.ToInt32(female.Age - female.AgeAtLastConception, CultureInfo.InvariantCulture));
                ConceptionDate = new DateTime(ConceptionDate.Year, ConceptionDate.Month, DateTime.DaysInMonth(ConceptionDate.Year, ConceptionDate.Month));
                break;

            case ConceptionStatus.Unsuccessful:
            case ConceptionStatus.NotMated:
            case ConceptionStatus.NotReady:
                ConceptionDate = dateTime;
                break;

            default:
                break;
            }
        }
Ejemplo n.º 8
0
        private void Muster()
        {
            Status = ActivityStatus.NotNeeded;
            foreach (Ruminant ind in this.CurrentHerd(false))
            {
                // set new location ID
                if (ind.Location != pastureName)
                {
                    this.Status = ActivityStatus.Success;
                }

                ind.Location = pastureName;

                // check if sucklings are to be moved with mother
                if (MoveSucklings)
                {
                    // if female
                    if (ind.GetType() == typeof(RuminantFemale))
                    {
                        RuminantFemale female = ind as RuminantFemale;
                        // check if mother with sucklings
                        if (female.SucklingOffspringList.Count > 0)
                        {
                            foreach (var suckling in female.SucklingOffspringList)
                            {
                                suckling.Location = pastureName;
                            }
                        }
                    }
                }
            }
        }
Ejemplo n.º 9
0
 /// <summary>
 /// A method to add the available male attributes to the female store at mating using attributes supplied by controlled mating
 /// </summary>
 /// <param name="female">The female breeder successfully mated</param>
 /// <param name="maleAttributes">a list of available male attributes setters</param>
 /// <param name="newMale">Create new instance (T) or use last created (F)</param>
 private void AddMalesAttributeDetails(RuminantFemale female, List <ISetAttribute> maleAttributes, bool newMale = true)
 {
     foreach (var attribute in female.Attributes.Items)
     {
         var maleAttribute = maleAttributes.FirstOrDefault(a => a.AttributeName == attribute.Key);
         SetFemaleMateAttributes(female, attribute, maleAttribute?.GetAttribute(newMale));
     }
 }
Ejemplo n.º 10
0
        /// <summary>
        /// A method to add the available male attributes to the female store at mating using attributes supplied by controlled mating
        /// </summary>
        /// <param name="female">The female breeder successfully mated</param>
        /// <param name="maleAttributes">a list of available male attributes setters</param>
        /// <param name="newMale">Create new instance (T) or use last created (F)</param>
        private void AddMalesAttributeDetails(RuminantFemale female, List <SetAttributeWithValue> maleAttributes, bool newMale = true)
        {
            foreach (var attribute in female.Attributes.Items)
            {
                var maleAttribute = maleAttributes.Where(a => a.AttributeName == attribute.Key).FirstOrDefault();
                if (maleAttribute != null)
                {
                    var calculatedAttribute = maleAttribute.GetAttribute(newMale);
                    if (attribute.Value != null && attribute.Value.InheritanceStyle != calculatedAttribute.InheritanceStyle)
                    {
                        throw new ApsimXException(this, $"The inheritance style for attribute [{attribute.Key}] differs between the breeder and attributes supplied by controlled mating in [a={this.Name}]");
                    }

                    if (attribute.Value != null)
                    {
                        attribute.Value.StoredMateValue = calculatedAttribute.StoredValue;
                    }
                }
                else
                {
                    // if there are random herd attributes available
                    if (randomHerdAttributes.Any())
                    {
                        if (!randomHerdAttributes.TryGetValue(attribute.Key, out IIndividualAttribute randomAttribute))
                        {
                            throw new ApsimXException(this, $"Unable to assign mandatory attribute from random herd selection for [a={this.Name}] and madatory attribute [{attribute.Key}]");
                        }
                        else
                        {
                            if (attribute.Value != null && attribute.Value.InheritanceStyle != randomAttribute.InheritanceStyle)
                            {
                                throw new ApsimXException(this, $"The inheritance style for attribute [{attribute.Key}] differs between the breeder and attributes supplied by random herd selection in [a={this.Name}]");
                            }

                            if (attribute.Value != null)
                            {
                                attribute.Value.StoredMateValue = randomAttribute.StoredValue;
                            }
                        }
                    }
                    else
                    {
                        if (attribute.Value != null)
                        {
                            attribute.Value.StoredMateValue = null;
                        }
                        if (female.BreedParams.IsMandatoryAttribute(attribute.Key))
                        {
                            throw new ApsimXException(this, $"The sire attributes provided for [a={this.Name}] do not include the madatory attribute [{attribute.Key}]");
                        }
                    }
                }
            }
        }
Ejemplo n.º 11
0
        /// <summary>
        /// A method to add the male attributes to the female attribute store at mating
        /// </summary>
        /// <param name="female">The female breeder successfully mated</param>
        /// <param name="male">The mated male</param>
        private void AddMalesAttributeDetails(RuminantFemale female, Ruminant male)
        {
            if (male is null)
            {
                return;
            }

            foreach (var attribute in female.Attributes.Items)
            {
                var maleAttribute = male.Attributes.GetValue(attribute.Key);
                SetFemaleMateAttributes(female, attribute, maleAttribute);
            }
        }
Ejemplo n.º 12
0
        /// <summary>
        /// Calculate conception rate for a female
        /// </summary>
        /// <param name="female">Female to calculate conception rate for</param>
        /// <param name="status">Returns conception status</param>
        /// <returns></returns>
        private double ConceptionRate(RuminantFemale female, out Reporting.ConceptionStatus status)
        {
            bool isConceptionReady = false;

            status = Reporting.ConceptionStatus.NotAvailable;
            if (!female.IsPregnant)
            {
                status = Reporting.ConceptionStatus.NotReady;
                if (female.Age >= female.BreedParams.MinimumAge1stMating && female.NumberOfBirths == 0)
                {
                    isConceptionReady = true;
                }
                else
                {
                    // add one to age to ensure that conception is due this timestep
                    if ((female.Age + 1 - female.AgeAtLastBirth) * 30.4 > female.BreedParams.MinimumDaysBirthToConception)
                    {
                        // only based upon period since birth
                        isConceptionReady = true;

                        // DEVELOPMENT NOTE:
                        // The following IPI calculation and check present in NABSA has been removed for testing
                        // It is assumed that the individual based model with weight influences will handle the old IPI calculation
                        // These parameters can now be removed form the RuminantType list
                        //double currentIPI = female.BreedParams.InterParturitionIntervalIntercept * Math.Pow(female.ProportionOfNormalisedWeight, female.BreedParams.InterParturitionIntervalCoefficient) * 30.4;
                        //double ageNextConception = female.AgeAtLastConception + (currentIPI / 30.4);
                        //isConceptionReady = (female.Age+1 >= ageNextConception);
                    }
                }
            }

            // if first mating and of age or sufficient time since last birth
            if (isConceptionReady)
            {
                status = Reporting.ConceptionStatus.Unsuccessful;

                // Get conception rate from conception model associated with the Ruminant Type parameters
                if (female.BreedParams.ConceptionModel == null)
                {
                    throw new ApsimXException(this, String.Format("No conception details were found for [r={0}]\r\nPlease add a conception component below the [r=RuminantType]", female.BreedParams.Name));
                }

                return(female.BreedParams.ConceptionModel.ConceptionRate(female));
            }
            return(0);
        }
Ejemplo n.º 13
0
        private void SetFemaleMateAttributes(RuminantFemale female, KeyValuePair <string, IIndividualAttribute> femaleAttribute, IIndividualAttribute maleAttribute)
        {
            if (maleAttribute != null)
            {
                if (femaleAttribute.Value != null && femaleAttribute.Value.InheritanceStyle != maleAttribute.InheritanceStyle)
                {
                    string errorMsg;
                    if (useControlledMating)
                    {
                        errorMsg = $"provided from [a={controlledMating.NameWithParent}]";
                    }
                    else
                    {
                        errorMsg = $"from the herd in [a={NameWithParent}]";
                    }
                    throw new ApsimXException(this, $"The inheritance style for attribute [{femaleAttribute.Key}] differs between the breeder [{femaleAttribute.Value.InheritanceStyle}] and breeding male [{maleAttribute.InheritanceStyle}] {errorMsg}");
                }

                if (femaleAttribute.Value != null)
                {
                    femaleAttribute.Value.StoredMateValue = maleAttribute.StoredValue;
                }
            }
            else
            {
                if (femaleAttribute.Value != null)
                {
                    femaleAttribute.Value.StoredMateValue = null;
                }
                if (female.BreedParams.IsMandatoryAttribute(femaleAttribute.Key))
                {
                    string errorMsg;
                    if (useControlledMating)
                    {
                        errorMsg = $"Cannot locate the madatory attribute [{femaleAttribute.Key}] in [a={controlledMating.NameWithParent}]{Environment.NewLine}Add a [SetAttribute] component below the [a=RuminantnActivityControlledMating]";
                    }
                    else
                    {
                        errorMsg = $"Cannot locate the madatory attribute [{femaleAttribute.Key}] in from the breeding male selected from the herd in [a={NameWithParent}]{Environment.NewLine}Ensure all sires in initial herd or purchased provide the appropriate [SetAttribute] component";
                    }
                    throw new ApsimXException(this, errorMsg);
                }
            }
        }
Ejemplo n.º 14
0
        /// <summary>
        /// Set the milk production of the selected female given diet drymatter digesibility
        /// </summary>
        /// <param name="ind">Female individual</param>
        /// <returns>energy of milk</returns>
        private double CalculateMilkProduction(RuminantFemale ind)
        {
            ind.MilkMilkedThisTimeStep  = 0;
            ind.MilkSuckledThisTimeStep = 0;

            double energyMetabolic = EnergyGross * (((ind.DietDryMatterDigestibility == 0)?50:ind.DietDryMatterDigestibility) / 100.0) * 0.81;
            // Reference: SCA p.
            double kl       = ind.BreedParams.ELactationEfficiencyCoefficient * energyMetabolic / EnergyGross + ind.BreedParams.ELactationEfficiencyIntercept;
            double milkTime = ind.DaysLactating;
            double milkCurve;

            // determine milk production curve to use
            // if milking is taking place use the non-suckling curve for duration of lactation
            // otherwise use the suckling curve where there is a larger drop off in milk production
            if (ind.MilkingPerformed)
            {
                milkCurve = ind.BreedParams.MilkCurveNonSuckling;
            }
            else // no milking
            {
                milkCurve = ind.BreedParams.MilkCurveSuckling;
            }
            ind.MilkProductionPotential = ind.BreedParams.MilkPeakYield * ind.Weight / ind.NormalisedAnimalWeight * (Math.Pow(((milkTime + ind.BreedParams.MilkOffsetDay) / ind.BreedParams.MilkPeakDay), milkCurve)) * Math.Exp(milkCurve * (1 - (milkTime + ind.BreedParams.MilkOffsetDay) / ind.BreedParams.MilkPeakDay));
            ind.MilkProductionPotential = Math.Max(ind.MilkProductionPotential, 0.0);
            // Reference: Potential milk prodn, 3.2 MJ/kg milk - Jouven et al 2008
            double energyMilk = ind.MilkProductionPotential * 3.2 / kl;
            // adjust last time step's energy balance
            double adjustedEnergyBalance = ind.EnergyBalance;

            if (adjustedEnergyBalance < (-0.5936 / 0.322 * energyMilk))
            {
                adjustedEnergyBalance = (-0.5936 / 0.322 * energyMilk);
            }

            // set milk production in lactating females for consumption.
            ind.MilkProduction         = Math.Max(0.0, ind.MilkProductionPotential * (0.5936 + 0.322 * adjustedEnergyBalance / energyMilk));
            ind.MilkCurrentlyAvailable = ind.MilkProduction * 30.4;

            // returns the energy required for milk production

            return(ind.MilkProduction * 3.2 / kl);
        }
Ejemplo n.º 15
0
        /// <summary>
        /// Calculate conception rate for a female
        /// </summary>
        /// <param name="female">Female to calculate conception rate for</param>
        /// <returns></returns>
        private double ConceptionRate(RuminantFemale female)
        {
            double rate = 0;

            switch (female.NumberOfBirths)
            {
            case 0:
                // first mating
                if (female.BreedParams.MinimumAge1stMating >= 24)
                {
                    // 1st mated at 24 months or older
                    rate = female.BreedParams.ConceptionRateAsymptote[1] / (1 + Math.Exp(female.BreedParams.ConceptionRateCoefficent[1] * female.WeightAtConception / female.StandardReferenceWeight + female.BreedParams.ConceptionRateIntercept[1]));
                }
                else if (female.BreedParams.MinimumAge1stMating >= 12)
                {
                    // 1st mated between 12 and 24 months
                    double rate24 = female.BreedParams.ConceptionRateAsymptote[1] / (1 + Math.Exp(female.BreedParams.ConceptionRateCoefficent[1] * female.WeightAtConception / female.StandardReferenceWeight + female.BreedParams.ConceptionRateIntercept[1]));
                    double rate12 = female.BreedParams.ConceptionRateAsymptote[0] / (1 + Math.Exp(female.BreedParams.ConceptionRateCoefficent[0] * female.WeightAtConception / female.StandardReferenceWeight + female.BreedParams.ConceptionRateIntercept[0]));
                    rate = (rate12 + rate24) / 2;
                    // Not sure what the next code was doing in old version
                    //Concep_rate = ((730 - Anim_concep(rumcat)) * temp1 + (Anim_concep(rumcat) - 365) * temp2) / 365 ' interpolate between 12 & 24 months
                }
                break;

            case 1:
                // second offspring mother
                rate = female.BreedParams.ConceptionRateAsymptote[2] / (1 + Math.Exp(female.BreedParams.ConceptionRateCoefficent[2] * female.WeightAtConception / female.StandardReferenceWeight + female.BreedParams.ConceptionRateIntercept[2]));
                break;

            default:
                // females who have had more then one birth (twins should could as one birth)
                if (female.WeightAtConception > female.BreedParams.CriticalCowWeight * female.StandardReferenceWeight)
                {
                    rate = female.BreedParams.ConceptionRateAsymptote[3] / (1 + Math.Exp(female.BreedParams.ConceptionRateCoefficent[3] * female.WeightAtConception / female.StandardReferenceWeight + female.BreedParams.ConceptionRateIntercept[3]));
                }
                break;
            }
            return(rate);
        }
Ejemplo n.º 16
0
 /// <summary>
 /// A method to add the available male attributes to the female store at mating using attributes supplied by controlled mating
 /// </summary>
 /// <param name="female">The female breeder successfully mated</param>
 /// <param name="maleAttributes">a list of available male attributes setters</param>
 private void AddMalesAttributeDetails(RuminantFemale female, List <SetAttributeWithValue> maleAttributes)
 {
     foreach (var attribute in female.Attributes)
     {
         var maleAttribute = maleAttributes.Where(a => a.AttributeName == attribute.Key).FirstOrDefault();
         if (maleAttribute != null)
         {
             var calculatedAttribute = maleAttribute.GetRandomSetAttribute();
             if (attribute.Value.InheritanceStyle != calculatedAttribute.InheritanceStyle)
             {
                 throw new ApsimXException(this, $"The inheritance style for attribute [{attribute.Key}] differs between the breeder and attributes supplied by controlled mating in [a={this.Name}]");
             }
             attribute.Value.storedMateValue = calculatedAttribute.storedValue;
         }
         else
         {
             attribute.Value.storedMateValue = null;
             if (female.BreedParams.IsMandatoryAttribute(attribute.Key))
             {
                 throw new ApsimXException(this, $"The sire attributes provided for [a={this.Name}] do not include the madatory attribute [{attribute.Key}]");
             }
         }
     }
 }
Ejemplo n.º 17
0
        private void Muster()
        {
            // get herd to muster
            RuminantHerd    ruminantHerd = Resources.RuminantHerd();
            List <Ruminant> herd         = ruminantHerd.Herd;

            if (herd == null && herd.Count == 0)
            {
                return;
            }

            // get list from filters
            foreach (Ruminant ind in herd.Filter(this))
            {
                // set new location ID
                ind.Location = pasture.Name;

                // check if sucklings are to be moved with mother
                if (MoveSucklings)
                {
                    // if female
                    if (ind.GetType() == typeof(RuminantFemale))
                    {
                        RuminantFemale female = ind as RuminantFemale;
                        // check if mother with sucklings
                        if (female.SucklingOffspring.Count > 0)
                        {
                            foreach (var suckling in female.SucklingOffspring)
                            {
                                suckling.Location = pasture.Name;
                            }
                        }
                    }
                }
            }
        }
Ejemplo n.º 18
0
        /// <summary>
        /// Calculate conception rate for a female
        /// </summary>
        /// <param name="female">Female to calculate conception rate for</param>
        /// <returns></returns>
        private double ConceptionRate(RuminantFemale female)
        {
            double rate = 0;

            bool isConceptionReady = false;

            if (female.Age >= female.BreedParams.MinimumAge1stMating && female.NumberOfBirths == 0)
            {
                isConceptionReady = true;
            }
            else
            {
                double IPIcurrent = female.BreedParams.InterParturitionIntervalIntercept * Math.Pow((female.Weight / female.StandardReferenceWeight), female.BreedParams.InterParturitionIntervalCoefficient) * 30.64;
                // calculate inter-parturition interval
                IPIcurrent = Math.Max(IPIcurrent, female.BreedParams.GestationLength * 30.4 + female.BreedParams.MinimumDaysBirthToConception); // 2nd param was 61
                double ageNextConception = female.AgeAtLastConception + (IPIcurrent / 30.4);
                isConceptionReady = (female.Age >= ageNextConception);
            }

            // if first mating and of age or suffcient time since last birth/conception
            if (isConceptionReady)
            {
                // get advanced conception rate if available otherwise use defaults.
                if (female.BreedParams.AdvancedConceptionParameters != null)
                {
                    // generalised curve
                    switch (female.NumberOfBirths)
                    {
                    case 0:
                        // first mating
                        if (female.BreedParams.MinimumAge1stMating >= 24)
                        {
                            // 1st mated at 24 months or older
                            rate = female.BreedParams.AdvancedConceptionParameters.ConceptionRateAsymptote[1] / (1 + Math.Exp(female.BreedParams.AdvancedConceptionParameters.ConceptionRateCoefficent[1] * female.WeightAtConception / female.StandardReferenceWeight + female.BreedParams.AdvancedConceptionParameters.ConceptionRateIntercept[1]));
                        }
                        else if (female.BreedParams.MinimumAge1stMating >= 12)
                        {
                            // 1st mated between 12 and 24 months
                            double rate24 = female.BreedParams.AdvancedConceptionParameters.ConceptionRateAsymptote[1] / (1 + Math.Exp(female.BreedParams.AdvancedConceptionParameters.ConceptionRateCoefficent[1] * female.WeightAtConception / female.StandardReferenceWeight + female.BreedParams.AdvancedConceptionParameters.ConceptionRateIntercept[1]));
                            double rate12 = female.BreedParams.AdvancedConceptionParameters.ConceptionRateAsymptote[0] / (1 + Math.Exp(female.BreedParams.AdvancedConceptionParameters.ConceptionRateCoefficent[0] * female.WeightAtConception / female.StandardReferenceWeight + female.BreedParams.AdvancedConceptionParameters.ConceptionRateIntercept[0]));
                            rate = (rate12 + rate24) / 2;
                            // Not sure what the next code was doing in old version
                            //Concep_rate = ((730 - Anim_concep(rumcat)) * temp1 + (Anim_concep(rumcat) - 365) * temp2) / 365 ' interpolate between 12 & 24 months
                        }
                        else
                        {
                            // first mating < 12 months old
                            rate = female.BreedParams.AdvancedConceptionParameters.ConceptionRateAsymptote[0] / (1 + Math.Exp(female.BreedParams.AdvancedConceptionParameters.ConceptionRateCoefficent[0] * female.WeightAtConception / female.StandardReferenceWeight + female.BreedParams.AdvancedConceptionParameters.ConceptionRateIntercept[0]));
                        }
                        break;

                    case 1:
                        // second offspring mother
                        rate = female.BreedParams.AdvancedConceptionParameters.ConceptionRateAsymptote[2] / (1 + Math.Exp(female.BreedParams.AdvancedConceptionParameters.ConceptionRateCoefficent[2] * female.WeightAtConception / female.StandardReferenceWeight + female.BreedParams.AdvancedConceptionParameters.ConceptionRateIntercept[2]));
                        break;

                    default:
                        // females who have had more than two births (twins should count as one birth)
                        if (female.WeightAtConception > female.BreedParams.CriticalCowWeight * female.StandardReferenceWeight)
                        {
                            rate = female.BreedParams.AdvancedConceptionParameters.ConceptionRateAsymptote[3] / (1 + Math.Exp(female.BreedParams.AdvancedConceptionParameters.ConceptionRateCoefficent[3] * female.WeightAtConception / female.StandardReferenceWeight + female.BreedParams.AdvancedConceptionParameters.ConceptionRateIntercept[3]));
                        }
                        break;
                    }
                }
                else
                {
                    // use default values
                    rate = female.BreedParams.ConceptionRateAsymptote / (1 + Math.Exp(female.BreedParams.ConceptionRateCoefficent * female.WeightAtConception / female.StandardReferenceWeight + female.BreedParams.ConceptionRateIntercept));
                }
            }
            return(rate / 100);
        }
Ejemplo n.º 19
0
        /// <summary>
        /// Function to calculate energy from intake and subsequent growth
        /// </summary>
        /// <param name="ind">Ruminant individual class</param>
        /// <param name="methaneProduced">Sets output variable to value of methane produced</param>
        /// <returns></returns>
        private void CalculateEnergy(Ruminant ind, out double methaneProduced)
        {
            double intakeDaily          = ind.Intake / 30.4;
            double potentialIntakeDaily = ind.PotentialIntake / 30.4;

            // Sme 1 for females and castrates
            // TODO: castrates not implemented
            double Sme = 1;

            // Sme 1.15 for all males.
            if (ind.Gender == Sex.Male)
            {
                Sme = 1.15;
            }

            double energyDiet = EnergyGross * ind.DietDryMatterDigestibility / 100.0;
            // Reference: Nutrient Requirements of domesticated ruminants (p7)
            double energyMetabolic          = energyDiet * 0.81;
            double energyMetablicFromIntake = energyMetabolic * intakeDaily;

            double km = ind.BreedParams.EMaintCoefficient * energyMetabolic / EnergyGross + ind.BreedParams.EMaintIntercept;
            // Reference: SCA p.49
            double kg = ind.BreedParams.EGrowthCoefficient * energyMetabolic / EnergyGross + ind.BreedParams.EGrowthIntercept;

            double energyPredictedBodyMassChange = 0;
            double energyMaintenance             = 0;

            if (!ind.Weaned)
            {
                // calculate engergy and growth from milk intake

                // old code
                // dum = potential milk intake daily
                // dumshort = potential intake. check that it isnt monthly

                // Below now uses actual intake received rather than assume all potential intake is eaten
                double kml = 1;
                double kgl = 1;
                if ((ind.Intake + ind.MilkIntake) > 0)
                {
                    // average energy efficiency for maintenance
                    kml = ((ind.MilkIntake * 0.7) + (intakeDaily * km)) / (ind.MilkIntake + intakeDaily);
                    // average energy efficiency for growth
                    kgl = ((ind.MilkIntake * 0.7) + (intakeDaily * kg)) / (ind.MilkIntake + intakeDaily);
                }
                double energyMilkConsumed = ind.MilkIntake * 3.2;
                // limit calf intake of milk per day
                energyMilkConsumed = Math.Min(ind.BreedParams.MilkIntakeMaximum * 3.2, energyMilkConsumed);

                energyMaintenance = (ind.BreedParams.EMaintCoefficient * Math.Pow(ind.Weight, 0.75) / kml) * Math.Exp(-ind.BreedParams.EMaintExponent * ind.AgeZeroCorrected);
                ind.EnergyBalance = energyMilkConsumed - energyMaintenance + energyMetablicFromIntake;

                double feedingValue = 0;
                if (ind.EnergyBalance > 0)
                {
                    feedingValue = 2 * 0.7 * ind.EnergyBalance / (kgl * energyMaintenance) - 1;
                }
                else
                {
                    //(from Hirata model)
                    feedingValue = 2 * ind.EnergyBalance / (0.85 * energyMaintenance) - 1;
                }
                double energyEmptyBodyGain = ind.BreedParams.GrowthEnergyIntercept1 + feedingValue + (ind.BreedParams.GrowthEnergyIntercept2 - feedingValue) / (1 + Math.Exp(-6 * (ind.Weight / ind.NormalisedAnimalWeight - 0.4)));

                energyPredictedBodyMassChange = ind.BreedParams.GrowthEfficiency * 0.7 * ind.EnergyBalance / energyEmptyBodyGain;
            }
            else
            {
                double energyMilk   = 0;
                double energyFoetus = 0;

                if (ind.Gender == Sex.Female)
                {
                    RuminantFemale femaleind = ind as RuminantFemale;

                    // calculate energy for lactation
                    if (femaleind.IsLactating)
                    {
                        // Reference: SCA p.
                        double kl       = ind.BreedParams.ELactationCoefficient * energyMetabolic / EnergyGross + ind.BreedParams.ELactationIntercept;
                        double milkTime = Math.Max(0.0, (ind.Age - femaleind.AgeAtLastBirth + 1) * 30.4);
                        if (milkTime <= ind.BreedParams.MilkingDays)
                        {
                            double milkCurve = 0;
                            if (femaleind.DryBreeder)                             // no suckling calf
                            {
                                milkCurve = ind.BreedParams.MilkCurveNonSuckling;
                            }
                            else                             // suckling calf
                            {
                                milkCurve = ind.BreedParams.MilkCurveSuckling;
                            }
                            //TODO: check this equation that I redefined it correctly.
                            double milkProduction = ind.BreedParams.MilkPeakYield * ind.Weight / ind.NormalisedAnimalWeight * (Math.Pow(((milkTime + ind.BreedParams.MilkOffsetDay) / ind.BreedParams.MilkPeakDay), milkCurve)) * Math.Exp(milkCurve * (1 - (milkTime + ind.BreedParams.MilkOffsetDay) / ind.BreedParams.MilkPeakDay));
                            milkProduction = Math.Max(milkProduction, 0.0);
                            // Reference: Potential milk prodn, 3.2 MJ/kg milk - Jouven et al 2008
                            energyMilk = milkProduction * 3.2 / kl;
                            if (ind.EnergyBalance < (-0.5936 / 0.322 * energyMilk))
                            {
                                ind.EnergyBalance = (-0.5936 / 0.322 * energyMilk);
                            }
                            milkProduction = Math.Max(0.0, milkProduction * (0.5936 + 0.322 * ind.EnergyBalance / energyMilk));
                            // Reference: Adjusted milk prodn, 3.2 MJ/kg milk - Jouven et al 2008
                            energyMilk = milkProduction * 3.2 / kl;
                        }
                    }

                    // Determine energy required for foetal development
                    if (femaleind.IsPregnant)
                    {
                        double standardReferenceWeight = ind.StandardReferenceWeight;
                        // Potential birth weight
                        // Reference: Freer
                        double potentialBirthWeight = ind.BreedParams.SRWBirth * standardReferenceWeight * (1 - 0.33 * (1 - ind.Weight / standardReferenceWeight));
                        double foetusAge            = (femaleind.Age - femaleind.AgeAtLastConception + 1) * 30.4;
                        //TODO: Check foetus gage correct
                        energyFoetus = potentialBirthWeight * 349.16 * 0.000058 * Math.Exp(345.67 - 0.000058 * foetusAge - 349.16 * Math.Exp(-0.000058 * foetusAge)) / 0.13;
                    }
                }

                //TODO: add draft energy requirement

                // set maintenance age to maximum of 6 years
                double maintenanceAge = Math.Min(ind.Age * 30.4, 2190);

                // Reference: SCA p.24
                // Regference p19 (1.20). Does not include MEgraze or Ecold, also skips M,
                // 0.000082 is -0.03 Age in Years/365 for days
                energyMaintenance = ind.BreedParams.Kme * Sme * (0.26 * Math.Pow(ind.Weight, 0.75) / km) * Math.Exp(-0.000082 * maintenanceAge) + (0.09 * energyMetablicFromIntake);
                ind.EnergyBalance = energyMetablicFromIntake - energyMaintenance - energyMilk - energyFoetus;                 // milk will be zero for non lactating individuals.

                // Reference: Feeding_value = Ajustment for rate of loss or gain (SCA p.43, ? different from Hirata model)
                double feedingValue = 0;
                if (ind.EnergyBalance > 0)
                {
                    feedingValue = 2 * ((kg * ind.EnergyBalance) / (km * energyMaintenance) - 1);
                }
                else
                {
                    feedingValue = 2 * (ind.EnergyBalance / (0.8 * energyMaintenance) - 1);                      //(from Hirata model)
                }
                double weightToReferenceRatio = Math.Min(1.0, ind.Weight / ind.StandardReferenceWeight);

                // Reference:  MJ of Energy required per kg Empty body gain (SCA p.43)
                double energyEmptyBodyGain = ind.BreedParams.GrowthEnergyIntercept1 + feedingValue + (ind.BreedParams.GrowthEnergyIntercept1 - feedingValue) / (1 + Math.Exp(-6 * (weightToReferenceRatio - 0.4)));
                // Determine Empty body change from Eebg and Ebal, and increase by 9% for LW change
                energyPredictedBodyMassChange = 0;
                if (ind.EnergyBalance > 0)
                {
                    energyPredictedBodyMassChange = ind.BreedParams.GrowthEfficiency * kg * ind.EnergyBalance / energyEmptyBodyGain;
                }
                else
                {
                    // Reference: from Hirata model
                    energyPredictedBodyMassChange = ind.BreedParams.GrowthEfficiency * km * ind.EnergyBalance / (0.8 * energyEmptyBodyGain);
                }
            }
            energyPredictedBodyMassChange *= 30.4;              // Convert to monthly

            ind.PreviousWeight = ind.Weight;
            ind.Weight        += energyPredictedBodyMassChange;
            ind.Weight         = Math.Max(0.0, ind.Weight);
            ind.Weight         = Math.Min(ind.Weight, ind.StandardReferenceWeight * ind.BreedParams.MaximumSizeOfIndividual);

            // Function to calculate approximate methane produced by animal, based on feed intake
            // Function based on Freer spreadsheet
            methaneProduced  = 0.02 * intakeDaily * ((13 + 7.52 * energyMetabolic) + energyMetablicFromIntake / energyMaintenance * (23.7 - 3.36 * energyMetabolic)); // MJ per day
            methaneProduced /= 55.28 * 1000;                                                                                                                          // grams per day
        }
Ejemplo n.º 20
0
        private void OnCLEMAnimalManage(object sender, EventArgs e)
        {
            // purchase details only on timer
            if (TimingOK)
            {
                this.Status = ActivityStatus.NotNeeded;
                // remove any old potential sales from list as these will be updated here
                Resources.RuminantHerd().PurchaseIndividuals.RemoveAll(a => a.Breed == this.PredictedHerdBreed && a.SaleFlag == HerdChangeReason.TradePurchase);

                foreach (RuminantTypeCohort purchasetype in this.Children.Where(a => a.GetType() == typeof(RuminantTypeCohort)).Cast <RuminantTypeCohort>())
                {
                    double number = purchasetype.Number;
                    if (numberToStock != null && foodStore != null)
                    {
                        //NOTE: ensure calculation method in relationship is fixed values
                        number = Convert.ToInt32(numberToStock.SolveY(foodStore.TonnesPerHectare), CultureInfo.InvariantCulture);
                    }

                    for (int i = 0; i < number; i++)
                    {
                        object ruminantBase = null;

                        double u1            = RandomNumberGenerator.Generator.NextDouble();
                        double u2            = RandomNumberGenerator.Generator.NextDouble();
                        double randStdNormal = Math.Sqrt(-2.0 * Math.Log(u1)) *
                                               Math.Sin(2.0 * Math.PI * u2);
                        double weight = purchasetype.Weight + purchasetype.WeightSD * randStdNormal;

                        if (purchasetype.Gender == Sex.Male)
                        {
                            ruminantBase = new RuminantMale(purchasetype.Age, purchasetype.Gender, weight, herdToUse);
                        }
                        else
                        {
                            ruminantBase = new RuminantFemale(purchasetype.Age, purchasetype.Gender, weight, herdToUse);
                        }

                        Ruminant ruminant = ruminantBase as Ruminant;
                        ruminant.ID             = 0;
                        ruminant.Breed          = this.PredictedHerdBreed;
                        ruminant.HerdName       = this.PredictedHerdName;
                        ruminant.PurchaseAge    = purchasetype.Age;
                        ruminant.SaleFlag       = HerdChangeReason.TradePurchase;
                        ruminant.Location       = grazeStore;
                        ruminant.PreviousWeight = ruminant.Weight;

                        switch (purchasetype.Gender)
                        {
                        case Sex.Male:
                            RuminantMale ruminantMale = ruminantBase as RuminantMale;
                            ruminantMale.BreedingSire = false;
                            break;

                        case Sex.Female:
                            RuminantFemale ruminantFemale = ruminantBase as RuminantFemale;
                            ruminantFemale.DryBreeder         = true;
                            ruminantFemale.WeightAtConception = ruminant.Weight;
                            ruminantFemale.NumberOfBirths     = 0;
                            break;

                        default:
                            break;
                        }

                        Resources.RuminantHerd().PurchaseIndividuals.Add(ruminantBase as Ruminant);
                        this.Status = ActivityStatus.Success;
                    }
                }
            }
            // sale details any timestep when conditions are met.
            foreach (Ruminant ind in this.CurrentHerd(true))
            {
                if (ind.Age - ind.PurchaseAge >= MinMonthsKept)
                {
                    ind.SaleFlag = HerdChangeReason.TradeSale;
                    this.Status  = ActivityStatus.Success;
                }
                if (TradeWeight > 0 && ind.Weight >= TradeWeight)
                {
                    ind.SaleFlag = HerdChangeReason.TradeSale;
                    this.Status  = ActivityStatus.Success;
                }
            }
        }
Ejemplo n.º 21
0
        private void OnCLEMAnimalManage(object sender, EventArgs e)
        {
            RuminantHerd ruminantHerd = Resources.RuminantHerd();

            // remove only the individuals that are affected by this activity.
            // these are old purchases that were not made. This list will be regenerated in this method.
            ruminantHerd.PurchaseIndividuals.RemoveAll(a => a.Breed == this.PredictedHerdBreed);

            List <Ruminant> herd = this.CurrentHerd(true);

            // can sell off males any month as per NABSA
            // if we don't need this monthly, then it goes into next if statement with herd declaration
            // NABSA MALES - weaners, 1-2, 2-3 and 3-4 yo, we check for any male weaned and not a breeding sire.
            // check for sell age/weight of young males
            // if SellYoungFemalesLikeMales then all apply to both sexes else only males.
            // SellFemalesLikeMales will grow out excess heifers until age/weight rather than sell immediately.
            if (this.TimingOK || ContinuousMaleSales)
            {
                foreach (var ind in herd.Where(a => a.Weaned && (SellFemalesLikeMales ? true : (a.Gender == Sex.Male)) && (a.Age >= MaleSellingAge || a.Weight >= MaleSellingWeight)))
                {
                    bool sell = true;
                    if (ind.GetType() == typeof(RuminantMale))
                    {
                        // don't sell breeding sires.
                        sell = !((ind as RuminantMale).BreedingSire);
                    }
                    else
                    {
                        // only sell females that were marked as excess
                        sell = ind.Tags.Contains("GrowHeifer");
                    }

                    if (sell)
                    {
                        ind.SaleFlag = HerdChangeReason.AgeWeightSale;
                    }
                }
            }

            // if management month
            if (this.TimingOK)
            {
                // ensure pasture limits are ok before purchases
                bool sufficientFood = true;
                if (foodStore != null)
                {
                    sufficientFood = (foodStore.TonnesPerHectare * 1000) >= MinimumPastureBeforeRestock;
                }

                // check for maximum age (females and males have different cutoffs)
                foreach (var ind in herd.Where(a => a.Age >= ((a.Gender == Sex.Female) ? MaximumBreederAge : MaximumBullAge)))
                {
                    ind.SaleFlag = HerdChangeReason.MaxAgeSale;

                    // ensure females are not pregnant and add warning if pregnant old females found.
                    if (ind.Gender == Sex.Female && (ind as RuminantFemale).IsPregnant)
                    {
                        string warning = "Some females sold at maximum age in [a=" + this.Name + "] were pregnant.\nConsider changing the MaximumBreederAge in [a=RuminantActivityManage] or ensure [r=RuminantType.MaxAgeMating] is less than or equal to the MaximumBreederAge to avoid selling pregnant individuals.";
                        if (!Warnings.Exists(warning))
                        {
                            Warnings.Add(warning);
                            Summary.WriteWarning(this, warning);
                        }
                    }
                }

                // MALES
                // check for breeder bulls after sale of old individuals and buy/sell
                int numberMaleSiresInHerd = herd.Where(a => a.Gender == Sex.Male && a.SaleFlag == HerdChangeReason.None).Cast <RuminantMale>().Where(a => a.BreedingSire).Count();

                // Number of females
                int numberFemaleBreedingInHerd = herd.Where(a => a.Gender == Sex.Female && a.Age >= a.BreedParams.MinimumAge1stMating && a.SaleFlag == HerdChangeReason.None).Count();
                int numberFemaleTotalInHerd    = herd.Where(a => a.Gender == Sex.Female && a.SaleFlag == HerdChangeReason.None).Count();

                // these are females that will exceed max age and be sold in next 12 months
                int numberFemaleOldInHerd = herd.Where(a => a.Gender == Sex.Female && (a.Age + 12 >= MaximumBreederAge) && a.SaleFlag == HerdChangeReason.None).Count();

                // defined heifers here as weaned and will be a breeder in the next year
                int numberFemaleHeifersInHerd = herd.Where(a => a.Gender == Sex.Female && a.Weaned && ((a.Age - a.BreedParams.MinimumAge1stMating < 0) && (a.Age - a.BreedParams.MinimumAge1stMating > -12)) && a.SaleFlag == HerdChangeReason.None).Count();

                if (numberMaleSiresInHerd > SiresKept)
                {
                    // sell bulls
                    // What rule? oldest first as they may be lost soonest?
                    int numberToRemove = numberMaleSiresInHerd - SiresKept;
                    if (numberToRemove > 0)
                    {
                        foreach (var male in herd.Where(a => a.Gender == Sex.Male).Cast <RuminantMale>().Where(a => a.BreedingSire).OrderByDescending(a => a.Age).Take(numberToRemove))
                        {
                            male.SaleFlag = HerdChangeReason.ExcessBullSale;
                            numberToRemove--;
                            if (numberToRemove == 0)
                            {
                                break;
                            }
                        }
                    }
                }
                else if (numberMaleSiresInHerd < SiresKept)
                {
                    if ((foodStore == null) || (sufficientFood))
                    {
                        if (AllowSireReplacement)
                        {
                            // remove young bulls from sale herd to replace breed bulls (not those sold because too old)
                            foreach (RuminantMale male in herd.Where(a => a.Gender == Sex.Male && a.SaleFlag == HerdChangeReason.AgeWeightSale).OrderByDescending(a => a.Weight))
                            {
                                male.SaleFlag     = HerdChangeReason.None;
                                male.BreedingSire = true;
                                numberMaleSiresInHerd++;
                                if (numberMaleSiresInHerd >= SiresKept)
                                {
                                    break;
                                }
                            }
                            // if still insufficent, look into current herd for replacement
                            // remaining males assumed to be too small, so await next time-step
                        }

                        // if still insufficient buy bulls.
                        if (numberMaleSiresInHerd < SiresKept && (MaximumSiresPerPurchase > 0))
                        {
                            // limit by breeders as proportion of max breeders so we don't spend alot on sires when building the herd and females more valuable
                            double propOfBreeders = (double)numberFemaleBreedingInHerd / (double)MaximumBreedersKept;
                            propOfBreeders = 1;

                            int sires       = Convert.ToInt32(Math.Ceiling(Math.Ceiling(SiresKept * propOfBreeders)));
                            int numberToBuy = Math.Min(MaximumSiresPerPurchase, Math.Max(0, sires - numberMaleSiresInHerd));

                            for (int i = 0; i < numberToBuy; i++)
                            {
                                if (i < MaximumSiresPerPurchase)
                                {
                                    RuminantMale newbull = new RuminantMale(48, Sex.Male, 450, breedParams)
                                    {
                                        Location       = grazeStore,
                                        Breed          = this.PredictedHerdBreed,
                                        HerdName       = this.PredictedHerdName,
                                        BreedingSire   = true,
                                        Gender         = Sex.Male,
                                        ID             = 0, // Next unique ide will be assigned when added
                                        PreviousWeight = 450,
                                        SaleFlag       = HerdChangeReason.SirePurchase
                                    };

                                    // add to purchase request list and await purchase in Buy/Sell
                                    ruminantHerd.PurchaseIndividuals.Add(newbull);
                                }
                            }
                        }
                    }
                }

                // FEMALES
                // Breeding herd sold as heifers only, purchased as breeders (>= minAge1stMating)
                int excessBreeders = 0;

                // get the mortality rate for the herd if available or assume zero
                double mortalityRate = breedParams.MortalityBase;

                // shortfall between actual and desired numbers of breeders (-ve for shortfall)
                excessBreeders = numberFemaleBreedingInHerd - MaximumBreedersKept;
                // IAT-NABSA removes adjusts to account for the old animals that will be sold in the next year
                // This is not required in CLEM as they have been sold in this method, and it wont be until this method is called again that the next lot are sold.
                // Like IAT-NABSA we will account for mortality losses in the next year in our breeder purchases
                // Account for whole individuals only.
                int numberDyingInNextYear = Convert.ToInt32(Math.Floor(numberFemaleBreedingInHerd * mortalityRate), CultureInfo.InvariantCulture);
                // adjust for future mortality
                excessBreeders -= numberDyingInNextYear;

                // account for heifers already in the herd
                // These are the next cohort that will become breeders in the next 12 months (before this method is called again)
                excessBreeders += numberFemaleHeifersInHerd;

                if (excessBreeders > 0) // surplus heifers to sell
                {
                    foreach (var female in herd.Where(a => a.Gender == Sex.Female && (a as RuminantFemale).IsHeifer).Take(excessBreeders))
                    {
                        // if sell like males tag for grow out otherwise mark for sale
                        if (SellFemalesLikeMales)
                        {
                            if (!female.Tags.Contains("GrowHeifer"))
                            {
                                female.Tags.Add("GrowHeifer");
                            }
                        }
                        else
                        {
                            // tag for sale.
                            female.SaleFlag = HerdChangeReason.ExcessHeiferSale;
                        }
                        excessBreeders--;
                        if (excessBreeders == 0)
                        {
                            break;
                        }
                    }
                }
                else if (excessBreeders < 0) // shortfall heifers to buy
                {
                    double minBreedAge = breedParams.MinimumAge1stMating;
                    excessBreeders *= -1;
                    if ((foodStore == null) || (sufficientFood))
                    {
                        // remove grow out heifers from grow out herd to replace breeders
                        if (SellFemalesLikeMales)
                        {
                            foreach (Ruminant female in herd.Where(a => a.Tags.Contains("GrowHeifer")).OrderByDescending(a => a.Age))
                            {
                                female.Tags.Remove("GrowHeifer");
                                excessBreeders--;
                                if (excessBreeders == 0)
                                {
                                    break;
                                }
                            }
                        }

                        // remove young females from sale herd to replace breeders (not those sold because too old)
                        foreach (RuminantFemale female in herd.Where(a => a.Gender == Sex.Female && (a.SaleFlag == HerdChangeReason.AgeWeightSale || a.SaleFlag == HerdChangeReason.ExcessHeiferSale)).OrderByDescending(a => a.Age))
                        {
                            female.SaleFlag = HerdChangeReason.None;
                            excessBreeders--;
                            if (excessBreeders == 0)
                            {
                                break;
                            }
                        }

                        // if still insufficient buy breeders.
                        if (excessBreeders > 0 && (MaximumProportionBreedersPerPurchase > 0))
                        {
                            int ageOfBreeder = 0;

                            // IAT-NABSA had buy mortality base% more to account for deaths before these individuals grow to breeding age
                            // These individuals are already of breeding age so we will ignore this in CLEM
                            // minimum of (max kept x prop in single purchase) and (the number needed + annual mortality)
                            int numberToBuy             = Math.Min(excessBreeders, Convert.ToInt32(Math.Ceiling(MaximumProportionBreedersPerPurchase * MaximumBreedersKept), CultureInfo.InvariantCulture));
                            int numberPerPurchaseCohort = Convert.ToInt32(Math.Ceiling(numberToBuy / Convert.ToDouble(NumberOfBreederPurchaseAgeClasses, CultureInfo.InvariantCulture)), CultureInfo.InvariantCulture);

                            int numberBought = 0;
                            while (numberBought < numberToBuy)
                            {
                                int breederClass = Convert.ToInt32(numberBought / numberPerPurchaseCohort, CultureInfo.InvariantCulture);
                                ageOfBreeder = Convert.ToInt32(minBreedAge + (breederClass * 12), CultureInfo.InvariantCulture);

                                RuminantFemale newBreeder = new RuminantFemale(ageOfBreeder, Sex.Female, 0, breedParams)
                                {
                                    Location    = grazeStore,
                                    Breed       = this.PredictedHerdBreed,
                                    HerdName    = this.PredictedHerdName,
                                    BreedParams = breedParams,
                                    Gender      = Sex.Female,
                                    ID          = 0,
                                    SaleFlag    = HerdChangeReason.BreederPurchase
                                };
                                // weight will be set to normalised weight as it was assigned 0 at initialisation
                                newBreeder.PreviousWeight = newBreeder.Weight;

                                // this individual must be weaned to be permitted to start breeding.
                                newBreeder.Wean(false, "Initial");
                                // add to purchase request list and await purchase in Buy/Sell
                                ruminantHerd.PurchaseIndividuals.Add(newBreeder);
                                numberBought++;
                            }
                        }
                    }
                }
                // Breeders themselves don't get sold. Trading is with Heifers
                // Breeders can be sold in seasonal and ENSO destocking.
                // sell breeders
                // What rule? oldest first as they may be lost soonest
                // should keep pregnant females... and young...
                // this will currently remove pregnant females and females with suckling calf
            }
        }
Ejemplo n.º 22
0
        private void CalculatePotentialIntake(Ruminant ind)
        {
            // calculate daily potential intake for the selected individual/cohort
            double standardReferenceWeight = ind.StandardReferenceWeight;

            ind.NormalisedAnimalWeight = standardReferenceWeight - ((1 - ind.BreedParams.SRWBirth) * standardReferenceWeight) * Math.Exp(-(ind.BreedParams.AgeGrowthRateCoefficient * (ind.Age * 30.4)) / (Math.Pow(standardReferenceWeight, ind.BreedParams.SRWGrowthScalar)));
            double liveWeightForIntake = ind.NormalisedAnimalWeight;

            ind.HighWeight = Math.Max(ind.HighWeight, ind.Weight);
            if (ind.HighWeight < ind.NormalisedAnimalWeight)
            {
                liveWeightForIntake = ind.HighWeight;
            }

            // Calculate potential intake based on current weight compared to SRW and previous highest weight
            double potentialIntake = 0;

            // calculate milk intake shortfall for sucklings
            if (!ind.Weaned)
            {
                // potential milk intake/animal/day
                double potentialMilkIntake = ind.BreedParams.MilkIntakeIntercept + ind.BreedParams.IntakeCoefficient * ind.Weight;

                // get mother
                ind.MilkIntake = Math.Min(potentialMilkIntake, ind.MothersMilkAvailable);

                // if milk supply low, calf will subsitute forage up to a specified % of bodyweight (R_C60)
                if (ind.MilkIntake < ind.Weight * ind.BreedParams.MilkLWTFodderSubstitutionProportion)
                {
                    potentialIntake = Math.Max(0.0, ind.Weight * ind.BreedParams.MaxJuvenileIntake - ind.MilkIntake * ind.BreedParams.ProportionalDiscountDueToMilk);
                }

                // This has been removed and replaced with prop of LWT based on milk supply.
                // Reference: SCA Metabolic LWTs
                //potentialIntake = ind.BreedParams.IntakeCoefficient * standardReferenceWeight * (Math.Pow(liveWeightForIntake, 0.75) / Math.Pow(standardReferenceWeight, 0.75)) * (ind.BreedParams.IntakeIntercept - (Math.Pow(liveWeightForIntake, 0.75) / Math.Pow(standardReferenceWeight, 0.75)));
            }
            else
            {
                // Reference: SCA based actual LWTs
                potentialIntake = ind.BreedParams.IntakeCoefficient * liveWeightForIntake * (ind.BreedParams.IntakeIntercept - liveWeightForIntake / standardReferenceWeight);

                if (ind.Gender == Sex.Female)
                {
                    RuminantFemale femaleind = ind as RuminantFemale;

                    // Increase potential intake for lactating breeder
                    if (femaleind.IsLactating)
                    {
                        double dayOfLactation = Math.Max((ind.Age - femaleind.AgeAtLastBirth) * 30.4, 0);
                        if (dayOfLactation > ind.BreedParams.MilkingDays)
                        {
                            // Reference: Intake multiplier for lactating cow (M.Freer)
                            // TODO: Need to look at equation to fix Math.Pow() ^ issue
                            //					double intakeMilkMultiplier = 1 + 0.57 * Math.Pow((dayOfLactation / 81.0), 0.7) * Math.Exp(0.7 * (1 - (dayOfLactation / 81.0)));
                            double intakeMilkMultiplier = 1 + ind.BreedParams.LactatingPotentialModifierConstantA * Math.Pow((dayOfLactation / ind.BreedParams.LactatingPotentialModifierConstantB), ind.BreedParams.LactatingPotentialModifierConstantC) * Math.Exp(ind.BreedParams.LactatingPotentialModifierConstantC * (1 - (dayOfLactation / ind.BreedParams.LactatingPotentialModifierConstantB)));
                            // To make this flexible for sheep and goats, added three new Ruminant Coeffs
                            // Feeding standard values for Beef, Dairy suck, Dairy non-suck and sheep are:
                            // For 0.57 (A) use .42, .58, .85 and .69; for 0.7 (B) use 1.7, 0.7, 0.7 and 1.4, for 81 (C) use 62, 81, 81, 28
                            // added LactatingPotentialModifierConstantA, LactatingPotentialModifierConstantB and LactatingPotentialModifierConstantC
                            potentialIntake *= intakeMilkMultiplier;
                        }
                    }
                }
                //TODO: option to restrict potential further due to stress (e.g. heat, cold, rain)

                // get monthly intake
                potentialIntake *= 30.4;
            }
            ind.PotentialIntake = potentialIntake;
        }
Ejemplo n.º 23
0
        private void OnCLEMAnimalBreeding(object sender, EventArgs e)
        {
            List <Ruminant> herd = CurrentHerd(true);

            int aDay = Clock.Today.Year;

            // get list of all individuals of breeding age and condition
            // grouped by location
            var breeders = from ind in herd
                           where ind.IsBreedingCondition
                           group ind by ind.Location into grp
                           select grp;

            // calculate labour and finance limitations if needed when doing AI
            int    breedersCount  = breeders.Count();
            int    numberPossible = breedersCount;
            int    numberServiced = 1;
            double limiter        = 1;

            if (UseAI && TimingOK)
            {
                // attempt to get required resources
                List <ResourceRequest> resourcesneeded = GetResourcesNeededForActivityLocal();
                CheckResources(resourcesneeded, Guid.NewGuid());
                bool tookRequestedResources = TakeResources(resourcesneeded, true);
                // get all shortfalls
                if (tookRequestedResources && (ResourceRequestList != null))
                {
                    //TODO: fix this to account for perHead payments and labour and not fixed expenses
                    double amountCashNeeded     = resourcesneeded.Where(a => a.ResourceType == typeof(Finance)).Sum(a => a.Required);
                    double amountCashProvided   = resourcesneeded.Where(a => a.ResourceType == typeof(Finance)).Sum(a => a.Provided);
                    double amountLabourNeeded   = resourcesneeded.Where(a => a.ResourceType == typeof(Labour)).Sum(a => a.Required);
                    double amountLabourProvided = resourcesneeded.Where(a => a.ResourceType == typeof(Labour)).Sum(a => a.Provided);
                    double cashlimit            = 1;
                    if (amountCashNeeded > 0)
                    {
                        cashlimit = amountCashProvided == 0 ? 0 : amountCashNeeded / amountCashProvided;
                    }
                    double labourlimit = 1;
                    if (amountLabourNeeded > 0)
                    {
                        labourlimit = amountLabourProvided == 0 ? 0 : amountLabourNeeded / amountLabourProvided;
                    }
                    limiter = Math.Min(cashlimit, labourlimit);

                    // TODO: determine if fixed payments were not possible
                    // TODO: determine limits by insufficient labour or cash for per head payments
                }
                // report that this activity was performed as it does not use base GetResourcesRequired
                this.TriggerOnActivityPerformed();
            }

            if (!UseAI)
            {
                // report that this activity was performed as it does not use base GetResourcesRequired
                this.TriggerOnActivityPerformed();
                this.Status = ActivityStatus.NotNeeded;
            }

            // for each location where parts of this herd are located
            foreach (var location in breeders)
            {
                // determine all fetus and newborn mortality of all pregnant females.
                foreach (RuminantFemale female in location.Where(a => a.Gender == Sex.Female).Cast <RuminantFemale>().Where(a => a.IsPregnant).ToList())
                {
                    // calculate fetus and newborn mortality
                    // total mortality / (gestation months + 1) to get monthly mortality
                    // done here before births to account for post birth motality as well..
                    // IsPregnant status does not change until births occur in next section so will include mortality in month of birth
                    // needs to be caclulated for each offspring carried.
                    for (int i = 0; i < female.CarryingCount; i++)
                    {
                        if (RandomNumberGenerator.Generator.NextDouble() < (female.BreedParams.PrenatalMortality / (female.BreedParams.GestationLength + 1)))
                        {
                            female.OneOffspringDies();
                            if (female.NumberOfOffspring == 0)
                            {
                                // report conception status changed when last multiple birth dies.
                                female.BreedParams.OnConceptionStatusChanged(new Reporting.ConceptionStatusChangedEventArgs(Reporting.ConceptionStatus.Failed, female, Clock.Today));
                            }
                        }
                    }
                }

                // check for births of all pregnant females.
                int month = Clock.Today.Month;
                foreach (RuminantFemale female in location.Where(a => a.Gender == Sex.Female).Cast <RuminantFemale>().ToList())
                {
                    if (female.BirthDue)
                    {
                        int numberOfNewborn = female.CarryingCount;
                        for (int i = 0; i < numberOfNewborn; i++)
                        {
                            // Foetal mortality is now performed each timestep at base of this method
                            object newCalf = null;
                            bool   isMale  = (RandomNumberGenerator.Generator.NextDouble() <= female.BreedParams.ProportionOffspringMale);
                            double weight  = female.BreedParams.SRWBirth * female.StandardReferenceWeight * (1 - 0.33 * (1 - female.Weight / female.StandardReferenceWeight));
                            if (isMale)
                            {
                                newCalf = new RuminantMale(0, Sex.Male, weight, female.BreedParams);
                            }
                            else
                            {
                                newCalf = new RuminantFemale(0, Sex.Female, weight, female.BreedParams);
                            }
                            Ruminant newCalfRuminant = newCalf as Ruminant;
                            newCalfRuminant.HerdName = female.HerdName;
                            newCalfRuminant.Breed    = female.BreedParams.Breed;
                            newCalfRuminant.ID       = Resources.RuminantHerd().NextUniqueID;
                            newCalfRuminant.Location = female.Location;
                            newCalfRuminant.Mother   = female;
                            newCalfRuminant.Number   = 1;
                            newCalfRuminant.SetUnweaned();
                            // calf weight from  Freer
                            newCalfRuminant.PreviousWeight = newCalfRuminant.Weight;
                            newCalfRuminant.SaleFlag       = HerdChangeReason.Born;
                            Resources.RuminantHerd().AddRuminant(newCalfRuminant, this);

                            // add to sucklings
                            female.SucklingOffspringList.Add(newCalfRuminant);
                            // this now reports for each individual born not a birth event as individual wean events are reported
                            female.BreedParams.OnConceptionStatusChanged(new Reporting.ConceptionStatusChangedEventArgs(Reporting.ConceptionStatus.Birth, female, Clock.Today));
                        }
                        female.UpdateBirthDetails();
                        this.Status = ActivityStatus.Success;
                    }
                }

                numberPossible = -1;
                if (!UseAI)
                {
                    numberPossible = 0;
                    // uncontrolled conception
                    if (location.GroupBy(a => a.Gender).Count() == 2)
                    {
                        int maleCount   = location.Where(a => a.Gender == Sex.Male).Count();
                        int femaleCount = location.Where(a => a.Gender == Sex.Female).Count();
                        numberPossible = Convert.ToInt32(Math.Ceiling(maleCount * location.FirstOrDefault().BreedParams.MaximumMaleMatingsPerDay * 30), CultureInfo.InvariantCulture);
                    }
                }
                else
                {
                    // controlled mating (AI)
                    if (this.TimingOK)
                    {
                        numberPossible = Convert.ToInt32(limiter * location.Where(a => a.Gender == Sex.Female).Count(), CultureInfo.InvariantCulture);
                    }
                }

                numberServiced = 1;
                foreach (RuminantFemale female in location.Where(a => a.Gender == Sex.Female).Cast <RuminantFemale>().Where(a => !a.IsPregnant & a.Age <= a.BreedParams.MaximumAgeMating).ToList())
                {
                    Reporting.ConceptionStatus status = Reporting.ConceptionStatus.NotMated;
                    if (numberServiced <= numberPossible)
                    {
                        // calculate conception
                        double conceptionRate = ConceptionRate(female, out status);
                        if (conceptionRate > 0)
                        {
                            if (RandomNumberGenerator.Generator.NextDouble() <= conceptionRate)
                            {
                                female.UpdateConceptionDetails(female.CalulateNumberOfOffspringThisPregnancy(), conceptionRate, 0);
                                status = Reporting.ConceptionStatus.Conceived;
                            }
                        }
                        numberServiced++;
                        this.Status = ActivityStatus.Success;
                    }

                    // report change in breeding status
                    // do not report for -1 (controlled mating outside timing)
                    if (numberPossible >= 0 && status != Reporting.ConceptionStatus.NotAvailable)
                    {
                        female.BreedParams.OnConceptionStatusChanged(new Reporting.ConceptionStatusChangedEventArgs(status, female, Clock.Today));
                    }
                }

                // report a natural mating locations for transparency via a message
                if (this.Status == ActivityStatus.Success && !UseAI)
                {
                    string warning = "Natural (uncontrolled) mating ocurred in [r=" + location.Key + "]";
                    if (!Warnings.Exists(warning))
                    {
                        Warnings.Add(warning);
                        Summary.WriteMessage(this, warning);
                    }
                }
            }
        }
Ejemplo n.º 24
0
        private void OnCLEMAnimalBreeding(object sender, EventArgs e)
        {
            this.Status     = ActivityStatus.NotNeeded;
            NumberConceived = 0;

            // get list of all pregnant females
            List <RuminantFemale> pregnantherd = CurrentHerd(true).Where(a => a.Gender == Sex.Female).Cast <RuminantFemale>().Where(a => a.IsPregnant).ToList();

            // determine all fetus and newborn mortality of all pregnant females.
            foreach (RuminantFemale female in pregnantherd)
            {
                // calculate fetus and newborn mortality
                // total mortality / (gestation months + 1) to get monthly mortality
                // done here before births to account for post birth motality as well..
                // IsPregnant status does not change until births occur in next section so will include mortality in month of birth
                // needs to be calculated for each offspring carried.
                for (int i = 0; i < female.CarryingCount; i++)
                {
                    if (RandomNumberGenerator.Generator.NextDouble() < (female.BreedParams.PrenatalMortality / (female.BreedParams.GestationLength + 1)))
                    {
                        female.OneOffspringDies();
                        if (female.NumberOfOffspring == 0)
                        {
                            // report conception status changed when last multiple birth dies.
                            female.BreedParams.OnConceptionStatusChanged(new Reporting.ConceptionStatusChangedEventArgs(Reporting.ConceptionStatus.Failed, female, Clock.Today));
                        }
                    }
                }

                if (female.BirthDue)
                {
                    int numberOfNewborn = female.CarryingCount;
                    for (int i = 0; i < numberOfNewborn; i++)
                    {
                        object newCalf = null;
                        bool   isMale  = (RandomNumberGenerator.Generator.NextDouble() <= female.BreedParams.ProportionOffspringMale);
                        double weight  = female.BreedParams.SRWBirth * female.StandardReferenceWeight * (1 - 0.33 * (1 - female.Weight / female.StandardReferenceWeight));
                        if (isMale)
                        {
                            newCalf = new RuminantMale(0, Sex.Male, weight, female.BreedParams);
                        }
                        else
                        {
                            newCalf = new RuminantFemale(0, Sex.Female, weight, female.BreedParams);
                        }
                        Ruminant newCalfRuminant = newCalf as Ruminant;
                        newCalfRuminant.HerdName = female.HerdName;
                        newCalfRuminant.Breed    = female.BreedParams.Breed;
                        newCalfRuminant.ID       = Resources.RuminantHerd().NextUniqueID;
                        newCalfRuminant.Location = female.Location;
                        newCalfRuminant.Mother   = female;
                        newCalfRuminant.Number   = 1;
                        newCalfRuminant.SetUnweaned();
                        // calf weight from  Freer
                        newCalfRuminant.PreviousWeight = newCalfRuminant.Weight;
                        newCalfRuminant.SaleFlag       = HerdChangeReason.Born;

                        // add attributes inherited from mother
                        foreach (var attribute in female.Attributes)
                        {
                            newCalfRuminant.AddAttribute(attribute.Key, attribute.Value.GetInheritedAttribute() as ICLEMAttribute);
                        }

                        Resources.RuminantHerd().AddRuminant(newCalfRuminant, this);

                        // add to sucklings
                        female.SucklingOffspringList.Add(newCalfRuminant);
                        // this now reports for each individual born not a birth event as individual wean events are reported
                        female.BreedParams.OnConceptionStatusChanged(new Reporting.ConceptionStatusChangedEventArgs(Reporting.ConceptionStatus.Birth, female, Clock.Today));
                    }
                    female.UpdateBirthDetails();
                    this.Status = ActivityStatus.Success;
                }
            }

            // Perform breeding
            IEnumerable <Ruminant> herd = null;

            if (useControlledMating && controlledMating.TimingOK)
            {
                // determined by controlled mating and subsequent timer (e.g. smart milking)
                herd = controlledMating.BreedersToMate();
                this.TriggerOnActivityPerformed();
            }
            else if (!useControlledMating && TimingOK)
            {
                // whole herd for activity
                herd = CurrentHerd(true);
                // report that this activity was performed as it does not use base GetResourcesRequired
                this.TriggerOnActivityPerformed();
            }

            if (herd != null && herd.Count() > 0)
            {
                // group by location
                var breeders = from ind in herd
                               where ind.IsAbleToBreed
                               group ind by ind.Location into grp
                               select grp;

                int             breedersCount  = breeders.Count();
                int             numberPossible = breedersCount;
                int             numberServiced = 1;
                List <Ruminant> maleBreeders   = new List <Ruminant>();

                // for each location where parts of this herd are located
                foreach (var location in breeders)
                {
                    numberPossible = -1;
                    if (useControlledMating)
                    {
                        numberPossible = Convert.ToInt32(location.Where(a => a.Gender == Sex.Female).Count(), CultureInfo.InvariantCulture);
                    }
                    else
                    {
                        numberPossible = 0;
                        // uncontrolled conception
                        if (location.GroupBy(a => a.Gender).Count() == 2)
                        {
                            int maleCount = location.Where(a => a.Gender == Sex.Male).Count();
                            // get a list of males to provide attributes when incontrolled mating.
                            if (maleCount > 0 && location.FirstOrDefault().BreedParams.IncludedAttributeInheritanceWhenMating)
                            {
                                maleBreeders = location.Where(a => a.Gender == Sex.Male).ToList();
                            }
                            int femaleCount = location.Where(a => a.Gender == Sex.Female).Count();
                            numberPossible = Convert.ToInt32(Math.Ceiling(maleCount * location.FirstOrDefault().BreedParams.MaximumMaleMatingsPerDay * 30), CultureInfo.InvariantCulture);
                        }
                    }

                    numberServiced = 1;
                    foreach (RuminantFemale female in location.Where(a => a.Gender == Sex.Female).Cast <RuminantFemale>().Where(a => !a.IsPregnant & a.Age <= a.BreedParams.MaximumAgeMating).ToList())
                    {
                        Reporting.ConceptionStatus status = Reporting.ConceptionStatus.NotMated;
                        if (numberServiced <= numberPossible)
                        {
                            // calculate conception
                            double conceptionRate = ConceptionRate(female, out status);
                            if (conceptionRate > 0)
                            {
                                if (RandomNumberGenerator.Generator.NextDouble() <= conceptionRate)
                                {
                                    female.UpdateConceptionDetails(female.CalulateNumberOfOffspringThisPregnancy(), conceptionRate, 0);

                                    // if mandatory attributes are present in the herd, save male value with female details.
                                    if (female.BreedParams.IncludedAttributeInheritanceWhenMating)
                                    {
                                        if (useControlledMating)
                                        {
                                            // save all male attributes
                                            AddMalesAttributeDetails(female, controlledMating.SireAttributes);
                                        }
                                        else
                                        {
                                            // randomly select male
                                            AddMalesAttributeDetails(female, maleBreeders[RandomNumberGenerator.Generator.Next(0, maleBreeders.Count() - 1)]);
                                        }
                                    }
                                    status = Reporting.ConceptionStatus.Conceived;
                                    NumberConceived++;
                                }
                            }
                            numberServiced++;
                            this.Status = ActivityStatus.Success;
                        }

                        // report change in breeding status
                        // do not report for -1 (controlled mating outside timing)
                        if (numberPossible >= 0 && status != Reporting.ConceptionStatus.NotAvailable)
                        {
                            female.BreedParams.OnConceptionStatusChanged(new Reporting.ConceptionStatusChangedEventArgs(status, female, Clock.Today));
                        }
                    }

                    // report a natural mating locations for transparency via a message
                    if (numberServiced > 0 & !useControlledMating)
                    {
                        string warning = "Natural (uncontrolled) mating ocurred in [r=" + location.Key + "]";
                        if (!Warnings.Exists(warning))
                        {
                            Warnings.Add(warning);
                            Summary.WriteMessage(this, warning);
                        }
                    }
                }
            }
        }
Ejemplo n.º 25
0
        private void OnCLEMAnimalManage(object sender, EventArgs e)
        {
            // purchase details only on timer
            if (TimingOK)
            {
                // remove any old potential sales from list as these will be updated here
                Resources.RuminantHerd().PurchaseIndividuals.RemoveAll(a => a.Breed == this.PredictedHerdBreed & a.SaleFlag == HerdChangeReason.TradePurchase);

                foreach (RuminantTypeCohort purchasetype in this.Children.Where(a => a.GetType() == typeof(RuminantTypeCohort)).Cast <RuminantTypeCohort>())
                {
                    for (int i = 0; i < purchasetype.Number; i++)
                    {
                        object ruminantBase = null;
                        if (purchasetype.Gender == Sex.Male)
                        {
                            ruminantBase = new RuminantMale();
                        }
                        else
                        {
                            ruminantBase = new RuminantFemale();
                        }

                        Ruminant ruminant = ruminantBase as Ruminant;
                        ruminant.ID          = 0;
                        ruminant.BreedParams = herdToUse;
                        ruminant.Breed       = this.PredictedHerdBreed;
                        ruminant.HerdName    = this.PredictedHerdName;
                        ruminant.Gender      = purchasetype.Gender;
                        ruminant.Age         = purchasetype.Age;
                        ruminant.PurchaseAge = purchasetype.Age;
                        ruminant.SaleFlag    = HerdChangeReason.TradePurchase;
                        ruminant.Location    = "";

                        double u1            = ZoneCLEM.RandomGenerator.NextDouble();
                        double u2            = ZoneCLEM.RandomGenerator.NextDouble();
                        double randStdNormal = Math.Sqrt(-2.0 * Math.Log(u1)) *
                                               Math.Sin(2.0 * Math.PI * u2);
                        ruminant.Weight         = purchasetype.Weight + purchasetype.WeightSD * randStdNormal;
                        ruminant.PreviousWeight = ruminant.Weight;

                        switch (purchasetype.Gender)
                        {
                        case Sex.Male:
                            RuminantMale ruminantMale = ruminantBase as RuminantMale;
                            ruminantMale.BreedingSire = false;
                            break;

                        case Sex.Female:
                            RuminantFemale ruminantFemale = ruminantBase as RuminantFemale;
                            ruminantFemale.DryBreeder         = true;
                            ruminantFemale.WeightAtConception = ruminant.Weight;
                            ruminantFemale.NumberOfBirths     = 0;
                            break;

                        default:
                            break;
                        }

                        Resources.RuminantHerd().PurchaseIndividuals.Add(ruminantBase as Ruminant);
                    }
                }
                //this.TriggerOnActivityPerformed();
            }
            // sale details any timestep when conditions are met.
            foreach (Ruminant ind in this.CurrentHerd(true))
            {
                if (ind.Age - ind.PurchaseAge >= MinMonthsKept & ind.Weight >= TradeWeight)
                {
                    ind.SaleFlag = HerdChangeReason.TradeSale;
                }
            }
        }
Ejemplo n.º 26
0
        /// <summary>
        /// Function to calculate energy from intake and subsequent growth
        /// </summary>
        /// <param name="ind">Ruminant individual class</param>
        /// <param name="methaneProduced">Sets output variable to value of methane produced</param>
        /// <returns></returns>
        private void CalculateEnergy(Ruminant ind, out double methaneProduced)
        {
            double intakeDaily = ind.MetabilicIntake / 30.4;

            // Sme 1 for females and castrates
            // TODO: castrates not implemented
            double sme = 1;

            // Sme 1.15 for all males.
            if (ind.Gender == Sex.Male)
            {
                sme = 1.15;
            }

            double energyDiet = EnergyGross * ind.DietDryMatterDigestibility / 100.0;
            // Reference: Nutrient Requirements of domesticated ruminants (p7)
            double energyMetabolic          = energyDiet * 0.81;
            double energyMetablicFromIntake = energyMetabolic * intakeDaily;

            double km = ind.BreedParams.EMaintEfficiencyCoefficient * energyMetabolic / EnergyGross + ind.BreedParams.EMaintEfficiencyIntercept;
            // Reference: SCA p.49
            double kg = ind.BreedParams.EGrowthEfficiencyCoefficient * energyMetabolic / EnergyGross + ind.BreedParams.EGrowthEfficiencyIntercept;
            double energyPredictedBodyMassChange;
            double energyMaintenance;

            if (!ind.Weaned)
            {
                // calculate engergy and growth from milk intake

                // recalculate milk intake based on mothers updated milk production for the time step
                double potentialMilkIntake = ind.BreedParams.MilkIntakeIntercept + ind.BreedParams.MilkIntakeCoefficient * ind.Weight;
                ind.MilkIntake = Math.Min(potentialMilkIntake, ind.MothersMilkProductionAvailable);
                if (ind.Mother != null)
                {
                    ind.Mother.TakeMilk(ind.MilkIntake * 30.4, MilkUseReason.Suckling);
                }

                // Below now uses actual intake received rather than assume all potential intake is eaten
                double kml = 1;
                double kgl = 1;
                if ((ind.MetabilicIntake + ind.MilkIntake) > 0)
                {
                    // average energy efficiency for maintenance
                    kml = ((ind.MilkIntake * 0.7) + (intakeDaily * km)) / (ind.MilkIntake + intakeDaily);
                    // average energy efficiency for growth
                    kgl = ((ind.MilkIntake * 0.7) + (intakeDaily * kg)) / (ind.MilkIntake + intakeDaily);
                }
                double energyMilkConsumed = ind.MilkIntake * 3.2;
                // limit calf intake of milk per day
                energyMilkConsumed = Math.Min(ind.BreedParams.MilkIntakeMaximum * 3.2, energyMilkConsumed);

                energyMaintenance = (ind.BreedParams.EMaintCoefficient * Math.Pow(ind.Weight, 0.75) / kml) * Math.Exp(-ind.BreedParams.EMaintExponent * ind.AgeZeroCorrected);
                ind.EnergyBalance = energyMilkConsumed - energyMaintenance + energyMetablicFromIntake;
                double feedingValue;
                if (ind.EnergyBalance > 0)
                {
                    feedingValue = 2 * 0.7 * ind.EnergyBalance / (kgl * energyMaintenance) - 1;
                }
                else
                {
                    //(from Hirata model)
                    feedingValue = 2 * ind.EnergyBalance / (0.85 * energyMaintenance) - 1;
                }
                double energyEmptyBodyGain = ind.BreedParams.GrowthEnergyIntercept1 + feedingValue + (ind.BreedParams.GrowthEnergyIntercept2 - feedingValue) / (1 + Math.Exp(-6 * (ind.Weight / ind.NormalisedAnimalWeight - 0.4)));

                energyPredictedBodyMassChange = ind.BreedParams.GrowthEfficiency * 0.7 * ind.EnergyBalance / energyEmptyBodyGain;
            }
            else
            {
                double energyMilk   = 0;
                double energyFoetus = 0;

                if (ind.Gender == Sex.Female)
                {
                    RuminantFemale femaleind = ind as RuminantFemale;

                    // calculate energy for lactation
                    if (femaleind.IsLactating)
                    {
                        // recalculate milk production based on DMD of food provided
                        energyMilk = CalculateMilkProduction(femaleind);
                    }
                    else
                    {
                        femaleind.MilkProductionPotential = 0;
                    }

                    // Determine energy required for foetal development
                    if (femaleind.IsPregnant)
                    {
                        double standardReferenceWeight = ind.StandardReferenceWeight;
                        // Potential birth weight
                        // Reference: Freer
                        double potentialBirthWeight = ind.BreedParams.SRWBirth * standardReferenceWeight * (1 - 0.33 * (1 - ind.Weight / standardReferenceWeight));
                        double foetusAge            = (femaleind.Age - femaleind.AgeAtLastConception) * 30.4;
                        //TODO: Check foetus gage correct
                        energyFoetus = potentialBirthWeight * 349.16 * 0.000058 * Math.Exp(345.67 - 0.000058 * foetusAge - 349.16 * Math.Exp(-0.000058 * foetusAge)) / 0.13;
                    }
                }

                //TODO: add draft individual energy requirement

                // set maintenance age to maximum of 6 years (2190 days). Now uses EnergeyMaintenanceMaximumAge
                double maintenanceAge = Math.Min(ind.Age * 30.4, ind.BreedParams.EnergyMaintenanceMaximumAge * 365);

                // Reference: SCA p.24
                // Reference p19 (1.20). Does not include MEgraze or Ecold, also skips M,
                // 0.000082 is -0.03 Age in Years/365 for days
                energyMaintenance = ind.BreedParams.Kme * sme * (ind.BreedParams.EMaintCoefficient * Math.Pow(ind.Weight, 0.75) / km) * Math.Exp(-ind.BreedParams.EMaintExponent * maintenanceAge) + (ind.BreedParams.EMaintIntercept * energyMetablicFromIntake);
                ind.EnergyBalance = energyMetablicFromIntake - energyMaintenance - energyMilk - energyFoetus; // milk will be zero for non lactating individuals.
                double feedingValue;

                // Reference: Feeding_value = Ajustment for rate of loss or gain (SCA p.43, ? different from Hirata model)
                if (ind.EnergyBalance > 0)
                {
                    feedingValue = 2 * ((kg * ind.EnergyBalance) / (km * energyMaintenance) - 1);
                }
                else
                {
                    feedingValue = 2 * (ind.EnergyBalance / (0.8 * energyMaintenance) - 1);  //(from Hirata model)
                }
                double weightToReferenceRatio = Math.Min(1.0, ind.Weight / ind.StandardReferenceWeight);

                // Reference:  MJ of Energy required per kg Empty body gain (SCA p.43)
                double energyEmptyBodyGain = ind.BreedParams.GrowthEnergyIntercept1 + feedingValue + (ind.BreedParams.GrowthEnergyIntercept1 - feedingValue) / (1 + Math.Exp(-6 * (weightToReferenceRatio - 0.4)));
                // Determine Empty body change from Eebg and Ebal, and increase by 9% for LW change
                if (ind.EnergyBalance > 0)
                {
                    energyPredictedBodyMassChange = ind.BreedParams.GrowthEfficiency * kg * ind.EnergyBalance / energyEmptyBodyGain;
                }
                else
                {
                    // Reference: from Hirata model
                    energyPredictedBodyMassChange = ind.BreedParams.GrowthEfficiency * km * ind.EnergyBalance / (0.8 * energyEmptyBodyGain);
                }
            }
            energyPredictedBodyMassChange *= 30.4;  // Convert to monthly

            ind.PreviousWeight = ind.Weight;
            if (ind.Gender == Sex.Female && (ind as RuminantFemale).BirthDue)
            {
                ind.Weight -= (ind as RuminantFemale).WeightLossDueToCalf;
            }
            ind.Weight += energyPredictedBodyMassChange;
            ind.Weight  = Math.Max(0.0, ind.Weight);
            ind.Weight  = Math.Min(ind.Weight, ind.StandardReferenceWeight * ind.BreedParams.MaximumSizeOfIndividual);

            // Function to calculate approximate methane produced by animal, based on feed intake
            // Function based on Freer spreadsheet
            // methane is  0.02 * intakeDaily * ((13 + 7.52 * energyMetabolic) + energyMetablicFromIntake / energyMaintenance * (23.7 - 3.36 * energyMetabolic)); // MJ per day
            // methane is methaneProduced / 55.28 * 1000; // grams per day

            // Charmely et al 2016 can be substituted by intercept = 0 and coefficient = 20.7
            methaneProduced = ind.BreedParams.MethaneProductionCoefficient * intakeDaily;
        }
Ejemplo n.º 27
0
        private void CalculatePotentialIntake(Ruminant ind)
        {
            // calculate daily potential intake for the selected individual/cohort
            double standardReferenceWeight = ind.StandardReferenceWeight;

            // now calculated in Ruminant
            // ind.NormalisedAnimalWeight = standardReferenceWeight - ((1 - ind.BreedParams.SRWBirth) * standardReferenceWeight) * Math.Exp(-(ind.BreedParams.AgeGrowthRateCoefficient * (ind.Age * 30.4)) / (Math.Pow(standardReferenceWeight, ind.BreedParams.SRWGrowthScalar)));
            double liveWeightForIntake = ind.NormalisedAnimalWeight;

            // now performed at allocation of weight in Ruminant
            if (ind.HighWeight < ind.NormalisedAnimalWeight)
            {
                liveWeightForIntake = ind.HighWeight;
            }

            // Calculate potential intake based on current weight compared to SRW and previous highest weight
            double potentialIntake = 0;

            ind.MilkIntakePotential = 0;

            // calculate milk intake shortfall for sucklings
            if (!ind.Weaned)
            {
                // potential milk intake/animal/day
                ind.MilkIntakePotential = ind.BreedParams.MilkIntakeIntercept + ind.BreedParams.MilkIntakeCoefficient * ind.Weight;

                // get estimated milk available
                // this will be updated to the corrected milk available in the calculate energy section.
                ind.MilkIntake = Math.Min(ind.MilkIntakePotential, ind.MothersMilkProductionAvailable);

                // if milk supply low, calf will subsitute forage up to a specified % of bodyweight (R_C60)
                if (ind.MilkIntake < ind.Weight * ind.BreedParams.MilkLWTFodderSubstitutionProportion)
                {
                    potentialIntake = Math.Max(0.0, ind.Weight * ind.BreedParams.MaxJuvenileIntake - ind.MilkIntake * ind.BreedParams.ProportionalDiscountDueToMilk);
                }
            }
            else
            {
                if (ind.Weaner)
                {
                    // Reference: SCA Metabolic LWTs
                    // restored in v112 of NABSA for weaner animals
                    potentialIntake = ind.BreedParams.IntakeCoefficient * standardReferenceWeight * (Math.Pow(liveWeightForIntake, 0.75) / Math.Pow(standardReferenceWeight, 0.75)) * (ind.BreedParams.IntakeIntercept - (Math.Pow(liveWeightForIntake, 0.75) / Math.Pow(standardReferenceWeight, 0.75)));
                    // older individual check. previous method before adding calulation for weaners after discussions with Cam McD
                    //double prevint = ind.BreedParams.IntakeCoefficient * liveWeightForIntake * (ind.BreedParams.IntakeIntercept - liveWeightForIntake / standardReferenceWeight);
                }
                else // 12month+ individuals
                {
                    // Reference: SCA based actual LWTs
                    potentialIntake = ind.BreedParams.IntakeCoefficient * liveWeightForIntake * (ind.BreedParams.IntakeIntercept - liveWeightForIntake / standardReferenceWeight);
                }

                if (ind.Gender == Sex.Female)
                {
                    RuminantFemale femaleind = ind as RuminantFemale;
                    // Increase potential intake for lactating breeder
                    if (femaleind.IsLactating)
                    {
                        // move to half way through timestep
                        double dayOfLactation = femaleind.DaysLactating;
                        // Reference: Intake multiplier for lactating cow (M.Freer)
                        // double intakeMilkMultiplier = 1 + 0.57 * Math.Pow((dayOfLactation / 81.0), 0.7) * Math.Exp(0.7 * (1 - (dayOfLactation / 81.0)));
                        double intakeMilkMultiplier = 1 + ind.BreedParams.LactatingPotentialModifierConstantA * Math.Pow((dayOfLactation / ind.BreedParams.LactatingPotentialModifierConstantB), ind.BreedParams.LactatingPotentialModifierConstantC) * Math.Exp(ind.BreedParams.LactatingPotentialModifierConstantC * (1 - (dayOfLactation / ind.BreedParams.LactatingPotentialModifierConstantB))) * (1 - 0.5 + 0.5 * (ind.Weight / ind.NormalisedAnimalWeight));

                        // To make this flexible for sheep and goats, added three new Ruminant Coeffs
                        // Feeding standard values for Beef, Dairy suck, Dairy non-suck and sheep are:
                        // For 0.57 (A) use .42, .58, .85 and .69; for 0.7 (B) use 1.7, 0.7, 0.7 and 1.4, for 81 (C) use 62, 81, 81, 28
                        // added LactatingPotentialModifierConstantA, LactatingPotentialModifierConstantB and LactatingPotentialModifierConstantC
                        // replaces (A), (B) and (C)
                        potentialIntake *= intakeMilkMultiplier;

                        // calculate estimated milk production for time step here
                        // assuming average feed quality if no previous diet values
                        // This need to happen before suckling potential intake can be determined.
                        CalculateMilkProduction(femaleind);
                        femaleind.MilkProducedThisTimeStep = femaleind.MilkProduction * 30.4;
                    }
                    else
                    {
                        femaleind.MilkProduction = 0;
                    }
                }

                //TODO: option to restrict potential further due to stress (e.g. heat, cold, rain)
            }
            // get monthly intake
            potentialIntake    *= 30.4;
            ind.PotentialIntake = potentialIntake;
        }
Ejemplo n.º 28
0
        private void OnCLEMAnimalBreeding(object sender, EventArgs e)
        {
//            RuminantHerd ruminantHerd = Resources.RuminantHerd();
            List <Ruminant> herd = CurrentHerd(true); //ruminantHerd.Herd.Where(a => a.BreedParams.Name == HerdName).ToList();

            // get list of all individuals of breeding age and condition
            // grouped by location
            var breeders = from ind in herd
                           where
                           (ind.Gender == Sex.Male & ind.Age >= ind.BreedParams.MinimumAge1stMating) ||
                           (ind.Gender == Sex.Female &
                            ind.Age >= ind.BreedParams.MinimumAge1stMating &
                            ind.Weight >= (ind.BreedParams.MinimumSize1stMating * ind.StandardReferenceWeight)
                           )
                           group ind by ind.Location into grp
                           select grp;


            // calculate labour and finance limitations if needed when doing AI
            int breedersCount  = breeders.Count();
            int numberPossible = breedersCount;
            int numberServiced = 1;

            if (UseAI & TimingOK)
            {
                // attempt to get required resources
                List <ResourceRequest> resourcesneeded = GetResourcesNeededForActivityLocal();
                bool tookRequestedResources            = TakeResources(resourcesneeded, true);
                // get all shortfalls
                if (tookRequestedResources & (ResourceRequestList != null))
                {
                    //TODO: fix this to account for perHead payments and labour and not fixed expenses
                    double amountCashNeeded     = resourcesneeded.Where(a => a.ResourceType == typeof(Finance)).Sum(a => a.Required);
                    double amountCashProvided   = resourcesneeded.Where(a => a.ResourceType == typeof(Finance)).Sum(a => a.Provided);
                    double amountLabourNeeded   = resourcesneeded.Where(a => a.ResourceType == typeof(Labour)).Sum(a => a.Required);
                    double amountLabourProvided = resourcesneeded.Where(a => a.ResourceType == typeof(Labour)).Sum(a => a.Provided);
                    double cashlimit            = 1;
                    if (amountCashNeeded > 0)
                    {
                        if (amountCashProvided == 0)
                        {
                            cashlimit = 0;
                        }
                        else
                        {
                            cashlimit = amountCashNeeded / amountCashProvided;
                        }
                    }
                    double labourlimit = 1;
                    if (amountLabourNeeded > 0)
                    {
                        if (amountLabourProvided == 0)
                        {
                            labourlimit = 0;
                        }
                        else
                        {
                            labourlimit = amountLabourNeeded / amountLabourProvided;
                        }
                    }
                    double limiter = Math.Min(cashlimit, labourlimit);
                    numberPossible = Convert.ToInt32(limiter * breedersCount);

                    // TODO: determine if fixed payments were not possible
                    // TODO: determine limits by insufficient labour or cash for per head payments
                }
                // report that this activity was performed as it does not use base GetResourcesRequired
                this.TriggerOnActivityPerformed();
            }

            if (!UseAI)
            {
                // report that this activity was performed as it does not use base GetResourcesRequired
                this.TriggerOnActivityPerformed();
            }

            // for each location where parts of this herd are located
            foreach (var location in breeders)
            {
                // determine all foetus and newborn mortality.
                foreach (RuminantFemale female in location.Where(a => a.Gender == Sex.Female).Cast <RuminantFemale>().ToList())
                {
                    if (female.IsPregnant)
                    {
                        // calculate foetus and newborn mortality
                        // total mortality / (gestation months + 1) to get monthly mortality
                        // done here before births to account for post birth motality as well..
                        double rnd = ZoneCLEM.RandomGenerator.NextDouble();
                        if (rnd < (female.BreedParams.PrenatalMortality / (female.BreedParams.GestationLength + 1)))
                        {
                            female.OneOffspringDies();
                        }
                    }
                }

                // check for births of all pregnant females.
                foreach (RuminantFemale female in location.Where(a => a.Gender == Sex.Female).Cast <RuminantFemale>().ToList())
                {
                    if (female.BirthDue)
                    {
                        female.WeightLossDueToCalf = 0;
                        int numberOfNewborn = (female.CarryingTwins) ? 2 : 1;
                        for (int i = 0; i < numberOfNewborn; i++)
                        {
                            // Foetal mortality is now performed each timestep at base of this method
                            object newCalf = null;
                            bool   isMale  = (ZoneCLEM.RandomGenerator.NextDouble() > 0.5);
                            if (isMale)
                            {
                                newCalf = new RuminantMale();
                            }
                            else
                            {
                                newCalf = new RuminantFemale();
                            }
                            Ruminant newCalfRuminant = newCalf as Ruminant;
                            newCalfRuminant.Age         = 0;
                            newCalfRuminant.HerdName    = female.HerdName;
                            newCalfRuminant.BreedParams = female.BreedParams;
                            newCalfRuminant.Breed       = female.BreedParams.Breed;
                            newCalfRuminant.Gender      = (isMale) ? Sex.Male : Sex.Female;
                            newCalfRuminant.ID          = Resources.RuminantHerd().NextUniqueID;
                            newCalfRuminant.Location    = female.Location;
                            newCalfRuminant.Mother      = female;
                            newCalfRuminant.Number      = 1;
                            newCalfRuminant.SetUnweaned();
                            // calf weight from  Freer
                            newCalfRuminant.Weight     = female.BreedParams.SRWBirth * female.StandardReferenceWeight * (1 - 0.33 * (1 - female.Weight / female.StandardReferenceWeight));
                            newCalfRuminant.HighWeight = newCalfRuminant.Weight;
                            newCalfRuminant.SaleFlag   = HerdChangeReason.Born;
                            Resources.RuminantHerd().AddRuminant(newCalfRuminant);

                            // add to sucklings
                            female.SucklingOffspring.Add(newCalfRuminant);
                            // remove calf weight from female
                            female.WeightLossDueToCalf += newCalfRuminant.Weight;
                        }
                        female.UpdateBirthDetails();
                    }
                }
                // uncontrolled conception
                if (!UseAI)
                {
                    // check if males and females of breeding condition are together
                    if (location.GroupBy(a => a.Gender).Count() == 2)
                    {
                        // servicing rate
                        int    maleCount       = location.Where(a => a.Gender == Sex.Male).Count();
                        int    femaleCount     = location.Where(a => a.Gender == Sex.Female).Count();
                        double matingsPossible = maleCount * location.FirstOrDefault().BreedParams.MaximumMaleMatingsPerDay * 30;
                        double maleLimiter     = Math.Min(1.0, matingsPossible / femaleCount);

                        foreach (RuminantFemale female in location.Where(a => a.Gender == Sex.Female).Cast <RuminantFemale>().ToList())
                        {
                            if (!female.IsPregnant && !female.IsLactating && (female.Age - female.AgeAtLastBirth) * 30.4 >= female.BreedParams.MinimumDaysBirthToConception)
                            {
                                // calculate conception
                                double conceptionRate = ConceptionRate(female) * maleLimiter;
                                conceptionRate = Math.Min(conceptionRate, MaximumConceptionRateUncontrolled);
                                if (ZoneCLEM.RandomGenerator.NextDouble() <= conceptionRate)
                                {
                                    female.UpdateConceptionDetails(ZoneCLEM.RandomGenerator.NextDouble() < female.BreedParams.TwinRate, conceptionRate);
                                }
                            }
                        }
                    }
                }
                // controlled conception
                else
                {
                    if (this.TimingOK)
                    {
                        foreach (RuminantFemale female in location.Where(a => a.Gender == Sex.Female).Cast <RuminantFemale>().ToList())
                        {
                            if (!female.IsPregnant && !female.IsLactating && (female.Age - female.AgeAtLastBirth) * 30.4 >= female.BreedParams.MinimumDaysBirthToConception)
                            {
                                // calculate conception
                                double conceptionRate = ConceptionRate(female);
                                if (numberServiced <= numberPossible) // labour/finance limited number
                                {
                                    if (ZoneCLEM.RandomGenerator.NextDouble() <= conceptionRate)
                                    {
                                        female.UpdateConceptionDetails(ZoneCLEM.RandomGenerator.NextDouble() < female.BreedParams.TwinRate, conceptionRate);
                                    }
                                    numberServiced++;
                                }
                            }
                        }
                    }
                }
            }
        }
Ejemplo n.º 29
0
        private void OnCLEMAnimalManage(object sender, EventArgs e)
        {
            //List<Ruminant> localHerd = this.CurrentHerd();
            RuminantHerd ruminantHerd = Resources.RuminantHerd();

            // clear store of individuals to try and purchase
            //            ruminantHerd.PurchaseIndividuals.Clear();

            // remove only the individuals that are affected by this activity.
            ruminantHerd.PurchaseIndividuals.RemoveAll(a => a.Breed == this.PredictedHerdBreed);

            List <Ruminant> herd = this.CurrentHerd(true);

            //            List<Ruminant> herd = ruminantHerd.Herd.Where(a => a.HerdName == HerdName).ToList();

            // can sell off males any month as per NABSA
            // if we don't need this monthly, then it goes into next if statement with herd declaration
            // NABSA MALES - weaners, 1-2, 2-3 and 3-4 yo, we check for any male weaned and not a breeding sire.
            // check for sell age/weight of young males
            // if SellYoungFemalesLikeMales then all apply to both sexes else only males.
            if (this.TimingOK || ContinuousMaleSales)
            {
                foreach (var ind in herd.Where(a => a.Weaned & (SellFemalesLikeMales ? true : (a.Gender == Sex.Male)) & (a.Age >= MaleSellingAge || a.Weight >= MaleSellingWeight)))
                {
                    bool sell = true;
                    if (ind.GetType() == typeof(RuminantMale))
                    {
                        // don't sell breeding sires.
                        sell = !((ind as RuminantMale).BreedingSire);
                    }
                    if (sell)
                    {
                        ind.SaleFlag = HerdChangeReason.AgeWeightSale;
                    }
                }
            }

            // if management month
            if (this.TimingOK)
            {
                bool sufficientFood = true;
                if (foodStore != null)
                {
                    sufficientFood = (foodStore.TonnesPerHectare * 1000) > MinimumPastureBeforeRestock;
                }

                // check for maximum age (females and males have different cutoffs)
                foreach (var ind in herd.Where(a => a.Age >= ((a.Gender == Sex.Female) ? MaximumBreederAge : MaximumBullAge)))
                {
                    ind.SaleFlag = HerdChangeReason.MaxAgeSale;
                }

                // MALES
                // check for breeder bulls after sale of old individuals and buy/sell
                int numberMaleSiresInHerd = herd.Where(a => a.Gender == Sex.Male & a.SaleFlag == HerdChangeReason.None).Cast <RuminantMale>().Where(a => a.BreedingSire).Count();

                // Number of females
                int numberFemaleBreedingInHerd = herd.Where(a => a.Gender == Sex.Female & a.Age >= a.BreedParams.MinimumAge1stMating & a.SaleFlag == HerdChangeReason.None).Count();
                int numberFemaleTotalInHerd    = herd.Where(a => a.Gender == Sex.Female & a.SaleFlag == HerdChangeReason.None).Count();
                int numberFemaleOldInHerd      = herd.Where(a => a.Gender == Sex.Female & MaximumBreederAge - a.Age <= 12 & a.SaleFlag == HerdChangeReason.None).Count();

                if (numberMaleSiresInHerd > MaximumSiresKept)
                {
                    // sell bulls
                    // What rule? oldest first as they may be lost soonest
                    int numberToRemove = MaximumSiresKept - numberMaleSiresInHerd;
                    foreach (var male in herd.Where(a => a.Gender == Sex.Male).Cast <RuminantMale>().Where(a => a.BreedingSire).OrderByDescending(a => a.Age).Take(numberToRemove))
                    {
                        male.SaleFlag = HerdChangeReason.ExcessBullSale;
                        numberToRemove--;
                        if (numberToRemove == 0)
                        {
                            break;
                        }
                    }
                }
                else if (numberMaleSiresInHerd < MaximumSiresKept)
                {
                    if ((foodStore == null) || (sufficientFood))
                    {
                        if (AllowSireReplacement)
                        {
                            // remove young bulls from sale herd to replace breed bulls (not those sold because too old)
                            foreach (RuminantMale male in herd.Where(a => a.Gender == Sex.Male & a.SaleFlag == HerdChangeReason.AgeWeightSale).OrderByDescending(a => a.Weight))
                            {
                                male.SaleFlag     = HerdChangeReason.None;
                                male.BreedingSire = true;
                                numberMaleSiresInHerd++;
                                if (numberMaleSiresInHerd >= MaximumSiresKept)
                                {
                                    break;
                                }
                            }
                            // if still insufficent, look into current herd for replacement
                            // remaining males assumed to be too small, so await next time-step
                        }

                        // if still insufficient buy bulls.
                        if (numberMaleSiresInHerd < MaximumSiresKept && (MaximumSiresPerPurchase > 0))
                        {
                            // limit by breeders as proportion of max breeders so we don't spend alot on sires when building the herd and females more valuable
                            double propOfBreeders = (double)numberFemaleBreedingInHerd / (double)MaximumBreedersKept;

                            int sires       = Convert.ToInt32(Math.Ceiling(Math.Ceiling(MaximumSiresKept * propOfBreeders)));
                            int numberToBuy = Math.Min(MaximumSiresPerPurchase, Math.Max(0, sires - numberMaleSiresInHerd));

                            for (int i = 0; i < numberToBuy; i++)
                            {
                                RuminantMale newbull = new RuminantMale
                                {
                                    Location     = GrazeFoodStoreName,
                                    Age          = 48,
                                    Breed        = this.PredictedHerdBreed,// breedParams.Breed;
                                    HerdName     = this.PredictedHerdName,
                                    BreedingSire = true,
                                    BreedParams  = breedParams,
                                    Gender       = Sex.Male,
                                    ID           = 0, // ruminantHerd.NextUniqueID;
                                    Weight       = 450,
                                    HighWeight   = 450,
                                    SaleFlag     = HerdChangeReason.SirePurchase
                                };

                                // add to purchase request list and await purchase in Buy/Sell
                                ruminantHerd.PurchaseIndividuals.Add(newbull);
                            }
                        }
                    }
                }

                // FEMALES
                // Breeding herd traded as heifers only
                int excessHeifers = 0;

                // check for maximum number of breeders remaining after sale and buy/sell
                if (numberFemaleBreedingInHerd > MaximumBreedersKept)
                {
                    // herd mortality of 5% plus those that will be culled in next 12 months
                    excessHeifers = Convert.ToInt32((numberFemaleTotalInHerd - numberFemaleOldInHerd) * 0.05) + numberFemaleOldInHerd;
                    // shortfall + (number of young - replacement heifers)
                    excessHeifers = (numberFemaleTotalInHerd - MaximumBreedersKept) + ((numberFemaleTotalInHerd - numberFemaleBreedingInHerd) - excessHeifers);
                }
                else
                {
                    // shortfall between actual and desired numbers
                    excessHeifers = MaximumBreedersKept - numberFemaleBreedingInHerd;
                    // add future cull for age + 5%
                    excessHeifers += Convert.ToInt32((numberFemaleTotalInHerd - numberFemaleOldInHerd) * 0.05) + numberFemaleOldInHerd;
                    excessHeifers  = (numberFemaleTotalInHerd - numberFemaleBreedingInHerd) - excessHeifers;
                }

                // surplus heifers to sell
                if (excessHeifers > 0)
                {
                    foreach (var female in herd.Where(a => a.Gender == Sex.Female & a.Age < a.BreedParams.MinimumAge1stMating & a.Weaned).OrderByDescending(a => a.Age).Take(excessHeifers))
                    {
                        // tag fo sale.
                        female.SaleFlag = HerdChangeReason.ExcessHeiferSale;
                        excessHeifers--;
                        if (excessHeifers == 0)
                        {
                            break;
                        }
                    }
                }
                else if (excessHeifers < 0)
                {
                    excessHeifers *= -1;
                    if ((foodStore == null) || (sufficientFood))
                    {
                        // remove young females from sale herd to replace breeders (not those sold because too old)
                        foreach (RuminantFemale female in herd.Where(a => a.Gender == Sex.Female & a.SaleFlag == HerdChangeReason.AgeWeightSale).OrderByDescending(a => a.Age))
                        {
                            female.SaleFlag = HerdChangeReason.None;
                            excessHeifers--;
                            if (excessHeifers == 0)
                            {
                                break;
                            }
                        }

                        // if still insufficient buy heifers.
                        if (excessHeifers > 0 & (MaximumBreedersPerPurchase > 0))
                        {
                            int    ageOfHeifer    = 12;
                            double weightOfHeifer = 260;

                            // buy 5% more to account for deaths before these individuals grow to breeding age
                            int numberToBuy = Math.Min(MaximumBreedersPerPurchase, Math.Max(0, Convert.ToInt32(excessHeifers * 1.05)));

                            for (int i = 0; i < numberToBuy; i++)
                            {
                                RuminantFemale newheifer = new RuminantFemale
                                {
                                    Location    = GrazeFoodStoreName,
                                    Age         = ageOfHeifer,
                                    Breed       = this.PredictedHerdBreed,
                                    HerdName    = this.PredictedHerdName,
                                    BreedParams = breedParams,
                                    Gender      = Sex.Female,
                                    ID          = 0,
                                    Weight      = weightOfHeifer,
                                    HighWeight  = weightOfHeifer,
                                    SaleFlag    = HerdChangeReason.HeiferPurchase
                                };

                                // add to purchase request list and await purchase in Buy/Sell
                                ruminantHerd.PurchaseIndividuals.Add(newheifer);
                            }
                        }
                    }
                }

                // report that this activity was performed as it does not use base GetResourcesRequired
                //this.TriggerOnActivityPerformed();

                // Breeders themselves don't get sold. Trading is with Heifers
                // Breeders can be sold in seasonal and ENSO destocking.
                // sell breeders
                // What rule? oldest first as they may be lost soonest
                // should keep pregnant females... and young...
                // this will currently remove pregnant females and females with suckling calf

                //            int numberToRemove = Convert.ToInt32((numberFemaleInHerd-MaximumBreedersKept));
                //    foreach (var female in herd.Where(a => a.Gender == Sex.Female & a.Age >= a.BreedParams.MinimumAge1stMating).OrderByDescending(a => a.Age).Take(numberToRemove))
                //    {
                //        female.SaleFlag = HerdChangeReason.ExcessBreederSale;
                //                    numberToRemove--;
                //                    if (numberToRemove == 0) break;
                //                }
                //            }
                //else
                //{
                //}
            }
        }
Ejemplo n.º 30
0
        private void OnCLEMAnimalBreeding(object sender, EventArgs e)
        {
            this.Status     = ActivityStatus.NotNeeded;
            NumberConceived = 0;

            // get list of all pregnant females
            List <RuminantFemale> pregnantherd = CurrentHerd(true).OfType <RuminantFemale>().Where(a => a.IsPregnant).ToList();

            // determine all fetus and newborn mortality of all pregnant females.
            foreach (RuminantFemale female in pregnantherd)
            {
                // calculate fetus and newborn mortality
                // total mortality / (gestation months + 1) to get monthly mortality
                // done here before births to account for post birth motality as well..
                // IsPregnant status does not change until births occur in next section so will include mortality in month of birth
                // needs to be calculated for each offspring carried.
                for (int i = 0; i < female.CarryingCount; i++)
                {
                    var rnd = RandomNumberGenerator.Generator.NextDouble();
                    if (rnd < (female.BreedParams.PrenatalMortality / (female.BreedParams.GestationLength + 1)))
                    {
                        female.OneOffspringDies();
                        if (female.NumberOfOffspring == 0)
                        {
                            // report conception status changed when last multiple birth dies.
                            female.BreedParams.OnConceptionStatusChanged(new Reporting.ConceptionStatusChangedEventArgs(Reporting.ConceptionStatus.Failed, female, clock.Today));
                        }
                    }
                }

                if (female.BirthDue)
                {
                    int numberOfNewborn = female.CarryingCount;
                    for (int i = 0; i < numberOfNewborn; i++)
                    {
                        bool   isMale = RandomNumberGenerator.Generator.NextDouble() <= female.BreedParams.ProportionOffspringMale;
                        Sex    sex    = isMale ? Sex.Male : Sex.Female;
                        double weight = female.BreedParams.SRWBirth * female.StandardReferenceWeight * (1 - 0.33 * (1 - female.Weight / female.StandardReferenceWeight));

                        Ruminant newSucklingRuminant = Ruminant.Create(sex, female.BreedParams, 0, weight);
                        newSucklingRuminant.HerdName = female.HerdName;
                        newSucklingRuminant.Breed    = female.BreedParams.Breed;
                        newSucklingRuminant.ID       = HerdResource.NextUniqueID;
                        newSucklingRuminant.Location = female.Location;
                        newSucklingRuminant.Mother   = female;
                        newSucklingRuminant.Number   = 1;
                        newSucklingRuminant.SetUnweaned();
                        // suckling/calf weight from Freer
                        newSucklingRuminant.PreviousWeight = newSucklingRuminant.Weight;
                        newSucklingRuminant.SaleFlag       = HerdChangeReason.Born;

                        // add attributes inherited from mother
                        foreach (var attribute in female.Attributes.Items)
                        {
                            if (attribute.Value != null)
                            {
                                newSucklingRuminant.Attributes.Add(attribute.Key, attribute.Value.GetInheritedAttribute() as IIndividualAttribute);
                            }
                        }

                        HerdResource.AddRuminant(newSucklingRuminant, this);

                        // add to sucklings
                        female.SucklingOffspringList.Add(newSucklingRuminant);
                        // this now reports for each individual born not a birth event as individual wean events are reported
                        female.BreedParams.OnConceptionStatusChanged(new Reporting.ConceptionStatusChangedEventArgs(Reporting.ConceptionStatus.Birth, female, clock.Today));
                    }
                    female.UpdateBirthDetails();
                    this.Status = ActivityStatus.Success;
                }
            }

            // Perform breeding
            IEnumerable <Ruminant> herd = null;

            if (useControlledMating && controlledMating.TimingOK)
            {
                // determined by controlled mating and subsequent timer (e.g. smart milking)
                herd = controlledMating.BreedersToMate();
            }
            else if (!useControlledMating && TimingOK)
            {
                // whole herd for activity including males
                herd = CurrentHerd(true);
            }

            if (herd != null && herd.Any())
            {
                // group by location
                var breeders = from ind in herd
                               where ind.IsAbleToBreed
                               group ind by ind.Location into grp
                               select grp;

                // identify not ready for reporting and tracking
                var notReadyBreeders = herd.Where(a => a.Sex == Sex.Female).Cast <RuminantFemale>().Where(a => a.IsBreeder && !a.IsAbleToBreed && !a.IsPregnant);
                foreach (RuminantFemale female in notReadyBreeders)
                {
                    female.BreedParams.OnConceptionStatusChanged(new Reporting.ConceptionStatusChangedEventArgs(Reporting.ConceptionStatus.NotReady, female, clock.Today));
                }

                int             numberPossible = breeders.Sum(a => a.Count());
                int             numberServiced = 1;
                List <Ruminant> maleBreeders   = new List <Ruminant>();

                // for each location where parts of this herd are located
                foreach (var location in breeders)
                {
                    numberPossible = -1;
                    if (useControlledMating)
                    {
                        numberPossible = Convert.ToInt32(location.OfType <RuminantFemale>().Count(), CultureInfo.InvariantCulture);
                    }
                    else
                    {
                        numberPossible = 0;
                        // uncontrolled conception
                        if (location.GroupBy(a => a.Sex).Count() == 2)
                        {
                            int maleCount = location.OfType <RuminantMale>().Count();
                            // get a list of males to provide attributes when incontrolled mating.
                            if (maleCount > 0 && location.FirstOrDefault().BreedParams.IncludedAttributeInheritanceWhenMating)
                            {
                                maleBreeders = location.Where(a => a.Sex == Sex.Male).ToList();
                            }

                            int femaleCount = location.Where(a => a.Sex == Sex.Female).Count();
                            numberPossible = Convert.ToInt32(Math.Ceiling(maleCount * location.FirstOrDefault().BreedParams.MaximumMaleMatingsPerDay * 30), CultureInfo.InvariantCulture);
                        }
                    }

                    numberServiced = 0;
                    lastJoinIndex  = -1;
                    int cnt = 0;
                    // shuffle the not pregnant females when obtained to avoid any inherant order by creation of individuals affecting which individuals are available first
                    var notPregnantFemales = location.OfType <RuminantFemale>().Where(a => !a.IsPregnant).OrderBy(a => RandomNumberGenerator.Generator.Next()).ToList();
                    int totalToBreed       = notPregnantFemales.Count;
                    while (cnt < totalToBreed)
                    {
                        RuminantFemale             female = notPregnantFemales.ElementAt(cnt);
                        Reporting.ConceptionStatus status = Reporting.ConceptionStatus.NotMated;
                        if (numberServiced < numberPossible)
                        {
                            // calculate conception
                            double conceptionRate = ConceptionRate(female, out status);

                            // if mandatory attributes are present in the herd, save male value with female details.
                            // update male for both successful and failed matings (next if statement
                            if (female.BreedParams.IncludedAttributeInheritanceWhenMating)
                            {
                                object male = null;

                                if (useControlledMating)
                                {
                                    bool newJoining = needsNewJoiningMale(controlledMating.JoiningsPerMale, numberServiced);
                                    // save all male attributes
                                    AddMalesAttributeDetails(female, controlledMating.SireAttributes, newJoining);
                                }
                                else
                                {
                                    male = maleBreeders[RandomNumberGenerator.Generator.Next(0, maleBreeders.Count() - 1)];
                                    female.LastMatingStyle = ((male as RuminantMale).IsWildBreeder ? MatingStyle.WildBreeder : MatingStyle.Natural);

                                    // randomly select male
                                    AddMalesAttributeDetails(female, male as Ruminant);
                                }
                            }

                            if (conceptionRate > 0)
                            {
                                if (RandomNumberGenerator.Generator.NextDouble() <= conceptionRate)
                                {
                                    female.UpdateConceptionDetails(female.CalulateNumberOfOffspringThisPregnancy(), conceptionRate, 0);

                                    if (useControlledMating)
                                    {
                                        female.LastMatingStyle = MatingStyle.Controlled;
                                    }

                                    status = Reporting.ConceptionStatus.Conceived;
                                    NumberConceived++;
                                }
                                else
                                {
                                    status = Reporting.ConceptionStatus.Unsuccessful;
                                }
                            }
                            numberServiced++;
                            this.Status = ActivityStatus.Success;
                        }

                        // report change in breeding status
                        // do not report for -1 (controlled mating outside timing)
                        if (numberPossible >= 0 && status != Reporting.ConceptionStatus.NotAvailable)
                        {
                            female.BreedParams.OnConceptionStatusChanged(new Reporting.ConceptionStatusChangedEventArgs(status, female, clock.Today));
                        }

                        cnt++;
                    }

                    // report a natural mating locations for transparency via a message
                    if (numberServiced > 0 & !useControlledMating)
                    {
                        string warning = $"Natural (uncontrolled) mating ocurred in [r={(location.Key ?? "Not specified - general yards")}]";
                        Warnings.CheckAndWrite(warning, Summary, this, MessageType.Information);
                    }
                }
            }
            // report that this activity was performed as it does not use base GetResourcesRequired
            this.TriggerOnActivityPerformed();
        }