diff --git a/VectoCore/VectoCore/Models/Declaration/DeclarationData.cs b/VectoCore/VectoCore/Models/Declaration/DeclarationData.cs index f5cfc1572816563c11293ace7e1adb22016aab8b..a2defbf06a5c0aa2244c710e66918d52617a81de 100644 --- a/VectoCore/VectoCore/Models/Declaration/DeclarationData.cs +++ b/VectoCore/VectoCore/Models/Declaration/DeclarationData.cs @@ -93,7 +93,7 @@ namespace TUGraz.VectoCore.Models.Declaration public static readonly PTOTransmission PTOTransmission = new PTOTransmission(); - public static readonly HEVStrategyParameters InitEquivalenceFactors = new HEVStrategyParametersLorry(); + public static readonly HEVStrategyParameters HEVStrategyParameters = new HEVStrategyParametersLorry(); //public static readonly HEVStrategyParameters InitEquivalenceFactorsBus = new HEVStrategyParametersBus(); public static readonly double ElectricMachineDefaultMechanicalTransmissionEfficiency = 1; diff --git a/VectoCore/VectoCore/Models/Declaration/InitEquivalenceFactors.cs b/VectoCore/VectoCore/Models/Declaration/InitEquivalenceFactors.cs index ab6574630cfc39a5bf1feb01d095c4bc08d20d8e..6369ed54c36defe7ee15e9d63c8f7084b4274b7a 100644 --- a/VectoCore/VectoCore/Models/Declaration/InitEquivalenceFactors.cs +++ b/VectoCore/VectoCore/Models/Declaration/InitEquivalenceFactors.cs @@ -2,11 +2,8 @@ using System.Collections.Generic; using System.Data; using System.Linq; -using Ninject.Infrastructure.Language; using TUGraz.VectoCommon.Models; using TUGraz.VectoCommon.Utils; -using TUGraz.VectoCore.InputData.FileIO.XML.Declaration.DataProvider.v24; -using TUGraz.VectoCore.OutputData.XML.DeclarationReports.CustomerInformationFile.CustomerInformationFile_0_9.CIFWriter; using TUGraz.VectoCore.Utils; namespace TUGraz.VectoCore.Models.Declaration @@ -23,19 +20,21 @@ namespace TUGraz.VectoCore.Models.Declaration public abstract class HEVStrategyParameters { - private Dictionary<int, InitEquivalenceFactors> _initEquivalenceFactors = new Dictionary<int, InitEquivalenceFactors>(3); - private IList<int> socRanges = new List<int>{ 10, 20, 40 }; + private readonly IList<int> _socRanges = new List<int>{ 10, 20, 40 }; + + private readonly Slope _slope; protected HEVStrategyParameters(string vehicle) { - - foreach(var range in socRanges) + foreach(var range in _socRanges) { _initEquivalenceFactors.Add(range, new InitEquivalenceFactors(range, vehicle)); } + + _slope = new Slope(vehicle); } /// <summary> @@ -49,8 +48,22 @@ namespace TUGraz.VectoCore.Models.Declaration public double LookupEquivalenceFactor(MissionType mission, VehicleClass hdvClass, LoadingType loading, double socRange) { - var range = socRanges.MinBy((i => Math.Abs(socRange - i))); - return _initEquivalenceFactors[range].LookupEquivalenceFactor(mission, hdvClass, loading); + var a = _socRanges.MinBy((i => Math.Abs(socRange - i))); //closest + + if (socRange <= _socRanges.Min() || socRange >= _socRanges.Max()) { + return _initEquivalenceFactors[a].LookupEquivalenceFactor(mission, hdvClass, loading); + } + + var b = _socRanges.Where(x => x != a).MinBy((i => Math.Abs(socRange - i))); //next close + + return VectoMath.Interpolate(a, b, _initEquivalenceFactors[a].LookupEquivalenceFactor(mission, hdvClass, loading), + _initEquivalenceFactors[b].LookupEquivalenceFactor(mission, hdvClass, loading), socRange); + } + + public double LookupSlope(MissionType mission, VehicleClass hdvClass, LoadingType loading) + { + return _slope.Lookup( hdvClass.GetClassNumber(), mission.GetNonEMSMissionType().GetName().ToLowerInvariant(), + loading); } private sealed class InitEquivalenceFactors : LookupData<string, InitEquivalenceFactors.Entry> @@ -72,7 +85,7 @@ namespace TUGraz.VectoCore.Models.Declaration } public double LookupEquivalenceFactor(MissionType mission, VehicleClass hdvClass, LoadingType loading) { - var entry = Lookup(hdvClass.GetClassNumber()).cycleDict[mission]; + var entry = Lookup(hdvClass.GetClassNumber()).cycleDict[mission.GetNonEMSMissionType()]; switch (loading) { @@ -94,8 +107,7 @@ namespace TUGraz.VectoCore.Models.Declaration { var vehicleClasses = table.Rows.Cast<DataRow>().Select(row => row.Field<string>("vehiclegroup")); - - var cycleEntries = table.Rows.Cast<DataRow>().Select(row => new CycleEntry + var cycleEntries = table.Rows.Cast<DataRow>().Select(row => new CycleEntry { VehicleGroup = row.Field<string>("vehiclegroup").RemoveWhitespace(), LongHaul = SplitStringToDoubleTuple(row.Field<string>("longhaul")), @@ -105,8 +117,7 @@ namespace TUGraz.VectoCore.Models.Declaration Construction = SplitStringToDoubleTuple(row.Field<string>("construction")) }); - - foreach (var cycleEntry in cycleEntries) + foreach (var cycleEntry in cycleEntries) { foreach (string vehClass in cycleEntry.VehicleGroup.Split('/')) { @@ -144,14 +155,57 @@ namespace TUGraz.VectoCore.Models.Declaration public Dictionary<MissionType, Tuple<double, double>> cycleDict; } - - private Tuple<double, double> SplitStringToDoubleTuple(string input) + private Tuple<double, double> SplitStringToDoubleTuple(string input) { var arr = input.Split('/'); return input.IsNullOrEmpty() ? Tuple.Create(0.0, 0.0) : Tuple.Create(Convert.ToDouble(arr[0]), Convert.ToDouble(arr[1])); } } - } + + + private sealed class Slope : LookupData<string, string, LoadingType, double> //Class, MissionNonEMS, LoadingType + { + #region Overrides of LookupData + + private string ResourceIdFormatString = DeclarationData.DeclarationDataResourcePrefix + ".HEVParameters.{0}.Gradient_40.csv"; + private string _resourceId; + + protected override string ResourceId => _resourceId; + protected override string ErrorMessage { get; } + + public Slope(string vehicleType) + { + _resourceId = string.Format(ResourceIdFormatString, vehicleType); + ReadData(); //call again here because the base constructor doesn't consider the updated ResourceId + } + protected override void ParseData(DataTable table) + { + foreach (DataRow row in table.Rows) + { + var vehicleClass = row.Field<string>("vehiclegroup"); + + foreach (DataColumn col in table.Columns) + { + if (col.Caption == "vehiclegroup") + { + continue; + } + + var values = SplitStringToDoubleTuple(row.Field<string>(col)); + Data[Tuple.Create(vehicleClass, col.Caption, LoadingType.LowLoading)] = values.Item1; + Data[Tuple.Create(vehicleClass, col.Caption, LoadingType.ReferenceLoad)] = values.Item2; + } + } + } + + private Tuple<double, double> SplitStringToDoubleTuple(string input) + { + var arr = input.Split('/'); + return input.IsNullOrEmpty() ? Tuple.Create(0.0, 0.0) : Tuple.Create(Convert.ToDouble(arr[0]), Convert.ToDouble(arr[1])); + } + #endregion + } + } } diff --git a/VectoCore/VectoCore/Resources/Declaration/HEVParameters/Bus/Gradient_40.csv b/VectoCore/VectoCore/Resources/Declaration/HEVParameters/Bus/Gradient_40.csv new file mode 100644 index 0000000000000000000000000000000000000000..0b84aecfcb420d91b884f9f8a5183d5400ce9164 --- /dev/null +++ b/VectoCore/VectoCore/Resources/Declaration/HEVParameters/Bus/Gradient_40.csv @@ -0,0 +1,11 @@ +vehiclegroup ,heavyurban ,suburban ,urban ,interurban ,coach + 31 ,0.0995/0.0925 ,0.0873/0.104 ,0.0983/0.0931 ,0.9/0.9 , + 32 , , , ,0.9/0.9 ,0.9/0.9 + 33 ,0.0995/0.0925 ,0.0873/0.104 ,0.0983/0.0931 ,0.9/0.9 , + 34 , , , ,0.9/0.9 ,0.9/0.9 + 35 ,0.0995/0.0925 ,0.0873/0.104 ,0.0983/0.0931 ,0.9/0.9 , + 36 , , , ,0.9/0.9 ,0.9/0.9 + 37 ,0.0995/0.0925 ,0.0873/0.104 ,0.0983/0.0931 ,0.9/0.9 , + 38 , , , ,0.9/0.9 ,0.9/0.9 + 39 ,0.0995/0.0925 ,0.0873/0.104 ,0.0983/0.0931 ,0.9/0.9 , + 40 , , , ,0.9/0.9 ,0.9/0.9 diff --git a/VectoCore/VectoCore/Resources/Declaration/HEVParameters/Lorry/Gradient_40.csv b/VectoCore/VectoCore/Resources/Declaration/HEVParameters/Lorry/Gradient_40.csv new file mode 100644 index 0000000000000000000000000000000000000000..1d7f0213d7a66b9f81bcc7cfd5aa872ba137b526 --- /dev/null +++ b/VectoCore/VectoCore/Resources/Declaration/HEVParameters/Lorry/Gradient_40.csv @@ -0,0 +1,14 @@ +vehiclegroup ,longhaul ,regionaldelivery ,urbandelivery ,municipalutility ,construction +53 , ,0.0898/0.0919 ,0.0957/0.096 , , +54 , ,0.0898/0.0919 ,0.0957/0.096 , , +1s , ,0.0898/0.0919 ,0.0957/0.096 , , +1 , ,0.0898/0.0919 ,0.0957/0.096 , , +2 ,0.0956/0.1062 ,0.0898/0.0919 ,0.0957/0.096 , , +3 , ,0.0898/0.0919 ,0.0957/0.096 , , +4 ,0.0993/0.0905 ,0.0723/0.0632 ,0.0876/0.0925 ,0.9/0.9 ,0.9/0.9 +5 ,0.0993/0.0905 ,0.0723/0.0632 ,0.0876/0.0925 , ,0.9/0.9 +9 ,0.0993/0.0905 ,0.0723/0.0632 , ,0.9/0.9 ,0.9/0.9 +10 ,0.0993/0.0905 ,0.0723/0.0632 , , ,0.9/0.9 +11 ,0.0993/0.0905 ,0.0723/0.0632 , ,0.9/0.9 ,0.9/0.9 +12 ,0.0993/0.0905 ,0.0723/0.0632 , , ,0.9/0.9 +16 , , , , ,0.9/0.9 diff --git a/VectoCore/VectoCoreTest/Models/Declaration/HevStrategyParametersTest.cs b/VectoCore/VectoCoreTest/Models/Declaration/HevStrategyParametersTest.cs index 727e20bd75596e8f05a5ab1aa4bb670bf1cc9c26..402f0a3865154fd671b3cd51b64516c5432c3492 100644 --- a/VectoCore/VectoCoreTest/Models/Declaration/HevStrategyParametersTest.cs +++ b/VectoCore/VectoCoreTest/Models/Declaration/HevStrategyParametersTest.cs @@ -26,15 +26,38 @@ namespace TUGraz.VectoCore.Tests.Models.Declaration public void TestHevStrategyParametersInputLorry() { Assert.DoesNotThrow(() => new HEVStrategyParametersLorry()); - } [TestCase] public void TestHevStrategyParametersInputBus() { Assert.DoesNotThrow(() => new HEVStrategyParametersBus()); + } + [Test, Combinatorial] + public void LorryLookupCombinations( + [Values(MissionType.LongHaul, + MissionType.LongHaulEMS, + MissionType.MunicipalUtility, + MissionType.RegionalDelivery, + MissionType.RegionalDeliveryEMS, + MissionType.UrbanDelivery)] + MissionType missionType, + [Values(VehicleClass.Class2)] + VehicleClass vehClass, + [Values(LoadingType.LowLoading, + LoadingType.ReferenceLoad)] + LoadingType loadingType, + [Values(10.0, + 20.0, + 40.0)] + double socRange) + { + Assert.DoesNotThrow(() => DeclarationData.HEVStrategyParameters.LookupEquivalenceFactor(missionType, vehClass, + loadingType, socRange)); } + + [TestCase(MissionType.LongHaul, VehicleClass.Class2, LoadingType.LowLoading, 2.00, 40)] [TestCase(MissionType.LongHaul, VehicleClass.Class2, LoadingType.ReferenceLoad, 2.20, 40)] [TestCase(MissionType.LongHaul, VehicleClass.Class2, LoadingType.LowLoading, 1.9, 20)] @@ -43,36 +66,55 @@ namespace TUGraz.VectoCore.Tests.Models.Declaration [TestCase(MissionType.LongHaul, VehicleClass.Class2, LoadingType.ReferenceLoad, 0.10, 10)] - //Lookup in nearest table + //Lookup in nearest table if higher or lower than given soc range [TestCase(MissionType.LongHaul, VehicleClass.Class2, LoadingType.LowLoading, 2.00, 90)] [TestCase(MissionType.LongHaul, VehicleClass.Class2, LoadingType.ReferenceLoad, 2.20, 90)] - [TestCase(MissionType.LongHaul, VehicleClass.Class2, LoadingType.LowLoading, 1.9, 21)] - [TestCase(MissionType.LongHaul, VehicleClass.Class2, LoadingType.ReferenceLoad, 2.40, 21)] + [TestCase(MissionType.LongHaul, VehicleClass.Class2, LoadingType.LowLoading, 0.10, 5)] + [TestCase(MissionType.LongHaul, VehicleClass.Class2, LoadingType.ReferenceLoad, 0.10, 5)] - //Currently looks up in the soc 20 csv, change if needed and remove the other testcase - [TestCase(MissionType.LongHaul, VehicleClass.Class2, LoadingType.LowLoading, 2.00, 30)] - [TestCase(MissionType.LongHaul, VehicleClass.Class2, LoadingType.ReferenceLoad, 2.20, 30)] - [TestCase(MissionType.LongHaul, VehicleClass.Class2, LoadingType.LowLoading, 1.9, 30)] - [TestCase(MissionType.LongHaul, VehicleClass.Class2, LoadingType.ReferenceLoad, 2.40, 30)] + //Currently looks up in the soc 20 csv, change if needed and remove the other testcase + [TestCase(MissionType.LongHaul, VehicleClass.Class2, LoadingType.LowLoading, 1.95, 30)] + [TestCase(MissionType.LongHaul, VehicleClass.Class2, LoadingType.LowLoading, 1.0, 15)] - [TestCase(MissionType.LongHaul, VehicleClass.Class2, LoadingType.LowLoading, 0.10, 10)] - [TestCase(MissionType.LongHaul, VehicleClass.Class2, LoadingType.ReferenceLoad, 0.10, 10)] + + //[TestCase(MissionType.LongHaul, VehicleClass.Class2, LoadingType.LowLoading, 0.10, 10)] + //[TestCase(MissionType.LongHaul, VehicleClass.Class2, LoadingType.ReferenceLoad, 0.10, 10)] public void TestHevStrategyLookup(MissionType missionType, VehicleClass vehicleClass, LoadingType loadingType, double expected, int socRange) { - LookupAndAssert(missionType, vehicleClass, loadingType, expected,socRange); + LookupEquivAndAssert(missionType, vehicleClass, loadingType, expected,socRange); } - private void LookupAndAssert(MissionType mission, VehicleClass hdvClass, LoadingType loading, double expected, int socRange) + [TestCase(MissionType.LongHaul, VehicleClass.Class2, LoadingType.LowLoading, 0.0956)] + public void LookUpSlope(MissionType missionType, VehicleClass vehicleClass, LoadingType loadingType, + double expected) { - var feq = DeclarationData.InitEquivalenceFactors.LookupEquivalenceFactor(mission, hdvClass, + LookupSlopeAndAssert(missionType, vehicleClass, loadingType, expected); + } + + private void LookupEquivAndAssert(MissionType mission, VehicleClass hdvClass, LoadingType loading, double expected, int socRange) + { + var feq = DeclarationData.HEVStrategyParameters.LookupEquivalenceFactor(mission, hdvClass, loading, socRange); + if (!feq.IsEqual(expected)) { + Assert.Fail($"Expected {expected} got {feq}"); + } + + } + + private void LookupSlopeAndAssert(MissionType mission, VehicleClass hdvClass, LoadingType loading, double expected) + { + var slope = DeclarationData.HEVStrategyParameters.LookupSlope(mission, hdvClass, + loading); + if (!slope.IsEqual(expected)) + { + Assert.Fail($"Expected {expected} got {slope}"); + } - Assert.IsTrue(feq.IsEqual(expected)); } } }