From ce8b38add50b47e482a1ee00ec15107dee85411a Mon Sep 17 00:00:00 2001 From: Michael Krisper <michael.krisper@tugraz.at> Date: Tue, 31 May 2016 13:22:30 +0200 Subject: [PATCH] gear calculation in 1Hz mode --- .../Utils/EnumberableExtensionMethods.cs | 20 +++++++ .../Models/Simulation/Data/ModalResult.cs | 3 +- .../OutputData/ModalDataContainer.cs | 54 +++++++++++-------- .../Utils/DictionaryExtensionMethods.cs | 12 ++++- VectoCore/VectoCore/Utils/SwitchExtension.cs | 6 +++ 5 files changed, 69 insertions(+), 26 deletions(-) diff --git a/VectoCommon/VectoCommon/Utils/EnumberableExtensionMethods.cs b/VectoCommon/VectoCommon/Utils/EnumberableExtensionMethods.cs index e201aff1d9..d60a984f40 100644 --- a/VectoCommon/VectoCommon/Utils/EnumberableExtensionMethods.cs +++ b/VectoCommon/VectoCommon/Utils/EnumberableExtensionMethods.cs @@ -189,6 +189,26 @@ namespace TUGraz.VectoCommon.Utils } } + public static TSource MaxBy<TSource>(this IEnumerable<TSource> source, + Func<TSource, IComparable> projectionToComparable) + { + using (var e = source.GetEnumerator()) { + if (!e.MoveNext()) { + throw new InvalidOperationException("Sequence is empty."); + } + var max = e.Current; + var maxProjection = projectionToComparable(e.Current); + + while (e.MoveNext()) { + var currentProjection = projectionToComparable(e.Current); + if (currentProjection.CompareTo(maxProjection) > 0) { + max = e.Current; + maxProjection = currentProjection; + } + } + return max; + } + } public static IEnumerable<TResult> Pairwise<TSource, TResult>(this IEnumerable<TSource> source, Func<TSource, TSource, TResult> resultSelector) diff --git a/VectoCore/VectoCore/Models/Simulation/Data/ModalResult.cs b/VectoCore/VectoCore/Models/Simulation/Data/ModalResult.cs index 4c98903fd6..912f7cad86 100644 --- a/VectoCore/VectoCore/Models/Simulation/Data/ModalResult.cs +++ b/VectoCore/VectoCore/Models/Simulation/Data/ModalResult.cs @@ -53,7 +53,7 @@ namespace TUGraz.VectoCore.Models.Simulation.Data public const string ShowUnit = "showUnit"; } - protected ModalResults(SerializationInfo info, StreamingContext context) : base(info, context){} + protected ModalResults(SerializationInfo info, StreamingContext context) : base(info, context) {} public ModalResults() { @@ -332,7 +332,6 @@ namespace TUGraz.VectoCore.Models.Simulation.Data [ModalResultField(typeof(SI), name: "ds [m]")] simulationDistance, - [ModalResultField(typeof(double), caption: "AA_NonSmartAlternatorsEfficiency [%]")] AA_NonSmartAlternatorsEfficiency, [ModalResultField(typeof(SI), caption: "AA_SmartIdleCurrent_Amps [A]")] AA_SmartIdleCurrent_Amps, [ModalResultField(typeof(double), caption: "AA_SmartIdleAlternatorsEfficiency [%]")] AA_SmartIdleAlternatorsEfficiency, diff --git a/VectoCore/VectoCore/OutputData/ModalDataContainer.cs b/VectoCore/VectoCore/OutputData/ModalDataContainer.cs index 15e38a591d..c994b0f011 100644 --- a/VectoCore/VectoCore/OutputData/ModalDataContainer.cs +++ b/VectoCore/VectoCore/OutputData/ModalDataContainer.cs @@ -271,27 +271,31 @@ namespace TUGraz.VectoCore.OutputData var remainingDt = 0.SI<Second>(); object[] remainingRow = null; + var gearsList = new Dictionary<object, Second>(3); foreach (DataRow row in data.Rows) { var currentDt = row.Field<Second>((int)ModalResultField.simulationInterval); - // if remaining + current >= 1: split current row and add remaining row. - // 1) take full remaining row - // 2) split current row on difference to next full second - // 3) continue with remaining time on current row + // if current + remaining time >= 1 second: take remaining row and split up currentRow to fill up 1 second. if (remainingDt > 0 && remainingDt + currentDt >= 1) { var diffDt = 1.SI<Second>() - remainingDt; var r = results.NewRow(); + + var gear = row[(int)ModalResultField.Gear]; + gearsList[gear] = gearsList.GetValueOrZero(gear) + diffDt; + r.ItemArray = AddRow(remainingRow, MultiplyRow(row.ItemArray, diffDt)); absTime += diffDt; r[(int)ModalResultField.time] = absTime; r[(int)ModalResultField.simulationInterval] = 1.SI<Second>(); + r[(int)ModalResultField.Gear] = gearsList.MaxBy(kv => kv.Value).Key; + gearsList.Clear(); results.Rows.Add(r); currentDt = VectoMath.Max(remainingDt + currentDt - 1.SI<Second>(), 0.SI<Second>()); remainingDt = 0.SI<Second>(); } - // split current Row until dt < 1 + // if current row still longer than 1 second: split it to 1 second slices until it is < 1 second while (currentDt >= 1) { currentDt = currentDt - 1.SI<Second>(); var r = results.NewRow(); @@ -302,49 +306,55 @@ namespace TUGraz.VectoCore.OutputData results.Rows.Add(r); } - // normalize rest of the remaining row if dt > 0 for summation of next row + // if the there still is something left in current row: add the weighted values to remainder-buffer if (currentDt > 0) { - if (remainingDt > 0) - remainingRow = AddRow(remainingRow, MultiplyRow(row.ItemArray, currentDt)); - else - remainingRow = MultiplyRow(row.ItemArray, currentDt); + var gear = row[(int)ModalResultField.Gear]; + gearsList[gear] = gearsList.GetValueOrZero(gear) + currentDt; + + remainingRow = AddRow(remainingRow, MultiplyRow(row.ItemArray, currentDt)); remainingDt += currentDt; absTime += currentDt; } else { remainingRow = null; remainingDt = 0.SI<Second>(); + gearsList.Clear(); } } // if last row was not enough to full second: take last row as whole second - if (remainingDt >= 0) { + if (remainingDt > 0) { var r = results.NewRow(); - r.ItemArray = MultiplyRow(remainingRow, 1 / remainingDt); + r.ItemArray = remainingRow; r[(int)ModalResultField.time] = VectoMath.Ceiling(absTime); r[(int)ModalResultField.simulationInterval] = 1.SI<Second>(); + r[(int)ModalResultField.Gear] = gearsList.MaxBy(kv => kv.Value).Key; results.Rows.Add(r); } return results; } - private static object[] MultiplyRow(IEnumerable<object> row, SI dt) + private static IEnumerable<object> MultiplyRow(IEnumerable<object> row, SI dt) { return row.Select(val => { - if (val is SI) { - val = (val as SI) * dt.Value(); - } else - val.Switch() - .Case<int>(i => val = i * dt.Value()) - .Case<double>(d => val = d * dt.Value()) - .Case<float>(f => val = f * dt.Value()) - .Case<uint>(ui => val = ui * dt.Value()); + val.Switch() + .Case<SI>(si => val = si * dt.Value()) + .Case<int>(i => val = i * dt.Value()) + .Case<double>(d => val = d * dt.Value()) + .Case<float>(f => val = f * dt.Value()) + .Case<uint>(ui => val = ui * dt.Value()); return val; - }).ToArray(); + }); } private static object[] AddRow(IEnumerable<object> row, IEnumerable<object> addRow) { + if (row == null) { + return addRow.ToArray(); + } + if (addRow == null) { + return row.ToArray(); + } return row.ZipAll(addRow, (val, addVal) => { val.Switch() .Case<SI>(si => val = si + (SI)addVal) diff --git a/VectoCore/VectoCore/Utils/DictionaryExtensionMethods.cs b/VectoCore/VectoCore/Utils/DictionaryExtensionMethods.cs index 5b901e91ed..f32c59dd05 100644 --- a/VectoCore/VectoCore/Utils/DictionaryExtensionMethods.cs +++ b/VectoCore/VectoCore/Utils/DictionaryExtensionMethods.cs @@ -31,15 +31,23 @@ using System; using System.Collections.Generic; +using TUGraz.VectoCommon.Utils; namespace TUGraz.VectoCore.Utils { internal static class DictionaryExtensionMethods { - public static object GetValueOrNull<TKey, TValue>(this IDictionary<TKey, TValue> dictionary,TKey key) + public static object GetValueOrNull<TKey, TValue>(this IDictionary<TKey, TValue> dictionary, TKey key) { TValue value; return dictionary.TryGetValue(key, out value) ? (object)value : DBNull.Value; } + + public static TValue GetValueOrZero<TKey, TValue>(this IDictionary<TKey, TValue> dictionary, TKey key) + where TValue : SIBase<TValue> + { + TValue value; + return dictionary.TryGetValue(key, out value) ? value : 0.SI<TValue>(); + } } -} +} \ No newline at end of file diff --git a/VectoCore/VectoCore/Utils/SwitchExtension.cs b/VectoCore/VectoCore/Utils/SwitchExtension.cs index 936dd629dc..be4d29ad28 100644 --- a/VectoCore/VectoCore/Utils/SwitchExtension.cs +++ b/VectoCore/VectoCore/Utils/SwitchExtension.cs @@ -31,6 +31,7 @@ using System; using System.Diagnostics; +using TUGraz.VectoCommon.Utils; namespace TUGraz.VectoCore.Utils { @@ -120,5 +121,10 @@ namespace TUGraz.VectoCore.Utils action(_value); } } + + public Switch<T> Case(Func<object, bool> action, Func<object, SI> func) + { + throw new NotImplementedException(); + } } } \ No newline at end of file -- GitLab