Пример #1
0
        /// <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
        }
Пример #2
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(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));
                }
            }
        }
Пример #3
0
        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);
        }
Пример #4
0
 /// <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;
     }
 }
Пример #5
0
        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 }));
        }
Пример #6
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 });
        }
Пример #7
0
        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 }));
        }
Пример #8
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));
                }
            }
        }
Пример #9
0
        /// <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);
                    }
                }
            }
        }
Пример #10
0
        /// <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);
                        }
                    }
                }
            }
        }
Пример #11
0
 /// <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;
     }
 }
Пример #12
0
        /// <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);
                            }
                        }
                    }
                }
            }
        }
Пример #13
0
        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 });
        }
Пример #14
0
    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));
    }
Пример #15
0
 /// <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;
     }
 }
Пример #16
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="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));
            }
        }
Пример #17
0
    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));
    }
Пример #18
0
    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));
    }
Пример #19
0
    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));
    }
Пример #20
0
    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));
    }
Пример #21
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))
            {
                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;
            }
        }
Пример #22
0
        /// <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);
                    }
                }
            }
        }
Пример #23
0
        /// <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);
            }
        }
Пример #24
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;
            }
        }
Пример #25
0
 /// <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);
             }
         }
     }
 }
Пример #26
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.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;
            }
        }
Пример #27
0
        /// <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);
                            }
                        }
                    }
                }
            }
        }
Пример #28
0
        /// <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);
            }
        }
Пример #29
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;
            }
        }
Пример #30
0
        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 }));
        }