def so3_quadrature(n): """ grid for averaging over Euler angles a,b,g according to Kostoloc,P. et.al. FFTs on the Rotation Group, section 2.3 """ alphas = [] betas = [] gammas = [] weights_beta = [] for i in range(0, 2*n): ai = (2.0*np.pi*i)/(2.0*n) bi = (np.pi*(2.0*i+1))/(4.0*n) gi = (2.0*np.pi*i)/(2.0*n) # weights wi = 0.0 for l in range(0, n): wi += 1.0/(2.0*l+1.0) * np.sin((2.0*l+1.0) * bi) wi *= 1.0/(1.0*n) * np.sin(bi) alphas.append(ai) betas.append(bi) gammas.append(gi) weights_beta.append(wi) # consistency check: The weights should be the solutions of the system of linear equations # sum_(k=0)^(2*n-1) wB(k) * Pm(cos(bk)) = delta_(0,m) for 0 <= m < n from scipy.special import legendre for m in range(0, n): sm = 0.0 Pm = legendre(m) for k in range(0, 2*n): sm += weights_beta[k] * Pm(np.cos(betas[k])) if m == 0: assert abs(sm-1.0) < 1.0e-10 else: assert abs(sm) < 1.0e-10 # # list of weights weights = [] # list of rotation matrices Rots = [] dV = 1.0/(2.0*n)**2 V = 0.0 for i in range(0, 2*n): ai = alphas[i] for j in range(0, 2*n): bj = betas[j] wj = weights_beta[j] for k in range(0, 2*n): gk = gammas[k] # R = MolCo.EulerAngles2Rotation(ai,bj,gk) weights.append( wj * dV ) Rots.append( R ) # V += wj * dV assert abs(V-1.0) < 1.0e-10 return weights, Rots
def asymptotic_density(wavefunction, Rmax, E): from PI import LebedevQuadrature k = np.sqrt(2*E) wavelength = 2.0 * np.pi/k r = np.linspace(Rmax, Rmax+wavelength, 30) n = 5810 th,phi,w = np.array(LebedevQuadrature.LebedevGridPoints[n]).transpose() x = LebedevQuadrature.outerN(r, np.sin(th)*np.cos(phi)) y = LebedevQuadrature.outerN(r, np.sin(th)*np.sin(phi)) z = LebedevQuadrature.outerN(r, np.cos(th)) wfn2 = abs(wavefunction((x,y,z), 1.0))**2 wfn2_angular = np.sum(w*wfn2, axis=0) from matplotlib.mlab import griddata import matplotlib.pyplot as plt th_resampled,phi_resampled = np.mgrid[0.0: np.pi: 30j, 0.0: 2*np.pi: 30j] resampled = griddata(th, phi, wfn2_angular, th_resampled, phi_resampled, interp="linear") # 2D PLOT plt.imshow(resampled.T, extent=(0.0, np.pi, 0.0, 2*np.pi)) plt.colorbar() from DFTB.Modeling import MolecularCoords as MolCo R = MolCo.EulerAngles2Rotation(1.0, 0.5, -0.3) th, phi = rotate_sphere(R, th, phi) plt.plot(th, phi, "r.") plt.plot(th_resampled, phi_resampled, "b.") plt.show() # SPHERICAL PLOT from mpl_toolkits.mplot3d import Axes3D x_resampled = resampled * np.sin(th_resampled) * np.cos(phi_resampled) y_resampled = resampled * np.sin(th_resampled) * np.sin(phi_resampled) z_resampled = resampled * np.cos(th_resampled) fig = plt.figure() ax = fig.add_subplot(111, projection='3d') ax.plot_surface(x_resampled, y_resampled, z_resampled, rstride=1, cstride=1) ax.scatter(x_resampled, y_resampled, z_resampled, color="k", s=20) plt.show()
def euler_average(n): """ grid for averaging over Euler angles a,b,g Parameters: =========== n: number of grid points for each of the 3 dimensions Returns: ======== w: list of n^3 weights R: list of n^3 rotation matrices a function of a vector v, f(v), can be averaged over all roations as <f> = sum_i w[i]*f(R[i].v) """ alpha = np.linspace(0, 2.0*np.pi, n+1)[:-1] # don't count alpha=0 and alpha=2pi twice beta = np.linspace(0, np.pi, n) gamma = np.linspace(0, 2.0*np.pi, n+1)[:-1] # don't count gamma=0 and gamma=2pi twice # list of weights weights = [] # list of rotation matrices Rots = [] da = alpha[1]-alpha[0] db = beta[1]-beta[0] dg = gamma[1]-gamma[0] dV = da*db*dg / (8.0*np.pi**2) for a in alpha: for b in beta: for g in gamma: w = np.sin(b) * dV if (abs(w) > 0.0): weights += [w] R = MolCo.EulerAngles2Rotation(a,b,g) Rots += [ R ] return weights, Rots
rotation_matrices.append(orb_rot_byl[l]) # rotate orbitals i = 0 orbs_rotated = np.copy(orbs) for rot in rotation_matrices: dim = rot.shape[0] orbs_rotated[i:i+dim] = np.dot(rot, orbs[i:i+dim]) i += dim return orbs_rotated if __name__ == "__main__": a,b,g = 0.345345, 1.234, 0.56 orb_rot = orbital_rotation_matrices(a,b,g) R = MolCo.EulerAngles2Rotation(a,b,g, convention="z-y-z") print "R" print R # print np.dot(R, R.transpose()) # print "Rorb" # print orb_rot[1] mapping = {0: 1, 1: 2, 2: 0} Rmapped = np.zeros((3,3)) for i in range(0, 3): for j in range(0, 3): Rmapped[mapping[i],mapping[j]] = orb_rot[1][i,j] print "Rmapped" print Rmapped print R-Rmapped # print np.dot(orb_rot[1], orb_rot[1].transpose())