public void ThreeJRecursion() { foreach (ThreeJSymbol symbol in GenerateRandomThreeJSymbols(50.0, 10)) { double j1 = symbol.Column1.J; double m1 = symbol.Column1.M; double j2 = symbol.Column2.J; double m2 = symbol.Column2.M; double j3 = symbol.Column3.J; double m3 = symbol.Column3.M; double s1 = SpinMath.ThreeJ(new SpinState(j1, m1), new SpinState(j2, m2), new SpinState(j3, m3)); double s2 = 0.0; if ((Math.Abs(m2 - 1.0) <= j2) && (Math.Abs(m3 + 1.0) <= j3)) { s2 = SpinMath.ThreeJ(new SpinState(j1, m1), new SpinState(j2, m2 - 1.0), new SpinState(j3, m3 + 1.0)); } double s3 = 0.0; if ((Math.Abs(m1 - 1.0) <= j1) && (Math.Abs(m3 + 1.0) <= j3)) { s3 = SpinMath.ThreeJ(new SpinState(j1, m1 - 1.0), new SpinState(j2, m2), new SpinState(j3, m3 + 1.0)); } double c1 = Math.Sqrt((j3 + m3 + 1.0) * (j3 - m3)); double c2 = Math.Sqrt((j2 - m2 + 1.0) * (j2 + m2)); double c3 = Math.Sqrt((j1 - m1 + 1.0) * (j1 + m1)); Assert.IsTrue(TestUtilities.IsSumNearlyEqual(c1 * s1, c2 * s2, -c3 * s3)); } }
public void ThreeJRacahSymmetry() { foreach (ThreeJSymbol symbol in GenerateRandomThreeJSymbols(50.0, 10)) { // compute the 3j symbol SpinState s1 = symbol.Column1; SpinState s2 = symbol.Column2; SpinState s3 = symbol.Column3; double C = SpinMath.ThreeJ(s1, s2, s3); // form other 3j symbols related by Racah symmetry double k1, k2, k3, n1, n2, n3; SpinState t1, t2, t3; // rows 1->2->3 k1 = (s2.J + s2.M + s3.J + s3.M) / 2.0; k2 = (s1.J + s1.M + s3.J + s3.M) / 2.0; k3 = (s1.J + s1.M + s2.J + s2.M) / 2.0; n1 = s1.J - s1.M - k1; n2 = s2.J - s2.M - k2; n3 = s3.J - s3.M - k3; t1 = new SpinState(k1, n1); t2 = new SpinState(k2, n2); t3 = new SpinState(k3, n3); double CC = SpinMath.ThreeJ(t1, t2, t3); Assert.IsTrue(TestUtilities.IsNearlyEqual(C, CC)); // transpose rows and columns /* * k1 = s1.J; * k2 = (s2.J + s3.J + s1.M) / 2.0; * k3 = (s2.J + s3.J - s1.M) / 2.0; * n1 = s2.J - s3.J; * n2 = s3.J - s3.M - k2; * n3 = s3.J + s3.M - k2; * * t1 = new SpinState(k1, n1); * t2 = new SpinState(k2, n2); * t3 = new SpinState(k3, n3); * double CT = SpinMath.ThreeJ(t1, t2, t3); * * Assert.IsTrue(TestUtilities.IsNearlyEqual(C, CT)); */ } }
public void ThreeJLegendreIntegral() { // pick three legendre polynomials foreach (int l1 in TestUtilities.GenerateUniformIntegerValues(0, 16, 8)) { foreach (int l2 in TestUtilities.GenerateUniformIntegerValues(0, 16, 4)) { foreach (int l3 in TestUtilities.GenerateUniformIntegerValues(0, 16, 2)) { Console.WriteLine("{0} {1} {2}", l1, l2, l3); // do the integral over their product Func <double, double> f = delegate(double x) { return( OrthogonalPolynomials.LegendreP(l1, x) * OrthogonalPolynomials.LegendreP(l2, x) * OrthogonalPolynomials.LegendreP(l3, x) ); }; double I = FunctionMath.Integrate(f, Interval.FromEndpoints(-1.0, 1.0)); // it should be the same as 2 ( l1 l2 l3 )^2 // ( 0 0 0 ) double S = SpinMath.ThreeJ(new SpinState(l1, 0), new SpinState(l2, 0), new SpinState(l3, 0)); Console.WriteLine(" {0} {1}", I, 2.0 * S * S); if (Math.Abs(S) < TestUtilities.TargetPrecision) { Assert.IsTrue(I < TestUtilities.TargetPrecision); } else { Assert.IsTrue(TestUtilities.IsNearlyEqual(I, 2.0 * S * S)); } } } } }
public void ThreeJExchangeSymmetry() { foreach (ThreeJSymbol symbol in GenerateRandomThreeJSymbols(50.0, 10)) { SpinState s1 = symbol.Column1; SpinState s2 = symbol.Column2; SpinState s3 = symbol.Column3; Console.WriteLine("( {0} {1} {2} )", s1.J, s2.J, s3.J); Console.WriteLine("( {0} {1} {2} )", s1.M, s2.M, s3.M); double s123 = SpinMath.ThreeJ(s1, s2, s3); double s231 = SpinMath.ThreeJ(s2, s3, s1); double s312 = SpinMath.ThreeJ(s3, s1, s2); Console.WriteLine("{0},{1},{2}", s123, s231, s312); Assert.IsTrue(TestUtilities.IsNearlyEqual(s123, s231)); Assert.IsTrue(TestUtilities.IsNearlyEqual(s123, s312)); int P; if (((int)(s1.J + s2.J + s3.J)) % 2 == 0) { P = 1; } else { P = -1; } double s132 = SpinMath.ThreeJ(s1, s3, s2); double s213 = SpinMath.ThreeJ(s2, s1, s3); double s321 = SpinMath.ThreeJ(s3, s2, s1); Console.WriteLine("{0},{1},{2}", s132, s213, s321); Assert.IsTrue(TestUtilities.IsNearlyEqual(s123, P * s132)); Assert.IsTrue(TestUtilities.IsNearlyEqual(s123, P * s213)); Assert.IsTrue(TestUtilities.IsNearlyEqual(s123, P * s321)); } }
public void SixJThreeJRelation() { SixJSymbol[] symbols = GenerateRandomSixJSymbols(50.0, 5); foreach (SixJSymbol symbol in symbols) { Spin a = symbol.J1; Spin b = symbol.J2; Spin c = symbol.J3; Spin d = symbol.J4; Spin e = symbol.J5; Spin f = symbol.J6; SpinState[] ams = GenerateRandomSpinStates(a, 2); SpinState[] bms = GenerateRandomSpinStates(b, 2); foreach (SpinState am in ams) { foreach (SpinState bm in bms) { if (Math.Abs(am.M + bm.M) > c.J) { continue; } SpinState cm = new SpinState(c, -(am.M + bm.M)); double g1 = SpinMath.ThreeJ(am, bm, cm); double g2 = SpinMath.SixJ(a, b, c, d, e, f); double p = g1 * g2; double q = 0.0; List <double> ts = new List <double>(); SpinState[] dms = d.States(); foreach (SpinState dm in dms) { if (Math.Abs(dm.M + cm.M) > e.J) { continue; } SpinState em = new SpinState(e, dm.M + cm.M); SpinState mem = new SpinState(e, -em.M); double f1 = SpinMath.ThreeJ(dm, mem, cm); if (Math.Abs(em.M + am.M) > f.J) { continue; } SpinState fm = new SpinState(f, em.M + am.M); SpinState mfm = new SpinState(f, -fm.M); double f2 = SpinMath.ThreeJ(em, mfm, am); SpinState mdm = new SpinState(d, -dm.M); double f3 = SpinMath.ThreeJ(fm, mdm, bm); double t = f1 * f2 * f3; int s = (int)Math.Round(dm.J + dm.M + em.J + em.M + fm.J + fm.M); if (s % 2 != 0) { t = -t; } q += t; ts.Add(t); } Console.WriteLine("{0} v. {1}", p, q); //Assert.IsTrue(TestUtilities.IsNearlyEqual(p, q)); Assert.IsTrue(TestUtilities.IsSumNearlyEqual(ts, p)); } } } }