Ejemplo n.º 1
0
        /// <summary>
        /// Single impulse transfer from an ellipitical, non-coplanar parking orbit to an arbitrary hyperbolic v-infinity target.
        ///
        /// Ocampo, C., & Saudemont, R. R. (2010). Initial Trajectory Model for a Multi-Maneuver Moon-to-Earth Abort Sequence.
        /// Journal of Guidance, Control, and Dynamics, 33(4), 1184–1194.
        /// </summary>
        ///
        /// <param name="mu">Gravitational parameter of central body.</param>
        /// <param name="r0">Reference position on the parking orbit.</param>
        /// <param name="v0">Reference velocity on the parking orbit.</param>
        /// <param name="v_inf">Target hyperbolic v-infinity vector.</param>
        /// <param name="vneg">Velocity on the parking orbit before the burn.</param>
        /// <param name="vpos">Velocity on the hyperboliic ejection orbit after the burn.</param>
        /// <param name="r">Position of the burn.</param>
        /// <param name="dt">Coasting time on the parking orbit from the reference to the burn.</param>
        ///
        public static void singleImpulseHyperbolicBurn(double mu, Vector3d r0, Vector3d v0, Vector3d v_inf,
                                                       ref Vector3d vneg, ref Vector3d vpos, ref Vector3d r, ref double dt, bool debug = false)
        {
            double   rot, dv;
            BrentFun f = delegate(double testrot, object ign) {
                double   dt   = 0;
                Vector3d vneg = new Vector3d();
                Vector3d vpos = new Vector3d();
                Vector3d r    = new Vector3d();
                singleImpulseHyperbolicBurn(mu, r0, v0, v_inf, ref vneg, ref vpos, ref r, ref dt, (float)testrot, debug);
                return((vpos - vneg).magnitude);
            };

            Brent.Minimize(f, -30, 30, 1e-6, out rot, out dv, null);
            singleImpulseHyperbolicBurn(mu, r0, v0, v_inf, ref vneg, ref vpos, ref r, ref dt, (float)rot, debug);
        }
Ejemplo n.º 2
0
        // Brent's 1-dimensional derivative-free local minimization method
        //
        // Uses golden section search and successive parabolic interpolation.
        //
        // f - 1-dimensional BrentFun function to find the minimum of
        // a - lower endpoint of the interval
        // b - upper endpoint of the interval
        // rtol - tolerance to solve to (1e-4 or something like that)
        // x - output of solved value
        // y - output of the function at the solved value
        // o - object to be passed to BrentFun for extra data (may be null)
        // maxiter - cap on iterations (will throw TimeoutException if exceeded)
        //
        public static void Minimize(BrentFun f, double a, double b, double tol, out double x, out double y, object o, int maxiter = 50)
        {
            double c;
            double d = 0;
            double e;
            double eps;
            double fu;
            double fv;
            double fw;
            double fx;
            double m;
            double p;
            double q;
            double r;
            double sa;
            double sb;
            double t2;
            double t;
            double u;
            double v;
            double w;
            int    i = 0;

            //
            //  C is the square of the inverse of the golden ratio.
            //
            c = 0.5 * (3.0 - Math.Sqrt(5.0));

            eps = Math.Sqrt(MuUtils.DBL_EPSILON);

            sa = a;
            sb = b;
            x  = sa + c * (b - a);
            w  = x;
            v  = w;
            e  = 0.0;
            fx = f(x, o);
            fw = fx;
            fv = fw;

            while (true)
            {
                m  = 0.5 * (sa + sb);
                t  = eps * Math.Abs(x) + tol;
                t2 = 2.0 * t;
                //
                //  Check the stopping criterion.
                //
                if (Math.Abs(x - m) <= t2 - 0.5 * (sb - sa))
                {
                    break;
                }
                //
                //  Fit a parabola.
                //
                r = 0.0;
                q = r;
                p = q;

                if (t < Math.Abs(e))
                {
                    r = (x - w) * (fx - fv);
                    q = (x - v) * (fx - fw);
                    p = (x - v) * q - (x - w) * r;
                    q = 2.0 * (q - r);
                    if (0.0 < q)
                    {
                        p = -p;
                    }
                    q = Math.Abs(q);
                    r = e;
                    e = d;
                }

                if (Math.Abs(p) < Math.Abs(0.5 * q * r) &&
                    q * (sa - x) < p &&
                    p < q * (sb - x))
                {
                    //
                    //  Take the parabolic interpolation step.
                    //
                    d = p / q;
                    u = x + d;
                    //
                    //  F must not be evaluated too close to A or B.
                    //
                    if ((u - sa) < t2 || (sb - u) < t2)
                    {
                        if (x < m)
                        {
                            d = t;
                        }
                        else
                        {
                            d = -t;
                        }
                    }
                }
                //
                //  A golden-section step.
                //
                else
                {
                    if (x < m)
                    {
                        e = sb - x;
                    }
                    else
                    {
                        e = sa - x;
                    }
                    d = c * e;
                }
                //
                //  F must not be evaluated too close to X.
                //
                if (t <= Math.Abs(d))
                {
                    u = x + d;
                }
                else if (0.0 < d)
                {
                    u = x + t;
                }
                else
                {
                    u = x - t;
                }

                fu = f(u, o);
                //
                //  Update A, B, V, W, and X.
                //
                if (fu <= fx)
                {
                    if (u < x)
                    {
                        sb = x;
                    }
                    else
                    {
                        sa = x;
                    }
                    v  = w;
                    fv = fw;
                    w  = x;
                    fw = fx;
                    x  = u;
                    fx = fu;
                }
                else
                {
                    if (u < x)
                    {
                        sa = u;
                    }
                    else
                    {
                        sb = u;
                    }

                    if (fu <= fw || w == x)
                    {
                        v  = w;
                        fv = fw;
                        w  = u;
                        fw = fu;
                    }
                    else if (fu <= fv || v == x || v == w)
                    {
                        v  = u;
                        fv = fu;
                    }
                }
                if (i++ >= maxiter)
                {
                    throw new TimeoutException("Brent's minimization method: maximum iterations exceeded");
                }
            }
            y = fx;
        }
Ejemplo n.º 3
0
        // Brent's rootfinding method
        //
        // Uses secant or inverse quadratic interpolation as appropriate, with a fallback to bisection if necessary.
        //
        // f - 1-dimensional BrentFun function to find the root on
        // a - first guess of x value
        // b - second guess of x value
        // rtol - tolerance to solve to (1e-4 or something like that)
        // x - output of solved value
        // y - output of the function at the solved value (should be zero to rtol)
        // o - object to be passed to BrentFun for extra data (may be null)
        // maxiter - cap on iterations (will throw TimeoutException if exceeded)
        // sign - select the positive or negative side of the root for return value
        //
        // NOTE: please make any fixes to both versions of this routine
        //
        public static void Root(BrentFun f, double a, double b, double rtol, out double x, out double y, object o, int maxiter = 50, int sign = 0)
        {
            double c = 0;
            double d = Double.MaxValue;

            double fa = f(a, o);
            double fb = f(b, o);

            double fc = 0;
            double s  = 0;
            double fs = 0;

            if (fa * fb >= 0)
            {
                throw new ArgumentException("Brent's rootfinding method: guess does not bracket the root");
            }

            if (Math.Abs(fa) < Math.Abs(fb))
            {
                double tmp = a;
                a   = b;
                b   = tmp;
                tmp = fa;
                fa  = fb;
                fb  = tmp;
            }

            c  = a;
            fc = fa;
            bool mflag = true;
            int  i     = 0;

            while ((!(fb == 0) && (Math.Abs(a - b) > rtol)) || ((sign != 0) && (Math.Sign(fb) != sign)))
            {
                if ((fa != fc) && (fb != fc))
                {
                    // inverse quadratic interpolation
                    s = a * fb * fc / (fa - fb) / (fa - fc) + b * fa * fc / (fb - fa) /
                        (fb - fc) + c * fa * fb / (fc - fa) / (fc - fb);
                }
                else
                {
                    // secant
                    s = b - fb * (b - a) / (fb - fa);
                }

                double tmp2 = (3 * a + b) / 4;
                if ((!(((s > tmp2) && (s < b)) || ((s < tmp2) && (s > b)))) ||
                    (mflag && (Math.Abs(s - b) >= (Math.Abs(b - c) / 2))) ||
                    (!mflag && (Math.Abs(s - b) >= (Math.Abs(c - d) / 2))))
                {
                    // bisection
                    s     = (a + b) / 2;
                    mflag = true;
                }
                else
                {
                    if ((mflag && (Math.Abs(b - c) < rtol)) || (!mflag && (Math.Abs(c - d) < rtol)))
                    {
                        s     = (a + b) / 2;
                        mflag = true;
                    }
                    else
                    {
                        mflag = false;
                    }
                }

                fs = f(s, o);
                d  = c;
                c  = b;
                fc = fb;

                if (fa * fs < 0)
                {
                    b  = s;
                    fb = fs;
                }
                else
                {
                    a  = s;
                    fa = fs;
                }

                if (Math.Abs(fa) < Math.Abs(fb))
                {
                    double tmp = a;
                    a   = b;
                    b   = tmp;
                    tmp = fa;
                    fa  = fb;
                    fb  = tmp;
                }

                if (i++ >= maxiter)
                {
                    x = b;
                    y = fb;
                    throw new TimeoutException("Brent's rootfinding method: maximum iterations exceeded");
                }
            }

            x = b;
            y = fb;
        }