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