Example #1
0
        /// <summary>
        /// Returns soil water uptake from each zone by the static tree model
        /// </summary>
        /// <param name="soilstate"></param>
        /// <returns></returns>
        public List<Soils.Arbitrator.ZoneWaterAndN> GetSWUptakes(Soils.Arbitrator.SoilState soilstate)
        {
            double SWDemand = 0;  // Tree water demand (L)
            double PotSWSupply = 0; // Total water supply (L)

            foreach (ZoneInfo ZI in ZoneInfoList)
            {
                Soils.SoilWater S = Apsim.Find(ZI.zone, typeof(Soils.SoilWater)) as Soils.SoilWater;
                SWDemand += S.Eo * (1 / (1 - ZI.Shade / 100) - 1) * ZI.zone.Area * 10000;
            }

            List<ZoneWaterAndN> Uptakes = new List<ZoneWaterAndN>();

            foreach (ZoneWaterAndN Z in soilstate.Zones)
            {
                foreach (ZoneInfo ZI in ZoneInfoList)
                {
                    if (Z.Name == ZI.zone.Name)
                    {
                        ZoneWaterAndN Uptake = new ZoneWaterAndN();
                        //Find the soil for this zone
                        Zone ThisZone = new Zone();
                        Soils.Soil ThisSoil = new Soils.Soil();

                        foreach (Zone SearchZ in Apsim.ChildrenRecursively(Parent, typeof(Zone)))
                            if (SearchZ.Name == Z.Name)
                                ThisSoil = Apsim.Find(SearchZ, typeof(Soils.Soil)) as Soils.Soil;

                        Uptake.Name = Z.Name;
                        double[] SW = Z.Water;
                        Uptake.NO3N = new double[SW.Length];
                        Uptake.NH4N = new double[SW.Length];
                        Uptake.Water = new double[SW.Length];
                        for (int i = 0; i <= SW.Length - 1; i++)
                        {
                            double[] LL15mm = MathUtilities.Multiply(ThisSoil.LL15,ThisSoil.Thickness);
                            Uptake.Water[i] = (SW[i] - LL15mm[i]) * ZI.RLD[i];
                            PotSWSupply += Uptake.Water[i] * ZI.zone.Area * 10000;
                        }
                        Uptakes.Add(Uptake);
                    }
                }
            }
            // Now scale back uptakes if supply > demand
            double F = 0;  // Uptake scaling factor
            if (PotSWSupply > 0)
            {
                F = SWDemand / PotSWSupply;
                if (F > 1)
                    F = 1;
            }
            else
                F = 1;

            foreach (ZoneWaterAndN Z in Uptakes)
                Z.Water = MathUtilities.Multiply_Value(Z.Water, F);
            return Uptakes;
        }
Example #2
0
        /// <summary>
        /// Return the %Wind Reduction for a given zone
        /// </summary>
        /// <param name="z">Zone</param>
        /// <param name="Today">The current date</param>
        /// <returns>%Wind Reduction</returns>
        public double GetWindReduction(Zone z, DateTime Today)
        {
            foreach (ZoneInfo zi in ZoneInfoList)
                if (zi.zone == z)
                {
                    double UrelMin = Math.Max(0.0, 1.14 * 0.5 - 0.16); // 0.5 is porosity, will be dynamic in the future
                    double Urel;
                    double H;
                    bool didInterp;
                    double[] OADates = new double[dates.Count()];
                    double heightToday;

                    for (int i = 0; i < dates.Count(); i++)
                        OADates[i] = dates[i].ToOADate();

                    heightToday = MathUtilities.LinearInterpReal(Today.ToOADate(), OADates, heights, out didInterp);

                    if (heightToday < 1000)
                        Urel = 1;
                    else
                    {
                        H = GetDistanceFromTrees(z) / (heightToday / 1000);
                        if (H < 6)
                            Urel = UrelMin + (1 - UrelMin) / 2 - H / 6 * (1 - UrelMin) / 2;
                        else if (H < 6.1)
                            Urel = UrelMin;
                        else
                            Urel = UrelMin + (1 - UrelMin) / (1 + 0.000928 * Math.Exp(Math.Pow(12.9372 * (H - 6), -0.26953)));
                    }
                    return Urel;
                }
            throw new ApsimXException(this, "Could not find zone called " + z.Name);
        }
Example #3
0
        /// <summary>
        /// Returns soil Nitrogen uptake from each zone by the static tree model
        /// </summary>
        /// <param name="soilstate"></param>
        /// <returns></returns>
        public List<Soils.Arbitrator.ZoneWaterAndN> GetNUptakes(Soils.Arbitrator.SoilState soilstate)
        {
            List<ZoneWaterAndN> Uptakes = new List<ZoneWaterAndN>();

            foreach (ZoneWaterAndN Z in soilstate.Zones)
            {
                foreach (ZoneInfo ZI in ZoneInfoList)
                {
                    if (Z.Name == ZI.zone.Name)
                    {
                        ZoneWaterAndN Uptake = new ZoneWaterAndN();
                        //Find the soil for this zone
                        Zone ThisZone = new Zone();
                        Soils.Soil ThisSoil = new Soils.Soil();

                        foreach (Zone SearchZ in Apsim.ChildrenRecursively(Parent, typeof(Zone)))
                            if (SearchZ.Name == Z.Name)
                                ThisSoil = Apsim.Find(SearchZ, typeof(Soils.Soil)) as Soils.Soil;

                        Uptake.Name = Z.Name;
                        double[] SW = Z.Water;
                        Uptake.NO3N = new double[SW.Length];
                        Uptake.NH4N = new double[SW.Length];
                        Uptake.Water = new double[SW.Length];
                        //for (int i = 0; i <= SW.Length-1; i++)
                        //    Uptake.NO3N[i] = Z.NO3N[i] * ZI.RLD[i];

                        Uptakes.Add(Uptake);
                    }
                }
            }
            return Uptakes;
        }
Example #4
0
 /// <summary>
 /// Return the %Shade for a given zone
 /// </summary>
 /// <param name="z">Zone</param>
 /// <returns>%Shade</returns>
 public double GetShade(Zone z)
 {
     foreach (ZoneInfo zi in ZoneInfoList)
         if (zi.zone == z)
             return zi.Shade;
     throw new ApsimXException(this, "Could not find a shade value for zone called " + z.Name);
 }
Example #5
0
        /// <summary>
        /// Return the %Wind Reduction for a given zone
        /// </summary>
        /// <param name="z">Zone</param>
        /// <returns>%Wind Reduction</returns>
        public double GetWindReduction(Zone z)
        {
            foreach (Zone zone in ZoneList)
                if (zone == z)
                {
                    double UrelMin = Math.Max(0.0, 1.14 * 0.40 - 0.16); // 0.4 is porosity, will be dynamic in the future

                    if (tree.heightToday < 1)
                        Urel = 1;
                    else
                    {
                        tree.H = GetDistanceFromTrees(z) / tree.heightToday;
                        if (tree.H < 6)
                            Urel = UrelMin + (1 - UrelMin) / 2 - tree.H / 6 * (1 - UrelMin) / 2;
                        else if (tree.H < 6.1)
                            Urel = UrelMin;
                        else
                            Urel = UrelMin + (1 - UrelMin) / (1 + 0.000928 * Math.Exp(12.9372 * Math.Pow((tree.H - 6), -0.26953)));
                    }
                    return Urel;
                }
            throw new ApsimXException(this, "Could not find zone called " + z.Name);
        }
Example #6
0
        /// <summary>
        /// Return the distance from the tree for a given zone. The tree is assumed to be in the first Zone.
        /// </summary>
        /// <param name="z">Zone</param>
        /// <returns>Distance from a static tree</returns>
        public double GetDistanceFromTrees(Zone z)
        {
            double D = 0;
            foreach (ZoneInfo zi in ZoneInfoList)
            {
                if (zi.zone is RectangularZone)
                    D += (zi.zone as RectangularZone).Width;
                else if (zi.zone is CircularZone)
                    D += (zi.zone as CircularZone).Width;
                else
                    throw new ApsimXException(this, "Cannot calculate distance for trees for zone of given type.");
                if (zi.zone == z)
                    return D;
            }

            throw new ApsimXException(this, "Could not find zone called " + z.Name);
        }
Example #7
0
 /// <summary>
 /// Passthrough for child nodes that need information from the tree.
 /// Saves having to query the simulation for the node location all the time.
 /// </summary>
 /// <param name="z">The zone.</param>
 /// <returns></returns>
 public double GetDistanceFromTrees(Zone z)
 {
     return tree.GetDistanceFromTrees(z);
 }
Example #8
0
 /// <summary>
 /// Return the %Radiation Reduction for a given zone
 /// </summary>
 /// <param name="z">Zone</param>
 /// <returns>%Radiation Reduction</returns>
 public double GetRadiationReduction(Zone z)
 {
     if (GetDistanceFromTrees(z) > 0.0)
             return 1.0-tree.GetShade(z)/100.0;
     else
             return 1.0;
 }
Example #9
0
        /// <summary>
        /// 
        /// </summary>
        /// <param name="z"></param>
        /// <returns></returns>
        private double ZoneDistanceInTreeHeights(Zone z)
        {
            double treeHeight = GetHeightToday();
            double distFromTree = GetDistanceFromTrees(z);

            return distFromTree / treeHeight;
        }
Example #10
0
        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(Soils.SoilWater)) as Soils.SoilWater;

            TreeWaterUptake = new double[ZoneList.Count];
        }
Example #11
0
 /// <summary>
 /// Return the width of the given zone.
 /// </summary>
 /// <param name="z">The width.</param>
 /// <returns></returns>
 private double GetZoneWidth(Zone z)
 {
     double D = 0;
     if (z is RectangularZone)
         D = (z as RectangularZone).Width;
     else if (z is CircularZone)
         D = (z as CircularZone).Width;
     else
         throw new ApsimXException(this, "Cannot calculate distance for trees for zone of given type.");
     return D;
 }
Example #12
0
 /// <summary>
 /// Return the %Shade for a given zone
 /// </summary>
 /// <param name="z"></param>
 public double GetShade(Zone z)
 {
     double distInTH = ZoneDistanceInTreeHeights(z);
     bool didInterp = false;
     return MathUtilities.LinearInterpReal(distInTH, shade.Keys.ToArray(), shade.Values.ToArray(), out didInterp);
 }
Example #13
0
        /// <summary>
        /// 
        /// </summary>
        /// <param name="z"></param>
        /// <returns></returns>
        public double[] GetRLD(Zone z)
        {
            double distInTH = ZoneDistanceInTreeHeights(z);
            bool didInterp = false;
            DenseMatrix rldM = DenseMatrix.OfColumnArrays(rld.Values);
            double[] rldInterp = new double[rldM.RowCount];

            for (int i=0;i< rldM.RowCount;i++)
            {
                rldInterp[i] = MathUtilities.LinearInterpReal(distInTH, rld.Keys.ToArray(), rldM.Row(i).ToArray(), out didInterp);
            }

            return rldInterp;
        }