/// <summary>Computes the allocation of new growth to roots for each layer.</summary> /// <remarks> /// The current target distribution for roots changes whenever then root depth changes, this is then used to allocate /// new growth to each layer within the root zone. The existing distribution is used on any DM removal, so it may /// take some time for the actual distribution to evolve to be equal to the target. /// </remarks> /// <param name="dGrowthRootDM">Root growth dry matter (kg/ha).</param> /// <param name="dGrowthRootN">Root growth nitrogen (kg/ha).</param> public void DoRootGrowthAllocation(double dGrowthRootDM, double dGrowthRootN) { if (MathUtilities.IsGreaterThan(dGrowthRootDM, 0)) { // root DM is changing due to growth, check potential changes in distribution double[] growthRootFraction; double[] currentRootTarget = CurrentRootDistributionTarget(); if (MathUtilities.AreEqual(Live.FractionWt, currentRootTarget)) { // no need to change the distribution growthRootFraction = Live.FractionWt; } else { // root distribution should change, get preliminary distribution (average of current and target) growthRootFraction = new double[nLayers]; for (int layer = 0; layer <= BottomLayer; layer++) { growthRootFraction[layer] = 0.5 * (Live.FractionWt[layer] + currentRootTarget[layer]); } // normalise distribution of allocation double layersTotal = growthRootFraction.Sum(); for (int layer = 0; layer <= BottomLayer; layer++) { growthRootFraction[layer] = growthRootFraction[layer] / layersTotal; } } Live.SetBiomassTransferIn(dm: MathUtilities.Multiply_Value(growthRootFraction, dGrowthRootDM), n: MathUtilities.Multiply_Value(growthRootFraction, dGrowthRootN)); } // TODO: currently only the roots at the main / home zone are considered, must add the other zones too }
/// <summary>Sets the soil organic matter thickness.</summary> /// <param name="soilOrganicMatter">The soil organic matter.</param> /// <param name="thickness">Thickness to change soil water to.</param> private static void SetSoilOrganicMatterThickness(SoilOrganicMatter soilOrganicMatter, double[] thickness) { if (soilOrganicMatter != null) { if (!MathUtilities.AreEqual(thickness, soilOrganicMatter.Thickness)) { soilOrganicMatter.FBiom = MapConcentration(soilOrganicMatter.FBiom, soilOrganicMatter.Thickness, thickness, MathUtilities.LastValue(soilOrganicMatter.FBiom)); soilOrganicMatter.FInert = MapConcentration(soilOrganicMatter.FInert, soilOrganicMatter.Thickness, thickness, MathUtilities.LastValue(soilOrganicMatter.FInert)); soilOrganicMatter.OC = MapConcentration(soilOrganicMatter.OC, soilOrganicMatter.Thickness, thickness, MathUtilities.LastValue(soilOrganicMatter.OC)); soilOrganicMatter.Thickness = thickness; soilOrganicMatter.OCMetadata = StringUtilities.CreateStringArray("Mapped", thickness.Length);; } if (soilOrganicMatter.FBiom != null) { MathUtilities.ReplaceMissingValues(soilOrganicMatter.FBiom, MathUtilities.LastValue(soilOrganicMatter.FBiom)); } if (soilOrganicMatter.FInert != null) { MathUtilities.ReplaceMissingValues(soilOrganicMatter.FInert, MathUtilities.LastValue(soilOrganicMatter.FInert)); } if (soilOrganicMatter.OC != null) { MathUtilities.ReplaceMissingValues(soilOrganicMatter.OC, MathUtilities.LastValue(soilOrganicMatter.OC)); } } }
public void TestLayerStructure() { Soil soil = Setup(); // convert sw from gravimetric to volumetric. APSIMReadySoil.Create(soil); // Make sure the samples have been removed. Assert.AreEqual(soil.Samples.Count, 0); // Check the SW values have been converted and that the bottom two layers are at CLL (0.402) MathUtilities.AreEqual(soil.Water.SW, new double[] { 0.140, 0.289, 0.314, 0.326, 0.402, 0.402 }); // Check the NO3 values haven't been converted and that the bottom layers have default values MathUtilities.AreEqual(soil.Nitrogen.NO3, new double[] { 23, 7, 2, 1, 0.01, 0.01 }); // Check that the OC sample values have been put on top of the SoilOrganicMatter OC values. MathUtilities.AreEqual(soil.SoilOrganicMatter.OC, new double[] { 1.35, 1, 0.5, 0.4, 0.3, 0.2 }); // Make sure the analysis missing value has been replaced with zero. MathUtilities.AreEqual(soil.Analysis.CL, new double[] { 38, 0.0, 500, 490, 500, 500 }); // Make sure that no predicted crops have been added. string[] cropNames = soil.Water.Crops.Select(c => c.Name).ToArray(); Assert.AreEqual(cropNames.Length, 1); }
/// <summary>Convert the SWIM component to the specified thicknesses.</summary> /// <param name="swim">The swim component.</param> /// <param name="thickness">The thickness to convert to.</param> private static void SetSWIM(Swim swim, double[] thickness) { if (swim != null && swim.SwimSoluteParameters != null && !MathUtilities.AreEqual(thickness, swim.SwimSoluteParameters.Thickness)) { swim.SwimSoluteParameters.NO3Exco = MapConcentration(swim.SwimSoluteParameters.NO3Exco, swim.SwimSoluteParameters.Thickness, thickness, MathUtilities.LastValue(swim.SwimSoluteParameters.NO3Exco)); swim.SwimSoluteParameters.NO3FIP = MapConcentration(swim.SwimSoluteParameters.NO3FIP, swim.SwimSoluteParameters.Thickness, thickness, 0.0); // Making these use the LastValue causes C:/Apsim/Tests/UserRuns/WinteringSystems/BaseSimulation.sum to fail swim.SwimSoluteParameters.NH4Exco = MapConcentration(swim.SwimSoluteParameters.NH4Exco, swim.SwimSoluteParameters.Thickness, thickness, 0.0); swim.SwimSoluteParameters.NH4FIP = MapConcentration(swim.SwimSoluteParameters.NH4FIP, swim.SwimSoluteParameters.Thickness, thickness, 0.0); swim.SwimSoluteParameters.UreaExco = MapConcentration(swim.SwimSoluteParameters.UreaExco, swim.SwimSoluteParameters.Thickness, thickness, MathUtilities.LastValue(swim.SwimSoluteParameters.UreaExco)); swim.SwimSoluteParameters.UreaFIP = MapConcentration(swim.SwimSoluteParameters.UreaFIP, swim.SwimSoluteParameters.Thickness, thickness, 0.0); swim.SwimSoluteParameters.ClExco = MapConcentration(swim.SwimSoluteParameters.ClExco, swim.SwimSoluteParameters.Thickness, thickness, MathUtilities.LastValue(swim.SwimSoluteParameters.ClExco)); swim.SwimSoluteParameters.ClFIP = MapConcentration(swim.SwimSoluteParameters.ClFIP, swim.SwimSoluteParameters.Thickness, thickness, MathUtilities.LastValue(swim.SwimSoluteParameters.ClFIP)); swim.SwimSoluteParameters.TracerExco = MapConcentration(swim.SwimSoluteParameters.TracerExco, swim.SwimSoluteParameters.Thickness, thickness, MathUtilities.LastValue(swim.SwimSoluteParameters.TracerExco)); swim.SwimSoluteParameters.TracerFIP = MapConcentration(swim.SwimSoluteParameters.TracerFIP, swim.SwimSoluteParameters.Thickness, thickness, MathUtilities.LastValue(swim.SwimSoluteParameters.TracerFIP)); swim.SwimSoluteParameters.MineralisationInhibitorExco = MapConcentration(swim.SwimSoluteParameters.MineralisationInhibitorExco, swim.SwimSoluteParameters.Thickness, thickness, MathUtilities.LastValue(swim.SwimSoluteParameters.MineralisationInhibitorExco)); swim.SwimSoluteParameters.MineralisationInhibitorFIP = MapConcentration(swim.SwimSoluteParameters.MineralisationInhibitorFIP, swim.SwimSoluteParameters.Thickness, thickness, MathUtilities.LastValue(swim.SwimSoluteParameters.MineralisationInhibitorFIP)); swim.SwimSoluteParameters.UreaseInhibitorExco = MapConcentration(swim.SwimSoluteParameters.UreaseInhibitorExco, swim.SwimSoluteParameters.Thickness, thickness, MathUtilities.LastValue(swim.SwimSoluteParameters.UreaseInhibitorExco)); swim.SwimSoluteParameters.UreaseInhibitorFIP = MapConcentration(swim.SwimSoluteParameters.UreaseInhibitorFIP, swim.SwimSoluteParameters.Thickness, thickness, MathUtilities.LastValue(swim.SwimSoluteParameters.UreaseInhibitorFIP)); swim.SwimSoluteParameters.NitrificationInhibitorExco = MapConcentration(swim.SwimSoluteParameters.NitrificationInhibitorExco, swim.SwimSoluteParameters.Thickness, thickness, MathUtilities.LastValue(swim.SwimSoluteParameters.NitrificationInhibitorExco)); swim.SwimSoluteParameters.NitrificationInhibitorFIP = MapConcentration(swim.SwimSoluteParameters.NitrificationInhibitorFIP, swim.SwimSoluteParameters.Thickness, thickness, MathUtilities.LastValue(swim.SwimSoluteParameters.NitrificationInhibitorFIP)); swim.SwimSoluteParameters.DenitrificationInhibitorExco = MapConcentration(swim.SwimSoluteParameters.DenitrificationInhibitorExco, swim.SwimSoluteParameters.Thickness, thickness, MathUtilities.LastValue(swim.SwimSoluteParameters.DenitrificationInhibitorExco)); swim.SwimSoluteParameters.DenitrificationInhibitorFIP = MapConcentration(swim.SwimSoluteParameters.DenitrificationInhibitorFIP, swim.SwimSoluteParameters.Thickness, thickness, MathUtilities.LastValue(swim.SwimSoluteParameters.DenitrificationInhibitorFIP)); swim.SwimSoluteParameters.Thickness = thickness; } }
public void TestUnsaturatedFlow() { SoilModel soil = new SoilModel(); APSIM.Shared.Soils.Soil soilProperties = Setup(); APSIMReadySoil.Create(soilProperties); UnsaturatedFlowModel unsaturatedFlow = new UnsaturatedFlowModel(); SetLink(soil, "properties", soilProperties); SetLink(unsaturatedFlow, "soil", soil); unsaturatedFlow.DiffusConst = 88; unsaturatedFlow.DiffusSlope = 35.4; // Profile at DUL. soil.Water = MathUtilities.Multiply(soilProperties.Water.DUL, soilProperties.Water.Thickness); double[] flow = unsaturatedFlow.Values; Assert.IsTrue(MathUtilities.AreEqual(flow, new double[] { 0, 0, 0, 0, 0, 0 })); // Profile at SAT. soil.Water = MathUtilities.Multiply(soilProperties.Water.SAT, soilProperties.Water.Thickness); flow = unsaturatedFlow.Values; Assert.IsTrue(MathUtilities.AreEqual(flow, new double[] { 0, 0, 0, 0, 0, 0 })); // Force some unsaturated flow by reducing the water to 0.8 of SAT. soil.Water = MathUtilities.Multiply_Value(soil.Water, 0.8); flow = unsaturatedFlow.Values; Assert.IsTrue(MathUtilities.AreEqual(flow, new double[] { 0.52148, -0.38359, -0.16771, -0.07481, 0, 0 })); }
public void TestInitialWater() { Soil soil = Setup(); soil.Samples[0].SW = null; soil.InitialWater = new InitialWater(); soil.InitialWater.PercentMethod = InitialWater.PercentMethodEnum.FilledFromTop; soil.InitialWater.RelativeTo = "LL15"; soil.InitialWater.FractionFull = 0.5; APSIMReadySoil.Create(soil); // Make sure the initial water has been removed. Assert.IsNull(soil.InitialWater); // Check the SW values. MathUtilities.AreEqual(soil.Water.SW, new double[] { 0.365, 0.461, 0.43, 0.281, 0.261, 0.261 }); // check evenly distributed method. soil.InitialWater = new InitialWater(); soil.InitialWater.PercentMethod = InitialWater.PercentMethodEnum.EvenlyDistributed; soil.InitialWater.RelativeTo = "LL15"; soil.InitialWater.FractionFull = 0.5; APSIMReadySoil.Create(soil); MathUtilities.AreEqual(soil.Water.SW, new double[] { 0.318, 0.364, 0.345, 0.336, 0.332, 0.333 }); }
public void TestLateralFlow() { APSIM.Shared.Soils.Soil soilProperties = Setup(); soilProperties.Samples.Clear(); // Setup our objects with links. SoilModel soil = new SoilModel(); LateralFlowModel lateralFlow = new LateralFlowModel(); SetLink(soil, "properties", soilProperties); SetLink(soil, "lateralFlowModel", lateralFlow); SetLink(lateralFlow, "soil", soil); // Set initial water to full. soilProperties.InitialWater = new InitialWater(); soilProperties.InitialWater.FractionFull = 1.0; APSIMReadySoil.Create(soilProperties); soil.Water = MathUtilities.Multiply(soilProperties.Water.SW, soilProperties.Water.Thickness); // No inflow, so there should be no outflow. lateralFlow.InFlow = null; Assert.AreEqual(lateralFlow.Values.Length, 0); // Profile is full so adding in flow will produce out flow. lateralFlow.InFlow = new double[] { 9, 9, 9, 9, 9, 9 }; lateralFlow.KLAT = MathUtilities.CreateArrayOfValues(8.0, soilProperties.Water.Thickness.Length); Assert.IsTrue(MathUtilities.AreEqual(lateralFlow.Values, new double[] { 0.45999, 0.80498, 0.80498, 0.80498, 0.80498, 0.80498 })); // Set initial water to empty. Out flow should be zeros. soilProperties.InitialWater = new InitialWater(); soilProperties.InitialWater.FractionFull = 0.0; APSIMReadySoil.Create(soilProperties); soil.Water = MathUtilities.Multiply(soilProperties.Water.SW, soilProperties.Water.Thickness); Assert.IsTrue(MathUtilities.AreEqual(lateralFlow.Values, new double[] { 0, 0, 0, 0, 0, 0 })); }
/// <summary>Sets the soil organic matter thickness.</summary> /// <param name="soilOrganicMatter">The soil organic matter.</param> /// <param name="thickness">Thickness to change soil water to.</param> private static void SetSoilOrganicMatterThickness(Organic soilOrganicMatter, double[] thickness) { if (soilOrganicMatter != null) { if (!MathUtilities.AreEqual(thickness, soilOrganicMatter.Thickness)) { soilOrganicMatter.FBiom = MapConcentration(soilOrganicMatter.FBiom, soilOrganicMatter.Thickness, thickness, MathUtilities.LastValue(soilOrganicMatter.FBiom)); soilOrganicMatter.FInert = MapConcentration(soilOrganicMatter.FInert, soilOrganicMatter.Thickness, thickness, MathUtilities.LastValue(soilOrganicMatter.FInert)); soilOrganicMatter.Carbon = MapConcentration(soilOrganicMatter.Carbon, soilOrganicMatter.Thickness, thickness, MathUtilities.LastValue(soilOrganicMatter.Carbon)); soilOrganicMatter.SoilCNRatio = MapConcentration(soilOrganicMatter.SoilCNRatio, soilOrganicMatter.Thickness, thickness, MathUtilities.LastValue(soilOrganicMatter.SoilCNRatio)); soilOrganicMatter.FOM = MapMass(soilOrganicMatter.FOM, soilOrganicMatter.Thickness, thickness, false); soilOrganicMatter.Thickness = thickness; } if (soilOrganicMatter.FBiom != null) { MathUtilities.ReplaceMissingValues(soilOrganicMatter.FBiom, MathUtilities.LastValue(soilOrganicMatter.FBiom)); } if (soilOrganicMatter.FInert != null) { MathUtilities.ReplaceMissingValues(soilOrganicMatter.FInert, MathUtilities.LastValue(soilOrganicMatter.FInert)); } if (soilOrganicMatter.Carbon != null) { MathUtilities.ReplaceMissingValues(soilOrganicMatter.Carbon, MathUtilities.LastValue(soilOrganicMatter.Carbon)); } } }
/// <summary> /// Called by solutes to set the value of a solute. /// </summary> /// <param name="callingModelType">Type of calling model.</param> /// <param name="name">The name of the solute to get.</param> /// <param name="value">The value of the solute.</param> /// <returns></returns> internal void SetSoluteKgha(SoluteSetterType callingModelType, string name, double[] value) { // Determine if value is different from the current value of the solute. var currentValues = GetSoluteKgha(name); bool hasChanges = currentValues == null || !MathUtilities.AreEqual(currentValues, value); // check partitioning and pass the appropriate values to patches if (hasChanges) { bool requiresPartitioning = patches.Count > 1 && (callingModelType == SoluteSetterType.Soil || callingModelType == SoluteSetterType.Plant); if (requiresPartitioning) { // the values require partitioning var deltaN = MathUtilities.Subtract(value, currentValues); double[][] newDelta = PartitionDelta(deltaN, name, callingModelType, NPartitionApproach); for (int i = 0; i < patches.Count; i++) { patches[i].AddKgHa(SoluteSetterType.Other, name, newDelta[i]); } } else { // the values do not require partitioning - perform solute set. foreach (var patch in patches) { patch.SetSoluteKgHa(SoluteSetterType.Other, name, value); } } } }
/// <summary>Sets the water thickness.</summary> /// <param name="water">The water.</param> /// <param name="toThickness">To thickness.</param> /// <param name="soil">Soil</param> private static void SetWaterThickness(Water water, double[] toThickness, Soil soil) { if (!MathUtilities.AreEqual(toThickness, water.Thickness)) { water.BD = MapConcentration(water.BD, water.Thickness, toThickness, MathUtilities.LastValue(water.BD)); water.SW = MapSW(water.SW, water.Thickness, toThickness, soil); water.AirDry = MapConcentration(water.AirDry, water.Thickness, toThickness, MathUtilities.LastValue(water.AirDry)); water.LL15 = MapConcentration(water.LL15, water.Thickness, toThickness, MathUtilities.LastValue(water.LL15)); water.DUL = MapConcentration(water.DUL, water.Thickness, toThickness, MathUtilities.LastValue(water.DUL)); water.SAT = MapConcentration(water.SAT, water.Thickness, toThickness, MathUtilities.LastValue(water.SAT)); water.KS = MapConcentration(water.KS, water.Thickness, toThickness, MathUtilities.LastValue(water.KS)); water.Thickness = toThickness; } if (water.Crops != null) { foreach (SoilCrop crop in water.Crops) { if (!MathUtilities.AreEqual(toThickness, crop.Thickness)) { crop.LL = MapConcentration(crop.LL, crop.Thickness, toThickness, MathUtilities.LastValue(crop.LL)); crop.KL = MapConcentration(crop.KL, crop.Thickness, toThickness, MathUtilities.LastValue(crop.KL)); crop.XF = MapConcentration(crop.XF, crop.Thickness, toThickness, MathUtilities.LastValue(crop.XF)); crop.Thickness = toThickness; // Ensure crop LL are between Airdry and DUL. for (int i = 0; i < crop.LL.Length; i++) { crop.LL = MathUtilities.Constrain(crop.LL, soil.Water.AirDry, soil.Water.DUL); } } } } }
/// <summary>Convert the soil temperature component to the specified thicknesses.</summary> /// <param name="soilTemperature">The soil temperature.</param> /// <param name="thickness">The thickness to convert to.</param> private static void SetSoilTemperature(SoilTemperature soilTemperature, double[] thickness) { if (soilTemperature != null && !MathUtilities.AreEqual(thickness, soilTemperature.Thickness)) { soilTemperature.InitialSoilTemperature = MapConcentration(soilTemperature.InitialSoilTemperature, soilTemperature.Thickness, thickness, MathUtilities.LastValue(soilTemperature.InitialSoilTemperature)); soilTemperature.Thickness = thickness; } }
/// <summary>Sets the water thickness.</summary> /// <param name="water">The water.</param> /// <param name="toThickness">To thickness.</param> /// <param name="soil">Soil</param> private static void SetWaterThickness(Physical water, double[] toThickness, Soil soil) { if (!MathUtilities.AreEqual(toThickness, soil.Thickness)) { bool needToConstrainCropLL = false; if (soil.Crops != null) { foreach (var crop in soil.Crops) { crop.KL = MapConcentration(crop.KL, soil.Thickness, toThickness, MathUtilities.LastValue(crop.KL)); crop.XF = MapConcentration(crop.XF, soil.Thickness, toThickness, MathUtilities.LastValue(crop.XF)); if (crop is SoilCrop) { needToConstrainCropLL = true; var soilCrop = crop as SoilCrop; soilCrop.LL = MapConcentration(soilCrop.LL, soil.Thickness, toThickness, MathUtilities.LastValue(soilCrop.LL)); } } } soil.BD = MapConcentration(soil.BD, soil.Thickness, toThickness, MathUtilities.LastValue(soil.BD)); soil.AirDry = MapConcentration(soil.AirDry, soil.Thickness, toThickness, MathUtilities.LastValue(soil.AirDry)); soil.LL15 = MapConcentration(soil.LL15, soil.Thickness, toThickness, MathUtilities.LastValue(soil.LL15)); soil.DUL = MapConcentration(soil.DUL, soil.Thickness, toThickness, MathUtilities.LastValue(soil.DUL)); soil.SAT = MapConcentration(soil.SAT, soil.Thickness, toThickness, MathUtilities.LastValue(soil.SAT)); soil.KS = MapConcentration(soil.KS, soil.Thickness, toThickness, MathUtilities.LastValue(soil.KS)); if (water != null) { if (water.ParticleSizeClay != null && water.ParticleSizeClay.Length == water.Thickness.Length) { water.ParticleSizeClay = MapConcentration(water.ParticleSizeClay, water.Thickness, toThickness, MathUtilities.LastValue(water.ParticleSizeClay)); } else { water.ParticleSizeClay = null; } } soil.Thickness = toThickness; if (needToConstrainCropLL) { foreach (var crop in soil.Crops) { if (crop is SoilCrop) { var soilCrop = crop as SoilCrop; // Ensure crop LL are between Airdry and DUL. for (int i = 0; i < soilCrop.LL.Length; i++) { soilCrop.LL = MathUtilities.Constrain(soilCrop.LL, water.AirDry, water.DUL); } } } } } }
public void CheckUserLayerStructure() { APSIM.Shared.Soils.Soil soil = Setup(); soil.LayerStructure = new LayerStructure(); soil.LayerStructure.Thickness = new double[] { 200, 200, 200, 200 }; APSIMReadySoil.Create(soil); MathUtilities.AreEqual(soil.Water.Thickness, new double[] { 200, 200, 200, 200 }); }
public void AreEqual_AgainstSelf() { double test_double = 0.999; Assert.True(MathUtilities.AreEqual(test_double, test_double)); float test_float = 0.999f; Assert.True(MathUtilities.AreEqual(test_float, test_float)); }
/// <summary>Convert the phosphorus component to the specified thicknesses.</summary> /// <param name="phosphorus">The phosphorus.</param> /// <param name="thickness">The thickness to convert to.</param> private static void SetPhosphorus(Phosphorus phosphorus, double[] thickness) { if (phosphorus != null && !MathUtilities.AreEqual(thickness, phosphorus.Thickness)) { phosphorus.BandedP = MapConcentration(phosphorus.BandedP, phosphorus.Thickness, thickness, MathUtilities.LastValue(phosphorus.BandedP)); phosphorus.LabileP = MapConcentration(phosphorus.LabileP, phosphorus.Thickness, thickness, MathUtilities.LastValue(phosphorus.LabileP)); phosphorus.RockP = MapConcentration(phosphorus.RockP, phosphorus.Thickness, thickness, MathUtilities.LastValue(phosphorus.RockP)); phosphorus.Sorption = MapConcentration(phosphorus.Sorption, phosphorus.Thickness, thickness, MathUtilities.LastValue(phosphorus.Sorption)); phosphorus.Thickness = thickness; } }
/// <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="physical">The soil the crop belongs to.</param> private static void SetCropThickness(SoilCrop crop, double[] thickness, IPhysical physical) { if (!MathUtilities.AreEqual(thickness, physical.Thickness)) { crop.LL = MapConcentration(crop.LL, physical.Thickness, thickness, MathUtilities.LastValue(crop.LL)); crop.KL = MapConcentration(crop.KL, physical.Thickness, thickness, MathUtilities.LastValue(crop.KL)); crop.XF = MapConcentration(crop.XF, physical.Thickness, thickness, MathUtilities.LastValue(crop.XF)); crop.LL = MathUtilities.Constrain(crop.LL, AirDryMapped(physical, thickness), DULMapped(physical, thickness)); } }
public void AreEqual_AgainstLargerValue() { double test_double_a = 0.12345; double test_double_b = 2.98765; Assert.False(MathUtilities.AreEqual(test_double_a, test_double_b)); float test_float_a = 0.12345f; float test_float_b = 2.98765f; Assert.False(MathUtilities.AreEqual(test_float_a, test_float_b)); }
public void AreEqual_AgainstSameValue() { double test_double_a = 1.0001; double test_double_b = 1.0001; Assert.True(MathUtilities.AreEqual(test_double_a, test_double_b)); float test_float_a = 1.0001f; float test_float_b = 1.0001f; Assert.True(MathUtilities.AreEqual(test_float_a, test_float_b)); }
public void AreEqual_AgainstCopy() { double test_double_a = 9.999; double test_double_b = test_double_a; Assert.True(MathUtilities.AreEqual(test_double_a, test_double_b)); float test_float_a = 9.999f; float test_float_b = test_float_a; Assert.True(MathUtilities.AreEqual(test_float_a, test_float_b)); }
public void AreEqual_AgainstSmallerValue() { double test_double_a = 3.1415; double test_double_b = 0.1415; Assert.False(MathUtilities.AreEqual(test_double_a, test_double_b)); float test_float_a = 3.1415f; float test_float_b = 0.1415f; Assert.False(MathUtilities.AreEqual(test_float_a, test_float_b)); }
/// <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)) { 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.2); } if (sample.NO3 != null) { sample.NO3 = MapConcentration(sample.NO3, sample.Thickness, thickness, 1.0); } // 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); } if (sample.LabileP != null) { sample.LabileP = MapConcentration(sample.LabileP, sample.Thickness, thickness, double.NaN, allowMissingValues: true); } if (sample.UnavailableP != null) { sample.UnavailableP = MapConcentration(sample.UnavailableP, sample.Thickness, thickness, double.NaN, allowMissingValues: true); } sample.Thickness = thickness; } }
/// <summary>Sets the water thickness.</summary> /// <param name="physical">The water.</param> /// <param name="toThickness">To thickness.</param> /// <param name="soil">Soil</param> private static void SetPhysicalPropertiesThickness(IPhysical physical, double[] toThickness, Soil soil) { if (!MathUtilities.AreEqual(toThickness, physical.Thickness)) { var crops = (physical as IModel).FindAllChildren <SoilCrop>(); foreach (var crop in crops) { crop.KL = MapConcentration(crop.KL, physical.Thickness, toThickness, MathUtilities.LastValue(crop.KL)); crop.XF = MapConcentration(crop.XF, physical.Thickness, toThickness, MathUtilities.LastValue(crop.XF)); crop.LL = MapConcentration(crop.LL, physical.Thickness, toThickness, MathUtilities.LastValue(crop.LL)); } physical.BD = MapConcentration(physical.BD, physical.Thickness, toThickness, MathUtilities.LastValue(physical.BD)); physical.AirDry = MapConcentration(physical.AirDry, physical.Thickness, toThickness, MathUtilities.LastValue(physical.AirDry)); physical.LL15 = MapConcentration(physical.LL15, physical.Thickness, toThickness, MathUtilities.LastValue(physical.LL15)); physical.DUL = MapConcentration(physical.DUL, physical.Thickness, toThickness, MathUtilities.LastValue(physical.DUL)); physical.SAT = MapConcentration(physical.SAT, physical.Thickness, toThickness, MathUtilities.LastValue(physical.SAT)); physical.KS = MapConcentration(physical.KS, physical.Thickness, toThickness, MathUtilities.LastValue(physical.KS)); if (physical != null) { if (physical.ParticleSizeClay != null && physical.ParticleSizeClay.Length > 0 && physical.ParticleSizeClay.Length != toThickness.Length) { physical.ParticleSizeClay = MapConcentration(physical.ParticleSizeClay, physical.Thickness, toThickness, MathUtilities.LastValue(physical.ParticleSizeClay)); } if (physical.ParticleSizeSand != null && physical.ParticleSizeSand.Length > 0 && physical.ParticleSizeSand.Length != toThickness.Length) { physical.ParticleSizeSand = MapConcentration(physical.ParticleSizeSand, physical.Thickness, toThickness, MathUtilities.LastValue(physical.ParticleSizeSand)); } if (physical.ParticleSizeSilt != null && physical.ParticleSizeSilt.Length > 0 && physical.ParticleSizeSilt.Length != toThickness.Length) { physical.ParticleSizeSilt = MapConcentration(physical.ParticleSizeSilt, physical.Thickness, toThickness, MathUtilities.LastValue(physical.ParticleSizeSilt)); } if (physical.Rocks != null && physical.Rocks.Length > 0 && physical.Rocks.Length != toThickness.Length) { physical.Rocks = MapConcentration(physical.Rocks, physical.Thickness, toThickness, MathUtilities.LastValue(physical.Rocks)); } } physical.Thickness = toThickness; foreach (var crop in crops) { var soilCrop = crop as SoilCrop; // Ensure crop LL are between Airdry and DUL. for (int i = 0; i < soilCrop.LL.Length; i++) { soilCrop.LL = MathUtilities.Constrain(soilCrop.LL, physical.AirDry, physical.DUL); } } } }
/// <summary>Sets the soil water thickness.</summary> /// <param name="soilWater">The soil water.</param> /// <param name="thickness">Thickness to change soil water to.</param> private static void SetSoilWaterThickness(SoilWater soilWater, double[] thickness) { if (soilWater != null) { if (!MathUtilities.AreEqual(thickness, soilWater.Thickness)) { soilWater.KLAT = MapConcentration(soilWater.KLAT, soilWater.Thickness, thickness, MathUtilities.LastValue(soilWater.KLAT)); soilWater.SWCON = MapConcentration(soilWater.SWCON, soilWater.Thickness, thickness, 0.0); soilWater.Thickness = thickness; } MathUtilities.ReplaceMissingValues(soilWater.SWCON, 0.0); } }
/// <summary>Sets the analysis thickness.</summary> /// <param name="analysis">The analysis.</param> /// <param name="thickness">The thickness to change the analysis to.</param> private static void SetAnalysisThickness(Chemical analysis, double[] thickness) { if (analysis != null && !MathUtilities.AreEqual(thickness, analysis.Thickness)) { string[] metadata = StringUtilities.CreateStringArray("Mapped", thickness.Length); analysis.NO3N = MapConcentration(analysis.NO3N, analysis.Thickness, thickness, 1.0); analysis.NH4N = MapConcentration(analysis.NH4N, analysis.Thickness, thickness, 0.2); analysis.CL = MapConcentration(analysis.CL, analysis.Thickness, thickness, MathUtilities.LastValue(analysis.CL)); analysis.EC = MapConcentration(analysis.EC, analysis.Thickness, thickness, MathUtilities.LastValue(analysis.EC)); analysis.ESP = MapConcentration(analysis.ESP, analysis.Thickness, thickness, MathUtilities.LastValue(analysis.ESP)); analysis.PH = MapConcentration(analysis.PH, analysis.Thickness, thickness, MathUtilities.LastValue(analysis.PH)); analysis.Thickness = thickness; } }
/// <summary>Sets the sample thickness.</summary> /// <param name="swim">The swim model.</param> /// <param name="thickness">The thickness to change the sample to.</param> /// <param name="soil">The soil</param> private static void SetSWIMThickness(Swim3 swim, double[] thickness, Soil soil) { foreach (var soluteParameters in soil.FindAllChildren <SwimSoluteParameters>()) { if (!MathUtilities.AreEqual(thickness, soluteParameters.Thickness)) { if (soluteParameters.Exco != null) { soluteParameters.Exco = MapConcentration(soluteParameters.Exco, soluteParameters.Thickness, thickness, 0.2); } if (soluteParameters.FIP != null) { soluteParameters.FIP = MapConcentration(soluteParameters.FIP, soluteParameters.Thickness, thickness, 0.2); } } } }
/// <summary>Sets the analysis thickness.</summary> /// <param name="analysis">The analysis.</param> /// <param name="thickness">The thickness to change the analysis to.</param> private static void SetAnalysisThickness(Analysis analysis, double[] thickness) { if (analysis != null && !MathUtilities.AreEqual(thickness, analysis.Thickness)) { string[] metadata = StringUtilities.CreateStringArray("Mapped", thickness.Length); analysis.CL = MapConcentration(analysis.CL, analysis.Thickness, thickness, MathUtilities.LastValue(analysis.CL)); analysis.CLMetadata = metadata; analysis.EC = MapConcentration(analysis.EC, analysis.Thickness, thickness, MathUtilities.LastValue(analysis.EC)); analysis.ECMetadata = metadata; analysis.ESP = MapConcentration(analysis.ESP, analysis.Thickness, thickness, MathUtilities.LastValue(analysis.ESP)); analysis.ESPMetadata = metadata; if (analysis.ParticleSizeClay != null && analysis.ParticleSizeClay.Length == analysis.Thickness.Length) { analysis.ParticleSizeClay = MapConcentration(analysis.ParticleSizeClay, analysis.Thickness, thickness, MathUtilities.LastValue(analysis.ParticleSizeClay)); analysis.ParticleSizeClayMetadata = metadata; } else { analysis.ParticleSizeClay = null; } if (analysis.ParticleSizeSand != null && analysis.ParticleSizeSand.Length == analysis.Thickness.Length) { analysis.ParticleSizeSand = MapConcentration(analysis.ParticleSizeSand, analysis.Thickness, thickness, MathUtilities.LastValue(analysis.ParticleSizeSand)); analysis.ParticleSizeSandMetadata = metadata; } else { analysis.ParticleSizeSand = null; } if (analysis.ParticleSizeSilt != null && analysis.ParticleSizeSilt.Length == analysis.Thickness.Length) { analysis.ParticleSizeSilt = MapConcentration(analysis.ParticleSizeSilt, analysis.Thickness, thickness, MathUtilities.LastValue(analysis.ParticleSizeSilt)); analysis.ParticleSizeSiltMetadata = metadata; } else { analysis.ParticleSizeSilt = null; } analysis.PH = MapConcentration(analysis.PH, analysis.Thickness, thickness, MathUtilities.LastValue(analysis.PH)); analysis.PHMetadata = metadata; analysis.Thickness = thickness; } }
/// <summary>Sets the water thickness.</summary> /// <param name="water">The water.</param> /// <param name="toThickness">To thickness.</param> /// <param name="soil">Soil</param> private static void SetWaterThickness(Water water, double[] toThickness, Soil soil) { if (!MathUtilities.AreEqual(toThickness, soil.Thickness)) { bool needToConstrainCropLL = false; foreach (var cropName in soil.CropNames) { var crop = soil.Crop(cropName); crop.KL = MapConcentration(crop.KL, soil.Thickness, toThickness, MathUtilities.LastValue(crop.KL)); crop.XF = MapConcentration(crop.XF, soil.Thickness, toThickness, MathUtilities.LastValue(crop.XF)); if (crop is SoilCrop) { needToConstrainCropLL = true; var soilCrop = crop as SoilCrop; soilCrop.LL = MapConcentration(soilCrop.LL, soil.Thickness, toThickness, MathUtilities.LastValue(soilCrop.LL)); } } soil.BD = MapConcentration(soil.BD, soil.Thickness, toThickness, MathUtilities.LastValue(soil.BD)); soil.AirDry = MapConcentration(soil.AirDry, soil.Thickness, toThickness, MathUtilities.LastValue(soil.AirDry)); soil.LL15 = MapConcentration(soil.LL15, soil.Thickness, toThickness, MathUtilities.LastValue(soil.LL15)); soil.DUL = MapConcentration(soil.DUL, soil.Thickness, toThickness, MathUtilities.LastValue(soil.DUL)); soil.SAT = MapConcentration(soil.SAT, soil.Thickness, toThickness, MathUtilities.LastValue(soil.SAT)); soil.KS = MapConcentration(soil.KS, soil.Thickness, toThickness, MathUtilities.LastValue(soil.KS)); soil.Thickness = toThickness; if (needToConstrainCropLL) { foreach (ISoilCrop crop in water.Crops) { if (crop is SoilCrop) { var soilCrop = crop as SoilCrop; // Ensure crop LL are between Airdry and DUL. for (int i = 0; i < soilCrop.LL.Length; i++) { soilCrop.LL = MathUtilities.Constrain(soilCrop.LL, water.AirDry, water.DUL); } } } } } }
/// <summary>Sets the soil water thickness.</summary> /// <param name="soilWater">The soil water.</param> /// <param name="thickness">Thickness to change soil water to.</param> private static void SetSoilWaterThickness(WaterModel.WaterBalance soilWater, double[] thickness) { if (soilWater != null) { if (!MathUtilities.AreEqual(thickness, soilWater.Thickness)) { soilWater.KLAT = MapConcentration(soilWater.KLAT, soilWater.Thickness, thickness, MathUtilities.LastValue(soilWater.KLAT)); soilWater.SWCON = MapConcentration(soilWater.SWCON, soilWater.Thickness, thickness, 0.0); soilWater.Thickness = thickness; } if (soilWater.SWCON == null) { soilWater.SWCON = MathUtilities.CreateArrayOfValues(0.3, soilWater.Thickness.Length); } MathUtilities.ReplaceMissingValues(soilWater.SWCON, 0.0); } }
/// <summary>Sets the analysis thickness.</summary> /// <param name="analysis">The analysis.</param> /// <param name="thickness">The thickness to change the analysis to.</param> private static void SetAnalysisThickness(Analysis analysis, double[] thickness) { if (analysis != null && !MathUtilities.AreEqual(thickness, analysis.Thickness)) { string[] metadata = StringUtilities.CreateStringArray("Mapped", thickness.Length); analysis.Al = MapConcentration(analysis.Al, analysis.Thickness, thickness, MathUtilities.LastValue(analysis.Al)); analysis.AlMetadata = metadata; analysis.Ca = MapConcentration(analysis.Ca, analysis.Thickness, thickness, MathUtilities.LastValue(analysis.Ca)); analysis.CaMetadata = metadata; analysis.CEC = MapConcentration(analysis.CEC, analysis.Thickness, thickness, MathUtilities.LastValue(analysis.CEC)); analysis.CECMetadata = metadata; analysis.CL = MapConcentration(analysis.CL, analysis.Thickness, thickness, MathUtilities.LastValue(analysis.CL)); analysis.CLMetadata = metadata; analysis.EC = MapConcentration(analysis.EC, analysis.Thickness, thickness, MathUtilities.LastValue(analysis.EC)); analysis.ECMetadata = metadata; analysis.ESP = MapConcentration(analysis.ESP, analysis.Thickness, thickness, MathUtilities.LastValue(analysis.ESP)); analysis.ESPMetadata = metadata; analysis.K = MapConcentration(analysis.K, analysis.Thickness, thickness, MathUtilities.LastValue(analysis.K)); analysis.KMetadata = metadata; analysis.Mg = MapConcentration(analysis.Mg, analysis.Thickness, thickness, MathUtilities.LastValue(analysis.Mg)); analysis.MgMetadata = metadata; analysis.Mn = MapConcentration(analysis.Mn, analysis.Thickness, thickness, MathUtilities.LastValue(analysis.Mn)); analysis.MnMetadata = metadata; analysis.MunsellColour = null; analysis.Na = MapConcentration(analysis.Na, analysis.Thickness, thickness, MathUtilities.LastValue(analysis.Na)); analysis.NaMetadata = metadata; analysis.ParticleSizeClay = MapConcentration(analysis.ParticleSizeClay, analysis.Thickness, thickness, MathUtilities.LastValue(analysis.ParticleSizeClay)); analysis.ParticleSizeClayMetadata = metadata; analysis.ParticleSizeSand = MapConcentration(analysis.ParticleSizeSand, analysis.Thickness, thickness, MathUtilities.LastValue(analysis.ParticleSizeSand)); analysis.ParticleSizeSandMetadata = metadata; analysis.ParticleSizeSilt = MapConcentration(analysis.ParticleSizeSilt, analysis.Thickness, thickness, MathUtilities.LastValue(analysis.ParticleSizeSilt)); analysis.ParticleSizeSiltMetadata = metadata; analysis.PH = MapConcentration(analysis.PH, analysis.Thickness, thickness, MathUtilities.LastValue(analysis.PH)); analysis.PHMetadata = metadata; analysis.Rocks = MapConcentration(analysis.Rocks, analysis.Thickness, thickness, MathUtilities.LastValue(analysis.Rocks)); analysis.RocksMetadata = metadata; analysis.Texture = null; analysis.Thickness = thickness; } }
public void TestSaturatedFlow() { SoilModel soil = new SoilModel(); APSIM.Shared.Soils.Soil soilProperties = Setup(); APSIMReadySoil.Create(soilProperties); SaturatedFlowModel saturatedFlow = new SaturatedFlowModel(); SetLink(soil, "properties", soilProperties); SetLink(saturatedFlow, "soil", soil); saturatedFlow.SWCON = new double[] { 0.3, 0.3, 0.3, 0.3, 0.3, 0.3 }; // Profile at DUL. soil.Water = MathUtilities.Multiply(soilProperties.Water.DUL, soilProperties.Water.Thickness); double[] flux = saturatedFlow.Values; Assert.IsTrue(MathUtilities.AreEqual(flux, new double[] { 0, 0, 0, 0, 0, 0 })); // Profile at SAT. soil.Water = MathUtilities.Multiply(soilProperties.Water.SAT, soilProperties.Water.Thickness); flux = saturatedFlow.Values; Assert.IsTrue(MathUtilities.AreEqual(flux, new double[] { 1.05, 2.85, 4.64999, 6.45, 8.25, 10.05 })); // Use the KS method soilProperties.Water.KS = new double[] { 1000, 300, 20, 100, 100, 100 }; flux = saturatedFlow.Values; Assert.IsTrue(MathUtilities.AreEqual(flux, new double[] { 1.05, 1.8000, 1.8000, 1.8000, 1.8000, 1.8000 })); Assert.AreEqual(saturatedFlow.backedUpSurface, 0); // Use the KS method, water above SAT. soilProperties.Water.KS = new double[] { 1000, 300, 20, 100, 100, 100 }; MathUtilities.AddValue(soil.Water, 10); // add 5 mm of water into each layer. flux = saturatedFlow.Values; Assert.IsTrue(MathUtilities.AreEqual(flux, new double[] { 1.05, 1.8000, 1.8000, 1.8000, 1.8000, 1.8000 })); }