private void ApplyBoost(out Vector2D[] x, out Vector2D[] v)
        {
            double h = 3.0;
            int numSteps = 7000;
            x = new Vector2D[numSteps + 1];
            v = new Vector2D[numSteps + 1];

            for (int i = 0; i < numSteps + 1; i++)
            {
                x[i] = new Vector2D();
                v[i] = new Vector2D();
            }

            x[0].x = 15e6;
            x[0].y = 1e6;
            v[0].x = 2e3;
            v[0].y = 4e3;

            bool boostDone = false;

            for (int step = 0; step < numSteps; step++)
            {
                if (h * step >= 2.0 * 3600.0 && !boostDone)
                {
                    v[step] += 300.0 * v[step] / v[step].Length();
                    boostDone = true;
                }

                Vector2D acceleration0 = Acceleration(x[step]);
                Vector2D xE = x[step] + h * v[step];
                Vector2D vE = v[step] + h * acceleration0;
                x[step + 1] = x[step] + h * 0.5 * (v[step] + vE);
                v[step + 1] = v[step] + h * 0.5 * (acceleration0 + Acceleration(xE));
            }
        }
        public Vector2D Acceleration(Vector2D moonPosition, Vector2D spaceshipPosition)
        {
            Vector2D vectorToEarth = -spaceshipPosition;
            Vector2D vectorToMoon = moonPosition - spaceshipPosition;

            Vector2D acc = G * (earthMass * vectorToEarth / Math.Pow(vectorToEarth.Length(), 3) + moonMass * vectorToMoon / Math.Pow(vectorToMoon.Length(), 3));
            return acc;
        }
        private Vector2D Acceleration(double time, Vector2D position)
        {
            Vector2D moonPos = MoonPosition(time);

            Vector2D vectorFromMoon = position - moonPos;
            Vector2D vectorFromEarth = position;
            Vector2D acc = -gravitationalConstant * (earthMass * vectorFromEarth / Math.Pow(vectorFromEarth.Length(), 3) + moonMass * vectorFromMoon / Math.Pow(vectorFromMoon.Length(), 3));
            return acc;
        }
        private void CalculateError(int numSteps, out double h, out double e)
        {
            h = totalTime / numSteps;
            Vector2D[] x = new Vector2D[numSteps + 1];
            Vector2D[] v = new Vector2D[numSteps + 1];

            for (int i = 0; i < numSteps + 1; i++)
            {
                x[i] = new Vector2D();
                v[i] = new Vector2D();
            }

            x[0].x = radius;
            v[0].y = speed;

            for (int step = 0; step < numSteps; step++)
            {
                x[step + 1] = x[step] + h * v[step];
                v[step + 1] = v[step] + h * Acceleration(x[step]);
            }
            e = (x[numSteps] - x[0]).Length();
        }
 private Vector2D Acceleration(Vector2D spaceshipPosition)
 {
     Vector2D vectorToEarth = -spaceshipPosition;//earth located at origin
     return gravitationalConstant * earthMass * vectorToEarth / Math.Pow(vectorToEarth.Length(), 3);
 }
        private void TotalEnergy(out Vector2D[] x, out double[] energy)
        {
            int numSteps = 20000;
            double h = 5.0;//s

            x = new Vector2D[numSteps + 1]; // m
            Vector2D[] v = new Vector2D[numSteps + 1]; // m / s
            energy = new double[numSteps + 1];//  J = kg m2 / s2

            for (int i = 0; i < numSteps + 1; i++)
            {
                x[i] = new Vector2D();
                v[i] = new Vector2D();
            }

            x[0].x = 15e6;
            x[0].y = 1e6;
            v[0].x = 2e3;
            v[0].y = 4e3;

            for (int step = 0; step < numSteps; step++)
            {
                x[step + 1] = x[step] + h * v[step];
                v[step + 1] = v[step] + h * Acceleration(x[step]);
            }

            for (int step = 0; step < numSteps + 1; step++)
            {
                energy[step] = 0.5 * spacecraftMass * Math.Pow(v[step].Length(), 2) - gravitationalConstant * earthMass * spacecraftMass / x[step].Length();
            }
        }
        private void Orbit(out Vector2D x, out Vector2D v)
        {
            x = new Vector2D(); // m
            v = new Vector2D(); // m / s
            x.x = 15e6;
            x.y = 1e6;
            v.x = 2e3;
            v.y = 4e3;

            StringBuilder sb = new StringBuilder();
            sb.Append("x.x,x.y,s" + Environment.NewLine);
            sb.Append(x.x + "," + x.y + "," + 4 + Environment.NewLine);

            double currentTime = 0.0d; // s
            double h = 100.0d;// s
            double hNew = h;// s, will store the adaptive step size of the next step
            double tolerance = 5e5;//m

            while (currentTime < totalTime)
            {
                Vector2D acceleration0 = Acceleration(x);
                Vector2D xE = x + h * v;
                Vector2D vE = v + h * acceleration0;
                Vector2D xH = x + h * 0.5 * (v + vE);
                Vector2D vH = v + h * 0.5 * (acceleration0 + Acceleration(xE));
                x = xH;
                v = vH;

                double error = (xE - xH).Length() + totalTime * ((vE - vH).Length());
                hNew = h * Math.Sqrt(tolerance / (error + 1e-50));
                hNew = Math.Min(1800.0d, Math.Max(0.1d, hNew));

                sb.Append(x.x + "," + x.y + "," + 1 + Environment.NewLine);
                currentTime += h;
                h = hNew;
            }

            sb.Append(0 + "," + 0 + "," + 0 + Environment.NewLine);

            File.WriteAllText("adaptive_step_size.csv", sb.ToString());
        }
        private void HeunsMethod(int numSteps, out Vector2D[] x, out Vector2D[] v, out double error)
        {
            double h = totalTime / numSteps;
            x = new Vector2D[numSteps + 1];
            v = new Vector2D[numSteps + 1];
            for (int i = 0; i < numSteps + 1; i++)
            {
                x[i] = new Vector2D();
                v[i] = new Vector2D();
            }
            x[0].x = radius;
            v[0].y = speed;

            for (int step = 0; step < numSteps; step++)
            {
                x[step + 1] = x[step] + h * v[step];
                v[step + 1] = v[step] + h * Acceleration(x[step]);
            }

            error = (x[numSteps] - x[0]).Length();

            hArray.Add(h);
            eulerErrorArray.Add(error);

            //Heun's Method
            for (int step = 0; step < numSteps; step++)
            {
                Vector2D initialAcceleration = Acceleration(x[step]);
                Vector2D xE = x[step] + h * v[step];
                Vector2D vE = v[step] + h * initialAcceleration;

                x[step + 1] = x[step] + h * 0.5 * (v[step] + vE);
                v[step + 1] = v[step] + h * 0.5 * (initialAcceleration + Acceleration(xE));
            }

            error = (x[numSteps] - x[0]).Length();
            heunsErrorArray.Add(error);
        }
 private Vector2D MoonPosition(double time)
 {
     double moonAngle = moonInitialAngle + 2.0 * Math.PI * time / moonPeriod;
     Vector2D position = new Vector2D();
     position.x = moonDistance * Math.Cos(moonAngle);
     position.y = moonDistance * Math.Sin(moonAngle);
     return position;
 }