From e511e9934a951e21c1dbd852f48daed9fb8e8ea6 Mon Sep 17 00:00:00 2001 From: Markus Quaritsch <quaritsch@ivt.tugraz.at> Date: Wed, 25 Jan 2023 15:03:14 +0100 Subject: [PATCH] Adding testcase for calculating electric ranges (using mock data) finish implementation calculating weighted results (ovc/non-ovc) --- .../Models/Declaration/DeclarationData.cs | 60 ++++++++++++-- .../VectoCore/OutputData/DeclarationReport.cs | 3 +- .../OutputData/XML/XMLDeclarationReport.cs | 5 +- .../Reports/TestXMLResultsWriting.cs | 81 ++++++++++++++----- 4 files changed, 120 insertions(+), 29 deletions(-) diff --git a/VectoCore/VectoCore/Models/Declaration/DeclarationData.cs b/VectoCore/VectoCore/Models/Declaration/DeclarationData.cs index db1ad76314..00e1aa316d 100644 --- a/VectoCore/VectoCore/Models/Declaration/DeclarationData.cs +++ b/VectoCore/VectoCore/Models/Declaration/DeclarationData.cs @@ -44,6 +44,7 @@ using TUGraz.VectoCommon.Utils; using TUGraz.VectoCore.Configuration; using TUGraz.VectoCore.InputData.FileIO.JSON; using TUGraz.VectoCore.InputData.Reader.ComponentData; +using TUGraz.VectoCore.InputData.Reader.DataObjectAdapter.SimulationComponents; using TUGraz.VectoCore.Models.BusAuxiliaries.DownstreamModules.Impl.Electrics; using TUGraz.VectoCore.Models.Declaration.Auxiliaries; using TUGraz.VectoCore.Models.Declaration.VehicleOperation; @@ -55,6 +56,8 @@ using TUGraz.VectoCore.Utils; using TUGraz.VectoCore.Models.BusAuxiliaries.DownstreamModules.Impl.HVAC; using TUGraz.VectoCore.Models.Simulation.Data; using TUGraz.VectoCore.Models.Simulation.Impl; +using TUGraz.VectoCore.Models.SimulationComponent.Data.Battery; +using TUGraz.VectoCore.Models.SimulationComponent.Impl; using TUGraz.VectoCore.OutputData; using TUGraz.VectoCore.OutputData.XML; @@ -1391,6 +1394,10 @@ namespace TUGraz.VectoCore.Models.Declaration if (cdResult.Status != VectoRun.Status.Success || csResult.Status != VectoRun.Status.Success) { return null; } + var batteryData = cdResult.BatteryData; + if (batteryData == null) { + throw new VectoException("Battery Data is required for OVC post-processing"); + } var vehicleOperation = VehicleOperation.LookupVehicleOperation(cdResult.VehicleClass, cdResult.Mission); var D9_dailySpecificMileage = vehicleOperation.Mileage.DailyMileage; @@ -1400,16 +1407,15 @@ namespace TUGraz.VectoCore.Models.Declaration var D13_realWorldFactorUsageStartSoC = vehicleOperation.RealWorldUsageFactors.StartSoCBeforeMission; var D14_realWorldFactorChargeDuringMission = vehicleOperation.RealWorldUsageFactors.StationaryChargingDuringMission; - var D15_chargingEffBatt = 0.975; // TODO!! - var D16_ = 1.0; + + var D15_chargingEffBatt = CalculateChargingEfficiency(cdResult, vehicleOperation, batteryData); var D18_maxStatChargingPower = cdResult.MaxChargingPower; - var D19_useableBatteryCapacity = 0.SI<WattSecond>(); // TODO! var D20_energyConsumptionCdMode = cdResult.ElectricEnergyConsumption / cdResult.Distance; var D21_fuelConsumptionCdMode = cdResult.FuelData.Sum(x => cdResult.FuelConsumptionFinal(x.FuelType).TotalFuelConsumptionCorrected * x.LowerHeatingValueVecto); var D22_fuelConsumptionCsMode = csResult.FuelData.Sum(x => csResult.FuelConsumptionFinal(x.FuelType).TotalFuelConsumptionCorrected * x.LowerHeatingValueVecto); - var D24_useableBatteryCapForR_CDA = D19_useableBatteryCapacity * D16_; + var D24_useableBatteryCapForR_CDA = cdResult.BatteryData.UseableStoredEnergy; var D25_actualChargeDepletingRange = D24_useableBatteryCapForR_CDA / D20_energyConsumptionCdMode; var D29_elRangefromStartSoC_ChargingAtDepot = D25_actualChargeDepletingRange * D13_realWorldFactorUsageStartSoC; @@ -1465,6 +1471,35 @@ namespace TUGraz.VectoCore.Models.Declaration return retVal; } + private static double CalculateChargingEfficiency(IResultEntry cdResult, + VehicleOperationLookup.VehicleOperationData vehicleOperation, BatterySystemData batteryData) + { + var minDepotChgPwr = 10.SI(Unit.SI.Kilo.Watt).Cast<Watt>(); + var depotChargingDuration = 6.SI(Unit.SI.Hour).Cast<Second>(); + var depotChargingPower = + VectoMath.Max(minDepotChgPwr, batteryData.UseableStoredEnergy / depotChargingDuration); + var inMissionChargingPower = VectoMath.Min(vehicleOperation.StationaryChargingMaxPwrInfrastructure, cdResult.MaxChargingPower); + + var tmpBattery = new BatterySystem(null, batteryData); + var centerSoC = (tmpBattery.MinSoC + tmpBattery.MaxSoC) / 2.0; + tmpBattery.Initialize(centerSoC); + + var respChgBatDepot = tmpBattery.Request(0.SI<Second>(), 1.SI<Second>(), depotChargingPower, true); + var respChgBatInMission = tmpBattery.Request(0.SI<Second>(), 1.SI<Second>(), inMissionChargingPower, true); + + var etaChgBatDepot = 1 - (respChgBatDepot.LossPower / respChgBatDepot.PowerDemand).Value(); + var etaChgBatInMission = 1 - (respChgBatInMission.LossPower / respChgBatInMission.PowerDemand).Value(); + + var chargedEnergyDepot = depotChargingPower * depotChargingDuration; + var chargedEnergyInMission = inMissionChargingPower * + vehicleOperation.StationaryChargingDuringMission_AvgDurationPerEvent * + vehicleOperation.StationaryChargingDuringMission_NbrEvents; + var totalChargedEnergy = chargedEnergyDepot + chargedEnergyInMission; + + return etaChgBatDepot * chargedEnergyDepot / totalChargedEnergy + + etaChgBatInMission * chargedEnergyInMission / totalChargedEnergy; + } + public static IWeightedResult CalculateWeightedSummary(IList<IResultEntry> entries) { if (entries == null || !entries.Any()) { @@ -1531,12 +1566,21 @@ namespace TUGraz.VectoCore.Models.Declaration }; } - public static void SetElectricRangesPEV(IResultEntry resultEntry, VectoRunData runData, IModalDataContainer data) + public static ElectricRangesPEV SetElectricRangesPEV(VectoRunData runData, IModalDataContainer data) { + var retVal = new ElectricRangesPEV(); // ToDo MQ 2022-12-12: add correct calculation method! - resultEntry.ActualChargeDepletingRange = 100.SI<Meter>(); - resultEntry.EquivalentAllElectricRange = 100.SI<Meter>(); - resultEntry.ZeroCO2EmissionsRange = 100.SI<Meter>(); + retVal.ActualChargeDepletingRange = 100.SI<Meter>(); + retVal.EquivalentAllElectricRange = 100.SI<Meter>(); + retVal.ZeroCO2EmissionsRange = 100.SI<Meter>(); + return retVal; + } + + public struct ElectricRangesPEV + { + public Meter ZeroCO2EmissionsRange { get; set; } + public Meter ActualChargeDepletingRange { get; set; } + public Meter EquivalentAllElectricRange { get; set; } } } } diff --git a/VectoCore/VectoCore/OutputData/DeclarationReport.cs b/VectoCore/VectoCore/OutputData/DeclarationReport.cs index 5dfb9a2755..f48d13a831 100644 --- a/VectoCore/VectoCore/OutputData/DeclarationReport.cs +++ b/VectoCore/VectoCore/OutputData/DeclarationReport.cs @@ -40,6 +40,7 @@ using TUGraz.VectoCommon.Utils; using TUGraz.VectoCore.Models.Declaration; using TUGraz.VectoCore.Models.Simulation.Data; using TUGraz.VectoCore.Models.Simulation.Impl; +using TUGraz.VectoCore.Models.SimulationComponent.Data.Battery; using TUGraz.VectoCore.Models.SimulationComponent.Data.Engine; namespace TUGraz.VectoCore.OutputData @@ -133,7 +134,7 @@ namespace TUGraz.VectoCore.OutputData string StackTrace { get; } - WattSecond UseableBatteryCapacity { get; } + BatterySystemData BatteryData { get; } } public interface IWeightedResult diff --git a/VectoCore/VectoCore/OutputData/XML/XMLDeclarationReport.cs b/VectoCore/VectoCore/OutputData/XML/XMLDeclarationReport.cs index 84b44a6343..0bf3deea2d 100644 --- a/VectoCore/VectoCore/OutputData/XML/XMLDeclarationReport.cs +++ b/VectoCore/VectoCore/OutputData/XML/XMLDeclarationReport.cs @@ -46,6 +46,7 @@ using TUGraz.VectoCommon.Utils; using TUGraz.VectoCore.Models.Declaration; using TUGraz.VectoCore.Models.Simulation.Data; using TUGraz.VectoCore.Models.Simulation.Impl; +using TUGraz.VectoCore.Models.SimulationComponent.Data.Battery; using TUGraz.VectoCore.OutputData.XML.DeclarationReports.CustomerInformationFile; using TUGraz.VectoCore.OutputData.XML.DeclarationReports.ManufacturerReport; @@ -86,7 +87,7 @@ namespace TUGraz.VectoCore.OutputData.XML VehicleClass = runData.Mission?.BusParameter?.BusGroup ?? runData.VehicleData.VehicleClass; PassengerCount = runData.VehicleData.PassengerCount; MaxChargingPower = runData.MaxChargingPower; - UseableBatteryCapacity = runData.BatteryData?.UseableStoredEnergy; + BatteryData = runData.BatteryData; } public MissionType Mission { get; set; } @@ -142,7 +143,7 @@ namespace TUGraz.VectoCore.OutputData.XML public VectoRun.Status Status { get; private set; } public string StackTrace { get; private set; } - public WattSecond UseableBatteryCapacity { get; private set; } + public BatterySystemData BatteryData { get; private set; } public PerSecond EngineSpeedDrivingMin { get; private set; } public PerSecond EngineSpeedDrivingAvg { get; private set; } diff --git a/VectoCore/VectoCoreTest/Reports/TestXMLResultsWriting.cs b/VectoCore/VectoCoreTest/Reports/TestXMLResultsWriting.cs index edf6a7fdf7..ce9817cb2e 100644 --- a/VectoCore/VectoCoreTest/Reports/TestXMLResultsWriting.cs +++ b/VectoCore/VectoCoreTest/Reports/TestXMLResultsWriting.cs @@ -14,10 +14,12 @@ using TUGraz.VectoCommon.InputData; using TUGraz.VectoCommon.Models; using TUGraz.VectoCommon.Utils; using TUGraz.VectoCore.InputData.FileIO.XML; +using TUGraz.VectoCore.InputData.Reader.ComponentData; using TUGraz.VectoCore.Models.Declaration; using TUGraz.VectoCore.Models.Simulation.Data; using TUGraz.VectoCore.Models.Simulation.Impl; using TUGraz.VectoCore.Models.SimulationComponent.Data; +using TUGraz.VectoCore.Models.SimulationComponent.Data.Battery; using TUGraz.VectoCore.OutputData; using TUGraz.VectoCore.OutputData.XML; using TUGraz.VectoCore.OutputData.XML.DeclarationReports.Common; @@ -135,7 +137,6 @@ public class TestXMLResultsWriting WriteToFile("CIF", doc, runData, success, exempted); } - [ TestCase(VectoSimulationJobType.ConventionalVehicle, false, false, true, TestName = "CIF_ReportResult_WritingResults: CompletedBus Conv SUCCESS"), @@ -422,6 +423,42 @@ public class TestXMLResultsWriting WriteToFile("VIF", doc, runData, success, exempted); } + // --------- + + [TestCase()] + public void TestCalculateOVCWeightedResult(params FuelType[] fuels) + { + var jobType = VectoSimulationJobType.ParallelHybridVehicle; + var vehicleCategory = VehicleCategory.RigidTruck; + var ovcmode = VectoRunData.OvcHevMode.ChargeDepleting; + var runData = GetMockRunData(vehicleCategory, jobType, true, false, ovcmode, fuels); + var modData = GetMockModData(VectoRun.Status.Success, fuels, ovcmode); + + var cdResult = GetResultEntry(runData); + cdResult.SetResultData(runData, modData, 1); + + var run2 = GetMockRunData(vehicleCategory, jobType, true, false, VectoRunData.OvcHevMode.ChargeSustaining, fuels); + var modData2 = GetMockModData(VectoRun.Status.Success, fuels, VectoRunData.OvcHevMode.ChargeSustaining); + var csResult = GetResultEntry(run2); + csResult.SetResultData(run2, modData2, 1); + + var weighted = DeclarationData.CalculateWeightedResult(cdResult, csResult); + + Console.WriteLine($"{weighted.ActualChargeDepletingRange.Value().ToXMLFormat(3)} {weighted.EquivalentAllElectricRange.Value().ToXMLFormat(3)} {weighted.ZeroCO2EmissionsRange.Value().ToXMLFormat(3)} {weighted.UtilityFactor.ToXMLFormat(3)}" + + $" {weighted.ElectricEnergyConsumption.Value().ToXMLFormat(3)} {weighted.FuelConsumption[FuelData.Diesel].Value().ToXMLFormat(3)} {weighted.CO2Total.Value().ToXMLFormat(3)}"); + + //1518.750 1366.875 1366.875 0.004 797877.345 30.890 20.000 + + Assert.AreEqual(1518.750, weighted.ActualChargeDepletingRange.Value(), 1e-3); + Assert.AreEqual(1366.875, weighted.EquivalentAllElectricRange.Value(), 1e-3); + Assert.AreEqual(1366.875, weighted.ZeroCO2EmissionsRange.Value(), 1e-3); + Assert.AreEqual(0.004, weighted.UtilityFactor, 1e-3); + Assert.AreEqual(797877.345, weighted.ElectricEnergyConsumption.Value(), 1e-3); + Assert.AreEqual(30.890, weighted.FuelConsumption[FuelData.Diesel].Value(), 1e-3); + Assert.AreEqual(20.000, weighted.CO2Total.Value(), 1e-3); + + } + // =================================== private static void WriteToConsole(XDocument doc) @@ -485,17 +522,8 @@ public class TestXMLResultsWriting private static XMLDeclarationReport.ResultEntry GetResultEntry(VectoRunData runData) { - var resultEntry = new XMLDeclarationReport.ResultEntry() { - Mission = runData.Mission.MissionType, - LoadingType = runData.Loading, - FuelMode = runData.EngineData?.FuelMode ?? 0, - FuelData = runData.EngineData?.Fuels.Select(x => x.FuelData).ToList(), - Payload = runData.VehicleData.Loading, - TotalVehicleMass = runData.VehicleData.TotalVehicleMass, - CargoVolume = runData.VehicleData.CargoVolume, - VehicleClass = runData.VehicleData.VehicleClass, - PassengerCount = runData.VehicleData.PassengerCount, - }; + var resultEntry = new XMLDeclarationReport.ResultEntry(); + resultEntry.Initialize(runData); return resultEntry; } @@ -523,7 +551,7 @@ public class TestXMLResultsWriting return doc; } - private IModalDataContainer GetMockModData(VectoRun.Status runStatus, FuelType[] fuelTypes) + private IModalDataContainer GetMockModData(VectoRun.Status runStatus, FuelType[] fuelTypes, VectoRunData.OvcHevMode ovcMode = VectoRunData.OvcHevMode.NotApplicable) { var fuels = fuelTypes == null || fuelTypes.Length == 0 ? new[] { FuelType.DieselCI } : fuelTypes; @@ -551,21 +579,22 @@ public class TestXMLResultsWriting modData.Setup(x => x.CorrectedModalData).Returns(mc.Object); var fcCorrected = new Dictionary<FuelType, IFuelConsumptionCorrection>(); + var ovcFactor = ovcMode == VectoRunData.OvcHevMode.ChargeDepleting ? 0.1 : 1.0; foreach (var fuelType in fuels) { var factor = fcCorrected.Count == 0 ? 1 : 0.1; var fc = new Mock<IFuelConsumptionCorrection>(); fc.Setup(x => x.Fuel).Returns(DeclarationData.FuelData.Lookup(fuelType, TankSystem.Liquefied)); - fc.Setup(x => x.TotalFuelConsumptionCorrected).Returns(31.SI<Kilogram>() * factor); - fc.Setup(x => x.EnergyDemand).Returns(31.SI<Kilogram>() * factor * FuelData.Diesel.LowerHeatingValueVecto); + fc.Setup(x => x.TotalFuelConsumptionCorrected).Returns(31.SI<Kilogram>() * factor * ovcFactor); + fc.Setup(x => x.EnergyDemand).Returns(31.SI<Kilogram>() * factor * ovcFactor * FuelData.Diesel.LowerHeatingValueVecto); fcCorrected.Add(fuelType, fc.Object); } mc.Setup(x => x.FuelCorrection).Returns(fcCorrected); mc.Setup(x => x.CO2Total).Returns(20.SI<Kilogram>()); mc.Setup(x => x.FuelEnergyConsumptionTotal).Returns(1e9.SI<Joule>()); - mc.Setup(x => x.ElectricEnergyConsumption).Returns(200.SI(Unit.SI.Mega.Joule).Cast<WattSecond>()); - + var elOvcFactor = ovcMode == VectoRunData.OvcHevMode.ChargeSustaining ? 0 : 1.0; + mc.Setup(x => x.ElectricEnergyConsumption).Returns(200.SI(Unit.SI.Mega.Joule).Cast<WattSecond>() * elOvcFactor); return modData.Object; } @@ -582,6 +611,7 @@ public class TestXMLResultsWriting Exempted = exempted, JobType = jobType, Loading = LoadingType.LowLoading, + MaxChargingPower = 250.SI(Unit.SI.Kilo.Watt).Cast<Watt>(), VehicleData = new VehicleData() { CurbMass = 7600.SI<Kilogram>(), Loading = 5000.SI<Kilogram>(), @@ -589,7 +619,7 @@ public class TestXMLResultsWriting PassengerCount = 20, VehicleClass = VehicleClass.Class5, VehicleCategory = vehicleCategory, - OffVehicleCharging = offVehicleCharging + OffVehicleCharging = offVehicleCharging, }, EngineData = new CombustionEngineData() { FuelMode = 0, @@ -599,6 +629,21 @@ public class TestXMLResultsWriting Retarder = new RetarderData() { Type = RetarderType.None, }, + BatteryData = new BatterySystemData() { + Batteries = new List<Tuple<int, BatteryData>>() { + Tuple.Create(1, new BatteryData() { + BatteryId = 0, + Capacity = 7.5.SI(Unit.SI.Ampere.Hour).Cast<AmpereSecond>(), + ChargeSustainingBattery = true, + MinSOC = 0.2, + MaxSOC = 0.8, + SOCMap = BatterySOCReader.Create("SoC, V\n0, 600\n100, 650\n".ToStream()), + InternalResistance = BatteryInternalResistanceReader.Create("SoC, Ri-2, Ri-10, Ri-20\n0, 20, 20, 20\n100, 20, 20, 20\n".ToStream(), true), + MaxCurrent = BatteryMaxCurrentReader.Create("SoC, I_charge, I_discharge\n0, 300, 300\n100, 500, 500\n".ToStream()) + + }) + } + } }; } } \ No newline at end of file -- GitLab