diff --git a/VectoCore/Models/SimulationComponent/Data/Engine/FuelConsumptionMap.cs b/VectoCore/Models/SimulationComponent/Data/Engine/FuelConsumptionMap.cs index 64bb14330ac052c23f5bfcc33294fd6d62ec63fb..439e5c3f0730cea31d2ce0bb486ccb62bdeec4c5 100644 --- a/VectoCore/Models/SimulationComponent/Data/Engine/FuelConsumptionMap.cs +++ b/VectoCore/Models/SimulationComponent/Data/Engine/FuelConsumptionMap.cs @@ -1,20 +1,48 @@ using System; +using System.Collections.Generic; +using System.Data; using System.IO; +using TUGraz.VectoCore.Utils; namespace TUGraz.VectoCore.Models.SimulationComponent.Data.Engine { + /// <summary> + /// Three columns + /// One header line + /// At least four lines with numeric values (below file header) + /// The map must cover the full engine range between full load and motoring curve. Extrapolation is not possible! + /// Columns: + /// * engine speed [1/min] + /// * engine torque [Nm] + /// * Fuel Consumption [g/h] + /// </summary> public class FuelConsumptionMap { - public static FuelConsumptionMap ReadFromFile(string fileName) + private class FuelConsumptionEntry { - return ReadFromJson(File.ReadAllText(fileName)); + public double EngineSpeed { get; set; } + public double Torque { get; set; } + public double FuelConsumption { get; set; } } - public static FuelConsumptionMap ReadFromJson(string json) + private List<FuelConsumptionEntry> entries; + + public static FuelConsumptionMap ReadFromFile(string fileName) { - //todo implement ReadFromJson - throw new NotImplementedException(); - return new FuelConsumptionMap(); + var fuelConsumptionMap = new FuelConsumptionMap(); + var data = VectoCSVReader.Read(fileName); + fuelConsumptionMap.entries = new List<FuelConsumptionEntry>(); + + //todo: catch exceptions if value format is wrong. + foreach (DataRow row in data.Rows) + { + var entry = new FuelConsumptionEntry(); + entry.EngineSpeed = row.GetDouble("engine speed"); + entry.Torque = row.GetDouble("torque"); + entry.FuelConsumption = row.GetDouble("fuel consumption"); + fuelConsumptionMap.entries.Add(entry); + } + return fuelConsumptionMap; } } } diff --git a/VectoCore/Models/SimulationComponent/Data/Engine/FullLoadCurve.cs b/VectoCore/Models/SimulationComponent/Data/Engine/FullLoadCurve.cs index c245c3f1f3c18db64640874af27aeb90610b382c..d4169f07e2c1c7fac63ee39594cd74106200895e 100644 --- a/VectoCore/Models/SimulationComponent/Data/Engine/FullLoadCurve.cs +++ b/VectoCore/Models/SimulationComponent/Data/Engine/FullLoadCurve.cs @@ -1,26 +1,49 @@ -using System; -using System.Collections.Generic; +using System.Collections.Generic; using System.Data; -using System.IO; -using System.Linq; -using System.Text; -using System.Threading.Tasks; +using TUGraz.VectoCore.Utils; namespace TUGraz.VectoCore.Models.SimulationComponent.Data.Engine { - public class FullLoadCurve - { - public static FullLoadCurve ReadFromFile(string fileName) - { - return ReadFromJson(File.ReadAllText(fileName)); - } + /// <summary> + /// Four columns + /// One header line + /// At least two lines with numeric values (below file header) + /// Columns: + /// * n engine speed [1/min] + /// * Mfull full load torque [Nm] + /// * Mdrag motoring torque [Nm] + /// * PT1 PT1 time constant [s] - public static FullLoadCurve ReadFromJson(string json) - { - //todo: implement ReadFromJson - throw new NotImplementedException(); - return new FullLoadCurve(); - } + /// </summary> + public class FullLoadCurve + { + private class FullLoadCurveEntry + { + public double EngineSpeed { get; set; } + public double TorqueFullLoad { get; set; } + public double TorqueDrag { get; set; } + public double PT1 { get; set; } + } - } + private List<FullLoadCurveEntry> entries; + + public static FullLoadCurve ReadFromFile(string fileName) + { + var fullLoadCurve = new FullLoadCurve(); + var data = VectoCSVReader.Read(fileName); + fullLoadCurve.entries = new List<FullLoadCurveEntry>(); + + //todo: catch exceptions if value format is wrong. + foreach (DataRow row in data.Rows) + { + var entry = new FullLoadCurveEntry(); + entry.EngineSpeed = row.GetDouble("n"); + entry.TorqueFullLoad = row.GetDouble("Mfull"); + entry.TorqueDrag = row.GetDouble("Mdrag"); + entry.PT1 = row.GetDouble("PT1"); + fullLoadCurve.entries.Add(entry); + } + return fullLoadCurve; + } + } } diff --git a/VectoCore/Models/SimulationComponent/Data/EngineOnlyDrivingCycle.cs b/VectoCore/Models/SimulationComponent/Data/EngineOnlyDrivingCycle.cs index a0f56e66a11c1f852e91a5f33d4d297548e31170..34493133b70cd6edbc186b3227bf2dd8c5a684a7 100644 --- a/VectoCore/Models/SimulationComponent/Data/EngineOnlyDrivingCycle.cs +++ b/VectoCore/Models/SimulationComponent/Data/EngineOnlyDrivingCycle.cs @@ -1,35 +1,52 @@ using System; using System.Collections.Generic; using System.Data; +using TUGraz.VectoCore.Utils; namespace TUGraz.VectoCore.Models.SimulationComponent.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 { /// <summary> /// Engine Speed /// </summary> - public double n { get; set; } + public double EngineSpeed { get; set; } /// <summary> /// Torque /// </summary> /// <remarks>Column "Me" in data file.</remarks> - public double T { get; set; } + public double Torque { get; set; } /// <summary> /// Engine power /// </summary> - public double Pe + public double PowerEngine { - get { return 2.0 * Math.PI / 60.0 * T * n; } - set { T = 60.0 / (2.0 * Math.PI) * value / n; } + get { return 2.0 * Math.PI / 60.0 * Torque * EngineSpeed; } + set { Torque = 60.0 / (2.0 * Math.PI) * value / EngineSpeed; } } - public static List<EngineOnlyDrivingCycle> Read(string fileName) + /// <summary> + /// Additional power demand (aux) (Optional). + /// </summary> + public double Padd { get; set; } + + public static List<EngineOnlyDrivingCycle> ReadFromFile(string fileName) { var data = VectoCSVReader.Read(fileName); @@ -39,15 +56,18 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Data foreach (DataRow row in data.Rows) { var cycle = new EngineOnlyDrivingCycle(); - cycle.n = double.Parse(row.Field<string>("n")); + cycle.EngineSpeed = row.GetDouble("n"); if (data.Columns.Contains("Pe")) - cycle.Pe = double.Parse(row.Field<string>("Pe")); + cycle.PowerEngine = row.GetDouble("Pe"); else - cycle.T = double.Parse(row.Field<string>("Me")); + cycle.Torque = row.GetDouble("Me"); + + if (data.Columns.Contains("Padd")) + cycle.Padd = row.GetDouble("Padd"); + cycles.Add(cycle); } - return cycles; } } diff --git a/VectoCore/Models/SimulationComponent/Data/VectoCSVReader.cs b/VectoCore/Models/SimulationComponent/Data/VectoCSVReader.cs index ff653117094f555253aa340ec81ec9c53a7ed5a9..d22b334d27a5977dbe7a7c7e29a9e0f5ce970669 100644 --- a/VectoCore/Models/SimulationComponent/Data/VectoCSVReader.cs +++ b/VectoCore/Models/SimulationComponent/Data/VectoCSVReader.cs @@ -13,9 +13,14 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Data /// <param name="fileName"></param> /// <returns>A DataTable which represents the CSV File.</returns> /// <remarks> - /// Header: All Combinations between max-format and min-format possible. Only "id"-field is used. - /// max: <id> (name) [unit], <id> (name) [unit], ... - /// min: id,id,... + /// The following format applies to all CSV (Comma-separated values) Input Files used in VECTO: + /// List Separator: Comma "," + /// Decimal-Mark: Dot "." + /// Comments: "#" at the beginning of the comment line. Number and position of comment lines is not limited. + /// Header: One header line (not a comment line) at the beginning of the file. + /// All Combinations between max-format and min-format possible. Only "id"-field is used. + /// max: <id> (name) [unit], <id> (name) [unit], ... + /// min: id,id,... /// </remarks> public static DataTable Read(string fileName) { diff --git a/VectoCore/Utils/DataRowExtensionMethods.cs b/VectoCore/Utils/DataRowExtensionMethods.cs new file mode 100644 index 0000000000000000000000000000000000000000..3c35077ae1b10611d21321cc6f07d42c71acdf3e --- /dev/null +++ b/VectoCore/Utils/DataRowExtensionMethods.cs @@ -0,0 +1,12 @@ +using System.Data; + +namespace TUGraz.VectoCore.Utils +{ + public static class DataRowExtensionMethods + { + public static double GetDouble(this DataRow row, string columnName) + { + return double.Parse(row.Field<string>(columnName)); + } + } +} \ No newline at end of file diff --git a/VectoCore/VectoCore.csproj b/VectoCore/VectoCore.csproj index 1f028bf6cf65af0f282c8f23894c1bccbf88a0b6..db298318d91b6fb208737e28928c61c691158322 100644 --- a/VectoCore/VectoCore.csproj +++ b/VectoCore/VectoCore.csproj @@ -86,6 +86,7 @@ <Compile Include="Models\SimulationComponent\SimulationComponentData.cs" /> <Compile Include="Models\SimulationComponent\VectoSimulationComponent.cs" /> <Compile Include="Properties\AssemblyInfo.cs" /> + <Compile Include="Utils\DataRowExtensionMethods.cs" /> </ItemGroup> <ItemGroup> <None Include="packages.config" /> diff --git a/VectoCoreTest/Models/SimulationComponent/CombustionEngineTest.cs b/VectoCoreTest/Models/SimulationComponent/CombustionEngineTest.cs index 4795a32cd3ac67fc0f513e6a47d285ebadaf93b1..8c68a0e0ac82494550f7af2a0ce6fa7e2d1b1737 100644 --- a/VectoCoreTest/Models/SimulationComponent/CombustionEngineTest.cs +++ b/VectoCoreTest/Models/SimulationComponent/CombustionEngineTest.cs @@ -88,7 +88,7 @@ namespace TUGraz.VectoCore.Tests.Models.SimulationComponent var engine = new CombustionEngine(engineData); var port = engine.OutShaft(); - var data = EngineOnlyDrivingCycle.Read("Coach Engine Only.vdri"); + var data = EngineOnlyDrivingCycle.ReadFromFile("Coach Engine Only.vdri"); var absTime = new TimeSpan(seconds: 0, minutes: 0, hours: 0); var dt = new TimeSpan(seconds: 1, minutes: 0, hours: 0); @@ -97,7 +97,7 @@ namespace TUGraz.VectoCore.Tests.Models.SimulationComponent foreach (var cycle in data) { - port.Request(absTime, dt, cycle.T, cycle.n); + port.Request(absTime, dt, cycle.Torque, cycle.EngineSpeed); engine.CommitSimulationStep(dataWriter); absTime += dt;