From b941003c8abb34bbb5279453fb3897b74fcb4f23 Mon Sep 17 00:00:00 2001
From: Michael Krisper <michael.krisper@tugraz.at>
Date: Wed, 20 Jan 2016 16:16:12 +0100
Subject: [PATCH] changed Gearbox to be derivable into a manual gearbox

---
 .../Simulation/Impl/PowertrainBuilder.cs      |  97 ++++++++++----
 .../Simulation/Impl/SimulatorFactory.cs       |   3 +-
 ...ivingCycle.cs => IPowertrainSimulation.cs} |   4 +-
 .../Impl/EngineOnlyGearbox.cs                 | 111 ----------------
 .../SimulationComponent/Impl/Gearbox.cs       | 109 ++++++++--------
 .../SimulationComponent/Impl/ManualGearbox.cs | 122 ++++++++++++++++++
 .../Impl/PowertrainDrivingCycle.cs            |   2 +-
 VectoCore/VectoCore.csproj                    |   4 +-
 .../EngineOnlyCycle/EngineOnlyCycleTest.cs    |   6 +-
 .../Simulation/PowerTrainBuilderTest.cs       |   2 +-
 .../CombustionEngineTest.cs                   |  22 ++--
 11 files changed, 272 insertions(+), 210 deletions(-)
 rename VectoCore/Models/SimulationComponent/{IEngineOnlyDrivingCycle.cs => IPowertrainSimulation.cs} (80%)
 delete mode 100644 VectoCore/Models/SimulationComponent/Impl/EngineOnlyGearbox.cs
 create mode 100644 VectoCore/Models/SimulationComponent/Impl/ManualGearbox.cs

diff --git a/VectoCore/Models/Simulation/Impl/PowertrainBuilder.cs b/VectoCore/Models/Simulation/Impl/PowertrainBuilder.cs
index 3a1d30058d..28a27ad6b1 100644
--- a/VectoCore/Models/Simulation/Impl/PowertrainBuilder.cs
+++ b/VectoCore/Models/Simulation/Impl/PowertrainBuilder.cs
@@ -14,6 +14,7 @@
 * limitations under the Licence.
 */
 
+using System;
 using TUGraz.VectoCore.Exceptions;
 using TUGraz.VectoCore.Models.Connector.Ports;
 using TUGraz.VectoCore.Models.Simulation.Data;
@@ -29,28 +30,33 @@ namespace TUGraz.VectoCore.Models.Simulation.Impl
 	/// </summary>
 	public class PowertrainBuilder
 	{
-		private readonly bool _engineOnly;
 		private readonly VehicleContainer _container;
 		private readonly IModalDataContainer _modData;
 
 
-		public PowertrainBuilder(IModalDataContainer modData, bool engineOnly, WriteSumData sumWriter = null)
+		public PowertrainBuilder(IModalDataContainer modData, WriteSumData sumWriter = null)
 		{
-			_engineOnly = engineOnly;
 			_modData = modData;
 			_container = new VehicleContainer(modData, sumWriter);
 		}
 
 		public VehicleContainer Build(VectoRunData data)
 		{
-			return _engineOnly ? BuildEngineOnly(data) : BuildFullPowertrain(data);
+			if (data.IsEngineOnly) {
+				return BuildEngineOnly(data);
+			}
+			if (data.Cycle.CycleType == CycleType.PWheel) {
+				return BuildPWheel(data);
+			}
+
+			return BuildFullPowertrain(data);
 		}
 
 		private VehicleContainer BuildEngineOnly(VectoRunData data)
 		{
-			var cycle = new EngineOnlyDrivingCycle(_container, data.Cycle);
+			var cycle = new PowertrainDrivingCycle(_container, data.Cycle);
 
-			var gearbox = new EngineOnlyGearbox(_container);
+			var gearbox = new ManualGearbox(_container);
 			cycle.InPort().Connect(gearbox.OutPort());
 
 			var directAux = new Auxiliary(_container);
@@ -63,6 +69,65 @@ namespace TUGraz.VectoCore.Models.Simulation.Impl
 			return _container;
 		}
 
+		private VehicleContainer BuildPWheel(VectoRunData data)
+		{
+			var cycle = new PowertrainDrivingCycle(_container, data.Cycle);
+
+			var tmp = AddComponent(cycle, new AxleGear(_container, data.AxleGearData));
+
+			switch (data.Retarder.Type) {
+				case RetarderData.RetarderType.Primary:
+					tmp = AddComponent(tmp, new Retarder(_container, data.Retarder.LossMap));
+					tmp = AddComponent(tmp, GetGearbox(_container, data.GearboxData));
+					break;
+				case RetarderData.RetarderType.Secondary:
+					tmp = AddComponent(tmp, GetGearbox(_container, data.GearboxData));
+					tmp = AddComponent(tmp, new Retarder(_container, data.Retarder.LossMap));
+					break;
+				case RetarderData.RetarderType.None:
+					tmp = AddComponent(tmp, GetGearbox(_container, data.GearboxData));
+					break;
+				case RetarderData.RetarderType.LossesIncludedInTransmission:
+					tmp = AddComponent(tmp, GetGearbox(_container, data.GearboxData));
+					break;
+				default:
+					throw new ArgumentOutOfRangeException();
+			}
+
+			var engine = new CombustionEngine(_container, data.EngineData);
+			var clutch = new Clutch(_container, data.EngineData, engine.IdleController);
+
+			// gearbox --> clutch
+			tmp = AddComponent(tmp, clutch);
+
+			// clutch --> direct aux --> ... --> aux_XXX --> directAux
+			if (data.Aux != null) {
+				var aux = new Auxiliary(_container);
+				foreach (var auxData in data.Aux) {
+					switch (auxData.DemandType) {
+						case AuxiliaryDemandType.Constant:
+							aux.AddConstant(auxData.ID, auxData.PowerDemand);
+							break;
+						case AuxiliaryDemandType.Direct:
+							aux.AddDirect(cycle);
+							break;
+						case AuxiliaryDemandType.Mapping:
+							aux.AddMapping(auxData.ID, cycle, auxData.Data);
+							break;
+					}
+					_modData.AddAuxiliary(auxData.ID);
+				}
+				tmp = AddComponent(tmp, aux);
+			}
+			// connect aux --> engine
+			AddComponent(tmp, engine);
+
+			engine.IdleController.RequestPort = clutch.IdleControlPort;
+
+			return _container;
+		}
+
+
 		private VehicleContainer BuildFullPowertrain(VectoRunData data)
 		{
 			_container.RunData = data;
@@ -74,29 +139,15 @@ namespace TUGraz.VectoCore.Models.Simulation.Impl
 				case CycleType.TimeBased:
 					cycle = new TimeBasedDrivingCycle(_container, data.Cycle);
 					break;
-				case CycleType.PWheel:
-					cycle = new PWheelDrivingCycle(_container, data.Cycle);
-					break;
-				//case CycleType.MeasuredSpeed:
-				//	cycle = new MeasuredSpeedDrivingCycle(_container, data.Cycle);
-				//	break;
 				default:
 					throw new VectoSimulationException("Unhandled Cycle Type");
 			}
 			// cycle --> driver --> vehicle --> wheels --> axleGear --> retarder --> gearBox
 			var driver = AddComponent(cycle, new Driver(_container, data.DriverData, new DefaultDriverStrategy()));
 			var vehicle = AddComponent(driver, new Vehicle(_container, data.VehicleData));
-
 			var wheels = AddComponent(vehicle, new Wheels(_container, data.VehicleData.DynamicTyreRadius));
 			var brakes = AddComponent(wheels, new Brakes(_container));
-
-			IPowerTrainComponent tmp;
-			if (data.Cycle.CycleType == CycleType.PWheel) {
-				tmp = new AxleGear(_container, data.AxleGearData);
-				//((PWheelDrivingCycle)cycle).InPort().Connect(tmp.OutPort());
-			} else {
-				tmp = AddComponent(brakes, new AxleGear(_container, data.AxleGearData));
-			}
+			var tmp = AddComponent(brakes, new AxleGear(_container, data.AxleGearData));
 
 			switch (data.Retarder.Type) {
 				case RetarderData.RetarderType.Primary:
@@ -113,6 +164,8 @@ namespace TUGraz.VectoCore.Models.Simulation.Impl
 				case RetarderData.RetarderType.LossesIncludedInTransmission:
 					tmp = AddComponent(tmp, GetGearbox(_container, data.GearboxData));
 					break;
+				default:
+					throw new ArgumentOutOfRangeException();
 			}
 
 			var engine = new CombustionEngine(_container, data.EngineData);
@@ -149,7 +202,7 @@ namespace TUGraz.VectoCore.Models.Simulation.Impl
 			return _container;
 		}
 
-		private IGearbox GetGearbox(VehicleContainer container, GearboxData data)
+		private static IGearbox GetGearbox(IVehicleContainer container, GearboxData data)
 		{
 			IShiftStrategy strategy;
 			switch (data.Type) {
diff --git a/VectoCore/Models/Simulation/Impl/SimulatorFactory.cs b/VectoCore/Models/Simulation/Impl/SimulatorFactory.cs
index 174fa4fd90..d0fe36fbed 100644
--- a/VectoCore/Models/Simulation/Impl/SimulatorFactory.cs
+++ b/VectoCore/Models/Simulation/Impl/SimulatorFactory.cs
@@ -100,8 +100,7 @@ namespace TUGraz.VectoCore.Models.Simulation.Impl
 						}, _mode);
 				modContainer.WriteModalResults = WriteModalResults;
 				var current = i++;
-				var builder = new PowertrainBuilder(modContainer,
-					data.IsEngineOnly, (writer, mass, loading) =>
+				var builder = new PowertrainBuilder(modContainer, (writer, mass, loading) =>
 						SumData.Write(d.IsEngineOnly, modContainer, d.JobName, string.Format("{0}-{1}", JobNumber, current),
 							d.Cycle.Name + Constants.FileExtensions.CycleFile, mass, loading));
 
diff --git a/VectoCore/Models/SimulationComponent/IEngineOnlyDrivingCycle.cs b/VectoCore/Models/SimulationComponent/IPowertrainSimulation.cs
similarity index 80%
rename from VectoCore/Models/SimulationComponent/IEngineOnlyDrivingCycle.cs
rename to VectoCore/Models/SimulationComponent/IPowertrainSimulation.cs
index 3b23170c09..edbba48e37 100644
--- a/VectoCore/Models/SimulationComponent/IEngineOnlyDrivingCycle.cs
+++ b/VectoCore/Models/SimulationComponent/IPowertrainSimulation.cs
@@ -19,7 +19,7 @@ using TUGraz.VectoCore.Models.Connector.Ports;
 namespace TUGraz.VectoCore.Models.SimulationComponent
 {
 	/// <summary>
-	/// Defines interfaces for a engine only driving cycle.
+	/// Defines interfaces for a powertrain only driving cycle.
 	/// </summary>
-	public interface IEngineOnlySimulation : ISimulationOutProvider, ITnInProvider {}
+	public interface IPowertrainSimulation : IDrivingCycleInfo, ISimulationOutProvider, ITnInProvider {}
 }
\ No newline at end of file
diff --git a/VectoCore/Models/SimulationComponent/Impl/EngineOnlyGearbox.cs b/VectoCore/Models/SimulationComponent/Impl/EngineOnlyGearbox.cs
deleted file mode 100644
index 9f4ea23f91..0000000000
--- a/VectoCore/Models/SimulationComponent/Impl/EngineOnlyGearbox.cs
+++ /dev/null
@@ -1,111 +0,0 @@
-/*
-* Copyright 2015 European Union
-*
-* Licensed under the EUPL (the "Licence");
-* You may not use this work except in compliance with the Licence.
-* You may obtain a copy of the Licence at:
-*
-* http://ec.europa.eu/idabc/eupl5
-*
-* Unless required by applicable law or agreed to in writing, software 
-* distributed under the Licence is distributed on an "AS IS" basis,
-* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-* See the Licence for the specific language governing permissions and 
-* limitations under the Licence.
-*/
-
-using System;
-using TUGraz.VectoCore.Exceptions;
-using TUGraz.VectoCore.Models.Connector.Ports;
-using TUGraz.VectoCore.Models.Simulation;
-using TUGraz.VectoCore.Models.Simulation.Data;
-using TUGraz.VectoCore.Models.Simulation.DataBus;
-using TUGraz.VectoCore.Models.SimulationComponent.Data;
-using TUGraz.VectoCore.OutputData;
-using TUGraz.VectoCore.Utils;
-
-namespace TUGraz.VectoCore.Models.SimulationComponent.Impl
-{
-	public class EngineOnlyGearbox : VectoSimulationComponent, IGearbox, ITnInPort, ITnOutPort
-	{
-		protected ITnOutPort NextComponent;
-		public EngineOnlyGearbox(IVehicleContainer cockpit) : base(cockpit) {}
-
-		#region ITnInProvider
-
-		public ITnInPort InPort()
-		{
-			return this;
-		}
-
-		#endregion ITnOutProvider
-
-		#region ITnOutProvider
-
-		public ITnOutPort OutPort()
-		{
-			return this;
-		}
-
-		#endregion
-
-		#region IGearboxCockpit
-
-		uint IGearboxInfo.Gear
-		{
-			get { return 0; }
-		}
-
-		public MeterPerSecond StartSpeed
-		{
-			get { throw new VectoSimulationException("Not Implemented: EngineOnlyGearbox has no StartSpeed value."); }
-		}
-
-		public MeterPerSquareSecond StartAcceleration
-		{
-			get { throw new VectoSimulationException("Not Implemented: EngineOnlyGearbox has no StartAcceleration value."); }
-		}
-
-		public FullLoadCurve GearFullLoadCurve
-		{
-			get { return null; }
-		}
-
-		#endregion
-
-		#region ITnInPort
-
-		void ITnInPort.Connect(ITnOutPort other)
-		{
-			NextComponent = other;
-		}
-
-		#endregion
-
-		#region ITnOutPort
-
-		IResponse ITnOutPort.Request(Second absTime, Second dt, NewtonMeter torque, PerSecond angularVelocity, bool dryRun)
-		{
-			if (NextComponent == null) {
-				Log.Error("Ccannot handle incoming request - no outport available. absTime: {0}, dt: {1}", absTime, dt);
-				throw new VectoSimulationException("Cannot handle incoming request - no outport available.");
-			}
-			return NextComponent.Request(absTime, dt, torque, angularVelocity, dryRun);
-		}
-
-		public IResponse Initialize(NewtonMeter torque, PerSecond angularSpeed)
-		{
-			return NextComponent.Initialize(torque, angularSpeed);
-		}
-
-		#endregion
-
-		#region VectoSimulationComponent
-
-		protected override void DoWriteModalResults(IModalDataContainer container) {}
-
-		protected override void DoCommitSimulationStep() {}
-
-		#endregion
-	}
-}
\ No newline at end of file
diff --git a/VectoCore/Models/SimulationComponent/Impl/Gearbox.cs b/VectoCore/Models/SimulationComponent/Impl/Gearbox.cs
index 857280a377..762c4e21bc 100644
--- a/VectoCore/Models/SimulationComponent/Impl/Gearbox.cs
+++ b/VectoCore/Models/SimulationComponent/Impl/Gearbox.cs
@@ -44,43 +44,48 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl
 		/// <summary>
 		/// The shift strategy.
 		/// </summary>
-		private readonly IShiftStrategy _strategy;
+		protected readonly IShiftStrategy Strategy;
 
 		/// <summary>
 		/// Time when a gearbox shift engages a new gear (shift is finished). Is set when shifting is needed.
 		/// </summary>
-		private Second _shiftTime = 0.SI<Second>();
+		protected Second ShiftTime = 0.SI<Second>();
 
 		/// <summary>
 		/// True if gearbox is disengaged (no gear is set).
 		/// </summary>
-		private bool _disengaged = true;
+		protected bool Disengaged = true;
 
 		/// <summary>
 		/// The power loss for the mod data.
 		/// </summary>
-		private Watt _powerLoss;
+		protected Watt PowerLoss;
 
 		/// <summary>
 		/// The inertia power loss for the mod data.
 		/// </summary>
-		private Watt _powerLossInertia;
+		protected Watt PowerLossInertia;
 
 		/// <summary>
 		/// The previous enginespeed for inertia calculation
 		/// </summary>
-		private PerSecond _previousInAngularSpeed = 0.SI<PerSecond>();
+		protected PerSecond PreviousInAngularSpeed = 0.SI<PerSecond>();
 
 		public bool ClutchClosed(Second absTime)
 		{
-			return _shiftTime.IsSmallerOrEqual(absTime);
+			return ShiftTime.IsSmallerOrEqual(absTime);
 		}
 
 		public Gearbox(IVehicleContainer container, GearboxData gearboxData, IShiftStrategy strategy) : base(container)
 		{
 			Data = gearboxData;
-			_strategy = strategy;
-			_strategy.Gearbox = this;
+			Strategy = strategy;
+			Strategy.Gearbox = this;
+		}
+
+		protected Gearbox(IVehicleContainer container, GearboxData gearboxData) : base(container)
+		{
+			Data = gearboxData;
 		}
 
 		#region ITnInProvider
@@ -102,20 +107,18 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl
 
 		#endregion
 
-		#region IGearboxCockpit
+		#region IGearboxInfo
 
 		/// <summary>
 		/// The current gear.
 		/// </summary>
 		public uint Gear { get; set; }
 
-		[DebuggerHidden]
 		public MeterPerSecond StartSpeed
 		{
 			get { return Data.StartSpeed; }
 		}
 
-		[DebuggerHidden]
 		public MeterPerSquareSecond StartAcceleration
 		{
 			get { return Data.StartAcceleration; }
@@ -130,15 +133,15 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl
 
 		#region ITnOutPort
 
-		public IResponse Initialize(NewtonMeter outTorque, PerSecond outAngularVelocity)
+		public virtual IResponse Initialize(NewtonMeter outTorque, PerSecond outAngularVelocity)
 		{
 			var absTime = 0.SI<Second>();
 			var dt = Constants.SimulationSettings.TargetTimeInterval;
-			_shiftTime = double.NegativeInfinity.SI<Second>();
-			_powerLoss = null;
+			ShiftTime = double.NegativeInfinity.SI<Second>();
+			PowerLoss = null;
 
-			if (_disengaged) {
-				Gear = _strategy.InitGear(absTime, dt, outTorque, outAngularVelocity);
+			if (Disengaged) {
+				Gear = Strategy.InitGear(absTime, dt, outTorque, outAngularVelocity);
 			}
 
 			var inAngularVelocity = outAngularVelocity * Data.Gears[Gear].Ratio;
@@ -146,14 +149,14 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl
 
 			var torqueLossInertia = outAngularVelocity.IsEqual(0)
 				? 0.SI<NewtonMeter>()
-				: Formulas.InertiaPower(inAngularVelocity, _previousInAngularSpeed, Data.Inertia, dt) / inAngularVelocity;
+				: Formulas.InertiaPower(inAngularVelocity, PreviousInAngularSpeed, Data.Inertia, dt) / inAngularVelocity;
 
 			inTorque += torqueLossInertia;
 
 			var response = NextComponent.Initialize(inTorque, inAngularVelocity);
 			if (response is ResponseSuccess) {
-				_previousInAngularSpeed = inAngularVelocity;
-				_disengaged = false;
+				PreviousInAngularSpeed = inAngularVelocity;
+				Disengaged = false;
 			}
 
 			return response;
@@ -165,7 +168,7 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl
 			var inTorque = Data.Gears[gear].LossMap.GetInTorque(inAngularVelocity, outTorque);
 
 			if (!inAngularVelocity.IsEqual(0)) {
-				var alpha = (Data.Inertia.IsEqual(0))
+				var alpha = Data.Inertia.IsEqual(0)
 					? 0.SI<PerSquareSecond>()
 					: outTorque / Data.Inertia;
 
@@ -211,7 +214,7 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl
 		{
 			Log.Debug("Gearbox Power Request: torque: {0}, angularVelocity: {1}", torque, angularVelocity);
 			if (DataBus.VehicleStopped) {
-				_shiftTime = absTime;
+				ShiftTime = absTime;
 			}
 			IResponse retVal;
 			if (ClutchClosed(absTime)) {
@@ -235,7 +238,8 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl
 		/// <item><term>else</term><description>Response from NextComponent</description></item>
 		/// </list>
 		/// </returns>
-		private IResponse RequestGearDisengaged(Second absTime, Second dt, NewtonMeter outTorque, PerSecond outAngularVelocity,
+		protected virtual IResponse RequestGearDisengaged(Second absTime, Second dt, NewtonMeter outTorque,
+			PerSecond outAngularVelocity,
 			bool dryRun)
 		{
 			Log.Debug("Current Gear: Neutral");
@@ -247,12 +251,12 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl
 				};
 			}
 
-			var shiftTimeExceeded = absTime.IsSmaller(_shiftTime) &&
-									_shiftTime.IsSmaller(absTime + dt, Data.TractionInterruption / 20.0);
+			var shiftTimeExceeded = absTime.IsSmaller(ShiftTime) &&
+									ShiftTime.IsSmaller(absTime + dt, Data.TractionInterruption / 20.0);
 			if (shiftTimeExceeded) {
 				return new ResponseFailTimeInterval {
 					Source = this,
-					DeltaT = _shiftTime - absTime,
+					DeltaT = ShiftTime - absTime,
 					GearboxPowerRequest = outTorque * outAngularVelocity
 				};
 			}
@@ -288,42 +292,43 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl
 		/// <item><term>else</term><description>Response from NextComponent.</description></item>
 		/// </list>
 		/// </returns>
-		private IResponse RequestGearEngaged(Second absTime, Second dt, NewtonMeter outTorque, PerSecond outAngularVelocity,
+		protected virtual IResponse RequestGearEngaged(Second absTime, Second dt, NewtonMeter outTorque,
+			PerSecond outAngularVelocity,
 			bool dryRun)
 		{
 			// Set a Gear if no gear was set and engineSpeed is not zero
-			if (_disengaged && !outAngularVelocity.IsEqual(0)) {
-				_disengaged = false;
+			if (Disengaged && !outAngularVelocity.IsEqual(0)) {
+				Disengaged = false;
 				if (DataBus.VehicleStopped) {
-					Gear = _strategy.InitGear(absTime, dt, outTorque, outAngularVelocity);
+					Gear = Strategy.InitGear(absTime, dt, outTorque, outAngularVelocity);
 				} else {
-					Gear = _strategy.Engage(absTime, dt, outTorque, outAngularVelocity);
+					Gear = Strategy.Engage(absTime, dt, outTorque, outAngularVelocity);
 				}
 
 				Log.Debug("Gearbox engaged gear {0}", Gear);
 			}
 
 			var inEngineSpeed = outAngularVelocity * Data.Gears[Gear].Ratio;
-			var inTorque = (outAngularVelocity.IsEqual(0))
+			var inTorque = outAngularVelocity.IsEqual(0)
 				? outTorque / Data.Gears[Gear].Ratio
 				: Data.Gears[Gear].LossMap.GetInTorque(inEngineSpeed, outTorque);
 
-			_powerLoss = inTorque * inEngineSpeed - outTorque * outAngularVelocity;
+			PowerLoss = inTorque * inEngineSpeed - outTorque * outAngularVelocity;
 
 			if (!inEngineSpeed.IsEqual(0)) {
-				_powerLossInertia = Formulas.InertiaPower(inEngineSpeed, _previousInAngularSpeed, Data.Inertia, dt);
-				inTorque += _powerLossInertia / inEngineSpeed;
+				PowerLossInertia = Formulas.InertiaPower(inEngineSpeed, PreviousInAngularSpeed, Data.Inertia, dt);
+				inTorque += PowerLossInertia / inEngineSpeed;
 			} else {
-				_powerLossInertia = 0.SI<Watt>();
+				PowerLossInertia = 0.SI<Watt>();
 			}
 
 			if (dryRun) {
 				if ((DataBus.DrivingBehavior == DrivingBehavior.Braking || DataBus.DrivingBehavior == DrivingBehavior.Coasting) &&
 					inEngineSpeed < DataBus.EngineIdleSpeed &&
 					DataBus.VehicleSpeed < Constants.SimulationSettings.VehicleStopClutchDisengageSpeed) {
-					_disengaged = true;
-					_shiftTime = absTime + dt;
-					_strategy.Disengage(absTime, dt, outTorque, outAngularVelocity);
+					Disengaged = true;
+					ShiftTime = absTime + dt;
+					Strategy.Disengage(absTime, dt, outTorque, outAngularVelocity);
 					Log.Debug("EngineSpeed is below IdleSpeed, Gearbox disengage!");
 					return new ResponseEngineSpeedTooLow() { Source = this, GearboxPowerRequest = outTorque * outAngularVelocity };
 				}
@@ -335,17 +340,17 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl
 			var shiftAllowed = !inEngineSpeed.IsEqual(0) && !DataBus.VehicleSpeed.IsEqual(0);
 
 			if (shiftAllowed) {
-				var shiftRequired = _strategy.ShiftRequired(absTime, dt, outTorque, outAngularVelocity, inTorque, inEngineSpeed,
-					Gear, _shiftTime + Data.TractionInterruption);
+				var shiftRequired = Strategy.ShiftRequired(absTime, dt, outTorque, outAngularVelocity, inTorque, inEngineSpeed,
+					Gear, ShiftTime + Data.TractionInterruption);
 
 				if (shiftRequired) {
-					_shiftTime = absTime + Data.TractionInterruption;
+					ShiftTime = absTime + Data.TractionInterruption;
 
 					Log.Debug("Gearbox is shifting. absTime: {0}, dt: {1}, shiftTime: {2}, out: ({3}, {4}), in: ({5}, {6})", absTime,
-						dt, _shiftTime, outTorque, outAngularVelocity, inTorque, inEngineSpeed);
+						dt, ShiftTime, outTorque, outAngularVelocity, inTorque, inEngineSpeed);
 
-					_disengaged = true;
-					_strategy.Disengage(absTime, dt, outTorque, outAngularVelocity);
+					Disengaged = true;
+					Strategy.Disengage(absTime, dt, outTorque, outAngularVelocity);
 					Log.Info("Gearbox disengaged");
 
 					return new ResponseGearShift {
@@ -359,7 +364,7 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl
 			var response = NextComponent.Request(absTime, dt, inTorque, inEngineSpeed);
 			response.GearboxPowerRequest = outTorque * outAngularVelocity;
 
-			_previousInAngularSpeed = inEngineSpeed;
+			PreviousInAngularSpeed = inEngineSpeed;
 			return response;
 		}
 
@@ -378,14 +383,14 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl
 
 		protected override void DoWriteModalResults(IModalDataContainer container)
 		{
-			container[ModalResultField.Gear] = _disengaged || DataBus.VehicleStopped ? 0 : Gear;
-			container[ModalResultField.PlossGB] = _powerLoss;
-			container[ModalResultField.PaGB] = _powerLossInertia;
+			container[ModalResultField.Gear] = Disengaged || DataBus.VehicleStopped ? 0 : Gear;
+			container[ModalResultField.PlossGB] = PowerLoss;
+			container[ModalResultField.PaGB] = PowerLossInertia;
 		}
 
 		protected override void DoCommitSimulationStep()
 		{
-			if (!_disengaged) {
+			if (!Disengaged) {
 				if (Data.Gears[Gear].LossMap.Extrapolated) {
 					// todo (MK, 2015-12-14): should we throw an interpolation error in EngineOnly Mode also?
 					Log.Warn("Gear {0} LossMap data was extrapolated: range for loss map is not sufficient.", Gear);
@@ -397,8 +402,8 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl
 				}
 			}
 
-			_powerLoss = null;
-			_powerLossInertia = null;
+			PowerLoss = null;
+			PowerLossInertia = null;
 		}
 
 		#endregion
diff --git a/VectoCore/Models/SimulationComponent/Impl/ManualGearbox.cs b/VectoCore/Models/SimulationComponent/Impl/ManualGearbox.cs
new file mode 100644
index 0000000000..8e91a5c4f5
--- /dev/null
+++ b/VectoCore/Models/SimulationComponent/Impl/ManualGearbox.cs
@@ -0,0 +1,122 @@
+/*
+* Copyright 2015 European Union
+*
+* Licensed under the EUPL (the "Licence");
+* You may not use this work except in compliance with the Licence.
+* You may obtain a copy of the Licence at:
+*
+* http://ec.europa.eu/idabc/eupl5
+*
+* Unless required by applicable law or agreed to in writing, software 
+* distributed under the Licence is distributed on an "AS IS" basis,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the Licence for the specific language governing permissions and 
+* limitations under the Licence.
+*/
+
+using TUGraz.VectoCore.Configuration;
+using TUGraz.VectoCore.Models.Connector.Ports;
+using TUGraz.VectoCore.Models.Connector.Ports.Impl;
+using TUGraz.VectoCore.Models.Simulation;
+using TUGraz.VectoCore.Models.SimulationComponent.Data;
+using TUGraz.VectoCore.Utils;
+
+namespace TUGraz.VectoCore.Models.SimulationComponent.Impl
+{
+	public class ManualGearbox : Gearbox
+	{
+		public ManualGearbox(IVehicleContainer container, GearboxData gearboxData = null) : base(container, gearboxData) {}
+
+		#region ITnOutPort
+
+		public override IResponse Initialize(NewtonMeter outTorque, PerSecond outAngularVelocity)
+		{
+			var dt = Constants.SimulationSettings.TargetTimeInterval;
+			ShiftTime = double.NegativeInfinity.SI<Second>();
+			PowerLoss = null;
+
+			if (Disengaged) {
+				Gear = DataBus.Gear;
+			}
+
+			var inAngularVelocity = outAngularVelocity * Data.Gears[Gear].Ratio;
+			var inTorque = Data.Gears[Gear].LossMap.GetInTorque(inAngularVelocity, outTorque);
+
+			var torqueLossInertia = outAngularVelocity.IsEqual(0)
+				? 0.SI<NewtonMeter>()
+				: Formulas.InertiaPower(inAngularVelocity, PreviousInAngularSpeed, Data.Inertia, dt) / inAngularVelocity;
+
+			inTorque += torqueLossInertia;
+
+			var response = NextComponent.Initialize(inTorque, inAngularVelocity);
+			if (response is ResponseSuccess) {
+				PreviousInAngularSpeed = inAngularVelocity;
+				Disengaged = false;
+			}
+
+			return response;
+		}
+
+
+		/// <summary>
+		/// Requests the gearbox in engaged mode. Sets the gear if no gear was set previously.
+		/// </summary>
+		/// <returns>
+		/// <list type="bullet">
+		/// <item><term>ResponseGearShift</term><description>if a shift is needed.</description></item>
+		/// <item><term>else</term><description>Response from NextComponent.</description></item>
+		/// </list>
+		/// </returns>
+		protected override IResponse RequestGearEngaged(Second absTime, Second dt, NewtonMeter outTorque,
+			PerSecond outAngularVelocity,
+			bool dryRun)
+		{
+			// Set a Gear if no gear was set and engineSpeed is not zero
+			if (Disengaged && !outAngularVelocity.IsEqual(0)) {
+				Disengaged = false;
+				Gear = DataBus.Gear;
+				Log.Debug("Gearbox engaged gear {0}", Gear);
+			}
+
+			var inEngineSpeed = outAngularVelocity * Data.Gears[Gear].Ratio;
+			var inTorque = outAngularVelocity.IsEqual(0)
+				? outTorque / Data.Gears[Gear].Ratio
+				: Data.Gears[Gear].LossMap.GetInTorque(inEngineSpeed, outTorque);
+
+			PowerLoss = inTorque * inEngineSpeed - outTorque * outAngularVelocity;
+
+			if (!inEngineSpeed.IsEqual(0)) {
+				PowerLossInertia = Formulas.InertiaPower(inEngineSpeed, PreviousInAngularSpeed, Data.Inertia, dt);
+				inTorque += PowerLossInertia / inEngineSpeed;
+			} else {
+				PowerLossInertia = 0.SI<Watt>();
+			}
+
+			var shiftRequired = Gear != DataBus.Gear;
+
+			if (shiftRequired) {
+				ShiftTime = absTime + Data.TractionInterruption;
+
+				Log.Debug("Gearbox is shifting. absTime: {0}, dt: {1}, shiftTime: {2}, out: ({3}, {4}), in: ({5}, {6})", absTime, dt,
+					ShiftTime, outTorque, outAngularVelocity, inTorque, inEngineSpeed);
+
+				Disengaged = true;
+				Log.Info("Gearbox disengaged");
+
+				return new ResponseGearShift {
+					Source = this,
+					SimulationInterval = Data.TractionInterruption,
+					GearboxPowerRequest = outTorque * outAngularVelocity
+				};
+			}
+
+			var response = NextComponent.Request(absTime, dt, inTorque, inEngineSpeed);
+			response.GearboxPowerRequest = outTorque * outAngularVelocity;
+
+			PreviousInAngularSpeed = inEngineSpeed;
+			return response;
+		}
+
+		#endregion
+	}
+}
\ No newline at end of file
diff --git a/VectoCore/Models/SimulationComponent/Impl/PowertrainDrivingCycle.cs b/VectoCore/Models/SimulationComponent/Impl/PowertrainDrivingCycle.cs
index 8c6c373472..e1dfeff2de 100644
--- a/VectoCore/Models/SimulationComponent/Impl/PowertrainDrivingCycle.cs
+++ b/VectoCore/Models/SimulationComponent/Impl/PowertrainDrivingCycle.cs
@@ -30,7 +30,7 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl
 	/// <summary>
 	/// Represents a driving cycle which directly is connected to the powertrain (e.g. engine, or axle gear).
 	/// </summary>
-	public class PowertrainDrivingCycle : VectoSimulationComponent, IDrivingCycleInfo, IEngineOnlySimulation, ITnInPort,
+	public class PowertrainDrivingCycle : VectoSimulationComponent, IPowertrainSimulation, ITnInPort,
 		ISimulationOutPort
 	{
 		protected DrivingCycleData Data;
diff --git a/VectoCore/VectoCore.csproj b/VectoCore/VectoCore.csproj
index 81706a3d75..d070f09a54 100644
--- a/VectoCore/VectoCore.csproj
+++ b/VectoCore/VectoCore.csproj
@@ -246,12 +246,12 @@
     <Compile Include="Models\SimulationComponent\Impl\Auxiliary.cs" />
     <Compile Include="Models\SimulationComponent\Impl\TimeBasedDrivingCycle.cs" />
     <Compile Include="Models\SimulationComponent\Impl\CombustionEngine.cs" />
-    <Compile Include="Models\SimulationComponent\Impl\EngineOnlyGearbox.cs" />
+    <Compile Include="Models\SimulationComponent\Impl\ManualGearbox.cs" />
     <Compile Include="Models\SimulationComponent\Impl\Gearbox.cs" />
     <Compile Include="Models\SimulationComponent\Impl\Wheels.cs" />
     <Compile Include="Models\SimulationComponent\IWheels.cs" />
     <Compile Include="Models\SimulationComponent\VectoSimulationComponent.cs" />
-    <Compile Include="Models\SimulationComponent\Impl\EngineOnlyDrivingCycle.cs" />
+    <Compile Include="Models\SimulationComponent\Impl\PowertrainDrivingCycle.cs" />
     <Compile Include="Models\Simulation\Data\ModalResult.cs">
       <SubType>Component</SubType>
     </Compile>
diff --git a/VectoCoreTest/Integration/EngineOnlyCycle/EngineOnlyCycleTest.cs b/VectoCoreTest/Integration/EngineOnlyCycle/EngineOnlyCycleTest.cs
index ac7acf2d6f..adf7298e70 100644
--- a/VectoCoreTest/Integration/EngineOnlyCycle/EngineOnlyCycleTest.cs
+++ b/VectoCoreTest/Integration/EngineOnlyCycle/EngineOnlyCycleTest.cs
@@ -14,9 +14,7 @@
 * limitations under the Licence.
 */
 
-using System.Data;
 using System.IO;
-using System.Linq;
 using Microsoft.VisualStudio.TestTools.UnitTesting;
 using TUGraz.VectoCore.Configuration;
 using TUGraz.VectoCore.InputData.Reader;
@@ -52,7 +50,7 @@ namespace TUGraz.VectoCore.Tests.Integration.EngineOnlyCycle
 
 			var aux = new Auxiliary(vehicle);
 			aux.AddDirect(cycle);
-			var gearbox = new EngineOnlyGearbox(vehicle);
+			var gearbox = new ManualGearbox(vehicle);
 
 			var engine = new EngineOnlyCombustionEngine(vehicle, engineData);
 
@@ -91,7 +89,7 @@ namespace TUGraz.VectoCore.Tests.Integration.EngineOnlyCycle
 
 			var vehicleContainer = new VehicleContainer();
 
-			var gearbox = new EngineOnlyGearbox(vehicleContainer);
+			var gearbox = new ManualGearbox(vehicleContainer);
 			var engine = new CombustionEngine(vehicleContainer,
 				MockSimulationDataFactory.CreateEngineDataFromFile(EngineFile));
 
diff --git a/VectoCoreTest/Models/Simulation/PowerTrainBuilderTest.cs b/VectoCoreTest/Models/Simulation/PowerTrainBuilderTest.cs
index 40c569194b..aaca466c8f 100644
--- a/VectoCoreTest/Models/Simulation/PowerTrainBuilderTest.cs
+++ b/VectoCoreTest/Models/Simulation/PowerTrainBuilderTest.cs
@@ -39,7 +39,7 @@ namespace TUGraz.VectoCore.Tests.Models.Simulation
 			var runData = reader.NextRun().First();
 
 			var writer = new MockModalDataContainer();
-			var builder = new PowertrainBuilder(writer, false);
+			var builder = new PowertrainBuilder(writer);
 
 			var powerTrain = builder.Build(runData);
 
diff --git a/VectoCoreTest/Models/SimulationComponent/CombustionEngineTest.cs b/VectoCoreTest/Models/SimulationComponent/CombustionEngineTest.cs
index 48a4a7cd6c..fdc15a653a 100644
--- a/VectoCoreTest/Models/SimulationComponent/CombustionEngineTest.cs
+++ b/VectoCoreTest/Models/SimulationComponent/CombustionEngineTest.cs
@@ -22,12 +22,10 @@ using System.Linq;
 using System.Reflection;
 using Microsoft.VisualStudio.TestTools.UnitTesting;
 using TUGraz.VectoCore.Configuration;
-using TUGraz.VectoCore.Exceptions;
 using TUGraz.VectoCore.Models.Connector.Ports;
 using TUGraz.VectoCore.Models.Connector.Ports.Impl;
 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.Utils;
 using TUGraz.VectoCore.Utils;
@@ -87,7 +85,7 @@ namespace TUGraz.VectoCore.Tests.Models.SimulationComponent
 			var engineData = MockSimulationDataFactory.CreateEngineDataFromFile(CoachEngine);
 			var engine = new CombustionEngine(vehicle, engineData);
 
-			new EngineOnlyGearbox(vehicle);
+			new ManualGearbox(vehicle);
 
 			var port = engine.OutPort();
 
@@ -105,7 +103,7 @@ namespace TUGraz.VectoCore.Tests.Models.SimulationComponent
 			var vehicle = new VehicleContainer();
 			var engineData = MockSimulationDataFactory.CreateEngineDataFromFile(CoachEngine);
 			var engine = new CombustionEngine(vehicle, engineData);
-			var gearbox = new EngineOnlyGearbox(vehicle);
+			var gearbox = new ManualGearbox(vehicle);
 			var port = engine.OutPort();
 
 			var absTime = 0.SI<Second>();
@@ -134,7 +132,6 @@ namespace TUGraz.VectoCore.Tests.Models.SimulationComponent
 			absTime += dt;
 
 			var power = new[] { 569.3641, 4264.177 };
-			;
 			for (var i = 0; i < 2; i++) {
 				port.Request(absTime, dt, Formulas.PowerToTorque(power[i].SI<Watt>(), engineSpeed), engineSpeed);
 				engine.CommitSimulationStep(dataWriter);
@@ -157,7 +154,6 @@ namespace TUGraz.VectoCore.Tests.Models.SimulationComponent
 
 			Assert.AreEqual(-7108.32, ((SI)dataWriter[ModalResultField.PaEng]).Value(), 0.001);
 			dataWriter.CommitSimulationStep(absTime, dt);
-			absTime += dt;
 
 			dataWriter.Data.WriteToFile(@"test1.csv");
 		}
@@ -169,7 +165,7 @@ namespace TUGraz.VectoCore.Tests.Models.SimulationComponent
 		public void TestEngineFullLoadJump()
 		{
 			var vehicleContainer = new VehicleContainer();
-			var gearbox = new EngineOnlyGearbox(vehicleContainer);
+			var gearbox = new ManualGearbox(vehicleContainer);
 			var engineData =
 				MockSimulationDataFactory.CreateEngineDataFromFile(
 					TestContext.DataRow["EngineFile"].ToString());
@@ -311,10 +307,10 @@ namespace TUGraz.VectoCore.Tests.Models.SimulationComponent
 			container.CommitSimulationStep(absTime, dt);
 			absTime += dt;
 
-			var engineSpeed = new PerSecond[] { 800.RPMtoRad(), 800.RPMtoRad(), 560.RPMtoRad(), 560.RPMtoRad() };
-			var enginePower = new Watt[] { 5000.SI<Watt>(), 5000.SI<Watt>(), -8601.6308.SI<Watt>(), 5000.SI<Watt>() };
+			var engineSpeed = new[] { 800.RPMtoRad(), 800.RPMtoRad(), 560.RPMtoRad(), 560.RPMtoRad() };
+			var enginePower = new[] { 5000.SI<Watt>(), 5000.SI<Watt>(), -8601.6308.SI<Watt>(), 5000.SI<Watt>() };
 
-			for (var i = 0; i < engineSpeed.Count(); i++) {
+			for (var i = 0; i < engineSpeed.Length; i++) {
 				torque = 0.SI<NewtonMeter>();
 
 				response = requestPort.Request(absTime, dt, torque, null);
@@ -371,13 +367,13 @@ namespace TUGraz.VectoCore.Tests.Models.SimulationComponent
 			container.CommitSimulationStep(absTime, dt);
 			absTime += dt;
 
-			var engineSpeed = new PerSecond[] {
+			var engineSpeed = new[] {
 				1680.RPMtoRad(), 1680.RPMtoRad(), 1467.014.RPMtoRad(), 1272.8658.RPMtoRad(), 1090.989.RPMtoRad(),
 				915.3533.RPMtoRad(), 738.599.RPMtoRad(), 560.RPMtoRad(), 560.RPMtoRad(), 560.RPMtoRad(), 560.RPMtoRad(),
 				560.RPMtoRad(), 560.RPMtoRad(), 560.RPMtoRad(), 560.RPMtoRad(), 560.RPMtoRad(), 560.RPMtoRad(), 560.RPMtoRad(),
 				560.RPMtoRad()
 			};
-			var enginePower = new Watt[] {
+			var enginePower = new[] {
 				5000.SI<Watt>(), 5000.SI<Watt>(), -32832.8834.SI<Watt>(), -25025.1308.SI<Watt>(), -19267.0360.SI<Watt>(),
 				-14890.1962.SI<Watt>(), -11500.7991.SI<Watt>(), -8091.0577.SI<Watt>(), 5000.SI<Watt>(), 5000.SI<Watt>(),
 				5000.SI<Watt>(), 5000.SI<Watt>(), 5000.SI<Watt>(), 5000.SI<Watt>(), 5000.SI<Watt>(), 5000.SI<Watt>(),
@@ -385,7 +381,7 @@ namespace TUGraz.VectoCore.Tests.Models.SimulationComponent
 			};
 
 			var engSpeedResults = new List<dynamic>();
-			for (var i = 0; i < engineSpeed.Count(); i++) {
+			for (var i = 0; i < engineSpeed.Length; i++) {
 				torque = 0.SI<NewtonMeter>();
 
 				response = requestPort.Request(absTime, dt, torque, null);
-- 
GitLab