Esempio n. 1
0
        // ( J1  J2    J1+J2  )
        // ( M1  M2  -(M1+M2) )
        private static double ThreeJ_MaxJ(SpinState j1, SpinState j2)
        {
            double r = AdvancedIntegerMath.LogFactorial(j1.TwoJ) +
                       AdvancedIntegerMath.LogFactorial(j2.TwoJ) +
                       AdvancedIntegerMath.LogFactorial(j1.JPlusM + j2.JPlusM) +
                       AdvancedIntegerMath.LogFactorial(j1.JMinusM + j2.JMinusM) -
                       AdvancedIntegerMath.LogFactorial(j1.TwoJ + j2.TwoJ + 1) -
                       AdvancedIntegerMath.LogFactorial(j1.JPlusM) -
                       AdvancedIntegerMath.LogFactorial(j1.JMinusM) -
                       AdvancedIntegerMath.LogFactorial(j2.JPlusM) -
                       AdvancedIntegerMath.LogFactorial(j2.JMinusM);

            r = Math.Exp(r / 2.0);
            return(r);
        }
        // Legendre polynomials normalized for their use in the spherical harmonics

        /// <summary>
        /// Computes the value of an associated Legendre polynomial.
        /// </summary>
        /// <param name="l">The order, which must be non-negative.</param>
        /// <param name="m">The associated order, which must lie between -l and l inclusive.</param>
        /// <param name="x">The argument, which must lie on the closed interval between -1 and +1.</param>
        /// <returns>The value of P<sub>l,m</sub>(x).</returns>
        /// <remarks>
        /// <para>Associated Legendre polynomials appear in the definition of the <see cref="AdvancedMath.SphericalHarmonic"/> functions.</para>
        /// <para>For values of l and m over about 150, values of this polynomial can exceed the capacity of double-wide floating point numbers.</para>
        /// </remarks>
        /// <seealso href="http://en.wikipedia.org/wiki/Associated_Legendre_polynomials"/>
        public static double LegendreP(int l, int m, double x)
        {
            if (l < 0)
            {
                throw new ArgumentOutOfRangeException(nameof(l));
            }

            //if (l < 0) {
            //    return (LegendreP(-l + 1, m, x));
            //}

            if (Math.Abs(m) > l)
            {
                throw new ArgumentOutOfRangeException(nameof(m));
            }

            double f;

            if (l < 10)
            {
                // for low enough orders, we can can get the factorial quickly from a table look-up and without danger of overflow
                f = Math.Sqrt(AdvancedIntegerMath.Factorial(l + m) / AdvancedIntegerMath.Factorial(l - m));
            }
            else
            {
                // for higher orders, we must move into log space to avoid overflow
                f = Math.Exp((AdvancedIntegerMath.LogFactorial(l + m) - AdvancedIntegerMath.LogFactorial(l - m)) / 2.0);
            }

            if (m < 0)
            {
                m = -m;
                if (m % 2 != 0)
                {
                    f = -f;
                }
            }

            if (Math.Abs(x) > 1.0)
            {
                throw new ArgumentOutOfRangeException(nameof(x));
            }

            return(f * LegendrePe(l, m, x));
        }
Esempio n. 3
0
        // ( J1  J2  J3 )
        // ( 0   0   0  )
        private static double ThreeJ_ZeroM(SpinState s1, SpinState s2, SpinState s3)
        {
            Debug.Assert(s1.TwoM == 0);
            Debug.Assert(s2.TwoM == 0);
            Debug.Assert(s3.TwoM == 0);

            int j = (s1.TwoJ + s2.TwoJ + s3.TwoJ) / 2;

            if (j % 2 != 0)
            {
                // zero by symmetry
                return(0.0);
            }
            else
            {
                double f = -AdvancedIntegerMath.LogFactorial(j + 1)
                           + AdvancedIntegerMath.LogFactorial(j - s1.TwoJ)
                           + AdvancedIntegerMath.LogFactorial(j - s2.TwoJ)
                           + AdvancedIntegerMath.LogFactorial(j - s3.TwoJ);
                f = Math.Exp(f / 2.0);

                int    k = j / 2;
                double g = AdvancedIntegerMath.LogFactorial(k)
                           - AdvancedIntegerMath.LogFactorial(k - s1.TwoJ / 2)
                           - AdvancedIntegerMath.LogFactorial(k - s2.TwoJ / 2)
                           - AdvancedIntegerMath.LogFactorial(k - s3.TwoJ / 2);
                g = Math.Exp(g);

                if (k % 2 != 0)
                {
                    return(-f * g);
                }
                else
                {
                    return(f * g);
                }
            }
        }
Esempio n. 4
0
        private static double ThreeJ_Any(SpinState j1, SpinState j2, SpinState j3)
        {
            // compute prefactor

            double f1 = 0.0
                        + AdvancedIntegerMath.LogFactorial((j1.TwoJ + j2.TwoJ - j3.TwoJ) / 2)
                        + AdvancedIntegerMath.LogFactorial((j1.TwoJ - j2.TwoJ + j3.TwoJ) / 2)
                        + AdvancedIntegerMath.LogFactorial((-j1.TwoJ + j2.TwoJ + j3.TwoJ) / 2)
                        - AdvancedIntegerMath.LogFactorial((j1.TwoJ + j2.TwoJ + j3.TwoJ) / 2 + 1);
            double f2 = 0.0
                        + AdvancedIntegerMath.LogFactorial(j1.JPlusM)
                        + AdvancedIntegerMath.LogFactorial(j1.JMinusM)
                        + AdvancedIntegerMath.LogFactorial(j2.JPlusM)
                        + AdvancedIntegerMath.LogFactorial(j2.JMinusM)
                        + AdvancedIntegerMath.LogFactorial(j3.JPlusM)
                        + AdvancedIntegerMath.LogFactorial(j3.JMinusM);
            double f = Math.Exp((f1 + f2) / 2.0);

            if ((j1.JPlusM - j2.JMinusM) % 2 != 0)
            {
                f = -f;
            }
            Console.WriteLine("f={0}", f);

            // determine maximum and minimum values of k in sum

            int kmin = 0;
            int k23  = j2.JPlusM - j3.JMinusM;

            if (kmin < k23)
            {
                kmin = k23;
            }
            int k13 = j1.JMinusM - j3.JPlusM;

            if (kmin < k13)
            {
                kmin = k13;
            }

            int k123 = (j1.TwoJ + j2.TwoJ - j3.TwoJ) / 2;
            int kmax = k123;
            int k1   = j1.JMinusM;

            if (k1 < kmax)
            {
                kmax = k1;
            }
            int k2 = j2.JPlusM;

            if (k2 < kmax)
            {
                kmax = k2;
            }


            Console.WriteLine("{0} <= k <= {1}", kmin, kmax);
            Debug.Assert(kmin <= kmax);

            // compute the sum

            double g = 0.0;

            for (int k = kmin; k <= kmax; k++)
            {
                double gt = AdvancedIntegerMath.LogFactorial(k)
                            + AdvancedIntegerMath.LogFactorial(k123 - k)
                            + AdvancedIntegerMath.LogFactorial(k1 - k)
                            + AdvancedIntegerMath.LogFactorial(k2 - k)
                            + AdvancedIntegerMath.LogFactorial(k - k13)
                            + AdvancedIntegerMath.LogFactorial(k - k23);
                gt = Math.Exp(-gt);
                if (k % 2 != 0)
                {
                    gt = -gt;
                }
                g += gt;
            }
            Console.WriteLine("g={0}", g);

            return(f * g);
        }