From d86445a15b3b4381189a20775b4f1749eea548dd Mon Sep 17 00:00:00 2001
From: "VKMTHD\\haraldmartini" <harald.martini@student.tugraz.at>
Date: Wed, 11 Jan 2023 09:21:00 +0100
Subject: [PATCH] enabled IEPC_S simulation (fails because of line search
 exception)

---
 ...clarationDataAdapterGenericCompletedBus.cs |   5 +
 .../DeclarationDataAdapterHeavyLorry.cs       |  40 +++-
 .../IDeclarationDataAdapter.cs                |   2 +
 .../DeclarationDataAdapterPrimaryBus.cs       |   5 +
 .../BatteryDataAdapter.cs                     |   6 +-
 .../ElectricMachinesDataAdapter.cs            |  98 ++++++++++
 .../GearBoxDataAdapter.cs                     |  87 ++++++++-
 .../SimulationComponents/IEPCDataAdapter.cs   |  19 ++
 .../HybridStrategyParameterDataAdapter.cs     |  10 -
 ...tionModeHeavyLorryRunDataFactory_Hybrid.cs | 180 +++++++++++++++---
 .../VectoRunDataFactoryNinjectModule.cs       |   2 +-
 11 files changed, 412 insertions(+), 42 deletions(-)
 create mode 100644 VectoCore/VectoCore/InputData/Reader/DataObjectAdapter/SimulationComponents/IEPCDataAdapter.cs

diff --git a/VectoCore/VectoCore/InputData/Reader/DataObjectAdapter/CompletedBus/Generic/DeclarationDataAdapterGenericCompletedBus.cs b/VectoCore/VectoCore/InputData/Reader/DataObjectAdapter/CompletedBus/Generic/DeclarationDataAdapterGenericCompletedBus.cs
index a858f92554..42e4911b54 100644
--- a/VectoCore/VectoCore/InputData/Reader/DataObjectAdapter/CompletedBus/Generic/DeclarationDataAdapterGenericCompletedBus.cs
+++ b/VectoCore/VectoCore/InputData/Reader/DataObjectAdapter/CompletedBus/Generic/DeclarationDataAdapterGenericCompletedBus.cs
@@ -85,6 +85,11 @@ namespace TUGraz.VectoCore.InputData.Reader.DataObjectAdapter.CompletedBus.Gener
 				return _retarderDataAdapter.CreateRetarderData(retarderData, position);
 			}
 
+			public List<Tuple<PowertrainPosition, ElectricMotorData>> CreateIEPCElectricMachines(IIEPCDeclarationInputData iepc, Volt averageVoltage)
+			{
+				throw new NotImplementedException();
+			}
+
 			public DriverData CreateDriverData(Segment segment)
 			{
 				return _driverDataAdapter.CreateDriverData(segment);
diff --git a/VectoCore/VectoCore/InputData/Reader/DataObjectAdapter/HeavyLorry/DeclarationDataAdapterHeavyLorry.cs b/VectoCore/VectoCore/InputData/Reader/DataObjectAdapter/HeavyLorry/DeclarationDataAdapterHeavyLorry.cs
index 1b01217727..1946157a9e 100644
--- a/VectoCore/VectoCore/InputData/Reader/DataObjectAdapter/HeavyLorry/DeclarationDataAdapterHeavyLorry.cs
+++ b/VectoCore/VectoCore/InputData/Reader/DataObjectAdapter/HeavyLorry/DeclarationDataAdapterHeavyLorry.cs
@@ -116,6 +116,9 @@ namespace TUGraz.VectoCore.InputData.Reader.DataObjectAdapter.HeavyLorry
 				throw new NotImplementedException();
 			}
 
+
+			
+
 			public virtual AirdragData CreateAirdragData(IAirdragDeclarationInputData airdragData, Mission mission,
 				Segment segment)
 			{
@@ -173,6 +176,12 @@ namespace TUGraz.VectoCore.InputData.Reader.DataObjectAdapter.HeavyLorry
 			}
 
 			#endregion
+
+			public virtual List<Tuple<PowertrainPosition, ElectricMotorData>> CreateIEPCElectricMachines(
+				IIEPCDeclarationInputData iepc, Volt averageVoltage)
+			{
+				throw new NotImplementedException();
+			}
 		}
 
 		public class Conventional : LorryBase
@@ -536,7 +545,36 @@ namespace TUGraz.VectoCore.InputData.Reader.DataObjectAdapter.HeavyLorry
 		}
 		public class HEV_S3 : SerialHybrid { }
 		public class HEV_S4 : SerialHybrid { }
-		public class HEV_S_IEPC : SerialHybrid { }
+
+		public class HEV_S_IEPC : SerialHybrid
+		{
+			
+			protected override GearboxType[] SupportedGearboxTypes => new[]
+				{ GearboxType.AMT, GearboxType.ATPowerSplit, GearboxType.ATSerial, GearboxType.APTN };
+
+
+
+			private IGearboxDataAdapter _gearBoxDataAdaper = new IEPCGearboxDataAdapter();
+			private ElectricMachinesDataAdapter _electricMachinesDataAdapter = new ElectricMachinesDataAdapter();
+
+			public override GearboxData CreateGearboxData(IVehicleDeclarationInputData inputData, VectoRunData runData,
+				IShiftPolygonCalculator shiftPolygonCalc)
+			{
+				return _gearBoxDataAdaper.CreateGearboxData(inputData, runData, shiftPolygonCalc, SupportedGearboxTypes);
+			}
+
+			public override ShiftStrategyParameters CreateGearshiftData(double axleRatio, PerSecond engineIdlingSpeed,
+				GearboxType gearboxType, int gearsCount)
+			{
+				return _gearBoxDataAdaper.CreateGearshiftData(axleRatio, engineIdlingSpeed, gearboxType, gearsCount);
+			}
+
+			public override List<Tuple<PowertrainPosition, ElectricMotorData>> CreateIEPCElectricMachines(
+				IIEPCDeclarationInputData iepc, Volt averageVoltage)
+			{
+				return _electricMachinesDataAdapter.CreateIEPCElectricMachines(iepc, averageVoltage);
+			}
+		}
 
 		public class HEV_P1 : ParallelHybrid
 		{
diff --git a/VectoCore/VectoCore/InputData/Reader/DataObjectAdapter/IDeclarationDataAdapter.cs b/VectoCore/VectoCore/InputData/Reader/DataObjectAdapter/IDeclarationDataAdapter.cs
index 86a4fedf5d..9ca808cc70 100644
--- a/VectoCore/VectoCore/InputData/Reader/DataObjectAdapter/IDeclarationDataAdapter.cs
+++ b/VectoCore/VectoCore/InputData/Reader/DataObjectAdapter/IDeclarationDataAdapter.cs
@@ -31,6 +31,8 @@ namespace TUGraz.VectoCore.InputData.Reader.DataObjectAdapter
 		VehicleData CreateVehicleData(IVehicleDeclarationInputData vehicle, Segment segment, Mission first, KeyValuePair<LoadingType, Tuple<Kilogram, double?>> keyValuePair, bool allowVocational);
 		RetarderData CreateRetarderData(IRetarderInputData retarderData, PowertrainPosition position = PowertrainPosition.HybridPositionNotSet);
 
+		List<Tuple<PowertrainPosition, ElectricMotorData>> CreateIEPCElectricMachines(
+			IIEPCDeclarationInputData iepc, Volt averageVoltage);
 	}
 
 	public interface ILorryDeclarationDataAdapter : IDeclarationDataAdapter
diff --git a/VectoCore/VectoCore/InputData/Reader/DataObjectAdapter/PrimaryBus/DeclarationDataAdapterPrimaryBus.cs b/VectoCore/VectoCore/InputData/Reader/DataObjectAdapter/PrimaryBus/DeclarationDataAdapterPrimaryBus.cs
index 51fd2369fb..5dc6fb684d 100644
--- a/VectoCore/VectoCore/InputData/Reader/DataObjectAdapter/PrimaryBus/DeclarationDataAdapterPrimaryBus.cs
+++ b/VectoCore/VectoCore/InputData/Reader/DataObjectAdapter/PrimaryBus/DeclarationDataAdapterPrimaryBus.cs
@@ -87,6 +87,11 @@ namespace TUGraz.VectoCore.InputData.Reader.DataObjectAdapter.PrimaryBus
 				return _retarderDataAdapter.CreateRetarderData(retarderData, position);
 			}
 
+			public virtual List<Tuple<PowertrainPosition, ElectricMotorData>> CreateIEPCElectricMachines(IIEPCDeclarationInputData iepc, Volt averageVoltage)
+			{
+				throw new NotImplementedException();
+			}
+
 			public IList<VectoRunData.AuxData> CreateAuxiliaryData(IAuxiliariesDeclarationInputData auxData,
 				IBusAuxiliariesDeclarationData busAuxData,
 				MissionType missionType, VehicleClass vehicleClass, Meter vehicleLength, int? numSteeredAxles,
diff --git a/VectoCore/VectoCore/InputData/Reader/DataObjectAdapter/SimulationComponents/BatteryDataAdapter.cs b/VectoCore/VectoCore/InputData/Reader/DataObjectAdapter/SimulationComponents/BatteryDataAdapter.cs
index d2ae59456a..dcae2e5c49 100644
--- a/VectoCore/VectoCore/InputData/Reader/DataObjectAdapter/SimulationComponents/BatteryDataAdapter.cs
+++ b/VectoCore/VectoCore/InputData/Reader/DataObjectAdapter/SimulationComponents/BatteryDataAdapter.cs
@@ -1,6 +1,7 @@
 using System;
 using System.Linq;
 using System.Security.Policy;
+using TUGraz.VectoCommon.Exceptions;
 using TUGraz.VectoCommon.InputData;
 using TUGraz.VectoCommon.Utils;
 using TUGraz.VectoCore.InputData.Reader.ComponentData;
@@ -116,9 +117,8 @@ namespace TUGraz.VectoCore.InputData.Reader.DataObjectAdapter.SimulationComponen
 	{
 		public static Volt CalculateAverageVoltage(this BatterySystemData battery)
 		{
-			if (battery == null)
-			{
-				return null;
+			if (battery == null) {
+				throw new VectoException("Battery not set");
 			}
 			var tmpBattery = new BatterySystem(null, battery);
 			var min = tmpBattery.MinSoC;
diff --git a/VectoCore/VectoCore/InputData/Reader/DataObjectAdapter/SimulationComponents/ElectricMachinesDataAdapter.cs b/VectoCore/VectoCore/InputData/Reader/DataObjectAdapter/SimulationComponents/ElectricMachinesDataAdapter.cs
index 11740b865d..0c37935c79 100644
--- a/VectoCore/VectoCore/InputData/Reader/DataObjectAdapter/SimulationComponents/ElectricMachinesDataAdapter.cs
+++ b/VectoCore/VectoCore/InputData/Reader/DataObjectAdapter/SimulationComponents/ElectricMachinesDataAdapter.cs
@@ -261,6 +261,104 @@ namespace TUGraz.VectoCore.InputData.Reader.DataObjectAdapter.SimulationComponen
 			}
 		}
 
+		public List<Tuple<PowertrainPosition, ElectricMotorData>> CreateIEPCElectricMachines(IIEPCDeclarationInputData iepc, Volt averageVoltage)
+		{
+			if (iepc == null)
+			{
+				return null;
+			}
+
+			var pos = PowertrainPosition.IEPC;
+			var count = iepc.DesignTypeWheelMotor && iepc.NrOfDesignTypeWheelMotorMeasured == 1 ? 2 : 1;
+
+			// the full-load curve is measured in the gear with the ratio closest to 1,
+			// in case two gears have the same difference, the higher one is used
+			var gearRatioUsedForMeasurement = iepc.Gears
+				.Select(x => new { x.GearNumber, x.Ratio, Diff = Math.Round(Math.Abs(x.Ratio - 1), 6) }).GroupBy(x => x.Diff)
+				.OrderBy(x => x.Key).First().OrderBy(x => x.Ratio).Reverse().First();
+
+
+			var voltageLevels = new List<ElectricMotorVoltageLevelData>();
+			foreach (var entry in iepc.VoltageLevels.OrderBy(x => x.VoltageLevel))
+			{
+				var effMap = new Dictionary<uint, EfficiencyMap>();
+				for (var i = 0u; i < entry.PowerMap.Count; i++)
+				{
+					var ratio = iepc.Gears.First(x => x.GearNumber == i + 1).Ratio;
+					effMap.Add(i + 1, IEPCMapReader.Create(entry.PowerMap[(int)i].PowerMap, count, ratio));
+					//fullLoadCurves.Add(i + 1, IEPCFullLoadCurveReader.Create(entry.FullLoadCurve, count, ratio));
+				}
+				voltageLevels.Add(new IEPCVoltageLevelData()
+				{
+					Voltage = entry.VoltageLevel,
+					FullLoadCurve = IEPCFullLoadCurveReader.Create(entry.FullLoadCurve, count, gearRatioUsedForMeasurement.Ratio),
+					EfficiencyMaps = effMap,
+				});
+			}
+
+			var dragCurves = new Dictionary<uint, DragCurve>();
+			if (iepc.DragCurves.Count > 1)
+			{
+				for (var i = 0u; i < iepc.DragCurves.Count; i++)
+				{
+					var ratio = iepc.Gears.First(x => x.GearNumber == i + 1).Ratio;
+					dragCurves.Add(i + 1, IEPCDragCurveReader.Create(iepc.DragCurves[(int)i].DragCurve, count, ratio));
+				}
+			}
+			else
+			{
+				var dragCurve = iepc.DragCurves.First().DragCurve;
+				for (var i = 0u; i < iepc.Gears.Count; i++)
+				{
+					var ratio = iepc.Gears.First(x => x.GearNumber == i + 1).Ratio;
+					dragCurves.Add(i + 1, IEPCDragCurveReader.Create(dragCurve, count, ratio));
+				}
+			}
+
+			var retVal = new IEPCElectricMotorData()
+			{
+				EfficiencyData = new VoltageLevelData() { VoltageLevels = voltageLevels },
+				IEPCDragCurves = dragCurves,
+				Inertia = iepc.Inertia * count,
+				OverloadRecoveryFactor = DeclarationData.OverloadRecoveryFactor,
+				RatioADC = 1,
+				RatioPerGear = null,
+				TransmissionLossMap = TransmissionLossMapReader.CreateEmADCLossMap(1.0, 1.0, "EM ADC LossMap Eff"),
+
+			};
+			retVal.Overload = CalculateOverloadData(iepc, count, retVal.EfficiencyData, averageVoltage,
+				Tuple.Create((uint)gearRatioUsedForMeasurement.GearNumber, gearRatioUsedForMeasurement.Ratio));
+			;
+			return new List<Tuple<PowertrainPosition, ElectricMotorData>>() { Tuple.Create<PowertrainPosition, ElectricMotorData>(pos, retVal) };
+		}
+
+		private OverloadData CalculateOverloadData(IIEPCDeclarationInputData iepc, int count,
+			VoltageLevelData voltageLevels, Volt averageVoltage, Tuple<uint, double> gearRatioUsedForMeasurement)
+		{
+			// if average voltage is outside of the voltage-level range, do not extrapolate but take the min voltage entry, or max voltage entry
+			if (averageVoltage < iepc.VoltageLevels.Min(x => x.VoltageLevel))
+			{
+				return CalculateOverloadBuffer(iepc.VoltageLevels.First(), count, voltageLevels, gearRatioUsedForMeasurement);
+			}
+			if (averageVoltage > iepc.VoltageLevels.Max(x => x.VoltageLevel))
+			{
+				return CalculateOverloadBuffer(iepc.VoltageLevels.Last(), count, voltageLevels, gearRatioUsedForMeasurement);
+			}
+
+			var (vLow, vHigh) = iepc.VoltageLevels.OrderBy(x => x.VoltageLevel).GetSection(x => x.VoltageLevel < averageVoltage);
+			var ovlLo = CalculateOverloadBuffer(vLow, count, voltageLevels, gearRatioUsedForMeasurement);
+			var ovlHi = CalculateOverloadBuffer(vHigh, count, voltageLevels, gearRatioUsedForMeasurement);
+
+			var retVal = new OverloadData()
+			{
+				OverloadBuffer = VectoMath.Interpolate(vLow.VoltageLevel, vHigh.VoltageLevel, ovlLo.OverloadBuffer, ovlHi.OverloadBuffer, averageVoltage),
+				ContinuousTorque = VectoMath.Interpolate(vLow.VoltageLevel, vHigh.VoltageLevel, ovlLo.ContinuousTorque, ovlHi.ContinuousTorque, averageVoltage),
+				ContinuousPowerLoss = VectoMath.Interpolate(vLow.VoltageLevel, vHigh.VoltageLevel, ovlLo.ContinuousPowerLoss, ovlHi.ContinuousPowerLoss, averageVoltage)
+			};
+			return retVal;
+		}
+
+
 		private OverloadData CalculateOverloadData(IElectricMotorDeclarationInputData motorData, int count, VoltageLevelData voltageLevels, Volt averageVoltage)
 		{
 
diff --git a/VectoCore/VectoCore/InputData/Reader/DataObjectAdapter/SimulationComponents/GearBoxDataAdapter.cs b/VectoCore/VectoCore/InputData/Reader/DataObjectAdapter/SimulationComponents/GearBoxDataAdapter.cs
index 4c3dc27c82..b9ab90b2ac 100644
--- a/VectoCore/VectoCore/InputData/Reader/DataObjectAdapter/SimulationComponents/GearBoxDataAdapter.cs
+++ b/VectoCore/VectoCore/InputData/Reader/DataObjectAdapter/SimulationComponents/GearBoxDataAdapter.cs
@@ -1,10 +1,13 @@
-using System.Collections.Generic;
+using System;
+using System.Collections.Generic;
 using System.ComponentModel;
 using System.Linq;
+using System.Security.Cryptography.X509Certificates;
 using TUGraz.VectoCommon.Exceptions;
 using TUGraz.VectoCommon.InputData;
 using TUGraz.VectoCommon.Models;
 using TUGraz.VectoCommon.Utils;
+using TUGraz.VectoCore.InputData.Impl;
 using TUGraz.VectoCore.InputData.Reader.ComponentData;
 using TUGraz.VectoCore.InputData.Reader.ShiftStrategy;
 using TUGraz.VectoCore.Models.Declaration;
@@ -417,4 +420,86 @@ namespace TUGraz.VectoCore.InputData.Reader.DataObjectAdapter.SimulationComponen
 
 		#endregion
 	}
+
+	public class IEPCGearboxDataAdapter : GearboxDataAdapterBase
+	{
+		private GearboxData CreateIEPCGearboxData(IVehicleDeclarationInputData vehicle, VectoRunData runData, IShiftPolygonCalculator shiftPolygonCalc)
+		{
+			
+
+			var iepc = vehicle.Components.IEPC;
+
+			var axlegearRatio = runData.AxleGearData?.AxleGear.Ratio ?? 1.0;
+			var dynamicTyreRadius = runData.VehicleData.DynamicTyreRadius;
+
+
+			var retVal = new GearboxData()
+			{
+				Type = GearboxType.APTN,
+				Inertia = 0.SI<KilogramSquareMeter>(),
+				TractionInterruption = 0.SI<Second>(),
+				InputData = new IEPCGearboxInputData(iepc),
+			};
+
+
+			var gearInput = iepc.Gears.Select((x, idx) => new TransmissionInputData() { Gear = idx + 1, Ratio = x.Ratio }).Cast<ITransmissionInputData>().ToList();
+			var gears = new Dictionary<uint, GearData>();
+			for (uint i = 0; i < iepc.Gears.Count; i++)
+			{
+				var gear = iepc.Gears[(int)i];
+				var lossMap = TransmissionLossMapReader.Create(1, gear.Ratio, $"Gear{i + 1}");
+
+				ShiftPolygon shiftPolygon = null;
+				if (iepc.Gears.Count > 1)
+				{
+					if (shiftPolygonCalc != null)
+					{
+						shiftPolygon = shiftPolygonCalc.ComputeDeclarationShiftPolygon(GearboxType.APTN, (int)i,
+							null, gearInput, null, axlegearRatio,
+							dynamicTyreRadius, runData.ElectricMachinesData?.FirstOrDefault()?.Item2);
+					}
+					else
+					{
+						shiftPolygon = DeclarationData.Gearbox.ComputeShiftPolygon(GearboxType.APTN, (int)i,
+							null, gearInput, null, axlegearRatio,
+							dynamicTyreRadius, runData.ElectricMachinesData?.FirstOrDefault()?.Item2);
+					}
+				}
+				var gearData = new GearData
+				{
+					ShiftPolygon = shiftPolygon,
+					MaxSpeed = gear.MaxOutputShaftSpeed == null ? null : gear.MaxOutputShaftSpeed * gear.Ratio,
+					MaxTorque = gear.MaxOutputShaftTorque == null ? null : gear.MaxOutputShaftTorque / gear.Ratio,
+					Ratio = gear.Ratio,
+					LossMap = lossMap,
+				};
+
+				gears.Add(i + 1, gearData);
+			}
+
+			retVal.Gears = gears;
+
+			// update disengageWhenHaltingSpeed
+			var firstGear = retVal.GearList.First(x => x.IsLockedGear());
+			if (iepc.Gears.Count > 1 && retVal.Gears[firstGear.Gear].ShiftPolygon.Downshift.Any())
+			{
+				var downshiftSpeedInc = retVal.Gears[firstGear.Gear].ShiftPolygon
+					.InterpolateDownshiftSpeed(0.SI<NewtonMeter>()) * 1.05;
+				var vehicleSpeedDisengage = downshiftSpeedInc / axlegearRatio / retVal.Gears[firstGear.Gear].Ratio *
+											dynamicTyreRadius;
+				retVal.DisengageWhenHaltingSpeed = vehicleSpeedDisengage;
+			}
+
+			return retVal;
+		}
+
+		#region Overrides of GearboxDataAdapterBase
+
+		protected override GearboxData DoCreateGearboxData(IVehicleDeclarationInputData inputData, VectoRunData runData,
+			IShiftPolygonCalculator shiftPolygonCalculator, GearboxType[] supportedGearboxTypes)
+		{
+			return CreateIEPCGearboxData(inputData, runData, shiftPolygonCalculator);
+		}
+		#endregion
+	}
 }
\ No newline at end of file
diff --git a/VectoCore/VectoCore/InputData/Reader/DataObjectAdapter/SimulationComponents/IEPCDataAdapter.cs b/VectoCore/VectoCore/InputData/Reader/DataObjectAdapter/SimulationComponents/IEPCDataAdapter.cs
new file mode 100644
index 0000000000..03c58d718a
--- /dev/null
+++ b/VectoCore/VectoCore/InputData/Reader/DataObjectAdapter/SimulationComponents/IEPCDataAdapter.cs
@@ -0,0 +1,19 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using TUGraz.VectoCommon.InputData;
+using TUGraz.VectoCommon.Utils;
+using TUGraz.VectoCore.InputData.Reader.ComponentData;
+using TUGraz.VectoCore.Models.Declaration;
+using TUGraz.VectoCore.Models.SimulationComponent.Data;
+using TUGraz.VectoCore.Models.SimulationComponent.Data.ElectricMotor;
+
+namespace TUGraz.VectoCore.InputData.Reader.DataObjectAdapter.SimulationComponents
+{
+    public class IEPCDataAdapter
+    {
+		
+	}
+}
diff --git a/VectoCore/VectoCore/InputData/Reader/DataObjectAdapter/SimulationComponents/StrategyDataAdapter/HybridStrategyParameterDataAdapter.cs b/VectoCore/VectoCore/InputData/Reader/DataObjectAdapter/SimulationComponents/StrategyDataAdapter/HybridStrategyParameterDataAdapter.cs
index 3d55c338e7..1fb472a253 100644
--- a/VectoCore/VectoCore/InputData/Reader/DataObjectAdapter/SimulationComponents/StrategyDataAdapter/HybridStrategyParameterDataAdapter.cs
+++ b/VectoCore/VectoCore/InputData/Reader/DataObjectAdapter/SimulationComponents/StrategyDataAdapter/HybridStrategyParameterDataAdapter.cs
@@ -74,8 +74,6 @@ namespace TUGraz.VectoCore.InputData.Reader.DataObjectAdapter.SimulationComponen
 		public HybridStrategyParameters CreateHybridStrategyParameters(BatterySystemData batterySystemData,
 			SuperCapData superCapData, Kilogram vehicleMass, VectoRunData.OvcHevMode ovcMode)
 		{
-
-			
 			if (batterySystemData == null && superCapData == null) {
 				return null;
 			}
@@ -83,9 +81,6 @@ namespace TUGraz.VectoCore.InputData.Reader.DataObjectAdapter.SimulationComponen
 			if (superCapData != null) {
 				throw new VectoException("Super cap for serial hybrid is not implemented");
 			}
-
-
-		
 			var result = new HybridStrategyParameters();
 			
 			result.AuxReserveTime = null;
@@ -115,11 +110,7 @@ namespace TUGraz.VectoCore.InputData.Reader.DataObjectAdapter.SimulationComponen
 					throw new ArgumentOutOfRangeException(nameof(ovcMode), ovcMode, null);
 			}
 
-
-
-
 			return result;
-
 		}
 
 		private void SetGenericParameters(HybridStrategyParameters result, BatterySystem tmpSystem,
@@ -127,7 +118,6 @@ namespace TUGraz.VectoCore.InputData.Reader.DataObjectAdapter.SimulationComponen
 			
 			deltaSoc = CalculatedDeltaSocSHev(vehicleMass, tmpSystem);
 
-
 			result.MinSoC = tmpSystem.MinSoC + 2 * deltaSoc;
 			result.TargetSoC = tmpSystem.MaxSoC - 5 * deltaSoc;
 			result.MaxSoC = double.NaN;
diff --git a/VectoCore/VectoCore/InputData/Reader/Impl/DeclarationMode/HeavyLorryRunDataFactory/DeclarationModeHeavyLorryRunDataFactory_Hybrid.cs b/VectoCore/VectoCore/InputData/Reader/Impl/DeclarationMode/HeavyLorryRunDataFactory/DeclarationModeHeavyLorryRunDataFactory_Hybrid.cs
index 42647efff2..9014db70ab 100644
--- a/VectoCore/VectoCore/InputData/Reader/Impl/DeclarationMode/HeavyLorryRunDataFactory/DeclarationModeHeavyLorryRunDataFactory_Hybrid.cs
+++ b/VectoCore/VectoCore/InputData/Reader/Impl/DeclarationMode/HeavyLorryRunDataFactory/DeclarationModeHeavyLorryRunDataFactory_Hybrid.cs
@@ -1,5 +1,7 @@
 using System;
 using System.Collections.Generic;
+using System.Linq;
+using TUGraz.VectoCommon.Exceptions;
 using TUGraz.VectoCommon.InputData;
 using TUGraz.VectoCommon.Models;
 using TUGraz.VectoCommon.Utils;
@@ -68,7 +70,10 @@ namespace TUGraz.VectoCore.InputData.Reader.Impl.DeclarationMode.HeavyLorryRunDa
 
 			public SerialHybrid(IDeclarationInputDataProvider dataProvider, IDeclarationReport report,
 				ILorryDeclarationDataAdapter declarationDataAdapter) : base(dataProvider, report,
-				declarationDataAdapter) { }
+				declarationDataAdapter)
+			{
+
+			}
 
 			#region Overrides of Hybrid
 
@@ -93,41 +98,40 @@ namespace TUGraz.VectoCore.InputData.Reader.Impl.DeclarationMode.HeavyLorryRunDa
 
 
 				runData.EngineData = DataAdapter.CreateEngineData(vehicle, engineMode, mission);
+				
 				DataAdapter.CreateREESSData(vehicle.Components.ElectricStorage, vehicle.VehicleType, vehicle.OvcHev,
 					((batteryData) => runData.BatteryData = batteryData),
 					((sCdata => runData.SuperCapData = sCdata)));
+
+				
 				runData.ElectricMachinesData = DataAdapter.CreateElectricMachines(
 					vehicle.Components.ElectricMachines, vehicle.ElectricMotorTorqueLimits,
 					runData.BatteryData.CalculateAverageVoltage());
+
+				
+
+
+
+				if (vehicle.VehicleType == VectoSimulationJobType.IEPC_S) {
+					var iepcData = DataAdapter.CreateIEPCElectricMachines(vehicle.Components.IEPC,
+						runData.BatteryData.CalculateAverageVoltage());
+					iepcData.ForEach(iepc => runData.ElectricMachinesData.Add(iepc));
+				}
+
 				if (vehicle.Components.AxleGearInputData != null) {
 					runData.AxleGearData = DataAdapter.CreateAxleGearData(vehicle.Components.AxleGearInputData);
 				}
 				
 				runData.Retarder = DataAdapter.CreateRetarderData(vehicle.Components.RetarderInputData);
+
 				runData.Aux = DataAdapter.CreateAuxiliaryData(vehicle.Components.AuxiliaryInputData, null, mission.MissionType,
 					_segment.VehicleClass, vehicle.Length, vehicle.Components.AxleWheels.NumSteeredAxles,
 					VectoSimulationJobType.SerialHybridVehicle);
 
-				if (vehicle.ArchitectureID == ArchitectureID.S2) {
-					runData.GearshiftParameters =
-						DataAdapter.CreateGearshiftData(
-							runData.AxleGearData?.AxleGear.Ratio ?? 1.0,
-							null,
-							vehicle.Components.GearboxInputData.Type,
-							vehicle.Components.GearboxInputData.Gears.Count
-						);
-					var shiftStrategyName =
-						PowertrainBuilder.GetShiftStrategyName(vehicle.Components.GearboxInputData.Type,
-							vehicle.VehicleType);
-					runData.GearboxData = DataAdapter.CreateGearboxData(vehicle, runData,
-						ShiftPolygonCalculator.Create(shiftStrategyName, runData.GearshiftParameters));
-				} else {
-					runData.GearshiftParameters = new ShiftStrategyParameters()
-					{
-						StartSpeed = DeclarationData.GearboxTCU.StartSpeed,
-						StartAcceleration = DeclarationData.GearboxTCU.StartAcceleration
-					};
-				}
+				
+				CreateGearboxAndGearshiftData(vehicle, runData);
+
+
 				runData.HybridStrategyParameters =
 					DataAdapter.CreateHybridStrategy(runData.BatteryData, runData.SuperCapData, runData.VehicleData.TotalVehicleMass, ovcMode, loading.Key, runData.VehicleData.VehicleClass, mission.MissionType);
 
@@ -147,9 +151,8 @@ namespace TUGraz.VectoCore.InputData.Reader.Impl.DeclarationMode.HeavyLorryRunDa
 					: ptoTransmissionData;
 
 
-				if (ovcMode != VectoRunData.OvcHevMode.NotApplicable) {
+				if (ovcMode != VectoRunData.OvcHevMode.NotApplicable && runData.InputData.JobInputData.Vehicle.OvcHev) {
 					runData.ModFileSuffix += ovcMode == VectoRunData.OvcHevMode.ChargeSustaining ? "CS" : "CD";
-
 				}
 
 				if (ovcMode == VectoRunData.OvcHevMode.ChargeDepleting) {
@@ -161,6 +164,14 @@ namespace TUGraz.VectoCore.InputData.Reader.Impl.DeclarationMode.HeavyLorryRunDa
 				return runData;
 			}
 
+			protected virtual void CreateGearboxAndGearshiftData(IVehicleDeclarationInputData vehicle, VectoRunData runData)
+			{
+				runData.GearshiftParameters = new ShiftStrategyParameters() {
+					StartSpeed = DeclarationData.GearboxTCU.StartSpeed,
+					StartAcceleration = DeclarationData.GearboxTCU.StartAcceleration
+				};
+			}
+
 			#endregion
 
 			#region Overrides of LorryBase
@@ -220,6 +231,8 @@ namespace TUGraz.VectoCore.InputData.Reader.Impl.DeclarationMode.HeavyLorryRunDa
 				runData.ElectricMachinesData = DataAdapter.CreateElectricMachines(
 					vehicle.Components.ElectricMachines, vehicle.ElectricMotorTorqueLimits,
 					runData.BatteryData.CalculateAverageVoltage());
+
+
 				
 				if (vehicle.Components.AxleGearInputData != null)
 				{
@@ -274,7 +287,7 @@ namespace TUGraz.VectoCore.InputData.Reader.Impl.DeclarationMode.HeavyLorryRunDa
 					: ptoTransmissionData;
 
 
-				if (ovcMode != VectoRunData.OvcHevMode.NotApplicable)
+				if (ovcMode != VectoRunData.OvcHevMode.NotApplicable && runData.InputData.JobInputData.Vehicle.OvcHev)
 				{
 					runData.ModFileSuffix += ovcMode == VectoRunData.OvcHevMode.ChargeSustaining ? "CS" : "CD";
 				}
@@ -301,7 +314,30 @@ namespace TUGraz.VectoCore.InputData.Reader.Impl.DeclarationMode.HeavyLorryRunDa
 			public HEV_S2(IDeclarationInputDataProvider dataProvider, IDeclarationReport report,
 				ILorryDeclarationDataAdapter declarationDataAdapter) : base(dataProvider, report,
 				declarationDataAdapter)
-			{ }
+			{
+
+
+			}
+
+			#region Overrides of SerialHybrid
+
+			protected override void CreateGearboxAndGearshiftData(IVehicleDeclarationInputData vehicle, VectoRunData runData)
+			{
+				runData.GearshiftParameters =
+					DataAdapter.CreateGearshiftData(
+						runData.AxleGearData?.AxleGear.Ratio ?? 1.0,
+						null,
+						vehicle.Components.GearboxInputData.Type,
+						vehicle.Components.GearboxInputData.Gears.Count
+					);
+				var shiftStrategyName =
+					PowertrainBuilder.GetShiftStrategyName(vehicle.Components.GearboxInputData.Type,
+						vehicle.VehicleType);
+				runData.GearboxData = DataAdapter.CreateGearboxData(vehicle, runData,
+					ShiftPolygonCalculator.Create(shiftStrategyName, runData.GearshiftParameters));
+			}
+
+			#endregion
 		}
 
 		public class HEV_S3 : SerialHybrid
@@ -319,7 +355,99 @@ namespace TUGraz.VectoCore.InputData.Reader.Impl.DeclarationMode.HeavyLorryRunDa
 		public class HEV_S_IEPC : SerialHybrid
 		{
 			public HEV_S_IEPC(IDeclarationInputDataProvider dataProvider, IDeclarationReport report,
-				ILorryDeclarationDataAdapter declarationDataAdapter) : base(dataProvider, report, declarationDataAdapter) { }
+				ILorryDeclarationDataAdapter declarationDataAdapter) : base(dataProvider, report,
+				declarationDataAdapter)
+			{
+
+			}
+
+			#region Overrides of SerialHybrid
+
+			protected override VectoRunData CreateVectoRunData(IVehicleDeclarationInputData vehicle, Mission mission, KeyValuePair<LoadingType, Tuple<Kilogram, double?>> loading,
+				int? modeIdx, VectoRunData.OvcHevMode ovcMode = VectoRunData.OvcHevMode.NotApplicable)
+			{
+				AxleGearRequired();
+				return base.CreateVectoRunData(vehicle, mission, loading, modeIdx, ovcMode);
+			}
+
+			#endregion
+
+			private bool AxleGearRequired()
+			{
+				var vehicle = InputDataProvider.JobInputData.Vehicle;
+				var iepcInput = vehicle.Components.IEPC;
+				var axleGearRequired = !iepcInput.DifferentialIncluded && !iepcInput.DesignTypeWheelMotor;
+				if (axleGearRequired && vehicle.Components.AxleGearInputData == null)
+				{
+					throw new VectoException(
+						$"Axlegear reqhired for selected type of IEPC! DifferentialIncluded: {iepcInput.DifferentialIncluded}, DesignTypeWheelMotor: {iepcInput.DesignTypeWheelMotor}");
+				}
+
+				var numGearsPowermap =
+					iepcInput.VoltageLevels.Select(x => Tuple.Create(x.VoltageLevel, x.PowerMap.Count)).ToArray();
+				var gearCount = iepcInput.Gears.Count;
+				var numGearsDrag = iepcInput.DragCurves.Count;
+
+				if (numGearsPowermap.Any(x => x.Item2 != gearCount))
+				{
+					throw new VectoException(
+						$"Number of gears for voltage levels does not match! PowerMaps: {numGearsPowermap.Select(x => $"{x.Item1}: {x.Item2}").Join()}; Gear count: {gearCount}");
+				}
+
+				if (numGearsDrag > 1 && numGearsDrag != gearCount)
+				{
+					throw new VectoException(
+						$"Number of gears drag curve does not match gear count! DragCurve {numGearsDrag}; Gear count: {gearCount}");
+				}
+
+				return axleGearRequired;
+			}
+
+			#region Overrides of SerialHybrid
+
+			protected override void CreateGearboxAndGearshiftData(IVehicleDeclarationInputData vehicle, VectoRunData runData)
+			{
+				runData.GearshiftParameters =
+					DataAdapter.CreateGearshiftData(
+						runData.AxleGearData?.AxleGear.Ratio ?? 1.0,
+						null,
+						GearboxType.APTN,
+						vehicle.Components.IEPC.Gears.Count
+					);
+				var shiftStrategyName =
+					PowertrainBuilder.GetShiftStrategyName(GearboxType.APTN,
+						vehicle.VehicleType);
+				runData.GearboxData = DataAdapter.CreateGearboxData(vehicle, runData,
+					ShiftPolygonCalculator.Create(shiftStrategyName, runData.GearshiftParameters));
+
+				//var gearshiftParams = dao.CreateGearshiftData(GearboxType.APTN,
+				//	InputDataProvider.DriverInputData.GearshiftInputData,
+				//	axlegearData?.AxleGear.Ratio ?? 1.0, null);
+				//var tmpRunData = new VectoRunData()
+				//{
+				//	JobType = VectoSimulationJobType.IEPC_E,
+				//	GearboxData = new GearboxData()
+				//	{
+				//		Type = GearboxType.APTN,
+				//	},
+				//	GearshiftParameters = gearshiftParams,
+				//	ElectricMachinesData = electricMachinesData,
+				//	//VehicleData = dao.CreateVehicleData(vehicle)
+				//};
+				//var tempVehicle = dao.CreateVehicleData(vehicle);
+				//var tmpStrategy = PowertrainBuilder.GetShiftStrategy(new SimplePowertrainContainer(tmpRunData));
+				//var gearboxData = dao.CreateIEPCGearboxData(
+				//	InputDataProvider, new VectoRunData()
+				//	{
+				//		JobType = VectoSimulationJobType.IEPC_E,
+				//		VehicleData = tempVehicle,
+				//		AxleGearData = axlegearData,
+				//		ElectricMachinesData = electricMachinesData
+				//	}, tmpStrategy);
+
+			}
+
+			#endregion
 		}
 
 		public class HEV_P1 : ParallelHybrid
diff --git a/VectoCore/VectoCore/InputData/Reader/VectoRunDataFactoryNinjectModule.cs b/VectoCore/VectoCore/InputData/Reader/VectoRunDataFactoryNinjectModule.cs
index c576dde4e6..afa6b4cd29 100644
--- a/VectoCore/VectoCore/InputData/Reader/VectoRunDataFactoryNinjectModule.cs
+++ b/VectoCore/VectoCore/InputData/Reader/VectoRunDataFactoryNinjectModule.cs
@@ -70,7 +70,7 @@ namespace TUGraz.VectoCore.InputData.Reader
 					ArchitectureID.S4));
 
 			Bind<IVectoRunDataFactory>().To<DeclarationModeHeavyLorryRunDataFactory.HEV_S_IEPC>().Named(
-				_vehicleStringHelper.GetName(VehicleCategoryHelper.Lorry, VectoSimulationJobType.SerialHybridVehicle,
+				_vehicleStringHelper.GetName(VehicleCategoryHelper.Lorry, VectoSimulationJobType.IEPC_S,
 					ArchitectureID.S_IEPC));
 			
 
-- 
GitLab