From 506b7dbfb68fca886cbec6392011b654b5acac4e Mon Sep 17 00:00:00 2001
From: Stefanos Doumpoulakis <dubulak@gmail.com>
Date: Wed, 28 Sep 2022 19:58:06 +0300
Subject: [PATCH] moved pollutants output from vsum to xml report

---
 .../OutputData/SummaryDataContainer.cs        |  76 -------------
 .../VectoCore/OutputData/XML/XMLVTPReport.cs  | 102 +++++++++++++++++-
 2 files changed, 101 insertions(+), 77 deletions(-)

diff --git a/VectoCore/VectoCore/OutputData/SummaryDataContainer.cs b/VectoCore/VectoCore/OutputData/SummaryDataContainer.cs
index 4283bba509..00cf8a634d 100644
--- a/VectoCore/VectoCore/OutputData/SummaryDataContainer.cs
+++ b/VectoCore/VectoCore/OutputData/SummaryDataContainer.cs
@@ -377,77 +377,10 @@ namespace TUGraz.VectoCore.OutputData
 			if (gearCount > 0)
 				WriteGearshiftStats(modData, row, gearCount);
 
-			WriteVTPPollutants(modData, row, runData);
-
 			lock (Table)
 				Table.Rows.Add(row);
         }
 
-        private void WriteVTPPollutants(IModalDataContainer modData, DataRow row, VectoRunData runData)
-        { 
-			if ((runData.SimulationType != SimulationType.VerificationTest) 
-				|| (runData.Cycle.Entries[0].CombustionEngineTorque == null)) {
-				return;
-			}
-
-			var fields = new List<string> { 
-				Fields.POLLUTANT_CO, 
-				Fields.POLLUTANT_NOX, 
-				Fields.POLLUTANT_THC, 
-				Fields.POLLUTANT_CO2,
-				Fields.PARTICULATE_MATTER,
-				Fields.ENGINE_ENERGY_RATIO
-			};
-			
-			if (runData.Cycle.Entries.First().CH4MassFlow != null) {
-				fields.Add(Fields.POLLUTANT_CH4);
-            }
-
-			if (runData.Cycle.Entries.First().NMHCMassFlow != null) {
-				fields.Add(Fields.POLLUTANT_NMHC);
-            }
-
-			foreach (var field in fields) {
-				lock (Table) {
-					if (!Table.Columns.Contains(field)) {
-						Table.Columns.Add(field, typeof(ConvertedSI));
-					}
-				}
-			}
-
-			var energy = runData.Cycle.Entries.Pairwise()
-				.Where(x => x.Item1.CombustionEngineTorque.IsGreaterOrEqual(0))
-				.Sum(x => (x.Item1.EngineSpeed * x.Item1.CombustionEngineTorque) * (x.Item2.Time - x.Item1.Time)).ConvertToKiloWattHour();
-
-			if (runData.Cycle.Entries.First().CH4MassFlow != null) {
-				var CH4 = runData.Cycle.Entries.Pairwise().Sum(x => (x.Item1.CH4MassFlow) * (x.Item2.Time - x.Item1.Time)).ConvertToGramm();
-				row[Fields.POLLUTANT_CH4] = (ConvertedSI) (CH4 / energy).SI<Scalar>();
-			}
-
-			var CO = runData.Cycle.Entries.Pairwise().Sum(x => x.Item1.COMassFlow * (x.Item2.Time - x.Item1.Time)).ConvertToGramm();
-			row[Fields.POLLUTANT_CO] = (ConvertedSI) (CO / energy).SI<Scalar>();
-			
-			if (runData.Cycle.Entries.First().NMHCMassFlow != null) {
-				var NMHC = runData.Cycle.Entries.Pairwise().Sum(x => x.Item1.NMHCMassFlow * (x.Item2.Time - x.Item1.Time)).ConvertToGramm();
-				row[Fields.POLLUTANT_NMHC] = (ConvertedSI) (NMHC / energy).SI<Scalar>();
-			}
-
-			var NOx = runData.Cycle.Entries.Pairwise().Sum(x => x.Item1.NOxMassFlow * (x.Item2.Time - x.Item1.Time)).ConvertToGramm();
-			row[Fields.POLLUTANT_NOX] = (ConvertedSI) (NOx / energy).SI<Scalar>();
-			
-			var THC = runData.Cycle.Entries.Pairwise().Sum(x => x.Item1.THCMassFlow * (x.Item2.Time - x.Item1.Time)).ConvertToGramm();
-			row[Fields.POLLUTANT_THC] = (ConvertedSI) (THC / energy).SI<Scalar>();
-			
-			var CO2 = runData.Cycle.Entries.Pairwise().Sum(x => x.Item1.CO2MassFlow * (x.Item2.Time - x.Item1.Time)).ConvertToGramm();
-			row[Fields.POLLUTANT_CO2] = (ConvertedSI) (CO2 / energy).SI<Scalar>();
-
-			var PN = runData.Cycle.Entries.Pairwise().Sum(x => (x.Item1.PMNumberFlow * (x.Item2.Time - x.Item1.Time)).Value()).SI<Scalar>();
-			row[Fields.PARTICULATE_MATTER] =  (ConvertedSI) (PN / energy);
-
-			var simulatedEnergy = modData.TotalEngineWorkPositive().ConvertToKiloWattHour();
-			row[Fields.ENGINE_ENERGY_RATIO] = (ConvertedSI) (energy / simulatedEnergy).SI<Scalar>();
-		}
-
         private void WriteFuelConsumptionEntries(
 			IModalDataContainer modData, DataRow row, Kilogram vehicleLoading,
 			CubicMeter cargoVolume, double? passengers, VectoRunData runData)
@@ -1252,15 +1185,6 @@ namespace TUGraz.VectoCore.OutputData
 
 			public const string AVERAGE_POS_ACC = "a_avg_acc";
 
-			public const string POLLUTANT_CH4 = "CH4 [g/kWh]";
-			public const string POLLUTANT_CO = "CO [g/kWh]";
-			public const string POLLUTANT_NMHC = "NMHC [g/kWh]";
-			public const string POLLUTANT_NOX = "NOx [g/kWh]";
-			public const string POLLUTANT_THC = "THC [g/kWh]";
-			public const string POLLUTANT_CO2 = "CO2 [g/kWh]";
-			public const string PARTICULATE_MATTER = "PM [#/kWh]";
-			public const string ENGINE_ENERGY_RATIO = "E_ICE_RATIO";
-
 			//public const string E_EM_DRIVE_FORMAT = "E_EM_{0}_drive [kWh]";
 			//public const string E_EM_GENERATE_FORMAT = "E_EM_{0}_gen [kWh]";
 			//public const string ETA_EM_DRIVE_FORMAT = "η_EM_{0}_drive";
diff --git a/VectoCore/VectoCore/OutputData/XML/XMLVTPReport.cs b/VectoCore/VectoCore/OutputData/XML/XMLVTPReport.cs
index c75773e612..0307ba0f81 100644
--- a/VectoCore/VectoCore/OutputData/XML/XMLVTPReport.cs
+++ b/VectoCore/VectoCore/OutputData/XML/XMLVTPReport.cs
@@ -53,6 +53,8 @@ using TUGraz.VectoHashing;
 using NLog;
 using TUGraz.VectoCore.Models.SimulationComponent.Impl;
 using LogManager = NLog.LogManager;
+using static TUGraz.VectoCore.Models.Simulation.Data.VectoRunData;
+using static TUGraz.VectoCore.Models.Declaration.PT1;
 
 namespace TUGraz.VectoCore.OutputData.XML
 {
@@ -60,6 +62,8 @@ namespace TUGraz.VectoCore.OutputData.XML
 	{
 		public const string CURRENT_SCHEMA_VERSION = "0.1";
 
+		private const double ENERGY_THRESHOLD_RANGE = 0.005;
+
 		private const string VTPReportTartetName = "VTPReportTarget";
 
 		protected XElement VehiclePart;
@@ -87,6 +91,16 @@ namespace TUGraz.VectoCore.OutputData.XML
 			public WattSecond VTPWorPWheelSimPos;
 			public TankSystem? TankSystem;
 
+			private const int MILLIGRAMS_PER_GRAM = 1000;
+			public Scalar CH4Emissions { protected set; get; } = null;
+			public Scalar COEmissions { protected set; get; } = null;
+			public Scalar NMHCEmissions { protected set; get; } = null;
+			public Scalar NOxEmissions { protected set; get; } = null;
+			public Scalar THCEmissions { protected set; get; } = null;
+			public Scalar CO2Emissions { protected set; get; } = null;
+			public Scalar PMFlow { protected set; get; } = null;
+			public Scalar ICEEnergyRatio { protected set; get; } = null;
+
 			#region Overrides of ResultEntry
 
 			public override void SetResultData(VectoRunData runData, IModalDataContainer data, double factor)
@@ -121,6 +135,43 @@ namespace TUGraz.VectoCore.OutputData.XML
 
 				//VTPFcFinalSimulated = data.TimeIntegral<Kilogram>(ModalResultField.FCFinal);
 				VTPFcCorrectionFactors = runData.VTPData.CorrectionFactors;
+
+				CalculateEmissions(runData, data);
+			}
+
+			private void CalculateEmissions(VectoRunData runData, IModalDataContainer data)
+			{
+				var energy = runData.Cycle.Entries.Pairwise()
+					.Where(x => x.Item1.CombustionEngineTorque.IsGreaterOrEqual(0))
+					.Sum(x => (x.Item1.EngineSpeed * x.Item1.CombustionEngineTorque) * (x.Item2.Time - x.Item1.Time)).ConvertToKiloWattHour();
+
+				if (runData.Cycle.Entries.First().CH4MassFlow != null) {
+					var CH4 = runData.Cycle.Entries.Pairwise().Sum(x => (x.Item1.CH4MassFlow) * (x.Item2.Time - x.Item1.Time)).ConvertToGramm();
+					CH4Emissions = ((CH4 / energy) * MILLIGRAMS_PER_GRAM).SI<Scalar>();
+				}
+
+				var CO = runData.Cycle.Entries.Pairwise().Sum(x => x.Item1.COMassFlow * (x.Item2.Time - x.Item1.Time)).ConvertToGramm();
+				COEmissions = ((CO / energy) * MILLIGRAMS_PER_GRAM).SI<Scalar>();
+
+				if (runData.Cycle.Entries.First().NMHCMassFlow != null) {
+					var NMHC = runData.Cycle.Entries.Pairwise().Sum(x => x.Item1.NMHCMassFlow * (x.Item2.Time - x.Item1.Time)).ConvertToGramm();
+					NMHCEmissions = ((NMHC / energy) * MILLIGRAMS_PER_GRAM).SI<Scalar>();
+				}
+
+				var NOx = runData.Cycle.Entries.Pairwise().Sum(x => x.Item1.NOxMassFlow * (x.Item2.Time - x.Item1.Time)).ConvertToGramm();
+				NOxEmissions = ((NOx / energy) * MILLIGRAMS_PER_GRAM).SI<Scalar>();
+
+				var THC = runData.Cycle.Entries.Pairwise().Sum(x => x.Item1.THCMassFlow * (x.Item2.Time - x.Item1.Time)).ConvertToGramm();
+				THCEmissions = ((THC / energy) * MILLIGRAMS_PER_GRAM).SI<Scalar>();
+
+				var CO2 = runData.Cycle.Entries.Pairwise().Sum(x => x.Item1.CO2MassFlow * (x.Item2.Time - x.Item1.Time)).ConvertToGramm();
+				CO2Emissions = ((CO2 / energy) * MILLIGRAMS_PER_GRAM).SI<Scalar>();
+
+				var PN = runData.Cycle.Entries.Pairwise().Sum(x => (x.Item1.PMNumberFlow * (x.Item2.Time - x.Item1.Time)).Value()).SI<Scalar>();
+				PMFlow = PN / energy;
+
+				var simulatedEnergy = data.TotalEngineWorkPositive().ConvertToKiloWattHour();
+				ICEEnergyRatio = (energy / simulatedEnergy).SI<Scalar>();
 			}
 
 			#endregion
@@ -258,12 +309,61 @@ namespace TUGraz.VectoCore.OutputData.XML
 						new ConvertedSI(declaredCO2.Value(), verifiedCO2.UnitString).ToMinSignificantDigits(3, 2)
 					)
 				),
-				new XElement(tns + "C_VTP", cVtp.ToXMLFormat(4)));
+				new XElement(tns + "C_VTP", cVtp.ToXMLFormat(4)),
+				CreatePollutantsElement(vtpResult));
+
+			if ((vtpResult.ICEEnergyRatio > 1 + ENERGY_THRESHOLD_RANGE) || (vtpResult.ICEEnergyRatio < 1 - ENERGY_THRESHOLD_RANGE)) {
+				LogList.Add($"Positive energy work differs too much from VECTO. ratio = {vtpResult.ICEEnergyRatio}");
+			}
+
 			if (LogList.Any()) {
 				Results.Add(new XElement(tns + "Warnings", LogList.Select(x => new XElement(tns + "Warning", x))));
 			}
 		}
 
+		private XElement CreatePollutantsElement(ResultEntry vtpResult)
+		{ 
+			var pollutantsElement = new XElement(
+				tns + "Pollutants",
+				new XElement(tns + "CO", new XAttribute(XMLNames.Report_Results_Unit_Attr, "mg/kWh"),
+					vtpResult.CO2Emissions.ToXMLFormat(3)
+				),
+				new XElement(tns + "NOx", new XAttribute(XMLNames.Report_Results_Unit_Attr, "mg/kWh"),
+					vtpResult.NOxEmissions.ToXMLFormat(3)
+				),
+				new XElement(tns + "THC", new XAttribute(XMLNames.Report_Results_Unit_Attr, "mg/kWh"),
+					vtpResult.THCEmissions.ToXMLFormat(3)
+				),
+				new XElement(tns + "CO2", new XAttribute(XMLNames.Report_Results_Unit_Attr, "mg/kWh"),
+					vtpResult.CO2Emissions.ToXMLFormat(3)
+				)
+			);
+
+			if (vtpResult.CH4Emissions != null) {
+				pollutantsElement.Add(
+					new XElement(tns + "CH4", new XAttribute(XMLNames.Report_Results_Unit_Attr, "mg/kWh"),
+						vtpResult.CH4Emissions.ToXMLFormat(3)
+					)
+				);
+			}
+
+			if (vtpResult.NMHCEmissions != null) {
+				pollutantsElement.Add(
+					new XElement(tns + "NMHC", new XAttribute(XMLNames.Report_Results_Unit_Attr, "mg/kWh"),
+						vtpResult.NMHCEmissions.ToXMLFormat(3)
+					)
+				);
+			}
+
+			pollutantsElement.Add(
+				new XElement(tns + "PM", new XAttribute(XMLNames.Report_Results_Unit_Attr, "#/kWh"),
+					vtpResult.PMFlow.ToXMLFormat(3)
+				)
+			);
+
+			return pollutantsElement;
+		}
+
 		private XDocument GenerateReport()
 		{
 			var xsi = XNamespace.Get("http://www.w3.org/2001/XMLSchema-instance");
-- 
GitLab