/// <summary> /// /// </summary> public override void Simulate() { try { if (CurrentCrop != null) { if (UseLAIModel()) { if (CurrentCrop.GetInFallow()) { TryAndPlantNewCrop(); } else if (CurrentCrop.IsGrowing()) { CurrentCrop.Simulate(); } } else { CurrentCrop.Simulate(); } ++DaysSinceHarvest; TotalTranspiration = CurrentCrop.TotalTranspiration; TotalEvapotranspiration = CurrentCrop.TotalTranspiration + Sim.SoilController.SoilEvap; UpdateCropWaterBalanceParameters(); } } catch (Exception e) { throw new Exception(e.Message); } }
/// <summary> /// /// </summary> public override void Simulate() { try { if (CurrentCrop != null) { if (UseLAIModel()) { if (CurrentCrop.GetInFallow()) { TryAndPlantNewCrop(); } else if (CurrentCrop.IsGrowing()) { CurrentCrop.Simulate(); } } else { CurrentCrop.Simulate(); } ++days_since_harvest; total_transpiration = CurrentCrop.total_transpiration; total_evapotranspiration = CurrentCrop.total_transpiration + sim.out_WatBal_SoilEvap_mm; UpdateCropWaterBalanceParameters(); } } catch (Exception e) { throw new Exception(e.Message); } }
/// <summary> /// /// </summary> /// <param name="crop"></param> /// <returns></returns> public bool CanPlantCrop(VegObjectController crop) { // Here are a few notes to try and get your head around the logic here. // First of all check to see if we leave left sufficient gap between this new // rotation and the previous rotation of this crop. // Case 1: // First test to see if this is the CurrentCrop. // If so, then make sure that we HAVENT exceeded max rotation count. Then we must // see if actually meet the planting criteria. If any of these fail, then return // "false" so that we can test another crop. Otherwise return "true" to tell the // sim to replant the CurrentCrop // Case 2: // If this is NOT the CurrentCrop - we had better first check that the CurrentCrop // is still expected to be in rotation. Then check to see that the sowing criteria // has been met. Return "true" if all good, otherwise return "false" so we can test // another crop. If we run out of crops, then the CurrentCrop stays in fallow. if (crop.IsSequenceCorrect() && crop.DoesCropMeetSowingCriteria()) { if (crop == CurrentCrop) { return(crop.IsCropUnderMaxContinuousRotations()); } else if (CurrentCrop.HasCropHadSufficientContinuousRotations()) { return(crop.HasCropBeenAbsentForSufficientYears(sim.today)); } } return(false); }
/// <summary> /// /// </summary> public void CalculateTotalResidue() { //TODO: Make the crop residue function more generic -- remove type condition if (CurrentCrop != null && CurrentCrop.GetType() == typeof(LAIVegObjectController)) { TotalCropResidue = 0; TotalResidueCover = 0; LAIVegObjectController crop = (LAIVegObjectController)CurrentCrop; TotalResidueCover = crop.ResidueCover; crop.CalculateResidue(); int count = ChildControllers.Count; for (int i = 1; i < count; ++i) { int index = GetCropIndex(crop) + 1; if (index == count) { index = 0; } crop = (LAIVegObjectController)ChildControllers[index]; TotalResidueCover = Math.Min(1.0, TotalResidueCover + crop.ResidueCover * (1 - TotalResidueCover)); } for (int i = 0; i < count; ++i) { TotalCropResidue += ((VegObjectController)ChildControllers[i]).ResidueAmount; } } else { TotalCropResidue = ((VegObjectController)ChildControllers[0]).CropResidue; TotalResidueCover = ((VegObjectController)ChildControllers[0]).ResidueCover; } TotalResidueCoverPercent = TotalResidueCover * 100.0; }
/// <summary> /// /// </summary> /// <returns></returns> public double CalcFallowSoilWater() { if (CurrentCrop != null) { return(CurrentCrop.CalcFallowSoilWater()); } return(0); }
/// <summary> /// /// </summary> /// <returns></returns> public bool InFallow() { if (CurrentCrop != null) { return(CurrentCrop.GetInFallow()); } return(true); }
/// <summary> /// /// </summary> /// <returns></returns> public double GetPotentialSoilEvaporation() { if (CurrentCrop != null) { return(CurrentCrop.GetPotentialSoilEvaporation()); } return(0); }
/// <summary> /// /// </summary> /// <returns></returns> public bool IsPlanting() { if (CurrentCrop != null) { return(CurrentCrop.GetIsPlanting()); } return(false); }
/// <summary> /// /// </summary> /// <param name="current"></param> /// <returns></returns> public double GetCropCoverIfLAIModel(double current) { if (CurrentCrop.GetType() == typeof(LAIVegObjectController)) { return(CurrentCrop.crop_cover); //LAI Model uses cover from the end of the previous day //whereas Cover model predefines at the start of the day } return(current); }
/// <summary> /// /// </summary> public void ResetAnyParametersIfRequired() { try { if (CurrentCrop != null) { CurrentCrop.ResetCropParametersAfterHarvest(); } } catch (Exception e) { throw new Exception(e.Message); } }
internal bool IsPlanting() { try { if (CurrentCrop != null) { return(CurrentCrop.GetIsPlanting()); } } catch (Exception ex) { throw ErrorLogger.CreateException(ex); } return(false); }
internal double CalcFallowSoilWater() { try { if (CurrentCrop != null) { return(CurrentCrop.CalcFallowSoilWater()); } } catch (Exception ex) { throw ErrorLogger.CreateException(ex); } return(0); }
/// <summary> /// /// </summary> /// <returns></returns> public double GetTotalCover() { if (CurrentCrop != null) { if (CurrentCrop.GetType() == typeof(LAIVegObjectController)) { return(Math.Min(1.0, CurrentCrop.crop_cover + sim.total_residue_cover * (1 - CurrentCrop.crop_cover))); } else { return(CurrentCrop.GetTotalCover()); } } return(0); }
internal double GetPotentialSoilEvaporation() { try { if (CurrentCrop != null) { return(CurrentCrop.GetPotentialSoilEvaporation()); } } catch (Exception ex) { throw ErrorLogger.CreateException(ex); } return(0); }
/// <summary> /// /// </summary> /// <returns></returns> public double GetTotalCover() { if (CurrentCrop != null) { if (CurrentCrop.GetType() == typeof(LAIVegObjectController)) { return(Math.Min(1.0, CurrentCrop.CropCover + Sim.SoilController.TotalResidueCover * (1 - CurrentCrop.CropCover))); } else { return(CurrentCrop.GetTotalCover()); } } return(0); }
internal bool InFallow() { try { if (CurrentCrop != null) { return(CurrentCrop.GetInFallow()); } } catch (Exception ex) { throw ErrorLogger.CreateException(ex); } return(true); }
public void TryModelVegetation() { try { if (VegetationModules != null) { if (CurrentCrop != null) { if (UseLAIModel()) { if (CurrentCrop.GetInFallow()) { foreach (var crop in SortedVegetationModules) { if (CanPlantCrop(crop)) { crop.Plant(); if (IrrigationModule != null) { IrrigationModule.FirstIrrigation = true; } return; } } } else if (CurrentCrop.IsGrowing()) { CurrentCrop.Simulate(); } } else { CurrentCrop.Simulate(); } ++DaysSinceHarvest; TotalTranspiration = CurrentCrop.TotalTranspiration; TotalEvapotranspiration = CurrentCrop.TotalTranspiration + SoilModule.SoilEvap; //UpdateCropWaterBalanceParameters(); } } } catch (Exception ex) { throw ErrorLogger.CreateException(ex); } }
internal double GetCropCoverIfLAIModel(double current) { try { if (CurrentCrop != null) { if (CurrentCrop.GetType() == typeof(HowLeakyEngineModule_LAIVeg)) { return(CurrentCrop.CropCover); //LAI Model uses cover from the end of the previous day //whereas Cover model predefines at the start of the day } } } catch (Exception ex) { throw ErrorLogger.CreateException(ex); } return(current); }
internal void CalculateTotalResidue() { try { //TODO: Make the crop residue function more generic -- remove type condition if (CurrentCrop != null && CurrentCrop.GetType() == typeof(HowLeakyEngineModule_LAIVeg)) { TotalCropResidue = 0; TotalResidueCover = 0; HowLeakyEngineModule_LAIVeg crop = (HowLeakyEngineModule_LAIVeg)CurrentCrop; TotalResidueCover = crop.ResidueCover; crop.CalculateResidue(); int count = VegetationModules.Count; for (int i = 1; i < count; ++i) { int index = GetCropIndex(crop) + 1; if (index == count) { index = 0; } crop = (HowLeakyEngineModule_LAIVeg)VegetationModules[index]; TotalResidueCover = Math.Min(1.0, TotalResidueCover + crop.ResidueCover * (1 - TotalResidueCover)); } for (int i = 0; i < count; ++i) { TotalCropResidue += ((HowLeakyEngineModule_LAIVeg)VegetationModules[i]).ResidueAmount; } } else { TotalCropResidue = VegetationModules[0].CropResidue; TotalResidueCover = VegetationModules[0].ResidueCover; } TotalResidueCoverPercent = TotalResidueCover * 100.0; } catch (Exception ex) { throw ErrorLogger.CreateException(ex); } }
internal double GetTotalCover() { try { if (CurrentCrop != null) { if (CurrentCrop.GetType() == typeof(HowLeakyEngineModule_LAIVeg)) { return(Math.Min(1.0, CurrentCrop.CropCover + SoilModule.TotalResidueCover * (1 - CurrentCrop.CropCover))); } else { return(CurrentCrop.GetTotalCover()); } } } catch (Exception ex) { throw ErrorLogger.CreateException(ex); } return(0); }
/// <summary> /// /// </summary> /// <returns></returns> public bool UseLAIModel() { return(CurrentCrop.GetType() == typeof(LAIVegObjectController)); //FIXME }
public void OnProcess() { //set up data table int NumLayers = 0; AllRootSystems.Rows.Clear(); foreach (Paddock p in paddock.ChildPaddocks) { foreach (Component c in p.Crops) { string PlantStatus; if (!c.Get("plant_status", out PlantStatus)) { throw new Exception("Could not find plant_status for crop :" + c.Name); } if (PlantStatus != "out") //if crop is not in ground, we don't care about it { if (c.GetObject("RootSystem", ref RootData)) //crop has a RootData structre { Dictionary <string, double> SWStrength = CalcSWSourceStrength(RootData); foreach (RootSystemZoneType zone in RootData.Zone) //add each zone to the table { AllRootSystems.Rows.Add(zone.ZoneName, c.Name, RootData.SWDemand, SWStrength, zone, true); } NumLayers = RootData.Zone[0].kl.Length; } else //crop does not have RootData structure, so make one. { Dictionary <string, double> SWStrength = new Dictionary <string, double>(); RootData = new RootSystemType(); RootData.Zone = new RootSystemZoneType[1]; RootData.Zone[0] = new RootSystemZoneType(); RootData.Zone[0].ZoneName = p.Name; RootData.Zone[0].ZoneArea = 1; if (!c.Get("sw_demand", out RootData.SWDemand)) { throw new Exception("Could not get sw_demand for crop " + c.Name); } if (!c.Get("root_depth", out RootData.Zone[0].RootDepth)) { throw new Exception("Could not get root_depth for crop " + c.Name); } if (!c.Get("ll", out RootData.Zone[0].ll)) { throw new Exception("Could not get ll for crop " + c.Name); } if (!c.Get("kl", out RootData.Zone[0].kl)) { throw new Exception("Could not get kl for crop " + c.Name); } SoilWat = (Component)p.LinkByType("SoilWat"); SWStrength.Add(p.Name, 1); if (!SoilWat.Get("dlayer", out RootData.Zone[0].dlayer)) { throw new Exception("Could not get dlayer for paddock " + p.Name); } AllRootSystems.Rows.Add(RootData.Zone[0].ZoneName, c.Name, RootData.SWDemand, SWStrength, RootData.Zone[0], true); NumLayers = RootData.Zone[0].kl.Length; } } } } //use LINQ to extract the paddocks for processing IEnumerable <string> paddockNames = AllRootSystems.AsEnumerable().Select <DataRow, string>(name => (string)name.ItemArray[0]).Distinct(); //do water allocation for each paddock foreach (string PaddockName in paddockNames) { IEnumerable <DataRow> RootZones = AllRootSystems.AsEnumerable().Where(row => row.ItemArray[0].Equals(PaddockName)); Paddock p = (Paddock)paddock.LinkByName(PaddockName); Component fieldProps = (Component)p.LinkByName("FieldProps"); double fieldArea; if (fieldProps == null || !fieldProps.Get("fieldArea", out fieldArea)) { throw new Exception("Could not find FieldProps component in field " + PaddockName); } Component Soil = (Component)p.LinkByType("SoilWat"); double[] SWDep; double[] dlayer; Soil.Get("dlayer", out dlayer); Soil.Get("sw_dep", out SWDep); double[] CropSWDemand = new double[RootZones.Count()]; for (int i = 0; i < RootZones.Count(); i++) //get demand for all crops in paddock using relative SW strength { Dictionary <string, double> PaddockSWDemands = (Dictionary <string, double>)RootZones.ToArray()[i].ItemArray[3]; CropSWDemand[i] = PaddockSWDemands[p.Name] * (double)RootZones.ToArray()[i].ItemArray[2]; } double[,] RelKLStrength = CalcRelKLStrength(RootZones, CropSWDemand); double[,] RelSWLayerStrength = CalcRelSWLayerStrength(RootZones, SWDep, NumLayers); double[,] SWSupply = CalcSWSupply(RootZones, SWDep, NumLayers); double[,] LayerUptake = new double[RootZones.Count(), NumLayers]; double[] LastCropSWDemand; double[,] LastSWSupply; int count = 0; do { count++; LastCropSWDemand = CropSWDemand; LastSWSupply = SWSupply; for (int i = 0; i < RootZones.Count(); i++) //get as much water as possible for the layer using relative kl strengths { RootSystemZoneType Zone = (RootSystemZoneType)RootZones.ToArray()[i].ItemArray[4]; for (int j = 0; j < NumLayers; j++) { if (MathUtility.Sum(CropSWDemand) < MathUtility.Sum(SWSupply)) { LayerUptake[i, j] = CropSWDemand[i] * RelSWLayerStrength[i, j]; } else { LayerUptake[i, j] = SWSupply[i, j] * RelKLStrength[j, i] * RootProportion(j, Zone.RootDepth, dlayer); } if (LayerUptake[i, j] < 0) { throw new Exception("Layer uptake should not be negative"); } } } DenseMatrix Uptake = DenseMatrix.OfArray(LayerUptake); Paddock CurrentPaddock; Component CurrentCrop; for (int i = 0; i < RootZones.Count(); i++) //subtract taken water from the supply and demand { CurrentPaddock = (Paddock)p.LinkByName((string)RootZones.ToArray()[i].ItemArray[0]); CurrentCrop = (Component)CurrentPaddock.LinkByName((string)RootZones.ToArray()[i].ItemArray[1]); CropSWDemand[i] -= Uptake.Row(i).Sum(); if (CurrentCrop != null && CurrentCrop.Name.ToLower().Equals("maize")) { CurrentCrop.Set("arb_water_uptake", Uptake.Row(i).ToArray()); } for (int j = 0; j < NumLayers; j++) { SWSupply[i, j] -= LayerUptake[i, j]; } } //subtract from soil water for (int j = 0; j < Uptake.ColumnCount; j++) { SWDep[j] -= Uptake.Column(j).Sum() / fieldArea; } Soil.Set("sw_dep", SWDep); } while (MathUtility.Sum(LastCropSWDemand) != MathUtility.Sum(CropSWDemand) && MathUtility.Sum(LastSWSupply) != MathUtility.Sum(SWSupply)); } }
public bool UseLAIModel() { return(CurrentCrop.GetType() == typeof(HowLeakyEngineModule_LAIVeg)); }