def initialize(self): if self.initialized: return cache = {} lmax = -1 # Fourier transform radial functions: for a, spline_j in enumerate(self.spline_aj): self.lf_aj.append([]) for spline in spline_j: l = spline.get_angular_momentum_number() if spline not in cache: f = ft(spline) f_qG = [] for G2_G in self.pd.G2_qG: G_G = G2_G**0.5 f_qG.append(f.map(G_G)) cache[spline] = f_qG else: f_qG = cache[spline] self.lf_aj[a].append((l, f_qG)) lmax = max(lmax, l) # Spherical harmonics: for q, K_v in enumerate(self.pd.K_qv): G_Gv = self.pd.get_reciprocal_vectors(q=q) Y_LG = np.empty(((lmax + 1)**2, len(G_Gv))) for L in range((lmax + 1)**2): Y_LG[L] = Y(L, *G_Gv.T) self.Y_qLG.append(Y_LG) self.initialized = True
def Y_rotation(l, angle): Y_mm = np.zeros((2 * l + 1, 2 * l + 1)) sn = sin(angle) cs = cos(angle) for m1, point in enumerate(sphere_lm[l]): x = point[0] y = cs * point[1] - sn * point[2] z = sn * point[1] + cs * point[2] for m2 in range(2 * l + 1): L = l**2 + m2 Y_mm[m1, m2] = Y(L, x, y, z) return Y_mm
def Y_matrix(l, U_vv): """YMatrix(l, symmetry) -> matrix. For 2*l+1 points on the unit sphere (m1=0,...,2*l) calculate the value of Y_lm2 for m2=0,...,2*l. The points are those from the list sphere_lm[l] rotated as described by U_vv.""" Y_mm = np.zeros((2 * l + 1, 2 * l + 1)) for m1, point in enumerate(sphere_lm[l]): x, y, z = np.dot(point, U_vv) for m2 in range(2 * l + 1): L = l**2 + m2 Y_mm[m1, m2] = Y(L, x, y, z) return Y_mm
def run(): from gpaw.spherical_harmonics import Y weight_n = np.zeros(50) Y_nL = np.zeros((50, 25)) R_nv = np.zeros((50, 3)) # We use 50 Lebedev quadrature points which will integrate # spherical harmonics correctly for l < 12: n = 0 for v in [0, 1, 2]: for s in [-1, 1]: R_nv[n, v] = s n += 1 C = 2**-0.5 for v1 in [0, 1, 2]: v2 = (v1 + 1) % 3 v3 = (v1 + 2) % 3 for s1 in [-1, 1]: for s2 in [-1, 1]: R_nv[n, v2] = s1 * C R_nv[n, v3] = s2 * C n += 1 C = 3**-0.5 for s1 in [-1, 1]: for s2 in [-1, 1]: for s3 in [-1, 1]: R_nv[n] = (s1 * C, s2 * C, s3 * C) n += 1 C1 = 0.30151134457776357 C2 = (1.0 - 2.0 * C1**2)**0.5 for v1 in [0, 1, 2]: v2 = (v1 + 1) % 3 v3 = (v1 + 2) % 3 for s1 in [-1, 1]: for s2 in [-1, 1]: for s3 in [-1, 1]: R_nv[n, v1] = s1 * C2 R_nv[n, v2] = s2 * C1 R_nv[n, v3] = s3 * C1 n += 1 assert n == 50 weight_n[0:6] = 0.01269841269841270 weight_n[6:18] = 0.02257495590828924 weight_n[18:26] = 0.02109375000000000 weight_n[26:50] = 0.02017333553791887 n = 0 for x, y, z in R_nv: Y_nL[n] = [Y(L, x, y, z) for L in range(25)] n += 1 # Write all 50 points to an xyz file as 50 hydrogen atoms: f = open('50.xyz', 'w') f.write('50\n\n') for x, y, z in R_nv: print('H', 4 * x, 4 * y, 4 * z, file=f) #print np.dot(weights, Y_nL) * (4*pi)**.5 print('weight_n = np.array(%s)' % weight_n.tolist()) print('Y_nL = np.array(%s)' % Y_nL.tolist()) print('R_nv = np.array(%s)' % R_nv.tolist()) return weight_n, Y_nL, R_nv
def two_phi_planewave_integrals(k_Gv, setup=None, Gstart=0, Gend=None, rgd=None, phi_jg=None, phit_jg=None, l_j=None): """Calculate PAW-correction matrix elements with planewaves. :: / _ _ ik.r _ ~ _ ik.r ~ _ | dr [phi (r) e phi (r) - phi (r) e phi (r)] / 1 2 1 2 ll - / 2 ~ ~ = 4 * pi \sum_lm i Y (k) | dr r [ phi (r) phi (r) - phi (r) phi (r) j (kr) lm / 1 2 1 2 ll / * | d\Omega Y Y Y / l1m1 l2m2 lm """ if Gend is None: Gend = len(k_Gv) if setup is not None: rgd = setup.rgd l_j = setup.l_j # Obtain the phi_j and phit_j phi_jg = [] phit_jg = [] rcut2 = 2 * max(setup.rcut_j) gcut2 = rgd.ceil(rcut2) for phi_g, phit_g in zip(setup.data.phi_jg, setup.data.phit_jg): phi_g = phi_g.copy() phit_g = phit_g.copy() phi_g[gcut2:] = phit_g[gcut2:] = 0. phi_jg.append(phi_g) phit_jg.append(phit_g) else: assert rgd is not None assert phi_jg is not None assert l_j is not None ng = rgd.N r_g = rgd.r_g dr_g = rgd.dr_g # Construct L (l**2 + m) and j (nl) index L_i = [] j_i = [] for j, l in enumerate(l_j): for m in range(2 * l + 1): L_i.append(l**2 + m) j_i.append(j) ni = len(L_i) nj = len(l_j) lmax = max(l_j) * 2 + 1 if setup is not None: assert ni == setup.ni and nj == setup.nj # Initialize npw = k_Gv.shape[0] R_jj = np.zeros((nj, nj)) R_ii = np.zeros((ni, ni)) phi_Gii = np.zeros((npw, ni, ni), dtype=complex) j_lg = np.zeros((lmax, ng)) # Store (phi_j1 * phi_j2 - phit_j1 * phit_j2 ) for further use tmp_jjg = np.zeros((nj, nj, ng)) for j1 in range(nj): for j2 in range(nj): tmp_jjg[j1, j2] = (phi_jg[j1] * phi_jg[j2] - phit_jg[j1] * phit_jg[j2]) # Loop over G vectors for iG in range(Gstart, Gend): kk = k_Gv[iG] k = np.sqrt(np.dot(kk, kk)) # calculate length of q+G # Calculating spherical bessel function for g, r in enumerate(r_g): j_lg[:, g] = sphj(lmax - 1, k * r)[1] for li in range(lmax): # Radial part for j1 in range(nj): for j2 in range(nj): R_jj[j1, j2] = np.dot(r_g**2 * dr_g, tmp_jjg[j1, j2] * j_lg[li]) for mi in range(2 * li + 1): # Angular part for i1 in range(ni): L1 = L_i[i1] j1 = j_i[i1] for i2 in range(ni): L2 = L_i[i2] j2 = j_i[i2] R_ii[i1, i2] = G_LLL[L1, L2, li**2 + mi] * R_jj[j1, j2] phi_Gii[iG] += R_ii * Y(li**2 + mi, kk[0] / k, kk[1] / k, kk[2] / k) * (-1j)**li phi_Gii *= 4 * pi return phi_Gii.reshape(npw, ni * ni)
phit_i = num.empty((s.ni, 59), num.Float) x = num.empty(59, num.Float) x[29:] = r x[29::-1] = -r x *= paw.a0 i = 0 nj = len(phi_j) for j in range(nj): f = phi_j[j] ft = phit_j[j] l = f.get_angular_momentum_number() f = num.array([f(R) for R in r]) * r**l ft = num.array([ft(R) for R in r]) * r**l for m in range(2 * l + 1): L = l**2 + m phi_i[i + m, 29:] = f * Y(L, 1, 0, 0) phi_i[i + m, 29::-1] = f * Y(L, -1, 0, 0) phit_i[i + m, 29:] = ft * Y(L, 1, 0, 0) phit_i[i + m, 29::-1] = ft * Y(L, -1, 0, 0) i += 2 * l + 1 assert i == s.ni P_i = n.P_uni[0, N] X = n.spos_c[0] * a - c p.plot(X + x, num.dot(P_i, phit_i), C + '-', lw=1, label=r'$\tilde{\psi}^%s$' % s.symbol) p.plot(X + x, num.dot(P_i, phi_i), C + '-',
def two_phi_nabla_planewave_integrals(k_Gv, setup=None, Gstart=0, Gend=None, rgd=None, phi_jg=None, phit_jg=None, l_j=None): """Calculate PAW-correction matrix elements with planewaves and gradient. :: / _ _ ik.r d _ ~ _ ik.r d ~ _ | dr [phi (r) e -- phi (r) - phi (r) e -- phi (r)] / 1 dx 2 1 dx 2 and similar for y and z.""" if Gend is None: Gend = len(k_Gv) if setup is not None: rgd = setup.rgd l_j = setup.l_j # Obtain the phi_j and phit_j phi_jg = [] phit_jg = [] rcut2 = 2 * max(setup.rcut_j) gcut2 = rgd.ceil(rcut2) for phi_g, phit_g in zip(setup.data.phi_jg, setup.data.phit_jg): phi_g = phi_g.copy() phit_g = phit_g.copy() phi_g[gcut2:] = phit_g[gcut2:] = 0. phi_jg.append(phi_g) phit_jg.append(phit_g) else: assert rgd is not None assert phi_jg is not None assert l_j is not None ng = rgd.N r_g = rgd.r_g dr_g = rgd.dr_g # Construct L (l**2 + m) and j (nl) index L_i = [] j_i = [] for j, l in enumerate(l_j): for m in range(2 * l + 1): L_i.append(l**2 + m) j_i.append(j) ni = len(L_i) nj = len(l_j) lmax = max(l_j) * 2 + 1 ljdef = 3 l2max = max(l_j) * (max(l_j) > ljdef) + ljdef * (max(l_j) <= ljdef) G_LLL = gaunt(l2max) Y_LLv = nabla(2 * l2max) if setup is not None: assert ni == setup.ni and nj == setup.nj # Initialize npw = k_Gv.shape[0] R1_jj = np.zeros((nj, nj)) R2_jj = np.zeros((nj, nj)) R_vii = np.zeros((3, ni, ni)) phi_vGii = np.zeros((3, npw, ni, ni), dtype=complex) j_lg = np.zeros((lmax, ng)) # Store (phi_j1 * dphidr_j2 - phit_j1 * dphitdr_j2) for further use tmp_jjg = np.zeros((nj, nj, ng)) tmpder_jjg = np.zeros((nj, nj, ng)) for j1 in range(nj): for j2 in range(nj): dphidr_g = np.empty_like(phi_jg[j2]) rgd.derivative(phi_jg[j2], dphidr_g) dphitdr_g = np.empty_like(phit_jg[j2]) rgd.derivative(phit_jg[j2], dphitdr_g) tmpder_jjg[j1, j2] = (phi_jg[j1] * dphidr_g - phit_jg[j1] * dphitdr_g) tmp_jjg[j1, j2] = (phi_jg[j1] * phi_jg[j2] - phit_jg[j1] * phit_jg[j2]) # Loop over G vectors for iG in range(Gstart, Gend): kk = k_Gv[iG] k = np.sqrt(np.dot(kk, kk)) # calculate length of q+G # Calculating spherical bessel function for g, r in enumerate(r_g): j_lg[:, g] = sphj(lmax - 1, k * r)[1] for li in range(lmax): # Radial part for j1 in range(nj): for j2 in range(nj): R1_jj[j1, j2] = np.dot(r_g**2 * dr_g, tmpder_jjg[j1, j2] * j_lg[li]) R2_jj[j1, j2] = np.dot(r_g * dr_g, tmp_jjg[j1, j2] * j_lg[li]) for mi in range(2 * li + 1): if k == 0: Ytmp = Y(li**2 + mi, 1.0, 0, 0) else: # Note the spherical bessel gives # zero when k == 0 for li != 0 Ytmp = Y(li**2 + mi, kk[0] / k, kk[1] / k, kk[2] / k) for v in range(3): Lv = 1 + (v + 2) % 3 # Angular part for i1 in range(ni): L1 = L_i[i1] j1 = j_i[i1] for i2 in range(ni): L2 = L_i[i2] j2 = j_i[i2] l2 = l_j[j2] R_vii[v, i1, i2] = ((4 * pi / 3)**0.5 * np.dot(G_LLL[L1, L2], G_LLL[Lv, li**2 + mi]) * (R1_jj[j1, j2] - l2 * R2_jj[j1, j2])) R_vii[v, i1, i2] += (R2_jj[j1, j2] * np.dot(G_LLL[L1, li**2 + mi], Y_LLv[:, L2, v])) phi_vGii[:, iG] += (R_vii * Ytmp * (-1j)**li) phi_vGii *= 4 * pi return phi_vGii.reshape(3, npw, ni * ni)