/// <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]; } }
/// <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>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]; } }
/// <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); }
/// <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)); }
public void SetValue(SoluteSetterType callingModelType, double[] value) { if (setMethod == null) { property.SetValue(model, value); } else { setMethod.Invoke(model, new object[] { callingModelType, value }); } }
/// <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); }
/// <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); }
/// <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); }
public void AddKgHaDelta(SoluteSetterType callingModelType, double[] delta) { kgha = MathUtilities.Add(kgha, delta); }
public void SetKgHa(SoluteSetterType callingModelType, double[] value) { kgha = value; }
/// <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); }
/// <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"); }
/// <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); }
/// <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); }