/// <summary> /// Calculate and return a predicted LL from the specified A and B values. /// </summary> /// <param name="soil">The soil.</param> /// <param name="A">a.</param> /// <param name="B">The b.</param> /// <returns></returns> private static double[] PredictedLL(Soil soil, double[] A, double B) { double[] LL15 = LayerStructure.LL15Mapped(soil, PredictedThickness); double[] DUL = LayerStructure.DULMapped(soil, PredictedThickness); double[] LL = new double[PredictedThickness.Length]; for (int i = 0; i != PredictedThickness.Length; i++) { double DULPercent = DUL[i] * 100.0; LL[i] = DULPercent * (A[i] + B * DULPercent); LL[i] /= 100.0; // Bound the predicted LL values. LL[i] = Math.Max(LL[i], LL15[i]); LL[i] = Math.Min(LL[i], DUL[i]); } // make the top 3 layers the same as the top 3 layers of LL15 if (LL.Length >= 3) { LL[0] = LL15[0]; LL[1] = LL15[1]; LL[2] = LL15[2]; } return(LL); }
/// <summary>Creates an apsim ready soil.</summary> /// <param name="soil">The soil.</param> /// <returns>A newly created soil ready to be run in APSIM.</returns> public static Soil Create(Soil soil) { Unit.Convert(soil); RemoveInitialWater(soil); LayerStructure.Standardise(soil); Defaults.FillInMissingValues(soil); RemoveSamples(soil); return(soil); }
/// <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> /// Return a predicted SoilCrop for the specified crop name or null if not found. /// </summary> /// <param name="soil">The soil.</param> /// <param name="CropName">Name of the crop.</param> /// <returns></returns> private static SoilCrop PredictedCrop(Soil soil, string CropName) { double[] A = null; double B = double.NaN; double[] KL = null; if (soil.SoilType == null) { return(null); } if (soil.SoilType.Equals("Black Vertosol", StringComparison.CurrentCultureIgnoreCase)) { if (CropName.Equals("Cotton", StringComparison.CurrentCultureIgnoreCase)) { A = BlackVertosol.CottonA; B = BlackVertosol.CottonB; KL = CottonKL; } else if (CropName.Equals("Sorghum", StringComparison.CurrentCultureIgnoreCase)) { A = BlackVertosol.SorghumA; B = BlackVertosol.SorghumB; KL = SorghumKL; } else if (CropName.Equals("Wheat", StringComparison.CurrentCultureIgnoreCase)) { A = BlackVertosol.WheatA; B = BlackVertosol.WheatB; KL = WheatKL; } } else if (soil.SoilType.Equals("Grey Vertosol", StringComparison.CurrentCultureIgnoreCase)) { if (CropName.Equals("Cotton", StringComparison.CurrentCultureIgnoreCase)) { A = GreyVertosol.CottonA; B = GreyVertosol.CottonB; KL = CottonKL; } else if (CropName.Equals("Sorghum", StringComparison.CurrentCultureIgnoreCase)) { A = GreyVertosol.SorghumA; B = GreyVertosol.SorghumB; KL = SorghumKL; } else if (CropName.Equals("Wheat", StringComparison.CurrentCultureIgnoreCase)) { A = GreyVertosol.WheatA; B = GreyVertosol.WheatB; KL = WheatKL; } else if (CropName.Equals("Barley", StringComparison.CurrentCultureIgnoreCase)) { A = GreyVertosol.BarleyA; B = GreyVertosol.BarleyB; KL = BarleyKL; } else if (CropName.Equals("Chickpea", StringComparison.CurrentCultureIgnoreCase)) { A = GreyVertosol.ChickpeaA; B = GreyVertosol.ChickpeaB; KL = ChickpeaKL; } else if (CropName.Equals("Fababean", StringComparison.CurrentCultureIgnoreCase)) { A = GreyVertosol.FababeanA; B = GreyVertosol.FababeanB; KL = FababeanKL; } else if (CropName.Equals("Mungbean", StringComparison.CurrentCultureIgnoreCase)) { A = GreyVertosol.MungbeanA; B = GreyVertosol.MungbeanB; KL = MungbeanKL; } } if (A == null) { return(null); } double[] LL = PredictedLL(soil, A, B); LL = LayerStructure.MapConcentration(LL, PredictedThickness, soil.Water.Thickness, LL.Last()); KL = LayerStructure.MapConcentration(KL, PredictedThickness, soil.Water.Thickness, KL.Last()); double[] XF = LayerStructure.MapConcentration(PredictedXF, PredictedThickness, soil.Water.Thickness, PredictedXF.Last()); string[] Metadata = StringUtilities.CreateStringArray("Estimated", soil.Water.Thickness.Length); return(new SoilCrop() { Name = CropName, Thickness = soil.Water.Thickness, LL = LL, LLMetadata = Metadata, KL = KL, KLMetadata = Metadata, XF = XF, XFMetadata = Metadata }); }
/// <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; } } }
/// <summary>Convert soil units to APSIM standard.</summary> /// <param name="soil">The soil.</param> public static void Convert(Soil soil) { // Convert soil organic matter OC to total % if (soil.SoilOrganicMatter != null) { soil.SoilOrganicMatter.OC = OCTotalPercent(soil.SoilOrganicMatter.OC, soil.SoilOrganicMatter.OCUnits); soil.SoilOrganicMatter.OCUnits = SoilOrganicMatter.OCUnitsEnum.Total; } // Convert nitrogen to ppm. if (soil.Nitrogen != null) { double[] bd = LayerStructure.BDMapped(soil, soil.Nitrogen.Thickness); soil.Nitrogen.NO3 = Nppm(soil.Nitrogen.NO3, soil.Nitrogen.Thickness, soil.Nitrogen.NO3Units, bd); soil.Nitrogen.NO3Units = Nitrogen.NUnitsEnum.ppm; soil.Nitrogen.NH4 = Nppm(soil.Nitrogen.NH4, soil.Nitrogen.Thickness, soil.Nitrogen.NH4Units, bd); soil.Nitrogen.NH4Units = Nitrogen.NUnitsEnum.ppm; } // Convert analysis. if (soil.Analysis != null) { soil.Analysis.PH = PHWater(soil.Analysis.PH, soil.Analysis.PHUnits); soil.Analysis.PHUnits = Analysis.PHUnitsEnum.Water; } // Convert all samples. if (soil.Samples != null) { foreach (Sample sample in soil.Samples) { // Convert sw units to volumetric. if (sample.SW != null) { sample.SW = SWVolumetric(sample, soil); } sample.SWUnits = Sample.SWUnitsEnum.Volumetric; // Convert no3 units to ppm. if (sample.NO3 != null) { double[] bd = LayerStructure.BDMapped(soil, sample.Thickness); sample.NO3 = Nppm(sample.NO3, sample.Thickness, sample.NO3Units, bd); } sample.NO3Units = Nitrogen.NUnitsEnum.ppm; // Convert nh4 units to ppm. if (sample.NH4 != null) { double[] bd = LayerStructure.BDMapped(soil, sample.Thickness); sample.NH4 = Nppm(sample.NH4, sample.Thickness, sample.NH4Units, bd); } sample.NH4Units = Nitrogen.NUnitsEnum.ppm; // Convert OC to total (%) if (sample.OC != null) { sample.OC = OCTotalPercent(sample.OC, sample.OCUnits); } sample.OCUnits = SoilOrganicMatter.OCUnitsEnum.Total; // Convert PH to water. if (sample.PH != null) { sample.PH = PHWater(sample.PH, sample.PHUnits); } sample.PHUnits = Analysis.PHUnitsEnum.Water; } } }