protected void StartSimulation(bool addParachuteError)
        {
            double altitudeOfPreviousPrediction         = 0;
            double parachuteMultiplierForThisSimulation = this.parachuteSemiDeployMultiplier;

            if (addParachuteError)
            {
                errorSimulationRunning = true;
                errorStopwatch.Start(); //starts a timer that times how long the simulation takes
            }
            else
            {
                simulationRunning = true;
                stopwatch.Start(); //starts a timer that times how long the simulation takes
            }

            Orbit patch = GetReenteringPatch() ?? orbit;

            // Work out what the landing altitude was of the last prediction, and use that to pass into the next simulation
            if (null != this.result)
            {
                if (result.outcome == ReentrySimulation.Outcome.LANDED && null != result.body)
                {
                    altitudeOfPreviousPrediction = this.GetResult().endASL; // Note that we are caling GetResult here to force the it to calculate the endASL, if it has not already done this. It is not allowed to do this previously as we are only allowed to do it from this thread, not the reentry simulation thread.
                }
            }

            // Is this a simulation run with errors added? If so then add some error to the parachute multiple
            if (addParachuteError)
            {
                System.Random random = new System.Random();
                parachuteMultiplierForThisSimulation *= (1d + ((random.Next(1000000) - 500000d) / 10000000d));
            }

            // The curves used for the sim are not thread safe so we need a copy used only by the thread
            ReentrySimulation.SimCurves simCurves = new ReentrySimulation.SimCurves(patch.referenceBody);

            SimulatedVessel simVessel = SimulatedVessel.New(vessel, simCurves, patch.StartUT, deployChutes ? limitChutesStage : -1);

            ReentrySimulation sim = new ReentrySimulation(patch, patch.StartUT, simVessel, simCurves, descentSpeedPolicy, decelEndAltitudeASL, vesselState.limitedMaxThrustAccel, parachuteMultiplierForThisSimulation, altitudeOfPreviousPrediction, addParachuteError, dt, Time.fixedDeltaTime);

            //MechJebCore.print("Sim ran with dt=" + dt.ToString("F3"));

            //Run the simulation in a separate thread
            ThreadPool.QueueUserWorkItem(RunSimulation, sim);
            //RunSimulation(sim);
        }
        protected void StartSimulation(bool addParachuteError)
        {
            double altitudeOfPreviousPrediction         = 0;
            double parachuteMultiplierForThisSimulation = this.parachuteSemiDeployMultiplier;

            if (addParachuteError)
            {
                errorSimulationRunning = true;
                errorStopwatch.Start(); //starts a timer that times how long the simulation takes
            }
            else
            {
                simulationRunning = true;
                stopwatch.Start(); //starts a timer that times how long the simulation takes
            }

            Orbit patch = GetReenteringPatch() ?? orbit;

            // Work out a mass for the total ship, a DragMass for everything except the parachutes that will be used (including the stowed parachutes that will not be used) and list of parchutes that will be used.
            double totalMass = 0;
            double dragMassExcludingUsedParachutes = 0;
            List <SimulatedParachute> usableChutes = new List <SimulatedParachute>();

            for (int index = 0; index < vessel.parts.Count; index++)
            {
                Part p = vessel.parts[index];
                if (p.IsPhysicallySignificant())
                {
                    bool   partIsParachute = false;
                    double partDrag        = 0;
                    double partMass        = p.TotalMass();

                    totalMass += partMass;

                    // Is this part a parachute?
                    for (int i = 0; i < p.Modules.Count; i++)
                    {
                        PartModule pm = p.Modules[i];
                        if (!pm.isEnabled)
                        {
                            continue;
                        }

                        if (pm is ModuleParachute)
                        {
                            ModuleParachute chute = (ModuleParachute)pm;
                            // This is a parachute, but is it one that will be used in the landing / rentry simulation?
                            if (deployChutes && p.inverseStage >= limitChutesStage)
                            {
                                // This chute will be used in the simualtion. Add it to the list of useage parachutes.
                                usableChutes.Add(new SimulatedParachute(chute, patch.StartUT));
                                partIsParachute = true;
                            }
                        }
                    }

                    if (!partIsParachute)
                    {
                        // Part is not a parachute. Just use its drag value.
                        partDrag = p.maximum_drag;
                    }

                    dragMassExcludingUsedParachutes += partDrag * partMass;
                }
            }

            // Work out what the landing altitude was of the last prediction, and use that to pass into the next simulation
            if (null != this.result)
            {
                if (result.outcome == ReentrySimulation.Outcome.LANDED && null != result.body)
                {
                    altitudeOfPreviousPrediction = this.GetResult().endASL; // Note that we are caling GetResult here to force the it to calculate the endASL, if it has not already done this. It is not allowed to do this previously as we are only allowed to do it from this thread, not the reentry simulation thread.
                }
            }

            // Is this a simulation run with errors added? If so then add some error to the parachute multiple
            if (addParachuteError)
            {
                System.Random random = new System.Random();
                parachuteMultiplierForThisSimulation *= (1d + ((random.Next(1000000) - 500000d) / 10000000d));
            }

            // The curves used for the simes are not thread safe so we need a copy used only by the thread
            ReentrySimulation.SimCurves simCurves = new ReentrySimulation.SimCurves(patch.referenceBody);

            SimulatedVessel simVessel = SimulatedVessel.New(vessel, simCurves);

            ReentrySimulation sim = new ReentrySimulation(patch, patch.StartUT, usableChutes, simVessel, simCurves, descentSpeedPolicy, decelEndAltitudeASL, vesselState.limitedMaxThrustAccel, parachuteMultiplierForThisSimulation, altitudeOfPreviousPrediction, addParachuteError, dt, Time.fixedDeltaTime);

            MechJebCore.print("Sim ran with dt=" + dt.ToString("F3"));

            //Run the simulation in a separate thread
            ThreadPool.QueueUserWorkItem(RunSimulation, sim);
            //RunSimulation(sim);
        }