//----------------------- Public methods ----------------------- /// <summary>Initialise this root instance (and tissues).</summary> /// <param name="zone">The zone the roots belong to.</param> /// <param name="minimumLiveWt">Minimum live DM biomass for this organ (kg/ha).</param> public void Initialise(Zone zone, double minimumLiveWt) { // link to soil models parameters soil = zone.FindInScope <Soil>(); if (soil == null) { throw new Exception($"Cannot find soil in zone {zone.Name}"); } soilPhysical = soil.FindInScope <IPhysical>(); if (soilPhysical == null) { throw new Exception($"Cannot find soil physical in soil {soil.Name}"); } waterBalance = soil.FindInScope <ISoilWater>(); if (waterBalance == null) { throw new Exception($"Cannot find a water balance model in soil {soil.Name}"); } soilCropData = soil.FindDescendant <SoilCrop>(species.Name + "Soil"); if (soilCropData == null) { throw new Exception($"Cannot find a soil crop parameterisation called {species.Name + "Soil"}"); } nutrient = zone.FindInScope <INutrient>(); if (nutrient == null) { throw new Exception($"Cannot find SoilNitrogen in zone {zone.Name}"); } no3 = zone.FindInScope("NO3") as ISolute; if (no3 == null) { throw new Exception($"Cannot find NO3 solute in zone {zone.Name}"); } nh4 = zone.FindInScope("NH4") as ISolute; if (nh4 == null) { throw new Exception($"Cannot find NH4 solute in zone {zone.Name}"); } // initialise soil related variables zoneName = soil.Parent.Name; nLayers = soilPhysical.Thickness.Length; mySoilNH4Available = new double[nLayers]; mySoilNO3Available = new double[nLayers]; mySoilWaterAvailable = new double[nLayers]; // save minimum DM and get target root distribution MinimumLiveDM = minimumLiveWt; TargetDistribution = RootDistributionTarget(); // initialise tissues Live.Initialise(); Dead.Initialise(); }
/// <summary>Calculate the interception loss of water from the canopy</summary> private void CalculateInterception(ZoneMicroClimate ZoneMC) { double sumLAI = 0.0; double sumLAItot = 0.0; for (int i = 0; i <= ZoneMC.numLayers - 1; i++) { for (int j = 0; j <= ZoneMC.Canopies.Count - 1; j++) { sumLAI += ZoneMC.Canopies[j].LAI[i]; sumLAItot += ZoneMC.Canopies[j].LAItot[i]; } } double totalInterception = a_interception * Math.Pow(weather.Rain, b_interception) + c_interception * sumLAItot + d_interception; totalInterception = Math.Max(0.0, Math.Min(0.99 * weather.Rain, totalInterception)); for (int i = 0; i <= ZoneMC.numLayers - 1; i++) { for (int j = 0; j <= ZoneMC.Canopies.Count - 1; j++) { ZoneMC.Canopies[j].interception[i] = MathUtilities.Divide(ZoneMC.Canopies[j].LAI[i], sumLAI, 0.0) * totalInterception; } } ISoilWater zonesoilwater = Apsim.Find(ZoneMC.zone, typeof(ISoilWater)) as ISoilWater; if (zonesoilwater != null) { zonesoilwater.PotentialInfiltration = Math.Max(0, weather.Rain - totalInterception); } }
/// <summary>Calculate the amtospheric potential evaporation rate for each zone</summary> private void CalculateEo(ZoneMicroClimate ZoneMC) { ISoilWater zoneSoilWater = Apsim.Find(ZoneMC.zone, typeof(ISoilWater)) as ISoilWater; ISurfaceOrganicMatter zoneSurfaceOM = Apsim.Find(ZoneMC.zone, typeof(ISurfaceOrganicMatter)) as ISurfaceOrganicMatter; double CoverGreen = 0; for (int j = 0; j <= ZoneMC.Canopies.Count - 1; j++) { if (ZoneMC.Canopies[j].Canopy != null) { CoverGreen += (1 - CoverGreen) * ZoneMC.Canopies[j].Canopy.CoverGreen; } } if (weather != null && zoneSoilWater != null && zoneSurfaceOM != null) { zoneSoilWater.Eo = AtmosphericPotentialEvaporationRate(weather.Radn, weather.MaxT, weather.MinT, zoneSoilWater.Salb, zoneSurfaceOM.Cover, CoverGreen); } }
/// <summary>Constructor.</summary> /// <param name="clockModel">The clock model.</param> /// <param name="zoneModel">The zone model.</param> /// <param name="minHeightDiffForNewLayer">Minimum canopy height diff for new layer.</param> public MicroClimateZone(Clock clockModel, Zone zoneModel, double minHeightDiffForNewLayer) { clock = clockModel; Zone = zoneModel; MinimumHeightDiffForNewLayer = minHeightDiffForNewLayer; canopyModels = Apsim.ChildrenRecursively(Zone, typeof(ICanopy)).Cast <ICanopy>(); modelsThatHaveCanopies = Apsim.ChildrenRecursively(Zone, typeof(IHaveCanopy)).Cast <IHaveCanopy>(); soilWater = Apsim.Find(Zone, typeof(ISoilWater)) as ISoilWater; surfaceOM = Apsim.Find(Zone, typeof(ISurfaceOrganicMatter)) as ISurfaceOrganicMatter; }
/// <summary>Constructor.</summary> /// <param name="clockModel">The clock model.</param> /// <param name="weatherModel">The weather model.</param> /// <param name="zoneModel">The zone model.</param> public MicroClimateZone(Clock clockModel, IWeather weatherModel, Zone zoneModel) { clock = clockModel; weather = weatherModel; Zone = zoneModel; canopyModels = Apsim.ChildrenRecursively(Zone, typeof(ICanopy)).Cast <ICanopy>(); modelsThatHaveCanopies = Apsim.ChildrenRecursively(Zone, typeof(IHaveCanopy)).Cast <IHaveCanopy>(); soilWater = Apsim.Find(Zone, typeof(ISoilWater)) as ISoilWater; surfaceOM = Apsim.Find(Zone, typeof(ISurfaceOrganicMatter)) as ISurfaceOrganicMatter; }
/// <summary>Constructor.</summary> /// <param name="clockModel">The clock model.</param> /// <param name="zoneModel">The zone model.</param> /// <param name="minHeightDiffForNewLayer">Minimum canopy height diff for new layer.</param> public MicroClimateZone(Clock clockModel, Zone zoneModel, double minHeightDiffForNewLayer) { clock = clockModel; Zone = zoneModel; MinimumHeightDiffForNewLayer = minHeightDiffForNewLayer; canopyModels = Zone.FindAllDescendants <ICanopy>().ToList(); modelsThatHaveCanopies = Zone.FindAllDescendants <IHaveCanopy>().ToList(); soilWater = Zone.FindInScope <ISoilWater>(); surfaceOM = Zone.FindInScope <ISurfaceOrganicMatter>(); }
private void OnSimulationCommencing(object sender, EventArgs e) { ZoneList = Parent.FindAllChildren <Zone>().ToList(); SetupTreeProperties(); //pre-fetch static information forestryZones = Parent.FindAllDescendants <Zone>().ToList(); treeZone = ZoneList.FirstOrDefault(); treeZoneWater = treeZone.FindInScope <ISoilWater>(); TreeWaterUptake = new double[ZoneList.Count()]; }
/// <summary> /// Constructor. Copy state from another instance. /// </summary> /// <param name="from">The instance to copy from.</param> public ZoneWaterAndN(ZoneWaterAndN from) { NO3Solute = from.NO3Solute; NH4Solute = from.NH4Solute; soilInZone = from.soilInZone; Zone = from.Zone; WaterBalance = from.WaterBalance; Water = from.Water; NO3N = from.NO3N; NH4N = from.NH4N; }
private void OnSimulationCommencing(object sender, EventArgs e) { ZoneList = Apsim.Children(this.Parent, typeof(Zone)); SetupTreeProperties(); //pre-fetch static information forestryZones = Apsim.ChildrenRecursively(Parent, typeof(Zone)); treeZone = ZoneList[0] as Zone; treeZoneWater = Apsim.Find(treeZone, typeof(ISoilWater)) as ISoilWater; TreeWaterUptake = new double[ZoneList.Count]; }
public void ImporterTests_SoilImports() { string oldXml = ReflectionUtilities.GetResourceAsString("UnitTests.ImporterTestsSoilImports.xml"); var importer = new Importer(); Simulations sims = importer.CreateSimulationsFromXml(oldXml); Soil s = sims.Children[0].Children[0] as Soil; Assert.AreEqual(s.Name, "Soil"); InitialWater initWater = s.Children[0] as InitialWater; Assert.AreEqual(initWater.FractionFull, 0.5); Assert.AreEqual(initWater.PercentMethod, InitialWater.PercentMethodEnum.FilledFromTop); Physical w = s.Children[1] as Physical; Assert.AreEqual(w.Thickness, new double[] { 150, 150, 300, 300 }); Assert.AreEqual(w.BD, new double[] { 1.02, 1.03, 1.02, 1.02 }); Assert.AreEqual(w.LL15, new double[] { 0.29, 0.29, 0.29, 0.29 }); ISoilWater sw = s.Children[2] as ISoilWater; Assert.AreEqual(sw.Thickness, new double[] { 150, 150, 300, 300 }); Assert.IsTrue(s.Children[3] is SoilNitrogen); Assert.IsTrue(s.Children[4] is CERESSoilTemperature); Organic som = s.Children[5] as Organic; Assert.AreEqual(som.Thickness, new double[] { 150, 150, 300, 300 }); Assert.AreEqual(som.Carbon, new double[] { 1.04, 0.89, 0.89, 0.89 }); Assert.AreEqual(som.FBiom, new double[] { 0.025, 0.02, 0.015, 0.01 }); Chemical a = s.Children[6] as Chemical; Assert.AreEqual(a.Thickness, new double[] { 150, 150, 300, 300 }); Assert.AreEqual(a.NO3N, new double[] { 6.5, 2.1, 2.1, 1.0 }); Assert.AreEqual(a.NH4N, new double[] { 0.5, 0.1, 0.1, 0.2 }); Assert.AreEqual(a.EC, new double[] { 0.2, 0.25, 0.31, 0.40 }); Assert.AreEqual(a.PH, new double[] { 8.4, 8.8, 9.0, 9.2 }); Sample sam = s.Children[7] as Sample; Assert.AreEqual(sam.Thickness, new double[] { 150, 150, 300 }); SoilCrop crop = s.Children[1].Children[0] as SoilCrop; Assert.AreEqual(crop.LL, new double[] { 0.29, 0.29, 0.32, 0.38 }); Assert.AreEqual(crop.KL, new double[] { 0.1, 0.1, 0.08, 0.06 }); Assert.AreEqual(crop.XF, new double[] { 1, 1, 1, 1 }); }
/// <summary>Initialises this instance.</summary> public void Initialise() { WaterBalance = soilInZone.FindInScope <ISoilWater>(); NO3Solute = soilInZone.FindInScope <ISolute>("NO3"); NH4Solute = soilInZone.FindInScope <ISolute>("NH4"); var PlantAvailableNO3Solute = soilInZone.FindInScope <ISolute>("PlantAvailableNO3"); if (PlantAvailableNO3Solute != null) { NO3Solute = PlantAvailableNO3Solute; } var PlantAvailableNH4Solute = soilInZone.FindInScope <ISolute>("PlantAvailableNH4"); if (PlantAvailableNH4Solute != null) { NH4Solute = PlantAvailableNH4Solute; } }
/// <summary>Constructor, initialise tissues for the roots.</summary> /// <param name="zone">The zone the roots belong in.</param> /// <param name="initialDM">Initial dry matter weight</param> /// <param name="initialDepth">Initial root depth</param> /// <param name="minLiveDM">The minimum biomass for this organ</param> public void Initialise(Zone zone, double initialDM, double initialDepth, double minLiveDM) { soil = zone.FindInScope <Soil>(); if (soil == null) { throw new Exception($"Cannot find soil in zone {zone.Name}"); } soilPhysical = soil.FindInScope <IPhysical>(); if (soilPhysical == null) { throw new Exception($"Cannot find soil physical in soil {soil.Name}"); } waterBalance = soil.FindInScope <ISoilWater>(); if (waterBalance == null) { throw new Exception($"Cannot find a water balance model in soil {soil.Name}"); } soilCropData = soil.FindDescendant <SoilCrop>(species.Name + "Soil"); if (soilCropData == null) { throw new Exception($"Cannot find a soil crop parameterisation called {species.Name + "Soil"}"); } nutrient = zone.FindInScope <INutrient>(); if (nutrient == null) { throw new Exception($"Cannot find SoilNitrogen in zone {zone.Name}"); } no3 = zone.FindInScope("NO3") as ISolute; if (no3 == null) { throw new Exception($"Cannot find NO3 solute in zone {zone.Name}"); } nh4 = zone.FindInScope("NH4") as ISolute; if (nh4 == null) { throw new Exception($"Cannot find NH4 solute in zone {zone.Name}"); } // link to soil and initialise related variables zoneName = soil.Parent.Name; nLayers = soilPhysical.Thickness.Length; dulMM = soilPhysical.DULmm; ll15MM = soilPhysical.LL15mm; mySoilNH4Available = new double[nLayers]; mySoilNO3Available = new double[nLayers]; // save minimum DM and get target root distribution Depth = initialDepth; minimumLiveDM = minLiveDM; CalculateRootZoneBottomLayer(); TargetDistribution = RootDistributionTarget(); // initialise tissues double[] initialDMByLayer = MathUtilities.Multiply_Value(CurrentRootDistributionTarget(), initialDM); double[] initialNByLayer = MathUtilities.Multiply_Value(initialDMByLayer, NConcOptimum); Live = tissue[0]; Dead = tissue[1]; Live.Initialise(initialDMByLayer, initialNByLayer); Dead.Initialise(null, null); }