From 70c9f0fef8ac28966bd3fd8d6f6df39880477041 Mon Sep 17 00:00:00 2001
From: "VKMTHD\\haraldmartini" <harald.martini@student.tugraz.at>
Date: Wed, 12 Oct 2022 11:45:05 +0200
Subject: [PATCH] implemented generic soc with deterioration for PEV, OVC-HEV,
 NOVC-HEV

---
 .../DeclarationDataAdapterHeavyLorry.cs       |  10 +-
 .../IDeclarationDataAdapter.cs                |   2 +-
 .../BatteryDataAdapter.cs                     |  11 +-
 ...DeclarationModeHeavyLorryRunDataFactory.cs |   2 +-
 ...tionModeHeavyLorryRunDataFactory_Hybrid.cs |   2 +-
 .../Models/Declaration/DeclarationData.cs     |   2 +
 .../Models/Declaration/GenericSOC.cs          | 103 +++++++++++++++
 .../DataAdapter/BatteryDataAdapterTest.cs     | 119 ++++++++++--------
 8 files changed, 187 insertions(+), 64 deletions(-)
 create mode 100644 VectoCore/VectoCore/Models/Declaration/GenericSOC.cs

diff --git a/VectoCore/VectoCore/InputData/Reader/DataObjectAdapter/HeavyLorry/DeclarationDataAdapterHeavyLorry.cs b/VectoCore/VectoCore/InputData/Reader/DataObjectAdapter/HeavyLorry/DeclarationDataAdapterHeavyLorry.cs
index 3ed33b0359..291c245610 100644
--- a/VectoCore/VectoCore/InputData/Reader/DataObjectAdapter/HeavyLorry/DeclarationDataAdapterHeavyLorry.cs
+++ b/VectoCore/VectoCore/InputData/Reader/DataObjectAdapter/HeavyLorry/DeclarationDataAdapterHeavyLorry.cs
@@ -90,7 +90,7 @@ namespace TUGraz.VectoCore.InputData.Reader.DataObjectAdapter.HeavyLorry
 				throw new NotImplementedException();
 			}
 
-			public virtual BatterySystemData CreateBatteryData(IElectricStorageSystemDeclarationInputData componentsElectricStorage)
+			public virtual BatterySystemData CreateBatteryData(IElectricStorageSystemDeclarationInputData componentsElectricStorage, VectoSimulationJobType jobType, bool ovc)
 			{
 				throw new NotImplementedException();
 			}
@@ -247,9 +247,9 @@ namespace TUGraz.VectoCore.InputData.Reader.DataObjectAdapter.HeavyLorry
 					gears);
 			}
 
-			public override BatterySystemData CreateBatteryData(IElectricStorageSystemDeclarationInputData batteryInputData)
+			public override BatterySystemData CreateBatteryData(IElectricStorageSystemDeclarationInputData batteryInputData, VectoSimulationJobType jobType, bool ovc)
 			{
-				return _eletricStorageAdapter.CreateBatteryData(batteryInputData);
+				return _eletricStorageAdapter.CreateBatteryData(batteryInputData, jobType, ovc);
 			}
 
 			public override SuperCapData CreateSuperCapData(IElectricStorageSystemDeclarationInputData reessInputData)
@@ -380,9 +380,9 @@ namespace TUGraz.VectoCore.InputData.Reader.DataObjectAdapter.HeavyLorry
 				return _electricMachineAdapter.CreateElectricMachines(electricMachines, torqueLimits, averageVoltage, gears);
 			}
 
-			public override BatterySystemData CreateBatteryData(IElectricStorageSystemDeclarationInputData componentsElectricStorage)
+			public override BatterySystemData CreateBatteryData(IElectricStorageSystemDeclarationInputData componentsElectricStorage, VectoSimulationJobType jobType, bool ovc)
 			{
-				return _electricStorageAdapter.CreateBatteryData(batteryInputData: componentsElectricStorage);
+				return _electricStorageAdapter.CreateBatteryData(batteryInputData: componentsElectricStorage, jobType: jobType, ovc: ovc);
 			}
 
 			public override SuperCapData CreateSuperCapData(IElectricStorageSystemDeclarationInputData componentsElectricStorage)
diff --git a/VectoCore/VectoCore/InputData/Reader/DataObjectAdapter/IDeclarationDataAdapter.cs b/VectoCore/VectoCore/InputData/Reader/DataObjectAdapter/IDeclarationDataAdapter.cs
index 08c27a6ae8..6c72b8f7b6 100644
--- a/VectoCore/VectoCore/InputData/Reader/DataObjectAdapter/IDeclarationDataAdapter.cs
+++ b/VectoCore/VectoCore/InputData/Reader/DataObjectAdapter/IDeclarationDataAdapter.cs
@@ -68,7 +68,7 @@ namespace TUGraz.VectoCore.InputData.Reader.DataObjectAdapter
 		
 		
 		IList<Tuple<PowertrainPosition, ElectricMotorData>> CreateElectricMachines(IElectricMachinesDeclarationInputData electricMachines, IDictionary<PowertrainPosition, IList<Tuple<Volt, TableData>>> torqueLimits, Volt averageVoltage, GearList gears = null);
-		BatterySystemData CreateBatteryData(IElectricStorageSystemDeclarationInputData componentsElectricStorage);
+		BatterySystemData CreateBatteryData(IElectricStorageSystemDeclarationInputData componentsElectricStorage, VectoSimulationJobType jobType, bool ovc);
 		SuperCapData CreateSuperCapData(IElectricStorageSystemDeclarationInputData componentsElectricStorage);
 		HybridStrategyParameters CreateHybridStrategy(BatterySystemData runDataBatteryData, SuperCapData runDataSuperCapData);
 		ShiftStrategyParameters CreateDummyGearshiftStrategy();
diff --git a/VectoCore/VectoCore/InputData/Reader/DataObjectAdapter/SimulationComponents/BatteryDataAdapter.cs b/VectoCore/VectoCore/InputData/Reader/DataObjectAdapter/SimulationComponents/BatteryDataAdapter.cs
index df6bf39ddc..82a4a9849d 100644
--- a/VectoCore/VectoCore/InputData/Reader/DataObjectAdapter/SimulationComponents/BatteryDataAdapter.cs
+++ b/VectoCore/VectoCore/InputData/Reader/DataObjectAdapter/SimulationComponents/BatteryDataAdapter.cs
@@ -13,7 +13,8 @@ namespace TUGraz.VectoCore.InputData.Reader.DataObjectAdapter.SimulationComponen
 {
 	public class ElectricStorageAdapter
 	{
-		public BatterySystemData CreateBatteryData(IElectricStorageSystemDeclarationInputData batteryInputData)
+		public BatterySystemData CreateBatteryData(IElectricStorageSystemDeclarationInputData batteryInputData,
+			VectoSimulationJobType jobType, bool ovc)
 		{
 			if (batteryInputData == null)
 			{
@@ -28,6 +29,7 @@ namespace TUGraz.VectoCore.InputData.Reader.DataObjectAdapter.SimulationComponen
 			}
 
 			var retVal = new BatterySystemData();
+			var genericSOC = DeclarationData.Battery.GenericSOC.Lookup(jobType, ovc);
 			foreach (var entry in batteries)
 			{
 				var b = entry.REESSPack as IBatteryPackDeclarationInputData;
@@ -37,12 +39,13 @@ namespace TUGraz.VectoCore.InputData.Reader.DataObjectAdapter.SimulationComponen
 				}
 
 				//for (var i = 0; i < entry.Count; i++) {
-					var minSoc = DeclarationData.Battery.GetMinSoc(b.BatteryType);
+					var minSoc = genericSOC.SOCMin;
 					if (b.MinSOC != null && b.MinSOC > minSoc) {
 						minSoc = b.MinSOC.Value;
 					}
-					var maxSoc = DeclarationData.Battery.GetMaxSoc(b.BatteryType);
-					if (b.MaxSOC != null && b.MaxSOC < maxSoc) {
+
+					var maxSoc = genericSOC.SOCMax;
+					if (b.MaxSOC != null && b.MaxSOC < maxSoc && b.MaxSOC > b.MinSOC) {
 						maxSoc = b.MaxSOC.Value;
 					}
 				
diff --git a/VectoCore/VectoCore/InputData/Reader/Impl/DeclarationMode/HeavyLorryRunDataFactory/DeclarationModeHeavyLorryRunDataFactory.cs b/VectoCore/VectoCore/InputData/Reader/Impl/DeclarationMode/HeavyLorryRunDataFactory/DeclarationModeHeavyLorryRunDataFactory.cs
index 32826432c5..0760346b47 100644
--- a/VectoCore/VectoCore/InputData/Reader/Impl/DeclarationMode/HeavyLorryRunDataFactory/DeclarationModeHeavyLorryRunDataFactory.cs
+++ b/VectoCore/VectoCore/InputData/Reader/Impl/DeclarationMode/HeavyLorryRunDataFactory/DeclarationModeHeavyLorryRunDataFactory.cs
@@ -333,7 +333,7 @@ namespace TUGraz.VectoCore.InputData.Reader.Impl.DeclarationMode.HeavyLorryRunDa
 				result.AirdragData =
 					DataAdapter.CreateAirdragData(vehicle.Components.AirdragInputData, mission, _segment);
 				result.DriverData = DataAdapter.CreateDriverData(_segment);
-				result.BatteryData = DataAdapter.CreateBatteryData(componentsElectricStorage: vehicle.Components.ElectricStorage);
+				result.BatteryData = DataAdapter.CreateBatteryData(componentsElectricStorage: vehicle.Components.ElectricStorage, vehicle.VehicleType, true);
 				result.SuperCapData = DataAdapter.CreateSuperCapData(componentsElectricStorage: vehicle.Components.ElectricStorage);
 				result.ElectricMachinesData = DataAdapter.CreateElectricMachines(vehicle.Components.ElectricMachines, vehicle.ElectricMotorTorqueLimits, result.BatteryData.CalculateAverageVoltage(), null);
 				result.AngledriveData = DataAdapter.CreateAngledriveData(vehicle.Components.AngledriveInputData);
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 8cf5ac751f..abbe21afb9 100644
--- a/VectoCore/VectoCore/InputData/Reader/Impl/DeclarationMode/HeavyLorryRunDataFactory/DeclarationModeHeavyLorryRunDataFactory_Hybrid.cs
+++ b/VectoCore/VectoCore/InputData/Reader/Impl/DeclarationMode/HeavyLorryRunDataFactory/DeclarationModeHeavyLorryRunDataFactory_Hybrid.cs
@@ -87,7 +87,7 @@ namespace TUGraz.VectoCore.InputData.Reader.Impl.DeclarationMode.HeavyLorryRunDa
 				var runData = CreateCommonRunData(vehicle, mission, loading, _segment, engineModes, modeIdx.Value);
 				runData.VehicleData = DataAdapter.CreateVehicleData(vehicle, _segment, mission, loading, _allowVocational);
 				runData.EngineData = DataAdapter.CreateEngineData(vehicle, engineMode, mission);
-				runData.BatteryData = DataAdapter.CreateBatteryData(vehicle.Components.ElectricStorage);
+				runData.BatteryData = DataAdapter.CreateBatteryData(vehicle.Components.ElectricStorage, vehicle.VehicleType, vehicle.OvcHev);
 				runData.SuperCapData = DataAdapter.CreateSuperCapData(vehicle.Components.ElectricStorage);
 				runData.ElectricMachinesData = DataAdapter.CreateElectricMachines(vehicle.Components.ElectricMachines, vehicle.ElectricMotorTorqueLimits, runData.BatteryData.CalculateAverageVoltage());
 				runData.GearboxData = _gearboxData;
diff --git a/VectoCore/VectoCore/Models/Declaration/DeclarationData.cs b/VectoCore/VectoCore/Models/Declaration/DeclarationData.cs
index 9c19fa28e5..0f24809961 100644
--- a/VectoCore/VectoCore/Models/Declaration/DeclarationData.cs
+++ b/VectoCore/VectoCore/Models/Declaration/DeclarationData.cs
@@ -1225,6 +1225,8 @@ namespace TUGraz.VectoCore.Models.Declaration
 
 		public static class Battery
 		{
+			public static GenericSOC GenericSOC = new GenericSOC();
+
 			/// <summary>
 			/// Percentage of the maximum voltage of the battery
 			/// </summary>
diff --git a/VectoCore/VectoCore/Models/Declaration/GenericSOC.cs b/VectoCore/VectoCore/Models/Declaration/GenericSOC.cs
new file mode 100644
index 0000000000..3d32cbecfd
--- /dev/null
+++ b/VectoCore/VectoCore/Models/Declaration/GenericSOC.cs
@@ -0,0 +1,103 @@
+using System;
+using System.Collections.Generic;
+using System.Data;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using TUGraz.VectoCommon.InputData;
+using TUGraz.VectoCommon.Utils;
+using TUGraz.VectoCore.InputData.Reader.Impl;
+using TUGraz.VectoCore.Utils;
+
+namespace TUGraz.VectoCore.Models.Declaration
+{
+
+	public class GenericSOC : LookupData<VectoSimulationJobType, bool, GenericSOC.GenericSOCData>
+    {
+		protected override string ResourceId => DeclarationData.DeclarationDataResourcePrefix + ".GenericSOC.csv";
+		protected override string ErrorMessage => "GenericSOC Lookup Error: no value found. Key: '{0}'";
+
+		private double _factor = 1d/100;
+		public struct GenericSOCData
+		{
+			public double SOCMin;
+			public double SOCMax;
+			public double GenericDetorioration;
+		}
+
+		public GenericSOC()
+		{
+		}
+
+		#region Overrides of LookupData
+
+		#region Overrides of LookupData<VectoSimulationJobType,bool,GenericSOCData>
+		
+		public override GenericSOCData Lookup(VectoSimulationJobType jobType, bool ovc)
+		{
+			return base.Lookup(jobType, ovc);
+		}
+
+		#endregion
+
+
+		protected override void ParseData(DataTable table)
+		{
+			foreach (DataRow row in table.Rows) {
+				var architecture = row["architecture"];
+				switch (architecture) {
+					case "PEV":
+						CreatePEVEntries(row);
+						break;
+					case "HEV":
+						CreateHEVEntries(row);
+						break;
+					default:
+						throw new ArgumentOutOfRangeException();
+				}
+			}
+		}
+		#endregion
+
+
+		private void CreatePEVEntries(DataRow row)
+		{
+			var architectures = new VectoSimulationJobType[] {
+				VectoSimulationJobType.BatteryElectricVehicle,
+				VectoSimulationJobType.IEPC_E
+			};
+			var val = GenericSocData(row);
+			foreach (var archs in architectures) {
+				Data.Add(new Tuple<VectoSimulationJobType, bool>(archs, row.ParseBoolean("ovc")), val);
+			}
+			
+		}
+
+		private GenericSOCData GenericSocData(DataRow row)
+		{
+			var val = new GenericSOCData() {
+				SOCMin = row.ParseDouble("genericsocmin") * _factor,
+				SOCMax = row.ParseDouble("genericsocmax") * _factor,
+				GenericDetorioration = row.ParseDouble("genericdeterioration") * _factor,
+			};
+			return val;
+		}
+
+		private void CreateHEVEntries(DataRow row)
+		{
+			var val = GenericSocData(row);
+			var architectures = new VectoSimulationJobType[] {
+				VectoSimulationJobType.ParallelHybridVehicle,
+				VectoSimulationJobType.SerialHybridVehicle,
+				VectoSimulationJobType.IHPC,
+				VectoSimulationJobType.IEPC_S
+			};
+			foreach (var archs in architectures)
+			{
+				Data.Add(new Tuple<VectoSimulationJobType, bool>(archs, row.ParseBoolean("ovc")), val);
+			}
+		}
+
+
+	}
+}
diff --git a/VectoCore/VectoCoreTest/Models/Declaration/DataAdapter/BatteryDataAdapterTest.cs b/VectoCore/VectoCoreTest/Models/Declaration/DataAdapter/BatteryDataAdapterTest.cs
index c124018e54..95b56f4bc6 100644
--- a/VectoCore/VectoCoreTest/Models/Declaration/DataAdapter/BatteryDataAdapterTest.cs
+++ b/VectoCore/VectoCoreTest/Models/Declaration/DataAdapter/BatteryDataAdapterTest.cs
@@ -1,4 +1,5 @@
-using System.Collections.Generic;
+using System;
+using System.Collections.Generic;
 using System.Data;
 using System.Linq;
 using System.Runtime.InteropServices.ComTypes;
@@ -6,6 +7,7 @@ using Castle.Core.Resource;
 using Moq;
 using NLog.LayoutRenderers;
 using NUnit.Framework;
+using TUGraz.VectoCommon.Exceptions;
 using TUGraz.VectoCommon.InputData;
 using TUGraz.VectoCommon.Utils;
 using TUGraz.VectoCore.InputData.FileIO.XML.Declaration.DataProvider;
@@ -27,73 +29,53 @@ public class BatteryDataAdapterTest
 
 	}
 
-	[TestCase(null, null, 0.0725, 0.9275, 0.8550)]
-	public void PEVBatteryDataAdapterTest(
+	//PEV
+	[TestCase(null, null, 0.0725, 0.9275, 0.8550, VectoSimulationJobType.BatteryElectricVehicle, true)]
+	[TestCase(null, null, 0.0725, 0.9275, 0.8550, VectoSimulationJobType.BatteryElectricVehicle, false)]
+
+	//HEV Ovc
+	[TestCase(0.23, 0.77, 0.2435, 0.7565, 0.5130, VectoSimulationJobType.SerialHybridVehicle, true)]
+	[TestCase(null, null, 0.1675, 0.8325, 0.6650, VectoSimulationJobType.SerialHybridVehicle, true)]
+	[TestCase(0.05, 0.97, 0.1675, 0.8325, 0.6650, VectoSimulationJobType.SerialHybridVehicle, true)]
+
+	//HEV Non Ovc
+	[TestCase(0.40, 0.60, 0.4050, 0.5950, 0.1900, VectoSimulationJobType.SerialHybridVehicle, false)]
+	[TestCase(null, null, 0.2625, 0.7375, 0.4750, VectoSimulationJobType.SerialHybridVehicle, false)]
+	[TestCase(0.15, 0.85, 0.2625, 0.7375, 0.4750, VectoSimulationJobType.SerialHybridVehicle, false)]
+
+
+	public void GenericSOCTest(
 		double inputMinSoc,
 		double inputMaxSoc,
 		double expectedMinSoc,
 		double expectedMaxSoc,
-		double usableSocRange)
+		double usableSocRange, VectoSimulationJobType vectoSimulationJobType, bool ovc)
 	{
-		var elStorage = CreateElectricStorage(null, null);
-		var inputData = CreateElectricStorageSystem(elStorage.Object);
 
+			var elStorage = CreateElectricStorage(inputMinSoc, inputMaxSoc);
+			var inputData = CreateElectricStorageSystem(elStorage.Object);
 
-		var batteryData = _electricStorageAdapter.CreateBatteryData(inputData.Object);
-		Assert.AreEqual(1, batteryData.Batteries.Count);
-		
-		var battery = batteryData.Batteries.FirstOrDefault().Item2;
-		
-		Assert.IsTrue(battery.MinSOC.IsEqual(expectedMinSoc));
-		Assert.IsTrue(battery.MaxSOC.IsEqual(expectedMaxSoc ));
 
-		Assert.IsTrue(usableSocRange.IsEqual(battery.GetUsableSocRange()), $"Invalid {nameof(usableSocRange)} expected {usableSocRange} got {battery.GetUsableSocRange()}");
+			BatterySystemData batteryData;
+			if (vectoSimulationJobType == VectoSimulationJobType.BatteryElectricVehicle && !ovc) {
 
-	}
+				Assert.Throws<VectoException>(() => _electricStorageAdapter.CreateBatteryData(inputData.Object, vectoSimulationJobType, ovc));
+				Assert.Pass();
+			}
 
-	private static Mock<IElectricStorageDeclarationInputData> CreateElectricStorage(double? minSoc, double? maxSoc)
-	{
-		var elStorage = new Mock<IElectricStorageDeclarationInputData>();
-		var ressPack = new Mock<IBatteryPackDeclarationInputData>();
+			batteryData = _electricStorageAdapter.CreateBatteryData(inputData.Object, vectoSimulationJobType, ovc);
 
-		ressPack.Setup(m => m.Capacity).Returns((1000).SI<AmpereSecond>());
 
-		ressPack.Setup(m => m.MinSOC).Returns(() => minSoc);
-		ressPack.Setup(m => m.MaxSOC).Returns(() => maxSoc);
-		ressPack.Setup(m => m.MaxCurrentMap).Returns(
-			GetMockTableData(new[] {
-				new[]{"0.0", "0.0", "0.0"}, 
-				new[]{"0.0", "0.0", "0.0"},
-				new[]{"0.0", "0.0", "0.0"}
-			}));
 
-		ressPack.Setup(m => m.InternalResistanceCurve).Returns(
-			GetMockTableData(new[] {
-				new[]{"0.0", "0.0"},
-				new[]{"0.0", "0.0"},
-				new[]{"0.0", "0.0"}
-			}));
-		ressPack.Setup(m => m.VoltageCurve).Returns(
-			GetMockTableData(new[] {
-				new[]{"0.0", "0.0"},
-				new[]{"0.0", "0.0"},
-				new[]{"0.0", "0.0"}
-			}));
-
-		elStorage.Setup(m => m.REESSPack).Returns(() => ressPack.Object);
-		return elStorage;
-	}
-
-	[TestCase]
-	public void OVCHevBatteryDataAdapterTest()
-	{
+			Assert.AreEqual(1, batteryData.Batteries.Count);
 
-	}
+			var battery = batteryData.Batteries.FirstOrDefault().Item2;
 
-	[TestCase]
-	public void NonOVCHevBatteryDataAdapterTest()
-	{
+			Assert.IsTrue(battery.MinSOC.IsEqual(expectedMinSoc), $"Expected: {expectedMinSoc}, Actual{battery.MinSOC}");
+			Assert.IsTrue(battery.MaxSOC.IsEqual(expectedMaxSoc), $"Expected: {expectedMaxSoc}, Actual{battery.MaxSOC}");
 
+			Assert.IsTrue(usableSocRange.IsEqual(battery.GetUsableSocRange()),
+				$"Invalid {nameof(usableSocRange)} expected {usableSocRange} got {battery.GetUsableSocRange()}");
 	}
 
 	Mock<IElectricStorageSystemDeclarationInputData> CreateElectricStorageSystem(params IElectricStorageDeclarationInputData[] elStorageInputData)
@@ -122,6 +104,39 @@ public class BatteryDataAdapterTest
 	}
 
 
+	private static Mock<IElectricStorageDeclarationInputData> CreateElectricStorage(double? minSoc, double? maxSoc)
+	{
+		var elStorage = new Mock<IElectricStorageDeclarationInputData>();
+		var ressPack = new Mock<IBatteryPackDeclarationInputData>();
+
+		ressPack.Setup(m => m.Capacity).Returns((1000).SI<AmpereSecond>());
+
+		ressPack.Setup(m => m.MinSOC).Returns(() => minSoc);
+		ressPack.Setup(m => m.MaxSOC).Returns(() => maxSoc);
+		ressPack.Setup(m => m.MaxCurrentMap).Returns(
+			GetMockTableData(new[] {
+				new[]{"0.0", "0.0", "0.0"},
+				new[]{"0.0", "0.0", "0.0"},
+				new[]{"0.0", "0.0", "0.0"}
+			}));
+
+		ressPack.Setup(m => m.InternalResistanceCurve).Returns(
+			GetMockTableData(new[] {
+				new[]{"0.0", "0.0"},
+				new[]{"0.0", "0.0"},
+				new[]{"0.0", "0.0"}
+			}));
+		ressPack.Setup(m => m.VoltageCurve).Returns(
+			GetMockTableData(new[] {
+				new[]{"0.0", "0.0"},
+				new[]{"0.0", "0.0"},
+				new[]{"0.0", "0.0"}
+			}));
+
+		elStorage.Setup(m => m.REESSPack).Returns(() => ressPack.Object);
+		return elStorage;
+	}
+
 }
 
 internal static class BatteryDataExtension
-- 
GitLab