Code development platform for open source projects from the European Union institutions :large_blue_circle: EU Login authentication by SMS has been phased out. To see alternatives please check here

Skip to content
Snippets Groups Projects
Commit 8f942d65 authored by Markus Quaritsch's avatar Markus Quaritsch
Browse files

Merge pull request #30 in VECTO/vecto-sim from...

Merge pull request #30 in VECTO/vecto-sim from ~EMQUARIMA/vecto-sim:bugfix/VECTO-76-calculation-of-power-loss-of-the to develop

* commit 'cc54aaf0':
  adding addtional test-cases for engine-only simulation. results match with modified Vecto 2.0 engine-only computation
  renaming extensionMethod
  modified unit test assertion to use expected value
parents a031ca01 cc54aaf0
No related branches found
No related tags found
No related merge requests found
Showing
with 151 additions and 71 deletions
using System;
using System.Collections.Generic;
using System.Data;
using TUGraz.VectoCore.Utils;
namespace TUGraz.VectoCore.Models.Simulation.Data
{
/// <summary>
/// Class for representation of one EngineOnly Driving Cycle
/// </summary>
/// <remarks>
/// The driving cylce (.vdri) must contain:
/// <n> Engine speed
/// <Me>|<Pe> Engine torque or engine power at clutch.
///
/// Optional:
/// <Padd> Additional power demand (aux)
///
/// To explicitly define motoring operation use the <DRAG> keyword, see below.
/// VECTO replaces the keyword with the motoring torque/power from the .vfld file during calculation.
/// </remarks>
public class EngineOnlyDrivingCycle
{
private static class Fields
{
public const string PowerEngine = "Pe";
public const string PowerAuxilaries = "Padd";
public const string Torque = "Me";
public const string EngineSpeed = "n";
}
/// <summary>
/// Engine Speed
/// </summary>
public double EngineSpeed { get; set; }
/// <summary>
/// Torque
/// </summary>
/// <remarks>Column "Me" in data file.</remarks>
public double Torque { get; set; }
/// <summary>
/// Engine power
/// </summary>
public double PowerEngine
{
get { return 2.0 * Math.PI / 60.0 * Torque * EngineSpeed; }
set { Torque = 60.0 / (2.0 * Math.PI) * value / EngineSpeed; }
}
/// <summary>
/// Additional power demand (aux) (Optional).
/// </summary>
public double PowerAuxilaries { get; set; }
public static List<EngineOnlyDrivingCycle> ReadFromFile(string fileName)
{
var data = VectoCSVFile.Read(fileName);
var cycles = new List<EngineOnlyDrivingCycle>();
//todo: catch exceptions if value format is wrong.
foreach (DataRow row in data.Rows)
{
var cycle = new EngineOnlyDrivingCycle();
cycle.EngineSpeed = row.ParseDouble(Fields.EngineSpeed);
if (data.Columns.Contains(Fields.PowerEngine))
cycle.PowerEngine = row.ParseDouble(Fields.PowerEngine);
else
cycle.Torque = row.ParseDouble(Fields.Torque);
if (data.Columns.Contains(Fields.PowerAuxilaries))
cycle.PowerAuxilaries = row.ParseDouble(Fields.PowerAuxilaries);
cycles.Add(cycle);
}
return cycles;
}
}
}
...@@ -36,7 +36,7 @@ namespace TUGraz.VectoCore.Models.Simulation.Data ...@@ -36,7 +36,7 @@ namespace TUGraz.VectoCore.Models.Simulation.Data
if (col.ColumnName == ModalResultField.FC.GetName() && row.Field<string>(col) == "ERROR") if (col.ColumnName == ModalResultField.FC.GetName() && row.Field<string>(col) == "ERROR")
continue; continue;
newRow.SetField(col.ColumnName, row.GetDouble(col.ColumnName)); newRow.SetField(col.ColumnName, row.ParseDouble(col.ColumnName));
} }
modalResults.Rows.Add(newRow); modalResults.Rows.Add(newRow);
......
...@@ -3,6 +3,7 @@ using Common.Logging; ...@@ -3,6 +3,7 @@ using Common.Logging;
using TUGraz.VectoCore.Models.Simulation.Data; using TUGraz.VectoCore.Models.Simulation.Data;
using TUGraz.VectoCore.Models.SimulationComponent.Data; using TUGraz.VectoCore.Models.SimulationComponent.Data;
using TUGraz.VectoCore.Models.SimulationComponent.Impl; using TUGraz.VectoCore.Models.SimulationComponent.Impl;
using EngineOnlyDrivingCycle = TUGraz.VectoCore.Models.SimulationComponent.Impl.EngineOnlyDrivingCycle;
namespace TUGraz.VectoCore.Models.Simulation.Impl namespace TUGraz.VectoCore.Models.Simulation.Impl
{ {
......
...@@ -259,14 +259,14 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Data ...@@ -259,14 +259,14 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Data
{ {
var entry = new DrivingCycleEntry var entry = new DrivingCycleEntry
{ {
Distance = row.GetDouble(Fields.Distance), Distance = row.ParseDouble(Fields.Distance),
VehicleSpeed = row.GetDouble(Fields.VehicleSpeed), VehicleSpeed = row.ParseDouble(Fields.VehicleSpeed),
RoadGradient = row.GetDoubleOrDefault(Fields.RoadGradient), RoadGradient = row.ParseDoubleOrGetDefault(Fields.RoadGradient),
AdditionalAuxPowerDemand = row.GetDoubleOrDefault(Fields.AdditionalAuxPowerDemand), AdditionalAuxPowerDemand = row.ParseDoubleOrGetDefault(Fields.AdditionalAuxPowerDemand),
EngineSpeed = row.GetDoubleOrDefault(Fields.EngineSpeed), EngineSpeed = row.ParseDoubleOrGetDefault(Fields.EngineSpeed),
Gear = row.GetDoubleOrDefault(Fields.Gear), Gear = row.ParseDoubleOrGetDefault(Fields.Gear),
AirSpeedRelativeToVehicle = row.GetDoubleOrDefault(Fields.AirSpeedRelativeToVehicle), AirSpeedRelativeToVehicle = row.ParseDoubleOrGetDefault(Fields.AirSpeedRelativeToVehicle),
WindYawAngle = row.GetDoubleOrDefault(Fields.WindYawAngle) WindYawAngle = row.ParseDoubleOrGetDefault(Fields.WindYawAngle)
}; };
// todo: implement additional aux as dictionary! // todo: implement additional aux as dictionary!
...@@ -300,14 +300,14 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Data ...@@ -300,14 +300,14 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Data
{ {
var entry = new DrivingCycleEntry var entry = new DrivingCycleEntry
{ {
Time = row.GetDoubleOrDefault(Fields.Time), Time = row.ParseDoubleOrGetDefault(Fields.Time),
VehicleSpeed = row.GetDouble(Fields.VehicleSpeed), VehicleSpeed = row.ParseDouble(Fields.VehicleSpeed),
RoadGradient = row.GetDoubleOrDefault(Fields.RoadGradient), RoadGradient = row.ParseDoubleOrGetDefault(Fields.RoadGradient),
AdditionalAuxPowerDemand = row.GetDoubleOrDefault(Fields.AdditionalAuxPowerDemand), AdditionalAuxPowerDemand = row.ParseDoubleOrGetDefault(Fields.AdditionalAuxPowerDemand),
Gear = row.GetDoubleOrDefault(Fields.Gear), Gear = row.ParseDoubleOrGetDefault(Fields.Gear),
EngineSpeed = row.GetDoubleOrDefault(Fields.EngineSpeed), EngineSpeed = row.ParseDoubleOrGetDefault(Fields.EngineSpeed),
AirSpeedRelativeToVehicle = row.GetDoubleOrDefault(Fields.AirSpeedRelativeToVehicle), AirSpeedRelativeToVehicle = row.ParseDoubleOrGetDefault(Fields.AirSpeedRelativeToVehicle),
WindYawAngle = row.GetDoubleOrDefault(Fields.WindYawAngle) WindYawAngle = row.ParseDoubleOrGetDefault(Fields.WindYawAngle)
}; };
// todo: implement additional aux as dictionary! // todo: implement additional aux as dictionary!
...@@ -339,25 +339,25 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Data ...@@ -339,25 +339,25 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Data
{ {
var entry = new DrivingCycleEntry(); var entry = new DrivingCycleEntry();
entry.EngineSpeed = row.GetDouble(Fields.EngineSpeed); entry.EngineSpeed = row.ParseDouble(Fields.EngineSpeed);
if (row.Table.Columns.Contains(Fields.EngineTorque)) if (row.Table.Columns.Contains(Fields.EngineTorque))
{ {
if (row.Field<string>(Fields.EngineTorque).Equals("<DRAG>")) if (row.Field<string>(Fields.EngineTorque).Equals("<DRAG>"))
entry.Drag = true; entry.Drag = true;
else else
entry.EngineTorque = row.GetDouble(Fields.EngineTorque); entry.EngineTorque = row.ParseDouble(Fields.EngineTorque);
} }
else else
{ {
if (row.Field<string>(Fields.EnginePower).Equals("<DRAG>")) if (row.Field<string>(Fields.EnginePower).Equals("<DRAG>"))
entry.Drag = true; entry.Drag = true;
else else
entry.EngineTorque = VectoMath.ConvertPowerToTorque(row.GetDouble(Fields.EnginePower), entry.EngineSpeed); entry.EngineTorque = VectoMath.ConvertPowerToTorque(row.ParseDouble(Fields.EnginePower), entry.EngineSpeed);
} }
if (row.Table.Columns.Contains(Fields.AdditionalAuxPowerDemand)) if (row.Table.Columns.Contains(Fields.AdditionalAuxPowerDemand))
entry.AdditionalAuxPowerDemand = row.GetDouble(Fields.AdditionalAuxPowerDemand); entry.AdditionalAuxPowerDemand = row.ParseDouble(Fields.AdditionalAuxPowerDemand);
return entry; return entry;
} }
......
...@@ -80,9 +80,9 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Data.Engine ...@@ -80,9 +80,9 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Data.Engine
{ {
var entry = new FuelConsumptionEntry var entry = new FuelConsumptionEntry
{ {
EngineSpeed = row.GetDouble(Fields.EngineSpeed), EngineSpeed = row.ParseDouble(Fields.EngineSpeed),
Torque = row.GetDouble(Fields.Torque), Torque = row.ParseDouble(Fields.Torque),
FuelConsumption = row.GetDouble(Fields.FuelConsumption) FuelConsumption = row.ParseDouble(Fields.FuelConsumption)
}; };
if (entry.FuelConsumption < 0) if (entry.FuelConsumption < 0)
......
...@@ -81,10 +81,10 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Data.Engine ...@@ -81,10 +81,10 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Data.Engine
{ {
var entry = new FullLoadCurveEntry var entry = new FullLoadCurveEntry
{ {
EngineSpeed = row.GetDouble(Fields.EngineSpeed), EngineSpeed = row.ParseDouble(Fields.EngineSpeed),
TorqueFullLoad = row.GetDouble(Fields.TorqueFullLoad), TorqueFullLoad = row.ParseDouble(Fields.TorqueFullLoad),
TorqueDrag = row.GetDouble(Fields.TorqueDrag), TorqueDrag = row.ParseDouble(Fields.TorqueDrag),
PT1 = row.GetDouble(Fields.PT1) PT1 = row.ParseDouble(Fields.PT1)
}; };
fullLoadCurve._entries.Add(entry); fullLoadCurve._entries.Add(entry);
} }
......
...@@ -7,47 +7,13 @@ namespace TUGraz.VectoCore.Utils ...@@ -7,47 +7,13 @@ namespace TUGraz.VectoCore.Utils
{ {
public static class DataRowExtensionMethods public static class DataRowExtensionMethods
{ {
public static double GetDouble(this DataRow row, DataColumn column, CultureInfo culture = null)
{
//todo ArgumentNullException?
try
{
return double.Parse(row.Field<string>(column), CultureInfo.InvariantCulture);
}
catch (IndexOutOfRangeException e)
{
throw new VectoException(string.Format("Column {0} was not found in DataRow.", column.ColumnName), e);
}
catch (NullReferenceException e)
{
throw new VectoException(string.Format("Column {0} must not be null.", column.ColumnName), e);
}
catch (FormatException e)
{
throw new VectoException(string.Format("Column {0} is not in a valid number format: {1}", column.ColumnName,
row.Field<string>(column)), e);
}
catch (OverflowException e)
{
throw new VectoException(string.Format("Column {0} has a value too high or too low: {1}", column.ColumnName,
row.Field<string>(column)), e);
}
catch (ArgumentNullException e)
{
throw new VectoException(string.Format("Column {0} contains null which cannot be converted to a number.", column.ColumnName), e);
}
catch (Exception e)
{
throw new VectoException(string.Format("Column {0}: {1}", column.ColumnName, e.Message), e);
}
}
public static double GetDoubleOrDefault(this DataRow row, string columnName) public static double ParseDoubleOrGetDefault(this DataRow row, string columnName)
{ {
return row.Table.Columns.Contains(columnName) ? row.GetDouble(columnName) : default(double); return row.Table.Columns.Contains(columnName) ? row.ParseDouble(columnName) : default(double);
} }
public static double GetDouble(this DataRow row, string columnName, CultureInfo culture = null) public static double ParseDouble(this DataRow row, string columnName, CultureInfo culture = null)
{ {
//todo ArgumentNullException? //todo ArgumentNullException?
try try
......
...@@ -82,6 +82,7 @@ ...@@ -82,6 +82,7 @@
<Compile Include="Models\SimulationComponent\IDrivingCycle.cs" /> <Compile Include="Models\SimulationComponent\IDrivingCycle.cs" />
<Compile Include="Models\SimulationComponent\Impl\DistanceBasedDrivingCycle.cs" /> <Compile Include="Models\SimulationComponent\Impl\DistanceBasedDrivingCycle.cs" />
<Compile Include="Models\SimulationComponent\Impl\TimeBasedDrivingCycle.cs" /> <Compile Include="Models\SimulationComponent\Impl\TimeBasedDrivingCycle.cs" />
<Compile Include="Models\Simulation\Data\EngineOnlyDrivingCycle.cs" />
<Compile Include="Utils\IMemento.cs" /> <Compile Include="Utils\IMemento.cs" />
<Compile Include="Models\SimulationComponent\Impl\CombustionEngine.cs" /> <Compile Include="Models\SimulationComponent\Impl\CombustionEngine.cs" />
<Compile Include="Models\SimulationComponent\Impl\EngineOnlyGearbox.cs" /> <Compile Include="Models\SimulationComponent\Impl\EngineOnlyGearbox.cs" />
......
...@@ -6,6 +6,7 @@ using TUGraz.VectoCore.Models.SimulationComponent; ...@@ -6,6 +6,7 @@ using TUGraz.VectoCore.Models.SimulationComponent;
using TUGraz.VectoCore.Models.SimulationComponent.Data; using TUGraz.VectoCore.Models.SimulationComponent.Data;
using TUGraz.VectoCore.Models.SimulationComponent.Impl; using TUGraz.VectoCore.Models.SimulationComponent.Impl;
using TUGraz.VectoCore.Tests.Utils; using TUGraz.VectoCore.Tests.Utils;
using EngineOnlyDrivingCycle = TUGraz.VectoCore.Models.SimulationComponent.Impl.EngineOnlyDrivingCycle;
namespace TUGraz.VectoCore.Tests.Models.Simulation namespace TUGraz.VectoCore.Tests.Models.Simulation
{ {
......
using System; using System;
using System.IO; using System.IO;
using System.Reflection; using System.Reflection;
using System.Data;
using Microsoft.VisualStudio.TestTools.UnitTesting; using Microsoft.VisualStudio.TestTools.UnitTesting;
using TUGraz.VectoCore.Models.Simulation.Data; using TUGraz.VectoCore.Models.Simulation.Data;
using TUGraz.VectoCore.Models.Simulation.Impl; using TUGraz.VectoCore.Models.Simulation.Impl;
...@@ -80,14 +81,35 @@ namespace TUGraz.VectoCore.Tests.Models.SimulationComponent ...@@ -80,14 +81,35 @@ namespace TUGraz.VectoCore.Tests.Models.SimulationComponent
absTime += dt; absTime += dt;
} }
port.Request(absTime, dt, VectoMath.ConvertPowerToTorque(2329.973, 644.4445), 644.4445); engineSpeed = 644.4445;
port.Request(absTime, dt, VectoMath.ConvertPowerToTorque(2329.973, engineSpeed), engineSpeed);
engine.CommitSimulationStep(dataWriter); engine.CommitSimulationStep(dataWriter);
absTime += dt;
Assert.AreEqual(1152.40304, dataWriter.GetDouble(ModalResultField.PaEng), 0.001);
torque = 4264.177;
for (var i = 0; i < 2; i++) {
port.Request(absTime, dt, torque, engineSpeed);
engine.CommitSimulationStep(dataWriter);
absTime += dt;
}
engineSpeed = 869.7512;
port.Request(absTime, dt, VectoMath.ConvertPowerToTorque(7984.56, engineSpeed), engineSpeed);
engine.CommitSimulationStep(dataWriter);
absTime += dt;
Assert.AreEqual(7108.32, dataWriter.GetDouble(ModalResultField.PaEng), 0.001);
engineSpeed = 644.4445;
port.Request(absTime, dt, VectoMath.ConvertPowerToTorque(7984.56, engineSpeed), engineSpeed);
engine.CommitSimulationStep(dataWriter);
absTime += dt;
Assert.AreEqual(-7108.32, dataWriter.GetDouble(ModalResultField.PaEng), 0.001);
//todo: test with correct output values, add other fields to test
//Assert.AreEqual(dataWriter[ModalResultField.FC], 13000);
//Assert.AreEqual(dataWriter[ModalResultField.FCAUXc], 14000);
//Assert.AreEqual(dataWriter[ModalResultField.FCWHTCc], 15000);
Assert.AreEqual(1152.40304, Double.Parse(dataWriter[ModalResultField.PaEng].ToString()), 0.001);
} }
[DataSource("Microsoft.VisualStudio.TestTools.DataSource.CSV", "|DataDirectory|\\TestData\\EngineTests.csv", "EngineTests#csv", DataAccessMethod.Sequential)] [DataSource("Microsoft.VisualStudio.TestTools.DataSource.CSV", "|DataDirectory|\\TestData\\EngineTests.csv", "EngineTests#csv", DataAccessMethod.Sequential)]
......
using System.Data; using System.Data;
using TUGraz.VectoCore.Models.Simulation.Data; using TUGraz.VectoCore.Models.Simulation.Data;
using TUGraz.VectoCore.Utils;
namespace TUGraz.VectoCore.Tests.Utils namespace TUGraz.VectoCore.Tests.Utils
{ {
...@@ -33,5 +34,11 @@ namespace TUGraz.VectoCore.Tests.Utils ...@@ -33,5 +34,11 @@ namespace TUGraz.VectoCore.Tests.Utils
get { return CurrentRow[key.GetName()]; } get { return CurrentRow[key.GetName()]; }
set { CurrentRow[key.GetName()] = value; } set { CurrentRow[key.GetName()] = value; }
} }
public double GetDouble(ModalResultField key)
{
return CurrentRow.Field<double>(key.GetName());
}
} }
} }
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment