Exemplo n.º 1
0
        private static double CoulombF_Integrate(int L, double eta, double rho)
        {
            // start at the series limit
            double rho0 = 4.0 + 2.0 * Math.Sqrt(L);

            if (Math.Abs(rho0 * eta) > 8.0 + 4.0 * L)
            {
                rho0 = (8.0 + 4.0 * L) / Math.Abs(eta);
            }
            double F, FP;

            CoulombF_Series(L, eta, rho0, out F, out FP);

            // TODO: switch so we integrate w/o the C factor, then apply it afterward
            if ((F == 0.0) && (FP == 0.0))
            {
                return(0.0);
            }

            // integrate out to rho
            BulrischStoerStoermerStepper s = new BulrischStoerStoermerStepper();

            s.RightHandSide = delegate(double x, double U) {
                return((L * (L + 1) / x / x + 2.0 * eta / x - 1.0) * U);
            };
            s.X        = rho0;
            s.Y        = F;
            s.YPrime   = FP;
            s.DeltaX   = 0.25;
            s.Accuracy = 2.5E-13;
            s.Integrate(rho);

            // return the result
            return(s.Y);
        }
        /// <summary>
        /// Computes the irregular Coulomb wave function.
        /// </summary>
        /// <param name="L">The angular momentum number, which must be non-negative.</param>
        /// <param name="eta">The charge parameter, which can be postive or negative.</param>
        /// <param name="rho">The radial distance parameter, which must be non-negative.</param>
        /// <returns>The value of G<sub>L</sub>(&#x3B7;,&#x3C1;).</returns>
        /// <remarks>
        /// <para>For information on the Coulomb wave functions, see the remarks on <see cref="CoulombF" />.</para>
        /// </remarks>
        /// <exception cref="ArgumentOutOfRangeException"><paramref name="L"/> or <paramref name="rho"/> is negative.</exception>
        /// <seealso cref="CoulombF"/>
        /// <seealso href="http://en.wikipedia.org/wiki/Coulomb_wave_function" />
        /// <seealso href="http://mathworld.wolfram.com/CoulombWaveFunction.html" />
        public static double CoulombG(int L, double eta, double rho)
        {
            if (L < 0) throw new ArgumentOutOfRangeException("L");
            if (rho < 0) throw new ArgumentOutOfRangeException("rho");

            if ((rho < 4.0) && Math.Abs(rho * eta) < 8.0) {
                // for small enough rho, use the power series for L=0, then recurse upward to desired L
                double F, FP, G, GP;
                Coulomb_Zero_Series(eta, rho, out F, out FP, out G, out GP);
                Coulomb_Recurse_Upward(0, L, eta, rho, ref G, ref GP);
                return (G);
            } else if (rho > 32.0 + (L * L + eta * eta) / 2.0) {
                // for large enough rho, use the asymptotic series
                double F, G;
                Coulomb_Asymptotic(L, eta, rho, out F, out G);
                return (G);
            } else {
                // transition region
                if (rho >= CoulombTurningPoint(L, eta)) {
                    // beyond the turning point, use Steed's method
                    SolutionPair result = Coulomb_Steed(L, eta, rho);
                    return (result.SecondSolutionValue);
                } else {

                    // we will start at L=0 (which has a smaller turning point radius) and recurse up to the desired L
                    // this is okay because G increasees with increasing L

                    double G, GP;

                    if (rho < 2.0 * eta) {

                        // if inside the turning point even for L=0, start at the turning point and integrate in
                        // this is okay becaue G increases with decraseing rho

                        // use Steed's method at the turning point
                        // for large enough eta, we could use the turning point expansion at L=0, but it contributes
                        // a lot of code for little overall performance increase so we have chosen not to
                        SolutionPair result;
                        //if (eta > 12.0) {
                        //    result = Coulomb_Zero_Turning_Expansion(eta);
                        //} else {
                            result = Coulomb_Steed(0, eta, 2.0 * eta);
                        //}

                        G = result.SecondSolutionValue;
                        GP = result.SecondSolutionDerivative;

                        BulrischStoerStoermerStepper s = new BulrischStoerStoermerStepper();
                        s.RightHandSide = delegate(double x, double U) {
                            return ((2.0 * eta / x - 1.0) * U);
                        };
                        s.X = 2.0 * eta;
                        s.Y = G;
                        s.YPrime = GP;
                        s.DeltaX = 0.25;
                        s.Accuracy = 2.5E-13;
                        s.Integrate(rho);

                        G = s.Y;
                        GP = s.YPrime;

                    } else {

                        // if beyond the turning point for L=0, just use Steeds method

                        SolutionPair result = Coulomb_Steed(0, eta, rho);
                        G = result.SecondSolutionValue;
                        GP = result.SecondSolutionDerivative;

                    }

                    // recurse up to desired L
                    Coulomb_Recurse_Upward(0, L, eta, rho, ref G, ref GP);

                    return (G);

                }
            }
        }
        private static double CoulombF_Integrate(int L, double eta, double rho)
        {
            // start at the series limit
            double rho0 = 4.0 + 2.0 * Math.Sqrt(L);
            if (Math.Abs(rho0 * eta) > 8.0 + 4.0 * L) rho0 = (8.0 + 4.0 * L) / Math.Abs(eta);
            double F, FP;
            CoulombF_Series(L, eta, rho0, out F, out FP);

            // TODO: switch so we integrate w/o the C factor, then apply it afterward
            if ((F == 0.0) && (FP == 0.0)) return (0.0);

            // integrate out to rho
            BulrischStoerStoermerStepper s = new BulrischStoerStoermerStepper();
            s.RightHandSide = delegate(double x, double U) {
                return ((L * (L + 1) / x / x + 2.0 * eta / x - 1.0) * U);
            };
            s.X = rho0;
            s.Y = F;
            s.YPrime = FP;
            s.DeltaX = 0.25;
            s.Accuracy = 2.5E-13;
            s.Integrate(rho);

            // return the result
            return (s.Y);
        }
Exemplo n.º 4
0
        /// <summary>
        /// Computes the irregular Coulomb wave function.
        /// </summary>
        /// <param name="L">The angular momentum number, which must be non-negative.</param>
        /// <param name="eta">The charge parameter, which can be postive or negative.</param>
        /// <param name="rho">The radial distance parameter, which must be non-negative.</param>
        /// <returns>The value of G<sub>L</sub>(&#x3B7;,&#x3C1;).</returns>
        /// <remarks>
        /// <para>For information on the Coulomb wave functions, see the remarks on <see cref="CoulombF" />.</para>
        /// </remarks>
        /// <exception cref="ArgumentOutOfRangeException"><paramref name="L"/> or <paramref name="rho"/> is negative.</exception>
        /// <seealso cref="CoulombF"/>
        /// <seealso href="http://en.wikipedia.org/wiki/Coulomb_wave_function" />
        /// <seealso href="http://mathworld.wolfram.com/CoulombWaveFunction.html" />
        public static double CoulombG(int L, double eta, double rho)
        {
            if (L < 0)
            {
                throw new ArgumentOutOfRangeException("L");
            }
            if (rho < 0)
            {
                throw new ArgumentOutOfRangeException("rho");
            }

            if ((rho < 4.0) && Math.Abs(rho * eta) < 8.0)
            {
                // for small enough rho, use the power series for L=0, then recurse upward to desired L
                double F, FP, G, GP;
                Coulomb_Zero_Series(eta, rho, out F, out FP, out G, out GP);
                Coulomb_Recurse_Upward(0, L, eta, rho, ref G, ref GP);
                return(G);
            }
            else if (rho > 32.0 + (L * L + eta * eta) / 2.0)
            {
                // for large enough rho, use the asymptotic series
                double F, G;
                Coulomb_Asymptotic(L, eta, rho, out F, out G);
                return(G);
            }
            else
            {
                // transition region
                if (rho >= CoulombTurningPoint(L, eta))
                {
                    // beyond the turning point, use Steed's method
                    SolutionPair result = Coulomb_Steed(L, eta, rho);
                    return(result.SecondSolutionValue);
                }
                else
                {
                    // we will start at L=0 (which has a smaller turning point radius) and recurse up to the desired L
                    // this is okay because G increasees with increasing L

                    double G, GP;

                    if (rho < 2.0 * eta)
                    {
                        // if inside the turning point even for L=0, start at the turning point and integrate in
                        // this is okay becaue G increases with decraseing rho

                        // use Steed's method at the turning point
                        // for large enough eta, we could use the turning point expansion at L=0, but it contributes
                        // a lot of code for little overall performance increase so we have chosen not to
                        SolutionPair result;
                        //if (eta > 12.0) {
                        //    result = Coulomb_Zero_Turning_Expansion(eta);
                        //} else {
                        result = Coulomb_Steed(0, eta, 2.0 * eta);
                        //}

                        G  = result.SecondSolutionValue;
                        GP = result.SecondSolutionDerivative;

                        BulrischStoerStoermerStepper s = new BulrischStoerStoermerStepper();
                        s.RightHandSide = delegate(double x, double U) {
                            return((2.0 * eta / x - 1.0) * U);
                        };
                        s.X        = 2.0 * eta;
                        s.Y        = G;
                        s.YPrime   = GP;
                        s.DeltaX   = 0.25;
                        s.Accuracy = 2.5E-13;
                        s.Integrate(rho);

                        G  = s.Y;
                        GP = s.YPrime;
                    }
                    else
                    {
                        // if beyond the turning point for L=0, just use Steeds method

                        SolutionPair result = Coulomb_Steed(0, eta, rho);
                        G  = result.SecondSolutionValue;
                        GP = result.SecondSolutionDerivative;
                    }


                    // recurse up to desired L
                    Coulomb_Recurse_Upward(0, L, eta, rho, ref G, ref GP);

                    return(G);
                }
            }
        }