diff --git a/VectoCore/VectoCore/Models/Simulation/Data/ModalResult.cs b/VectoCore/VectoCore/Models/Simulation/Data/ModalResult.cs index 93489234bc60aec2c8c855e5a8900aa73a54f590..4ea5b71e6f8ca6f384ed305a89d1746b00549a30 100644 --- a/VectoCore/VectoCore/Models/Simulation/Data/ModalResult.cs +++ b/VectoCore/VectoCore/Models/Simulation/Data/ModalResult.cs @@ -438,7 +438,9 @@ namespace TUGraz.VectoCore.Models.Simulation.Data var entry = BatteryColumns.GetOrAdd(idx, _ => new Dictionary<ModalResultField, DataColumn>()); foreach (var key in BatterySignals) { entry.GetOrAdd(key, _ => { - var c = Columns.Add($"{key.GetName()}_{idx}", typeof(SI)); + var c = Columns.Add($"{key.GetName()}_{idx}", + typeof(SI)); + c.Caption = key.GetCaption("_" + idx.ToString()); c.ExtendedProperties[ModalResults.ExtendedPropertyNames.Decimals] = key.GetAttribute().Decimals; c.ExtendedProperties[ModalResults.ExtendedPropertyNames.OutputFactor] = key.GetAttribute().OutputFactor; diff --git a/VectoCore/VectoCore/Models/Simulation/Data/ModalResultField.cs b/VectoCore/VectoCore/Models/Simulation/Data/ModalResultField.cs index a4d1cf384ef8b9ea10ef96384da0158112963197..b5f91fae1e4be629381085bd5a21f30036624f0e 100644 --- a/VectoCore/VectoCore/Models/Simulation/Data/ModalResultField.cs +++ b/VectoCore/VectoCore/Models/Simulation/Data/ModalResultField.cs @@ -32,6 +32,7 @@ using System; using System.Collections.Concurrent; using System.Reflection; +using System.Security.Policy; using System.Text.RegularExpressions; using TUGraz.VectoCommon.Utils; using TUGraz.VectoCore.Models.Simulation.DataBus; @@ -274,6 +275,7 @@ namespace TUGraz.VectoCore.Models.Simulation.Data /// [kW] Power demand of Auxiliary with ID xxx. See also Aux Dialog and Driving Cycle. /// </summary> [ModalResultField(typeof(SI), caption: "P_aux_{0} [kW]", outputFactor: 1e-3)] P_aux_, + [ModalResultField(typeof(SI), caption: "P_aux_{0}_el [kW]", outputFactor: 1e-3)] P_aux_el_, /// Bus Aux Data [ModalResultField(typeof(SI), caption: "P_busAux_ES_HVAC [kW]", outputFactor: 1e-3)] P_busAux_ES_HVAC, @@ -451,15 +453,15 @@ namespace TUGraz.VectoCore.Models.Simulation.Data // --> - [ModalResultField(typeof(SI), caption: "P_REESS_T [kW]", outputFactor: 1e-3)] P_reess_terminal, - [ModalResultField(typeof(SI), caption: "P_REESS_int [kW]", outputFactor: 1e-3)] P_reess_int, - [ModalResultField(typeof(SI), caption: "P_REESS_loss [kW]", outputFactor: 1e-3)] P_reess_loss, - [ModalResultField(typeof(SI), caption: "REESS SOC [%]", outputFactor: 100)] REESSStateOfCharge, - [ModalResultField(typeof(SI), caption: "P_REESS_charge_max [kW]", outputFactor: 1e-3)] P_reess_charge_max, - [ModalResultField(typeof(SI), caption: "P_REESS_discharge_max [kW]", outputFactor: 1e-3)] P_reess_discharge_max, - [ModalResultField(typeof(SI), caption: "U_REESS_terminal [V]")] U_reess_terminal, - [ModalResultField(typeof(SI), caption: "U_0_REESS [V]")] U0_reess, - [ModalResultField(typeof(SI), caption: "I_REESS [A]")] I_reess, + [ModalResultField(typeof(SI), caption: "P_REESS_T [kW]", outputFactor: 1e-3, showUnit: true)] P_reess_terminal, + [ModalResultField(typeof(SI), caption: "P_REESS_int [kW]", outputFactor: 1e-3, showUnit: true)] P_reess_int, + [ModalResultField(typeof(SI), caption: "P_REESS_loss [kW]", outputFactor: 1e-3, showUnit: true)] P_reess_loss, + [ModalResultField(typeof(SI), caption: "REESS SOC [%]", outputFactor: 100, showUnit: true)] REESSStateOfCharge, + [ModalResultField(typeof(SI), caption: "P_REESS_charge_max [kW]", outputFactor: 1e-3, showUnit: true)] P_reess_charge_max, + [ModalResultField(typeof(SI), caption: "P_REESS_discharge_max [kW]", outputFactor: 1e-3, showUnit:true)] P_reess_discharge_max, + [ModalResultField(typeof(SI), caption: "U_REESS_terminal [V]", showUnit:true)] U_reess_terminal, + [ModalResultField(typeof(SI), caption: "U_0_REESS [V]", showUnit:true)] U0_reess, + [ModalResultField(typeof(SI), caption: "I_REESS [A]", showUnit: true)] I_reess, [ModalResultField(typeof(SI), caption: "T_max_propulsion [Nm]")] MaxPropulsionTorqe, [ModalResultField(typeof(SI), caption: "P_DC/DC_In [kW]", outputFactor: 1e-3)] P_DCDC_In, @@ -500,10 +502,21 @@ namespace TUGraz.VectoCore.Models.Simulation.Data return GetAttribute(field).Name ?? field.ToString(); } - public static string GetCaption(this ModalResultField field) + + public static string GetCaption(this ModalResultField field, string suffix = null) { var attribute = GetAttribute(field); - return attribute.Caption ?? attribute.Name ?? field.ToString(); + if (suffix != null) { + var captionNoUnit = field.GetShortCaption(); + var captionUnit = field.GetCaption(); + var captionWithSuffix = captionUnit.Replace(captionNoUnit, captionNoUnit + suffix); + + return captionWithSuffix; + } else { + return attribute.Caption ?? attribute.Name ?? field.ToString(); + } + + } public static string GetShortCaption(this ModalResultField field) @@ -512,6 +525,7 @@ namespace TUGraz.VectoCore.Models.Simulation.Data return Regex.Replace(caption, @"\[.*?\]|\<|\>", "").Trim(); } + public static Type GetDataType(this ModalResultField field) { return GetAttribute(field).DataType; diff --git a/VectoCore/VectoCore/Models/SimulationComponent/Impl/Auxiliaries/ElectricAuxiliaries.cs b/VectoCore/VectoCore/Models/SimulationComponent/Impl/Auxiliaries/ElectricAuxiliaries.cs index 9cea019940a510dc051cc24a6cdd8d089a8704be..2d949c722530d35aac4c5be6cfe65b4f1cbe62ce 100644 --- a/VectoCore/VectoCore/Models/SimulationComponent/Impl/Auxiliaries/ElectricAuxiliaries.cs +++ b/VectoCore/VectoCore/Models/SimulationComponent/Impl/Auxiliaries/ElectricAuxiliaries.cs @@ -55,9 +55,10 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl { foreach (var auxId in _auxData.Keys) { - var name = $"P_{auxId}_el [kW]"; - _auxColumnName.Add(auxId, name); //use column name as ID - VehicleContainer.AddAuxiliary(name, name); + var id = $"{auxId}_el"; + + _auxColumnName.Add(auxId, id); //use column name as ID + VehicleContainer.AddAuxiliary(id); } diff --git a/VectoCore/VectoCore/OutputData/SummaryDataContainer.cs b/VectoCore/VectoCore/OutputData/SummaryDataContainer.cs index 5deb15736aeea2537ea4cc7e07e57b009756d155..9b394ce388ff03c2925afa1f43e881775ac1ecac 100644 --- a/VectoCore/VectoCore/OutputData/SummaryDataContainer.cs +++ b/VectoCore/VectoCore/OutputData/SummaryDataContainer.cs @@ -564,9 +564,11 @@ namespace TUGraz.VectoCore.OutputData SumDataFields.AXLE_RATIO }); cols.AddRange(new[] { - Constants.Auxiliaries.IDs.SteeringPump, Constants.Auxiliaries.IDs.Fan, + Constants.Auxiliaries.IDs.SteeringPump, + Constants.Auxiliaries.IDs.Fan, Constants.Auxiliaries.IDs.HeatingVentilationAirCondition, - Constants.Auxiliaries.IDs.PneumaticSystem, Constants.Auxiliaries.IDs.ElectricSystem + Constants.Auxiliaries.IDs.PneumaticSystem, + Constants.Auxiliaries.IDs.ElectricSystem }.Select(x => string.Format(SumDataFields.AUX_TECH_FORMAT, x))); cols.AddRange(new[] { diff --git a/VectoCore/VectoCoreTest/Integration/Declaration/HeavyLorry/HeavyLorrySimulation.cs b/VectoCore/VectoCoreTest/Integration/Declaration/HeavyLorry/HeavyLorrySimulation.cs index 71b9e347951f84ee09f6a755dccb4c18306381f8..0ead6a76cd078958ab2ec9964e052069741833f1 100644 --- a/VectoCore/VectoCoreTest/Integration/Declaration/HeavyLorry/HeavyLorrySimulation.cs +++ b/VectoCore/VectoCoreTest/Integration/Declaration/HeavyLorry/HeavyLorrySimulation.cs @@ -2,13 +2,19 @@ //#define singlethreaded +using System; +using System.Collections.Generic; using System.Collections.Immutable; +using System.Data; using System.IO; using System.Linq; +using System.Text.RegularExpressions; using Ninject; using NUnit.Framework; +using TUGraz.VectoCommon.Exceptions; using TUGraz.VectoCommon.InputData; using TUGraz.VectoCommon.Models; +using TUGraz.VectoCommon.Utils; using TUGraz.VectoCore.Configuration; using TUGraz.VectoCore.InputData.FileIO.XML; using TUGraz.VectoCore.InputData.FileIO.XML.Declaration; @@ -20,6 +26,8 @@ using TUGraz.VectoCore.Models.Simulation.Impl.SimulatorFactory; using TUGraz.VectoCore.OutputData; using TUGraz.VectoCore.OutputData.FileIO; using TUGraz.VectoCore.Tests.Models.Simulation; +using TUGraz.VectoCore.Tests.Utils; +using TUGraz.VectoCore.Utils; namespace TUGraz.VectoCore.Tests.Integration.Declaration.HeavyLorry; @@ -33,8 +41,8 @@ public class HeavyLorrySimulation private const string BASE_DIR = @"TestData\Integration\DeclarationMode\V24_DeclarationMode\"; - private const string HeavylorryGroup2HevS2XML = @"HeavyLorry\Group2_HEV_S2.xml"; - private const string HeavylorryGroup2HevS4XML = @"HeavyLorry\Group2_HEV_S4.xml"; + private const string HeavylorryGroup2HevS2XML = @"HeavyLorry\S-HEV\Group2_HEV_S2.xml"; + private const string HeavylorryGroup2HevS4XML = @"HeavyLorry\S-HEV\Group2_HEV_S4.xml"; private StandardKernel _kernel; private IXMLInputDataReader _xmlReader; @@ -100,6 +108,75 @@ public class HeavyLorrySimulation } + [TestCase(@"HeavyLorry\S-HEV\Group2_HEV_S2_ovc.xml")] + public void VMOD_VSUMUnitTest(string jobFile) + { + var columnsWithoutUnit = new List<ModalResultField> { + ModalResultField.ICEOn, + ModalResultField.EM_Off_, + ModalResultField.HybridStrategyScore, + ModalResultField.HybridStrategySolution, + }.Select(m => m.GetCaption()); + + + // .ToHashSet(); + + var filePath = Path.Combine(BASE_DIR, jobFile); + SummaryDataContainer sumDataContainer; + var jobContainer = GetJobContainer(jobFile, null, out var fileWriter, out var runs, out sumDataContainer); + + var run = runs.First(); + jobContainer.AddRun(run); + //run.GetContainer().ModalData.Finish(runStatus:VectoRun.Status.Success, null); + run.GetContainer().FinishSingleSimulationRun(null); + var modFileName = fileWriter.GetModDataFileName(run.RunName, run.CycleName, run.RunSuffix); + + var sumFileName = fileWriter.SumFileName; + Assert.IsTrue(File.Exists(modFileName)); + var mod = VectoCSVFile.Read(modFileName, false, true); + + var columnsWithoutUnitHashSet = new HashSet<string>(); + foreach (var col in columnsWithoutUnit) { + var emPositions = run.GetContainer().PowertrainInfo.ElectricMotorPositions; + foreach (var emPosition in emPositions) { + columnsWithoutUnitHashSet.Add(string.Format(col, emPosition.GetLabel())); + } + } + + + List<string> columnHeaders = new List<string>(); + foreach (DataColumn modColumn in mod.Columns) { + columnHeaders.Add(modColumn.Caption); + } + + + var unitColumnHeaders = columnHeaders.Where(h => !columnsWithoutUnitHashSet.Contains(h)); + foreach (string header in unitColumnHeaders) { + TestContext.WriteLine(header); + } + foreach (string header in unitColumnHeaders) { + var regex = new Regex(@"\[\S+\]"); + Assert.AreEqual(1, regex.Matches(header).Count(), $"missing unit {header}"); + } + + + var sumCols = new List<string>(); + TestContext.WriteLine("\n -----------------------SumFile captions----------------------------- \n"); + foreach (DataColumn col in sumDataContainer.Table.Columns) { + var caption = col.Caption; + sumCols.Add(caption); + TestContext.WriteLine(caption); + } + foreach (string sumHeader in sumCols) + { + var regex = new Regex(@"\[\S+\]"); + Assert.IsTrue(regex.Matches(sumHeader).Count() <= 1, $"double units {sumHeader}"); + } + + + + } + [Test] public void HEVS4() { @@ -127,55 +204,127 @@ public class HeavyLorrySimulation //Assume.That(ps.PowerDemandMech != ps.PowerDemandElectric * DeclarationData.AlternatorEfficiency); Assert.That(ps.ConnectToREESS); - - + } + [TestCase(@"HeavyLorry\S-HEV\Group2_HEV_S4_invalid_pto.xml")] + public void PTOWithoutTransmissionTest(string jobFile) + { + SummaryDataContainer sumDataContainer; + var exception = Assert.Throws<VectoException>(() => GetJobContainer(jobFile, null, out var fileWriter, out var runs, out sumDataContainer)); + TestContext.WriteLine(exception.Message); } + [TestCase(@"HeavyLorry\S-HEV\Group2_HEV_S2_ovc.xml", 12)] + [TestCase(@"HeavyLorry\S-HEV\Group2_HEV_S3_ovc.xml", 12)] + public void HEV_ChargeDepleting(string jobFile, int nrRuns) + { + SummaryDataContainer sumDataContainer; + var jobContainer = GetJobContainer(jobFile, nrRuns, out var fileWriter, out var runs, out sumDataContainer); + + Assert.AreEqual(runs.Count(r => r.GetContainer().RunData.OVCMode == VectoRunData.OvcHevMode.ChargeDepleting), + runs.Count(r => r.GetContainer().RunData.OVCMode == VectoRunData.OvcHevMode.ChargeSustaining)); + Assert.AreEqual(0, runs.Count(r => r.GetContainer().RunData.OVCMode == VectoRunData.OvcHevMode.NotApplicable)); - [TestCase(@"HeavyLorry\HEV_heavy_lorry_S4_ovc.xml", 12)] - [TestCase(HeavylorryGroup2HevS2XML, 6)] - [TestCase(@"HeavyLorry\Group5_HEV_P3_ovc.xml", 20)] - public void OVCHevSimulationSingleRun(string jobFile, int nrRuns) - { - var filePath = Path.Combine(BASE_DIR, jobFile); - var dataProvider = _xmlReader.CreateDeclaration(filePath); - var fileWriter = new FileOutputWriter(filePath); - var runsFactory = SimulatorFactory.CreateSimulatorFactory(ExecutionMode.Declaration, dataProvider, fileWriter); - runsFactory.WriteModalResults = true; - var sumWriter = new MockSumWriter(); - var jobContainer = new JobContainer(sumWriter); - runsFactory.SumData = sumWriter; - var runs = runsFactory.SimulationRuns().ToList(); - Assert.AreEqual(nrRuns, runs.Count); + runs = runs.Where(run => { + var rd = run.GetContainer().RunData; + return rd.OVCMode == VectoRunData.OvcHevMode.ChargeDepleting && + rd.Mission.MissionType == MissionType.UrbanDelivery && rd.Loading == LoadingType.ReferenceLoad; + }).ToList(); + jobContainer.AddRun(runs.Single()); - jobContainer.AddRun(runs.First(r => r.GetContainer().RunData.BatteryData.Batteries.Any(tuple => !tuple.Item2.ChargeSustainingBattery))); Assert.AreEqual(1, jobContainer.Runs.Count); - jobContainer.Execute(false); - - jobContainer.WaitFinished(); - Assert.IsTrue(jobContainer.AllCompleted); - Assert.IsTrue(jobContainer.Runs.TrueForAll(runEntry => runEntry.Success)); - PrintRuns(jobContainer, fileWriter); - PrintFiles(fileWriter); + var modData = ((ModalDataContainer)((VehicleContainer)runs.Single().GetContainer()).ModData).Data; + jobContainer.Execute(false); + WaitAndAssertSuccess(jobContainer, fileWriter); + var soc = modData.Rows[0].Field<Scalar>(ModalResultField.REESSStateOfCharge.GetName()); + foreach (DataRow modDataRow in modData.Rows) { + Assert.AreEqual(soc, modDataRow.Field<Scalar>(ModalResultField.REESSStateOfCharge.GetName())); + Assert.IsFalse(modDataRow.Field<bool>(ModalResultField.ICEOn.GetName())); + } + Assert.IsTrue(modData.Rows.Count > 0); } + [TestCase(@"HeavyLorry\S-HEV\Group2_HEV_S2_pto_transmission.xml", 6)] + public void SHEV_PTO_Transmission(string jobFile, int nrRuns) + { + SummaryDataContainer sumDataContainer; + var jobContainer = GetJobContainer(jobFile, nrRuns, out var fileWriter, out var runs, out sumDataContainer); - + Assert.AreEqual(0, runs.Count(r => r.GetContainer().RunData.OVCMode == VectoRunData.OvcHevMode.NotApplicable)); + Assert.AreEqual(6, runs.Count(r => r.GetContainer().RunData.OVCMode == VectoRunData.OvcHevMode.ChargeSustaining)); + Assert.AreEqual(0, runs.Count(r => r.GetContainer().RunData.OVCMode == VectoRunData.OvcHevMode.ChargeDepleting)); + runs = runs.Where(run => { + var rd = run.GetContainer().RunData; + return rd.Mission.MissionType == MissionType.LongHaul && rd.Loading == LoadingType.ReferenceLoad; + }).ToList(); + jobContainer.AddRun(runs.Single()); + Assert.AreEqual(1, jobContainer.Runs.Count); + var modDataContainer = ((ModalDataContainer)((VehicleContainer)runs.Single().GetContainer()).ModData); + var modData = modDataContainer.Data; + var aux = modDataContainer.Auxiliaries.ToDictionary(entry => entry.Key, entry => entry.Value); + + + jobContainer.Execute(false); + WaitAndAssertSuccess(jobContainer, fileWriter); + + + modDataContainer.Data = modData; + modDataContainer.Auxiliaries = aux; + //modDataContainer.GetValues<double>(ModalResultField + + var soc = modData.Rows[0].Field<Scalar>(ModalResultField.REESSStateOfCharge.GetName()); + + var ptoTransm = modDataContainer[Constants.Auxiliaries.IDs.PTOTransmission]; + Assert.IsNotNull(ptoTransm); + //modData. + foreach (DataRow modDataRow in modData.Rows) + { + + } + Assert.IsTrue(modData.Rows.Count > 0); + } + [TestCase(@"HeavyLorry\S-HEV")] + private void WaitAndAssertSuccess(JobContainer jobContainer, FileOutputWriter fileWriter) + { + jobContainer.WaitFinished(); + Assert.IsTrue(jobContainer.AllCompleted); + Assert.IsTrue(jobContainer.Runs.TrueForAll(runEntry => runEntry.Success)); + PrintRuns(jobContainer, fileWriter); + PrintFiles(fileWriter); + } + private JobContainer GetJobContainer(string jobFile, int? nrRuns, out FileOutputWriter fileWriter, + out List<IVectoRun> runs, out SummaryDataContainer sumDataContainer) + { + var filePath = Path.Combine(BASE_DIR, jobFile); + var dataProvider = _xmlReader.CreateDeclaration(filePath); + fileWriter = new FileOutputWriter(filePath); + var runsFactory = SimulatorFactory.CreateSimulatorFactory(ExecutionMode.Declaration, dataProvider, fileWriter); + runsFactory.WriteModalResults = true; + var sumWriter = new MockSumWriter(); + + var jobContainer = new JobContainer(sumWriter); + runsFactory.SumData = sumWriter; + sumDataContainer = sumWriter; + runs = runsFactory.SimulationRuns().ToList(); + if (nrRuns.HasValue) { + Assert.AreEqual(nrRuns, runs.Count); + } + return jobContainer; + } private void PrintRuns(JobContainer jobContainer, FileOutputWriter fileWriter = null)