Skip to content

Commit

Permalink
Merge pull request #1655 from hut104/SoilNutrient
Browse files Browse the repository at this point in the history
Soil nutrient
  • Loading branch information
hol353 authored May 23, 2017
2 parents f713a14 + 54ee868 commit f7bf62a
Show file tree
Hide file tree
Showing 23 changed files with 13,061 additions and 885 deletions.
3 changes: 3 additions & 0 deletions ApsimNG/ApsimNG.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -320,6 +320,9 @@
<EmbeddedResource Include="Resources\PresenterPictures\RectangularZone.png" />
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="Resources\TreeViewImages\CFlow.png" />
<EmbeddedResource Include="Resources\TreeViewImages\NFlow.png" />
<EmbeddedResource Include="Resources\TreeViewImages\Solute.png" />
<EmbeddedResource Include="Resources\TreeViewImages\LinearAfterThresholdFunction.png" />
<EmbeddedResource Include="Resources\TreeViewImages\Evapotranspiration.png" />
<EmbeddedResource Include="Resources\TreeViewImages\LayerStructure.png" />
Expand Down
Binary file added ApsimNG/Resources/TreeViewImages/CFlow.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added ApsimNG/Resources/TreeViewImages/NFlow.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added ApsimNG/Resources/TreeViewImages/Solute.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 2 additions & 2 deletions Models/Agroforestry/TreeProxy.cs
Original file line number Diff line number Diff line change
Expand Up @@ -628,8 +628,8 @@ public void SetNUptake(List<Soils.Arbitrator.ZoneWaterAndN> info)
ThisSoil = Apsim.Find(SearchZ, typeof(Soils.Soil)) as Soils.Soil;
double[] NewNO3 = new double[ZI.NO3N.Length];
for (int i = 0; i <= ZI.NO3N.Length - 1; i++)
NewNO3[i] = ThisSoil.SoilNitrogen.NO3[i] - ZI.NO3N[i];
ThisSoil.SoilNitrogen.NO3 = NewNO3;
NewNO3[i] = ThisSoil.NO3N[i] - ZI.NO3N[i];
ThisSoil.NO3N = NewNO3;
}
}
}
Expand Down
24 changes: 24 additions & 0 deletions Models/Interfaces/INutrient.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
// -----------------------------------------------------------------------
// <copyright file="INutrient.cs" company="APSIM Initiative">
// Copyright (c) APSIM Initiative
// </copyright>
//-----------------------------------------------------------------------
namespace Models.Interfaces
{
using System.Collections.Generic;
using Models.Soils.Arbitrator;
using Models.Soils;

/// <summary>
/// This interface defines the communications between a soil arbitrator and
/// and crop.
/// </summary>
public interface INutrient
{

/// <summary>
/// Calculate actual decomposition
/// </summary>
SurfaceOrganicMatterDecompType CalculateActualSOMDecomp();
}
}
1 change: 1 addition & 0 deletions Models/Models.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,7 @@
<Compile Include="Interfaces\ICanopy.cs" />
<Compile Include="Interfaces\ISoilWater.cs" />
<Compile Include="Interfaces\ISolute.cs" />
<Compile Include="Interfaces\INutrient.cs" />
<Compile Include="Interfaces\IWeather.cs" />
<Compile Include="Lifecycle\Cohort.cs" />
<Compile Include="Lifecycle\Lifecycle.cs" />
Expand Down
122 changes: 90 additions & 32 deletions Models/Soils/Nutrient/CFlow.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,53 +5,55 @@ namespace Models.Soils.Nutrient
using Models.PMF.Functions;
using System;
using APSIM.Shared.Utilities;
using System.Collections.Generic;

/// <summary>
/// Encapsulates a carbon flow between pools.
/// </summary>
[Serializable]
[ValidParent(ParentType = typeof(Nutrient))]
[ValidParent(ParentType = typeof(NutrientPool))]
[PresenterName("UserInterface.Presenters.PropertyPresenter")]
[ViewName("UserInterface.Views.GridView")]
public class CarbonFlow : Model
{
private NutrientPool source = null;
private NutrientPool destination = null;
private List<NutrientPool> destinations = new List<NutrientPool>();

[Link]
private IFunction rate = null;
[ChildLinkByName]
private IFunction Rate = null;

[Link]
[ChildLinkByName]
private IFunction CO2Efficiency = null;

[Link]
private Clock Clock = null;

[Link]
private SoluteManager solutes = null;

/// <summary>
/// Name of source pool
/// Name of destination pool
/// </summary>
[Description("Name of source pool")]
public string sourceName { get; set; }

[Description("Names of destination pools (CSV)")]
public string[] destinationNames { get; set; }
/// <summary>
/// Name of destination pool
/// Fractions for each destination pool
/// </summary>
[Description("Name of destination pool")]
public string destinationName { get; set; }
[Description("Fractions of flow to each pool (CSV)")]
public double[] destinationFraction { get; set; }

/// <summary>Performs the initial checks and setup</summary>
/// <param name="sender">The sender.</param>
/// <param name="e">The <see cref="EventArgs"/> instance containing the event data.</param>
[EventSubscribe("Commencing")]
private void OnSimulationCommencing(object sender, EventArgs e)
{
source = Apsim.Find(this, sourceName) as NutrientPool;
if (source == null)
throw new Exception("Cannot find source pool with name: " + sourceName);

destination = Apsim.Find(this, destinationName) as NutrientPool;
if (destination == null)
throw new Exception("Cannot find destination pool with name: " + destinationName);
foreach (string destinationName in destinationNames)
{
NutrientPool destination = Apsim.Find(this, destinationName) as NutrientPool;
if (destination == null)
throw new Exception("Cannot find destination pool with name: " + destinationName);
destinations.Add(destination);
}
}

/// <summary>
Expand All @@ -62,21 +64,77 @@ private void OnSimulationCommencing(object sender, EventArgs e)
[EventSubscribe("DoSoilOrganicMatter")]
private void OnDoSoilOrganicMatter(object sender, EventArgs e)
{
for (int i= 0; i < source.C.Length; i++)
if (DateUtilities.DatesEqual("01-Oct",Clock.Today))
{ }

NutrientPool source = Parent as NutrientPool;
double[] NH4 = solutes.GetSolute("NH4");
double[] NO3 = solutes.GetSolute("NO3");

for (int i = 0; i < source.C.Length; i++)
{
double carbonFlow = rate.Value(i) * source.C[i];
double nitrogenFlow = MathUtilities.Divide(carbonFlow, source.CNRatio[i],0);
double carbonFlowToDestination = carbonFlow * CO2Efficiency.Value(i);
double nitrogenFlowToDestination = carbonFlowToDestination / destination.CNRatio[i];
source.C[i] -= carbonFlow;
source.N[i] -= nitrogenFlow;
destination.C[i] += carbonFlowToDestination;
destination.N[i] += nitrogenFlowToDestination;
if (nitrogenFlowToDestination <= nitrogenFlow)
solutes.AddToLayer(i, "NH4", nitrogenFlow - nitrogenFlowToDestination);
double carbonFlowFromSource = Rate.Value(i) * source.C[i];
double nitrogenFlowFromSource = MathUtilities.Divide(carbonFlowFromSource, source.CNRatio[i], 0);

double[] carbonFlowToDestination = new double[destinations.Count];
double[] nitrogenFlowToDestination = new double[destinations.Count];

for (int j = 0; j < destinations.Count; j++)
{
carbonFlowToDestination[j] = carbonFlowFromSource * CO2Efficiency.Value(i) * destinationFraction[j];
nitrogenFlowToDestination[j] = MathUtilities.Divide(carbonFlowToDestination[j],destinations[j].CNRatio[i],0.0);
}

double TotalNitrogenFlowToDestinations = MathUtilities.Sum(nitrogenFlowToDestination);
double NSupply = nitrogenFlowFromSource + NO3[i] + NH4[i];

if (MathUtilities.Sum(nitrogenFlowToDestination) > NSupply)
{
double NSupplyFactor = MathUtilities.Bound(MathUtilities.Divide(NO3[i] + NH4[i], TotalNitrogenFlowToDestinations - nitrogenFlowFromSource, 1.0), 0.0, 1.0);

for (int j = 0; j < destinations.Count; j++)
{
carbonFlowToDestination[j] *= NSupplyFactor;
nitrogenFlowToDestination[j] *= NSupplyFactor;
if (nitrogenFlowToDestination[j] > 0.5)
{ }
}
TotalNitrogenFlowToDestinations *= NSupplyFactor;

carbonFlowFromSource *= NSupplyFactor;
nitrogenFlowFromSource *= NSupplyFactor;

}

source.C[i] -= carbonFlowFromSource;
source.N[i] -= nitrogenFlowFromSource;
for (int j = 0; j < destinations.Count; j++)
{
destinations[j].C[i] += carbonFlowToDestination[j];
destinations[j].N[i] += nitrogenFlowToDestination[j];
}


if (TotalNitrogenFlowToDestinations <= nitrogenFlowFromSource)
NH4[i] += nitrogenFlowFromSource - TotalNitrogenFlowToDestinations;
else
throw new NotImplementedException();
{
double NDeficit = TotalNitrogenFlowToDestinations - nitrogenFlowFromSource;
double NH4Immobilisation = Math.Min(NH4[i], NDeficit);
NH4[i] -= NH4Immobilisation;
NDeficit -= NH4Immobilisation;

double NO3Immobilisation = Math.Min(NO3[i], NDeficit);
NO3[i] -= NO3Immobilisation;
NDeficit -= NO3Immobilisation;

if (MathUtilities.IsGreaterThan(NDeficit, 0.0))
throw new Exception("Insufficient mineral N for immobilisation demand for C flow " + Name);
}

}
solutes.SetSolute("NH4", NH4);
solutes.SetSolute("NO3", NO3);
}


Expand Down
40 changes: 29 additions & 11 deletions Models/Soils/Nutrient/NFlow.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ namespace Models.Soils.Nutrient
/// Encapsulates a nitrogen flow between mineral N pools.
/// </summary>
[Serializable]
[ValidParent(ParentType = typeof(Nutrient))]
[ValidParent(ParentType = typeof(Solute))]
[PresenterName("UserInterface.Presenters.PropertyPresenter")]
[ViewName("UserInterface.Views.GridView")]
public class NFlow : Model
Expand All @@ -24,8 +24,14 @@ public class NFlow : Model
[Link]
private SoluteManager solutes = null;

[Link]
private Soil soil = null;
/// <summary>
/// Value of total N flow into destination
/// </summary>
public double[] Value { get; set; }
/// <summary>
/// Value of total loss
/// </summary>
public double[] Loss { get; set; }

/// <summary>
/// Name of source pool
Expand All @@ -46,22 +52,34 @@ public class NFlow : Model
/// <param name="e">The <see cref="EventArgs"/> instance containing the event data.</param>
[EventSubscribe("DoSoilOrganicMatter")]
private void OnDoSoilOrganicMatter(object sender, EventArgs e)
{

double[] source = solutes.GetSolute(sourceName);
{
double[] source = solutes.GetSolute(Parent.Name);
if (Value == null)
Value = new double[source.Length];
if (Loss == null)
Loss = new double[source.Length];

double[] destination = solutes.GetSolute(destinationName);
double[] destination = null;
if (destinationName !=null)
destination = solutes.GetSolute(destinationName);

for (int i= 0; i < soil.Thickness.Length; i++)
for (int i= 0; i < source.Length; i++)
{
double nitrogenFlow = rate.Value(i) * source[i];
double nitrogenFlowToDestination = nitrogenFlow * (1-NLoss.Value(i));
Loss[i]= nitrogenFlow * NLoss.Value(i); // keep value of loss for use in output
double nitrogenFlowToDestination = nitrogenFlow - Loss[i];

if (destination == null && NLoss.Value(i) != 1)
throw new Exception("N loss fraction for N flow must be 1 if no destination is specified.");

source[i] -= nitrogenFlow;
destination[i] += nitrogenFlowToDestination;
Value[i] = nitrogenFlowToDestination; // keep value of flow for use in output
if (destination != null)
destination[i] += nitrogenFlowToDestination;
}
solutes.SetSolute(sourceName, source);
solutes.SetSolute(destinationName, destination);
if (destination != null)
solutes.SetSolute(destinationName, destination);
}


Expand Down
Loading

0 comments on commit f7bf62a

Please sign in to comment.