示例#1
0
文件: ham.py 项目: celesmec/eps
def kepler_trig_expand(s):
    """
	Transform trigonometric part of series s [sin(nM) and cos(nM)]
	to sum of items like cos(M)^k1 * sin(M)^k2, where n=k1+k2.
	- s is series of e and M,
	- n is number of terms.
	"""
    from math import ceil
    from pyranha.math import binomial, cos, sin, degree
    temp, e, M, ecosM, esinM = 0, epst('e'), epst('M'), epst('ecosM'), epst(
        'esinM')
    n = degree(s).numerator
    s_list = s.list
    for i in range(len(s_list)):
        for j in range(n + 1):
            trig_cos, trig_sin = 0, 0
            # calculate cos(nM):
            if s_list[i][1] == cos(j * M):
                for k in range(int(ceil(j / 2)) + 1):
                    trig_cos = trig_cos + (-1)**k * binomial(
                        j, 2 * k) * ecosM**(j - 2 * k) * esinM**(2 * k) * e**-j
                temp = temp + s_list[i][0] * trig_cos
            # calculate sin(nM):
            if s_list[i][1] == sin(j * M):
                for k in range(int(ceil((j - 1) / 2)) + 1):
                    trig_sin = trig_sin + (-1)**k * binomial(
                        j, 2 * k + 1) * ecosM**(j - 2 * k -
                                                1) * esinM**(2 * k + 1) * e**-j
                temp = temp + s_list[i][0] * trig_sin
    if type(temp) != type(1): temp = temp.trim()
    return temp
示例#2
0
文件: keproc.py 项目: celesmec/eps3
def a_r(e, M, order):
    """
	Celestial mechanics classical expansion of a/r.
	"""
    from pyranha.math import cos
    from fractions import Fraction as F
    temp = 1
    for k in range(1, order + 1):
        temp = temp + F(2, 1) * besselJ(k, k * e, order) * cos(k * M)
    return temp
示例#3
0
文件: keproc.py 项目: celesmec/eps3
def cos_E(e, M, order):
    """
	Celestial mechanics classical expansion of cosE.
	"""
    from pyranha.math import cos
    from fractions import Fraction as F
    temp = F(-1, 2) * e
    for k in range(1, order + 2):
        temp = temp + F(1, k) * (besselJ(k - 1, k * e, order) -
                                 besselJ(k + 1, k * e, order)) * cos(k * M)
    return temp
示例#4
0
文件: keproc.py 项目: celesmec/eps3
def r_a(e, M, order):
    """
	Celestial mechanics classical expansion of r/a.
	"""
    from pyranha.math import cos
    from fractions import Fraction as F
    temp = 1 + F(1, 2) * e**2
    for k in range(1, order + 1):
        temp = temp - e * F(1, k) * (besselJ(k - 1, k * e, order - 1) -
                                     besselJ(k + 1, k * e, order - 1)) * cos(
                                         k * M)
    return temp
示例#5
0
文件: keproc.py 项目: celesmec/eps3
def cos_f(e, M, order):
    """
	Celestial mechanics classical expansion of cosf.
	"""
    from pyranha.math import cos
    temp = 0
    for k in range(1, order + 2):
        temp = temp + (besselJ(k - 1, k * e, order) +
                       besselJ(k + 1, k * e, order)) * cos(k * M)
    temp = temp * (1 - e**2) - e
    return temp.transform(
        lambda t: (t[0].filter(lambda u: u[1].degree(['e']) <= order), t[1]))
示例#6
0
文件: ham.py 项目: celesmec/eps
def rrr(q, n, deg):
    """
	Calculation expansions for r and them powers.
	- n is maximum degree of variables.
	"""
    from pyranha.math import cos, sin
    from eps.keproc import binomial_exp, r_a
    deg_max, e_max = n / 2 + 1, n
    MM, LL, xx, yy, uu, vv, qq = [
        epst(i + str(q)) for i in ('m', 'L', 'x', 'y', 'u', 'v', 'q')
    ]
    K0, ee, MA = epst('K0'), epst('e'), epst('M')
    S1 = epst('s' + str(q - 1)) if q != 1 else F(1, 1)
    S2 = epst('s' + str(q))
    ##################################################
    temp2 = binomial_exp(epst(1), -epst('eps'), F(1, 2), deg_max)
    temp5 = LL**F(-1, 2) * temp2.subs('eps',
                                      F(1, 4) * LL**-1 * (xx**2 + yy**2))
    ecospi = xx * temp5
    esinpi = -yy * temp5
    ##################################################
    ra = r_a(ee, MA, e_max)
    ra = kepler_trig_expand(ra)
    ra = ra.subs('e', ee**F(1, 2))
    subs1 = ecospi * cos(qq) + esinpi * sin(qq)
    subs2 = ecospi * sin(qq) - esinpi * cos(qq)
    subs3 = LL**-1 * (xx**2 + yy**2) * (1 - F(1, 4) * LL**-1 * (xx**2 + yy**2))
    ##################################################
    pt.set_auto_truncate_degree(F(n), ['x' + str(q), 'y' + str(q)])
    ra = ra.subs('ecosM', subs1)
    ra = ra.subs('esinM', subs2)
    ra = ra.subs('e', subs3)
    ra = ra.trim()
    aa = (K0 * MM**2 * S1)**-1 * S2 * LL**2
    ra_deg = (ra * aa)**deg
    pt.unset_auto_truncate_degree()
    return ra_deg.trim()
示例#7
0
文件: ham.py 项目: celesmec/eps3
def one_r(p, n, deg):
    """
	Calculation expansions for 1/r and their powers (deg).
	- n is maximum degree of variables.
	"""
    from pyranha.math import cos, sin
    from eps.keproc import binomial_exp, a_r
    deg_max, e_max = n / 2 + 1, n
    MM, LL, xx, yy, uu, vv, qq = [
        epst(i + str(p)) for i in ('m', 'L', 'x', 'y', 'u', 'v', 'q')
    ]
    K0, ee, MA = epst('K0'), epst('e'), epst('M')
    S1 = epst('s' + str(p - 1)) if p != 1 else F(1, 1)
    S2 = epst('s' + str(p))
    ########################################################################
    temp2 = binomial_exp(epst(1), -epst('eps'), F(1, 2), deg_max)
    temp5 = LL**F(-1, 2) * temp2.subs('eps',
                                      F(1, 4) * LL**-1 * (xx**2 + yy**2))
    ecospi = xx * temp5
    esinpi = -yy * temp5
    ########################################################################
    ar = a_r(ee, MA, e_max)
    ar = kepler_trig_expand(ar)
    ar = ar.subs('e', ee**F(1, 2))
    subs1 = ecospi * cos(qq) + esinpi * sin(qq)
    subs2 = ecospi * sin(qq) - esinpi * cos(qq)
    subs3 = LL**-1 * (xx**2 + yy**2) * (1 - F(1, 4) * LL**-1 * (xx**2 + yy**2))
    ########################################################################
    pt.set_auto_truncate_degree(F(n), ['x' + str(p), 'y' + str(p)])
    ar = ar.subs('ecosM', subs1)
    ar = ar.subs('esinM', subs2)
    ar = ar.subs('e', subs3)
    ar = ar.trim()
    aa = (K0 * MM**2 * S1)**-1 * S2 * LL**2
    ar_deg = (ar * aa**-1)**deg
    pt.unset_auto_truncate_degree()
    return ar_deg.trim()
示例#8
0
文件: ham.py 项目: celesmec/eps
def xyz(p, n):
    """
	Calculation expansions for vector of x, y, z-coordinates.
	- n is maximum degree of variables.
	"""
    from pyranha.math import cos, sin
    from eps.keproc import binomial_exp, cos_E, sin_E
    deg_max, e_max = n / 2 + 1, n
    MM, LL, xx, yy, uu, vv, qq = [
        epst(i + str(p)) for i in ('m', 'L', 'x', 'y', 'u', 'v', 'q')
    ]
    K0, ee, MA, ecosM, esinM = epst('K0'), epst('e'), epst('M'), epst(
        'ecosM'), epst('esinM')
    S1 = epst('s' + str(p - 1)) if p != 1 else F(1, 1)
    S2 = epst('s' + str(p))
    ##################################################
    temp1 = binomial_exp(epst(1), -epst('eps'), -1, deg_max)
    temp2 = binomial_exp(epst(1), -epst('eps'), F(1, 2), deg_max)
    temp3 = F(1, 4) * LL**-1 * temp1.subs('eps',
                                          F(1, 2) * LL**-1 * (xx**2 + yy**2))
    temp5 = LL**F(-1, 2) * temp2.subs('eps',
                                      F(1, 4) * LL**-1 * (xx**2 + yy**2))
    temp4 = LL**F(-1,2)   * temp1.subs('eps', F(1,2)*LL**-1 *    (xx**2 + yy**2)) * \
                            temp2.subs('eps', F(1,4)*LL**-1 * (2*(xx**2 + yy**2) + (uu**2 + vv**2)))
    cos2I = 1 - (uu**2 + vv**2) * temp3
    sin2Icos2Om = (uu**2 - vv**2) * temp3
    sin2Isin2Om = -2 * (uu * vv) * temp3
    sinIsinOm = -vv * temp4
    sinIcosOm = uu * temp4
    ecospi = xx * temp5
    esinpi = -yy * temp5
    ##################################################
    temp = binomial_exp(epst(1), -ee**2, F(1, 2), e_max)
    sqrt1 = F(1, 2) * (1 + temp)
    sqrt2 = F(1, 2) * (1 - temp)
    cosEM1 = cos_E(ee, MA, e_max) * cos(MA) + sin_E(ee, MA, e_max) * sin(MA)
    cosEM2 = cos_E(ee, MA, e_max) * cos(MA) - sin_E(ee, MA, e_max) * sin(MA)
    sinEM1 = sin_E(ee, MA, e_max) * cos(MA) - cos_E(ee, MA, e_max) * sin(MA)
    sinEM2 = sin_E(ee, MA, e_max) * cos(MA) + cos_E(ee, MA, e_max) * sin(MA)
    cosEM1 = (sqrt1 * cosEM1).truncate_degree(e_max, ['e'])
    cosEM2 = (sqrt2 * cosEM2).truncate_degree(e_max, ['e'])
    sinEM1 = (sqrt1 * sinEM1).truncate_degree(e_max, ['e'])
    sinEM2 = (sqrt2 * sinEM2).truncate_degree(e_max, ['e'])
    cosEM1 = kepler_trig_expand(cosEM1)
    cosEM2 = kepler_trig_expand(cosEM2)
    sinEM1 = kepler_trig_expand(sinEM1)
    sinEM2 = kepler_trig_expand(sinEM2)
    X_a = -ecosM + cosEM1 + cosEM2
    Y_a = esinM + sinEM1 - sinEM2
    X_a = X_a.subs('e', ee**F(1, 2))
    Y_a = Y_a.subs('e', ee**F(1, 2))
    subs1 = ecospi * cos(qq) + esinpi * sin(qq)
    subs2 = ecospi * sin(qq) - esinpi * cos(qq)
    subs3 = LL**-1 * (xx**2 + yy**2) * (1 - F(1, 4) * LL**-1 * (xx**2 + yy**2))
    ##################################################
    pt.set_auto_truncate_degree(
        F(n), ['x' + str(p), 'y' + str(p), 'u' + str(p), 'v' + str(p)])
    X_a = X_a.subs('ecosM', subs1)
    X_a = X_a.subs('esinM', subs2)
    X_a = X_a.subs('e', subs3)
    Y_a = Y_a.subs('ecosM', subs1)
    Y_a = Y_a.subs('esinM', subs2)
    Y_a = Y_a.subs('e', subs3)
    aa = (K0 * MM**2 * S1)**-1 * S2 * LL**2
    xa = aa * (X_a * (cos2I * cos(qq) + sin2Icos2Om * cos(qq) + sin2Isin2Om * sin(qq)) -\
         Y_a * (cos2I * sin(qq) + sin2Icos2Om * sin(qq) - sin2Isin2Om * cos(qq)))
    ya = aa * (X_a * (cos2I * sin(qq) - sin2Icos2Om * sin(qq) + sin2Isin2Om * cos(qq)) +\
         Y_a * (cos2I * cos(qq) - sin2Icos2Om * cos(qq) - sin2Isin2Om * sin(qq)))
    za = aa * (X_a * (sinIcosOm * sin(qq) - sinIsinOm * cos(qq)) +\
         Y_a * (sinIcosOm * cos(qq) + sinIsinOm * sin(qq)))
    pt.unset_auto_truncate_degree()
    return [xa.trim(), ya.trim(), za.trim()]
	def __init__(self,params = __default_params):
		from numpy import dot
		from mpmath import mpf
		from fractions import Fraction as Frac
		import sympy
		from IPython.parallel import Client
		# Set up constants.
		self.__eps_val = (1./mpf(299792458.))**2
		self.__GG_val = mpf(6.673E-11)
		# Various variables.
		Gt,I1,GG,m2,L,r,a,v2,Gtxy,ht,Ht,Gxy,h,H,J2,g,G,f,e,E,eps,hs,Hts,Gtxys = [pt(name) for name in ['\\tilde{G}','\\mathcal{I}_1',\
			'\\mathcal{G}','m_2','L','r','a','v2','\\tilde{G}_{xy}','\\tilde{h}','\\tilde{H}','G_{xy}','h','H','J_2','g','G','f','e','E',\
			'\\varepsilon','h_\\ast','\\tilde{H}_\\ast','\\tilde{G}_{xy\\ast}']]
		# The unperturbed Hamiltonian.
		H0 = Gt**2 * I1 / 2 - GG**2 * m2**2 * L**-2 / 2
		self.__HH0 = H0
		# Pieces of the perturbed Hamiltonian.
		Gt_vec = [Gtxy * math.sin(ht),-Gtxy * math.cos(ht),Ht]
		J2_vec = [0,0,J2]
		r_vec = dot(celmec.orbitalR([math.cos(g),math.sin(g),H*G**-1,Gxy*G**-1,math.cos(h),math.sin(h)]),[r*math.cos(f),r*math.sin(f),0])
		r_cross_v = [Gxy * math.sin(h),-Gxy * math.cos(h),H]
		H1 = -Frac(1,8) * v2 ** 2 - Frac(3,2) * v2 * GG * m2 * r ** -1 + Frac(1,2) * GG**2 * m2**2 * r**-2 +\
			Frac(3,2) * GG * m2 * r**-3 * dot(Gt_vec,r_cross_v) + 2 * GG * r**-3 * dot(J2_vec,r_cross_v) +\
			GG * r**-3 * (3 * dot(Gt_vec,r_vec) * dot(J2_vec,r_vec) * r**-2 - dot(Gt_vec,J2_vec))
		H1 = H1.subs('v2',GG * m2 * (2 * r**-1 - a ** -1)).subs('a',L ** 2 * (GG * m2)**-1)
		# Verify formula in the paper.
		assert(-Frac(1,8)*GG**4*m2**4*L**-4+r**-1*2*GG**3*m2**3*L**-2-r**-2*3*GG**2*m2**2+GG*r**-3*(\
			2*J2*H+3*J2*Gxy**2*Ht*(G**-2)/2+3*m2*Ht*H/2-J2*Ht+(3*m2/2*Gtxy*Gxy-3*J2/2*H*Gxy*Gtxy*G**-2)*math.cos(ht-h)+\
			3*J2*(-Frac(1,2)*Gxy**2*Ht*G**-2*math.cos(2*f+2*g)-Frac(1,4)*Gxy*Gtxy*G**-1*(1-H*G**-1)*math.cos(2*f+2*g+ht-h)+\
			Frac(1,4)*Gxy*Gtxy*G**-1*(1+H*G**-1)*math.cos(2*f+2*g-ht+h))) == H1)
		# Split the Hamiltonian in parts.
		A0 = H1.transform(lambda t: (t[0].filter(lambda t: t[1].degree(['r']) == 0),t[1])).filter(lambda t: t[1] == pt(1)).subs('r',pt(1))
		A1 = H1.transform(lambda t: (t[0].filter(lambda t: t[1].degree(['r']) == -1),t[1])).filter(lambda t: t[1] == pt(1)).subs('r',pt(1))
		A2 = H1.transform(lambda t: (t[0].filter(lambda t: t[1].degree(['r']) == -2),t[1])).filter(lambda t: t[1] == pt(1)).subs('r',pt(1))
		A3a = H1.transform(lambda t: (t[0].filter(lambda t: t[1].degree(['r']) == -3),t[1])).filter(lambda t: t[1] == pt(1)).subs('r',pt(1))
		A3b = H1.filter(lambda t: t[1] == math.cos(ht - h)).transform(lambda t: (t[0],pt(1))).subs('r',pt(1))
		B0 = H1.filter(lambda t: t[1] == math.cos(2*f + 2*g)).transform(lambda t: (t[0],pt(1))).subs('r',pt(1))
		B1 = H1.filter(lambda t: t[1] == math.cos(2*f + 2*g + ht - h)).transform(lambda t: (t[0],pt(1))).subs('r',pt(1))
		B2 = H1.filter(lambda t: t[1] == math.cos(2*f + 2*g - ht + h)).transform(lambda t: (t[0],pt(1))).subs('r',pt(1))
		# Make sure we got them right.
		assert(A0 + A1 * r**-1 + A2 * r**-2 + r**-3 * (A3a + A3b * math.cos(ht - h)) + r**-3 * (B0 * math.cos(2*f + 2*g) +\
			B1 * math.cos(2*f + 2*g + ht - h) + B2 * math.cos(2*f + 2*g - ht + h)) == H1)
		# This is the integrand in f (without the part that is integrated in E).
		f_int = A2 * r**-2 + r**-3 * (A3a + A3b * math.cos(ht - h)) + r**-3 * (B0 * math.cos(2*f + 2*g) + B1 * math.cos(2*f + 2*g + ht - h) + B2 * math.cos(2*f + 2*g - ht + h))
		# Change the integration variable to f (with the constant parts already taken out of the integral).
		f_int *= r**2
		# Substitute the definition of 1/r in terms of f.
		f_int = f_int.subs('r',pt('rm1')**-1).subs('rm1',GG*m2*G**-2*(1+e*math.cos(f)))
		# This is the integrand in E.
		E_int = A1 * r**-1
		# Change the integration variable to f.
		E_int *= r**2
		# Change the integration variable to E.
		E_int *= L*G*r**-1*GG**-1*m2**-1
		assert(E_int == A1*G*L*GG**-1*m2**-1)
		# K1.
		K1 = GG**2 * m2**2 * G**-1 * L**-3 * (f_int + E_int).filter(lambda t: t[1].t_degree(['f']) == 0)
		# K.
		K = K1 + A0
		# The generator.
		chi = G**-1 * (E_int.integrate('E') + f_int.integrate('f')) - L**3 * GG**-2 * m2**-2 * K1.integrate('l')
		# Verifiy that chi satisfies the homological equation, yielding K.
		assert((math.pbracket(H0,chi,['L','G','H','\\tilde{G}','\\tilde{H}'],['l','g','h','\\tilde{g}','\\tilde{h}']) + H1)\
			.subs('r',pt('rm1')**-1).subs('rm1',GG*m2*G**-2*(1+e*math.cos(f))) == K)
		# This is the complete Hamiltonian, with the two coordinates compressed into a single one.
		HHp = H0 + eps * K.subs('h',ht+hs).subs('\\tilde{H}',Hts-H).subs('\\tilde{G}_{xy}',Gtxys)
		# Record it as a member.
		self.__HHp = HHp
		# F0 and F1.
		F0 = HHp.filter(lambda t: t[1].t_degree(['h_\\ast']) == 0).transform(lambda t: (t[0].filter(lambda t: t[1].degree(['\\varepsilon']) == 1),t[1])).subs('\\varepsilon',pt(1))
		F1 = HHp.filter(lambda t: t[1].t_degree(['h_\\ast']) == 1).transform(lambda t: (t[0].filter(lambda t: t[1].degree(['\\varepsilon']) == 1),t[1])).subs('\\varepsilon',pt(1)).subs('h_\\ast',pt(0))
		assert(H0 + eps * F0 + eps * F1 * math.cos(pt('h_\\ast')) == H0 + eps * K.subs('h',ht+hs).subs('\\tilde{H}',Hts-H).subs('\\tilde{G}_{xy}',Gtxys))
		self.__F0 = F0
		self.__F1 = F1
		# Quartic polynomial.
		f4H = (eps**2 * F1 ** 2 - (pt('\\mathcal{H}^\\prime') - H0 - eps * F0)**2)\
			.ipow_subs('G_{xy}',2,G**2-H**2)\
			.ipow_subs('\\tilde{G}_{xy\\ast}',2,Gt**2-(Hts-H)**2)
		a4 = f4H.transform(lambda t: (t[0].filter(lambda t: t[1].degree(['H']) == 0),t[1]))
		a3 = f4H.transform(lambda t: (t[0].filter(lambda t: t[1].degree(['H']) == 1),t[1])).subs('H',pt(1)) / 4
		a2 = f4H.transform(lambda t: (t[0].filter(lambda t: t[1].degree(['H']) == 2),t[1])).subs('H',pt(1)) / 6
		a1 = f4H.transform(lambda t: (t[0].filter(lambda t: t[1].degree(['H']) == 3),t[1])).subs('H',pt(1)) / 4
		a0 = f4H.transform(lambda t: (t[0].filter(lambda t: t[1].degree(['H']) == 4),t[1])).subs('H',pt(1))
		# NOTE: these are not the polynomial coefficient strictly speaking, they are normalised by 4, 6 and 4
		# as shown above and in the assert below.
		self.__f4_cf = (a0,a1,a2,a3,a4)
		# Check we got them right.
		assert(a4+4*a3*H+6*a2*H**2+4*a1*H**3+a0*H**4 == f4H)
		# Store the coefficients - from high degree to low.
		self.__f4_coeffs = [t[0] * t[1].trim() for t in zip([1,4,6,4,1],self.__f4_cf)]
		# Derivatives of the quartic poly.
		f4Hp = math.partial(f4H,'H')
		f4Hpp = math.partial(f4Hp,'H')
		f4Hppp = math.partial(f4Hpp,'H')
		f4Hpppp = math.partial(f4Hppp,'H')
		# Check the derivatives for consistency.
		assert(f4Hp == 4*a3 + 12*a2*H + 12*a1*H**2 + 4*a0*H**3)
		assert(f4Hpp == 12*a2 + 24*a1*H + 12*a0*H**2)
		assert(f4Hppp == 24*a1 + 24*a0*H)
		assert(f4Hpppp == 24*a0)
		self.__f4 = [f4H, f4Hp, f4Hpp, f4Hppp, f4Hpppp]
		# Invariants for wp.
		g2 = a0*a4 - 4*a1*a3 + 3*a2**2
		g3 = a0*a2*a4 + 2*a1*a2*a3 - (a2**3) - (a0*a3**2) - (a1**2*a4)
		self.__g2 = g2
		self.__g3 = g3
		# Solve the angles.
		# Extract cosine of h_s.
		#chs = sympy.solve((spin_gr_theory.__to_sympy(self.HHp.trim())-sympy.Symbol('\\mathcal{H}^\\prime')).replace(sympy.cos(sympy.Symbol('h_\\ast')),sympy.Symbol('chs')),sympy.Symbol('chs'))[0]
		#ipy_view = Client().load_balanced_view()
		#g_sol = ipy_view.apply_async(spin_gr_theory.__solve_g,chs,spin_gr_theory.__to_sympy(math.partial(self.HHp.trim(),'G')))
		#hs_sol = ipy_view.apply_async(spin_gr_theory.__solve_hs,chs,spin_gr_theory.__to_sympy(math.partial(self.HHp.trim(),'H')))
		#ht_sol = ipy_view.apply_async(spin_gr_theory.__solve_ht,chs,spin_gr_theory.__to_sympy(math.partial(self.HHp.trim(),'\\tilde{H}_\\ast')))
		#self.__g_sol = g_sol.get()
		#self.__hs_sol = hs_sol.get()
		#self.__ht_sol = ht_sol.get()
		import pickle
		self.__g_sol = pickle.load(open('g_sol.pickle','rb'))
		self.__hs_sol = pickle.load(open('hs_sol.pickle','rb'))
		self.__ht_sol = pickle.load(open('ht_sol.pickle','rb'))
		# Set the parameters of the theory.
		self.__set_params(params)
		# Some sanity checks.
		HHp,G,L,H,GG,eps,m2,Hts,Gt,J2,hs,Gxy,Gtxys = [sympy.Symbol(s) for s in ['\\mathcal{H}^\\prime','G','L','H','\\mathcal{G}',\
			'\\varepsilon','m_2','\\tilde{H}_\\ast','\\tilde{G}','J_2','h_\\ast','G_{xy}','\\tilde{G}_{xy\\ast}']]
		# Phi_g^4 going to zero in the equilibrium point.
		assert(self.g_sol[0][3][1].subs(HHp,spin_gr_theory.__to_sympy(self.HHp.ipow_subs('G_{xy}',2,pt('G')**2\
			-pt('H')**2).subs('H',pt('G')**2*pt('m_2')*pt('J_2')**-1))).ratsimp() == 0)
		# Reduction to Einstein precession.
		simpl_HHp_ein = spin_gr_theory.__to_sympy(self.HHp.subs('J_2',0).subs('\\tilde{G}_{xy\\ast}',0).subs('\\tilde{H}_\\ast',pt('H'))\
			.subs('\\tilde{G}',0))
		ein_prec = sum([t[0]*t[1] for t in self.g_sol[0]]).subs('J_2',0).subs(Hts,H).subs(Gt,0)\
			.subs(HHp,simpl_HHp_ein).ratsimp()
		assert(ein_prec == 3 * eps * GG**4 * m2**4/(G**2*L**3))
		# Lense-Thirring precession for g.
		simpl_HHp_lt = spin_gr_theory.__to_sympy(self.HHp.subs('\\tilde{G}_{xy\\ast}',0).subs('\\tilde{H}_\\ast',pt('H'))\
			.subs('\\tilde{G}',0))
		lt_prec = sum([t[0]*t[1] for t in self.g_sol[0]]).subs(Hts,H).subs(Gt,0).subs(HHp,simpl_HHp_lt).ratsimp()
		assert(lt_prec == (eps * ((-6*H*J2*GG**4*m2**3)/(G**4*L**3)+3*GG**4*m2**4/(G**2*L**3))).ratsimp())
		# Geodetic effect on g.
		simpl_HHp_ge = spin_gr_theory.__to_sympy(self.HHp.subs('J_2',0)).subs(sympy.cos(hs),-1).subs(Gxy,sympy.sqrt(G**2-H**2))\
			.subs(Gtxys,sympy.sqrt(Gt**2-(Hts-H)**2)).subs(H,(Hts**2+G**2-Gt**2)/(2*Hts))
		ge_g = sum([t[0]*t[1] for t in self.g_sol[0]]).subs(J2,0).subs(Gxy,sympy.sqrt(G**2-H**2))\
			.subs(Gtxys,sympy.sqrt(Gt**2-(Hts-H)**2)).subs(H,(Hts**2+G**2-Gt**2)/(2*Hts)).subs(HHp,simpl_HHp_ge).ratsimp()
		assert(ge_g == (1 / (4*G**4*L**3) * (15*G**2*GG**4*eps*m2**4+9*GG**4*Gt**2*eps*m2**4-9*GG**4*Hts**2*eps*m2**4)).ratsimp())
		# No precession in h for Einstein case.
		assert((sum([t[0]*t[1] for t in self.hs_sol[0]]) + sum([t[0]*t[1] for t in self.ht_sol[0]])).subs(HHp,simpl_HHp_ein)\
			.subs('J_2',0).subs(Hts,H).ratsimp().subs(Gt,0) == 0)
		# h precession in LT.
		assert((sum([t[0]*t[1] for t in self.hs_sol[0]]) + sum([t[0]*t[1] for t in self.ht_sol[0]])).subs(HHp,simpl_HHp_lt)\
			.subs(Hts,H).ratsimp().subs(Gt,0).ratsimp() == 2*eps*J2*GG**4*m2**3/(G**3*L**3))
		# Geodetic effect for h and ht.
		assert((sum([t[0]*t[1] for t in self.hs_sol[0]]) + sum([t[0]*t[1] for t in self.ht_sol[0]])).subs(HHp,simpl_HHp_ge)\
			.subs(J2,0).subs(H,(Hts**2+G**2-Gt**2)/(2*Hts)).ratsimp() == 3*GG**4*Hts*eps*m2**4/(2*G**3*L**3))
		assert((sum([t[0]*t[1] for t in self.ht_sol[0]])).subs(HHp,simpl_HHp_ge)\
			.subs(J2,0).subs(H,(Hts**2+G**2-Gt**2)/(2*Hts)).ratsimp() == 3*GG**4*Hts*eps*m2**4/(2*G**3*L**3))