Fixed issue with null references being thrown when the atmospheric slider on the build engineer is visible.
Fixed issue with null references being thrown when the atmospheric slider on the build engineer is visible.

--- a/KerbalEngineer/Editor/BuildAdvanced.cs
+++ b/KerbalEngineer/Editor/BuildAdvanced.cs
@@ -65,6 +65,7 @@
         private GUIStyle titleStyle;
         private bool visible = true;
         private GUIStyle windowStyle;
+        private float maxMach;
 
         #endregion
 
@@ -139,7 +140,7 @@
             }
             catch (Exception ex)
             {
-                Logger.Exception(ex);
+                Logger.Exception(ex, "BuildAdvanced.Awake()");
             }
         }
 
@@ -165,7 +166,7 @@
             }
             catch (Exception ex)
             {
-                Logger.Exception(ex);
+                Logger.Exception(ex, "BuildAdvanced.OnDestroy()");
             }
         }
 
@@ -215,7 +216,7 @@
             }
             catch (Exception ex)
             {
-                Logger.Exception(ex);
+                Logger.Exception(ex, "BuildAdvanced.OnGUI()");
             }
         }
 
@@ -228,7 +229,7 @@
             }
             catch (Exception ex)
             {
-                Logger.Exception(ex);
+                Logger.Exception(ex, "BuildAdvanced.Start()");
             }
         }
 
@@ -270,7 +271,7 @@
             }
             catch (Exception ex)
             {
-                Logger.Exception(ex, "BuildAdvanced->Update");
+                Logger.Exception(ex, "BuildAdvanced.Update()");
             }
         }
 
@@ -294,23 +295,30 @@
         /// </summary>
         private void DrawAtmosphericDetails()
         {
-            GUILayout.BeginHorizontal();
-            GUILayout.BeginVertical();
-            GUILayout.Label("Altitude: " + (Altitude * 0.001f).ToString("F1") + "km", this.settingAtmoStyle, GUILayout.Width(125.0f * GuiDisplaySize.Offset));
-            GUI.skin = HighLogic.Skin;
-            Altitude = GUILayout.HorizontalSlider(Altitude, 0.0f, (float)(CelestialBodies.SelectedBody.CelestialBody.atmosphereDepth));
-            GUI.skin = null;
-            GUILayout.EndVertical();
-
-            GUILayout.Space(5.0f);
-            
-            GUILayout.BeginVertical();
-            GUILayout.Label("Mach: " + this.atmosphericMach.ToString("F1"), this.settingAtmoStyle, GUILayout.Width(125.0f * GuiDisplaySize.Offset));
-            GUI.skin = HighLogic.Skin;
-            atmosphericMach = GUILayout.HorizontalSlider(Mathf.Clamp(atmosphericMach, 0.0f, SimManager.LastStage.maxMach), 0.0f, SimManager.LastStage.maxMach);
-            GUI.skin = null;
-            GUILayout.EndVertical();
-            GUILayout.EndHorizontal();
+            try
+            {
+                GUILayout.BeginHorizontal();
+                GUILayout.BeginVertical();
+                GUILayout.Label("Altitude: " + (Altitude * 0.001f).ToString("F1") + "km", this.settingAtmoStyle, GUILayout.Width(125.0f * GuiDisplaySize.Offset));
+                GUI.skin = HighLogic.Skin;
+                Altitude = GUILayout.HorizontalSlider(Altitude, 0.0f, (float)(CelestialBodies.SelectedBody.CelestialBody.atmosphereDepth));
+                GUI.skin = null;
+                GUILayout.EndVertical();
+
+                GUILayout.Space(5.0f);
+
+                GUILayout.BeginVertical();
+                GUILayout.Label("Mach: " + this.atmosphericMach.ToString("F1"), this.settingAtmoStyle, GUILayout.Width(125.0f * GuiDisplaySize.Offset));
+                GUI.skin = HighLogic.Skin;
+                atmosphericMach = GUILayout.HorizontalSlider(Mathf.Clamp(atmosphericMach, 0.0f, maxMach), 0.0f, maxMach);
+                GUI.skin = null;
+                GUILayout.EndVertical();
+                GUILayout.EndHorizontal();
+            }
+            catch (Exception ex)
+            {
+                Logger.Exception(ex, "BuildAdvanced.DrawAtmosphericDetails()");
+            }
         }
 
         private void DrawBodiesList()
@@ -590,7 +598,11 @@
 
         private void GetStageInfo()
         {
-            this.stages = SimManager.Stages;
+            stages = SimManager.Stages;
+            if (stages != null && stages.Length > 0)
+            {
+                maxMach = stages[stages.Length - 1].maxMach;
+            }
         }
 
         /// <summary>
@@ -703,7 +715,7 @@
             }
             catch (Exception ex)
             {
-                Logger.Exception(ex, "BuildAdvanced->Load");
+                Logger.Exception(ex, "BuildAdvanced.Load()");
             }
         }
 
@@ -798,7 +810,7 @@
             }
             catch (Exception ex)
             {
-                Logger.Exception(ex);
+                Logger.Exception(ex, "BuildAdvanced.Window()");
             }
         }
 

--- a/KerbalEngineer/VesselSimulator/AttachNodeSim.cs
+++ b/KerbalEngineer/VesselSimulator/AttachNodeSim.cs
@@ -19,42 +19,44 @@
 
 #region Using Directives
 
-using System;
-using System.Text;
-
 #endregion
 
 namespace KerbalEngineer.VesselSimulator
 {
-    internal class AttachNodeSim
+    using System;
+    using System.Text;
+
+    internal class AttachNodeSim : Pool<AttachNodeSim>
     {
         public PartSim attachedPartSim;
         public String id;
         public AttachNode.NodeType nodeType;
 
-        public AttachNodeSim(PartSim partSim, String newId, AttachNode.NodeType newNodeType)
-        {
-            this.attachedPartSim = partSim;
-            this.nodeType = newNodeType;
-            this.id = newId;
-        }
-
         public void DumpToBuffer(StringBuilder buffer)
         {
-            if (this.attachedPartSim == null)
+            if (attachedPartSim == null)
             {
                 buffer.Append("<staged>:<n>");
             }
             else
             {
-                buffer.Append(this.attachedPartSim.name);
+                buffer.Append(attachedPartSim.name);
                 buffer.Append(":");
-                buffer.Append(this.attachedPartSim.partId);
+                buffer.Append(attachedPartSim.partId);
             }
             buffer.Append("#");
-            buffer.Append(this.nodeType);
+            buffer.Append(nodeType);
             buffer.Append(":");
-            buffer.Append(this.id);
+            buffer.Append(id);
+        }
+
+        public AttachNodeSim Initialise(PartSim partSim, String newId, AttachNode.NodeType newNodeType)
+        {
+            attachedPartSim = partSim;
+            nodeType = newNodeType;
+            id = newId;
+
+            return this;
         }
     }
 }

--- a/KerbalEngineer/VesselSimulator/EngineSim.cs
+++ b/KerbalEngineer/VesselSimulator/EngineSim.cs
@@ -41,7 +41,7 @@
         public Vector3 thrustVec;
         private readonly ResourceContainer resourceConsumptions = new ResourceContainer();
 
-        public EngineSim Init(PartSim theEngine,
+        public EngineSim Initialise(PartSim theEngine,
             double atmosphere,
             float machNumber,
             float maxFuelFlow,
@@ -102,47 +102,22 @@
                 flowRate = GetFlowRate(thrust, isp);
             }
 
-            if (SimManager.logOutput)
-            {
-                buffer = new StringBuilder(1024);
-                buffer.AppendFormat("flowRate = {0:g6}\n", flowRate);
-            }
-
-            float flowMass = 0f;
-            foreach (Propellant propellant in propellants)
-            {
+            float flowMass = 0.0f;
+
+            for (int i = 0; i < propellants.Count; ++i)
+            {
+                Propellant propellant = propellants[i];
                 flowMass += propellant.ratio * ResourceContainer.GetResourceDensity(propellant.id);
-            }
-
-            if (SimManager.logOutput)
-            {
-                buffer.AppendFormat("flowMass = {0:g6}\n", flowMass);
-            }
-
-            foreach (Propellant propellant in propellants)
-            {
-                if (propellant.name == "ElectricCharge" || propellant.name == "IntakeAir")
-                {
-                    continue;
-                }
 
                 double consumptionRate = propellant.ratio * flowRate / flowMass;
-                if (SimManager.logOutput)
-                {
-                    buffer.AppendFormat("Add consumption({0}, {1}:{2:d}) = {3:g6}\n", ResourceContainer.GetResourceName(propellant.id), theEngine.name, theEngine.partId, consumptionRate);
-                }
                 resourceConsumptions.Add(propellant.id, consumptionRate);
             }
 
-            if (SimManager.logOutput)
-            {
-                MonoBehaviour.print(buffer);
-            }
-
-            appliedForces.Clear();
             double thrustPerThrustTransform = thrust / thrustTransforms.Count;
-            foreach (Transform thrustTransform in thrustTransforms)
-            {
+            for (int i = 0; i < thrustTransforms.Count; ++i)
+            {
+                Transform thrustTransform = thrustTransforms[i];
+
                 Vector3d direction = thrustTransform.forward.normalized;
                 Vector3d position = thrustTransform.position;
                 appliedForces.Add(new AppliedForce(direction * thrustPerThrustTransform, position));
@@ -220,8 +195,9 @@
             // A dictionary to hold a set of parts for each resource
             Dictionary<int, HashSet<PartSim>> sourcePartSets = new Dictionary<int, HashSet<PartSim>>();
 
-            foreach (int type in resourceConsumptions.Types)
-            {
+            for (int i = 0; i < resourceConsumptions.Types.Count; ++i)
+            {
+                int type = resourceConsumptions.Types[i];
                 HashSet<PartSim> sourcePartSet = null;
                 switch (ResourceContainer.GetResourceFlowMode(type))
                 {
@@ -235,8 +211,10 @@
                         break;
 
                     case ResourceFlowMode.ALL_VESSEL:
-                        foreach (PartSim aPartSim in allParts)
-                        {
+                        for (int j = 0; j < allParts.Count; ++j)
+                        {
+                            PartSim aPartSim = allParts[j];
+
                             if (aPartSim.resources[type] > SimManager.RESOURCE_MIN && aPartSim.resourceFlowStates[type] != 0)
                             {
                                 if (sourcePartSet == null)
@@ -253,9 +231,10 @@
                         Dictionary<int, HashSet<PartSim>> stagePartSets = new Dictionary<int, HashSet<PartSim>>();
                         int maxStage = -1;
 
-                        //Logger.Log(type);
-                        foreach (PartSim aPartSim in allParts)
-                        {
+                        for (int j = 0; j < allParts.Count; ++j)
+                        {
+                            PartSim aPartSim = allParts[j];
+
                             if (aPartSim.resources[type] <= SimManager.RESOURCE_MIN || aPartSim.resourceFlowStates[type] == 0)
                             {
                                 continue;
@@ -275,10 +254,10 @@
                             sourcePartSet.Add(aPartSim);
                         }
 
-                        for (int i = 0; i <= maxStage; i++)
+                        for (int j = 0; j <= maxStage; j++)
                         {
                             HashSet<PartSim> stagePartSet;
-                            if (stagePartSets.TryGetValue(i, out stagePartSet) && stagePartSet.Count > 0)
+                            if (stagePartSets.TryGetValue(j, out stagePartSet) && stagePartSet.Count > 0)
                             {
                                 sourcePartSet = stagePartSet;
                             }
@@ -322,8 +301,10 @@
             }
 
             // If we don't have sources for all the needed resources then return false without setting up any drains
-            foreach (int type in resourceConsumptions.Types)
-            {
+            for(int i = 0; i < resourceConsumptions.Types.Count; ++i)
+            {
+                int type = resourceConsumptions.Types[i];
+
                 if (!sourcePartSets.ContainsKey(type))
                 {
                     if (SimManager.logOutput)
@@ -337,8 +318,10 @@
             }
 
             // Now we set the drains on the members of the sets and update the draining parts set
-            foreach (int type in resourceConsumptions.Types)
-            {
+            for (int i = 0; i < resourceConsumptions.Types.Count; ++i)
+            {
+                int type = resourceConsumptions.Types[i];
+
                 HashSet<PartSim> sourcePartSet = sourcePartSets[type];
                 // Loop through the members of the set 
                 double amount = resourceConsumptions[type] / sourcePartSet.Count;

--- a/KerbalEngineer/VesselSimulator/PartSim.cs
+++ b/KerbalEngineer/VesselSimulator/PartSim.cs
@@ -34,11 +34,11 @@
 {
     using CompoundParts;
 
-    public class PartSim
+    public class PartSim : Pool<PartSim>
     {
         private readonly List<AttachNodeSim> attachNodes = new List<AttachNodeSim>();
         public Vector3d centerOfMass;
-        public double baseMass = 0d;
+        public double baseMass;
         public double cost;
         public int decoupledInStage;
         public bool fuelCrossFeed;
@@ -71,8 +71,47 @@
         public String vesselName;
         public VesselType vesselType;
 
-        public PartSim(Part thePart, int id, double atmosphere, LogMsg log)
-        {
+        private static void Reset(PartSim partSim)
+        {
+            partSim.attachNodes.Clear();
+            partSim.fuelTargets.Clear();
+            partSim.resourceDrains.Reset();
+            partSim.resourceFlowStates.Reset();
+            partSim.resources.Reset();
+            partSim.baseMass = 0.0;
+            partSim.startMass = 0.0;
+            partSim.centerOfMass = Vector3d.zero;
+            partSim.cost = 0.0;
+            partSim.decoupledInStage = 0;
+            partSim.fuelCrossFeed = false;
+            partSim.hasModuleEngines = false;
+            partSim.hasModuleEnginesFX = false;
+            partSim.hasMultiModeEngine = false;
+            partSim.hasVessel = false;
+            partSim.initialVesselName = null;
+            partSim.inverseStage = 0;
+            partSim.isDecoupler = false;
+            partSim.isEngine = false;
+            partSim.isFuelLine = false;
+            partSim.isFuelTank = false;
+            partSim.isLanded = false;
+            partSim.isNoPhysics = false;
+            partSim.isSepratron = false;
+            partSim.localCorrectThrust = false;
+            partSim.name = null;
+            partSim.noCrossFeedNodeKey = null;
+            partSim.parent = null;
+            partSim.parentAttach = AttachModes.SRF_ATTACH;
+            partSim.part = null;
+            partSim.partId = 0;
+            partSim.vesselName = null;
+            partSim.vesselType = VesselType.Base;
+        }
+
+        public PartSim Initialise(Part thePart, int id, double atmosphere, LogMsg log)
+        {
+            Reset(this);
+
             this.part = thePart;
             this.centerOfMass = thePart.transform.TransformPoint(thePart.CoMOffset);
             this.partId = id;
@@ -97,13 +136,11 @@
             this.cost = this.part.GetCostWet();
 
             // Work out if the part should have no physical significance
-            this.isNoPhysics = this.part.HasModule<LaunchClamp>() ||
-                               this.part.physicalSignificance == Part.PhysicalSignificance.NONE ||
-                               this.part.PhysicsSignificance == 1;
-
-            if (!this.isNoPhysics)
-            {
-                this.baseMass = this.part.mass;
+            this.isNoPhysics = this.part.HasModule<LaunchClamp>();
+
+            if (isNoPhysics == false)
+            {
+                baseMass = part.mass;
             }
 
             if (SimManager.logOutput)
@@ -111,8 +148,10 @@
                 MonoBehaviour.print((this.isNoPhysics ? "Ignoring" : "Using") + " part.mass of " + this.part.mass);
             }
 
-            foreach (PartResource resource in this.part.Resources)
-            {
+            for (int i = 0; i < part.Resources.Count; ++i)
+            {
+                PartResource resource = part.Resources[i];
+
                 // Make sure it isn't NaN as this messes up the part mass and hence most of the values
                 // This can happen if a resource capacity is 0 and tweakable
                 if (!Double.IsNaN(resource.amount))
@@ -152,6 +191,8 @@
             {
                 MonoBehaviour.print("Created " + this.name + ". Decoupled in stage " + this.decoupledInStage);
             }
+
+            return this;
         }
 
         public ResourceContainer Resources
@@ -185,8 +226,12 @@
                 // The mode of the engine is the engineID of the ModuleEnginesFX that is active
                 string mode = this.part.GetModule<MultiModeEngine>().mode;
 
-                foreach (ModuleEnginesFX engine in this.part.GetModules<ModuleEnginesFX>())
-                {
+                List<ModuleEnginesFX> engines = part.GetModules<ModuleEnginesFX>();
+
+                for (int i = 0; i < engines.Count; ++i)
+                {
+                    ModuleEnginesFX engine = engines[i];
+
                     if (engine.engineID == mode)
                     {
                         if (log != null)
@@ -196,7 +241,7 @@
 
                         Vector3 thrustvec = this.CalculateThrustVector(vectoredThrust ? engine.thrustTransforms : null, log);
 
-                        EngineSim engineSim = EngineSim.GetPoolObject().Init(this,
+                        EngineSim engineSim = EngineSim.GetPoolObject().Initialise(this,
                             atmosphere,
                             (float)mach,
                             engine.maxFuelFlow,
@@ -221,8 +266,10 @@
             {
                 if (this.hasModuleEngines)
                 {
-                    foreach (ModuleEngines engine in this.part.GetModules<ModuleEngines>())
-                    {
+                    List<ModuleEngines> engines = part.GetModules<ModuleEngines>();
+                    for (int i = 0; i < engines.Count; ++i)
+                    {
+                        ModuleEngines engine = engines[i];
                         if (log != null)
                         {
                             log.buf.AppendLine("Module: " + engine.moduleName);
@@ -230,7 +277,7 @@
 
                         Vector3 thrustvec = this.CalculateThrustVector(vectoredThrust ? engine.thrustTransforms : null, log);
 
-                        EngineSim engineSim = EngineSim.GetPoolObject().Init(this,
+                        EngineSim engineSim = EngineSim.GetPoolObject().Initialise(this,
                             atmosphere,
                             (float)mach,
                             engine.maxFuelFlow,
@@ -266,8 +313,10 @@
             }
 
             Vector3 thrustvec = Vector3.zero;
-            foreach (Transform trans in thrustTransforms)
-            {
+            for (int i = 0; i < thrustTransforms.Count; ++i)
+            {
+                Transform trans = thrustTransforms[i];
+
                 if (log != null)
                 {
                     log.buf.AppendFormat("Transform = ({0:g6}, {1:g6}, {2:g6})   length = {3:g6}\n", trans.forward.x, trans.forward.y, trans.forward.z, trans.forward.magnitude);
@@ -320,9 +369,12 @@
                 log.buf.AppendLine("SetupAttachNodes for " + this.name + ":" + this.partId + "");
             }
 
-            this.attachNodes.Clear();
-            foreach (AttachNode attachNode in this.part.attachNodes)
-            {
+            attachNodes.Clear();
+
+            for (int i = 0; i < part.attachNodes.Count; ++i)
+            {
+                AttachNode attachNode = part.attachNodes[i];
+
                 if (log != null)
                 {
                     log.buf.AppendLine("AttachNode " + attachNode.id + " = " + (attachNode.attachedPart != null ? attachNode.attachedPart.partInfo.name : "null"));
@@ -338,7 +390,7 @@
                             log.buf.AppendLine("Adding attached node " + attachedSim.name + ":" + attachedSim.partId + "");
                         }
 
-                        this.attachNodes.Add(new AttachNodeSim(attachedSim, attachNode.id, attachNode.nodeType));
+                        attachNodes.Add(AttachNodeSim.GetPoolObject().Initialise(attachedSim, attachNode.id, attachNode.nodeType));
                     }
                     else
                     {
@@ -350,8 +402,10 @@
                 }
             }
 
-            foreach (Part p in this.part.fuelLookupTargets)
-            {
+            for (int i = 0; i < part.fuelLookupTargets.Count; ++i)
+            {
+                Part p = part.fuelLookupTargets[i];
+
                 if (p != null)
                 {
                     PartSim targetSim;
@@ -469,9 +523,10 @@
             // Rule 2: Part performs scan on start of every fuel pipe ending in it. This scan is done in order in which pipes were installed.
             // Then it makes an union of fuel tank sets each pipe scan returned. If the resulting list is not empty, it is returned as result.
             //MonoBehaviour.print("foreach fuel line");
-
-            foreach (PartSim partSim in this.fuelTargets)
-            {
+            for (int i = 0; i < fuelTargets.Count; ++i)
+            {
+                PartSim partSim = fuelTargets[i];
+
                 if (visited.Contains(partSim))
                 {
                     //if (log != null)
@@ -511,8 +566,10 @@
             if (this.fuelCrossFeed)
             {
                 //MonoBehaviour.print("foreach attach node");
-                foreach (AttachNodeSim attachSim in this.attachNodes)
-                {
+                for (int i = 0; i < attachNodes.Count; ++i)
+                {
+                    AttachNodeSim attachSim = attachNodes[i];
+
                     if (attachSim.attachedPartSim != null)
                     {
                         if (attachSim.nodeType == AttachNode.NodeType.Stack)
@@ -608,8 +665,10 @@
         public void RemoveAttachedParts(HashSet<PartSim> partSims)
         {
             // Loop through the attached parts
-            foreach (AttachNodeSim attachSim in this.attachNodes)
-            {
+            for (int i = 0; i < attachNodes.Count; ++i)
+            {
+                AttachNodeSim attachSim = attachNodes[i];
+
                 // If the part is in the set then "remove" it by clearing the PartSim reference
                 if (partSims.Contains(attachSim.attachedPartSim))
                 {
@@ -621,8 +680,10 @@
         public void DrainResources(double time)
         {
             //MonoBehaviour.print("DrainResources(" + name + ":" + partId + ", " + time + ")");
-            foreach (int type in this.resourceDrains.Types)
-            {
+            for (int i = 0; i < resourceDrains.Types.Count; ++i)
+            {
+                int type = resourceDrains.Types[i];
+
                 //MonoBehaviour.print("draining " + (time * resourceDrains[type]) + " " + ResourceContainer.GetResourceName(type));
                 this.resources.Add(type, -time * this.resourceDrains[type]);
                 //MonoBehaviour.print(ResourceContainer.GetResourceName(type) + " left = " + resources[type]);
@@ -634,8 +695,10 @@
             //MonoBehaviour.print("TimeToDrainResource(" + name + ":" + partId + ")");
             double time = double.MaxValue;
 
-            foreach (int type in this.resourceDrains.Types)
-            {
+            for (int i = 0; i < resourceDrains.Types.Count; ++i)
+            {
+                int type = resourceDrains.Types[i];
+
                 if (this.resourceDrains[type] > 0)
                 {
                     time = Math.Min(time, this.resources[type] / this.resourceDrains[type]);
@@ -686,9 +749,9 @@
         {
             double mass = this.baseMass;
 
-            foreach (int type in this.resources.Types)
-            {
-                mass += this.resources.GetResourceMass(type);
+            for (int i = 0; i < resources.Types.Count; ++i)
+            {
+                mass += this.resources.GetResourceMass(resources.Types[i]);
             }
 
             return mass;

--- a/KerbalEngineer/VesselSimulator/SimManager.cs
+++ b/KerbalEngineer/VesselSimulator/SimManager.cs
@@ -302,8 +302,7 @@
             }
             catch (Exception e)
             {
-                MonoBehaviour.print("Exception in RunSimulation: " + e);
-                Logger.Exception(e);
+                Logger.Exception(e, "SimManager.RunSimulation()");
                 Stages = null;
                 LastStage = null;
                 failMessage = e.ToString();
@@ -368,8 +367,8 @@
                 // This call doesn't ever fail at the moment but we'll check and return a sensible error for display
                 if (simulation.PrepareSimulation(parts, Gravity, Atmosphere, Mach, dumpTree, vectoredThrust))
                 {
-                    //ThreadPool.QueueUserWorkItem(RunSimulation, simulation);
-                    RunSimulation(simulation);
+                    ThreadPool.QueueUserWorkItem(RunSimulation, simulation);
+                    //RunSimulation(simulation);
                 }
                 else
                 {
@@ -383,8 +382,7 @@
             }
             catch (Exception e)
             {
-                MonoBehaviour.print("Exception in StartSimulation: " + e);
-                Logger.Exception(e);
+                Logger.Exception(e, "SimManager.StartSimulation()");
                 failMessage = e.ToString();
                 lock (locker)
                 {

--- a/KerbalEngineer/VesselSimulator/Simulation.cs
+++ b/KerbalEngineer/VesselSimulator/Simulation.cs
@@ -32,10 +32,10 @@
 {
     using CompoundParts;
     using Extensions;
+    using Helpers;
 
     public class Simulation
     {
-        private const double STD_GRAVITY = 9.82;
         private const double SECONDS_PER_DAY = 86400;
         private readonly Stopwatch _timer = new Stopwatch();
         private List<EngineSim> activeEngines = new List<EngineSim>();
@@ -144,7 +144,9 @@
             activeEngines.Clear();
             drainingResources.Clear();
 
+            PartSim.ReleaseAll();
             EngineSim.ReleaseAll();
+            AttachNodeSim.ReleaseAll();
 
             // A dictionary for fast lookup of Part->PartSim during the preparation phase
             partSimLookup.Clear();
@@ -170,7 +172,7 @@
                 }
 
                 // Create the PartSim
-                PartSim partSim = new PartSim(part, partId, this.atmosphere, log);
+                PartSim partSim = PartSim.GetPoolObject().Initialise(part, partId, this.atmosphere, log);
 
                 // Add it to the Part lookup dictionary and the necessary lists
                 partSimLookup.Add(part, partSim);
@@ -504,7 +506,7 @@
                     // If we have drained anything and the masses make sense then add this step's deltaV to the stage total
                     if (resourceDrainTime > 0d && this.stepStartMass > this.stepEndMass && this.stepStartMass > 0d && this.stepEndMass > 0d)
                     {
-                        this.vecStageDeltaV += this.vecThrust * (float)((this.currentisp * STD_GRAVITY * Math.Log(this.stepStartMass / this.stepEndMass)) / this.simpleTotalThrust);
+                        this.vecStageDeltaV += this.vecThrust * (float)((this.currentisp * Units.GRAVITY * Math.Log(this.stepStartMass / this.stepEndMass)) / this.simpleTotalThrust);
                     }
 
                     // Update the active engines and resource drains for the next step
@@ -548,7 +550,7 @@
                 // Note: If the mass doesn't change then this is a divide by zero
                 if (this.stageStartMass != this.stepStartMass)
                 {
-                    stage.isp = stage.deltaV / (STD_GRAVITY * Math.Log(this.stageStartMass / this.stepStartMass));
+                    stage.isp = stage.deltaV / (Units.GRAVITY * Math.Log(this.stageStartMass / this.stepStartMass));
                 }
                 else
                 {

 Binary files a/Output/KerbalEngineer/KerbalEngineer.dll and b/Output/KerbalEngineer/KerbalEngineer.dll differ