diff --git a/VectoCore/VectoCore/InputData/Reader/ComponentData/FuelConsumptionMapReader.cs b/VectoCore/VectoCore/InputData/Reader/ComponentData/FuelConsumptionMapReader.cs index 448157e3b1054f9d65f33f9d90865283f3958c5a..19690eae244a46f6e4f7c0ae845f13798d0d1775 100644 --- a/VectoCore/VectoCore/InputData/Reader/ComponentData/FuelConsumptionMapReader.cs +++ b/VectoCore/VectoCore/InputData/Reader/ComponentData/FuelConsumptionMapReader.cs @@ -31,6 +31,7 @@ using System; using System.Data; +using System.IO; using System.Linq; using TUGraz.VectoCommon.BusAuxiliaries; using TUGraz.VectoCommon.Exceptions; @@ -53,6 +54,16 @@ namespace TUGraz.VectoCore.InputData.Reader.ComponentData } } + public static FuelConsumptionMap ReadFromStream(Stream stream) + { + try { + var data = VectoCSVFile.ReadStream(stream); + return Create(data); + } catch (Exception e) { + throw new VectoException($"Failed reading stream: {e.Message}", e); + } + } + public static FuelConsumptionMap Create(DataTable data) { var headerValid = HeaderIsValid(data.Columns); diff --git a/VectoCore/VectoCore/OutputData/ModalDataContainer.cs b/VectoCore/VectoCore/OutputData/ModalDataContainer.cs index 43c458c508f3f0fb7d0178d0d65bdf2b125997d8..0f491ee2dcef27afc38dc4a34a097323cb599542 100644 --- a/VectoCore/VectoCore/OutputData/ModalDataContainer.cs +++ b/VectoCore/VectoCore/OutputData/ModalDataContainer.cs @@ -206,7 +206,7 @@ namespace TUGraz.VectoCore.OutputData x => x.Field<bool>(ModalResultField.ICEOn.GetName()) ? new Point( x.Field<SI>(ModalResultField.P_ice_fcmap.GetName()).Value(), - x.Field<SI>(GetColumnName(fuel, ModalResultField.FCFinal)).Value()) + x.Field<SI>(GetColumnName(fuel, ModalResultField.FCWHTCc)).Value()) : null).Where(x => x != null && x.Y > 0), out var k, out var d, out var r); if (double.IsInfinity(k) || double.IsNaN(k)) { diff --git a/VectoCore/VectoCore/OutputData/ModalDataPostprocessingCorrection.cs b/VectoCore/VectoCore/OutputData/ModalDataPostprocessingCorrection.cs index cc2188ed1d2563ecee06d06a91fc23f72a654228..9705cc728cdb32c2bd7c452d57449028164cc8e6 100644 --- a/VectoCore/VectoCore/OutputData/ModalDataPostprocessingCorrection.cs +++ b/VectoCore/VectoCore/OutputData/ModalDataPostprocessingCorrection.cs @@ -5,8 +5,11 @@ using TUGraz.VectoCommon.BusAuxiliaries; using TUGraz.VectoCommon.Exceptions; using TUGraz.VectoCommon.Models; using TUGraz.VectoCommon.Utils; +using TUGraz.VectoCore.Models.BusAuxiliaries; +using TUGraz.VectoCore.Models.BusAuxiliaries.DownstreamModules.Impl.Pneumatics; using TUGraz.VectoCore.Models.Declaration; using TUGraz.VectoCore.Models.Simulation.Data; +using TUGraz.VectoCore.Models.SimulationComponent.Data; namespace TUGraz.VectoCore.OutputData { @@ -20,45 +23,13 @@ namespace TUGraz.VectoCore.OutputData var r = new CorrectedModalData(); var duration = modData.Duration; var distance = modData.Distance; - var essParams = runData.DriverData.EngineStopStart; - - var entriesAuxICEStandstill = modData.GetValues(x => new - { - dt = x.Field<Second>(ModalResultField.simulationInterval.GetName()), - P_off = x.Field<Watt>(ModalResultField.P_aux_ESS_mech_ice_off.GetName()) ?? 0.SI<Watt>(), - P_on = x.Field<Watt>(ModalResultField.P_aux_ESS_mech_ice_on.GetName()) ?? 0.SI<Watt>(), - v = x.Field<MeterPerSecond>(ModalResultField.v_act.GetName()), - IceOn = x.Field<bool>(ModalResultField.ICEOn.GetName()) - }).Where(x => x.v != null && x.v.IsEqual(0) && !x.IceOn).ToList(); - var entriesAuxICEDriving = modData.GetValues(x => new { - dt = x.Field<Second>(ModalResultField.simulationInterval.GetName()), - P_off = x.Field<Watt>(ModalResultField.P_aux_ESS_mech_ice_off.GetName()) ?? 0.SI<Watt>(), - P_on = x.Field<Watt>(ModalResultField.P_aux_ESS_mech_ice_on.GetName()) ?? 0.SI<Watt>(), - v = x.Field<MeterPerSecond>(ModalResultField.v_act.GetName()), - IceOn = x.Field<bool>(ModalResultField.ICEOn.GetName()) - }).Where(x => x.v != null && !x.v.IsEqual(0) && !x.IceOn).ToList(); + + SetMissingEnergyICEOFf(modData, r); - r.ICEOffTimeStandstill = entriesAuxICEStandstill.Sum(x => x.dt) ?? 0.SI<Second>(); - r.EnergyAuxICEOffStandstill = entriesAuxICEStandstill.Sum(x => x.P_off * x.dt) ?? 0.SI<WattSecond>(); - r.EnergyAuxICEOnStandstill = entriesAuxICEStandstill.Sum(x => x.P_on * x.dt) ?? 0.SI<WattSecond>(); - - r.ICEOffTimeDriving = entriesAuxICEDriving.Sum(x => x.dt) ?? 0.SI<Second>(); - r.EnergyAuxICEOffDriving = entriesAuxICEDriving.Sum(x => x.P_off * x.dt) ?? 0.SI<WattSecond>(); - r.EnergyPowerICEOnDriving = entriesAuxICEDriving.Sum(x => x.P_on * x.dt) ?? 0.SI<WattSecond>(); + SetWHRWork(modData, runData, r); - - r.WorkWHREl = modData.TimeIntegral<WattSecond>(ModalResultField.P_WHR_el_corr); - r.WorkWHRElMech = -r.WorkWHREl / DeclarationData.AlternaterEfficiency; - r.WorkWHRMech = -modData.TimeIntegral<WattSecond>(ModalResultField.P_WHR_mech_corr); - if (runData.BusAuxiliaries != null) { - var workBusAuxPSCompOff = modData.EnergyPneumaticCompressorPowerOff(); - var workBusAuxPSCompOn = modData.EnergyPneumaticCompressorAlwaysOn(); - var airBusAuxPSON = modData.AirGeneratedAlwaysOn(); - var deltaAir = modData.AirConsumed() - modData.AirGenerated(); - - var kAir = airBusAuxPSON.IsEqual(0) ? 0.SI(Unit.SI.Watt.Second.Per.Cubic.Meter) :(workBusAuxPSCompOn - workBusAuxPSCompOff) / (airBusAuxPSON - 0.SI<NormLiter>()); - r.WorkBusAuxPSCorr = (kAir * deltaAir).Cast<WattSecond>(); + SetBusAuxMissingPSWork(modData, runData, r); var workBusAuxES = modData.EnergyBusAuxESConsumed() - modData.EnergyBusAuxESGenerated(); r.WorkBusAuxESMech = workBusAuxES / @@ -70,73 +41,20 @@ namespace TUGraz.VectoCore.OutputData r.WorkBusAuxESMech = 0.SI<WattSecond>(); } - var engineWasteheatSum = modData.FuelData.Aggregate( - 0.SI<Joule>(), - (current, fuel) => current + modData.TotalFuelConsumption(ModalResultField.FCFinal, fuel) * - fuel.LowerHeatingValueVecto); r.EnergyDCDCMissing = 0.SI<WattSecond>(); if (runData.BusAuxiliaries != null && runData.BusAuxiliaries.ElectricalUserInputsConfig.ConnectESToREESS) { - // either case C1, C2a, or C3a - var missingDCDCEnergy = modData.TimeIntegral<WattSecond>(ModalResultField.P_DCDC_missing); - if (runData.BusAuxiliaries.ElectricalUserInputsConfig.AlternatorType == AlternatorType.Smart) { - // case C3a - if (runData.ElectricMachinesData.Count != 1) { - throw new VectoException("exactly 1 electric machine is required. got {0} ({1})", - runData.ElectricMachinesData.Count, - string.Join(",", runData.ElectricMachinesData.Select(x => x.Item1.ToString()))); - } - var emPos = runData.ElectricMachinesData.First().Item1; - var averageEmEfficiencyCharging = modData.ElectricMotorEfficiencyGenerate(emPos); - r.EnergyDCDCMissing = missingDCDCEnergy / - runData.BusAuxiliaries.ElectricalUserInputsConfig.DCDCEfficiency / - averageEmEfficiencyCharging; - } else { - // case C1, C2a - r.EnergyDCDCMissing = missingDCDCEnergy / DeclarationData.AlternaterEfficiency; - } + SetMissingDCDCEnergy(modData, runData, r); } - r.AuxHeaterDemand = modData.AuxHeaterDemandCalc == null - ? 0.SI<Joule>() - : modData.AuxHeaterDemandCalc(duration, engineWasteheatSum); + SetAuxHeaterDemand(modData, r, duration); var kilogramCO2PerMeter = 0.SI<KilogramPerMeter>(); var firstFuel = true; foreach (var fuel in modData.FuelData) { - var engFuel = runData.EngineData.Fuels.First(x => x.FuelData.Equals(fuel)); - var f = new FuelConsumptionCorrection(); - f.Fuel = fuel; - f.Distance = distance != null && distance.IsGreater(0) ? distance : null; - f.Duration = duration != null && duration.IsGreater(0) ? duration : null; - - f.EngineLineCorrectionFactor = modData.EngineLineCorrectionFactor(fuel); - f.VehicleLine = modData.VehicleLineSlope(fuel); - - f.FcModSum = modData.TotalFuelConsumption(ModalResultField.FCFinal, fuel); - - var fcIceOnAuxStandstill = engFuel.ConsumptionMap.GetFuelConsumptionValue( - r.AvgAuxPowerICEOnStandstill / runData.EngineData.IdleSpeed, runData.EngineData.IdleSpeed); - var fcIceOnAuxDriving = engFuel.ConsumptionMap.GetFuelConsumptionValue( - r.AvgAuxPowerICEOnDriving / runData.EngineData.IdleSpeed, runData.EngineData.IdleSpeed); - - f.FcESS_EngineStart = f.EngineLineCorrectionFactor * modData.WorkEngineStart(); - f.FcESS_AuxStandstill_ICEOff = r.EnergyAuxICEOffStandstill * f.EngineLineCorrectionFactor * - essParams.UtilityFactorStandstill; - f.FcESS_AuxStandstill_ICEOn = fcIceOnAuxStandstill * r.ICEOffTimeStandstill * - (1 - essParams.UtilityFactorStandstill); - f.FcESS_AuxDriving_ICEOn = r.EnergyAuxICEOffDriving * f.EngineLineCorrectionFactor * - essParams.UtilityFactorDriving; - f.FcESS_AuxDriving_ICEOff = fcIceOnAuxDriving * r.ICEOffTimeDriving * - (1 - essParams.UtilityFactorDriving); - f.FcESS_DCDCMissing = - r.EnergyDCDCMissing * f.EngineLineCorrectionFactor * essParams.UtilityFactorStandstill; - - f.FcBusAuxPs = f.EngineLineCorrectionFactor * r.WorkBusAuxPSCorr; - f.FcBusAuxEs = f.EngineLineCorrectionFactor * r.WorkBusAuxESMech; - f.FcWHR = f.EngineLineCorrectionFactor * r.WorkWHR; - f.FcAuxHtr = 0.SI<Kilogram>(); + + var f = SetFuelConsumptionCorrection(modData, runData, r, fuel); if (firstFuel) { firstFuel = false; f.FcAuxHtr = r.AuxHeaterDemand / fuel.LowerHeatingValueVecto; @@ -146,7 +64,6 @@ namespace TUGraz.VectoCore.OutputData ? 0.SI<KilogramPerMeter>() : f.FcFinal * fuel.CO2PerFuelWeight / distance; - //-- r.FuelCorrection[fuel.FuelType] = f; } @@ -154,6 +71,164 @@ namespace TUGraz.VectoCore.OutputData return r; } + private static 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 engLine = modData.EngineLineCorrectionFactor(fuel); + + 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 * engLine * + essParams.UtilityFactorStandstill, + FcESS_AuxStandstill_ICEOn = r.EnergyAuxICEOnStandstill * engLine * (1 - essParams.UtilityFactorStandstill) + + fcIceIdle * r.ICEOffTimeStandstill * (1 - essParams.UtilityFactorStandstill), + + FcESS_AuxDriving_ICEOff = r.EnergyAuxICEOffDriving * engLine * essParams.UtilityFactorDriving, + FcESS_AuxDriving_ICEOn = r.EnergyAuxICEOnDriving * engLine * (1 - essParams.UtilityFactorDriving) + + fcIceIdle * r.ICEOffTimeDriving * (1 - essParams.UtilityFactorDriving), + + FcESS_DCDCMissing = r.EnergyDCDCMissing * engLine * essParams.UtilityFactorStandstill, + FcBusAuxPs = engLine * r.WorkBusAuxPSCorr, + FcBusAuxEs = engLine * r.WorkBusAuxESMech, + FcWHR = engLine * r.WorkWHR, + FcAuxHtr = 0.SI<Kilogram>() + }; + + return f; + } + + private static void SetAuxHeaterDemand(IModalDataContainer modData, CorrectedModalData r, Second duration) + { + var engineWasteheatSum = modData.FuelData.Aggregate( + 0.SI<Joule>(), + (current, fuel) => current + modData.TotalFuelConsumption(ModalResultField.FCFinal, fuel) * + fuel.LowerHeatingValueVecto); + r.AuxHeaterDemand = modData.AuxHeaterDemandCalc == null + ? 0.SI<Joule>() + : modData.AuxHeaterDemandCalc(duration, engineWasteheatSum); + } + + private static void SetMissingDCDCEnergy(IModalDataContainer modData, VectoRunData runData, CorrectedModalData r) + { + // either case C1, C2a, or C3a + var missingDCDCEnergy = modData.TimeIntegral<WattSecond>(ModalResultField.P_DCDC_missing); + if (runData.BusAuxiliaries.ElectricalUserInputsConfig.AlternatorType == AlternatorType.Smart) { + // case C3a + if (runData.ElectricMachinesData.Count != 1) { + throw new VectoException("exactly 1 electric machine is required. got {0} ({1})", + runData.ElectricMachinesData.Count, + string.Join(",", runData.ElectricMachinesData.Select(x => x.Item1.ToString()))); + } + + var emPos = runData.ElectricMachinesData.First().Item1; + var averageEmEfficiencyCharging = modData.ElectricMotorEfficiencyGenerate(emPos); + r.EnergyDCDCMissing = missingDCDCEnergy / + runData.BusAuxiliaries.ElectricalUserInputsConfig.DCDCEfficiency / + averageEmEfficiencyCharging; + } else { + // case C1, C2a + r.EnergyDCDCMissing = missingDCDCEnergy / DeclarationData.AlternaterEfficiency; + } + } + + private static void SetBusAuxMissingPSWork(IModalDataContainer modData, VectoRunData runData, CorrectedModalData r) + { + var actuations = new Actuations() { + Braking = runData.BusAuxiliaries.Actuations.Braking, + ParkBrakeAndDoors = runData.BusAuxiliaries.Actuations.ParkBrakeAndDoors, + Kneeling = runData.BusAuxiliaries.Actuations.Kneeling, + CycleTime = modData.Duration + }; + var airDemand = M03Impl.TotalAirDemandCalculation(runData.BusAuxiliaries, actuations); + + var deltaAir = airDemand - modData.AirGenerated(); + + var nonSmartAirGen = modData.GetValues(x => new { + dt = x.Field<Second>(ModalResultField.simulationInterval.GetName()), + airConsumed = x.Field<NormLiter>(ModalResultField.Nl_busAux_PS_consumer.GetName()), + airGenerated = x.Field<NormLiter>(ModalResultField.Nl_busAux_PS_generated.GetName()), + P_compOff = x.Field<Watt>(ModalResultField.P_busAux_PS_generated_dragOnly.GetName()), + P_compOn = x.Field<Watt>(ModalResultField.P_busAux_PS_generated_alwaysOn.GetName()), + Nl_alwaysOn = x.Field<NormLiter>(ModalResultField.Nl_busAux_PS_generated_alwaysOn.GetName()) + }).Where(x => x.airConsumed.IsEqual(x.airGenerated)).ToArray(); + + var workBusAuxPSCompOff = nonSmartAirGen.Sum(x => x.P_compOff * x.dt); + var workBusAuxPSCompOn = nonSmartAirGen.Sum(x => x.P_compOn * x.dt); + var airBusAuxPSON = nonSmartAirGen.Sum(x => x.Nl_alwaysOn); + + var kAir = airBusAuxPSON.IsEqual(0) + ? 0.SI(Unit.SI.Watt.Second.Per.Cubic.Meter) + : (workBusAuxPSCompOn - workBusAuxPSCompOff) / (airBusAuxPSON - 0.SI<NormLiter>()); + r.WorkBusAuxPSCorr = (kAir * deltaAir).Cast<WattSecond>(); + } + + private static void SetMissingEnergyICEOFf(IModalDataContainer modData, CorrectedModalData r) + { + var entriesAuxICEStandstill = modData.GetValues(x => new { + dt = x.Field<Second>(ModalResultField.simulationInterval.GetName()), + P_off = x.Field<Watt>(ModalResultField.P_aux_ESS_mech_ice_off.GetName()) ?? 0.SI<Watt>(), + P_on = x.Field<Watt>(ModalResultField.P_aux_ESS_mech_ice_on.GetName()) ?? 0.SI<Watt>(), + v = x.Field<MeterPerSecond>(ModalResultField.v_act.GetName()), + IceOn = x.Field<bool>(ModalResultField.ICEOn.GetName()) + }).Where(x => x.v != null && x.v.IsEqual(0) && !x.IceOn).ToArray(); + + var entriesAuxICEDriving = modData.GetValues(x => new { + dt = x.Field<Second>(ModalResultField.simulationInterval.GetName()), + P_off = x.Field<Watt>(ModalResultField.P_aux_ESS_mech_ice_off.GetName()) ?? 0.SI<Watt>(), + P_on = x.Field<Watt>(ModalResultField.P_aux_ESS_mech_ice_on.GetName()) ?? 0.SI<Watt>(), + v = x.Field<MeterPerSecond>(ModalResultField.v_act.GetName()), + IceOn = x.Field<bool>(ModalResultField.ICEOn.GetName()) + }).Where(x => x.v != null && !x.v.IsEqual(0) && !x.IceOn).ToArray(); + + r.ICEOffTimeStandstill = entriesAuxICEStandstill.Sum(x => x.dt) ?? 0.SI<Second>(); + + r.EnergyAuxICEOffStandstill = entriesAuxICEStandstill.Sum(x => x.P_off * x.dt) ?? 0.SI<WattSecond>(); + r.EnergyAuxICEOnStandstill = entriesAuxICEStandstill.Sum(x => x.P_on * x.dt) ?? 0.SI<WattSecond>(); + + r.ICEOffTimeDriving = entriesAuxICEDriving.Sum(x => x.dt) ?? 0.SI<Second>(); + + r.EnergyAuxICEOffDriving = entriesAuxICEDriving.Sum(x => x.P_off * x.dt) ?? 0.SI<WattSecond>(); + r.EnergyAuxICEOnDriving = entriesAuxICEDriving.Sum(x => x.P_on * x.dt) ?? 0.SI<WattSecond>(); + } + + private static void SetWHRWork(IModalDataContainer modData, VectoRunData runData, CorrectedModalData r) + { + r.WorkWHREl = modData.TimeIntegral<WattSecond>(ModalResultField.P_WHR_el_corr); + var altEff = DeclarationData.AlternaterEfficiency; + if (runData.BusAuxiliaries != null && runData.BusAuxiliaries.ElectricalUserInputsConfig.AlternatorType == AlternatorType.Smart) { + // case C3a + if (runData.ElectricMachinesData.Count != 1) { + throw new VectoException("exactly 1 electric machine is required. got {0} ({1})", + runData.ElectricMachinesData.Count, + string.Join(",", runData.ElectricMachinesData.Select(x => x.Item1.ToString()))); + } + + var emPos = runData.ElectricMachinesData.First().Item1; + altEff = modData.ElectricMotorEfficiencyGenerate(emPos); + } + + r.WorkWHRElMech = -r.WorkWHREl / altEff; + r.WorkWHRMech = -modData.TimeIntegral<WattSecond>(ModalResultField.P_WHR_mech_corr); + } + #endregion } @@ -214,8 +289,8 @@ namespace TUGraz.VectoCore.OutputData public Second ICEOffTimeDriving { get; set; } public WattSecond EnergyAuxICEOffDriving { get; set; } - public WattSecond EnergyPowerICEOnDriving { get; set; } - public Watt AvgAuxPowerICEOnDriving => ICEOffTimeDriving.IsEqual(0) ? 0.SI<Watt>() : EnergyPowerICEOnDriving / ICEOffTimeDriving; + public WattSecond EnergyAuxICEOnDriving { get; set; } + public Watt AvgAuxPowerICEOnDriving => ICEOffTimeDriving.IsEqual(0) ? 0.SI<Watt>() : EnergyAuxICEOnDriving / ICEOffTimeDriving; public WattSecond EnergyDCDCMissing { get; set; } diff --git a/VectoCore/VectoCoreTest/Reports/ModDataPostprocessingTest.cs b/VectoCore/VectoCoreTest/Reports/ModDataPostprocessingTest.cs new file mode 100644 index 0000000000000000000000000000000000000000..3e2d2098657a1b8d9f7b9d00e884738da74116be --- /dev/null +++ b/VectoCore/VectoCoreTest/Reports/ModDataPostprocessingTest.cs @@ -0,0 +1,381 @@ +using System; +using System.Collections.Generic; +using NUnit.Framework; +using TUGraz.VectoCommon.Utils; +using TUGraz.VectoCore.InputData.Reader.ComponentData; +using TUGraz.VectoCore.Models.Declaration; +using TUGraz.VectoCore.Models.Simulation.Data; +using TUGraz.VectoCore.Models.SimulationComponent.Data; +using TUGraz.VectoCore.Models.SimulationComponent.Data.Engine; +using TUGraz.VectoCore.OutputData; +using TUGraz.VectoCore.Tests.Utils; + +namespace TUGraz.VectoCore.Tests.Reports +{ + [TestFixture] + [Parallelizable] + public class ModDataPostprocessingTest + { + + [TestCase()] + public void TestAuxESSStandstill_ModDataCorrection() + { + var runData = GetRunData(); + var modData = new ModalDataContainer(runData, null, null); + + var fuel = runData.EngineData.Fuels[0]; + + var absTime = 0.SI<Second>(); + var rnd = new Random(210629); + var dt = 0.SI<Second>(); + + var i = 0; + // constant driving + var n_ice = 800.RPMtoRad(); + var t_ice = 400.SI<NewtonMeter>(); + for (; i < 100; i++) { + dt = (rnd.NextDouble() * 0.2 + 0.4).SI<Second>(); + + modData[ModalResultField.time] = absTime; + modData[ModalResultField.simulationInterval] = dt; + + modData[ModalResultField.v_act] = 50.KMPHtoMeterPerSecond(); + modData[ModalResultField.ICEOn] = true; + + modData[ModalResultField.n_ice_avg] = n_ice; + modData[ModalResultField.P_ice_fcmap] = n_ice * t_ice; + var fc = fuel.ConsumptionMap.GetFuelConsumption(t_ice, n_ice).Value * + fuel.FuelConsumptionCorrectionFactor; + modData[ModalResultField.FCWHTCc] = fc; + modData[ModalResultField.FCFinal] = fc; + + modData[ModalResultField.P_aux_ESS_mech_ice_off] = 0.SI<Watt>(); + modData[ModalResultField.P_aux_ESS_mech_ice_on] = 0.SI<Watt>(); + + // WHR + modData[ModalResultField.P_WHR_el_corr] = 0.SI<Watt>(); + modData[ModalResultField.P_WHR_mech_corr] = 0.SI<Watt>(); + + modData.CommitSimulationStep(); + absTime += dt; + } + + // standstill + for (; i < 200; i++) { + dt = (rnd.NextDouble() * 0.2 + 0.4).SI<Second>(); + + modData[ModalResultField.time] = absTime; + modData[ModalResultField.simulationInterval] = dt; + + modData[ModalResultField.v_act] = 0.KMPHtoMeterPerSecond(); + modData[ModalResultField.ICEOn] = false; + + modData[ModalResultField.n_ice_avg] = 0.RPMtoRad(); + modData[ModalResultField.P_ice_fcmap] = 0.SI<Watt>(); + modData[ModalResultField.FCWHTCc] = 0.SI<KilogramPerSecond>(); + modData[ModalResultField.FCFinal] = 0.SI<KilogramPerSecond>(); + + modData[ModalResultField.P_aux_ESS_mech_ice_off] = 300.SI<Watt>(); + modData[ModalResultField.P_aux_ESS_mech_ice_on] = 900.SI<Watt>(); + + // WHR + modData[ModalResultField.P_WHR_el_corr] = 0.SI<Watt>(); + modData[ModalResultField.P_WHR_mech_corr] = 0.SI<Watt>(); + + modData.CommitSimulationStep(); + absTime += dt; + } + + // constant driving different speed + modData[ModalResultField.P_ice_start] = 0000.SI<Watt>(); + n_ice = 1200.RPMtoRad(); + for (; i < 300; i++) { + dt = (rnd.NextDouble() * 0.2 + 0.4).SI<Second>(); + + modData[ModalResultField.time] = absTime; + modData[ModalResultField.simulationInterval] = dt; + + modData[ModalResultField.v_act] = 50.KMPHtoMeterPerSecond(); + modData[ModalResultField.ICEOn] = true; + + modData[ModalResultField.n_ice_avg] = n_ice; + modData[ModalResultField.P_ice_fcmap] = n_ice * t_ice; + var fc = fuel.ConsumptionMap.GetFuelConsumption(400.SI<NewtonMeter>(), n_ice).Value * + fuel.FuelConsumptionCorrectionFactor; + modData[ModalResultField.FCWHTCc] = fc; + modData[ModalResultField.FCFinal] = fc; + + + modData[ModalResultField.P_aux_ESS_mech_ice_off] = 0.SI<Watt>(); + modData[ModalResultField.P_aux_ESS_mech_ice_on] = 0.SI<Watt>(); + + // WHR + modData[ModalResultField.P_WHR_el_corr] = 0.SI<Watt>(); + modData[ModalResultField.P_WHR_mech_corr] = 0.SI<Watt>(); + + modData.CommitSimulationStep(); + absTime += dt; + } + + var corr = modData.CorrectedModalData as CorrectedModalData; + + Assert.AreEqual(2.625452e-8, modData.EngineLineCorrectionFactor(fuel.FuelData).Value(), 1e-12); + Assert.AreEqual(0, corr.WorkWHREl.Value()); + Assert.AreEqual(0, corr.WorkWHRElMech.Value()); + Assert.AreEqual(0, corr.WorkWHRMech.Value()); + + Assert.AreEqual(46054.609, corr.EnergyAuxICEOnStandstill.Value(), 1e-3); + Assert.AreEqual(15351.536, corr.EnergyAuxICEOffStandstill.Value(), 1e-3); + + Assert.AreEqual(0, corr.EnergyAuxICEOnDriving.Value(), 1e-3); + Assert.AreEqual(0, corr.EnergyAuxICEOffDriving.Value(), 1e-3); + + + var f = corr.FuelCorrection[fuel.FuelData.FuelType] as FuelConsumptionCorrection; + + var fcEssStandStillOff = 0.0002821330689; + var fcEssStandStillOn = 0.0048594804294; + Assert.AreEqual(fcEssStandStillOff, f.FcESS_AuxStandstill_ICEOff.Value(), 1e-12); + Assert.AreEqual(fcEssStandStillOn, f.FcESS_AuxStandstill_ICEOn.Value(), 1e-12); + Assert.AreEqual(0, f.FcESS_AuxDriving_ICEOff.Value(), 1e-12); + Assert.AreEqual(0, f.FcESS_AuxDriving_ICEOn.Value(), 1e-12); + + + var fcModSum = 0.195725; + var fcIdle = + fuel.ConsumptionMap.GetFuelConsumption(0.SI<NewtonMeter>(), runData.EngineData.IdleSpeed).Value + .Value() * fuel.FuelConsumptionCorrectionFactor; + Assert.AreEqual(fcModSum, modData.TotalFuelConsumption(ModalResultField.FCWHTCc, fuel.FuelData).Value(), 1e-6); + Assert.AreEqual(fcModSum + fcEssStandStillOff + fcEssStandStillOn , f.FcEssCorr.Value(), 1e-6); + + } + + + + [TestCase()] + public void TestAuxESSDriving_ModDataCorrection() + { + var runData = GetRunData(); + var modData = new ModalDataContainer(runData, null, null); + + var fuel = runData.EngineData.Fuels[0]; + + var absTime = 0.SI<Second>(); + var rnd = new Random(210629); + var dt = 0.SI<Second>(); + + var i = 0; + // constant driving + var n_ice = 800.RPMtoRad(); + var t_ice = 400.SI<NewtonMeter>(); + for (; i < 100; i++) { + dt = (rnd.NextDouble() * 0.2 + 0.4).SI<Second>(); + + modData[ModalResultField.time] = absTime; + modData[ModalResultField.simulationInterval] = dt; + + modData[ModalResultField.v_act] = 50.KMPHtoMeterPerSecond(); + modData[ModalResultField.ICEOn] = true; + + modData[ModalResultField.n_ice_avg] = n_ice; + modData[ModalResultField.P_ice_fcmap] = n_ice * t_ice; + var fc = fuel.ConsumptionMap.GetFuelConsumption(t_ice, n_ice).Value * + fuel.FuelConsumptionCorrectionFactor; + modData[ModalResultField.FCWHTCc] = fc; + modData[ModalResultField.FCFinal] = fc; + + modData[ModalResultField.P_aux_ESS_mech_ice_off] = 0.SI<Watt>(); + modData[ModalResultField.P_aux_ESS_mech_ice_on] = 0.SI<Watt>(); + + // WHR + modData[ModalResultField.P_WHR_el_corr] = 0.SI<Watt>(); + modData[ModalResultField.P_WHR_mech_corr] = 0.SI<Watt>(); + + modData.CommitSimulationStep(); + absTime += dt; + } + + // driving ICE Off + for (; i < 200; i++) { + dt = (rnd.NextDouble() * 0.2 + 0.4).SI<Second>(); + + modData[ModalResultField.time] = absTime; + modData[ModalResultField.simulationInterval] = dt; + + modData[ModalResultField.v_act] = 50.KMPHtoMeterPerSecond(); + modData[ModalResultField.ICEOn] = false; + + modData[ModalResultField.n_ice_avg] = 0.RPMtoRad(); + modData[ModalResultField.P_ice_fcmap] = 0.SI<Watt>(); + modData[ModalResultField.FCWHTCc] = 0.SI<KilogramPerSecond>(); + modData[ModalResultField.FCFinal] = 0.SI<KilogramPerSecond>(); + + modData[ModalResultField.P_aux_ESS_mech_ice_off] = 300.SI<Watt>(); + modData[ModalResultField.P_aux_ESS_mech_ice_on] = 900.SI<Watt>(); + + // WHR + modData[ModalResultField.P_WHR_el_corr] = 0.SI<Watt>(); + modData[ModalResultField.P_WHR_mech_corr] = 0.SI<Watt>(); + + modData.CommitSimulationStep(); + absTime += dt; + } + + // constant driving different speed + modData[ModalResultField.P_ice_start] = 0000.SI<Watt>(); + n_ice = 1200.RPMtoRad(); + for (; i < 300; i++) { + dt = (rnd.NextDouble() * 0.2 + 0.4).SI<Second>(); + + modData[ModalResultField.time] = absTime; + modData[ModalResultField.simulationInterval] = dt; + + modData[ModalResultField.v_act] = 50.KMPHtoMeterPerSecond(); + modData[ModalResultField.ICEOn] = true; + + modData[ModalResultField.n_ice_avg] = n_ice; + modData[ModalResultField.P_ice_fcmap] = n_ice * t_ice; + var fc = fuel.ConsumptionMap.GetFuelConsumption(400.SI<NewtonMeter>(), n_ice).Value * + fuel.FuelConsumptionCorrectionFactor; + modData[ModalResultField.FCWHTCc] = fc; + modData[ModalResultField.FCFinal] = fc; + + + modData[ModalResultField.P_aux_ESS_mech_ice_off] = 0.SI<Watt>(); + modData[ModalResultField.P_aux_ESS_mech_ice_on] = 0.SI<Watt>(); + + // WHR + modData[ModalResultField.P_WHR_el_corr] = 0.SI<Watt>(); + modData[ModalResultField.P_WHR_mech_corr] = 0.SI<Watt>(); + + modData.CommitSimulationStep(); + absTime += dt; + } + + var corr = modData.CorrectedModalData as CorrectedModalData; + + Assert.AreEqual(2.625452e-8, modData.EngineLineCorrectionFactor(fuel.FuelData).Value(), 1e-12); + Assert.AreEqual(0, corr.WorkWHREl.Value()); + Assert.AreEqual(0, corr.WorkWHRElMech.Value()); + Assert.AreEqual(0, corr.WorkWHRMech.Value()); + + Assert.AreEqual(0, corr.EnergyAuxICEOnStandstill.Value(), 1e-3); + Assert.AreEqual(0, corr.EnergyAuxICEOffStandstill.Value(), 1e-3); + + Assert.AreEqual(46054.609, corr.EnergyAuxICEOnDriving.Value(), 1e-3); + Assert.AreEqual(15351.536, corr.EnergyAuxICEOffDriving.Value(), 1e-3); + + var f = corr.FuelCorrection[fuel.FuelData.FuelType] as FuelConsumptionCorrection; + + var fcEssDrivingOff = 0.0003224377930; + var fcEssDrivingOn = 0.0032396536196; + Assert.AreEqual(0, f.FcESS_AuxStandstill_ICEOff.Value(), 1e-12); + Assert.AreEqual(0, f.FcESS_AuxStandstill_ICEOn.Value(), 1e-12); + Assert.AreEqual(fcEssDrivingOff, f.FcESS_AuxDriving_ICEOff.Value(), 1e-12); + Assert.AreEqual(fcEssDrivingOn, f.FcESS_AuxDriving_ICEOn.Value(), 1e-12); + + var fcModSum = 0.195725; + var fcIdle = + fuel.ConsumptionMap.GetFuelConsumption(0.SI<NewtonMeter>(), runData.EngineData.IdleSpeed).Value + .Value() * fuel.FuelConsumptionCorrectionFactor; + Assert.AreEqual(fcModSum, modData.TotalFuelConsumption(ModalResultField.FCWHTCc, fuel.FuelData).Value(), 1e-6); + Assert.AreEqual(fcModSum + fcEssDrivingOff + fcEssDrivingOn, f.FcEssCorr.Value(), 1e-6); + } + + [TestCase()] + public void TestBusAuxPSESSStandstill_ModDataCorrection() + { + Assert.Fail(); + + } + + [TestCase()] + public void TestBusAuxPSESSDriving_ModDataCorrection() + { + Assert.Fail(); + + } + + [TestCase()] + public void TestBusAuxSmartES_ModDataCorrection() + { + Assert.Fail(); + + } + + [TestCase()] + public void TestBusAuxDCDCMissing_ModDataCorrection() + { + Assert.Fail(); + + } + + [TestCase()] + public void TestBusAuxSmartPS_ModDataCorrection() + { + Assert.Fail(); + + } + + [TestCase()] + public void TestBusAuxPSDemand_ModDataCorrection() + { + Assert.Fail(); + + } + + [TestCase()] + public void TestWHRElAlternator_ModDataCorrection() + { + Assert.Fail(); + + } + + [TestCase()] + public void TestWHRElNoAlternator_ModDataCorrection() + { + Assert.Fail(); + + } + + [TestCase] + public void TestWHRMech_ModDataCorrection() + { + Assert.Fail(); + + } + + + private VectoRunData GetRunData() + { + var fcMapHeader = "engine speed [rpm],torque [Nm],fuel consumption [g/h]"; + var fcMapEntries = new[] { + "600,-107,0", + "600,0,1042", + "600,916,10963", + "2000,-215,0", + "2000,0,6519", + "2000,966,40437" + }; + + return new VectoRunData() { + DriverData = new DriverData() { + EngineStopStart = new DriverData.EngineStopStartData() { + UtilityFactorDriving = 0.8, + UtilityFactorStandstill = 0.7 + } + }, + EngineData = new CombustionEngineData() { + IdleSpeed = 600.RPMtoRad(), + Fuels = new List<CombustionEngineFuelData>() { + new CombustionEngineFuelData() { + FuelData = FuelData.Diesel, + FuelConsumptionCorrectionFactor = 1.012, + ConsumptionMap = FuelConsumptionMapReader.ReadFromStream(InputDataHelper.InputDataAsStream(fcMapHeader, fcMapEntries)) + } + } + } + }; + } + } +} \ No newline at end of file diff --git a/VectoCore/VectoCoreTest/VectoCoreTest.csproj b/VectoCore/VectoCoreTest/VectoCoreTest.csproj index c60edb48e0329015705afc477f96d2552f1d7097..9b0fcf185eee37579b8f1ae43d074aab7190d46f 100644 --- a/VectoCore/VectoCoreTest/VectoCoreTest.csproj +++ b/VectoCore/VectoCoreTest/VectoCoreTest.csproj @@ -153,6 +153,7 @@ <Compile Include="Models\SimulationComponent\EngineFanAuxTest.cs" /> <Compile Include="Models\SimulationComponent\GearboxShiftLossesTest.cs" /> <Compile Include="Models\SimulationComponent\SuperCapTest.cs" /> + <Compile Include="Reports\ModDataPostprocessingTest.cs" /> <Compile Include="Utils\CompletedVIF.cs" /> <Compile Include="Utils\MockElectricConsumer.cs" /> <Compile Include="Utils\MockHybridControl.cs" />