private void OnCLEMInitialiseActivity(object sender, EventArgs e) { InsideMultiHarvestSequence = false; // activity is performed in CLEMDoCutAndCarry not CLEMGetResources this.AllocationStyle = ResourceAllocationStyle.Manual; fileCrop = simulation.FindAllDescendants().Where(a => a.Name == ModelNameFileCrop).FirstOrDefault() as IFileCrop; if (fileCrop == null) { throw new ApsimXException(this, String.Format("Unable to locate crop data reader [x={0}] requested by [a={1}]", this.ModelNameFileCrop ?? "Unknown", this.Name)); } LinkedResourceItem = Resources.FindResourceType <ResourceBaseWithTransactions, IResourceType>(this, StoreItemName, OnMissingResourceActionTypes.ReportErrorAndStop, OnMissingResourceActionTypes.ReportErrorAndStop); if ((LinkedResourceItem as Model).Parent is GrazeFoodStore) { // set manager of graze food store if linked (LinkedResourceItem as GrazeFoodStoreType).Manager = (Parent as IPastureManager); addReason = "Growth"; } // look up tree until we find a parent to allow nested crop products for rotate vs mixed cropping/products parentManagementActivity = FindAncestor <CropActivityManageCrop>(); // Retrieve harvest data from the forage file for the entire run. // only get entries where a harvest happened (Amtkg > 0) HarvestData = fileCrop.GetCropDataForEntireRun(parentManagementActivity.LinkedLandItem.SoilType, CropName, clock.StartDate, clock.EndDate).Where(a => a.AmtKg > 0).OrderBy(a => a.Year * 100 + a.Month).ToList <CropDataType>(); if ((HarvestData == null) || (HarvestData.Count == 0)) { Summary.WriteWarning(this, $"Unable to locate any harvest data in [x={fileCrop.Name}] using [x={fileCrop.FileName}] for soil type [{parentManagementActivity.LinkedLandItem.SoilType}] and crop name [{CropName}] between the dates [{clock.StartDate.ToShortDateString()}] and [{clock.EndDate.ToShortDateString()}]"); } IsTreeCrop = (TreesPerHa == 0) ? false : true; //using this boolean just makes things more readable. UnitsToHaConverter = (parentManagementActivity.LinkedLandItem.Parent as Land).UnitsOfAreaToHaConversion; // locate a cut and carry limiter associated with this event. limiter = LocateCutAndCarryLimiter(this); // check if harvest type tags have been provided HarvestTagsUsed = HarvestData.Where(a => a.HarvestType != "").Count() > 0; if (LinkedResourceItem is GrazeFoodStoreType) { double firstMonthsGrowth = 0; CropDataType cropData = HarvestData.Where(a => a.Year == clock.StartDate.Year && a.Month == clock.StartDate.Month).FirstOrDefault(); if (cropData != null) { firstMonthsGrowth = cropData.AmtKg; } (LinkedResourceItem as GrazeFoodStoreType).SetupStartingPasturePools(UnitsToHaConverter * (Parent as CropActivityManageCrop).Area * UnitsToHaConverter, firstMonthsGrowth); addReason = "Growth"; } }
/// <summary> /// Get the cost date from the harvest date. /// This will happen every month in case the harvest has occured and there is a new harvest date. /// </summary> /// <returns></returns> private DateTime CostDateFromHarvestDate() { DateTime nextdate; CropDataType nextharvest = parentGrowCrop.HarvestData.FirstOrDefault(); if (nextharvest != null) { nextdate = nextharvest.HarvestDate; return(nextdate.AddMonths(-1 * MthsBeforeHarvest)); } else { return(new DateTime()); } }
private void OnCLEMDoCutAndCarry(object sender, EventArgs e) { int year = Clock.Today.Year; int month = Clock.Today.Month; //nb. we are relying on the fact that the HarvestData list is sorted by date. CropDataType nextHarvest = HarvestData.FirstOrDefault(); if (nextHarvest != null) { //if this month is a harvest month for this crop if ((year == nextHarvest.Year) && (month == nextHarvest.Month)) { double totalamount; if (IsTreeCrop) { totalamount = nextHarvest.AmtKg * TreesPerHa * cropLand.Area * unitsToHaConverter * (PercentKept / 100); } else { totalamount = nextHarvest.AmtKg * cropLand.Area * unitsToHaConverter * (PercentKept / 100); } switch (Store) { case StoresForCrops.HumanFoodStore: if (totalamount > 0) { //TODO: check that there is no N provided with grain LinkedHumanFoodItem.Add(totalamount, this.Name, "Harvest"); } break; case StoresForCrops.AnimalFoodStore: if (totalamount > 0) { //if Npct column was not in the file if (nextHarvest.Npct == double.NaN) { //Add without adding any new nitrogen. //The nitrogen value for this feed item in the store remains the same. LinkedAnimalFoodItem.Add(totalamount, this.Name, "Harvest"); } else { FoodResourcePacket packet = new FoodResourcePacket() { Amount = totalamount, PercentN = nextHarvest.Npct }; LinkedAnimalFoodItem.Add(packet, this.Name, "Harvest"); } } break; case StoresForCrops.ProductStore: if (totalamount > 0) { LinkedProductItem.Add(totalamount, this.Name, "Harvest"); } break; default: throw new Exception(String.Format("Store {0} is not supported for {1}", Enum.GetName(typeof(StoresForCrops), Store), this.Name)); } //Now remove the first item from the harvest data list because it has happened. //This causes a problem for the children of this model //because of a race condition that occurs if user sets MthsBeforeHarvest = 0 //for any of the children of this model. //Then because this model and children are all executing on the harvest month and //this executes first and it removes the harvest from the harvest list, //then the chidren never get the Clock.Today == harvest date (aka costdate). //So to fix this problem, in the children we store the next harvest date (aka costdate) //in a global variable and don't update its value //until after we have done the Clock.Today == harvest date (aka costdate) comparison. HarvestData.RemoveAt(0); } } }