Beispiel #1
0
 /// <summary>Return the plant available water CAPACITY for the specified crop. Units: mm/mm</summary>
 /// <param name="soil">The soil to calculate PAWC for.</param>
 /// <param name="crop">The crop.</param>
 /// <returns></returns>
 public static double[] OfCrop(Soil soil, SoilCrop crop)
 {
     return(PAWC.PAWCInternal(soil.Water.Thickness,
                              crop.LL,
                              soil.Water.DUL,
                              crop.XF));
 }
Beispiel #2
0
        /// <summary>Convert the crop to the specified thickness. Ensures LL is between AirDry and DUL.</summary>
        /// <param name="crop">The crop to convert</param>
        /// <param name="thickness">The thicknesses to convert the crop to.</param>
        /// <param name="soil">The soil the crop belongs to.</param>
        private static void SetCropThickness(SoilCrop crop, double[] thickness, Soil soil)
        {
            if (!MathUtilities.AreEqual(thickness, crop.Thickness))
            {
                crop.LL        = MapConcentration(crop.LL, crop.Thickness, thickness, MathUtilities.LastValue(crop.LL));
                crop.KL        = MapConcentration(crop.KL, crop.Thickness, thickness, MathUtilities.LastValue(crop.KL));
                crop.XF        = MapConcentration(crop.XF, crop.Thickness, thickness, MathUtilities.LastValue(crop.XF));
                crop.Thickness = thickness;

                crop.LL = MathUtilities.Constrain(crop.LL, AirDryMapped(soil, thickness), DULMapped(soil, thickness));
            }
        }
Beispiel #3
0
 /// <summary>Checks the crop for missing values.</summary>
 /// <param name="crop">The crop.</param>
 /// <param name="soil">The soil.</param>
 private static void CheckCropForMissingValues(SoilCrop crop, Soil soil)
 {
     for (int i = 0; i < crop.Thickness.Length; i++)
     {
         if (crop.LL != null && double.IsNaN(crop.LL[i]))
         {
             crop.LL[i] = soil.Water.LL15[i];
         }
         if (crop.KL != null && double.IsNaN(crop.KL[i]))
         {
             crop.KL[i] = 0;
         }
         if (crop.XF != null && double.IsNaN(crop.XF[i]))
         {
             crop.XF[i] = 0;
         }
     }
 }
Beispiel #4
0
        /// <summary>Fills in KL for crop.</summary>
        /// <param name="crop">The crop.</param>
        private static void FillInKLForCrop(SoilCrop crop)
        {
            if (crop.Name == null)
                throw new Exception("Crop has no name");
            int i = StringUtilities.IndexOfCaseInsensitive(cropNames, crop.Name);
            if (i != -1)
            {
                double[] KLs = GetRowOfArray(defaultKLs, i);

                double[] cumThickness = SoilUtilities.ToCumThickness(crop.Thickness);
                crop.KL = new double[crop.Thickness.Length];
                for (int l = 0; l < crop.Thickness.Length; l++)
                {
                    bool didInterpolate;
                    crop.KL[l] = MathUtilities.LinearInterpReal(cumThickness[l], defaultKLThickness, KLs, out didInterpolate);
                }
            }
        }
Beispiel #5
0
        /// <summary>Calculate a layered soil water. Units: mm/mm</summary>
        public double[] SW(Soil soil)
        {
            string[] cropNames = soil.Water.Crops.Select(c => c.Name).ToArray();

            // Get the correct LL and XF
            int cropIndex = -1;

            if (RelativeTo != null)
            {
                cropIndex = StringUtilities.IndexOfCaseInsensitive(cropNames, RelativeTo);
            }
            double[] ll;
            double[] xf = null;
            double[] PAWCmm;
            if (cropIndex == -1)
            {
                ll     = soil.Water.LL15;
                PAWCmm = PAWC.OfSoilmm(soil);
            }
            else
            {
                SoilCrop crop = soil.Water.Crops[cropIndex];
                ll     = crop.LL;
                xf     = crop.XF;
                PAWCmm = PAWC.OfCropmm(soil, crop);
            }

            if (double.IsNaN(DepthWetSoil))
            {
                if (PercentMethod == InitialWater.PercentMethodEnum.FilledFromTop)
                {
                    return(SWFilledFromTop(PAWCmm, ll, soil.Water.DUL, xf));
                }
                else
                {
                    return(SWEvenlyDistributed(ll, soil.Water.DUL));
                }
            }
            else
            {
                return(SWDepthWetSoil(soil.Water.Thickness, ll, soil.Water.DUL));
            }
        }
Beispiel #6
0
        /// <summary>Test setup routine. Returns a soil properties that can be used for testing.</summary>
        public static APSIM.Shared.Soils.Soil Setup()
        {
            APSIM.Shared.Soils.Soil soil = new APSIM.Shared.Soils.Soil();
            soil.Water = new Water();
            soil.Water.Thickness = new double[] { 100, 300, 300, 300, 300, 300 };
            soil.Water.BD = new double[] { 1.36, 1.216, 1.24, 1.32, 1.372, 1.368 };
            soil.Water.AirDry = new double[] { 0.135, 0.214, 0.261, 0.261, 0.261, 0.261 };
            soil.Water.LL15 = new double[] { 0.27, 0.267, 0.261, 0.261, 0.261, 0.261 };
            soil.Water.DUL = new double[] { 0.365, 0.461, 0.43, 0.412, 0.402, 0.404 };
            soil.Water.SAT = new double[] { 0.400, 0.481, 0.45, 0.432, 0.422, 0.424 };

            // Add a wheat crop.
            SoilCrop crop = new SoilCrop();
            crop.Thickness = soil.Water.Thickness;
            crop.Name = "Wheat";
            crop.KL = new double[] { 0.06, 0.060, 0.060, 0.060, 0.060, 0.060 };
            crop.LL = new double[] { 0.27, 0.267, 0.261, 0.315, 0.402, 0.402 };
            soil.Water.Crops = new List<SoilCrop>();
            soil.Water.Crops.Add(crop);

            // Add OC values into SoilOrganicMatter.
            soil.SoilOrganicMatter = new SoilOrganicMatter();
            soil.SoilOrganicMatter.Thickness = soil.Water.Thickness;
            soil.SoilOrganicMatter.OC = new double[] { 2, 1, 0.5, 0.4, 0.3, 0.2 };

            // Add in CL into analysis.
            soil.Analysis = new Analysis();
            soil.Analysis.Thickness = soil.Water.Thickness;
            soil.Analysis.CL = new double[] { 38, double.NaN, 500, 490, 500, 500 };

            // Add a sample.
            Sample sample = new Sample();
            sample.Thickness = new double[] { 100, 300, 300, 300 };
            sample.SW = new double[] { 0.103, 0.238, 0.253, 0.247 };
            sample.NO3 = new double[] { 23, 7, 2, 1 };
            sample.OC = new double[] { 1.35, double.NaN, double.NaN, double.NaN };
            sample.SWUnits = Sample.SWUnitsEnum.Gravimetric;
            soil.Samples = new List<Sample>();
            soil.Samples.Add(sample);
            return soil;
        }
Beispiel #7
0
        /// <summary>Fills in KL for crop.</summary>
        /// <param name="crop">The crop.</param>
        private static void FillInKLForCrop(SoilCrop crop)
        {
            if (crop.Name == null)
            {
                throw new Exception("Crop has no name");
            }
            int i = StringUtilities.IndexOfCaseInsensitive(cropNames, crop.Name);

            if (i != -1)
            {
                double[] KLs = GetRowOfArray(defaultKLs, i);

                double[] cumThickness = SoilUtilities.ToCumThickness(crop.Thickness);
                crop.KL = new double[crop.Thickness.Length];
                for (int l = 0; l < crop.Thickness.Length; l++)
                {
                    bool didInterpolate;
                    crop.KL[l] = MathUtilities.LinearInterpReal(cumThickness[l], defaultKLThickness, KLs, out didInterpolate);
                }
            }
        }
Beispiel #8
0
 /// <summary>Crop lower limit - mapped to the specified layer structure. Units: mm/mm        /// </summary>
 /// <param name="crop">The crop.</param>
 /// <param name="ToThickness">To thickness.</param>
 /// <returns></returns>
 private static double[] LLMapped(SoilCrop crop, double[] ToThickness)
 {
     return(MapConcentration(crop.LL, crop.Thickness, ToThickness, MathUtilities.LastValue(crop.LL)));
 }
 /// <summary>Crop lower limit - mapped to the specified layer structure. Units: mm/mm        /// </summary>
 /// <param name="crop">The crop.</param>
 /// <param name="ToThickness">To thickness.</param>
 /// <returns></returns>
 private static double[] LLMapped(SoilCrop crop, double[] ToThickness)
 {
     return MapConcentration(crop.LL, crop.Thickness, ToThickness, MathUtilities.LastValue(crop.LL));
 }
Beispiel #10
0
 /// <summary>Convert the crop to the specified thickness. Ensures LL is between AirDry and DUL.</summary>
 /// <param name="crop">The crop to convert</param>
 /// <param name="thickness">The thicknesses to convert the crop to.</param>
 /// <param name="soil">The soil the crop belongs to.</param>
 private static void SetCropThickness(SoilCrop crop, double[] thickness, Soil soil)
 {
     if (!MathUtilities.AreEqual(thickness, crop.Thickness))
     {
         crop.LL = MapConcentration(crop.LL, crop.Thickness, thickness, MathUtilities.LastValue(crop.LL));
         crop.KL = MapConcentration(crop.KL, crop.Thickness, thickness, MathUtilities.LastValue(crop.KL));
         crop.XF = MapConcentration(crop.XF, crop.Thickness, thickness, MathUtilities.LastValue(crop.XF));
         crop.Thickness = thickness;
         
         crop.LL = MathUtilities.Constrain(crop.LL, AirDryMapped(soil, thickness), DULMapped(soil, thickness));
     }
 }
Beispiel #11
0
 /// <summary>Checks the crop for missing values.</summary>
 /// <param name="crop">The crop.</param>
 /// <param name="soil">The soil.</param>
 private static void CheckCropForMissingValues(SoilCrop crop, Soil soil)
 {
     for (int i = 0; i < crop.Thickness.Length; i++)
     {
         if (crop.LL != null && double.IsNaN(crop.LL[i]))
             crop.LL[i] = soil.Water.LL15[i];
         if (crop.KL != null && double.IsNaN(crop.KL[i]))
             crop.KL[i] = 0;
         if (crop.XF != null && double.IsNaN(crop.XF[i]))
             crop.XF[i] = 0;
     }
 }
Beispiel #12
0
    private static string ReplaceSoilMacros(XmlNode SoilNode, string ApsimToSimContents)
    {
        // Get rid of nodes under <soil> that are disabled.
        RemoveDisabledNodes(SoilNode);

        APSIM.Shared.Soils.Soil mySoil = APSIM.Shared.Soils.SoilUtilities.FromXML(SoilNode.OuterXml);
        mySoil = APSIM.Shared.Soils.APSIMReadySoil.Create(mySoil);
        if (mySoil.Name == null)
        {
            mySoil.Name = "Soil";
        }

        // Loop through all soil macros.
        int PosMacro = 0;

        PosMacro = ApsimToSimContents.IndexOf("[soil.", PosMacro);
        while (PosMacro != -1)
        {
            int PosEndMacro = ApsimToSimContents.IndexOf(']', PosMacro);
            if (PosEndMacro == -1)
            {
                throw new Exception("Invalid soil macro found: " + ApsimToSimContents.Substring(PosMacro));
            }

            // Get macro name e.g. soil.thickness
            string MacroName = ApsimToSimContents.Substring(PosMacro + 1, PosEndMacro - PosMacro - 1);

            //if (MacroName.Contains("soil."))
            {
                // remove the soil. prefix from the MacroName.
                MacroName = MacroName.Substring(MacroName.IndexOf('.') + 1);

                // Is it a crop macro i.e. wheat ll
                object Obj = null;
                if (MacroName.Contains(" "))
                {
                    string CropName     = MacroName.Substring(0, MacroName.IndexOf(' '));
                    string VariableName = MacroName.Substring(MacroName.IndexOf(' ') + 1);
                    APSIM.Shared.Soils.SoilCrop crop = mySoil.Water.Crops.Find(c => c.Name.Equals(CropName, StringComparison.InvariantCultureIgnoreCase));
                    if (crop == null)
                    {
                        throw new Exception("Cannot find soil water information for crop '" + CropName + "'. " +
                                            "You likely need to \"Manage Crops\" in the Water node of your soil, and set the water properties of this crop");
                    }
                    if (VariableName.Equals("ll", StringComparison.CurrentCultureIgnoreCase))
                    {
                        Obj = crop.LL;
                    }
                    else if (VariableName.Equals("kl", StringComparison.CurrentCultureIgnoreCase))
                    {
                        Obj = crop.KL;
                    }
                    else if (VariableName.Equals("xf", StringComparison.CurrentCultureIgnoreCase))
                    {
                        Obj = crop.XF;
                    }
                }
                else
                {
                    Obj = Utility.GetValueOfFieldOrProperty(MacroName, mySoil);
                }

                if (Obj != null)
                {
                    string MacroValue = "";
                    if (Obj is IList)
                    {
                        foreach (object I in Obj as IList)
                        {
                            if (I is double)
                            {
                                MacroValue += ((double)I).ToString("f3", CultureInfo.CreateSpecificCulture("en-AU")) + " ";
                            }
                            else
                            {
                                MacroValue += I.ToString() + " ";
                            }
                        }
                    }
                    else if (Obj is double)
                    {
                        if (double.IsNaN(Convert.ToDouble(Obj)))
                        {
                            MacroValue = "";
                        }
                        else
                        {
                            MacroValue = ((Double)Obj).ToString("f3", CultureInfo.CreateSpecificCulture("en-AU"));
                        }
                    }
                    else
                    {
                        MacroValue = Obj.ToString();
                    }

                    ApsimToSimContents = ApsimToSimContents.Remove(PosMacro, PosEndMacro - PosMacro + 1);
                    ApsimToSimContents = ApsimToSimContents.Insert(PosMacro, MacroValue);
                }
                PosMacro = ApsimToSimContents.IndexOf("[soil.", PosMacro + 1);
            }
        }

        return(ApsimToSimContents);
    }
Beispiel #13
0
 /// <summary>Return the plant available water CAPACITY for the specified crop. Units: mm</summary>
 /// <param name="soil">The soil to calculate PAWC for.</param>
 /// <param name="crop">The crop.</param>
 /// <returns></returns>
 public static double[] OfCropmm(Soil soil, SoilCrop crop)
 {
     double[] pawc = PAWC.OfCrop(soil, crop);
     return(MathUtilities.Multiply(pawc, soil.Water.Thickness));
 }