From 1bf55295fcc73dd428d043a760400d60ac6b163e Mon Sep 17 00:00:00 2001 From: Markus Quaritsch <markus.quaritsch@tugraz.at> Date: Mon, 7 May 2018 11:08:32 +0200 Subject: [PATCH] add logging of warnings in vtp cycle to report, adapt calculation of FC-Limits --- VectoCommon/VectoCommon/Utils/SI.cs | 2 + .../Utils/SIConvertExtensionMethods.cs | 226 +++++++++--------- .../Models/Declaration/DeclarationData.cs | 4 +- .../SimulationComponent/Impl/VTPCycle.cs | 40 ++-- .../VectoCore/OutputData/XML/XMLVTPReport.cs | 41 ++++ 5 files changed, 183 insertions(+), 130 deletions(-) diff --git a/VectoCommon/VectoCommon/Utils/SI.cs b/VectoCommon/VectoCommon/Utils/SI.cs index ed8559e923..d8158aaf5e 100644 --- a/VectoCommon/VectoCommon/Utils/SI.cs +++ b/VectoCommon/VectoCommon/Utils/SI.cs @@ -894,6 +894,8 @@ namespace TUGraz.VectoCommon.Utils private static readonly int[] Units = { 0, -2,2, 0, 0, 0, 0 }; private SpecificFuelConsumption(double val) : base(val, Units) { } + + public override string UnitString { get { return "kg/Ws"; } } } /// <summary> diff --git a/VectoCommon/VectoCommon/Utils/SIConvertExtensionMethods.cs b/VectoCommon/VectoCommon/Utils/SIConvertExtensionMethods.cs index 29d55faca6..17a38dc03b 100644 --- a/VectoCommon/VectoCommon/Utils/SIConvertExtensionMethods.cs +++ b/VectoCommon/VectoCommon/Utils/SIConvertExtensionMethods.cs @@ -34,16 +34,16 @@ using System.Globalization; namespace TUGraz.VectoCommon.Utils { - public class ConvertedSI - { - private readonly double _value; - public string Units { get; } + public class ConvertedSI + { + private readonly double _value; + public string Units { get; } - public ConvertedSI(double value, string units) - { - _value = value; - Units = units; - } + public ConvertedSI(double value, string units) + { + _value = value; + Units = units; + } public double Value { get { return _value; } } @@ -71,25 +71,25 @@ namespace TUGraz.VectoCommon.Utils } public static implicit operator double(ConvertedSI self) - { - return self._value; - } - - public static implicit operator ConvertedSI(SI self) - { - return self == null ? null : new ConvertedSI(self.Value(), self.UnitString); - } - - public override string ToString() - { - // todo mk2017-10-13: decimal places? - return _value.ToString(CultureInfo.InvariantCulture); // + " [" + _units + "]"; - } - - public object ToString(CultureInfo invariantCulture) - { - throw new NotImplementedException(); - } + { + return self._value; + } + + public static implicit operator ConvertedSI(SI self) + { + return self == null ? null : new ConvertedSI(self.Value(), self.UnitString); + } + + public override string ToString() + { + // todo mk2017-10-13: decimal places? + return _value.ToString(CultureInfo.InvariantCulture); // + " [" + _units + "]"; + } + + public object ToString(CultureInfo invariantCulture) + { + throw new NotImplementedException(); + } public string ToOutputFormat(uint? decimals = null, double? outputFactor = null, bool? showUnit = null) { @@ -106,27 +106,27 @@ namespace TUGraz.VectoCommon.Utils } } - public static class SIConvertExtensionMethods - { - private const int Kilo = 1000; - private const int SecondsPerHour = 60 * 60; - - public static ConvertedSI ConvertToGramm(this Kilogram value) - { - return new ConvertedSI(value.Value() * Kilo, "g"); - } - public static ConvertedSI ConvertToTon(this Kilogram value) - { - return new ConvertedSI(value.Value() / Kilo, "t"); - } - public static ConvertedSI ConvertToKiloMeterPerHour(this MeterPerSecond value) - { - return new ConvertedSI(value.Value() * SecondsPerHour / Kilo, "km/h"); - } - public static ConvertedSI ConvertToGrammPerKiloMeter(this KilogramPerMeter value) - { - return value == null ? null : new ConvertedSI(value.Value() * Kilo * Kilo, "g/km"); - } + public static class SIConvertExtensionMethods + { + private const int Kilo = 1000; + private const int SecondsPerHour = 60 * 60; + + public static ConvertedSI ConvertToGramm(this Kilogram value) + { + return new ConvertedSI(value.Value() * Kilo, "g"); + } + public static ConvertedSI ConvertToTon(this Kilogram value) + { + return new ConvertedSI(value.Value() / Kilo, "t"); + } + public static ConvertedSI ConvertToKiloMeterPerHour(this MeterPerSecond value) + { + return new ConvertedSI(value.Value() * SecondsPerHour / Kilo, "km/h"); + } + public static ConvertedSI ConvertToGrammPerKiloMeter(this KilogramPerMeter value) + { + return value == null ? null : new ConvertedSI(value.Value() * Kilo * Kilo, "g/km"); + } public static ConvertedSI ConvertToGramPerKiloWattHour(this SpecificFuelConsumption value) { @@ -135,72 +135,72 @@ namespace TUGraz.VectoCommon.Utils public static ConvertedSI ConvertToLiterPer100Kilometer(this VolumePerMeter value) - { - return value == null ? null : new ConvertedSI(value.Value() * (10*10*10) * (100*1000), "l/100km"); - } - - public static ConvertedSI ConvertToLiterPer100TonKiloMeter(this VolumePerMeterMass value) - { - const int CubicMeterToLiter = 10 * 10 * 10; - const int MeterTo100KiloMeter = 100 * Kilo; - const int KilogrammToTon = Kilo; - - return value == null ? null : new ConvertedSI(value.Value() * CubicMeterToLiter * (MeterTo100KiloMeter * KilogrammToTon), "l/100tkm"); - } + { + return value == null ? null : new ConvertedSI(value.Value() * (10*10*10) * (100*1000), "l/100km"); + } + + public static ConvertedSI ConvertToLiterPer100TonKiloMeter(this VolumePerMeterMass value) + { + const int CubicMeterToLiter = 10 * 10 * 10; + const int MeterTo100KiloMeter = 100 * Kilo; + const int KilogrammToTon = Kilo; + + return value == null ? null : new ConvertedSI(value.Value() * CubicMeterToLiter * (MeterTo100KiloMeter * KilogrammToTon), "l/100tkm"); + } public static ConvertedSI ConvertToLiterPerCubicMeter100KiloMeter(this VolumePerMeterVolume value) - { - const int CubicMeterToLiter = 10 * 10 * 10; - const int MeterTo100KiloMeter = 100 * Kilo; - return new ConvertedSI(value.Value() * CubicMeterToLiter * MeterTo100KiloMeter, "l/100m^3km"); - } - - public static ConvertedSI ConvertToGrammPerHour(this KilogramPerSecond value) - { - return new ConvertedSI(value.Value() * Kilo * SecondsPerHour, "g/h"); - } - - public static ConvertedSI ConvertToKiloMeter(this Meter value) - { - return new ConvertedSI(value.Value() / Kilo, "km"); - } - - public static ConvertedSI ConvertToCubicCentiMeter(this CubicMeter value) - { - return new ConvertedSI(value.Value() * 100 * 100 * 100, "cm^3"); - } - - public static ConvertedSI ConvertToGrammPerCubicMeterKiloMeter(this KilogramPerMeterCubicMeter value) - { - return new ConvertedSI(value.Value() * Kilo * Kilo, "g/m^3km"); - } - - public static ConvertedSI ConvertToGrammPerTonKilometer(this KilogramPerMeterMass value) - { - return new ConvertedSI(value.Value() * Kilo * Kilo * Kilo, "g/tkm"); - } - - public static ConvertedSI ConvertToKiloWattHour(this WattSecond value) - { - return new ConvertedSI(value.Value() / Kilo / SecondsPerHour, "kWh"); - } - public static ConvertedSI ConvertToKiloWatt(this Watt value) - { - return new ConvertedSI(value.Value() / Kilo, "kW"); - } - - public static ConvertedSI ConvertToRoundsPerMinute(this PerSecond value) - { - return new ConvertedSI(value.AsRPM, "rpm"); - } - public static ConvertedSI ConvertToCubicDeziMeter(this CubicMeter value) - { - return new ConvertedSI(value.Value() * 10 * 10 * 10, "dm^3"); - } - public static ConvertedSI ConvertToMilliMeter(this Meter value) - { - return new ConvertedSI(value.Value() * Kilo, "mm"); - } + { + const int CubicMeterToLiter = 10 * 10 * 10; + const int MeterTo100KiloMeter = 100 * Kilo; + return new ConvertedSI(value.Value() * CubicMeterToLiter * MeterTo100KiloMeter, "l/100m^3km"); + } + + public static ConvertedSI ConvertToGrammPerHour(this KilogramPerSecond value) + { + return new ConvertedSI(value.Value() * Kilo * SecondsPerHour, "g/h"); + } + + public static ConvertedSI ConvertToKiloMeter(this Meter value) + { + return new ConvertedSI(value.Value() / Kilo, "km"); + } + + public static ConvertedSI ConvertToCubicCentiMeter(this CubicMeter value) + { + return new ConvertedSI(value.Value() * 100 * 100 * 100, "cm^3"); + } + + public static ConvertedSI ConvertToGrammPerCubicMeterKiloMeter(this KilogramPerMeterCubicMeter value) + { + return new ConvertedSI(value.Value() * Kilo * Kilo, "g/m^3km"); + } + + public static ConvertedSI ConvertToGrammPerTonKilometer(this KilogramPerMeterMass value) + { + return new ConvertedSI(value.Value() * Kilo * Kilo * Kilo, "g/tkm"); + } + + public static ConvertedSI ConvertToKiloWattHour(this WattSecond value) + { + return new ConvertedSI(value.Value() / Kilo / SecondsPerHour, "kWh"); + } + public static ConvertedSI ConvertToKiloWatt(this Watt value) + { + return new ConvertedSI(value.Value() / Kilo, "kW"); + } + + public static ConvertedSI ConvertToRoundsPerMinute(this PerSecond value) + { + return new ConvertedSI(value.AsRPM, "rpm"); + } + public static ConvertedSI ConvertToCubicDeziMeter(this CubicMeter value) + { + return new ConvertedSI(value.Value() * 10 * 10 * 10, "dm^3"); + } + public static ConvertedSI ConvertToMilliMeter(this Meter value) + { + return new ConvertedSI(value.Value() * Kilo, "mm"); + } public static ConvertedSI ConvertToMegaJoulePerKilogram(this JoulePerKilogramm value) { diff --git a/VectoCore/VectoCore/Models/Declaration/DeclarationData.cs b/VectoCore/VectoCore/Models/Declaration/DeclarationData.cs index 44cda17332..cb8017175c 100644 --- a/VectoCore/VectoCore/Models/Declaration/DeclarationData.cs +++ b/VectoCore/VectoCore/Models/Declaration/DeclarationData.cs @@ -524,8 +524,8 @@ namespace TUGraz.VectoCore.Models.Declaration public static readonly Second SamplingInterval = 0.5.SI<Second>(); - public static readonly KilogramPerSecond LowerFCThreshold = 180.SI(Unit.SI.Gramm.Per.Hour).Cast<KilogramPerSecond>(); - public static readonly KilogramPerSecond UpperFCThreshold = 600.SI(Unit.SI.Gramm.Per.Hour).Cast<KilogramPerSecond>(); + public static readonly SpecificFuelConsumption LowerFCThreshold = 180.SI(Unit.SI.Gramm.Per.Kilo.Watt.Hour).Cast<SpecificFuelConsumption>(); + public static readonly SpecificFuelConsumption UpperFCThreshold = 600.SI(Unit.SI.Gramm.Per.Kilo.Watt.Hour).Cast<SpecificFuelConsumption>(); public static readonly Second FCAccumulationWindow = 10.SI(Unit.SI.Minute).Cast<Second>(); } } diff --git a/VectoCore/VectoCore/Models/SimulationComponent/Impl/VTPCycle.cs b/VectoCore/VectoCore/Models/SimulationComponent/Impl/VTPCycle.cs index 7735c430b6..5f75ce6edf 100644 --- a/VectoCore/VectoCore/Models/SimulationComponent/Impl/VTPCycle.cs +++ b/VectoCore/VectoCore/Models/SimulationComponent/Impl/VTPCycle.cs @@ -53,10 +53,10 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl public override IResponse Initialize() { + PrepareCycleData(); if (DataBus.ExecutionMode == ExecutionMode.Declaration) { VerifyInputData(); } - PrepareCycleData(); SelectStartGear(); return base.Initialize(); } @@ -100,24 +100,34 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl private void VerifyFCInput() { var idx = 0L; - int count = Convert.ToInt32(DeclarationData.VTPMode.FCAccumulationWindow / DeclarationData.VTPMode.SamplingInterval); - var sum = 0.SI<Kilogram>(); - var window = 0.SI<Kilogram>().Repeat(count).ToArray(); + var count = Convert.ToInt32(DeclarationData.VTPMode.FCAccumulationWindow / DeclarationData.VTPMode.SamplingInterval); + var sumFC= 0.SI<Kilogram>(); + var sumEWheel = 0.SI<WattSecond>(); + + var window = new {FC = 0.SI<Kilogram>(), EWheel = 0.SI<WattSecond>()}.Repeat(count).ToArray(); foreach (var entry in Data.Entries.Pairwise()) { - var fc = entry.Item1.Fuelconsumption * (entry.Item2.Time - entry.Item1.Time); - window[idx % count] = fc; - sum += window[idx % count]; - sum -= window[(idx + 1) % count]; - if (idx >= count && sum < DeclarationData.VTPMode.LowerFCThreshold * DeclarationData.VTPMode.FCAccumulationWindow) { - Log.Error("Fuel consumption for the previous {0} below threshold of {1}. t: {2}, FC: {3}", DeclarationData.VTPMode.FCAccumulationWindow.ConvertToMinutes(), - DeclarationData.VTPMode.LowerFCThreshold.ConvertToGrammPerHour(), entry.Item1.Time, (sum / DeclarationData.VTPMode.FCAccumulationWindow).ConvertToGrammPerHour()); + var dt = entry.Item2.Time - entry.Item1.Time; + var fc = entry.Item1.Fuelconsumption * dt; + var eWheel = entry.Item1.PWheel > 0 ? entry.Item1.PWheel * dt : 0.SI<WattSecond>(); + window[idx % count] = new {FC= fc, EWheel = eWheel}; + sumFC += window[idx % count].FC; + sumFC -= window[(idx + 1) % count].FC; + sumEWheel += window[idx % count].EWheel; + sumEWheel -= window[(idx + 1) % count].EWheel; + idx++; + + if (sumEWheel.IsSmaller(1.SI(Unit.SI.Kilo.Watt.Hour))) { + continue; } - if (idx >= count && sum > DeclarationData.VTPMode.UpperFCThreshold * DeclarationData.VTPMode.FCAccumulationWindow) { - Log.Error("Fuel consumption for the previous {0} above threshold of {1}. t: {2}, FC: {3}", DeclarationData.VTPMode.FCAccumulationWindow.ConvertToMinutes(), - DeclarationData.VTPMode.UpperFCThreshold.ConvertToGrammPerHour(), entry.Item1.Time, (sum / DeclarationData.VTPMode.FCAccumulationWindow).ConvertToGrammPerHour()); + if (sumFC / sumEWheel < DeclarationData.VTPMode.LowerFCThreshold ) { + Log.Error("Fuel consumption for the previous {0} [min] below threshold of {1} [g/kWh]. t: {2} [s], FC: {3} [g/kWh]", DeclarationData.VTPMode.FCAccumulationWindow.ConvertToMinutes(), + DeclarationData.VTPMode.LowerFCThreshold.ConvertToGramPerKiloWattHour(), entry.Item1.Time, (sumFC / sumEWheel).ConvertToGramPerKiloWattHour()); + } + if (sumFC / sumEWheel > DeclarationData.VTPMode.UpperFCThreshold) { + Log.Error("Fuel consumption for the previous {0} [min] above threshold of {1} [g/kWh]. t: {2} [s], FC: {3} [g/kWh]", DeclarationData.VTPMode.FCAccumulationWindow.ConvertToMinutes(), + DeclarationData.VTPMode.UpperFCThreshold.ConvertToGramPerKiloWattHour(), entry.Item1.Time, (sumFC / sumEWheel).ConvertToGramPerKiloWattHour()); } - idx++; } } diff --git a/VectoCore/VectoCore/OutputData/XML/XMLVTPReport.cs b/VectoCore/VectoCore/OutputData/XML/XMLVTPReport.cs index 70ed49896a..e059e1f316 100644 --- a/VectoCore/VectoCore/OutputData/XML/XMLVTPReport.cs +++ b/VectoCore/VectoCore/OutputData/XML/XMLVTPReport.cs @@ -3,6 +3,8 @@ using System.Collections.Generic; using System.Linq; using System.Xml; using System.Xml.Linq; +using NLog.Config; +using NLog.Targets; using TUGraz.IVT.VectoXML.Writer; using TUGraz.VectoCommon.Hashing; using TUGraz.VectoCommon.InputData; @@ -17,6 +19,9 @@ using TUGraz.VectoCore.Models.SimulationComponent.Data; using TUGraz.VectoCore.Models.SimulationComponent.Data.Gearbox; using TUGraz.VectoCore.Utils; using TUGraz.VectoHashing; +using NLog; +using TUGraz.VectoCore.Models.SimulationComponent.Impl; +using LogManager = NLog.LogManager; namespace TUGraz.VectoCore.OutputData.XML { @@ -24,6 +29,8 @@ namespace TUGraz.VectoCore.OutputData.XML { public const string CURRENT_SCHEMA_VERSION = "0.1"; + private const string VTPReportTartetName = "VTPReportTarget"; + protected XElement VehiclePart; protected XElement GeneralPart; protected XElement DataIntegrityPart; @@ -34,6 +41,8 @@ namespace TUGraz.VectoCore.OutputData.XML protected XNamespace tns; private IOutputDataWriter _writer; + private static List<string> LogList = new List<string>(); + private LoggingRule cycleChecksRule; //protected XNamespace di; //private bool allSuccess = true; @@ -87,8 +96,32 @@ namespace TUGraz.VectoCore.OutputData.XML Results = new XElement(tns + "Results"); _writer = writer; + + + AddLogging(); } + private void AddLogging() + { + LogList.Clear(); + var target = new MethodCallTarget { + ClassName = typeof(XMLVTPReport).AssemblyQualifiedName, + MethodName = "LogMethod" + }; + target.Parameters.Add(new MethodCallParameter("${level}")); + target.Parameters.Add(new MethodCallParameter("${message}")); + var config = LogManager.Configuration; + cycleChecksRule = new LoggingRule(typeof(VTPCycle).FullName, LogLevel.Error, target); + config.AddTarget(VTPReportTartetName, target); + config.LoggingRules.Add(cycleChecksRule); + LogManager.Configuration.Reload(); + } + + // ReSharper disable once UnusedMember.Global -- see AddLogging Method + public static void LogMethod(string level, string message) + { + LogList.Add(message); + } #region Overrides of DeclarationReport<ResultEntry> @@ -100,6 +133,11 @@ namespace TUGraz.VectoCore.OutputData.XML protected internal override void DoWriteReport() { + var config = LogManager.Configuration; + config.LoggingRules.Remove(cycleChecksRule); + config.RemoveTarget(VTPReportTartetName); + LogManager.Configuration.Reload(); + GenerateResults(); var report = GenerateReport(); @@ -170,6 +208,9 @@ namespace TUGraz.VectoCore.OutputData.XML ) ), new XElement(tns + "VTRatio", cVtp.ToXMLFormat(4))); + if (LogList.Any()) { + Results.Add(new XElement(tns + "Warnings", LogList.Select(x => new XElement(tns + "Warning", x)))); + } } private XDocument GenerateReport() -- GitLab