Esempio n. 1
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;
        }
Esempio n. 2
0
        /// <summary>Sets the sample thickness.</summary>
        /// <param name="sample">The sample.</param>
        /// <param name="thickness">The thickness to change the sample to.</param>
        /// <param name="soil">The soil</param>
        private static void SetSampleThickness(Sample sample, double[] thickness, Soil soil)
        {
            if (!MathUtilities.AreEqual(thickness, sample.Thickness))
            {
                sample.Name = sample.Name;
                sample.Date = sample.Date;

                if (sample.SW != null)
                    sample.SW = MapSW(sample.SW, sample.Thickness, thickness, soil);
                if (sample.NH4 != null)
                    sample.NH4 = MapConcentration(sample.NH4, sample.Thickness, thickness, 0.01);
                if (sample.NO3 != null)
                    sample.NO3 = MapConcentration(sample.NO3, sample.Thickness, thickness, 0.01);

                // The elements below will be overlaid over other arrays of values so we want 
                // to have missing values (double.NaN) used at the bottom of the profile.
                
                if (sample.CL != null)
                    sample.CL = MapConcentration(sample.CL, sample.Thickness, thickness, double.NaN, allowMissingValues:true);
                if (sample.EC != null)
                    sample.EC = MapConcentration(sample.EC, sample.Thickness, thickness, double.NaN, allowMissingValues: true);
                if (sample.ESP != null)
                    sample.ESP = MapConcentration(sample.ESP, sample.Thickness, thickness, double.NaN, allowMissingValues: true);
                if (sample.OC != null)
                    sample.OC = MapConcentration(sample.OC, sample.Thickness, thickness, double.NaN, allowMissingValues: true);
                if (sample.PH != null)
                    sample.PH = MapConcentration(sample.PH, sample.Thickness, thickness, double.NaN, allowMissingValues: true);
                sample.Thickness = thickness;
            }
        }
        /// <summary>Converts the paddock XML.</summary>
        /// <param name="paddock">The paddock.</param>
        /// <exception cref="System.Exception">Bad paddock name:  + name</exception>
        private static Paddock CreateSimulationSpec(XmlNode paddock, string baseFolder)
        {
            Paddock simulation = new Paddock();

            string name = XmlUtilities.NameAttr(paddock);
            string delimiter = "^";
            int posCaret = name.IndexOf(delimiter);

            if (posCaret == -1)
                throw new Exception("Bad paddock name: " + name);

            string remainder = StringUtilities.SplitOffAfterDelimiter(ref name, delimiter);
            string growerName;
            string paddockName = StringUtilities.SplitOffAfterDelimiter(ref remainder, delimiter);
            if (paddockName == string.Empty)
            {
                growerName = name;
                paddockName = remainder;
            }
            else
                growerName = remainder;

            simulation.StartSeasonDate = GetDate(paddock, "StartSeasonDateFull");

            // Give the paddock a name.
            string fullName = string.Format("{0}^{1}^{2}", simulation.StartSeasonDate.Year, growerName, paddockName);
            simulation.Name = fullName;

            // Set the report date.
            simulation.NowDate = GetDate(paddock.ParentNode, "TodayDateFull");
            if (simulation.NowDate == DateTime.MinValue)
                simulation.NowDate = DateTime.Now;

            // Store any rainfall data in the simulation.
            simulation.RainfallSource = GetString(paddock, "RainfallSource");
            if (simulation.RainfallSource != "Weather station")
            {
                string rainFileName = GetString(paddock, "RainfallFilename");
                if (rainFileName != string.Empty)
                {
                    string fullFileName = Path.Combine(baseFolder, rainFileName);
                    if (!File.Exists(fullFileName))
                        throw new Exception("Cannot find file: " + fullFileName);
                    simulation.ObservedData = ApsimTextFile.ToTable(fullFileName);
                    if (simulation.ObservedData.Rows.Count == 0)
                        simulation.ObservedData = null;
                }
            }
            // Set the reset dates
            simulation.SoilWaterSampleDate = GetDate(paddock, "ResetDateFull");
            simulation.SoilNitrogenSampleDate = GetDate(paddock, "SoilNitrogenSampleDateFull");

            simulation.StationNumber = GetInteger(paddock, "StationNumber");
            simulation.StationName = GetString(paddock, "StationName");
            
            // Create a sowing management
            Sow sowing = new Sow();
            simulation.Management.Add(sowing);
            sowing.Date = GetDate(paddock, "SowDateFull");
            sowing.EmergenceDate = GetDate(paddock, "EmergenceDateFull");
            sowing.Crop = GetString(paddock, "Crop");           
            sowing.Cultivar = GetString(paddock, "Cultivar");
            sowing.SkipRow = GetString(paddock, "SkipRow");
            sowing.SowingDensity = GetInteger(paddock, "SowingDensity");
            sowing.MaxRootDepth = GetInteger(paddock, "MaxRootDepth") * 10;  // cm to mm
            sowing.BedWidth = GetInteger(paddock, "BedWidth");
            sowing.BedRowSpacing = GetDouble(paddock, "BedRowSpacing");

            // Make sure we have a stubbletype
            simulation.StubbleType = GetString(paddock, "StubbleType");
            if (simulation.StubbleType == string.Empty || simulation.StubbleType == "None")
                simulation.StubbleType = "Wheat";
            simulation.StubbleMass = GetDouble(paddock, "StubbleMass");
            simulation.Slope = GetDouble(paddock, "Slope");
            simulation.SlopeLength = GetDouble(paddock, "SlopeLength");
            simulation.UseEC = GetBoolean(paddock, "UseEC");

            // Fertilise nodes.
            List<XmlNode> fertiliserNodes = XmlUtilities.ChildNodes(paddock, "Fertilise");
            for (int f = 0; f < fertiliserNodes.Count; f++)
            {
                Fertilise fertilise = new Fertilise();
                simulation.Management.Add(fertilise);
                fertilise.Date = GetDate(fertiliserNodes[f], "FertDateFull");
                fertilise.Amount = GetDouble(fertiliserNodes[f], "FertAmount");
                fertilise.Scenario = GetBoolean(fertiliserNodes[f], "Scenario");
            }

            // Irrigate nodes.
            List<XmlNode> irrigateNodes = XmlUtilities.ChildNodes(paddock, "Irrigate");
            for (int i = 0; i < irrigateNodes.Count; i++)
            {
                Irrigate irrigate = new Irrigate();
                simulation.Management.Add(irrigate);
                irrigate.Date = GetDate(irrigateNodes[i], "IrrigateDateFull");
                irrigate.Amount = GetDouble(irrigateNodes[i], "IrrigateAmount");
                irrigate.Efficiency = GetDouble(irrigateNodes[i], "IrrigateEfficiency");
                irrigate.Scenario = GetBoolean(irrigateNodes[i], "Scenario");
            }

            // Tillage nodes.
            foreach (XmlNode tillageNode in XmlUtilities.ChildNodes(paddock, "Tillage"))
            {
                Tillage tillage = new Tillage();
                simulation.Management.Add(tillage);
                tillage.Date = GetDate(tillageNode, "TillageDateFull");
                string disturbance = GetString(tillageNode, "Disturbance");
                if (disturbance == "Low")
                    tillage.Disturbance = Tillage.DisturbanceEnum.Low;
                else if (disturbance == "Medium")
                    tillage.Disturbance = Tillage.DisturbanceEnum.Medium;
                else
                    tillage.Disturbance = Tillage.DisturbanceEnum.High;
                tillage.Scenario = GetBoolean(tillageNode, "Scenario");
            }

            // Stubble removed nodes.
            foreach (XmlNode stubbleRemovedNode in XmlUtilities.ChildNodes(paddock, "StubbleRemoved"))
            {
                StubbleRemoved stubbleRemoved = new StubbleRemoved();
                simulation.Management.Add(stubbleRemoved);

                stubbleRemoved.Date = GetDate(stubbleRemovedNode, "StubbleRemovedDateFull");
                stubbleRemoved.Percent = GetDouble(stubbleRemovedNode, "StubbleRemovedAmount");
            }

            // Look for a soil node.
            XmlNode soilNode = XmlUtilities.FindByType(paddock, "Soil");

            if (soilNode != null)
            {
                string testValue = XmlUtilities.Value(soilNode, "Water/Layer/Thickness");
                if (testValue != string.Empty)
                {
                    // old format.
                    soilNode = ConvertSoilNode.Upgrade(soilNode);
                }
            }

            // Fix up soil sample variables.
            Sample sample1 = new Sample();
            sample1.Name = "Sample1";
            sample1.Thickness = GetArray(paddock, "Sample1Thickness");
            sample1.SW = GetArray(paddock, "SW");
            if (sample1.SW == null)
            {
                // Really old way of doing samples - they are stored under soil.
                List<XmlNode> sampleNodes = XmlUtilities.ChildNodes(soilNode, "Sample");
                if (sampleNodes.Count > 0)
                    sample1 = XmlUtilities.Deserialise(sampleNodes[0], typeof(Sample)) as Sample;
            }
            else
            {
                sample1.NO3 = GetArray(paddock, "NO3");
                sample1.NH4 = GetArray(paddock, "NH4");
            }

            Sample sample2 = null;
            double[] sample2Thickness = GetArray(paddock, "Sample2Thickness");
            if (sample2Thickness == null)
            {
                // Really old way of doing samples - they are stored under soil.
                List<XmlNode> sampleNodes = XmlUtilities.ChildNodes(soilNode, "Sample");
                if (sampleNodes.Count > 1)
                    sample2 = XmlUtilities.Deserialise(sampleNodes[1], typeof(Sample)) as Sample;
            }
            else
            {
                sample2 = sample1;
                if (!MathUtilities.AreEqual(sample2Thickness, sample1.Thickness))
                {
                    sample2 = new Sample();
                    sample2.Name = "Sample2";
                }
                sample2.OC = GetArray(paddock, "OC");
                sample2.EC = GetArray(paddock, "EC");
                sample2.PH = GetArray(paddock, "PH");
                sample2.CL = GetArray(paddock, "CL");
                sample2.OCUnits = SoilOrganicMatter.OCUnitsEnum.WalkleyBlack;
                sample2.PHUnits = Analysis.PHUnitsEnum.CaCl2;
            }

            // Make sure we have NH4 values.
            if (sample1.NH4 == null && sample1.NO3 != null)
            {
                string[] defaultValues = StringUtilities.CreateStringArray("0.1", sample1.NO3.Length);
                sample1.NH4 = MathUtilities.StringsToDoubles(defaultValues);
            }

            RemoveNullFieldsFromSample(sample1);
            if (sample2 != null)
                RemoveNullFieldsFromSample(sample2);


            // Fix up <WaterFormat>
            string waterFormatString = GetString(paddock, "WaterFormat");
            if (waterFormatString.Contains("Gravimetric"))
                sample1.SWUnits = Sample.SWUnitsEnum.Gravimetric;
            else
                sample1.SWUnits = Sample.SWUnitsEnum.Volumetric;

            if (MathUtilities.ValuesInArray(sample1.Thickness))
                simulation.Samples.Add(sample1);

            if (sample2 != null && MathUtilities.ValuesInArray(sample2.Thickness) && sample2 != sample1)
                simulation.Samples.Add(sample2);

            // Check for InitTotalWater & InitTotalNitrogen
            simulation.InitTotalWater = GetDouble(paddock, "InitTotalWater");
            simulation.InitTotalNitrogen = GetDouble(paddock, "InitTotalNitrogen");

            // Check to see if we need to convert the soil structure.
            simulation.SoilPath = GetString(paddock, "SoilName");

            
            if (soilNode != null)
            {
                // See if there is a 'SWUnits' value. If found then copy it into 
                // <WaterFormat>
                string waterFormat = XmlUtilities.Value(paddock, "WaterFormat");
                if (waterFormat == string.Empty)
                {
                    int sampleNumber = 0;
                    foreach (XmlNode soilSample in XmlUtilities.ChildNodes(soilNode, "Sample"))
                    {
                        string swUnits = XmlUtilities.Value(soilSample, "SWUnits");
                        if (swUnits != string.Empty)
                            XmlUtilities.SetValue(paddock, "WaterFormat", swUnits);

                        // Also make sure we don't have 2 samples with the same name.
                        string sampleName = "Sample" + (sampleNumber + 1).ToString();
                        XmlUtilities.SetAttribute(soilSample, "name", sampleName);
                        sampleNumber++;
                    }
                }
                simulation.Soil = SoilUtilities.FromXML(soilNode.OuterXml);
                if (simulation.Samples != null)
                    simulation.Soil.Samples = simulation.Samples;
            }
            return simulation;
        }
 private static void RemoveNullFieldsFromSample(Sample sample)
 {
     if (sample.CL == null) sample.CL = new double[0];
     if (sample.EC == null) sample.EC = new double[0];
     if (sample.ESP == null) sample.ESP = new double[0];
     if (sample.NH4 == null) sample.NH4 = new double[0];
     if (sample.NO3 == null) sample.NO3 = new double[0];
     if (sample.OC == null) sample.OC = new double[0];
     if (sample.PH == null) sample.PH = new double[0];
     if (sample.SW == null) sample.SW = new double[0];
 }
Esempio n. 5
0
        /// <summary>Checks the sample for missing values.</summary>
        /// <param name="sample">The sample.</param>
        /// <param name="soil">The soil.</param>
        private static void CheckSampleForMissingValues(Sample sample, Soil soil)
        {
            if (!MathUtilities.ValuesInArray(sample.SW))
                sample.SW = null;
            if (!MathUtilities.ValuesInArray(sample.NO3))
                sample.NO3 = null;
            if (!MathUtilities.ValuesInArray(sample.CL))
                sample.CL = null;
            if (!MathUtilities.ValuesInArray(sample.EC))
                sample.EC = null;
            if (!MathUtilities.ValuesInArray(sample.ESP))
                sample.ESP = null;
            if (!MathUtilities.ValuesInArray(sample.PH))
                sample.PH = null;
            if (!MathUtilities.ValuesInArray(sample.OC))
                sample.OC = null;

            if (sample.SW != null)
                sample.SW = MathUtilities.FixArrayLength(sample.SW, sample.Thickness.Length);
            if (sample.NO3 != null)
                sample.NO3 = MathUtilities.FixArrayLength(sample.NO3, sample.Thickness.Length);
            if (sample.NH4 != null)
                sample.NH4 = MathUtilities.FixArrayLength(sample.NH4, sample.Thickness.Length);
            if (sample.CL != null)
                sample.CL = MathUtilities.FixArrayLength(sample.CL, sample.Thickness.Length);
            if (sample.EC != null)
                sample.EC = MathUtilities.FixArrayLength(sample.EC, sample.Thickness.Length);
            if (sample.ESP != null)
                sample.ESP = MathUtilities.FixArrayLength(sample.ESP, sample.Thickness.Length);
            if (sample.PH != null)
                sample.PH = MathUtilities.FixArrayLength(sample.PH, sample.Thickness.Length);
            if (sample.OC != null)
                sample.OC = MathUtilities.FixArrayLength(sample.OC, sample.Thickness.Length);

            double[] ll15 = LayerStructure.LL15Mapped(soil, sample.Thickness);
            for (int i = 0; i < sample.Thickness.Length; i++)
            {
                if (sample.SW != null && double.IsNaN(sample.SW[i]))
                    sample.SW[i] = ll15[i];
                if (sample.NO3 != null && double.IsNaN(sample.NO3[i]))
                    sample.NO3[i] = 1.0;
                if (sample.NH4 != null && double.IsNaN(sample.NH4[i]))
                    sample.NH4[i] = 0.1;
                if (sample.CL != null && double.IsNaN(sample.CL[i]))
                    sample.CL[i] = 0;
                if (sample.EC != null && double.IsNaN(sample.EC[i]))
                    sample.EC[i] = 0;
                if (sample.ESP != null && double.IsNaN(sample.ESP[i]))
                    sample.ESP[i] = 0;
                if (sample.PH != null && (double.IsNaN(sample.PH[i]) || sample.PH[i] == 0.0))
                    sample.PH[i] = 7.0;
                if (sample.OC != null && (double.IsNaN(sample.OC[i]) || sample.OC[i] == 0.0))
                    sample.OC[i] = 0.5;
            }
        }
Esempio n. 6
0
        /// <summary>Calculates volumetric soil water for the given sample.</summary>
        /// <param name="sample">The sample.</param>
        /// <param name="soil">The soil.</param>
        /// <returns>Volumetric water (mm/mm)</returns>
        private static double[] SWVolumetric(Sample sample, Soil soil)
        {
            if (sample.SWUnits == Sample.SWUnitsEnum.Volumetric || sample.SW == null)
                return sample.SW;
            else
            {
                // convert the numbers
                if (sample.SWUnits == Sample.SWUnitsEnum.Gravimetric)
                {
                    double[] bd = LayerStructure.BDMapped(soil, sample.Thickness);

                    return MathUtilities.Multiply(sample.SW, bd);
                }
                else
                    return MathUtilities.Divide(sample.SW, sample.Thickness); // from mm to mm/mm
            }
        }
        /// <summary>Checks the soil sample.</summary>
        /// <param name="parentSoil">The parent soil.</param>
        /// <param name="sample">The sample.</param>
        private static void CheckSample(Soil parentSoil, Sample sample)
        {

            // Do some checking of NO3 / NH4
            CheckMissingValuesAreNaN(sample.NO3);
            CheckMissingValuesAreNaN(sample.NH4);
            CheckMissingValuesAreNaN(sample.OC);
            CheckMissingValuesAreNaN(sample.EC);
            CheckMissingValuesAreNaN(sample.PH);

            if (sample.NO3 != null)
                sample.NO3 = FixArrayLength(sample.NO3, sample.Thickness.Length);
            if (sample.NH4 != null)
                sample.NH4 = FixArrayLength(sample.NH4, sample.Thickness.Length);

            // NH4 can be null so give default values if that is the case.
            for (int i = 0; i < sample.NH4.Length; i++)
                if (double.IsNaN(sample.NH4[i]))
                    sample.NH4[i] = 0.1;

            sample.OCUnits = SoilOrganicMatter.OCUnitsEnum.WalkleyBlack;
            if (sample.OC != null)
                sample.OC = FixArrayLength(sample.OC, sample.Thickness.Length);

            if (sample.EC != null)
                sample.EC = FixArrayLength(sample.EC, sample.Thickness.Length);

            if (sample.PH != null)
                sample.PH = FixArrayLength(sample.PH, sample.Thickness.Length);
        }