diff --git a/VectoCore/VectoCore/InputData/Reader/ComponentData/FuelConsumptionMapReader.cs b/VectoCore/VectoCore/InputData/Reader/ComponentData/FuelConsumptionMapReader.cs
index 448157e3b1054f9d65f33f9d90865283f3958c5a..19690eae244a46f6e4f7c0ae845f13798d0d1775 100644
--- a/VectoCore/VectoCore/InputData/Reader/ComponentData/FuelConsumptionMapReader.cs
+++ b/VectoCore/VectoCore/InputData/Reader/ComponentData/FuelConsumptionMapReader.cs
@@ -31,6 +31,7 @@
 
 using System;
 using System.Data;
+using System.IO;
 using System.Linq;
 using TUGraz.VectoCommon.BusAuxiliaries;
 using TUGraz.VectoCommon.Exceptions;
@@ -53,6 +54,16 @@ namespace TUGraz.VectoCore.InputData.Reader.ComponentData
 			}
 		}
 
+		public static FuelConsumptionMap ReadFromStream(Stream stream)
+		{
+			try {
+				var data = VectoCSVFile.ReadStream(stream);
+				return Create(data);
+			} catch (Exception e) {
+				throw new VectoException($"Failed reading stream: {e.Message}", e);
+			}
+		}
+
 		public static FuelConsumptionMap Create(DataTable data)
 		{
 			var headerValid = HeaderIsValid(data.Columns);
diff --git a/VectoCore/VectoCore/OutputData/ModalDataContainer.cs b/VectoCore/VectoCore/OutputData/ModalDataContainer.cs
index 43c458c508f3f0fb7d0178d0d65bdf2b125997d8..0f491ee2dcef27afc38dc4a34a097323cb599542 100644
--- a/VectoCore/VectoCore/OutputData/ModalDataContainer.cs
+++ b/VectoCore/VectoCore/OutputData/ModalDataContainer.cs
@@ -206,7 +206,7 @@ namespace TUGraz.VectoCore.OutputData
 					x => x.Field<bool>(ModalResultField.ICEOn.GetName())
 						? new Point(
 							x.Field<SI>(ModalResultField.P_ice_fcmap.GetName()).Value(),
-							x.Field<SI>(GetColumnName(fuel, ModalResultField.FCFinal)).Value())
+							x.Field<SI>(GetColumnName(fuel, ModalResultField.FCWHTCc)).Value())
 						: null).Where(x => x != null && x.Y > 0),
 				out var k, out var d, out var r);
 			if (double.IsInfinity(k) || double.IsNaN(k)) {
diff --git a/VectoCore/VectoCore/OutputData/ModalDataPostprocessingCorrection.cs b/VectoCore/VectoCore/OutputData/ModalDataPostprocessingCorrection.cs
index cc2188ed1d2563ecee06d06a91fc23f72a654228..9705cc728cdb32c2bd7c452d57449028164cc8e6 100644
--- a/VectoCore/VectoCore/OutputData/ModalDataPostprocessingCorrection.cs
+++ b/VectoCore/VectoCore/OutputData/ModalDataPostprocessingCorrection.cs
@@ -5,8 +5,11 @@ using TUGraz.VectoCommon.BusAuxiliaries;
 using TUGraz.VectoCommon.Exceptions;
 using TUGraz.VectoCommon.Models;
 using TUGraz.VectoCommon.Utils;
+using TUGraz.VectoCore.Models.BusAuxiliaries;
+using TUGraz.VectoCore.Models.BusAuxiliaries.DownstreamModules.Impl.Pneumatics;
 using TUGraz.VectoCore.Models.Declaration;
 using TUGraz.VectoCore.Models.Simulation.Data;
+using TUGraz.VectoCore.Models.SimulationComponent.Data;
 
 namespace TUGraz.VectoCore.OutputData
 {
@@ -20,45 +23,13 @@ namespace TUGraz.VectoCore.OutputData
 			var r = new CorrectedModalData();
 			var duration = modData.Duration;
 			var distance = modData.Distance;
-			var essParams = runData.DriverData.EngineStopStart;
-
-			var entriesAuxICEStandstill = modData.GetValues(x => new
-			{
-				dt = x.Field<Second>(ModalResultField.simulationInterval.GetName()), 
-				P_off = x.Field<Watt>(ModalResultField.P_aux_ESS_mech_ice_off.GetName()) ?? 0.SI<Watt>(),
-				P_on = x.Field<Watt>(ModalResultField.P_aux_ESS_mech_ice_on.GetName()) ?? 0.SI<Watt>(),
-				v = x.Field<MeterPerSecond>(ModalResultField.v_act.GetName()),
-				IceOn = x.Field<bool>(ModalResultField.ICEOn.GetName())
-			}).Where(x => x.v != null && x.v.IsEqual(0) && !x.IceOn).ToList();
-			var entriesAuxICEDriving = modData.GetValues(x => new {
-				dt = x.Field<Second>(ModalResultField.simulationInterval.GetName()),
-				P_off = x.Field<Watt>(ModalResultField.P_aux_ESS_mech_ice_off.GetName()) ?? 0.SI<Watt>(),
-				P_on = x.Field<Watt>(ModalResultField.P_aux_ESS_mech_ice_on.GetName()) ?? 0.SI<Watt>(),
-				v = x.Field<MeterPerSecond>(ModalResultField.v_act.GetName()),
-				IceOn = x.Field<bool>(ModalResultField.ICEOn.GetName())
-			}).Where(x => x.v != null && !x.v.IsEqual(0) && !x.IceOn).ToList();
+			
+			SetMissingEnergyICEOFf(modData, r);
 
-			r.ICEOffTimeStandstill = entriesAuxICEStandstill.Sum(x => x.dt) ?? 0.SI<Second>();
-			r.EnergyAuxICEOffStandstill = entriesAuxICEStandstill.Sum(x => x.P_off * x.dt) ?? 0.SI<WattSecond>(); 
-			r.EnergyAuxICEOnStandstill = entriesAuxICEStandstill.Sum(x => x.P_on * x.dt) ?? 0.SI<WattSecond>();
-				
-			r.ICEOffTimeDriving = entriesAuxICEDriving.Sum(x => x.dt) ?? 0.SI<Second>();
-			r.EnergyAuxICEOffDriving = entriesAuxICEDriving.Sum(x => x.P_off * x.dt) ?? 0.SI<WattSecond>();
-			r.EnergyPowerICEOnDriving = entriesAuxICEDriving.Sum(x => x.P_on * x.dt) ?? 0.SI<WattSecond>();
+			SetWHRWork(modData, runData, r);
 
-			
-			r.WorkWHREl = modData.TimeIntegral<WattSecond>(ModalResultField.P_WHR_el_corr);
-			r.WorkWHRElMech = -r.WorkWHREl / DeclarationData.AlternaterEfficiency;
-			r.WorkWHRMech = -modData.TimeIntegral<WattSecond>(ModalResultField.P_WHR_mech_corr);
-			
 			if (runData.BusAuxiliaries != null) {
-				var workBusAuxPSCompOff = modData.EnergyPneumaticCompressorPowerOff();
-				var workBusAuxPSCompOn = modData.EnergyPneumaticCompressorAlwaysOn();
-				var airBusAuxPSON = modData.AirGeneratedAlwaysOn();
-				var deltaAir = modData.AirConsumed() - modData.AirGenerated();
-
-				var kAir = airBusAuxPSON.IsEqual(0) ? 0.SI(Unit.SI.Watt.Second.Per.Cubic.Meter) :(workBusAuxPSCompOn - workBusAuxPSCompOff) / (airBusAuxPSON - 0.SI<NormLiter>());
-				r.WorkBusAuxPSCorr = (kAir * deltaAir).Cast<WattSecond>();
+				SetBusAuxMissingPSWork(modData, runData, r);
 
 				var workBusAuxES = modData.EnergyBusAuxESConsumed() - modData.EnergyBusAuxESGenerated();
 				r.WorkBusAuxESMech = workBusAuxES /
@@ -70,73 +41,20 @@ namespace TUGraz.VectoCore.OutputData
 				r.WorkBusAuxESMech = 0.SI<WattSecond>();
 			}
 
-			var engineWasteheatSum = modData.FuelData.Aggregate(
-				0.SI<Joule>(),
-				(current, fuel) => current + modData.TotalFuelConsumption(ModalResultField.FCFinal, fuel) *
-					fuel.LowerHeatingValueVecto);
 
 			r.EnergyDCDCMissing = 0.SI<WattSecond>();
 			if (runData.BusAuxiliaries != null && runData.BusAuxiliaries.ElectricalUserInputsConfig.ConnectESToREESS) {
-				// either case C1, C2a, or C3a
-				var missingDCDCEnergy = modData.TimeIntegral<WattSecond>(ModalResultField.P_DCDC_missing);
-				if (runData.BusAuxiliaries.ElectricalUserInputsConfig.AlternatorType == AlternatorType.Smart) {
-					// case C3a
-					if (runData.ElectricMachinesData.Count != 1) {
-						throw new VectoException("exactly 1 electric machine is required. got {0} ({1})",
-							runData.ElectricMachinesData.Count,
-							string.Join(",", runData.ElectricMachinesData.Select(x => x.Item1.ToString())));
-					}
-					var emPos = runData.ElectricMachinesData.First().Item1;
-					var averageEmEfficiencyCharging = modData.ElectricMotorEfficiencyGenerate(emPos);
-					r.EnergyDCDCMissing = missingDCDCEnergy /
-										runData.BusAuxiliaries.ElectricalUserInputsConfig.DCDCEfficiency /
-										averageEmEfficiencyCharging;
-				} else {
-					// case C1, C2a
-					r.EnergyDCDCMissing = missingDCDCEnergy / DeclarationData.AlternaterEfficiency;
-				}
+				SetMissingDCDCEnergy(modData, runData, r);
 			}
 
-			r.AuxHeaterDemand = modData.AuxHeaterDemandCalc == null
-				? 0.SI<Joule>()
-				: modData.AuxHeaterDemandCalc(duration, engineWasteheatSum);
+			SetAuxHeaterDemand(modData, r, duration);
 
 			var kilogramCO2PerMeter = 0.SI<KilogramPerMeter>();
 
 			var firstFuel = true;
 			foreach (var fuel in modData.FuelData) {
-				var engFuel = runData.EngineData.Fuels.First(x => x.FuelData.Equals(fuel));
-				var f = new FuelConsumptionCorrection();
-				f.Fuel = fuel;
-				f.Distance = distance != null && distance.IsGreater(0) ? distance : null;
-				f.Duration = duration != null && duration.IsGreater(0) ? duration : null;
-
-				f.EngineLineCorrectionFactor = modData.EngineLineCorrectionFactor(fuel);
-				f.VehicleLine = modData.VehicleLineSlope(fuel);
-
-				f.FcModSum = modData.TotalFuelConsumption(ModalResultField.FCFinal, fuel);
-
-				var fcIceOnAuxStandstill = engFuel.ConsumptionMap.GetFuelConsumptionValue(
-					r.AvgAuxPowerICEOnStandstill / runData.EngineData.IdleSpeed, runData.EngineData.IdleSpeed);
-				var fcIceOnAuxDriving = engFuel.ConsumptionMap.GetFuelConsumptionValue(
-					r.AvgAuxPowerICEOnDriving / runData.EngineData.IdleSpeed, runData.EngineData.IdleSpeed);
-
-				f.FcESS_EngineStart = f.EngineLineCorrectionFactor * modData.WorkEngineStart();
-				f.FcESS_AuxStandstill_ICEOff = r.EnergyAuxICEOffStandstill * f.EngineLineCorrectionFactor *
-												essParams.UtilityFactorStandstill;
-				f.FcESS_AuxStandstill_ICEOn = fcIceOnAuxStandstill * r.ICEOffTimeStandstill *
-											(1 - essParams.UtilityFactorStandstill);
-				f.FcESS_AuxDriving_ICEOn = r.EnergyAuxICEOffDriving * f.EngineLineCorrectionFactor *
-											essParams.UtilityFactorDriving;
-				f.FcESS_AuxDriving_ICEOff = fcIceOnAuxDriving * r.ICEOffTimeDriving *
-											(1 - essParams.UtilityFactorDriving);
-				f.FcESS_DCDCMissing =
-					r.EnergyDCDCMissing * f.EngineLineCorrectionFactor * essParams.UtilityFactorStandstill;
-
-				f.FcBusAuxPs = f.EngineLineCorrectionFactor * r.WorkBusAuxPSCorr;
-				f.FcBusAuxEs =  f.EngineLineCorrectionFactor * r.WorkBusAuxESMech;
-				f.FcWHR =  f.EngineLineCorrectionFactor * r.WorkWHR;
-				f.FcAuxHtr = 0.SI<Kilogram>();
+				
+				var f = SetFuelConsumptionCorrection(modData, runData, r, fuel);
 				if (firstFuel) {
 					firstFuel = false;
 					f.FcAuxHtr = r.AuxHeaterDemand / fuel.LowerHeatingValueVecto;
@@ -146,7 +64,6 @@ namespace TUGraz.VectoCore.OutputData
 					? 0.SI<KilogramPerMeter>()
 					: f.FcFinal * fuel.CO2PerFuelWeight / distance;
 				
-				//--
 				r.FuelCorrection[fuel.FuelType] = f;
 			}
 
@@ -154,6 +71,164 @@ namespace TUGraz.VectoCore.OutputData
 			return r;
 		}
 
+		private static FuelConsumptionCorrection SetFuelConsumptionCorrection(IModalDataContainer modData, VectoRunData runData,
+			CorrectedModalData r, IFuelProperties fuel)
+		{
+			var duration = modData.Duration;
+			var distance = modData.Distance;
+			var essParams = runData.DriverData.EngineStopStart;
+			var engFuel = runData.EngineData.Fuels.First(x => x.FuelData.Equals(fuel));
+
+			var fcIceIdle = engFuel.ConsumptionMap.GetFuelConsumptionValue(
+											0.SI<NewtonMeter>(),
+											runData.EngineData.IdleSpeed) *
+										engFuel.FuelConsumptionCorrectionFactor;
+			
+
+			var engLine = modData.EngineLineCorrectionFactor(fuel);
+
+			var f = new FuelConsumptionCorrection {
+				Fuel = fuel,
+				Distance = distance != null && distance.IsGreater(0) ? distance : null,
+				Duration = duration != null && duration.IsGreater(0) ? duration : null,
+				EngineLineCorrectionFactor = engLine,
+				VehicleLine = modData.VehicleLineSlope(fuel),
+				FcModSum = modData.TotalFuelConsumption(ModalResultField.FCFinal, fuel),
+				FcESS_EngineStart = engLine * modData.WorkEngineStart(),
+
+				FcESS_AuxStandstill_ICEOff = r.EnergyAuxICEOffStandstill * engLine *
+											essParams.UtilityFactorStandstill,
+				FcESS_AuxStandstill_ICEOn = r.EnergyAuxICEOnStandstill * engLine * (1 - essParams.UtilityFactorStandstill) + 
+											fcIceIdle * r.ICEOffTimeStandstill * (1 - essParams.UtilityFactorStandstill),
+
+				FcESS_AuxDriving_ICEOff = r.EnergyAuxICEOffDriving * engLine * essParams.UtilityFactorDriving,
+				FcESS_AuxDriving_ICEOn = r.EnergyAuxICEOnDriving * engLine * (1 - essParams.UtilityFactorDriving) +
+										fcIceIdle * r.ICEOffTimeDriving * (1 - essParams.UtilityFactorDriving),
+
+				FcESS_DCDCMissing = r.EnergyDCDCMissing * engLine * essParams.UtilityFactorStandstill,
+				FcBusAuxPs = engLine * r.WorkBusAuxPSCorr,
+				FcBusAuxEs = engLine * r.WorkBusAuxESMech,
+				FcWHR = engLine * r.WorkWHR,
+				FcAuxHtr = 0.SI<Kilogram>()
+			};
+
+			return f;
+		}
+
+		private static void SetAuxHeaterDemand(IModalDataContainer modData, CorrectedModalData r, Second duration)
+		{
+			var engineWasteheatSum = modData.FuelData.Aggregate(
+				0.SI<Joule>(),
+				(current, fuel) => current + modData.TotalFuelConsumption(ModalResultField.FCFinal, fuel) *
+					fuel.LowerHeatingValueVecto);
+			r.AuxHeaterDemand = modData.AuxHeaterDemandCalc == null
+				? 0.SI<Joule>()
+				: modData.AuxHeaterDemandCalc(duration, engineWasteheatSum);
+		}
+
+		private static void SetMissingDCDCEnergy(IModalDataContainer modData, VectoRunData runData, CorrectedModalData r)
+		{
+			// either case C1, C2a, or C3a
+			var missingDCDCEnergy = modData.TimeIntegral<WattSecond>(ModalResultField.P_DCDC_missing);
+			if (runData.BusAuxiliaries.ElectricalUserInputsConfig.AlternatorType == AlternatorType.Smart) {
+				// case C3a
+				if (runData.ElectricMachinesData.Count != 1) {
+					throw new VectoException("exactly 1 electric machine is required. got {0} ({1})",
+						runData.ElectricMachinesData.Count,
+						string.Join(",", runData.ElectricMachinesData.Select(x => x.Item1.ToString())));
+				}
+
+				var emPos = runData.ElectricMachinesData.First().Item1;
+				var averageEmEfficiencyCharging = modData.ElectricMotorEfficiencyGenerate(emPos);
+				r.EnergyDCDCMissing = missingDCDCEnergy /
+									runData.BusAuxiliaries.ElectricalUserInputsConfig.DCDCEfficiency /
+									averageEmEfficiencyCharging;
+			} else {
+				// case C1, C2a
+				r.EnergyDCDCMissing = missingDCDCEnergy / DeclarationData.AlternaterEfficiency;
+			}
+		}
+
+		private static void SetBusAuxMissingPSWork(IModalDataContainer modData, VectoRunData runData, CorrectedModalData r)
+		{
+			var actuations = new Actuations() {
+				Braking = runData.BusAuxiliaries.Actuations.Braking,
+				ParkBrakeAndDoors = runData.BusAuxiliaries.Actuations.ParkBrakeAndDoors,
+				Kneeling = runData.BusAuxiliaries.Actuations.Kneeling,
+				CycleTime = modData.Duration
+			};
+			var airDemand = M03Impl.TotalAirDemandCalculation(runData.BusAuxiliaries, actuations);
+
+			var deltaAir = airDemand - modData.AirGenerated();
+
+			var nonSmartAirGen = modData.GetValues(x => new {
+				dt = x.Field<Second>(ModalResultField.simulationInterval.GetName()),
+				airConsumed = x.Field<NormLiter>(ModalResultField.Nl_busAux_PS_consumer.GetName()),
+				airGenerated = x.Field<NormLiter>(ModalResultField.Nl_busAux_PS_generated.GetName()),
+				P_compOff = x.Field<Watt>(ModalResultField.P_busAux_PS_generated_dragOnly.GetName()),
+				P_compOn = x.Field<Watt>(ModalResultField.P_busAux_PS_generated_alwaysOn.GetName()),
+				Nl_alwaysOn = x.Field<NormLiter>(ModalResultField.Nl_busAux_PS_generated_alwaysOn.GetName())
+			}).Where(x => x.airConsumed.IsEqual(x.airGenerated)).ToArray();
+
+			var workBusAuxPSCompOff = nonSmartAirGen.Sum(x => x.P_compOff * x.dt);
+			var workBusAuxPSCompOn = nonSmartAirGen.Sum(x => x.P_compOn * x.dt);
+			var airBusAuxPSON = nonSmartAirGen.Sum(x => x.Nl_alwaysOn);
+
+			var kAir = airBusAuxPSON.IsEqual(0)
+				? 0.SI(Unit.SI.Watt.Second.Per.Cubic.Meter)
+				: (workBusAuxPSCompOn - workBusAuxPSCompOff) / (airBusAuxPSON - 0.SI<NormLiter>());
+			r.WorkBusAuxPSCorr = (kAir * deltaAir).Cast<WattSecond>();
+		}
+
+		private static void SetMissingEnergyICEOFf(IModalDataContainer modData, CorrectedModalData r)
+		{
+			var entriesAuxICEStandstill = modData.GetValues(x => new {
+				dt = x.Field<Second>(ModalResultField.simulationInterval.GetName()),
+				P_off = x.Field<Watt>(ModalResultField.P_aux_ESS_mech_ice_off.GetName()) ?? 0.SI<Watt>(),
+				P_on = x.Field<Watt>(ModalResultField.P_aux_ESS_mech_ice_on.GetName()) ?? 0.SI<Watt>(),
+				v = x.Field<MeterPerSecond>(ModalResultField.v_act.GetName()),
+				IceOn = x.Field<bool>(ModalResultField.ICEOn.GetName())
+			}).Where(x => x.v != null && x.v.IsEqual(0) && !x.IceOn).ToArray();
+
+			var entriesAuxICEDriving = modData.GetValues(x => new {
+				dt = x.Field<Second>(ModalResultField.simulationInterval.GetName()),
+				P_off = x.Field<Watt>(ModalResultField.P_aux_ESS_mech_ice_off.GetName()) ?? 0.SI<Watt>(),
+				P_on = x.Field<Watt>(ModalResultField.P_aux_ESS_mech_ice_on.GetName()) ?? 0.SI<Watt>(),
+				v = x.Field<MeterPerSecond>(ModalResultField.v_act.GetName()),
+				IceOn = x.Field<bool>(ModalResultField.ICEOn.GetName())
+			}).Where(x => x.v != null && !x.v.IsEqual(0) && !x.IceOn).ToArray();
+
+			r.ICEOffTimeStandstill = entriesAuxICEStandstill.Sum(x => x.dt) ?? 0.SI<Second>();
+
+			r.EnergyAuxICEOffStandstill = entriesAuxICEStandstill.Sum(x => x.P_off * x.dt) ?? 0.SI<WattSecond>();
+			r.EnergyAuxICEOnStandstill = entriesAuxICEStandstill.Sum(x => x.P_on * x.dt) ?? 0.SI<WattSecond>();
+
+			r.ICEOffTimeDriving = entriesAuxICEDriving.Sum(x => x.dt) ?? 0.SI<Second>();
+
+			r.EnergyAuxICEOffDriving = entriesAuxICEDriving.Sum(x => x.P_off * x.dt) ?? 0.SI<WattSecond>();
+			r.EnergyAuxICEOnDriving = entriesAuxICEDriving.Sum(x => x.P_on * x.dt) ?? 0.SI<WattSecond>();
+		}
+
+		private static void SetWHRWork(IModalDataContainer modData, VectoRunData runData, CorrectedModalData r)
+		{
+			r.WorkWHREl = modData.TimeIntegral<WattSecond>(ModalResultField.P_WHR_el_corr);
+			var altEff = DeclarationData.AlternaterEfficiency;
+			if (runData.BusAuxiliaries != null && runData.BusAuxiliaries.ElectricalUserInputsConfig.AlternatorType == AlternatorType.Smart) {
+				// case C3a
+				if (runData.ElectricMachinesData.Count != 1) {
+					throw new VectoException("exactly 1 electric machine is required. got {0} ({1})",
+						runData.ElectricMachinesData.Count,
+						string.Join(",", runData.ElectricMachinesData.Select(x => x.Item1.ToString())));
+				}
+
+				var emPos = runData.ElectricMachinesData.First().Item1;
+				altEff = modData.ElectricMotorEfficiencyGenerate(emPos);
+			}
+
+			r.WorkWHRElMech = -r.WorkWHREl / altEff;
+			r.WorkWHRMech = -modData.TimeIntegral<WattSecond>(ModalResultField.P_WHR_mech_corr);
+		}
+
 		#endregion
 	}
 
@@ -214,8 +289,8 @@ namespace TUGraz.VectoCore.OutputData
 
 		public Second ICEOffTimeDriving { get; set; }
 		public WattSecond EnergyAuxICEOffDriving { get; set; }
-		public WattSecond EnergyPowerICEOnDriving { get; set; }
-		public Watt AvgAuxPowerICEOnDriving => ICEOffTimeDriving.IsEqual(0) ? 0.SI<Watt>() : EnergyPowerICEOnDriving / ICEOffTimeDriving;
+		public WattSecond EnergyAuxICEOnDriving { get; set; }
+		public Watt AvgAuxPowerICEOnDriving => ICEOffTimeDriving.IsEqual(0) ? 0.SI<Watt>() : EnergyAuxICEOnDriving / ICEOffTimeDriving;
 
 		public WattSecond EnergyDCDCMissing { get; set; }
 
diff --git a/VectoCore/VectoCoreTest/Reports/ModDataPostprocessingTest.cs b/VectoCore/VectoCoreTest/Reports/ModDataPostprocessingTest.cs
new file mode 100644
index 0000000000000000000000000000000000000000..3e2d2098657a1b8d9f7b9d00e884738da74116be
--- /dev/null
+++ b/VectoCore/VectoCoreTest/Reports/ModDataPostprocessingTest.cs
@@ -0,0 +1,381 @@
+using System;
+using System.Collections.Generic;
+using NUnit.Framework;
+using TUGraz.VectoCommon.Utils;
+using TUGraz.VectoCore.InputData.Reader.ComponentData;
+using TUGraz.VectoCore.Models.Declaration;
+using TUGraz.VectoCore.Models.Simulation.Data;
+using TUGraz.VectoCore.Models.SimulationComponent.Data;
+using TUGraz.VectoCore.Models.SimulationComponent.Data.Engine;
+using TUGraz.VectoCore.OutputData;
+using TUGraz.VectoCore.Tests.Utils;
+
+namespace TUGraz.VectoCore.Tests.Reports
+{
+	[TestFixture]
+	[Parallelizable]
+	public class ModDataPostprocessingTest
+	{
+
+		[TestCase()]
+		public void TestAuxESSStandstill_ModDataCorrection()
+		{
+			var runData = GetRunData();
+			var modData = new ModalDataContainer(runData, null, null);
+
+			var fuel = runData.EngineData.Fuels[0];
+
+			var absTime = 0.SI<Second>();
+			var rnd = new Random(210629);
+			var dt = 0.SI<Second>();
+
+			var i = 0;
+			// constant driving
+			var n_ice = 800.RPMtoRad();
+			var t_ice = 400.SI<NewtonMeter>();
+			for (; i < 100; i++) {
+				dt = (rnd.NextDouble() * 0.2 + 0.4).SI<Second>();
+
+				modData[ModalResultField.time] = absTime;
+				modData[ModalResultField.simulationInterval] = dt;
+
+				modData[ModalResultField.v_act] = 50.KMPHtoMeterPerSecond();
+				modData[ModalResultField.ICEOn] = true;
+
+				modData[ModalResultField.n_ice_avg] = n_ice;
+				modData[ModalResultField.P_ice_fcmap] = n_ice * t_ice;
+				var fc = fuel.ConsumptionMap.GetFuelConsumption(t_ice, n_ice).Value *
+						fuel.FuelConsumptionCorrectionFactor;
+				modData[ModalResultField.FCWHTCc] = fc;
+				modData[ModalResultField.FCFinal] = fc;
+
+				modData[ModalResultField.P_aux_ESS_mech_ice_off] = 0.SI<Watt>();
+				modData[ModalResultField.P_aux_ESS_mech_ice_on] = 0.SI<Watt>();
+
+				// WHR
+				modData[ModalResultField.P_WHR_el_corr] = 0.SI<Watt>();
+				modData[ModalResultField.P_WHR_mech_corr] = 0.SI<Watt>();
+				
+				modData.CommitSimulationStep();
+				absTime += dt;
+			}
+
+			// standstill
+			for (; i < 200; i++) {
+				dt = (rnd.NextDouble() * 0.2 + 0.4).SI<Second>();
+
+				modData[ModalResultField.time] = absTime;
+				modData[ModalResultField.simulationInterval] = dt;
+
+				modData[ModalResultField.v_act] = 0.KMPHtoMeterPerSecond();
+				modData[ModalResultField.ICEOn] = false;
+
+				modData[ModalResultField.n_ice_avg] = 0.RPMtoRad();
+				modData[ModalResultField.P_ice_fcmap] = 0.SI<Watt>();
+				modData[ModalResultField.FCWHTCc] = 0.SI<KilogramPerSecond>();
+				modData[ModalResultField.FCFinal] = 0.SI<KilogramPerSecond>();
+
+				modData[ModalResultField.P_aux_ESS_mech_ice_off] = 300.SI<Watt>();
+				modData[ModalResultField.P_aux_ESS_mech_ice_on] = 900.SI<Watt>();
+
+				// WHR
+				modData[ModalResultField.P_WHR_el_corr] = 0.SI<Watt>();
+				modData[ModalResultField.P_WHR_mech_corr] = 0.SI<Watt>();
+
+				modData.CommitSimulationStep();
+				absTime += dt;
+			}
+
+			// constant driving different speed
+			modData[ModalResultField.P_ice_start] = 0000.SI<Watt>();
+			n_ice = 1200.RPMtoRad();
+			for (; i < 300; i++) {
+				dt = (rnd.NextDouble() * 0.2 + 0.4).SI<Second>();
+
+				modData[ModalResultField.time] = absTime;
+				modData[ModalResultField.simulationInterval] = dt;
+
+				modData[ModalResultField.v_act] = 50.KMPHtoMeterPerSecond();
+				modData[ModalResultField.ICEOn] = true;
+
+				modData[ModalResultField.n_ice_avg] = n_ice;
+				modData[ModalResultField.P_ice_fcmap] = n_ice * t_ice;
+				var fc = fuel.ConsumptionMap.GetFuelConsumption(400.SI<NewtonMeter>(), n_ice).Value *
+					fuel.FuelConsumptionCorrectionFactor;
+				modData[ModalResultField.FCWHTCc] = fc;
+				modData[ModalResultField.FCFinal] = fc;
+
+
+				modData[ModalResultField.P_aux_ESS_mech_ice_off] = 0.SI<Watt>();
+				modData[ModalResultField.P_aux_ESS_mech_ice_on] = 0.SI<Watt>();
+
+				// WHR
+				modData[ModalResultField.P_WHR_el_corr] = 0.SI<Watt>();
+				modData[ModalResultField.P_WHR_mech_corr] = 0.SI<Watt>();
+
+				modData.CommitSimulationStep();
+				absTime += dt;
+			}
+
+			var corr = modData.CorrectedModalData as CorrectedModalData;
+
+			Assert.AreEqual(2.625452e-8, modData.EngineLineCorrectionFactor(fuel.FuelData).Value(), 1e-12);
+			Assert.AreEqual(0, corr.WorkWHREl.Value());
+			Assert.AreEqual(0, corr.WorkWHRElMech.Value());
+			Assert.AreEqual(0, corr.WorkWHRMech.Value());
+
+			Assert.AreEqual(46054.609, corr.EnergyAuxICEOnStandstill.Value(), 1e-3);
+			Assert.AreEqual(15351.536, corr.EnergyAuxICEOffStandstill.Value(), 1e-3);
+
+			Assert.AreEqual(0, corr.EnergyAuxICEOnDriving.Value(), 1e-3);
+			Assert.AreEqual(0, corr.EnergyAuxICEOffDriving.Value(), 1e-3);
+
+
+			var f = corr.FuelCorrection[fuel.FuelData.FuelType] as FuelConsumptionCorrection;
+
+			var fcEssStandStillOff = 0.0002821330689;
+			var fcEssStandStillOn = 0.0048594804294;
+			Assert.AreEqual(fcEssStandStillOff, f.FcESS_AuxStandstill_ICEOff.Value(), 1e-12);
+			Assert.AreEqual(fcEssStandStillOn, f.FcESS_AuxStandstill_ICEOn.Value(), 1e-12);
+			Assert.AreEqual(0, f.FcESS_AuxDriving_ICEOff.Value(), 1e-12);
+			Assert.AreEqual(0, f.FcESS_AuxDriving_ICEOn.Value(), 1e-12);
+
+
+			var fcModSum = 0.195725;
+			var fcIdle =
+				fuel.ConsumptionMap.GetFuelConsumption(0.SI<NewtonMeter>(), runData.EngineData.IdleSpeed).Value
+					.Value() * fuel.FuelConsumptionCorrectionFactor;
+			Assert.AreEqual(fcModSum, modData.TotalFuelConsumption(ModalResultField.FCWHTCc, fuel.FuelData).Value(), 1e-6);
+			Assert.AreEqual(fcModSum + fcEssStandStillOff + fcEssStandStillOn , f.FcEssCorr.Value(), 1e-6);
+
+		}
+
+
+
+		[TestCase()]
+		public void TestAuxESSDriving_ModDataCorrection()
+		{
+			var runData = GetRunData();
+			var modData = new ModalDataContainer(runData, null, null);
+
+			var fuel = runData.EngineData.Fuels[0];
+
+			var absTime = 0.SI<Second>();
+			var rnd = new Random(210629);
+			var dt = 0.SI<Second>();
+
+			var i = 0;
+			// constant driving
+			var n_ice = 800.RPMtoRad();
+			var t_ice = 400.SI<NewtonMeter>();
+			for (; i < 100; i++) {
+				dt = (rnd.NextDouble() * 0.2 + 0.4).SI<Second>();
+
+				modData[ModalResultField.time] = absTime;
+				modData[ModalResultField.simulationInterval] = dt;
+
+				modData[ModalResultField.v_act] = 50.KMPHtoMeterPerSecond();
+				modData[ModalResultField.ICEOn] = true;
+
+				modData[ModalResultField.n_ice_avg] = n_ice;
+				modData[ModalResultField.P_ice_fcmap] = n_ice * t_ice;
+				var fc = fuel.ConsumptionMap.GetFuelConsumption(t_ice, n_ice).Value *
+						fuel.FuelConsumptionCorrectionFactor;
+				modData[ModalResultField.FCWHTCc] = fc;
+				modData[ModalResultField.FCFinal] = fc;
+
+				modData[ModalResultField.P_aux_ESS_mech_ice_off] = 0.SI<Watt>();
+				modData[ModalResultField.P_aux_ESS_mech_ice_on] = 0.SI<Watt>();
+
+				// WHR
+				modData[ModalResultField.P_WHR_el_corr] = 0.SI<Watt>();
+				modData[ModalResultField.P_WHR_mech_corr] = 0.SI<Watt>();
+
+				modData.CommitSimulationStep();
+				absTime += dt;
+			}
+
+			// driving ICE Off
+			for (; i < 200; i++) {
+				dt = (rnd.NextDouble() * 0.2 + 0.4).SI<Second>();
+
+				modData[ModalResultField.time] = absTime;
+				modData[ModalResultField.simulationInterval] = dt;
+
+				modData[ModalResultField.v_act] = 50.KMPHtoMeterPerSecond();
+				modData[ModalResultField.ICEOn] = false;
+
+				modData[ModalResultField.n_ice_avg] = 0.RPMtoRad();
+				modData[ModalResultField.P_ice_fcmap] = 0.SI<Watt>();
+				modData[ModalResultField.FCWHTCc] = 0.SI<KilogramPerSecond>();
+				modData[ModalResultField.FCFinal] = 0.SI<KilogramPerSecond>();
+
+				modData[ModalResultField.P_aux_ESS_mech_ice_off] = 300.SI<Watt>();
+				modData[ModalResultField.P_aux_ESS_mech_ice_on] = 900.SI<Watt>();
+
+				// WHR
+				modData[ModalResultField.P_WHR_el_corr] = 0.SI<Watt>();
+				modData[ModalResultField.P_WHR_mech_corr] = 0.SI<Watt>();
+
+				modData.CommitSimulationStep();
+				absTime += dt;
+			}
+
+			// constant driving different speed
+			modData[ModalResultField.P_ice_start] = 0000.SI<Watt>();
+			n_ice = 1200.RPMtoRad();
+			for (; i < 300; i++) {
+				dt = (rnd.NextDouble() * 0.2 + 0.4).SI<Second>();
+
+				modData[ModalResultField.time] = absTime;
+				modData[ModalResultField.simulationInterval] = dt;
+
+				modData[ModalResultField.v_act] = 50.KMPHtoMeterPerSecond();
+				modData[ModalResultField.ICEOn] = true;
+
+				modData[ModalResultField.n_ice_avg] = n_ice;
+				modData[ModalResultField.P_ice_fcmap] = n_ice * t_ice;
+				var fc = fuel.ConsumptionMap.GetFuelConsumption(400.SI<NewtonMeter>(), n_ice).Value *
+					fuel.FuelConsumptionCorrectionFactor;
+				modData[ModalResultField.FCWHTCc] = fc;
+				modData[ModalResultField.FCFinal] = fc;
+
+
+				modData[ModalResultField.P_aux_ESS_mech_ice_off] = 0.SI<Watt>();
+				modData[ModalResultField.P_aux_ESS_mech_ice_on] = 0.SI<Watt>();
+
+				// WHR
+				modData[ModalResultField.P_WHR_el_corr] = 0.SI<Watt>();
+				modData[ModalResultField.P_WHR_mech_corr] = 0.SI<Watt>();
+
+				modData.CommitSimulationStep();
+				absTime += dt;
+			}
+
+			var corr = modData.CorrectedModalData as CorrectedModalData;
+
+			Assert.AreEqual(2.625452e-8, modData.EngineLineCorrectionFactor(fuel.FuelData).Value(), 1e-12);
+			Assert.AreEqual(0, corr.WorkWHREl.Value());
+			Assert.AreEqual(0, corr.WorkWHRElMech.Value());
+			Assert.AreEqual(0, corr.WorkWHRMech.Value());
+
+			Assert.AreEqual(0, corr.EnergyAuxICEOnStandstill.Value(), 1e-3);
+			Assert.AreEqual(0, corr.EnergyAuxICEOffStandstill.Value(), 1e-3);
+
+			Assert.AreEqual(46054.609, corr.EnergyAuxICEOnDriving.Value(), 1e-3);
+			Assert.AreEqual(15351.536, corr.EnergyAuxICEOffDriving.Value(), 1e-3);
+
+			var f = corr.FuelCorrection[fuel.FuelData.FuelType] as FuelConsumptionCorrection;
+
+			var fcEssDrivingOff = 0.0003224377930;
+			var fcEssDrivingOn = 0.0032396536196;
+			Assert.AreEqual(0, f.FcESS_AuxStandstill_ICEOff.Value(), 1e-12);
+			Assert.AreEqual(0, f.FcESS_AuxStandstill_ICEOn.Value(), 1e-12);
+			Assert.AreEqual(fcEssDrivingOff, f.FcESS_AuxDriving_ICEOff.Value(), 1e-12);
+			Assert.AreEqual(fcEssDrivingOn, f.FcESS_AuxDriving_ICEOn.Value(), 1e-12);
+
+			var fcModSum = 0.195725;
+			var fcIdle =
+				fuel.ConsumptionMap.GetFuelConsumption(0.SI<NewtonMeter>(), runData.EngineData.IdleSpeed).Value
+					.Value() * fuel.FuelConsumptionCorrectionFactor;
+			Assert.AreEqual(fcModSum, modData.TotalFuelConsumption(ModalResultField.FCWHTCc, fuel.FuelData).Value(), 1e-6);
+			Assert.AreEqual(fcModSum + fcEssDrivingOff + fcEssDrivingOn, f.FcEssCorr.Value(), 1e-6);
+		}
+
+		[TestCase()]
+		public void TestBusAuxPSESSStandstill_ModDataCorrection()
+		{
+			Assert.Fail();
+
+		}
+
+		[TestCase()]
+		public void TestBusAuxPSESSDriving_ModDataCorrection()
+		{
+			Assert.Fail();
+
+		}
+
+		[TestCase()]
+		public void TestBusAuxSmartES_ModDataCorrection()
+		{
+			Assert.Fail();
+
+		}
+
+		[TestCase()]
+		public void TestBusAuxDCDCMissing_ModDataCorrection()
+		{
+			Assert.Fail();
+
+		}
+
+		[TestCase()]
+		public void TestBusAuxSmartPS_ModDataCorrection()
+		{
+			Assert.Fail();
+
+		}
+
+		[TestCase()]
+		public void TestBusAuxPSDemand_ModDataCorrection()
+		{
+			Assert.Fail();
+
+		}
+
+		[TestCase()]
+		public void TestWHRElAlternator_ModDataCorrection()
+		{
+			Assert.Fail();
+
+		}
+
+		[TestCase()]
+		public void TestWHRElNoAlternator_ModDataCorrection()
+		{
+			Assert.Fail();
+
+		}
+
+		[TestCase]
+		public void TestWHRMech_ModDataCorrection()
+		{
+			Assert.Fail();
+
+		}
+
+
+		private VectoRunData GetRunData()
+		{
+			var fcMapHeader = "engine speed [rpm],torque [Nm],fuel consumption [g/h]";
+			var fcMapEntries = new[] {
+				"600,-107,0",
+				"600,0,1042",
+				"600,916,10963",
+				"2000,-215,0",
+				"2000,0,6519",
+				"2000,966,40437"
+			};
+
+			return new VectoRunData() {
+				DriverData = new DriverData() {
+					EngineStopStart = new DriverData.EngineStopStartData() {
+						UtilityFactorDriving = 0.8,
+						UtilityFactorStandstill = 0.7
+					}
+				},
+				EngineData = new CombustionEngineData() {
+					IdleSpeed = 600.RPMtoRad(),
+					Fuels = new List<CombustionEngineFuelData>() {
+						new CombustionEngineFuelData() {
+							FuelData = FuelData.Diesel,
+							FuelConsumptionCorrectionFactor = 1.012,
+							ConsumptionMap = FuelConsumptionMapReader.ReadFromStream(InputDataHelper.InputDataAsStream(fcMapHeader, fcMapEntries))
+						}
+					}
+				}
+			};
+		}
+	}
+}
\ No newline at end of file
diff --git a/VectoCore/VectoCoreTest/VectoCoreTest.csproj b/VectoCore/VectoCoreTest/VectoCoreTest.csproj
index c60edb48e0329015705afc477f96d2552f1d7097..9b0fcf185eee37579b8f1ae43d074aab7190d46f 100644
--- a/VectoCore/VectoCoreTest/VectoCoreTest.csproj
+++ b/VectoCore/VectoCoreTest/VectoCoreTest.csproj
@@ -153,6 +153,7 @@
     <Compile Include="Models\SimulationComponent\EngineFanAuxTest.cs" />
     <Compile Include="Models\SimulationComponent\GearboxShiftLossesTest.cs" />
     <Compile Include="Models\SimulationComponent\SuperCapTest.cs" />
+    <Compile Include="Reports\ModDataPostprocessingTest.cs" />
     <Compile Include="Utils\CompletedVIF.cs" />
     <Compile Include="Utils\MockElectricConsumer.cs" />
     <Compile Include="Utils\MockHybridControl.cs" />