From 4d099c5925be2eeeff9bf0a40de1ff6fb52915a4 Mon Sep 17 00:00:00 2001 From: Markus Quaritsch <markus.quaritsch@tugraz.at> Date: Mon, 18 Jan 2016 16:57:43 +0100 Subject: [PATCH] gearbox fullload curve has only two columns --- .../Data/Engine/EngineFullLoadCurve.cs | 93 ++++++++++--------- .../SimulationComponent/Data/FullLoadCurve.cs | 36 ++++--- 2 files changed, 70 insertions(+), 59 deletions(-) diff --git a/VectoCore/Models/SimulationComponent/Data/Engine/EngineFullLoadCurve.cs b/VectoCore/Models/SimulationComponent/Data/Engine/EngineFullLoadCurve.cs index 5d21f7b858..5f3b04d0c7 100644 --- a/VectoCore/Models/SimulationComponent/Data/Engine/EngineFullLoadCurve.cs +++ b/VectoCore/Models/SimulationComponent/Data/Engine/EngineFullLoadCurve.cs @@ -16,8 +16,9 @@ using System; using System.Collections.Generic; -using System.ComponentModel.DataAnnotations; using System.Data; +using System.Diagnostics.Contracts; +using System.Dynamic; using System.Linq; using TUGraz.VectoCore.Utils; @@ -33,15 +34,53 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Data.Engine private PerSecond _engineSpeedHi; // 70% of Pmax private PerSecond _n95hSpeed; // 95% of Pmax - [Required] + public static EngineFullLoadCurve ReadFromFile(string fileName, bool declarationMode = false) + { + var curve = FullLoadCurve.ReadFromFile(fileName, declarationMode, true); + return new EngineFullLoadCurve { FullLoadEntries = curve.FullLoadEntries, PT1Data = curve.PT1Data }; + } + + public static EngineFullLoadCurve Create(DataTable data, bool declarationMode = false) + { + var curve = FullLoadCurve.Create(data, declarationMode, true); + return new EngineFullLoadCurve() { FullLoadEntries = curve.FullLoadEntries, PT1Data = curve.PT1Data }; + } + + public Watt FullLoadStationaryPower(PerSecond angularVelocity) + { + return Formulas.TorqueToPower(FullLoadStationaryTorque(angularVelocity), angularVelocity); + } + + public Watt DragLoadStationaryPower(PerSecond angularVelocity) + { + Contract.Requires(angularVelocity.HasEqualUnit(new SI().Radian.Per.Second)); + Contract.Ensures(Contract.Result<SI>().HasEqualUnit(new SI().Watt)); + + return Formulas.TorqueToPower(DragLoadStationaryTorque(angularVelocity), angularVelocity); + } + + public CombustionEngineData EngineData { get; internal set; } + + public Second PT1(PerSecond angularVelocity) + { + return PT1Data.Lookup(angularVelocity); + } + + /// <summary> /// Get the engine's preferred speed from the given full-load curve (i.e. Speed at 51% torque/speed-integral between idling and N95h.) /// </summary> public PerSecond PreferredSpeed { - get { return _preferredSpeed ?? (_preferredSpeed = ComputePreferredSpeed()); } + get + { + if (_preferredSpeed == null) { + ComputePreferredSpeed(); + } + return _preferredSpeed; + } } public PerSecond N95hSpeed @@ -49,6 +88,7 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Data.Engine get { return _n95hSpeed ?? (_n95hSpeed = FindEngineSpeedForPower(0.95 * MaxPower).Last()); } } + public PerSecond LoSpeed { get { return _engineSpeedLo ?? (_engineSpeedLo = FindEngineSpeedForPower(0.55 * MaxPower).First()); } @@ -59,6 +99,7 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Data.Engine get { return _engineSpeedHi ?? (_engineSpeedHi = FindEngineSpeedForPower(0.7 * MaxPower).Last()); } } + public NewtonMeter MaxLoadTorque { get { return FullLoadEntries.Max(x => x.TorqueFullLoad); } @@ -69,44 +110,8 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Data.Engine get { return FullLoadEntries.Min(x => x.TorqueDrag); } } - /// <summary> - /// Reads the EngineFullLoadCurve from a csv file. - /// </summary> - /// <param name="fileName">Name of the file.</param> - /// <param name="declarationMode">if set to <c>true</c> then the file is read in declaration mode.</param> - public new static EngineFullLoadCurve ReadFromFile(string fileName, bool declarationMode = false) - { - var curve = FullLoadCurve.ReadFromFile(fileName, declarationMode); - return new EngineFullLoadCurve { FullLoadEntries = curve.FullLoadEntries, PT1Data = curve.PT1Data }; - } - - /// <summary> - /// Creates the FullLoadCurve from a datatable. - /// </summary> - /// <param name="data">The data.</param> - /// <param name="declarationMode">if set to <c>true</c> then the file is read in declaration mode.</param> - public new static EngineFullLoadCurve Create(DataTable data, bool declarationMode = false) - { - var curve = FullLoadCurve.Create(data, declarationMode); - return new EngineFullLoadCurve() { FullLoadEntries = curve.FullLoadEntries, PT1Data = curve.PT1Data }; - } - - public Watt FullLoadStationaryPower(PerSecond angularVelocity) - { - return Formulas.TorqueToPower(FullLoadStationaryTorque(angularVelocity), angularVelocity); - } - - public Watt DragLoadStationaryPower(PerSecond angularVelocity) - { - return DragLoadStationaryTorque(angularVelocity) * angularVelocity; - } - - public Second PT1(PerSecond angularVelocity) - { - return PT1Data.Lookup(angularVelocity); - } - private PerSecond ComputePreferredSpeed() + private void ComputePreferredSpeed() { var maxArea = ComputeArea(EngineData.IdleSpeed, N95hSpeed); @@ -116,12 +121,12 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Data.Engine var additionalArea = ComputeArea(FullLoadEntries[idx - 1].EngineSpeed, FullLoadEntries[idx].EngineSpeed); if (area + additionalArea > 0.51 * maxArea) { var deltaArea = 0.51 * maxArea - area; - return ComputeEngineSpeedForSegmentArea(FullLoadEntries[idx - 1], FullLoadEntries[idx], deltaArea); + _preferredSpeed = ComputeEngineSpeedForSegmentArea(FullLoadEntries[idx - 1], FullLoadEntries[idx], deltaArea); + return; } area += additionalArea; } Log.Warn("Could not compute preferred speed, check FullLoadCurve! N95h: {0}, maxArea: {1}", N95hSpeed, maxArea); - return null; } private PerSecond ComputeEngineSpeedForSegmentArea(FullLoadCurveEntry p1, FullLoadCurveEntry p2, Watt area) @@ -145,7 +150,7 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Data.Engine return retVal.First(x => x >= p1.EngineSpeed && x <= p2.EngineSpeed).SI<PerSecond>(); } - private IEnumerable<PerSecond> FindEngineSpeedForPower(Watt power) + private List<PerSecond> FindEngineSpeedForPower(Watt power) { var retVal = new List<PerSecond>(); for (var idx = 1; idx < FullLoadEntries.Count; idx++) { @@ -156,7 +161,7 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Data.Engine return retVal; } - private IEnumerable<PerSecond> FindEngineSpeedForPower(FullLoadCurveEntry p1, FullLoadCurveEntry p2, Watt power) + private List<PerSecond> FindEngineSpeedForPower(FullLoadCurveEntry p1, FullLoadCurveEntry p2, Watt power) { var k = (p2.TorqueFullLoad - p1.TorqueFullLoad) / (p2.EngineSpeed - p1.EngineSpeed); var d = p2.TorqueFullLoad - k * p2.EngineSpeed; diff --git a/VectoCore/Models/SimulationComponent/Data/FullLoadCurve.cs b/VectoCore/Models/SimulationComponent/Data/FullLoadCurve.cs index 40832e2e42..9fe9f82d58 100644 --- a/VectoCore/Models/SimulationComponent/Data/FullLoadCurve.cs +++ b/VectoCore/Models/SimulationComponent/Data/FullLoadCurve.cs @@ -53,21 +53,27 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Data get { return _maxPower ?? ComputeRatedSpeed().Item2; } } - public static FullLoadCurve ReadFromFile(string fileName, bool declarationMode = false) + public static FullLoadCurve ReadFromFile(string fileName, bool declarationMode = false, bool engineFld = false) { try { var data = VectoCSVFile.Read(fileName); - return Create(data, declarationMode); + return Create(data, declarationMode, engineFld); } catch (Exception ex) { throw new VectoException("ERROR while reading FullLoadCurve File: " + ex.Message); } } - public static FullLoadCurve Create(DataTable data, bool declarationMode = false) + public static FullLoadCurve Create(DataTable data, bool declarationMode = false, bool engineFld = false) { - if (data.Columns.Count < 3) { - throw new VectoException("FullLoadCurve Data File must consist of at least 3 columns."); + if (engineFld) { + if (data.Columns.Count < 3) { + throw new VectoException("Engine FullLoadCurve Data File must consist of at least 3 columns."); + } + } else { + if (data.Columns.Count < 2) { + throw new VectoException("Gearbox FullLoadCurve Data File must consist of at least 2 columns."); + } } if (data.Rows.Count < 2) { @@ -76,8 +82,8 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Data } List<FullLoadCurveEntry> entriesFld; - if (HeaderIsValid(data.Columns)) { - entriesFld = CreateFromColumnNames(data); + if (HeaderIsValid(data.Columns, engineFld)) { + entriesFld = CreateFromColumnNames(data, engineFld); } else { Logger<FullLoadCurve>().Warn( "FullLoadCurve: Header Line is not valid. Expected: '{0}, {1}, {2}', Got: '{3}'. Falling back to column index.", @@ -85,7 +91,7 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Data Fields.TorqueDrag, string.Join(", ", data.Columns.Cast<DataColumn>().Select(c => c.ColumnName))); - entriesFld = CreateFromColumnIndizes(data); + entriesFld = CreateFromColumnIndizes(data, engineFld); } LookupData<PerSecond, Second> tmp; @@ -98,30 +104,30 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Data return new FullLoadCurve { FullLoadEntries = entriesFld, PT1Data = tmp }; } - private static bool HeaderIsValid(DataColumnCollection columns) + private static bool HeaderIsValid(DataColumnCollection columns, bool engineFld) { return columns.Contains(Fields.EngineSpeed) - && columns.Contains(Fields.TorqueDrag) - && columns.Contains(Fields.TorqueFullLoad); + && columns.Contains(Fields.TorqueFullLoad) + && (!engineFld || columns.Contains(Fields.TorqueDrag)); } - private static List<FullLoadCurveEntry> CreateFromColumnNames(DataTable data) + private static List<FullLoadCurveEntry> CreateFromColumnNames(DataTable data, bool engineFld) { return (from DataRow row in data.Rows select new FullLoadCurveEntry { EngineSpeed = row.ParseDouble(Fields.EngineSpeed).RPMtoRad(), TorqueFullLoad = row.ParseDouble(Fields.TorqueFullLoad).SI<NewtonMeter>(), - TorqueDrag = row.ParseDouble(Fields.TorqueDrag).SI<NewtonMeter>() + TorqueDrag = (engineFld ? row.ParseDouble(Fields.TorqueDrag).SI<NewtonMeter>() : null) }).ToList(); } - private static List<FullLoadCurveEntry> CreateFromColumnIndizes(DataTable data) + private static List<FullLoadCurveEntry> CreateFromColumnIndizes(DataTable data, bool engineFld) { return (from DataRow row in data.Rows select new FullLoadCurveEntry { EngineSpeed = row.ParseDouble(0).RPMtoRad(), TorqueFullLoad = row.ParseDouble(1).SI<NewtonMeter>(), - TorqueDrag = row.ParseDouble(2).SI<NewtonMeter>() + TorqueDrag = (engineFld ? row.ParseDouble(2).SI<NewtonMeter>() : null) }).ToList(); } -- GitLab