Exemplo n.º 1
0
    def get_rho(self):

        self.rho = tuck.zeros(self.psi[0].n)
        for i in xrange(len(self.psi)):
            self.rho += tuck.cross.multifun([self.psi[i]], self.params.eps,
                                            lambda x: x[0]**2)
            self.rho = tuck.round(self.rho, self.params.eps)
Exemplo n.º 2
0
def local(a,eps):
    
    b = tuck.zeros(a.n)
    b.n = a.n

    u1,v1,r1 = svd_trunc(a.u[0],eps)
    u2,v2,r2 = svd_trunc(a.u[1],eps)
    u3,v3,r3 = svd_trunc(a.u[2],eps)
    
    b.u[0] = u1
    b.u[1] = u2
    b.u[2] = u3
    b.r = (r1,r2,r3)
    

    g = np.dot(a.core, np.transpose(v3))
    g = np.transpose(g, [2,0,1])
    g = np.dot(g, np.transpose(v2))
    g = np.transpose(g, [0,2,1])
    g = np.dot(g, np.transpose(v1))
    b.core = np.transpose(g, [2,1,0])
  


    return b
Exemplo n.º 3
0
def LT_prod(psi, L, eps):  #psi by L - Lower Triangular matrix multiplication

    Norb = len(psi)
    psi_new = [tuck.zeros(psi[0].n)] * Norb
    for i in xrange(Norb):
        for j in xrange(i + 1):
            psi_new[i] = psi_new[i] + L[i, j] * psi[j]
            psi_new[i] = tuck.round(psi_new[i], eps)
    return psi_new
Exemplo n.º 4
0
def LT_prod(psi, L, eps): #psi by L - Lower Triangular matrix multiplication

    Norb = len(psi) 
    psi_new = [tuck.zeros(psi[0].n)]*Norb
    for i in xrange(Norb):
        for j in xrange(i+1):
            psi_new[i] = psi_new[i] + L[i,j]*psi[j]
            psi_new[i] = tuck.round(psi_new[i], eps)
    return psi_new
Exemplo n.º 5
0
def psi2dens(psi, eps):
    
    density = tuck.zeros(psi[0].n)
    for i in xrange(len(psi)):
        density = density + tuck.cross.multifun([psi[i]], eps/10, lambda a: a[0]**2, y0 = psi[i])
        density = tuck.round(density, eps/10)
    density = 2*density
    
    return density
Exemplo n.º 6
0
def psi2dens(psi, eps):
    
    density = tuck.zeros(psi[0].n)
    for i in xrange(len(psi)):
        density = density + tuck.cross.multifun([psi[i], psi[i]], eps/10, lambda (a,b): a*b, y0 = psi[i])
        density = tuck.round(density, eps)
    density = 2*density
    
    return density
Exemplo n.º 7
0
def UT_prod(psi, R, eps): #psi by R - Upper Triangular matrix multiplication
    
    Norb = len(psi)
    psi_new = [tuck.zeros(psi[0].n)]*Norb
    for i in xrange(Norb):
        for j in xrange(i+1):
            psi_new[i] = psi_new[i] + R[j,i]*psi[j]
            psi_new[i] = tuck.round(psi_new[i], eps)
    return psi_new
Exemplo n.º 8
0
def UT_prod(psi, R, eps):  #psi by R - Upper Triangular matrix multiplication

    Norb = len(psi)
    psi_new = [tuck.zeros(psi[0].n)] * Norb
    for i in xrange(Norb):
        for j in xrange(i + 1):
            psi_new[i] = psi_new[i] + R[j, i] * psi[j]
            psi_new[i] = tuck.round(psi_new[i], eps)
    return psi_new
Exemplo n.º 9
0
def hf(molecule,
       psi,
       E,
       eps,
       grid,
       T,
       ind,
       max_iter,
       poisson_solver='Fourier'):

    a = grid[0]
    b = grid[1]
    N = grid[2]

    h = (b - a) / (N - 1)

    x = np.zeros(N)
    for i in xrange(N):
        x[i] = a + i * h

    Norb = molecule.orbitals
    num_atoms = molecule.num_atoms

    pot_coulomb = tuck.zeros((N, N, N))
    for i in xrange(num_atoms):
        vec = molecule.atoms[i].rad
        charge = molecule.atoms[i].charge
        pot_coulomb = pot_coulomb - charge * qt.pots.coulomb(x, vec, ind, eps)
        pot_coulomb = tuck.round(pot_coulomb, eps)

    T0 = tuck.round(T, eps)
    k = 0
    for i in xrange(max_iter):
        psi, E_new = hf1iter(molecule, psi, E, grid, T0, pot_coulomb, eps,
                             poisson_solver)
        #print E
        if max(abs((E - E_new) / E)) < eps:
            k += 1
            if k == 4:
                print 'Process converged with', i, 'iterations'
                break

        E = E_new
        print E

    if i == max_iter - 1:
        print 'Process did not converge with eps precision'

    E_full = hf_full_energy(molecule, psi, E, grid, tuck.round(T, eps * 1e-3),
                            eps * 1e-3)

    print E_full
    return psi, E, E_full
Exemplo n.º 10
0
def exchange(psi1, psi2, i, eps_exchange, T, molecule):

    exchange = tuck.zeros(psi1[0].n)
    for j in xrange(molecule.orbitals):
        conv = tuck.cross.multifun([psi1[i], psi2[j]], eps_exchange, lambda (a,b): a*b, y0 = psi1[i])
        conv = tuck.cross.conv(T, conv, eps_exchange, y0 = conv)
        conv = tuck.round(tuck.real(conv),eps_exchange)
        conv = tuck.cross.multifun([psi2[j], conv], eps_exchange, lambda (a,b): a*b,y0 = psi2[j])
        exchange = exchange + conv
        exchange = tuck.round(exchange, eps_exchange)

    return exchange
Exemplo n.º 11
0
 def get_coulomb(self):
     molecule = self.molecule
     x = self.params.grid
     N = len(self.params.grid)
     Norb = self.molecule.orbitals
     num_atoms = self.molecule.num_atoms
     
     pot_coulomb = tuck.zeros((N, N, N))
     for i in xrange(num_atoms):
         vec = molecule.atoms[i].rad
         charge = molecule.atoms[i].charge
         pot_coulomb = pot_coulomb - charge * qt.pots.coulomb(x, vec, self.params.ind, self.params.eps)
         pot_coulomb = tuck.round(pot_coulomb, self.params.eps)
     self.pots.coulomb = pot_coulomb
Exemplo n.º 12
0
def hf_full_energy(molecule, psi, E, grid, T, eps):

    eps_exchange = eps

    a = grid[0]
    b = grid[1]
    N = grid[2]

    h = (b - a) / (N - 1)

    sf = h**(3. / 2)

    Norb = molecule.orbitals
    num_atoms = molecule.num_atoms

    prod = lambda A, B, C: tuck.cross.multifun(
        [A, B], eps, lambda (a, b): a * b, y0=C)

    density = tuck.zeros((N, N, N))  # density calculation
    for i in xrange(Norb):
        density = density + prod(psi[i], psi[i], psi[i])  # !can be faster!
        density = tuck.round(density, eps)

    pot_hartree = tuck.cross.conv(T, density, eps)
    pot_hartree = tuck.real(pot_hartree)
    pot_hartree = tuck.round(pot_hartree, eps)

    V = [0] * Norb
    for i in xrange(Norb):
        V[i] = (prod(tuck.round(2 * pot_hartree, eps), psi[i], psi[i]) -
                qt.pots.exchange(psi, psi, i, eps_exchange, T, molecule))
        V[i] = tuck.round(V[i], eps)

    E_electr = 0
    for i in xrange(Norb):
        E_electr = E_electr + 2 * E[i] - sf**2 * tuck.dot(psi[i], V[i])

    E_nuc = 0
    for i in xrange(num_atoms):
        vec_i = molecule.atoms[i].rad
        charge_i = molecule.atoms[i].charge
        for j in xrange(i):
            vec_j = molecule.atoms[j].rad
            charge_j = molecule.atoms[j].charge
            E_nuc = (E_nuc +
                     charge_i * charge_j / np.sqrt((vec_i[0] - vec_j[0])**2 +
                                                   (vec_i[1] - vec_j[1])**2 +
                                                   (vec_i[2] - vec_j[2])**2))

    return E_nuc + E_electr
Exemplo n.º 13
0
def hf_full_energy(molecule, psi, E, grid, T, eps):
    
    eps_exchange = eps
    
    a = grid[0]
    b = grid[1]
    N = grid[2]
    
    h = (b-a)/(N-1)
    
    sf = h ** (3./2)
    
    Norb = molecule.orbitals
    num_atoms = molecule.num_atoms
    
    prod = lambda A,B,C: tuck.cross.multifun([A,B], eps, lambda (a,b): a*b, y0=C)
    
    density = tuck.zeros((N,N,N))  # density calculation
    for i in xrange(Norb):
        density = density + prod(psi[i], psi[i], psi[i]) # !can be faster!
        density = tuck.round(density, eps)
    
    pot_hartree = tuck.cross.conv(T, density, eps)
    pot_hartree = tuck.real(pot_hartree)
    pot_hartree = tuck.round(pot_hartree, eps)
    
    V = [0] * Norb
    for i in xrange(Norb):
        V[i] =  (prod(tuck.round(2*pot_hartree, eps), psi[i], psi[i]) -
                 qt.pots.exchange(psi, psi, i, eps_exchange, T, molecule))
        V[i] = tuck.round(V[i], eps)
    
    
    E_electr = 0
    for i in xrange(Norb):
        E_electr = E_electr + 2*E[i] - sf**2*tuck.dot(psi[i], V[i])
    
    
    E_nuc = 0
    for i in xrange(num_atoms):
        vec_i = molecule.atoms[i].rad
        charge_i = molecule.atoms[i].charge
        for j in xrange(i):
            vec_j = molecule.atoms[j].rad
            charge_j = molecule.atoms[j].charge
            E_nuc = (E_nuc + charge_i*charge_j/
                     np.sqrt((vec_i[0] - vec_j[0])**2 + (vec_i[1] - vec_j[1])**2 + (vec_i[2] - vec_j[2])**2))
    
    return E_nuc + E_electr
Exemplo n.º 14
0
    def get_coulomb(self):
        molecule = self.molecule
        x = self.params.grid
        N = len(self.params.grid)
        Norb = self.molecule.orbitals
        num_atoms = self.molecule.num_atoms

        pot_coulomb = tuck.zeros((N, N, N))
        for i in xrange(num_atoms):
            vec = molecule.atoms[i].rad
            charge = molecule.atoms[i].charge
            pot_coulomb = pot_coulomb - charge * qt.pots.coulomb(
                x, vec, self.params.ind, self.params.eps)
            pot_coulomb = tuck.round(pot_coulomb, self.params.eps)
        self.pots.coulomb = pot_coulomb
Exemplo n.º 15
0
def prod(psi, S, density, eps):  #psi by S matrix multiplication

    Norb = len(psi)
    psi_new = [tuck.zeros(psi[0].n)] * Norb
    for i in xrange(Norb):
        for j in xrange(Norb):
            psi_new[i] = psi_new[i] + S[i, j] * psi[j]
            psi_new[i] = tuck.round(psi_new[i], eps)

        #def psi_S_i(psi):
        #    res = 0.
        #    for j in xrange(Norb):
        #        res += (S[i, j]) * psi[j]
        #    return np.real(res)

        #psi_new[i] = tuck.cross.multifun(psi, eps, lambda a: psi_S_i(a), y0 = density, pr = 1)
    return psi_new
Exemplo n.º 16
0
def prod(psi, S, density, eps): #psi by S matrix multiplication

    Norb = len(psi)
    psi_new = [tuck.zeros(psi[0].n)]*Norb
    for i in xrange(Norb):
        for j in xrange(Norb):
            psi_new[i] = psi_new[i] + S[i,j]*psi[j]
            psi_new[i] = tuck.round(psi_new[i], eps)
    
        #def psi_S_i(psi):
        #    res = 0.
        #    for j in xrange(Norb):
        #        res += (S[i, j]) * psi[j]
        #    return np.real(res)
        
        #psi_new[i] = tuck.cross.multifun(psi, eps, lambda a: psi_S_i(a), y0 = density, pr = 1)
    return psi_new
Exemplo n.º 17
0
def exchange(psi1, psi2, i, eps_exchange, T, molecule):

    exchange = tuck.zeros(psi1[0].n)
    for j in xrange(molecule.orbitals):
        conv = tuck.cross.multifun([psi1[i], psi2[j]],
                                   eps_exchange,
                                   lambda (a, b): a * b,
                                   y0=psi1[i])
        conv = tuck.cross.conv(T, conv, eps_exchange, y0=conv)
        conv = tuck.round(tuck.real(conv), eps_exchange)
        conv = tuck.cross.multifun([psi2[j], conv],
                                   eps_exchange,
                                   lambda (a, b): a * b,
                                   y0=psi2[j])
        exchange = exchange + conv
        exchange = tuck.round(exchange, eps_exchange)

    return exchange
Exemplo n.º 18
0
def hf(molecule, psi, E, eps, grid, T, ind, max_iter, poisson_solver='Fourier'):
    
    a = grid[0]
    b = grid[1]
    N = grid[2]
    
    h = (b-a)/(N-1)
    
    x = np.zeros(N)
    for i in xrange(N):
        x[i] = a + i*h
    
    Norb = molecule.orbitals
    num_atoms = molecule.num_atoms
    
    pot_coulomb = tuck.zeros((N,N,N))
    for i in xrange(num_atoms):
        vec = molecule.atoms[i].rad
        charge = molecule.atoms[i].charge
        pot_coulomb = pot_coulomb - charge * qt.pots.coulomb(x, vec, ind, eps)
        pot_coulomb = tuck.round(pot_coulomb, eps)
    
    T0 = tuck.round(T, eps)
    k=0
    for i in xrange(max_iter):
        psi, E_new = hf1iter(molecule, psi, E, grid, T0, pot_coulomb, eps, poisson_solver)
        #print E
        if max(abs((E-E_new)/E))<eps:
            k += 1
            if k == 4:
                print 'Process converged with', i, 'iterations'
                break
        
        E = E_new
        print E

    if i == max_iter - 1:
        print 'Process did not converge with eps precision'

    E_full = hf_full_energy(molecule, psi, E, grid, tuck.round(T, eps*1e-3), eps*1e-3)
    
    print E_full
    return psi, E, E_full
Exemplo n.º 19
0
def local(a, eps):

    b = tuck.zeros(a.n, dtype=np.float64)
    b.n = a.n

    u1, v1, r1 = svd_trunc(a.u[0], eps)
    u2, v2, r2 = svd_trunc(a.u[1], eps)
    u3, v3, r3 = svd_trunc(a.u[2], eps)

    b.u[0] = np.real(u1)
    b.u[1] = np.real(u2)
    b.u[2] = np.real(u3)
    b.r = (r1, r2, r3)

    g = np.dot(a.core, np.transpose(v3))
    g = np.transpose(g, [2, 0, 1])
    g = np.dot(g, np.transpose(v2))
    g = np.transpose(g, [0, 2, 1])
    g = np.dot(g, np.transpose(v1))
    b.core = np.real(np.transpose(g, [2, 1, 0]))

    return b
Exemplo n.º 20
0
def Hartree(molecule, psi_0, E_0, grid, T, num_iter, eps, ind):
    
    alpha = 0.0
    
    a = grid[0]
    b = grid[1]
    N = grid[2]
    
    h = (b-a)/(N-1)
    
    x = np.zeros(N)
    for i in xrange(N):
        x[i] = a + i*h

    sf = h ** (3./2) # scaling factor

    Norb = molecule.orbitals
    num_atoms = molecule.num_atoms
    
    
    ############################# Programm body ######################################
    
    psi = psi_0
    E = E_0
    V = [0]*Norb
    psi_new = [0]*Norb
    ################## Coulomb potential calculation ####################
            
    prod = lambda A,B: tuck.cross.multifun([A,B], eps, lambda (a,b): a*b)
    
    print "Coulomb potential..."
    
    pot_coulomb = tuck.zeros((N,N,N))
    for i in xrange(num_atoms):
        vec = molecule.atoms[i].rad
        charge = molecule.atoms[i].charge
        pot_coulomb = pot_coulomb - charge * qt.pots.coulomb(x, vec, ind, eps)
        pot_coulomb = tuck.round(pot_coulomb, eps)

    ################## Iteration process ####################
    print "Iteration process..."

    for k in xrange(num_iter):
        
        density = tuck.zeros((N,N,N))  # density calculation
        for i in xrange(Norb):
            density = density + prod(tuck.conj(psi[i]), psi[i]) # !can be faster!
            density = tuck.round(density, eps)
        pot_hartree = tuck.cross.conv(T, density, eps)
        pot_hartree = tuck.round(tuck.real(pot_hartree),eps)

        for i in xrange(Norb):
            V[i] =  prod(tuck.round(pot_coulomb + pot_hartree, eps), psi[i])
            V[i] = tuck.round(V[i], eps)
            
            psi_new[i] = -qt.poisson(2*V[i], -2*E[i], N, h, eps)

        ################# Fock matrix ###################

        L = np.linalg.cholesky(qt.bilinear(psi_new, psi_new)*sf**2) # orthogonalization
        psi_Q = qt.UT_prod(psi_new, H(np.linalg.inv(L)), eps)

        # Fock matrix

        V_new = [0]*Norb
        for i in xrange(Norb):
            V_new[i] =  prod(tuck.round(pot_coulomb + pot_hartree,eps), psi_Q[i])
            V_new[i] = tuck.round(V_new[i], eps)

        Energ1 = np.dot(np.diag(E), H(np.linalg.inv(L)))
        Energ2 = qt.bilinear(psi_new, psi_new)*sf**2
        Energ2 = np.dot(np.linalg.inv(L), Energ2)
        Energ = np.dot(Energ2, Energ1)
        F = qt.bilinear(psi_Q, V_new)*sf**2 - np.dot(qt.bilinear(psi_Q, V)*sf**2, H(np.linalg.inv(L))) + Energ
        print F
        #F = np.real((F + F.T)/2)

        E_new = np.zeros(Norb, dtype = np.complex128)
        E_new, S = np.linalg.eigh(F)
        #E_new = alpha*E + (1-alpha)*E_new
        
        print np.array(E_new)
        
        psi_new = qt.prod(psi_Q, S.T, eps)
        for i in xrange(Norb):
            psi[i] = alpha*psi[i] + (1-alpha)*qt.normalize(psi_new[i], h)
            psi[i] = tuck.round(psi[i], eps)
        
        E = E_new.copy()
        
        for i in xrange(Norb):
            if E[i]>0:
                E[i] = -0.0    
    
    return E, psi
Exemplo n.º 21
0
def lda(molecule,
        psi,
        E,
        density,
        grid,
        T,
        eps,
        pot_coulomb,
        max_iter=3,
        pr=None):

    E_correct = molecule.energy

    a = grid[0]
    b = grid[1]
    N = grid[2]

    h = (b - a) / (N - 1)

    x = np.zeros(N)
    for i in xrange(N):
        x[i] = a + i * h

    accuracy = np.zeros(max_iter)
    timing = np.zeros(max_iter)

    sf = h**(3. / 2)  # scaling factor

    Norb = molecule.orbitals
    num_atoms = molecule.num_atoms

    ##### Output #####
    #output_E = np.zeros((Norb+1, max_iter))
    #output_r = np.zeros((3, max_iter))
    #fname = molecule.name + '_' + 'lda' + '_'  + str(N) + '_' + str(eps)

    ############################# Programm body ######################################

    V = [0] * Norb
    psi_new = [0] * Norb

    prod = lambda A, B, C: tuck.cross.multifun(
        [A, B], eps, lambda (a, b): a * b, y0=C)

    ################## Iteration process ####################

    pot_hartree = tuck.cross.conv(T, density, eps, y0=density, pr=None)
    pot_hartree = tuck.round(tuck.real(pot_hartree), eps)

    for k in xrange(max_iter):

        for i in xrange(Norb):
            V[i] = prod(tuck.round(pot_coulomb + pot_hartree, eps), psi[i],
                        psi[i])
            psi[i] = tuck.real(psi[i])
            psi[i] = tuck.round(psi[i], eps)

        for i in xrange(Norb):
            Vxc = tuck.cross.multifun([density, psi[i]],
                                      10 * eps,
                                      lambda (a, b):
                                      ((cpot_fun(np.abs(np.real(a))) +
                                        xpot_fun(np.abs(np.real(a)))) * (b)),
                                      y0=psi[i],
                                      pr=None)
            V[i] = tuck.round(V[i] + Vxc, eps)
            psi_new[i] = -qt.poisson(2 * V[i], -2 * E[i], N, h, eps)

        ################# Fock matrix ###################

        L = np.linalg.cholesky(qt.bilinear(psi_new, psi_new) *
                               sf**2)  # orthogonalization
        psi_Q = qt.UT_prod(psi_new, H(np.linalg.inv(L)), eps)

        # Fock matrix

        V_new = [0] * Norb
        for i in xrange(Norb):
            V_new[i] = prod(tuck.round(pot_coulomb + pot_hartree, eps),
                            psi_Q[i], psi_Q[i])
            psi_Q[i] = tuck.real(psi_Q[i])
            psi_Q[i] = tuck.round(psi_Q[i], eps)

        for i in xrange(Norb):
            Vxc_new = tuck.cross.multifun([density, psi_Q[i]],
                                          10 * eps,
                                          lambda (a, b):
                                          ((cpot_fun(np.abs(np.real(a))) +
                                            xpot_fun(np.abs(np.real(a)))) *
                                           (b)),
                                          y0=psi_Q[i],
                                          pr=None)
            V_new[i] = tuck.round(V_new[i] + Vxc_new, eps)

        Energ1 = np.dot(np.diag(E), H(np.linalg.inv(L)))
        Energ2 = qt.bilinear(psi_new, psi_new) * sf**2
        Energ2 = np.dot(np.linalg.inv(L), Energ2)
        Energ = np.dot(Energ2, Energ1)
        F = qt.bilinear(psi_Q, V_new) * sf**2 - np.dot(
            qt.bilinear(psi_Q, V) * sf**2, H(np.linalg.inv(L))) + Energ
        print 'Fock Matrix:'
        print F
        #F = np.real((F + F.T)/2)

        E_new = np.zeros(Norb, dtype=np.complex128)
        E_new, S = np.linalg.eigh(F)

        #output_E[:Norb,k] = E_new
        #output_E[Norb,k] = E_full
        #output_r[:,k] = density.r
        #np.save('experiments/' + fname, [output_E[:,:k], output_r[:,:k]])

        print 'Orbital Energies:'
        print np.array(E_new)

        psi = qt.prod(psi_Q, S.T, density, eps)
        for i in xrange(Norb):
            psi[i] = qt.normalize(psi[i], h)
            psi[i] = tuck.round(psi[i], eps)

        if np.linalg.norm(E - E_new) / np.linalg.norm(E_new) < 2 * eps:
            break

        E = E_new.copy()

        for i in xrange(Norb):
            if E[i] > 0:
                E[i] = -0.0

    density = tuck.zeros((N, N, N))  # density calculation
    for i in xrange(Norb):
        density = density + prod(tuck.conj(psi[i]), psi[i],
                                 psi[i])  # !can be faster!
        density = tuck.round(density, eps)
    density = 2 * density

    return psi, E, density, F
Exemplo n.º 22
0
def lda_full_energy(molecule, psi, E, density, grid, T, eps, pr=None):

    a = grid[0]
    b = grid[1]
    N = grid[2]

    h = (b - a) / (N - 1)

    x = np.zeros(N)
    for i in xrange(N):
        x[i] = a + i * h

    accuracy = np.zeros(max_iter)
    timing = np.zeros(max_iter)

    sf = h**(3. / 2)  # scaling factor

    prod = lambda A, B: tuck.cross.multifun([A, B], eps, lambda (a, b): a * b)

    Norb = molecule.orbitals
    num_atoms = molecule.num_atoms

    density = tuck.zeros((N, N, N))  # density calculation
    for i in xrange(Norb):
        density = density + prod(psi[i], psi[i], psi[i])  # !can be faster!
        density = tuck.round(density, eps)

    pot_hartree = tuck.cross.conv(T, density, eps)

    E_electr = 0
    e_xc = tuck.cross.multifun([density, density],
                               eps,
                               lambda (a, b):
                               ((cen_fun(np.abs(np.real(a))) + xen_fun(
                                   np.abs(np.real(a)))) * np.abs(b)),
                               y0=density,
                               pr=pr)
    de_xc = tuck.cross.multifun(
        [density, density],
        eps,
        lambda (a, b):
        ((cpot_fun(np.abs(np.real(a))) + xpot_fun(np.abs(np.real(a)))) * (b)),
        y0=density,
        pr=pr)
    e_h = 0.5 * prod(pot_hartree, density, density)

    E_h = sf**2 * tuck.dot(e_h, tuck.ones(e_xc.n))
    E_xc = sf**2 * tuck.dot(e_xc, tuck.ones(e_xc.n))
    dE_xc = sf**2 * tuck.dot(de_xc, tuck.ones(e_xc.n))
    #print E_xc, dE_xc, E_h

    for i in xrange(Norb):
        V[i] = prod(tuck.round(pot_coulomb + pot_hartree, eps), psi[i], psi[i])
        psi[i] = tuck.real(psi[i])
        psi[i] = tuck.round(psi[i], eps)

    for i in xrange(Norb):
        E_electr += 2 * E[i]

    E_nuc = 0
    for i in xrange(num_atoms):
        vec_i = molecule.atoms[i].rad
        charge_i = molecule.atoms[i].charge
        for j in xrange(i):
            vec_j = molecule.atoms[j].rad
            charge_j = molecule.atoms[j].charge
            E_nuc = (E_nuc +
                     charge_i * charge_j / np.sqrt((vec_i[0] - vec_j[0])**2 +
                                                   (vec_i[1] - vec_j[1])**2 +
                                                   (vec_i[2] - vec_j[2])**2))

    E_full = E_electr - E_h + E_nuc + E_xc - dE_xc

    print 'Full Energy = %s' % (E_full)
    #accuracy[k] =  ((E_correct - E_full)/abs(E_correct))
    #print 'Relative Precision of the full Energy = %s' % (accuracy[k])

    return E_full
Exemplo n.º 23
0
def lda_full_energy(molecule, psi, E, density, grid, T, eps, ind, pr=None):

    a = grid[0]
    b = grid[1]
    N = grid[2]

    h = (b - a) / (N - 1)

    x = np.zeros(N)
    for i in xrange(N):
        x[i] = a + i * h

    prod = lambda A, B, C: tuck.cross.multifun(
        [A, B], eps, lambda (a, b): a * b, y0=C, pr=pr)

    sf = h**(3. / 2)  # scaling factor

    Norb = molecule.orbitals
    num_atoms = molecule.num_atoms

    pot_coulomb = tuck.zeros((N, N, N))
    for i in xrange(num_atoms):
        vec = molecule.atoms[i].rad
        charge = molecule.atoms[i].charge
        pot_coulomb = pot_coulomb - charge * qt.pots.coulomb(x, vec, ind, eps)
        pot_coulomb = tuck.round(pot_coulomb, eps)

    pot_hartree = tuck.cross.conv(T, density, eps)
    pot_hartree = tuck.real(pot_hartree)
    pot_hartree = tuck.round(pot_hartree, eps)

    E_electr = 0
    e_xc = tuck.cross.multifun([density, density],
                               eps,
                               lambda (a, b):
                               ((cen_fun(np.abs(np.real(a))) + xen_fun(
                                   np.abs(np.real(a)))) * np.abs(b)),
                               y0=density,
                               pr=pr)
    de_xc = tuck.cross.multifun(
        [density, density],
        eps,
        lambda (a, b):
        ((cpot_fun(np.abs(np.real(a))) + xpot_fun(np.abs(np.real(a)))) * (b)),
        y0=density,
        pr=pr)
    e_h = 0.5 * prod(pot_hartree, density, density)

    E_h = sf**2 * tuck.dot(e_h, tuck.ones(e_xc.n, dtype=np.float64))
    E_xc = sf**2 * tuck.dot(e_xc, tuck.ones(e_xc.n, dtype=np.float64))
    dE_xc = sf**2 * tuck.dot(de_xc, tuck.ones(e_xc.n, dtype=np.float64))
    #print E_xc, dE_xc, E_h

    for i in xrange(Norb):
        E_electr += 2 * E[i]

    E_nuc = 0
    for i in xrange(num_atoms):
        vec_i = molecule.atoms[i].rad
        charge_i = molecule.atoms[i].charge
        for j in xrange(i):
            vec_j = molecule.atoms[j].rad
            charge_j = molecule.atoms[j].charge
            E_nuc = (E_nuc +
                     charge_i * charge_j / np.sqrt((vec_i[0] - vec_j[0])**2 +
                                                   (vec_i[1] - vec_j[1])**2 +
                                                   (vec_i[2] - vec_j[2])**2))

    E_full = -E_h + E_nuc + E_xc - dE_xc

    print 'Full Energy = %s' % (E_full)
    #accuracy[k] =  ((E_correct - E_full)/abs(E_correct))
    #print 'Relative Precision of the full Energy = %s' % (accuracy[k])

    return E_full
Exemplo n.º 24
0
def hf1iter(molecule,
            psi,
            E,
            grid,
            T,
            pot_coulomb,
            eps,
            poisson_solver,
            num_iter=1):

    E_correct = molecule.energy

    eps_exchange = eps

    a = grid[0]
    b = grid[1]
    N = grid[2]

    h = (b - a) / (N - 1)

    x = np.zeros(N)
    for i in xrange(N):
        x[i] = a + i * h

    sf = h**(3. / 2)  # scaling factor

    Norb = molecule.orbitals
    num_atoms = molecule.num_atoms

    V = [0] * Norb
    psi_new = [0] * Norb

    prod = lambda A, B, C: tuck.cross.multifun(
        [A, B], eps, lambda (a, b): a * b, y0=C)

    for k in xrange(num_iter):

        density = tuck.zeros((N, N, N))  # density calculation
        for i in xrange(Norb):
            density = density + prod(tuck.conj(psi[i]), psi[i],
                                     psi[i])  # !can be faster!
            density = tuck.round(density, eps)
        pot_hartree = tuck.cross.conv(T, density, eps, pr=None)
        pot_hartree = tuck.round(tuck.real(pot_hartree), eps)

        E_electr = 0
        for i in xrange(Norb):
            V[i] = prod(tuck.round(pot_coulomb + 2 * pot_hartree, eps), psi[i],
                        psi[i])
            exchange = qt.pots.exchange(psi, psi, i, eps_exchange, T, molecule)
            V[i] = tuck.round(V[i] - exchange, eps)

            # Full energy computation
            #V_energ = tuck.round(prod(2*pot_hartree, psi[i],psi[i]) - exchange, eps)
            #E_electr += 2*E[i] - sf**2*tuck.dot(psi[i], V_energ)

            psi_new[i] = -qt.poisson(
                2 * V[i], -2 * E[i], N, h, eps, solver=poisson_solver)

            #if abs( (E_full_1-E_full_0)/E_full_1 ) <= 3 * eps:
            #check += 1
            #if check == 3:
        #break

        ################# Fock matrix ###################

        L = np.linalg.cholesky(qt.bilinear(psi_new, psi_new) *
                               sf**2)  # orthogonalization
        psi_Q = qt.UT_prod(psi_new, H(np.linalg.inv(L)), eps)

        # Fock matrix

        V_new = [0] * Norb
        for i in xrange(Norb):
            V_new[i] = prod(tuck.round(pot_coulomb + 2 * pot_hartree, eps),
                            psi_Q[i], psi_Q[i])
            exchange_new = qt.pots.exchange(psi_Q, psi, i, eps_exchange, T,
                                            molecule)
            V_new[i] = tuck.round(V_new[i] - exchange_new, eps)

        Energ1 = np.dot(np.diag(E), H(np.linalg.inv(L)))
        Energ2 = qt.bilinear(psi_new, psi_new) * sf**2
        Energ2 = np.dot(np.linalg.inv(L), Energ2)
        Energ = np.dot(Energ2, Energ1)
        F = qt.bilinear(psi_Q, V_new) * sf**2 - np.dot(
            qt.bilinear(psi_Q, V) * sf**2, H(np.linalg.inv(L))) + Energ
        #F = np.real((F + F.T)/2)

        E_new = np.zeros(Norb, dtype=np.float64)
        E_new, S = np.linalg.eigh(F)

        psi = qt.prod(psi_Q, S.T, density, eps)
        for i in xrange(Norb):
            psi[i] = qt.normalize(psi[i], h)
            psi[i] = tuck.round(psi[i], eps)

        E = E_new.copy()

        for i in xrange(Norb):
            if E[i] > 0:
                E[i] = -0.0

    return psi, E
Exemplo n.º 25
0
def mixing(solver, molecule, psi_0, E_0, eps, grid, T, ind, max_iter, m,
           max_iter_inscf, pr):

    count = 0

    a = grid[0]
    b = grid[1]
    N = grid[2]

    h = (b - a) / (N - 1)

    x = np.zeros(N)
    for i in xrange(N):
        x[i] = a + i * h

    Norb = molecule.orbitals
    num_atoms = molecule.num_atoms

    pot_coulomb = tuck.zeros((N, N, N))
    for i in xrange(num_atoms):
        vec = molecule.atoms[i].rad
        charge = molecule.atoms[i].charge
        pot_coulomb = pot_coulomb - charge * qt.pots.coulomb(x, vec, ind, eps)
        pot_coulomb = tuck.round(pot_coulomb, eps)

    G = lambda psi, E, rho: solvers.dft_dens.lda(molecule,
                                                 psi,
                                                 E,
                                                 rho,
                                                 grid,
                                                 T,
                                                 eps,
                                                 pot_coulomb,
                                                 max_iter=max_iter_inscf,
                                                 pr=pr)[0:4]

    Norb = molecule.orbitals

    rho = psi2dens(psi_0, eps)

    rho_m = []
    Grho_m = []
    D_m = []

    rho_m.append(rho)

    res = G(psi_0, E_0, rho)
    psi = res[0]
    E = res[1]
    Grho_m.append(res[2])

    D_m.append(tuck.round(Grho_m[0] - rho, eps))
    rho = Grho_m[0]

    err_and = np.zeros(max_iter)
    for k in xrange(1, max_iter):
        mk = min(k, m)

        f = np.zeros(mk + 1)
        f[mk] = 1.

        A = np.ones((mk + 1, mk + 1))
        A[mk, mk] = 0.

        for p in xrange(mk):
            for q in xrange(mk):
                A[p, q] += 2 * qt.inner(D_m[p], D_m[q], h)

        alpha = np.linalg.pinv(A).dot(f)
        #alpha = np.array([0.5, 0.5, 1.])

        if len(alpha) == 3:
            if alpha[0] > 1. + 1e-2:
                alpha[0] = .1
                alpha[1] = .9

            if alpha[0] < 0. - 1e-2:
                alpha[0] = 0.1
                alpha[1] = .9

        rho_temp = tuck.zeros((N, N, N))
        for p in xrange(mk):
            rho_temp += tuck.round(alpha[p] * Grho_m[p], eps / 10)
        rho = tuck.round(rho_temp, eps / 10)

        #print alpha

        rho_m.append(rho)
        rho_m = rho_m[-min(k + 1, m):]

        res = G(psi, E, rho)
        psi = res[0]
        E_new = res[1]

        err_and[k] = max(np.abs(E - E_new) / np.abs(E_new))
        #if err_and[k] < eps:
        #break

        solver.psi = psi
        solver.orb_energies = E_new

        print solver.psi[0].r, solver.psi[-1].r
        print E_new
        err = abs((E - E_new) / E)
        E = copy.copy(E_new)
        #solver.iterative.orb_energies.append(E_new)
        #solver.iterative.convergence.append(err)
        print 'Iteration', k, 'accuracy = %.2e' % max(err)

        if max(err) < 4 * eps:
            count += 1
            if count == 4:
                print 'Process converged with', i, 'iterations'
                break

        Grho_m.append(res[2])
        Grho_m = Grho_m[-min(k + 1, m):]

        D_m.append(tuck.round(Grho_m[-1] - rho_m[-1], eps))
        D_m = D_m[-min(k + 1, m):]

    Eel = solvers.dft_dens.lda(molecule,
                               psi,
                               E,
                               rho,
                               grid,
                               T,
                               eps * 1e-2,
                               pot_coulomb,
                               max_iter=max_iter_inscf,
                               pr=pr)[1]
    Efull = solvers.dft_dens.lda_full_energy(
        molecule, psi, E, rho, grid, T, eps * 1e-2, ind,
        pr=None) + 2 * np.sum(Eel)
    print Efull
    solver.energy = Efull

    return psi, E, rho, Efull, err_and
Exemplo n.º 26
0
def mixing(solver, molecule, psi_0, E_0, eps, grid, T, ind, max_iter, m, max_iter_inscf,  pr):
    
    count = 0
    
    a = grid[0]
    b = grid[1]
    N = grid[2]
    
    h = (b-a)/(N-1)
    
    x = np.zeros(N)
    for i in xrange(N):
        x[i] = a + i*h
    
    Norb = molecule.orbitals
    num_atoms = molecule.num_atoms
    
    pot_coulomb = tuck.zeros((N,N,N))
    for i in xrange(num_atoms):
        vec = molecule.atoms[i].rad
        charge = molecule.atoms[i].charge
        pot_coulomb = pot_coulomb - charge * qt.pots.coulomb(x, vec, ind, eps)
        pot_coulomb = tuck.round(pot_coulomb, eps)
    
    G = lambda psi, E, rho: solvers.dft_dens.lda(molecule, psi, E, rho, grid, T, eps, pot_coulomb, max_iter = max_iter_inscf, pr=pr)[0:4]


    Norb = molecule.orbitals

    rho = psi2dens(psi_0, eps)

    rho_m = []
    Grho_m = []
    D_m = []

    rho_m.append(rho)

    res = G(psi_0, E_0, rho)
    psi = res[0]
    E = res[1]
    Grho_m.append(res[2])


    D_m.append(tuck.round(Grho_m[0] - rho, eps))
    rho = Grho_m[0]

    err_and = np.zeros(max_iter)
    for k in xrange(1, max_iter):
        mk = min(k, m)
    
        f = np.zeros(mk + 1)
        f[mk] = 1.
    
        A = np.ones((mk + 1, mk + 1))
        A[mk, mk] = 0.
    
    
        for p in xrange(mk):
            for q in xrange(mk):
                A[p, q] += 2 * qt.inner(D_m[p], D_m[q], h)

    
        alpha = np.linalg.pinv(A).dot(f)
        #alpha = np.array([0.5, 0.5, 1.])

        if len(alpha) == 3:
            if alpha[0]> 1. + 1e-2:
                alpha[0] = .1
                alpha[1] = .9

            if alpha[0]< 0. - 1e-2:
                alpha[0] = 0.1
                alpha[1] = .9

        rho_temp = tuck.zeros((N, N, N))
        for p in xrange(mk):
            rho_temp += tuck.round(alpha[p] * Grho_m[p], eps/10)
        rho = tuck.round(rho_temp, eps/10)

        #print alpha


        rho_m.append(rho)
        rho_m = rho_m[-min(k + 1, m):]


        res = G(psi, E, rho)
        psi = res[0]
        E_new = res[1]

        err_and[k] = max(np.abs(E - E_new)/np.abs(E_new))
            #if err_and[k] < eps:
                #break


        solver.psi = psi
        solver.orb_energies = E_new

        print solver.psi[0].r, solver.psi[-1].r
        print E_new
        err = abs((E-E_new)/E)
        E = copy.copy(E_new)
        #solver.iterative.orb_energies.append(E_new)
        #solver.iterative.convergence.append(err)
        print 'Iteration', k, 'accuracy = %.2e' % max(err)

        if max(err) < 4 * eps:
            count += 1
            if count == 4:
                print 'Process converged with', i, 'iterations'
                break


        Grho_m.append(res[2])
        Grho_m = Grho_m[-min(k + 1, m):]

        D_m.append(tuck.round(Grho_m[-1] - rho_m[-1], eps))
        D_m = D_m[-min(k + 1, m):]

    Eel = solvers.dft_dens.lda(molecule, psi, E, rho, grid, T, eps*1e-2, pot_coulomb, max_iter = max_iter_inscf, pr=pr)[1]
    Efull = solvers.dft_dens.lda_full_energy(molecule, psi, E, rho, grid, T, eps*1e-2, ind, pr = None) + 2*np.sum(Eel)
    print Efull
    solver.energy = Efull
            
    return psi, E, rho, Efull, err_and
Exemplo n.º 27
0
    def get_rho(self):

        self.rho = tuck.zeros(self.psi[0].n)
        for i in xrange(len(self.psi)):
            self.rho += tuck.cross.multifun([self.psi[i]], self.params.eps, lambda x: x[0]**2)
            self.rho = tuck.round(self.rho, self.params.eps)
Exemplo n.º 28
0
def hf1iter(molecule, psi, E, grid, T, pot_coulomb, eps, poisson_solver, num_iter=1):
    
    
    E_correct = molecule.energy
    
    eps_exchange = eps
    
    a = grid[0]
    b = grid[1]
    N = grid[2]
    
    h = (b-a)/(N-1)
    
    x = np.zeros(N)
    for i in xrange(N):
        x[i] = a + i*h
    
    
    sf = h ** (3./2) # scaling factor
    
    Norb = molecule.orbitals
    num_atoms = molecule.num_atoms

    
    
    V = [0]*Norb
    psi_new = [0]*Norb


    prod = lambda A,B,C: tuck.cross.multifun([A,B], eps, lambda (a,b): a*b, y0=C)
    
    
    
    for k in xrange(num_iter):

        
        density = tuck.zeros((N,N,N))  # density calculation
        for i in xrange(Norb):
            density = density + prod(tuck.conj(psi[i]), psi[i], psi[i]) # !can be faster!
            density = tuck.round(density, eps)
        pot_hartree = tuck.cross.conv(T, density, eps,pr=None)
        pot_hartree = tuck.round(tuck.real(pot_hartree),eps)

    
        E_electr = 0
        for i in xrange(Norb):
            V[i] =  prod(tuck.round(pot_coulomb + 2*pot_hartree, eps), psi[i], psi[i])
            exchange = qt.pots.exchange(psi, psi, i, eps_exchange, T, molecule)
            V[i] = tuck.round(V[i] - exchange, eps)
            
            # Full energy computation
            #V_energ = tuck.round(prod(2*pot_hartree, psi[i],psi[i]) - exchange, eps)
            #E_electr += 2*E[i] - sf**2*tuck.dot(psi[i], V_energ)
            
            psi_new[i] = -qt.poisson(2*V[i], -2*E[i], N, h, eps, solver=poisson_solver)
    

                
            #if abs( (E_full_1-E_full_0)/E_full_1 ) <= 3 * eps:
            #check += 1
                #if check == 3:
        #break

        
        ################# Fock matrix ###################
        
        L = np.linalg.cholesky(qt.bilinear(psi_new, psi_new)*sf**2) # orthogonalization
        psi_Q = qt.UT_prod(psi_new, H(np.linalg.inv(L)), eps)
        
        # Fock matrix
        
        V_new = [0]*Norb
        for i in xrange(Norb):
            V_new[i] = prod(tuck.round(pot_coulomb + 2*pot_hartree,eps), psi_Q[i],psi_Q[i])
            exchange_new = qt.pots.exchange(psi_Q, psi, i, eps_exchange, T, molecule)
            V_new[i] = tuck.round(V_new[i] - exchange_new, eps)
    
    
    
        Energ1 = np.dot(np.diag(E), H(np.linalg.inv(L)))
        Energ2 = qt.bilinear(psi_new, psi_new)*sf**2
        Energ2 = np.dot(np.linalg.inv(L), Energ2)
        Energ = np.dot(Energ2, Energ1)
        F = qt.bilinear(psi_Q, V_new)*sf**2 - np.dot(qt.bilinear(psi_Q, V)*sf**2, H(np.linalg.inv(L))) + Energ
        #F = np.real((F + F.T)/2)
        
        E_new = np.zeros(Norb, dtype = np.float64)
        E_new, S = np.linalg.eigh(F)
        
        
        
        psi = qt.prod(psi_Q, S.T, density, eps)
        for i in xrange(Norb):
            psi[i] = qt.normalize(psi[i], h)
            psi[i] = tuck.round(psi[i], eps)
        
        E = E_new.copy()
        
        for i in xrange(Norb):
            if E[i]>0:
                E[i] = -0.0
    
    
    return psi, E
Exemplo n.º 29
0
def lda_full_energy(molecule, psi, E, density, grid, T, eps, ind, pr = None):
    
    a = grid[0]
    b = grid[1]
    N = grid[2]
    
    h = (b-a)/(N-1)
    
    x = np.zeros(N)
    for i in xrange(N):
        x[i] = a + i*h

    prod = lambda A,B,C: tuck.cross.multifun([A,B], eps, lambda (a,b): a*b, y0=C, pr=pr)

    sf = h ** (3./2) # scaling factor
    
    
    Norb = molecule.orbitals
    num_atoms = molecule.num_atoms

    pot_coulomb = tuck.zeros((N,N,N))
    for i in xrange(num_atoms):
        vec = molecule.atoms[i].rad
        charge = molecule.atoms[i].charge
        pot_coulomb = pot_coulomb - charge * qt.pots.coulomb(x, vec, ind, eps)
        pot_coulomb = tuck.round(pot_coulomb, eps)

    pot_hartree = tuck.cross.conv(T, density, eps)
    pot_hartree = tuck.real(pot_hartree)
    pot_hartree = tuck.round(pot_hartree, eps)


    E_electr = 0
    e_xc = tuck.cross.multifun([density, density], eps, lambda (a, b): ((cen_fun(np.abs(np.real(a))) + xen_fun(np.abs(np.real(a))))*np.abs(b)), y0 = density, pr = pr)
    de_xc = tuck.cross.multifun([density, density],  eps, lambda (a, b): ((cpot_fun(np.abs(np.real(a))) + xpot_fun(np.abs(np.real(a))))*(b)), y0 = density, pr=pr)
    e_h = 0.5 * prod(pot_hartree, density, density)
    
    E_h = sf**2*tuck.dot(e_h, tuck.ones(e_xc.n, dtype=np.float64))
    E_xc = sf**2*tuck.dot(e_xc, tuck.ones(e_xc.n, dtype=np.float64))
    dE_xc = sf**2*tuck.dot(de_xc, tuck.ones(e_xc.n, dtype=np.float64))
    #print E_xc, dE_xc, E_h
    
    

    for i in xrange(Norb):
        E_electr += 2*E[i]

    E_nuc = 0
    for i in xrange(num_atoms):
        vec_i = molecule.atoms[i].rad
        charge_i = molecule.atoms[i].charge
        for j in xrange(i):
            vec_j = molecule.atoms[j].rad
            charge_j = molecule.atoms[j].charge
            E_nuc = (E_nuc + charge_i*charge_j/
                 np.sqrt((vec_i[0] - vec_j[0])**2 + (vec_i[1] - vec_j[1])**2 + (vec_i[2] - vec_j[2])**2))

    E_full = - E_h + E_nuc + E_xc - dE_xc

    print 'Full Energy = %s' % (E_full)
    #accuracy[k] =  ((E_correct - E_full)/abs(E_correct))
    #print 'Relative Precision of the full Energy = %s' % (accuracy[k])

    return E_full
Exemplo n.º 30
0
def lda(molecule, psi_0, E, density, grid, T, eps, pot_coulomb, pr = None, max_iter = 3):
    
    E_correct = molecule.energy
    
    
    a = grid[0]
    b = grid[1]
    N = grid[2]
    
    h = (b-a)/(N-1)
    
    x = np.zeros(N)
    for i in xrange(N):
        x[i] = a + i*h
    
    accuracy = np.zeros(max_iter)
    timing = np.zeros(max_iter)
    
    sf = h ** (3./2) # scaling factor
    
    Norb = molecule.orbitals
    num_atoms = molecule.num_atoms

            ##### Output #####
    #output_E = np.zeros((Norb+1, max_iter))
    #output_r = np.zeros((3, max_iter))
    #fname = molecule.name + '_' + 'lda' + '_'  + str(N) + '_' + str(eps)
    
    ############################# Programm body ######################################
    
    psi = psi_0
    V = [0]*Norb
    psi_new = [0]*Norb

    prod = lambda A,B,C: tuck.cross.multifun([A,B], eps, lambda (a,b): a*b, y0=C, pr=pr)



    ################## Iteration process ####################
    
    pot_hartree = tuck.cross.conv(T, density, eps, y0=density, pr=pr)
    pot_hartree = tuck.round(tuck.real(pot_hartree), eps)
    pot_V = tuck.round(pot_coulomb + pot_hartree, eps)
    
    for k in xrange(max_iter):
    
        #print "1 scf iter", E
        
        for i in xrange(Norb):
            V[i] =  prod(pot_V, psi[i], psi[i])
            psi[i] = tuck.real(psi[i])
            psi[i] = tuck.round(psi[i], eps)
        

        for i in xrange(Norb):
            Vxc = tuck.cross.multifun(psi_0 + [psi[i]], 5*eps, lambda a: ((cpot_fun(density_fun(a[:-1])) + xpot_fun(density_fun(a[:-1])))*(a[-1])), y0 = psi[i], pr=pr)
            V[i] = tuck.round(V[i] + Vxc, eps)
            psi_new[i] = -qt.poisson(2*V[i], -2*E[i], N, h, eps)
    

                

        
        ################# Fock matrix ###################
        
        L = np.linalg.cholesky(qt.bilinear(psi_new, psi_new)*sf**2) # orthogonalization
        psi_Q = qt.UT_prod(psi_new, H(np.linalg.inv(L)), eps)
        
        # Fock matrix
        
        V_new = [0]*Norb
        for i in xrange(Norb):
            V_new[i] = prod(pot_V, psi_Q[i], psi_Q[i])
            psi_Q[i] = tuck.real(psi_Q[i])
            psi_Q[i] = tuck.round(psi_Q[i], eps)
    
        for i in xrange(Norb):
            Vxc_new = tuck.cross.multifun(psi_0 + [psi_Q[i]], 5*eps, lambda a: ((cpot_fun(density_fun(a[:-1])) + xpot_fun(density_fun(a[:-1])))*(a[-1])), y0 = psi_Q[i], pr=pr)
            V_new[i] = tuck.round(V_new[i] + Vxc_new, eps)
    
        
        Energ1 = np.dot(np.diag(E), H(np.linalg.inv(L)))
        Energ2 = qt.bilinear(psi_new, psi_new)*sf**2
        Energ2 = np.dot(np.linalg.inv(L), Energ2)
        Energ = np.dot(Energ2, Energ1)
        F = ((qt.bilinear(psi_Q, V_new)*sf**2 - np.dot(qt.bilinear(psi_Q, V)*sf**2, H(np.linalg.inv(L))) + Energ ))
        #print 'Fock Matrix:'
        #print F
        #F = np.real((F + F.T)/2)
        
        #E_new = np.zeros(Norb, dtype = np.float64)
        E_new, S = np.linalg.eigh(F)
        #S+= 1e-15
        #output_E[:Norb,k] = E_new
        #output_E[Norb,k] = E_full
        #output_r[:,k] = density.r
        #np.save('experiments/' + fname, [output_E[:,:k], output_r[:,:k]])
        
        #print 'Orbital Energies:'
        #print np.array(E_new)

        #psi = copy.copy(psi_Q)
        psi = qt.prod(psi_Q, S.T, density, eps)
        for i in xrange(Norb):
            psi[i] = qt.normalize(psi[i], h)
            psi[i] = tuck.round(psi[i], eps)
            
        #if np.linalg.norm(E - E_new)/np.linalg.norm(E_new) < 2*eps:
        #    break
        
        E = E_new.copy()
        

        for i in xrange(Norb):
            if E[i]>0:
                E[i] = -0.0
    

                    
    density = tuck.zeros((N,N,N))  # density calculation
    density = tuck.cross.multifun(psi, eps/10, lambda a: density_fun(a), y0 = psi_Q[i], pr=pr)

    return psi, E, density, F
Exemplo n.º 31
0
def lda(molecule, psi_0, E_0, grid, T, num_iter, eps, ind):

    pr = None

    E_correct = molecule.energy

    eps_exchange = eps

    a = grid[0]
    b = grid[1]
    N = grid[2]

    h = (b - a) / (N - 1)

    x = np.zeros(N)
    for i in xrange(N):
        x[i] = a + i * h

    accuracy = np.zeros(num_iter)
    timing = np.zeros(num_iter)

    sf = h**(3. / 2)  # scaling factor

    Norb = molecule.orbitals
    num_atoms = molecule.num_atoms

    ##### Output #####
    output_E = np.zeros((Norb + 1, num_iter))
    output_r = np.zeros((3, num_iter))
    fname = molecule.name + '_' + 'lda' + '_' + str(N) + '_' + str(eps)

    ############################# Programm body ######################################

    psi = psi_0
    E = E_0
    V = [0] * Norb
    psi_new = [0] * Norb
    ################## Coulomb potential calculation ####################

    prod = lambda A, B, C: tuck.cross.multifun(
        [A, B], eps, lambda (a, b): a * b, y0=C)

    E_nuc = 0
    for i in xrange(num_atoms):
        vec_i = molecule.atoms[i].rad
        charge_i = molecule.atoms[i].charge
        for j in xrange(i):
            vec_j = molecule.atoms[j].rad
            charge_j = molecule.atoms[j].charge
            E_nuc = (E_nuc +
                     charge_i * charge_j / np.sqrt((vec_i[0] - vec_j[0])**2 +
                                                   (vec_i[1] - vec_j[1])**2 +
                                                   (vec_i[2] - vec_j[2])**2))

    print "Coulomb potential..."

    pot_coulomb = tuck.zeros((N, N, N))
    for i in xrange(num_atoms):
        vec = molecule.atoms[i].rad
        charge = molecule.atoms[i].charge
        pot_coulomb = pot_coulomb - charge * qt.pots.coulomb(x, vec, ind, eps)
        pot_coulomb = tuck.round(pot_coulomb, eps)

    ################## Iteration process ####################
    print "Iteration process..."

    time_hartree = 0
    time_exchange = 0
    time_other = 0
    time_whole = 0
    time_iter = 0

    check = 0

    E_full = 0
    E_full_0 = 0
    E_full_1 = 1

    for k in xrange(num_iter):
        print "############################################ "
        print "Iteration Number %s" % (k + 1)
        print "############################################ "

        time_hartree_iter = 0
        time_exchange_iter = 0
        start_iter = time.time()

        start_hartree_iter = time.time()
        density = tuck.zeros((N, N, N))  # density calculation
        for i in xrange(Norb):
            density = density + prod(tuck.conj(psi[i]), psi[i],
                                     psi[i])  # !can be faster!
            density = tuck.round(density, eps)
        density = 2 * density
        pot_hartree = tuck.cross.conv(T, density, eps, pr=None)
        pot_hartree = tuck.round(tuck.real(pot_hartree), eps)

        #density = tuck.real(density)
        #density = tuck.round(density , eps)
        end_hartree_iter = time.time()
        time_hartree_iter += (end_hartree_iter - start_hartree_iter)
        time_hartree += (end_hartree_iter - start_hartree_iter)

        E_electr = 0
        e_xc = tuck.cross.multifun([density, density],
                                   3 * eps,
                                   lambda (a, b):
                                   ((cen_fun(np.abs(np.real(a))) + xen_fun(
                                       np.abs(np.real(a)))) * np.abs(b)),
                                   y0=density,
                                   pr=pr)
        de_xc = tuck.cross.multifun(
            [density, density],
            3 * eps,
            lambda (a, b):
            ((cpot_fun(np.abs(np.real(a))) + xpot_fun(np.abs(np.real(a)))) *
             (b)),
            y0=density,
            pr=pr)
        e_h = 0.5 * prod(pot_hartree, density, density)

        E_h = sf**2 * tuck.dot(e_h, tuck.ones(e_xc.n))
        E_xc = sf**2 * tuck.dot(e_xc, tuck.ones(e_xc.n))
        dE_xc = sf**2 * tuck.dot(de_xc, tuck.ones(e_xc.n))
        #print E_xc, dE_xc, E_h

        for i in xrange(Norb):
            V[i] = prod(tuck.round(pot_coulomb + pot_hartree, eps), psi[i],
                        psi[i])
            psi[i] = tuck.real(psi[i])
            psi[i] = tuck.round(psi[i], eps)

        list = [None] * (Norb + 1)
        list[1:] = psi
        for i in xrange(Norb):
            list[0] = psi[i]
            Vxc = tuck.cross.multifun(
                list,
                10 * eps,
                lambda (a): ((cpot_fun(density_fun(a[1:])) + xpot_fun(
                    density_fun(a[1:]))) * (a[0])),
                y0=density,
                pr=pr
            )  # Somehow it can not converge if precision eps. That is why 3*eps is used
            V[i] = tuck.round(V[i] + Vxc, eps)

            # Full energy computation
            #V_energ = prod(pot_hartree, psi[i], psi[i])
            E_electr += 2 * E[
                i]  # - sf**2*tuck.dot(psi[i], V_energ)/2 #- sf**2*tuck.dot(e_xc, tuck.ones(Exc.n))

            psi_new[i] = -qt.poisson(2 * V[i], -2 * E[i], N, h, eps)

        E_full_0 = E_full
        E_full = E_electr - E_h + E_nuc + E_xc - dE_xc
        E_full_1 = E_full
        print 'Full Energy = %s' % (E_full)
        print 'Correct Energy = %s' % (E_correct)
        accuracy[k] = ((E_correct - E_full) / abs(E_correct))
        print 'Relative Precision of the full Energy = %s' % (accuracy[k])

        ################# Fock matrix ###################

        L = np.linalg.cholesky(qt.bilinear(psi_new, psi_new) *
                               sf**2)  # orthogonalization
        psi_Q = qt.UT_prod(psi_new, H(np.linalg.inv(L)), eps)

        # Fock matrix

        V_new = [0] * Norb
        for i in xrange(Norb):
            V_new[i] = prod(tuck.round(pot_coulomb + pot_hartree, eps),
                            psi_Q[i], psi_Q[i])
            psi_Q[i] = tuck.real(psi_Q[i])
            psi_Q[i] = tuck.round(psi_Q[i], eps)

        list = [None] * (Norb + 1)
        list[1:] = psi_Q
        for i in xrange(Norb):
            list[0] = psi_Q[i]
            Vxc_new = tuck.cross.multifun(list,
                                          eps * 10,
                                          lambda (a):
                                          ((cpot_fun(density_fun(a[1:])) +
                                            xpot_fun(density_fun(a[1:]))) *
                                           (a[0])),
                                          y0=density,
                                          pr=pr)
            V_new[i] = tuck.round(V_new[i] + Vxc_new, eps)

        Energ1 = np.dot(np.diag(E), H(np.linalg.inv(L)))
        Energ2 = qt.bilinear(psi_new, psi_new) * sf**2
        Energ2 = np.dot(np.linalg.inv(L), Energ2)
        Energ = np.dot(Energ2, Energ1)
        F = qt.bilinear(psi_Q, V_new) * sf**2 - np.dot(
            qt.bilinear(psi_Q, V) * sf**2, H(np.linalg.inv(L))) + Energ
        print 'Fock Matrix:'
        print F
        #F = np.real((F + F.T)/2)

        E_new = np.zeros(Norb, dtype=np.float64)
        E_new, S = np.linalg.eigh(F)

        output_E[:Norb, k] = E_new
        output_E[Norb, k] = E_full
        output_r[:, k] = density.r
        np.save('experiments/' + fname, [output_E[:, :k], output_r[:, :k]])

        print 'Orbital Energies:'
        print np.array(E_new)

        psi = qt.prod(psi_Q, S.T, density, eps)
        for i in xrange(Norb):
            psi[i] = qt.normalize(psi[i], h)
            psi[i] = tuck.round(psi[i], eps)

        E = E_new.copy()

        for i in xrange(Norb):
            if E[i] > 0:
                E[i] = -0.0

        end_iter = time.time()
        print '1 Iteration Time: %s' % (end_iter - start_iter)
        print 'Hartree Time on this Iteration: %s' % (time_hartree_iter)
        #print 'Exchange Time on this Iteration: %s' % (time_exchange_iter)
        time_whole += (end_iter - start_iter)
        timing[k] = end_iter - start_iter

        if abs((E_full_1 - E_full_0) / E_full_1) <= 10 * eps:
            check += 1
            if check == 3:
                break

    print 'The Whole Time: %s' % (time_whole)
    return psi, E, accuracy, timing, E_full
Exemplo n.º 32
0
def lda(molecule, psi_0, E_0, grid, T, num_iter, eps, ind):
    
    pr = None
    
    E_correct = molecule.energy
    
    eps_exchange = eps
    
    a = grid[0]
    b = grid[1]
    N = grid[2]
    
    h = (b-a)/(N-1)
    
    x = np.zeros(N)
    for i in xrange(N):
        x[i] = a + i*h
    
    accuracy = np.zeros(num_iter)
    timing = np.zeros(num_iter)
    
    sf = h ** (3./2) # scaling factor
    
    Norb = molecule.orbitals
    num_atoms = molecule.num_atoms

            ##### Output #####
    output_E = np.zeros((Norb+1, num_iter))
    output_r = np.zeros((3, num_iter))
    fname = molecule.name + '_' + 'lda' + '_'  + str(N) + '_' + str(eps)
    
    ############################# Programm body ######################################
    
    psi = psi_0
    E = E_0
    V = [0]*Norb
    psi_new = [0]*Norb
    ################## Coulomb potential calculation ####################

    prod = lambda A,B,C: tuck.cross.multifun([A,B], eps, lambda (a,b): a*b, y0=C)
    
    E_nuc = 0
    for i in xrange(num_atoms):
        vec_i = molecule.atoms[i].rad
        charge_i = molecule.atoms[i].charge
        for j in xrange(i):
            vec_j = molecule.atoms[j].rad
            charge_j = molecule.atoms[j].charge
            E_nuc = (E_nuc + charge_i*charge_j/
                     np.sqrt((vec_i[0] - vec_j[0])**2 + (vec_i[1] - vec_j[1])**2 + (vec_i[2] - vec_j[2])**2))
    
    print "Coulomb potential..."
    
    pot_coulomb = tuck.zeros((N,N,N))
    for i in xrange(num_atoms):
        vec = molecule.atoms[i].rad
        charge = molecule.atoms[i].charge
        pot_coulomb = pot_coulomb - charge * qt.pots.coulomb(x, vec, ind, eps)
        pot_coulomb = tuck.round(pot_coulomb, eps)

    ################## Iteration process ####################
    print "Iteration process..."
    
    time_hartree = 0
    time_exchange = 0
    time_other = 0
    time_whole = 0
    time_iter = 0
    
    check = 0
    
    E_full = 0
    E_full_0 = 0
    E_full_1 = 1
    
    
    
    for k in xrange(num_iter):
        print "############################################ "
        print "Iteration Number %s" % (k + 1)
        print "############################################ "
        
        time_hartree_iter = 0
        time_exchange_iter = 0
        start_iter = time.time()
        
        start_hartree_iter = time.time()
        density = tuck.zeros((N,N,N))  # density calculation
        for i in xrange(Norb):
            density = density + prod(tuck.conj(psi[i]), psi[i], psi[i]) # !can be faster!
            density = tuck.round(density, eps)
        density = 2*density
        pot_hartree = tuck.cross.conv(T, density, eps,pr=None)
        pot_hartree = tuck.round(tuck.real(pot_hartree), eps)

    #density = tuck.real(density)
    #density = tuck.round(density , eps)
        end_hartree_iter = time.time()
        time_hartree_iter += (end_hartree_iter - start_hartree_iter)
        time_hartree += (end_hartree_iter - start_hartree_iter)

    
        E_electr = 0
        e_xc = tuck.cross.multifun([density, density], 3*eps, lambda (a, b): ((cen_fun(np.abs(np.real(a))) + xen_fun(np.abs(np.real(a))))*np.abs(b)), y0 = density, pr = pr)
        de_xc = tuck.cross.multifun([density, density],  3*eps, lambda (a, b): ((cpot_fun(np.abs(np.real(a))) + xpot_fun(np.abs(np.real(a))))*(b)), y0 = density, pr=pr)
        e_h = 0.5 * prod(pot_hartree, density, density)
        
        E_h = sf**2*tuck.dot(e_h, tuck.ones(e_xc.n))
        E_xc = sf**2*tuck.dot(e_xc, tuck.ones(e_xc.n))
        dE_xc = sf**2*tuck.dot(de_xc, tuck.ones(e_xc.n))
        #print E_xc, dE_xc, E_h
        
        
        for i in xrange(Norb):
            V[i] =  prod(tuck.round(pot_coulomb + pot_hartree, eps), psi[i], psi[i])
            psi[i] = tuck.real(psi[i])
            psi[i] = tuck.round(psi[i], eps)
        
        list = [None]*(Norb+1)
        list[1:] = psi
        for i in xrange(Norb):
            list[0] = psi[i]
            Vxc = tuck.cross.multifun(list, 10*eps, lambda (a): ((cpot_fun(density_fun(a[1:])) + xpot_fun(density_fun(a[1:])))*(a[0])), y0 = density, pr=pr) # Somehow it can not converge if precision eps. That is why 3*eps is used
            V[i] = tuck.round(V[i] + Vxc, eps)
            
            # Full energy computation
            #V_energ = prod(pot_hartree, psi[i], psi[i])
            E_electr += 2*E[i]# - sf**2*tuck.dot(psi[i], V_energ)/2 #- sf**2*tuck.dot(e_xc, tuck.ones(Exc.n))
            
            psi_new[i] = -qt.poisson(2*V[i], -2*E[i], N, h, eps)
    
        E_full_0 = E_full
        E_full = E_electr - E_h + E_nuc + E_xc - dE_xc
        E_full_1 = E_full
        print 'Full Energy = %s' % (E_full)
        print 'Correct Energy = %s' %(E_correct)
        accuracy[k] =  ((E_correct - E_full)/abs(E_correct))
        print 'Relative Precision of the full Energy = %s' % (accuracy[k])
                

        
        ################# Fock matrix ###################
        
        L = np.linalg.cholesky(qt.bilinear(psi_new, psi_new)*sf**2) # orthogonalization
        psi_Q = qt.UT_prod(psi_new, H(np.linalg.inv(L)), eps)
        
        # Fock matrix
        
        V_new = [0]*Norb
        for i in xrange(Norb):
            V_new[i] = prod(tuck.round(pot_coulomb + pot_hartree,eps), psi_Q[i], psi_Q[i])
            psi_Q[i] = tuck.real(psi_Q[i])
            psi_Q[i] = tuck.round(psi_Q[i], eps)
    
        list = [None]*(Norb+1)
        list[1:] = psi_Q
        for i in xrange(Norb):
            list[0] = psi_Q[i]
            Vxc_new = tuck.cross.multifun(list, eps*10, lambda (a): ((cpot_fun(density_fun(a[1:])) + xpot_fun(density_fun(a[1:])))*(a[0])), y0 = density, pr = pr)
            V_new[i] = tuck.round(V_new[i] + Vxc_new, eps)
    
    
        Energ1 = np.dot(np.diag(E), H(np.linalg.inv(L)))
        Energ2 = qt.bilinear(psi_new, psi_new)*sf**2
        Energ2 = np.dot(np.linalg.inv(L), Energ2)
        Energ = np.dot(Energ2, Energ1)
        F = qt.bilinear(psi_Q, V_new)*sf**2 - np.dot(qt.bilinear(psi_Q, V)*sf**2, H(np.linalg.inv(L))) + Energ
        print 'Fock Matrix:'
        print F
        #F = np.real((F + F.T)/2)
        
        E_new = np.zeros(Norb, dtype = np.float64)
        E_new, S = np.linalg.eigh(F)
        
        output_E[:Norb,k] = E_new
        output_E[Norb,k] = E_full
        output_r[:,k] = density.r
        np.save('experiments/'+fname, [output_E[:,:k], output_r[:,:k]])
        
        print 'Orbital Energies:'
        print np.array(E_new)
        
        psi = qt.prod(psi_Q, S.T, density, eps)
        for i in xrange(Norb):
            psi[i] = qt.normalize(psi[i], h)
            psi[i] = tuck.round(psi[i], eps)
        
        E = E_new.copy()
        
        for i in xrange(Norb):
            if E[i]>0:
                E[i] = -0.0
    
        end_iter = time.time()
        print '1 Iteration Time: %s' % (end_iter - start_iter)
        print 'Hartree Time on this Iteration: %s' % (time_hartree_iter)
                    #print 'Exchange Time on this Iteration: %s' % (time_exchange_iter)
        time_whole += (end_iter - start_iter)
        timing[k] = end_iter - start_iter
            
        if abs( (E_full_1-E_full_0)/E_full_1 ) <= 10 * eps:
            check += 1
            if check == 3:
                break

    print 'The Whole Time: %s' % (time_whole)                
    return psi, E, accuracy, timing, E_full