diff --git a/GraphDrawer/Program.cs b/GraphDrawer/Program.cs index 31d4120c3dac63b66ce60cbf9fe7228d6b832814..9cde53c0c72c3d218dc9ac49047fb55b564140b4 100644 --- a/GraphDrawer/Program.cs +++ b/GraphDrawer/Program.cs @@ -9,11 +9,36 @@ using System.Windows.Forms.DataVisualization.Charting; namespace GraphDrawer { - internal class Program - { - private static void Main(string[] args) - { - GraphWriter.Write(args[0], args[1]); - } - } + internal class Program + { + private const string HELP = @" +Tool for plotting graphs comparing Vecto 2.2 and Vecto 3 + +--split <leng> ... split input into parts of length <len> (in m), only distance output + +"; + + private static void Main(string[] args) + { + if (args.Contains("--split")) { + Console.WriteLine("plotting graphs splitted by distance"); + var idx = Array.FindIndex(args, x => x == "--split"); + var lenght = int.Parse(args[idx + 1]); + var success = true; + var start = 0; + do { + Console.WriteLine("plotting {0} - {1}", start / 1000, (start + lenght) / 1000); + success = GraphWriter.WriteDistanceSlice(args[0], args[1], start, start + lenght); + start += lenght; + } while (success); + Console.WriteLine("plotting full cycle"); + GraphWriter.Write(args[0], args[1]); + Console.WriteLine("done"); + return; + } + Console.WriteLine("plotting graphs..."); + GraphWriter.Write(args[0], args[1]); + Console.WriteLine("done"); + } + } } \ No newline at end of file diff --git a/VectoConsole/Program.cs b/VectoConsole/Program.cs index 64ddb2f4503283ee3338aa7ef2135420bee889d3..6172449a69ea5186b5b1fb14962949a5e7991e47 100644 --- a/VectoConsole/Program.cs +++ b/VectoConsole/Program.cs @@ -14,14 +14,14 @@ using TUGraz.VectoCore.Models.Simulation.Impl; namespace VectoConsole { - internal static class Program - { - private static int NumLines; - private static int ProgessCounter { get; set; } + internal static class Program + { + private static int NumLines; + private static int ProgessCounter { get; set; } - private const string USAGE = @"Usage: vecto.exe [-h] [-v] FILE1.vecto [FILE2.vecto ...]"; + private const string USAGE = @"Usage: vecto.exe [-h] [-v] FILE1.vecto [FILE2.vecto ...]"; - private const string HELP = @" + private const string HELP = @" Commandline Interface for Vecto. Synopsis: @@ -50,173 +50,180 @@ Examples: vecto.exe -h "; - private static int Main(string[] args) - { - try { - // on -h display help and terminate. - if (args.Contains("-h")) { - ShowVersionInformation(); - Console.Write(HELP); - return 0; - } - - // on -v: activate verbose console logger - var logLevel = LogLevel.Fatal; - - // Fatal > Error > Warn > Info > Debug > Trace - var debugEnabled = false; - - if (args.Contains("-v")) { - // display errors, warnings - logLevel = LogLevel.Warn; - debugEnabled = true; - } else if (args.Contains("-vv")) { - // also display info - logLevel = LogLevel.Info; - debugEnabled = true; - } else if (args.Contains("-vvv")) { - // display debug messages - logLevel = LogLevel.Debug; - debugEnabled = true; - } else if (args.Contains("-vvvv")) { - // display everything! - logLevel = LogLevel.Trace; - debugEnabled = true; - } - - var config = LogManager.Configuration; - //config.LoggingRules.Add(new LoggingRule("*", logLevel, config.FindTargetByName("ConsoleLogger"))); - config.LoggingRules.Add(new LoggingRule("*", logLevel, config.FindTargetByName("LogFile"))); - LogManager.Configuration = config; - Trace.Listeners.Add(new ConsoleTraceListener(true)); - - if (args.Contains("-V") || debugEnabled) { - ShowVersionInformation(); - } - - args = args.Except(new[] { "-v", "-vv", "-vvv", "-vvvv", "-V", "-mod", "-eng", "-t" }).ToArray(); - - // if no other arguments given: display usage and terminate - if (!args.Any()) { - Console.Write(USAGE); - return 1; - } - - var stopWatch = new Stopwatch(); - var timings = new Dictionary<string, double>(); - - // process the file list and start simulation - var fileList = args; - - var sumFileName = Path.Combine(Path.GetDirectoryName(fileList.First()) ?? "", - Path.GetFileNameWithoutExtension(fileList.First()) + Constants.FileExtensions.SumFile); - var sumWriter = new SummaryFileWriter(sumFileName); - var jobContainer = new JobContainer(sumWriter); - - var mode = SimulatorFactory.FactoryMode.DeclarationMode; - if (args.Contains("-eng")) { - mode = SimulatorFactory.FactoryMode.EngineeringMode; - Console.ForegroundColor = ConsoleColor.White; - Console.WriteLine("Switching to Engineering Mode. Make sure the job-file is saved in engineering mode!"); - Console.ResetColor(); - } - - Console.WriteLine("Reading Job Files"); - stopWatch.Start(); - foreach (var file in fileList.Where(f => Path.GetExtension(f) == Constants.FileExtensions.VectoJobFile)) { - var runsFactory = new SimulatorFactory(mode, file); - if (args.Contains("-mod")) { - runsFactory.WriteModalResults = true; - } - jobContainer.AddRuns(runsFactory); - } - stopWatch.Stop(); - timings.Add("Reading input files", stopWatch.Elapsed.TotalMilliseconds); - stopWatch.Reset(); - - Console.WriteLine("Starting simulation runs"); - if (debugEnabled) { - Console.ForegroundColor = ConsoleColor.White; - Console.WriteLine("Debug-Output is enabled, executing simulation runs sequentially"); - Console.ResetColor(); - } - Console.WriteLine(); - stopWatch.Start(); - jobContainer.Execute(!debugEnabled); - - Console.CancelKeyPress += (object sender, ConsoleCancelEventArgs e) => { - var isCtrlC = e.SpecialKey == ConsoleSpecialKey.ControlC; - var isCtrlBreak = e.SpecialKey == ConsoleSpecialKey.ControlBreak; - - if (isCtrlC) { - Console.WriteLine("Canceling simulation!"); - } - }; - - //var x = Console.CursorLeft; - while (!jobContainer.AllCompleted) { - PrintProgress(jobContainer.GetProgress()); - Thread.Sleep(250); - } - stopWatch.Stop(); - timings.Add("Simulation runs", stopWatch.Elapsed.TotalMilliseconds); - - PrintProgress(jobContainer.GetProgress(), args.Contains("-t")); - if (args.Contains("-t")) { - PrintTimings(timings); - } - } catch (Exception e) { - Console.Error.WriteLine(e.Message); - //Trace.TraceError(e.ToString()); - Console.ForegroundColor = ConsoleColor.Red; - Console.Error.WriteLine("Please see log-file for further details (logs/log.txt)"); - Console.ResetColor(); - Environment.ExitCode = Environment.ExitCode != 0 ? Environment.ExitCode : 1; - } - return Environment.ExitCode; - } - - private static void ShowVersionInformation() - { - var vectodll = AssemblyName.GetAssemblyName("VectoCore.dll"); - Console.WriteLine("VectoConsole: {0}", Assembly.GetExecutingAssembly().GetName().Version); - Console.WriteLine("VectoCore: {0}", vectodll.Version); - } - - private static void PrintProgress(Dictionary<string, JobContainer.ProgressEntry> progessData, bool showTiming = true) - { - Console.SetCursorPosition(0, Console.CursorTop - NumLines); - NumLines = 0; - var sumProgress = 0.0; - foreach (var progressEntry in progessData) { - if (progressEntry.Value.Success) { - Console.ForegroundColor = ConsoleColor.Green; - } else if (progressEntry.Value.Error != null) { - Console.ForegroundColor = ConsoleColor.Red; - } - var timingString = ""; - if (showTiming && progressEntry.Value.ExecTime > 0) { - timingString = string.Format("{0,9:F2}s", progressEntry.Value.ExecTime / 1000.0); - } - Console.WriteLine("{0,-60} {1,8:P}{2}", progressEntry.Key, progressEntry.Value.Progress, timingString); - Console.ResetColor(); - sumProgress += progressEntry.Value.Progress; - NumLines++; - } - sumProgress /= NumLines; - var spinner = "/-\\|"[ProgessCounter++ % 4]; - var bar = new string('#', (int)(sumProgress * 100.0 / 2)); - Console.WriteLine(string.Format(" {2} [{1,-50}] [{0,7:P}]", sumProgress, bar, spinner)); - NumLines++; - } - - private static void PrintTimings(Dictionary<string, double> timings) - { - Console.WriteLine(); - Console.WriteLine("---- timing information ----"); - foreach (var timing in timings) { - Console.WriteLine("{0,-20}: {1:F2}s", timing.Key, timing.Value / 1000); - } - } - } + private static JobContainer jobContainer; + + private static int Main(string[] args) + { + try { + // on -h display help and terminate. + if (args.Contains("-h")) { + ShowVersionInformation(); + Console.Write(HELP); + return 0; + } + + // on -v: activate verbose console logger + var logLevel = LogLevel.Fatal; + + // Fatal > Error > Warn > Info > Debug > Trace + var debugEnabled = false; + + if (args.Contains("-v")) { + // display errors, warnings + logLevel = LogLevel.Warn; + debugEnabled = true; + } else if (args.Contains("-vv")) { + // also display info + logLevel = LogLevel.Info; + debugEnabled = true; + } else if (args.Contains("-vvv")) { + // display debug messages + logLevel = LogLevel.Debug; + debugEnabled = true; + } else if (args.Contains("-vvvv")) { + // display everything! + logLevel = LogLevel.Trace; + debugEnabled = true; + } + + var config = LogManager.Configuration; + //config.LoggingRules.Add(new LoggingRule("*", logLevel, config.FindTargetByName("ConsoleLogger"))); + config.LoggingRules.Add(new LoggingRule("*", logLevel, config.FindTargetByName("LogFile"))); + LogManager.Configuration = config; + Trace.Listeners.Add(new ConsoleTraceListener(true)); + + if (args.Contains("-V") || debugEnabled) { + ShowVersionInformation(); + } + + args = args.Except(new[] { "-v", "-vv", "-vvv", "-vvvv", "-V", "-mod", "-eng", "-t" }).ToArray(); + + // if no other arguments given: display usage and terminate + if (!args.Any()) { + Console.Write(USAGE); + return 1; + } + + var stopWatch = new Stopwatch(); + var timings = new Dictionary<string, double>(); + + // process the file list and start simulation + var fileList = args; + + var sumFileName = Path.Combine(Path.GetDirectoryName(fileList.First()) ?? "", + Path.GetFileNameWithoutExtension(fileList.First()) + Constants.FileExtensions.SumFile); + var sumWriter = new SummaryFileWriter(sumFileName); + jobContainer = new JobContainer(sumWriter); + + var mode = SimulatorFactory.FactoryMode.DeclarationMode; + if (args.Contains("-eng")) { + mode = SimulatorFactory.FactoryMode.EngineeringMode; + Console.ForegroundColor = ConsoleColor.White; + Console.WriteLine( + "Switching to Engineering Mode. Make sure the job-file is saved in engineering mode!"); + Console.ResetColor(); + } + + Console.WriteLine("Reading Job Files"); + stopWatch.Start(); + foreach (var file in fileList.Where(f => Path.GetExtension(f) == Constants.FileExtensions.VectoJobFile)) { + var runsFactory = new SimulatorFactory(mode, file); + if (args.Contains("-mod")) { + runsFactory.WriteModalResults = true; + } + jobContainer.AddRuns(runsFactory); + } + stopWatch.Stop(); + timings.Add("Reading input files", stopWatch.Elapsed.TotalMilliseconds); + stopWatch.Reset(); + + Console.WriteLine("Starting simulation runs"); + if (debugEnabled) { + Console.ForegroundColor = ConsoleColor.White; + Console.WriteLine("Debug-Output is enabled, executing simulation runs sequentially"); + Console.ResetColor(); + } + Console.WriteLine(); + stopWatch.Start(); + jobContainer.Execute(!debugEnabled); + + Console.CancelKeyPress += (object sender, ConsoleCancelEventArgs e) => { + var isCtrlC = e.SpecialKey == ConsoleSpecialKey.ControlC; + var isCtrlBreak = e.SpecialKey == ConsoleSpecialKey.ControlBreak; + + if (!isCtrlC) { + return; + } + //Console.WriteLine("Canceling simulation!"); + e.Cancel = true; + Program.jobContainer.CancelCurrent(); + }; + + //var x = Console.CursorLeft; + while (!jobContainer.AllCompleted) { + PrintProgress(jobContainer.GetProgress()); + Thread.Sleep(250); + } + stopWatch.Stop(); + timings.Add("Simulation runs", stopWatch.Elapsed.TotalMilliseconds); + + PrintProgress(jobContainer.GetProgress(), args.Contains("-t")); + if (args.Contains("-t")) { + PrintTimings(timings); + } + } catch (Exception e) { + Console.Error.WriteLine(e.Message); + //Trace.TraceError(e.ToString()); + Console.ForegroundColor = ConsoleColor.Red; + Console.Error.WriteLine("Please see log-file for further details (logs/log.txt)"); + Console.ResetColor(); + Environment.ExitCode = Environment.ExitCode != 0 ? Environment.ExitCode : 1; + } + return Environment.ExitCode; + } + + private static void ShowVersionInformation() + { + var vectodll = AssemblyName.GetAssemblyName("VectoCore.dll"); + Console.WriteLine("VectoConsole: {0}", Assembly.GetExecutingAssembly().GetName().Version); + Console.WriteLine("VectoCore: {0}", vectodll.Version); + } + + private static void PrintProgress(Dictionary<string, JobContainer.ProgressEntry> progessData, + bool showTiming = true) + { + Console.SetCursorPosition(0, Console.CursorTop - NumLines); + NumLines = 0; + var sumProgress = 0.0; + foreach (var progressEntry in progessData) { + if (progressEntry.Value.Success) { + Console.ForegroundColor = ConsoleColor.Green; + } else if (progressEntry.Value.Error != null) { + Console.ForegroundColor = ConsoleColor.Red; + } + var timingString = ""; + if (showTiming && progressEntry.Value.ExecTime > 0) { + timingString = string.Format("{0,9:F2}s", progressEntry.Value.ExecTime / 1000.0); + } + Console.WriteLine("{0,-60} {1,8:P}{2}", progressEntry.Key, progressEntry.Value.Progress, timingString); + Console.ResetColor(); + sumProgress += progressEntry.Value.Progress; + NumLines++; + } + sumProgress /= NumLines; + var spinner = "/-\\|"[ProgessCounter++ % 4]; + var bar = new string('#', (int)(sumProgress * 100.0 / 2)); + Console.WriteLine(string.Format(" {2} [{1,-50}] [{0,7:P}]", sumProgress, bar, spinner)); + NumLines++; + } + + private static void PrintTimings(Dictionary<string, double> timings) + { + Console.WriteLine(); + Console.WriteLine("---- timing information ----"); + foreach (var timing in timings) { + Console.WriteLine("{0,-20}: {1:F2}s", timing.Key, timing.Value / 1000); + } + } + } } \ No newline at end of file diff --git a/VectoConsole/Properties/Version.cs b/VectoConsole/Properties/Version.cs index b36d9440a8be6660a878cbfb452b791090729d37..aa78e2c8134211088851fa33c5493e8b88518594 100644 --- a/VectoConsole/Properties/Version.cs +++ b/VectoConsole/Properties/Version.cs @@ -1,6 +1,6 @@ using System.Reflection; -// generated on 07.11.2015 21:12:54 -[assembly: AssemblyVersion("3.0.1.310")] -[assembly: AssemblyFileVersion("3.0.1.310")] +// generated on 09.11.2015 10:21:43 +[assembly: AssemblyVersion("3.0.1.312")] +[assembly: AssemblyFileVersion("3.0.1.312")] diff --git a/VectoCore/FileIO/Reader/DataObjectAdaper/DeclarationDataAdapter.cs b/VectoCore/FileIO/Reader/DataObjectAdaper/DeclarationDataAdapter.cs index e8d924479a63deb6fb4deed113a59e45bd2b8d2a..cca4596af963ce05f783a2e83ef4f819097aba2b 100644 --- a/VectoCore/FileIO/Reader/DataObjectAdaper/DeclarationDataAdapter.cs +++ b/VectoCore/FileIO/Reader/DataObjectAdaper/DeclarationDataAdapter.cs @@ -183,11 +183,13 @@ namespace TUGraz.VectoCore.FileIO.Reader.DataObjectAdaper retVal.HasTorqueConverter = false; var axleGear = gearbox.Body.Gears.First(); - var axleLossMap = TransmissionLossMap.ReadFromFile(Path.Combine(gearbox.BasePath, axleGear.LossMap), axleGear.Ratio); + var axleLossMap = TransmissionLossMap.ReadFromFile(Path.Combine(gearbox.BasePath, axleGear.LossMap), axleGear.Ratio, + "AxleGear"); retVal.AxleGearData = new GearData { LossMap = axleLossMap, Ratio = axleGear.Ratio, TorqueConverterActive = false }; retVal.Gears = gearbox.Body.Gears.Skip(1).Select((gear, i) => { - var gearLossMap = TransmissionLossMap.ReadFromFile(Path.Combine(gearbox.BasePath, gear.LossMap), gear.Ratio); + var gearLossMap = TransmissionLossMap.ReadFromFile(Path.Combine(gearbox.BasePath, gear.LossMap), gear.Ratio, + string.Format("Gear {0}", i)); var gearFullLoad = (string.IsNullOrWhiteSpace(gear.FullLoadCurve) || gear.FullLoadCurve == "<NOFILE>") ? engine.FullLoadCurve : FullLoadCurve.ReadFromFile(Path.Combine(gearbox.BasePath, gear.FullLoadCurve)); diff --git a/VectoCore/FileIO/Reader/DataObjectAdaper/EngineeringDataAdapter.cs b/VectoCore/FileIO/Reader/DataObjectAdaper/EngineeringDataAdapter.cs index e8ef2f3ce6a1729d6ed74e09241081f3d6755c45..ba80fcbb6e292140523e4859c9c70871d93d7184 100644 --- a/VectoCore/FileIO/Reader/DataObjectAdaper/EngineeringDataAdapter.cs +++ b/VectoCore/FileIO/Reader/DataObjectAdaper/EngineeringDataAdapter.cs @@ -170,7 +170,8 @@ namespace TUGraz.VectoCore.FileIO.Reader.DataObjectAdaper for (uint i = 0; i < gearbox.Body.Gears.Count; i++) { var gearSettings = gearbox.Body.Gears[(int)i]; var lossMapPath = Path.Combine(gearbox.BasePath, gearSettings.LossMap); - var lossMap = TransmissionLossMap.ReadFromFile(lossMapPath, gearSettings.Ratio); + var gearName = i == 0 ? "AxleGear" : string.Format("Gear {0}", i); + var lossMap = TransmissionLossMap.ReadFromFile(lossMapPath, gearSettings.Ratio, gearName); var shiftPolygon = !string.IsNullOrEmpty(gearSettings.ShiftPolygon) && gearSettings.ShiftPolygon != "-" && gearSettings.ShiftPolygon != "<NOFILE>" diff --git a/VectoCore/Models/LoggingObject.cs b/VectoCore/Models/LoggingObject.cs index a0199a7878f145ed447bfc3cd0981ed2ea68bf15..d1eb9209907bc908cb8416e3bdd8382e13263d09 100644 --- a/VectoCore/Models/LoggingObject.cs +++ b/VectoCore/Models/LoggingObject.cs @@ -6,9 +6,12 @@ namespace TUGraz.VectoCore.Models { protected Logger Log { get; private set; } + protected Logger GUILogger { get; private set; } + protected LoggingObject() { Log = LogManager.GetLogger(GetType().FullName); + GUILogger = LogManager.GetLogger("GUI"); } protected static Logger Logger<T>() diff --git a/VectoCore/Models/Simulation/Impl/JobContainer.cs b/VectoCore/Models/Simulation/Impl/JobContainer.cs index e25d268d6fac0a72885553c0c2c917b0ae00922b..8d7c748dbe18a2e1e4b6aeb5ecb651b009a37c0e 100644 --- a/VectoCore/Models/Simulation/Impl/JobContainer.cs +++ b/VectoCore/Models/Simulation/Impl/JobContainer.cs @@ -8,179 +8,191 @@ using TUGraz.VectoCore.Models.Simulation.Data; namespace TUGraz.VectoCore.Models.Simulation.Impl { - /// <summary> - /// Container for simulation jobs. - /// </summary> - public class JobContainer : LoggingObject - { - internal readonly List<JobEntry> Runs = new List<JobEntry>(); - private readonly SummaryFileWriter _sumWriter; - - private static int _jobNumber; - - /// <summary> - /// Initializes a new empty instance of the <see cref="JobContainer"/> class. - /// </summary> - /// <param name="sumWriter">The sum writer.</param> - public JobContainer(SummaryFileWriter sumWriter) - { - _sumWriter = sumWriter; - } - - public void AddRun(IVectoRun run) - { - _jobNumber++; - Runs.Add(new JobEntry() { - Run = run, - Container = this, - }); - } - - public void AddRuns(IEnumerable<IVectoRun> runs) - { - _jobNumber++; - //Runs.AddRange(runs); - foreach (var run in runs) { - Runs.Add(new JobEntry() { - Run = run, - Container = this, - }); - } - } - - public void AddRuns(SimulatorFactory factory) - { - factory.SumWriter = _sumWriter; - factory.JobNumber = _jobNumber++; - AddRuns(factory.SimulationRuns()); - } - - /// <summary> - /// Execute all runs, waits until finished. - /// </summary> - public void Execute(bool multithreaded = true) - { - Log.Info("VectoRun started running. Executing Runs."); - - foreach (var job in Runs) { - job.Worker = new BackgroundWorker() { - WorkerSupportsCancellation = true, - WorkerReportsProgress = true, - }; - job.Worker.DoWork += job.DoWork; - job.Worker.ProgressChanged += job.ProgressChanged; - job.Worker.RunWorkerCompleted += job.RunWorkerCompleted; - if (multithreaded) { - job.Started = true; - job.Worker.RunWorkerAsync(); - } - } - if (!multithreaded) { - var entry = Runs.First(); - entry.Started = true; - entry.Worker.RunWorkerAsync(); - } - } - - public void Cancel() - { - foreach (var job in Runs) { - if (job.Worker != null && job.Worker.WorkerSupportsCancellation) { - job.Worker.CancelAsync(); - } - } - } - - private static AutoResetEvent resetEvent = new AutoResetEvent(false); - - public void WaitFinished() - { - resetEvent.WaitOne(); - } - - - private void JobCompleted(JobEntry jobEntry) - { - var next = Runs.FirstOrDefault(x => x.Started == false); - if (next != null) { - next.Started = true; - next.Worker.RunWorkerAsync(); - } - if (Runs.Count(x => x.Done == true) == Runs.Count()) { - _sumWriter.Finish(); - resetEvent.Set(); - } - } - - public Dictionary<string, ProgressEntry> GetProgress() - { - return Runs.ToDictionary(jobEntry => jobEntry.Run.Name, entry => new ProgressEntry() { - Progress = entry.Progress, - Done = entry.Done, - ExecTime = entry.ExecTime, - Success = entry.Success, - Canceled = entry.Canceled, - Error = entry.ExecException - }); - } - - public bool AllCompleted - { - get { return (Runs.Count(x => x.Done == true) == Runs.Count()); } - } - - public class ProgressEntry - { - public double Progress; - public double ExecTime; - public Exception Error; - public bool Canceled; - public bool Success; - public bool Done; - } - - internal class JobEntry : LoggingObject - { - public IVectoRun Run; - public JobContainer Container; - public double Progress; - public bool Done; - public bool Started; - public bool Success; - public bool Canceled; - public double ExecTime; - public Exception ExecException; - - public BackgroundWorker Worker; - - public void DoWork(object sender, DoWorkEventArgs e) - { - var stopWatch = new Stopwatch(); - stopWatch.Start(); - var worker = sender as BackgroundWorker; - try { - Run.Run(worker); - } catch (Exception ex) { - Log.Error(ex, "Error during simulation run!"); - ExecException = ex; - } - if (worker != null && worker.CancellationPending) { - e.Cancel = true; - Canceled = true; - } - stopWatch.Stop(); - Success = Run.FinishedWithoutErrors; - Done = true; - ExecTime = stopWatch.Elapsed.TotalMilliseconds; - Container.JobCompleted(this); - } - - public void RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) {} - - public void ProgressChanged(object sender, ProgressChangedEventArgs e) - { - Progress = e.ProgressPercentage / 10000.0; - } - } - } + /// <summary> + /// Container for simulation jobs. + /// </summary> + public class JobContainer : LoggingObject + { + internal readonly List<JobEntry> Runs = new List<JobEntry>(); + private readonly SummaryFileWriter _sumWriter; + + private static int _jobNumber; + + /// <summary> + /// Initializes a new empty instance of the <see cref="JobContainer"/> class. + /// </summary> + /// <param name="sumWriter">The sum writer.</param> + public JobContainer(SummaryFileWriter sumWriter) + { + _sumWriter = sumWriter; + } + + public void AddRun(IVectoRun run) + { + _jobNumber++; + Runs.Add(new JobEntry() { + Run = run, + Container = this, + }); + } + + public void AddRuns(IEnumerable<IVectoRun> runs) + { + _jobNumber++; + //Runs.AddRange(runs); + foreach (var run in runs) { + Runs.Add(new JobEntry() { + Run = run, + Container = this, + }); + } + } + + public void AddRuns(SimulatorFactory factory) + { + factory.SumWriter = _sumWriter; + factory.JobNumber = _jobNumber++; + AddRuns(factory.SimulationRuns()); + } + + /// <summary> + /// Execute all runs, waits until finished. + /// </summary> + public void Execute(bool multithreaded = true) + { + Log.Info("VectoRun started running. Executing Runs."); + + foreach (var job in Runs) { + job.Worker = new BackgroundWorker() { + WorkerSupportsCancellation = true, + WorkerReportsProgress = true, + }; + job.Worker.DoWork += job.DoWork; + job.Worker.ProgressChanged += job.ProgressChanged; + job.Worker.RunWorkerCompleted += job.RunWorkerCompleted; + if (multithreaded) { + job.Started = true; + job.Worker.RunWorkerAsync(); + } + } + if (!multithreaded) { + var entry = Runs.First(); + entry.Started = true; + entry.Worker.RunWorkerAsync(); + } + //Task.WaitAll(_runs.Select(r => Task.Factory.StartNew(r.Run)).ToArray()); + + //_sumWriter.Finish(); + } + + public void Cancel() + { + foreach (var job in Runs) { + if (job.Worker != null && job.Worker.WorkerSupportsCancellation) { + job.Worker.CancelAsync(); + } + } + } + + public void CancelCurrent() + { + foreach (var job in Runs) { + if (job.Worker != null && job.Worker.IsBusy && job.Worker.WorkerSupportsCancellation) { + job.Worker.CancelAsync(); + } + } + } + + private static AutoResetEvent resetEvent = new AutoResetEvent(false); + + public void WaitFinished() + { + resetEvent.WaitOne(); + } + + + private void JobCompleted(JobEntry jobEntry) + { + var next = Runs.FirstOrDefault(x => x.Started == false); + if (next != null) { + next.Started = true; + next.Worker.RunWorkerAsync(); + } + if (Runs.Count(x => x.Done == true) == Runs.Count()) { + _sumWriter.Finish(); + resetEvent.Set(); + } + } + + public Dictionary<string, ProgressEntry> GetProgress() + { + return Runs.ToDictionary(jobEntry => jobEntry.Run.Name, entry => new ProgressEntry() { + Progress = entry.Progress, + Done = entry.Done, + ExecTime = entry.ExecTime, + Success = entry.Success, + Canceled = entry.Canceled, + Error = entry.ExecException + }); + } + + public bool AllCompleted + { + get { return (Runs.Count(x => x.Done == true) == Runs.Count()); } + } + + public class ProgressEntry + { + public double Progress; + public double ExecTime; + public Exception Error; + public bool Canceled; + public bool Success; + public bool Done; + } + + internal class JobEntry : LoggingObject + { + public IVectoRun Run; + public JobContainer Container; + public double Progress; + public bool Done; + public bool Started; + public bool Success; + public bool Canceled; + public double ExecTime; + public Exception ExecException; + + public BackgroundWorker Worker; + + public void DoWork(object sender, DoWorkEventArgs e) + { + var stopWatch = new Stopwatch(); + stopWatch.Start(); + var worker = sender as BackgroundWorker; + try { + Run.Run(worker); + } catch (Exception ex) { + Log.Error(ex, "Error during simulation run!"); + ExecException = ex; + } + if (worker != null && worker.CancellationPending) { + e.Cancel = true; + Canceled = true; + } + stopWatch.Stop(); + Success = Run.FinishedWithoutErrors; + Done = true; + ExecTime = stopWatch.Elapsed.TotalMilliseconds; + Container.JobCompleted(this); + } + + public void RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) {} + + public void ProgressChanged(object sender, ProgressChangedEventArgs e) + { + Progress = e.ProgressPercentage / 10000.0; + } + } + } } \ No newline at end of file diff --git a/VectoCore/Models/SimulationComponent/Data/Gearbox/TransmissionLossMap.cs b/VectoCore/Models/SimulationComponent/Data/Gearbox/TransmissionLossMap.cs index 485275c55719ecdf940a1f6f4e82b25c40767147..5364dd3acef157d599df444795b3330dc2a075b7 100644 --- a/VectoCore/Models/SimulationComponent/Data/Gearbox/TransmissionLossMap.cs +++ b/VectoCore/Models/SimulationComponent/Data/Gearbox/TransmissionLossMap.cs @@ -24,17 +24,20 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Data.Gearbox private readonly PerSecond _maxSpeed = double.NegativeInfinity.SI<PerSecond>(); private readonly PerSecond _minSpeed = double.PositiveInfinity.SI<PerSecond>(); - public static TransmissionLossMap ReadFromFile(string fileName, double gearRatio) + public string GearName { get; protected set; } + + + public static TransmissionLossMap ReadFromFile(string fileName, double gearRatio, string gearName) { var data = VectoCSVFile.Read(fileName, true); if (data.Columns.Count < 3) { - throw new VectoException("TransmissionLossMap Data File must consist of at least 3 columns."); + 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 must consist of at least four lines with numeric values (below file header"); + "TransmissionLossMap for {0} must consist of at least four lines with numeric values (below file header", gearName); } List<GearLossMapEntry> entries; @@ -42,14 +45,14 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Data.Gearbox entries = CreateFromColumnNames(data); } else { Logger<TransmissionLossMap>().Warn( - "TransmissionLossMap: Header line is not valid. Expected: '{0}, {1}, {2}, <{3}>'. Got: '{4}'. Falling back to column index.", + "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, - string.Join(", ", data.Columns.Cast<DataColumn>().Select(c => c.ColumnName).Reverse())); + string.Join(", ", data.Columns.Cast<DataColumn>().Select(c => c.ColumnName).Reverse()), gearName); entries = CreateFromColumIndizes(data); } - return new TransmissionLossMap(entries, gearRatio); + return new TransmissionLossMap(entries, gearRatio, gearName); } private static bool HeaderIsValid(DataColumnCollection columns) @@ -85,8 +88,9 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Data.Gearbox }).ToList(); } - private TransmissionLossMap(List<GearLossMapEntry> entries, double gearRatio) + private TransmissionLossMap(List<GearLossMapEntry> entries, double gearRatio, string gearName) { + GearName = gearName; _ratio = gearRatio; _entries = entries; _lossMap = new DelauneyMap(); @@ -104,6 +108,7 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Data.Gearbox _lossMap.Triangulate(); } + /// <summary> /// Computes the INPUT torque given by the input engineSpeed and the output torque. /// </summary> @@ -117,13 +122,14 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Data.Gearbox //var limitedTorque = VectoMath.Limit(outTorque, _minTorque, _maxTorque).Value(); var inTorque = _lossMap.Interpolate(inAngularVelocity.Value(), outTorque.Value()).SI<NewtonMeter>(); - Log.Debug("GearboxLoss: {0}", inTorque - outTorque); + Log.Debug("GearboxLoss {0}: {1}", GearName, inTorque - outTorque); // Limit input torque to a maximum value without losses (just torque/ratio) return VectoMath.Max(inTorque, outTorque / _ratio); } catch (VectoException) { - Log.Error("Failed to interpolate in TransmissionLossMap. angularVelocity: {0}, torque: {1}", inAngularVelocity, - outTorque); + Log.Error("{0} - Failed to interpolate in TransmissionLossMap. angularVelocity: {1}, torque: {2}", GearName, + inAngularVelocity, outTorque); + return outTorque / _ratio; } } diff --git a/VectoCore/Models/SimulationComponent/Impl/DefaultDriverStrategy.cs b/VectoCore/Models/SimulationComponent/Impl/DefaultDriverStrategy.cs index b982f09e13b2ee0729a9776cf5e5c50cf2726470..eee3a3addf9d9a879977e3dd353bd816e016195c 100644 --- a/VectoCore/Models/SimulationComponent/Impl/DefaultDriverStrategy.cs +++ b/VectoCore/Models/SimulationComponent/Impl/DefaultDriverStrategy.cs @@ -83,6 +83,7 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl public IResponse Request(Second absTime, Second dt, MeterPerSecond targetVelocity, Radian gradient) { DriverBehavior = DrivingBehavior.Halted; + CurrentDrivingMode = DrivingMode.DrivingModeDrive; return Driver.DrivingActionHalt(absTime, dt, targetVelocity, gradient); } @@ -510,6 +511,9 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl if (!DataBus.ClutchClosed(absTime)) { Log.Warn("Clutch is open - trying RollAction"); response = Driver.DrivingActionRoll(absTime, ds, targetVelocity, gradient); + } else { + Log.Warn("Clutch is open - trying AccelerateAction"); + response = Driver.DrivingActionAccelerate(absTime, ds, targetVelocity, gradient); } }); break; diff --git a/VectoCore/Models/SimulationComponent/Impl/Driver.cs b/VectoCore/Models/SimulationComponent/Impl/Driver.cs index 048cda32490370f53fbc65dce215e35f4f920057..d2ee769e33823c14bc37fba04ca7ad8b7e191dda 100644 --- a/VectoCore/Models/SimulationComponent/Impl/Driver.cs +++ b/VectoCore/Models/SimulationComponent/Impl/Driver.cs @@ -71,7 +71,7 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl public IResponse Request(Second absTime, Meter ds, MeterPerSecond targetVelocity, Radian gradient) { VehicleStopped = false; - Log.Debug("==== DRIVER Request ===="); + Log.Debug("==== DRIVER Request (distance) ===="); Log.Debug( "Request: absTime: {0}, ds: {1}, targetVelocity: {2}, gradient: {3} | distance: {4}, velocity: {5}, vehicle stopped: {6}", absTime, ds, targetVelocity, gradient, DataBus.Distance, DataBus.VehicleSpeed, VehicleStopped); @@ -90,7 +90,7 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl public IResponse Request(Second absTime, Second dt, MeterPerSecond targetVelocity, Radian gradient) { VehicleStopped = true; - Log.Debug("==== DRIVER Request ===="); + Log.Debug("==== DRIVER Request (time) ===="); Log.Debug( "Request: absTime: {0}, dt: {1}, targetVelocity: {2}, gradient: {3} | distance: {4}, velocity: {5} gear: {6}: vehicle stopped: {7}", absTime, dt, targetVelocity, gradient, DataBus.Distance, DataBus.VehicleSpeed, DataBus.Gear, VehicleStopped); @@ -628,11 +628,13 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl } while (retryCount++ < Constants.SimulationSettings.DriverSearchLoopThreshold); LogManager.EnableLogging(); - Log.Warn("Exceeded max iterations when searching for operating point!"); - Log.Warn("acceleration: {0} ... {1}", ", ".Join(debug.Take(5).Select(x => x.acceleration)), + Log.Error("Exceeded max iterations when searching for operating point!"); + Log.Error("acceleration: {0} ... {1}", ", ".Join(debug.Take(5).Select(x => x.acceleration)), ", ".Join(debug.Slice(-6).Select(x => x.acceleration))); - Log.Warn("exceeded: {0} ... {1}", ", ".Join(debug.Take(5).Select(x => x.delta)), + Log.Error("exceeded: {0} ... {1}", ", ".Join(debug.Take(5).Select(x => x.delta)), ", ".Join(debug.Slice(-6).Select(x => x.delta))); + // issue request once more for logging... + NextComponent.Request(absTime, retVal.SimulationInterval, retVal.Acceleration, gradient, true); Log.Error("Failed to find operating point! absTime: {0}", absTime); throw new VectoSearchFailedException("Failed to find operating point! exceeded: {0} ... {1}", ", ".Join(debug.Take(5).Select(x => x.delta)), @@ -715,9 +717,11 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl retVal.SimulationInterval = ds / currentSpeed; return retVal; } - Log.Error("vehicle speed is {0}, acceleration is {1}", currentSpeed.Value(), acceleration.Value()); + Log.Error("{2}: vehicle speed is {0}, acceleration is {1}", currentSpeed.Value(), acceleration.Value(), + DataBus.Distance); throw new VectoSimulationException( - "vehicle speed has to be > 0 if acceleration = 0! v: {0}, a: {1}", currentSpeed.Value(), acceleration.Value()); + "vehicle speed has to be > 0 if acceleration = 0! v: {0}, a: {1}, distance: ", currentSpeed.Value(), + acceleration.Value(), DataBus.Distance); } // we need to accelerate / decelerate. solve quadratic equation... diff --git a/VectoCore/Models/SimulationComponent/Impl/EngineOnlyDrivingCycle.cs b/VectoCore/Models/SimulationComponent/Impl/EngineOnlyDrivingCycle.cs index aa69f91b6b0d8a0945abeed5933e32446b1f74a2..e21d22d6f5a8aa1616d80bca032e4f8e25021b09 100644 --- a/VectoCore/Models/SimulationComponent/Impl/EngineOnlyDrivingCycle.cs +++ b/VectoCore/Models/SimulationComponent/Impl/EngineOnlyDrivingCycle.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Linq; using TUGraz.VectoCore.Exceptions; using TUGraz.VectoCore.Models.Connector.Ports; using TUGraz.VectoCore.Models.Connector.Ports.Impl; @@ -21,6 +22,8 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl private IEnumerator<DrivingCycleData.DrivingCycleEntry> RightSample { get; set; } private IEnumerator<DrivingCycleData.DrivingCycleEntry> LeftSample { get; set; } + protected Second AbsTime { get; set; } + public EngineOnlyDrivingCycle(IVehicleContainer container, DrivingCycleData cycle) : base(container) { @@ -65,7 +68,7 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl if (index >= Data.Entries.Count) { return new ResponseCycleFinished(); } - + AbsTime = absTime; return NextComponent.Request(absTime, dt, Data.Entries[index].EngineTorque, Data.Entries[index].EngineSpeed); } @@ -77,12 +80,13 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl public double Progress { - get { throw new NotImplementedException(); } + get { return AbsTime.Value() / Data.Entries.Last().Time.Value(); } } + public Meter StartDistance { - get { throw new NotImplementedException(); } + get { return 0.SI<Meter>(); } } #endregion diff --git a/VectoCore/Models/SimulationComponent/Impl/Vehicle.cs b/VectoCore/Models/SimulationComponent/Impl/Vehicle.cs index a47539256054af46ac6df0f1a7739cca62782571..f711e75172b179806442eaf1b717681ab6087721 100644 --- a/VectoCore/Models/SimulationComponent/Impl/Vehicle.cs +++ b/VectoCore/Models/SimulationComponent/Impl/Vehicle.cs @@ -128,7 +128,7 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl if (_currentState.Velocity.IsEqual(0.SI<MeterPerSecond>(), Constants.SimulationSettings.VehicleSpeedHaltTolerance)) { _currentState.Velocity = 0.SI<MeterPerSecond>(); } - _currentState.Distance = _previousState.Distance + dt * (_previousState.Velocity + _currentState.Velocity) / 2; + _currentState.Distance = _previousState.Distance + _previousState.Velocity * dt + acceleration * dt * dt / 2; _currentState.DriverAcceleration = DriverAcceleration(acceleration); _currentState.RollingResistance = RollingResistance(gradient); diff --git a/VectoCore/Properties/Version.cs b/VectoCore/Properties/Version.cs index 3f913b040844e50d1f62d65b505304451f2a75cf..d1252b4226b28f046edfa9c7c817c807e2345380 100644 --- a/VectoCore/Properties/Version.cs +++ b/VectoCore/Properties/Version.cs @@ -1,5 +1,5 @@ using System.Reflection; -// generated on 07.11.2015 22:40:05 -[assembly: AssemblyVersion("3.0.1.310")] -[assembly: AssemblyFileVersion("3.0.1.310")] +// generated on 09.11.2015 10:21:28 +[assembly: AssemblyVersion("3.0.1.312")] +[assembly: AssemblyFileVersion("3.0.1.312")] diff --git a/VectoCoreTest/Integration/CoachPowerTrain.cs b/VectoCoreTest/Integration/CoachPowerTrain.cs index ede8a73579a2b73b5596f4827d11dda9394dee10..2ed08020c52b409d2b51088a17e5c74f4f355d5d 100644 --- a/VectoCoreTest/Integration/CoachPowerTrain.cs +++ b/VectoCoreTest/Integration/CoachPowerTrain.cs @@ -82,8 +82,8 @@ namespace TUGraz.VectoCore.Tests.Integration new GearData { FullLoadCurve = FullLoadCurve.ReadFromFile(GearboxFullLoadCurveFile), LossMap = (ratio != 1.0) - ? TransmissionLossMap.ReadFromFile(GearboxIndirectLoss, ratio) - : TransmissionLossMap.ReadFromFile(GearboxDirectLoss, ratio), + ? TransmissionLossMap.ReadFromFile(GearboxIndirectLoss, ratio, string.Format("Gear {0}", i)) + : TransmissionLossMap.ReadFromFile(GearboxDirectLoss, ratio, string.Format("Gear {0}", i)), Ratio = ratio, ShiftPolygon = ShiftPolygon.ReadFromFile(GearboxShiftPolygonFile) })) @@ -104,7 +104,7 @@ namespace TUGraz.VectoCore.Tests.Integration const double ratio = 3.240355; return new GearData { Ratio = ratio, - LossMap = TransmissionLossMap.ReadFromFile(AxleGearLossMap, ratio) + LossMap = TransmissionLossMap.ReadFromFile(AxleGearLossMap, ratio, "AxleGear") }; } diff --git a/VectoCoreTest/Integration/FullCycleDeclarationTest.cs b/VectoCoreTest/Integration/FullCycleDeclarationTest.cs index 6e27ea4acbe2f40a25644aa6bbc8ce4f2c5d4346..48c387b3bd37fb1b0ccf5a352301b815e2122f43 100644 --- a/VectoCoreTest/Integration/FullCycleDeclarationTest.cs +++ b/VectoCoreTest/Integration/FullCycleDeclarationTest.cs @@ -1,4 +1,5 @@ using System.IO; +using System.Linq; using Microsoft.VisualStudio.TestTools.UnitTesting; using NLog; using TUGraz.VectoCore.Configuration; @@ -40,6 +41,22 @@ namespace TUGraz.VectoCore.Tests.Integration Assert.IsTrue(run.FinishedWithoutErrors); } + [TestMethod] + public void Truck40t_RegionalDeliveryCycle_RefLoad_Declaration() + { + var factory = new SimulatorFactory(SimulatorFactory.FactoryMode.DeclarationMode, + @"c:\Users\Technik\Downloads\40t Long Haul Truck\40t_Long_Haul_Truck.vecto"); + factory.WriteModalResults = true; + factory.SumWriter = new SummaryFileWriter("Test.vsum"); + var runs = factory.SimulationRuns().ToArray(); + + var run = runs[4]; + run.Run(); + + Assert.IsTrue(run.FinishedWithoutErrors); + } + + [TestMethod] public void Truck40t_UrbanDeliveryCycle_RefLoad() { @@ -135,5 +152,37 @@ namespace TUGraz.VectoCore.Tests.Integration Assert.IsTrue(run.Run.FinishedWithoutErrors); } } + + [TestMethod] + public void Truck12t_LongHaulCycle_RefLoad_Declaration() + { + // TODO: fails due to interpolaion failure in Gear 4 + var factory = new SimulatorFactory(SimulatorFactory.FactoryMode.DeclarationMode, + @"c:\Users\Technik\Downloads\12t Delivery Truck\12t Delivery Truck.vecto"); + factory.WriteModalResults = true; + factory.SumWriter = new SummaryFileWriter("Test.vsum"); + var runs = factory.SimulationRuns().ToArray(); + + var run = runs[1]; + run.Run(); + + Assert.IsTrue(run.FinishedWithoutErrors); + } + + [TestMethod] + public void Truck12t_UrbanDeliveryCycle_RefLoad_Declaration() + { + // TODO: fails due to interpolaion failure in Gear 4 + var factory = new SimulatorFactory(SimulatorFactory.FactoryMode.DeclarationMode, + @"c:\Users\Technik\Downloads\12t Delivery Truck\12t Delivery Truck.vecto"); + factory.WriteModalResults = true; + factory.SumWriter = new SummaryFileWriter("Test.vsum"); + var runs = factory.SimulationRuns().ToArray(); + + var run = runs[7]; + run.Run(); + + Assert.IsTrue(run.FinishedWithoutErrors); + } } } \ No newline at end of file diff --git a/VectoCoreTest/Integration/SimulationRuns/FullPowertrain.cs b/VectoCoreTest/Integration/SimulationRuns/FullPowertrain.cs index 7951a8be95c99af3bc8721deabf19898d913b060..65764e6bff8c4a58ca394f07873d88fdf502b1c2 100644 --- a/VectoCoreTest/Integration/SimulationRuns/FullPowertrain.cs +++ b/VectoCoreTest/Integration/SimulationRuns/FullPowertrain.cs @@ -255,6 +255,7 @@ namespace TUGraz.VectoCore.Tests.Integration.SimulationRuns jobContainer.AddRuns(factory); jobContainer.Execute(); + jobContainer.WaitFinished(); ResultFileHelper.TestSumFile(@"TestData\Results\Integration\job.vsum", @"job.vsum"); ResultFileHelper.TestModFile(@"TestData\Results\Integration\job_1-Gear-Test-dist.vmod", @@ -272,7 +273,7 @@ namespace TUGraz.VectoCore.Tests.Integration.SimulationRuns Tuple.Create((uint)i, new GearData { FullLoadCurve = FullLoadCurve.ReadFromFile(GearboxFullLoadCurveFile), - LossMap = TransmissionLossMap.ReadFromFile(GearboxLossMap, ratio), + LossMap = TransmissionLossMap.ReadFromFile(GearboxLossMap, ratio, string.Format("Gear {0}", i)), Ratio = ratio, ShiftPolygon = ShiftPolygon.ReadFromFile(GearboxShiftPolygonFile) })) @@ -293,7 +294,7 @@ namespace TUGraz.VectoCore.Tests.Integration.SimulationRuns var ratio = 3.240355; return new GearData { Ratio = ratio, - LossMap = TransmissionLossMap.ReadFromFile(GearboxLossMap, ratio) + LossMap = TransmissionLossMap.ReadFromFile(GearboxLossMap, ratio, "AxleGear") }; } @@ -305,7 +306,7 @@ namespace TUGraz.VectoCore.Tests.Integration.SimulationRuns { 1, new GearData { FullLoadCurve = null, - LossMap = TransmissionLossMap.ReadFromFile(GearboxLossMap, ratio), + LossMap = TransmissionLossMap.ReadFromFile(GearboxLossMap, ratio, "Gear 1"), Ratio = ratio, ShiftPolygon = ShiftPolygon.ReadFromFile(GearboxShiftPolygonFile) } diff --git a/VectoCoreTest/Integration/SimulationRuns/MinimalPowertrain.cs b/VectoCoreTest/Integration/SimulationRuns/MinimalPowertrain.cs index cf5550e30588233d399e58bd3e96fff0de417050..39a3e1c293aa54b952473bde11e50bb9e26105e5 100644 --- a/VectoCoreTest/Integration/SimulationRuns/MinimalPowertrain.cs +++ b/VectoCoreTest/Integration/SimulationRuns/MinimalPowertrain.cs @@ -216,7 +216,7 @@ namespace TUGraz.VectoCore.Tests.Integration.SimulationRuns { return new GearData { Ratio = 3.0 * 3.5, - LossMap = TransmissionLossMap.ReadFromFile(GbxLossMap, 3.0 * 3.5) + LossMap = TransmissionLossMap.ReadFromFile(GbxLossMap, 3.0 * 3.5, "AxleGear") }; } diff --git a/VectoCoreTest/Integration/Truck40tPowerTrain.cs b/VectoCoreTest/Integration/Truck40tPowerTrain.cs index 42f18a6746da6c5e0294cd198e23644114b960a0..b3fba6eb62e7bab75fcdeeabd15071b6fb5ed34d 100644 --- a/VectoCoreTest/Integration/Truck40tPowerTrain.cs +++ b/VectoCoreTest/Integration/Truck40tPowerTrain.cs @@ -88,8 +88,8 @@ namespace TUGraz.VectoCore.Tests.Integration FullLoadCurve = FullLoadCurve.ReadFromFile(GearboxFullLoadCurveFile), LossMap = (ratio != 1.0) - ? TransmissionLossMap.ReadFromFile(GearboxIndirectLoss, ratio) - : TransmissionLossMap.ReadFromFile(GearboxDirectLoss, ratio), + ? TransmissionLossMap.ReadFromFile(GearboxIndirectLoss, ratio, string.Format("Gear {0}", i)) + : TransmissionLossMap.ReadFromFile(GearboxDirectLoss, ratio, string.Format("Gear {0}", i)), Ratio = ratio, ShiftPolygon = ShiftPolygon.ReadFromFile(ShiftPolygonFile), //ShiftPolygon = DeclarationData.Gearbox.ComputeShiftPolygon(engineData.FullLoadCurve, engineData.IdleSpeed) @@ -112,7 +112,7 @@ namespace TUGraz.VectoCore.Tests.Integration const double ratio = 2.59; return new GearData { Ratio = ratio, - LossMap = TransmissionLossMap.ReadFromFile(AxleGearLossMap, ratio) + LossMap = TransmissionLossMap.ReadFromFile(AxleGearLossMap, ratio, "AxleGear") }; } diff --git a/VectoCoreTest/Models/Simulation/AuxTests.cs b/VectoCoreTest/Models/Simulation/AuxTests.cs index f438501cf880e27c25e4d35262f261dd0eb80779..0e75df621772e5662210459a6e23eae95a7ecafe 100644 --- a/VectoCoreTest/Models/Simulation/AuxTests.cs +++ b/VectoCoreTest/Models/Simulation/AuxTests.cs @@ -53,6 +53,7 @@ namespace TUGraz.VectoCore.Tests.Models.Simulation for (var i = 0; i < 11; i++) { aux.OutPort().Request(t, dt, torque, speed); + dataWriter[ModalResultField.dist] = i.SI<Meter>(); container.CommitSimulationStep(t, dt); t += dt; } diff --git a/VectoCoreTest/Models/Simulation/SimulationTests.cs b/VectoCoreTest/Models/Simulation/SimulationTests.cs index 727b69f265dba48e03905208b0c6eec16e358eaf..8201a30ab6d09c60aba786e627e0011b0d1c41bd 100644 --- a/VectoCoreTest/Models/Simulation/SimulationTests.cs +++ b/VectoCoreTest/Models/Simulation/SimulationTests.cs @@ -92,6 +92,8 @@ namespace TUGraz.VectoCore.Tests.Models.Simulation jobContainer.AddRuns(runsFactory); jobContainer.Execute(); + jobContainer.WaitFinished(); + ResultFileHelper.TestSumFile(@"TestData\Results\EngineOnlyCycles\24t Coach.vsum", @"24t Coach.vsum"); ResultFileHelper.TestModFiles(new[] { diff --git a/VectoCoreTest/Models/SimulationComponent/GearboxTest.cs b/VectoCoreTest/Models/SimulationComponent/GearboxTest.cs index bf03b90d46a275b6dfcd3972f429055e77523ff4..1f7a41629cda700936a89a9703b8add83aa52eb0 100644 --- a/VectoCoreTest/Models/SimulationComponent/GearboxTest.cs +++ b/VectoCoreTest/Models/SimulationComponent/GearboxTest.cs @@ -48,7 +48,7 @@ namespace TUGraz.VectoCore.Tests.Models.SimulationComponent Tuple.Create((uint)i, new GearData { FullLoadCurve = FullLoadCurve.ReadFromFile(GearboxFullLoadCurveFile), - LossMap = TransmissionLossMap.ReadFromFile((i != 6) ? IndirectLossMap : DirectLossMap, ratio), + LossMap = TransmissionLossMap.ReadFromFile((i != 6) ? IndirectLossMap : DirectLossMap, ratio, i.ToString()), Ratio = ratio, ShiftPolygon = ShiftPolygon.ReadFromFile(GearboxShiftPolygonFile) })) diff --git a/VectoCoreTest/TestData/Results/EngineOnlyCycles/24t Coach.vsum b/VectoCoreTest/TestData/Results/EngineOnlyCycles/24t Coach.vsum index a2f10c7f2d43ccbc74afa731ac473435e813a3cf..9ad88585ec47c79f25265c440e6e72431ecced05 100644 --- a/VectoCoreTest/TestData/Results/EngineOnlyCycles/24t Coach.vsum +++ b/VectoCoreTest/TestData/Results/EngineOnlyCycles/24t Coach.vsum @@ -1,4 +1,4 @@ -Job [-],Input File [-],Cycle [-],time [s],Ppos [kW],Pneg [kW],FC-Map [g/h],FC-AUXc [g/h],FC-WHTCc [g/h] -1,24t Coach.vecto,Engine Only1.vdri,3951,29.5999634846317,-1.63579455196953,ERROR,-,- -1,24t Coach.vecto,Engine Only2.vdri,3951,29.5999634846317,-1.63579455196953,ERROR,-,- -1,24t Coach.vecto,Engine Only3.vdri,3951,29.5999634846317,-1.63579455196953,ERROR,-,- +Job [-],Input File [-],Cycle [-],Status,time [s],Ppos [kW],Pneg [kW],FC-Map [g/h],FC-AUXc [g/h],FC-WHTCc [g/h] +1,24t Coach.vecto,Engine Only1.vdri,Success,3951,29.5999634846317,-1.63579455196953,ERROR,-,- +1,24t Coach.vecto,Engine Only2.vdri,Success,3951,29.5999634846317,-1.63579455196953,ERROR,-,- +1,24t Coach.vecto,Engine Only3.vdri,Success,3951,29.5999634846317,-1.63579455196953,ERROR,-,- diff --git a/VectoCoreTest/TestData/Results/Integration/job.vsum b/VectoCoreTest/TestData/Results/Integration/job.vsum index 88388dc426773c003c1e1b0e0048e8183ed479de..12c714a9121a8b9d5097a89b0ab9175b5897994e 100644 --- a/VectoCoreTest/TestData/Results/Integration/job.vsum +++ b/VectoCoreTest/TestData/Results/Integration/job.vsum @@ -1,2 +1,2 @@ -Job [-],Input File [-],Cycle [-],time [s],distance [km],speed [km/h],∆altitude [m],Ppos [kW],Pneg [kW],FC-Map [g/h],FC-Map [g/km],FC-AUXc [g/h],FC-AUXc [g/km],FC-WHTCc [g/h],FC-WHTCc [g/km],CO2 [g/km],CO2 [g/tkm],FC-Final [g/km],FC-Final [l/100tkm],FC-Final [l/100km],PwheelPos [kW],Pbrake [kW],EposICE [kWh],EnegICE [kWh],Eair [kWh],Eroll [kWh],Egrad [kWh],Eacc [kWh],Eaux [kWh],Ebrake [kWh],Etransm [kWh],Eretarder [kWh],Etorqueconv [kWh],Mass [kg],Loading [kg],a [m/s^2],a_pos [m/s^2],a_neg [m/s^2],Acc.Noise [m/s^2],pAcc [%],pDec [%],pCruise [%],pStop [%] -0-0,job.vecto,1-Gear-Test-dist,8522.5000,16812.0086,4.0893,,15403.1928,-12521.5157,3672.4548,,,,,,,,,,,,Infinity,15403.1928,-12521.5157,,,,20412.4831,0.0000,Infinity,11089490.8510,10157295.6812,,15700.0000,3300.0000,0.0000,,,,0.0000,0.0000,100.0000,0.0117 +Job [-],Input File [-],Cycle [-],Status,time [s],distance [km],speed [km/h],∆altitude [m],Ppos [kW],Pneg [kW],FC-Map [g/h],FC-Map [g/km],FC-AUXc [g/h],FC-AUXc [g/km],FC-WHTCc [g/h],FC-WHTCc [g/km],CO2 [g/km],CO2 [g/tkm],FC-Final [g/km],FC-Final [l/100tkm],FC-Final [l/100km],PwheelPos [kW],Pbrake [kW],EposICE [kWh],EnegICE [kWh],Eair [kWh],Eroll [kWh],Egrad [kWh],Eacc [kWh],Eaux [kWh],Ebrake [kWh],Etransm [kWh],Eretarder [kWh],Etorqueconv [kWh],Mass [kg],Loading [kg],a [m/s^2],a_pos [m/s^2],a_neg [m/s^2],Acc.Noise [m/s^2],pAcc [%],pDec [%],pCruise [%],pStop [%] +0-0,job.vecto,1-Gear-Test-dist,Success,8522.5000,16812.0086,4.0893,,15403.1928,-12521.5157,3672.4548,,,,,,,,,,,,Infinity,15403.1928,-12521.5157,,,,20412.4831,0.0000,Infinity,11089490.8510,10157295.6812,,15700.0000,3300.0000,0.0000,,,,0.0000,0.0000,100.0000,0.0117 diff --git a/VectoCoreTest/Utils/GraphWriter.cs b/VectoCoreTest/Utils/GraphWriter.cs index 4522ac47f39fdbeda5073b5ca75cb3d6b1ac79cb..4c62b9881a821257d457bbd8fe5f7b4050de78b4 100644 --- a/VectoCoreTest/Utils/GraphWriter.cs +++ b/VectoCoreTest/Utils/GraphWriter.cs @@ -18,248 +18,403 @@ using Point = System.Drawing.Point; namespace TUGraz.VectoCore.Tests.Utils { - public static class GraphWriter - { - private static bool _enabled = true; + public static class GraphWriter + { + private static bool _enabled = true; - private static Size _diagramSize = new Size(2000, 440); + private static Size _diagramSize = new Size(2000, 440); private static readonly Font AxisLabelFont = new Font("Consolas", 10); - private static readonly Font AxisTitleFont = new Font("Verdana", 12); + private static readonly Font AxisTitleFont = new Font("Verdana", 12); private static readonly Font LegendFont = new Font("Verdana", 14); - public static void Enabled() - { - _enabled = true; - } - - public static void Disable() - { - _enabled = false; - } - - public static void Write(string fileNameV3, string fileNameV22 = null) - { - if (!_enabled) { - return; - } - - var modDataV3 = VectoCSVFile.Read(fileNameV3); - if (!File.Exists(fileNameV22)) { - LogManager.GetCurrentClassLogger().Error("Modfile V2.2 not found: " + fileNameV22); - //Write(fileNameV3); - //return; - } - DataTable modDataV22 = null; - if (fileNameV22 != null) { - modDataV22 = VectoCSVFile.Read(fileNameV22); - } - var xfields = new[] { ModalResultField.time, ModalResultField.dist }; - - var yfields = new[] { ModalResultField.v_act, ModalResultField.acc, ModalResultField.n, ModalResultField.Gear, ModalResultField.Pe_eng, ModalResultField.Tq_eng, ModalResultField.FCMap }; - - var titleHeight = (50 * 100.0f) / (_diagramSize.Height * yfields.Count()); - - foreach (var xfield in xfields) { - var fileName = string.Format("{0}_{1}.png", Path.GetFileNameWithoutExtension(fileNameV3), xfield.GetName()); - - var x = LoadData(modDataV3, xfield.GetName()); - var x2 = new double[]{ double.NegativeInfinity}; - if (fileNameV22 != null && modDataV22 != null) { - x2 = LoadData(modDataV22, xfield.GetName()); - } - var plotSize = new Size(_diagramSize.Width, _diagramSize.Height * yfields.Count()); - var maxX = (int)(Math.Ceiling(Math.Max(x.Max(), x2.Max()) * 1.01 / 10.0) * 10.0); - var minX = (int)(Math.Floor(Math.Max(x.Min(), x2.Min()) / 10.0) * 10.0); - var chart = new Chart { Size = plotSize }; - - - for (var i = 0; i < yfields.Length; i++) { - var yfield = yfields[i]; + public static void Enabled() + { + _enabled = true; + } + + public static void Disable() + { + _enabled = false; + } + + public static void Write(string fileNameV3, string fileNameV22 = null) + { + if (!_enabled) { + return; + } + + var modDataV3 = VectoCSVFile.Read(fileNameV3); + if (!File.Exists(fileNameV22)) { + LogManager.GetCurrentClassLogger().Error("Modfile V2.2 not found: " + fileNameV22); + //Write(fileNameV3); + //return; + } + DataTable modDataV22 = null; + if (fileNameV22 != null) { + modDataV22 = VectoCSVFile.Read(fileNameV22); + } + var xfields = new[] { ModalResultField.time, ModalResultField.dist }; + + var yfields = new[] { + ModalResultField.v_act, ModalResultField.acc, ModalResultField.n, ModalResultField.Gear, + ModalResultField.Pe_eng, ModalResultField.Tq_eng, ModalResultField.FCMap + }; + + var titleHeight = (50 * 100.0f) / (_diagramSize.Height * yfields.Count()); + + foreach (var xfield in xfields) { + var fileName = string.Format("{0}_{1}.png", Path.GetFileNameWithoutExtension(fileNameV3), + xfield.GetName()); + + var x = LoadData(modDataV3, xfield.GetName()); + var x2 = new double[] { double.NegativeInfinity }; + if (fileNameV22 != null && modDataV22 != null) { + x2 = LoadData(modDataV22, xfield.GetName()); + } + var plotSize = new Size(_diagramSize.Width, _diagramSize.Height * yfields.Count()); + var maxX = (int)(Math.Ceiling(Math.Max(x.Max(), x2.Max()) * 1.01 / 10.0) * 10.0); + var minX = (int)(Math.Floor(Math.Max(x.Min(), x2.Min()) / 10.0) * 10.0); + var chart = new Chart { Size = plotSize }; + + + for (var i = 0; i < yfields.Length; i++) { + var yfield = yfields[i]; var y = LoadData(modDataV3, yfield.GetName()); - var chartArea = AddChartArea(chart, yfield.ToString(), xfield.GetCaption(), maxX, minX, yfield.GetCaption(), yfield == ModalResultField.Gear); + var chartArea = AddChartArea(chart, yfield.ToString(), xfield.GetCaption(), maxX, minX, + yfield.GetCaption(), yfield == ModalResultField.Gear); - var legend = CreateLegend(chart, yfield.ToString()); + var legend = CreateLegend(chart, yfield.ToString()); - if (yfield == ModalResultField.v_act) { - var y3 = LoadData(modDataV3, ModalResultField.v_targ.GetName()); + if (yfield == ModalResultField.v_act) { + var y3 = LoadData(modDataV3, ModalResultField.v_targ.GetName()); var series3 = CreateSeries("v_target", legend, chartArea, chart, Color.Green, x, y3); - } - var series1 = CreateSeries( string.Format("Vecto 3 - {0}", yfield), legend, chartArea, chart,Color.Blue, x, y); - - if (fileNameV22 != null) { - var y2 = LoadData(modDataV22, yfield.GetName()); - var series2 = CreateSeries(string.Format("Vecto 2.2 - {0}", yfield), legend, chartArea, chart, Color.Red, x2, - y2); - } + var grad = LoadData(modDataV3, ModalResultField.grad.GetName()); + + chartArea.AxisY2.Enabled = AxisEnabled.True; + chartArea.AxisY2.Title = "gradient [%]"; + chartArea.AxisY2.TitleFont = AxisTitleFont; + chartArea.AxisY2.LabelStyle.Font = AxisLabelFont; + chartArea.AxisY2.LabelAutoFitStyle = LabelAutoFitStyles.None; + chartArea.AxisY2.MinorGrid.Enabled = false; + chartArea.AxisY2.MajorGrid.Enabled = false; + var max = Math.Max(-Math.Round(grad.Min() * 2), Math.Round(grad.Max() * 2)); + //chartArea.AxisY2.si + //chartArea.AxisY2.Minimum = -max; + //chartArea.AxisY2.Maximum = max; + chartArea.AxisY2.RoundAxisValues(); + chartArea.AxisY2.Interval = Math.Round(max / 5); + + var seriesGrad = CreateSeries("Gradient", legend, chartArea, chart, Color.Coral, x, grad); + seriesGrad.YAxisType = AxisType.Secondary; + } + + var series1 = CreateSeries(string.Format("Vecto 3 - {0}", yfield), legend, chartArea, chart, + Color.Blue, x, y); + + if (fileNameV22 != null) { + var y2 = LoadData(modDataV22, yfield.GetName()); + var series2 = CreateSeries(string.Format("Vecto 2.2 - {0}", yfield), legend, chartArea, chart, + Color.Red, x2, + y2); + } + + PositionChartArea(chartArea, titleHeight, i, yfields.Count()); + + if (i > 0) { + AlignChart(chart, yfield.ToString(), yfields[0].ToString()); + } + } - PositionChartArea(chartArea, titleHeight, i, yfields.Count()); + AddTitle(chart, Path.GetFileNameWithoutExtension(fileName), yfields[0].ToString()); - if (i > 0) { - AlignChart(chart, yfield.ToString(), yfields[0].ToString()); - } - } + chart.Invalidate(); + chart.SaveImage(fileName, ChartImageFormat.Png); + } + } + + public static bool WriteDistanceSlice(string fileNameV3, string fileNameV22, double start, double end) + { + if (!_enabled) { + return true; + } + + var modDataV3Iput = VectoCSVFile.Read(fileNameV3); + //var modDataV3View = new DataView(modDataV3Iput) { + // RowFilter = string.Format(@"dist > {0} AND dist < {1}", start, end) + //}; + //var modDataV3 = modDataV3View.ToTable(); + var modDataV3tmp = modDataV3Iput.AsEnumerable().Where(row => { + var s = row.ParseDouble("dist"); + return s >= start && s <= end; + }); + + + if (!File.Exists(fileNameV22)) { + //LogManager.GetCurrentClassLogger().Error("Modfile V2.2 not found: " + fileNameV22); + //Write(fileNameV3); + //return; + } + DataTable modDataV22 = null; + if (fileNameV22 != null) { + var modDataV22Input = VectoCSVFile.Read(fileNameV22); + //var modDataV22View = new DataView(modDataV22Input) { + // RowFilter = string.Format(@"dist > {0} AND dist < {1}", start, end) + //}; + var modDataV22tmp = modDataV22Input.AsEnumerable().Where(row => { + var s = row.ParseDouble("dist"); + return s >= start && s <= end; + }); + if (!(modDataV3tmp.Any() || modDataV22tmp.Any())) { + return false; + } + modDataV22 = modDataV22tmp.CopyToDataTable(); + } else { + if (!modDataV3tmp.Any()) { + return false; + } + } + var modDataV3 = modDataV3tmp.CopyToDataTable(); + + //var xfields = new[] { ModalResultField.dist }; + var xfield = ModalResultField.dist; + var yfields = new[] { + ModalResultField.v_act, ModalResultField.acc, ModalResultField.n, ModalResultField.Gear, + ModalResultField.Pe_eng, ModalResultField.Tq_eng, ModalResultField.FCMap + }; + + var titleHeight = (50 * 100.0f) / (_diagramSize.Height * yfields.Count()); + + //foreach (var xfield in xfields) { + var fileName = string.Format("{0}_{1}-{2:D3}_{3:D3}.png", Path.GetFileNameWithoutExtension(fileNameV3), + xfield.GetName(), (int)(start / 1000), (int)(end / 1000)); + + var x = LoadData(modDataV3, xfield.GetName()); + var x2 = new double[] { double.NegativeInfinity }; + if (fileNameV22 != null && modDataV22 != null) { + x2 = LoadData(modDataV22, xfield.GetName()); + } + var plotSize = new Size(_diagramSize.Width, _diagramSize.Height * yfields.Count()); + var maxX = (int)(Math.Ceiling(Math.Max(x.Max(), x2.Max()) * 1.01 / 10.0) * 10.0); + var minX = (int)(Math.Floor(Math.Max(x.Min(), x2.Min()) / 10.0) * 10.0); + var chart = new Chart { Size = plotSize }; + + + for (var i = 0; i < yfields.Length; i++) { + var yfield = yfields[i]; + var y = LoadData(modDataV3, yfield.GetName()); + + + var chartArea = AddChartArea(chart, yfield.ToString(), xfield.GetCaption(), maxX, minX, + yfield.GetCaption(), yfield == ModalResultField.Gear); + + var legend = CreateLegend(chart, yfield.ToString()); + + if (yfield == ModalResultField.v_act) { + var y3 = LoadData(modDataV3, ModalResultField.v_targ.GetName()); + var series3 = CreateSeries("v_target", legend, chartArea, chart, Color.Green, x, y3); + + var grad = LoadData(modDataV3, ModalResultField.grad.GetName()); + + chartArea.AxisY2.Enabled = AxisEnabled.True; + chartArea.AxisY2.Title = "gradient [%]"; + chartArea.AxisY2.TitleFont = AxisTitleFont; + chartArea.AxisY2.LabelStyle.Font = AxisLabelFont; + chartArea.AxisY2.LabelAutoFitStyle = LabelAutoFitStyles.None; + chartArea.AxisY2.MinorGrid.Enabled = false; + chartArea.AxisY2.MajorGrid.Enabled = false; + var max = Math.Max(-Math.Round(grad.Min() * 2), Math.Round(grad.Max() * 2)); + //chartArea.AxisY2.si + chartArea.AxisY2.Minimum = -max; + chartArea.AxisY2.Maximum = max; + chartArea.AxisY2.RoundAxisValues(); + + var seriesGrad = CreateSeries("Gradient", legend, chartArea, chart, Color.Coral, x, grad); + seriesGrad.YAxisType = AxisType.Secondary; + } + + + var series1 = CreateSeries(string.Format("Vecto 3 - {0}", yfield), legend, chartArea, chart, + Color.Blue, x, y); + + if (fileNameV22 != null) { + var y2 = LoadData(modDataV22, yfield.GetName()); + var series2 = CreateSeries(string.Format("Vecto 2.2 - {0}", yfield), legend, chartArea, chart, + Color.Red, x2, y2); + } + + PositionChartArea(chartArea, titleHeight, i, yfields.Count()); + + if (i > 0) { + AlignChart(chart, yfield.ToString(), yfields[0].ToString()); + } + //} AddTitle(chart, Path.GetFileNameWithoutExtension(fileName), yfields[0].ToString()); - chart.Invalidate(); - chart.SaveImage(fileName, ChartImageFormat.Png); - } - } - - private static void AddTitle(Chart chart, string titleText, string dockToChartArea) - { - var title = new Title(); - title.Text = titleText; - title.DockedToChartArea = dockToChartArea; - title.IsDockedInsideChartArea = false; - title.Font = new Font("Verdana", 18, FontStyle.Bold); - chart.Titles.Add(title); - } - - private static double[] LoadData(DataTable modDataV3, string field) - { - return modDataV3.Rows.Cast<DataRow>() - .Select(v => v.Field<string>(field).Length == 0 - ? Double.NaN - : v.Field<string>(field).ToDouble()) - .ToArray(); - } - - private static void AlignChart(Chart chart, string chartToAlign, string chartToAlignWith) - { - chart.ChartAreas[chartToAlign].AlignWithChartArea = chartToAlignWith; - chart.ChartAreas[chartToAlign].AlignmentOrientation = AreaAlignmentOrientations.Vertical; - chart.ChartAreas[chartToAlign].AlignmentStyle = AreaAlignmentStyles.All; - } - - private static void PositionChartArea(ChartArea chartArea, float titleHeight, int i, int numCharts) - { - chartArea.Position.Auto = false; - chartArea.Position.Width = 85; - chartArea.Position.Height = (100.0f - titleHeight) / numCharts; - chartArea.Position.X = 0; - chartArea.Position.Y = (i * (100.0f - titleHeight)) / numCharts + titleHeight; - } - - private static ChartArea AddChartArea(Chart chart, string name, string axisXTitle, int xMax, int xMin, string axisYTitle, bool discreteValues) - { - var chartArea = new ChartArea { Name = name }; - chartArea.AxisX.MajorGrid.LineColor = Color.DarkGray; - chartArea.AxisY.MajorGrid.LineColor = Color.DarkGray; - chartArea.AxisX.LabelStyle.Font = AxisLabelFont; - chartArea.AxisY.LabelStyle.Font = AxisLabelFont; - - chartArea.AxisX.Interval = xMax / 20.0; - chartArea.AxisX.Maximum = xMax; - chartArea.AxisX.Minimum = xMin; - chartArea.AxisX.MinorGrid.Enabled = true; - chartArea.AxisX.MinorGrid.Interval = xMax / 100.0; - chartArea.AxisX.MinorGrid.LineColor = Color.LightGray; - chartArea.AxisX.Title = axisXTitle; - chartArea.AxisX.TitleFont = AxisTitleFont; - chartArea.AxisX.RoundAxisValues(); - chartArea.AxisX.MajorTickMark.Size = 2 * 100.0f / _diagramSize.Height; - - chartArea.AxisY.Title = axisYTitle; - chartArea.AxisY.TitleFont = AxisTitleFont; - chartArea.AxisY.RoundAxisValues(); - if (discreteValues) { - chartArea.AxisY.MajorGrid.Interval = 1; - chartArea.AxisY.MinorGrid.Enabled = false; - } else { - chartArea.AxisY.MinorGrid.Enabled = true; - } - chartArea.AxisY.MinorGrid.LineColor = Color.LightGray; - chartArea.AxisY.MajorTickMark.Size = 5 * 100.0f / _diagramSize.Width; - - chart.ChartAreas.Add(chartArea); - return chartArea; - } - - private static Legend CreateLegend(Chart chart, string dockToChartArea) - { - var legend = new Legend(dockToChartArea.ToString()) { - Docking = Docking.Right, - IsDockedInsideChartArea = false, - DockedToChartArea = dockToChartArea, - Font = LegendFont, - }; - chart.Legends.Add(legend); - return legend; - } - - private static Series CreateSeries(String name, Legend legend, ChartArea chartArea, Chart chart, Color color, double[] x, double[] y) - { - ModalResultField yfield; - var series1 = new Series { - Name = name, - ChartType = SeriesChartType.Line, - Color = color, - BorderWidth = 2, - Legend = legend.Name, - IsVisibleInLegend = true, - ChartArea = chartArea.Name, - }; - - chart.Series.Add(series1); - chart.Series[series1.Name].Points.DataBindXY(x, y); - return series1; - } - - //public static void Write(string fileName) - //{ - // if (!_enabled) { - // return; - // } - - // var modDataV3 = VectoCSVFile.Read(fileName); - - // var xfields = new[] { ModalResultField.time, ModalResultField.dist }; - - // var yfields = new[] { - // ModalResultField.v_act, ModalResultField.acc, ModalResultField.n, ModalResultField.Gear, ModalResultField.Pe_eng, - // ModalResultField.Tq_eng, ModalResultField.FCMap - // }; - - // var images = new List<Stream>(); - // try { - // foreach (var xfield in xfields) { - // var x = modDataV3.Rows.Cast<DataRow>().Select(v => v.Field<string>(xfield.GetName())).ToArray(); - - // for (var i = 1; i <= yfields.Length; i++) { - // var yfield = yfields[i - 1]; - // var y = modDataV3.Rows.Cast<DataRow>().Select(v => v.Field<string>(yfield.GetName())).ToArray(); - - // var values = string.Format("{0}|{1}", string.Join(",", x), string.Join(",", y)); - - // if (yfield == ModalResultField.v_act) { - // var y3 = - // modDataV3.Rows.Cast<DataRow>() - // .Select(v => v.Field<string>(ModalResultField.v_targ.GetName())) - // .Select(v => string.IsNullOrWhiteSpace(v) ? "0" : v); - - // values += string.Format("|{0}|{1}|0|0", string.Join(",", x), string.Join(",", y3)); - // } - - // values = values.Replace("NaN", "0"); - // if (values.Length > 14000) { - // // remove all decimal places to reduce request size - // values = Regex.Replace(values, @"\..*?,", ","); - // } - // var maxX = (int)Math.Ceiling(x.ToDouble().Max()); - // images.Add(CreateGraphStream(xfield.GetCaption(), yfield.GetCaption(), maxX, values)); - // } - // var outfileName = string.Format("{0}_{1}.png", Path.GetFileNameWithoutExtension(fileName), xfield.GetName()); - // SaveImages(outfileName, images.ToArray()); - // images.Clear(); - // } - // } finally { - // images.ForEach(x => x.Close()); - // } - //} - } + chart.Invalidate(); + chart.SaveImage(fileName, ChartImageFormat.Png); + } + return true; + } + + + private static void AddTitle(Chart chart, string titleText, string dockToChartArea) + { + var title = new Title(); + title.Text = titleText; + title.DockedToChartArea = dockToChartArea; + title.IsDockedInsideChartArea = false; + title.Font = new Font("Verdana", 18, FontStyle.Bold); + chart.Titles.Add(title); + } + + private static double[] LoadData(DataTable modDataV3, string field) + { + return modDataV3.Rows.Cast<DataRow>() + .Select(v => v.Field<string>(field).Length == 0 + ? Double.NaN + : v.Field<string>(field).ToDouble()) + .ToArray(); + } + + + private static void AlignChart(Chart chart, string chartToAlign, string chartToAlignWith) + { + chart.ChartAreas[chartToAlign].AlignWithChartArea = chartToAlignWith; + chart.ChartAreas[chartToAlign].AlignmentOrientation = AreaAlignmentOrientations.Vertical; + chart.ChartAreas[chartToAlign].AlignmentStyle = AreaAlignmentStyles.All; + } + + private static void PositionChartArea(ChartArea chartArea, float titleHeight, int i, int numCharts) + { + chartArea.Position.Auto = false; + chartArea.Position.Width = 85; + chartArea.Position.Height = (100.0f - titleHeight) / numCharts; + chartArea.Position.X = 0; + chartArea.Position.Y = (i * (100.0f - titleHeight)) / numCharts + titleHeight; + } + + private static ChartArea AddChartArea(Chart chart, string name, string axisXTitle, int xMax, int xMin, + string axisYTitle, bool discreteValues) + { + var chartArea = new ChartArea { Name = name }; + chartArea.AxisX.MajorGrid.LineColor = Color.DarkGray; + chartArea.AxisY.MajorGrid.LineColor = Color.DarkGray; + chartArea.AxisX.LabelStyle.Font = AxisLabelFont; + chartArea.AxisY.LabelStyle.Font = AxisLabelFont; + + chartArea.AxisX.Interval = xMax / 20.0; + chartArea.AxisX.Maximum = xMax; + chartArea.AxisX.Minimum = xMin; + chartArea.AxisX.MinorGrid.Enabled = true; + chartArea.AxisX.MinorGrid.Interval = (xMax - xMin) / 100.0; + chartArea.AxisX.MinorGrid.LineColor = Color.LightGray; + chartArea.AxisX.Title = axisXTitle; + chartArea.AxisX.TitleFont = AxisTitleFont; + chartArea.AxisX.RoundAxisValues(); + chartArea.AxisX.MajorTickMark.Size = 2 * 100.0f / _diagramSize.Height; + + chartArea.AxisY.Title = axisYTitle; + chartArea.AxisY.TitleFont = AxisTitleFont; + chartArea.AxisY.RoundAxisValues(); + if (discreteValues) { + chartArea.AxisY.MajorGrid.Interval = 1; + chartArea.AxisY.MinorGrid.Enabled = false; + } else { + chartArea.AxisY.MinorGrid.Enabled = true; + } + chartArea.AxisY.MinorGrid.LineColor = Color.LightGray; + chartArea.AxisY.MajorTickMark.Size = 5 * 100.0f / _diagramSize.Width; + + chart.ChartAreas.Add(chartArea); + return chartArea; + } + + private static Legend CreateLegend(Chart chart, string dockToChartArea) + { + var legend = new Legend(dockToChartArea.ToString()) { + Docking = Docking.Right, + IsDockedInsideChartArea = false, + DockedToChartArea = dockToChartArea, + Font = LegendFont, + }; + chart.Legends.Add(legend); + return legend; + } + + private static Series CreateSeries(String name, Legend legend, ChartArea chartArea, Chart chart, Color color, + double[] x, double[] y) + { + ModalResultField yfield; + var series1 = new Series { + Name = name, + ChartType = SeriesChartType.Line, + Color = color, + BorderWidth = 2, + Legend = legend.Name, + IsVisibleInLegend = true, + ChartArea = chartArea.Name, + }; + + chart.Series.Add(series1); + chart.Series[series1.Name].Points.DataBindXY(x, y); + return series1; + } + + //public static void Write(string fileName) + //{ + // if (!_enabled) { + // return; + // } + + // var modDataV3 = VectoCSVFile.Read(fileName); + + // var xfields = new[] { ModalResultField.time, ModalResultField.dist }; + + // var yfields = new[] { + // ModalResultField.v_act, ModalResultField.acc, ModalResultField.n, ModalResultField.Gear, ModalResultField.Pe_eng, + // ModalResultField.Tq_eng, ModalResultField.FCMap + // }; + + // var images = new List<Stream>(); + // try { + // foreach (var xfield in xfields) { + // var x = modDataV3.Rows.Cast<DataRow>().Select(v => v.Field<string>(xfield.GetName())).ToArray(); + + // for (var i = 1; i <= yfields.Length; i++) { + // var yfield = yfields[i - 1]; + // var y = modDataV3.Rows.Cast<DataRow>().Select(v => v.Field<string>(yfield.GetName())).ToArray(); + + // var values = string.Format("{0}|{1}", string.Join(",", x), string.Join(",", y)); + + // if (yfield == ModalResultField.v_act) { + // var y3 = + // modDataV3.Rows.Cast<DataRow>() + // .Select(v => v.Field<string>(ModalResultField.v_targ.GetName())) + // .Select(v => string.IsNullOrWhiteSpace(v) ? "0" : v); + + // values += string.Format("|{0}|{1}|0|0", string.Join(",", x), string.Join(",", y3)); + // } + + // values = values.Replace("NaN", "0"); + // if (values.Length > 14000) { + // // remove all decimal places to reduce request size + // values = Regex.Replace(values, @"\..*?,", ","); + // } + // var maxX = (int)Math.Ceiling(x.ToDouble().Max()); + // images.Add(CreateGraphStream(xfield.GetCaption(), yfield.GetCaption(), maxX, values)); + // } + // var outfileName = string.Format("{0}_{1}.png", Path.GetFileNameWithoutExtension(fileName), xfield.GetName()); + // SaveImages(outfileName, images.ToArray()); + // images.Clear(); + // } + // } finally { + // images.ForEach(x => x.Close()); + // } + //} + } } \ No newline at end of file