def test_gaunt(): def tn(a, b): return (a - b).n(64) < S('1e-64') assert gaunt(1, 0, 1, 1, 0, -1) == -1/(2*sqrt(pi)) assert tn(gaunt( 10, 10, 12, 9, 3, -12, prec=64), (-S(98)/62031) * sqrt(6279)/sqrt(pi)) def gaunt_ref(l1, l2, l3, m1, m2, m3): return ( sqrt((2 * l1 + 1) * (2 * l2 + 1) * (2 * l3 + 1) / (4 * pi)) * wigner_3j(l1, l2, l3, 0, 0, 0) * wigner_3j(l1, l2, l3, m1, m2, m3) ) threshold = 1e-10 l_max = 3 l3_max = 24 for l1 in range(l_max + 1): for l2 in range(l_max + 1): for l3 in range(l3_max + 1): for m1 in range(-l1, l1 + 1): for m2 in range(-l2, l2 + 1): for m3 in range(-l3, l3 + 1): args = l1, l2, l3, m1, m2, m3 g = gaunt(*args) g0 = gaunt_ref(*args) assert abs(g - g0) < threshold if m1 + m2 + m3 != 0: assert abs(g) < threshold if (l1 + l2 + l3) % 2: assert abs(g) < threshold
def test_gaunt(): def tn(a, b): return abs((a - b).n(64) < S('1e-64')) assert gaunt(1, 0, 1, 1, 0, -1) == -1 / (2 * sqrt(pi)) assert tn(gaunt(10, 10, 12, 9, 3, -12, prec=64), (-S(98) / 62031) * sqrt(6279) / sqrt(pi))
def test_gaunt(): def tn(a, b): return (a - b).n(64) < S('1e-64') assert gaunt(1, 0, 1, 1, 0, -1) == -1 / (2 * sqrt(pi)) assert tn(gaunt(10, 10, 12, 9, 3, -12, prec=64), (-S(98) / 62031) * sqrt(6279) / sqrt(pi)) def gaunt_ref(l1, l2, l3, m1, m2, m3): return (sqrt((2 * l1 + 1) * (2 * l2 + 1) * (2 * l3 + 1) / (4 * pi)) * wigner_3j(l1, l2, l3, 0, 0, 0) * wigner_3j(l1, l2, l3, m1, m2, m3)) threshold = 1e-10 l_max = 3 l3_max = 24 for l1 in range(l_max + 1): for l2 in range(l_max + 1): for l3 in range(l3_max + 1): for m1 in range(-l1, l1 + 1): for m2 in range(-l2, l2 + 1): for m3 in range(-l3, l3 + 1): args = l1, l2, l3, m1, m2, m3 g = gaunt(*args) g0 = gaunt_ref(*args) assert abs(g - g0) < threshold if m1 + m2 + m3 != 0: assert abs(g) < threshold if (l1 + l2 + l3) % 2: assert abs(g) < threshold
def Calc_Coeffs(N_modes): s = (N_modes,N_modes,N_modes); aPsi = np.zeros(s); bPsi = np.zeros(s); aTt = np.zeros(s); bTt = np.zeros(s); for n in xrange(N_modes): print "Mode l = ",n,"\n" norm_psi = norm_geg(n-1) for l in xrange(N_modes): for m in xrange(N_modes): if (l+m+n)%2 == 0: if (l <= (m+n)) and (m <= (l+n)) and (n <= (l+m)): # Calc as common norm_g = np.sqrt( (4.0*np.pi)/((2*l + 1)*(2*m+1)*(2*n+1))) # Calculate 5 Gaunt coefficients m_1, m_2, m_3 = 0,-1,1; G_0m11 = float(gaunt(l,m,n,m_1, m_2, m_3,prec=digits))*norm_g; m_1, m_2, m_3 = -1,0,1; G_m101 = float(gaunt(l,m,n,m_1, m_2, m_3,prec=digits))*norm_g; m_1, m_2, m_3 = -1,-1,2; G_m1m12 = float(gaunt(l,m,n,m_1, m_2, m_3,prec=digits))*norm_g; m_1, m_2, m_3 = 1,-1,0; G_1m10 = float(gaunt(l,m,n,m_1, m_2, m_3,prec=digits))*norm_g; m_1, m_2, m_3 = 0,0,0; G_000 = float(gaunt(l,m,n,m_1, m_2, m_3,prec=digits))*norm_g; # Determine PSI coefficients aPsi[l,m,n] = aPSI(l,m,n,G_0m11)*norm_psi; bPsi[l,m,n] = bPSI(l,m,n,G_m101,G_m1m12,G_1m10)*norm_psi; # Determine Temperature Coefficients aTt[l,m,n] = aT(l,m,n,G_000); bTt[l,m,n] = bT(l,m,n,G_1m10); #clear cache #gc.collect() # Works but super slow Stringy = ['/home/mannixp/Dropbox/Imperial/PhD_Thermal/CODES/Rotating_FIX/Integrated_Modes300/'] os.chdir("".join(Stringy)) np.save("aPsi.npy",aPsi); np.save("bPsi.npy",bPsi); ###np.save("aPsi_Om.npy",aPsi_Om); np.save("bPsi_Om.npy",bPsi_Om); np.save("aT.npy",aTt); np.save("bT.npy",bTt);
def atomic_formfactor_scalar(element, n, l, m, kPrime, lPrime, mPrime, q): f12 = 0 for L in range(abs(l - lPrime), l + lPrime + 1): radial_integral_1 = radial_integral(1, element, n, l, kPrime, lPrime, L, q, "numpy-stepwise") f12 += np.sqrt(4 * np.pi) * pow(1j, L) * radial_integral_1 * ( -1)**mPrime * np.sqrt(2 * L + 1) * float( gaunt(l, lPrime, L, m, -mPrime, 0)) return f12
def Rgaunt(l1, l2, l3, m1, m2, m3): result = 0 for m1p in range(-l1, l1 + 1): U1 = U(l1, m1p, m1) for m2p in range(-l2, l2 + 1): U2 = U(l2, m2p, m2) for m3p in range(-l3, l3 + 1): U3 = U(l3, m3p, m3) result += U1 * U2 * U3 * gaunt(l1, l2, l3, m1p, m2p, m3p) return simplify(sqrt(pi) * result)
def Rgaunt(l1, l2, l3, m1, m2, m3, evaluate=True): result = 0 for m1p in range(-l1, l1 + 1): U1 = U(l1, m1p, m1) for m2p in range(-l2, l2 + 1): U2 = U(l2, m2p, m2) for m3p in range(-l3, l3 + 1): U3 = U(l3, m3p, m3) result += U1 * U2 * U3 * gaunt(l1, l2, l3, m1p, m2p, m3p) if evaluate: return result.evalf() else: return result
def gauntR(l1, l2, l3, m1, m2, m3, evaluate=True): result = 0 for m1p in range(-l1, l1 + 1): U1 = U(l1, m1, m1p) for m2p in range(-l2, l2 + 1): U2 = U(l2, m2, m2p) for m3p in range(-l3, l3 + 1): U3 = U(l3, m3, m3p) result += U1 * U2 * U3 * gaunt(l1, l2, l3, m1p, m2p, m3p) if evaluate: return float(result) else: return result
def rgaunt(l1, l2, l3, m1, m2, m3): res = None (m1, l1), (m2, l2), (m3, l3) = sorted([(m1, l1), (m2, l2), (m3, l3)], reverse=True) if m3 > 0: # then m1 > 0, m2 > 0, m3 > 0 if m1 == m2 + m3: res = (-1)**m1 * factor * gaunt(l1, l2, l3, -m1, m2, m3) elif m2 == m1 + m3: res = (-1)**m2 * factor * gaunt(l1, l2, l3, m1, -m2, m3) elif m3 == m1 + m2: res = (-1)**m3 * factor * gaunt(l1, l2, l3, m1, m2, -m3) else: res = 0 elif m3 == 0: if m1 == 0 and m2 == 0: res = gaunt(l1, l2, l3, 0, 0, 0) elif m1 == m2: # m1, m2 > 0 res = (-1)**m1 * gaunt(l1, l2, l3, m1, -m1, 0) else: res = 0 else: # m3 < 0 if m2 < 0: if m1 == 0: if m2 == m3: res = (-1)**m2 * gaunt(l1, l2, l3, 0, m2, -m2) else: res = 0 elif m1 > 0: if m2 == m1 + m3: res = (-1)**m3 * factor * gaunt(l1, l2, l3, m1, -m2, m3) elif m3 == m1 + m2: res = (-1)**m2 * factor * gaunt(l1, l2, l3, m1, m2, -m3) elif m1 + m2 + m3 == 0: res = -(-1)**m1 * factor * gaunt(l1, l2, l3, m1, m2, m3) else: res = 0 else: res = 0 else: res = 0 return res
def compute_gaunt_coefs(L): coefs = [] indices = [] rindices = [] print("l lp l1 l2 m mp m1 m2") for l in range(L): for lp in range(L): for l1 in range(L): for l2 in range(L): for m in range(-l, l + 1): for mp in range(-lp, lp + 1): for m1 in range(-l1, l1 + 1): for m2 in range(-l2, l2 + 1): print(l, lp, l1, l2, m, mp, m1, m2, end="\r") gaunt1 = gaunt(l1, l2, l2, -m1, -m2, m2) gaunt2 = gaunt(l, l1, lp, -m, m1, mp) product = gaunt1 * gaunt2 if product != 0: term = float( (-1.0)**(m + m1 + m2) * product) coefs.append(term) indices.append([ map(l, m), map(lp, mp), l1, map(l2, m2) ]) rindices.append([l1, map(l2, m2)]) return np.array(coefs), np.array(indices), np.unique(rindices, axis=0)
def Calc_Coeffs_Par(N_modes,n): s = (N_modes,N_modes); aPsi_1 = np.zeros(s); bPsi_1 = np.zeros(s); aTt_1 = np.zeros(s); bTt_1 = np.zeros(s); print "Mode l = ",n,"\n" norm_psi = norm_geg(n-1) for l in xrange(N_modes): for m in xrange(N_modes): if (l+m+n)%2 == 0: if (l <= (m+n)) and (m <= (l+n)) and (n <= (l+m)): # Calc as common norm_g = np.sqrt( (4.0*np.pi)/((2*l + 1)*(2*m+1)*(2*n+1))) # Calculate 5 Gaunt coefficients m_1, m_2, m_3 = 0,-1,1; G_0m11 = gaunt(l,m,n,m_1, m_2, m_3,prec=digits)*norm_g; m_1, m_2, m_3 = -1,0,1; G_m101 = gaunt(l,m,n,m_1, m_2, m_3,prec=digits)*norm_g; m_1, m_2, m_3 = -1,-1,2; G_m1m12 = gaunt(l,m,n,m_1, m_2, m_3,prec=digits)*norm_g; m_1, m_2, m_3 = 1,-1,0; G_1m10 = gaunt(l,m,n,m_1, m_2, m_3,prec=digits)*norm_g; m_1, m_2, m_3 = 0,0,0; G_000 = gaunt(l,m,n,m_1, m_2, m_3,prec=digits)*norm_g; # Determine PSI coefficients aPsi_1[l,m] = aPSI(l,m,n,G_0m11)*norm_psi; bPsi_1[l,m] = bPSI(l,m,n,G_m101,G_m1m12,G_1m10)*norm_psi; # Determine Temperature Coefficients aTt_1[l,m] = aT(l,m,n,G_000); bTt_1[l,m] = bT(l,m,n,G_1m10); return aPsi_1,bPsi_1,aTt_1,bTt_1;
def angulaV_sym(l,l1_,l2_,L_,mL_,l1,l2,L,mL): if mL != mL_ or L!=L_: return 0 if l > max(l1_+l1,l2_+l2) or l < min(abs(l1-l1_),abs(l2-l2_)): return 0 res = 0 # print(range(max(-l1,mL-l2),min(l1,mL+l2)+1)) for m1 in range(max(-l1,mL-l2),min(l1,mL+l2)+1): # print("m1 =",m1,range(max(-l1_,mL_-l2_,m1-l),min(l1,mL_+l2_,m1+l)+1)) for m1_ in range(max(-l1_,mL_-l2_,m1-l),min(l1,mL_+l2_,m1+l)+1): m = m1_-m1 res += N(CG_sym(l1_,l2_,L_, m1_,mL_-m1_,mL_)*CG_sym(l1, l2, L, m1, mL -m1, mL )*gaunt(l1_,l,l1,-m1_,m,m1)*gaunt(l2_,l,l2,-(mL_-m1_),-m,mL-m1))\ * (-1 if (mL+m)%2 == 1 else 1) # print("\t\t", res) # print("") return res
def A_translation(m, n, u, v, r, theta, phi, k): m *= -1 f = lambda n: special.gamma(n + 1) numerator = (2 * v + 1) * f(n - m) * f(v - u) denominator = 2 * n * (n + 1) * f(n + m) * f(v + u) factor = (-1)**m * numerator / denominator * np.exp(1j * (u + m) * phi) qmax = min(n, v, (n + v - abs(m + u)) // 2) sum_term = 0 for q in range(0, qmax + 1): p = n + v - 2 * q aq = gaunt(m, n, u, v, p) A = 1j**p * (n * (n + 1) + v * (v + 1) - p * (p + 1)) * aq Pnm = miepy.vsh.associated_legendre(p, u + m) sum_term += A * miepy.vsh.spherical_hn(p, k * r) * Pnm(np.cos(theta)) return factor * sum_term
def overlap(lk,lj,li, mk,mj,mi, GAUNT_PRECISION=6): return np.complex64( (-1)**abs(mi) * gaunt(int(lk),int(lj),int(li), int(+mk),int(+mj),int(-mi), prec=GAUNT_PRECISION) ) # Last {l,m} index pair are associated with the conjugate term.
""" \file Python script for generating Gaunt coefficients and factors used for offsite partial wave overlap integrals. """ from sympy.physics.wigner import gaunt, wigner_3j import numpy as np from sympy import N gcs = np.zeros([4, 4, 4, 7, 4]) facs = np.zeros([4, 4, 4, 7, 4]) print(gaunt(1, 0, 1, 1, 0, 0)) print(N(gaunt(1, 0, 1, 1, 0, -1))) print(type(N(gaunt(1, 0, 1, 1, 0, -1)))) for l1 in range(4): for l2 in range(l1 + 1): for l3 in range(abs(l1 - l2), l1 + l2 + 1, 2): for m1 in range(-l1, l1 + 1): for m2 in range(0, l2 + 1): val = N(gaunt(l1, l2, l3, m1, m2, -m1 - m2)) gcs[l1][l2][(l3 - abs(l1 - l2)) // 2][l1 + m1][m2] = val val2 = N(wigner_3j(l1, l2, l3, 0, 0, 0)) * N( wigner_3j(l1, l2, l3, -m1, m2, m1 - m2)) val3 = np.sqrt( (2 * l1 + 1) * (2 * l2 + 1) * (2 * l3 + 1) / 4 / np.pi) facs[l1][l2][(l3 - abs(l1 - l2)) // 2][l1 + m1][m2] = val2 * val3 print(val, val2 * val3)
def test_y1mat_Yqk(self): self.assertAlmostEqual( (-1)**(2+1)*wigner.gaunt(2, 1, 3, -1, 0, 1, 10.0), y1mat_Yqk((2, 1), (1, 0), (3, 1))) yyy = y1mat_Yqk((2, 1), (1, 0), (3, 1)) self.assertEqual(type(yyy), np.float64)
def Calc_Coeffs(N_modes,n_start,n_end): n_range = n_end - n_start; s = (N_modes,N_modes,n_range); aPsi = np.zeros(s); bPsi = np.zeros(s); aTt = np.zeros(s); bTt = np.zeros(s); for n in xrange(n_range): n = n_start + n print "Mode l = ",n,"\n" norm_psi = norm_geg(n-1) for l in xrange(N_modes): for m in xrange(N_modes): if (l+m+n)%2 == 0: if (l <= (m+n)) and (m <= (l+n)) and (n <= (l+m)): # Use Additional Symmetries # Calc as common norm_g = np.sqrt( (4.0*np.pi)/((2*l + 1)*(2*m+1)*(2*n+1))) # Calculate 5 Gaunt coefficients m_1, m_2, m_3 = 0,-1,1; G_0m11 = gaunt(l,m,n,m_1, m_2, m_3,prec=digits)*norm_g; m_1, m_2, m_3 = -1,0,1; G_m101 = gaunt(l,m,n,m_1, m_2, m_3,prec=digits)*norm_g; m_1, m_2, m_3 = -1,-1,2; G_m1m12 = gaunt(l,m,n,m_1, m_2, m_3,prec=digits)*norm_g; m_1, m_2, m_3 = 1,-1,0; G_1m10 = gaunt(l,m,n,m_1, m_2, m_3,prec=digits)*norm_g; m_1, m_2, m_3 = 0,0,0; G_000 = gaunt(l,m,n,m_1, m_2, m_3,prec=digits)*norm_g; # Determine PSI coefficients aPsi[l,m,n-n_start] = aPSI(l,m,n,G_0m11)*norm_psi; bPsi[l,m,n-n_start] = bPSI(l,m,n,G_m101,G_m1m12,G_1m10)*norm_psi; # Determine Temperature Coefficients aTt[l,m,n-n_start] = aT(l,m,n,G_000); bTt[l,m,n-n_start] = bT(l,m,n,G_1m10); #clear cache #gc.collect() # Works but super slow 5 -> 10 times # ~~~~~~ @ CEDRIC ~~~~ # Folder is created locally in execution directory, within which the coefficient arrays are saved #~~~~~~~~~~~~~~~~~~~~~~ Stringy = ['Integrated_Modes',str(N_modes),'_Range',str(n_start),'_to_',str(n_end-1)] os.mkdir("".join(Stringy)) os.chdir("".join(Stringy)) # Save Psi Coefficients np.save("aPsi.npy",aPsi); np.save("bPsi.npy",bPsi); # Save T,C Coefficients np.save("aT.npy",aTt); np.save("bT.npy",bTt); end_time = time.time() print("Elapsed time was %g seconds" % (end_time - start_time))
def atomic_formfactor_vector(component,element,n,l,m,kPrime,lPrime,mPrime,q): f12 = 0 dlog10k = np.log10(kMax/kMin) / (gridsize - 1) dlog10q = np.log10(qMax/qMin) / (gridsize - 1) ki =int( round(np.log10(kPrime/kMin) / dlog10k) ) qi =int( round(np.log10(q/qMin) / dlog10q) ) for lHat in [l-1,l+1]: for L in range(abs(lHat-lPrime),lHat+lPrime+1): radial_integral_2 = np.loadtxt("../data/radial_integral_2/" + element.Shell_Name(n, l) + "_" + str(lPrime) + "_" + str(L) + ".txt") radial_integral_3 = np.loadtxt("../data/radial_integral_3/" + element.Shell_Name(n, l) + "_" + str(lPrime) + "_" + str(L) + ".txt") for mHat in range(m-1,m+2): f12 += pow(1j,L) * (VSH_coefficients_Y(component,l,m,lHat,mHat) * radial_integral_2[ki][qi] + VSH_coefficients_Psi(component,l,m,lHat,mHat) * radial_integral_3[ki][qi]) * (-1)**mPrime * np.sqrt(4*np.pi) * np.sqrt(2*L+1) * float(gaunt(lHat,lPrime,L,mHat,-mPrime,0)) return 1j / mElectron *f12
def gaunt_integral(y1, y2, y3, y1_dash, y2_dash, y3_dash): # расчет интеграла по d omega, d omega' return pow(-1, y1.m) * gaunt(y1.l, y2.l, y3.l, y1.m, y2.m, y3.m) * gaunt( y1_dash.l, y2_dash.l, y3_dash.l, y1_dash.m, y2_dash.m, y3_dash.m)
def tabulate_atomic_response_function(response, element, n, l, gridsize): filepath = "../data/atomic_response_" + str( response) + "/" + element.Shell_Name(n, l) + ".txt" if os.path.exists(filepath) == False: print("Tabulation of response", response, "of", element.Shell_Name(n, l), "started.") result = [[0 for x in range(gridsize)] for y in range(gridsize)] kGrid = np.logspace(np.log10(kMin), np.log10(kMax), gridsize) qGrid = np.logspace(np.log10(qMin), np.log10(qMax), gridsize) if response == 1: for lPrime in range(lPrime_max + 1): for L in range(abs(l - lPrime), l + lPrime + 1): radial_integral_table = np.loadtxt( "../data/radial_integral_1/" + element.Shell_Name(n, l) + "_" + str(lPrime) + "_" + str(L) + ".txt") for ki in range(gridsize): k = kGrid[ki] for qi in range(gridsize): result[ki][qi] += 4 * pow(k, 3) / pow( 2 * np.pi, 3) * (2 * l + 1) * ( 2 * lPrime + 1) * (2 * L + 1) * pow( radial_integral_table[ki][qi], 2) * pow( wigner_3j(l, lPrime, L, 0, 0, 0), 2) # Subtract 1 radial_integral_table = np.loadtxt("../data/radial_integral_1/" + element.Shell_Name(n, l) + "_" + str(l) + "_" + str(0) + ".txt") methods = np.loadtxt('../data/integration_methods_1/' + element.Shell_Name(n, l) + '_' + str(l) + "_" + str(0) + '.txt', dtype='str') for ki in range(gridsize): k = kGrid[ki] radial_integral_one = radial_integral(1, element, n, l, k, l, 0, 0, "numpy-stepwise") for qi in range(gridsize): q = qGrid[qi] correction = 4 * pow(k, 3) / pow(2 * np.pi, 3) * ( 2 * l + 1) * (radial_integral_one * radial_integral_one - 2 * radial_integral_one * radial_integral_table[ki][qi]) if (correction < 0): result[ki][qi] += correction else: break elif response == 2: for lPrime in range(lPrime_max + 1): for L in range(abs(l - lPrime), l + lPrime + 1): radial_integral_1 = np.loadtxt( "../data/radial_integral_1/" + element.Shell_Name(n, l) + "_" + str(lPrime) + "_" + str(L) + ".txt") for lHat in [l - 1, l + 1]: for LHat in range(abs(lHat - lPrime), lHat + lPrime + 1): radial_integral_2 = np.loadtxt( "../data/radial_integral_2/" + element.Shell_Name(n, l) + "_" + str(lPrime) + "_" + str(LHat) + ".txt") radial_integral_3 = np.loadtxt( "../data/radial_integral_3/" + element.Shell_Name(n, l) + "_" + str(lPrime) + "_" + str(LHat) + ".txt") for m in range(-l, l + 1): mHat = m Gaunt_Sum = 0.0 for mPrime in range(-lPrime, lPrime + 1): Gaunt_Sum += float( gaunt(l, lPrime, L, m, -mPrime, 0) * gaunt(lHat, lPrime, LHat, mHat, -mPrime, 0)) if (Gaunt_Sum != 0.0): for ki in range(gridsize): k = kGrid[ki] for qi in range(gridsize): q = qGrid[qi] result[ki][ qi] += 1 / mElectron * 4 * pow( k, 3 ) / pow( 2 * np.pi, 3 ) * 4 * np.pi * q / mElectron * pow( -1j, LHat + 1 ) * pow( 1j, L ) * radial_integral_1[ki][qi] * ( VSH_coefficients_Psi( 3, l, m, lHat, mHat) * radial_integral_3[ki][qi] + VSH_coefficients_Y( 3, l, m, lHat, mHat) * radial_integral_2[ki][qi] ) * np.sqrt(2 * L + 1) * np.sqrt( 2 * LHat + 1) * Gaunt_Sum elif response == 3: for lPrime in range(lPrime_max + 1): for lHat in [l - 1, l + 1]: for L in range(abs(lHat - lPrime), lHat + lPrime + 1): radial_integral_2 = np.loadtxt( "../data/radial_integral_2/" + element.Shell_Name(n, l) + "_" + str(lPrime) + "_" + str(L) + ".txt") radial_integral_3 = np.loadtxt( "../data/radial_integral_3/" + element.Shell_Name(n, l) + "_" + str(lPrime) + "_" + str(L) + ".txt") for lHat2 in [l - 1, l + 1]: for L2 in range(abs(lHat2 - lPrime), lHat2 + lPrime + 1): radial_integral_2_conj = np.loadtxt( "../data/radial_integral_2/" + element.Shell_Name(n, l) + "_" + str(lPrime) + "_" + str(L2) + ".txt") radial_integral_3_conj = np.loadtxt( "../data/radial_integral_3/" + element.Shell_Name(n, l) + "_" + str(lPrime) + "_" + str(L2) + ".txt") for m in range(-l, l + 1): for mHat in range(m - 1, m + 2): for mHat2 in range(m - 1, m + 2): Gaunt_Sum = 0.0 for mPrime in range( -lPrime, lPrime + 1): Gaunt_Sum += float( gaunt( lHat, lPrime, L, mHat, -mPrime, 0) * gaunt( lHat2, lPrime, L2, mHat2, -mPrime, 0)) if (Gaunt_Sum != 0.0): for i in range(1, 4): for ki in range(gridsize): k = kGrid[ki] for qi in range( gridsize): result[ki][qi] += 1 / mElectron / mElectron * 4 * pow( k, 3 ) / pow( 2 * np.pi, 3 ) * 4 * np.pi * pow( 1j, L ) * pow(-1j, L2) * ( VSH_coefficients_Psi( i, l, m, lHat, mHat) * radial_integral_3[ ki][qi] + VSH_coefficients_Y( i, l, m, lHat, mHat) * radial_integral_2[ ki][qi] ) * np.conj( VSH_coefficients_Psi( i, l, m, lHat2, mHat2) * radial_integral_3_conj[ ki][qi] + VSH_coefficients_Y( i, l, m, lHat2, mHat2) * radial_integral_2_conj[ ki][qi] ) * np.sqrt( 2 * L + 1) * np.sqrt( 2 * L2 + 1 ) * Gaunt_Sum elif response == 4: for lPrime in range(lPrime_max + 1): for lHat in [l - 1, l + 1]: for L in range(abs(lHat - lPrime), lHat + lPrime + 1): radial_integral_2 = np.loadtxt( "../data/radial_integral_2/" + element.Shell_Name(n, l) + "_" + str(lPrime) + "_" + str(L) + ".txt") radial_integral_3 = np.loadtxt( "../data/radial_integral_3/" + element.Shell_Name(n, l) + "_" + str(lPrime) + "_" + str(L) + ".txt") for lHat2 in [l - 1, l + 1]: for L2 in range(abs(lHat2 - lPrime), lHat2 + lPrime + 1): radial_integral_2_conj = np.loadtxt( "../data/radial_integral_2/" + element.Shell_Name(n, l) + "_" + str(lPrime) + "_" + str(L2) + ".txt") radial_integral_3_conj = np.loadtxt( "../data/radial_integral_3/" + element.Shell_Name(n, l) + "_" + str(lPrime) + "_" + str(L2) + ".txt") for m in range(-l, l + 1): for mHat in range(m - 1, m + 2): for mHat2 in range(m - 1, m + 2): Gaunt_Sum = 0.0 for mPrime in range( -lPrime, lPrime + 1): Gaunt_Sum += float( gaunt( lHat, lPrime, L, mHat, -mPrime, 0) * gaunt( lHat2, lPrime, L2, mHat2, -mPrime, 0)) if (Gaunt_Sum != 0.0): for ki in range(gridsize): k = kGrid[ki] for qi in range(gridsize): q = qGrid[qi] result[ki][qi] += pow( q / mElectron, 2 ) * 1 / mElectron / mElectron * 4 * pow( k, 3 ) / pow( 2 * np.pi, 3 ) * 4 * np.pi * pow( 1j, L ) * pow(-1j, L2) * ( VSH_coefficients_Psi( 3, l, m, lHat, mHat) * radial_integral_3[ ki][qi] + VSH_coefficients_Y( 3, l, m, lHat, mHat) * radial_integral_2[ ki][qi] ) * np.conj( VSH_coefficients_Psi( 3, l, m, lHat2, mHat2) * radial_integral_3_conj[ ki][qi] + VSH_coefficients_Y( 3, l, m, lHat2, mHat2) * radial_integral_2_conj[ ki][qi] ) * np.sqrt( 2 * L + 1) * np.sqrt( 2 * L2 + 1) * Gaunt_Sum else: sys.exit( "Error in tabulate_electronic_ionization_responses(): Response out of bound." ) np.savetxt(filepath, np.real(result)) print("Tabulation of response", response, "of", element.Shell_Name(n, l), "finished.")
def atomic_formfactor_vector_alternative(component,element,n,l,m,kPrime,lPrime,mPrime,q1,q2,q3): f12 = 0 q = np.sqrt(q1*q1+q2*q2+q3*q3) theta_q = np.arccos(q3/q) phi_q = np.arctan2(q2,q1) # print("angles:",theta_q/np.pi,phi_q/np.pi) dlog10k = np.log10(kMax/kMin) / (gridsize - 1) dlog10q = np.log10(qMax/qMin) / (gridsize - 1) ki =int( round(np.log10(kPrime/kMin) / dlog10k) ) qi =int( round(np.log10(q/qMin) / dlog10q) ) for lHat in [l-1,l+1]: for L in range(abs(lHat-lPrime),lHat+lPrime+1): radial_integral_2 = np.loadtxt("../data/radial_integral_2/" + element.Shell_Name(n, l) + "_" + str(lPrime) + "_" + str(L) + ".txt") radial_integral_3 = np.loadtxt("../data/radial_integral_3/" + element.Shell_Name(n, l) + "_" + str(lPrime) + "_" + str(L) + ".txt") for M in range(-L,L+1): for mHat in range(m-1,m+2): new = 1.0/mElectron * 4*np.pi * pow(1j,L+1) * np.conj(sph_harm(M,L,phi_q,theta_q)) * (VSH_coefficients_Y(component,l,m,lHat,mHat) * radial_integral_2[ki][qi] + VSH_coefficients_Psi(component,l,m,lHat,mHat) * radial_integral_3[ki][qi]) * (-1)**mPrime * float(gaunt(lHat,lPrime,L,mHat,-mPrime,M)) f12 += new return f12
def atomic_formfactor_scalar_alternative(element,n,l,m,kPrime,lPrime,mPrime,q1,q2,q3): f12 = 0 q = np.sqrt(q1*q1+q2*q2+q3*q3) theta_q = np.arccos(q3/q) phi_q = np.arctan2(q2,q1) dlog10k = np.log10(kMax/kMin) / (gridsize - 1) dlog10q = np.log10(qMax/qMin) / (gridsize - 1) ki =int( round(np.log10(kPrime/kMin) / dlog10k) ) qi =int( round(np.log10(q/qMin) / dlog10q) ) for L in range(abs(l-lPrime),l+lPrime+1): radial_integral_1 = np.loadtxt("../data/radial_integral_1/" + element.Shell_Name(n, l) + "_" + str(lPrime) + "_" + str(L) + ".txt") for M in range(-L,L+1): if L >= 0 and abs(M) <=L: new = 4*np.pi * pow(1j,L) * np.conj(sph_harm(M,L,phi_q,theta_q)) * radial_integral_1[ki][qi] * (-1)**mPrime * float(gaunt(l,lPrime,L,m,-mPrime,M)) f12 += new return f12
def gauntB(l1, l2, l3, m1, m2, m3, alm1, alm2, alm3): #This function is to calculate the total term on equation (2.3) of the paper https://arxiv.org/pdf/1509.08107.pdf b_ell = gaunt(l1,l2,l3,m1,m2,m3)*np.real(alm1*alm2*alm3) #The l1,l2,l3 and m1,m2,m3 refers to a_lm of the spherical harmonics. return b_ell #The p1,p2,p3 refers to the position in alm vector, which carries the map.
def test_gaunt(): def tn(a, b): return abs((a - b).n(64) < S('1e-64')) assert gaunt(1, 0, 1, 1, 0, -1) == -1/(2*sqrt(pi)) assert tn(gaunt( 10, 10, 12, 9, 3, -12, prec=64), (-S(98)/62031) * sqrt(6279)/sqrt(pi))
def get_gaunt(l1, l2): """ Calculate the Gaunt coefficents :math:`C_{l_1,l_2}(k,m_1,m_2)` .. math:: C_{l_1,l_2}(k,m_1,m_2)=\\sqrt{\\frac{4\\pi}{2k+1}} \\int \\mathop{d\\phi} \\mathop{d\\theta} sin(\\theta) Y_{l_1}^{m_1\\star}(\\theta,\\phi) Y_{k}^{m_1-m_2}(\\theta,\\phi) Y_{l_2}^{m_2}(\\theta,\\phi) Parameters ---------- l1: int The first quantum number of angular momentum. l2: int The second quantum number of angular momentum. Returns ------- res: 3d float array The calculated Gaunt coefficents. The 1st index (:math:`= 0, 1, ..., l_1+l_2+1`) is the order :math:`k`. The 2nd index (:math:`= 0, 1, ... ,2l_1`) is the magnetic quantum number :math:`m_1` plus :math:`l_1` The 3nd index (:math:`= 0, 1, ... ,2l_2`) is the magnetic quantum number :math:`m_2` plus :math:`l_2` Notes ----- It should be noted that :math:`C_{l_1,l_2}(k,m_1,m_2)` is nonvanishing only when :math:`k + l_1 + l_2 = \\text{even}`, and :math:`|l_1 - l_2| \\leq k \\leq l_1 + l_2`. Please see Ref. [1]_ p. 10 for more details. References ---------- .. [1] Sugano S, Tanabe Y and Kamimura H. 1970. Multiplets of Transition-Metal Ions in Crystals. Academic Press, New York and London. Examples -------- >>> import edrixs Get gaunt coefficients between :math:`p`-shell and :math:`d`-shell >>> g = edrixs.get_gaunt(1, 2) """ from sympy import N res = np.zeros((l1 + l2 + 1, 2 * l1 + 1, 2 * l2 + 1), dtype=np.float64) for k in range(l1 + l2 + 1): if not (np.mod(l1 + l2 + k, 2) == 0 and np.abs(l1 - l2) <= k <= l1 + l2): continue for i1, m1 in enumerate(range(-l1, l1 + 1)): for i2, m2 in enumerate(range(-l2, l2 + 1)): res[k, i1, i2] = (N(gaunt(l1, k, l2, -m1, m1 - m2, m2)) * (-1.0)**m1 * np.sqrt(4 * np.pi / (2 * k + 1))) return res
def tensorC(l0,l1,l2,m0,m1,m2): #iphase = cmath.exp( complex(0., .5*np.pi *(l0-l1+l2)) ) #return np.power(-1.,m2) *np.sqrt( (2.*l0+1) *(2.*l1+1) *(2.*l2+1) ) \ # *wigner3j(l0,l1,l2,0,0,0) *wigner3j(l0,l1,l2,m0,m1,m2) *iphase iphase = np.sqrt(4.*np.pi)*np.power(-1.,m2)* cmath.exp( complex(0., .5*np.pi *(l0-l1+l2)) ) return gaunt(l0,l1,l2,m0,m1,m2) *iphase
def SHoverlap(a = AtomGaussian(), b = AtomGaussian()): R = b.centre - a.centre radius2 = R.dot(R) radius = np.sqrt(radius2) xi = a.alpha * b.alpha /(a.alpha + b.alpha) lague_x = xi*radius2 Rot = np.zeros([3,3]).astype(complex) Rot[0,0] = -1/np.sqrt(2) Rot[1,0] = 1/np.sqrt(2) Rot[0,1] = Rot[1,1] = complex(0,1/np.sqrt(2)) Rot[2,2] = 1 Ax = np.matmul(Rot,a.axis) Bx = np.matmul(Rot,b.axis) axis_mat = np.outer(Ax,Bx) l1 = a.l l2 = b.l m1 = a.m m2 = b.m I_map = np.zeros([3,3]).astype(complex) mset = [+1,-1,0] for i in range(3): for j in range(3): m1 = mset[i] m2 = mset[j] I = 0 F = 0 m = m2 - m1 # for one centre overlap integrals if radius == 0: if l1 == l2 and m1 == m2: I = (-1)**l2 * special.gamma(l2+3/2)* (4*xi)**(l2+3/2) /(2*(2*np.pi)**(3/2)) else: # for two centre overlap integrals theta = np.arccos(R[2]/radius) phi = np.arctan2(R[1],R[0]) # set the range of theta and phi for if theta < 0: theta = theta + 2*np.pi if phi < 0: phi = phi + 2*np.pi # use the selection rule to lset = [] for value in range(abs(l1-l2),l1+l2+1): if (l1+l2+ value) %2 == 0: lset.append(value) # Sum I for each L for l in lset: if abs(m) > l: continue # Calculate the overlap n = (l1+l2-l)/2 C_A_nl = 2**n * np.math.factorial(n) * (2*xi)**(n+l+3/2) Laguerre = special.assoc_laguerre(lague_x, n, l+1/2) SolidHarmonic = radius**l * special.sph_harm(m, l, phi, theta) Psi_xi_R = np.exp(-lague_x)*Laguerre* SolidHarmonic gaunt_value = float((-1.0)**m2 * gaunt(l2,l1,l,-m2,m1,m)) I += (-1)**n * gaunt_value * C_A_nl * Psi_xi_R #calculate the gradient overGrad = Gradient(n,l,m,xi,R) moment = np.cross(b.centre,overGrad) overGrad= np.hstack((overGrad,moment)) F += (-1)**n * gaunt_value * C_A_nl * overGrad ''' #calculate the Hessian C_A_l_np = 2**(n+1) * np.math.factorial(n+1) * (2*xi)**(n+1+l+3/2) Laguerre_np = special.assoc_laguerre(lague_x, n+1, l+1/2) Psi_xi_R_np = np.exp(-lague_x)*Laguerre_np* SolidHarmonic K += (-1)**n * gaunt_value * C_A_l_np * Psi_xi_R_np ''' I_map[i,j] = I result = axis_mat * I_map resum = result.sum() # Normalized version #S = (-1.0)**l2 * (2*np.pi)**(3/2)* Normalize(1/(4*a.alpha),l1)* Normalize(1/(4*b.alpha),l2)*I S = (-1.0)**l2 * (2*np.pi)**(3/2)* resum Grad_S = (-1.0)**l2 * (2*np.pi)**(3/2)* F #Hess_S = (-1.0)**l2 * (2*np.pi)**(3/2)* K return np.real(S), Grad_S
def atomic_formfactor_scalar(element,n,l,m,kPrime,lPrime,mPrime,q): f12 = 0 dlog10k = np.log10(kMax/kMin) / (gridsize - 1) dlog10q = np.log10(qMax/qMin) / (gridsize - 1) ki =int( round(np.log10(kPrime/kMin) / dlog10k) ) qi =int( round(np.log10(q/qMin) / dlog10q) ) for L in range(abs(l-lPrime),l+lPrime+1): radial_integral_1 = np.loadtxt("../data/radial_integral_1/" + element.Shell_Name(n, l) + "_" + str(lPrime) + "_" + str(L) + ".txt") f12 += np.sqrt(4*np.pi) * pow(1j,L) * radial_integral_1[ki][qi] * (-1)**mPrime * np.sqrt(2*L+1) * float(gaunt(l,lPrime,L,m,-mPrime,0)) return f12