Ejemplo n.º 1
0
def compute_CCD(Settings, silent=False, compare=True):

    t0 = time.time()

    printif = print if not silent else lambda *k, **w: None

    Escf, Ca, Cb, epsa, epsb, _, g, Vnuc = compute_uhf(Settings,
                                                       return_C=True,
                                                       return_integrals=True,
                                                       silent=silent)

    printif("""
    =======================================================
             Spin-Orbital Coupled Cluster Doubles 
                             {}
    =======================================================
    """.format('\U0001F9D9'))

    tsave = []
    show_progress(tsave, printif)
    t = time.time()

    # Create Spin-Orbital arrays
    C = np.block([[Ca, np.zeros(Ca.shape)], [np.zeros(Cb.shape), Cb]])

    eps = np.concatenate((epsa, epsb))

    g = np.kron(np.eye(2), g)
    g = np.kron(np.eye(2), g.T)

    # re-Sorting orbitals
    s = np.argsort(eps)
    eps = eps[s]
    C = C[:, s]

    tsave.append(time.time() - t)
    show_progress(tsave, printif)
    t = time.time()

    # Get the MO integral

    nelec = Settings['nalpha'] + Settings['nbeta']
    # Converto to Physicists notation
    g = g.transpose(0, 2, 1, 3)
    # Antisymmetrize
    g = g - g.transpose(0, 1, 3, 2)

    # Save Slices
    ERI = lambda a, b, c, d: np.einsum('ap,bq,cr,ds,abcd->pqrs',
                                       C[:, a],
                                       C[:, b],
                                       C[:, c],
                                       C[:, d],
                                       g,
                                       optimize='optimal')
    o = slice(0, nelec)
    v = slice(nelec, len(g))
    Voovv = ERI(o, o, v, v)
    Voooo = ERI(o, o, o, o)
    Vvvvv = ERI(v, v, v, v)
    Vvoov = ERI(v, o, o, v)

    g = None

    tsave.append(time.time() - t)
    show_progress(tsave, printif)
    t = time.time()

    # Get eigenvalues Matrix D
    new = np.newaxis
    eo = eps[:nelec]
    ev = eps[nelec:]
    D = 1.0 / (eo[:, new, new, new] + eo[new, :, new, new] -
               ev[new, new, :, new] - ev[new, new, new, :])

    tsave.append(time.time() - t)
    show_progress(tsave, printif)
    t = time.time()

    # Initial guess for amplitudes

    T = Voovv * D

    # Get MP2 energy

    E = CCD_Energy(T, Voovv)

    printif('\nMP2 Energy:   {:<15.10f}\n'.format(E + Escf))

    # Setup iteration options
    rms = 0.0
    dE = 1
    ite = 1
    rms_LIM = 10**(-8)
    E_LIM = 10**(-12)
    t0 = time.time()
    printif('\U00003030' * 20)

    # Start CC iterations
    while abs(dE) > E_LIM or rms > rms_LIM:
        t = time.time()
        if ite > Settings["cc_max_iter"]:
            raise NameError('CCD equations did not converge')
        T, rms = CCD_Amplitude(T, D, Voovv, Voooo, Vvvvv, Vvoov)
        dE = -E
        E = CCD_Energy(T, Voovv)
        dE += E
        printif("Iteration  {}".format(numoji(ite)))
        printif("\U000027B0 Correlation energy:     {:< 15.10f}".format(E))
        printif("\U0001F53A Energy change:          {:< 15.10f}".format(dE))
        printif("\U00002622  Max RMS residue:        {:< 15.10f}".format(rms))
        printif("\U0001F570  Time required:          {:< 15.10f}".format(
            time.time() - t))
        printif('\U00003030' * 20)
        ite += 1

    printif('\U0001F3C1 CCD Energy:   {:<15.10f}'.format(E + Escf))
    printif('\U000023F3 CCD iterations took %.2f seconds.\n' %
            (time.time() - t0))

    return (E + Escf)
Ejemplo n.º 2
0
from input import Settings

if 'active_space' in Settings:
    print('TEST')
    from CI import compute_CI
    compute_CI(Settings)
else:
    from uhf import compute_uhf
    compute_uhf(Settings)
Ejemplo n.º 3
0
def compute_SOMP2(Settings, silent=False, psi4compare=True):

    printif = print if not silent else lambda *k, **w: None

    Escf, Ca, Cb, epsa, epsb, _, g, Vnuc = compute_uhf(Settings,
                                                       return_C=True,
                                                       return_integrals=True,
                                                       psi4compare=psi4compare,
                                                       silent=silent)

    printif("""
    ===================================================
      Spin-Orbital Møller-Plesset Perturbation Theory
                           {}
    ===================================================
    """.format(emoji('wine')))

    tasks = """
    Building:
      \U0001F426  Spin-Orbital arrays               {}
      \U0001F986  MO integral <OO|VV>               {}
      \U0001F9A2   Eigenvalues auxiliar array Dijab  {}"""

    printif(tasks.format('', '', ''))
    if not silent: sys.stdout.write("\033[F" * 5)
    time.sleep(0.1)

    # Create Spin-Orbital arrays
    C = np.block([[Ca, np.zeros(Ca.shape)], [np.zeros(Cb.shape), Cb]])

    eps = np.concatenate((epsa, epsb))

    g = np.kron(np.eye(2), g)
    g = np.kron(np.eye(2), g.T)

    # re-Sorting orbitals
    s = np.argsort(eps)
    eps = eps[s]
    C = C[:, s]

    printif(tasks.format(emoji('check'), '', ''))
    if not silent: sys.stdout.write("\033[F" * 5)
    time.sleep(0.1)

    # Get the MO integral OOVV

    nelec = Settings['nalpha'] + Settings['nbeta']
    # Converto to Physicists notation
    g = g.transpose(0, 2, 1, 3)
    ERI = np.einsum('ap,bq,cr,ds,abcd->pqrs',
                    C[:, :nelec],
                    C[:, :nelec],
                    C[:, nelec:],
                    C[:, nelec:],
                    g,
                    optimize='optimal')
    # Antisymmetrize
    ERI = ERI - ERI.transpose(0, 1, 3, 2)

    printif(tasks.format(emoji('check'), emoji('check'), ''))
    if not silent: sys.stdout.write("\033[F" * 5)
    time.sleep(0.1)

    # Get eigenvalues Matrix D
    new = np.newaxis
    eo = eps[:nelec]
    ev = eps[nelec:]
    D = 1.0 / (eo[:, new, new, new] + eo[new, :, new, new] -
               ev[new, new, :, new] - ev[new, new, new, :])

    printif(tasks.format(emoji('check'), emoji('check'), emoji('check')))
    time.sleep(0.1)

    # Get MP2 energy

    printif('\n{}  Computing MP2 energy'.format('\U0001F9ED'), end=' ')
    Emp2 = (1.0 / 4.0) * np.einsum('ijab,ijab,ijab->', ERI, ERI, D)
    printif(emoji('check'))

    printif('\n{} MP2 Correlation Energy:    {:>16.10f}'.format(
        emoji('bolt'), Emp2))
    printif('\U0001F308 Final Electronic Energy:   {:>16.10f}'.format(Emp2 +
                                                                      Escf))

    if psi4compare:

        psi4.set_options({
            'basis': Settings['basis'],
            'scf_type': 'pk',
            'mp2_type': 'conv',
            'puream': False,
            'reference': 'uhf'
        })

        psi4_mp2 = psi4.energy('mp2')
        printif('\n\n{} Psi4  MP2 Energy:          {:>16.10f}'.format(
            emoji('eyes'), psi4_mp2))

        if abs(psi4_mp2 - Emp2 - Escf) < 1.e-8:
            printif('\n         ' + emoji('books'), end=' ')
            printif('My grade:')
            printif(\
        """   
                       AAA               
                      A:::A              
                     A:::::A             
                    A:::::::A            
                   A:::::::::A           
                  A:::::A:::::A          
                 A:::::A A:::::A         
                A:::::A   A:::::A        
               A:::::A     A:::::A       
              A:::::AAAAAAAAA:::::A      
             A:::::::::::::::::::::A     
            A:::::AAAAAAAAAAAAA:::::A    
           A:::::A             A:::::A   
          A:::::A               A:::::A  
         A:::::A                 A:::::A 
        AAAAAAA                   AAAAAAA""")

    return Emp2
Ejemplo n.º 4
0
def compute_DFMP2(Settings, silent=False):

    t0 = time.time()

    printif = print if not silent else lambda *k, **w: None

    Escf, Ca, Cb, epsa, epsb, = compute_uhf(Settings,
                                            return_C=True,
                                            return_integrals=False)

    printif("""
    ===================================================
               Density-Fitting Spin-Orbital
            Møller-Plesset Perturbation Theory
                           {}
    ===================================================
    """.format('\U0001F347' + '\U000027A1' + emoji('wine')))

    tasks = """
    Building:
      \U0001F426  Spin-Orbital arrays            {} 
      \U0001F986  J^(-1/2) (P|Q)                 {}
      \U0001F989  (uv|P)                         {}
      \U0001F9A2   b(ia|Q)                        {}"""

    printif(tasks.format('', '', '', ''))

    # Create Spin-Orbital arrays
    tsave = []
    t = time.time()
    C = np.block([[Ca, np.zeros(Ca.shape)], [np.zeros(Cb.shape), Cb]])

    eps = np.concatenate((epsa, epsb))
    nmo = len(eps)

    ## Sorting orbitals
    s = np.argsort(eps)
    eps = eps[s]
    C = C[:, s]

    tsave.append(time.time() - t)
    show_progress(tsave, printif)

    # Create slices
    nelec = Settings['nalpha'] + Settings['nbeta']
    o = slice(0, nelec)
    v = slice(nelec, nmo)

    # Build J^(-1/2) using Psi4
    t = time.time()
    molecule = psi4.geometry(Settings['molecule'])
    basis = psi4.core.BasisSet.build(molecule,
                                     'BASIS',
                                     Settings['basis'],
                                     puream=0)
    dfbasis = psi4.core.BasisSet.build(molecule,
                                       'DF_BASIS_MP2',
                                       Settings['df_basis'],
                                       puream=0)
    mints = psi4.core.MintsHelper(basis)
    zero = psi4.core.BasisSet.zero_ao_basis_set()

    Jinvs = np.squeeze(mints.ao_eri(dfbasis, zero, dfbasis, zero).np)
    Jinvs = psi4.core.Matrix.from_array(Jinvs)
    Jinvs.power(-0.5, 1.e-14)
    Jinvs = Jinvs.np

    tsave.append(time.time() - t)
    show_progress(tsave, printif)

    # Get integrals uvP

    t = time.time()
    ao_uvP = np.squeeze(mints.ao_eri(basis, basis, dfbasis, zero).np)

    fh = slice(0, int(nmo / 2))
    sh = slice(int(nmo / 2), nmo)

    ## Build spin-blocks
    uvP = np.zeros((nmo, nmo, ao_uvP.shape[2]))
    uvP[fh, fh, :] = ao_uvP
    uvP[sh, sh, :] = ao_uvP

    tsave.append(time.time() - t)
    show_progress(tsave, printif)

    # Get b(iaP)

    t = time.time()
    biaQ = np.einsum('ui, va, uvP, PQ -> iaQ',
                     C[:, o],
                     C[:, v],
                     uvP,
                     Jinvs,
                     optimize='optimal')
    print(biaQ)
    tsave.append(time.time() - t)
    show_progress(tsave, printif)

    # Get MP2 energy

    printif('\n{}  Computing DF-MP2 energy'.format('\U0001F9ED'), end=' ')
    t = time.time()
    Emp2 = 0
    new = np.newaxis
    eo = eps[o]
    ev = eps[v]
    for i in range(nelec):
        for j in range(nelec):
            D = -ev[:, new] - ev[new, :]
            D = D + eo[i] + eo[j]
            D = 1.0 / D
            bAB = np.einsum('aQ, bQ-> ab', biaQ[i, :, :], biaQ[j, :, :])
            bBA = np.einsum('bQ, aQ-> ab', biaQ[i, :, :], biaQ[j, :, :])
            Emp2 += np.einsum('ab, ab->',
                              np.square(bAB - bBA),
                              D,
                              optimize='optimal')

    Emp2 = Emp2 / 4.0

    tsave.append(time.time() - t)
    printif('\n{} DF-MP2 Correlation Energy:    {:>16.10f}'.format(
        emoji('bolt'), Emp2))
    printif('\U0001F308 Final Electronic Energy:      {:>16.10f}'.format(Emp2 +
                                                                         Escf))
    printif('\n{} Total Computation time: {:10.5f} seconds'.format(
        '\U0000231B',
        time.time() - t0))

    # Compare results with SO-MP2

    printif('\n   \U0001F4C8 Comparing results with regular MP2:')

    t0 = time.time()
    E0mp2 = compute_SOMP2(Settings, psi4compare=False, silent=True)
    printif('\n{} MP2 Correlation Energy:    {:>16.10f}'.format(
        emoji('bolt'), E0mp2))
    printif('{} DF error:                  {:>16.10f}'.format(
        '\U0000274C', E0mp2 - Emp2))
    printif('\n{} Total Computation time: {:10.5f} seconds'.format(
        '\U0000231B',
        time.time() - t0))

    # Compare with Psi4

    psi4.set_options({
        'basis': Settings['basis'],
        'df_basis_mp2': Settings['df_basis'],
        'e_convergence': 1e-12,
        'scf_type': 'pk',
        'puream': False,
        'reference': 'uhf'
    })

    psi4_mp2 = psi4.energy('mp2')
    printif('\n\n{} Psi4  DF-MP2 Energy:          {:>16.10f}'.format(
        emoji('eyes'), psi4_mp2))
Ejemplo n.º 5
0
def compute_DFMP2(Settings):
    Escf, Ca, Cb, epsa, epsb, = compute_uhf(Settings,
                                            return_C=True,
                                            return_integrals=False)

    print("""
    ===================================================
      Density-Fitting Møller-Plesset Perturbation Theory
                           {}
    ===================================================
    """.format(emoji('wine')))

    tasks = """
    Building:
      \U0001F426  Spin-Orbital arrays               {}
      \U0001F986  MO integral <OO|VV>               {}
      \U0001F9A2   Eigenvalues auxiliar array Dijab  {}"""

    print(tasks.format('', '', ''))
    sys.stdout.write("\033[F" * 5)
    time.sleep(0.1)

    # Create Spin-Orbital arrays
    #C = np.block([
    #    [Ca,                 np.zeros(Ca.shape)],
    #    [np.zeros(Cb.shape), Cb]
    #    ])

    #eps = np.concatenate((epsa, epsb))
    eps = epsa
    nmo = len(eps)

    # re-Sorting orbitals
    #s = np.argsort(eps)
    #eps = eps[s]
    #C = C[:,s]

    print(tasks.format(emoji('check'), '', ''))

    # Create slices
    nelec = Settings['nalpha'] + Settings['nbeta']
    ndocc = int(nelec / 2)
    nmo = len(eps)
    nvir = nmo - ndocc
    o = slice(0, ndocc)
    v = slice(ndocc, nmo)

    # Build J^(-1/2) using Psi4

    molecule = psi4.geometry(Settings['molecule'])
    basis = psi4.core.BasisSet.build(molecule,
                                     'BASIS',
                                     Settings['basis'],
                                     puream=0)
    dfbasis = psi4.core.BasisSet.build(molecule,
                                       'DF_BASIS_MP2',
                                       Settings['df_basis'],
                                       puream=0)
    mints = psi4.core.MintsHelper(basis)
    zero = psi4.core.BasisSet.zero_ao_basis_set()

    Jinvs = np.squeeze(mints.ao_eri(dfbasis, zero, dfbasis, zero).np)
    Jinvs = psi4.core.Matrix.from_array(Jinvs)
    Jinvs.power(-0.5, 1.e-14)
    Jinvs = Jinvs.np

    # Get integrals uvP

    uvP = np.squeeze(mints.ao_eri(basis, basis, dfbasis, zero).np)

    #fh = slice(0, int(nmo/2))
    #sh = slice(int(nmo/2), nmo)

    #uvP = np.zeros((nmo, nmo, ao_uvP.shape[2]))
    #uvP[fh, fh, :] = ao_uvP
    #uvP[sh, sh, :] = ao_uvP

    #uvP = uvP[s,:,:]
    #uvP = uvP[:,s,:]
    #print(uvP.shape)

    # Get b(iaP)

    # b(uvQ)
    biaQ = np.einsum('uvP, PQ-> uvQ', uvP, Jinvs)

    # b(ivQ)
    biaQ = np.einsum('ui, uvQ-> ivQ', Ca[:, o], biaQ)

    # b(iaQ)
    biaQ = np.einsum('va, ivQ-> iaQ', Ca[:, v], biaQ)

    # Get eigenvalues Matrix D
    new = np.newaxis
    eo = eps[o]
    ev = eps[v]
    D = 1.0 / (eo[:, new, new, new] - ev[new, :, new, new] +
               eo[new, new, :, new] - ev[new, new, new, :])

    # Get MP2 energy

    print('\n{}  Computing MP2 energy'.format('\U0001F9ED'), end=' ')
    Emp2 = 0
    for i in range(ndocc):
        for j in range(ndocc):
            bAB = np.einsum('aQ, bQ-> ab', biaQ[i, :, :], biaQ[j, :, :])
            bBA = np.einsum('bQ, aQ-> ab', biaQ[i, :, :], biaQ[j, :, :])
            Emp2 += np.einsum('ab, ab, ab->',
                              bAB, (2 * bAB - bBA),
                              D[i, :, j, :],
                              optimize='optimal')

    print('\n{} MP2 Correlation Energy:    {:>16.10f}'.format(
        emoji('bolt'), Emp2))
    print('\U0001F308 Final Electronic Energy:   {:>16.10f}'.format(Emp2 +
                                                                    Escf))

    psi4.set_options({
        'basis': Settings['basis'],
        'df_basis_mp2': Settings['df_basis'],
        'e_convergence': 1e-12,
        'scf_type': 'pk',
        'puream': False,
        'reference': 'uhf'
    })

    psi4_mp2 = psi4.energy('mp2')
    print('\n\n{} Psi4  MP2 Energy:          {:>16.10f}'.format(
        emoji('eyes'), psi4_mp2))
Ejemplo n.º 6
0
def compute_CI(Settings):
    Escf, C, _, _, _, h, g, Vnuc = compute_uhf(Settings,
                                               return_C=True,
                                               return_integrals=True)

    print("""
    =========================================
       Configuration Interaction Starting
                       {}
    =========================================
    """.format(emoji('brinde')))

    # Initial workup

    nmo = len(C)
    nelec = Settings['nalpha'] + Settings['nbeta']
    if nelec % 2 != 0:
        raise NameError('This code works only for closed-shell molecules')

    ndocc = int(nelec / 2)
    nvir = nmo - ndocc

    # Read in excitation level
    if type(Settings["excitation_level"]) == int:
        exlv = int(Settings["excitation_level"])

    elif type(Settings["excitation_level"]) == str:
        if Settings["excitation_level"].lower() == 'full':
            exlv = nelec
        elif Settings["excitation_level"].lower() == 'cis':
            exlv = 1
        elif Settings["excitation_level"].lower() == 'cisd':
            exlv = 2
        elif Settings["excitation_level"].lower() == 'cisdt':
            exlv = 3
        elif Settings["excitation_level"].lower() == 'cisdtq':
            exlv = 4
        elif Settings["excitation_level"].lower() == 'cisdtqp':
            exlv = 5
        else:
            raise TypeError('Invalid excitation level: {}'.format(
                Settings["excitation_level"]))
    else:
        raise TypeError('Invalid excitation level: {}'.format(
            Settings["excitation_level"]))

    # Convert AO integrals to Molecular integrals

    h = np.einsum('up,vq,uv->pq', C, C, h, optimize='optimal')
    ERI = np.einsum('ap,bq,cr,ds,abcd->pqrs',
                    C,
                    C,
                    C,
                    C,
                    g,
                    optimize='optimal')

    ############### STEP 1 ###############
    ########  Read Active Space  #########

    ## The active_space must be a string containing the letters 'o', 'a' and 'u':
    ##  'o' represents frozen doubly occupied orbitals;
    ##  'a' represents active orbitals;
    ##  'u' represents frozen unoccupied orbitals.
    ## However, the active_space can also be given in three alternative ways:
    ## active_space = 'full': for a full CI computation;
    ## active_space = 'none': for a emputy active space (output energy is SCF energy);
    ## If the active_space string is shorter than expected, remaining orbitals will be
    ## considered 'u' (unoccupied)
    ## Note that, the first orbital has index 0

    active_space = Settings['active_space']

    if active_space == 'full':
        active_space = 'a' * nmo

    elif active_space == 'none':
        active_space = 'o' * ndocc + 'u' * nvir

    # If the active space string is smaller than the number of orbitals,
    # append 'u' (unoccupied) at the end

    while len(active_space) < nmo:
        active_space += 'u'

    # Check if active space size is consistem with given integrals
    if len(active_space) != nmo:
        raise NameError(
            'Active Space size is {} than the number of molecular orbitals'.
            format('greater' if len(active_space) > nmo else 'smaller'))

    nfrozen = active_space.count('o')
    nactive = active_space.count('a')
    active_elec = nelec - 2 * nfrozen

    # Check if number of frozen orbitals is valid (must be less than the number of electron pairs)
    if active_elec < 0:
        raise NameError(
            'Invalid number of frozen orbitals ({}), for {} electrons'.format(
                nfrozen, nelec))

    # Check if there are enough active orbitals for the active electrons
    if 2 * nactive < active_elec:
        raise NameError(
            '{} active orbitals not enough for {} active electrons'.format(
                nactive, active_elec))

    print("Active Space:")
    out = ''
    for x in active_space:
        if x == 'o':
            out += emoji('Obold')
        elif x == 'a':
            out += emoji('O')
        elif x == 'u':
            out += emoji('X')
        else:
            raise TypeError('Invalid active space key: {}'.format(x))
    print(out + '\n')
    print("Number of active spatial orbitals:  {}".format(numoji(nactive)))
    print("Number of active electrons:         {}".format(numoji(active_elec)))
    print("Number of frozen orbitals:          {}\n".format(numoji(nfrozen)))

    ############### STEP 2 ###############
    ######  Generate Determinants  #######

    # Creating a template string. Active orbitals are represented by {}
    # Occupied orbitals are 1, and unnocupied 0.
    # For example: 11{}{}{}000 represents a system with 8 orbitals where the two lowest ones are frozen (doubly occupied)
    # and the three highest ones are frozen (unnocupied). Thus, there are 3 active orbitals.

    template_space = active_space.replace('o', '1')
    template_space = template_space.replace('u', '0')
    template_space = template_space.replace('a', '{}')

    # Produce a reference determinant

    ref = Determinant(a = ('1'*ndocc + '0'*nvir), \
              b = ('1'*ndocc + '0'*nvir))

    # Produces a list of active electrons in active orbitals and get all permutations of it.
    # For example. Say we have a template 11{}{}{}000 as in the example above. If the system contains 6 electrons
    # we have one pair of active electrons. The list of active electrons will look like '100' and the permutations
    # will be generated (as lists): ['1', '0', '0'], ['0', '1', '0'], and ['0', '0', '1'].

    # Each permutation is then merged with the template above to generate a string used ot create a Determinant object
    # For example. 11{}{}{}000 is combine with ['0','1', '0'] to produce an alpha/beta string 11010000.
    # These strings are then combined to form various determinants

    print("Generating excitations", end=' ')
    perms = set(
        permutations('1' * int(active_elec / 2) +
                     '0' * int(nactive - active_elec / 2)))
    print(emoji('check'))

    determinants = []
    for p1 in perms:
        for p2 in perms:
            newdet = Determinant(a=template_space.format(*p1),
                                 b=template_space.format(*p2))
            if ref - newdet > 2 * exlv:
                continue
            else:
                determinants.append(newdet)

    ndets = len(determinants)
    nelements = int((ndets * (ndets + 1)) / 2)
    print("Number of determinants:                   {}".format(numoji(ndets)))
    print("Number of unique matrix elements:         {}\n".format(
        numoji(nelements)))

    # Build Hamiltonian matrix
    print("Building Hamiltonian Matrix", end=' ')
    H = get_Hamiltonian(determinants, h, ERI)

    print(emoji('check'))

    # Diagonalize Hamiltonian
    print("Diagonalizing Hamiltonian Matrix", end=' ')
    Eci, Cci = np.linalg.eigh(H)
    print(emoji('check'))

    E0 = Eci[0] + Vnuc
    C0 = Cci[:, 0]

    print('\nFinal CASCI Energy: {:<14.10f}'.format(E0))

    if exlv == nelec:
        psi4.set_options({
            'basis': Settings['basis'],
            'scf_type': 'pk',
            'puream': False,
            'FROZEN_DOCC': [nfrozen],
            'ACTIVE': [nactive],
            'FCI': True,
            'reference': 'rhf'
        })

        print('Final DETCI Energy: {:<14.10f}'.format(psi4.energy('detci')))

    # Print wavefunction analysis

    ndet = 10
    args = np.argsort(C0 * C0)
    sortedC = C0[args]
    sortedC = sortedC[::-1]
    sortedC = sortedC[:ndet]

    sortedD = np.array(determinants)[args]
    sortedD = sortedD[::-1]
    sortedD = sortedD[:ndet]

    print('\n\n' + emoji('bchart') + ' Wave function analysis')
    print('=' * 25)
    print('\n')

    print(' ' * 10 + emoji('top') +
          ' Top {} determinants as voted by the public\n'.format(ndet))

    # Header
    l = len(ref.short_info())
    header = '    {:^7s}   {:^8s}   {:^' + str(l) + 's}   {:^9s}'
    print(header.format('%', 'Coef', 'Determinant', 'Exc lv'))
    print(' ' * 4 + '=' * 7 + '   ' + '=' * 8 + '   ' + '=' * l + '   ' +
          '=' * 9)

    # Actual info
    f = True
    for c, d in zip(sortedC, sortedD):
        sq = c * c
        ex = int((ref - d) / 2)
        if f:
            print(' ' * 2 + emoji('trophy') +
                  '{:7.5f}   {: 8.5f}   {}   {:^9s}'.format(
                      sq, c, d.short_info(), numoji(ex)))
            f = False
        else:
            print(' ' * 4 + '{:7.5f}   {: 8.5f}   {}   {:^9s}'.format(
                sq, c, d.short_info(), numoji(ex)))
Ejemplo n.º 7
0
def compute_dfCEPA(Settings, silent=False, compare=False):

    t0 = time.time()

    printif = print if not silent else lambda *k, **w: None

    Escf, Ca, Cb, epsa, epsb, _, g, Vnuc = compute_uhf(Settings,
                                                       return_C=True,
                                                       return_integrals=True)

    printif("""
    =======================================================
                   Density-Fitting CEPA0
      (For those who havent heard Coupled Cluster exists)
                             {}
    =======================================================
    """.format('\U0001F474'))

    tsave = []
    show_progress(tsave, printif)

    # Create Spin-Orbital arrays
    t = time.time()
    C = np.block([[Ca, np.zeros(Ca.shape)], [np.zeros(Cb.shape), Cb]])

    eps = np.concatenate((epsa, epsb))

    g = np.kron(np.eye(2), g)
    g = np.kron(np.eye(2), g.T)

    # re-Sorting orbitals
    s = np.argsort(eps)
    eps = eps[s]
    C = C[:, s]

    tsave.append(time.time() - t)
    show_progress(tsave, printif)

    # Get the MO integral

    t = time.time()
    nelec = Settings['nalpha'] + Settings['nbeta']
    # Converto to Physicists notation
    g = g.transpose(0, 2, 1, 3)
    # Antisymmetrize
    g = g - g.transpose(0, 1, 3, 2)

    # Save Slices
    ERI = lambda ax, bx, cx, dx: np.einsum('ap,bq,cr,ds,abcd->pqrs',
                                           C[:, ax],
                                           C[:, bx],
                                           C[:, cx],
                                           C[:, dx],
                                           g,
                                           optimize='optimal')
    nmo = len(g)
    o = slice(0, nelec)
    v = slice(nelec, nmo)
    Voovv = ERI(o, o, v, v)
    Voooo = ERI(o, o, o, o)
    Vvoov = ERI(v, o, o, v)

    tsave.append(time.time() - t)
    show_progress(tsave, printif)

    # Use Density-Fitting for the Vvvvv case
    # Build J^(-1/2) using Psi4
    t = time.time()
    molecule = psi4.geometry(Settings['molecule'])
    basis = psi4.core.BasisSet.build(molecule,
                                     'BASIS',
                                     Settings['basis'],
                                     puream=0)
    dfbasis = psi4.core.BasisSet.build(molecule,
                                       'DF_BASIS_MP2',
                                       Settings['df_basis'],
                                       puream=0)
    mints = psi4.core.MintsHelper(basis)
    zero = psi4.core.BasisSet.zero_ao_basis_set()

    Jinvs = np.squeeze(mints.ao_eri(dfbasis, zero, dfbasis, zero).np)
    Jinvs = psi4.core.Matrix.from_array(Jinvs)
    Jinvs.power(-0.5, 1.e-14)
    Jinvs = Jinvs.np

    tsave.append(time.time() - t)
    show_progress(tsave, printif)

    # Get integrals uvP

    t = time.time()
    ao_uvP = np.squeeze(mints.ao_eri(basis, basis, dfbasis, zero).np)

    fh = slice(0, int(nmo / 2))
    sh = slice(int(nmo / 2), nmo)

    ## Build spin-blocks
    uvP = np.zeros((nmo, nmo, ao_uvP.shape[2]))
    uvP[fh, fh, :] = ao_uvP
    uvP[sh, sh, :] = ao_uvP

    tsave.append(time.time() - t)
    show_progress(tsave, printif)

    # Get b(abP)

    t = time.time()
    babQ = np.einsum('ua, vb, uvP, PQ -> abQ',
                     C[:, v],
                     C[:, v],
                     uvP,
                     Jinvs,
                     optimize='optimal')
    tsave.append(time.time() - t)
    show_progress(tsave, printif)

    # Get eigenvalues Matrix D
    t = time.time()
    new = np.newaxis
    eo = eps[:nelec]
    ev = eps[nelec:]
    D = 1.0 / (eo[:, new, new, new] + eo[new, :, new, new] -
               ev[new, new, :, new] - ev[new, new, new, :])

    tsave.append(time.time() - t)
    show_progress(tsave, printif)
    t = time.time()

    # Initial guess for amplitudes

    T = Voovv * D

    # Get MP2 energy

    E = CEPA_Energy(T, Voovv)

    print('\nMP2 Energy:   {:<15.10f}\n'.format(E + Escf))

    # Setup iteration options
    rms = 0.0
    dE = 1
    ite = 1
    rms_LIM = 10**(-8)
    E_LIM = 10**(-12)
    t0 = time.time()
    printif('\U00003030' * 20)

    # Start CC iterations
    while abs(dE) > E_LIM or rms > rms_LIM:
        t = time.time()
        if ite > Settings["cc_max_iter"]:
            raise NameError('CEPA0 equations did not converge')
        T, rms = CEPA_Amplitude(T, D, Voovv, Voooo, babQ, Vvoov)
        dE = -E
        E = CEPA_Energy(T, Voovv)
        dE += E
        printif("Iteration  {}".format(numoji(ite)))
        printif("\U000027B0 Correlation energy:     {:< 15.10f}".format(E))
        printif("\U0001F53A Energy change:          {:< 15.10f}".format(dE))
        printif("\U00002622  Max RMS residue:        {:< 15.10f}".format(rms))
        printif("\U0001F570  Time required:          {:< 15.10f}".format(
            time.time() - t))
        printif('\U00003030' * 20)
        ite += 1

    printif('\U0001F3C1 DF-CEPA0 Energy:    {:<15.10f}'.format(E + Escf))
    printif('\U000023F3 CEPA0 iterations took %.2f seconds.\n' %
            (time.time() - t0))

    if compare:

        from CEPA import compute_CEPA

        printif('\n   Running regular CEPA...\n')

        t0 = time.time()
        Efull = compute_CEPA(Settings, silent=True, compare=False)
        printif('\U0001F3C1 CEPA0 Energy:    {:<15.10f}'.format(Efull))
        printif('\U000023F3 CEPA0 iterations took %.2f seconds.\n' %
                (time.time() - t0))

        printif(
            '\n\U0000274C Density Fitting Error:   {:<15.10f}'.format(E +
                                                                      Escf -
                                                                      Efull))

    return (E + Escf)