private void OnCLEMStartOfTimeStep(object sender, EventArgs e) { RuminantHerd ruminantHerd = Resources.RuminantHerd(); List <Ruminant> herd = ruminantHerd.Herd; // Natural weaning takes place here before animals eat or take milk from mother. foreach (var ind in herd.Where(a => a.Weaned == false)) { double weaningAge = ind.BreedParams.NaturalWeaningAge; if (weaningAge == 0) { weaningAge = ind.BreedParams.GestationLength; } if (ind.Age >= weaningAge) { ind.Wean(true, "Natural"); if (ind.Mother != null) { // report conception status changed when last multiple birth dies. ind.Mother.BreedParams.OnConceptionStatusChanged(new Reporting.ConceptionStatusChangedEventArgs(Reporting.ConceptionStatus.Weaned, ind.Mother, Clock.Today)); } } } }
private void OnCommencing(object sender, EventArgs e) { ruminantHerd = resources.FindResourceGroup <RuminantHerd>(); // determine any herd filtering herdFilters = new List <RuminantGroup>(); IModel current = this; while (current.GetType() != typeof(ZoneCLEM)) { var filtergroup = current.Children.OfType <RuminantGroup>(); if (filtergroup.Count() > 1) { Summary.WriteWarning(this, "Multiple ruminant filter groups have been supplied for [" + current.Name + "]" + Environment.NewLine + "Only the first filter group will be used."); } if (filtergroup.FirstOrDefault() != null) { herdFilters.Insert(0, filtergroup.FirstOrDefault()); } current = current.Parent as IModel; } // get full name for reporting current = this; string name = this.Name; while (current.GetType() != typeof(ZoneCLEM)) { string quoteName = (current.GetType() == typeof(ActivitiesHolder)) ? "[" + current.Name + "]":current.Name; name = quoteName + "." + name; current = current.Parent as IModel; } }
private void OnCLEMAnimalMilking(object sender, EventArgs e) { if (this.TimingOK & this.Status != ActivityStatus.Ignored) { if (ProportionToRemove > 0) { // get labour shortfall double labourLimiter = 1.0; if (this.Status == ActivityStatus.Partial & this.OnPartialResourcesAvailableAction == OnPartialResourcesAvailableActionTypes.UseResourcesAvailable) { double labourLimit = 1; double labourNeeded = ResourceRequestList.Where(a => a.ResourceType == typeof(Labour)).Sum(a => a.Required); double labourProvided = ResourceRequestList.Where(a => a.ResourceType == typeof(Labour)).Sum(a => a.Provided); if (labourNeeded > 0) { labourLimit = labourProvided / labourNeeded; } } // get dry breeders RuminantHerd ruminantHerd = Resources.RuminantHerd(); List <RuminantFemale> herd = this.CurrentHerd(true).Where(a => a.Gender == Sex.Female).Cast <RuminantFemale>().ToList(); // get dry breeders from females foreach (RuminantFemale female in herd.Where(a => a.Age - a.AgeAtLastBirth >= MonthsSinceBirth & a.PreviousConceptionRate >= MinimumConceptionBeforeSell & a.AgeAtLastBirth > 0)) { if (ZoneCLEM.RandomGenerator.NextDouble() <= ProportionToRemove * labourLimiter) { // flag female ready to transport. female.SaleFlag = HerdChangeReason.DryBreederSale; } } } } }
/// <summary> /// Method to determine resources required for this activity in the current month /// </summary> /// <returns>List of required resource requests</returns> public override List <ResourceRequest> DetermineResourcesNeeded() { ResourceRequestList = null; if (Clock.Today.Month == Month) { // if labour item(s) found labour will be requested for this activity. if (LabourRequired > 0) { if (ResourceRequestList == null) { ResourceRequestList = new List <ResourceRequest>(); } // determine head to be mustered RuminantHerd ruminantHerd = Resources.RuminantHerd(); List <Ruminant> herd = ruminantHerd.Herd; int head = herd.Filter(this).Count(); ResourceRequestList.Add(new ResourceRequest() { AllowTransmutation = true, Required = Math.Ceiling(head / this.LabourHeadUnit) * this.LabourRequired, ResourceName = "Labour", ResourceTypeName = "", Requestor = this.Name, FilterSortDetails = LabourFilterList } ); } } return(ResourceRequestList); }
private void OnCLEMInitialiseActivity(object sender, EventArgs e) { this.InitialiseHerd(false, true); bankAccount = Resources.GetResourceItem(this, typeof(Finance), BankAccountName, OnMissingResourceActionTypes.Ignore, OnMissingResourceActionTypes.ReportErrorAndStop) as FinanceType; // get labour specifications labour = Apsim.Children(this, typeof(LabourFilterGroupSpecified)).Cast <LabourFilterGroupSpecified>().ToList(); // this.Children.Where(a => a.GetType() == typeof(LabourFilterGroupSpecified)).Cast<LabourFilterGroupSpecified>().ToList(); if (labour == null) { labour = new List <LabourFilterGroupSpecified>(); } // get trucking settings trucking = Apsim.Children(this, typeof(TruckingSettings)).FirstOrDefault() as TruckingSettings; // check if pricing is present if (bankAccount != null) { RuminantHerd ruminantHerd = Resources.RuminantHerd(); var breeds = ruminantHerd.Herd.Where(a => a.BreedParams.Breed == this.PredictedHerdBreed).GroupBy(a => a.HerdName); foreach (var herd in breeds) { if (!herd.FirstOrDefault().BreedParams.PricingAvailable()) { Summary.WriteWarning(this, String.Format("No pricing schedule has been provided for herd ({0}). No transactions will be recorded for activity ({1}).", herd.Key, this.Name)); } } } }
/// <summary> /// Method to determine resources required for this activity in the current month /// </summary> /// <returns>List of required resource requests</returns> public override List <ResourceRequest> DetermineResourcesNeeded() { ResourceRequestList = null; if (ControlledMatings != null) { ResourceRequestList = new List <ResourceRequest>(); RuminantHerd ruminantHerd = Resources.RuminantHerd(); List <Ruminant> herd = ruminantHerd.Herd.Where(a => a.BreedParams.Name == HerdName).ToList(); int breeders = (from ind in herd where (ind.Gender == Sex.Female & ind.Age >= ind.BreedParams.MinimumAge1stMating & ind.Weight >= (ind.BreedParams.MinimumSize1stMating * ind.StandardReferenceWeight) ) select ind).Count(); ResourceRequestList.Add(new ResourceRequest() { AllowTransmutation = false, Required = Math.Ceiling(breeders / ControlledMatings.LabourBreedersUnit) * ControlledMatings.LabourRequired, ResourceName = "Labour", ResourceTypeName = this.HerdName, Requestor = this.Name, FilterSortDetails = ControlledMatings.LabourFilterList } ); } return(ResourceRequestList); }
private void OnCLEMPotentialIntake(object sender, EventArgs e) { RuminantHerd ruminantHerd = Resources.RuminantHerd(); List <Ruminant> herd = ruminantHerd.Herd; // Calculate potential intake and reset stores // Order age descending so breeder females calculate milkproduction before suckings grow DateTime start = DateTime.Now; foreach (var ind in herd.GroupBy(a => a.Weaned).OrderByDescending(a => a.Key)) { foreach (var indi in ind) { // reset tallies at start of the month indi.DietDryMatterDigestibility = 0; indi.PercentNOfIntake = 0; indi.Intake = 0; indi.MilkIntake = 0; CalculatePotentialIntake(indi); } } var diff = DateTime.Now - start; }
private void OnCLEMAnimalStock(object sender, EventArgs e) { // this event happens after management has marked individuals for purchase or sale. if (Clock.Today.Month == AssessmentMonth) { this.Status = ActivityStatus.NotNeeded; // calculate dry season pasture available for each managed paddock holding stock not flagged for sale RuminantHerd ruminantHerd = Resources.RuminantHerd(); foreach (var paddockGroup in ruminantHerd.Herd.Where(a => a.Location != "").GroupBy(a => a.Location)) { // multiple breeds are currently not supported as we need to work out what to do with diferent AEs if (paddockGroup.GroupBy(a => a.Breed).Count() > 1) { throw new ApsimXException(this, "Dry season destocking paddocks with multiple breeds is currently not supported\nActivity:" + this.Name + ", Paddock: " + paddockGroup.Key); } // total adult equivalents not marked for sale of all breeds on pasture for utilisation double totalAE = paddockGroup.Where(a => a.SaleFlag == HerdChangeReason.None).Sum(a => a.AdultEquivalent); double shortfallAE = 0; // Determine total feed requirements for dry season for all ruminants on the pasture // We assume that all ruminant have the BaseAnimalEquivalent to the specified herd shortfallAE = 0; GrazeFoodStoreType pasture = Resources.GetResourceItem(this, typeof(GrazeFoodStore), paddockGroup.Key, OnMissingResourceActionTypes.ReportErrorAndStop, OnMissingResourceActionTypes.ReportErrorAndStop) as GrazeFoodStoreType; double pastureBiomass = pasture.Amount; // Adjust fodder balance for detachment rate (6%/month) double feedRequiredAE = paddockGroup.FirstOrDefault().BreedParams.BaseAnimalEquivalent * 0.02 * 30.4; // 2% of AE animal per day for (int i = 0; i < this.DrySeasonLength; i++) { pastureBiomass *= (1.0 - pasture.DetachRate); pastureBiomass -= feedRequiredAE * totalAE; } // Shortfall in Fodder in kg per hectare // pasture at end of period in kg/ha double pastureShortFallKgHa = pastureBiomass / pasture.Manager.Area; // shortfall from low limit pastureShortFallKgHa = Math.Max(0, FeedLowLimit - pastureShortFallKgHa); // Shortfall in Fodder in kg for paddock double pastureShortFallKg = pastureShortFallKgHa * pasture.Manager.Area; if (pastureShortFallKg == 0) { return; } // number of AE to sell to balance shortfall_kg shortfallAE = pastureShortFallKg / feedRequiredAE; // get prediction HandleDestocking(shortfallAE, paddockGroup.Key); } } else { this.Status = ActivityStatus.Ignored; } }
private void OnCommencing(object sender, EventArgs e) { ruminantHerd = resources.FindResourceGroup <RuminantHerd>(); if (ruminantHerd is null) { return; } }
/// <summary> /// Method to get the set herd filters /// </summary> public void InitialiseHerd(bool allowMultipleBreeds, bool allowMultipleHerds) { HerdResource = Resources.FindResourceGroup <RuminantHerd>(); GetHerdFilters(); this.allowMultipleBreeds = allowMultipleBreeds; this.allowMultipleHerds = allowMultipleHerds; DetermineHerdName(); }
/// <summary> /// Method to perform destocking /// </summary> /// <param name="animalEquivalentsForSale"></param> /// <param name="paddockName"></param> /// <returns>The AE that were not handled</returns> private double HandleDestocking(double animalEquivalentsForSale, string paddockName) { if (animalEquivalentsForSale <= 0) { return(0); } // move to underutilised paddocks // TODO: This can be added later as an activity including spelling // remove all potential purchases from list as they can't be supported. // This does not change the shortfall AE as they were not counted in TotalAE pressure. RuminantHerd ruminantHerd = Resources.RuminantHerd(); ruminantHerd.PurchaseIndividuals.RemoveAll(a => a.Location == paddockName); var destockGroups = FindAllChildren <RuminantGroup>().Where(a => a.Reason == RuminantStockGroupStyle.Destock); if (destockGroups.Count() == 0) { string warn = $"No [f=FilterGroup]s with a [Destock] Reason were provided in [a={this.Name}]\r\nNo destocking will be performed."; this.Status = ActivityStatus.Warning; if (!Warnings.Exists(warn)) { Summary.WriteWarning(this, warn); Warnings.Add(warn); } } // remove individuals to sale as specified by destock groups foreach (RuminantGroup item in destockGroups) { // works with current filtered herd to obey filtering. var herd = CurrentHerd(false) .Where(a => a.Location == paddockName && !a.ReadyForSale) .FilterRuminants(item).FilterRuminants(item).FilterRuminants(item) .ToList(); int cnt = 0; while (cnt < herd.Count() && animalEquivalentsForSale > 0) { if (herd[cnt].SaleFlag != HerdChangeReason.DestockSale) { animalEquivalentsForSale -= herd[cnt].AdultEquivalent; herd[cnt].SaleFlag = HerdChangeReason.DestockSale; } cnt++; } if (animalEquivalentsForSale <= 0) { return(0); } } return(animalEquivalentsForSale); // handling of sucklings with sold female is in RuminantActivityBuySell // buy or sell is handled by the buy sell activity }
private void OnCLEMInitialiseActivity(object sender, EventArgs e) { this.InitialiseHerd(false, true); breedParams = Resources.GetResourceItem(this, typeof(RuminantHerd), this.PredictedHerdName, OnMissingResourceActionTypes.ReportErrorAndStop, OnMissingResourceActionTypes.ReportErrorAndStop) as RuminantType; // max sires if (MaximumSiresKept < 1 & MaximumSiresKept > 0) { SiresKept = Convert.ToInt32(Math.Ceiling(MaximumBreedersKept * MaximumSiresKept), CultureInfo.InvariantCulture); } else { SiresKept = Convert.ToInt32(Math.Truncate(MaximumSiresKept), CultureInfo.InvariantCulture); } if (FillBreedingMalesAtStartup) { RuminantHerd herd = Resources.RuminantHerd(); if (herd != null) { // get number in herd int numberPresent = this.CurrentHerd(false).Where(a => a.Gender == Sex.Male).Cast <RuminantMale>().Where(a => a.BreedingSire).Count(); // fill to number needed for (int i = numberPresent; i < SiresKept; i++) { RuminantMale newbull = new RuminantMale(48, Sex.Male, 450, breedParams) { Breed = this.PredictedHerdBreed, HerdName = this.PredictedHerdName, BreedingSire = true, ID = herd.NextUniqueID, PreviousWeight = 450, SaleFlag = HerdChangeReason.InitialHerd }; herd.AddRuminant(newbull, this); } } } // check GrazeFoodStoreExists grazeStore = ""; if (GrazeFoodStoreName != null && !GrazeFoodStoreName.StartsWith("Not specified")) { grazeStore = GrazeFoodStoreName.Split('.').Last(); foodStore = Resources.GetResourceItem(this, GrazeFoodStoreName, OnMissingResourceActionTypes.ReportErrorAndStop, OnMissingResourceActionTypes.ReportErrorAndStop) as GrazeFoodStoreType; } // check for managed paddocks and warn if animals placed in yards. if (grazeStore == "") { var ah = Apsim.Find(this, typeof(ActivitiesHolder)); if (Apsim.ChildrenRecursively(ah, typeof(PastureActivityManage)).Count() != 0) { Summary.WriteWarning(this, String.Format("Animals purchased by [a={0}] are currently placed in [Not specified - general yards] while a managed pasture is available. These animals will not graze until mustered and will require feeding while in yards.\nSolution: Set the [GrazeFoodStore to place purchase in] located in the properties [General].[PastureDetails]", this.Name)); } } }
private void OnCLEMHerdSummary(object sender, EventArgs e) { timestep++; RuminantHerd ruminantHerd = Resources.RuminantHerd(); List <Ruminant> herd = ruminantHerd.Herd; // one individual herd = herd.ToList(); // group by breed foreach (var breedGroup in herd.GroupBy(a => a.Breed)) { // group by herd foreach (var herdGroup in breedGroup.GroupBy(a => a.HerdName)) { // group by sex foreach (var sexGroup in herdGroup.GroupBy(a => a.Gender)) { // weaned foreach (var ageGroup in sexGroup.OrderBy(a => a.Age).GroupBy(a => Math.Truncate(a.Age / 12.0))) { ReportDetails = new HerdReportItemGeneratedEventArgs(); ReportDetails.TimeStep = timestep; ReportDetails.Breed = breedGroup.Key; ReportDetails.Herd = herdGroup.Key; ReportDetails.Age = Convert.ToInt32(ageGroup.Key); ReportDetails.Sex = sexGroup.Key.ToString().Substring(0, 1); ReportDetails.Number = ageGroup.Sum(a => a.Number); ReportDetails.AverageWeight = ageGroup.Average(a => a.Weight); ReportDetails.AverageWeightGain = ageGroup.Average(a => a.WeightGain); ReportDetails.AverageIntake = ageGroup.Average(a => (a.Intake + a.MilkIntake)); //now daily/30.4; ReportDetails.AdultEquivalents = ageGroup.Sum(a => a.AdultEquivalent); if (sexGroup.Key == Sex.Female) { ReportDetails.NumberPregnant = ageGroup.Cast <RuminantFemale>().Where(a => a.IsPregnant).Count(); ReportDetails.NumberLactating = ageGroup.Cast <RuminantFemale>().Where(a => a.IsLactating).Count(); ReportDetails.NumberOfBirths = ageGroup.Cast <RuminantFemale>().Sum(a => a.NumberOfBirthsThisTimestep); } else { ReportDetails.NumberPregnant = 0; ReportDetails.NumberLactating = 0; ReportDetails.NumberOfBirths = 0; } ReportItemGenerated(ReportDetails); // reset birth count if (sexGroup.Key == Sex.Female) { ageGroup.Cast <RuminantFemale>().ToList().ForEach(a => a.NumberOfBirthsThisTimestep = 0); } } } } } }
private void HandleDestocking(double animalEquivalentsforSale, string paddockName) { if (animalEquivalentsforSale <= 0) { AeDestocked = 0; this.Status = ActivityStatus.Ignored; return; } // move to underutilised paddocks // TODO: This can be added later as an activity including spelling // remove all potential purchases from list as they can't be supported. // This does not change the shortfall AE as they were not counted in TotalAE pressure. RuminantHerd ruminantHerd = Resources.RuminantHerd(); ruminantHerd.PurchaseIndividuals.RemoveAll(a => a.Location == paddockName); // remove individuals to sale as specified by destock groups foreach (RuminantDestockGroup item in this.Children.Where(a => a.GetType() == typeof(RuminantDestockGroup))) { // works with current filtered herd to obey filtering. List <Ruminant> herd = this.CurrentHerd(false).Where(a => a.Location == paddockName && !a.ReadyForSale).ToList(); herd = herd.Filter(item); int cnt = 0; while (cnt < herd.Count() && animalEquivalentsforSale > 0) { this.Status = ActivityStatus.Success; animalEquivalentsforSale -= herd[cnt].AdultEquivalent; herd[cnt].SaleFlag = HerdChangeReason.DestockSale; //if (animalEquivalentsforSale < herd.Min(a => a.AdultEquivalent)) //{ // animalEquivalentsforSale = 0; //} cnt++; } if (animalEquivalentsforSale <= 0) { AeDestocked = 0; this.Status = ActivityStatus.Success; return; } } AeDestocked = AeToDestock - animalEquivalentsforSale; this.Status = ActivityStatus.Partial; // Idea of possible destock groups // Steers, Male, Not BreedingSire, > Age // Dry Cows, IsDryBreeder // Breeders, IsBreeder, !IsPregnant, > Age // Underweight ProportionOfMaxWeight < 0.6 // handling of sucklings with sold female is in RuminantActivityBuySell // buy or sell is handled by the buy sell activity }
private void OnCLEMAgeResources(object sender, EventArgs e) { RuminantHerd ruminantHerd = Resources.RuminantHerd(); // grow all individuals foreach (Ruminant ind in ruminantHerd.Herd) { ind.IncrementAge(); } }
private void OnWFAnimalDeath(object sender, EventArgs e) { // remove individuals that died // currently performed in the month after weight has been adjusted // and before breeding, trading, culling etc (See Clock event order) // Calculated by // critical weight & // juvenile (unweaned) death based on mothers weight & // adult weight adjusted base mortality. RuminantHerd ruminantHerd = Resources.RuminantHerd(); List <Ruminant> herd = ruminantHerd.Herd; // weight based mortality List <Ruminant> died = herd.Where(a => a.Weight < (a.HighWeight * (1.0 - a.BreedParams.ProportionOfMaxWeightToSurvive))).ToList(); // set died flag died.Select(a => { a.SaleFlag = Common.HerdChangeReason.Died; return(a); }).ToList(); ruminantHerd.RemoveRuminant(died); // base mortality adjusted for condition foreach (var ind in ruminantHerd.Herd) { double mortalityRate = 0; if (!ind.Weaned) { mortalityRate = 0; if ((ind.Mother == null) || (ind.Mother.Weight < ind.BreedParams.CriticalCowWeight * ind.StandardReferenceWeight)) { // if no mohter assigned or mother's weight is < CriticalCowWeight * SFR mortalityRate = ind.BreedParams.JuvenileMortalityMaximum; } else { // if mother's weight >= criticalCowWeight * SFR mortalityRate = Math.Exp(-Math.Pow(ind.BreedParams.JuvenileMortalityCoefficient * (ind.Mother.Weight / ind.Mother.NormalisedAnimalWeight), ind.BreedParams.JuvenileMortalityExponent)); } mortalityRate = mortalityRate + ind.BreedParams.MortalityBase; mortalityRate = Math.Max(mortalityRate, ind.BreedParams.JuvenileMortalityMaximum); } else { mortalityRate = 1 - (1 - ind.BreedParams.MortalityBase) * (1 - Math.Exp(Math.Pow(-(ind.BreedParams.MortalityCoefficient * (ind.Weight / ind.NormalisedAnimalWeight - ind.BreedParams.MortalityIntercept)), ind.BreedParams.MortalityExponent))); } if (WholeFarm.RandomGenerator.NextDouble() <= mortalityRate) { ind.Died = true; } } died = herd.Where(a => a.Died).ToList(); died.Select(a => { a.SaleFlag = Common.HerdChangeReason.Died; return(a); }).ToList(); ruminantHerd.RemoveRuminant(died); }
private void OnWFAgeResources(object sender, EventArgs e) { RuminantHerd ruminantHerd = Resources.RuminantHerd(); List <Ruminant> herd = ruminantHerd.Herd; // grow all individuals foreach (Ruminant ind in herd) { ind.Age++; } }
private void OnWFRequestFeed(object sender, EventArgs e) { if (labourLimiter > 0) { RuminantHerd ruminantHerd = Resources.RuminantHerd(); List <Ruminant> herd = ruminantHerd.Herd; if (herd == null && herd.Count == 0) { return; } // get month from clock int month = Clock.Today.Month; // get list from filters foreach (var child in this.Children) { if (child.GetType() == typeof(RuminantFilterGroup)) { foreach (Ruminant ind in herd.Filter(child as RuminantFilterGroup)) { RuminantFeedRequest freqest = new RuminantFeedRequest(); freqest.FeedActivity = this; freqest.Requestor = ind; freqest.Amount = 0; switch (FeedStyle) { case RuminantFeedActivityTypes.SpecifiedDailyAmount: freqest.Amount = (child as RuminantFilterGroup).MonthlyValues[month - 1] * 30.4; // * ind.Number; break; case RuminantFeedActivityTypes.ProportionOfWeight: freqest.Amount = (child as RuminantFilterGroup).MonthlyValues[month - 1] * ind.Weight * 30.4; // * ind.Number; break; case RuminantFeedActivityTypes.ProportionOfPotentialIntake: freqest.Amount = (child as RuminantFilterGroup).MonthlyValues[month - 1] * ind.PotentialIntake; // * ind.Number; break; case RuminantFeedActivityTypes.ProportionOfRemainingIntakeRequired: freqest.Amount = (child as RuminantFilterGroup).MonthlyValues[month - 1] * (ind.PotentialIntake - ind.Intake); // * ind.Number; break; default: break; } freqest.Amount *= labourLimiter; FoodSource.Remove(freqest); } } } } }
private void OnCLEMAnimalStock(object sender, EventArgs e) { // this event happens after management has marked individuals for purchase or sale. if (Clock.Today.Month == AssessmentMonth) { // Get ENSO forcase for current time ENSOState forecastEnsoState = GetENSOMeasure(); // calculate dry season pasture available for each managed paddock holding stock RuminantHerd ruminantHerd = Resources.RuminantHerd(); foreach (var newgroup in ruminantHerd.Herd.Where(a => a.Location != "").GroupBy(a => a.Location)) { // total adult equivalents of all breeds on pasture for utilisation double totalAE = newgroup.Sum(a => a.AdultEquivalent); // determine AE marked for sale and purchase of managed herd double markedForSaleAE = newgroup.Where(a => a.ReadyForSale && a.HerdName == HerdName).Sum(a => a.AdultEquivalent); double purchaseAE = ruminantHerd.PurchaseIndividuals.Where(a => a.Location == newgroup.Key && a.HerdName == HerdName).Sum(a => a.AdultEquivalent); double herdChange = 1.0; switch (forecastEnsoState) { case ENSOState.Neutral: break; case ENSOState.ElNino: GrazeFoodStoreType pasture = Resources.GetResourceItem(this, typeof(GrazeFoodStoreType), newgroup.Key, OnMissingResourceActionTypes.Ignore, OnMissingResourceActionTypes.Ignore) as GrazeFoodStoreType; double kgha = pasture.TonnesPerHectare * 1000; //NOTE: ensure calculation method in relationship is fixed values herdChange = this.PastureToStockingChangeElNino.SolveY(kgha); break; case ENSOState.LaNina: pasture = Resources.GetResourceItem(this, typeof(GrazeFoodStoreType), newgroup.Key, OnMissingResourceActionTypes.Ignore, OnMissingResourceActionTypes.Ignore) as GrazeFoodStoreType; kgha = pasture.TonnesPerHectare * 1000; herdChange = this.PastureToStockingChangeLaNina.SolveY(kgha); break; default: break; } if (herdChange > 1.0) { double toBuyAE = Math.Max(0, (totalAE * herdChange) - purchaseAE); HandleRestocking(toBuyAE, newgroup.Key, newgroup.FirstOrDefault()); } else if (herdChange < 1.0) { double toSellAE = Math.Max(0, (totalAE * (1 - herdChange)) - markedForSaleAE); HandleDestocking(toSellAE, newgroup.Key); } } } }
private void HandleDestocking(double animalEquivalentsforSale, string paddockName) { if (animalEquivalentsforSale <= 0) { AeDestocked = 0; this.Status = ActivityStatus.Ignored; return; } // move to underutilised paddocks // TODO: This can be added later as an activity including spelling // remove all potential purchases from list as they can't be supported. // This does not change the shortfall AE as they were not counted in TotalAE pressure. RuminantHerd ruminantHerd = Resources.RuminantHerd(); ruminantHerd.PurchaseIndividuals.RemoveAll(a => a.Location == paddockName); // remove individuals to sale as specified by destock groups foreach (var item in FindAllChildren <RuminantGroup>().Where(a => a.Reason == RuminantStockGroupStyle.Destock)) { // works with current filtered herd to obey filtering. var herd = CurrentHerd(false) .Where(a => a.Location == paddockName && !a.ReadyForSale) .FilterRuminants(item) .ToList(); int cnt = 0; while (cnt < herd.Count() && animalEquivalentsforSale > 0) { this.Status = ActivityStatus.Success; if (herd[cnt].SaleFlag != HerdChangeReason.DestockSale) { animalEquivalentsforSale -= herd[cnt].AdultEquivalent; herd[cnt].SaleFlag = HerdChangeReason.DestockSale; } cnt++; } if (animalEquivalentsforSale <= 0) { AeDestocked = 0; this.Status = ActivityStatus.Success; return; } } AeDestocked = AeToDestock - animalEquivalentsforSale; this.Status = ActivityStatus.Partial; // handling of sucklings with sold female is in RuminantActivityBuySell // buy or sell is handled by the buy sell activity }
public IEnumerable <RuminantType> GetRuminants(RuminantHerd herd) { List <RuminantType> types = new List <RuminantType>(); // Iterate over all breeds, adding cohorts and pricing to each foreach (string breed in PresentBreeds) { RuminantType type = new RuminantType(herd, breed); SetParameters(type); types.Add(type); } return(types); }
private void OnCLEMAnimalStock(object sender, EventArgs e) { // this event happens after management has marked individuals for purchase or sale. if (Clock.Today.Month == AssessmentMonth) { // calculate dry season pasture available for each managed paddock holding stock not flagged for sale RuminantHerd ruminantHerd = Resources.RuminantHerd(); foreach (var paddockGroup in ruminantHerd.Herd.Where(a => a.Location != "" & a.SaleFlag == HerdChangeReason.None).GroupBy(a => a.Location)) { // total adult equivalents of all breeds on pasture for utilisation double AETotal = paddockGroup.Sum(a => a.AdultEquivalent); // determine AE marked for sale and purchase of managed herd double AEmarkedForSale = paddockGroup.Where(a => a.ReadyForSale & a.HerdName == HerdName).Sum(a => a.AdultEquivalent); double AEPurchase = ruminantHerd.PurchaseIndividuals.Where(a => a.Location == paddockGroup.Key & a.HerdName == HerdName).Sum(a => a.AdultEquivalent); double ShortfallAE = 0; // Determine total feed requirements for dry season for all ruminants on the pasture // We assume that all ruminant have the BaseAnimalEquivalent to the specified herd ShortfallAE = 0; GrazeFoodStoreType pasture = Resources.GetResourceItem(this, typeof(GrazeFoodStoreType), paddockGroup.Key, OnMissingResourceActionTypes.ReportErrorAndStop, OnMissingResourceActionTypes.ReportErrorAndStop) as GrazeFoodStoreType; double pastureBiomass = pasture.Amount; // Adjust fodder balance for detachment rate (6%/month) double feedRequiredAE = paddockGroup.FirstOrDefault().BreedParams.BaseAnimalEquivalent * 0.02 * 30.4; // 2% of AE animal per day for (int i = 0; i < this.DrySeasonLength; i++) { pastureBiomass *= (1.0 - pasture.DetachRate); pastureBiomass -= feedRequiredAE * AETotal; } // Shortfall in Fodder in kg per hectare double pastureShortFallKgHa = pastureBiomass / pasture.Area; pastureShortFallKgHa = Math.Max(0, pastureShortFallKgHa - FeedLowLimit); // Shortfalll in Fodder in kg for paddock double pastureShortFallKg = pastureShortFallKgHa * pasture.Area; if (pastureShortFallKg == 0) { return; } // number of AE to sell to balance shortfall_kg ShortfallAE = pastureShortFallKg / feedRequiredAE; // get prediction HandleDestocking(ShortfallAE, paddockGroup.Key); } } }
private void OnWFAnimalBuy(object sender, EventArgs e) { RuminantHerd ruminantHerd = Resources.RuminantHerd(); Finance Accounts = Resources.FinanceResource() as Finance; FinanceType bankAccount = Accounts.GetFirst() as FinanceType; var newRequests = ruminantHerd.PurchaseIndividuals.Where(a => a.BreedParams.Breed == BreedName).ToList(); foreach (var newgroup in newRequests.GroupBy(a => a.SaleFlag)) { double fundsAvailable = 100000000; if (bankAccount != null) { fundsAvailable = bankAccount.FundsAvailable; } double cost = 0; foreach (var newind in newgroup) { double value = 0; if (newgroup.Key == Common.HerdChangeReason.SirePurchase) { value = BreedingSirePrice; } else { RuminantValue getvalue = PriceList.Where(a => a.Age < newind.Age).OrderBy(a => a.Age).LastOrDefault(); value = getvalue.PurchaseValue * ((getvalue.Style == Common.PricingStyleType.perKg) ? newind.Weight : 1.0); } if (cost + value <= fundsAvailable) { ruminantHerd.AddRuminant(newind); cost += value; } else { break; } } if (bankAccount != null) { bankAccount.Remove(cost, this.Name, newgroup.Key.ToString()); } } }
/// <summary> /// Validate model /// </summary> /// <param name="validationContext"></param> /// <returns></returns> public IEnumerable <ValidationResult> Validate(ValidationContext validationContext) { ruminantHerd = resources.FindResourceGroup <RuminantHerd>(); var results = new List <ValidationResult>(); // check that this activity has a parent of type CropActivityManageProduct if (ruminantHerd is null) { string[] memberNames = new string[] { "Missing resource" }; results.Add(new ValidationResult($"No ruminant herd resource could be found for [ReportRuminantAttributeSummary] [{this.Name}]", memberNames)); } if (!this.FindAllChildren <RuminantGroup>().Any()) { string[] memberNames = new string[] { "Missing ruminant filter group" }; results.Add(new ValidationResult($"The [ReportRuminantAttributeSummary] [{this.Name}] requires at least one filter group to identify individuals to report", memberNames)); } return(results); }
private void OnCLEMStartOfTimeStep(object sender, EventArgs e) { RuminantHerd ruminantHerd = Resources.RuminantHerd(); List <Ruminant> herd = ruminantHerd.Herd; // Natural weaning takes place here before animals eat or take milk from mother. foreach (var ind in herd.Where(a => a.Weaned == false)) { double weaningAge = ind.BreedParams.NaturalWeaningAge; if (weaningAge == 0) { weaningAge = ind.BreedParams.GestationLength; } if (ind.Age >= weaningAge) { ind.Wean(true, "Natural"); } } }
private void OnWFPotentialIntake(object sender, EventArgs e) { RuminantHerd ruminantHerd = Resources.RuminantHerd(); List <Ruminant> herd = ruminantHerd.Herd; // Natural weaning takes place here before animals eat or take milk from mother. foreach (var ind in herd.Where(a => a.Weaned == false)) { if (ind.Age >= ind.BreedParams.GestationLength + 1) { ind.Wean(); } } // Calculate potential intake and reset stores foreach (var ind in herd) { // reset tallies at start of the month ind.DietDryMatterDigestibility = 0; ind.PercentNOfIntake = 0; ind.Intake = 0; ind.MilkIntake = 0; CalculatePotentialIntake(ind); } // TODO: Future cohort based run may speed up simulation // Calculate by cohort method and assign values to individuals. // Need work out what grouping should be based on Name, Breed, Gender, Weight, Parity... // This approach will not currently work as individual may have individual weights and females may be in various states of breeding. // //var cohorts = herd.GroupBy(a => new { a.BreedParams.Breed, a.Gender, a.Age, lactating = (a.DryBreeder | a.Milk) }); //foreach (var cohort in cohorts) //{ // CalculatePotentialIntake(cohort.FirstOrDefault()); // double potintake = cohort.FirstOrDefault().PotentialIntake; // foreach (var ind in cohort) // { // ind.PotentialIntake = potintake; // } //} }
private void OnCLEMInitialiseActivity(object sender, EventArgs e) { this.InitialiseHerd(false, true); List <Ruminant> testherd = this.CurrentHerd(true); // check if finance is available and warn if not supplying bank account. if (Resources.ResourceGroupExist(typeof(Finance))) { if (Resources.ResourceItemsExist(typeof(Finance))) { if (BankAccountName == "") { Summary.WriteWarning(this, "No bank account has been specified in [a={0}] while Finances are available in the simulation. No financial transactions will be recorded for the purchase and sale of animals."); } } } if (BankAccountName != "") { bankAccount = Resources.GetResourceItem(this, BankAccountName, OnMissingResourceActionTypes.Ignore, OnMissingResourceActionTypes.ReportErrorAndStop) as FinanceType; } // get trucking settings trucking = Apsim.Children(this, typeof(TruckingSettings)).FirstOrDefault() as TruckingSettings; // check if pricing is present if (bankAccount != null) { RuminantHerd ruminantHerd = Resources.RuminantHerd(); var breeds = ruminantHerd.Herd.Where(a => a.BreedParams.Breed == this.PredictedHerdBreed).GroupBy(a => a.HerdName); foreach (var herd in breeds) { if (!herd.FirstOrDefault().BreedParams.PricingAvailable()) { Summary.WriteWarning(this, String.Format("No pricing schedule has been provided for herd [r={0}]. No transactions will be recorded for activity [a={1}]", herd.Key, this.Name)); } } } }
/// <summary> /// Model all present ruminant breeds /// </summary> public IEnumerable <RuminantType> GetRuminants(RuminantHerd parent) { List <RuminantType> ruminants = new List <RuminantType>(); // Iterate over all the present breeds foreach (int id in RumIDs) { RumActiveID = id; string breed = RumNumbers.ColumnNames[id].Replace(".", ""); RuminantType ruminant = new RuminantType(parent) { Name = breed, Breed = breed }; SetParameters(ruminant); ruminants.Add(ruminant); } return(ruminants); }
/// <summary> /// Method to determine resources required for this activity in the current month /// </summary> /// <returns>List of required resource requests</returns> public override List <ResourceRequest> GetResourcesNeededForActivity() { ResourceRequestList = null; double kgPerHa = grazeType.Amount / paddockActivity.Area; RuminantHerd ruminantHerd = Resources.RuminantHerd(); List <Ruminant> herd = ruminantHerd.Herd.Where(a => a.Location == PaddockName).ToList(); if (herd.Count() > 0) { double amount = 0; // get list of all Ruminants in this paddock foreach (Ruminant ind in herd) { // Reduce potential intake based on pasture quality for the proportion consumed. // TODO: build in pasture quality intake correction // calculate intake from potential modified by pasture availability and hours grazed amount += ind.PotentialIntake * (1 - Math.Exp(-ind.BreedParams.IntakeCoefficientBiomass * kgPerHa)) * (HoursGrazed / 8); } if (ResourceRequestList == null) { ResourceRequestList = new List <ResourceRequest>(); } ResourceRequestList.Add(new ResourceRequest() { AllowTransmutation = true, Required = amount, ResourceType = typeof(GrazeFoodStore), ResourceTypeName = this.grazeType.Name, ActivityModel = this } ); } return(ResourceRequestList); }
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; } } } } } }