From 687c5f3805134ada130bbce16f491e5c1bfe1017 Mon Sep 17 00:00:00 2001 From: Michael Krisper <michael.krisper@tugraz.at> Date: Mon, 11 Jul 2016 15:15:08 +0200 Subject: [PATCH] simplified retarder loss map, documented code --- .../Data/RetarderLossMap.cs | 102 +++++++++--------- 1 file changed, 51 insertions(+), 51 deletions(-) diff --git a/VectoCore/VectoCore/Models/SimulationComponent/Data/RetarderLossMap.cs b/VectoCore/VectoCore/Models/SimulationComponent/Data/RetarderLossMap.cs index fc8b6904e8..1b50887eb0 100644 --- a/VectoCore/VectoCore/Models/SimulationComponent/Data/RetarderLossMap.cs +++ b/VectoCore/VectoCore/Models/SimulationComponent/Data/RetarderLossMap.cs @@ -40,29 +40,58 @@ using TUGraz.VectoCore.Utils; namespace TUGraz.VectoCore.Models.SimulationComponent.Data { + /// <summary> + /// LossMap for retarder. + /// </summary> public class RetarderLossMap : SimulationComponentData { [ValidateObject] private List<RetarderLossEntry> _entries; + private PerSecond _minSpeed; + private PerSecond _maxSpeed; + /// <summary> + /// Gets the minimal defined speed of the retarder loss map. + /// </summary> + public PerSecond MinSpeed + { + get { return _minSpeed ?? (_minSpeed = _entries.Min(e => e.RetarderSpeed)); } + } + + /// <summary> + /// Gets the maximal defined speed of the retarder loss map. + /// </summary> + public PerSecond MaxSpeed + { + 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 { - DataTable data; - data = VectoCSVFile.Read(fileName); - return Create(data); + 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."); + 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 consist of at least two entries."); + throw new VectoException("RetarderLossMap must contain at least 2 entries."); } List<RetarderLossEntry> entries; @@ -75,55 +104,27 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Data ", ".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 }; } - public NewtonMeter RetarderLoss(PerSecond angularVelocity, bool allowExtrapolation) + /// <summary> + /// Calculates the retarder losses. + /// </summary> + /// <param name="angularVelocity"></param> + /// <returns></returns> + public NewtonMeter RetarderLoss(PerSecond angularVelocity) { - if (angularVelocity < _entries.First().RetarderSpeed) { - if (!allowExtrapolation) { - throw new VectoSimulationException("angular velocity {0} below min. entry in retarder loss map ({1})", - angularVelocity, _entries.First().RetarderSpeed); - } - Log.Warn("Extrapolating retarder losses! Angular velocity {0} below min. entry in retarder loss map ({1})", - angularVelocity, _entries.First().RetarderSpeed); - } - if (angularVelocity > _entries.Last().RetarderSpeed) { - if (!allowExtrapolation) { - throw new VectoSimulationException("angular velocity {0} above max. entry in retarder loss map ({1})", - angularVelocity, _entries.Last().RetarderSpeed); - } - Log.Warn("Extrapolating retarder losses! Angular velocity {0} above max. entry in retarder loss map ({1})", - angularVelocity, _entries.Last().RetarderSpeed); - } - - var idx = FindIndex(angularVelocity); - return VectoMath.Interpolate(_entries[idx - 1].RetarderSpeed, _entries[idx].RetarderSpeed, - _entries[idx - 1].TorqueLoss, _entries[idx].TorqueLoss, angularVelocity); - } - - protected int FindIndex(PerSecond angularVelocity) - { - int idx; - if (angularVelocity < _entries[0].RetarderSpeed) { - Log.Info("requested rpm below minimum rpm in retarder loss map - extrapolating. n_eng_avg: {0}, rpm_min: {1}", - angularVelocity.ConvertTo().Rounds.Per.Minute, - _entries[0].RetarderSpeed.ConvertTo().Rounds.Per.Minute); - idx = 1; - } else { - idx = _entries.FindIndex(x => x.RetarderSpeed > angularVelocity); - } - if (idx <= 0) { - idx = angularVelocity > _entries[0].RetarderSpeed ? _entries.Count - 1 : 1; - } - return idx; + var s = _entries.GetSection(e => e.RetarderSpeed < angularVelocity); + return VectoMath.Interpolate(s.Item1.RetarderSpeed, s.Item2.RetarderSpeed, s.Item1.TorqueLoss, s.Item2.TorqueLoss, + angularVelocity); } private static List<RetarderLossEntry> CreateFromColumnNames(DataTable data) { - return (from DataRow row in data.Rows - select new RetarderLossEntry { + return data.Rows.Cast<DataRow>() + .Select(row => new RetarderLossEntry { RetarderSpeed = row.ParseDouble(Fields.RetarderSpeed).RPMtoRad(), TorqueLoss = row.ParseDouble(Fields.TorqueLoss).SI<NewtonMeter>() }).ToList(); @@ -136,12 +137,11 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Data private static List<RetarderLossEntry> CreateFromColumnIndizes(DataTable data) { - return (from DataRow row in data.Rows - select - new RetarderLossEntry { - RetarderSpeed = row.ParseDouble(0).RPMtoRad(), - TorqueLoss = row.ParseDouble(1).SI<NewtonMeter>() - }).ToList(); + return data.Rows.Cast<DataRow>() + .Select(row => new RetarderLossEntry { + RetarderSpeed = row.ParseDouble(0).RPMtoRad(), + TorqueLoss = row.ParseDouble(1).SI<NewtonMeter>() + }).ToList(); } private class RetarderLossEntry -- GitLab