Files
CarbonLib/CarbonCalculation.cs
Francisco Salas 5c40805a3b
All checks were successful
FarmMaps/CarbonLib/pipeline/head This commit looks good
FarmMaps.Develop/CarbonLib/pipeline/head This commit looks good
merged from master
2024-01-23 14:40:26 +01:00

2043 lines
105 KiB
C#

using Base.Core.Common;
using Base.Core.Common.Geometry;
using CarbonService.Models;
using FarmMapsAPI.Carbon.Models;
using NetTopologySuite.Geometries;
using OSGeo.OGR;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
namespace FarmMapsAPI.Carbon
{
public class CarbonCalculation
{
private readonly string configPath;
private SetsForDataTransformation dataTransformationSet;
private GIS_Soils_Sets gisSoilSet;
private CropSets cropSet;
private ParameterSet parameterSet;
private FarmInputsetsModel farmInputSet;
private List<CropYieldModel> cropYieldConfig;
private List<ManCcontModel> manCcontConfig;
private List<CropPropertyModel> cropPropertyConfig;
private List<YieldGreenManureModel> yieldGreenManureConfig;
private List<CropCoverMonthsModel> cropCoverMonthConfig;
private List<MappingCropFarmmapsMiterraRothC> mappingCropFarmmapsMiterraRothC;
private List<MappingGreenManureFarmmapsMiterraRothC> mappingGreenManureFarmmapsMiterraRothC;
public CarbonCalculation(string configPath)
{
this.configPath = configPath;
var dataTransformationSetFile = Helper.GetPlatformIndependentDirectoryPath(Path.Combine(configPath, "SetsForDataTransformation.json"));
var gisSoilFile = Helper.GetPlatformIndependentDirectoryPath(Path.Combine(configPath, "GIS_Soil_Sets.json"));
var cropSetFile = Helper.GetPlatformIndependentDirectoryPath(Path.Combine(configPath, "CropSets.json"));
var parameterRothCFile = Helper.GetPlatformIndependentDirectoryPath(Path.Combine(configPath, "ParametersRothC.json"));
var farmInputSetFile = Helper.GetPlatformIndependentDirectoryPath(Path.Combine(configPath, "Farm_input_sets.json"));
var cropYieldFile = Helper.GetPlatformIndependentDirectoryPath(Path.Combine(configPath, "CropYield.json"));
var manCcontFile = Helper.GetPlatformIndependentDirectoryPath(Path.Combine(configPath, "ManCcont.json"));
var cropPropertyFile = Helper.GetPlatformIndependentDirectoryPath(Path.Combine(configPath, "CropProperties.json"));
var yieldGreenManureFile = Helper.GetPlatformIndependentDirectoryPath(Path.Combine(configPath, "YieldGreenManure.json"));
var cropCoverMonthFile = Helper.GetPlatformIndependentDirectoryPath(Path.Combine(configPath, "CropCoverMonth.json"));
var mappingCropFarmmapsMiterraFile = Helper.GetPlatformIndependentDirectoryPath(Path.Combine(configPath, "Mapping", "MappingCropsFarmmapsMiterraRothC.json"));
var mappingGreenManureFarmmapsMiterraFile = Helper.GetPlatformIndependentDirectoryPath(Path.Combine(configPath, "Mapping", "MappingGreenManureFarmmapsMiterraRothC.json"));
// sets
//var regionSet = GamsSets.ReadSets<RegionSets>(regionSetFile);
dataTransformationSet = GamsSets.ReadSets<SetsForDataTransformation>(dataTransformationSetFile);
gisSoilSet = GamsSets.ReadSets<GIS_Soils_Sets>(gisSoilFile);
cropSet = GamsSets.ReadSets<CropSets>(cropSetFile);
parameterSet = GamsSets.ReadSets<ParameterSet>(parameterRothCFile);
farmInputSet = GamsSets.ReadSets<FarmInputsetsModel>(farmInputSetFile);
cropYieldConfig = GamsSets.ReadSets<List<CropYieldModel>>(cropYieldFile);
manCcontConfig = GamsSets.ReadSets<List<ManCcontModel>>(manCcontFile);
cropPropertyConfig = GamsSets.ReadSets<List<CropPropertyModel>>(cropPropertyFile);
yieldGreenManureConfig = GamsSets.ReadSets<List<YieldGreenManureModel>>(yieldGreenManureFile);
cropCoverMonthConfig = GamsSets.ReadSets<List<CropCoverMonthsModel>>(cropCoverMonthFile);
// mapping
mappingCropFarmmapsMiterraRothC = GamsSets.ReadSets<List<MappingCropFarmmapsMiterraRothC>>(mappingCropFarmmapsMiterraFile);
mappingGreenManureFarmmapsMiterraRothC = GamsSets.ReadSets<List<MappingGreenManureFarmmapsMiterraRothC>>(mappingGreenManureFarmmapsMiterraFile);
}
public string Validate(CarbonRequest farmInput)
{
var postalCodePresent = dataTransformationSet.KNMI_zone_Reg.Any(x => x.Reg.Any(y => y == farmInput.PostalCode));
if (!postalCodePresent)
{
return $"Unknown postalcode (reg) {farmInput.PostalCode}";
}
var allCrops = farmInput.CropFields.SelectMany(s => s.HistoricalCropData.SelectMany(x => x.Crops)).Distinct();
foreach (var crop in allCrops)
{
if (string.IsNullOrEmpty(crop.Crop))
{
return "Missing crop";
}
var cropPresent = cropPropertyConfig.Any(x => x.Name.ToLower() == crop.Crop.ToLower());
if (!cropPresent)
{
return $"Unknown crop {crop.Crop}";
}
}
var allSoils = farmInput.CropFields.Select(s => s.SoilType);
foreach (var soil in allSoils)
{
if (!gisSoilSet.SoilType.Any(x => x == soil))
{
return $"Unknown soil {soil}";
}
}
var allGreenManure = farmInput.CropFields.SelectMany(s => s.GreenManures.SelectMany(x=>x.GreenManureTypes)).Distinct();
foreach (var greenManure in allGreenManure)
{
if (!yieldGreenManureConfig.Any(x=>x.ManureName.ToLower() == greenManure.Type.ToLower()))
{
return $"Unknown green manure {greenManure.Type}";
}
}
var allOrgManure = farmInput.CropFields.SelectMany(x => x.HistoricalCropData.SelectMany(s => s.Crops.Where(w=>w.OrganicManures != null).SelectMany(y=>y.OrganicManures.Select(r=>r.Type)))).Distinct();
foreach (var orgManure in allOrgManure)
{
if (!manCcontConfig.Any(x=>x.ManCcont == orgManure))
{
return $"Unknown organic manure {orgManure}";
}
}
//var allYears
return null;
}
public CarbonRequest MapFarmMapsToMiterra(FarmMapsCarbonRequest farmInput)
{
var mappedInput = new CarbonRequest();
mappedInput.PostalCode = farmInput.PostalCode;
mappedInput.CropFields = new List<CropField>();
foreach (var cropField in farmInput.CropFields)
{
var mappedCropData = new List<HistoricalCropData>();
var greenManures = new List<GreenManure>();
mappedInput.CropFields.Add(new CropField
{
Name = cropField.Name,
Area = cropField.Area,
HistoricalCropData = mappedCropData,
SoilType = MapSoil(cropField.SoilType),
SoilProperty = new SoilProperty { Clay_Content = cropField.SoilProperty.Clay_Content, OM_Const = cropField.SoilProperty.OM_Const, Depth10 = cropField.SoilProperty.Depth10, Depth = cropField.SoilProperty.Depth, OM_Type = cropField.SoilProperty.OM_Type },
GreenManures = greenManures
});
foreach (var crops in cropField.HistoricalCropData)
{
foreach (var cropYear in crops.Crops)
{
if (!string.IsNullOrEmpty(cropYear.MiterraCropName))
{
mappedCropData.Add(new HistoricalCropData
{
Year = crops.Year,
Crops = new List<OrgManureApplied> {
new OrgManureApplied {
Crop = cropYear.MiterraCropName,
CropRes = cropYear.CropRes,
OrganicManures =
cropYear.OrganicManures.Where(y=>y.Quantity > 0 && !string.IsNullOrEmpty(y.Type)).Select(x => new OrganicManureType { Type = x.Type, Quantity = x.Quantity }).ToList(),
CropYield = cropYear.CropYield,
Irrigation = crops.Irrigations} }
});
}
else
{
var cropMapping = mappingCropFarmmapsMiterraRothC.FirstOrDefault(x => x.CropCode == cropYear.CropCode);
if (cropMapping != null)
{
var orgManure = new List<OrganicManureType>();
if (cropYear.OrganicManures != null)
{
foreach (var manure in cropYear.OrganicManures)
{
if (!string.IsNullOrEmpty(manure.Type) && manure.Quantity > 0)
{
orgManure.Add(new OrganicManureType { Type = manure.Type, Quantity = manure.Quantity });
}
}
}
var crop = mappedCropData.SingleOrDefault(x => x.Year == crops.Year);
if (crop == null)
{
mappedCropData.Add(new HistoricalCropData { Year = crops.Year, Crops = new List<OrgManureApplied> { new OrgManureApplied { Crop = cropMapping.MiterraRothCCrop, OrganicManures = orgManure, CropYield = cropYear.CropYield, CropRes = cropYear.CropRes } } });
}
else
{
crop.Crops.Add(new OrgManureApplied { Crop = cropMapping.MiterraRothCCrop, OrganicManures = orgManure, CropYield = cropYear.CropYield, CropRes = cropYear.CropRes });
}
}
else
{
mappedCropData.Add(new HistoricalCropData { Year = crops.Year, Crops = new List<OrgManureApplied> { new OrgManureApplied { Crop = cropYear.CropCode, OrganicManures = null, CropYield = cropYear.CropYield, CropRes = cropYear.CropRes } } });
}
}
}
foreach (var cropYear in crops.GreenManures)
{
if (string.IsNullOrEmpty(cropYear.CropCode))
{
continue;
}
var greenManure = cropYear.CropCode;// mappingGreenManureFarmmapsMiterraRothC.FirstOrDefault(x => x.CropCode == cropYear.CropCode && x.PurposeCode == "118");
var manureYear = greenManures.SingleOrDefault(x => x.Year == crops.Year);
if (manureYear == null)
{
greenManures.Add(new GreenManure { Year = crops.Year, GreenManureTypes = new List<GreenManureType> { new GreenManureType { Type = greenManure, Quality = cropYear.Quality == QualityFarmMaps.Good ? Quality.Good : cropYear.Quality == QualityFarmMaps.Bad ? Quality.Bad : Quality.Average } } });
}
}
}
}
return mappedInput;
}
public double? GetCropYield(string cropCode, int year, int postalCode)
{
string provinceCode = GetProvinceCode(dataTransformationSet, postalCode);
var crpYield = cropYieldConfig.SingleOrDefault(x => x.CropName.ToLower() == cropCode.ToLower());
var crpYieldProvince = crpYield.Yields.SingleOrDefault(x => x.ProvinceCode == provinceCode);
var cropYield = crpYieldProvince.YearData.SingleOrDefault(x => x.Year == year)?.YieldValue;
return cropYield;
}
public CarbonSummary Calculate(CarbonRequest farmInput)
{
var knmiFile = Helper.GetPlatformIndependentDirectoryPath(Path.Combine(configPath, "KNMI_data.csv"));
// soilTypeData (external input)
var soilTypeData = GetSoilTypeData(farmInput);
//soilPropertiesField (external input)
var soilPropertiesField = GetSoilPropertiesField(farmInput);
// HistoricalCropData (external input)
var historicalCropdata = GetHistoricalCropdata(farmInput);
// cropAreaSheet (external input)
var cropAreaField = GetCropAreaField(farmInput);
var year = GetYears(farmInputSet, farmInput);
var carbon_organicmatter_factor = 0.54;
//////////////////////////////////////////////
// precalculations
//////////////////////////////////////////////
//soilPropSoilType
var soilPropSoilType = GetSoilPropSoilType(soilTypeData, soilPropertiesField);
//soilPropertiesField (again) --> remove this
foreach (var item in soilPropertiesField)
{
var soilProps = soilPropSoilType.Keys.Where(x => x.Item1 == item.Key).ToList();
var sumCorr = 0.0;
foreach (var soilProp in soilProps)
{
sumCorr += soilPropSoilType[soilProp].OM_Corr;
}
item.Value.OM_Corr = sumCorr;
}
var oM_corr_SoilType = new Dictionary<(string,string), double>();
foreach (var item in soilPropertiesField)
{
var soilOfItem = soilTypeData[item.Key].FirstOrDefault();
var initialSoilKey = historicalCropdata.Keys.FirstOrDefault(x => x.Item1 == item.Key && x.Item2 == year.First());
var initialSoil = historicalCropdata[initialSoilKey].FirstOrDefault();
var soilPropertyDepth10 = item.Value.Depth10;
if (item.Value.Depth.HasValue && item.Value.Depth.Value == 10)
{
soilPropertyDepth10 = true;
}
//FSA todo: different corrections for depth10 (10, 25, 30 cm)
if (initialSoil == "Temp_gras" && soilPropertyDepth10)
{
oM_corr_SoilType.Add((item.Key, soilOfItem), item.Value.OM_Cont * 0.97);
}
else if (cropSet.Grass_nat.Contains(initialSoil) && soilPropertyDepth10 && (soilOfItem == "Klei" || soilOfItem == "Zand"))
{
if (soilOfItem == "Klei")
{
oM_corr_SoilType.Add((item.Key, soilOfItem), item.Value.OM_Cont * 0.67);
}
else
{
oM_corr_SoilType.Add((item.Key, soilOfItem), item.Value.OM_Cont * 0.81);
}
}
else
{
oM_corr_SoilType.Add((item.Key, soilOfItem), item.Value.OM_Cont);
}
}
var oM_Corr = new Dictionary<string, double>();
foreach (var item in oM_corr_SoilType)
{
oM_Corr.Add(item.Key.Item1, item.Value);
}
// soilBulkDensities
Dictionary<string, SoilBulkDensityType> soilBulkDensities = GetSoilBulkDensities(soilPropertiesField, soilTypeData, soilPropSoilType, oM_corr_SoilType);
foreach (var soilBulkDensity in soilBulkDensities)
{
if (soilPropSoilType.ContainsKey((soilBulkDensity.Key, "Klei")))
{
soilPropSoilType[(soilBulkDensity.Key, "Klei")].Bulk_Density = (1.0 / soilBulkDensity.Value.Clay);
soilBulkDensity.Value.Clay = (1.0 / soilBulkDensity.Value.Clay);
}
if (soilPropSoilType.ContainsKey((soilBulkDensity.Key, "Zand")))
{
soilPropSoilType[(soilBulkDensity.Key, "Zand")].Bulk_Density = (1.0 / soilBulkDensity.Value.Sand);
soilBulkDensity.Value.Sand = (1.0 / soilBulkDensity.Value.Sand);
}
}
var bulkDens = new Dictionary<string, double>();
foreach (var soilBulkDensity in soilBulkDensities)
{
bulkDens.Add(soilBulkDensity.Key, (soilBulkDensity.Value.Clay + soilBulkDensity.Value.Sand));
}
foreach (var item in soilPropertiesField)
{
var soilProps = soilPropSoilType.Keys.Where(x => x.Item1 == item.Key).ToList();
var sumBulkDensity = 0.0;
foreach (var soilProp in soilProps)
{
sumBulkDensity += soilPropSoilType[soilProp].Bulk_Density;
}
item.Value.Bulk_Density = sumBulkDensity;
}
// finish precalculations
//////////////////////////////////////////
// loop rothc
//////////////////////////////////////////
var soc_Field = new Dictionary<string, List<YearColumnValue>>();
var cropAreaField1 = new Dictionary<(string, int), List<ColumnValue>>();
var carbonInputs = new GamsThreeKeyParameter();
var soc_Balance = new Dictionary<(string, int), List<ColumnValue>>();
var socIni = new Dictionary<(string, int), List<ColumnValue>>();
var cropAreaFarm = new Dictionary<(string, int), List<ColumnValue>>();
// start loop year
foreach (var loopYear in year)
{
var historicalCropYearKeys = historicalCropdata.Keys.Where(k => k.Item2 == loopYear).Distinct().ToList();
foreach (var historicalCropYearKey in historicalCropYearKeys)
{
foreach (var historicalCropKeyValue in historicalCropdata[historicalCropYearKey])
{
if (cropAreaField1.ContainsKey(historicalCropYearKey))
{
cropAreaField1[historicalCropYearKey].Add(new ColumnValue(historicalCropKeyValue, cropAreaField[historicalCropYearKey.Item1]));
}
else
{
cropAreaField1.Add(historicalCropYearKey, new List<ColumnValue> { new ColumnValue(historicalCropKeyValue, cropAreaField[historicalCropYearKey.Item1]) });
}
}
}
// cropAreaFarm
var croplist = new List<ColumnValue>();
foreach (var field in farmInput.CropFields.Select(s => s.Name))
{
croplist.AddRange(cropAreaField1[(field, loopYear)]);
}
cropAreaFarm.Add(("Farmname", loopYear), croplist);
Dictionary<string, List<ClimateVariable>> climateVariable = GetClimateVariable(knmiFile, dataTransformationSet, gisSoilSet, loopYear, farmInput);
// Crop and soil areas
// soilArea keys: (fieldname, year, soil)
var soilArea = new Dictionary<(string, int, string), List<ColumnValue>>();
foreach (var cropArea in cropAreaField1)
{
foreach (var soilType in soilTypeData[cropArea.Key.Item1])
{
foreach (var crparea in cropArea.Value)
{
var key = (cropArea.Key.Item1, loopYear, crparea.Key);
if (soilArea.ContainsKey(key))
{
soilArea[key].Add(new ColumnValue(soilType, crparea.Value));
}
else
{
soilArea.Add(key, new List<ColumnValue> { new ColumnValue(soilType, crparea.Value) });
}
}
}
}
// Mineral soils
var mineralSoilArea = new Dictionary<(string, int), List<ColumnValue>>();
foreach (var cropArea in cropAreaField1)
{
foreach (var soilType in soilTypeData[cropArea.Key.Item1])
{
if (!gisSoilSet.MineralSoils.Contains(soilType))
{
continue;
}
var total = 0.0;
foreach (var crparea in cropArea.Value)
{
total += crparea.Value;
var key = (cropArea.Key.Item1, loopYear);
if (mineralSoilArea.ContainsKey(key))
{
var miniralSoil = mineralSoilArea[key].FirstOrDefault(x => x.Key == crparea.Key);
if (miniralSoil == null)
{
mineralSoilArea[key].Add(new ColumnValue(crparea.Key, crparea.Value));
}
else
{
miniralSoil.Value += crparea.Value;
}
}
else
{
mineralSoilArea.Add(key, new List<ColumnValue> { new ColumnValue(crparea.Key, crparea.Value) });
}
}
}
}
// carbon input
// This part had organic manure per year per cropfield
var carbonInputManure2 = new Dictionary<(string, string), List<ColumnValue>>();
var carbonInputCompost2 = new Dictionary<(string, string), ColumnValue>();
foreach (var field in farmInput.CropFields)
{
foreach (var cropData in field.HistoricalCropData.Where(x => x.Year == loopYear).SelectMany(s => s.Crops))
{
if (cropData.OrganicManures == null)
{
continue;
}
foreach (var compost in cropData.OrganicManures)
{
if (farmInputSet.ManureSources_liv.Any(x => x.ManureSource_liv.ToUpper() == compost.Type.ToUpper()))
{
var result = compost.Quantity * manCcontConfig.SingleOrDefault(x => x.ManCcont.ToUpper() == compost.Type.ToUpper())?.Value ?? 0;
if (carbonInputManure2.ContainsKey((field.Name, cropData.Crop)))
{
carbonInputManure2[(field.Name, cropData.Crop)].Add(new ColumnValue(compost.Type, result));
}
else
{
carbonInputManure2.Add((field.Name, cropData.Crop), new List<ColumnValue> { new ColumnValue(compost.Type, result) });
}
}
else if (farmInputSet.composts.Any(x => x.compost.ToUpper() == compost.Type.ToUpper()))
{
var result = compost.Quantity * manCcontConfig.SingleOrDefault(x => x.ManCcont.ToUpper() == compost.Type.ToUpper())?.Value ?? 0;
if (carbonInputCompost2.ContainsKey((field.Name, cropData.Crop)))
{
carbonInputCompost2[(field.Name, cropData.Crop)] = new ColumnValue(compost.Type, result);
}
else
{
carbonInputCompost2.Add((field.Name, cropData.Crop), new ColumnValue(compost.Type, result));
}
}
}
}
}
// CarbonInputCompost
// cropYield
var yieldField = new Dictionary<(string, int), List<ColumnValue>>();
foreach (var fieldYear in cropAreaField1)
{
string provinceCode = GetProvinceCode(dataTransformationSet, farmInput.PostalCode);
var valueList = new List<ColumnValue>();
foreach (var item in fieldYear.Value)
{
var crpYield = cropYieldConfig.SingleOrDefault(x => x.CropName.ToLower() == item.Key.ToLower());
if (crpYield != null)
{
double yieldValue = 0;
var yieldProvinceYear = crpYield.Yields.Single(x => x.ProvinceCode == provinceCode).YearData.FirstOrDefault(y => y.Year == loopYear);
if (yieldProvinceYear == null)
{
yieldValue = 0;
}
else
{
yieldValue = yieldProvinceYear.YieldValue;
}
valueList.Add(new ColumnValue(crpYield.CropName, yieldValue));
}
}
yieldField.Add(fieldYear.Key, valueList);
var farmfield = farmInput.CropFields.SingleOrDefault(x => x.Name == fieldYear.Key.Item1);
var crop = farmfield.HistoricalCropData.SingleOrDefault(x => x.Year == fieldYear.Key.Item2);
foreach (var cropItem in crop.Crops)
{
if (cropItem.CropYield.HasValue)
{
valueList.SingleOrDefault(x => x.Key.ToLower() == cropItem.Crop.ToLower()).Value = cropItem.CropYield.Value;
}
}
}
// DM_Yield_Field
// dm_Yield_Field key: (field, year)
var dm_Yield_Field = new Dictionary<(string, int), List<ColumnValue>>();
foreach (var yieldFieldYear in yieldField)
{
var valueList = new List<ColumnValue>();
foreach (var value in yieldFieldYear.Value)
{
var newValue = value.Value * 0.001;
var dmValue = cropPropertyConfig.SingleOrDefault(x => x.Name == value.Key)?.DM_content ?? 0;
newValue = newValue * dmValue;
valueList.Add(new ColumnValue(value.Key, newValue));
}
dm_Yield_Field.Add(yieldFieldYear.Key, valueList);
}
var harvestIndexField = new Dictionary<(string, int), List<ColumnValue>>();
foreach (var dmField in dm_Yield_Field)
{
var valueList = new List<ColumnValue>();
foreach (var item in dmField.Value)
{
var newValue = 0.0;
switch (item.Key)
{
// maybe in json strawcrops?
case "Maize":
newValue = 0.024 * item.Value + 0.228;
valueList.Add(new ColumnValue(item.Key, newValue));
break;
case "Corn_Cob_mix":
newValue = 0.024 * item.Value + 0.228;
valueList.Add(new ColumnValue(item.Key, newValue));
break;
case "Winter_wheat":
newValue = 0.0246 * item.Value + 0.3192;
valueList.Add(new ColumnValue(item.Key, newValue));
break;
case "Summer_wheat":
newValue = 0.0246 * item.Value + 0.3192;
valueList.Add(new ColumnValue(item.Key, newValue));
break;
case "Summer_barley":
newValue = 0.0256 * item.Value + 0.3727;
valueList.Add(new ColumnValue(item.Key, newValue));
break;
case "winter_barley":
newValue = 0.0256 * item.Value + 0.3727;
valueList.Add(new ColumnValue(item.Key, newValue));
break;
case "Rapeseed":
newValue = 0.008 * item.Value + 0.3037;
valueList.Add(new ColumnValue(item.Key, newValue));
break;
case "Rye":
newValue = 0.0256 * item.Value + 0.3727;
valueList.Add(new ColumnValue(item.Key, newValue));
break;
case "oats":
newValue = 0.0256 * item.Value + 0.3727;
valueList.Add(new ColumnValue(item.Key, newValue));
break;
case "Sunflower":
newValue = 0.0077 * item.Value + 0.3045;
valueList.Add(new ColumnValue(item.Key, newValue));
break;
case "Other_cereals":
newValue = 0.0256 * item.Value + 0.3727;
valueList.Add(new ColumnValue(item.Key, newValue));
break;
default:
break;
}
}
if (valueList.Count > 0)
{
harvestIndexField.Add(dmField.Key, valueList);
}
}
// AboveGroundResidues
var aboveGroundResidues = new Dictionary<(string, int), List<ColumnValue>>();
var stubbleChaff = new Dictionary<(string, int), List<ColumnValue>>();
var strawYield = new Dictionary<(string, int), List<ColumnValue>>();
foreach (var harvestField in harvestIndexField)
{
var valueList = new List<ColumnValue>();
var valueListStubbleChaff = new List<ColumnValue>();
var valueListStrawYield = new List<ColumnValue>();
foreach (var harvestValue in harvestField.Value)
{
var dm_YieldValue = dm_Yield_Field[harvestField.Key].SingleOrDefault(x => x.Key == harvestValue.Key);
var result = (dm_YieldValue.Value / harvestValue.Value) - dm_YieldValue.Value;
valueList.Add(new ColumnValue(harvestValue.Key, result));
valueListStubbleChaff.Add(new ColumnValue(harvestValue.Key, result * parameterSet.StubbleFraction));
valueListStrawYield.Add(new ColumnValue(harvestValue.Key, result * (1 - parameterSet.StubbleFraction)));
}
aboveGroundResidues.Add(harvestField.Key, valueList);
stubbleChaff.Add(harvestField.Key, valueListStubbleChaff);
strawYield.Add(harvestField.Key, valueListStrawYield);
}
// BelowGroundCarbonInput
// (field, year) --> crop,value
var belowGroundCarbonInput = new Dictionary<(string, int), List<ColumnValue>>();
foreach (var stubbleC in stubbleChaff)
{
var valueList = new List<ColumnValue>();
foreach (var stubbleKeyValue in stubbleC.Value)
{
var dmYieldValue = dm_Yield_Field[stubbleC.Key].Single(s => s.Key.ToLower() == stubbleKeyValue.Key.ToLower());
var strawYieldValue = strawYield[stubbleC.Key].Single(s => s.Key.ToLower() == stubbleKeyValue.Key.ToLower());
var dmContentStraw = cropSet.StrawCrops.Single(s => s.StrawCrop.ToLower() == stubbleKeyValue.Key.ToLower());
var result = ((dmYieldValue.Value + ((stubbleKeyValue.Value + strawYieldValue.Value) * dmContentStraw.DM_Content)) * parameterSet.CarbonBiomass) / ((1 / parameterSet.FracBelowGroundCinput) - 1);
valueList.Add(new ColumnValue(stubbleKeyValue.Key, result));
}
belowGroundCarbonInput.Add(stubbleC.Key, valueList);
}
// CarbonInputs
// (field, year, crop)
// what to do with carbon residues??
// other cereals?? (has value in cInputCropRes and is strawCrop)
foreach (var cropArea in cropAreaField1.Where(x => x.Key.Item2 == loopYear))
{
foreach (var crop in cropArea.Value)
{
var cInputCropRes = cropPropertyConfig.SingleOrDefault(s => s.Name.ToLower() == crop.Key.ToLower())?.C_input_CropRes ?? 0.0;
carbonInputs.AddValue((cropArea.Key.Item1, cropArea.Key.Item2, crop.Key), "CarbonResidues", cInputCropRes);
if (cropSet.StrawCrops.Any(x => x.StrawCrop.ToLower() == crop.Key.ToLower()))
{
var belowGroundCarbon = belowGroundCarbonInput[cropArea.Key].SingleOrDefault(x => x.Key.ToLower() == crop.Key.ToLower());
var below2 = GetColumnValueForKey(belowGroundCarbonInput, cropArea.Key, crop.Key);
var stubble = GetColumnValueForKey(stubbleChaff, cropArea.Key, crop.Key);
var dm_contentStraw = cropSet.StrawCrops.SingleOrDefault(x => x.StrawCrop.ToLower() == crop.Key.ToLower())?.DM_Content ?? 0;
var strawYld = strawYield[cropArea.Key].SingleOrDefault(x => x.Key.ToLower() == crop.Key.ToLower())?.Value ?? 0;
var fracR = cropPropertyConfig.SingleOrDefault(x => x.Name.ToLower() == crop.Key.ToLower())?.FracR ?? 0.0;
var field = farmInput.CropFields.SingleOrDefault(x => x.Name == cropArea.Key.Item1);
var crop_res = field.HistoricalCropData.SingleOrDefault(x => x.Year == loopYear).Crops[0].CropRes ? 0 : 1;
//var result = belowGroundCarbon.Value + (stubble * dm_contentStraw * parameterSet.CarbonBiomass) + ((1 - fracR) * strawYld * dm_contentStraw * parameterSet.CarbonBiomass);
var result = belowGroundCarbon.Value + (stubble * dm_contentStraw * parameterSet.CarbonBiomass) + (crop_res * strawYld * dm_contentStraw * parameterSet.CarbonBiomass);
//check if key exists (from if condition (in case of other cereals))
if (result > 12000)
{
result = 12000;
}
carbonInputs.AddOrUpdateValue((cropArea.Key.Item1, cropArea.Key.Item2, crop.Key), "CarbonResidues", result);
}
}
}
// CarbonInputGreenManure
var carbonInputGreenManure = GetCarbonInputGreenManure(loopYear, farmInput, yieldGreenManureConfig);
//Total carbon input[in ton C / ha] from manure, compost, crop residues and green manure
// CarbonInputs(field, year, crop,'CarbonResidues')$(CarbonInputs(field, year,crop,'CarbonResidues')>12000) = 12000;???
foreach (var carbon in carbonInputManure2)
{
var sumCarbonInputManure = carbon.Value.Sum(x => x.Value);
var carbonKeyInput = carbonInputs.TrippleKeyParam.Where(x => x.Key.Item1 == carbon.Key.Item1 && x.Key.Item3.ToLower() == carbon.Key.Item2.ToLower() && x.Key.Item2 == loopYear).Select(s => s.Key).ToList();
foreach (var carbonKey in carbonKeyInput)
{
carbonInputs.AddValue(carbonKey, "CarbonManure", sumCarbonInputManure);
}
}
foreach (var carbonManure in carbonInputGreenManure.Where(x => x.Key.Item2 == loopYear))
{
var sum = carbonManure.Value.Sum(x => x.Value);
foreach (var item in historicalCropdata[carbonManure.Key])
{
carbonInputs.AddValue((carbonManure.Key.Item1, carbonManure.Key.Item2, item), "CarbonGreenManure", sum);
}
}
foreach (var carbon in carbonInputCompost2)
{
foreach (var historicData in historicalCropdata.Where(x => x.Key.Item2 == loopYear))
{
var historicDataItem = historicData.Value.SingleOrDefault(x => x.ToLower() == carbon.Key.Item2.ToLower());
if (historicDataItem != null)
{
carbonInputs.AddValueSkipIfColumnExists((historicData.Key.Item1, historicData.Key.Item2, historicDataItem), "CarbonCompost", carbon.Value.Value);
}
}
}
// TempModFactor
var tempModFactor = new Dictionary<string, List<ColumnValue>>();
foreach (var climateVar in climateVariable)
{
var valueList = new List<ColumnValue>();
var count = 1;
foreach (var temperature in climateVar.Value)
{
var temp = 47.9 / (1 + Math.Exp(106.0 / (temperature.Temperature + 18.3)));
valueList.Add(new ColumnValue($"M{count}", temp));
count++;
}
tempModFactor.Add(climateVar.Key, valueList);
}
// CoverModFactor
// input sheet
var coverModFactor = new Dictionary<string, List<ColumnValue>>();
foreach (var crpCover in cropCoverMonthConfig)
{
var valueList = new List<ColumnValue>();
for (int i = 1; i < 13; i++)
{
if (crpCover.CoverMonths.Contains($"M{i}"))
{
valueList.Add(new ColumnValue($"M{i}", 0.6));
}
else
{
valueList.Add(new ColumnValue($"M{i}", 1.0));
}
}
coverModFactor.Add(crpCover.CropName, valueList);
}
// SMDMax
// field, crop
var smdMax = new Dictionary<string, double>();
foreach (var soil in soilPropertiesField)
{
var result = -(20 + (1.3 * soil.Value.Clay_Content) - (0.01 * Math.Pow(soil.Value.Clay_Content, 2))) * (parameterSet.LayerDepth / 23);
smdMax.Add(soil.Key, result);
}
// SMDaccMonthi
var smdAccMonthi = new Dictionary<string, List<ColumnValue>>();
foreach (var climateItem in climateVariable)
{
var valueList = new List<ColumnValue>();
for (int i = 0; i < climateItem.Value.Count; i++)
{
if (i == 0)
{
/* smdMax met factor maand corrigeren
SMDmax(Field,Crop,AllMonths) = ifthen(CropCoverMonths(Crop,AllMonths)=1,
SMDmax(Field,Crop,AllMonths),SMDmax(Field,Crop,AllMonths)/1.8);
*/
var crop = cropAreaField1.SingleOrDefault(x => x.Key.Item2 == loopYear).Value[0].Key;
var cover = cropCoverMonthConfig.SingleOrDefault(x => x.CropName.ToLower() == crop.ToLower())?.CoverMonths;
var hasCover = cover.Any(x => x == $"M{i + 1}");
var smdMaxValue = smdMax[climateItem.Key];
if (!hasCover)
{
smdMaxValue = smdMax[climateItem.Key] / 1.8;
}
//fsa todo: add precipitation
var irrigation = 0;
var irrigations = farmInput.CropFields[0].HistoricalCropData.SingleOrDefault(x => x.Year == loopYear).Crops[0].Irrigation;
if (!string.IsNullOrEmpty(irrigations))
{
var irrigationArray = irrigations.Split(',');
if (irrigationArray.Length > i)
{
irrigation = string.IsNullOrEmpty(irrigationArray[i]) ? 0 : Convert.ToInt16(irrigationArray[i]);
}
}
var result = climateItem.Value[i].Precipitation - climateItem.Value[i].Evapotranspiration + irrigation;
result = result < 0 ? result : 0;
result = result < smdMaxValue ? smdMaxValue : result;
valueList.Add(new ColumnValue("M1", result));
}
else
{
/* smdMax met factor maand corrigeren
SMDmax(Field,Crop,AllMonths) = ifthen(CropCoverMonths(Crop,AllMonths)=1,
SMDmax(Field,Crop,AllMonths),SMDmax(Field,Crop,AllMonths)/1.8);
*/
var crop = cropAreaField1.SingleOrDefault(x => x.Key.Item2 == loopYear).Value[0].Key;
var cover = cropCoverMonthConfig.SingleOrDefault(x => x.CropName.ToLower() == crop.ToLower())?.CoverMonths;
var hasCover = cover.Any(x => x == $"M{i + 1}");
var smdMaxValue = smdMax[climateItem.Key];
if (!hasCover)
{
smdMaxValue = smdMax[climateItem.Key] / 1.8;
}
var irrigation = 0;
var irrigations = farmInput.CropFields[0].HistoricalCropData.SingleOrDefault(x => x.Year == loopYear).Crops[0].Irrigation;
if (!string.IsNullOrEmpty(irrigations))
{
var irrigationArray = irrigations.Split(',');
if (irrigationArray.Length > i)
{
irrigation = string.IsNullOrEmpty(irrigationArray[i]) ? 0 : Convert.ToInt16(irrigationArray[i]);
}
}
var result = climateItem.Value[i].Precipitation - climateItem.Value[i].Evapotranspiration + valueList.SingleOrDefault(x => x.Key == $"M{i}").Value + irrigation;
result = result < 0 ? result : 0;
result = result < smdMaxValue ? smdMaxValue : result;
valueList.Add(new ColumnValue($"M{i + 1}", result));
}
}
smdAccMonthi.Add(climateItem.Key, valueList);
}
//MoistureModFactor
var moistureModFactor = new Dictionary<string, List<ColumnValue>>();
foreach (var fieldSmdAccMonthi in smdAccMonthi)
{
var valueList = new List<ColumnValue>();
foreach (var smdAccMonth in fieldSmdAccMonthi.Value)
{
/* smdMax met factor maand corrigeren
SMDmax(Field,Crop,AllMonths) = ifthen(CropCoverMonths(Crop,AllMonths)=1,
SMDmax(Field,Crop,AllMonths),SMDmax(Field,Crop,AllMonths)/1.8);
*/
var crop = cropAreaField1.SingleOrDefault(x => x.Key.Item2 == loopYear).Value[0].Key;
var cover = cropCoverMonthConfig.SingleOrDefault(x => x.CropName.ToLower() == crop.ToLower())?.CoverMonths;
var hasCover = cover.Any(x => x == smdAccMonth.Key);
var smdMaxValue = smdMax[fieldSmdAccMonthi.Key];
if (!hasCover)
{
smdMaxValue = smdMax[fieldSmdAccMonthi.Key] / 1.8;
}
if (smdAccMonth.Value > 0.444 * smdMaxValue)
{
valueList.Add(new ColumnValue(smdAccMonth.Key, 1));
}
else
{
var result = (0.2 + 0.8 * ((smdMaxValue - smdAccMonth.Value) / (smdMaxValue - 0.444 * smdMaxValue)));
valueList.Add(new ColumnValue(smdAccMonth.Key, result));
}
}
moistureModFactor.Add(fieldSmdAccMonthi.Key, valueList);
}
// TempCoverMoistureModFactorAverage
var tempCoverMoistureModFactorAverage = new Dictionary<string, List<ColumnValue>>();
foreach (var field in moistureModFactor.Select(s => s.Key))
{
var valueList = new List<ColumnValue>();
foreach (var coverMod in coverModFactor)
{
var result = 0.0;
foreach (var monthValue in coverMod.Value)
{
var covermodValue = monthValue.Value;
var tempModValue = tempModFactor[field].SingleOrDefault(x => x.Key == monthValue.Key).Value;
var moistureModValue = moistureModFactor[field].SingleOrDefault(x => x.Key == monthValue.Key).Value;
result += covermodValue * tempModValue * moistureModValue;
}
result = (1.0 / 12.0) * result;
valueList.Add(new ColumnValue(coverMod.Key, result));
}
tempCoverMoistureModFactorAverage.Add(field, valueList);
}
//step1
//SOCini
if (loopYear == year.First())
{
foreach (var field in cropAreaField1.Where(x => x.Key.Item2 == loopYear))
{
var valueList = new List<ColumnValue>();
var result = parameterSet.LayerDepth * bulkDens[field.Key.Item1] * oM_Corr[field.Key.Item1] * carbon_organicmatter_factor;// 0.54;
foreach (var crop in field.Value)
{
valueList.Add(new ColumnValue(crop.Key, result));
}
socIni.Add(field.Key, valueList);
}
}
else
{
foreach (var fieldItem in soc_Field)
{
var valueList = new List<ColumnValue>();
var prev = fieldItem.Value.SingleOrDefault(x => x.Key == loopYear - 1);
if (prev == null)
{
continue;
}
foreach (var cropItem in historicalCropdata[(fieldItem.Key, loopYear)])
{
valueList.Add(new ColumnValue(cropItem, prev.Value));
}
socIni.Add((fieldItem.Key, loopYear), valueList);
}
}
//step 2
// RPM_in_residues
// DPM_in_residues
var rpm_in_residues = new Dictionary<(string, int), List<ColumnValue>>();
var dpm_in_residues = new Dictionary<(string, int), List<ColumnValue>>();
foreach (var carbonInput in carbonInputs.TrippleKeyParam.Where(x => x.Key.Item2 == loopYear))
{
var carbonResidues = carbonInput.Value.SingleOrDefault(x => x.Key == "CarbonResidues")?.Value ?? 0;
var carbonGreenManure = carbonInput.Value.SingleOrDefault(x => x.Key == "CarbonGreenManure")?.Value ?? 0;
var resultRpm = 0.0;
var resultDpm = 0.0;
if (cropSet.Perennial.Any(x=>x.ToLower() == carbonInput.Key.Item3.ToLower()))
{
resultRpm = (carbonResidues) * 0.6;
resultDpm = (carbonResidues) * 0.4;
}
else
{
resultRpm = (carbonResidues + carbonGreenManure) * 0.41;
resultDpm = (carbonResidues + carbonGreenManure) * 0.59;
}
if (rpm_in_residues.ContainsKey((carbonInput.Key.Item1, carbonInput.Key.Item2)))
{
rpm_in_residues[(carbonInput.Key.Item1, carbonInput.Key.Item2)].Add(new ColumnValue(carbonInput.Key.Item3, resultRpm));
}
else
{
rpm_in_residues.Add((carbonInput.Key.Item1, carbonInput.Key.Item2), new List<ColumnValue> { new ColumnValue(carbonInput.Key.Item3, resultRpm) });
}
if (dpm_in_residues.ContainsKey((carbonInput.Key.Item1, carbonInput.Key.Item2)))
{
dpm_in_residues[(carbonInput.Key.Item1, carbonInput.Key.Item2)].Add(new ColumnValue(carbonInput.Key.Item3, resultDpm));
}
else
{
dpm_in_residues.Add((carbonInput.Key.Item1, carbonInput.Key.Item2), new List<ColumnValue> { new ColumnValue(carbonInput.Key.Item3, resultDpm) });
}
}
// DPM_in_Manure
// RPM_in_manure
// HUM_in_manure
var dpm_in_Manure = new Dictionary<(string, int), List<ColumnValue>>();
var rpm_in_manure = new Dictionary<(string, int), List<ColumnValue>>();
var hum_in_manure = new Dictionary<(string, int), List<ColumnValue>>();
foreach (var carbonInput in carbonInputs.TrippleKeyParam.Where(x => x.Key.Item2 == loopYear))
{
var carbonManure = carbonInput.Value.SingleOrDefault(x => x.Key == "CarbonManure")?.Value ?? 0;
var resultRpm = (carbonManure) * 0.49;
var resultDpm = (carbonManure) * 0.49;
var resultHum = (carbonManure) * 0.02;
if (rpm_in_manure.ContainsKey((carbonInput.Key.Item1, carbonInput.Key.Item2)))
{
rpm_in_manure[(carbonInput.Key.Item1, carbonInput.Key.Item2)].Add(new ColumnValue(carbonInput.Key.Item3, resultRpm));
}
else
{
rpm_in_manure.Add((carbonInput.Key.Item1, carbonInput.Key.Item2), new List<ColumnValue> { new ColumnValue(carbonInput.Key.Item3, resultRpm) });
}
if (dpm_in_Manure.ContainsKey((carbonInput.Key.Item1, carbonInput.Key.Item2)))
{
dpm_in_Manure[(carbonInput.Key.Item1, carbonInput.Key.Item2)].Add(new ColumnValue(carbonInput.Key.Item3, resultDpm));
}
else
{
dpm_in_Manure.Add((carbonInput.Key.Item1, carbonInput.Key.Item2), new List<ColumnValue> { new ColumnValue(carbonInput.Key.Item3, resultDpm) });
}
if (hum_in_manure.ContainsKey((carbonInput.Key.Item1, carbonInput.Key.Item2)))
{
hum_in_manure[(carbonInput.Key.Item1, carbonInput.Key.Item2)].Add(new ColumnValue(carbonInput.Key.Item3, resultHum));
}
else
{
hum_in_manure.Add((carbonInput.Key.Item1, carbonInput.Key.Item2), new List<ColumnValue> { new ColumnValue(carbonInput.Key.Item3, resultHum) });
}
}
// DPM_compost
// RPM_compost
// HUM_compost
var dpm_compost = new Dictionary<(string, int), List<ColumnValue>>();
var rpm_compost = new Dictionary<(string, int), List<ColumnValue>>();
var hum_compost = new Dictionary<(string, int), List<ColumnValue>>();
foreach (var carbonInput in carbonInputs.TrippleKeyParam.Where(x => x.Key.Item2 == loopYear))
{
var carbonCompost = carbonInput.Value.SingleOrDefault(x => x.Key == "CarbonCompost")?.Value ?? 0;
var resultRpm = (carbonCompost) * 0.70;
var resultDpm = (carbonCompost) * 0.15;
var resultHum = (carbonCompost) * 0.15;
if (rpm_compost.ContainsKey((carbonInput.Key.Item1, carbonInput.Key.Item2)))
{
rpm_compost[(carbonInput.Key.Item1, carbonInput.Key.Item2)].Add(new ColumnValue(carbonInput.Key.Item3, resultRpm));
}
else
{
rpm_compost.Add((carbonInput.Key.Item1, carbonInput.Key.Item2), new List<ColumnValue> { new ColumnValue(carbonInput.Key.Item3, resultRpm) });
}
if (dpm_compost.ContainsKey((carbonInput.Key.Item1, carbonInput.Key.Item2)))
{
dpm_compost[(carbonInput.Key.Item1, carbonInput.Key.Item2)].Add(new ColumnValue(carbonInput.Key.Item3, resultDpm));
}
else
{
dpm_compost.Add((carbonInput.Key.Item1, carbonInput.Key.Item2), new List<ColumnValue> { new ColumnValue(carbonInput.Key.Item3, resultDpm) });
}
if (hum_compost.ContainsKey((carbonInput.Key.Item1, carbonInput.Key.Item2)))
{
hum_compost[(carbonInput.Key.Item1, carbonInput.Key.Item2)].Add(new ColumnValue(carbonInput.Key.Item3, resultHum));
}
else
{
hum_compost.Add((carbonInput.Key.Item1, carbonInput.Key.Item2), new List<ColumnValue> { new ColumnValue(carbonInput.Key.Item3, resultHum) });
}
}
// DPM_in
// RPM_in
// HUM_in
var dpm_in = new Dictionary<(string, int), List<ColumnValue>>();
var rpm_in = new Dictionary<(string, int), List<ColumnValue>>();
var hum_in = new Dictionary<(string, int), List<ColumnValue>>();
foreach (var dpmitem in dpm_in_Manure)
{
foreach (var item in dpmitem.Value)
{
var valueDpmManure = item.Value;
var valueDpmResidues = dpm_in_residues[dpmitem.Key].SingleOrDefault(x => x.Key == item.Key)?.Value ?? 0;
var valueDpmCompost = dpm_compost[dpmitem.Key].SingleOrDefault(x => x.Key == item.Key)?.Value ?? 0;
var result = valueDpmManure + valueDpmResidues + valueDpmCompost;
if (dpm_in.ContainsKey(dpmitem.Key))
{
dpm_in[dpmitem.Key].Add(new ColumnValue(item.Key, result));
}
else
{
dpm_in.Add(dpmitem.Key, new List<ColumnValue> { new ColumnValue(item.Key, result) });
}
}
}
foreach (var rpmitem in rpm_in_manure)
{
foreach (var item in rpmitem.Value)
{
var valueRpmManure = item.Value;
var valueRpmResidues = rpm_in_residues[rpmitem.Key].SingleOrDefault(x => x.Key == item.Key)?.Value ?? 0;
var valueRpmCompost = rpm_compost[rpmitem.Key].SingleOrDefault(x => x.Key == item.Key)?.Value ?? 0;
var result = valueRpmManure + valueRpmResidues + valueRpmCompost;
if (rpm_in.ContainsKey(rpmitem.Key))
{
rpm_in[rpmitem.Key].Add(new ColumnValue(item.Key, result));
}
else
{
rpm_in.Add(rpmitem.Key, new List<ColumnValue> { new ColumnValue(item.Key, result) });
}
}
}
foreach (var humitem in hum_in_manure)
{
foreach (var item in humitem.Value)
{
var valueHumManure = item.Value;
var valueHumCompost = hum_compost[humitem.Key].SingleOrDefault(x => x.Key == item.Key)?.Value ?? 0;
var result = valueHumManure + valueHumCompost;
if (hum_in.ContainsKey(humitem.Key))
{
hum_in[humitem.Key].Add(new ColumnValue(item.Key, result));
}
else
{
hum_in.Add(humitem.Key, new List<ColumnValue> { new ColumnValue(item.Key, result) });
}
}
}
//step 3
//DPMini
var dpmIni = new Dictionary<(string, int), List<ColumnValue>>();
foreach (var dpmItem in dpm_in)
{
foreach (var item in dpmItem.Value)
{
var tempCover = tempCoverMoistureModFactorAverage[dpmItem.Key.Item1].SingleOrDefault(x => x.Key.ToLower() == item.Key.ToLower())?.Value ?? 0;
var result = (item.Value / tempCover) / parameterSet.kDPM;
if (dpmIni.ContainsKey(dpmItem.Key))
{
dpmIni[dpmItem.Key].Add(new ColumnValue(item.Key, result));
}
else
{
dpmIni.Add(dpmItem.Key, new List<ColumnValue> { new ColumnValue(item.Key, result) });
}
}
}
//RPMini
var rpmIni = new Dictionary<(string, int), List<ColumnValue>>();
foreach (var rpmItem in rpm_in)
{
foreach (var item in rpmItem.Value)
{
var tempCover = tempCoverMoistureModFactorAverage[rpmItem.Key.Item1].SingleOrDefault(x => x.Key.ToLower() == item.Key.ToLower())?.Value ?? 0;
var result = (item.Value / tempCover) / parameterSet.kRPM;
if (rpmIni.ContainsKey(rpmItem.Key))
{
rpmIni[rpmItem.Key].Add(new ColumnValue(item.Key, result));
}
else
{
rpmIni.Add(rpmItem.Key, new List<ColumnValue> { new ColumnValue(item.Key, result) });
}
}
}
//IOMini
var iomIni = new Dictionary<(string, int), List<ColumnValue>>();
foreach (var socItem in socIni)
{
foreach (var item in socItem.Value)
{
var result = 0.049 * Math.Pow(item.Value, 1.139);
if (iomIni.ContainsKey(socItem.Key))
{
iomIni[socItem.Key].Add(new ColumnValue(item.Key, result));
}
else
{
iomIni.Add(socItem.Key, new List<ColumnValue> { new ColumnValue(item.Key, result) });
}
}
}
// BIOplusHUM_ini
var bioPlusHUM_ini = new Dictionary<(string, int), List<ColumnValue>>();
foreach (var socItem in socIni.Where(x => x.Key.Item2 == loopYear))
{
foreach (var item in socItem.Value)
{
var socIniValue = item.Value;
var dpmIniValue = dpmIni[socItem.Key].SingleOrDefault(x => x.Key == item.Key)?.Value ?? 0;
var rpmIniValue = rpmIni[socItem.Key].SingleOrDefault(x => x.Key == item.Key)?.Value ?? 0;
var iomIniValue = iomIni[socItem.Key].SingleOrDefault(x => x.Key == item.Key)?.Value ?? 0;
var result = socIniValue - (dpmIniValue + rpmIniValue + iomIniValue);
if (bioPlusHUM_ini.ContainsKey(socItem.Key))
{
bioPlusHUM_ini[socItem.Key].Add(new ColumnValue(item.Key, result));
}
else
{
bioPlusHUM_ini.Add(socItem.Key, new List<ColumnValue> { new ColumnValue(item.Key, result) });
}
}
}
// BIOini
// HUMini
var bioIni = new Dictionary<(string, int), List<ColumnValue>>();
var humIni = new Dictionary<(string, int), List<ColumnValue>>();
foreach (var bioPlusItem in bioPlusHUM_ini)
{
foreach (var item in bioPlusItem.Value)
{
var bioIniValue = item.Value / (1 + 0.66 / 0.02);
var humIniValue = item.Value / (1 + 0.02 / 0.66);
if (bioIni.ContainsKey(bioPlusItem.Key))
{
bioIni[bioPlusItem.Key].Add(new ColumnValue(item.Key, bioIniValue));
}
else
{
bioIni.Add(bioPlusItem.Key, new List<ColumnValue> { new ColumnValue(item.Key, bioIniValue) });
}
if (humIni.ContainsKey(bioPlusItem.Key))
{
humIni[bioPlusItem.Key].Add(new ColumnValue(item.Key, humIniValue));
}
else
{
humIni.Add(bioPlusItem.Key, new List<ColumnValue> { new ColumnValue(item.Key, humIniValue) });
}
}
}
//step 4
// DPMdec_fraction
// RPMdec_fraction
// BIOdec_fraction
// HUMdec_fraction
var dpmDec_fraction = new Dictionary<(string, int), List<ColumnValue>>();
var rpmDec_fraction = new Dictionary<(string, int), List<ColumnValue>>();
var bioDec_fraction = new Dictionary<(string, int), List<ColumnValue>>();
var humDec_fraction = new Dictionary<(string, int), List<ColumnValue>>();
foreach (var tempCover in tempCoverMoistureModFactorAverage)
{
foreach (var item in tempCover.Value)
{
var dpmDecValue = 1 - Math.Exp(-(item.Value * parameterSet.kDPM / 12));
var rpmDecValue = 1 - Math.Exp(-(item.Value * parameterSet.kRPM / 12));
var bioDecValue = 1 - Math.Exp(-(item.Value * 0.66 / 12));
var humDecValue = 1 - Math.Exp(-(item.Value * 0.02 / 12));
if (dpmDec_fraction.ContainsKey((tempCover.Key, loopYear)))
{
dpmDec_fraction[(tempCover.Key, loopYear)].Add(new ColumnValue(item.Key, dpmDecValue));
}
else
{
dpmDec_fraction.Add((tempCover.Key, loopYear), new List<ColumnValue> { new ColumnValue(item.Key, dpmDecValue) });
}
if (rpmDec_fraction.ContainsKey((tempCover.Key, loopYear)))
{
rpmDec_fraction[(tempCover.Key, loopYear)].Add(new ColumnValue(item.Key, rpmDecValue));
}
else
{
rpmDec_fraction.Add((tempCover.Key, loopYear), new List<ColumnValue> { new ColumnValue(item.Key, rpmDecValue) });
}
if (bioDec_fraction.ContainsKey((tempCover.Key, loopYear)))
{
bioDec_fraction[(tempCover.Key, loopYear)].Add(new ColumnValue(item.Key, bioDecValue));
}
else
{
bioDec_fraction.Add((tempCover.Key, loopYear), new List<ColumnValue> { new ColumnValue(item.Key, bioDecValue) });
}
if (humDec_fraction.ContainsKey((tempCover.Key, loopYear)))
{
humDec_fraction[(tempCover.Key, loopYear)].Add(new ColumnValue(item.Key, humDecValue));
}
else
{
humDec_fraction.Add((tempCover.Key, loopYear), new List<ColumnValue> { new ColumnValue(item.Key, humDecValue) });
}
}
}
// step 5
// CO2LostRatio
var co2LostRatio = new Dictionary<(string, int), List<ColumnValue>>();
foreach (var soilProperty in soilPropertiesField)
{
var result = 1.67 * (1.85 + 1.60 * Math.Exp(-0.0786 * soilProperty.Value.Clay_Content));
var data1 = cropAreaField1[(soilProperty.Key, loopYear)];
var valueList = new List<ColumnValue>();
foreach (var item in data1)
{
valueList.Add(new ColumnValue(item.Key, result));
}
co2LostRatio.Add((soilProperty.Key, loopYear), valueList);
}
// CO2LostRate
var co2LostRate = new Dictionary<(string, int), List<ColumnValue>>();
foreach (var co2 in co2LostRatio)
{
var valueList = new List<ColumnValue>();
foreach (var item in co2.Value)
{
var result = item.Value / (1 + item.Value);
valueList.Add(new ColumnValue(item.Key, result));
}
co2LostRate.Add(co2.Key, valueList);
}
// step 6
// DPM
// RPM
// BIO
// HUM
var dpm = new Dictionary<(string, int), List<ColumnValue>>();
var rpm = new Dictionary<(string, int), List<ColumnValue>>();
var bio = new Dictionary<(string, int), List<ColumnValue>>();
var hum = new Dictionary<(string, int), List<ColumnValue>>();
foreach (var dpmItem in dpmIni)
{
var valueList = new List<ColumnValue>();
foreach (var item in dpmItem.Value)
{
valueList.Add(new ColumnValue(item.Key, item.Value));
}
dpm.Add(dpmItem.Key, valueList);
}
foreach (var rpmItem in rpmIni)
{
var valueList = new List<ColumnValue>();
foreach (var item in rpmItem.Value)
{
valueList.Add(new ColumnValue(item.Key, item.Value));
}
rpm.Add(rpmItem.Key, valueList);
}
foreach (var bioItem in bioIni)
{
var valueList = new List<ColumnValue>();
foreach (var item in bioItem.Value)
{
valueList.Add(new ColumnValue(item.Key, item.Value));
}
bio.Add(bioItem.Key, valueList);
}
foreach (var humItem in humIni)
{
var valueList = new List<ColumnValue>();
foreach (var item in humItem.Value)
{
valueList.Add(new ColumnValue(item.Key, item.Value));
}
hum.Add(humItem.Key, valueList);
}
// ToSOM
var toSOM = new Dictionary<(string, int), List<ColumnValue>>();
foreach (var dpmItem in dpm)
{
var valueList = new List<ColumnValue>();
foreach (var item in dpmItem.Value)
{
var result = 0.0;
for (int i = 0; i < 12; i++)
{
var dpmValue = item.Value;
var dpm_inValue = dpm_in[dpmItem.Key].SingleOrDefault(x => x.Key == item.Key)?.Value ?? 0;
var dpmDec_FractionValue = dpmDec_fraction[dpmItem.Key].SingleOrDefault(x => x.Key.ToLower() == item.Key.ToLower())?.Value ?? 0;
var temp1 = (dpmValue + (dpm_inValue / 12)) * dpmDec_FractionValue;
var rpmValue = rpm[dpmItem.Key].SingleOrDefault(x => x.Key == item.Key)?.Value ?? 0;
var rpm_InValue = rpm_in[dpmItem.Key].SingleOrDefault(x => x.Key == item.Key)?.Value ?? 0;
var rpmDec_FractionValue = rpmDec_fraction[dpmItem.Key].SingleOrDefault(x => x.Key.ToLower() == item.Key.ToLower())?.Value ?? 0;
var temp2 = (rpmValue + (rpm_InValue / 12)) * rpmDec_FractionValue;
var bioValue = bio[dpmItem.Key].SingleOrDefault(x => x.Key == item.Key)?.Value ?? 0;
var bioDec_FractionValue = bioDec_fraction[dpmItem.Key].SingleOrDefault(x => x.Key.ToLower() == item.Key.ToLower())?.Value ?? 0;
var humValue = hum[dpmItem.Key].SingleOrDefault(x => x.Key == item.Key)?.Value ?? 0;
var hum_InValue = hum_in[dpmItem.Key].SingleOrDefault(x => x.Key == item.Key)?.Value ?? 0;
var humDec_FractionValue = humDec_fraction[dpmItem.Key].SingleOrDefault(x => x.Key.ToLower() == item.Key.ToLower())?.Value ?? 0;
var co2 = co2LostRate[dpmItem.Key].SingleOrDefault(x => x.Key == item.Key)?.Value ?? 0;
result = ((dpmValue + (dpm_inValue / 12)) * dpmDec_FractionValue + (rpmValue + (rpm_InValue / 12)) * rpmDec_FractionValue + (bioValue * bioDec_FractionValue) + ((humValue + (hum_InValue / 12)) * humDec_FractionValue)) * (1 - co2);
item.Value = (dpmValue + (dpm_inValue / 12)) * (1 - dpmDec_FractionValue);
rpm[dpmItem.Key].SingleOrDefault(x => x.Key == item.Key).Value = (rpmValue + (rpm_InValue / 12)) * (1 - rpmDec_FractionValue);
bio[dpmItem.Key].SingleOrDefault(x => x.Key == item.Key).Value = bioValue * (1 - bioDec_FractionValue) + result * 0.46;
hum[dpmItem.Key].SingleOrDefault(x => x.Key == item.Key).Value = (humValue + (hum_InValue / 12)) * (1 - humDec_FractionValue) + result * 0.54;
}
valueList.Add(new ColumnValue(item.Key, result));
}
toSOM.Add(dpmItem.Key, valueList);
}
// SOC
var soc = new Dictionary<(string, int), List<ColumnValue>>();
foreach (var dpmItem in dpm)
{
var valueList = new List<ColumnValue>();
foreach (var item in dpmItem.Value)
{
if (!mineralSoilArea.ContainsKey(dpmItem.Key))
{
continue;
}
var dpmValue = item.Value;
var rpmValue = rpm[dpmItem.Key].SingleOrDefault(x => x.Key == item.Key)?.Value ?? 0;
var bioValue = bio[dpmItem.Key].SingleOrDefault(x => x.Key == item.Key)?.Value ?? 0;
var humValue = hum[dpmItem.Key].SingleOrDefault(x => x.Key == item.Key)?.Value ?? 0;
var iomValue = iomIni[dpmItem.Key].SingleOrDefault(x => x.Key == item.Key)?.Value ?? 0;
var result = dpmValue + rpmValue + bioValue + humValue + iomValue;
valueList.Add(new ColumnValue(item.Key, result));
}
soc.Add(dpmItem.Key, valueList);
}
// step 7
// DPMss
// RPMss
// IOMss
var dpmSs = new Dictionary<(string, int), List<ColumnValue>>();
var rpmSs = new Dictionary<(string, int), List<ColumnValue>>();
var iomSs = new Dictionary<(string, int), List<ColumnValue>>();
foreach (var dpmItem in dpmIni)
{
var valueList = new List<ColumnValue>();
foreach (var item in dpmItem.Value)
{
valueList.Add(new ColumnValue(item.Key, item.Value));
}
dpmSs.Add(dpmItem.Key, valueList);
}
foreach (var rpmItem in rpmIni)
{
var valueList = new List<ColumnValue>();
foreach (var item in rpmItem.Value)
{
valueList.Add(new ColumnValue(item.Key, item.Value));
}
rpmSs.Add(rpmItem.Key, valueList);
}
foreach (var iomItem in iomIni)
{
var valueList = new List<ColumnValue>();
foreach (var item in iomItem.Value)
{
valueList.Add(new ColumnValue(item.Key, item.Value));
}
iomSs.Add(iomItem.Key, valueList);
}
// BIOss
// HUMss
var bioSs = new Dictionary<(string, int), List<ColumnValue>>();
var humSs = new Dictionary<(string, int), List<ColumnValue>>();
foreach (var co2Lost in co2LostRatio)
{
var valueListBio = new List<ColumnValue>();
var valueListHum = new List<ColumnValue>();
foreach (var item in co2Lost.Value)
{
var co2Value = item.Value;
var tempCoverValue = 0.0;
if (tempCoverMoistureModFactorAverage.ContainsKey(co2Lost.Key.Item1))
{
tempCoverValue = tempCoverMoistureModFactorAverage[co2Lost.Key.Item1].SingleOrDefault(x => x.Key == item.Key)?.Value ?? 0;
}
if (co2Value * tempCoverValue * parameterSet.kBIO > 0)
{
var sumCarbon = carbonInputs.TrippleKeyParam[(co2Lost.Key.Item1, co2Lost.Key.Item2, item.Key)].Sum(x => x.Value);
var result = sumCarbon * 0.46 / (co2Value * tempCoverValue * parameterSet.kBIO);
valueListBio.Add(new ColumnValue(item.Key, result));
}
if (co2Value * tempCoverValue * parameterSet.kHUM > 0)
{
var sumCarbon = carbonInputs.TrippleKeyParam[(co2Lost.Key.Item1, co2Lost.Key.Item2, item.Key)].Sum(x => x.Value);
var result = sumCarbon * 0.54 / (co2Value * tempCoverValue * parameterSet.kHUM);
valueListHum.Add(new ColumnValue(item.Key, result));
}
}
bioSs.Add(co2Lost.Key, valueListBio);
humSs.Add(co2Lost.Key, valueListHum);
}
// SOC_SteadyState
var soc_SteadyState = new Dictionary<(string, int), List<ColumnValue>>();
foreach (var dpms in dpmSs)
{
var valueList = new List<ColumnValue>();
foreach (var item in dpms.Value)
{
var dpmSValue = item.Value;
var rpmSValue = rpmSs[dpms.Key].SingleOrDefault(x => x.Key == item.Key)?.Value ?? 0;
var bioSValue = bioSs[dpms.Key].SingleOrDefault(x => x.Key == item.Key)?.Value ?? 0;
var humSValue = humSs[dpms.Key].SingleOrDefault(x => x.Key == item.Key)?.Value ?? 0;
var iomSValue = iomSs[dpms.Key].SingleOrDefault(x => x.Key == item.Key)?.Value ?? 0;
var result = dpmSValue + rpmSValue + bioSValue + humSValue + iomSValue;
valueList.Add(new ColumnValue(item.Key, result));
}
soc_SteadyState.Add(dpms.Key, valueList);
}
// SOC_Field
foreach (var item in soc.Where(x => x.Key.Item2 == loopYear))
{
var result = item.Value.Sum(x => x.Value);
if (soc_Field.ContainsKey(item.Key.Item1))
{
soc_Field[item.Key.Item1].Add(new YearColumnValue(loopYear, result));
}
else
{
soc_Field.Add(item.Key.Item1, new List<YearColumnValue> { new YearColumnValue(loopYear, result) });
}
}
// SOC_Balance
foreach (var socItem in soc)
{
var valueList = new List<ColumnValue>();
foreach (var item in socItem.Value)
{
var socValue = item.Value;
var socIniValue = socIni[socItem.Key].SingleOrDefault(x => x.Key == item.Key)?.Value ?? 0;
var result = socValue - socIniValue;
valueList.Add(new ColumnValue(item.Key, result));
}
soc_Balance.Add(socItem.Key, valueList);
}
// SOC_Relative
var soc_Relative = new Dictionary<(string, int), List<ColumnValue>>();
foreach (var socItem in socIni)
{
var valueList = new List<ColumnValue>();
foreach (var item in socItem.Value)
{
var socIniValue = item.Value;
var socBalanceValue = soc_Balance[socItem.Key].SingleOrDefault(x => x.Key == item.Key)?.Value ?? 0;
var result = socBalanceValue / socIniValue;
valueList.Add(new ColumnValue(item.Key, result));
}
soc_Relative.Add(socItem.Key, valueList);
}
}
//end loopYear
// SOC_output.gms
// SOC_Summary
var carbonSummary = new CarbonSummary();
var cropFieldSummary = new List<CropFieldSummary>();
carbonSummary.CropField = cropFieldSummary;
var soc_Summary = new Dictionary<(string, int), List<ColumnValue>>();
foreach (var item in cropAreaField1)
{
var sum = item.Value.Sum(x => x.Value);
soc_Summary.Add(item.Key, new List<ColumnValue> { new ColumnValue("Total_crop_area", sum) });
}
foreach (var item in cropAreaField1)
{
var sum = item.Value.Sum(x => x.Value);
var crpField = cropFieldSummary.SingleOrDefault(x => x.Name == item.Key.Item1);
if (crpField == null)
{
cropFieldSummary.Add(new CropFieldSummary { Name = item.Key.Item1, Summary = new List<YearSummary> { new YearSummary { Year = item.Key.Item2, Total_crop_area = sum } } });
}
else
{
crpField.Summary.Add(new YearSummary { Year = item.Key.Item2, Total_crop_area = sum });
}
}
var allFields = carbonInputs.TrippleKeyParam.Keys.Select(x => x.Item1).Distinct();
var allYears = carbonInputs.TrippleKeyParam.Keys.Select(x => x.Item2).Distinct();
foreach (var fieldLoop in allFields)
{
foreach (var yLoop in allYears)
{
var sumCarbonManure = 0.0;
var sumCarbonResidues = 0.0;
var sumCarbonGreenManure = 0.0;
var sumCarbonCompost = 0.0;
foreach (var item in carbonInputs.TrippleKeyParam.Where(x => x.Key.Item1 == fieldLoop && x.Key.Item2 == yLoop))
{
sumCarbonManure += item.Value.SingleOrDefault(x => x.Key == "CarbonManure")?.Value ?? 0;
sumCarbonResidues += item.Value.SingleOrDefault(x => x.Key == "CarbonResidues")?.Value ?? 0;
sumCarbonGreenManure += item.Value.SingleOrDefault(x => x.Key == "CarbonGreenManure")?.Value ?? 0;
sumCarbonCompost += item.Value.SingleOrDefault(x => x.Key == "CarbonCompost")?.Value ?? 0;
}
soc_Summary[(fieldLoop, yLoop)].Add(new ColumnValue("SOC_CarbonManure", sumCarbonManure));
soc_Summary[(fieldLoop, yLoop)].Add(new ColumnValue("SOC_CarbonResidues", sumCarbonResidues));
soc_Summary[(fieldLoop, yLoop)].Add(new ColumnValue("SOC_CarbonGreenManure", sumCarbonGreenManure));
soc_Summary[(fieldLoop, yLoop)].Add(new ColumnValue("SOC_CarbonCompost", sumCarbonCompost));
var crpField = cropFieldSummary.Single(x => x.Name == fieldLoop);
var summary = crpField.Summary.Single(x => x.Year == yLoop);
summary.SOC_CarbonManure = sumCarbonManure;
summary.SOC_CarbonResidues = sumCarbonResidues;
summary.SOC_CarbonGreenManure = sumCarbonGreenManure;
summary.SOC_CarbonCompost = sumCarbonCompost;
}
}
foreach (var item in soc_Balance)
{
var sum = item.Value.Sum(x => x.Value);
soc_Summary[item.Key].Add(new ColumnValue("Balance", sum));
var crpField = cropFieldSummary.Single(x => x.Name == item.Key.Item1);
var summary = crpField.Summary.Single(x => x.Year == item.Key.Item2);
summary.Balance = sum;
}
foreach (var item in socIni)
{
var sum = item.Value.Sum(x => x.Value);
soc_Summary[item.Key].Add(new ColumnValue("Initial", sum));
var crpField = cropFieldSummary.Single(x => x.Name == item.Key.Item1);
var summary = crpField.Summary.Single(x => x.Year == item.Key.Item2);
summary.Initial = sum;
}
foreach(var item in bulkDens)
{
var result = item.Value;
foreach (var lYear in allYears)
{
soc_Summary[(item.Key, lYear)].Add(new ColumnValue("Bulk_Density", result));
}
}
foreach (var item in bulkDens)
{
var result = item.Value;
foreach (var lYear in allYears)
{
var summaries = cropFieldSummary.Single(x => x.Name == item.Key);
var summary = summaries.Summary.Single(x => x.Year == lYear);
summary.Bulk_Density = result;
}
}
foreach (var item in socIni)
{
var crpField = cropFieldSummary.Single(x => x.Name == item.Key.Item1);
var summary = crpField.Summary.Single(x => x.Year == item.Key.Item2);
summary.Crop = item.Value[0].Key;
}
foreach (var item in soc_Summary)
{
var balanceValue = item.Value.SingleOrDefault(x => x.Key == "Balance")?.Value ?? 0;
var initValue = item.Value.SingleOrDefault(x => x.Key == "Initial")?.Value ?? 0;
var bulkValue = item.Value.SingleOrDefault(x => x.Key == "Bulk_Density")?.Value ?? 0;
double result = 0;
if (bulkValue > 0)
{
result = (balanceValue + initValue) / parameterSet.LayerDepth / bulkValue;
}
item.Value.Add(new ColumnValue("IniCcontent", result));
var carbonManure = item.Value.SingleOrDefault(x => x.Key == "SOC_CarbonManure")?.Value ?? 0;
var carbonResidues = item.Value.SingleOrDefault(x => x.Key == "SOC_CarbonResidues")?.Value ?? 0;
var carbonGreenManure = item.Value.SingleOrDefault(x => x.Key == "SOC_CarbonGreenManure")?.Value ?? 0;
var carbonCompost = item.Value.SingleOrDefault(x => x.Key == "SOC_CarbonCompost")?.Value ?? 0;
var emision = -1 * (carbonManure + carbonResidues + carbonGreenManure + carbonCompost - balanceValue);
item.Value.Add(new ColumnValue("Emision", emision));
}
foreach (var item in cropFieldSummary)
{
foreach (var crpSummary in item.Summary)
{
var result = (crpSummary.Balance + crpSummary.Initial) / parameterSet.LayerDepth / crpSummary.Bulk_Density;
crpSummary.IniCcontent = result;
}
}
foreach (var item in soc_Summary)
{
var iniValue = item.Value.SingleOrDefault(x => x.Key == "IniCcontent")?.Value ?? 0;
var balanceValue = item.Value.SingleOrDefault(x => x.Key == "Balance")?.Value ?? 0;
var resultOmIni = iniValue / carbon_organicmatter_factor;// 0.54;
var resultCo2 = balanceValue * (44.0 / 12.0);
item.Value.Add(new ColumnValue("OM_ini", resultOmIni));
item.Value.Add(new ColumnValue("CO2seq", resultCo2));
}
foreach (var summaries in cropFieldSummary)
{
foreach (var item in summaries.Summary)
{
var iniValue = item.IniCcontent;
var balanceValue = item.Balance;
var manure = item.SOC_CarbonManure;
var residues = item.SOC_CarbonResidues;
var greenManure = item.SOC_CarbonGreenManure;
var compost = item.SOC_CarbonCompost;
item.OM_ini = iniValue / carbon_organicmatter_factor;// 0.54;
item.CO2seq = balanceValue * (44.0 / 12.0);
var emision = -1 * (manure + residues + greenManure + compost - balanceValue);
item.Emision = emision;
}
}
// SOC_Summary_Farm
var soc_Summary_Farm = new List<FarmYearSummary>();
foreach (var item in cropAreaFarm)
{
var sum = item.Value.Sum(x => x.Value);
soc_Summary_Farm.Add(new FarmYearSummary { Year = item.Key.Item2, Total_crop_area = sum });
}
foreach (var farm in cropAreaFarm)
{
var sumCarbonMan = 0.0;
var sumCarbonRes = 0.0;
var sumCarbonGreenMan = 0.0;
var sumCarbonCom = 0.0;
var sumEmision = 0.0;
var sumBal = 0.0;
var sumIni = 0.0;
var sumInicc = 0.0;
foreach (var item in soc_Summary.Where(x=>x.Key.Item2 == farm.Key.Item2))
{
var cropfieldArea = item.Value.SingleOrDefault(x => x.Key == "Total_crop_area")?.Value ?? 0;
sumCarbonMan += item.Value.SingleOrDefault(x => x.Key == "SOC_CarbonManure")?.Value ?? 0;
sumCarbonRes += item.Value.SingleOrDefault(x => x.Key == "SOC_CarbonResidues")?.Value ?? 0;
sumCarbonGreenMan += item.Value.SingleOrDefault(x => x.Key == "SOC_CarbonGreenManure")?.Value ?? 0;
sumCarbonCom += item.Value.SingleOrDefault(x => x.Key == "SOC_CarbonCompost")?.Value ?? 0;
sumEmision += item.Value.SingleOrDefault(x => x.Key == "Emision")?.Value ?? 0;
sumBal += item.Value.SingleOrDefault(x => x.Key == "Balance")?.Value * cropfieldArea ?? 0;
sumIni += item.Value.SingleOrDefault(x => x.Key == "Initial")?.Value ?? 0;
sumInicc += item.Value.SingleOrDefault(x => x.Key == "IniCcontent")?.Value ?? 0;
}
var farmArea = soc_Summary_Farm.SingleOrDefault(x => x.Year == farm.Key.Item2);
if (farmArea != null && farmArea.Total_crop_area > 0)
{
var resultCarbonMan = sumCarbonMan / farmArea.Total_crop_area;
var resultCarbonRes = sumCarbonRes / farmArea.Total_crop_area;
var resultCarbonGreenMan = sumCarbonGreenMan / farmArea.Total_crop_area;
var resultCarboncom = sumCarbonCom / farmArea.Total_crop_area;
var resultEmision = sumEmision / farmArea.Total_crop_area;
var resultBal = sumBal / farmArea.Total_crop_area;
var resultIni = sumIni / farmArea.Total_crop_area;
var resultiniCc = sumInicc / farmArea.Total_crop_area;
var resultOm_Ini = resultiniCc / carbon_organicmatter_factor;// 0.54;
var resultCo2 = resultBal * (44.0 / 12.0);
var resultCo2Tot = resultCo2 * farmArea.Total_crop_area;
farmArea.SOC_CarbonManure = resultCarbonMan;
farmArea.SOC_CarbonResidues = resultCarbonRes;
farmArea.SOC_CarbonGreenManure = resultCarbonGreenMan;
farmArea.SOC_CarbonCompost = resultCarboncom;
farmArea.Balance = resultBal;
farmArea.Initial = resultIni;
farmArea.IniCcontent = resultiniCc;
farmArea.OM_ini = resultOm_Ini;
farmArea.CO2seq = resultCo2;
farmArea.CO2seq_total = resultCo2Tot;
farmArea.Emision = resultEmision;
}
}
return carbonSummary;
}
private double GetColumnValueForKey(Dictionary<(string, int), List<ColumnValue>> input, (string, int) key, string column)
{
return input[key].SingleOrDefault(x => x.Key.ToLower() == column.ToLower())?.Value ?? 0;
}
private List<int> GetYears(FarmInputsetsModel farmInputSet, CarbonRequest farmInput)
{
// assume for all cropfields the same years apply
return farmInput.CropFields.First().HistoricalCropData.Select(x => x.Year).Distinct().OrderBy(o=>o).ToList();
}
private Dictionary<string, List<string>> GetSoilTypeData(CarbonRequest farmInput)
{
var soilTypeData = new Dictionary<string, List<string>>();
foreach (var field in farmInput.CropFields)
{
soilTypeData.Add(field.Name, new List<string> { field.SoilType });
}
return soilTypeData;
}
private Dictionary<string, SoilPropertyType> GetSoilPropertiesField(CarbonRequest farmInput)
{
var soilPropertiesField = new Dictionary<string, SoilPropertyType>();
foreach (var field in farmInput.CropFields)
{
soilPropertiesField.Add(field.Name, new SoilPropertyType { OM_Cont = field.SoilProperty.OM_Const.Value, Clay_Content = field.SoilProperty.Clay_Content.Value, OM_Corr = field.SoilProperty.OM_Const.Value <= 20 ? field.SoilProperty.OM_Const.Value : 0, Depth10 = field.SoilProperty.Depth10.Value, Depth = field.SoilProperty.Depth });
}
return soilPropertiesField;
}
private Dictionary<(string, string), SoilPropertyType> GetSoilPropSoilType(Dictionary<string, List<string>> soilTypeData, Dictionary<string, SoilPropertyType> soilPropertiesField)
{
var soilPropSoilType = new Dictionary<(string, string), SoilPropertyType>();
foreach (var item in soilTypeData)
{
foreach (var item2 in item.Value)
{
soilPropSoilType.Add((item.Key, item2), new SoilPropertyType { Bulk_Density = soilPropertiesField[item.Key].Bulk_Density, Clay_Content = soilPropertiesField[item.Key].Clay_Content, OM_Cont = soilPropertiesField[item.Key].OM_Cont, OM_Corr = soilPropertiesField[item.Key].OM_Corr }); // soilPropertiesField[item.Key]);
}
}
return soilPropSoilType;
}
private Dictionary<(string, int), List<string>> GetHistoricalCropdata(CarbonRequest farmInput)
{
var historicalCropData = new Dictionary<(string, int), List<string>>();
foreach (var field in farmInput.CropFields)
{
foreach (var cropYear in field.HistoricalCropData)
{
historicalCropData.Add((field.Name, cropYear.Year), cropYear.Crops.Select(x => x.Crop).ToList());
}
}
return historicalCropData;
}
private Dictionary<string, double> GetCropAreaField(CarbonRequest farmInput)
{
var cropAreaField = new Dictionary<string, double>();
foreach (var field in farmInput.CropFields)
{
cropAreaField.Add(field.Name, field.Area);
}
return cropAreaField;
}
private Dictionary<string, SoilBulkDensityType> GetSoilBulkDensities(Dictionary<string, SoilPropertyType> soilPropertiesField, Dictionary<string, List<string>> soilTypeData, Dictionary<(string, string), SoilPropertyType> soilPropSoilType, Dictionary<(string, string), double> oM_corr_SoilType)
{
var soilBulkDensities = new Dictionary<string, SoilBulkDensityType>();
foreach (var item in soilPropertiesField)
{
soilBulkDensities.Add(item.Key, new SoilBulkDensityType());
if (soilTypeData[item.Key].Any(x => x == "Klei"))
{
var soilBulkDensityKey = soilPropSoilType.Keys.Single(x => x.Item1 == item.Key && x.Item2 == "Klei");
var clay = (0.6117 + (0.003601 * item.Value.Clay_Content)) +
(0.002172 * oM_corr_SoilType[(item.Key, "Klei")] * oM_corr_SoilType[(item.Key, "Klei")]) +
(0.01715 * Math.Log(oM_corr_SoilType[(item.Key, "Klei")]));
soilBulkDensities[item.Key].Clay = clay;
}
if (soilTypeData[item.Key].Any(x => x == "Zand"))
{
var soilBulkDensityKey = soilPropSoilType.Keys.Single(x => x.Item1 == item.Key && x.Item2 == "Zand");
soilBulkDensities[item.Key].Sand = 0.667 + (0.021 * oM_corr_SoilType[(item.Key, "Zand")]);
}
}
return soilBulkDensities;
}
private static Dictionary<string, List<ClimateVariable>> GetClimateVariable(string knmiFile, SetsForDataTransformation dataTransformationSet, GIS_Soils_Sets gisSoilSet, int loopYear, CarbonRequest farmInput)
{
var data = new List<string>();
using (StreamReader r = new StreamReader(knmiFile))
{
string line;
while ((line = r.ReadLine()) != null)
{
data.Add(line);
}
}
var farmPostalCode = farmInput.PostalCode;
if (farmInput.geometry != null)
{
// determine poatalcode from geometry
string res = GetPostalCodeFromGeometry(farmInput.geometry);
farmPostalCode = 8211;
}
var farmZone = dataTransformationSet.KNMI_zone_Reg.SingleOrDefault(x => x.Reg.Contains(farmPostalCode)).KNMI_zone;
// climate (zone, month, year)
var climate = new Dictionary<(string, string, int), ClimateVariable>();
foreach (var row in data)
{
if (string.IsNullOrEmpty(row) || row.Split(';').Length == 0 || string.IsNullOrEmpty(row.Split(';')[0]))
{
continue;
}
var rowArr = row.Split(';');
climate.Add((rowArr[0], rowArr[1], int.Parse(rowArr[2])), new ClimateVariable(double.Parse(rowArr[3], CultureInfo.InvariantCulture), double.Parse(rowArr[4], CultureInfo.InvariantCulture), double.Parse(rowArr[5], CultureInfo.InvariantCulture)));
}
var climateVariable = new Dictionary<string, List<ClimateVariable>>();
foreach (var field in farmInput.CropFields.Select(s=>s.Name))
{
var monthClimateList = new List<ClimateVariable>();
foreach (var month in gisSoilSet.AllMonths)
{
var climateYear = loopYear > 2050 || loopYear < 2011 ? 2012 : loopYear;
var monthData = climate.Single(x => x.Key.Item1 == farmZone && x.Key.Item2 == month && x.Key.Item3 == climateYear).Value;
var newMonthData = new ClimateVariable(monthData.Temperature, monthData.Precipitation, monthData.Evapotranspiration * 1.25);
monthClimateList.Add(newMonthData);
}
climateVariable.Add(field, monthClimateList);
}
return climateVariable;
}
private string GetProvinceCode(SetsForDataTransformation dataTransformationSet, int postalCode)
{
// get number of postalcode based on geometry?
var farm_reg = dataTransformationSet.NUTS0NUTSII.SingleOrDefault(s => s.reg.Any(x => x == postalCode));
if (farm_reg == null)
{
throw new Exception($"reg {postalCode} not found");
}
var provinceCode = farm_reg.prov;
return provinceCode;
}
private Dictionary<(string, int), List<ColumnValue>> GetCarbonInputGreenManure(int loopYear, CarbonRequest farmInput, List<YieldGreenManureModel> yieldGreenManureConfig)
{
var carbonInputGreenManure = new Dictionary<(string, int), List<ColumnValue>>();
if (farmInput == null)
{
}
else
{
foreach (var field in farmInput.CropFields)
{
foreach (var manures in field.GreenManures)
{
foreach (var manure in manures.GreenManureTypes)
{
var manureQ = yieldGreenManureConfig.SingleOrDefault(x => x.ManureName.ToLower() == manure.Type.ToLower());
double manureQuality2 = manure.Quality == Quality.Good ? manureQ.GoodQuality : manure.Quality == Quality.Average ? manureQ.AverageQuality : manure.Quality == Quality.Bad ? manureQ.BadQuality : 0;
if (manureQuality2 > 0)
{
carbonInputGreenManure.Add((field.Name, manures.Year), new List<ColumnValue> { new ColumnValue(manure.Type, manureQuality2) });
}
}
}
}
}
return carbonInputGreenManure;
}
private static string GetPostalCodeFromGeometry(NetTopologySuite.Geometries.Geometry geometry)
{
//// Set crs default geometry factory to EPSG:4326
NetTopologySuite.NtsGeometryServices.Instance = new NetTopologySuite.NtsGeometryServices(NetTopologySuite.Geometries.Implementation.CoordinateArraySequenceFactory.Instance,
new PrecisionModel(PrecisionModels.Floating), 4326);
// Register all vector drivers
Ogr.RegisterAll();
// item.geometry is always in WGS84 so reproject to EPSG:28992
var localReference = new LocalReference("EPSG:28992");
var localGeometry = localReference.ToLocalPolygon(geometry as Polygon);
// get postal code from shape file
// open shape file
using (var postalcodes = Ogr.Open("config/PC4/PC4.shp", 0))
{
// get first layer
var pc4Layer = postalcodes.GetLayerByIndex(0);
// set spatial filter to geometry ( only intersecting features are retrieved )
pc4Layer.SetSpatialFilter(localGeometry.Centroid.ToOGRGeometry());
// get next feature
var pc4Feature = pc4Layer.GetNextFeature();
// if feature retrieved get the PC4 attribute from it
if (pc4Feature is object)
{
return pc4Feature.GetFieldAsString("PC4");
}
}
return "";
}
private string MapSoil(string soil)
{
switch (soil)
{
case "6":
case "7":
return "Klei";
case "1":
return "Zand";
default:
return "Loss";
}
}
}
}