diff --git a/VectoCore/VectoCore/InputData/Reader/ComponentData/BatteryInternalResistanceReader.cs b/VectoCore/VectoCore/InputData/Reader/ComponentData/BatteryInternalResistanceReader.cs index ed4b1eb13512769185dc6ffe4c71e776201edcc7..9cd1b6847b0f1a748102ca89585522559718dbe6 100644 --- a/VectoCore/VectoCore/InputData/Reader/ComponentData/BatteryInternalResistanceReader.cs +++ b/VectoCore/VectoCore/InputData/Reader/ComponentData/BatteryInternalResistanceReader.cs @@ -15,6 +15,10 @@ namespace TUGraz.VectoCore.InputData.Reader.ComponentData { public static InternalResistanceMap Create(DataTable data, bool inputInMiliOhm) { + if (data == null) { + // may be null in case it is used to create a temp battery system to calc stored energy + return null; + } if (!(data.Columns.Count == 2 || data.Columns.Count == 4 || data.Columns.Count == 5)) { throw new VectoException( "Internal Resistance Map data must contain either two, four or five columns: {0}, {1}", diff --git a/VectoCore/VectoCore/InputData/Reader/ComponentData/BatterySOCReader.cs b/VectoCore/VectoCore/InputData/Reader/ComponentData/BatterySOCReader.cs index bdbeab40af3d3ce98564611c2b4c4cfb4ecff6bd..5b9de5568b09efbb0ebdf7f8f900fe1bece5d40b 100644 --- a/VectoCore/VectoCore/InputData/Reader/ComponentData/BatterySOCReader.cs +++ b/VectoCore/VectoCore/InputData/Reader/ComponentData/BatterySOCReader.cs @@ -52,20 +52,4 @@ namespace TUGraz.VectoCore.InputData.Reader.ComponentData { } } - public static class BatteryHelper - { - public static WattSecond TotalUsableCapacityInSimulation(this IBatteryPackDeclarationInputData batteryData) - { - var tmp = BatterySOCReader.Create(batteryData.VoltageCurve); - var voltage = tmp.Lookup(((batteryData.MinSOC ?? 0) + (batteryData.MaxSOC ?? 1)) / 2.0); - return batteryData.Capacity * voltage; - } - - public static WattSecond TotalStorageCapacity(this IBatteryPackDeclarationInputData batteryData) - { - var tmp = BatterySOCReader.Create(batteryData.VoltageCurve); - var voltage = tmp.Lookup(((batteryData.MinSOC ?? 0) + (batteryData.MaxSOC ?? 1)) / 2.0); - return batteryData.Capacity * voltage; - } - } } \ No newline at end of file diff --git a/VectoCore/VectoCore/InputData/Reader/DataObjectAdapter/SimulationComponents/BatteryDataAdapter.cs b/VectoCore/VectoCore/InputData/Reader/DataObjectAdapter/SimulationComponents/BatteryDataAdapter.cs index fd380f0d28c375f44a7f874d75ddbb27364ef7e7..288210b21eefbfc5992e0579c737700e026d9e92 100644 --- a/VectoCore/VectoCore/InputData/Reader/DataObjectAdapter/SimulationComponents/BatteryDataAdapter.cs +++ b/VectoCore/VectoCore/InputData/Reader/DataObjectAdapter/SimulationComponents/BatteryDataAdapter.cs @@ -61,6 +61,7 @@ namespace TUGraz.VectoCore.InputData.Reader.DataObjectAdapter.SimulationComponen InternalResistance = BatteryInternalResistanceReader.Create(b.InternalResistanceCurve, true), SOCMap = BatterySOCReader.Create(b.VoltageCurve), + InputData = entry }; retVal.Batteries.Add(Tuple.Create(entry.StringId, batteryData)); diff --git a/VectoCore/VectoCore/Models/SimulationComponent/Data/ElectricComponents/Battery/BatteryData.cs b/VectoCore/VectoCore/Models/SimulationComponent/Data/ElectricComponents/Battery/BatteryData.cs index 0449e5656888c717a2e2d7caeae66ab17b007dbb..dd4b37c7318fdb1f034dcda9f6ec4dc0fa229201 100644 --- a/VectoCore/VectoCore/Models/SimulationComponent/Data/ElectricComponents/Battery/BatteryData.cs +++ b/VectoCore/VectoCore/Models/SimulationComponent/Data/ElectricComponents/Battery/BatteryData.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using System.Linq; using TUGraz.VectoCommon.Exceptions; +using TUGraz.VectoCommon.InputData; using TUGraz.VectoCommon.Utils; namespace TUGraz.VectoCore.Models.SimulationComponent.Data.ElectricComponents.Battery { @@ -60,6 +61,7 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Data.ElectricComponents.Ba public bool ChargeSustainingBattery { get; internal set; } public WattSecond UseableStoredEnergy => _useableStoredEnergy ?? (_useableStoredEnergy = CalculateUsableEnergy()); + public IElectricStorageDeclarationInputData InputData { get; internal set; } protected WattSecond CalculateUsableEnergy() { diff --git a/VectoCore/VectoCore/OutputData/XML/DeclarationReports/CustomerInformationFile/CustomerInformationFile_0_9/CIFWriter/AbstractCIFGroupWriter.cs b/VectoCore/VectoCore/OutputData/XML/DeclarationReports/CustomerInformationFile/CustomerInformationFile_0_9/CIFWriter/AbstractCIFGroupWriter.cs index 5f5ce5e906a320ad773578b46e929541cc7d6d15..b618180bf464a0007936850d183aea416a19df2e 100644 --- a/VectoCore/VectoCore/OutputData/XML/DeclarationReports/CustomerInformationFile/CustomerInformationFile_0_9/CIFWriter/AbstractCIFGroupWriter.cs +++ b/VectoCore/VectoCore/OutputData/XML/DeclarationReports/CustomerInformationFile/CustomerInformationFile_0_9/CIFWriter/AbstractCIFGroupWriter.cs @@ -32,9 +32,9 @@ namespace TUGraz.VectoCore.OutputData.XML.DeclarationReports.ManufacturerReport. { if (inputData is IMultistepBusInputDataProvider multistep) { return multistep.JobInputData.PrimaryVehicle.Vehicle; - } else { - return inputData.JobInputData.Vehicle; } + + return inputData.JobInputData.Vehicle; } } diff --git a/VectoCore/VectoCore/OutputData/XML/DeclarationReports/CustomerInformationFile/CustomerInformationFile_0_9/CIFWriter/ComponentGroupWriters.cs b/VectoCore/VectoCore/OutputData/XML/DeclarationReports/CustomerInformationFile/CustomerInformationFile_0_9/CIFWriter/ComponentGroupWriters.cs index 473ec5329cb93c2647dc324c6dfeb73377474792..f499da1116e1714df3246b7b3368d676c5b78736 100644 --- a/VectoCore/VectoCore/OutputData/XML/DeclarationReports/CustomerInformationFile/CustomerInformationFile_0_9/CIFWriter/ComponentGroupWriters.cs +++ b/VectoCore/VectoCore/OutputData/XML/DeclarationReports/CustomerInformationFile/CustomerInformationFile_0_9/CIFWriter/ComponentGroupWriters.cs @@ -11,6 +11,9 @@ using TUGraz.VectoCommon.Models; using TUGraz.VectoCommon.Resources; using TUGraz.VectoCommon.Utils; using TUGraz.VectoCore.InputData.Reader.ComponentData; +using TUGraz.VectoCore.InputData.Reader.DataObjectAdapter.SimulationComponents; +using TUGraz.VectoCore.Models.SimulationComponent.Data.ElectricComponents.Battery; +using TUGraz.VectoCore.Models.SimulationComponent.Impl; using TUGraz.VectoCore.OutputData.XML.DeclarationReports.ManufacturerReport.ManufacturerReport_0_9.ManufacturerReportGroupWriter; using TUGraz.VectoCore.Utils; @@ -225,18 +228,32 @@ namespace TUGraz.VectoCore.OutputData.XML.DeclarationReports.CustomerInformation { var vehicle = GetVehicle(inputData); var reess = vehicle.Components.ElectricStorage; - var batteries = reess.ElectricStorageElements - .Where(es => es.REESSPack.StorageType == REESSType.Battery) - .Select(es => es.REESSPack as IBatteryPackDeclarationInputData).ToArray(); + //var batteries = reess.ElectricStorageElements + // .Where(es => es.REESSPack.StorageType == REESSType.Battery) + // .Select(es => es.REESSPack as IBatteryPackDeclarationInputData).ToArray(); + + var batTotalCap = 0.SI<WattSecond>(); + var batUsableCap = 0.SI<WattSecond>(); + if (reess.ElectricStorageElements.Any(x => x.REESSPack.StorageType == REESSType.Battery)) { + var eletricStorageAdapter = new ElectricStorageAdapter(); + var batData = eletricStorageAdapter.CreateBatteryData(reess, vehicle.VehicleType, vehicle.OvcHev); + batUsableCap = GetEnergyStoredInBatterySystem(batData); + + foreach (var entry in batData.Batteries) { + entry.Item2.MinSOC = 0; + entry.Item2.MaxSOC = 1; + } + + batTotalCap = GetEnergyStoredInBatterySystem(batData); + } + var capacitors = reess.ElectricStorageElements.Where(es => es.REESSPack.StorageType == REESSType.SuperCap) .Select(es => es.REESSPack as ISuperCapDeclarationInputData).ToArray(); var totalStorageCapacity = - (batteries.Length > 0 ? batteries.Sum(bp => bp.TotalStorageCapacity()) : 0.SI<WattSecond>()) + + batTotalCap + (capacitors.Length > 0 ? capacitors.Sum(cap => GetStorageCapacity(cap)) : 0.SI<WattSecond>()); - var totalUsableCapacity = (batteries.Length > 0 - ? batteries.Sum(bp => bp.TotalUsableCapacityInSimulation()) - : 0.SI<WattSecond>()) + + var totalUsableCapacity = batUsableCap + (capacitors.Length > 0 ? capacitors.Sum(cap => GetTotalUsableCapacityInSimulation(cap)) : 0.SI<WattSecond>()); @@ -247,6 +264,24 @@ namespace TUGraz.VectoCore.OutputData.XML.DeclarationReports.CustomerInformation }; } + private static WattSecond GetEnergyStoredInBatterySystem(BatterySystemData batData) + { + var tmpBat = new BatterySystem(null, batData); + // set every single battery to its max SoC - initializing the battery system does + // not work as individual batteries may have different SoC limits + foreach (var battery in tmpBat.Batteries.SelectMany(batteryString => batteryString.Value.Batteries)) { + battery.Initialize(battery.MaxSoC); + } + var energyFull = tmpBat.StoredEnergy; + // set every single battery to its min SoC - initializing the battery system does + // not work as individual batteries may have different SoC limits + foreach (var battery in tmpBat.Batteries.SelectMany(batteryString => batteryString.Value.Batteries)) { + battery.Initialize(battery.MinSoC); + } + var energyEmpty = tmpBat.StoredEnergy; + return energyFull - energyEmpty; + } + private WattSecond GetTotalUsableCapacityInSimulation(ISuperCapDeclarationInputData cap) { return GetStorageCapacity(cap) * 0.8; diff --git a/VectoCore/VectoCore/OutputData/XML/DeclarationReports/ManufacturerReport/ManufacturerReport_0_9/ManufacturerReportXMLTypeWriter/AbstractMrfXmlType.cs b/VectoCore/VectoCore/OutputData/XML/DeclarationReports/ManufacturerReport/ManufacturerReport_0_9/ManufacturerReportXMLTypeWriter/AbstractMrfXmlType.cs index d59563f0a578dbdb32b84029fc0dc8baccdacaea..88dc62eb8e120dc91089b248c9c0fb5f27cdc983 100644 --- a/VectoCore/VectoCore/OutputData/XML/DeclarationReports/ManufacturerReport/ManufacturerReport_0_9/ManufacturerReportXMLTypeWriter/AbstractMrfXmlType.cs +++ b/VectoCore/VectoCore/OutputData/XML/DeclarationReports/ManufacturerReport/ManufacturerReport_0_9/ManufacturerReportXMLTypeWriter/AbstractMrfXmlType.cs @@ -14,5 +14,13 @@ namespace TUGraz.VectoCore.OutputData.XML.DeclarationReports.ManufacturerReport. _mrfFactory = mrfFactory; } + protected virtual IVehicleDeclarationInputData GetVehicle(IDeclarationInputDataProvider inputData) + { + if (inputData is IMultistepBusInputDataProvider multistep) { + return multistep.JobInputData.PrimaryVehicle.Vehicle; + } + + return inputData.JobInputData.Vehicle; + } } } diff --git a/VectoCore/VectoCore/OutputData/XML/DeclarationReports/ManufacturerReport/ManufacturerReport_0_9/ManufacturerReportXMLTypeWriter/Components/MRFREESSSpecificationsType.cs b/VectoCore/VectoCore/OutputData/XML/DeclarationReports/ManufacturerReport/ManufacturerReport_0_9/ManufacturerReportXMLTypeWriter/Components/MRFREESSSpecificationsType.cs index ecc5e92c139eabe4c9b386dc34dcab5f125c6b8b..c47495ed0f0f54db4b83a8c00e6deda20e81de7d 100644 --- a/VectoCore/VectoCore/OutputData/XML/DeclarationReports/ManufacturerReport/ManufacturerReport_0_9/ManufacturerReportXMLTypeWriter/Components/MRFREESSSpecificationsType.cs +++ b/VectoCore/VectoCore/OutputData/XML/DeclarationReports/ManufacturerReport/ManufacturerReport_0_9/ManufacturerReportXMLTypeWriter/Components/MRFREESSSpecificationsType.cs @@ -10,6 +10,9 @@ using TUGraz.VectoCommon.Models; using TUGraz.VectoCommon.Resources; using TUGraz.VectoCommon.Utils; using TUGraz.VectoCore.InputData.Reader.ComponentData; +using TUGraz.VectoCore.InputData.Reader.DataObjectAdapter.SimulationComponents; +using TUGraz.VectoCore.Models.SimulationComponent.Data.ElectricComponents.Battery; +using TUGraz.VectoCore.Models.SimulationComponent.Impl; using TUGraz.VectoCore.Utils; namespace TUGraz.VectoCore.OutputData.XML.DeclarationReports.ManufacturerReport.ManufacturerReport_0_9.ManufacturerReportXMLTypeWriter.Components @@ -22,26 +25,39 @@ namespace TUGraz.VectoCore.OutputData.XML.DeclarationReports.ManufacturerReport. public XElement GetElement(IDeclarationInputDataProvider inputData) { - var reessElements = inputData.JobInputData.Vehicle.Components.ElectricStorage.ElectricStorageElements; + var vehicle = GetVehicle(inputData); + var reess = inputData.JobInputData.Vehicle.Components.ElectricStorage; + var reessElements = reess.ElectricStorageElements; var result = new XElement(_mrf + "REESSSpecifications"); - foreach (var electricStorage in reessElements.OrderBy((element) => element.StringId)) { - if (electricStorage.REESSPack.StorageType == REESSType.Battery && - electricStorage.REESSPack is IBatteryPackDeclarationInputData battery) { + if (reessElements.Any(x => x.REESSPack.StorageType == REESSType.Battery)) { + var eletricStorageAdapter = new ElectricStorageAdapter(); + var batData = eletricStorageAdapter.CreateBatteryData(reess, vehicle.VehicleType, vehicle.OvcHev); + foreach (var entry in batData.Batteries.OrderBy(x => x.Item1)) { + var batteryPackInput = entry.Item2.InputData; + var battery = batteryPackInput.REESSPack as IBatteryPackDeclarationInputData; + var batUsableCap = GetEnergyStoredInBattery(entry); + entry.Item2.MaxSOC = 1; + entry.Item2.MinSOC = 0; + var batTotalCap = GetEnergyStoredInBattery(entry); + result.Add(new XElement(_mrf + XMLNames.ElectricEnergyStorage_Battery, - new XAttribute("stringId", electricStorage.StringId), - new XElement(_mrf + XMLNames.Component_Model, battery.Model), - new XElement(_mrf + XMLNames.Component_CertificationNumber, battery.CertificationNumber), - new XElement(_mrf + XMLNames.DI_Signature_Reference_DigestValue, battery.DigestValue?.DigestValue ?? ""), - new XElement(_mrf + XMLNames.BusAux_ElectricSystem_NominalVoltage, BatterySOCReader.Create(battery.VoltageCurve).Lookup(0.5).ToXMLFormat(0)), - new XElement(_mrf + "TotalStorageCapacity", battery.TotalStorageCapacity().ValueAsUnit("kWh", 0)), - new XElement(_mrf + "TotalUsableCapacityInSimulation", battery.TotalUsableCapacityInSimulation().ValueAsUnit("kWh"), 0), - new XElement(_mrf + XMLNames.Component_CertificationMethod, battery.CertificationMethod.ToXMLFormat()) + new XAttribute("stringId", entry.Item1), + new XElement(_mrf + XMLNames.Component_Model, battery.Model), + new XElement(_mrf + XMLNames.Component_CertificationNumber, battery.CertificationNumber), + new XElement(_mrf + XMLNames.DI_Signature_Reference_DigestValue, battery.DigestValue?.DigestValue ?? ""), + new XElement(_mrf + XMLNames.BusAux_ElectricSystem_NominalVoltage, BatterySOCReader.Create(battery.VoltageCurve).Lookup(0.5).ToXMLFormat(0)), + new XElement(_mrf + "TotalStorageCapacity", batTotalCap.ValueAsUnit("kWh", 0)), + new XElement(_mrf + "TotalUsableCapacityInSimulation", batUsableCap.ValueAsUnit("kWh", 0)), + new XElement(_mrf + XMLNames.Component_CertificationMethod, battery.CertificationMethod.ToXMLFormat()) ) ); - } else if (electricStorage.REESSPack.StorageType == REESSType.SuperCap && - electricStorage.REESSPack is ISuperCapDeclarationInputData superCap) { + } + + } else { + foreach (var electricStorage in reessElements.Where(x => x.REESSPack.StorageType == REESSType.SuperCap)) { + var superCap = electricStorage.REESSPack as ISuperCapDeclarationInputData; result.Add(new XElement(_mrf + XMLNames.ElectricEnergyStorage_Capacitor, new XElement(_mrf + XMLNames.Component_Model, superCap.Model), new XElement(_mrf + XMLNames.Component_CertificationNumber, superCap.CertificationNumber), @@ -52,13 +68,21 @@ namespace TUGraz.VectoCore.OutputData.XML.DeclarationReports.ManufacturerReport. new XElement(_mrf + XMLNames.Capacitor_MaxVoltage, superCap.MaxVoltage.ToXMLFormat(2)) ) ); - } else { - throw new VectoException("Invalid REESS type"); } } return result; } + private static WattSecond GetEnergyStoredInBattery(Tuple<int, BatteryData> entry) + { + var tmpBattery = new Battery(null, entry.Item2); + tmpBattery.Initialize(tmpBattery.MaxSoC); + var energyFull = tmpBattery.StoredEnergy; + tmpBattery.Initialize(tmpBattery.MinSoC); + var energyEmpty = tmpBattery.StoredEnergy; + return energyFull - energyEmpty; + } + #endregion } }