コード例 #1
0
ファイル: RuminantHerd.cs プロジェクト: hol353/ApsimX
 /// <summary>
 /// Add individual/cohort to the the herd
 /// </summary>
 /// <param name="ind">Individual Ruminant to add</param>
 public void AddRuminant(Ruminant ind)
 {
     if (ind.ID == 0)
     {
         ind.ID = this.NextUniqueID;
     }
     Herd.Add(ind);
     LastIndividualChanged = ind;
     HerdChangedEventArgs args = new HerdChangedEventArgs();
     args.Details = ind;
     HerdChanged(args);
     // remove change flag
     ind.SaleFlag = Common.HerdChangeReason.None;
 }
コード例 #2
0
        /// <summary>
        /// Add individual/cohort to the the herd
        /// </summary>
        /// <param name="ind">Individual Ruminant to add</param>
        public void AddRuminant(Ruminant ind)
        {
            if (ind.ID == 0)
            {
                ind.ID = this.NextUniqueID;
            }
            Herd.Add(ind);
            LastIndividualChanged = ind;
            HerdChangedEventArgs args = new HerdChangedEventArgs();

            args.Details = ind;
            HerdChanged(args);
            // remove change flag
            ind.SaleFlag = Common.HerdChangeReason.None;
        }
コード例 #3
0
        /// <summary>
        /// Remove individual/cohort from the herd
        /// </summary>
        /// <param name="ind">Individual Ruminant to remove</param>
        public void RemoveRuminant(Ruminant ind)
        {
            // Remove mother ID from any suckling offspring
            if (ind.Gender == Sex.Female)
            {
                foreach (var offspring in (ind as RuminantFemale).SucklingOffspring)
                {
                    offspring.Mother = null;
                }
            }
            Herd.Remove(ind);
            LastIndividualChanged = ind;
            HerdChangedEventArgs args = new HerdChangedEventArgs();

            args.Details = ind;
            HerdChanged(args);
            // remove change flag
            ind.SaleFlag = Common.HerdChangeReason.None;
        }
コード例 #4
0
        private void OnStartOfSimulation(object sender, EventArgs e)
        {
            id   = 1;
            Herd = new List <Ruminant>();
            PurchaseIndividuals   = new List <Ruminant>();
            LastIndividualChanged = new Ruminant();

            List <IModel> childNodes = Apsim.Children(this, typeof(IModel));

            foreach (IModel childModel in childNodes)
            {
                //cast the generic IModel to a specfic model.
                RuminantType ruminantType = childModel as RuminantType;
                foreach (var ind in ruminantType.CreateIndividuals())
                {
                    ind.SaleFlag = Common.HerdChangeReason.InitialHerd;
                    AddRuminant(ind);
                }
            }
        }
コード例 #5
0
        /// <summary>
        /// Create the individual ruminant animals using the Cohort parameterisations.
        /// </summary>
        /// <returns></returns>
        public List <Ruminant> CreateIndividuals()
        {
            List <Ruminant> Individuals = new List <Ruminant>();

            IModel       parentNode = Apsim.Parent(this, typeof(IModel));
            RuminantType parent     = parentNode as RuminantType;

            // get Ruminant Herd resource for unique ids
            RuminantHerd ruminantHerd = Resources.RuminantHerd();

            parent = this.Parent as RuminantType;

            if (StartingNumber > 0)
            {
                //TODO: get random generator from global store with seed
                Random rand = new Random();
                for (int i = 1; i <= StartingNumber; i++)
                {
                    object ruminantBase = null;
                    if (this.Gender == Sex.Male)
                    {
                        ruminantBase = new RuminantMale();
                    }
                    else
                    {
                        ruminantBase = new RuminantFemale();
                    }

                    Ruminant ruminant = ruminantBase as Ruminant;

                    ruminant.ID          = ruminantHerd.NextUniqueID;
                    ruminant.BreedParams = parent;
                    ruminant.Breed       = parent.Breed;
                    ruminant.HerdName    = parent.Name;
                    ruminant.Gender      = Gender;
                    ruminant.Age         = StartingAge;
                    ruminant.SaleFlag    = Common.HerdChangeReason.None;
                    if (Suckling)
                    {
                        ruminant.SetUnweaned();
                    }

                    double u1            = rand.NextDouble();
                    double u2            = rand.NextDouble();
                    double randStdNormal = Math.Sqrt(-2.0 * Math.Log(u1)) *
                                           Math.Sin(2.0 * Math.PI * u2);
                    ruminant.Weight         = StartingWeight + StartingWeightSD * randStdNormal;
                    ruminant.PreviousWeight = ruminant.Weight;

                    if (this.Gender == Sex.Female)
                    {
                        RuminantFemale ruminantFemale = ruminantBase as RuminantFemale;
                        ruminantFemale.DryBreeder         = true;
                        ruminantFemale.WeightAtConception = this.StartingWeight;
                        ruminantFemale.NumberOfBirths     = 0;
                    }

                    Individuals.Add(ruminantBase as Ruminant);
                }
            }

            return(Individuals);
        }
コード例 #6
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;
        }
コード例 #7
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)
        {
            // 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 * ind.Intake;

            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)
            {
                // old code
                // dum = potential milk intake daily
                // dumshort = potential intake. check that it isnt monthly

                // average energy efficiency for maintenance
                double kml = ((ind.MilkIntake * 0.7) + (ind.PotentialIntake * km)) / (ind.MilkIntake + ind.PotentialIntake);
                // average energy efficiency for growth
                double kgl = ((ind.MilkIntake * 0.7) + (ind.PotentialIntake * kg)) / (ind.MilkIntake + ind.PotentialIntake);

                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.Age);
                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
            {
                //all weaned individuals

                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 * ind.Intake * ((13 + 7.52 * energyMetabolic) + energyMetablicFromIntake / energyMaintenance * (23.7 - 3.36 * energyMetabolic)); // MJ per day
            methaneProduced /= 55.28 * 1000;                                                                                                                         // grams per day
        }
コード例 #8
0
ファイル: RuminantTypeCohort.cs プロジェクト: hol353/ApsimX
        /// <summary>
        /// Create the individual ruminant animals using the Cohort parameterisations.
        /// </summary>
        /// <returns></returns>
        public List<Ruminant> CreateIndividuals()
        {
            List<Ruminant> Individuals = new List<Ruminant>();

            IModel parentNode = Apsim.Parent(this, typeof(IModel));
            RuminantType parent = parentNode as RuminantType;

            for (int i = 1; i <= StartingNumber; i++)
            {
                Ruminant ruminant = new Ruminant();

                ruminant.BreedParams = parent;

                ruminant.Gender = Gender;
                ruminant.Age = StartingAge;
                ruminant.Weight = StartingWeight;
                ruminant.Price = StartingPrice;

                Individuals.Add(ruminant);
            }

            return Individuals;
        }
コード例 #9
0
        private void OnWFAnimalBreeding(object sender, EventArgs e)
        {
            RuminantHerd    ruminantHerd = Resources.RuminantHerd();
            List <Ruminant> herd         = 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;

            // for each location where parts of this herd are located
            foreach (var location in breeders)
            {
                // check for births of all pregnant females.
                foreach (RuminantFemale female in location.Where(a => a.Gender == Sex.Female).Cast <RuminantFemale>().ToList())
                {
                    if (female.BirthDue)
                    {
                        int numberOfNewborn = (female.CarryingTwins) ? 2 : 1;
                        for (int i = 0; i < numberOfNewborn; i++)
                        {
                            // Determine if the offspring died during pregancy from conception to after birth
                            // This is currently only performed at time of birth rather than monthly during pregnancy
                            // and so does not reflect changes in female intake etc after dead of foetus.

                            // this now occurs monthly at the ned of this breeding method.
                            //if (randomGenerator.RandNo > female.BreedParams.PrenatalMortality)
                            //{
                            object newCalf = null;
                            bool   isMale  = (randomGenerator.RandNo > 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.Gender      = (isMale) ? Sex.Male : Sex.Female;
                            newCalfRuminant.ID          = 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   = Common.HerdChangeReason.Born;
                            ruminantHerd.AddRuminant(newCalfRuminant);

                            // add to sucklings
                            female.SucklingOffspring.Add(newCalfRuminant);

                            //}
                        }
                        female.UpdateBirthDetails();
                    }
                }

                // Conception
                // 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.Max(1.0, matingsPossible / femaleCount);

                    foreach (RuminantFemale female in location.Where(a => a.Gender == Sex.Female).Cast <RuminantFemale>().ToList())
                    {
                        //TODO: ensure enough time since last calf
                        if (!female.IsPregnant & !female.IsLactating)
                        {
                            // calculate conception
                            double conceptionRate = ConceptionRate(female) * maleLimiter;
                            if (randomGenerator.RandNo <= conceptionRate)
                            {
                                female.UpdateConceptionDetails(randomGenerator.RandNo > female.BreedParams.TwinRate, conceptionRate);
                            }
                        }
                    }
                }

                // 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 to get monthly mortality

                        // TODO: check if need to be done before births to get last month mortality
                        if (randomGenerator.RandNo > female.BreedParams.PrenatalMortality / female.BreedParams.GestationLength)
                        {
                            female.OneOffspringDies();
                        }
                    }
                }
            }
        }
コード例 #10
0
ファイル: RuminantHerd.cs プロジェクト: hol353/ApsimX
 /// <summary>
 /// Remove individual/cohort from the herd
 /// </summary>
 /// <param name="ind">Individual Ruminant to remove</param>
 public void RemoveRuminant(Ruminant ind)
 {
     // Remove mother ID from any suckling offspring
     if (ind.Gender == Sex.Female)
     {
         foreach (var offspring in (ind as RuminantFemale).SucklingOffspring)
         {
             offspring.Mother = null;
         }
     }
     Herd.Remove(ind);
     LastIndividualChanged = ind;
     HerdChangedEventArgs args = new HerdChangedEventArgs();
     args.Details = ind;
     HerdChanged(args);
     // remove change flag
     ind.SaleFlag = Common.HerdChangeReason.None;
 }
コード例 #11
0
ファイル: RuminantHerd.cs プロジェクト: hol353/ApsimX
        private void OnStartOfSimulation(object sender, EventArgs e)
        {
            id = 1;
            Herd = new List<Ruminant>();
            PurchaseIndividuals = new List<Ruminant>();
            LastIndividualChanged = new Ruminant();

            List<IModel> childNodes = Apsim.Children(this, typeof(IModel));

            foreach (IModel childModel in childNodes)
            {
                //cast the generic IModel to a specfic model.
                RuminantType ruminantType = childModel as RuminantType;
                foreach (var ind in ruminantType.CreateIndividuals())
                {
                    ind.SaleFlag = Common.HerdChangeReason.InitialHerd;
                    AddRuminant(ind);
                }
            }
        }
コード例 #12
0
ファイル: RuminantActivityGrow.cs プロジェクト: hol353/ApsimX
        /// <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)
        {
            // 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 * ind.Intake;

            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)
            {
                // old code
                // dum = potential milk intake daily
                // dumshort = potential intake. check that it isnt monthly

                // average energy efficiency for maintenance
                double kml = ((ind.MilkIntake * 0.7) + (ind.PotentialIntake * km)) / (ind.MilkIntake + ind.PotentialIntake);
                // average energy efficiency for growth
                double kgl = ((ind.MilkIntake * 0.7) + (ind.PotentialIntake * kg)) / (ind.MilkIntake + ind.PotentialIntake);

                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.Age);
                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
            {
                //all weaned individuals

                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 * ind.Intake * ((13 + 7.52 * energyMetabolic) + energyMetablicFromIntake / energyMaintenance * (23.7 - 3.36 * energyMetabolic)); // MJ per day
            methaneProduced /= 55.28 * 1000; // grams per day
        }
コード例 #13
0
ファイル: RuminantActivityGrow.cs プロジェクト: hol353/ApsimX
        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;
        }