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 4d099c59 authored by Markus Quaritsch's avatar Markus Quaritsch
Browse files

gearbox fullload curve has only two columns

parent 54f55ee0
Branches
Tags
No related merge requests found
...@@ -16,8 +16,9 @@ ...@@ -16,8 +16,9 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Data; using System.Data;
using System.Diagnostics.Contracts;
using System.Dynamic;
using System.Linq; using System.Linq;
using TUGraz.VectoCore.Utils; using TUGraz.VectoCore.Utils;
...@@ -33,15 +34,53 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Data.Engine ...@@ -33,15 +34,53 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Data.Engine
private PerSecond _engineSpeedHi; // 70% of Pmax private PerSecond _engineSpeedHi; // 70% of Pmax
private PerSecond _n95hSpeed; // 95% of Pmax private PerSecond _n95hSpeed; // 95% of Pmax
[Required] public static EngineFullLoadCurve ReadFromFile(string fileName, bool declarationMode = false)
{
var curve = FullLoadCurve.ReadFromFile(fileName, declarationMode, true);
return new EngineFullLoadCurve { FullLoadEntries = curve.FullLoadEntries, PT1Data = curve.PT1Data };
}
public static EngineFullLoadCurve Create(DataTable data, bool declarationMode = false)
{
var curve = FullLoadCurve.Create(data, declarationMode, true);
return new EngineFullLoadCurve() { FullLoadEntries = curve.FullLoadEntries, PT1Data = curve.PT1Data };
}
public Watt FullLoadStationaryPower(PerSecond angularVelocity)
{
return Formulas.TorqueToPower(FullLoadStationaryTorque(angularVelocity), angularVelocity);
}
public Watt DragLoadStationaryPower(PerSecond angularVelocity)
{
Contract.Requires(angularVelocity.HasEqualUnit(new SI().Radian.Per.Second));
Contract.Ensures(Contract.Result<SI>().HasEqualUnit(new SI().Watt));
return Formulas.TorqueToPower(DragLoadStationaryTorque(angularVelocity), angularVelocity);
}
public CombustionEngineData EngineData { get; internal set; } public CombustionEngineData EngineData { get; internal set; }
public Second PT1(PerSecond angularVelocity)
{
return PT1Data.Lookup(angularVelocity);
}
/// <summary> /// <summary>
/// Get the engine's preferred speed from the given full-load curve (i.e. Speed at 51% torque/speed-integral between idling and N95h.) /// Get the engine's preferred speed from the given full-load curve (i.e. Speed at 51% torque/speed-integral between idling and N95h.)
/// </summary> /// </summary>
public PerSecond PreferredSpeed public PerSecond PreferredSpeed
{ {
get { return _preferredSpeed ?? (_preferredSpeed = ComputePreferredSpeed()); } get
{
if (_preferredSpeed == null) {
ComputePreferredSpeed();
}
return _preferredSpeed;
}
} }
public PerSecond N95hSpeed public PerSecond N95hSpeed
...@@ -49,6 +88,7 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Data.Engine ...@@ -49,6 +88,7 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Data.Engine
get { return _n95hSpeed ?? (_n95hSpeed = FindEngineSpeedForPower(0.95 * MaxPower).Last()); } get { return _n95hSpeed ?? (_n95hSpeed = FindEngineSpeedForPower(0.95 * MaxPower).Last()); }
} }
public PerSecond LoSpeed public PerSecond LoSpeed
{ {
get { return _engineSpeedLo ?? (_engineSpeedLo = FindEngineSpeedForPower(0.55 * MaxPower).First()); } get { return _engineSpeedLo ?? (_engineSpeedLo = FindEngineSpeedForPower(0.55 * MaxPower).First()); }
...@@ -59,6 +99,7 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Data.Engine ...@@ -59,6 +99,7 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Data.Engine
get { return _engineSpeedHi ?? (_engineSpeedHi = FindEngineSpeedForPower(0.7 * MaxPower).Last()); } get { return _engineSpeedHi ?? (_engineSpeedHi = FindEngineSpeedForPower(0.7 * MaxPower).Last()); }
} }
public NewtonMeter MaxLoadTorque public NewtonMeter MaxLoadTorque
{ {
get { return FullLoadEntries.Max(x => x.TorqueFullLoad); } get { return FullLoadEntries.Max(x => x.TorqueFullLoad); }
...@@ -69,44 +110,8 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Data.Engine ...@@ -69,44 +110,8 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Data.Engine
get { return FullLoadEntries.Min(x => x.TorqueDrag); } get { return FullLoadEntries.Min(x => x.TorqueDrag); }
} }
/// <summary>
/// Reads the EngineFullLoadCurve from a csv file.
/// </summary>
/// <param name="fileName">Name of the file.</param>
/// <param name="declarationMode">if set to <c>true</c> then the file is read in declaration mode.</param>
public new static EngineFullLoadCurve ReadFromFile(string fileName, bool declarationMode = false)
{
var curve = FullLoadCurve.ReadFromFile(fileName, declarationMode);
return new EngineFullLoadCurve { FullLoadEntries = curve.FullLoadEntries, PT1Data = curve.PT1Data };
}
/// <summary>
/// Creates the FullLoadCurve from a datatable.
/// </summary>
/// <param name="data">The data.</param>
/// <param name="declarationMode">if set to <c>true</c> then the file is read in declaration mode.</param>
public new static EngineFullLoadCurve Create(DataTable data, bool declarationMode = false)
{
var curve = FullLoadCurve.Create(data, declarationMode);
return new EngineFullLoadCurve() { FullLoadEntries = curve.FullLoadEntries, PT1Data = curve.PT1Data };
}
public Watt FullLoadStationaryPower(PerSecond angularVelocity)
{
return Formulas.TorqueToPower(FullLoadStationaryTorque(angularVelocity), angularVelocity);
}
public Watt DragLoadStationaryPower(PerSecond angularVelocity)
{
return DragLoadStationaryTorque(angularVelocity) * angularVelocity;
}
public Second PT1(PerSecond angularVelocity)
{
return PT1Data.Lookup(angularVelocity);
}
private PerSecond ComputePreferredSpeed() private void ComputePreferredSpeed()
{ {
var maxArea = ComputeArea(EngineData.IdleSpeed, N95hSpeed); var maxArea = ComputeArea(EngineData.IdleSpeed, N95hSpeed);
...@@ -116,12 +121,12 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Data.Engine ...@@ -116,12 +121,12 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Data.Engine
var additionalArea = ComputeArea(FullLoadEntries[idx - 1].EngineSpeed, FullLoadEntries[idx].EngineSpeed); var additionalArea = ComputeArea(FullLoadEntries[idx - 1].EngineSpeed, FullLoadEntries[idx].EngineSpeed);
if (area + additionalArea > 0.51 * maxArea) { if (area + additionalArea > 0.51 * maxArea) {
var deltaArea = 0.51 * maxArea - area; var deltaArea = 0.51 * maxArea - area;
return ComputeEngineSpeedForSegmentArea(FullLoadEntries[idx - 1], FullLoadEntries[idx], deltaArea); _preferredSpeed = ComputeEngineSpeedForSegmentArea(FullLoadEntries[idx - 1], FullLoadEntries[idx], deltaArea);
return;
} }
area += additionalArea; area += additionalArea;
} }
Log.Warn("Could not compute preferred speed, check FullLoadCurve! N95h: {0}, maxArea: {1}", N95hSpeed, maxArea); Log.Warn("Could not compute preferred speed, check FullLoadCurve! N95h: {0}, maxArea: {1}", N95hSpeed, maxArea);
return null;
} }
private PerSecond ComputeEngineSpeedForSegmentArea(FullLoadCurveEntry p1, FullLoadCurveEntry p2, Watt area) private PerSecond ComputeEngineSpeedForSegmentArea(FullLoadCurveEntry p1, FullLoadCurveEntry p2, Watt area)
...@@ -145,7 +150,7 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Data.Engine ...@@ -145,7 +150,7 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Data.Engine
return retVal.First(x => x >= p1.EngineSpeed && x <= p2.EngineSpeed).SI<PerSecond>(); return retVal.First(x => x >= p1.EngineSpeed && x <= p2.EngineSpeed).SI<PerSecond>();
} }
private IEnumerable<PerSecond> FindEngineSpeedForPower(Watt power) private List<PerSecond> FindEngineSpeedForPower(Watt power)
{ {
var retVal = new List<PerSecond>(); var retVal = new List<PerSecond>();
for (var idx = 1; idx < FullLoadEntries.Count; idx++) { for (var idx = 1; idx < FullLoadEntries.Count; idx++) {
...@@ -156,7 +161,7 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Data.Engine ...@@ -156,7 +161,7 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Data.Engine
return retVal; return retVal;
} }
private IEnumerable<PerSecond> FindEngineSpeedForPower(FullLoadCurveEntry p1, FullLoadCurveEntry p2, Watt power) private List<PerSecond> FindEngineSpeedForPower(FullLoadCurveEntry p1, FullLoadCurveEntry p2, Watt power)
{ {
var k = (p2.TorqueFullLoad - p1.TorqueFullLoad) / (p2.EngineSpeed - p1.EngineSpeed); var k = (p2.TorqueFullLoad - p1.TorqueFullLoad) / (p2.EngineSpeed - p1.EngineSpeed);
var d = p2.TorqueFullLoad - k * p2.EngineSpeed; var d = p2.TorqueFullLoad - k * p2.EngineSpeed;
......
...@@ -53,21 +53,27 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Data ...@@ -53,21 +53,27 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Data
get { return _maxPower ?? ComputeRatedSpeed().Item2; } get { return _maxPower ?? ComputeRatedSpeed().Item2; }
} }
public static FullLoadCurve ReadFromFile(string fileName, bool declarationMode = false) public static FullLoadCurve ReadFromFile(string fileName, bool declarationMode = false, bool engineFld = false)
{ {
try { try {
var data = VectoCSVFile.Read(fileName); var data = VectoCSVFile.Read(fileName);
return Create(data, declarationMode); return Create(data, declarationMode, engineFld);
} catch (Exception ex) { } catch (Exception ex) {
throw new VectoException("ERROR while reading FullLoadCurve File: " + ex.Message); throw new VectoException("ERROR while reading FullLoadCurve File: " + ex.Message);
} }
} }
public static FullLoadCurve Create(DataTable data, bool declarationMode = false) public static FullLoadCurve Create(DataTable data, bool declarationMode = false, bool engineFld = false)
{ {
if (engineFld) {
if (data.Columns.Count < 3) { if (data.Columns.Count < 3) {
throw new VectoException("FullLoadCurve Data File must consist of at least 3 columns."); throw new VectoException("Engine FullLoadCurve Data File must consist of at least 3 columns.");
}
} else {
if (data.Columns.Count < 2) {
throw new VectoException("Gearbox FullLoadCurve Data File must consist of at least 2 columns.");
}
} }
if (data.Rows.Count < 2) { if (data.Rows.Count < 2) {
...@@ -76,8 +82,8 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Data ...@@ -76,8 +82,8 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Data
} }
List<FullLoadCurveEntry> entriesFld; List<FullLoadCurveEntry> entriesFld;
if (HeaderIsValid(data.Columns)) { if (HeaderIsValid(data.Columns, engineFld)) {
entriesFld = CreateFromColumnNames(data); entriesFld = CreateFromColumnNames(data, engineFld);
} else { } else {
Logger<FullLoadCurve>().Warn( Logger<FullLoadCurve>().Warn(
"FullLoadCurve: Header Line is not valid. Expected: '{0}, {1}, {2}', Got: '{3}'. Falling back to column index.", "FullLoadCurve: Header Line is not valid. Expected: '{0}, {1}, {2}', Got: '{3}'. Falling back to column index.",
...@@ -85,7 +91,7 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Data ...@@ -85,7 +91,7 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Data
Fields.TorqueDrag, Fields.TorqueDrag,
string.Join(", ", data.Columns.Cast<DataColumn>().Select(c => c.ColumnName))); string.Join(", ", data.Columns.Cast<DataColumn>().Select(c => c.ColumnName)));
entriesFld = CreateFromColumnIndizes(data); entriesFld = CreateFromColumnIndizes(data, engineFld);
} }
LookupData<PerSecond, Second> tmp; LookupData<PerSecond, Second> tmp;
...@@ -98,30 +104,30 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Data ...@@ -98,30 +104,30 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Data
return new FullLoadCurve { FullLoadEntries = entriesFld, PT1Data = tmp }; return new FullLoadCurve { FullLoadEntries = entriesFld, PT1Data = tmp };
} }
private static bool HeaderIsValid(DataColumnCollection columns) private static bool HeaderIsValid(DataColumnCollection columns, bool engineFld)
{ {
return columns.Contains(Fields.EngineSpeed) return columns.Contains(Fields.EngineSpeed)
&& columns.Contains(Fields.TorqueDrag) && columns.Contains(Fields.TorqueFullLoad)
&& columns.Contains(Fields.TorqueFullLoad); && (!engineFld || columns.Contains(Fields.TorqueDrag));
} }
private static List<FullLoadCurveEntry> CreateFromColumnNames(DataTable data) private static List<FullLoadCurveEntry> CreateFromColumnNames(DataTable data, bool engineFld)
{ {
return (from DataRow row in data.Rows return (from DataRow row in data.Rows
select new FullLoadCurveEntry { select new FullLoadCurveEntry {
EngineSpeed = row.ParseDouble(Fields.EngineSpeed).RPMtoRad(), EngineSpeed = row.ParseDouble(Fields.EngineSpeed).RPMtoRad(),
TorqueFullLoad = row.ParseDouble(Fields.TorqueFullLoad).SI<NewtonMeter>(), TorqueFullLoad = row.ParseDouble(Fields.TorqueFullLoad).SI<NewtonMeter>(),
TorqueDrag = row.ParseDouble(Fields.TorqueDrag).SI<NewtonMeter>() TorqueDrag = (engineFld ? row.ParseDouble(Fields.TorqueDrag).SI<NewtonMeter>() : null)
}).ToList(); }).ToList();
} }
private static List<FullLoadCurveEntry> CreateFromColumnIndizes(DataTable data) private static List<FullLoadCurveEntry> CreateFromColumnIndizes(DataTable data, bool engineFld)
{ {
return (from DataRow row in data.Rows return (from DataRow row in data.Rows
select new FullLoadCurveEntry { select new FullLoadCurveEntry {
EngineSpeed = row.ParseDouble(0).RPMtoRad(), EngineSpeed = row.ParseDouble(0).RPMtoRad(),
TorqueFullLoad = row.ParseDouble(1).SI<NewtonMeter>(), TorqueFullLoad = row.ParseDouble(1).SI<NewtonMeter>(),
TorqueDrag = row.ParseDouble(2).SI<NewtonMeter>() TorqueDrag = (engineFld ? row.ParseDouble(2).SI<NewtonMeter>() : null)
}).ToList(); }).ToList();
} }
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment