Example #1
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
Example #2
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
Example #3
0
def lda_full_energy(molecule, psi, E, pot_coulomb, 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

    density = psi2dens(psi, 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_electr - E_h + E_nuc + E_xc - dE_xc

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

    return E_full
Example #4
0
def pyquante_hf(mol, x, eps, basis = "sto-3g"):

    
    atoms = [None]*mol.num_atoms
    for i in xrange(mol.num_atoms):
        atoms[i] = (mol.atoms[i].charge,
                    (mol.atoms[i].rad[0],mol.atoms[i].rad[1],mol.atoms[i].rad[2]))
        
    mol_pq = Molecule(mol.name, atoms, units='Bohr')
    solver = SCF(mol_pq,method="HF",ConvCriteria=1e-7,MaxIter=40,basis=basis)
    print 'SCF iteration - done'


    solver.iterate()
    norb=int(solver.solver.nclosed)
    w=solver.basis_set.get()


    cf=solver.solver.orbs[:,0:norb]

    psi = [None]*norb
    for i in xrange(norb):
        psi[i] = gto2tuck(w,cf[:,i],x)
        print psi[i].r
        psi[i] = local(psi[i],1e-14)
        psi[i] = tuck.round(psi[i],eps)
        print psi[i].r

    E = solver.solver.orbe[:norb]

    return psi,E
Example #5
0
def lda_full_energy(molecule, psi, E, grid, T, eps, eps_exchange):
    
    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: tuck.cross.multifun([A,B], eps, lambda (a,b): a*b)
    
    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)
    
    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
Example #6
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
Example #7
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
Example #8
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
Example #9
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
Example #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
Example #11
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
Example #12
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
Example #13
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
Example #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
Example #15
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
Example #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
Example #17
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
Example #18
0
def newton_galerkin(x, eps, ind):

    # galerkin tensor for convolution as a hartree potential

    if ind == 6:
        a, b, r = -15., 10, 80
    elif ind == 8:
        a, b, r = -20., 15, 145
    elif ind == 10:
        a, b, r = -25., 20, 220
    elif ind == 12:
        a, b, r = -30., 25, 320
    else:
        raise Exception("wrong ind parameter")
    
        
    N = x.shape

    hr = (b-a)/(r - 1)
    h = x[1]-x[0]

    s = np.array(range(r), dtype = np.complex128)
    s = a + hr * (s - 1)

    w = np.zeros(r, dtype = np.complex128)
    for alpha in xrange(r):
        w[alpha] = 2*hr * np.exp(s[alpha]) / np.sqrt(pi)
    w[0]   = w[0]/2
    w[r-1] = w[r-1]/2


    U = np.zeros((N[0], r), dtype = np.complex128)
    for alpha in xrange(r):
        U[:, alpha] = (  func_int(x-h/2, x[0]-h/2, np.exp(2*s[alpha])) -
                         func_int(x+h/2, x[0]-h/2, np.exp(2*s[alpha])) +
                         func_int(x+h/2, x[0]+h/2, np.exp(2*s[alpha])) -
                         func_int(x-h/2, x[0]+h/2, np.exp(2*s[alpha]))  )

    newton = can2tuck(w, U, U, U)
    newton = tuck.round(newton, eps)
    
    return (1./h**3) * newton
Example #19
0
def newton_galerkin(x, eps, ind):

    # galerkin tensor for convolution as a hartree potential

    if ind == 6:
        a, b, r = -15., 10, 80
    elif ind == 8:
        a, b, r = -20., 15, 145
    elif ind == 10:
        a, b, r = -25., 20, 220
    elif ind == 12:
        a, b, r = -30., 25, 320
    else:
        raise Exception("wrong ind parameter")

    N = x.shape

    hr = (b - a) / (r - 1)
    h = x[1] - x[0]

    s = np.array(range(r), dtype=np.complex128)
    s = a + hr * (s - 1)

    w = np.zeros(r, dtype=np.complex128)
    for alpha in xrange(r):
        w[alpha] = 2 * hr * np.exp(s[alpha]) / np.sqrt(pi)
    w[0] = w[0] / 2
    w[r - 1] = w[r - 1] / 2

    U = np.zeros((N[0], r), dtype=np.complex128)
    for alpha in xrange(r):
        U[:,
          alpha] = (func_int(x - h / 2, x[0] - h / 2, np.exp(2 * s[alpha])) -
                    func_int(x + h / 2, x[0] - h / 2, np.exp(2 * s[alpha])) +
                    func_int(x + h / 2, x[0] + h / 2, np.exp(2 * s[alpha])) -
                    func_int(x - h / 2, x[0] + h / 2, np.exp(2 * s[alpha])))

    newton = can2tuck(w, U, U, U)
    newton = tuck.round(newton, eps)

    return (1. / h**3) * newton
Example #20
0
    def gradient_diatomic(self, smoothing=0.01):

        # pot squared
        #tensor_x = charge*tuck.round(vec[0]*tuck.ones((N, N, N)) - tensor_x, self.params.eps)
        #qt.pots.coulomb(x, vec, self.params.ind, self.params.eps, beta=3.0)
        #d_coulomb -= tuck.cross.multifun([tensor_x, pot_squared], self.params.eps, lambda x: x[0]*x[1])

        molecule = self.molecule
        x = self.params.grid
        h = x[1] - x[0]
        N = len(self.params.grid)
        Norb = self.molecule.orbitals
        num_atoms = self.molecule.num_atoms

        i = 0
        vec = molecule.atoms[i].rad
        charge = molecule.atoms[i].charge

        def fun_coulomb_squared((i, j, k)):
            r = np.sqrt((vec[0] - x[i])**2 + (vec[1] - x[j])**2 +
                        (vec[2] - x[k])**2)
            return charge * (x[i] - vec[0]) / r / (
                -smoothed_coulomb_derivative(r / smoothing)) / smoothing**2

        d_coulomb = tuck.cross.cross3d(fun_coulomb_squared, N, self.params.eps)
        d_coulomb = tuck.round(d_coulomb, self.params.eps)

        self.get_rho()

        dE_nuc = 0.0
        j = 1
        i = 0
        vec_i = molecule.atoms[i].rad
        charge_i = molecule.atoms[i].charge
        vec_j = molecule.atoms[j].rad
        charge_j = molecule.atoms[j].charge
        dE_nuc = (dE_nuc + (vec_i[0] - vec_j[0]) * 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)**3)

        return tuck.dot(d_coulomb, 2 * self.rho) * (x[1] - x[0])**3 + dE_nuc
Example #21
0
def coulomb(x, vec, ind, eps, beta=1.0):  # 1/|r-vec|**beta in Tucker format

    if ind == 6:
        a, b, r = -15., 10, 80
    elif ind == 8:
        a, b, r = -20., 15, 145
    elif ind == 10:
        a, b, r = -25., 20, 220
    elif ind == 12:
        a, b, r = -30., 25, 320
    else:
        raise Exception("wrong ind parameter")    

    N = x.shape
    h = (b-a)/(r - 1)

    s = np.array(range(r))
    s = a + h * (s - 1)

    w = np.zeros(r, dtype = np.float64)
    for alpha in xrange(r):
        w[alpha] = 2*h * np.exp(beta*s[alpha]) / gamma(beta/2)
    w[0]   = w[0]/2
    w[r-1] = w[r-1]/2


    U1 = np.zeros((N[0], r), dtype=np.float64)
    U2 = np.zeros((N[0], r), dtype=np.float64)
    U3 = np.zeros((N[0], r), dtype=np.float64)

    for alpha in xrange(r):
        U1[:, alpha] = np.exp(-(x-vec[0])**2 * np.exp(2*s[alpha]))
        U2[:, alpha] = np.exp(-(x-vec[1])**2 * np.exp(2*s[alpha]))
        U3[:, alpha] = np.exp(-(x-vec[2])**2 * np.exp(2*s[alpha]))

    
    newton = tuck.can2tuck(w, U1, U2, U3)
    newton = tuck.round(newton, eps)
    
    return newton
Example #22
0
    def gradient_diatomic(self, smoothing=0.01):

        # pot squared
        #tensor_x = charge*tuck.round(vec[0]*tuck.ones((N, N, N)) - tensor_x, self.params.eps)
        #qt.pots.coulomb(x, vec, self.params.ind, self.params.eps, beta=3.0)
        #d_coulomb -= tuck.cross.multifun([tensor_x, pot_squared], self.params.eps, lambda x: x[0]*x[1])

        molecule = self.molecule
        x = self.params.grid
        h = x[1] - x[0]
        N = len(self.params.grid)
        Norb = self.molecule.orbitals
        num_atoms = self.molecule.num_atoms
        
        i = 0
        vec = molecule.atoms[i].rad
        charge = molecule.atoms[i].charge
        def fun_coulomb_squared((i, j, k)):
            r = np.sqrt((vec[0] - x[i])**2 + (vec[1] - x[j])**2 + (vec[2] - x[k])**2)
            return charge*(x[i] - vec[0]) / r / (-smoothed_coulomb_derivative(r/smoothing))/smoothing**2
        d_coulomb = tuck.cross.cross3d(fun_coulomb_squared, N, self.params.eps)
        d_coulomb = tuck.round(d_coulomb, self.params.eps)
        

        self.get_rho()
        
        dE_nuc = 0.0
        j = 1
        i = 0
        vec_i = molecule.atoms[i].rad
        charge_i = molecule.atoms[i].charge
        vec_j = molecule.atoms[j].rad
        charge_j = molecule.atoms[j].charge
        dE_nuc = (dE_nuc + (vec_i[0] - vec_j[0])*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)**3)


        return tuck.dot(d_coulomb, 2*self.rho)*(x[1]-x[0])**3 + dE_nuc
Example #23
0
def coulomb(x, vec, ind, eps, beta=1.0):  # 1/|r-vec|**beta in Tucker format

    if ind == 6:
        a, b, r = -15., 10, 80
    elif ind == 8:
        a, b, r = -20., 15, 145
    elif ind == 10:
        a, b, r = -25., 20, 220
    elif ind == 12:
        a, b, r = -30., 25, 320
    else:
        raise Exception("wrong ind parameter")

    N = x.shape
    h = (b - a) / (r - 1)

    s = np.array(range(r))
    s = a + h * (s - 1)

    w = np.zeros(r, dtype=np.float64)
    for alpha in xrange(r):
        w[alpha] = 2 * h * np.exp(beta * s[alpha]) / gamma(beta / 2)
    w[0] = w[0] / 2
    w[r - 1] = w[r - 1] / 2

    U1 = np.zeros((N[0], r), dtype=np.float64)
    U2 = np.zeros((N[0], r), dtype=np.float64)
    U3 = np.zeros((N[0], r), dtype=np.float64)

    for alpha in xrange(r):
        U1[:, alpha] = np.exp(-(x - vec[0])**2 * np.exp(2 * s[alpha]))
        U2[:, alpha] = np.exp(-(x - vec[1])**2 * np.exp(2 * s[alpha]))
        U3[:, alpha] = np.exp(-(x - vec[2])**2 * np.exp(2 * s[alpha]))

    newton = tuck.can2tuck(w, U1, U2, U3)
    newton = tuck.round(newton, eps)

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

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


def slater_fun((i, j, k)):
    return np.exp(-(x[i]**2 + x[j]**2 + x[k]**2)**0.5)


def gaussian_fun((i, j, k)):
    return np.exp(-(x[i]**2 + x[j]**2 + x[k]**2))


print 'Converting tensors in the Tucker format...'
print '(significantly faster version to be updated soon)'
a = tuck.cross.cross3d(slater_fun, N, eps)
b = tuck.cross.cross3d(gaussian_fun, N, eps)
print 'Converting is done'

print 'tensor a: %s' % (a)
print 'tensor b: %s' % (b)
print 'tensor 2a: %s' % (2 * a)
print 'tensor a+a: %s' % (a + a)
print 'tensor a+a after rounding: %s' % (tuck.round(a + a, eps))
print 'relative Frobenius norm of a-a: %s' % (tuck.norm(a - a) / tuck.norm(a))

# Warning! for big mode sizes (N >~ 256) full tensors may be out of memory.
# So, use tensor_full function carefully.
Example #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
Example #26
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
Example #27
0

def gaussian_fun((i,j,k)):
    return  np.exp(-(x[i]**2 + x[j]**2 + x[k]**2))



print 'Converting tensors in the Tucker format...'
print '(significantly faster version to be updated soon)'
a = tuck.cross.cross3d(slater_fun, N, eps)
b = tuck.cross.cross3d(gaussian_fun, N, eps)
print 'Converting is done'

print 'tensor a: %s' % (a)
print 'tensor b: %s' % (b)
print 'tensor 2a: %s' % (2*a)
print 'tensor a+a: %s' % (a + a)
print 'tensor a+a after rounding: %s' % (tuck.round(a+a, eps))
print 'relative Frobenius norm of a-a: %s' % (tuck.norm(a-a)/tuck.norm(a))

# Warning! for big mode sizes (N >~ 256) full tensors may be out of memory.
# So, use tensor_full function carefully.








Example #28
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
Example #29
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
Example #30
0
def cross3d(func, M, eps_init, delta_add = 1e-5):


    N = int((M+1)/2)

    r1 = 2
    r2 = 2
    r3 = 2

    GG = np.zeros((r1,r2,r3),dtype=np.complex128)

    U1 = np.zeros((M,r1),dtype=np.complex128)
    U2 = np.zeros((M,r2),dtype=np.complex128)
    U3 = np.zeros((M,r3),dtype=np.complex128)

    U1[:N,:] = np.random.random((N,r1))
    U2[:N,:] = np.random.random((N,r2))
    U3[:N,:] = np.random.random((N,r3))

    U1, R = np.linalg.qr(U1)
    U2, R = np.linalg.qr(U2)
    U3, R = np.linalg.qr(U3)

    eps_cross = 1

    while True:


        row_order_U1 = tuck.mv.maxvol(U1)
        row_order_U2 = tuck.mv.maxvol(U2)
        row_order_U3 = tuck.mv.maxvol(U3)


        Ar = np.zeros((r1,r2,r3),dtype=np.complex128)

        for i in xrange(r1):
            for j in xrange(r2):
                for k in xrange(r3):
                    Ar[i,j,k] = func((row_order_U1[i],row_order_U2[j],row_order_U3[k]))


        U1_r = U1[row_order_U1,:]
        U2_r = U2[row_order_U2,:]
        U3_r = U3[row_order_U3,:]

        G_UV = np.linalg.solve(U3_r,np.reshape(np.transpose(Ar,[2,0,1]),(r3,r1*r2),order='f'))
        G_UV = np.reshape(G_UV,(r3,r1,r2),order='f')
        G_UV = np.transpose(G_UV,[1,2,0])

        G_U = np.linalg.solve(U2_r,np.reshape(np.transpose(G_UV,[1,2,0]),(r2,r1*r3),order='f'))
        G_U = np.reshape(G_U,(r2,r3,r1),order='f')
        G_U = np.transpose(G_U,[2,0,1])

        G = np.linalg.solve(U1_r,np.reshape(G_U,(r1,r2*r3),order='f'))
        G = np.reshape(G,(r1,r2,r3),order='f')

        norm = np.linalg.norm(G)
        eps_cross = (np.linalg.norm(GG-G))/norm
    #print 'relative accuracy = %s' % (eps_cross), 'ranks = %s' % r1, r2, r3
        G_Tucker = tuck.tensor(G, eps_init/10)


        G = G_Tucker.core

        U1 = np.dot(U1, G_Tucker.u[0])
        U2 = np.dot(U2, G_Tucker.u[1])
        U3 = np.dot(U3, G_Tucker.u[2])

        (r1, r2, r3) = G_Tucker.r

        if eps_cross < eps_init:
            break

        row_order_U1 = tuck.mv.maxvol(U1)
        row_order_U2 = tuck.mv.maxvol(U2)
        row_order_U3 = tuck.mv.maxvol(U3)


        Ar = np.zeros((r1,r2,r3),dtype=np.complex128)

        for i in xrange(r1):
            for j in xrange(r2):
                for k in xrange(r3):
                    Ar[i, j, k] = func((row_order_U1[i], row_order_U2[j], row_order_U3[k]))


        A1 = np.reshape(Ar, [r1,-1], order='f')
        A1_r = np.transpose(A1)
        A1_r,R = np.linalg.qr(A1_r)
        column_order_U1 = tuck.mv.maxvol(A1_r)


        A2 = np.reshape(np.transpose(Ar, [1,0,2]), [r2,-1], order='f')
        A2_r = np.transpose(A2)
        A2_r,R = np.linalg.qr(A2_r)
        column_order_U2 = tuck.mv.maxvol(A2_r)


        A3 = np.reshape(np.transpose(Ar, [2,0,1]), [r3,-1], order='f')
        A3_r = np.transpose(A3)
        A3_r,R = np.linalg.qr(A3_r)
        column_order_U3 = tuck.mv.maxvol(A3_r)


        u1 = np.zeros((M, r1), dtype=np.complex128)
        for i in xrange(r1):
            for ii in xrange(M):
                k1_order, j1_order = mod(column_order_U1[i], r2)
                u1[ii,i] = func((ii, row_order_U2[j1_order], row_order_U3[k1_order]))

        u2 = np.zeros((M, r2), dtype=np.complex128)
        for j in xrange(r2):
            for jj in xrange(M):
                k1_order, i1_order = mod(column_order_U2[j], r1)
                u2[jj,j] = func((row_order_U1[i1_order], jj, row_order_U3[k1_order]))

        u3 = np.zeros((M, r3), dtype=np.complex128)
        for k in xrange(r3):
            for kk in xrange(M):
                j1_order, i1_order = mod(column_order_U3[k], r1)
                u3[kk,k] = func((row_order_U1[i1_order], row_order_U2[j1_order], kk))


        u1, v, r11 = round_matrix(u1, delta_add)
        u2, v, r22 = round_matrix(u2, delta_add)
        u3, v, r33 = round_matrix(u3, delta_add)

        u1 = u1[:,:r11]
        u2 = u2[:,:r22]
        u3 = u3[:,:r33]

        U1_0 = np.zeros((M,r1+r11),dtype=np.complex128)
        U2_0 = np.zeros((M,r2+r22),dtype=np.complex128)
        U3_0 = np.zeros((M,r3+r33),dtype=np.complex128)

        U1_0[:,:r1] = U1.copy()
        U2_0[:,:r2] = U2.copy()
        U3_0[:,:r3] = U3.copy()

        U1_0[:,r1:r1+r11] = u1
        U2_0[:,r2:r2+r22] = u2
        U3_0[:,r3:r3+r33] = u3


        U1 = U1_0.copy()
        U2 = U2_0.copy()
        U3 = U3_0.copy()

        r1 = r1+r11
        r2 = r2+r22
        r3 = r3+r33


        U1, R1 = np.linalg.qr(U1)
        U2, R2 = np.linalg.qr(U2)
        U3, R3 = np.linalg.qr(U3)


        GG = np.zeros((r1,r2,r3),dtype=np.complex128)
        GG[:(r1-r11),:(r2-r22),:(r3-r33)] = G.copy()


        GG = np.dot(np.transpose(GG,[2,1,0]),np.transpose(R1))
        GG = np.dot(np.transpose(GG,[0,2,1]),np.transpose(R2))
        GG = np.transpose(GG,[1,2,0])
        GG = np.dot(GG,np.transpose(R3))

            #print 'ranks after rounding = %s' % r1, r2, r3
    G_Tucker.n = (M, M, M)
    G_Tucker.u[0] = U1
    G_Tucker.u[1] = U2
    G_Tucker.u[2] = U3
    G_Tucker.r = [r1, r2, r3]


    return tuck.round(G_Tucker, eps_init)
Example #31
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)
Example #32
0
def cross3d(func, M, eps_init, delta_add=1e-5):

    N = int((M + 1) / 2)

    r1 = 2
    r2 = 2
    r3 = 2

    GG = np.zeros((r1, r2, r3), dtype=np.complex128)

    U1 = np.zeros((M, r1), dtype=np.complex128)
    U2 = np.zeros((M, r2), dtype=np.complex128)
    U3 = np.zeros((M, r3), dtype=np.complex128)

    U1[:N, :] = np.random.random((N, r1))
    U2[:N, :] = np.random.random((N, r2))
    U3[:N, :] = np.random.random((N, r3))

    U1, R = np.linalg.qr(U1)
    U2, R = np.linalg.qr(U2)
    U3, R = np.linalg.qr(U3)

    eps_cross = 1

    while True:

        row_order_U1 = tuck.mv.maxvol(U1)
        row_order_U2 = tuck.mv.maxvol(U2)
        row_order_U3 = tuck.mv.maxvol(U3)

        Ar = np.zeros((r1, r2, r3), dtype=np.complex128)

        for i in xrange(r1):
            for j in xrange(r2):
                for k in xrange(r3):
                    Ar[i, j, k] = func(
                        (row_order_U1[i], row_order_U2[j], row_order_U3[k]))

        U1_r = U1[row_order_U1, :]
        U2_r = U2[row_order_U2, :]
        U3_r = U3[row_order_U3, :]

        G_UV = np.linalg.solve(
            U3_r,
            np.reshape(np.transpose(Ar, [2, 0, 1]), (r3, r1 * r2), order='f'))
        G_UV = np.reshape(G_UV, (r3, r1, r2), order='f')
        G_UV = np.transpose(G_UV, [1, 2, 0])

        G_U = np.linalg.solve(
            U2_r,
            np.reshape(np.transpose(G_UV, [1, 2, 0]), (r2, r1 * r3),
                       order='f'))
        G_U = np.reshape(G_U, (r2, r3, r1), order='f')
        G_U = np.transpose(G_U, [2, 0, 1])

        G = np.linalg.solve(U1_r, np.reshape(G_U, (r1, r2 * r3), order='f'))
        G = np.reshape(G, (r1, r2, r3), order='f')

        norm = np.linalg.norm(G)
        eps_cross = (np.linalg.norm(GG - G)) / norm
        #print 'relative accuracy = %s' % (eps_cross), 'ranks = %s' % r1, r2, r3
        G_Tucker = tuck.tensor(G, eps_init / 10)

        G = G_Tucker.core

        U1 = np.dot(U1, G_Tucker.u[0])
        U2 = np.dot(U2, G_Tucker.u[1])
        U3 = np.dot(U3, G_Tucker.u[2])

        (r1, r2, r3) = G_Tucker.r

        if eps_cross < eps_init:
            break

        row_order_U1 = tuck.mv.maxvol(U1)
        row_order_U2 = tuck.mv.maxvol(U2)
        row_order_U3 = tuck.mv.maxvol(U3)

        Ar = np.zeros((r1, r2, r3), dtype=np.complex128)

        for i in xrange(r1):
            for j in xrange(r2):
                for k in xrange(r3):
                    Ar[i, j, k] = func(
                        (row_order_U1[i], row_order_U2[j], row_order_U3[k]))

        A1 = np.reshape(Ar, [r1, -1], order='f')
        A1_r = np.transpose(A1)
        A1_r, R = np.linalg.qr(A1_r)
        column_order_U1 = tuck.mv.maxvol(A1_r)

        A2 = np.reshape(np.transpose(Ar, [1, 0, 2]), [r2, -1], order='f')
        A2_r = np.transpose(A2)
        A2_r, R = np.linalg.qr(A2_r)
        column_order_U2 = tuck.mv.maxvol(A2_r)

        A3 = np.reshape(np.transpose(Ar, [2, 0, 1]), [r3, -1], order='f')
        A3_r = np.transpose(A3)
        A3_r, R = np.linalg.qr(A3_r)
        column_order_U3 = tuck.mv.maxvol(A3_r)

        u1 = np.zeros((M, r1), dtype=np.complex128)
        for i in xrange(r1):
            for ii in xrange(M):
                k1_order, j1_order = mod(column_order_U1[i], r2)
                u1[ii, i] = func(
                    (ii, row_order_U2[j1_order], row_order_U3[k1_order]))

        u2 = np.zeros((M, r2), dtype=np.complex128)
        for j in xrange(r2):
            for jj in xrange(M):
                k1_order, i1_order = mod(column_order_U2[j], r1)
                u2[jj, j] = func(
                    (row_order_U1[i1_order], jj, row_order_U3[k1_order]))

        u3 = np.zeros((M, r3), dtype=np.complex128)
        for k in xrange(r3):
            for kk in xrange(M):
                j1_order, i1_order = mod(column_order_U3[k], r1)
                u3[kk, k] = func(
                    (row_order_U1[i1_order], row_order_U2[j1_order], kk))

        u1, v, r11 = round_matrix(u1, delta_add)
        u2, v, r22 = round_matrix(u2, delta_add)
        u3, v, r33 = round_matrix(u3, delta_add)

        u1 = u1[:, :r11]
        u2 = u2[:, :r22]
        u3 = u3[:, :r33]

        U1_0 = np.zeros((M, r1 + r11), dtype=np.complex128)
        U2_0 = np.zeros((M, r2 + r22), dtype=np.complex128)
        U3_0 = np.zeros((M, r3 + r33), dtype=np.complex128)

        U1_0[:, :r1] = U1.copy()
        U2_0[:, :r2] = U2.copy()
        U3_0[:, :r3] = U3.copy()

        U1_0[:, r1:r1 + r11] = u1
        U2_0[:, r2:r2 + r22] = u2
        U3_0[:, r3:r3 + r33] = u3

        U1 = U1_0.copy()
        U2 = U2_0.copy()
        U3 = U3_0.copy()

        r1 = r1 + r11
        r2 = r2 + r22
        r3 = r3 + r33

        U1, R1 = np.linalg.qr(U1)
        U2, R2 = np.linalg.qr(U2)
        U3, R3 = np.linalg.qr(U3)

        GG = np.zeros((r1, r2, r3), dtype=np.complex128)
        GG[:(r1 - r11), :(r2 - r22), :(r3 - r33)] = G.copy()

        GG = np.dot(np.transpose(GG, [2, 1, 0]), np.transpose(R1))
        GG = np.dot(np.transpose(GG, [0, 2, 1]), np.transpose(R2))
        GG = np.transpose(GG, [1, 2, 0])
        GG = np.dot(GG, np.transpose(R3))

        #print 'ranks after rounding = %s' % r1, r2, r3
    G_Tucker.n = (M, M, M)
    G_Tucker.u[0] = U1
    G_Tucker.u[1] = U2
    G_Tucker.u[2] = U3
    G_Tucker.r = [r1, r2, r3]

    return tuck.round(G_Tucker, eps_init)
Example #33
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
Example #34
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
Example #35
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
Example #36
0
def lda_scf(solver, molecule, psi_0, E, grid, T, eps, pot_coulomb, pr=None, max_iter=1):
    
    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)

    density = psi2dens(psi_0, eps)

    ################## 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]], 10*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]], 10*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
Example #37
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
Example #38
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
Example #39
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