Esempio n. 1
0
 /// <summary>Setter for kgha delta.</summary>
 /// <param name="callingModelType">Type of calling model</param>
 /// <param name="delta">New delta values</param>
 public void AddKgHaDelta(SoluteSetterType callingModelType, double[] delta)
 {
     for (int i = 0; i < delta.Length; i++)
     {
         kgha[i] += delta[i];
     }
 }
Esempio n. 2
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);
                    }
                }
            }
        }
Esempio n. 3
0
 /// <summary>Setter for kgha.</summary>
 /// <param name="callingModelType">Type of calling model.</param>
 /// <param name="value">New values.</param>
 public void SetKgHa(SoluteSetterType callingModelType, double[] value)
 {
     for (int i = 0; i < value.Length; i++)
     {
         kgha[i] = value[i];
     }
 }
Esempio n. 4
0
        /// <summary>Setter for kgha delta.</summary>
        /// <param name="callingModelType">Type of calling model</param>
        /// <param name="delta">New delta values</param>
        public void AddKgHaDelta(SoluteSetterType callingModelType, double[] delta)
        {
            var values = kgha;

            for (int i = 0; i < delta.Length; i++)
            {
                kgha[i] += delta[i];
            }
            SetKgHa(callingModelType, values);
        }
Esempio n. 5
0
        /// <summary>
        /// Set the value of a solute by specifying a delta. Will throw if solute not found.
        /// </summary>
        /// <param name="name">Name of solute</param>
        /// <param name="callingModelType">Type of calling model</param>
        /// <param name="delta">Delta values to be added to solute</param>
        public void Add(string name, SoluteSetterType callingModelType, double[] delta)
        {
            Solute foundSolute = solutes.Find(solute => solute.Name.Equals(name, StringComparison.InvariantCultureIgnoreCase));

            if (foundSolute == null)
            {
                throw new Exception("Cannot find solute: " + name);
            }
            foundSolute.SetValue(callingModelType, MathUtilities.Add(foundSolute.GetValue(), delta));
        }
Esempio n. 6
0
 public void SetValue(SoluteSetterType callingModelType, double[] value)
 {
     if (setMethod == null)
     {
         property.SetValue(model, value);
     }
     else
     {
         setMethod.Invoke(model, new object[] { callingModelType, value });
     }
 }
Esempio n. 7
0
        /// <summary>
        /// Add a delta value to the top layer of a solute. Will throw if solute not found.
        /// </summary>
        /// <param name="name">Name of solute</param>
        /// <param name="callingModelType">Type of calling model</param>
        /// <param name="layerIndex">Layer index to add delta to</param>
        /// <param name="delta">Value to be added to top layer of solute</param>
        public void AddToLayer(int layerIndex, string name, SoluteSetterType callingModelType, double delta)
        {
            Solute foundSolute = solutes.Find(solute => solute.Name.Equals(name, StringComparison.InvariantCultureIgnoreCase));

            if (foundSolute == null)
            {
                throw new Exception("Cannot find solute: " + name);
            }

            double[] values = foundSolute.GetValue();
            values[layerIndex] += delta;
            foundSolute.SetValue(callingModelType, values);
        }
Esempio n. 8
0
 /// <summary>Setter for kgha delta.</summary>
 /// <param name="callingModelType">Type of calling model</param>
 /// <param name="delta">New delta values</param>
 public void AddKgHaDelta(SoluteSetterType callingModelType, double[] delta)
 {
     parent.SetNO3Delta(callingModelType, delta);
 }
Esempio n. 9
0
 /// <summary>Setter for kgha.</summary>
 /// <param name="callingModelType">Type of calling model.</param>
 /// <param name="value">New values.</param>
 public void SetKgHa(SoluteSetterType callingModelType, double[] value)
 {
     parent.SetNO3(callingModelType, value);
 }
Esempio n. 10
0
 public void AddKgHaDelta(SoluteSetterType callingModelType, double[] delta)
 {
     kgha = MathUtilities.Add(kgha, delta);
 }
Esempio n. 11
0
 public void SetKgHa(SoluteSetterType callingModelType, double[] value)
 {
     kgha = value;
 }
Esempio n. 12
0
 /// <summary>Set the value of a solute (kg/ha).</summary>
 /// <param name="callingModelType">Type of calling model.</param>
 /// <param name="name">The name of the solute.</param>
 /// <param name="value">The value to set the solute to.</param>
 /// <returns></returns>
 public void AddKgHa(SoluteSetterType callingModelType, string name, double[] value)
 {
     GetSoluteObject(name).AddKgHaDelta(callingModelType, value);
 }
Esempio n. 13
0
 /// <summary>Setter for kgha delta.</summary>
 /// <param name="callingModelType">Type of calling model</param>
 /// <param name="delta">New delta values</param>
 public void AddKgHaDelta(SoluteSetterType callingModelType, double[] delta)
 {
     throw new NotImplementedException("should not be trying to set plant available no3");
 }
Esempio n. 14
0
        /// <summary>
        /// calculate how the dlt's (C and N) are partitioned amongst patches
        /// </summary>
        /// <param name="callingModelType">Type of calling model.</param>
        /// <param name="incomingDelta">The dlt to be partioned amongst patches</param>
        /// <param name="soluteName">The solute or pool that is changing</param>
        /// <param name="partitionApproach">The type of partition to be used</param>
        /// <returns>The values of dlt partitioned for each existing patch</returns>
        private double[][] PartitionDelta(double[] incomingDelta, string soluteName, SoluteSetterType callingModelType, PartitionApproachEnum partitionApproach)
        {
            int numberLayers = incomingDelta.Length;

            // 1. initialise the result array
            double[][] Result = new double[patches.Count][];
            for (int k = 0; k < patches.Count; k++)
            {
                Result[k] = new double[numberLayers];
            }

            try
            {
                // 1.5 If the calling model is a plant and the solute is NO3 or NH4 then use the 'PlantAvailable' solutes instead.
                if (callingModelType == SoluteSetterType.Plant && (soluteName == "NO3" || soluteName == "NH4"))
                {
                    soluteName = "PlantAvailable" + soluteName;
                }

                // 2- gather how much solute is already in the soil
                double[][] existingSoluteAmount = new double[patches.Count][];
                for (int k = 0; k < patches.Count; k++)
                {
                    existingSoluteAmount[k] = patches[k].GetSoluteKgHa(soluteName);
                }

                // 3- calculate partition weighting factors, done for each layer based on existing solute amount
                double[] partitionWeight;
                double[] thisLayerPatchSolute;
                double   thisLayersTotalSolute;
                for (int layer = 0; layer < numberLayers; layer++)
                {
                    if (Math.Abs(incomingDelta[layer]) > epsilon)
                    {
                        // 3.1- zero and initialise the variables
                        partitionWeight      = new double[patches.Count];
                        thisLayerPatchSolute = new double[patches.Count];

                        // 3.2- get the solute amounts for each patch in this layer
                        if (partitionApproach == PartitionApproachEnum.BasedOnLayerConcentration ||
                            (partitionApproach == PartitionApproachEnum.BasedOnConcentrationAndDelta && incomingDelta[layer] < epsilon))
                        {
                            for (int k = 0; k < patches.Count; k++)
                            {
                                thisLayerPatchSolute[k] = existingSoluteAmount[k][layer] * patches[k].RelativeArea;
                            }
                        }
                        else if (partitionApproach == PartitionApproachEnum.BasedOnSoilConcentration ||
                                 (partitionApproach == PartitionApproachEnum.BasedOnConcentrationAndDelta && incomingDelta[layer] >= epsilon))
                        {
                            for (int k = 0; k < patches.Count; k++)
                            {
                                double layerUsed = 0.0;
                                for (int z = layer; z >= 0; z--)        // goes backwards till soil surface (but may stop before that)
                                {
                                    thisLayerPatchSolute[k] += existingSoluteAmount[k][z];
                                    layerUsed += soilPhysical.Thickness[z];
                                    if ((LayerForNPartition > epsilon) && (layerUsed >= LayerForNPartition))
                                    {
                                        // stop if thickness reaches a defined value
                                        z = -1;
                                    }
                                }
                                thisLayerPatchSolute[k] *= patches[k].RelativeArea;
                            }
                        }

                        // 3.3- get the total solute amount for this layer
                        thisLayersTotalSolute = MathUtilities.Sum(thisLayerPatchSolute);

                        // 3.4- Check whether the existing solute is greater than the incoming delta
                        if (MathUtilities.IsLessThan(thisLayersTotalSolute + incomingDelta[layer], 0))
                        {
                            throw new Exception($"Attempt to change {soluteName}[{layer + 1}] to a negative value");
                        }

                        // 3.5- Compute the partition weights for each patch
                        for (int k = 0; k < patches.Count; k++)
                        {
                            partitionWeight[k] = 0.0;
                            if (thisLayersTotalSolute >= epsilon)
                            {
                                partitionWeight[k] = MathUtilities.Divide(thisLayerPatchSolute[k], thisLayersTotalSolute, 0.0);
                            }
                        }

                        // 4- Compute the partitioned values for each patch
                        for (int k = 0; k < patches.Count; k++)
                        {
                            Result[k][layer] = (incomingDelta[layer] * partitionWeight[k]) / patches[k].RelativeArea;
                        }
                    }
                    else
                    {
                        // there is no incoming solute for this layer
                        for (int k = 0; k < patches.Count; k++)
                        {
                            Result[k][layer] = 0.0;
                        }
                    }
                }
            }
            catch (Exception e)
            {
                throw new Exception($"Problems with partitioning {soluteName} - {e}");
            }

            return(Result);
        }
 /// <summary>Setter for kgha.</summary>
 /// <param name="callingModelType">Type of calling model.</param>
 /// <param name="value">New values.</param>
 public void SetKgHa(SoluteSetterType callingModelType, double[] value)
 {
     parent.SetPlantAvailableNH4(callingModelType, value);
 }
Esempio n. 16
0
 /// <summary>Setter for kgha.</summary>
 /// <param name="callingModelType">Type of calling model.</param>
 /// <param name="value">New values.</param>
 public void SetKgHa(SoluteSetterType callingModelType, double[] value)
 {
     patchManager.SetSoluteKgha(callingModelType, Name, value);
 }