public void CoulombAgreement()
        {
            // The individual CoulombF and CoulombG functions should agree with the Coulomb
            // function that computes both.

            foreach (int L in TestUtilities.GenerateIntegerValues(1, 100, 4))
            {
                foreach (double eta in TestUtilities.GenerateRealValues(1.0E-1, 1.0E2, 8))
                {
                    foreach (double rho in TestUtilities.GenerateRealValues(1.0E-2, 1.0E4, 16))
                    {
                        double       F = AdvancedMath.CoulombF(L, eta, rho);
                        double       G = AdvancedMath.CoulombG(L, eta, rho);
                        SolutionPair s = AdvancedMath.Coulomb(L, eta, rho);

                        Assert.IsTrue(TestUtilities.IsNearlyEqual(F, s.FirstSolutionValue));

                        // We are producing NaNs for divergent G rathar than infinities
                        if (F == 0.0)
                        {
                            continue;
                        }

                        Assert.IsTrue(TestUtilities.IsNearlyEqual(G, s.SecondSolutionValue));
                    }
                }
            }
        }
        public void CoulombRhoZero()
        {
            // L = 0
            foreach (double eta in TestUtilities.GenerateRealValues(1.0E-2, 1.0E3, 4))
            {
                foreach (int sign in new int[] { 1, -1 })
                {
                    // F is zero
                    Assert.IsTrue(AdvancedMath.CoulombF(0, sign * eta, 0.0) == 0.0);
                    // G is 1/C_{\ell}(\eta), F' = C_{\ell}(eta), so product is 1
                    SolutionPair s = AdvancedMath.Coulomb(0, sign * eta, 0.0);
                    Assert.IsTrue(TestUtilities.IsNearlyEqual(s.FirstSolutionDerivative * s.SecondSolutionValue, 1.0));
                    Assert.IsTrue(Double.IsNegativeInfinity(s.SecondSolutionDerivative));
                }
            }


            // L > 0
            foreach (int L in TestUtilities.GenerateIntegerValues(1, 100, 4))
            {
                foreach (int sign in new int[] { +1, -1 })
                {
                    foreach (double eta in TestUtilities.GenerateRealValues(1.0E-2, 1.0E3, 8))
                    {
                        // F is zero, G is infinite
                        Assert.IsTrue(AdvancedMath.CoulombF(L, sign * eta, 0.0) == 0.0);
                        Assert.IsTrue(Double.IsInfinity(AdvancedMath.CoulombG(L, sign * eta, 0.0)));
                    }
                }
            }
        }
        public void CoulombRecursion()
        {
            foreach (int L in TestUtilities.GenerateIntegerValues(1, 100, 8))
            {
                foreach (double eta in TestUtilities.GenerateRealValues(1.0E-2, 1.0E2, 16))
                {
                    foreach (double rho in TestUtilities.GenerateRealValues(1.0E-3, 1.0E3, 32))
                    {
                        CoulombRecursionHelper(L, eta, rho,
                                               AdvancedMath.CoulombF(L - 1, eta, rho), AdvancedMath.CoulombF(L, eta, rho), AdvancedMath.CoulombF(L + 1, eta, rho)
                                               );

                        CoulombRecursionHelper(L, -eta, rho,
                                               AdvancedMath.CoulombF(L - 1, -eta, rho), AdvancedMath.CoulombF(L, -eta, rho), AdvancedMath.CoulombF(L + 1, -eta, rho)
                                               );

                        CoulombRecursionHelper(L, eta, rho,
                                               AdvancedMath.CoulombG(L - 1, eta, rho), AdvancedMath.CoulombG(L, eta, rho), AdvancedMath.CoulombG(L + 1, eta, rho)
                                               );

                        CoulombRecursionHelper(L, -eta, rho,
                                               AdvancedMath.CoulombG(L - 1, -eta, rho), AdvancedMath.CoulombG(L, -eta, rho), AdvancedMath.CoulombG(L + 1, -eta, rho)
                                               );
                    }
                }
            }
        }
        public void CoulombAgreement()
        {
            // The individual CoulombF and CoulombG functions should agree with the Coulomb
            // function that computes both.

            foreach (int L in TestUtilities.GenerateIntegerValues(1, 100, 8))
            {
                foreach (int sign in new int[] { +1, -1 })
                {
                    foreach (double eta in TestUtilities.GenerateRealValues(1.0E-1, 1.0E2, 16))
                    {
                        foreach (double rho in TestUtilities.GenerateRealValues(1.0E-2, 1.0E4, 32))
                        {
                            double       F = AdvancedMath.CoulombF(L, sign * eta, rho);
                            double       G = AdvancedMath.CoulombG(L, sign * eta, rho);
                            SolutionPair s = AdvancedMath.Coulomb(L, sign * eta, rho);

                            // Deep in transition region, there are cases where we integrate for full solution pair in order to get G,
                            // then use Wronskian from that G to get F. But if we are just computing F, we use series to get a different
                            // (and more accurate) answer. So we relax agreement criteria a bit. Eventually, would be great to do
                            // series for G everywhere we can do series for F.

                            if (!TestUtilities.IsNearlyEqual(F, s.FirstSolutionValue, 4.0 * TestUtilities.TargetPrecision))
                            {
                                Console.WriteLine($"L={L} eta={eta} rho={rho} F={F} s.F={s.FirstSolutionValue} b={Double.IsNaN(s.SecondSolutionDerivative)}");
                            }

                            Assert.IsTrue(TestUtilities.IsNearlyEqual(F, s.FirstSolutionValue, 4.0 * TestUtilities.TargetPrecision));

                            Assert.IsTrue(TestUtilities.IsNearlyEqual(G, s.SecondSolutionValue));
                        }
                    }
                }
            }
        }
        public void CoulombAtOrigin()
        {
            // F is zero at origin for all L and eta
            Assert.IsTrue(AdvancedMath.CoulombF(0, -1.2, 0.0) == 0.0);
            Assert.IsTrue(AdvancedMath.CoulombF(5, 4.3, 0.0) == 0.0);


            // For L = 0, F' and G are finite, non-zero, and related
            SolutionPair s = AdvancedMath.Coulomb(0, 5.6, 0.0);

            Assert.IsTrue(s.FirstSolutionValue == 0.0);
            Assert.IsTrue(TestUtilities.IsNearlyEqual(
                              s.FirstSolutionDerivative * s.SecondSolutionValue,
                              1.0
                              ));
            Assert.IsTrue(s.SecondSolutionDerivative == Double.NegativeInfinity);
        }
        public void CoulombEtaZero()
        {
            // For \eta = 0, Coulomb wave functions reduce to spherical Bessel functions

            foreach (int L in TestUtilities.GenerateIntegerValues(1, 100, 8))
            {
                foreach (double rho in TestUtilities.GenerateRealValues(1.0E-2, 1.0E4, 16))
                {
                    double F = AdvancedMath.CoulombF(L, 0, rho);
                    double j = AdvancedMath.SphericalBesselJ(L, rho);
                    Assert.IsTrue(TestUtilities.IsNearlyEqual(F, rho * j, 16.0 * TestUtilities.TargetPrecision));

                    double G = AdvancedMath.CoulombG(L, 0, rho);
                    double y = AdvancedMath.SphericalBesselY(L, rho);
                    Assert.IsTrue(TestUtilities.IsNearlyEqual(G, -rho * y, 32.0 * TestUtilities.TargetPrecision));
                }
            }
        }
Esempio n. 7
0
        private static Complex[] GetCoulombWaveArray(
            int quantumNumberL,
            double alphaEff,
            double quarkMass_MeV,
            double waveVector_fm,
            double[] radius_fm
            )
        {
            double twoOverPi = Math.Sqrt(2 / Math.PI);
            double eta       = -0.5 * alphaEff * quarkMass_MeV / waveVector_fm / Constants.HbarC_MeV_fm;

            Complex[] coulombWave = new Complex[radius_fm.Length];
            for (int j = 0; j < radius_fm.Length; j++)
            {
                coulombWave[j] = new Complex(twoOverPi * AdvancedMath.CoulombF(quantumNumberL, eta,
                                                                               waveVector_fm * radius_fm[j]), 0);
            }

            return(coulombWave);
        }