/// <summary>
        /// Instantiates a new SpinState with the given spin and magnetic quantum number.
        /// </summary>
        /// <param name="s">The spin.</param>
        /// <param name="m">The magnetic quantum number.</param>
        public SpinState(Spin s, double m)
        {
            spin = s;

            // 2M must be an integer
            double tm  = 2.0 * m;
            double tmt = Math.Floor(tm);

            if (tmt != tm)
            {
                throw new ArgumentOutOfRangeException("m");
            }

            int tmti = (int)tmt;

            twoM = (int)tmt;
            // -J <= M <= J
            if (Math.Abs(tmti) > s.TwoJ)
            {
                throw new ArgumentOutOfRangeException("m");
            }

            // half-integer J requires half-integer M; integer J requires integer M
            if ((s.TwoJ % 2) != Math.Abs(twoM % 2))
            {
                throw new ArgumentOutOfRangeException("m");
            }
        }
Exemple #2
0
        // j1 j2 j3
        // j2 j1 0

        private static double SixJ_Zero(Spin j1, Spin j2, Spin j3)
        {
            double f = 1.0 / Math.Sqrt((j1.TwoJ + 1) * (j2.TwoJ + 1));

            if ((j1.TwoJ + j2.TwoJ + j3.TwoJ) / 2 % 2 != 0)
            {
                f = -f;
            }
            return(f);
        }
Exemple #3
0
        // SixJ

        /// <summary>
        /// Computes the value of the 6j symbol for the six given spins.
        /// </summary>
        /// <param name="j1">Upper left spin.</param>
        /// <param name="j2">Upper middle spin.</param>
        /// <param name="j3">Upper right spin.</param>
        /// <param name="j4">Lower left spin.</param>
        /// <param name="j5">Lower middle spin.</param>
        /// <param name="j6">Lower right spin.</param>
        /// <returns>The value of {{j1,j2,j3},{j4,j5,j6}}.</returns>
        public static double SixJ(Spin j1, Spin j2, Spin j3, Spin j4, Spin j5, Spin j6)
        {
            // check for required triangle relations
            bool t = (Triangle(j1, j2, j3) && Triangle(j1, j5, j6) && Triangle(j4, j2, j6) && Triangle(j4, j5, j3));

            if (!t)
            {
                return(0.0);
            }


            // move the smallest entry to the lower-right corner
            // move lowest entry in first column to bottom
            if (j1.TwoJ < j4.TwoJ)
            {
                Swap(ref j1, ref j4); Swap(ref j2, ref j5);
            }
            // move lowest entry in second column to bottom
            if (j2.TwoJ < j5.TwoJ)
            {
                Swap(ref j2, ref j5); Swap(ref j3, ref j6);
            }
            // move lowest of first two entries in lower row to right
            if (j4.TwoJ < j5.TwoJ)
            {
                Swap(ref j1, ref j2); Swap(ref j4, ref j5);
            }
            // move lowest entry in third column to bottom
            if (j3.TwoJ < j6.TwoJ)
            {
                Swap(ref j3, ref j6); Swap(ref j1, ref j4);
            }
            // move lowest of last two entries in lower row to right
            if (j5.TwoJ < j6.TwoJ)
            {
                Swap(ref j2, ref j3); Swap(ref j5, ref j6);
            }


            if (j6.TwoJ == 0)
            {
                // special case for 0 entry
                return(SixJ_Zero(j1, j2, j3));
            }
            else if (j6.TwoJ == 1)
            {
                // special case for 1/2 entry
                return(SixJ_OneHalf(j1, j2, j3, j4, j5));
            }
            else
            {
                // general case
                return(SixJ_ShultenGorton_Recurse(j1.TwoJ, j2.TwoJ, j3.TwoJ, j4.TwoJ, j5.TwoJ, j6.TwoJ));
            }
        }
Exemple #4
0
        private static bool Triangle(Spin a, Spin b, Spin c)
        {
            // check integer relationships
            int s = (a.TwoJ + b.TwoJ + c.TwoJ);

            if (s % 2 != 0)
            {
                return(false);
            }

            // check triangle inequality
            return((Math.Abs(a.TwoJ - b.TwoJ) <= c.TwoJ) && (c.TwoJ <= (a.TwoJ + b.TwoJ)));
        }
Exemple #5
0
        /// <summary>
        /// Enumerates all the spins that can be obtained by combining two spins.
        /// </summary>
        /// <param name="j1">The first spin.</param>
        /// <param name="j2">The second spin.</param>
        /// <returns>A list of spins which may be obtained.</returns>
        public static Spin[] Combine(Spin j1, Spin j2)
        {
            int tj_min = Math.Abs(j1.TwoJ - j2.TwoJ);
            int tj_max = j1.TwoJ + j2.TwoJ;

            Spin[] spins = new Spin[(tj_max - tj_min) / 2 + 1];
            for (int i = 0; i < spins.Length; i++)
            {
                spins[i] = new Spin((tj_min + 2 * i) / 2.0);
            }

            return(spins);
        }
Exemple #6
0
        // j1 j2 j3
        // j4 j5 1/2

        private static double SixJ_OneHalf(Spin j1, Spin j2, Spin j3, Spin j4, Spin j5)
        {
            Debug.Assert(Math.Abs(j1.TwoJ - j5.TwoJ) == 1); Debug.Assert(Math.Abs(j2.TwoJ - j4.TwoJ) == 1);

            // make j5 = j1-1/2, reducing the number of formulae required
            if (j5.TwoJ > j1.TwoJ)
            {
                Swap(ref j1, ref j5); Swap(ref j2, ref j4);
            }

            double f;

            if (j4.TwoJ < j2.TwoJ)
            {
                //   a     b    c
                // b-1/2 a-1/2 1/2
                f = (j1.TwoJ + j2.TwoJ - j3.TwoJ) * (j1.TwoJ + j2.TwoJ + j3.TwoJ + 2) / 4.0 / (j1.TwoJ * (j1.TwoJ + 1)) / (j2.TwoJ * (j2.TwoJ + 1));
            }
            else
            {
                //   a     b    c
                // b+1/2 a-1/2 1/2
                f = (j1.TwoJ - j2.TwoJ + j3.TwoJ) * (j2.TwoJ + j3.TwoJ - j1.TwoJ + 2) / 4.0 / (j1.TwoJ * (j1.TwoJ + 1)) / ((j2.TwoJ + 1) * (j2.TwoJ + 2));
            }
            f = Math.Sqrt(f);
            if ((j1.TwoJ + j2.TwoJ + j3.TwoJ) % 4 != 0)
            {
                f = -f;
            }
            return(f);

            /*
             * // ensure that J1, J2 are integer-spins; J3, J4 are half-spins
             * if (j1.TwoJ % 2 != 0) { Swap(ref j1, ref j4); Swap(ref j2, ref j5); }
             *
             * // apply relation to 3j symbols
             * // re-write to call directly into specialized 3j routines
             * if ((j1.TwoJ + j2.TwoJ + j3.TwoJ) % 4 == 0) {
             *  double p = ThreeJ(new SpinState(j4, 0.5), new SpinState(j5, -0.5), new SpinState(j3, 0.0));
             *  double q = ThreeJ(new SpinState(j1, 0.0), new SpinState(j2, 0.0), new SpinState(j3, 0.0));
             *  double r = Math.Sqrt((j1.TwoJ + 1) * (j2.TwoJ + 1));
             *  return (- p / q / r);
             * } else {
             *  return (0.0);
             * }
             */
        }