From 2d7586f5d27941c690ba4d7a5c0ae5abb7bedbb4 Mon Sep 17 00:00:00 2001 From: Markus Quaritsch <markus.quaritsch@tugraz.at> Date: Thu, 21 Jul 2016 16:09:08 +0200 Subject: [PATCH] separate reading input data into independent classes --- .../ComponentData/AccelerationCurveReader.cs | 95 ++++++++++++++ .../CrossWindCorrectionCurveReader.cs | 0 .../ComponentData/RetarderLossMapReader.cs | 94 +++++++++++++ .../TorqueConverterDataReader.cs | 76 +++++++++++ .../TransmissionLossMapReader.cs | 124 ++++++++++++++++++ .../Data/AccelerationCurve.cs | 85 +----------- .../Data/Gearbox/TorqueConverterData.cs | 35 ++++- .../Data/Gearbox/TransmissionLossMap.cs | 120 ++--------------- .../Data/RetarderLossMap.cs | 89 +------------ 9 files changed, 442 insertions(+), 276 deletions(-) create mode 100644 VectoCore/VectoCore/InputData/Reader/ComponentData/AccelerationCurveReader.cs rename VectoCore/VectoCore/{Models/SimulationComponent/Data => InputData/Reader/ComponentData}/CrossWindCorrectionCurveReader.cs (100%) create mode 100644 VectoCore/VectoCore/InputData/Reader/ComponentData/RetarderLossMapReader.cs create mode 100644 VectoCore/VectoCore/InputData/Reader/ComponentData/TorqueConverterDataReader.cs create mode 100644 VectoCore/VectoCore/InputData/Reader/ComponentData/TransmissionLossMapReader.cs diff --git a/VectoCore/VectoCore/InputData/Reader/ComponentData/AccelerationCurveReader.cs b/VectoCore/VectoCore/InputData/Reader/ComponentData/AccelerationCurveReader.cs new file mode 100644 index 0000000000..1319d7c684 --- /dev/null +++ b/VectoCore/VectoCore/InputData/Reader/ComponentData/AccelerationCurveReader.cs @@ -0,0 +1,95 @@ +using System; +using System.Collections.Generic; +using System.Data; +using System.IO; +using System.Linq; +using TUGraz.VectoCommon.Exceptions; +using TUGraz.VectoCommon.Models; +using TUGraz.VectoCommon.Utils; +using TUGraz.VectoCore.Utils; + +namespace TUGraz.VectoCore.Models.SimulationComponent.Data +{ + public class AccelerationCurveReader + { + public static AccelerationCurveData ReadFromStream(Stream stream) + { + var data = VectoCSVFile.ReadStream(stream); + return Create(data); + } + + public static AccelerationCurveData ReadFromFile(string fileName) + { + try { + var data = VectoCSVFile.Read(fileName); + return Create(data); + } catch (Exception ex) { + throw new VectoException("ERROR while reading AccelerationCurve File: " + ex.Message); + } + } + + internal static AccelerationCurveData Create(DataTable data) + { + if (data.Columns.Count != 3) { + throw new VectoException("Acceleration Limiting File must consist of 3 columns."); + } + + if (data.Rows.Count < 2) { + throw new VectoException("Acceleration Limiting File must consist of at least two entries."); + } + + if (HeaderIsValid(data.Columns)) { + return CreateFromColumnNames(data); + } + LoggingObject.Logger<AccelerationCurveData>() + .Warn("Acceleration Curve: Header Line is not valid. Expected: '{0}, {1}, {2}', Got: {3}", + Fields.Velocity, AccelerationCurveReader.Fields.Acceleration, + Fields.Deceleration, + ", ".Join(data.Columns.Cast<DataColumn>().Select(c => c.ColumnName))); + return CreateFromColumnIndizes(data); + } + + private static AccelerationCurveData CreateFromColumnIndizes(DataTable data) + { + return new AccelerationCurveData(data.Rows.Cast<DataRow>() + .Select(r => new KeyValuePair<MeterPerSecond, AccelerationCurveData.AccelerationEntry>( + r.ParseDouble(0).KMPHtoMeterPerSecond(), + new AccelerationCurveData.AccelerationEntry { + Acceleration = r.ParseDouble(1).SI<MeterPerSquareSecond>(), + Deceleration = r.ParseDouble(2).SI<MeterPerSquareSecond>() + })) + .OrderBy(x => x.Key) + .ToList()); + } + + private static AccelerationCurveData CreateFromColumnNames(DataTable data) + { + return new AccelerationCurveData( + data.Rows.Cast<DataRow>() + .Select(r => new KeyValuePair<MeterPerSecond, AccelerationCurveData.AccelerationEntry>( + r.ParseDouble(Fields.Velocity).KMPHtoMeterPerSecond(), + new AccelerationCurveData.AccelerationEntry { + Acceleration = r.ParseDouble(Fields.Acceleration).SI<MeterPerSquareSecond>(), + Deceleration = r.ParseDouble(Fields.Deceleration).SI<MeterPerSquareSecond>() + })) + .OrderBy(x => x.Key) + .ToList()); + } + + private static bool HeaderIsValid(DataColumnCollection columns) + { + return columns.Contains(Fields.Velocity) && + columns.Contains(Fields.Acceleration) && + columns.Contains(Fields.Deceleration); + } + + public static class Fields + { + public const string Velocity = "v"; + + public const string Acceleration = "acc"; + + public const string Deceleration = "dec"; + } + } +} \ No newline at end of file diff --git a/VectoCore/VectoCore/Models/SimulationComponent/Data/CrossWindCorrectionCurveReader.cs b/VectoCore/VectoCore/InputData/Reader/ComponentData/CrossWindCorrectionCurveReader.cs similarity index 100% rename from VectoCore/VectoCore/Models/SimulationComponent/Data/CrossWindCorrectionCurveReader.cs rename to VectoCore/VectoCore/InputData/Reader/ComponentData/CrossWindCorrectionCurveReader.cs diff --git a/VectoCore/VectoCore/InputData/Reader/ComponentData/RetarderLossMapReader.cs b/VectoCore/VectoCore/InputData/Reader/ComponentData/RetarderLossMapReader.cs new file mode 100644 index 0000000000..9cd7522be1 --- /dev/null +++ b/VectoCore/VectoCore/InputData/Reader/ComponentData/RetarderLossMapReader.cs @@ -0,0 +1,94 @@ +using System; +using System.Collections.Generic; +using System.Data; +using System.Linq; +using TUGraz.VectoCommon.Exceptions; +using TUGraz.VectoCommon.Models; +using TUGraz.VectoCommon.Utils; +using TUGraz.VectoCore.Utils; + +namespace TUGraz.VectoCore.Models.SimulationComponent.Data +{ + public class RetarderLossMapReader + { + /// <summary> + /// Read the retarder loss map from a file. + /// </summary> + /// <param name="fileName"></param> + /// <returns></returns> + public static RetarderLossMap ReadFromFile(string fileName) + { + try { + return Create(VectoCSVFile.Read(fileName)); + } catch (Exception ex) { + throw new VectoException("ERROR while loading RetarderLossMap: " + ex.Message); + } + } + + /// <summary> + /// Create the retarder loss map from an appropriate datatable. (2 columns: Retarder Speed, Torque Loss) + /// </summary> + /// <param name="data"></param> + /// <returns></returns> + public static RetarderLossMap Create(DataTable data) + { + if (data.Columns.Count != 2) { + throw new VectoException("RetarderLossMap Data File must consist of 2 columns: Retarder Speed, Torque Loss"); + } + + if (data.Rows.Count < 2) { + throw new VectoException("RetarderLossMap must contain at least 2 entries."); + } + + List<RetarderLossMap.RetarderLossEntry> entries; + if (HeaderIsValid(data.Columns)) { + entries = CreateFromColumnNames(data); + } else { + LoggingObject.Logger<RetarderLossMap>().Warn( + "RetarderLossMap: Header Line is not valid. Expected: '{0}, {1}', Got: '{2}'. Falling back to column index.", + Fields.RetarderSpeed, Fields.TorqueLoss, + ", ".Join(data.Columns.Cast<DataColumn>().Select(c => c.ColumnName).Reverse())); + entries = CreateFromColumnIndizes(data); + } + + entries.Sort((entry1, entry2) => entry1.RetarderSpeed.Value().CompareTo(entry2.RetarderSpeed.Value())); + return new RetarderLossMap(entries); + } + + private static List<RetarderLossMap.RetarderLossEntry> CreateFromColumnNames(DataTable data) + { + return data.Rows.Cast<DataRow>() + .Select(row => new RetarderLossMap.RetarderLossEntry { + RetarderSpeed = DataTableExtensionMethods.ParseDouble(row, (string)Fields.RetarderSpeed).RPMtoRad(), + TorqueLoss = DataTableExtensionMethods.ParseDouble(row, (string)Fields.TorqueLoss).SI<NewtonMeter>() + }).ToList(); + } + + private static bool HeaderIsValid(DataColumnCollection columns) + { + return columns.Contains(Fields.RetarderSpeed) && columns.Contains(Fields.TorqueLoss); + } + + private static List<RetarderLossMap.RetarderLossEntry> CreateFromColumnIndizes(DataTable data) + { + return data.Rows.Cast<DataRow>() + .Select(row => new RetarderLossMap.RetarderLossEntry { + RetarderSpeed = row.ParseDouble(0).RPMtoRad(), + TorqueLoss = row.ParseDouble(1).SI<NewtonMeter>() + }).ToList(); + } + + private static class Fields + { + /// <summary> + /// [rpm] + /// </summary> + public const string RetarderSpeed = "Retarder Speed"; + + /// <summary> + /// [Nm] + /// </summary> + public const string TorqueLoss = "Torque Loss"; + } + } +} \ No newline at end of file diff --git a/VectoCore/VectoCore/InputData/Reader/ComponentData/TorqueConverterDataReader.cs b/VectoCore/VectoCore/InputData/Reader/ComponentData/TorqueConverterDataReader.cs new file mode 100644 index 0000000000..f6deb29f19 --- /dev/null +++ b/VectoCore/VectoCore/InputData/Reader/ComponentData/TorqueConverterDataReader.cs @@ -0,0 +1,76 @@ +using System.Collections.Generic; +using System.Data; +using System.IO; +using System.Linq; +using TUGraz.VectoCommon.Exceptions; +using TUGraz.VectoCommon.Utils; +using TUGraz.VectoCore.Utils; + +namespace TUGraz.VectoCore.Models.SimulationComponent.Data.Gearbox +{ + public class TorqueConverterDataReader { + public static TorqueConverterData ReadFromFile(string filename) + { + return Create(VectoCSVFile.Read(filename)); + } + + public static TorqueConverterData ReadFromStream(Stream stream) + { + return Create(VectoCSVFile.ReadStream(stream)); + } + + public static TorqueConverterData Create(DataTable data) + { + if (data.Columns.Count != 3) { + throw new VectoException("TorqueConverter Characteristics data must consist of 3 columns"); + } + if (data.Rows.Count < 2) { + throw new VectoException("TorqueConverter Characteristics data must contain at least 2 lines with numeric values"); + } + + List<TorqueRatioCurveEntry> torqueRatio; + List<CharacteristicTorqueEntry> characteristicTorque; + if (HeaderIsValid(data.Columns)) { + torqueRatio = (from DataRow row in data.Rows + select + new TorqueRatioCurveEntry() { + SpeedRatio = DataTableExtensionMethods.ParseDouble(row, (string)Fields.SpeedRatio), + TorqueRatio = DataTableExtensionMethods.ParseDouble(row, (string)Fields.TorqueRatio) + }).ToList(); + characteristicTorque = (from DataRow row in data.Rows + select + new CharacteristicTorqueEntry() { + SpeedRatio = DataTableExtensionMethods.ParseDouble(row, (string)Fields.SpeedRatio), + Torque = DataTableExtensionMethods.ParseDouble(row, (string)Fields.CharacteristicTorque).SI<NewtonMeter>() + }).ToList(); + } else { + torqueRatio = (from DataRow row in data.Rows + select + new TorqueRatioCurveEntry() { + SpeedRatio = row.ParseDouble(0), + TorqueRatio = row.ParseDouble(1) + }).ToList(); + characteristicTorque = (from DataRow row in data.Rows + select + new CharacteristicTorqueEntry() { + SpeedRatio = row.ParseDouble(0), + Torque = row.ParseDouble(2).SI<NewtonMeter>() + }).ToList(); + } + return new TorqueConverterData(torqueRatio, characteristicTorque); + } + + private static bool HeaderIsValid(DataColumnCollection columns) + { + return columns.Contains(Fields.SpeedRatio) && columns.Contains(Fields.TorqueRatio) && + columns.Contains(Fields.CharacteristicTorque); + } + + public static class Fields + { + public const string SpeedRatio = "Speed Ratio"; + public const string TorqueRatio = "Torque Ratio"; + public const string CharacteristicTorque = "MP1000"; + } + } +} \ No newline at end of file diff --git a/VectoCore/VectoCore/InputData/Reader/ComponentData/TransmissionLossMapReader.cs b/VectoCore/VectoCore/InputData/Reader/ComponentData/TransmissionLossMapReader.cs new file mode 100644 index 0000000000..ca761e29df --- /dev/null +++ b/VectoCore/VectoCore/InputData/Reader/ComponentData/TransmissionLossMapReader.cs @@ -0,0 +1,124 @@ +using System; +using System.Collections.Generic; +using System.Data; +using System.Linq; +using TUGraz.VectoCommon.Exceptions; +using TUGraz.VectoCommon.Models; +using TUGraz.VectoCommon.Utils; +using TUGraz.VectoCore.Utils; + +namespace TUGraz.VectoCore.Models.SimulationComponent.Data.Gearbox +{ + public sealed class TransmissionLossMapReader + { + public static TransmissionLossMap ReadFromFile(string fileName, double gearRatio, string gearName) + { + try { + var data = VectoCSVFile.Read(fileName, true); + return Create(data, gearRatio, gearName); + } catch (Exception ex) { + throw new VectoException("ERROR while reading TransmissionLossMap: " + ex.Message); + } + } + + /// <summary> + /// Create a TransmissionLoss Map from a DataTable. + /// </summary> + /// <param name="data"></param> + /// <param name="gearRatio"></param> + /// <param name="gearName"></param> + /// <returns></returns> + public static TransmissionLossMap Create(DataTable data, double gearRatio, string gearName) + { + if (data.Columns.Count < 3) { + throw new VectoException("TransmissionLossMap Data File for {0} must consist of at least 3 columns.", gearName); + } + + if (data.Rows.Count < 4) { + throw new VectoException( + "TransmissionLossMap for {0} must consist of at least four lines with numeric values (below file header", gearName); + } + + List<TransmissionLossMap.GearLossMapEntry> entries; + if (HeaderIsValid(data.Columns)) { + entries = CreateFromColumnNames(data); + } else { + LoggingObject.Logger<TransmissionLossMap>().Warn( + "TransmissionLossMap {5}: Header line is not valid. Expected: '{0}, {1}, {2}, <{3}>'. Got: '{4}'. Falling back to column index.", + TransmissionLossMapReader.Fields.InputSpeed, TransmissionLossMapReader.Fields.InputTorque, + TransmissionLossMapReader.Fields.TorqeLoss, TransmissionLossMapReader.Fields.Efficiency, + ", ".Join(data.Columns.Cast<DataColumn>().Select(c => c.ColumnName).Reverse()), gearName); + + entries = CreateFromColumIndizes(data); + } + + return new TransmissionLossMap(entries, gearRatio, gearName); + } + + /// <summary> + /// Create a DataTable from an efficiency value. + /// </summary> + /// <param name="efficiency"></param> + /// <param name="gearRatio"></param> + /// <param name="gearName"></param> + /// <returns></returns> + public static TransmissionLossMap Create(double efficiency, double gearRatio, string gearName) + { + var entries = new List<TransmissionLossMap.GearLossMapEntry> { + new TransmissionLossMap.GearLossMapEntry(0.RPMtoRad(), 1e5.SI<NewtonMeter>(), + (1 - efficiency) * 1e5.SI<NewtonMeter>()), + new TransmissionLossMap.GearLossMapEntry(0.RPMtoRad(), -1e5.SI<NewtonMeter>(), + (1 - efficiency) * 1e5.SI<NewtonMeter>()), + new TransmissionLossMap.GearLossMapEntry(0.RPMtoRad(), 0.SI<NewtonMeter>(), 0.SI<NewtonMeter>()), + new TransmissionLossMap.GearLossMapEntry(5000.RPMtoRad(), 0.SI<NewtonMeter>(), 0.SI<NewtonMeter>()), + new TransmissionLossMap.GearLossMapEntry(5000.RPMtoRad(), -1e5.SI<NewtonMeter>(), + (1 - efficiency) * 1e5.SI<NewtonMeter>()), + new TransmissionLossMap.GearLossMapEntry(5000.RPMtoRad(), 1e5.SI<NewtonMeter>(), + (1 - efficiency) * 1e5.SI<NewtonMeter>()), + }; + return new TransmissionLossMap(entries, gearRatio, gearName); + } + + private static bool HeaderIsValid(DataColumnCollection columns) + { + return columns.Contains(TransmissionLossMapReader.Fields.InputSpeed) && + columns.Contains(TransmissionLossMapReader.Fields.InputTorque) && + columns.Contains(TransmissionLossMapReader.Fields.TorqeLoss); + } + + private static List<TransmissionLossMap.GearLossMapEntry> CreateFromColumnNames(DataTable data) + { + return (from DataRow row in data.Rows + select new TransmissionLossMap.GearLossMapEntry( + inputSpeed: row.ParseDouble(Fields.InputSpeed).RPMtoRad(), + inputTorque: row.ParseDouble(Fields.InputTorque).SI<NewtonMeter>(), + torqueLoss: row.ParseDouble(Fields.TorqeLoss).SI<NewtonMeter>())) + .ToList(); + } + + private static List<TransmissionLossMap.GearLossMapEntry> CreateFromColumIndizes(DataTable data) + { + return (from DataRow row in data.Rows + select new TransmissionLossMap.GearLossMapEntry( + inputSpeed: row.ParseDouble(0).RPMtoRad(), + inputTorque: row.ParseDouble(1).SI<NewtonMeter>(), + torqueLoss: row.ParseDouble(2).SI<NewtonMeter>())) + .ToList(); + } + + public static class Fields + { + /// <summary>[rpm]</summary> + public const string InputSpeed = "Input Speed"; + + /// <summary>[Nm]</summary> + public const string InputTorque = "Input Torque"; + + /// <summary>[Nm]</summary> + public const string TorqeLoss = "Torque Loss"; + + /// <summary>[-]</summary> + public const string Efficiency = "Eff"; + } + } +} \ No newline at end of file diff --git a/VectoCore/VectoCore/Models/SimulationComponent/Data/AccelerationCurve.cs b/VectoCore/VectoCore/Models/SimulationComponent/Data/AccelerationCurve.cs index ca50bfcc17..e8053c20ea 100644 --- a/VectoCore/VectoCore/Models/SimulationComponent/Data/AccelerationCurve.cs +++ b/VectoCore/VectoCore/Models/SimulationComponent/Data/AccelerationCurve.cs @@ -43,86 +43,18 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Data { public class AccelerationCurveData : SimulationComponentData { - private List<KeyValuePair<MeterPerSecond, AccelerationEntry>> _entries; + private readonly List<KeyValuePair<MeterPerSecond, AccelerationEntry>> _entries; - public static AccelerationCurveData ReadFromStream(Stream stream) + protected internal AccelerationCurveData(List<KeyValuePair<MeterPerSecond, AccelerationEntry>> entries) { - var data = VectoCSVFile.ReadStream(stream); - return Create(data); - } - - public static AccelerationCurveData ReadFromFile(string fileName) - { - try { - var data = VectoCSVFile.Read(fileName); - return Create(data); - } catch (Exception ex) { - throw new VectoException("ERROR while reading AccelerationCurve File: " + ex.Message); - } - } - - internal static AccelerationCurveData Create(DataTable data) - { - if (data.Columns.Count != 3) { - throw new VectoException("Acceleration Limiting File must consist of 3 columns."); - } - - if (data.Rows.Count < 2) { - throw new VectoException("Acceleration Limiting File must consist of at least two entries."); - } - - if (HeaderIsValid(data.Columns)) { - return CreateFromColumnNames(data); - } - Logger<AccelerationCurveData>() - .Warn("Acceleration Curve: Header Line is not valid. Expected: '{0}, {1}, {2}', Got: {3}", - Fields.Velocity, Fields.Acceleration, Fields.Deceleration, - ", ".Join(data.Columns.Cast<DataColumn>().Select(c => c.ColumnName))); - return CreateFromColumnIndizes(data); - } - - private static AccelerationCurveData CreateFromColumnIndizes(DataTable data) - { - return new AccelerationCurveData { - _entries = data.Rows.Cast<DataRow>() - .Select(r => new KeyValuePair<MeterPerSecond, AccelerationEntry>( - r.ParseDouble(0).KMPHtoMeterPerSecond(), - new AccelerationEntry { - Acceleration = r.ParseDouble(1).SI<MeterPerSquareSecond>(), - Deceleration = r.ParseDouble(2).SI<MeterPerSquareSecond>() - })) - .OrderBy(x => x.Key) - .ToList() - }; - } - - private static AccelerationCurveData CreateFromColumnNames(DataTable data) - { - return new AccelerationCurveData { - _entries = data.Rows.Cast<DataRow>() - .Select(r => new KeyValuePair<MeterPerSecond, AccelerationEntry>( - r.ParseDouble(Fields.Velocity).KMPHtoMeterPerSecond(), - new AccelerationEntry { - Acceleration = r.ParseDouble(Fields.Acceleration).SI<MeterPerSquareSecond>(), - Deceleration = r.ParseDouble(Fields.Deceleration).SI<MeterPerSquareSecond>() - })) - .OrderBy(x => x.Key) - .ToList() - }; - } - - private static bool HeaderIsValid(DataColumnCollection columns) - { - return columns.Contains(Fields.Velocity) && - columns.Contains(Fields.Acceleration) && - columns.Contains(Fields.Deceleration); + _entries = entries; } public AccelerationEntry Lookup(MeterPerSecond key) { var index = FindIndex(key); - return new AccelerationEntry { + return new AccelerationCurveData.AccelerationEntry { Acceleration = VectoMath.Interpolate(_entries[index - 1].Key, _entries[index].Key, _entries[index - 1].Value.Acceleration, @@ -234,14 +166,5 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Data var t = Math.Log(((v2 * k + d) / (v1 * k + d)).Cast<Scalar>()) / k; return m / k * Math.Exp((k * t).Value()) + b * t + c; } - - private static class Fields - { - public const string Velocity = "v"; - - public const string Acceleration = "acc"; - - public const string Deceleration = "dec"; - } } } \ No newline at end of file diff --git a/VectoCore/VectoCore/Models/SimulationComponent/Data/Gearbox/TorqueConverterData.cs b/VectoCore/VectoCore/Models/SimulationComponent/Data/Gearbox/TorqueConverterData.cs index cd32910fff..237c80718c 100644 --- a/VectoCore/VectoCore/Models/SimulationComponent/Data/Gearbox/TorqueConverterData.cs +++ b/VectoCore/VectoCore/Models/SimulationComponent/Data/Gearbox/TorqueConverterData.cs @@ -29,7 +29,40 @@ * Martin Rexeis, rexeis@ivt.tugraz.at, IVT, Graz University of Technology */ +using System.Collections.Generic; +using System.Data; +using System.IO; +using System.Linq; +using iTextSharp.text.pdf.codec; +using TUGraz.VectoCommon.Exceptions; +using TUGraz.VectoCommon.Utils; +using TUGraz.VectoCore.Utils; + namespace TUGraz.VectoCore.Models.SimulationComponent.Data.Gearbox { - public class TorqueConverterData {} + public class TorqueConverterData + { + public List<TorqueRatioCurveEntry> TorqueRatio; + public List<CharacteristicTorqueEntry> CharacteristicTorque; + + protected internal TorqueConverterData(List<TorqueRatioCurveEntry> torqueRatio, + List<CharacteristicTorqueEntry> characteristicTorque) + { + TorqueRatio = torqueRatio; + CharacteristicTorque = characteristicTorque; + } + } + + + public class CharacteristicTorqueEntry + { + public double SpeedRatio; + public NewtonMeter Torque; + } + + public class TorqueRatioCurveEntry + { + public double SpeedRatio; + public double TorqueRatio; + } } \ No newline at end of file diff --git a/VectoCore/VectoCore/Models/SimulationComponent/Data/Gearbox/TransmissionLossMap.cs b/VectoCore/VectoCore/Models/SimulationComponent/Data/Gearbox/TransmissionLossMap.cs index 91c7fc84a5..90441ee4d8 100644 --- a/VectoCore/VectoCore/Models/SimulationComponent/Data/Gearbox/TransmissionLossMap.cs +++ b/VectoCore/VectoCore/Models/SimulationComponent/Data/Gearbox/TransmissionLossMap.cs @@ -45,7 +45,7 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Data.Gearbox { public sealed class TransmissionLossMap : LoggingObject { - [ValidateObject] private readonly List<GearLossMapEntry> _entries; + [ValidateObject] private readonly IReadOnlyList<GearLossMapEntry> _entries; private readonly double _ratio; @@ -59,103 +59,9 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Data.Gearbox /// </summary> private readonly DelaunayMap _invertedLossMap; - public void DrawGraph() - { - _lossMap.DrawGraph(); - } - public string GearName { get; private set; } - public static TransmissionLossMap ReadFromFile(string fileName, double gearRatio, string gearName) - { - try { - var data = VectoCSVFile.Read(fileName, true); - return Create(data, gearRatio, gearName); - } catch (Exception ex) { - throw new VectoException("ERROR while reading TransmissionLossMap: " + ex.Message); - } - } - - /// <summary> - /// Create a TransmissionLoss Map from a DataTable. - /// </summary> - /// <param name="data"></param> - /// <param name="gearRatio"></param> - /// <param name="gearName"></param> - /// <returns></returns> - public static TransmissionLossMap Create(DataTable data, double gearRatio, string gearName) - { - if (data.Columns.Count < 3) { - throw new VectoException("TransmissionLossMap Data File for {0} must consist of at least 3 columns.", gearName); - } - - if (data.Rows.Count < 4) { - throw new VectoException( - "TransmissionLossMap for {0} must consist of at least four lines with numeric values (below file header", gearName); - } - - List<GearLossMapEntry> entries; - if (HeaderIsValid(data.Columns)) { - entries = CreateFromColumnNames(data); - } else { - Logger<TransmissionLossMap>().Warn( - "TransmissionLossMap {5}: Header line is not valid. Expected: '{0}, {1}, {2}, <{3}>'. Got: '{4}'. Falling back to column index.", - Fields.InputSpeed, Fields.InputTorque, Fields.TorqeLoss, Fields.Efficiency, - ", ".Join(data.Columns.Cast<DataColumn>().Select(c => c.ColumnName).Reverse()), gearName); - - entries = CreateFromColumIndizes(data); - } - - return new TransmissionLossMap(entries, gearRatio, gearName); - } - - /// <summary> - /// Create a DataTable from an efficiency value. - /// </summary> - /// <param name="efficiency"></param> - /// <param name="gearRatio"></param> - /// <param name="gearName"></param> - /// <returns></returns> - public static TransmissionLossMap Create(double efficiency, double gearRatio, string gearName) - { - var entries = new List<GearLossMapEntry> { - new GearLossMapEntry(0.RPMtoRad(), 1e5.SI<NewtonMeter>(), (1 - efficiency) * 1e5.SI<NewtonMeter>()), - new GearLossMapEntry(0.RPMtoRad(), -1e5.SI<NewtonMeter>(), (1 - efficiency) * 1e5.SI<NewtonMeter>()), - new GearLossMapEntry(0.RPMtoRad(), 0.SI<NewtonMeter>(), 0.SI<NewtonMeter>()), - new GearLossMapEntry(5000.RPMtoRad(), 0.SI<NewtonMeter>(), 0.SI<NewtonMeter>()), - new GearLossMapEntry(5000.RPMtoRad(), -1e5.SI<NewtonMeter>(), (1 - efficiency) * 1e5.SI<NewtonMeter>()), - new GearLossMapEntry(5000.RPMtoRad(), 1e5.SI<NewtonMeter>(), (1 - efficiency) * 1e5.SI<NewtonMeter>()), - }; - return new TransmissionLossMap(entries, gearRatio, gearName); - } - - private static bool HeaderIsValid(DataColumnCollection columns) - { - return columns.Contains(Fields.InputSpeed) && columns.Contains(Fields.InputTorque) && - columns.Contains(Fields.TorqeLoss); - } - - private static List<GearLossMapEntry> CreateFromColumnNames(DataTable data) - { - return (from DataRow row in data.Rows - select new GearLossMapEntry( - inputSpeed: row.ParseDouble(Fields.InputSpeed).RPMtoRad(), - inputTorque: row.ParseDouble(Fields.InputTorque).SI<NewtonMeter>(), - torqueLoss: row.ParseDouble(Fields.TorqeLoss).SI<NewtonMeter>())) - .ToList(); - } - - private static List<GearLossMapEntry> CreateFromColumIndizes(DataTable data) - { - return (from DataRow row in data.Rows - select new GearLossMapEntry( - inputSpeed: row.ParseDouble(0).RPMtoRad(), - inputTorque: row.ParseDouble(1).SI<NewtonMeter>(), - torqueLoss: row.ParseDouble(2).SI<NewtonMeter>())) - .ToList(); - } - - private TransmissionLossMap(List<GearLossMapEntry> entries, double gearRatio, string gearName) + public TransmissionLossMap(IReadOnlyList<GearLossMapEntry> entries, double gearRatio, string gearName) { GearName = gearName; _ratio = gearRatio; @@ -181,7 +87,7 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Data.Gearbox /// <returns>Torque loss as seen on input side (towards the engine).</returns> public LossMapResult GetTorqueLoss(PerSecond outAngularVelocity, NewtonMeter outTorque) { - var result = new LossMapResult(); + var result = new TransmissionLossMap.LossMapResult(); var torqueLoss = _lossMap.Interpolate(outAngularVelocity.ConvertTo().Rounds.Per.Minute.Value() * _ratio, outTorque.Value() / _ratio); @@ -233,6 +139,11 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Data.Gearbox get { return _entries[i]; } } + public void DrawGraph() + { + _lossMap.DrawGraph(); + } + [DebuggerDisplay("GearLossMapEntry({InputSpeed}, {InputTorque}, {TorqueLoss})")] public class GearLossMapEntry { @@ -252,20 +163,5 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Data.Gearbox TorqueLoss = torqueLoss; } } - - private static class Fields - { - /// <summary>[rpm]</summary> - public const string InputSpeed = "Input Speed"; - - /// <summary>[Nm]</summary> - public const string InputTorque = "Input Torque"; - - /// <summary>[Nm]</summary> - public const string TorqeLoss = "Torque Loss"; - - /// <summary>[-]</summary> - public const string Efficiency = "Eff"; - } } } \ No newline at end of file diff --git a/VectoCore/VectoCore/Models/SimulationComponent/Data/RetarderLossMap.cs b/VectoCore/VectoCore/Models/SimulationComponent/Data/RetarderLossMap.cs index 1b50887eb0..319f5b3e94 100644 --- a/VectoCore/VectoCore/Models/SimulationComponent/Data/RetarderLossMap.cs +++ b/VectoCore/VectoCore/Models/SimulationComponent/Data/RetarderLossMap.cs @@ -45,10 +45,15 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Data /// </summary> public class RetarderLossMap : SimulationComponentData { - [ValidateObject] private List<RetarderLossEntry> _entries; + [ValidateObject] private readonly IReadOnlyList<RetarderLossEntry> _entries; private PerSecond _minSpeed; private PerSecond _maxSpeed; + protected internal RetarderLossMap(List<RetarderLossEntry> entries) + { + _entries = entries; + } + /// <summary> /// Gets the minimal defined speed of the retarder loss map. /// </summary> @@ -65,50 +70,6 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Data get { return _maxSpeed ?? (_maxSpeed = _entries.Max(e => e.RetarderSpeed)); } } - /// <summary> - /// Read the retarder loss map from a file. - /// </summary> - /// <param name="fileName"></param> - /// <returns></returns> - public static RetarderLossMap ReadFromFile(string fileName) - { - try { - return Create(VectoCSVFile.Read(fileName)); - } catch (Exception ex) { - throw new VectoException("ERROR while loading RetarderLossMap: " + ex.Message); - } - } - - /// <summary> - /// Create the retarder loss map from an appropriate datatable. (2 columns: Retarder Speed, Torque Loss) - /// </summary> - /// <param name="data"></param> - /// <returns></returns> - public static RetarderLossMap Create(DataTable data) - { - if (data.Columns.Count != 2) { - throw new VectoException("RetarderLossMap Data File must consist of 2 columns: Retarder Speed, Torque Loss"); - } - - if (data.Rows.Count < 2) { - throw new VectoException("RetarderLossMap must contain at least 2 entries."); - } - - List<RetarderLossEntry> entries; - if (HeaderIsValid(data.Columns)) { - entries = CreateFromColumnNames(data); - } else { - Logger<RetarderLossMap>().Warn( - "RetarderLossMap: Header Line is not valid. Expected: '{0}, {1}', Got: '{2}'. Falling back to column index.", - Fields.RetarderSpeed, Fields.TorqueLoss, - ", ".Join(data.Columns.Cast<DataColumn>().Select(c => c.ColumnName).Reverse())); - entries = CreateFromColumnIndizes(data); - } - - entries.Sort((entry1, entry2) => entry1.RetarderSpeed.Value().CompareTo(entry2.RetarderSpeed.Value())); - return new RetarderLossMap { _entries = entries }; - } - /// <summary> /// Calculates the retarder losses. /// </summary> @@ -121,30 +82,7 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Data angularVelocity); } - private static List<RetarderLossEntry> CreateFromColumnNames(DataTable data) - { - return data.Rows.Cast<DataRow>() - .Select(row => new RetarderLossEntry { - RetarderSpeed = row.ParseDouble(Fields.RetarderSpeed).RPMtoRad(), - TorqueLoss = row.ParseDouble(Fields.TorqueLoss).SI<NewtonMeter>() - }).ToList(); - } - - private static bool HeaderIsValid(DataColumnCollection columns) - { - return columns.Contains(Fields.RetarderSpeed) && columns.Contains(Fields.TorqueLoss); - } - - private static List<RetarderLossEntry> CreateFromColumnIndizes(DataTable data) - { - return data.Rows.Cast<DataRow>() - .Select(row => new RetarderLossEntry { - RetarderSpeed = row.ParseDouble(0).RPMtoRad(), - TorqueLoss = row.ParseDouble(1).SI<NewtonMeter>() - }).ToList(); - } - - private class RetarderLossEntry + public class RetarderLossEntry { [Required, SIRange(0, double.MaxValue)] public PerSecond RetarderSpeed { get; set; } @@ -152,18 +90,5 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Data [Required, SIRange(0, 500)] public NewtonMeter TorqueLoss { get; set; } } - - private static class Fields - { - /// <summary> - /// [rpm] - /// </summary> - public const string RetarderSpeed = "Retarder Speed"; - - /// <summary> - /// [Nm] - /// </summary> - public const string TorqueLoss = "Torque Loss"; - } } } \ No newline at end of file -- GitLab