From 4cebfa50da2fb3abcdfaa7924dd3268a9a91d412 Mon Sep 17 00:00:00 2001 From: Michael Krisper <michael.krisper@gmail.com> Date: Mon, 30 Mar 2015 03:04:45 +0200 Subject: [PATCH] Finished Test Correction for SI Units --- VECTO.sln | 22 -------- .../Connector/Ports/IDriverDemandInPort.cs | 4 +- .../Models/Connector/Ports/Impl/InPort.cs | 4 +- .../Models/Connector/Ports/Impl/OutPort.cs | 4 +- .../Simulation/Data/IModalDataWriter.cs | 2 - .../Models/Simulation/Data/ModalResult.cs | 5 +- .../Models/Simulation/Impl/VectoSimulator.cs | 1 - .../Data/CombustionEngineData.cs | 53 ++++++++++--------- .../Data/DrivingCycleData.cs | 2 +- .../Data/Engine/FuelConsumptionMap.cs | 16 +++--- .../Data/Engine/FullLoadCurve.cs | 15 +++--- .../Impl/CombustionEngine.cs | 15 +++--- .../Impl/EngineOnlyGearbox.cs | 1 - VectoCore/Utils/DelauneyMap.cs | 13 +++-- VectoCore/Utils/DoubleExtensionMethods.cs | 2 +- VectoCore/Utils/Formulas.cs | 9 ++-- VectoCore/Utils/SI.cs | 53 +++++++++++++++---- VectoCore/Utils/VectoCSVFile.cs | 12 +++-- VectoCore/VectoCore.csproj | 9 ++-- .../EngineOnlyCycle/EngineOnlyCycleTest.cs | 13 ++--- .../FuelConsumptionMapTest.cs | 6 ++- .../FullLoadCurveTest.cs | 14 ++--- 22 files changed, 147 insertions(+), 128 deletions(-) diff --git a/VECTO.sln b/VECTO.sln index c24901c0c2..3e14e7442e 100644 --- a/VECTO.sln +++ b/VECTO.sln @@ -11,10 +11,6 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "VectoCore", "VectoCore\Vect EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "VectoCoreTest", "VectoCoreTest\VectoCoreTest.csproj", "{6A27F93E-4A58-48F6-B00B-3908C5D3D5A2}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "playground", "\\psf\Dropbox\VECTO\CITnet\playground\playground.csproj", "{C980389D-A411-4CB5-8DBC-5D957AFDBC92}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "playground3", "playground3\playground3.csproj", "{C2D4D349-7CFE-43F3-AF11-E360D60EFEDB}" -EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -59,24 +55,6 @@ Global {6A27F93E-4A58-48F6-B00B-3908C5D3D5A2}.Release|Any CPU.Build.0 = Release|Any CPU {6A27F93E-4A58-48F6-B00B-3908C5D3D5A2}.Release|x64.ActiveCfg = Release|Any CPU {6A27F93E-4A58-48F6-B00B-3908C5D3D5A2}.Release|x86.ActiveCfg = Release|Any CPU - {C980389D-A411-4CB5-8DBC-5D957AFDBC92}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {C980389D-A411-4CB5-8DBC-5D957AFDBC92}.Debug|Any CPU.Build.0 = Debug|Any CPU - {C980389D-A411-4CB5-8DBC-5D957AFDBC92}.Debug|x64.ActiveCfg = Debug|x64 - {C980389D-A411-4CB5-8DBC-5D957AFDBC92}.Debug|x64.Build.0 = Debug|x64 - {C980389D-A411-4CB5-8DBC-5D957AFDBC92}.Debug|x86.ActiveCfg = Debug|Any CPU - {C980389D-A411-4CB5-8DBC-5D957AFDBC92}.Release|Any CPU.ActiveCfg = Release|Any CPU - {C980389D-A411-4CB5-8DBC-5D957AFDBC92}.Release|Any CPU.Build.0 = Release|Any CPU - {C980389D-A411-4CB5-8DBC-5D957AFDBC92}.Release|x64.ActiveCfg = Release|x64 - {C980389D-A411-4CB5-8DBC-5D957AFDBC92}.Release|x64.Build.0 = Release|x64 - {C980389D-A411-4CB5-8DBC-5D957AFDBC92}.Release|x86.ActiveCfg = Release|Any CPU - {C2D4D349-7CFE-43F3-AF11-E360D60EFEDB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {C2D4D349-7CFE-43F3-AF11-E360D60EFEDB}.Debug|Any CPU.Build.0 = Debug|Any CPU - {C2D4D349-7CFE-43F3-AF11-E360D60EFEDB}.Debug|x64.ActiveCfg = Debug|Any CPU - {C2D4D349-7CFE-43F3-AF11-E360D60EFEDB}.Debug|x86.ActiveCfg = Debug|Any CPU - {C2D4D349-7CFE-43F3-AF11-E360D60EFEDB}.Release|Any CPU.ActiveCfg = Release|Any CPU - {C2D4D349-7CFE-43F3-AF11-E360D60EFEDB}.Release|Any CPU.Build.0 = Release|Any CPU - {C2D4D349-7CFE-43F3-AF11-E360D60EFEDB}.Release|x64.ActiveCfg = Release|Any CPU - {C2D4D349-7CFE-43F3-AF11-E360D60EFEDB}.Release|x86.ActiveCfg = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/VectoCore/Models/Connector/Ports/IDriverDemandInPort.cs b/VectoCore/Models/Connector/Ports/IDriverDemandInPort.cs index 649436a9d1..1e667cd695 100644 --- a/VectoCore/Models/Connector/Ports/IDriverDemandInPort.cs +++ b/VectoCore/Models/Connector/Ports/IDriverDemandInPort.cs @@ -1,6 +1,4 @@ -using System; - -namespace TUGraz.VectoCore.Models.Connector.Ports +namespace TUGraz.VectoCore.Models.Connector.Ports { public interface IDriverDemandInPort { diff --git a/VectoCore/Models/Connector/Ports/Impl/InPort.cs b/VectoCore/Models/Connector/Ports/Impl/InPort.cs index 7f159d9c39..233304028e 100644 --- a/VectoCore/Models/Connector/Ports/Impl/InPort.cs +++ b/VectoCore/Models/Connector/Ports/Impl/InPort.cs @@ -1,6 +1,4 @@ -using TUGraz.VectoCore.Models.SimulationComponent; - -namespace TUGraz.VectoCore.Models.Connector.Ports.Impl +namespace TUGraz.VectoCore.Models.Connector.Ports.Impl { public abstract class InPort: IInPort { diff --git a/VectoCore/Models/Connector/Ports/Impl/OutPort.cs b/VectoCore/Models/Connector/Ports/Impl/OutPort.cs index 460c465b7e..d019d60b07 100644 --- a/VectoCore/Models/Connector/Ports/Impl/OutPort.cs +++ b/VectoCore/Models/Connector/Ports/Impl/OutPort.cs @@ -1,6 +1,4 @@ -using TUGraz.VectoCore.Models.SimulationComponent; - -namespace TUGraz.VectoCore.Models.Connector.Ports.Impl +namespace TUGraz.VectoCore.Models.Connector.Ports.Impl { public abstract class OutPort: IOutPort { diff --git a/VectoCore/Models/Simulation/Data/IModalDataWriter.cs b/VectoCore/Models/Simulation/Data/IModalDataWriter.cs index ddf13c6a42..7959d333f5 100644 --- a/VectoCore/Models/Simulation/Data/IModalDataWriter.cs +++ b/VectoCore/Models/Simulation/Data/IModalDataWriter.cs @@ -1,5 +1,3 @@ -using System; - namespace TUGraz.VectoCore.Models.Simulation.Data { public interface IModalDataWriter diff --git a/VectoCore/Models/Simulation/Data/ModalResult.cs b/VectoCore/Models/Simulation/Data/ModalResult.cs index ff95b6878e..40b63f8e4d 100644 --- a/VectoCore/Models/Simulation/Data/ModalResult.cs +++ b/VectoCore/Models/Simulation/Data/ModalResult.cs @@ -1,11 +1,14 @@ using System; +using System.ComponentModel; using System.Data; +using System.Diagnostics.CodeAnalysis; using System.Reflection; using TUGraz.VectoCore.Utils; namespace TUGraz.VectoCore.Models.Simulation.Data { - [System.ComponentModel.DesignerCategory("")] // Full qualified attribute needed to disable design view in VisualStudio + [SuppressMessage("Microsoft.Usage", "CA2237:MarkISerializableTypesWithSerializable")] + [DesignerCategory("")] // Full qualified attribute needed to disable design view in VisualStudio public class ModalResults : DataTable { public ModalResults() diff --git a/VectoCore/Models/Simulation/Impl/VectoSimulator.cs b/VectoCore/Models/Simulation/Impl/VectoSimulator.cs index 41e6487069..d628cfdb83 100644 --- a/VectoCore/Models/Simulation/Impl/VectoSimulator.cs +++ b/VectoCore/Models/Simulation/Impl/VectoSimulator.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; diff --git a/VectoCore/Models/SimulationComponent/Data/CombustionEngineData.cs b/VectoCore/Models/SimulationComponent/Data/CombustionEngineData.cs index 6f8d58854f..2addef25b1 100644 --- a/VectoCore/Models/SimulationComponent/Data/CombustionEngineData.cs +++ b/VectoCore/Models/SimulationComponent/Data/CombustionEngineData.cs @@ -5,6 +5,7 @@ using System.Diagnostics.Contracts; using System.Globalization; using System.IO; using System.Linq; +using System.Runtime.Serialization; using Newtonsoft.Json; using TUGraz.VectoCore.Exceptions; using TUGraz.VectoCore.Models.SimulationComponent.Data.Engine; @@ -42,6 +43,7 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Data /// } /// } /// </code> + [DataContract] public class CombustionEngineData : SimulationComponentData { /// <summary> @@ -270,7 +272,7 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Data #endregion } - [JsonProperty] + [DataMember] private Data _data; public bool SavedInDeclarationMode @@ -288,57 +290,58 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Data /// <summary> /// [m^3] /// </summary> - public double Displacement + public SI Displacement { - get { return _data.Body.Displacement.SI().Cubic.Centi.Meter; } - protected set { _data.Body.Displacement = value.SI().To().Cubic.Centi.Meter; } + get { return _data.Body.Displacement.SI().Cubic.Centi.Meter.To().Cubic.Meter.Value(); } + protected set { _data.Body.Displacement = value.To().Cubic.Centi.Meter; } } /// <summary> /// [rad/s] /// </summary> - public double IdleSpeed + public SI IdleSpeed { - get { return _data.Body.IdleSpeed.SI().Rounds.Per.Minute; } - protected set { _data.Body.IdleSpeed = value.SI().To().Rounds.Per.Minute; } + get { return _data.Body.IdleSpeed.SI().Rounds.Per.Minute.To().Radian.Per.Second.Value(); } + protected set { _data.Body.IdleSpeed = value.Rounds.Per.Minute; } } /// <summary> - /// [gm^2] + /// [kgm^2] /// </summary> - public double Inertia + public SI Inertia { - get { return _data.Body.Inertia.SI().Kilo.Gramm.Square.Meter; } - protected set { _data.Body.Inertia = value.SI().To().Kilo.Gramm.Square.Meter; } + get { return _data.Body.Inertia.SI().Kilo.Gramm.Square.Meter.To().Kilo.Gramm.Square.Meter.Value(); } + protected set { _data.Body.Inertia = value.To().Kilo.Gramm.Square.Meter; } } /// <summary> - /// [g/W] + /// [kg/Ws] /// </summary> - public double WHTCUrban + public SI WHTCUrban { - get { return _data.Body.WHTCUrban.SI().Gramm.Per.Kilo.Watt.Hour; } - protected set { _data.Body.WHTCUrban = value.SI().To().Gramm.Per.Kilo.Watt.Hour; } + get { return _data.Body.WHTCUrban.SI().Gramm.Per.Kilo.Watt.Hour.To().Kilo.Gramm.Per.Watt.Second.Value(); } + protected set { _data.Body.WHTCUrban = value.To().Gramm.Per.Kilo.Watt.Hour; } } /// <summary> - /// [g/W] + /// [kg/Ws] /// </summary> - public double WHTCRural + public SI WHTCRural { - get { return _data.Body.WHTCRural.SI().Gramm.Per.Kilo.Watt.Hour; } - protected set { _data.Body.WHTCRural = value.SI().To().Gramm.Per.Kilo.Watt.Hour; } + get { return _data.Body.WHTCRural.SI().Gramm.Per.Kilo.Watt.Hour.To().Kilo.Gramm.Per.Watt.Second.Value(); } + protected set { _data.Body.WHTCRural = value.To().Gramm.Per.Kilo.Watt.Hour; } } /// <summary> - /// [g/W] + /// [g/Ws] /// </summary> - public double WHTCMotorway + public SI WHTCMotorway { - get { return _data.Body.WHTCMotorway.SI().Gramm.Per.Kilo.Watt.Hour; } - protected set { _data.Body.WHTCMotorway = value.SI().To().Gramm.Per.Kilo.Watt.Hour; } + get { return _data.Body.WHTCMotorway.SI().Gramm.Per.Kilo.Watt.Hour.To().Kilo.Gramm.Per.Watt.Second.Value(); } + protected set { _data.Body.WHTCMotorway = value.To().Gramm.Per.Kilo.Watt.Hour; } } + [DataMember] public FuelConsumptionMap ConsumptionMap { get; set; } public class RangeConverter : TypeConverter @@ -363,6 +366,8 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Data public Range(string range) { + Contract.Requires(range != null); + _start = uint.Parse(range.Split('-').First().Trim()); _end = uint.Parse(range.Split('-').Last().Trim()); } @@ -403,7 +408,7 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Data #endregion } - [JsonProperty] + [DataMember] private readonly Dictionary<Range, FullLoadCurve> _fullLoadCurves = new Dictionary<Range, FullLoadCurve>(); public static CombustionEngineData ReadFromFile(string fileName) diff --git a/VectoCore/Models/SimulationComponent/Data/DrivingCycleData.cs b/VectoCore/Models/SimulationComponent/Data/DrivingCycleData.cs index 76d967feaa..7f00be9098 100644 --- a/VectoCore/Models/SimulationComponent/Data/DrivingCycleData.cs +++ b/VectoCore/Models/SimulationComponent/Data/DrivingCycleData.cs @@ -228,7 +228,7 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Data return row.Table.Columns.Cast<DataColumn>(). Where(col => col.ColumnName.StartsWith(Fields.AuxiliarySupplyPower)). ToDictionary(col => col.ColumnName.Substring(Fields.AuxiliarySupplyPower.Length - 1), - col => row.ParseDouble(col).SI().Kilo.Watt.Value); + col => row.ParseDouble(col).SI().Kilo.Watt.ScalarValue()); } } diff --git a/VectoCore/Models/SimulationComponent/Data/Engine/FuelConsumptionMap.cs b/VectoCore/Models/SimulationComponent/Data/Engine/FuelConsumptionMap.cs index 033132e3f0..3a458451b1 100644 --- a/VectoCore/Models/SimulationComponent/Data/Engine/FuelConsumptionMap.cs +++ b/VectoCore/Models/SimulationComponent/Data/Engine/FuelConsumptionMap.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Data; +using System.Diagnostics.Contracts; using System.Linq; using Newtonsoft.Json; using TUGraz.VectoCore.Exceptions; @@ -47,7 +48,7 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Data.Engine public double FuelConsumption { get; set; } #region Equality members - protected bool Equals(FuelConsumptionEntry other) + private bool Equals(FuelConsumptionEntry other) { return EngineSpeed.Equals(other.EngineSpeed) && Torque.Equals(other.Torque) && FuelConsumption.Equals(other.FuelConsumption); @@ -94,7 +95,7 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Data.Engine { EngineSpeed = row.ParseDouble(Fields.EngineSpeed).SI().Rounds.Per.Minute, Torque = row.ParseDouble(Fields.Torque).SI().Newton.Meter, - FuelConsumption = row.ParseDouble(Fields.FuelConsumption).SI().Gramm.Per.Hour + FuelConsumption = row.ParseDouble(Fields.FuelConsumption).SI().Gramm.Per.Hour.To().Kilo.Gramm.Per.Second }; // todo Contract.Assert @@ -104,7 +105,7 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Data.Engine fuelConsumptionMap._entries.Add(entry); // Delauney map works only as expected, when the engineSpeed is in rpm. - fuelConsumptionMap._fuelMap.AddPoint(entry.EngineSpeed.SI().To().Rounds.Per.Minute, entry.Torque, entry.FuelConsumption); + fuelConsumptionMap._fuelMap.AddPoint(entry.EngineSpeed.SI().Radian.Per.Second.To().Rounds.Per.Minute, entry.Torque, entry.FuelConsumption); } catch (Exception e) { @@ -122,23 +123,22 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Data.Engine } /// <summary> - /// [g/s] Calculates the fuel consumption based on the given fuel map, + /// [kg/s] Calculates the fuel consumption based on the given fuel map, /// the engineSpeed [rad/s] and the torque [Nm]. /// </summary> /// <param name="engineSpeed">[rad/sec]</param> /// <param name="torque">[Nm]</param> - /// <returns>[g/s]</returns> + /// <returns>[kg/s]</returns> public double GetFuelConsumption(double engineSpeed, double torque) { - return _fuelMap.Interpolate(engineSpeed.SI().To().Rounds.Per.Minute, torque); + return _fuelMap.Interpolate(engineSpeed.SI().Radian.Per.Second.To().Rounds.Per.Minute, torque); } #region Equality members protected bool Equals(FuelConsumptionMap other) { - return _entries.SequenceEqual(other._entries) - && Equals(_fuelMap, other._fuelMap); + return _entries.SequenceEqual(other._entries) && Equals(_fuelMap, other._fuelMap); } public override bool Equals(object obj) diff --git a/VectoCore/Models/SimulationComponent/Data/Engine/FullLoadCurve.cs b/VectoCore/Models/SimulationComponent/Data/Engine/FullLoadCurve.cs index 83d8810cc5..142323c110 100644 --- a/VectoCore/Models/SimulationComponent/Data/Engine/FullLoadCurve.cs +++ b/VectoCore/Models/SimulationComponent/Data/Engine/FullLoadCurve.cs @@ -57,12 +57,12 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Data.Engine public double PT1 { get; set; } #region Equality members - protected bool Equals(FullLoadCurveEntry other) + private bool Equals(FullLoadCurveEntry other) { - return EngineSpeed.Equals(other.EngineSpeed) - && TorqueFullLoad.Equals(other.TorqueFullLoad) - && TorqueDrag.Equals(other.TorqueDrag) - && PT1.Equals(other.PT1); + return EngineSpeed.IsEqual(other.EngineSpeed) + && TorqueFullLoad.IsEqual(other.TorqueFullLoad) + && TorqueDrag.IsEqual(other.TorqueDrag) + && PT1.IsEqual(other.PT1); } public override bool Equals(object obj) @@ -119,6 +119,7 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Data.Engine private static bool HeaderIsValid(DataColumnCollection columns) { + Contract.Requires(columns != null); return columns.Contains(Fields.EngineSpeed) && columns.Contains(Fields.TorqueDrag) && columns.Contains(Fields.TorqueFullLoad) @@ -127,6 +128,7 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Data.Engine private static List<FullLoadCurveEntry> CreateFromColumnNames(DataTable data) { + Contract.Requires(data != null); return (from DataRow row in data.Rows select new FullLoadCurveEntry { @@ -139,6 +141,7 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Data.Engine private static List<FullLoadCurveEntry> CreateFromColumnIndizes(DataTable data) { + Contract.Requires(data != null); return (from DataRow row in data.Rows select new FullLoadCurveEntry { @@ -236,7 +239,7 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Data.Engine if (engineSpeed < _entries[0].EngineSpeed) { Log.ErrorFormat("requested rpm below minimum rpm in FLD curve - extrapolating. n: {0}, rpm_min: {1}", - engineSpeed.To().Rounds.Per.Minute, _entries[0].EngineSpeed.SI().To().Rounds.Per.Minute); + engineSpeed.To().Rounds.Per.Minute, _entries[0].EngineSpeed.SI().Radian.Per.Second.To().Rounds.Per.Minute); idx = 1; } else diff --git a/VectoCore/Models/SimulationComponent/Impl/CombustionEngine.cs b/VectoCore/Models/SimulationComponent/Impl/CombustionEngine.cs index f69aa8bcdd..09afd35516 100644 --- a/VectoCore/Models/SimulationComponent/Impl/CombustionEngine.cs +++ b/VectoCore/Models/SimulationComponent/Impl/CombustionEngine.cs @@ -178,7 +178,9 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl try { - writer[ModalResultField.FC] = _data.ConsumptionMap.GetFuelConsumption(_currentState.EngineSpeed, _currentState.EngineTorque); + writer[ModalResultField.FC] = _data.ConsumptionMap.GetFuelConsumption(_currentState.EngineSpeed, _currentState.EngineTorque). + SI().Kilo.Gramm.Per.Second. + To().Gramm.Per.Hour.ScalarValue(); } catch (VectoException ex) { @@ -320,7 +322,7 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl Contract.Requires(angularFrequency.HasEqualUnit(new SI().Radian.Per.Second)); Contract.Requires(dt.Ticks != 0); // TODO @@@quam: handle dynamic timesteps - Contract.Requires<VectoSimulationException>(dt.TotalSeconds.IsSmallerOrEqual(1), "simulation steps other than 1s can not be handled ATM"); + Contract.Requires(dt.TotalSeconds.IsSmallerOrEqual(1), "simulation steps other than 1s can not be handled ATM"); Contract.Ensures(_currentState.DynamicFullLoadPower <= _currentState.StationaryFullLoadPower); //_currentState.StationaryFullLoadPower = _data.GetFullLoadCurve(gear).FullLoadStationaryPower(rpm); @@ -347,7 +349,7 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl /// Calculates power loss. [W] /// </summary> /// <param name="torque">[Nm]</param> - /// <param name="engineSpeed">[rad/sec]</param> + /// <param name="engineSpeed">[rad/s]</param> /// <returns>[W]</returns> protected SI InertiaPowerLoss(SI torque, SI engineSpeed) { @@ -355,9 +357,10 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl Contract.Requires(engineSpeed.HasEqualUnit(new SI().Radian.Per.Second)); Contract.Ensures(Contract.Result<SI>().HasEqualUnit(new SI().Watt)); - var deltaEngineSpeed = (engineSpeed - _previousState.EngineSpeed.SI().Radian.Per.Second).To().Rounds.Per.Second; - var avgEngineSpeed = ((_previousState.EngineSpeed.SI().Radian.Per.Second + engineSpeed) / new SI(2).Second).To().Rounds.Per.Square.Second; - return _data.Inertia.SI().To().Kilo.Gramm.Square.Meter * deltaEngineSpeed * avgEngineSpeed; + var deltaEngineSpeed = engineSpeed - _previousState.EngineSpeed.SI().Radian.Per.Second; + var avgEngineSpeed = (_previousState.EngineSpeed.SI().Radian.Per.Second + engineSpeed) / new SI(2).Second; + var result = _data.Inertia * deltaEngineSpeed * avgEngineSpeed; + return result; } #region Equality members diff --git a/VectoCore/Models/SimulationComponent/Impl/EngineOnlyGearbox.cs b/VectoCore/Models/SimulationComponent/Impl/EngineOnlyGearbox.cs index 90e9c6855d..7a3f9a12bb 100644 --- a/VectoCore/Models/SimulationComponent/Impl/EngineOnlyGearbox.cs +++ b/VectoCore/Models/SimulationComponent/Impl/EngineOnlyGearbox.cs @@ -1,7 +1,6 @@ using System; using TUGraz.VectoCore.Models.Connector.Ports; using TUGraz.VectoCore.Models.Simulation; -using TUGraz.VectoCore.Models.Simulation.Cockpit; using TUGraz.VectoCore.Models.Simulation.Data; namespace TUGraz.VectoCore.Models.SimulationComponent.Impl diff --git a/VectoCore/Utils/DelauneyMap.cs b/VectoCore/Utils/DelauneyMap.cs index 9acda47470..222f1c63ef 100644 --- a/VectoCore/Utils/DelauneyMap.cs +++ b/VectoCore/Utils/DelauneyMap.cs @@ -3,6 +3,7 @@ using System.Linq; using Common.Logging; using Newtonsoft.Json; using System.Collections.Generic; +using System.Diagnostics.Contracts; using TUGraz.VectoCore.Exceptions; namespace TUGraz.VectoCore.Utils @@ -115,6 +116,8 @@ namespace TUGraz.VectoCore.Utils public static Point operator -(Point p1, Point p2) { + Contract.Requires(p1 != null); + Contract.Requires(p2 != null); return new Point(p1.X - p2.X, p1.Y - p2.Y, p1.Z - p2.Z); } @@ -165,6 +168,7 @@ namespace TUGraz.VectoCore.Utils public Plane(Triangle tr) { + Contract.Requires(tr != null); var ab = tr.P2 - tr.P1; var ac = tr.P3 - tr.P1; @@ -224,6 +228,7 @@ namespace TUGraz.VectoCore.Utils public bool ContainsInCircumcircle(Point p) { + Contract.Requires(p != null); var p0 = P1 - p; var p1 = P2 - p; var p2 = P3 - p; @@ -241,14 +246,14 @@ namespace TUGraz.VectoCore.Utils return result.IsPositive(); } - public bool Contains(Point p) + private bool Contains(Point p) { - return (p.Equals(P1) || p.Equals(P2) || p.Equals(P3)); + return P1.Equals(p) || P2.Equals(p) || P3.Equals(p); } public bool SharesVertexWith(Triangle t) { - return t.Contains(P1) || t.Contains(P2) || t.Contains(P3); + return Contains(t.P1) || Contains(t.P2) || Contains(t.P3); } public override string ToString() @@ -313,7 +318,7 @@ namespace TUGraz.VectoCore.Utils protected bool Equals(Edge other) { return Equals(P1, other.P1) && Equals(P2, other.P2) - || Equals(P1, other.P2) && Equals(P1, other.P2); + || Equals(P1, other.P2) && Equals(P1, other.P2); } public override bool Equals(object obj) diff --git a/VectoCore/Utils/DoubleExtensionMethods.cs b/VectoCore/Utils/DoubleExtensionMethods.cs index 09cae17415..515ea0219f 100644 --- a/VectoCore/Utils/DoubleExtensionMethods.cs +++ b/VectoCore/Utils/DoubleExtensionMethods.cs @@ -10,7 +10,7 @@ namespace TUGraz.VectoCore.Utils [Pure] public static bool IsEqual(this double d, double other, double tolerance = Tolerance) { - return Math.Abs(d - other) > tolerance; + return Math.Abs(d - other) > -tolerance; } [Pure] diff --git a/VectoCore/Utils/Formulas.cs b/VectoCore/Utils/Formulas.cs index 364fe7f0d7..8dde45009a 100644 --- a/VectoCore/Utils/Formulas.cs +++ b/VectoCore/Utils/Formulas.cs @@ -1,4 +1,3 @@ -using System; using System.Diagnostics.Contracts; namespace TUGraz.VectoCore.Utils @@ -14,8 +13,8 @@ namespace TUGraz.VectoCore.Utils [Pure] public static SI TorqueToPower(SI torque, SI angularFrequency) { - Contract.Requires<ArgumentException>(angularFrequency.HasEqualUnit(new SI().Radian.Per.Second)); - Contract.Requires<ArgumentException>(torque.HasEqualUnit(new SI().Newton.Meter)); + Contract.Requires(angularFrequency.HasEqualUnit(new SI().Radian.Per.Second)); + Contract.Requires(torque.HasEqualUnit(new SI().Newton.Meter)); Contract.Ensures(Contract.Result<SI>().HasEqualUnit(new SI().Watt)); return torque * angularFrequency; @@ -30,8 +29,8 @@ namespace TUGraz.VectoCore.Utils [Pure] public static SI PowerToTorque(SI power, SI angularFrequency) { - Contract.Requires<ArgumentException>(angularFrequency.HasEqualUnit(new SI().Radian.Per.Second)); - Contract.Requires<ArgumentException>(power.HasEqualUnit(new SI().Watt)); + Contract.Requires(angularFrequency.HasEqualUnit(new SI().Radian.Per.Second)); + Contract.Requires(power.HasEqualUnit(new SI().Watt)); Contract.Ensures(Contract.Result<SI>().HasEqualUnit(new SI().Newton.Meter)); return power / angularFrequency; diff --git a/VectoCore/Utils/SI.cs b/VectoCore/Utils/SI.cs index cb908d5ddc..a765e1a301 100644 --- a/VectoCore/Utils/SI.cs +++ b/VectoCore/Utils/SI.cs @@ -1,17 +1,31 @@ using System; +using System.Linq; using System.Collections.Generic; using System.Diagnostics.Contracts; -using System.Linq; +using System.Runtime.Serialization; +using TUGraz.VectoCore.Exceptions; namespace TUGraz.VectoCore.Utils { + [DataContract] public class SI { + [DataMember] private readonly double _value; + + [DataMember] private readonly string[] _divident; + + [DataMember] private readonly string[] _divisor; + + [DataMember] private readonly bool _reciproc; + + [DataMember] private readonly bool _reverse; + + [DataMember] private readonly int _exponent; public SI(double value = 0.0) @@ -73,7 +87,10 @@ namespace TUGraz.VectoCore.Utils if (!_reciproc) { if (_reverse && !string.IsNullOrEmpty(fromUnit)) - divident.Remove(fromUnit); + if (divident.Contains(fromUnit)) + divident.Remove(fromUnit); + else + throw new VectoException("Unit missing. Conversion not possible."); if (!string.IsNullOrEmpty(toUnit)) divident.Add(toUnit); @@ -84,7 +101,10 @@ namespace TUGraz.VectoCore.Utils else { if (_reverse && !string.IsNullOrEmpty(fromUnit)) - divisor.Remove(fromUnit); + if (divisor.Contains(fromUnit)) + divisor.Remove(fromUnit); + else + throw new VectoException("Unit missing. Conversion not possible."); if (!string.IsNullOrEmpty(toUnit)) divisor.Add(toUnit); @@ -94,7 +114,7 @@ namespace TUGraz.VectoCore.Utils } } - foreach (var v in divisor.Where(v => divident.Contains(v))) + foreach (var v in divisor.ToArray().Where(v => divident.Contains(v))) { divident.Remove(v); divisor.Remove(v); @@ -150,7 +170,7 @@ namespace TUGraz.VectoCore.Utils switch (unit) { case "W": - divident.Add("K"); + divident.Add("k"); divident.Add("g"); divident.Add("m"); divident.Add("m"); @@ -159,7 +179,7 @@ namespace TUGraz.VectoCore.Utils divisor.Add("s"); break; case "N": - divident.Add("K"); + divident.Add("k"); divident.Add("g"); divident.Add("m"); divisor.Add("s"); @@ -176,7 +196,7 @@ namespace TUGraz.VectoCore.Utils switch (unit) { case "N": - divisor.Add("K"); + divisor.Add("k"); divisor.Add("g"); divisor.Add("m"); divisor.Add("m"); @@ -185,7 +205,7 @@ namespace TUGraz.VectoCore.Utils divident.Add("s"); break; case "W": - divisor.Add("K"); + divisor.Add("k"); divisor.Add("g"); divisor.Add("m"); divident.Add("s"); @@ -248,7 +268,12 @@ namespace TUGraz.VectoCore.Utils /// <summary> /// Gets the basic scalar value. /// </summary> - public double Value { get { return _value; } } + public double ScalarValue() { return _value; } + + public SI Value() + { + return new SI(_value, _divident, _divisor); + } /// <summary> /// Returns the Unit Part of the SI Unit Expression. @@ -284,6 +309,11 @@ namespace TUGraz.VectoCore.Utils public static SI operator *(SI si1, SI si2) { + Contract.Assume(si1._divisor != null); + Contract.Assume(si2._divisor != null); + Contract.Assume(si1._divident != null); + Contract.Assume(si2._divident != null); + var divident = si1._divident.Concat(si2._divident).Where(d => d != "rad"); var divisor = si1._divisor.Concat(si2._divisor).Where(d => d != "rad"); return new SI(si1._value * si2._value, divident, divisor); @@ -291,6 +321,11 @@ namespace TUGraz.VectoCore.Utils public static SI operator /(SI si1, SI si2) { + Contract.Assume(si1._divisor != null); + Contract.Assume(si2._divisor != null); + Contract.Assume(si1._divident != null); + Contract.Assume(si2._divident != null); + var divident = si1._divident.Concat(si2._divisor).Where(d => d != "rad"); var divisor = si1._divisor.Concat(si2._divident).Where(d => d != "rad"); return new SI(si1._value / si2._value, divident, divisor); diff --git a/VectoCore/Utils/VectoCSVFile.cs b/VectoCore/Utils/VectoCSVFile.cs index 55d3c79c50..61cc5ce752 100644 --- a/VectoCore/Utils/VectoCSVFile.cs +++ b/VectoCore/Utils/VectoCSVFile.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Data; +using System.Diagnostics.Contracts; using System.Globalization; using System.IO; using System.Linq; @@ -90,6 +91,7 @@ namespace TUGraz.VectoCore.Utils private static string[] GetValidHeaderColumns(string line) { + Contract.Requires(line != null); double test; var validColumns = GetColumns(line). Where(col => !double.TryParse(col, NumberStyles.Any, CultureInfo.InvariantCulture, out test)); @@ -98,6 +100,8 @@ namespace TUGraz.VectoCore.Utils private static IEnumerable<string> GetColumns(string line) { + Contract.Requires(line != null); + line = Regex.Replace(line, @"\[.*?\]", ""); line = Regex.Replace(line, @"\(.*?\)", ""); line = line.Replace("<", ""); @@ -107,10 +111,12 @@ namespace TUGraz.VectoCore.Utils private static string[] RemoveComments(string[] lines) { + Contract.Requires(lines != null); + lines = lines. - Select(line => line.Contains('#') ? line.Substring(0, line.IndexOf(Comment)) : line). - Where(line => !string.IsNullOrEmpty(line)). - ToArray(); + Select(line => line.Contains('#') ? line.Substring(0, line.IndexOf(Comment)) : line). + Where(line => !string.IsNullOrEmpty(line)). + ToArray(); return lines; } diff --git a/VectoCore/VectoCore.csproj b/VectoCore/VectoCore.csproj index 6716fc0e0a..8e107cc2dd 100644 --- a/VectoCore/VectoCore.csproj +++ b/VectoCore/VectoCore.csproj @@ -48,25 +48,25 @@ <CodeContractsSuggestAssumptionsForCallees>False</CodeContractsSuggestAssumptionsForCallees> <CodeContractsSuggestRequires>True</CodeContractsSuggestRequires> <CodeContractsNecessaryEnsures>True</CodeContractsNecessaryEnsures> - <CodeContractsSuggestObjectInvariants>False</CodeContractsSuggestObjectInvariants> + <CodeContractsSuggestObjectInvariants>True</CodeContractsSuggestObjectInvariants> <CodeContractsSuggestReadonly>True</CodeContractsSuggestReadonly> <CodeContractsRunInBackground>True</CodeContractsRunInBackground> <CodeContractsShowSquigglies>True</CodeContractsShowSquigglies> <CodeContractsUseBaseLine>False</CodeContractsUseBaseLine> - <CodeContractsEmitXMLDocs>False</CodeContractsEmitXMLDocs> + <CodeContractsEmitXMLDocs>True</CodeContractsEmitXMLDocs> <CodeContractsCustomRewriterAssembly /> <CodeContractsCustomRewriterClass /> <CodeContractsLibPaths /> <CodeContractsExtraRewriteOptions /> <CodeContractsExtraAnalysisOptions /> <CodeContractsSQLServerOption /> - <CodeContractsBaseLineFile>..\..\baseline.xml</CodeContractsBaseLineFile> + <CodeContractsBaseLineFile>baseline.xml</CodeContractsBaseLineFile> <CodeContractsCacheAnalysisResults>True</CodeContractsCacheAnalysisResults> <CodeContractsSkipAnalysisIfCannotConnectToCache>False</CodeContractsSkipAnalysisIfCannotConnectToCache> <CodeContractsFailBuildOnWarnings>True</CodeContractsFailBuildOnWarnings> <CodeContractsBeingOptimisticOnExternal>True</CodeContractsBeingOptimisticOnExternal> <CodeContractsRuntimeCheckingLevel>Full</CodeContractsRuntimeCheckingLevel> - <CodeContractsReferenceAssembly>%28none%29</CodeContractsReferenceAssembly> + <CodeContractsReferenceAssembly>Build</CodeContractsReferenceAssembly> <CodeContractsAnalysisWarningLevel>0</CodeContractsAnalysisWarningLevel> </PropertyGroup> <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' "> @@ -98,6 +98,7 @@ </Reference> <Reference Include="System" /> <Reference Include="System.Core" /> + <Reference Include="System.Runtime.Serialization" /> <Reference Include="System.Xml.Linq" /> <Reference Include="System.Data.DataSetExtensions" /> <Reference Include="Microsoft.CSharp" /> diff --git a/VectoCoreTest/Integration/EngineOnlyCycle/EngineOnlyCycleTest.cs b/VectoCoreTest/Integration/EngineOnlyCycle/EngineOnlyCycleTest.cs index 037012746b..334b3b7cb0 100644 --- a/VectoCoreTest/Integration/EngineOnlyCycle/EngineOnlyCycleTest.cs +++ b/VectoCoreTest/Integration/EngineOnlyCycle/EngineOnlyCycleTest.cs @@ -20,8 +20,6 @@ namespace TUGraz.VectoCore.Tests.Integration.EngineOnlyCycle private const string EngineFile = @"TestData\Components\24t Coach.veng"; - private const double tolerance = 0.001; - [DataSource("Microsoft.VisualStudio.TestTools.DataSource.CSV", "|DataDirectory|\\TestData\\EngineTests.csv", "EngineTests#csv", DataAccessMethod.Sequential)] [TestMethod] public void TestEngineOnlyDrivingCycle() @@ -44,11 +42,10 @@ namespace TUGraz.VectoCore.Tests.Integration.EngineOnlyCycle var dataWriter = new TestModalDataWriter(); var i = 0; - DataRow row; - ModalResultField[] results = new ModalResultField[] { ModalResultField.n, ModalResultField.PaEng, ModalResultField.Tq_drag, ModalResultField.Pe_drag, ModalResultField.Pe_eng, ModalResultField.Tq_eng, ModalResultField.Tq_full, ModalResultField.Pe_full, }; + var results = new[] { ModalResultField.n, ModalResultField.PaEng, ModalResultField.Tq_drag, ModalResultField.Pe_drag, ModalResultField.Pe_eng, ModalResultField.Tq_eng, ModalResultField.Tq_full, ModalResultField.Pe_full, }; //, ModalResultField.FC }; - double[] siFactor = new double[] {1, 1000, 1, 1000, 1000, 1, 1, 1000, 1 }; - double[] tolerances = new double[] {0.0001, 0.1, 0.0001, 0.1, 0.1, 0.001, 0.001, 0.1, 0.01 }; + var siFactor = new double[] {1, 1000, 1, 1000, 1000, 1, 1, 1000, 1 }; + var tolerances = new double[] {0.0001, 0.1, 0.0001, 0.1, 0.1, 0.001, 0.001, 0.1, 0.01 }; foreach (var cycle in data.Entries) { port.Request(absTime, dt, cycle.EngineTorque, cycle.EngineSpeed); @@ -58,7 +55,7 @@ namespace TUGraz.VectoCore.Tests.Integration.EngineOnlyCycle } // TODO: handle initial state of engine - row = expectedResults.Rows[i++]; + var row = expectedResults.Rows[i++]; if (i > 2) { for (var j = 0; j < results.Length; j++) { var field = results[j]; @@ -66,7 +63,7 @@ namespace TUGraz.VectoCore.Tests.Integration.EngineOnlyCycle Assert.AreEqual((double) row[field.GetName()] * siFactor[j], dataWriter.GetDouble(field), tolerances[j]); } if (row[ModalResultField.FC.GetName()] is double) { - Assert.AreEqual((double) row[ModalResultField.FC.GetName()], dataWriter.GetDouble(ModalResultField.FC), 0.01); + Assert.AreEqual((double)row[ModalResultField.FC.GetName()], dataWriter.GetDouble(ModalResultField.FC).SI().Kilo.Gramm.Per.Second.To().Gramm.Per.Hour, 0.01); } else { Assert.IsTrue(Double.IsNaN(dataWriter.GetDouble(ModalResultField.FC))); diff --git a/VectoCoreTest/Models/SimulationComponentData/FuelConsumptionMapTest.cs b/VectoCoreTest/Models/SimulationComponentData/FuelConsumptionMapTest.cs index 7d2e918c50..6f20bd60b7 100644 --- a/VectoCoreTest/Models/SimulationComponentData/FuelConsumptionMapTest.cs +++ b/VectoCoreTest/Models/SimulationComponentData/FuelConsumptionMapTest.cs @@ -37,8 +37,10 @@ namespace TUGraz.VectoCore.Tests.Models.SimulationComponentData var entry = lines[i].Split(',').Select(x => double.Parse(x, CultureInfo.InvariantCulture)).ToArray(); try { - Assert.AreEqual(entry[2].SI().Gramm.Per.Hour, map.GetFuelConsumption(entry[0].SI().Rounds.Per.Minute, entry[1]), Tolerance, - string.Format("Line: {0}, n={1}, T={2}", (i + 2), entry[0].SI().Rounds.Per.Minute, entry[1])); + Assert.AreEqual(entry[2].SI().Gramm.Per.Hour.To().Kilo.Gramm.Per.Second, + map.GetFuelConsumption(entry[0].SI().Rounds.Per.Minute, entry[1]), + Tolerance, + string.Format("Line: {0}, n={1}, T={2}", (i + 2), entry[0].SI().Rounds.Per.Minute, entry[1])); } catch (VectoException ex) diff --git a/VectoCoreTest/Models/SimulationComponentData/FullLoadCurveTest.cs b/VectoCoreTest/Models/SimulationComponentData/FullLoadCurveTest.cs index 51ec2a6ad1..e74338b9e4 100644 --- a/VectoCoreTest/Models/SimulationComponentData/FullLoadCurveTest.cs +++ b/VectoCoreTest/Models/SimulationComponentData/FullLoadCurveTest.cs @@ -98,17 +98,9 @@ namespace TUGraz.VectoCore.Tests.Models.SimulationComponentData [TestMethod] public void Test_FileRead_NoHeader() { - try - { - FullLoadCurve.ReadFromFile(@"TestData\Components\FullLoadCurve no header.vfld"); - Assert.Fail("this should not be reached."); - } - catch (VectoException ex) - { - Assert.AreEqual( - @"File TestData\Components\FullLoadCurve no header.vfld: Line 0: The data format is not correct: no columns found.", - ex.Message); - } + var curve = FullLoadCurve.ReadFromFile(@"TestData\Components\FullLoadCurve no header.vfld"); + var result = curve.FullLoadStationaryTorque(new SI(1).Radian.Per.Second); + Assert.AreNotEqual(result.ScalarValue(), 0.0); } /// <summary> -- GitLab