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
Exemple #4
0
            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())