diff --git a/VectoCommon/VectoCommon/Utils/VectoMath.cs b/VectoCommon/VectoCommon/Utils/VectoMath.cs
index e3c10c4302dca7c8666acebd50fc14500329ec2d..f488301deff3abe1ba54ea3a72f3d846e2576ff8 100644
--- a/VectoCommon/VectoCommon/Utils/VectoMath.cs
+++ b/VectoCommon/VectoCommon/Utils/VectoMath.cs
@@ -122,6 +122,12 @@ namespace TUGraz.VectoCommon.Utils
 			return Interpolate(p1.X, p2.X, p1.Y, p2.Y, x);
 		}
 
+		[MethodImpl(MethodImplOptions.AggressiveInlining)]
+		public static double Interpolate(Edge edge, double x)
+		{
+			return Interpolate(edge.P1, edge.P2, x);
+		}
+
 		/// <summary>
 		/// Linearly interpolates a value between two points.
 		/// </summary>
@@ -332,6 +338,8 @@ namespace TUGraz.VectoCommon.Utils
 			return retVal;
 		}
 
+		
+
 		[DebuggerStepThrough]
 		[MethodImpl(MethodImplOptions.AggressiveInlining)]
 		public static T Ceiling<T>(T si) where T : SIBase<T>
diff --git a/VectoCore/VectoCore/Models/SimulationComponent/Data/Gearbox/TorqueConverterData.cs b/VectoCore/VectoCore/Models/SimulationComponent/Data/Gearbox/TorqueConverterData.cs
index 18b7a47d7e104470f2445ad1a3b93e08e013c09f..8b38730ef69a83f9abaa0a260ca1023c1e7d814d 100644
--- a/VectoCore/VectoCore/Models/SimulationComponent/Data/Gearbox/TorqueConverterData.cs
+++ b/VectoCore/VectoCore/Models/SimulationComponent/Data/Gearbox/TorqueConverterData.cs
@@ -29,264 +29,287 @@
 *   Martin Rexeis, rexeis@ivt.tugraz.at, IVT, Graz University of Technology
 */
 
-using System;
-using System.Collections.Generic;
-using System.ComponentModel.DataAnnotations;
-using System.Linq;
-using TUGraz.VectoCommon.Exceptions;
-using TUGraz.VectoCommon.Utils;
-
-namespace TUGraz.VectoCore.Models.SimulationComponent.Data.Gearbox
-{
-	[CustomValidation(typeof(TorqueConverterData), "ValidateData")]
-	public class TorqueConverterData : SimulationComponentData
-	{
-		protected internal readonly TorqueConverterEntry[] TorqueConverterEntries;
-
-		[Required, SIRange(0, double.MaxValue)]
-		public PerSecond ReferenceSpeed { get; protected internal set; }
-
-		[Required, SIRange(0, double.MaxValue)]
-		public MeterPerSquareSecond CLUpshiftMinAcceleration { get; internal set; }
-
-		[Required, SIRange(0, double.MaxValue)]
-		public MeterPerSquareSecond CCUpshiftMinAcceleration { get; internal set; }
-
-		[Required, SIRange(0, double.MaxValue)]
-		public PerSecond TorqueConverterSpeedLimit { get; protected internal set; }
-
-		internal double RequiredSpeedRatio; // only used for validation!
-
-		protected internal TorqueConverterData(IEnumerable<TorqueConverterEntry> torqueConverterEntries,
-			PerSecond referenceSpeed, PerSecond maxRpm, MeterPerSquareSecond clUpshiftMinAcceleration,
-			MeterPerSquareSecond ccUpshiftMinAcceleration)
-		{
-			TorqueConverterEntries = torqueConverterEntries.ToArray();
-			ReferenceSpeed = referenceSpeed;
-			TorqueConverterSpeedLimit = maxRpm;
-			CLUpshiftMinAcceleration = clUpshiftMinAcceleration;
-			CCUpshiftMinAcceleration = ccUpshiftMinAcceleration;
-		}
-
-		/// <summary>
-		/// find an operating point for the torque converter
-		/// 
-		/// find the input speed and input torque for the given output torque and output speed. 
-		/// </summary>
-		/// <param name="torqueOut">torque provided at the TC output</param>
-		/// <param name="angularSpeedOut">angular speed at the TC output</param>
-		/// <param name="minSpeed"></param>
-		/// <returns></returns>
-		public IList<TorqueConverterOperatingPoint> FindOperatingPoint(NewtonMeter torqueOut, PerSecond angularSpeedOut,
-			PerSecond minSpeed)
-		{
-			var solutions = new List<double>();
-			var mpNorm = ReferenceSpeed.Value();
-
-			var min = minSpeed == null ? 0 : minSpeed.Value();
-
-			// Find analytic solution for torque converter operating point
-			// mu = f(nu) = f(n_out / n_in) = T_out / T_in
-			// MP1000 = f(nu) = f(n_out / n_in)
-			// Tq_in = MP1000(nu) * (n_in/1000)^2 = T_out / mu
-			//
-			// mu(nu) and MP1000(nu) are provided as piecewise linear functions (y = k*x+d)
-			// solving the equation above for n_in results in a quadratic equation
-			foreach (var segment in TorqueConverterEntries.Pairwise(Tuple.Create)) {
-				var mpEdge = Edge.Create(new Point(segment.Item1.SpeedRatio, segment.Item1.Torque.Value()),
-					new Point(segment.Item2.SpeedRatio, segment.Item2.Torque.Value()));
-				var muEdge = Edge.Create(new Point(segment.Item1.SpeedRatio, segment.Item1.TorqueRatio),
-					new Point(segment.Item2.SpeedRatio, segment.Item2.TorqueRatio));
-
-				var a = muEdge.OffsetXY * mpEdge.OffsetXY / (mpNorm * mpNorm);
-				var b = angularSpeedOut.Value() * (muEdge.SlopeXY * mpEdge.OffsetXY + mpEdge.SlopeXY * muEdge.OffsetXY) /
-						(mpNorm * mpNorm);
-				var c = angularSpeedOut.Value() * angularSpeedOut.Value() * mpEdge.SlopeXY * muEdge.SlopeXY / (mpNorm * mpNorm) -
-						torqueOut.Value();
-
-				solutions.AddRange(VectoMath.QuadraticEquationSolver(a, b, c).Where(x => {
-					var ratio = angularSpeedOut.Value() / x;
-					return x > min && muEdge.P1.X <= ratio && ratio < muEdge.P2.X;
-				}));
-			}
-
-			if (solutions.Count == 0) {
-				Log.Debug(
-					"TorqueConverterData::FindOperatingPoint No solution for input torque/input speed found! n_out: {0}, tq_out: {1}",
-					angularSpeedOut, torqueOut);
-			}
-
-			return solutions.Select(sol => {
-				var s = sol.SI<PerSecond>();
-				var mu = MuLookup(angularSpeedOut / s);
-				return new TorqueConverterOperatingPoint {
-					OutTorque = torqueOut,
-					OutAngularVelocity = angularSpeedOut,
-					InAngularVelocity = s,
-					SpeedRatio = angularSpeedOut / s,
-					TorqueRatio = mu,
-					InTorque = torqueOut / mu,
-				};
-			}).ToList();
-		}
-
-		/// <summary>
-		/// find an operating point for the torque converter
-		/// 
-		/// find the input torque and output torque for the given input and output speeds.
-		/// Computes the speed ratio nu of input and output. Interpolates MP1000 and mu, Computes input torque and output torque
-		/// </summary>
-		/// <param name="inAngularVelocity">speed at the input of the TC</param>
-		/// <param name="outAngularVelocity">speed at the output of the TC</param>
-		/// <returns></returns>
-		public TorqueConverterOperatingPoint FindOperatingPoint(PerSecond inAngularVelocity, PerSecond outAngularVelocity)
-		{
-			var retVal = new TorqueConverterOperatingPoint {
-				InAngularVelocity = inAngularVelocity,
-				OutAngularVelocity = outAngularVelocity,
-				SpeedRatio = outAngularVelocity.Value() / inAngularVelocity.Value(),
-			};
-
-			foreach (var segment in TorqueConverterEntries.Pairwise()) {
-				if (retVal.SpeedRatio.IsBetween(segment.Item1.SpeedRatio, segment.Item2.SpeedRatio)) {
-					var mpTorque = segment.Interpolate(x => x.SpeedRatio, y => y.Torque, retVal.SpeedRatio);
-					retVal.TorqueRatio = segment.Interpolate(x => x.SpeedRatio, y => y.TorqueRatio, retVal.SpeedRatio);
-					retVal.InTorque = mpTorque * (inAngularVelocity * inAngularVelocity / ReferenceSpeed / ReferenceSpeed).Value();
-					retVal.OutTorque = retVal.InTorque * retVal.TorqueRatio;
-					return retVal;
-				}
-			}
-
-			// No solution found. Throw Error
-			var nu = outAngularVelocity / inAngularVelocity;
-			var nuMax = TorqueConverterEntries.Last().SpeedRatio;
-
-			if (nu.IsGreater(nuMax)) {
-				throw new VectoException(
-					"Torque Converter: Range of torque converter data is not sufficient. Required nu: {0}, Got nu_max: {1}", nu, nuMax);
-			}
-
-			throw new VectoException(
-				"Torque Converter: No solution for output speed/input speed found! n_out: {0}, n_in: {1}, nu: {2}, nu_max: {3}",
-				outAngularVelocity, inAngularVelocity, nu, nuMax);
-		}
-
-		/// <summary>
-		/// find an operating point for the torque converter
-		/// 
-		/// find the output torque and output speed for the given input torque and input speed
-		/// </summary>
-		/// <param name="inTorque"></param>
-		/// <param name="inAngularVelocity"></param>
-		/// <param name="outAngularSpeedEstimated"></param>
-		/// <returns></returns>
-		public TorqueConverterOperatingPoint FindOperatingPointForward(NewtonMeter inTorque, PerSecond inAngularVelocity,
-			PerSecond outAngularSpeedEstimated)
-		{
-			var referenceTorque = inTorque.Value() / inAngularVelocity.Value() / inAngularVelocity.Value() *
-								ReferenceSpeed.Value() * ReferenceSpeed.Value();
-			var maxTorque = TorqueConverterEntries.Max(x => x.Torque.Value());
-			if (referenceTorque.IsGreaterOrEqual(maxTorque)) {
-				referenceTorque = outAngularSpeedEstimated != null
-					? ReferenceTorqueLookup(outAngularSpeedEstimated / inAngularVelocity).Value()
-					: 0.9 * maxTorque;
-			}
-
-			var solutions = new List<double>();
-			foreach (var edge in TorqueConverterEntries.Pairwise(
-				(p1, p2) => Edge.Create(new Point(p1.SpeedRatio, p1.Torque.Value()), new Point(p2.SpeedRatio, p2.Torque.Value())))) {
-				var x = (referenceTorque - edge.OffsetXY) / edge.SlopeXY;
-				if (x >= edge.P1.X && x < edge.P2.X) {
-					solutions.Add(x * inAngularVelocity.Value());
-				}
-			}
-			if (solutions.Count == 0) {
-				throw new VectoSimulationException(
-					"Torque Converter: Failed to find operating point for inputTorque/inputSpeed! n_in: {0}, tq_in: {1}",
-					inAngularVelocity, inTorque);
-			}
-			return FindOperatingPoint(inAngularVelocity, solutions.Max().SI<PerSecond>());
-		}
-
-		public TorqueConverterOperatingPoint FindOperatingPointForPowerDemand(Watt power, PerSecond prevInputSpeed,
-			PerSecond nextOutputSpeed, KilogramSquareMeter inertia, Second dt, Watt previousPower)
-		{
-			var solutions = new List<double>();
-			var mpNorm = ReferenceSpeed.Value();
-
-			foreach (var segment in TorqueConverterEntries.Pairwise(Tuple.Create)) {
-				var mpEdge = Edge.Create(new Point(segment.Item1.SpeedRatio, segment.Item1.Torque.Value()),
-					new Point(segment.Item2.SpeedRatio, segment.Item2.Torque.Value()));
-
-				var a = mpEdge.OffsetXY / (2 * mpNorm * mpNorm);
-				var b = inertia.Value() / (2 * dt.Value()) + mpEdge.SlopeXY * nextOutputSpeed.Value() / (2 * mpNorm * mpNorm);
-				var c = 0;
-				var d = -inertia.Value() * prevInputSpeed.Value() * prevInputSpeed.Value() / (2 * dt.Value()) - power.Value() +
-						previousPower.Value() / 2;
-				var sol = VectoMath.CubicEquationSolver(a, b, c, d);
-
-				var selected = sol.Where(x => x > 0 && nextOutputSpeed / x >= mpEdge.P1.X && nextOutputSpeed / x < mpEdge.P2.X);
-				solutions.AddRange(selected);
-			}
-
-			if (solutions.Count == 0) {
-				throw new VectoException(
-					"Failed to find operating point for power {0}, prevInputSpeed {1}, nextOutputSpeed {2}", power,
-					prevInputSpeed, nextOutputSpeed);
-			}
-			solutions.Sort();
-
-			return FindOperatingPoint(solutions.First().SI<PerSecond>(), nextOutputSpeed);
-		}
-
-		private double MuLookup(double speedRatio)
-		{
-			return TorqueConverterEntries.Interpolate(x => x.SpeedRatio, y => y.TorqueRatio, speedRatio);
-		}
-
-		private NewtonMeter ReferenceTorqueLookup(double speedRatio)
-		{
-			return TorqueConverterEntries.Interpolate(x => x.SpeedRatio, y => y.Torque, speedRatio);
-		}
-
-		// ReSharper disable once UnusedMember.Global -- used by validation
-		public static ValidationResult ValidateData(TorqueConverterData data, ValidationContext validationContext)
-		{
-			var min = data.TorqueConverterEntries.Min(e => e.SpeedRatio);
-			var max = data.TorqueConverterEntries.Max(e => e.SpeedRatio);
-			if (min > 0 || max < data.RequiredSpeedRatio) {
-				return new ValidationResult(string.Format(
-					"Torque Converter Data invalid - Speedratio has to cover the range from 0.0 to {2}: given data only goes from {0} to {1}",
-					min, max, data.RequiredSpeedRatio));
-			}
-
-			return ValidationResult.Success;
-		}
-	}
-
-	public class TorqueConverterOperatingPoint
-	{
-		public PerSecond OutAngularVelocity;
-		public NewtonMeter OutTorque;
-
-		public PerSecond InAngularVelocity;
-		public NewtonMeter InTorque;
-
-		public double SpeedRatio;
-		public double TorqueRatio;
-		public bool Creeping;
-
-		public override string ToString()
-		{
-			return string.Format("n_out: {0}, n_in: {1}, tq_out: {2}, tq_in {3}, nu: {4}, my: {5}", OutAngularVelocity,
-				InAngularVelocity, OutTorque, InTorque, SpeedRatio, TorqueRatio);
-		}
-	}
-
-	public class TorqueConverterEntry
-	{
-		public double SpeedRatio;
-		public NewtonMeter Torque;
-		public double TorqueRatio;
-	}
+using System;
+using System.Collections.Generic;
+using System.ComponentModel.DataAnnotations;
+using System.Linq;
+using TUGraz.VectoCommon.Exceptions;
+using TUGraz.VectoCommon.Utils;
+using TUGraz.VectoCore.Models.Declaration;
+
+namespace TUGraz.VectoCore.Models.SimulationComponent.Data.Gearbox
+{
+	[CustomValidation(typeof(TorqueConverterData), "ValidateData")]
+	public class TorqueConverterData : SimulationComponentData
+	{
+		protected internal readonly TorqueConverterEntry[] TorqueConverterEntries;
+
+		[Required, SIRange(0, double.MaxValue)]
+		public PerSecond ReferenceSpeed { get; protected internal set; }
+
+		[Required, SIRange(0, double.MaxValue)]
+		public MeterPerSquareSecond CLUpshiftMinAcceleration { get; internal set; }
+
+		[Required, SIRange(0, double.MaxValue)]
+		public MeterPerSquareSecond CCUpshiftMinAcceleration { get; internal set; }
+
+		[Required, SIRange(0, double.MaxValue)]
+		public PerSecond TorqueConverterSpeedLimit { get; protected internal set; }
+
+		internal double RequiredSpeedRatio; // only used for validation!
+
+		protected internal TorqueConverterData(IEnumerable<TorqueConverterEntry> torqueConverterEntries,
+			PerSecond referenceSpeed, PerSecond maxRpm, MeterPerSquareSecond clUpshiftMinAcceleration,
+			MeterPerSquareSecond ccUpshiftMinAcceleration)
+		{
+			TorqueConverterEntries = torqueConverterEntries.ToArray();
+			ReferenceSpeed = referenceSpeed;
+			TorqueConverterSpeedLimit = maxRpm;
+			CLUpshiftMinAcceleration = clUpshiftMinAcceleration;
+			CCUpshiftMinAcceleration = ccUpshiftMinAcceleration;
+		}
+
+		/// <summary>
+		/// find an operating point for the torque converter
+		/// 
+		/// find the input speed and input torque for the given output torque and output speed. 
+		/// </summary>
+		/// <param name="torqueOut">torque provided at the TC output</param>
+		/// <param name="angularSpeedOut">angular speed at the TC output</param>
+		/// <param name="minSpeed"></param>
+		/// <returns></returns>
+		public IList<TorqueConverterOperatingPoint> FindOperatingPoint(NewtonMeter torqueOut, PerSecond angularSpeedOut,
+			PerSecond minSpeed)
+		{
+			var solutions = new List<double>();
+			var mpNorm = ReferenceSpeed.Value();
+
+			var min = minSpeed == null ? 0 : minSpeed.Value();
+
+			// Find analytic solution for torque converter operating point
+			// mu = f(nu) = f(n_out / n_in) = T_out / T_in
+			// MP1000 = f(nu) = f(n_out / n_in)
+			// Tq_in = MP1000(nu) * (n_in/1000)^2 = T_out / mu
+			//
+			// mu(nu) and MP1000(nu) are provided as piecewise linear functions (y = k*x+d)
+			// solving the equation above for n_in results in a quadratic equation
+			foreach (var segment in TorqueConverterEntries.Pairwise(Tuple.Create)) {
+				var mpEdge = Edge.Create(new Point(segment.Item1.SpeedRatio, segment.Item1.Torque.Value()),
+					new Point(segment.Item2.SpeedRatio, segment.Item2.Torque.Value()));
+				var muEdge = Edge.Create(new Point(segment.Item1.SpeedRatio, segment.Item1.TorqueRatio),
+					new Point(segment.Item2.SpeedRatio, segment.Item2.TorqueRatio));
+
+				var a = muEdge.OffsetXY * mpEdge.OffsetXY / (mpNorm * mpNorm);
+				var b = angularSpeedOut.Value() * (muEdge.SlopeXY * mpEdge.OffsetXY + mpEdge.SlopeXY * muEdge.OffsetXY) /
+						(mpNorm * mpNorm);
+				var c = angularSpeedOut.Value() * angularSpeedOut.Value() * mpEdge.SlopeXY * muEdge.SlopeXY / (mpNorm * mpNorm) -
+						torqueOut.Value();
+
+				solutions.AddRange(VectoMath.QuadraticEquationSolver(a, b, c).Where(x => {
+					var ratio = angularSpeedOut.Value() / x;
+					return x > min && muEdge.P1.X <= ratio && ratio < muEdge.P2.X;
+				}));
+			}
+
+			if (solutions.Count == 0) {
+				Log.Debug(
+					"TorqueConverterData::FindOperatingPoint No solution for input torque/input speed found! n_out: {0}, tq_out: {1}",
+					angularSpeedOut, torqueOut);
+			}
+
+			return solutions.Select(sol => {
+				var s = sol.SI<PerSecond>();
+				var mu = MuLookup(angularSpeedOut / s);
+				return new TorqueConverterOperatingPoint {
+					OutTorque = torqueOut,
+					OutAngularVelocity = angularSpeedOut,
+					InAngularVelocity = s,
+					SpeedRatio = angularSpeedOut / s,
+					TorqueRatio = mu,
+					InTorque = torqueOut / mu,
+				};
+			}).ToList();
+		}
+
+		/// <summary>
+		/// find an operating point for the torque converter
+		/// 
+		/// find the input torque and output torque for the given input and output speeds.
+		/// Computes the speed ratio nu of input and output. Interpolates MP1000 and mu, Computes input torque and output torque
+		/// </summary>
+		/// <param name="inAngularVelocity">speed at the input of the TC</param>
+		/// <param name="outAngularVelocity">speed at the output of the TC</param>
+		/// <returns></returns>
+		public TorqueConverterOperatingPoint FindOperatingPoint(PerSecond inAngularVelocity, PerSecond outAngularVelocity)
+		{
+			var retVal = new TorqueConverterOperatingPoint {
+				InAngularVelocity = inAngularVelocity,
+				OutAngularVelocity = outAngularVelocity,
+				SpeedRatio = outAngularVelocity.Value() / inAngularVelocity.Value(),
+			};
+
+			foreach (var segment in TorqueConverterEntries.Pairwise()) {
+				if (retVal.SpeedRatio.IsBetween(segment.Item1.SpeedRatio, segment.Item2.SpeedRatio)) {
+					var mpTorque = segment.Interpolate(x => x.SpeedRatio, y => y.Torque, retVal.SpeedRatio);
+					retVal.TorqueRatio = segment.Interpolate(x => x.SpeedRatio, y => y.TorqueRatio, retVal.SpeedRatio);
+					retVal.InTorque = mpTorque * (inAngularVelocity * inAngularVelocity / ReferenceSpeed / ReferenceSpeed).Value();
+					retVal.OutTorque = retVal.InTorque * retVal.TorqueRatio;
+					return retVal;
+				}
+			}
+
+			// No solution found. Throw Error
+			var nu = outAngularVelocity / inAngularVelocity;
+			var nuMax = TorqueConverterEntries.Last().SpeedRatio;
+
+			if (nu.IsGreater(nuMax)) {
+				throw new VectoException(
+					"Torque Converter: Range of torque converter data is not sufficient. Required nu: {0}, Got nu_max: {1}", nu, nuMax);
+			}
+
+			throw new VectoException(
+				"Torque Converter: No solution for output speed/input speed found! n_out: {0}, n_in: {1}, nu: {2}, nu_max: {3}",
+				outAngularVelocity, inAngularVelocity, nu, nuMax);
+		}
+
+		/// <summary>
+		/// find an operating point for the torque converter
+		/// 
+		/// find the output torque and output speed for the given input torque and input speed
+		/// </summary>
+		/// <param name="inTorque"></param>
+		/// <param name="inAngularVelocity"></param>
+		/// <param name="outAngularSpeedEstimated"></param>
+		/// <returns></returns>
+		public TorqueConverterOperatingPoint FindOperatingPointForward(NewtonMeter inTorque, PerSecond inAngularVelocity,
+			PerSecond outAngularSpeedEstimated)
+		{
+			var referenceTorque = inTorque.Value() / inAngularVelocity.Value() / inAngularVelocity.Value() *
+								ReferenceSpeed.Value() * ReferenceSpeed.Value();
+			var maxTorque = TorqueConverterEntries.Max(x => x.Torque.Value());
+			if (referenceTorque.IsGreaterOrEqual(maxTorque)) {
+				referenceTorque = outAngularSpeedEstimated != null
+					? ReferenceTorqueLookup(outAngularSpeedEstimated / inAngularVelocity).Value()
+					: 0.9 * maxTorque;
+			}
+
+			var solutions = new List<double>();
+			foreach (var edge in TorqueConverterEntries.Pairwise(
+				(p1, p2) => Edge.Create(new Point(p1.SpeedRatio, p1.Torque.Value()), new Point(p2.SpeedRatio, p2.Torque.Value())))) {
+				var x = (referenceTorque - edge.OffsetXY) / edge.SlopeXY;
+				if (x >= edge.P1.X && x < edge.P2.X) {
+					solutions.Add(x * inAngularVelocity.Value());
+				}
+			}
+			if (solutions.Count == 0) {
+				throw new VectoSimulationException(
+					"Torque Converter: Failed to find operating point for inputTorque/inputSpeed! n_in: {0}, tq_in: {1}",
+					inAngularVelocity, inTorque);
+			}
+			return FindOperatingPoint(inAngularVelocity, solutions.Max().SI<PerSecond>());
+		}
+
+		public TorqueConverterOperatingPoint LookupOperatingPoint(
+			PerSecond outAngularVelocity, PerSecond inAngularVelocity, NewtonMeter outTorque)
+		{
+			var nu = outAngularVelocity / inAngularVelocity;
+			foreach (var edge in TorqueConverterEntries.Pairwise((p1, p2) => Edge.Create(new Point(p1.SpeedRatio, p1.TorqueRatio), new Point(p2.SpeedRatio, p2.TorqueRatio)))) {
+				if (nu >= edge.P1.X && nu < edge.P2.X) {
+					var my = VectoMath.Interpolate(edge, nu);
+					return new TorqueConverterOperatingPoint() {
+						InAngularVelocity = inAngularVelocity,
+						OutAngularVelocity = outAngularVelocity,
+						OutTorque = outTorque,
+						InTorque = outTorque / my,
+						SpeedRatio = nu,
+						TorqueRatio = my,
+					};
+				}
+			}
+			throw new VectoSimulationException(
+				"Torque Converter: Failed to find operating point for outputSpeed/outputTorque/inputSpeed! n_out: {0}, n_in: {1}, tq_out: {2}",
+				outAngularVelocity, inAngularVelocity, outTorque);
+		}
+
+		public TorqueConverterOperatingPoint FindOperatingPointForPowerDemand(Watt power, PerSecond prevInputSpeed,
+			PerSecond nextOutputSpeed, KilogramSquareMeter inertia, Second dt, Watt previousPower)
+		{
+			var solutions = new List<double>();
+			var mpNorm = ReferenceSpeed.Value();
+
+			foreach (var segment in TorqueConverterEntries.Pairwise(Tuple.Create)) {
+				var mpEdge = Edge.Create(new Point(segment.Item1.SpeedRatio, segment.Item1.Torque.Value()),
+					new Point(segment.Item2.SpeedRatio, segment.Item2.Torque.Value()));
+
+				var a = mpEdge.OffsetXY / (2 * mpNorm * mpNorm);
+				var b = inertia.Value() / (2 * dt.Value()) + mpEdge.SlopeXY * nextOutputSpeed.Value() / (2 * mpNorm * mpNorm);
+				var c = 0;
+				var d = -inertia.Value() * prevInputSpeed.Value() * prevInputSpeed.Value() / (2 * dt.Value()) - power.Value() +
+						previousPower.Value() / 2;
+				var sol = VectoMath.CubicEquationSolver(a, b, c, d);
+
+				var selected = sol.Where(x => x > 0 && nextOutputSpeed / x >= mpEdge.P1.X && nextOutputSpeed / x < mpEdge.P2.X);
+				solutions.AddRange(selected);
+			}
+
+			if (solutions.Count == 0) {
+				throw new VectoException(
+					"Failed to find operating point for power {0}, prevInputSpeed {1}, nextOutputSpeed {2}", power,
+					prevInputSpeed, nextOutputSpeed);
+			}
+			solutions.Sort();
+
+			return FindOperatingPoint(solutions.First().SI<PerSecond>(), nextOutputSpeed);
+		}
+
+		private double MuLookup(double speedRatio)
+		{
+			return TorqueConverterEntries.Interpolate(x => x.SpeedRatio, y => y.TorqueRatio, speedRatio);
+		}
+
+		private NewtonMeter ReferenceTorqueLookup(double speedRatio)
+		{
+			return TorqueConverterEntries.Interpolate(x => x.SpeedRatio, y => y.Torque, speedRatio);
+		}
+
+		// ReSharper disable once UnusedMember.Global -- used by validation
+		public static ValidationResult ValidateData(TorqueConverterData data, ValidationContext validationContext)
+		{
+			var min = data.TorqueConverterEntries.Min(e => e.SpeedRatio);
+			var max = data.TorqueConverterEntries.Max(e => e.SpeedRatio);
+			if (min > 0 || max < data.RequiredSpeedRatio) {
+				return new ValidationResult(string.Format(
+					"Torque Converter Data invalid - Speedratio has to cover the range from 0.0 to {2}: given data only goes from {0} to {1}",
+					min, max, data.RequiredSpeedRatio));
+			}
+
+			return ValidationResult.Success;
+		}
+	}
+
+	public class TorqueConverterOperatingPoint
+	{
+		public PerSecond OutAngularVelocity;
+		public NewtonMeter OutTorque;
+
+		public PerSecond InAngularVelocity;
+		public NewtonMeter InTorque;
+
+		public double SpeedRatio;
+		public double TorqueRatio;
+		public bool Creeping;
+
+		public override string ToString()
+		{
+			return string.Format("n_out: {0}, n_in: {1}, tq_out: {2}, tq_in {3}, nu: {4}, my: {5}", OutAngularVelocity,
+				InAngularVelocity, OutTorque, InTorque, SpeedRatio, TorqueRatio);
+		}
+	}
+
+	public class TorqueConverterEntry
+	{
+		public double SpeedRatio;
+		public NewtonMeter Torque;
+		public double TorqueRatio;
+	}
 }
\ No newline at end of file
diff --git a/VectoCore/VectoCore/Models/SimulationComponent/Impl/CycleGearbox.cs b/VectoCore/VectoCore/Models/SimulationComponent/Impl/CycleGearbox.cs
index 5d585fe3cc9a00ba6f3022460954c7de2c7ad518..6ba54d2fecbd2fefd407111aecfd536fa8f1d153 100644
--- a/VectoCore/VectoCore/Models/SimulationComponent/Impl/CycleGearbox.cs
+++ b/VectoCore/VectoCore/Models/SimulationComponent/Impl/CycleGearbox.cs
@@ -54,7 +54,7 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl
 
 		protected bool? TorqueConverterActive;
 
-		protected internal readonly TorqueConverter TorqueConverter;
+		protected internal readonly CycleTorqueConverter TorqueConverter;
 
 		public CycleGearbox(IVehicleContainer container, VectoRunData runData)
 			: base(container, runData)
@@ -62,8 +62,9 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl
 			if (!ModelData.Type.AutomaticTransmission()) {
 				return;
 			}
+
 			var strategy = new CycleShiftStrategy(ModelData, null);
-			TorqueConverter = new TorqueConverter(this, strategy, container, ModelData.TorqueConverterData, runData);
+			TorqueConverter = new CycleTorqueConverter(container, ModelData.TorqueConverterData);
 			if (TorqueConverter == null) {
 				throw new VectoException("Torque Converter required for AT transmission!");
 			}
@@ -106,7 +107,7 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl
 				inTorque += torqueLossInertia;
 
 				response = TorqueConverterActive != null && TorqueConverterActive.Value && TorqueConverter != null
-					? TorqueConverter.Initialize(inTorque, inAngularVelocity)
+					? TorqueConverter.Initialize(inTorque, inAngularVelocity, GetEngineSpeedFromCycle())
 					: NextComponent.Initialize(inTorque, inAngularVelocity);
 			} else {
 				response = NextComponent.Initialize(inTorque, inAngularVelocity);
@@ -130,7 +131,8 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl
 		/// <item><description>ResponseGearshift</description></item>
 		/// </list>
 		/// </returns>
-		public override IResponse Request(Second absTime, Second dt, NewtonMeter outTorque, PerSecond outAngularVelocity,
+		public override IResponse Request(
+			Second absTime, Second dt, NewtonMeter outTorque, PerSecond outAngularVelocity,
 			bool dryRun = false)
 		{
 			Log.Debug("Gearbox Power Request: torque: {0}, angularVelocity: {1}", outTorque, outAngularVelocity);
@@ -150,6 +152,7 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl
 			// mk 2016-11-30: added additional check for outAngularVelocity due to failing test: MeasuredSpeed_Gear_AT_PS_Run
 			// mq 2016-12-16: changed check to vehicle halted due to failing test: MeasuredSpeed_Gear_AT_*
 			var retVal = gear == 0 || DataBus.DriverBehavior == DrivingBehavior.Halted
+
 				//|| (outAngularVelocity.IsSmallerOrEqual(0, 1) && outTorque.IsSmallerOrEqual(0, 1))
 				? RequestDisengaged(absTime, dt, outTorque, outAngularVelocity, dryRun)
 				: RequestEngaged(absTime, dt, outTorque, outAngularVelocity, dryRun);
@@ -165,6 +168,13 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl
 				: DataBus.CycleData.RightSample.Gear;
 		}
 
+		protected virtual PerSecond GetEngineSpeedFromCycle()
+		{
+			return DataBus.DriverBehavior == DrivingBehavior.Braking
+				? DataBus.CycleData.LeftSample.EngineSpeed
+				: DataBus.CycleData.RightSample.EngineSpeed;
+		}
+
 		/// <summary>
 		/// Handles requests when a gear is engaged
 		/// </summary>
@@ -174,7 +184,8 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl
 		/// <param name="outAngularVelocity"></param>
 		/// <param name="dryRun"></param>
 		/// <returns></returns>
-		private IResponse RequestEngaged(Second absTime, Second dt, NewtonMeter outTorque, PerSecond outAngularVelocity,
+		private IResponse RequestEngaged(
+			Second absTime, Second dt, NewtonMeter outTorque, PerSecond outAngularVelocity,
 			bool dryRun)
 		{
 			Disengaged = null;
@@ -222,15 +233,17 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl
 
 			CurrentState.SetState(inTorque, inAngularVelocity, outTorque, outAngularVelocity);
 			CurrentState.Gear = Gear;
+
 			// end critical section
 
 			if (TorqueConverter != null && !torqueConverterLocked) {
 				CurrentState.TorqueConverterActive = true;
-				return TorqueConverter.Request(absTime, dt, inTorque, inAngularVelocity);
+				return TorqueConverter.Request(absTime, dt, inTorque, inAngularVelocity, GetEngineSpeedFromCycle());
 			}
 
 			if (TorqueConverter != null) {
-				TorqueConverter.Locked(CurrentState.InTorque, CurrentState.InAngularVelocity, CurrentState.InTorque,
+				TorqueConverter.Locked(
+					CurrentState.InTorque, CurrentState.InAngularVelocity, CurrentState.InTorque,
 					CurrentState.InAngularVelocity);
 			}
 			var response = NextComponent.Request(absTime, dt, inTorque, inAngularVelocity);
@@ -241,7 +254,8 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl
 		private void CheckModelData(TransmissionLossMap effectiveLossMap, double effectiveRatio, bool torqueConverterLocked)
 		{
 			if (effectiveLossMap == null || double.IsNaN(effectiveRatio)) {
-				throw new VectoSimulationException("Ratio or loss-map for gear {0}{1} invalid. Please check input data", Gear,
+				throw new VectoSimulationException(
+					"Ratio or loss-map for gear {0}{1} invalid. Please check input data", Gear,
 					torqueConverterLocked ? "L" : "C");
 			}
 			if (!torqueConverterLocked && !ModelData.Gears[Gear].HasTorqueConverter) {
@@ -249,12 +263,14 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl
 			}
 		}
 
-		private IResponse HandleDryRunRequest(Second absTime, Second dt, bool torqueConverterLocked, NewtonMeter inTorque,
+		private IResponse HandleDryRunRequest(
+			Second absTime, Second dt, bool torqueConverterLocked, NewtonMeter inTorque,
 			PerSecond inAngularVelocity)
 		{
 			if (TorqueConverter != null && !torqueConverterLocked) {
-				return TorqueConverter.Request(absTime, dt, inTorque, inAngularVelocity, true);
+				return TorqueConverter.Request(absTime, dt, inTorque, inAngularVelocity, GetEngineSpeedFromCycle(), true);
 			}
+
 			// mk 2016-12-13
 			//if (outTorque.IsSmaller(0) && inAngularVelocity.IsSmaller(DataBus.EngineIdleSpeed)) {
 			//	//Log.Warn("engine speed would fall below idle speed - disengage! gear from cycle: {0}, vehicle speed: {1}", Gear,
@@ -274,7 +290,8 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl
 		/// <param name="outAngularVelocity"></param>
 		/// <param name="dryRun"></param>
 		/// <returns></returns>
-		private IResponse RequestDisengaged(Second absTime, Second dt, NewtonMeter outTorque, PerSecond outAngularVelocity,
+		private IResponse RequestDisengaged(
+			Second absTime, Second dt, NewtonMeter outTorque, PerSecond outAngularVelocity,
 			bool dryRun)
 		{
 			if (Disengaged == null) {
@@ -314,16 +331,19 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl
 				disengagedResponse = EngineIdleRequest(absTime, dt);
 			} else {
 				disengagedResponse = NextGear.Gear > 0
-					? NextComponent.Request(absTime, dt, 0.SI<NewtonMeter>(),
+					? NextComponent.Request(
+						absTime, dt, 0.SI<NewtonMeter>(),
 						outAngularVelocity * ModelData.Gears[NextGear.Gear].Ratio)
 					: EngineIdleRequest(absTime, dt);
 			}
 			if (TorqueConverter != null) {
 				if (DataBus.VehicleStopped) {
-					TorqueConverter.Locked(0.SI<NewtonMeter>(), disengagedResponse.EngineSpeed, CurrentState.InTorque,
+					TorqueConverter.Locked(
+						0.SI<NewtonMeter>(), disengagedResponse.EngineSpeed, CurrentState.InTorque,
 						outAngularVelocity);
 				} else {
-					TorqueConverter.Locked(CurrentState.InTorque, disengagedResponse.EngineSpeed, CurrentState.InTorque,
+					TorqueConverter.Locked(
+						CurrentState.InTorque, disengagedResponse.EngineSpeed, CurrentState.InTorque,
 						disengagedResponse.EngineSpeed);
 				}
 			}
@@ -340,11 +360,13 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl
 			if (disengagedResponse is ResponseSuccess) {
 				return disengagedResponse;
 			}
+
 			var motoringSpeed = DataBus.EngineSpeed;
 			if (motoringSpeed.IsGreater(DataBus.EngineIdleSpeed)) {
 				var first = (ResponseDryRun)NextComponent.Request(absTime, dt, 0.SI<NewtonMeter>(), motoringSpeed, true);
 				try {
-					motoringSpeed = SearchAlgorithm.Search(motoringSpeed, first.DeltaDragLoad,
+					motoringSpeed = SearchAlgorithm.Search(
+						motoringSpeed, first.DeltaDragLoad,
 						Constants.SimulationSettings.EngineIdlingSearchInterval,
 						getYValue: result => ((ResponseDryRun)result).DeltaDragLoad,
 						evaluateFunction: n => NextComponent.Request(absTime, dt, 0.SI<NewtonMeter>(), n, true),
@@ -378,6 +400,7 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl
 					? 0.SI<Watt>()
 					: CurrentState.PowershiftLosses * avgInAngularSpeed;
 			}
+
 			// torque converter fields are written by TorqueConverter (if present), called from Vehicle container 
 		}
 
@@ -395,6 +418,7 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl
 					}
 				}
 			}
+
 			base.DoCommitSimulationStep();
 		}
 
@@ -402,11 +426,11 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl
 
 		public override GearInfo NextGear
 		{
-			get
-			{
+			get {
 				if (Disengaged == null) {
 					return new GearInfo(Gear, !TorqueConverterActive ?? true);
 				}
+
 				var future = DataBus.LookAhead(ModelData.TractionInterruption * 5);
 				var nextGear = 0u;
 				var torqueConverterLocked = false;
@@ -419,24 +443,27 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl
 						// vehicle is stopped, no next gear, engine should go to idle
 						break;
 					}
+
 					if (entry.Gear == 0) {
 						continue;
 					}
+
 					nextGear = entry.Gear;
 					torqueConverterLocked = !entry.TorqueConverterActive ?? false;
 					break;
 				}
+
 				return new GearInfo(nextGear, torqueConverterLocked);
 			}
 		}
 
 		public override Second TractionInterruption
 		{
-			get
-			{
+			get {
 				if (Disengaged == null) {
 					return ModelData.TractionInterruption;
 				}
+
 				var future = DataBus.LookAhead(ModelData.TractionInterruption * 5);
 				foreach (var entry in future) {
 					if (entry.VehicleTargetSpeed != null && entry.VehicleTargetSpeed.IsEqual(0)) {
@@ -447,11 +474,14 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl
 						// vehicle is stopped, no next gear, engine should go to idle
 						break;
 					}
+
 					if (entry.Gear == 0) {
 						continue;
 					}
+
 					return entry.Time - Disengaged;
 				}
+
 				return ModelData.TractionInterruption;
 			}
 		}
@@ -459,8 +489,8 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl
 		public override bool ClutchClosed(Second absTime)
 		{
 			return (DataBus.DriverBehavior == DrivingBehavior.Braking
-				? DataBus.CycleData.LeftSample.Gear
-				: DataBus.CycleData.RightSample.Gear) != 0;
+						? DataBus.CycleData.LeftSample.Gear
+						: DataBus.CycleData.RightSample.Gear) != 0;
 		}
 
 		#endregion
@@ -473,11 +503,12 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl
 
 		public class CycleShiftStrategy : BaseShiftStrategy
 		{
-			public CycleShiftStrategy(GearboxData data, IDataBus dataBus) : base(data, dataBus) {}
+			public CycleShiftStrategy(GearboxData data, IDataBus dataBus) : base(data, dataBus) { }
 
 			public override IGearbox Gearbox { get; set; }
 
-			public override bool ShiftRequired(Second absTime, Second dt, NewtonMeter outTorque, PerSecond outAngularVelocity,
+			public override bool ShiftRequired(
+				Second absTime, Second dt, NewtonMeter outTorque, PerSecond outAngularVelocity,
 				NewtonMeter inTorque,
 				PerSecond inAngularVelocity, uint gear, Second lastShiftTime)
 			{
@@ -505,4 +536,69 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl
 			}
 		}
 	}
+
+	public class CycleTorqueConverter : StatefulVectoSimulationComponent<TorqueConverter.TorqueConverterComponentState>
+	{
+		protected internal ITnOutPort NextComponent;
+		private TorqueConverterData ModelData;
+
+		public CycleTorqueConverter(IVehicleContainer container, TorqueConverterData modelData) : base(container)
+		{
+			ModelData = modelData;
+		}
+
+		public IResponse Initialize(NewtonMeter outTorque, PerSecond outAngularVelocity, PerSecond inAngularVelocity)
+		{
+			
+			var operatingPoint = ModelData.LookupOperatingPoint(outAngularVelocity, inAngularVelocity, outTorque);
+
+			PreviousState.OperatingPoint = operatingPoint;
+			return NextComponent.Initialize(operatingPoint.InTorque, inAngularVelocity);
+		}
+
+		public IResponse Request(
+			Second absTime, Second dt, NewtonMeter outTorque, PerSecond outAngularVelocity, PerSecond inAngularVelocity,
+			bool dryRun = false)
+		{
+			var operatingPoint = ModelData.LookupOperatingPoint(outAngularVelocity, inAngularVelocity, outTorque);
+			if (!dryRun) {
+				CurrentState.OperatingPoint = operatingPoint;
+			}
+			return NextComponent.Request(absTime, dt, operatingPoint.InTorque, inAngularVelocity, dryRun);
+		}
+
+		public void Locked(
+			NewtonMeter inTorque, PerSecond inAngularVelocity, NewtonMeter outTorque,
+			PerSecond outAngularVelocity) { }
+
+		#region Overrides of VectoSimulationComponent
+
+		protected override void DoWriteModalResults(IModalDataContainer container)
+		{
+			if (CurrentState.OperatingPoint == null) {
+				container[ModalResultField.TorqueConverterTorqueRatio] = 1.0;
+				container[ModalResultField.TorqueConverterSpeedRatio] = 1.0;
+			} else {
+				container[ModalResultField.TorqueConverterTorqueRatio] = CurrentState.OperatingPoint.TorqueRatio;
+				container[ModalResultField.TorqueConverterSpeedRatio] = CurrentState.OperatingPoint.SpeedRatio;
+			}
+			container[ModalResultField.TC_TorqueIn] = CurrentState.InTorque;
+			container[ModalResultField.TC_TorqueOut] = CurrentState.OutTorque;
+			container[ModalResultField.TC_angularSpeedIn] = CurrentState.InAngularVelocity;
+			container[ModalResultField.TC_angularSpeedOut] = CurrentState.OutAngularVelocity;
+
+			var avgOutVelocity = (PreviousState.OutAngularVelocity + CurrentState.OutAngularVelocity) / 2.0;
+			var avgInVelocity = (PreviousState.InAngularVelocity + CurrentState.InAngularVelocity) / 2.0;
+			container[ModalResultField.P_TC_out] = CurrentState.OutTorque * avgOutVelocity;
+			container[ModalResultField.P_TC_loss] = CurrentState.InTorque * avgInVelocity -
+													CurrentState.OutTorque * avgOutVelocity;
+		}
+
+		protected override void DoCommitSimulationStep()
+		{
+			AdvanceState();
+		}
+
+		#endregion
+	}
 }
\ No newline at end of file
diff --git a/VectoCore/VectoCore/Models/SimulationComponent/Impl/VTPCycle.cs b/VectoCore/VectoCore/Models/SimulationComponent/Impl/VTPCycle.cs
index a0edc11e16c94a0f2680e939615c173f6382cc90..95c9d50e4747e3addc97d75f7001048d39374c54 100644
--- a/VectoCore/VectoCore/Models/SimulationComponent/Impl/VTPCycle.cs
+++ b/VectoCore/VectoCore/Models/SimulationComponent/Impl/VTPCycle.cs
@@ -47,7 +47,9 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl
 {
 	internal class VTPCycle : PWheelCycle
 	{
-		private uint StartGear;
+		protected uint StartGear;
+
+		protected Second SimulationIntervalEndTime;
 
 		public VTPCycle(VehicleContainer container, IDrivingCycleData cycle) : base(container, cycle) { }
 
@@ -311,6 +313,11 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl
 					DeltaT = CycleIterator.RightSample.Time - absTime
 				};
 			}
+
+			SimulationIntervalEndTime = absTime + dt;
+			if (CycleIterator.LeftSample.Time > absTime) {
+				Log.Warn("absTime: {0} cycle: {1}", absTime, CycleIterator.LeftSample.Time);
+			}
 			var tmp = NextComponent.Initialize(CycleIterator.LeftSample.Torque, CycleIterator.LeftSample.WheelAngularVelocity);
 
 			return DoHandleRequest(absTime, dt, CycleIterator.LeftSample.WheelAngularVelocity);
@@ -325,6 +332,14 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl
 			}
 		}
 
+		protected override void DoCommitSimulationStep()
+		{
+			if (SimulationIntervalEndTime.IsGreaterOrEqual(CycleIterator.RightSample.Time)) {
+				CycleIterator.MoveNext();
+			}
+			AdvanceState();
+		}
+
 		protected override void DoWriteModalResults(IModalDataContainer container)
 		{
 			base.DoWriteModalResults(container);