From 1c124b6e56544159049baf298ca33c01bb94b6d0 Mon Sep 17 00:00:00 2001 From: Markus Quaritsch <markus.quaritsch@tugraz.at> Date: Fri, 10 Jun 2022 14:14:16 +0200 Subject: [PATCH] add new mod-data postprocessing class for serial hybrid vehicles. pass over genet characteristics from powertrain to postprocessing via run-data instance --- .../Simulation/Data/ModalResultField.cs | 1 + .../Models/Simulation/Data/VectoRunData.cs | 10 ++ .../Models/Simulation/Impl/JobContainer.cs | 3 +- .../Strategies/SerialHybridStrategy.cs | 2 +- .../OutputData/ModalDataContainer.cs | 6 +- .../ModalDataPostprocessingCorrection.cs | 103 ++++++++++++++++-- 6 files changed, 111 insertions(+), 14 deletions(-) diff --git a/VectoCore/VectoCore/Models/Simulation/Data/ModalResultField.cs b/VectoCore/VectoCore/Models/Simulation/Data/ModalResultField.cs index 882d1441f3..c447ede967 100644 --- a/VectoCore/VectoCore/Models/Simulation/Data/ModalResultField.cs +++ b/VectoCore/VectoCore/Models/Simulation/Data/ModalResultField.cs @@ -480,6 +480,7 @@ namespace TUGraz.VectoCore.Models.Simulation.Data { private static ConcurrentDictionary<ModalResultField, ModalResultFieldAttribute> _attributeDictionary = new ConcurrentDictionary<ModalResultField, ModalResultFieldAttribute>(); + public static string GetName(this ModalResultField field) { return GetAttribute(field).Name ?? field.ToString(); diff --git a/VectoCore/VectoCore/Models/Simulation/Data/VectoRunData.cs b/VectoCore/VectoCore/Models/Simulation/Data/VectoRunData.cs index 3d2659fe3b..9dcc8106ab 100644 --- a/VectoCore/VectoCore/Models/Simulation/Data/VectoRunData.cs +++ b/VectoCore/VectoCore/Models/Simulation/Data/VectoRunData.cs @@ -48,6 +48,7 @@ using TUGraz.VectoCore.Models.SimulationComponent.Data; using TUGraz.VectoCore.Models.SimulationComponent.Data.Battery; using TUGraz.VectoCore.Models.SimulationComponent.Data.Gearbox; using TUGraz.VectoCore.Models.SimulationComponent.Impl; +using TUGraz.VectoCore.Models.SimulationComponent.Strategies; using TUGraz.VectoCore.OutputData; using DriverData = TUGraz.VectoCore.Models.SimulationComponent.Data.DriverData; @@ -157,6 +158,9 @@ namespace TUGraz.VectoCore.Models.Simulation.Data [JsonIgnore] public IMultistageVIFInputData MultistageVIFInputData { get; internal set; } + // container to pass genset data from powertrain to post-processing, not filled by dataadapter/rundatafactory + public GenSetData GenSet { get; set; } + public class AuxData { // ReSharper disable once InconsistentNaming @@ -175,6 +179,12 @@ namespace TUGraz.VectoCore.Models.Simulation.Data public MissionType? MissionType; } + // container to pass genset data from powertrain to post-processing, not filled by dataadapter/rundatafactory + public class GenSetData + { + public GenSetCharacteristics GenSetCharacteristics { get; set; } + } + public static ValidationResult ValidateRunData(VectoRunData runData, ValidationContext validationContext) { var gearboxData = runData.GearboxData; diff --git a/VectoCore/VectoCore/Models/Simulation/Impl/JobContainer.cs b/VectoCore/VectoCore/Models/Simulation/Impl/JobContainer.cs index 648327b84a..75c7e3e7f1 100644 --- a/VectoCore/VectoCore/Models/Simulation/Impl/JobContainer.cs +++ b/VectoCore/VectoCore/Models/Simulation/Impl/JobContainer.cs @@ -349,8 +349,7 @@ namespace TUGraz.VectoCore.Models.Simulation.Impl _runsRwLock.EnterWriteLock(); //_unfinishedRuns.Remove(runId); _unfinishedRuns.TryRemove(runId, out var tmpVal); - if (AllCompletedUnsafe()) - { + if (AllCompletedUnsafe()) { _sumWriter.Finish(); } } finally { diff --git a/VectoCore/VectoCore/Models/SimulationComponent/Strategies/SerialHybridStrategy.cs b/VectoCore/VectoCore/Models/SimulationComponent/Strategies/SerialHybridStrategy.cs index e835e31d6e..2f6e212cb0 100644 --- a/VectoCore/VectoCore/Models/SimulationComponent/Strategies/SerialHybridStrategy.cs +++ b/VectoCore/VectoCore/Models/SimulationComponent/Strategies/SerialHybridStrategy.cs @@ -277,7 +277,7 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Strategies var minGensetPower = emDtData.EfficiencyData.VoltageLevels.First().FullLoadCurve.MaxPower * StrategyParameters.GensetMinOptPowerFactor; GenSetCharacteristics = new GenSetCharacteristics(minGensetPower); - + runData.GenSet = new VectoRunData.GenSetData() { GenSetCharacteristics = GenSetCharacteristics }; // create testcontainer var modData = new ModalDataContainer(runData, null, null); diff --git a/VectoCore/VectoCore/OutputData/ModalDataContainer.cs b/VectoCore/VectoCore/OutputData/ModalDataContainer.cs index a201cbe249..ca208b405b 100644 --- a/VectoCore/VectoCore/OutputData/ModalDataContainer.cs +++ b/VectoCore/VectoCore/OutputData/ModalDataContainer.cs @@ -165,7 +165,11 @@ namespace TUGraz.VectoCore.OutputData return; } - PostProcessingCorrection = new ModalDataPostprocessingCorrection(); + var isSerialHybrid = runData.JobType == VectoSimulationJobType.IEPC_S || + runData.JobType == VectoSimulationJobType.SerialHybridVehicle; + PostProcessingCorrection = isSerialHybrid + ? new SerialHybridModalDataPostprocessingCorrection() + : new ModalDataPostprocessingCorrection(); var multipleEngineModes = runData.EngineData?.MultipleEngineFuelModes ?? false; var fuels = runData.EngineData?.Fuels ?? new List<CombustionEngineFuelData>(); diff --git a/VectoCore/VectoCore/OutputData/ModalDataPostprocessingCorrection.cs b/VectoCore/VectoCore/OutputData/ModalDataPostprocessingCorrection.cs index 411fea3308..e0aa4832bc 100644 --- a/VectoCore/VectoCore/OutputData/ModalDataPostprocessingCorrection.cs +++ b/VectoCore/VectoCore/OutputData/ModalDataPostprocessingCorrection.cs @@ -3,6 +3,7 @@ using System.Data; using System.Linq; using TUGraz.VectoCommon.BusAuxiliaries; using TUGraz.VectoCommon.Exceptions; +using TUGraz.VectoCommon.InputData; using TUGraz.VectoCommon.Models; using TUGraz.VectoCommon.Utils; using TUGraz.VectoCore.Models.BusAuxiliaries; @@ -13,6 +14,88 @@ using TUGraz.VectoCore.Models.SimulationComponent.Data; namespace TUGraz.VectoCore.OutputData { + public class SerialHybridModalDataPostprocessingCorrection : ModalDataPostprocessingCorrection + { + + protected override void SetReesCorrectionDemand(IModalDataContainer modData, VectoRunData runData, + CorrectedModalData r) + { + var deltaEReess = modData.TimeIntegral<WattSecond>(ModalResultField.P_reess_int.GetName()); + var startSoc = modData.REESSStartSoC(); + var endSoc = modData.REESSEndSoC(); + var emEff = 0.0; + if (endSoc < startSoc) { + var etaReessChg = modData.WorkREESSChargeInternal().Value() / modData.WorkREESSChargeTerminal().Value(); + emEff = 1.0 / (etaReessChg); + } + if (endSoc > startSoc) { + var etaReessDischg = modData.WorkREESSDischargeTerminal().Value() / modData.WorkREESSDischargeInternal().Value(); + emEff = etaReessDischg; + } + + r.DeltaEReessMech = double.IsNaN(emEff) ? 0.SI<WattSecond>() : -deltaEReess * emEff; + } + + protected override FuelConsumptionCorrection SetFuelConsumptionCorrection(IModalDataContainer modData, VectoRunData runData, + CorrectedModalData r, IFuelProperties fuel) + { + var duration = modData.Duration; + var distance = modData.Distance; + var essParams = runData.DriverData.EngineStopStart; + var engFuel = runData.EngineData.Fuels.First(x => x.FuelData.Equals(fuel)); + + var fcIceIdle = engFuel.ConsumptionMap.GetFuelConsumptionValue( + 0.SI<NewtonMeter>(), + runData.EngineData.IdleSpeed) * + engFuel.FuelConsumptionCorrectionFactor; + + var elPowerGenerated = modData.TimeIntegral<WattSecond>(string.Format(ModalResultField.P_EM_electricMotor_el_.GetCaption(), PowertrainPosition.GEN)); + var fcGenCharging = modData.TotalFuelConsumption(ModalResultField.FCFinal, fuel); + var socCorr = elPowerGenerated.IsEqual(0) + ? (runData.GenSet.GenSetCharacteristics.OptimalPoint.FuelConsumption / + runData.GenSet.GenSetCharacteristics.OptimalPoint.ElectricPower).Cast<KilogramPerWattSecond>() + : (fcGenCharging / elPowerGenerated).Cast<KilogramPerWattSecond>(); + var engLine = modData.EngineLineCorrectionFactor(fuel); + var comp = + runData.BusAuxiliaries?.PneumaticUserInputsConfig.CompressorMap + .Interpolate(runData.EngineData.IdleSpeed); + + var f = new FuelConsumptionCorrection { + Fuel = fuel, + Distance = distance != null && distance.IsGreater(0) ? distance : null, + Duration = duration != null && duration.IsGreater(0) ? duration : null, + EngineLineCorrectionFactor = engLine, + VehicleLine = modData.VehicleLineSlope(fuel), + FcModSum = modData.TotalFuelConsumption(ModalResultField.FCFinal, fuel), + FcESS_EngineStart = engLine * modData.WorkEngineStart(), + + FcESS_AuxStandstill_ICEOff = r.EnergyAuxICEOffStandstill_UF * engLine, + FcESS_AuxStandstill_ICEOn = r.EnergyAuxICEOnStandstill_UF * engLine + + fcIceIdle * r.ICEOffTimeStandstill * (1 - r.UtilityFactorStandstill), + + FcESS_AuxDriving_ICEOff = r.EnergyAuxICEOffDriving_UF * engLine, + FcESS_AuxDriving_ICEOn = r.EnergyAuxICEOnDriving_UF * engLine + + fcIceIdle * r.ICEOffTimeDriving * (1 - r.UtilityFactorDriving), + + FcESS_DCDCMissing = r.EnergyDCDCMissing * engLine, + FcBusAuxPSAirDemand = engLine * r.WorkBusAuxPSCorr, + + FcBusAuxPSDragICEOffStandstill = comp == null + ? 0.SI<Kilogram>() + : comp.PowerOff * r.ICEOffTimeStandstill * engLine * (1 - essParams.UtilityFactorStandstill), + FcBusAuxPSDragICEOffDriving = comp == null + ? 0.SI<Kilogram>() + : comp.PowerOff * r.ICEOffTimeDriving * engLine * (1 - essParams.UtilityFactorDriving), + FcREESSSoc = r.DeltaEReessMech * socCorr, + FcBusAuxEs = engLine * r.WorkBusAuxESMech, + FcWHR = engLine * r.WorkWHR, + FcAuxHtr = 0.SI<Kilogram>() + }; + + return f; + } + } + public class ModalDataPostprocessingCorrection : IModalDataPostProcessor { @@ -80,17 +163,17 @@ namespace TUGraz.VectoCore.OutputData return r; } - private void SetReesCorrectionDemand(IModalDataContainer modData, VectoRunData runData, + protected virtual void SetReesCorrectionDemand(IModalDataContainer modData, VectoRunData runData, CorrectedModalData r) { - var em = runData.ElectricMachinesData?.FirstOrDefault(); + var em = runData.ElectricMachinesData?.FirstOrDefault(x => x.Item1 != PowertrainPosition.GEN); if (em != null) { var deltaEReess = modData.TimeIntegral<WattSecond>(ModalResultField.P_reess_int.GetName()); var startSoc = modData.REESSStartSoC(); var endSoc = modData.REESSEndSoC(); - var emEff = 0.0; - if (endSoc < startSoc) { + var emEff = 0.0; + if (endSoc < startSoc) { var etaEmChg = modData.ElectricMotorEfficiencyGenerate(em.Item1); var etaReessChg = modData.WorkREESSChargeInternal().Value() / modData.WorkREESSChargeTerminal().Value(); emEff = 1.0 / (etaEmChg * etaReessChg); @@ -107,7 +190,7 @@ namespace TUGraz.VectoCore.OutputData } } - private static FuelConsumptionCorrection SetFuelConsumptionCorrection(IModalDataContainer modData, VectoRunData runData, + protected virtual FuelConsumptionCorrection SetFuelConsumptionCorrection(IModalDataContainer modData, VectoRunData runData, CorrectedModalData r, IFuelProperties fuel) { var duration = modData.Duration; @@ -163,7 +246,7 @@ namespace TUGraz.VectoCore.OutputData return f; } - private static void SetAuxHeaterDemand(IModalDataContainer modData, CorrectedModalData r, Second duration) + protected virtual void SetAuxHeaterDemand(IModalDataContainer modData, CorrectedModalData r, Second duration) { var engineWasteheatSum = modData.FuelData.Aggregate( 0.SI<Joule>(), @@ -174,7 +257,7 @@ namespace TUGraz.VectoCore.OutputData : modData.AuxHeaterDemandCalc(duration, engineWasteheatSum); } - private static void SetMissingDCDCEnergy(IModalDataContainer modData, VectoRunData runData, CorrectedModalData r) + protected virtual void SetMissingDCDCEnergy(IModalDataContainer modData, VectoRunData runData, CorrectedModalData r) { // either case C1, C2a, or C3a var missingDCDCEnergy = modData.TimeIntegral<WattSecond>(ModalResultField.P_DCDC_missing); @@ -203,7 +286,7 @@ namespace TUGraz.VectoCore.OutputData //} } - private static void SetBusAuxMissingPSWork(IModalDataContainer modData, VectoRunData runData, CorrectedModalData r) + protected virtual void SetBusAuxMissingPSWork(IModalDataContainer modData, VectoRunData runData, CorrectedModalData r) { var actuations = new Actuations() { Braking = runData.BusAuxiliaries.Actuations.Braking, @@ -234,7 +317,7 @@ namespace TUGraz.VectoCore.OutputData r.WorkBusAuxPSCorr = (r.kAir * r.DeltaAir).Cast<WattSecond>(); } - private static void SetMissingEnergyICEOFf(IModalDataContainer modData, CorrectedModalData r) + protected virtual void SetMissingEnergyICEOFf(IModalDataContainer modData, CorrectedModalData r) { var entriesAuxICEStandstill = modData.GetValues(x => new { dt = x.Field<Second>(ModalResultField.simulationInterval.GetName()), @@ -263,7 +346,7 @@ namespace TUGraz.VectoCore.OutputData r.EnergyAuxICEOnDriving = entriesAuxICEDriving.Sum(x => x.P_on * x.dt) ?? 0.SI<WattSecond>(); } - private static void SetWHRWork(IModalDataContainer modData, VectoRunData runData, CorrectedModalData r) + protected virtual void SetWHRWork(IModalDataContainer modData, VectoRunData runData, CorrectedModalData r) { // no post-processing correction for electric WHR for HEV (WHR is connected to REESS in simulation) r.WorkWHREl = (runData.BatteryData != null || runData.SuperCapData != null) && runData.EngineData.WHRType.IsElectrical() -- GitLab