diff --git a/VectoCommon/VectoCommon/Utils/SI.cs b/VectoCommon/VectoCommon/Utils/SI.cs index 344db00e282a75e3ba81cafd55cd6ebdb241abfb..55e3a1df345fb78a7a384e539678b88b4598e9ae 100644 --- a/VectoCommon/VectoCommon/Utils/SI.cs +++ b/VectoCommon/VectoCommon/Utils/SI.cs @@ -273,11 +273,11 @@ namespace TUGraz.VectoCommon.Utils return SIBase<KilogramPerSecond>.Create(kg.Val / second.Value()); } - [DebuggerHidden] - public static SI operator /(Kilogram kg, Joule j) - { - return (kg as SI) / j; - } + //[DebuggerHidden] + //public static SI operator /(Kilogram kg, Joule j) + //{ + // return (kg as SI) / j; + //} [DebuggerHidden] public static Scalar operator /(Kilogram kg, Kilogram kg2) @@ -291,7 +291,13 @@ namespace TUGraz.VectoCommon.Utils return SIBase<KilogramPerMeter>.Create(kg.Val / m.Value()); } - [DebuggerHidden] + [DebuggerHidden] + public static SpecificFuelConsumption operator /(Kilogram kg, WattSecond ws) + { + return SIBase<SpecificFuelConsumption>.Create(kg.Val / ws.Value()); + } + + [DebuggerHidden] public static Newton operator *(Kilogram kg, MeterPerSquareSecond m) { return SIBase<Newton>.Create(kg.Val * m.Value()); @@ -842,6 +848,13 @@ namespace TUGraz.VectoCommon.Utils private KilogramPerMeterMass(double val) : base(val, Units) { } } + public class SpecificFuelConsumption : SIBase<SpecificFuelConsumption> + { + private static readonly int[] Units = { 0, -2,2, 0, 0, 0, 0 }; + + private SpecificFuelConsumption(double val) : base(val, Units) { } + } + /// <summary> /// Base Class for all special SI Classes. Not intended to be used directly. /// Implements templated operators for type safety and convenience. diff --git a/VectoCommon/VectoCommon/Utils/SIConvertExtensionMethods.cs b/VectoCommon/VectoCommon/Utils/SIConvertExtensionMethods.cs index bf773c34686f0a31e3438a0688edbd2d0fc0c53e..545e08e7ea15f70a38e5d1113ff09e242e6b010a 100644 --- a/VectoCommon/VectoCommon/Utils/SIConvertExtensionMethods.cs +++ b/VectoCommon/VectoCommon/Utils/SIConvertExtensionMethods.cs @@ -126,7 +126,13 @@ namespace TUGraz.VectoCommon.Utils return value == null ? null : new ConvertedSI(value.Value() * Kilo * Kilo, "g/km"); } - public static ConvertedSI ConvertToLiterPer100Kilometer(this VolumePerMeter value) + public static ConvertedSI ConvertToGramPerKiloWattHour(this SpecificFuelConsumption value) + { + return new ConvertedSI(value.Value() * 3600e6, "g/kWh"); + } + + + public static ConvertedSI ConvertToLiterPer100Kilometer(this VolumePerMeter value) { return value == null ? null : new ConvertedSI(value.Value() * (10*10*10) * (100*1000), "l/100km"); } diff --git a/VectoCore/VectoCore/Models/Simulation/Impl/PowertrainBuilder.cs b/VectoCore/VectoCore/Models/Simulation/Impl/PowertrainBuilder.cs index 148899b410a44306dce012881ee9a697167342f1..ce9a92b600ffcaddf7c7b009f242f07389cea3e8 100644 --- a/VectoCore/VectoCore/Models/Simulation/Impl/PowertrainBuilder.cs +++ b/VectoCore/VectoCore/Models/Simulation/Impl/PowertrainBuilder.cs @@ -134,7 +134,7 @@ namespace TUGraz.VectoCore.Models.Simulation.Impl } var container = new VehicleContainer(ExecutionMode.Engineering, _modData, _sumWriter) { RunData = data }; - var gearbox = new CycleGearbox(container, data); + var gearbox = new VTPGearbox(container, data); // VTPCycle --> AxleGear --> Clutch --> Engine <-- Aux var powertrain = new VTPCycle(container, data.Cycle, data.AxleGearData.AxleGear.Ratio, data.VehicleData, diff --git a/VectoCore/VectoCore/Models/SimulationComponent/Impl/Clutch.cs b/VectoCore/VectoCore/Models/SimulationComponent/Impl/Clutch.cs index ab488ae867df7ec8734cc941d4dfe200d29b01fa..e2175d10804d9711fcfbd89e6a01173c6a5e6175 100644 --- a/VectoCore/VectoCore/Models/SimulationComponent/Impl/Clutch.cs +++ b/VectoCore/VectoCore/Models/SimulationComponent/Impl/Clutch.cs @@ -48,6 +48,8 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl private readonly PerSecond _idleSpeed; private readonly PerSecond _ratedSpeed; + private bool firstInitialize = true; + public IIdleController IdleController { get { return _idleController; } @@ -77,9 +79,12 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl engineSpeedIn = _idleSpeed; torqueIn = 0.SI<NewtonMeter>(); } else { - AddClutchLoss(outTorque, outAngularVelocity, true, out torqueIn, out engineSpeedIn); + AddClutchLoss(outTorque, outAngularVelocity, firstInitialize || DataBus.VehicleStopped, out torqueIn, out engineSpeedIn); } - PreviousState.SetState(torqueIn, outAngularVelocity, outTorque, outAngularVelocity); + PreviousState.SetState(torqueIn, engineSpeedIn, outTorque, outAngularVelocity); + //if (!firstInitialize) { + // PreviousState. + //} var retVal = NextComponent.Initialize(torqueIn, engineSpeedIn); retVal.ClutchPowerRequest = outTorque * outAngularVelocity; @@ -89,6 +94,7 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl public IResponse Request(Second absTime, Second dt, NewtonMeter outTorque, PerSecond outAngularVelocity, bool dryRun = false) { + firstInitialize = false; var startClutch = DataBus.VehicleStopped || !PreviousState.ClutchLoss.IsEqual(0); if (!DataBus.ClutchClosed(absTime) && !dryRun) { Log.Debug("Invoking IdleController..."); diff --git a/VectoCore/VectoCore/Models/SimulationComponent/Impl/CombustionEngine.cs b/VectoCore/VectoCore/Models/SimulationComponent/Impl/CombustionEngine.cs index 94f85088e9c18441cc1ec94697686a8cd043c9b2..032a25d0a6a5a49ef4d60bcead23aa470a5f13d4 100644 --- a/VectoCore/VectoCore/Models/SimulationComponent/Impl/CombustionEngine.cs +++ b/VectoCore/VectoCore/Models/SimulationComponent/Impl/CombustionEngine.cs @@ -314,7 +314,7 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl : VectoMath.Min(DataBus.GetGearData(DataBus.Gear).MaxSpeed, ModelData.FullLoadCurves[0].N95hSpeed); } - public IResponse Initialize(NewtonMeter outTorque, PerSecond outAngularVelocity) + public virtual IResponse Initialize(NewtonMeter outTorque, PerSecond outAngularVelocity) { if (outAngularVelocity == null) { outAngularVelocity = EngineIdleSpeed; diff --git a/VectoCore/VectoCore/Models/SimulationComponent/Impl/CycleGearbox.cs b/VectoCore/VectoCore/Models/SimulationComponent/Impl/CycleGearbox.cs index a0294af47544181cf6622e07836ee207bb1e454d..e4d3288a6a7fcafde6f7f148e5bfb7f0eb438b0d 100644 --- a/VectoCore/VectoCore/Models/SimulationComponent/Impl/CycleGearbox.cs +++ b/VectoCore/VectoCore/Models/SimulationComponent/Impl/CycleGearbox.cs @@ -81,7 +81,7 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl { var dt = Constants.SimulationSettings.TargetTimeInterval; - Gear = DataBus.CycleData.LeftSample.Gear; + Gear = GetGearFromCycle(); TorqueConverterActive = DataBus.CycleData.LeftSample.TorqueConverterActive; if (TorqueConverter != null && TorqueConverterActive == null) { @@ -158,7 +158,7 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl return retVal; } - private uint GetGearFromCycle() + protected virtual uint GetGearFromCycle() { return DataBus.DriverBehavior == DrivingBehavior.Braking ? DataBus.CycleData.LeftSample.Gear @@ -362,10 +362,12 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl { var avgInAngularSpeed = (PreviousState.InAngularVelocity + CurrentState.InAngularVelocity) / 2.0; var avgOutAngularSpeed = (PreviousState.OutAngularVelocity + CurrentState.OutAngularVelocity) / 2.0; + var inPower = CurrentState.InTorque * avgInAngularSpeed; + var outPower = CurrentState.OutTorque * avgOutAngularSpeed; container[ModalResultField.Gear] = Disengaged != null ? 0 : Gear; - container[ModalResultField.P_gbx_loss] = CurrentState.TransmissionTorqueLoss * avgOutAngularSpeed; + container[ModalResultField.P_gbx_loss] = inPower - outPower; container[ModalResultField.P_gbx_inertia] = CurrentState.InertiaTorqueLossOut * avgOutAngularSpeed; - container[ModalResultField.P_gbx_in] = CurrentState.InTorque * avgInAngularSpeed; + container[ModalResultField.P_gbx_in] = inPower; container[ModalResultField.n_gbx_out_avg] = (PreviousState.OutAngularVelocity + CurrentState.OutAngularVelocity) / 2.0; container[ModalResultField.T_gbx_out] = CurrentState.OutTorque; diff --git a/VectoCore/VectoCore/Models/SimulationComponent/Impl/DrivingCycleEnumerator.cs b/VectoCore/VectoCore/Models/SimulationComponent/Impl/DrivingCycleEnumerator.cs index b2ef8c304e8fb6c60b14af01b8ee8300cc982c77..74f8018540815a815ac74c57e3c99ac3f0f56e83 100644 --- a/VectoCore/VectoCore/Models/SimulationComponent/Impl/DrivingCycleEnumerator.cs +++ b/VectoCore/VectoCore/Models/SimulationComponent/Impl/DrivingCycleEnumerator.cs @@ -29,6 +29,7 @@ * Martin Rexeis, rexeis@ivt.tugraz.at, IVT, Graz University of Technology */ +using System; using System.Collections.Generic; using TUGraz.VectoCore.Models.SimulationComponent.Data; @@ -39,11 +40,18 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl private int _currentCycleIndex; private readonly IDrivingCycleData _data; - public DrivingCycleEnumerator(IDrivingCycleData data) - { - _currentCycleIndex = 0; - _data = data; - LastEntry = false; + public DrivingCycleEnumerator(IDrivingCycleData data) + { + _currentCycleIndex = 0; + _data = data; + LastEntry = false; + } + + public DrivingCycleEnumerator Previous() + { + var retVal = new DrivingCycleEnumerator(_data); + retVal._currentCycleIndex = Math.Max(0, _currentCycleIndex - 1); + return retVal; } public DrivingCycleEnumerator Clone() diff --git a/VectoCore/VectoCore/Models/SimulationComponent/Impl/Gearbox.cs b/VectoCore/VectoCore/Models/SimulationComponent/Impl/Gearbox.cs index 55bef61985f88a1599528efbb53e7ee8fdbac931..565fabc1c82ba402b22b4a101507dd30e46753e4 100644 --- a/VectoCore/VectoCore/Models/SimulationComponent/Impl/Gearbox.cs +++ b/VectoCore/VectoCore/Models/SimulationComponent/Impl/Gearbox.cs @@ -390,13 +390,10 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl { var avgInAngularSpeed = (PreviousState.InAngularVelocity + CurrentState.InAngularVelocity) / 2.0; var avgOutAngularSpeed = (PreviousState.OutAngularVelocity + CurrentState.OutAngularVelocity) / 2.0; - // (PreviousState.OutAngularVelocity + - //CurrentState.OutAngularVelocity) / 2.0 * ModelData.Gears[Gear].Ratio; var inPower = CurrentState.InTorque * avgInAngularSpeed; var outPower = CurrentState.OutTorque * avgOutAngularSpeed; container[ModalResultField.Gear] = Disengaged || DataBus.VehicleStopped ? 0 : Gear; container[ModalResultField.P_gbx_loss] = inPower - outPower; - //CurrentState.TransmissionTorqueLoss * avgOutAngularSpeed; container[ModalResultField.P_gbx_inertia] = CurrentState.InertiaTorqueLossOut * avgOutAngularSpeed; container[ModalResultField.P_gbx_in] = inPower; container[ModalResultField.n_gbx_out_avg] = (PreviousState.OutAngularVelocity + diff --git a/VectoCore/VectoCore/Models/SimulationComponent/Impl/PowertrainDrivingCycle.cs b/VectoCore/VectoCore/Models/SimulationComponent/Impl/PowertrainDrivingCycle.cs index ceffb5ad603acb4b18f6e844218ce2b936fa3bd2..8ab87a9c102d883a436ec4923fe447674cf7320a 100644 --- a/VectoCore/VectoCore/Models/SimulationComponent/Impl/PowertrainDrivingCycle.cs +++ b/VectoCore/VectoCore/Models/SimulationComponent/Impl/PowertrainDrivingCycle.cs @@ -134,6 +134,7 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl criterion: y => ((ResponseDryRun)y).DeltaFullLoad.Value()); response = NextComponent.Request(absTime, dt, torque, angularVelocity); CurrentState.InAngularVelocity = angularVelocity; + CurrentState.InTorque = torque; }) .Case<ResponseEngineSpeedTooHigh>(r => { angularVelocity = SearchAlgorithm.Search(angularVelocity, r.DeltaEngineSpeed, diff --git a/VectoCore/VectoCore/Models/SimulationComponent/Impl/VTPCombustionEngine.cs b/VectoCore/VectoCore/Models/SimulationComponent/Impl/VTPCombustionEngine.cs index 2ad3c5a8b72dee75b4be2725d3d8f60c2243311b..2aa7ea01550d29c885f4a7db3a876878748e5fb7 100644 --- a/VectoCore/VectoCore/Models/SimulationComponent/Impl/VTPCombustionEngine.cs +++ b/VectoCore/VectoCore/Models/SimulationComponent/Impl/VTPCombustionEngine.cs @@ -45,11 +45,39 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl { public class VTPCombustionEngine : CombustionEngine { + private bool firstInit = true; + public VTPCombustionEngine(IVehicleContainer container, CombustionEngineData modelData, bool pt1Disabled = false) : base(container, modelData, pt1Disabled) { } + public override IResponse Initialize(NewtonMeter outTorque, PerSecond outAngularVelocity) + { + if (outAngularVelocity == null) { + outAngularVelocity = EngineIdleSpeed; + } + var auxDemand = EngineAux == null ? 0.SI<NewtonMeter>() : EngineAux.Initialize(outTorque, outAngularVelocity); + if (firstInit) { + PreviousState = new EngineState { + EngineSpeed = outAngularVelocity, + dt = 1.SI<Second>(), + InertiaTorqueLoss = 0.SI<NewtonMeter>(), + StationaryFullLoadTorque = ModelData.FullLoadCurves[DataBus.Gear].FullLoadStationaryTorque(outAngularVelocity), + FullDragTorque = ModelData.FullLoadCurves[DataBus.Gear].DragLoadStationaryTorque(outAngularVelocity), + EngineTorque = outTorque + auxDemand, + EnginePower = (outTorque + auxDemand) * outAngularVelocity, + }; + PreviousState.DynamicFullLoadTorque = PreviousState.StationaryFullLoadTorque; + } + return new ResponseSuccess { + Source = this, + EnginePowerRequest = PreviousState.EnginePower, + EngineSpeed = outAngularVelocity + }; + } + protected override IResponse DoHandleRequest(Second absTime, Second dt, NewtonMeter torqueReq, PerSecond angularVelocity, bool dryRun) { + firstInit = false; var powerDemand = angularVelocity * torqueReq; var avgEngineSpeed = GetEngineSpeed(angularVelocity); @@ -63,10 +91,13 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl Formulas.InertiaPower(angularVelocity, PreviousState.EngineSpeed, ModelData.Inertia, dt) / avgEngineSpeed; + if (EngineAux != null) { + EngineAux.Initialize(0.SI<NewtonMeter>(), avgEngineSpeed); + } var auxTorqueDemand = EngineAux == null ? 0.SI<NewtonMeter>() : EngineAux.TorqueDemand(absTime, dt, torqueOut, - torqueOut + inertiaTorqueLoss, angularVelocity, dryRun); + torqueOut + inertiaTorqueLoss, avgEngineSpeed, dryRun); // compute the torque the engine has to provide. powertrain + aux + its own inertia var totalTorqueDemand = torqueOut + auxTorqueDemand + inertiaTorqueLoss; diff --git a/VectoCore/VectoCore/Models/SimulationComponent/Impl/VTPCycle.cs b/VectoCore/VectoCore/Models/SimulationComponent/Impl/VTPCycle.cs index c556de1b25f04232b53adbe7cccd08ae9dc2fb7c..212b4689bdac5c8cf19056ce6c83a3df5a174701 100644 --- a/VectoCore/VectoCore/Models/SimulationComponent/Impl/VTPCycle.cs +++ b/VectoCore/VectoCore/Models/SimulationComponent/Impl/VTPCycle.cs @@ -143,14 +143,15 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl var cardanSpeed = entry.WheelAngularVelocity * RunData.AxleGearData.AxleGear.Ratio * (RunData.AngledriveData?.Angledrive.Ratio ?? 1); - if (cardanSpeed.IsEqual(0.RPMtoRad(), 1.RPMtoRad())) { + if (cardanSpeed.IsEqual(0.RPMtoRad(), 1.RPMtoRad()) || entry.AngularVelocity.IsEqual(0.RPMtoRad(), 1.RPMtoRad())) { entry.Gear = 0; continue; } var ratio = (entry.EngineSpeed / cardanSpeed).Value(); var gear = gearRatios.Aggregate((x, y) => - Math.Abs(x.Value / ratio - 1) < Math.Abs(y.Value / ratio - 1) ? x : y).Key; - + Math.Abs(ratio/x.Value - 1) < Math.Abs(ratio/y.Value - 1) ? x : y).Key; + while (gear > 0 && cardanSpeed * gearRatios[gear] < RunData.EngineData.IdleSpeed) + gear--; //entry.Gear = entry.EngineSpeed < (RunData.EngineData.IdleSpeed + 50.RPMtoRad()) && entry.VehicleTargetSpeed < 5.KMPHtoMeterPerSecond() ? 0 : gear; if (stopped && gear <= StartGear) { @@ -166,27 +167,38 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl } } + public override IResponse Request(Second absTime, Second dt) + { + if (CycleIterator.LastEntry && CycleIterator.RightSample.Time == absTime) { + return new ResponseCycleFinished { Source = this }; + } + + // interval exceeded + if (CycleIterator.RightSample != null && (absTime + dt).IsGreater(CycleIterator.RightSample.Time)) { + return new ResponseFailTimeInterval { + AbsTime = absTime, + Source = this, + DeltaT = CycleIterator.RightSample.Time - absTime + }; + } + var tmp = NextComponent.Initialize(CycleIterator.LeftSample.Torque, CycleIterator.LeftSample.WheelAngularVelocity); + + return DoHandleRequest(absTime, dt, CycleIterator.LeftSample.WheelAngularVelocity); + } + public override bool VehicleStopped { get { - if (CycleIterator.LeftSample.Gear == 0) - return true; - if (CycleIterator.LeftSample.Gear != StartGear) - return false; - - var transmissionRatio = RunData.AxleGearData.AxleGear.Ratio * - (RunData.AngledriveData?.Angledrive.Ratio ?? 1.0); - return CycleIterator.LeftSample.WheelAngularVelocity * transmissionRatio * - RunData.GearboxData.Gears[CycleIterator.LeftSample.Gear].Ratio < DataBus.EngineIdleSpeed; - //return CycleIterator.LeftSample.VehicleTargetSpeed.IsEqual(0.KMPHtoMeterPerSecond(), - // 0.3.KMPHtoMeterPerSecond()); + return CycleIterator.Previous().LeftSample.VehicleTargetSpeed + .IsEqual(0.KMPHtoMeterPerSecond(), 0.3.KMPHtoMeterPerSecond()); } } protected override void DoWriteModalResults(IModalDataContainer container) { base.DoWriteModalResults(container); + container[ModalResultField.P_wheel_in] = CurrentState.InTorque * CurrentState.InAngularVelocity; container[ModalResultField.v_act] = CycleIterator.LeftSample.VehicleTargetSpeed; } } diff --git a/VectoCore/VectoCore/Models/SimulationComponent/Impl/VTPGearbox.cs b/VectoCore/VectoCore/Models/SimulationComponent/Impl/VTPGearbox.cs new file mode 100644 index 0000000000000000000000000000000000000000..c255a8b188c9e5727d54f407205907804753c5ce --- /dev/null +++ b/VectoCore/VectoCore/Models/SimulationComponent/Impl/VTPGearbox.cs @@ -0,0 +1,21 @@ +using TUGraz.VectoCommon.Utils; +using TUGraz.VectoCore.Models.Simulation; +using TUGraz.VectoCore.Models.Simulation.Data; + +namespace TUGraz.VectoCore.Models.SimulationComponent.Impl +{ + public class VTPGearbox : CycleGearbox + { + public VTPGearbox(IVehicleContainer container, VectoRunData runData) : base(container, runData) { } + + protected override uint GetGearFromCycle() + { + return DataBus.CycleData.LeftSample.Gear; + } + + public override bool ClutchClosed(Second absTime) + { + return DataBus.CycleData.LeftSample.Gear != 0; + } + } +} \ No newline at end of file diff --git a/VectoCore/VectoCore/OutputData/IModalDataContainer.cs b/VectoCore/VectoCore/OutputData/IModalDataContainer.cs index 43f16c5b77dce3f83871ed5e2d82ea74cdc20baf..897874f494e0cfff669b4227e2d9400c26cc34cf 100644 --- a/VectoCore/VectoCore/OutputData/IModalDataContainer.cs +++ b/VectoCore/VectoCore/OutputData/IModalDataContainer.cs @@ -225,6 +225,16 @@ namespace TUGraz.VectoCore.OutputData return data.TimeIntegral<WattSecond>(ModalResultField.P_gbx_loss); } + public static WattSecond WorkWheels(this IModalDataContainer data) + { + return data.TimeIntegral<WattSecond>(ModalResultField.P_wheel_in); + } + + public static WattSecond WorkWheelsPos(this IModalDataContainer data) + { + return data.TimeIntegral<WattSecond>(ModalResultField.P_wheel_in, x => x > 0); + } + public static WattSecond WorkAxlegear(this IModalDataContainer data) { return data.TimeIntegral<WattSecond>(ModalResultField.P_axle_loss); @@ -306,7 +316,7 @@ namespace TUGraz.VectoCore.OutputData public static Watt PowerWheelPositive(this IModalDataContainer data) { - return data.TimeIntegral<WattSecond>(ModalResultField.P_wheel_in, x => x > 0) / data.Duration(); + return data.WorkWheelsPos() / data.Duration(); } public static KilogramPerMeter FuelConsumptionWHTC(this IModalDataContainer data) @@ -394,9 +404,14 @@ namespace TUGraz.VectoCore.OutputData return data.TimeIntegral<Kilogram>(ModalResultField.FCFinal) * data.FuelData.LowerHeatingValue / distance; } + public static Kilogram TotalFuelConsumption(this IModalDataContainer data) + { + return data.TimeIntegral<Kilogram>(ModalResultField.FCMap); + } + public static KilogramPerSecond FCMapPerSecond(this IModalDataContainer data) { - return data.TimeIntegral<Kilogram>(ModalResultField.FCMap) / data.Duration(); + return data.TotalFuelConsumption() / data.Duration(); } public static KilogramPerMeter FCMapPerMeter(this IModalDataContainer data) @@ -405,7 +420,7 @@ namespace TUGraz.VectoCore.OutputData if (distance == null || distance.IsEqual(0)) { return null; } - return data.TimeIntegral<Kilogram>(ModalResultField.FCMap) / distance; + return data.TotalFuelConsumption() / distance; } diff --git a/VectoCore/VectoCore/OutputData/SummaryDataContainer.cs b/VectoCore/VectoCore/OutputData/SummaryDataContainer.cs index bff31b09126e7a747289744894f02b9eb48de98b..4786be4b9dcf0e2f9d76c465c0d827337fcb5094 100644 --- a/VectoCore/VectoCore/OutputData/SummaryDataContainer.cs +++ b/VectoCore/VectoCore/OutputData/SummaryDataContainer.cs @@ -149,6 +149,7 @@ namespace TUGraz.VectoCore.OutputData public const string E_GRAD = "E_grad [kWh]"; public const string E_VEHICLE_INERTIA = "E_vehi_inertia [kWh]"; public const string E_POWERTRAIN_INERTIA = "E_powertrain_inertia [kWh]"; + public const string E_WHEEL = "E_wheel [kWh]"; public const string E_BRAKE = "E_brake [kWh]"; public const string E_GBX_LOSS = "E_gbx_loss [kWh]"; public const string E_SHIFT_LOSS = "E_shift_loss [kWh]"; @@ -160,6 +161,8 @@ namespace TUGraz.VectoCore.OutputData public const string E_FCMAP_POS = "E_fcmap_pos [kWh]"; public const string E_FCMAP_NEG = "E_fcmap_neg [kWh]"; + public const string SPECIFIC_FC = "Specific FC [g/kWh] wheel pos."; + public const string ACC = "a [m/s^2]"; public const string ACC_POS = "a_pos [m/s^2]"; public const string ACC_NEG = "a_neg [m/s^2]"; @@ -190,17 +193,17 @@ namespace TUGraz.VectoCore.OutputData internal readonly DataTable Table; private readonly ISummaryWriter _sumWriter; - protected SummaryDataContainer() {} /// <summary> /// Initializes a new instance of the <see cref="SummaryDataContainer"/> class. /// </summary> /// <param name="writer"></param> + public SummaryDataContainer(ISummaryWriter writer) { _sumWriter = writer; - + Table = new DataTable(); Table.Columns.AddRange(new[] { @@ -270,12 +273,12 @@ namespace TUGraz.VectoCore.OutputData FCWHTCC_H, FCWHTCC_KM, FCAAUX_H, FCAAUX_KM, FCFINAL_H, FCFINAL_KM, - FCFINAL_LITERPER100KM, FCFINAL_LITERPER100TKM, FCFINAL_LiterPer100M3KM, + FCFINAL_LITERPER100KM, FCFINAL_LITERPER100TKM, FCFINAL_LiterPer100M3KM,SPECIFIC_FC, CO2_KM, CO2_TKM, CO2_M3KM, P_WHEEL_POS, P_FCMAP_POS, E_FCMAP_POS, E_FCMAP_NEG, E_POWERTRAIN_INERTIA, E_AUX, E_CLUTCH_LOSS, E_TC_LOSS, E_SHIFT_LOSS, E_GBX_LOSS, - E_RET_LOSS, E_ANGLE_LOSS, E_AXL_LOSS, E_BRAKE, E_VEHICLE_INERTIA, E_AIR, E_ROLL, E_GRAD, + E_RET_LOSS, E_ANGLE_LOSS, E_AXL_LOSS, E_BRAKE, E_VEHICLE_INERTIA, E_WHEEL , E_AIR, E_ROLL, E_GRAD , ACC, ACC_POS, ACC_NEG, ACC_TIMESHARE, DEC_TIMESHARE, CRUISE_TIMESHARE, MAX_SPEED, MAX_ACCELERATION, MAX_DECELERATION, AVG_ENGINE_SPEED, MAX_ENGINE_SPEED, NUM_GEARSHIFTS, STOP_TIMESHARE, ENGINE_FULL_LOAD_TIME_SHARE, COASTING_TIME_SHARE, BRAKING_TIME_SHARE @@ -292,6 +295,12 @@ namespace TUGraz.VectoCore.OutputData var view = new DataView(Table, "", SORT, DataViewRowState.CurrentRows).ToTable(); var toRemove = view.Columns.Cast<DataColumn>().Where(column => column.ColumnName.StartsWith(INTERNAL_PREFIX)).ToList(); + foreach (var colName in new[] { E_WHEEL, SPECIFIC_FC }) { + var column = view.Columns[colName]; + if (view.AsEnumerable().All(dr => dr.IsNull(column))) { + toRemove.Add(column); + } + } foreach (var dataColumn in toRemove) { view.Columns.Remove(dataColumn); } @@ -342,7 +351,7 @@ namespace TUGraz.VectoCore.OutputData row[ALTITUDE_DELTA] = (ConvertedSI)modData.AltitudeDelta(); - WriteFuelconsumptionEntries(modData, row, vehicleLoading, cargoVolume); + WriteFuelconsumptionEntries(modData, row, vehicleLoading, cargoVolume, runData.Cycle.CycleType == CycleType.VTP); var kilogramPerMeter = modData.CO2PerMeter(); if (kilogramPerMeter != null) { @@ -361,7 +370,7 @@ namespace TUGraz.VectoCore.OutputData WriteAuxiliaries(modData, row); - WriteWorkEntries(modData, row); + WriteWorkEntries(modData, row, runData.Cycle.CycleType == CycleType.VTP); WritePerformanceEntries(modData, row); @@ -377,7 +386,7 @@ namespace TUGraz.VectoCore.OutputData } private static void WriteFuelconsumptionEntries(IModalDataContainer modData, DataRow row, Kilogram vehicleLoading, - CubicMeter cargoVolume) + CubicMeter cargoVolume, bool vtpCycle) { var tmp = modData.FCMapPerSecond(); row[FCMAP_H] = tmp.ConvertToGrammPerHour(); @@ -410,6 +419,10 @@ namespace TUGraz.VectoCore.OutputData if (cargoVolume > 0 && fcFinal != null) { row[FCFINAL_LiterPer100M3KM] = (fcFinal / cargoVolume).ConvertToLiterPerCubicMeter100KiloMeter(); } + + if (vtpCycle) { + row[SPECIFIC_FC] = (modData.TotalFuelConsumption() / modData.WorkWheelsPos()).ConvertToGramPerKiloWattHour(); + } } @@ -478,7 +491,7 @@ namespace TUGraz.VectoCore.OutputData } } - private static void WriteWorkEntries(IModalDataContainer modData, DataRow row) + private static void WriteWorkEntries(IModalDataContainer modData, DataRow row, bool vtpMode) { row[E_FCMAP_POS] = modData.TotalEngineWorkPositive().ConvertToKiloWattHour(); row[E_FCMAP_NEG] = (-modData.TotalEngineWorkNegative()).ConvertToKiloWattHour(); @@ -496,6 +509,9 @@ namespace TUGraz.VectoCore.OutputData row[E_AIR] = modData.WorkAirResistance().ConvertToKiloWattHour(); row[E_ROLL] = modData.WorkRollingResistance().ConvertToKiloWattHour(); row[E_GRAD] = modData.WorkRoadGradientResistance().ConvertToKiloWattHour(); + if (vtpMode) { + row[E_WHEEL] = modData.WorkWheels().ConvertToKiloWattHour(); + } } private void WriteFullPowertrain(VectoRunData runData, DataRow row) diff --git a/VectoCore/VectoCore/VectoCore.csproj b/VectoCore/VectoCore/VectoCore.csproj index 858f6ac925714ee3bb24b1f643f165c7ed32f262..688a3f6ed0145886926bd51c7353e132d745c098 100644 --- a/VectoCore/VectoCore/VectoCore.csproj +++ b/VectoCore/VectoCore/VectoCore.csproj @@ -188,6 +188,7 @@ <Compile Include="Models\SimulationComponent\Impl\PWheelCycle.cs" /> <Compile Include="Models\SimulationComponent\Impl\TorqueConverter.cs" /> <Compile Include="Models\SimulationComponent\Impl\IdleControllerSwitcher.cs" /> + <Compile Include="Models\SimulationComponent\Impl\VTPGearbox.cs" /> <Compile Include="Models\Simulation\Data\ModalResultField.cs" /> <Compile Include="InputData\Reader\Impl\EngineeringVTPModeVectoRunDataFactory.cs" /> <Compile Include="Models\SimulationComponent\Impl\VTPCycle.cs" /> diff --git a/VectoCore/VectoCoreTest/Integration/SimulationRuns/FullPowertrain.cs b/VectoCore/VectoCoreTest/Integration/SimulationRuns/FullPowertrain.cs index ec9121a26a12ef3781b4a04459890b9ca008c35b..1826542ecd7ccbdcd62fd30fdb5738dc30628041 100644 --- a/VectoCore/VectoCoreTest/Integration/SimulationRuns/FullPowertrain.cs +++ b/VectoCore/VectoCoreTest/Integration/SimulationRuns/FullPowertrain.cs @@ -31,6 +31,7 @@ using System; using System.Collections.Generic; +using System.IO; using System.Linq; using TUGraz.VectoCommon.Models; using TUGraz.VectoCommon.Utils; @@ -67,6 +68,12 @@ namespace TUGraz.VectoCore.Tests.Integration.SimulationRuns //public const string GearboxFullLoadCurveFile = @"TestData\Components\Gearbox.vfld"; private static readonly LoggingObject Log = LogManager.GetLogger(typeof(FullPowerTrain).ToString()); + [OneTimeSetUp] + public void Init() + { + Directory.SetCurrentDirectory(TestContext.CurrentContext.TestDirectory); + } + [TestCase, Category("LongRunning")] public void Test_FullPowertrain_SimpleGearbox() { diff --git a/VectoCore/VectoCoreTest/Reports/ModDataTest.cs b/VectoCore/VectoCoreTest/Reports/ModDataTest.cs index e335e7c11680d6414b384ed856066fed818228e9..9717eec19852867112ea8a7ad6388600a1266919 100644 --- a/VectoCore/VectoCoreTest/Reports/ModDataTest.cs +++ b/VectoCore/VectoCoreTest/Reports/ModDataTest.cs @@ -212,14 +212,16 @@ namespace TUGraz.VectoCore.Tests.Reports fcMap = FuelConsumptionMapReader.Create(vtpInput.JobInputData.Vehicle .EngineInputData.FuelConsumptionMap); } + var disatanceBased = + ((VehicleContainer)(jobContainer.Runs.First().Run.GetContainer())).DrivingCycle is DistanceBasedDrivingCycle; foreach (var modalResults in modData) { - AssertModDataIntegrity(modalResults.Item1, auxKeys, modalResults.Item2,fcMap, ((VehicleContainer)(jobContainer.Runs.First().Run.GetContainer())).DrivingCycle is DistanceBasedDrivingCycle); + AssertModDataIntegrity(modalResults.Item1, auxKeys, modalResults.Item2,fcMap, disatanceBased); } - AssertSumDataIntegrity(sumData, mode); + AssertSumDataIntegrity(sumData, mode, disatanceBased); } - private static void AssertSumDataIntegrity(SummaryDataContainer sumData, ExecutionMode mode) + private static void AssertSumDataIntegrity(SummaryDataContainer sumData, ExecutionMode mode, bool distanceBased) { Assert.IsTrue(sumData.Table.Rows.Count > 0); @@ -250,31 +252,40 @@ namespace TUGraz.VectoCore.Tests.Reports var eAxlLoss = ((ConvertedSI)row[SummaryDataContainer.E_AXL_LOSS]); var eBrakeLoss = ((ConvertedSI)row[SummaryDataContainer.E_BRAKE]); var eVehInertia = ((ConvertedSI)row[SummaryDataContainer.E_VEHICLE_INERTIA]); + var eWheel = !distanceBased ? ((ConvertedSI)row[SummaryDataContainer.E_WHEEL]) : null ; var eAir = ((ConvertedSI)row[SummaryDataContainer.E_AIR]); var eRoll = ((ConvertedSI)row[SummaryDataContainer.E_ROLL]); var eGrad = ((ConvertedSI)row[SummaryDataContainer.E_GRAD]); var cargoVolume = mode == ExecutionMode.Engineering ? 0.0 : ((ConvertedSI)row[SummaryDataContainer.CARGO_VOLUME]); var loadingValue = ((ConvertedSI)row[SummaryDataContainer.LOADING]) / 1000; - var fcPer100km = ((ConvertedSI)row[SummaryDataContainer.FCFINAL_LITERPER100KM]); + var fcPer100km = distanceBased ? ((ConvertedSI)row[SummaryDataContainer.FCFINAL_LITERPER100KM]) : null; var fcPerVolume = mode == ExecutionMode.Engineering ? 0.0 : ((ConvertedSI)row[SummaryDataContainer.FCFINAL_LiterPer100M3KM]); var fcPerLoad = loadingValue > 0 ? ((ConvertedSI)row[SummaryDataContainer.FCFINAL_LITERPER100TKM]) : 0.0; - var co2PerKm = ((ConvertedSI)row[SummaryDataContainer.CO2_KM]); + var co2PerKm = distanceBased? ((ConvertedSI)row[SummaryDataContainer.CO2_KM]) : null; var co2PerVolume = mode == ExecutionMode.Engineering ? 0.0 : ((ConvertedSI)row[SummaryDataContainer.CO2_M3KM]); var co2PerLoad = loadingValue > 0 ? ((ConvertedSI)row[SummaryDataContainer.CO2_TKM]) : 0.0; var ePTOtransm = ptoTransmissionColumn != null ? ((ConvertedSI)row[ptoTransmissionColumn]) : 0.0; var ePTOconsumer = ptoConsumerColumn != null ? ((ConvertedSI)row[ptoConsumerColumn]) : 0.0; - // E_fcmap_pos = E_fcmap_neg + E_powertrain_inertia + E_aux_xxx + E_aux_sum + E_clutch_loss + E_tc_loss + E_gbx_loss + E_shift_loss + E_ret_loss + E_angle_loss + E_axl_loss + E_brake + E_vehicle_inertia + E_air + E_roll + E_grad + E_PTO_CONSUM + E_PTO_TRANSM - Assert.AreEqual(eFcMapPos, - eFcMapNeg + ePowertrainInertia + eAux + eClutchLoss + eTcLoss + eGbxLoss + eRetLoss + eAngleLoss + - eAxlLoss + eBrakeLoss + eVehInertia + eAir + eRoll + eGrad + ePTOconsumer + ePTOtransm, 1e-5, - "input file: {0} cycle: {1} loading: {2}", - inputFile, cycle, loading); - + if (distanceBased) { + // E_fcmap_pos = E_fcmap_neg + E_powertrain_inertia + E_aux_xxx + E_aux_sum + E_clutch_loss + E_tc_loss + E_gbx_loss + E_shift_loss + E_ret_loss + E_angle_loss + E_axl_loss + E_brake + E_vehicle_inertia + E_air + E_roll + E_grad + E_PTO_CONSUM + E_PTO_TRANSM + Assert.AreEqual(eFcMapPos, + eFcMapNeg + ePowertrainInertia + eAux + eClutchLoss + eTcLoss + eGbxLoss + eRetLoss + eAngleLoss + + eAxlLoss + eBrakeLoss + eVehInertia + eAir + eRoll + eGrad + ePTOconsumer + ePTOtransm, 1e-5, + "input file: {0} cycle: {1} loading: {2}", + inputFile, cycle, loading); + } else { + // E_fcmap_pos = E_fcmap_neg + E_powertrain_inertia + E_aux_xxx + E_aux_sum + E_clutch_loss + E_tc_loss + E_gbx_loss + E_shift_loss + E_ret_loss + E_angle_loss + E_axl_loss + E_brake + E_vehicle_inertia + E_wheel + E_PTO_CONSUM + E_PTO_TRANSM + Assert.AreEqual(eFcMapPos, + eFcMapNeg + ePowertrainInertia + eAux + eClutchLoss + eTcLoss + eGbxLoss + eRetLoss + eAngleLoss + + eAxlLoss + eBrakeLoss + eVehInertia + eWheel + ePTOconsumer + ePTOtransm, 1e-5, + "input file: {0} cycle: {1} loading: {2}", + inputFile, cycle, loading); + } var pFcmapPos = ((ConvertedSI)row[SummaryDataContainer.P_FCMAP_POS]); var time = ((ConvertedSI)row[SummaryDataContainer.TIME]); @@ -282,7 +293,7 @@ namespace TUGraz.VectoCore.Tests.Reports Assert.AreEqual(eFcMapPos, pFcmapPos * (time / 3600), 1e-3, "input file: {0} cycle: {1} loading: {2}", inputFile, cycle, loading); - if (cargoVolume > 0) { + if (distanceBased && cargoVolume > 0) { Assert.AreEqual(fcPerVolume, fcPer100km / cargoVolume, 1e-3, "input file: {0} cycle: {1} loading: {2}", inputFile, cycle, loading); @@ -291,7 +302,7 @@ namespace TUGraz.VectoCore.Tests.Reports cycle, loading); } - if (loadingValue > 0) { + if (distanceBased && loadingValue > 0) { Assert.AreEqual(co2PerLoad, co2PerKm / loadingValue, 1e-3, "input file: {0} cycle: {1} loading: {2}", inputFile, cycle, loading); Assert.AreEqual(fcPerLoad, fcPer100km / loadingValue, 1e-3, "input file: {0} cycle: {1} loading: {2}", @@ -306,9 +317,10 @@ namespace TUGraz.VectoCore.Tests.Reports Assert.AreEqual(100, stopTimeShare + accTimeShare + decTimeShare + cruiseTimeShare, 1e-3, "input file: {0} cycle: {1} loading: {2}", inputFile, cycle, loading); - Assert.IsTrue(((ConvertedSI)row[SummaryDataContainer.ACC_POS]) > 0); - Assert.IsTrue(((ConvertedSI)row[SummaryDataContainer.ACC_NEG]) < 0); - + if (distanceBased) { + Assert.IsTrue(((ConvertedSI)row[SummaryDataContainer.ACC_POS]) > 0); + Assert.IsTrue(((ConvertedSI)row[SummaryDataContainer.ACC_NEG]) < 0); + } var gearshifts = ((ConvertedSI)row[SummaryDataContainer.NUM_GEARSHIFTS]); Assert.IsTrue(gearshifts > 0); @@ -357,7 +369,7 @@ namespace TUGraz.VectoCore.Tests.Reports var pRoll = distanceBased ? (Watt)row[(int)ModalResultField.P_roll] : 0.SI<Watt>(); var pGrad = distanceBased ? (Watt)row[(int)ModalResultField.P_slope] : 0.SI<Watt>(); var pVehInertia = distanceBased ? (Watt)row[(int)ModalResultField.P_veh_inertia] : 0.SI<Watt>(); - var pTrac = distanceBased ? (Watt)row[(int)ModalResultField.P_trac] : 0.SI<Watt>(); + var pTrac = distanceBased ? (Watt)row[(int)ModalResultField.P_trac] : pWheelIn; // P_eng_out = P_wheel + P_lossgearbox + P_lossaxle + P_lossretarder + P_agbx + Pa_eng + P_aux - P_brake_loss var pEngOut = (Watt)row[(int)ModalResultField.P_eng_out]; @@ -387,9 +399,13 @@ namespace TUGraz.VectoCore.Tests.Reports var pPTOtransm = ptoTransmissionColumn == null || row[ptoTransmissionColumn.ColumnName] is DBNull ? 0.SI<Watt>() : (Watt)row[ptoTransmissionColumn.ColumnName]; - // P_trac = P_veh_inertia + P_roll + P_air + P_slope - Assert.AreEqual(pTrac.Value(), (pAir + pRoll + pGrad + pVehInertia).Value(), 1E-3, "time: {0} distance: {1}", time, - distance); + + if (distanceBased) { + // P_trac = P_veh_inertia + P_roll + P_air + P_slope + Assert.AreEqual(pTrac.Value(), (pAir + pRoll + pGrad + pVehInertia).Value(), 1E-3, "time: {0} distance: {1}", + time, + distance); + } if (distanceBased) { // P_wheel_in = P_trac + P_wheel_inertia @@ -437,8 +453,8 @@ namespace TUGraz.VectoCore.Tests.Reports "time: {0} distance: {1}", time, distance); // P_eng_fcmap = sum(Losses Powertrain) - var pLossTot = pClutchLoss + pTC_Loss + pLossGbx + pLossRet + pGbxInertia + pLossAngle + pLossAxle + pBrakeLoss + - pWheelInertia + pAir + pRoll + pGrad + pVehInertia + pPTOconsumer + pPTOtransm; + var pLossTot = pClutchLoss + pTC_Loss + pLossGbx + pLossRet + pGbxInertia + pLossAngle + pLossAxle + (distanceBased ? (pBrakeLoss + + pWheelInertia + pAir + pRoll + pGrad + pVehInertia) : pTrac) + pPTOconsumer + pPTOtransm; var pEngFcmapCalc = (pLossTot + pEngInertia + pAux).Value(); Assert.AreEqual(pEngFcmap.Value(), pEngFcmapCalc, 0.5, "time: {0} distance: {1}", time, distance); @@ -480,7 +496,7 @@ namespace TUGraz.VectoCore.Tests.Reports FuelConsumptionMapReader.Create(((IEngineeringInputDataProvider)inputData).JobInputData.Vehicle.EngineInputData.FuelConsumptionMap)); } - AssertSumDataIntegrity(sumData, ExecutionMode.Engineering); + AssertSumDataIntegrity(sumData, ExecutionMode.Engineering, true); } private static void AssertModDataIntegrityAT(ModalResults modData, Dictionary<string, DataColumn> auxKeys,