/// <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); }
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; } } } } } }
/// <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; }
private void OnWFAnimalManage(object sender, EventArgs e) { RuminantHerd ruminantHerd = Resources.RuminantHerd(); List<Ruminant> herd = ruminantHerd.Herd.Where(a => a.HerdName == HerdName).ToList(); RuminantType breedParams; // get breedParams when no herd remaining if (herd.Count() == 0) { breedParams = Resources.GetResourceItem("Ruminants", HerdName) as RuminantType; } else { breedParams = herd.FirstOrDefault().BreedParams; } // 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. foreach (var ind in herd.Where(a => a.Weaned & (SellFemalesLikeMales ? true : (a.Gender == Sex.Male)) & (a.Age >= SellingAge ^ a.Weight >= SellingWeight))) { bool sell = true; if (ind.GetType() == typeof(RuminantMale)) { // don't sell breeding sires. sell = !((ind as RuminantMale).BreedingSire); } if (sell) { ind.SaleFlag = Common.HerdChangeReason.AgeWeightSale; } } // if management month if (Clock.Today.Month == ManagementMonth ^ MonthlyManagement) { // Perform weaning foreach (var ind in herd.Where(a => a.Weaned == false)) { if (ind.Age >= WeaningAge ^ ind.Weight >= WeaningWeight) { ind.Wean(); } } // 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 = Common.HerdChangeReason.MaxAgeSale; } // MALES // check for breeder bulls after sale of old individuals and buy/sell int numberinherd = herd.Where(a => a.Gender == Sex.Male & a.SaleFlag == Common.HerdChangeReason.None).Cast<RuminantMale>().Where(a => a.BreedingSire).Count(); if (numberinherd > MaximumSiresKept) { // sell bulls // What rule? oldest first as they may be lost soonest int numberToRemove = MaximumSiresKept - numberinherd; 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 = Common.HerdChangeReason.ExcessBullSale; } } else if(numberinherd < MaximumSiresKept) { // 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 == Common.HerdChangeReason.AgeWeightSale).OrderByDescending(a => a.Weight)) { male.SaleFlag = Common.HerdChangeReason.None; male.BreedingSire = true; numberinherd++; if (numberinherd >= MaximumSiresKept) break; } // if still insufficient buy bulls. if (numberinherd < MaximumSiresKept) { int numberToBuy = Convert.ToInt32((MaximumSiresKept - numberinherd) * 0.05); for (int i = 0; i < numberToBuy; i++) { RuminantMale newbull = new RuminantMale(); newbull.Age = 48; newbull.HerdName = HerdName; newbull.BreedingSire = true; newbull.BreedParams = breedParams; newbull.Gender = Sex.Male; newbull.ID = ruminantHerd.NextUniqueID; newbull.Weight = 450; newbull.HighWeight = newbull.Weight; newbull.SaleFlag = Common.HerdChangeReason.SirePurchase; // add to purchase request list and await purchase in Buy/ Sell ruminantHerd.PurchaseIndividuals.Add(newbull); } } } // FEMALES // check for maximum number of breeders remaining after sale and buy/sell numberinherd = herd.Where(a => a.Gender == Sex.Female & a.Age >= a.BreedParams.MinimumAge1stMating & a.SaleFlag == Common.HerdChangeReason.None).Count(); if (numberinherd > MaximumBreedersKept) { // 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 = MaximumBreedersKept - numberinherd; foreach (var female in herd.Where(a => a.Gender == Sex.Female & a.Age >= a.BreedParams.MinimumAge1stMating).OrderByDescending(a => a.Age).Take(numberToRemove)) { female.SaleFlag = Common.HerdChangeReason.ExcessBreederSale; } } else { // 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 == Common.HerdChangeReason.AgeWeightSale).OrderByDescending(a => a.Weight)) { female.SaleFlag = Common.HerdChangeReason.None; numberinherd++; if (numberinherd >= MaximumBreedersKept) break; } // if still insufficient buy breeders. if (numberinherd < MaximumBreedersKept) { int ageOfHeifer = 12; double weightOfHeifer = 260; int numberToBuy = Convert.ToInt32((MaximumBreedersKept - numberinherd) * 0.05); for (int i = 0; i < numberToBuy; i++) { RuminantFemale newheifer = new RuminantFemale(); newheifer.Age = ageOfHeifer; newheifer.HerdName = HerdName; newheifer.BreedParams = breedParams; newheifer.Gender = Sex.Female; newheifer.ID = ruminantHerd.NextUniqueID; newheifer.Weight = weightOfHeifer; newheifer.HighWeight = newheifer.Weight; newheifer.SaleFlag = Common.HerdChangeReason.HeiferPurchase; // add to purchase request list and await purchase in Buy/ Sell ruminantHerd.PurchaseIndividuals.Add(newheifer); } } } } }
/// <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); }
private void OnWFAnimalManage(object sender, EventArgs e) { RuminantHerd ruminantHerd = Resources.RuminantHerd(); List <Ruminant> herd = ruminantHerd.Herd.Where(a => a.HerdName == HerdName).ToList(); RuminantType breedParams; // get breedParams when no herd remaining if (herd.Count() == 0) { breedParams = Resources.GetResourceItem("Ruminants", HerdName) as RuminantType; } else { breedParams = herd.FirstOrDefault().BreedParams; } // 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. foreach (var ind in herd.Where(a => a.Weaned & (SellFemalesLikeMales ? true : (a.Gender == Sex.Male)) & (a.Age >= SellingAge ^ a.Weight >= SellingWeight))) { bool sell = true; if (ind.GetType() == typeof(RuminantMale)) { // don't sell breeding sires. sell = !((ind as RuminantMale).BreedingSire); } if (sell) { ind.SaleFlag = Common.HerdChangeReason.AgeWeightSale; } } // if management month if (Clock.Today.Month == ManagementMonth ^ MonthlyManagement) { // Perform weaning foreach (var ind in herd.Where(a => a.Weaned == false)) { if (ind.Age >= WeaningAge ^ ind.Weight >= WeaningWeight) { ind.Wean(); } } // 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 = Common.HerdChangeReason.MaxAgeSale; } // MALES // check for breeder bulls after sale of old individuals and buy/sell int numberinherd = herd.Where(a => a.Gender == Sex.Male & a.SaleFlag == Common.HerdChangeReason.None).Cast <RuminantMale>().Where(a => a.BreedingSire).Count(); if (numberinherd > MaximumSiresKept) { // sell bulls // What rule? oldest first as they may be lost soonest int numberToRemove = MaximumSiresKept - numberinherd; 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 = Common.HerdChangeReason.ExcessBullSale; } } else if (numberinherd < MaximumSiresKept) { // 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 == Common.HerdChangeReason.AgeWeightSale).OrderByDescending(a => a.Weight)) { male.SaleFlag = Common.HerdChangeReason.None; male.BreedingSire = true; numberinherd++; if (numberinherd >= MaximumSiresKept) { break; } } // if still insufficient buy bulls. if (numberinherd < MaximumSiresKept) { int numberToBuy = Convert.ToInt32((MaximumSiresKept - numberinherd) * 0.05); for (int i = 0; i < numberToBuy; i++) { RuminantMale newbull = new RuminantMale(); newbull.Age = 48; newbull.HerdName = HerdName; newbull.BreedingSire = true; newbull.BreedParams = breedParams; newbull.Gender = Sex.Male; newbull.ID = ruminantHerd.NextUniqueID; newbull.Weight = 450; newbull.HighWeight = newbull.Weight; newbull.SaleFlag = Common.HerdChangeReason.SirePurchase; // add to purchase request list and await purchase in Buy/ Sell ruminantHerd.PurchaseIndividuals.Add(newbull); } } } // FEMALES // check for maximum number of breeders remaining after sale and buy/sell numberinherd = herd.Where(a => a.Gender == Sex.Female & a.Age >= a.BreedParams.MinimumAge1stMating & a.SaleFlag == Common.HerdChangeReason.None).Count(); if (numberinherd > MaximumBreedersKept) { // 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 = MaximumBreedersKept - numberinherd; foreach (var female in herd.Where(a => a.Gender == Sex.Female & a.Age >= a.BreedParams.MinimumAge1stMating).OrderByDescending(a => a.Age).Take(numberToRemove)) { female.SaleFlag = Common.HerdChangeReason.ExcessBreederSale; } } else { // 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 == Common.HerdChangeReason.AgeWeightSale).OrderByDescending(a => a.Weight)) { female.SaleFlag = Common.HerdChangeReason.None; numberinherd++; if (numberinherd >= MaximumBreedersKept) { break; } } // if still insufficient buy breeders. if (numberinherd < MaximumBreedersKept) { int ageOfHeifer = 12; double weightOfHeifer = 260; int numberToBuy = Convert.ToInt32((MaximumBreedersKept - numberinherd) * 0.05); for (int i = 0; i < numberToBuy; i++) { RuminantFemale newheifer = new RuminantFemale(); newheifer.Age = ageOfHeifer; newheifer.HerdName = HerdName; newheifer.BreedParams = breedParams; newheifer.Gender = Sex.Female; newheifer.ID = ruminantHerd.NextUniqueID; newheifer.Weight = weightOfHeifer; newheifer.HighWeight = newheifer.Weight; newheifer.SaleFlag = Common.HerdChangeReason.HeiferPurchase; // add to purchase request list and await purchase in Buy/ Sell ruminantHerd.PurchaseIndividuals.Add(newheifer); } } } } }
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; }
/// <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 }
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(); } } } } }
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(); } } } } }
/// <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; }