From 065e2536ec62b8eb63a266610ec5debd9757a8fa Mon Sep 17 00:00:00 2001
From: Markus Quaritsch <markus.quaritsch@tugraz.at>
Date: Fri, 4 May 2018 14:12:42 +0200
Subject: [PATCH] adding validation of VTP input data (cycle), adding testcases
 for VTP cycle validation, refactoring VTP cycle constructor (remove unused
 parameters), add info to Fan technologies if only electrical

---
 .../Utils/SIConvertExtensionMethods.cs        |   5 +
 .../Models/Declaration/DeclarationData.cs     |  20 +
 VectoCore/VectoCore/Models/Declaration/Fan.cs |  19 +-
 .../Simulation/Impl/PowertrainBuilder.cs      |   5 +-
 .../Simulation/Impl/SimulatorFactory.cs       |   2 +-
 .../Simulation/Impl/VehicleContainer.cs       |  15 +-
 .../Data/Gearbox/TransmissionLossMap.cs       | 262 ++++-----
 .../Impl/BusAuxiliariesAdapter.cs             | 502 ++++++++---------
 .../Impl/CombustionEngine.cs                  |   2 +-
 .../SimulationComponent/Impl/VTPCycle.cs      | 115 +++-
 .../Resources/Declaration/VAUX/Fan-Tech.csv   |  24 +-
 .../VTPCycleValidationTest.cs                 | 515 ++++++++++++++++++
 ...or_4x2_vehicle-class-5_Generic vehicle.xml |  16 +-
 .../VectoCoreTest/Utils/InputDataHelper.cs    |  38 +-
 VectoCore/VectoCoreTest/VectoCoreTest.csproj  |   1 +
 15 files changed, 1112 insertions(+), 429 deletions(-)
 create mode 100644 VectoCore/VectoCoreTest/Models/SimulationComponent/VTPCycleValidationTest.cs

diff --git a/VectoCommon/VectoCommon/Utils/SIConvertExtensionMethods.cs b/VectoCommon/VectoCommon/Utils/SIConvertExtensionMethods.cs
index 575608ab10..29d55faca6 100644
--- a/VectoCommon/VectoCommon/Utils/SIConvertExtensionMethods.cs
+++ b/VectoCommon/VectoCommon/Utils/SIConvertExtensionMethods.cs
@@ -206,6 +206,11 @@ namespace TUGraz.VectoCommon.Utils
 		{
 			return new ConvertedSI(value.Value() / Kilo / Kilo, "MJ/kg");
 		}
+
+		public static ConvertedSI ConvertToMinutes(this Second sec)
+		{
+			return new ConvertedSI(sec.Value() / 60.0, "min");
+		}
 	}
 }
 
diff --git a/VectoCore/VectoCore/Models/Declaration/DeclarationData.cs b/VectoCore/VectoCore/Models/Declaration/DeclarationData.cs
index f8888def8e..44cda17332 100644
--- a/VectoCore/VectoCore/Models/Declaration/DeclarationData.cs
+++ b/VectoCore/VectoCore/Models/Declaration/DeclarationData.cs
@@ -507,6 +507,26 @@ namespace TUGraz.VectoCore.Models.Declaration
 
 			public const MissionType SelectedMission = MissionType.LongHaul;
 			public const LoadingType SelectedLoading = LoadingType.ReferenceLoad;
+
+			// verification of input data
+
+			public const double WheelSpeedDifferenceFactor = 1.4;
+			public const double WheelTorqueDifferenceFactor = 3;
+
+			public static readonly PerSecond WheelSpeedZeroTolerance = 0.1.RPMtoRad();
+			public static readonly PerSecond MaxWheelSpeedDifferenceStandstill = 1.RPMtoRad();
+
+			public static readonly NewtonMeter WheelTorqueZeroTolerance = 10.SI<NewtonMeter>();
+			public static readonly NewtonMeter MaxWheelTorqueZeroDifference = 100.SI<NewtonMeter>();
+
+			public static readonly PerSecond MinFanSpeed = 20.RPMtoRad();
+			public static readonly PerSecond MaxFanSpeed = 4000.RPMtoRad();
+
+			public static readonly Second SamplingInterval = 0.5.SI<Second>();
+
+			public static readonly KilogramPerSecond LowerFCThreshold = 180.SI(Unit.SI.Gramm.Per.Hour).Cast<KilogramPerSecond>();
+			public static readonly KilogramPerSecond UpperFCThreshold = 600.SI(Unit.SI.Gramm.Per.Hour).Cast<KilogramPerSecond>();
+			public static readonly Second FCAccumulationWindow = 10.SI(Unit.SI.Minute).Cast<Second>();
 		}
 	}
 }
\ No newline at end of file
diff --git a/VectoCore/VectoCore/Models/Declaration/Fan.cs b/VectoCore/VectoCore/Models/Declaration/Fan.cs
index 3a576c5d04..0f161d59cb 100644
--- a/VectoCore/VectoCore/Models/Declaration/Fan.cs
+++ b/VectoCore/VectoCore/Models/Declaration/Fan.cs
@@ -30,6 +30,7 @@
 */
 
 using System;
+using System.Collections.Generic;
 using System.Data;
 using System.Linq;
 using TUGraz.VectoCommon.Utils;
@@ -39,6 +40,8 @@ namespace TUGraz.VectoCore.Models.Declaration
 {
 	public sealed class Fan : LookupData<MissionType, string, AuxDemandEntry>, IDeclarationAuxiliaryTable
 	{
+		private readonly List<string> FullyElectricFanTechnologies = new List<string>();
+
 		protected override string ResourceId
 		{
 			get { return DeclarationData.DeclarationDataResourcePrefix + ".VAUX.Fan-Tech.csv"; }
@@ -53,10 +56,15 @@ namespace TUGraz.VectoCore.Models.Declaration
 		{
 			foreach (DataRow row in table.Rows) {
 				var name = row.Field<string>("technology");
-
+				var electric = row.ParseBoolean("fullyelectric");
+				if (electric) {
+					FullyElectricFanTechnologies.Add(name);
+				}
 				foreach (DataColumn col in table.Columns) {
-					if (col.Caption != "technology") {
-						Data[Tuple.Create(col.Caption.ParseEnum<MissionType>(), name)] = new AuxDemandEntry(){PowerDemand = row.ParseDouble(col).SI<Watt>()};
+					if (col.Caption != "technology" && col.Caption != "fullyelectric") {
+						Data[Tuple.Create(col.Caption.ParseEnum<MissionType>(), name)] = new AuxDemandEntry {
+							PowerDemand = row.ParseDouble(col).SI<Watt>(),
+						};
 					}
 				}
 			}
@@ -70,6 +78,11 @@ namespace TUGraz.VectoCore.Models.Declaration
 			return base.Lookup(mission, technology);
 		}
 
+		public string[] FullyElectricTechnologies()
+		{
+			return FullyElectricFanTechnologies.ToArray();
+		}
+
 		public string[] GetTechnologies()
 		{
 			return Data.Keys.Select(x => x.Item2).Distinct().ToArray();
diff --git a/VectoCore/VectoCore/Models/Simulation/Impl/PowertrainBuilder.cs b/VectoCore/VectoCore/Models/Simulation/Impl/PowertrainBuilder.cs
index ce9a92b600..9ce663527c 100644
--- a/VectoCore/VectoCore/Models/Simulation/Impl/PowertrainBuilder.cs
+++ b/VectoCore/VectoCore/Models/Simulation/Impl/PowertrainBuilder.cs
@@ -133,12 +133,11 @@ namespace TUGraz.VectoCore.Models.Simulation.Impl
                 throw new VectoException("CycleType must be VTP.");
             }
 
-            var container = new VehicleContainer(ExecutionMode.Engineering, _modData, _sumWriter) { RunData = data };
+            var container = new VehicleContainer(data.ExecutionMode, _modData, _sumWriter) { RunData = data };
             var gearbox = new VTPGearbox(container, data);
 
             // VTPCycle --> AxleGear --> Clutch --> Engine <-- Aux
-            var powertrain = new VTPCycle(container, data.Cycle, data.AxleGearData.AxleGear.Ratio, data.VehicleData,
-                    gearbox.ModelData.Gears.ToDictionary(g => g.Key, g => g.Value.Ratio))
+            var powertrain = new VTPCycle(container, data.Cycle)
                 .AddComponent(new AxleGear(container, data.AxleGearData))
                 .AddComponent(data.AngledriveData != null ? new Angledrive(container, data.AngledriveData) : null)
                 .AddComponent(gearbox, data.Retarder, container)
diff --git a/VectoCore/VectoCore/Models/Simulation/Impl/SimulatorFactory.cs b/VectoCore/VectoCore/Models/Simulation/Impl/SimulatorFactory.cs
index d799958c7e..2d3520853d 100644
--- a/VectoCore/VectoCore/Models/Simulation/Impl/SimulatorFactory.cs
+++ b/VectoCore/VectoCore/Models/Simulation/Impl/SimulatorFactory.cs
@@ -124,7 +124,7 @@ namespace TUGraz.VectoCore.Models.Simulation.Impl
 
 		public bool Validate { get; set; }
 
-		public IVectoRunDataFactory DataReader { get; private set; }
+		protected internal IVectoRunDataFactory DataReader { get; private set; }
 
 		public SummaryDataContainer SumData { get; set; }
 
diff --git a/VectoCore/VectoCore/Models/Simulation/Impl/VehicleContainer.cs b/VectoCore/VectoCore/Models/Simulation/Impl/VehicleContainer.cs
index 57f4a2e5ea..ee2d540538 100644
--- a/VectoCore/VectoCore/Models/Simulation/Impl/VehicleContainer.cs
+++ b/VectoCore/VectoCore/Models/Simulation/Impl/VehicleContainer.cs
@@ -36,6 +36,7 @@ using System.Linq;
 using TUGraz.VectoCommon.Exceptions;
 using TUGraz.VectoCommon.Models;
 using TUGraz.VectoCommon.Utils;
+using TUGraz.VectoCore.InputData.Reader.Impl;
 using TUGraz.VectoCore.Models.Connector.Ports;
 using TUGraz.VectoCore.Models.Simulation.Data;
 using TUGraz.VectoCore.Models.Simulation.DataBus;
@@ -351,11 +352,15 @@ namespace TUGraz.VectoCore.Models.Simulation.Impl
 		public Meter Distance
 		{
 			get {
-				if (MilageCounter == null) {
-					Log.Warn("No MileageCounter in VehicleContainer. Distance cannot be measured.");
+				if (RunData.SimulationType != SimulationType.DistanceCycle) {
 					return 0.SI<Meter>();
 				}
-				return MilageCounter.Distance;
+				if (MilageCounter != null) {
+					return MilageCounter.Distance;
+				}
+
+				Log.Warn("No MileageCounter in VehicleContainer. Distance cannot be measured.");
+				return 0.SI<Meter>();
 			}
 		}
 
@@ -411,7 +416,9 @@ namespace TUGraz.VectoCore.Models.Simulation.Impl
 		}
 
 		public VectoRunData RunData { get; set; }
-		public ExecutionMode ExecutionMode { get; set; }
+		public ExecutionMode ExecutionMode { get; }
+
+
 
 		public CycleData CycleData
 		{
diff --git a/VectoCore/VectoCore/Models/SimulationComponent/Data/Gearbox/TransmissionLossMap.cs b/VectoCore/VectoCore/Models/SimulationComponent/Data/Gearbox/TransmissionLossMap.cs
index ccc17e5f94..ea99a0124c 100644
--- a/VectoCore/VectoCore/Models/SimulationComponent/Data/Gearbox/TransmissionLossMap.cs
+++ b/VectoCore/VectoCore/Models/SimulationComponent/Data/Gearbox/TransmissionLossMap.cs
@@ -29,135 +29,135 @@
 *   Martin Rexeis, rexeis@ivt.tugraz.at, IVT, Graz University of Technology
 */
 
-using System.Collections.Generic;
-using System.ComponentModel.DataAnnotations;
-using System.Diagnostics;
-using TUGraz.VectoCommon.Exceptions;
-using TUGraz.VectoCommon.Models;
-using TUGraz.VectoCommon.Utils;
-using TUGraz.VectoCore.Configuration;
-using TUGraz.VectoCore.Utils;
-
-namespace TUGraz.VectoCore.Models.SimulationComponent.Data.Gearbox
-{
-	public sealed class TransmissionLossMap : LoggingObject
-	{
-		[ValidateObject] private readonly IReadOnlyList<GearLossMapEntry> _entries;
-
-		private readonly double _ratio;
-
-		/// <summary>
-		/// The Loss map. [X=Output EngineSpeed, Y=Output Torque] => Z=Torque Loss
-		/// </summary>
-		private readonly DelaunayMap _lossMap;
-
-		/// <summary>
-		/// The inverted loss map for range sanity checks. [X=Input EngineSpeed, Y=Input Torque] => Z=Output Torque
-		/// </summary>
-		private readonly DelaunayMap _invertedLossMap;
-
-		public string GearName { get; private set; }
-
-		public TransmissionLossMap(IReadOnlyList<GearLossMapEntry> entries, double gearRatio, string gearName)
-		{
-			GearName = gearName;
-			_ratio = gearRatio;
-			_entries = entries;
-			_lossMap = new DelaunayMap("TransmissionLossMap " + GearName);
-			_invertedLossMap = new DelaunayMap("TransmissionLossMapInv. " + GearName);
-			foreach (var entry in _entries) {
-				_lossMap.AddPoint(entry.InputSpeed.Value(), (entry.InputTorque - entry.TorqueLoss).Value(), entry.TorqueLoss.Value());
-				_invertedLossMap.AddPoint(entry.InputSpeed.Value(), entry.InputTorque.Value(), entry.TorqueLoss.Value());
-			}
-
-			_lossMap.Triangulate();
-			_invertedLossMap.Triangulate();
-		}
-
-		/// <summary>
-		///	Computes the torque loss (input side) given by the output gearbox speed and the output-torque.
-		/// </summary>
-		/// <param name="outAngularVelocity">Angular speed at output side.</param>
-		/// <param name="outTorque">Torque at output side (as requested by the previous componend towards the wheels).</param>
-		/// <returns>Torque loss as seen on input side (towards the engine).</returns>
-		public LossMapResult GetTorqueLoss(PerSecond outAngularVelocity, NewtonMeter outTorque)
-		{
-			var result = new LossMapResult();
-			var torqueLoss = _lossMap.Interpolate(outAngularVelocity.Value() * _ratio, outTorque.Value() / _ratio);
-
-			if (!torqueLoss.HasValue) {
-				torqueLoss = _lossMap.Extrapolate(outAngularVelocity.Value() * _ratio, outTorque.Value() / _ratio);
-				result.Extrapolated = true;
-			}
-
-			result.Value = torqueLoss.Value.SI<NewtonMeter>();
-
-			Log.Debug("GearboxLoss {0}: {1}, outAngularVelocity: {2}, outTorque: {3}", GearName, torqueLoss,
-				outAngularVelocity, outTorque);
-			return result;
-		}
-
-		[DebuggerDisplay("{Value} (extrapolated: {Extrapolated})")]
-		public class LossMapResult
-		{
-			public bool Extrapolated;
-			public NewtonMeter Value;
-		}
-
-		///  <summary>
-		/// 	Computes the OUTPUT torque given by the input engineSpeed and the input torque.
-		///  </summary>
-		///  <param name="inAngularVelocity">Angular speed at input side.</param>
-		///  <param name="inTorque">Torque at input side.</param>
-		/// <param name="allowExtrapolation"></param>
-		/// <returns>Torque needed at output side (towards the wheels).</returns>
-		public NewtonMeter GetOutTorque(PerSecond inAngularVelocity, NewtonMeter inTorque, bool allowExtrapolation = false)
-		{
-			var torqueLoss = _invertedLossMap.Interpolate(inAngularVelocity.Value(), inTorque.Value());
-			if (torqueLoss.HasValue) {
-				return (inTorque - torqueLoss.Value.SI<NewtonMeter>()) / _ratio;
-			}
-
-			if (allowExtrapolation) {
-				torqueLoss = _invertedLossMap.Extrapolate(inAngularVelocity.Value(), inTorque.Value());
-				return (inTorque - torqueLoss.Value.SI<NewtonMeter>()) / _ratio;
-			}
-
-			throw new VectoException("TransmissionLossMap {0}: Interpolation failed. inTorque: {1}, inAngularVelocity: {2}",
-				GearName, inTorque,
-				inAngularVelocity.AsRPM);
-		}
-
-		public GearLossMapEntry this[int i]
-		{
-			get { return _entries[i]; }
-		}
-
-#if DEBUG
-		public void DrawGraph()
-		{
-			_lossMap.DrawGraph();
-		}
-#endif
-
-		[DebuggerDisplay("GearLossMapEntry({InputSpeed}, {InputTorque}, {TorqueLoss})")]
-		public class GearLossMapEntry
-		{
-			[Required, SIRange(0, 10000 * Constants.RPMToRad)]
-			public PerSecond InputSpeed { get; private set; }
-
-			[Required, SIRange(-100000, 100000)]
-			public NewtonMeter InputTorque { get; private set; }
-
-			[Required, SIRange(0, 100000)]
-			public NewtonMeter TorqueLoss { get; private set; }
-
-			public GearLossMapEntry(PerSecond inputSpeed, NewtonMeter inputTorque, NewtonMeter torqueLoss)
-			{
-				InputSpeed = inputSpeed;
-				InputTorque = inputTorque;
-				TorqueLoss = torqueLoss;
-			}
-		}
-	}
+using System.Collections.Generic;
+using System.ComponentModel.DataAnnotations;
+using System.Diagnostics;
+using TUGraz.VectoCommon.Exceptions;
+using TUGraz.VectoCommon.Models;
+using TUGraz.VectoCommon.Utils;
+using TUGraz.VectoCore.Configuration;
+using TUGraz.VectoCore.Utils;
+
+namespace TUGraz.VectoCore.Models.SimulationComponent.Data.Gearbox
+{
+	public sealed class TransmissionLossMap : LoggingObject
+	{
+		[ValidateObject] private readonly IReadOnlyList<GearLossMapEntry> _entries;
+
+		private readonly double _ratio;
+
+		/// <summary>
+		/// The Loss map. [X=Output EngineSpeed, Y=Output Torque] => Z=Torque Loss
+		/// </summary>
+		private readonly DelaunayMap _lossMap;
+
+		/// <summary>
+		/// The inverted loss map for range sanity checks. [X=Input EngineSpeed, Y=Input Torque] => Z=Output Torque
+		/// </summary>
+		private readonly DelaunayMap _invertedLossMap;
+
+		public string GearName { get; private set; }
+
+		public TransmissionLossMap(IReadOnlyList<GearLossMapEntry> entries, double gearRatio, string gearName)
+		{
+			GearName = gearName;
+			_ratio = gearRatio;
+			_entries = entries;
+			_lossMap = new DelaunayMap("TransmissionLossMap " + GearName);
+			_invertedLossMap = new DelaunayMap("TransmissionLossMapInv. " + GearName);
+			foreach (var entry in _entries) {
+				_lossMap.AddPoint(entry.InputSpeed.Value(), (entry.InputTorque - entry.TorqueLoss).Value(), entry.TorqueLoss.Value());
+				_invertedLossMap.AddPoint(entry.InputSpeed.Value(), entry.InputTorque.Value(), entry.TorqueLoss.Value());
+			}
+
+			_lossMap.Triangulate();
+			_invertedLossMap.Triangulate();
+		}
+
+		/// <summary>
+		///	Computes the torque loss (input side) given by the output gearbox speed and the output-torque.
+		/// </summary>
+		/// <param name="outAngularVelocity">Angular speed at output side.</param>
+		/// <param name="outTorque">Torque at output side (as requested by the previous componend towards the wheels).</param>
+		/// <returns>Torque loss as seen on input side (towards the engine).</returns>
+		public LossMapResult GetTorqueLoss(PerSecond outAngularVelocity, NewtonMeter outTorque)
+		{
+			var result = new LossMapResult();
+			var torqueLoss = _lossMap.Interpolate(outAngularVelocity.Value() * _ratio, outTorque.Value() / _ratio);
+
+			if (!torqueLoss.HasValue) {
+				torqueLoss = _lossMap.Extrapolate(outAngularVelocity.Value() * _ratio, outTorque.Value() / _ratio);
+				result.Extrapolated = true;
+			}
+
+			result.Value = torqueLoss.Value.SI<NewtonMeter>();
+
+			Log.Debug("GearboxLoss {0}: {1}, outAngularVelocity: {2}, outTorque: {3}", GearName, torqueLoss,
+				outAngularVelocity, outTorque);
+			return result;
+		}
+
+		[DebuggerDisplay("{Value} (extrapolated: {Extrapolated})")]
+		public class LossMapResult
+		{
+			public bool Extrapolated;
+			public NewtonMeter Value;
+		}
+
+		///  <summary>
+		/// 	Computes the OUTPUT torque given by the input engineSpeed and the input torque.
+		///  </summary>
+		///  <param name="inAngularVelocity">Angular speed at input side.</param>
+		///  <param name="inTorque">Torque at input side.</param>
+		/// <param name="allowExtrapolation"></param>
+		/// <returns>Torque needed at output side (towards the wheels).</returns>
+		public NewtonMeter GetOutTorque(PerSecond inAngularVelocity, NewtonMeter inTorque, bool allowExtrapolation = false)
+		{
+			var torqueLoss = _invertedLossMap.Interpolate(inAngularVelocity.Value(), inTorque.Value());
+			if (torqueLoss.HasValue) {
+				return (inTorque - torqueLoss.Value.SI<NewtonMeter>()) / _ratio;
+			}
+
+			if (allowExtrapolation) {
+				torqueLoss = _invertedLossMap.Extrapolate(inAngularVelocity.Value(), inTorque.Value());
+				return (inTorque - torqueLoss.Value.SI<NewtonMeter>()) / _ratio;
+			}
+
+			throw new VectoException("TransmissionLossMap {0}: Interpolation failed. inTorque: {1}, inAngularVelocity: {2}",
+				GearName, inTorque,
+				inAngularVelocity.AsRPM);
+		}
+
+		public GearLossMapEntry this[int i]
+		{
+			get { return _entries[i]; }
+		}
+
+#if DEBUG
+		public void DrawGraph()
+		{
+			_lossMap.DrawGraph();
+		}
+#endif
+
+		[DebuggerDisplay("GearLossMapEntry({InputSpeed}, {InputTorque}, {TorqueLoss})")]
+		public class GearLossMapEntry
+		{
+			[Required, SIRange(0, 10000 * Constants.RPMToRad)]
+			public PerSecond InputSpeed { get; private set; }
+
+			[Required, SIRange(-100000, 100000)]
+			public NewtonMeter InputTorque { get; private set; }
+
+			[Required, SIRange(0, 100000)]
+			public NewtonMeter TorqueLoss { get; private set; }
+
+			public GearLossMapEntry(PerSecond inputSpeed, NewtonMeter inputTorque, NewtonMeter torqueLoss)
+			{
+				InputSpeed = inputSpeed;
+				InputTorque = inputTorque;
+				TorqueLoss = torqueLoss;
+			}
+		}
+	}
 }
\ No newline at end of file
diff --git a/VectoCore/VectoCore/Models/SimulationComponent/Impl/BusAuxiliariesAdapter.cs b/VectoCore/VectoCore/Models/SimulationComponent/Impl/BusAuxiliariesAdapter.cs
index 4bdde41d73..af42da7f9b 100644
--- a/VectoCore/VectoCore/Models/SimulationComponent/Impl/BusAuxiliariesAdapter.cs
+++ b/VectoCore/VectoCore/Models/SimulationComponent/Impl/BusAuxiliariesAdapter.cs
@@ -29,255 +29,255 @@
 *   Martin Rexeis, rexeis@ivt.tugraz.at, IVT, Graz University of Technology
 */
 
-using System;
-using System.IO;
-using TUGraz.VectoCommon.Models;
-using TUGraz.VectoCommon.Utils;
-using TUGraz.VectoCore.Models.Declaration;
-using TUGraz.VectoCore.Models.Simulation.Data;
-using TUGraz.VectoCore.Models.Simulation.DataBus;
-using TUGraz.VectoCore.Models.SimulationComponent.Data.Engine;
-using TUGraz.VectoCore.OutputData;
-using VectoAuxiliaries;
-using VectoAuxiliaries.Pneumatics;
-
-namespace TUGraz.VectoCore.Models.SimulationComponent.Impl
-{
-	public class BusAuxiliariesAdapter : LoggingObject, IAuxInProvider, IAuxPort
-	{
-		protected readonly IDataBus DataBus;
-		protected internal BusAuxState CurrentState;
-		protected internal BusAuxState PreviousState;
-
-		protected internal readonly IAuxPort AdditionalAux;
-
-		protected IAdvancedAuxiliaries Auxiliaries;
-		private readonly FuelConsumptionAdapter _fcMapAdapter;
-
-		public BusAuxiliariesAdapter(IDataBus container, string aauxFile, string cycleName, Kilogram vehicleWeight,
-			FuelConsumptionMap fcMap, PerSecond engineIdleSpeed, IAuxPort additionalAux = null)
-		{
-			//	mAAUX_Global.advancedAuxModel.Signals.DeclarationMode = Cfg.DeclMode
-			//	mAAUX_Global.advancedAuxModel.Signals.WHTC = Declaration.WHTCcorrFactor
-			CurrentState = new BusAuxState();
-			PreviousState = new BusAuxState { AngularSpeed = engineIdleSpeed };
-
-			AdditionalAux = additionalAux;
-
-			DataBus = container;
-			var tmpAux = new AdvancedAuxiliaries {
-				VectoInputs = {
-					Cycle = DetermineCycle(cycleName),
-					VehicleWeightKG = vehicleWeight
-				}
-			};
-
-			_fcMapAdapter = new FuelConsumptionAdapter() { FcMap = fcMap };
-			tmpAux.VectoInputs.FuelMap = _fcMapAdapter;
-			tmpAux.VectoInputs.FuelDensity = FuelData.Instance().Lookup(container.FuelType).FuelDensity;
-
-			//'Set Signals
-			tmpAux.Signals.EngineIdleSpeed = engineIdleSpeed;
-			tmpAux.Initialise(Path.GetFileName(aauxFile), Path.GetDirectoryName(Path.GetFullPath(aauxFile)) + @"\");
-
-			tmpAux.Signals.TotalCycleTimeSeconds =
-				tmpAux.actuationsMap.GetNumActuations(new ActuationsKey("CycleTime", tmpAux.VectoInputs.Cycle));
-
-			// call initialize again _after_ setting the cycle time to get the correct consumtions
-			tmpAux.Initialise(Path.GetFileName(aauxFile), Path.GetDirectoryName(Path.GetFullPath(aauxFile)) + @"\");
-
-
-			Auxiliaries = tmpAux;
-		}
-
-		private static string DetermineCycle(string cycleName)
-		{
-			var cycle = cycleName.ToLower();
-
-			if (cycle.Contains("bus")) {
-				if (cycle.Contains("heavy_urban")) {
-					return "Heavy urban";
-				}
-				if (cycle.Contains("suburban")) {
-					return "Suburban";
-				}
-				if (cycle.Contains("interurban")) {
-					return "Interurban";
-				}
-				if (cycle.Contains("urban")) {
-					return "Urban";
-				}
-			}
-			if (cycle.Contains("coach")) {
-				return "Coach";
-			}
-			Logger<BusAuxiliariesAdapter>()
-				.Warn("UnServiced Cycle Name '{0}' in Pneumatics Actuations Map 0 Actuations returned", cycleName);
-			return cycleName;
-		}
-
-		public IAuxPort Port()
-		{
-			return this;
-		}
-
-		public NewtonMeter Initialize(NewtonMeter torque, PerSecond angularSpeed)
-		{
-			//PreviousState.TotalFuelConsumption = 0.SI<Kilogram>();
-			PreviousState.AngularSpeed = angularSpeed;
-			CurrentState.AngularSpeed = angularSpeed;
-			if (AdditionalAux != null) {
-				AdditionalAux.Initialize(torque, angularSpeed);
-			}
-			PreviousState.PowerDemand = GetBusAuxPowerDemand(0.SI<Second>(), 1.SI<Second>(), torque, torque, angularSpeed);
-			return PreviousState.PowerDemand / angularSpeed;
-		}
-
-
-		public NewtonMeter TorqueDemand(Second absTime, Second dt, NewtonMeter torquePowerTrain, NewtonMeter torqueEngine,
-			PerSecond angularSpeed, bool dryRun = false)
-		{
-			CurrentState.AngularSpeed = angularSpeed;
-			CurrentState.dt = dt;
-			CurrentState.PowerDemand = GetBusAuxPowerDemand(absTime, dt, torquePowerTrain, torqueEngine, angularSpeed, dryRun);
-
-			var avgAngularSpeed = (CurrentState.AngularSpeed + PreviousState.AngularSpeed) / 2.0;
-			return CurrentState.PowerDemand / avgAngularSpeed;
-		}
-
-
-		protected internal void DoWriteModalResults(IModalDataContainer container)
-		{
-			_fcMapAdapter.AllowExtrapolation = true;
-			// cycleStep has to be called here and not in DoCommit, write is called before Commit!
-			var message = String.Empty;
-			Auxiliaries.CycleStep(CurrentState.dt, ref message);
-			Log.Warn(message);
-
-			CurrentState.TotalFuelConsumption = Auxiliaries.TotalFuelGRAMS;
-			container[ModalResultField.P_aux] = CurrentState.PowerDemand;
-
-			container[ModalResultField.AA_NonSmartAlternatorsEfficiency] = Auxiliaries.AA_NonSmartAlternatorsEfficiency;
-			if (Auxiliaries.AA_SmartIdleCurrent_Amps != null) {
-				container[ModalResultField.AA_SmartIdleCurrent_Amps] = Auxiliaries.AA_SmartIdleCurrent_Amps;
-			}
-			container[ModalResultField.AA_SmartIdleAlternatorsEfficiency] = Auxiliaries.AA_SmartIdleAlternatorsEfficiency;
-			if (Auxiliaries.AA_SmartTractionCurrent_Amps != null) {
-				container[ModalResultField.AA_SmartTractionCurrent_Amps] =
-					Auxiliaries.AA_SmartTractionCurrent_Amps;
-			}
-			container[ModalResultField.AA_SmartTractionAlternatorEfficiency] = Auxiliaries.AA_SmartTractionAlternatorEfficiency;
-			if (Auxiliaries.AA_SmartOverrunCurrent_Amps != null) {
-				container[ModalResultField.AA_SmartOverrunCurrent_Amps] = Auxiliaries.AA_SmartOverrunCurrent_Amps;
-			}
-			container[ModalResultField.AA_SmartOverrunAlternatorEfficiency] = Auxiliaries.AA_SmartOverrunAlternatorEfficiency;
-			if (Auxiliaries.AA_CompressorFlowRate_LitrePerSec != null) {
-				container[ModalResultField.AA_CompressorFlowRate_LitrePerSec] =
-					Auxiliaries.AA_CompressorFlowRate_LitrePerSec;
-			}
-			container[ModalResultField.AA_OverrunFlag] = Auxiliaries.AA_OverrunFlag;
-			container[ModalResultField.AA_EngineIdleFlag] = Auxiliaries.AA_EngineIdleFlag;
-			container[ModalResultField.AA_CompressorFlag] = Auxiliaries.AA_CompressorFlag;
-			if (Auxiliaries.AA_TotalCycleFC_Grams != null) {
-				container[ModalResultField.AA_TotalCycleFC_Grams] = Auxiliaries.AA_TotalCycleFC_Grams;
-			}
-			if (Auxiliaries.AA_TotalCycleFC_Litres != null) {
-				container[ModalResultField.AA_TotalCycleFC_Litres] = Auxiliaries.AA_TotalCycleFC_Litres;
-			}
-			if (Auxiliaries.AA_AveragePowerDemandCrankHVACMechanicals != null) {
-				container[ModalResultField.AA_AveragePowerDemandCrankHVACMechanicals] =
-					Auxiliaries.AA_AveragePowerDemandCrankHVACMechanicals;
-			}
-			if (Auxiliaries.AA_AveragePowerDemandCrankHVACElectricals != null) {
-				container[ModalResultField.AA_AveragePowerDemandCrankHVACElectricals] =
-					Auxiliaries.AA_AveragePowerDemandCrankHVACElectricals;
-			}
-			if (Auxiliaries.AA_AveragePowerDemandCrankElectrics != null) {
-				container[ModalResultField.AA_AveragePowerDemandCrankElectrics] =
-					Auxiliaries.AA_AveragePowerDemandCrankElectrics;
-			}
-			if (Auxiliaries.AA_AveragePowerDemandCrankPneumatics != null) {
-				container[ModalResultField.AA_AveragePowerDemandCrankPneumatics] =
-					Auxiliaries.AA_AveragePowerDemandCrankPneumatics;
-			}
-			if (Auxiliaries.AA_TotalCycleFuelConsumptionCompressorOff != null) {
-				container[ModalResultField.AA_TotalCycleFuelConsumptionCompressorOff] =
-					Auxiliaries.AA_TotalCycleFuelConsumptionCompressorOff;
-			}
-			container[ModalResultField.AA_TotalCycleFuelConsumptionCompressorOn] =
-				Auxiliaries.AA_TotalCycleFuelConsumptionCompressorOn;
-		}
-
-		protected internal void DoCommitSimulationStep()
-		{
-			PreviousState = CurrentState;
-			CurrentState = new BusAuxState();
-		}
-
-		protected internal KilogramPerSecond AAuxFuelConsumption
-		{
-			get { return (CurrentState.TotalFuelConsumption - PreviousState.TotalFuelConsumption) / CurrentState.dt; }
-		}
-
-		private Watt GetBusAuxPowerDemand(Second absTime, Second dt, NewtonMeter torquePowerTrain, NewtonMeter torqueEngine,
-			PerSecond angularSpeed, bool dryRun = false)
-		{
-			_fcMapAdapter.AllowExtrapolation = true;
-
-			Auxiliaries.Signals.ClutchEngaged = DataBus.ClutchClosed(absTime);
-			Auxiliaries.Signals.EngineDrivelinePower = torquePowerTrain * angularSpeed;
-			Auxiliaries.Signals.EngineDrivelineTorque = torquePowerTrain;
-			Auxiliaries.Signals.InternalEnginePower = torqueEngine * angularSpeed - DataBus.BrakePower;
-			if (DataBus.DriverBehavior == DrivingBehavior.Coasting) {
-				// make sure smart aux are _not_ enabled for now
-				// set internal_engine_power a little bit lower so there is no excessive power for smart aux
-				Auxiliaries.Signals.InternalEnginePower = 0.9 * torqueEngine * angularSpeed /*- DataBus.BrakePower*/;
-				// if smart aux should be on during coasting use the following line
-				// set internal_engine_power to a large value (*10) so that there's excessive power for smart aux (alreadin during search operating point)
-				//(float)DataBus.EngineDragPower(angularSpeed).Value() / 100;
-			} else {
-				if (DataBus.DriverBehavior != DrivingBehavior.Braking) {
-					Auxiliaries.Signals.InternalEnginePower = 0.SI<Watt>();
-					//(float)((0.9 * torqueEngine * angularSpeed - DataBus.BrakePower) / 1000).Value();
-				} else {
-					// smart aux should be on during braking
-				}
-			}
-			Auxiliaries.Signals.EngineMotoringPower = -DataBus.EngineDragPower(angularSpeed);
-			Auxiliaries.Signals.EngineSpeed = angularSpeed;
-			var avgAngularSpeed = (PreviousState.AngularSpeed + CurrentState.AngularSpeed) / 2;
-			Auxiliaries.Signals.PreExistingAuxPower = AdditionalAux != null
-				? AdditionalAux.TorqueDemand(absTime, dt, torquePowerTrain, torqueEngine, angularSpeed, dryRun) * avgAngularSpeed
-				: 0.SI<Watt>();
-			//mAAUX_Global.PreExistingAuxPower;
-			Auxiliaries.Signals.Idle = DataBus.VehicleStopped;
-			Auxiliaries.Signals.InNeutral = DataBus.Gear == 0;
-			Auxiliaries.Signals.RunningCalc = true;
-
-			//mAAUX_Global.Internal_Engine_Power;
-			//'Power coming out of Advanced Model is in Watts.
-
-			return Auxiliaries.AuxiliaryPowerAtCrankWatts + Auxiliaries.Signals.PreExistingAuxPower;
-		}
-
-		protected class FuelConsumptionAdapter : IFuelConsumptionMap
-		{
-			protected internal FuelConsumptionMap FcMap;
-
-			public bool AllowExtrapolation { get; set; }
-
-			public KilogramPerSecond GetFuelConsumption(NewtonMeter torque, PerSecond angularVelocity)
-			{
-				return FcMap.GetFuelConsumption(torque, angularVelocity, AllowExtrapolation).Value;
-			}
-		}
-
-		public class BusAuxState
-		{
-			public Second dt;
-			public PerSecond AngularSpeed;
-			public Watt PowerDemand;
-			public Kilogram TotalFuelConsumption = 0.SI<Kilogram>();
-		}
-	}
+using System;
+using System.IO;
+using TUGraz.VectoCommon.Models;
+using TUGraz.VectoCommon.Utils;
+using TUGraz.VectoCore.Models.Declaration;
+using TUGraz.VectoCore.Models.Simulation.Data;
+using TUGraz.VectoCore.Models.Simulation.DataBus;
+using TUGraz.VectoCore.Models.SimulationComponent.Data.Engine;
+using TUGraz.VectoCore.OutputData;
+using VectoAuxiliaries;
+using VectoAuxiliaries.Pneumatics;
+
+namespace TUGraz.VectoCore.Models.SimulationComponent.Impl
+{
+	public class BusAuxiliariesAdapter : LoggingObject, IAuxInProvider, IAuxPort
+	{
+		protected readonly IDataBus DataBus;
+		protected internal BusAuxState CurrentState;
+		protected internal BusAuxState PreviousState;
+
+		protected internal readonly IAuxPort AdditionalAux;
+
+		protected IAdvancedAuxiliaries Auxiliaries;
+		private readonly FuelConsumptionAdapter _fcMapAdapter;
+
+		public BusAuxiliariesAdapter(IDataBus container, string aauxFile, string cycleName, Kilogram vehicleWeight,
+			FuelConsumptionMap fcMap, PerSecond engineIdleSpeed, IAuxPort additionalAux = null)
+		{
+			//	mAAUX_Global.advancedAuxModel.Signals.DeclarationMode = Cfg.DeclMode
+			//	mAAUX_Global.advancedAuxModel.Signals.WHTC = Declaration.WHTCcorrFactor
+			CurrentState = new BusAuxState();
+			PreviousState = new BusAuxState { AngularSpeed = engineIdleSpeed };
+
+			AdditionalAux = additionalAux;
+
+			DataBus = container;
+			var tmpAux = new AdvancedAuxiliaries {
+				VectoInputs = {
+					Cycle = DetermineCycle(cycleName),
+					VehicleWeightKG = vehicleWeight
+				}
+			};
+
+			_fcMapAdapter = new FuelConsumptionAdapter() { FcMap = fcMap };
+			tmpAux.VectoInputs.FuelMap = _fcMapAdapter;
+			tmpAux.VectoInputs.FuelDensity = FuelData.Instance().Lookup(container.FuelType).FuelDensity;
+
+			//'Set Signals
+			tmpAux.Signals.EngineIdleSpeed = engineIdleSpeed;
+			tmpAux.Initialise(Path.GetFileName(aauxFile), Path.GetDirectoryName(Path.GetFullPath(aauxFile)) + @"\");
+
+			tmpAux.Signals.TotalCycleTimeSeconds =
+				tmpAux.actuationsMap.GetNumActuations(new ActuationsKey("CycleTime", tmpAux.VectoInputs.Cycle));
+
+			// call initialize again _after_ setting the cycle time to get the correct consumtions
+			tmpAux.Initialise(Path.GetFileName(aauxFile), Path.GetDirectoryName(Path.GetFullPath(aauxFile)) + @"\");
+
+
+			Auxiliaries = tmpAux;
+		}
+
+		private static string DetermineCycle(string cycleName)
+		{
+			var cycle = cycleName.ToLower();
+
+			if (cycle.Contains("bus")) {
+				if (cycle.Contains("heavy_urban")) {
+					return "Heavy urban";
+				}
+				if (cycle.Contains("suburban")) {
+					return "Suburban";
+				}
+				if (cycle.Contains("interurban")) {
+					return "Interurban";
+				}
+				if (cycle.Contains("urban")) {
+					return "Urban";
+				}
+			}
+			if (cycle.Contains("coach")) {
+				return "Coach";
+			}
+			Logger<BusAuxiliariesAdapter>()
+				.Warn("UnServiced Cycle Name '{0}' in Pneumatics Actuations Map 0 Actuations returned", cycleName);
+			return cycleName;
+		}
+
+		public IAuxPort Port()
+		{
+			return this;
+		}
+
+		public NewtonMeter Initialize(NewtonMeter torque, PerSecond angularSpeed)
+		{
+			//PreviousState.TotalFuelConsumption = 0.SI<Kilogram>();
+			PreviousState.AngularSpeed = angularSpeed;
+			CurrentState.AngularSpeed = angularSpeed;
+			if (AdditionalAux != null) {
+				AdditionalAux.Initialize(torque, angularSpeed);
+			}
+			PreviousState.PowerDemand = GetBusAuxPowerDemand(0.SI<Second>(), 1.SI<Second>(), torque, torque, angularSpeed);
+			return PreviousState.PowerDemand / angularSpeed;
+		}
+
+
+		public NewtonMeter TorqueDemand(Second absTime, Second dt, NewtonMeter torquePowerTrain, NewtonMeter torqueEngine,
+			PerSecond angularSpeed, bool dryRun = false)
+		{
+			CurrentState.AngularSpeed = angularSpeed;
+			CurrentState.dt = dt;
+			CurrentState.PowerDemand = GetBusAuxPowerDemand(absTime, dt, torquePowerTrain, torqueEngine, angularSpeed, dryRun);
+
+			var avgAngularSpeed = (CurrentState.AngularSpeed + PreviousState.AngularSpeed) / 2.0;
+			return CurrentState.PowerDemand / avgAngularSpeed;
+		}
+
+
+		protected internal void DoWriteModalResults(IModalDataContainer container)
+		{
+			_fcMapAdapter.AllowExtrapolation = true;
+			// cycleStep has to be called here and not in DoCommit, write is called before Commit!
+			var message = String.Empty;
+			Auxiliaries.CycleStep(CurrentState.dt, ref message);
+			Log.Warn(message);
+
+			CurrentState.TotalFuelConsumption = Auxiliaries.TotalFuelGRAMS;
+			container[ModalResultField.P_aux] = CurrentState.PowerDemand;
+
+			container[ModalResultField.AA_NonSmartAlternatorsEfficiency] = Auxiliaries.AA_NonSmartAlternatorsEfficiency;
+			if (Auxiliaries.AA_SmartIdleCurrent_Amps != null) {
+				container[ModalResultField.AA_SmartIdleCurrent_Amps] = Auxiliaries.AA_SmartIdleCurrent_Amps;
+			}
+			container[ModalResultField.AA_SmartIdleAlternatorsEfficiency] = Auxiliaries.AA_SmartIdleAlternatorsEfficiency;
+			if (Auxiliaries.AA_SmartTractionCurrent_Amps != null) {
+				container[ModalResultField.AA_SmartTractionCurrent_Amps] =
+					Auxiliaries.AA_SmartTractionCurrent_Amps;
+			}
+			container[ModalResultField.AA_SmartTractionAlternatorEfficiency] = Auxiliaries.AA_SmartTractionAlternatorEfficiency;
+			if (Auxiliaries.AA_SmartOverrunCurrent_Amps != null) {
+				container[ModalResultField.AA_SmartOverrunCurrent_Amps] = Auxiliaries.AA_SmartOverrunCurrent_Amps;
+			}
+			container[ModalResultField.AA_SmartOverrunAlternatorEfficiency] = Auxiliaries.AA_SmartOverrunAlternatorEfficiency;
+			if (Auxiliaries.AA_CompressorFlowRate_LitrePerSec != null) {
+				container[ModalResultField.AA_CompressorFlowRate_LitrePerSec] =
+					Auxiliaries.AA_CompressorFlowRate_LitrePerSec;
+			}
+			container[ModalResultField.AA_OverrunFlag] = Auxiliaries.AA_OverrunFlag;
+			container[ModalResultField.AA_EngineIdleFlag] = Auxiliaries.AA_EngineIdleFlag;
+			container[ModalResultField.AA_CompressorFlag] = Auxiliaries.AA_CompressorFlag;
+			if (Auxiliaries.AA_TotalCycleFC_Grams != null) {
+				container[ModalResultField.AA_TotalCycleFC_Grams] = Auxiliaries.AA_TotalCycleFC_Grams;
+			}
+			if (Auxiliaries.AA_TotalCycleFC_Litres != null) {
+				container[ModalResultField.AA_TotalCycleFC_Litres] = Auxiliaries.AA_TotalCycleFC_Litres;
+			}
+			if (Auxiliaries.AA_AveragePowerDemandCrankHVACMechanicals != null) {
+				container[ModalResultField.AA_AveragePowerDemandCrankHVACMechanicals] =
+					Auxiliaries.AA_AveragePowerDemandCrankHVACMechanicals;
+			}
+			if (Auxiliaries.AA_AveragePowerDemandCrankHVACElectricals != null) {
+				container[ModalResultField.AA_AveragePowerDemandCrankHVACElectricals] =
+					Auxiliaries.AA_AveragePowerDemandCrankHVACElectricals;
+			}
+			if (Auxiliaries.AA_AveragePowerDemandCrankElectrics != null) {
+				container[ModalResultField.AA_AveragePowerDemandCrankElectrics] =
+					Auxiliaries.AA_AveragePowerDemandCrankElectrics;
+			}
+			if (Auxiliaries.AA_AveragePowerDemandCrankPneumatics != null) {
+				container[ModalResultField.AA_AveragePowerDemandCrankPneumatics] =
+					Auxiliaries.AA_AveragePowerDemandCrankPneumatics;
+			}
+			if (Auxiliaries.AA_TotalCycleFuelConsumptionCompressorOff != null) {
+				container[ModalResultField.AA_TotalCycleFuelConsumptionCompressorOff] =
+					Auxiliaries.AA_TotalCycleFuelConsumptionCompressorOff;
+			}
+			container[ModalResultField.AA_TotalCycleFuelConsumptionCompressorOn] =
+				Auxiliaries.AA_TotalCycleFuelConsumptionCompressorOn;
+		}
+
+		protected internal void DoCommitSimulationStep()
+		{
+			PreviousState = CurrentState;
+			CurrentState = new BusAuxState();
+		}
+
+		protected internal KilogramPerSecond AAuxFuelConsumption
+		{
+			get { return (CurrentState.TotalFuelConsumption - PreviousState.TotalFuelConsumption) / CurrentState.dt; }
+		}
+
+		private Watt GetBusAuxPowerDemand(Second absTime, Second dt, NewtonMeter torquePowerTrain, NewtonMeter torqueEngine,
+			PerSecond angularSpeed, bool dryRun = false)
+		{
+			_fcMapAdapter.AllowExtrapolation = true;
+
+			Auxiliaries.Signals.ClutchEngaged = DataBus.ClutchClosed(absTime);
+			Auxiliaries.Signals.EngineDrivelinePower = torquePowerTrain * angularSpeed;
+			Auxiliaries.Signals.EngineDrivelineTorque = torquePowerTrain;
+			Auxiliaries.Signals.InternalEnginePower = torqueEngine * angularSpeed - DataBus.BrakePower;
+			if (DataBus.DriverBehavior == DrivingBehavior.Coasting) {
+				// make sure smart aux are _not_ enabled for now
+				// set internal_engine_power a little bit lower so there is no excessive power for smart aux
+				Auxiliaries.Signals.InternalEnginePower = 0.9 * torqueEngine * angularSpeed /*- DataBus.BrakePower*/;
+				// if smart aux should be on during coasting use the following line
+				// set internal_engine_power to a large value (*10) so that there's excessive power for smart aux (alreadin during search operating point)
+				//(float)DataBus.EngineDragPower(angularSpeed).Value() / 100;
+			} else {
+				if (DataBus.DriverBehavior != DrivingBehavior.Braking) {
+					Auxiliaries.Signals.InternalEnginePower = 0.SI<Watt>();
+					//(float)((0.9 * torqueEngine * angularSpeed - DataBus.BrakePower) / 1000).Value();
+				} else {
+					// smart aux should be on during braking
+				}
+			}
+			Auxiliaries.Signals.EngineMotoringPower = -DataBus.EngineDragPower(angularSpeed);
+			Auxiliaries.Signals.EngineSpeed = angularSpeed;
+			var avgAngularSpeed = (PreviousState.AngularSpeed + CurrentState.AngularSpeed) / 2;
+			Auxiliaries.Signals.PreExistingAuxPower = AdditionalAux != null
+				? AdditionalAux.TorqueDemand(absTime, dt, torquePowerTrain, torqueEngine, angularSpeed, dryRun) * avgAngularSpeed
+				: 0.SI<Watt>();
+			//mAAUX_Global.PreExistingAuxPower;
+			Auxiliaries.Signals.Idle = DataBus.VehicleStopped;
+			Auxiliaries.Signals.InNeutral = DataBus.Gear == 0;
+			Auxiliaries.Signals.RunningCalc = true;
+
+			//mAAUX_Global.Internal_Engine_Power;
+			//'Power coming out of Advanced Model is in Watts.
+
+			return Auxiliaries.AuxiliaryPowerAtCrankWatts + Auxiliaries.Signals.PreExistingAuxPower;
+		}
+
+		protected class FuelConsumptionAdapter : IFuelConsumptionMap
+		{
+			protected internal FuelConsumptionMap FcMap;
+
+			public bool AllowExtrapolation { get; set; }
+
+			public KilogramPerSecond GetFuelConsumption(NewtonMeter torque, PerSecond angularVelocity)
+			{
+				return FcMap.GetFuelConsumption(torque, angularVelocity, AllowExtrapolation).Value;
+			}
+		}
+
+		public class BusAuxState
+		{
+			public Second dt;
+			public PerSecond AngularSpeed;
+			public Watt PowerDemand;
+			public Kilogram TotalFuelConsumption = 0.SI<Kilogram>();
+		}
+	}
 }
\ No newline at end of file
diff --git a/VectoCore/VectoCore/Models/SimulationComponent/Impl/CombustionEngine.cs b/VectoCore/VectoCore/Models/SimulationComponent/Impl/CombustionEngine.cs
index 032a25d0a6..5881f2ae2f 100644
--- a/VectoCore/VectoCore/Models/SimulationComponent/Impl/CombustionEngine.cs
+++ b/VectoCore/VectoCore/Models/SimulationComponent/Impl/CombustionEngine.cs
@@ -366,7 +366,7 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl
 			var avgEngineSpeed = GetEngineSpeed(CurrentState.EngineSpeed);
 			if (avgEngineSpeed.IsSmaller(EngineIdleSpeed,
 				DataBus.ExecutionMode == ExecutionMode.Engineering ? 20.RPMtoRad() : 1e-3.RPMtoRad())) {
-				Log.Warn("EngineSpeed below idling speed! n_eng_avg: {0}, n_idle: {1}", avgEngineSpeed, EngineIdleSpeed);
+				Log.Warn("EngineSpeed below idling speed! n_eng_avg: {0}, n_idle: {1}", avgEngineSpeed.AsRPM, EngineIdleSpeed.AsRPM);
 			}
 			container[ModalResultField.P_eng_fcmap] = CurrentState.EngineTorque * avgEngineSpeed;
 			container[ModalResultField.P_eng_out] = container[ModalResultField.P_eng_out] is DBNull
diff --git a/VectoCore/VectoCore/Models/SimulationComponent/Impl/VTPCycle.cs b/VectoCore/VectoCore/Models/SimulationComponent/Impl/VTPCycle.cs
index 48cb3ae007..7735c430b6 100644
--- a/VectoCore/VectoCore/Models/SimulationComponent/Impl/VTPCycle.cs
+++ b/VectoCore/VectoCore/Models/SimulationComponent/Impl/VTPCycle.cs
@@ -36,6 +36,7 @@ using TUGraz.VectoCommon.Models;
 using TUGraz.VectoCommon.Utils;
 using TUGraz.VectoCore.Configuration;
 using TUGraz.VectoCore.Models.Connector.Ports.Impl;
+using TUGraz.VectoCore.Models.Declaration;
 using TUGraz.VectoCore.Models.Simulation.Data;
 using TUGraz.VectoCore.Models.Simulation.Impl;
 using TUGraz.VectoCore.Models.SimulationComponent.Data;
@@ -48,11 +49,13 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl
 	{
 		private uint StartGear;
 
-		public VTPCycle(VehicleContainer container, IDrivingCycleData cycle, double axleGearRatio,
-			VehicleData vehicleData, Dictionary<uint, double> gearRatios) : base(container, cycle) { }
+		public VTPCycle(VehicleContainer container, IDrivingCycleData cycle) : base(container, cycle) { }
 
 		public override IResponse Initialize()
 		{
+			if (DataBus.ExecutionMode == ExecutionMode.Declaration) {
+				VerifyInputData();
+			}
 			PrepareCycleData();
 			SelectStartGear();
 			return base.Initialize();
@@ -68,6 +71,114 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl
 				entry.Torque = wheelSpeed.IsEqual(0, 1e-3) ? 0.SI<NewtonMeter>() : wheelPower / wheelSpeed;
 			}
 		}
+
+		protected internal void VerifyInputData()
+		{
+			var electricFanTechs = DeclarationData.Fan.FullyElectricTechnologies();
+			var hasElectricFan = RunData.Aux.Any(
+				x => x.ID == Constants.Auxiliaries.IDs.Fan && x.Technology.Any(t => electricFanTechs.Contains(t)));
+
+			foreach (var tuple in Data.Entries.Pairwise()) {
+				if (!(tuple.Item2.Time - tuple.Item1.Time).IsEqual(
+						DeclarationData.VTPMode.SamplingInterval, 0.1 * DeclarationData.VTPMode.SamplingInterval)) {
+					Log.Error("Cycle Data exceeds expected sampling frequence of {0}: t: {1}, dt: {2}",
+						DeclarationData.VTPMode.SamplingInterval, tuple.Item1.Time, tuple.Item2.Time - tuple.Item1.Time);
+				}
+			}
+
+			foreach (var entry in Data.Entries) {
+				VerifyWheelSpeeds(entry);
+
+				VerifyWheelTorque(entry);
+
+				VerifyFanSpeed(hasElectricFan, entry);
+			}
+
+			VerifyFCInput();
+		}
+
+		private void VerifyFCInput()
+		{
+			var idx = 0L;
+			int count = Convert.ToInt32(DeclarationData.VTPMode.FCAccumulationWindow / DeclarationData.VTPMode.SamplingInterval);
+			var sum = 0.SI<Kilogram>();
+			var window = 0.SI<Kilogram>().Repeat(count).ToArray();
+			
+			foreach (var entry in Data.Entries.Pairwise()) {
+				var fc = entry.Item1.Fuelconsumption * (entry.Item2.Time - entry.Item1.Time);
+				window[idx % count] = fc;
+				sum += window[idx % count];
+				sum -= window[(idx + 1) % count];
+				if (idx >= count && sum < DeclarationData.VTPMode.LowerFCThreshold * DeclarationData.VTPMode.FCAccumulationWindow) {
+					Log.Error("Fuel consumption for the previous {0} below threshold of {1}. t: {2}, FC: {3}", DeclarationData.VTPMode.FCAccumulationWindow.ConvertToMinutes(),
+						DeclarationData.VTPMode.LowerFCThreshold.ConvertToGrammPerHour(), entry.Item1.Time, (sum / DeclarationData.VTPMode.FCAccumulationWindow).ConvertToGrammPerHour());
+				}
+				if (idx >= count && sum > DeclarationData.VTPMode.UpperFCThreshold * DeclarationData.VTPMode.FCAccumulationWindow) {
+					Log.Error("Fuel consumption for the previous {0} above threshold of {1}. t: {2}, FC: {3}", DeclarationData.VTPMode.FCAccumulationWindow.ConvertToMinutes(),
+							DeclarationData.VTPMode.UpperFCThreshold.ConvertToGrammPerHour(), entry.Item1.Time, (sum / DeclarationData.VTPMode.FCAccumulationWindow).ConvertToGrammPerHour());
+				}
+				idx++;
+			}
+		}
+
+		private void VerifyFanSpeed(bool hasElectricFan, DrivingCycleData.DrivingCycleEntry entry)
+		{
+			if (hasElectricFan) {
+				if (entry.FanSpeed.IsSmaller(0)) {
+					Log.Error("Fan speed (electric) below zero! t: {0}, n_fan: {1}", entry.Time, entry.FanSpeed);
+				}
+			} else {
+				if (entry.FanSpeed.IsSmaller(DeclarationData.VTPMode.MinFanSpeed) ||
+					entry.FanSpeed.IsGreater(DeclarationData.VTPMode.MaxFanSpeed)) {
+					Log.Error(
+						"Fan speed (non-electric) exceeds range {0} < n_fan < {1}. t: {2}, n_fan: {3}", DeclarationData.VTPMode.MinFanSpeed,
+						DeclarationData.VTPMode.MaxFanSpeed, entry.Time, entry.FanSpeed);
+				}
+			}
+		}
+
+		private void VerifyWheelTorque(DrivingCycleData.DrivingCycleEntry entry)
+		{
+			if (!entry.TorqueWheelLeft.IsEqual(0.SI<NewtonMeter>(), DeclarationData.VTPMode.WheelTorqueZeroTolerance) &&
+				!entry.TorqueWheelRight.IsEqual(0.SI<NewtonMeter>(), DeclarationData.VTPMode.WheelTorqueZeroTolerance)) {
+				var torqueRatio = VectoMath.Max(
+					entry.TorqueWheelLeft / entry.TorqueWheelRight, entry.TorqueWheelRight / entry.TorqueWheelLeft);
+				if (torqueRatio > DeclarationData.VTPMode.WheelTorqueDifferenceFactor) {
+					Log.Error(
+						"Torque difference rel. (L/R) too high! t: {0} tq_left: {1}, tq_right: {2}", entry.Time, entry.TorqueWheelLeft,
+						entry.TorqueWheelRight);
+				}
+			} else {
+				if (VectoMath.Abs(entry.TorqueWheelLeft - entry.TorqueWheelRight) >
+					DeclarationData.VTPMode.MaxWheelTorqueZeroDifference) {
+					Log.Error(
+						"Torque difference abs. (L/R) too high! t: {0} tq_left: {1}, tq_right: {2}", entry.Time, entry.TorqueWheelLeft,
+						entry.TorqueWheelRight);
+				}
+			}
+		}
+
+		private void VerifyWheelSpeeds(DrivingCycleData.DrivingCycleEntry entry)
+		{
+			if (!entry.WheelSpeedLeft.IsEqual(0.RPMtoRad(), DeclarationData.VTPMode.WheelSpeedZeroTolerance) &&
+				!entry.WheelSpeedRight.IsEqual(0.RPMtoRad(), DeclarationData.VTPMode.WheelSpeedZeroTolerance)) {
+				var wheelSpeedRatio = VectoMath.Max(
+					entry.WheelSpeedLeft / entry.WheelSpeedRight, entry.WheelSpeedRight / entry.WheelSpeedLeft);
+				if (wheelSpeedRatio > DeclarationData.VTPMode.WheelSpeedDifferenceFactor) {
+					Log.Error(
+						"Wheel-speed difference rel. (L/R) too high! t: {0} n_left: {1}, n_right: {2}", entry.Time,
+						entry.WheelSpeedLeft.AsRPM, entry.WheelSpeedRight.AsRPM);
+				}
+			} else {
+				if (VectoMath.Abs(entry.WheelSpeedLeft - entry.WheelSpeedRight) >
+					DeclarationData.VTPMode.MaxWheelSpeedDifferenceStandstill) {
+					Log.Error(
+						"Wheel-speed difference abs. (L/R) too high! t: {0} n_left: {1}, n_right: {2}", entry.Time,
+						entry.WheelSpeedLeft.AsRPM, entry.WheelSpeedRight.AsRPM);
+				}
+			}
+		}
+
 		private void SelectStartGear()
 		{
 			var transmissionRatio = RunData.AxleGearData.AxleGear.Ratio *
diff --git a/VectoCore/VectoCore/Resources/Declaration/VAUX/Fan-Tech.csv b/VectoCore/VectoCore/Resources/Declaration/VAUX/Fan-Tech.csv
index 10e393a595..a09dd8ea95 100644
--- a/VectoCore/VectoCore/Resources/Declaration/VAUX/Fan-Tech.csv
+++ b/VectoCore/VectoCore/Resources/Declaration/VAUX/Fan-Tech.csv
@@ -1,12 +1,12 @@
-Technology                                                                 , Long haul , Regional delivery , Urban delivery , Municipal utility , Construction
-Crankshaft mounted - Electronically controlled visco clutch                , 618       , 671               , 516            , 566               , 1037
-Crankshaft mounted - Bimetallic controlled visco clutch                    , 818       , 871               , 676            , 766               , 1277
-Crankshaft mounted - Discrete step clutch                                  , 668       , 721               , 616            , 616               , 1157
-Crankshaft mounted - On/off clutch                                         , 718       , 771               , 666            , 666               , 1237
-Belt driven or driven via transm. - Electronically controlled visco clutch , 989       , 1044              , 833            , 933               , 1478
-Belt driven or driven via transm. - Bimetallic controlled visco clutch     , 1189      , 1244              , 993            , 1133              , 1718
-Belt driven or driven via transm. - Discrete step clutch                   , 1039      , 1094              , 983            , 983               , 1598
-Belt driven or driven via transm. - On/off clutch                          , 1089      , 1144              , 1033           , 1033              , 1678
-Hydraulic driven - Variable displacement pump                              , 938       , 1155              , 832            , 917               , 1872
-Hydraulic driven - Constant displacement pump                              , 1200      , 1400              , 1000           , 1100              , 2300
-Electrically driven - Electronically controlled                            , 700       , 800               , 600            , 600               , 1400
\ No newline at end of file
+Technology                                                                 , fully electric , Long haul , Regional delivery , Urban delivery , Municipal utility , Construction
+Crankshaft mounted - Electronically controlled visco clutch                ,         0      , 618       , 671               , 516            , 566               , 1037
+Crankshaft mounted - Bimetallic controlled visco clutch                    ,         0      , 818       , 871               , 676            , 766               , 1277
+Crankshaft mounted - Discrete step clutch                                  ,         0      , 668       , 721               , 616            , 616               , 1157
+Crankshaft mounted - On/off clutch                                         ,         0      , 718       , 771               , 666            , 666               , 1237
+Belt driven or driven via transm. - Electronically controlled visco clutch ,         0      , 989       , 1044              , 833            , 933               , 1478
+Belt driven or driven via transm. - Bimetallic controlled visco clutch     ,         0      , 1189      , 1244              , 993            , 1133              , 1718
+Belt driven or driven via transm. - Discrete step clutch                   ,         0      , 1039      , 1094              , 983            , 983               , 1598
+Belt driven or driven via transm. - On/off clutch                          ,         0      , 1089      , 1144              , 1033           , 1033              , 1678
+Hydraulic driven - Variable displacement pump                              ,         0      , 938       , 1155              , 832            , 917               , 1872
+Hydraulic driven - Constant displacement pump                              ,         0      , 1200      , 1400              , 1000           , 1100              , 2300
+Electrically driven - Electronically controlled                            ,         1      , 700       , 800               , 600            , 600               , 1400
\ No newline at end of file
diff --git a/VectoCore/VectoCoreTest/Models/SimulationComponent/VTPCycleValidationTest.cs b/VectoCore/VectoCoreTest/Models/SimulationComponent/VTPCycleValidationTest.cs
new file mode 100644
index 0000000000..b713e4c8a6
--- /dev/null
+++ b/VectoCore/VectoCoreTest/Models/SimulationComponent/VTPCycleValidationTest.cs
@@ -0,0 +1,515 @@
+using System.Collections.Generic;
+using NLog;
+using NLog.Config;
+using NLog.Targets;
+using NUnit.Framework;
+using TUGraz.VectoCommon.Models;
+using TUGraz.VectoCommon.Utils;
+using TUGraz.VectoCore.Configuration;
+using TUGraz.VectoCore.InputData.Reader;
+using TUGraz.VectoCore.Models.Declaration;
+using TUGraz.VectoCore.Models.Simulation.Data;
+using TUGraz.VectoCore.Models.Simulation.Impl;
+using TUGraz.VectoCore.Models.SimulationComponent.Data;
+using TUGraz.VectoCore.Models.SimulationComponent.Impl;
+using TUGraz.VectoCore.Tests.Integration;
+using TUGraz.VectoCore.Tests.Models.SimulationComponentData;
+using TUGraz.VectoCore.Tests.Utils;
+using TUGraz.VectoCore.Utils;
+
+namespace TUGraz.VectoCore.Tests.Models.SimulationComponent
+{
+	[TestFixture]
+	public class VTPCycleValidationTest
+	{
+		public static List<string> LogList = new List<string>();
+
+		const string Header = "<t> [s],<v> [km/h],<n_eng> [rpm],<n_fan> [rpm],<tq_left> [Nm],<tq_right> [Nm],<n_wh_left> [rpm],<n_wh_right> [rpm],<fc> [g/h],<gear>";
+
+
+		[TestCase()]
+		public void TestWheelSpeedRatioExceeds_Left()
+		{
+			SetupLogging();
+
+			var wheelSpeed = 100;
+
+			var cycleEntries = string.Format(
+				@"  0   ,    0,  600, 400, 200, 200, {0}, {0}	, 100, 3
+				    0.5 ,    0,  600, 400, 200, 200, {0}, {0}	, 100, 3
+				    1   ,    0,  600, 400, 200, 200, {0}, {1}	, 100, 3
+				    1.5 ,    0,  600, 400, 200, 200, {1}, {1}	, 100, 3
+				", wheelSpeed, wheelSpeed * DeclarationData.VTPMode.WheelSpeedDifferenceFactor * 1.1);
+
+			var container = new VehicleContainer(ExecutionMode.Declaration) {
+				RunData = new VectoRunData() {
+					Aux = new List<VectoRunData.AuxData>()
+				}
+			};
+			var cycle = InputDataHelper.InputDataAsStream(Header, cycleEntries.Split('\n'));
+			var cycleData = DrivingCycleDataReader.ReadFromDataTable(VectoCSVFile.ReadStream(cycle), "VTP Cycle", false);
+			var vtpCycle = new VTPCycle(container, cycleData);
+
+			vtpCycle.VerifyInputData();
+
+			Assert.AreEqual(1, LogList.Count);
+			Assert.IsTrue(LogList[0].Contains("Wheel-speed difference rel."));
+		}
+
+		[TestCase()]
+		public void TestWheelSpeedRatioExceeds_Right()
+		{
+			SetupLogging();
+
+			var wheelSpeed = 100;
+
+			var cycleEntries = string.Format(
+				@"  0   ,    0,  600, 400, 200, 200, {0}, {0}	, 100, 3
+				    0.5 ,    0,  600, 400, 200, 200, {0}, {0}	, 100, 3
+				    1   ,    0,  600, 400, 200, 200, {0}, {1}	, 100, 3
+				    1.5 ,    0,  600, 400, 200, 200, {1}, {1}	, 100, 3
+				", wheelSpeed, wheelSpeed * DeclarationData.VTPMode.WheelSpeedDifferenceFactor * 1.1);
+
+			var container = new VehicleContainer(ExecutionMode.Declaration) {
+				RunData = new VectoRunData() {
+					Aux = new List<VectoRunData.AuxData>()
+				}
+			};
+			var cycle = InputDataHelper.InputDataAsStream(Header, cycleEntries.Split('\n'));
+			var cycleData = DrivingCycleDataReader.ReadFromDataTable(VectoCSVFile.ReadStream(cycle), "VTP Cycle", false);
+			var vtpCycle = new VTPCycle(container, cycleData);
+
+			vtpCycle.VerifyInputData();
+
+			Assert.AreEqual(1, LogList.Count);
+			Assert.IsTrue(LogList[0].Contains("Wheel-speed difference rel."));
+		}
+
+		[TestCase()]
+		public void TestWheelSpeedDifferenceStandstillExceeds_Left()
+		{
+			SetupLogging();
+
+			var wheelSpeed = 0.95 * DeclarationData.VTPMode.WheelSpeedZeroTolerance.AsRPM; 
+
+			var cycleEntries = string.Format(
+				@"  0   ,    0,  600, 400, 200, 200, {0}, {0}	, 100, 3
+				    0.5 ,    0,  600, 400, 200, 200, {0}, {0}	, 100, 3
+				    1   ,    0,  600, 400, 200, 200, {1}, {0}	, 100, 3
+				    1.5 ,    0,  600, 400, 200, 200, {1}, {1}	, 100, 3
+				", wheelSpeed, wheelSpeed + DeclarationData.VTPMode.MaxWheelSpeedDifferenceStandstill.AsRPM * 1.1);
+
+			var container = new VehicleContainer(ExecutionMode.Declaration) {
+				RunData = new VectoRunData() {
+					Aux = new List<VectoRunData.AuxData>()
+				}
+			};
+			var cycle = InputDataHelper.InputDataAsStream(Header, cycleEntries.Split('\n'));
+			var cycleData = DrivingCycleDataReader.ReadFromDataTable(VectoCSVFile.ReadStream(cycle), "VTP Cycle", false);
+			var vtpCycle = new VTPCycle(container, cycleData);
+			vtpCycle.VerifyInputData();
+
+			Assert.AreEqual(1, LogList.Count);
+			Assert.IsTrue(LogList[0].Contains("Wheel-speed difference abs."));
+		}
+
+		[TestCase()]
+		public void TestWheelSpeedDifferenceStandstillExceeds_Right()
+		{
+			SetupLogging();
+
+			var wheelSpeed = 0.95*DeclarationData.VTPMode.WheelSpeedZeroTolerance.AsRPM;
+
+			var cycleEntries = string.Format(
+				@"  0   ,    0,  600, 400, 200, 200, {0}, {0}	, 100, 3
+				    0.5 ,    0,  600, 400, 200, 200, {0}, {0}	, 100, 3
+				    1   ,    0,  600, 400, 200, 200, {0}, {1}	, 100, 3
+				    1.5 ,    0,  600, 400, 200, 200, {1}, {1}	, 100, 3
+				", wheelSpeed, wheelSpeed + DeclarationData.VTPMode.MaxWheelSpeedDifferenceStandstill.AsRPM * 1.1);
+
+			var container = new VehicleContainer(ExecutionMode.Declaration) {
+				RunData = new VectoRunData() {
+					Aux = new List<VectoRunData.AuxData>()
+				}
+			};
+			var cycle = InputDataHelper.InputDataAsStream(Header, cycleEntries.Split('\n'));
+			var cycleData = DrivingCycleDataReader.ReadFromDataTable(VectoCSVFile.ReadStream(cycle), "VTP Cycle", false);
+			var vtpCycle = new VTPCycle(container, cycleData);
+
+			vtpCycle.VerifyInputData();
+
+			Assert.AreEqual(1, LogList.Count);
+			Assert.IsTrue(LogList[0].Contains("Wheel-speed difference abs."));
+		}
+
+
+
+		[TestCase()]
+		public void TestWheelTorqueRatioExceeds_Left()
+		{
+			SetupLogging();
+
+			var torque = 300;
+
+			var cycleEntries = string.Format(
+				@"  0   ,    0,  600, 400, {0}, {0} , 50 , 50 , 100, 3
+				    0.5 ,    0,  600, 400, {0}, {0} , 50 , 50 , 100, 3
+				    1   ,    0,  600, 400, {0}, {1} , 50 , 50 , 100, 3
+				    1.5 ,    0,  600, 400, {1}, {1} , 50 , 50 , 100, 3
+				", torque, torque * DeclarationData.VTPMode.WheelTorqueDifferenceFactor * 1.1);
+
+			var container = new VehicleContainer(ExecutionMode.Declaration) {
+				RunData = new VectoRunData() {
+					Aux = new List<VectoRunData.AuxData>()
+				}
+			};
+			var cycle = InputDataHelper.InputDataAsStream(Header, cycleEntries.Split('\n'));
+			var cycleData = DrivingCycleDataReader.ReadFromDataTable(VectoCSVFile.ReadStream(cycle), "VTP Cycle", false);
+			var vtpCycle = new VTPCycle(container, cycleData);
+
+			vtpCycle.VerifyInputData();
+
+			Assert.AreEqual(1, LogList.Count);
+			Assert.IsTrue(LogList[0].Contains("Torque difference rel."));
+		}
+
+
+		[TestCase()]
+		public void TestWheelTorqueRatioExceeds_Right()
+		{
+			SetupLogging();
+
+			var torque = 300;
+
+			var cycleEntries = string.Format(
+				@"  0   ,    0,  600, 400, {0}, {0} , 50 , 50 , 100, 3
+				    0.5 ,    0,  600, 400, {0}, {0} , 50 , 50 , 100, 3
+				    1   ,    0,  600, 400, {1}, {0} , 50 , 50 , 100, 3
+				    1.5 ,    0,  600, 400, {1}, {1} , 50 , 50 , 100, 3
+				", torque, torque * DeclarationData.VTPMode.WheelTorqueDifferenceFactor * 1.1);
+
+			var container = new VehicleContainer(ExecutionMode.Declaration) {
+				RunData = new VectoRunData() {
+					Aux = new List<VectoRunData.AuxData>()
+				}
+			};
+			var cycle = InputDataHelper.InputDataAsStream(Header, cycleEntries.Split('\n'));
+			var cycleData = DrivingCycleDataReader.ReadFromDataTable(VectoCSVFile.ReadStream(cycle), "VTP Cycle", false);
+			var vtpCycle = new VTPCycle(container, cycleData);
+
+			vtpCycle.VerifyInputData();
+
+			Assert.AreEqual(1, LogList.Count);
+			Assert.IsTrue(LogList[0].Contains("Torque difference rel."));
+		}
+
+		[TestCase()]
+		public void TestWheelTorqueDiffExceeds_Left()
+		{
+			SetupLogging();
+
+			var torque = 0.95*DeclarationData.VTPMode.WheelTorqueZeroTolerance.Value();
+
+			var cycleEntries = string.Format(
+				@"  0   ,    0,  600, 400, {0}, {0} , 50 , 50 , 100, 3
+				    0.5 ,    0,  600, 400, {0}, {0} , 50 , 50 , 100, 3
+				    1   ,    0,  600, 400, {0}, {1} , 50 , 50 , 100, 3
+				    1.5 ,    0,  600, 400, {1}, {1} , 50 , 50 , 100, 3
+				", torque, torque + DeclarationData.VTPMode.MaxWheelTorqueZeroDifference.Value() * 1.1);
+
+			var container = new VehicleContainer(ExecutionMode.Declaration) {
+				RunData = new VectoRunData() {
+					Aux = new List<VectoRunData.AuxData>()
+				}
+			};
+			var cycle = InputDataHelper.InputDataAsStream(Header, cycleEntries.Split('\n'));
+			var cycleData = DrivingCycleDataReader.ReadFromDataTable(VectoCSVFile.ReadStream(cycle), "VTP Cycle", false);
+			var vtpCycle = new VTPCycle(container, cycleData);
+
+			vtpCycle.VerifyInputData();
+
+			Assert.AreEqual(1, LogList.Count);
+			Assert.IsTrue(LogList[0].Contains("Torque difference abs."));
+		}
+
+		[TestCase()]
+		public void TestWheelTorqueDiffExceeds_Right()
+		{
+			SetupLogging();
+
+			var torque = 0.95 * DeclarationData.VTPMode.WheelTorqueZeroTolerance.Value();
+
+			var cycleEntries = string.Format(
+				@"  0   ,    0,  600, 400, {0}, {0} , 50 , 50 , 100, 3
+				    0.5 ,    0,  600, 400, {0}, {0} , 50 , 50 , 100, 3
+				    1   ,    0,  600, 400, {1}, {0} , 50 , 50 , 100, 3
+				    1.5 ,    0,  600, 400, {1}, {1} , 50 , 50 , 100, 3
+				", torque, torque + DeclarationData.VTPMode.MaxWheelTorqueZeroDifference.Value() * 1.1);
+
+			var container = new VehicleContainer(ExecutionMode.Declaration) {
+				RunData = new VectoRunData() {
+					Aux = new List<VectoRunData.AuxData>()
+				}
+			};
+			var cycle = InputDataHelper.InputDataAsStream(Header, cycleEntries.Split('\n'));
+			var cycleData = DrivingCycleDataReader.ReadFromDataTable(VectoCSVFile.ReadStream(cycle), "VTP Cycle", false);
+			var vtpCycle = new VTPCycle(container, cycleData);
+
+			vtpCycle.VerifyInputData();
+
+			Assert.AreEqual(1, LogList.Count);
+			Assert.IsTrue(LogList[0].Contains("Torque difference abs."));
+		}
+
+		[TestCase()]
+		public void TestFanSpeedTooLow()
+		{
+			SetupLogging();
+
+			var fanSpeed = 1.05 * DeclarationData.VTPMode.MinFanSpeed.AsRPM;
+
+			var cycleEntries = string.Format(
+				@"  0   ,    0,  600, {0}, 300 , 290 , 50 , 50 , 100, 3
+				    0.5 ,    0,  600, {0}, 300 , 290 , 50 , 50 , 100, 3
+				    1   ,    0,  600, {1}, 300 , 290 , 50 , 50 , 100, 3
+				    1.5 ,    0,  600, {0}, 300 , 290 , 50 , 50 , 100, 3
+				", fanSpeed, fanSpeed * 0.9);
+
+			var container = new VehicleContainer(ExecutionMode.Declaration) {
+				RunData = new VectoRunData() {
+					Aux = new List<VectoRunData.AuxData>() {
+						new VectoRunData.AuxData() {
+							ID = Constants.Auxiliaries.IDs.Fan,
+							Technology = new List<string>() { "Crankshaft mounted - On/off clutch" }
+						}
+					}
+				}
+			};
+			var cycle = InputDataHelper.InputDataAsStream(Header, cycleEntries.Split('\n'));
+			var cycleData = DrivingCycleDataReader.ReadFromDataTable(VectoCSVFile.ReadStream(cycle), "VTP Cycle", false);
+			var vtpCycle = new VTPCycle(container, cycleData);
+			vtpCycle.VerifyInputData();
+
+			Assert.AreEqual(1, LogList.Count);
+			Assert.IsTrue(LogList[0].Contains("Fan speed (non-electric) exceeds range"));
+		}
+
+		[TestCase()]
+		public void TestFanSpeedTooHigh()
+		{
+			SetupLogging();
+
+			var fanSpeed = 0.95 * DeclarationData.VTPMode.MaxFanSpeed.AsRPM;
+
+			var cycleEntries = string.Format(
+				@"  0   ,    0,  600, {0}, 300 , 290 , 50 , 50 , 100, 3
+				    0.5 ,    0,  600, {0}, 300 , 290 , 50 , 50 , 100, 3
+				    1   ,    0,  600, {1}, 300 , 290 , 50 , 50 , 100, 3
+				    1.5 ,    0,  600, {0}, 300 , 290 , 50 , 50 , 100, 3
+				", fanSpeed, 1.1 * fanSpeed );
+
+			var container = new VehicleContainer(ExecutionMode.Declaration) {
+				RunData = new VectoRunData() {
+					Aux = new List<VectoRunData.AuxData>() {
+						new VectoRunData.AuxData() {
+							ID = Constants.Auxiliaries.IDs.Fan,
+							Technology = new List<string>() { "Crankshaft mounted - On/off clutch" }
+						}
+					}
+				}
+			};
+			var cycle = InputDataHelper.InputDataAsStream(Header, cycleEntries.Split('\n'));
+			var cycleData = DrivingCycleDataReader.ReadFromDataTable(VectoCSVFile.ReadStream(cycle), "VTP Cycle", false);
+			var vtpCycle = new VTPCycle(container, cycleData);
+			vtpCycle.VerifyInputData();
+
+			Assert.AreEqual(1, LogList.Count);
+			Assert.IsTrue(LogList[0].Contains("Fan speed (non-electric) exceeds range"));
+		}
+
+
+		[TestCase()]
+		public void TestFanSpeedElectricLow()
+		{
+			SetupLogging();
+
+			var fanSpeed = 1.05 * DeclarationData.VTPMode.MinFanSpeed.AsRPM;
+
+			var cycleEntries = string.Format(
+				@"  0   ,    0,  600, {0}, 300 , 290 , 50 , 50 , 100, 3
+				    0.5 ,    0,  600, {0}, 300 , 290 , 50 , 50 , 100, 3
+				    1   ,    0,  600, {1}, 300 , 290 , 50 , 50 , 100, 3
+				    1.5 ,    0,  600, {0}, 300 , 290 , 50 , 50 , 100, 3
+				", fanSpeed, fanSpeed * 0.9);
+
+			var container = new VehicleContainer(ExecutionMode.Declaration) {
+				RunData = new VectoRunData() {
+					Aux = new List<VectoRunData.AuxData>() {
+						new VectoRunData.AuxData() {
+							ID = Constants.Auxiliaries.IDs.Fan,
+							Technology = new List<string>() { "Electrically driven - Electronically controlled" }
+						}
+					}
+				}
+			};
+			var cycle = InputDataHelper.InputDataAsStream(Header, cycleEntries.Split('\n'));
+			var cycleData = DrivingCycleDataReader.ReadFromDataTable(VectoCSVFile.ReadStream(cycle), "VTP Cycle", false);
+			var vtpCycle = new VTPCycle(container, cycleData);
+			vtpCycle.VerifyInputData();
+
+			Assert.AreEqual(0, LogList.Count);
+		}
+
+		[TestCase()]
+		public void TestFanSpeedElectricHigh()
+		{
+			SetupLogging();
+
+			var fanSpeed = 0.95 * DeclarationData.VTPMode.MaxFanSpeed.AsRPM;
+
+			var cycleEntries = string.Format(
+				@"  0   ,    0,  600, {0}, 300 , 290 , 50 , 50 , 100, 3
+				    0.5 ,    0,  600, {0}, 300 , 290 , 50 , 50 , 100, 3
+				    1   ,    0,  600, {1}, 300 , 290 , 50 , 50 , 100, 3
+				    1.5 ,    0,  600, {0}, 300 , 290 , 50 , 50 , 100, 3
+				", fanSpeed, 1.1 * fanSpeed);
+
+			var container = new VehicleContainer(ExecutionMode.Declaration) {
+				RunData = new VectoRunData() {
+					Aux = new List<VectoRunData.AuxData>() {
+						new VectoRunData.AuxData() {
+							ID = Constants.Auxiliaries.IDs.Fan,
+							Technology = new List<string>() { "Electrically driven - Electronically controlled" }
+						}
+					}
+				}
+			};
+			var cycle = InputDataHelper.InputDataAsStream(Header, cycleEntries.Split('\n'));
+			var cycleData = DrivingCycleDataReader.ReadFromDataTable(VectoCSVFile.ReadStream(cycle), "VTP Cycle", false);
+			var vtpCycle = new VTPCycle(container, cycleData);
+			vtpCycle.VerifyInputData();
+
+			Assert.AreEqual(0, LogList.Count);
+			
+		}
+
+		[TestCase()]
+		public void TestFuelConsumptionTooLow()
+		{
+			SetupLogging();
+
+			var fanSpeed = 0.95 * DeclarationData.VTPMode.MaxFanSpeed.AsRPM;
+
+			var cycleEntries = "";
+			for (var i = 0; i < 2000; i++)
+				cycleEntries += string.Format("  {0} ,    0,  600, 400, 300 , 290 , 50 , 50 , {1}, 3 \n", i / 2.0, DeclarationData.VTPMode.LowerFCThreshold.ConvertToGrammPerHour() / 1.01);
+
+			var container = new VehicleContainer(ExecutionMode.Declaration) {
+				RunData = new VectoRunData() {
+					Aux = new List<VectoRunData.AuxData>()
+				}
+			};
+			var cycle = InputDataHelper.InputDataAsStream(Header, cycleEntries.Split('\n'));
+			var cycleData = DrivingCycleDataReader.ReadFromDataTable(VectoCSVFile.ReadStream(cycle), "VTP Cycle", false);
+			var vtpCycle = new VTPCycle(container, cycleData);
+			vtpCycle.VerifyInputData();
+
+			Assert.Greater(LogList.Count, 1);
+
+		}
+
+		[TestCase()]
+		public void TestFuelConsumptionLowOK()
+		{
+			SetupLogging();
+
+			var fanSpeed = 0.95 * DeclarationData.VTPMode.MaxFanSpeed.AsRPM;
+
+			var cycleEntries = "";
+			for (var i = 0; i < 2000; i++)
+				cycleEntries += string.Format("  {0} ,    0,  600, 400, 300 , 290 , 50 , 50 , {1}, 3 \n", i / 2.0, DeclarationData.VTPMode.LowerFCThreshold.ConvertToGrammPerHour() * 1.01);
+
+			var container = new VehicleContainer(ExecutionMode.Declaration) {
+				RunData = new VectoRunData() {
+					Aux = new List<VectoRunData.AuxData>()
+				}
+			};
+			var cycle = InputDataHelper.InputDataAsStream(Header, cycleEntries.Split('\n'));
+			var cycleData = DrivingCycleDataReader.ReadFromDataTable(VectoCSVFile.ReadStream(cycle), "VTP Cycle", false);
+			var vtpCycle = new VTPCycle(container, cycleData);
+			vtpCycle.VerifyInputData();
+
+			Assert.AreEqual(0, LogList.Count);
+
+		}
+
+		[TestCase()]
+		public void TestFuelConsumptionTooHigh()
+		{
+			SetupLogging();
+
+			var fanSpeed = 0.95 * DeclarationData.VTPMode.MaxFanSpeed.AsRPM;
+
+			var cycleEntries = "";
+			for (var i = 0; i < 2000; i++)
+				cycleEntries += string.Format("  {0} ,    0,  600, 400, 300 , 290 , 50 , 50 , {1}, 3 \n", i / 2.0, DeclarationData.VTPMode.UpperFCThreshold.ConvertToGrammPerHour() * 1.01);
+
+			var container = new VehicleContainer(ExecutionMode.Declaration) {
+				RunData = new VectoRunData() {
+					Aux = new List<VectoRunData.AuxData>()
+				}
+			};
+			var cycle = InputDataHelper.InputDataAsStream(Header, cycleEntries.Split('\n'));
+			var cycleData = DrivingCycleDataReader.ReadFromDataTable(VectoCSVFile.ReadStream(cycle), "VTP Cycle", false);
+			var vtpCycle = new VTPCycle(container, cycleData);
+			vtpCycle.VerifyInputData();
+
+			Assert.Greater(LogList.Count, 1);
+
+		}
+
+		[TestCase()]
+		public void TestFuelConsumptionHighOK()
+		{
+			SetupLogging();
+
+			var fanSpeed = 0.95 * DeclarationData.VTPMode.MaxFanSpeed.AsRPM;
+
+			var cycleEntries = "";
+			for (var i = 0; i < 2000; i++)
+				cycleEntries += string.Format("  {0} ,    0,  600, 400, 300 , 290 , 50 , 50 , {1}, 3 \n", i / 2.0, DeclarationData.VTPMode.UpperFCThreshold.ConvertToGrammPerHour() / 1.01);
+
+			var container = new VehicleContainer(ExecutionMode.Declaration) {
+				RunData = new VectoRunData() {
+					Aux = new List<VectoRunData.AuxData>()
+				}
+			};
+			var cycle = InputDataHelper.InputDataAsStream(Header, cycleEntries.Split('\n'));
+			var cycleData = DrivingCycleDataReader.ReadFromDataTable(VectoCSVFile.ReadStream(cycle), "VTP Cycle", false);
+			var vtpCycle = new VTPCycle(container, cycleData);
+			vtpCycle.VerifyInputData();
+
+			Assert.AreEqual(0, LogList.Count);
+
+		}
+
+		private static void SetupLogging()
+		{
+			LogList.Clear();
+			var target = new MethodCallTarget {
+				ClassName = typeof(VTPCycleValidationTest).AssemblyQualifiedName,
+				MethodName = "LogMethod"
+			};
+			target.Parameters.Add(new MethodCallParameter("${level}"));
+			target.Parameters.Add(new MethodCallParameter("${message}"));
+			SimpleConfigurator.ConfigureForTargetLogging(target, LogLevel.Error);
+		}
+
+		
+		// ReSharper disable once UnusedMember.Global -- used by logging framework, see SetupLogging method
+		public static void LogMethod(string level, string message)
+		{
+			LogList.Add(message);
+		}
+	}
+}
diff --git a/VectoCore/VectoCoreTest/TestData/Integration/VTPMode/GenericVehicle/Tractor_4x2_vehicle-class-5_Generic vehicle.xml b/VectoCore/VectoCoreTest/TestData/Integration/VTPMode/GenericVehicle/Tractor_4x2_vehicle-class-5_Generic vehicle.xml
index dfa7c42f70..634a24cbb6 100644
--- a/VectoCore/VectoCoreTest/TestData/Integration/VTPMode/GenericVehicle/Tractor_4x2_vehicle-class-5_Generic vehicle.xml	
+++ b/VectoCore/VectoCoreTest/TestData/Integration/VTPMode/GenericVehicle/Tractor_4x2_vehicle-class-5_Generic vehicle.xml	
@@ -15,7 +15,7 @@
     <AxleConfiguration>4x2</AxleConfiguration>
     <CurbMassChassis>7800</CurbMassChassis>
     <GrossVehicleMass>40000</GrossVehicleMass>
-    <IdlingSpeed>600</IdlingSpeed>
+    <IdlingSpeed>590</IdlingSpeed>
     <RetarderType>Transmission Output Retarder</RetarderType>
     <RetarderRatio>1.000</RetarderRatio>
     <AngledriveType>None</AngledriveType>
@@ -32,7 +32,7 @@
           <Date>2017-11-20T12:31:47.2109026Z</Date>
           <AppVersion>VectoCore</AppVersion>
           <Displacement>13000</Displacement>
-          <IdlingSpeed>600</IdlingSpeed>
+          <IdlingSpeed>590</IdlingSpeed>
           <RatedSpeed>1736</RatedSpeed>
           <RatedPower>325032</RatedPower>
           <MaxEngineTorque>2134</MaxEngineTorque>
@@ -44,6 +44,18 @@
           <CFNCV>1.0000</CFNCV>
           <FuelType>Diesel CI</FuelType>
           <FuelConsumptionMap>
+			<Entry engineSpeed="550.00" torque="-150.00" fuelConsumption="0.00" />
+            <Entry engineSpeed="550.00" torque="0.00" fuelConsumption="1488.18" />
+            <Entry engineSpeed="550.00" torque="216.90" fuelConsumption="3609.53" />
+            <Entry engineSpeed="550.00" torque="433.80" fuelConsumption="6055.65" />
+            <Entry engineSpeed="550.00" torque="650.70" fuelConsumption="8756.65" />
+            <Entry engineSpeed="550.00" torque="867.60" fuelConsumption="10922.44" />
+            <Entry engineSpeed="550.00" torque="1084.50" fuelConsumption="13315.08" />
+            <Entry engineSpeed="550.00" torque="1301.40" fuelConsumption="15886.96" />
+            <Entry engineSpeed="550.00" torque="1518.30" fuelConsumption="18459.52" />
+            <Entry engineSpeed="550.00" torque="1735.20" fuelConsumption="21032.07" />
+            <Entry engineSpeed="550.00" torque="1952.10" fuelConsumption="23604.64" />
+            <Entry engineSpeed="550.00" torque="2169.00" fuelConsumption="26177.20" />
             <Entry engineSpeed="600.00" torque="-150.00" fuelConsumption="0.00" />
             <Entry engineSpeed="600.00" torque="0.00" fuelConsumption="1488.18" />
             <Entry engineSpeed="600.00" torque="216.90" fuelConsumption="3609.53" />
diff --git a/VectoCore/VectoCoreTest/Utils/InputDataHelper.cs b/VectoCore/VectoCoreTest/Utils/InputDataHelper.cs
index 17f6f39a52..c42ea75b75 100644
--- a/VectoCore/VectoCoreTest/Utils/InputDataHelper.cs
+++ b/VectoCore/VectoCoreTest/Utils/InputDataHelper.cs
@@ -29,23 +29,23 @@
 *   Martin Rexeis, rexeis@ivt.tugraz.at, IVT, Graz University of Technology
 */
 
-using System.IO;
-
-namespace TUGraz.VectoCore.Tests.Utils
-{
-	public class InputDataHelper
-	{
-		public static MemoryStream InputDataAsStream(string header, string[] entries)
-		{
-			var cycleData = new MemoryStream();
-			var writer = new StreamWriter(cycleData);
-			writer.WriteLine(header);
-			foreach (var entry in entries) {
-				writer.WriteLine(entry);
-			}
-			writer.Flush();
-			cycleData.Seek(0, SeekOrigin.Begin);
-			return cycleData;
-		}
-	}
+using System.IO;
+
+namespace TUGraz.VectoCore.Tests.Utils
+{
+	public class InputDataHelper
+	{
+		public static MemoryStream InputDataAsStream(string header, string[] entries)
+		{
+			var cycleData = new MemoryStream();
+			var writer = new StreamWriter(cycleData);
+			writer.WriteLine(header);
+			foreach (var entry in entries) {
+				writer.WriteLine(entry);
+			}
+			writer.Flush();
+			cycleData.Seek(0, SeekOrigin.Begin);
+			return cycleData;
+		}
+	}
 }
\ No newline at end of file
diff --git a/VectoCore/VectoCoreTest/VectoCoreTest.csproj b/VectoCore/VectoCoreTest/VectoCoreTest.csproj
index 74e7cf04ef..177296fc13 100644
--- a/VectoCore/VectoCoreTest/VectoCoreTest.csproj
+++ b/VectoCore/VectoCoreTest/VectoCoreTest.csproj
@@ -105,6 +105,7 @@
     <Compile Include="Models\SimulationComponent\ATGearboxTest.cs" />
     <Compile Include="Models\SimulationComponent\EngineFanAuxTest.cs" />
     <Compile Include="Models\SimulationComponent\GearboxShiftLossesTest.cs" />
+    <Compile Include="Models\SimulationComponent\VTPCycleValidationTest.cs" />
     <Compile Include="Models\Simulation\FactoryTest.cs" />
     <Compile Include="Models\Simulation\PTOIdleLossTest.cs" />
     <Compile Include="Models\Simulation\LossMapRangeValidationTest.cs" />
-- 
GitLab