Skip to content

Commit

Permalink
Merge branch 'holos-aafc:main' into main
Browse files Browse the repository at this point in the history
  • Loading branch information
sarahp1980 authored Apr 12, 2024
2 parents 876742e + a46b098 commit 814d68a
Show file tree
Hide file tree
Showing 11 changed files with 178 additions and 13 deletions.
22 changes: 17 additions & 5 deletions H.Content/Documentation/FAQ/FAQ.md
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,19 @@ Currently Holos does not offer the option to simulate different grazing systems,
>*Please note: more intensive grazing systems have been shown to improve the feed quality, but this must be specified for each animal group grazing on a specific pasture and for each relevant management period, using the Diet tab for that animal group/management period, e.g., by creating a custom pasture diet using the ‘Custom Diet Creator’ tool.*

### 2. I want to compare livestock management options, how can I do that in Holos?
### 2. How does Holos estimate pasture yields when animals are grazing on a field?
When the model user 'places' grazing animals on a perennial field (i.e., rangeland (native), seeded grassland, tame grass, tame legume, tame mixed (grass/legume)) for a specified period of time, Holos estimates the total annual aboveground biomass yield for each year based on the number of animals grazing on the field, the number of days spent grazing, the total daily dry matter intake and the pasture utilization rate (default values: 40% for grassland (native), 50% for seeded grassland, 60% for tame grass, tame legume and tame mixed (grass/legume) pasture). When there are two or more grazing periods in a calendar year, we assume that the leftover (i.e., unconsumed) forage/forage carbon (C) remaining at the end of the first grazing period is not returned to the soil but rather forms the basis for later vegetation growth that is consumed by grazing livestock in subsequent grazing periods in the same year. Therefore, leftover forage/C is added to the soil only at the end of the final grazing period in a given year, with the Cptosoil value for all earlier grazing periods set to zero. Further details of the methodology used to estimate aboveground biomass yield and C inputs to soil from forage residue on grazed fields can be found in Appendix 11 in the Holos algorithm document. Note: the user can adjust the default Utilization rates for each grazing animal group and field on the 'Grazing' tab for the relevant field in the user interface. The user can also override the Holos-estimated forage biomass yield estimates by entering custom yield estimates on the Details screen for the relevant field and years - these new yield estimates will then be used in all subsequent equations to estimate forage C and N inputs to the soil.


### 3. How can I graze animals on harvested annual croplands (stubble grazing) in Holos?
To graze animals on crop stubble, you should create the field as normal, specifying the field history and management practices under Steps 1-3 on the Component Selection screen, making sure to select 'Cash crop' as the Harvest method under Step 3. Grazing animals should be 'placed' on this field in the appropriate livestock components. Note: typically for annual croplands, the 'Straw returned to soil' value on the Residue tab is set to 100%, but when stubble grazing takes place, this value needs to be adjusted to reflect the proportion of this straw/residue that is removed by grazing animals, e.g., if the animals consume 60% of the stubble, then the 'Straw returned to soil' should be set to 40%. Holos accounts for manure C and N deposited on the field by the animals during the grazing period. Note: as these fields are harvested in a conventional manner using the 'Cash crop' Harvest method, the Yield (kg product/grain per ha) is estimated based on either user input or default Small Area Data yields, rather than based on animal forage intake (as is the case with grazed perennial or stubble/swath grazed fields, where livestock feed on the total aboveground biomass (i.e., product/grain + straw).


### 4. How can I swath graze a field or graze animals on standing vegetation in an annual cropfield in Holos?
To graze animals on swathed or standing vegetation, you should create the field as normal, specifying the field history and management practices under Steps 1-3 on the Component Selection screen, making sure to select 'Swathing' as the Harvest method under Step 3 (even if the vegetation is not actually swathed, it still remains in the field). Note: when you select 'Swathing' as the Harvest method, the Yield value should represent the total aboveground biomass (i.e., product + straw/residue). 'Product returned to soil' and 'Straw returned to soil' values on the Residue tab should be altered as needed, to reflect the amount of aboveground biomass that remains in the field after the animals have finished grazing, i.e., if the model user estimates that the grazing animals would consume 60% of the swathed forage, then the 'Product returned to soil' and 'Straw returned to soil' values can be set to 40% - the C in this biomass will be added to the soil C pool. Swath grazing animals should be 'placed' on this field in the appropriate livestock components. Holos accounts for manure C and N deposited on the field by the animals during the grazing period.


### 5. I want to compare livestock management options, how can I do that in Holos?
There are three options to do this:
- Set up two different farms
- Set up two livestock components within a single farm
Expand All @@ -162,12 +174,12 @@ Each of these allows the model user to compare model outputs for the different m
>*Please note: if the model user sets up two (or more) different farms, they can compare the model outputs for these farms by selecting ‘Yes’ for ‘Compare Multiple Farms’ on the Results screen and selecting the farms they wish to compare from the list available.*

### 3. I want to know what the carbon footprint of my livestock system is, what do I need to do?
### 6. I want to know what the carbon footprint of my livestock system is, what do I need to do?
The Holos model is set up to calculate a farm’s greenhouse gas (GHG) budget, meaning it accounts for all farm-based sources of GHG that we can estimate based on available information and data . To calculate the carbon footprint of a product, we need to account for all emissions generated as a result of the production of this product. For a livestock system, that means accounting for the feed production, whether that feed is grown on the actual farm or not. Before adding feed-producing fields to the simulated farm, the user must first calculate the area of each pasture or crop field required to sustain the animals on the farm – Holos will generate a warning message if not enough feed is being “grown” to satisfy animal requirements, as an internal check. Emissions generated as a result of inputs to the feed production system (e.g., fertilizer and pesticide production) are also accounted for. In Holos, upstream emissions for these farm inputs are also reported, i.e., CO2 generated from the upstream production of synthetic For the livestock system itself, emissions related to the breeding stock must be included in the calculations, as well as those relating to their progeny. Holos then outputs all of the emissions for this system up until the farm gate – any emissions related to transport, processing, etc. will need to be estimated by the user outside of Holos and added to the Holos outputs, if so desired.
>*Please note: it is up to the user to allocate the emissions according to the product, e.g., in a beef production system the outputs could easily be broken down to CO2eq per animal carcass, but for a CO2eq per kg meat it needs to be decided whether all emissions are assigned to the meat part of the carcass, or whether a portion of the emissions are allocated to the different parts of the carcass (Consulting an LCA expert is advised.)*

### 4. I want to add an ingredient to my custom diet that is not in the ingredient list, how can I do this?
### 7. I want to add an ingredient to my custom diet that is not in the ingredient list, how can I do this?
Using the Custom Diet Creator, the model user can create new feed ingredients, that can then be added to a custom diet. Open the Custom Diet Creator on the Diet tab and under Step 2, click on ‘Create Custom Ingredient’. A new row should appear at the top of the ingredient list – you can click on the ingredient name to change it. To define this ingredient, you will need to enter the relevant data in the rest of the row.
>*Please note: not all data columns in this table are necessary for the Holos calculations and the data required vary depending on the animal group under consideration.*
Expand All @@ -178,11 +190,11 @@ At a minimum, the following data are required for different animal groups :
Once you are finished, click ‘OK’ and your changes will be saved automatically.


### 5. Where can I see the full details of the default diets built into Holos?
### 8. Where can I see the full details of the default diets built into Holos?
Some of the data for the selected diet is visible when you select ‘Show Additional Information’ on the Diet tab, however you can see the full details for this diet if you open the Custom Diet Creator. Once open, select ‘Yes’ for ‘Show Default Diets’ under Step 1 – you will now see data related to the nutritional content of each default diet available for the relevant livestock type in this section, as well as data related to the percentage of the total dietary DM that is composed of the different diet ingredients (under Step 3).


### 6. How can I modify one of the default diets in Holos or create a new diet based on a default diet?
### 9. How can I modify one of the default diets in Holos or create a new diet based on a default diet?
To modify one of the default diets in Holos for a specific animal group and management period, make a copy of the default diet and then alter the data inputs for the copy. To make a copy of a default diet, open the Custom Diet Creator and under Step 1, click ‘Yes’ for ‘Show Default Diets’. In the list of default diets below, right-click on the diet of interest and click ‘Create a Copy’. You can change the name of the copy diet, if needed. Under Step 3, you can alter the % of the different ingredients in the diet or delete specific ingredients, and under Step 2 you can add ingredients. Once you have finished modifying the diet, click ‘OK’ to return to the main Diet tab and select the copied diet from the drop-down Diet menu.
>*Please note: if the user selects the same diet (either the original default diet or a copy) for more than one management period, any changes made to the diet in one management period will automatically be replicated for any other management periods using the same diet. Therefore, if the user needs to make different modifications to an existing diet for multiple animal groups/management periods, it is recommended that a copy be created for each management period, and then modified accordingly. Alternatively, the user can create an entirely new diet for each management period using the Custom Diet Creator.*
Expand Down
102 changes: 102 additions & 0 deletions H.Core.Test/Calculators/Nitrogen/N2OEmissionFactorCalculatorTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -775,6 +775,108 @@ public void GetTotalDigestateVolumeAppliedFromLivestockAndImportsInYearReturnsZe
Assert.AreEqual(0, result);
}

[TestMethod]
public void GetTotalManureVolumeAppliedFromLivestockAndImportsInYearReturnsZero()
{
_viewItem.Area = 50;
_viewItem.ManureApplicationViewItems.Clear();

var result = _sut.GetTotalManureVolumeAppliedFromLivestockAndImportsInYear(_viewItem, _farm);

Assert.AreEqual(0, result);
}

[TestMethod]
public void GetTotalManureVolumeAppliedFromLivestockAndImportsInYear()
{
_viewItem.Area = 50;
_viewItem.ManureApplicationViewItems.Clear();

_viewItem.ManureApplicationViewItems.Add(new ManureApplicationViewItem() { ManureLocationSourceType = ManureLocationSourceType.Livestock, DateOfApplication = DateTime.Now, AmountOfManureAppliedPerHectare = 100 });
_viewItem.ManureApplicationViewItems.Add(new ManureApplicationViewItem() { ManureLocationSourceType = ManureLocationSourceType.Imported, DateOfApplication = DateTime.Now, AmountOfManureAppliedPerHectare = 100 });

var result = _sut.GetTotalManureVolumeAppliedFromLivestockAndImportsInYear(_viewItem, _farm);

Assert.AreEqual((50 * 100) * 2, result);
}

[TestMethod]
public void GetTotalManureVolumeAppliedFromLivestockInYear()
{
_viewItem.Area = 50;
_viewItem.ManureApplicationViewItems.Clear();

_viewItem.ManureApplicationViewItems.Add(new ManureApplicationViewItem() { ManureLocationSourceType = ManureLocationSourceType.Livestock, DateOfApplication = DateTime.Now, AmountOfManureAppliedPerHectare = 100 });

var result = _sut.GetTotalManureVolumeAppliedFromLivestockAndImportsInYear(_viewItem, _farm);

Assert.AreEqual((50 * 100), result);
}

[TestMethod]
public void GetTotalManureVolumeAppliedFromImportsInYear()
{
_viewItem.Area = 50;
_viewItem.ManureApplicationViewItems.Clear();

_viewItem.ManureApplicationViewItems.Add(new ManureApplicationViewItem() { ManureLocationSourceType = ManureLocationSourceType.Imported, DateOfApplication = DateTime.Now, AmountOfManureAppliedPerHectare = 100 });

var result = _sut.GetTotalManureVolumeAppliedFromLivestockAndImportsInYear(_viewItem, _farm);

Assert.AreEqual((50 * 100), result);
}

[TestMethod]
public void CalculateWeightedOrganicNitrogenEmissionFactor()
{
var viewItem1 = new CropViewItem();
var viewItem2 = new CropViewItem();

var items = new List<CropViewItem>();
items.Add(viewItem1);
items.Add(viewItem2);

var field = base.GetTestFieldComponent();
_farm.Components.Add(field);

field.CropViewItems.Add(viewItem1);
field.CropViewItems.Add(viewItem2);

viewItem1.FieldSystemComponentGuid = field.Guid;
viewItem2.FieldSystemComponentGuid = field.Guid;

var result = _sut.CalculateWeightedOrganicNitrogenEmissionFactor(items, _farm);

Assert.AreEqual(0.00010811767111339097, result);
}

[TestMethod]
public void CalculateDirectN2ONFromLeftOverManureForField()
{
var stageState = _farm.GetFieldSystemDetailsStageState();
stageState.DetailsScreenViewCropViewItems.Add(_viewItem);
_farm.StageStates.Add(stageState);

var fieldWithManureApplication = base.GetTestFieldComponent();
fieldWithManureApplication.FieldArea = 133;

_farm.Components.Clear();
_farm.Components.Add(fieldWithManureApplication);
_viewItem.FieldSystemComponentGuid = fieldWithManureApplication.Guid;

var fieldWithOutManureApplications = new FieldSystemComponent();
fieldWithOutManureApplications.FieldArea = 222;
fieldWithOutManureApplications.CropViewItems.Add(new CropViewItem() {CropType = CropType.Barley});

_farm.Components.Add(fieldWithOutManureApplications);

_mockManureService.Setup(x => x.GetTotalNitrogenRemainingForFarmAndYear(It.IsAny<int>(), It.IsAny<Farm>())).Returns(10);

var result = _sut.CalculateDirectN2ONFromLeftOverManureForField(_farm, _viewItem);

Assert.AreEqual(0.0021318977402640473, result);
}

#endregion
}
}
2 changes: 1 addition & 1 deletion H.Core/Calculators/Carbon/ICBMSoilCarbonCalculator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ public CropViewItem SetCarbonInputs(
nextYearViewItem: nextYearViewItem,
farm: farm);

if (currentYearViewItem.TotalCarbonLossesByGrazingAnimals > 0 && farm.CropHasGrazingAnimals(currentYearViewItem) && farm.YieldAssignmentMethod != YieldAssignmentMethod.Custom)
if (currentYearViewItem.TotalCarbonLossesByGrazingAnimals > 0 && farm.CropHasGrazingAnimals(currentYearViewItem) && farm.YieldAssignmentMethod != YieldAssignmentMethod.Custom && currentYearViewItem.HarvestMethod != HarvestMethods.StubbleGrazing)
{
// Total C losses from grazing animals is calculated in Equation 11.3.2-4

Expand Down
1 change: 0 additions & 1 deletion H.Core/Calculators/Carbon/IPCCTier2SoilCarbonCalculator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -198,7 +198,6 @@ public void CalculateInputs(CropViewItem viewItem, Farm farm)

viewItem.AboveGroundResidueDryMatter = this.CalculateAboveGroundResidueDryMatter(harvestIndex: harvestIndex, viewItem: viewItem);


viewItem.AboveGroundResidueDryMatterExported = this.CalculateAboveGroundResidueDryMatterExported(
freshWeightOfYield: viewItem.Yield,
harvestIndex: harvestIndex,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ public double GetTotalManureVolumeAppliedFromLivestockAndImportsInYear(CropViewI
///
/// There can be multiple fields on a farm and the emission factor calculations are field-dependent (accounts for crop type, fertilizer, etc.). So
/// we take the weighted average of these fields when calculating the EF for organic nitrogen (ON). This is to be used when calculating direct emissions
/// from land applied manure. Native rangeland is not included.
/// from land applied manure or digestate. Native rangeland is not included.
/// </summary>
public double CalculateWeightedOrganicNitrogenEmissionFactor(
List<CropViewItem> itemsByYear,
Expand Down
3 changes: 3 additions & 0 deletions H.Core/Enumerations/HarvestMethods.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,5 +22,8 @@ public enum HarvestMethods
/// </summary>
[LocalizedDescription("EnumNone", typeof(Resources))]
None,

[LocalizedDescription("EnumStubbleGrazing", typeof(Resources))]
StubbleGrazing,
}
}
27 changes: 27 additions & 0 deletions H.Core/Properties/Resources.Designer.cs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

9 changes: 9 additions & 0 deletions H.Core/Properties/Resources.fr-CA.resx
Original file line number Diff line number Diff line change
Expand Up @@ -5708,4 +5708,13 @@
<data name="MessageTheSelectedYieldAssignmentMethod" xml:space="preserve">
<value>Please note that the selected yield assignement method chosen will be used for all fields on this farm. Select the 'Custom Yield' or 'Input File' assignement methods to modify the yields for individual fields</value>
</data>
<data name="EnumStubbleGrazing" xml:space="preserve">
<value>Stubble grazing</value>
</data>
<data name="LabelStrawReturnedToSoil" xml:space="preserve">
<value>Straw returned to soil</value>
</data>
<data name="LabelStrawReturnedToSoilAfterStubbleGrazing" xml:space="preserve">
<value>Straw returned to soil after stubble grazing</value>
</data>
</root>
Loading

0 comments on commit 814d68a

Please sign in to comment.