Beispiel #1
0
    def _cache_and_analyze_(self, calcname, E, focka_fockb, dma_dmb, JKidem,
                            JKcorr, oneRDMcorr_loc, loc2idem, loc2corr,
                            nelec_idem, oneRDM_loc, oneSDM_loc):

        ########################################################################################################
        self.e_tot = E
        self.activeVSPIN = (focka_fockb[0] - focka_fockb[1]) / 2
        #self.activeFOCK     = get_roothaan_fock (focka_fockb, dma_dmb, np.eye (self.norbs_tot))
        self.activeFOCK = (focka_fockb[0] + focka_fockb[1]) / 2
        self.activeJKidem = JKidem
        self.activeJKcorr = JKcorr
        self.oneRDMcorr_loc = oneRDMcorr_loc
        self.oneSDMcorr_loc = oneSDM_loc
        self.loc2idem = loc2idem
        self.nelec_idem = nelec_idem
        self.oneRDM_loc = oneRDM_loc
        self.oneSDM_loc = oneSDM_loc
        ########################################################################################################

        # Analysis: 1RDM and total energy
        print("LASSCF trial wave function total energy: {:.9f}".format(E))
        ao2molden, ene_no, occ_no = self.get_trial_nos(aobasis=True,
                                                       loc2wmas=loc2corr,
                                                       oneRDM_loc=oneRDM_loc,
                                                       fock=self.activeFOCK,
                                                       jmol_shift=True,
                                                       try_symmetrize=True)
        if self.mol.verbose:
            print("Writing trial wave function molden")
            molden.from_mo(self.mol,
                           calcname + '_trial_wvfn.molden',
                           ao2molden,
                           occ=occ_no,
                           ene=ene_no)
Beispiel #2
0
def examine_wmcs (dmet_obj):
    loc2wmas = np.concatenate ([f.loc2amo for f in dmet_obj.fragments], axis=1)
    loc2wmcs = get_complementary_states (loc2wmas)

    print ("Examining whole-molecule active space:")
    loc2wmas = dmet_obj.ints.compare_basis_to_loc (loc2wmas, dmet_obj.fragments, quiet=False)[0]
    norbs_wmas = np.array ([f.norbs_as for f in dmet_obj.fragments])

    print ("Examining whole-molecule core space:")
    norbs_wmcs_before = dmet_obj.ints.compare_basis_to_loc (loc2wmcs, dmet_obj.fragments, quiet=True)[1]
    norbs_before = norbs_wmas + norbs_wmcs_before
    ao2loc = dmet_obj.ints.ao2loc
    loc2ao = ao2loc.conjugate ().T
    ao2wmcs = np.dot (ao2loc, loc2wmcs)
    ao2wmcs_new = boys.Boys (dmet_obj.ints.mol, ao2wmcs).kernel ()
    aoOao_inv = np.linalg.inv (np.dot (ao2loc, loc2ao))
    loc2wmcs_new = reduce (np.dot, [loc2ao, aoOao_inv, ao2wmcs_new])
    loc2wmcs_new, norbs_wmcs_after = dmet_obj.ints.compare_basis_to_loc (loc2wmcs_new, dmet_obj.fragments, quiet=False)
    norbs_after = norbs_wmas + norbs_wmcs_after

    loc2new = np.append (loc2wmas, loc2wmcs_new, axis=1)
    active_flag = np.append (np.ones (loc2wmas.shape[1]), np.zeros (loc2wmcs_new.shape[1]))
    print ("Is the new basis orthonormal and complete? {0}".format (is_basis_orthonormal_and_complete (loc2new)))
    print ("Fragment-orbital assignment breakdown:")
    print ("Frag Before After")
    for frag, bef, aft in zip (dmet_obj.fragments, norbs_before, norbs_after):
        print ('{:>4s} {:6d} {:5d}'.format (frag.frag_name, int (bef), int (aft)))

    filename = 'relocalized_basis.molden'
    mol = dmet_obj.ints.mol.copy ()
    ao2new = np.dot (dmet_obj.ints.ao2loc, loc2new)
    molden.from_mo (mol, filename, ao2new, occ=active_flag)
    '''
Beispiel #3
0
def make_guess_molden (frag, filename, imp2mo, norbs_cmo, norbs_amo):
    norbs_tot = imp2mo.shape[1]
    mo_occ = np.zeros (norbs_tot)
    norbs_occ = norbs_cmo + norbs_amo
    mo_occ[:norbs_cmo] = 2
    mo_occ[norbs_cmo:norbs_occ] = 1
    mo = reduce (np.dot, (frag.ints.ao2loc, frag.loc2imp, imp2mo))
    molden.from_mo (frag.ints.mol, filename, mo, occ=mo_occ)
    return
Beispiel #4
0
    def test_dump_cartesian_gto_symm_orbital(self):
        ftmp = tempfile.NamedTemporaryFile()
        fname = ftmp.name

        pmol = mol.copy()
        pmol.cart = True
        pmol.build()
        mf = scf.RHF(pmol).run()
        molden.from_mo(pmol, fname, mf.mo_coeff)

        res = molden.read(fname)
        mo_coeff = res[2]
        self.assertAlmostEqual(abs(mf.mo_coeff - mo_coeff).max(), 0, 12)
Beispiel #5
0
def from_sa_mcscf(mc,
                  fname,
                  state=None,
                  cas_natorb=False,
                  cas_mo_energy=False,
                  **kwargs):
    if state is None:
        return from_mcscf(mc, fname, cas_natorb=cas_natorb, **kwargs)
    casdm1 = mc.fcisolver.states_make_rdm1(mc.ci, mc.ncas, mc.nelecas)[state]
    mo_coeff, mo_ci, mo_energy = mc.canonicalize(ci=mc.ci[state],
                                                 cas_natorb=cas_natorb,
                                                 casdm1=casdm1)
    if not cas_mo_energy:
        mo_energy[mc.ncore:][:mc.ncas] = 0.0
    # TODO: cleaner interface. Probably invent "state_make_?dm*" functions ("state" singular)
    # and apply them also to the StateAverageMCSCFSolver instance
    mo_occ = np.zeros_like(mo_energy)
    mo_occ[:mc.ncore] = 2.0
    ci = mc.ci
    ci[state] = mo_ci
    mo_occ[mc.ncore:][:mc.ncas] = mc.fcisolver.states_make_rdm1(
        ci, mc.ncas, mc.nelecas)[state].diagonal()
    return from_mo(mc.mol,
                   fname,
                   mo_coeff,
                   occ=mo_occ,
                   ene=mo_energy,
                   **kwargs)
Beispiel #6
0
def visualize_mos(mol: gto.mole.Mole,
                  mo_coeff: np.ndarray,
                  act_mos: list,
                  nroot: int = 1,
                  name: str = 'act_mo',
                  keepmolden: bool = False,
                  mo_occ: list = None,
                  mo_ene: list = None):
    r"""Function to visualize the active MOs via Jmol.
        Orbitals are counted from 0!

        Args:
            mol:		                The molecule in PySCF's gto.Mole() format.
            mo_coeff (np.ndarray):  	The MO coeff. matrix obtained via DMRG.
            act_mos (list):	            The suggested active MOs which will be plotted.
            nroot (int):		        Number of the root that is being plotted.
                                        Only for purpose of naming.
            name (str):		            Prefix of the filename for orbitals.
            keepmolden (bool):          Keep the molden file used for visualization.
            mo_occ (list):              MO_occupation to be written in molden file.
            mo_ene (list):              MO energy to be written in molden file.
    """
    # Create molden orbitals
    from pyscf.tools import molden
    molden.from_mo(mol, 'asf_mos.molden', mo_coeff, ene=mo_ene, occ=mo_occ)

    # Write jmol script
    with open('plot.spt', 'w') as plotfile:
        print('initialize;\nset background [xffffff];\nset frank off;\n',
              'set autoBond true;\nset bondRadiusMilliAngstroms 66;\n',
              'set bondTolerance 0.5;\nset forceAutoBond false;\n',
              'load asf_mos.molden;\nrotate 45 x;\nrotate 45 y;\n', 'zoom 100;'
              '',
              file=plotfile)

        for ii in act_mos:
            print('isosurface color yellow purple mo ',
                  '%s translucent; write PNG 200 "%s_%s_%s.png"' %
                  (ii + 1, name, nroot, ii),
                  file=plotfile)
        print('exitJmol;\n', file=plotfile)
    os.system('jmol plot.spt')
    os.remove('plot.spt')
Beispiel #7
0
    idx_h0_2s = mol.search_ao_label ('0 H 2s')[0]
    idx_h1_2s = mol.search_ao_label ('1 H 2s')[0]
    dma = np.zeros ((nao, nao))
    dmb = np.zeros ((nao, nao))
    dma[idx_h0_1s,idx_h0_1s] = dmb[idx_h1_1s,idx_h1_1s] = dma[idx_h0_2s,idx_h0_2s] = dmb[idx_h1_2s,idx_h1_2s] = 1
dm0 = [dma, dmb]

# Restricted mean-field base of MC-SCF objects
mf = scf.RHF (mol).run ()

# MC-PDFT objects
if gsbasis:
    gsmo = np.load (gsmofile)
    mc = mcpdft.CASSCF (mf, transl_type + fnal, ncas, nelecas, grids_level = 3)
    mo = mcscf.project_init_guess (mc, gsmo, prev_mol=gsmol)
    molden.from_mo (mol, 'check_projection.molden', mo)
    mc.kernel (mo)
    mc = mc.as_scanner ()
else:  
    mc = mcpdft.CASSCF (mf, transl_type + fnal, ncas, nelecas, grids_level = 3).run ().as_scanner ()
np.save (mofile, mc.mo_coeff)

# Do MCSCF scan forwards
table = np.zeros ((HHrange.size, 9))
table[:,0] = HHrange
for ix, HHdist in enumerate (HHrange):
    geom = 'H 0 0 0; H 0 0 {:.6f}'.format (HHdist)
    table[ix,1] = mc (geom)
    table[ix,2] = mc.e_mcscf
    table[ix,3:] = list (mc.get_energy_decomposition ())
Beispiel #8
0
def solve (frag, guess_1RDM, chempot_imp):

    # Augment OEI with the chemical potential
    OEI = frag.impham_OEI_C - chempot_imp

    # Do I need to get the full RHF solution?
    guess_orbs_av = len (frag.imp_cache) == 2 or frag.norbs_as > 0 

    # Get the RHF solution
    mol = gto.Mole()
    abs_2MS = int (round (2 * abs (frag.target_MS)))
    abs_2S = int (round (2 * abs (frag.target_S)))
    sign_MS = int (np.sign (frag.target_MS)) or 1
    mol.spin = abs_2MS
    mol.verbose = 0 
    if frag.mol_stdout is None:
        mol.output = frag.mol_output
        mol.verbose = 0 if frag.mol_output is None else lib.logger.DEBUG
    mol.atom.append(('H', (0, 0, 0)))
    mol.nelectron = frag.nelec_imp
    if frag.enforce_symmetry:
        mol.groupname  = frag.symmetry
        mol.symm_orb   = get_subspace_symmetry_blocks (frag.loc2imp, frag.loc2symm)
        mol.irrep_name = frag.ir_names
        mol.irrep_id   = frag.ir_ids
    mol.max_memory = frag.ints.max_memory
    mol.build ()
    if frag.mol_stdout is None:
        frag.mol_stdout = mol.stdout
    else:
        mol.stdout = frag.mol_stdout
        mol.verbose = 0 if frag.mol_output is None else lib.logger.DEBUG
    if frag.enforce_symmetry: mol.symmetry = True
    #mol.incore_anyway = True
    mf = scf.RHF(mol)
    mf.get_hcore = lambda *args: OEI
    mf.get_ovlp = lambda *args: np.eye(frag.norbs_imp)
    mf.energy_nuc = lambda *args: frag.impham_CONST
    if frag.impham_CDERI is not None:
        mf = mf.density_fit ()
        mf.with_df._cderi = frag.impham_CDERI
    else:
        mf._eri = ao2mo.restore(8, frag.impham_TEI, frag.norbs_imp)
    mf = fix_my_RHF_for_nonsinglet_env (mf, frag.impham_OEI_S)
    mf.__dict__.update (frag.mf_attr)
    if guess_orbs_av: mf.max_cycle = 2
    mf.scf (guess_1RDM)
    if (not mf.converged) and (not guess_orbs_av):
        if np.any (np.abs (frag.impham_OEI_S) > 1e-8) and mol.spin != 0:
            raise NotImplementedError('Gradient and Hessian fixes for nonsinglet environment of Newton-descent ROHF algorithm')
        print ("CASSCF RHF-step not converged on fixed-point iteration; initiating newton solver")
        mf = mf.newton ()
        mf.kernel ()

    # Instability check and repeat
    if not guess_orbs_av:
        for i in range (frag.num_mf_stab_checks):
            if np.any (np.abs (frag.impham_OEI_S) > 1e-8) and mol.spin != 0:
                raise NotImplementedError('ROHF stability-check fixes for nonsinglet environment')
            mf.mo_coeff = mf.stability ()[0]
            guess_1RDM = mf.make_rdm1 ()
            mf = scf.RHF(mol)
            mf.get_hcore = lambda *args: OEI
            mf.get_ovlp = lambda *args: np.eye(frag.norbs_imp)
            mf._eri = ao2mo.restore(8, frag.impham_TEI, frag.norbs_imp)
            mf = fix_my_RHF_for_nonsinglet_env (mf, frag.impham_OEI_S)
            mf.scf (guess_1RDM)
            if not mf.converged:
                mf = mf.newton ()
                mf.kernel ()

    E_RHF = mf.e_tot
    print ("CASSCF RHF-step energy: {}".format (E_RHF))

    # Get the CASSCF solution
    CASe = frag.active_space[0]
    CASorb = frag.active_space[1] 
    checkCAS =  (CASe <= frag.nelec_imp) and (CASorb <= frag.norbs_imp)
    if (checkCAS == False):
        CASe = frag.nelec_imp
        CASorb = frag.norbs_imp
    if (abs_2MS > abs_2S):
        CASe = ((CASe + sign_MS * abs_2S) // 2, (CASe - sign_MS * abs_2S) // 2)
    else:
        CASe = ((CASe + sign_MS * abs_2MS) // 2, (CASe - sign_MS * abs_2MS) // 2)
    if frag.impham_CDERI is not None:
        mc = mcscf.DFCASSCF(mf, CASorb, CASe)
    else:
        mc = mcscf.CASSCF(mf, CASorb, CASe)
    smult = abs_2S + 1 if frag.target_S is not None else (frag.nelec_imp % 2) + 1
    mc.fcisolver = csf_solver (mf.mol, smult, symm=frag.enforce_symmetry)
    if frag.enforce_symmetry: mc.fcisolver.wfnsym = frag.wfnsym
    mc.max_cycle_macro = 50 if frag.imp_maxiter is None else frag.imp_maxiter
    mc.conv_tol = min (1e-9, frag.conv_tol_grad**2)  
    mc.ah_start_tol = mc.conv_tol / 10
    mc.ah_conv_tol = mc.conv_tol / 10
    mc.__dict__.update (frag.corr_attr)
    mc = fix_my_CASSCF_for_nonsinglet_env (mc, frag.impham_OEI_S)
    norbs_amo = mc.ncas
    norbs_cmo = mc.ncore
    norbs_imo = frag.norbs_imp - norbs_amo
    nelec_amo = sum (mc.nelecas)
    norbs_occ = norbs_amo + norbs_cmo
    #mc.natorb = True

    # Guess orbitals
    ci0 = None
    dm_imp = frag.get_oneRDM_imp ()
    fock_imp = mf.get_fock (dm=dm_imp)
    if len (frag.imp_cache) == 2:
        imp2mo, ci0 = frag.imp_cache
        print ("Taking molecular orbitals and ci vector from cache")
    elif frag.norbs_as > 0:
        nelec_imp_guess = int (round (np.trace (frag.oneRDMas_loc)))
        norbs_cmo_guess = (frag.nelec_imp - nelec_imp_guess) // 2
        print ("Projecting stored amos (frag.loc2amo; spanning {} electrons) onto the impurity basis and filling the remainder with default guess".format (nelec_imp_guess))
        imp2mo, my_occ = project_amo_manually (frag.loc2imp, frag.loc2amo, fock_imp, norbs_cmo_guess, dm=frag.oneRDMas_loc)
    elif frag.loc2amo_guess is not None:
        print ("Projecting stored amos (frag.loc2amo_guess) onto the impurity basis (no amo dm available)")
        imp2mo, my_occ = project_amo_manually (frag.loc2imp, frag.loc2amo_guess, fock_imp, norbs_cmo, dm=None)
        frag.loc2amo_guess = None
    else:
        dm_imp = np.asarray (mf.make_rdm1 ())
        while dm_imp.ndim > 2:
            dm_imp = dm_imp.sum (0)
        imp2mo = mf.mo_coeff
        fock_imp = mf.get_fock (dm=dm_imp)
        fock_mo = represent_operator_in_basis (fock_imp, imp2mo)
        _, evecs = matrix_eigen_control_options (fock_mo, sort_vecs=1)
        imp2mo = imp2mo @ evecs
        my_occ = ((dm_imp @ imp2mo) * imp2mo).sum (0)
        print ("No stored amos; using mean-field canonical MOs as initial guess")
    # Guess orbital processing
    if callable (frag.cas_guess_callback):
        mo = reduce (np.dot, (frag.ints.ao2loc, frag.loc2imp, imp2mo))
        mo = frag.cas_guess_callback (frag.ints.mol, mc, mo)
        imp2mo = reduce (np.dot, (frag.imp2loc, frag.ints.ao2loc.conjugate ().T, frag.ints.ao_ovlp, mo))
        frag.cas_guess_callback = None

    # Guess CI vector
    if len (frag.imp_cache) != 2 and frag.ci_as is not None:
        loc2amo_guess = np.dot (frag.loc2imp, imp2mo[:,norbs_cmo:norbs_occ])
        metric = np.arange (CASorb) + 1
        gOc = np.dot (loc2amo_guess.conjugate ().T, (frag.ci_as_orb * metric[None,:]))
        umat_g, svals, umat_c = matrix_svd_control_options (gOc, sort_vecs=1, only_nonzero_vals=True)
        if (svals.size == norbs_amo):
            print ("Loading ci guess despite shifted impurity orbitals; singular value error sum: {}".format (np.sum (svals - metric)))
            imp2mo[:,norbs_cmo:norbs_occ] = np.dot (imp2mo[:,norbs_cmo:norbs_occ], umat_g)
            ci0 = transform_ci_for_orbital_rotation (frag.ci_as, CASorb, CASe, umat_c)
        else:
            print ("Discarding stored ci guess because orbitals are too different (missing {} nonzero svals)".format (norbs_amo-svals.size))

    # Symmetry align if possible
    imp2unac = frag.align_imporbs_symm (np.append (imp2mo[:,:norbs_cmo], imp2mo[:,norbs_occ:], axis=1), sorting_metric=fock_imp,
        sort_vecs=1, orbital_type='guess unactive', mol=mol)[0]
    imp2mo[:,:norbs_cmo] = imp2unac[:,:norbs_cmo]
    imp2mo[:,norbs_occ:] = imp2unac[:,norbs_cmo:]
    #imp2mo[:,:norbs_cmo] = frag.align_imporbs_symm (imp2mo[:,:norbs_cmo], sorting_metric=fock_imp, sort_vecs=1, orbital_type='guess inactive', mol=mol)[0]
    imp2mo[:,norbs_cmo:norbs_occ], umat = frag.align_imporbs_symm (imp2mo[:,norbs_cmo:norbs_occ], sorting_metric=fock_imp,
        sort_vecs=1, orbital_type='guess active', mol=mol)
    #imp2mo[:,norbs_occ:] = frag.align_imporbs_symm (imp2mo[:,norbs_occ:], sorting_metric=fock_imp, sort_vecs=1, orbital_type='guess external', mol=mol)[0]
    if frag.enforce_symmetry:
        imp2mo = cleanup_subspace_symmetry (imp2mo, mol.symm_orb)
        err_symm = measure_subspace_blockbreaking (imp2mo, mol.symm_orb)
        err_orth = measure_basis_nonorthonormality (imp2mo)
        print ("Initial symmetry error after cleanup = {}".format (err_symm))
        print ("Initial orthonormality error after cleanup = {}".format (err_orth))
    if ci0 is not None: ci0 = transform_ci_for_orbital_rotation (ci0, CASorb, CASe, umat)
        

    # Guess orbital printing
    if frag.mfmo_printed == False and frag.ints.mol.verbose:
        ao2mfmo = reduce (np.dot, [frag.ints.ao2loc, frag.loc2imp, imp2mo])
        print ("Writing {} {} orbital molden".format (frag.frag_name, 'CAS guess'))
        molden.from_mo (frag.ints.mol, frag.filehead + frag.frag_name + '_mfmorb.molden', ao2mfmo, occ=my_occ)
        frag.mfmo_printed = True
    elif len (frag.active_orb_list) > 0: # This is done AFTER everything else so that the _mfmorb.molden always has consistent ordering
        print('Applying caslst: {}'.format (frag.active_orb_list))
        imp2mo = mc.sort_mo(frag.active_orb_list, mo_coeff=imp2mo)
        frag.active_orb_list = []
    if len (frag.frozen_orb_list) > 0:
        mc.frozen = copy.copy (frag.frozen_orb_list)
        print ("Applying frozen-orbital list (this macroiteration only): {}".format (frag.frozen_orb_list))
        frag.frozen_orb_list = []

    if frag.enforce_symmetry: imp2mo = lib.tag_array (imp2mo, orbsym=label_orb_symm (mol, mol.irrep_id, mol.symm_orb, imp2mo, s=mf.get_ovlp (), check=False))

    t_start = time.time()
    E_CASSCF = mc.kernel(imp2mo, ci0)[0]
    if (not mc.converged) and np.all (np.abs (frag.impham_OEI_S) < 1e-8):
        mc = mc.newton ()
        E_CASSCF = mc.kernel(mc.mo_coeff, mc.ci)[0]
    if not mc.converged:
        print ('Assuming ci vector is poisoned; discarding...')
        imp2mo = mc.mo_coeff.copy ()
        mc = mcscf.CASSCF(mf, CASorb, CASe)
        smult = abs_2S + 1 if frag.target_S is not None else (frag.nelec_imp % 2) + 1
        mc.fcisolver = csf_solver (mf.mol, smult)
        E_CASSCF = mc.kernel(imp2mo)[0]
        if not mc.converged:
            if np.any (np.abs (frag.impham_OEI_S) > 1e-8):
                raise NotImplementedError('Gradient and Hessian fixes for nonsinglet environment of Newton-descent CASSCF algorithm')
            mc = mc.newton ()
            E_CASSCF = mc.kernel(mc.mo_coeff, mc.ci)[0]
    assert (mc.converged)

    '''
    mc.conv_tol = 1e-12
    mc.ah_start_tol = 1e-10
    mc.ah_conv_tol = 1e-12
    E_CASSCF = mc.kernel(mc.mo_coeff, mc.ci)[0]
    if not mc.converged:
        mc = mc.newton ()
        E_CASSCF = mc.kernel(mc.mo_coeff, mc.ci)[0]
    #assert (mc.converged)
    '''
    
    # Get twoRDM + oneRDM. cs: MC-SCF core, as: MC-SCF active space
    # I'm going to need to keep some representation of the active-space orbitals

    # Symmetry align if possible
    oneRDM_amo, twoRDM_amo = mc.fcisolver.make_rdm12 (mc.ci, mc.ncas, mc.nelecas)
    fock_imp = mc.get_fock ()
    mc.mo_coeff[:,:norbs_cmo] = frag.align_imporbs_symm (mc.mo_coeff[:,:norbs_cmo], sorting_metric=fock_imp, sort_vecs=1, orbital_type='optimized inactive', mol=mol)[0]
    mc.mo_coeff[:,norbs_cmo:norbs_occ], umat = frag.align_imporbs_symm (mc.mo_coeff[:,norbs_cmo:norbs_occ],
        sorting_metric=oneRDM_amo, sort_vecs=-1, orbital_type='optimized active', mol=mol)
    mc.mo_coeff[:,norbs_occ:] = frag.align_imporbs_symm (mc.mo_coeff[:,norbs_occ:], sorting_metric=fock_imp, sort_vecs=1, orbital_type='optimized external', mol=mol)[0]
    if frag.enforce_symmetry:
        amo2imp = mc.mo_coeff[:,norbs_cmo:norbs_occ].conjugate ().T
        mc.mo_coeff = cleanup_subspace_symmetry (mc.mo_coeff, mol.symm_orb)
        umat = umat @ (amo2imp @ mc.mo_coeff[:,norbs_cmo:norbs_occ])
        err_symm = measure_subspace_blockbreaking (mc.mo_coeff, mol.symm_orb)
        err_orth = measure_basis_nonorthonormality (mc.mo_coeff)
        print ("Final symmetry error after cleanup = {}".format (err_symm))
        print ("Final orthonormality error after cleanup = {}".format (err_orth))
    mc.ci = transform_ci_for_orbital_rotation (mc.ci, CASorb, CASe, umat)

    # Cache stuff
    imp2mo = mc.mo_coeff #mc.cas_natorb()[0]
    loc2mo = np.dot (frag.loc2imp, imp2mo)
    imp2amo = imp2mo[:,norbs_cmo:norbs_occ]
    loc2amo = loc2mo[:,norbs_cmo:norbs_occ]
    frag.imp_cache = [mc.mo_coeff, mc.ci]
    frag.ci_as = mc.ci
    frag.ci_as_orb = loc2amo.copy ()
    t_end = time.time()

    # oneRDM
    oneRDM_imp = mc.make_rdm1 ()

    # twoCDM
    oneRDM_amo, twoRDM_amo = mc.fcisolver.make_rdm12 (mc.ci, mc.ncas, mc.nelecas)
    oneRDMs_amo = np.stack (mc.fcisolver.make_rdm1s (mc.ci, mc.ncas, mc.nelecas), axis=0)
    oneSDM_amo = oneRDMs_amo[0] - oneRDMs_amo[1] if frag.target_MS >= 0 else oneRDMs_amo[1] - oneRDMs_amo[0]
    oneSDM_imp = represent_operator_in_basis (oneSDM_amo, imp2amo.conjugate ().T)
    print ("Norm of spin density: {}".format (linalg.norm (oneSDM_amo)))
    # Note that I do _not_ do the *real* cumulant decomposition; I do one assuming oneSDM_amo = 0.
    # This is fine as long as I keep it consistent, since it is only in the orbital gradients for this impurity that
    # the spin density matters. But it has to stay consistent!
    twoCDM_amo = get_2CDM_from_2RDM (twoRDM_amo, oneRDM_amo)
    twoCDM_imp = represent_operator_in_basis (twoCDM_amo, imp2amo.conjugate ().T)
    print('Impurity CASSCF energy (incl chempot): {}; spin multiplicity: {}; time to solve: {}'.format (E_CASSCF, spin_square (mc)[1], t_end - t_start))

    # Active-space RDM data
    frag.oneRDMas_loc  = symmetrize_tensor (represent_operator_in_basis (oneRDM_amo, loc2amo.conjugate ().T))
    frag.oneSDMas_loc  = symmetrize_tensor (represent_operator_in_basis (oneSDM_amo, loc2amo.conjugate ().T))
    frag.twoCDMimp_amo = twoCDM_amo
    frag.loc2mo  = loc2mo
    frag.loc2amo = loc2amo
    frag.E2_cum  = np.tensordot (ao2mo.restore (1, mc.get_h2eff (), mc.ncas), twoCDM_amo, axes=4) / 2
    frag.E2_cum += (mf.get_k (dm=oneSDM_imp) * oneSDM_imp).sum () / 4
    # The second line compensates for my incorrect cumulant decomposition. Anything to avoid changing the checkpoint files...

    # General impurity data
    frag.oneRDM_loc = frag.oneRDMfroz_loc + symmetrize_tensor (represent_operator_in_basis (oneRDM_imp, frag.imp2loc))
    frag.oneSDM_loc = frag.oneSDMfroz_loc + frag.oneSDMas_loc
    frag.twoCDM_imp = None # Experiment: this tensor is huge. Do I actually need to keep it? In principle, of course not.
    frag.E_imp      = E_CASSCF + np.einsum ('ab,ab->', chempot_imp, oneRDM_imp)

    return None
Beispiel #9
0
#!/usr/bin/env python
#
# Author: Qiming Sun <*****@*****.**>
#
'''
TDDFT NTO analysis.
'''

from pyscf import gto, dft, tddft

mol = gto.Mole()
mol.build(
    atom='H 0 0 0; F 0 0 1.1',  # in Angstrom
    basis='631g',
    symmetry=True,
)

mf = dft.RKS(mol)
mf.xc = 'b3lyp'
mf.kernel()

mytd = tddft.TDDFT(mf)
mytd.kernel()

weights_1, nto_1 = mytd.get_nto(state=1, verbose=4)
weights_2, nto_2 = mytd.get_nto(state=2, verbose=4)
weights_3, nto_3 = mytd.get_nto(state=3, verbose=4)

from pyscf.tools import molden
molden.from_mo(mol, 'nto-td-3.molden', nto_3)
C   -1.211265339156     0.699329968382     0.000000000000
C   -1.211265339156    -0.699329968382     0.000000000000
H    0.000000000000     2.491406946734     0.000000000000
H    0.000000000000    -2.491406946734     0.000000000000
H    2.157597486829     1.245660462400     0.000000000000
H    2.157597486829    -1.245660462400     0.000000000000
H   -2.157597486829     1.245660462400     0.000000000000
H   -2.157597486829    -1.245660462400     0.000000000000''',
    basis = '6-31g')
mf = scf.RHF(mol)
mf.chkfile = 'benzene-631g.chk'
mf.kernel()

pz_idx = numpy.array([17,20,21,22,23,30,36,41,42,47,48,49])-1
loc_orb = lo.Boys(mol, mf.mo_coeff[:,pz_idx]).kernel()
molden.from_mo(mol, 'benzene-631g-boys.molden', loc_orb)



import numpy
from pyscf import lib
from pyscf import tools
from pyscf.tools import mo_mapping

mol, mo_energy, mo_coeff, mo_occ, irrep_labels, spins = \
        tools.molden.load('benzene-631g-boys.molden')

comp = mo_mapping.mo_comps('C.*2p[yz]',  # regular expression
                           mol, mo_coeff)

mol = lib.chkfile.load_mol('benzene-631g.chk')
Beispiel #11
0
mf = scf.RHF(mol)
mf.kernel()

#
# First method is to explicit call the functions provided by molden.py
#
with open('C6H6mo.molden', 'w') as f1:
    molden.header(mol, f1)
    molden.orbital_coeff(mol, f1, mf.mo_coeff, ene=mf.mo_energy, occ=mf.mo_occ)

#
# Second method is to simply call from_mo function to write the orbitals
#
c_loc_orth = lo.orth.orth_ao(mol)
molden.from_mo(mol, 'C6H6loc.molden', c_loc_orth)


#
# Molden format does not support high angular momentum basis.  To handle the
# orbitals which have l>=5 functions, a hacky way is to call molden.remove_high_l
# function.  However, the resultant orbitals may not be orthnormal.
#
mol = gto.M(
    atom = 'He 0 0 0',
    basis = {'He': gto.expand_etbs(((0, 3, 1., 2.), (5, 2, 1., 2.)))})
mf = scf.RHF(mol).run()
try:
    molden.from_mo(mol, 'He_without_h.molden', mf.mo_coeff)
except RuntimeError:
    print('    Found l=5 in basis.')
Beispiel #12
0
def solve(frag, guess_1RDM, chempot_imp):

    # Augment OEI with the chemical potential
    OEI = frag.impham_OEI - chempot_imp

    # Do I need to get the full RHF solution?
    guess_orbs_av = len(frag.imp_cache) == 2 or frag.norbs_as > 0

    # Get the RHF solution
    mol = gto.Mole()
    mol.spin = int(round(2 * frag.target_MS))
    mol.verbose = 0 if frag.mol_output is None else lib.logger.DEBUG
    mol.output = frag.mol_output
    mol.atom.append(('H', (0, 0, 0)))
    mol.nelectron = frag.nelec_imp
    mol.build()
    #mol.incore_anyway = True
    mf = scf.RHF(mol)
    mf.get_hcore = lambda *args: OEI
    mf.get_ovlp = lambda *args: np.eye(frag.norbs_imp)
    mf.energy_nuc = lambda *args: frag.impham_CONST
    if frag.impham_CDERI is not None:
        mf = mf.density_fit()
        mf.with_df._cderi = frag.impham_CDERI
    else:
        mf._eri = ao2mo.restore(8, frag.impham_TEI, frag.norbs_imp)
    mf.__dict__.update(frag.mf_attr)
    if guess_orbs_av: mf.max_cycle = 2
    mf.scf(guess_1RDM)
    if (not mf.converged) and (not guess_orbs_av):
        print(
            "CASSCF RHF-step not converged on fixed-point iteration; initiating newton solver"
        )
        mf = mf.newton()
        mf.kernel()

    # Instability check and repeat
    if not guess_orbs_av:
        for i in range(frag.num_mf_stab_checks):
            mf.mo_coeff = mf.stability()[0]
            guess_1RDM = mf.make_rdm1()
            mf = scf.RHF(mol)
            mf.get_hcore = lambda *args: OEI
            mf.get_ovlp = lambda *args: np.eye(frag.norbs_imp)
            mf._eri = ao2mo.restore(8, frag.impham_TEI, frag.norbs_imp)
            mf.scf(guess_1RDM)
            if not mf.converged:
                mf = mf.newton()
                mf.kernel()

    print("CASSCF RHF-step energy: {}".format(mf.e_tot))
    #print(mf.mo_occ)
    '''    
    idx = mf.mo_energy.argsort()
    mf.mo_energy = mf.mo_energy[idx]
    mf.mo_coeff = mf.mo_coeff[:,idx]'''

    # Get the CASSCF solution
    CASe = frag.active_space[0]
    CASorb = frag.active_space[1]
    checkCAS = (CASe <= frag.nelec_imp) and (CASorb <= frag.norbs_imp)
    if (checkCAS == False):
        CASe = frag.nelec_imp
        CASorb = frag.norbs_imp
    if (frag.target_MS > frag.target_S):
        CASe = ((CASe // 2) + frag.target_S, (CASe // 2) - frag.target_S)
    else:
        CASe = ((CASe // 2) + frag.target_MS, (CASe // 2) - frag.target_MS)
    if frag.impham_CDERI is not None:
        mc = mcscf.DFCASSCF(mf, CASorb, CASe)
    else:
        mc = mcscf.CASSCF(mf, CASorb, CASe)
    norbs_amo = mc.ncas
    norbs_cmo = mc.ncore
    norbs_imo = frag.norbs_imp - norbs_amo
    nelec_amo = sum(mc.nelecas)
    norbs_occ = norbs_amo + norbs_cmo
    #mc.natorb = True

    # Guess orbitals
    ci0 = None
    if len(frag.imp_cache) == 2:
        imp2mo, ci0 = frag.imp_cache
        print("Taking molecular orbitals and ci vector from cache")
    elif frag.norbs_as > 0:
        nelec_imp_guess = int(round(np.trace(frag.oneRDMas_loc)))
        norbs_cmo_guess = (frag.nelec_imp - nelec_imp_guess) // 2
        print(
            "Projecting stored amos (frag.loc2amo; spanning {} electrons) onto the impurity basis and filling the remainder with default guess"
            .format(nelec_imp_guess))
        imp2mo, my_occ = project_amo_manually(
            frag.loc2imp,
            frag.loc2amo,
            mf.get_fock(dm=frag.get_oneRDM_imp()),
            norbs_cmo_guess,
            dm=frag.oneRDMas_loc)
    elif frag.loc2amo_guess is not None:
        print(
            "Projecting stored amos (frag.loc2amo_guess) onto the impurity basis (no dm available)"
        )
        imp2mo, my_occ = project_amo_manually(
            frag.loc2imp,
            frag.loc2amo_guess,
            mf.get_fock(dm=frag.get_oneRDM_imp()),
            norbs_cmo,
            dm=None)
        frag.loc2amo_guess = None
    else:
        imp2mo = mc.mo_coeff
        my_occ = mf.mo_occ
        print(
            "No stored amos; using mean-field canonical MOs as initial guess")

    # Guess orbital processing
    if callable(frag.cas_guess_callback):
        mo = reduce(np.dot, (frag.ints.ao2loc, frag.loc2imp, imp2mo))
        mo = frag.cas_guess_callback(frag.ints.mol, mc, mo)
        imp2mo = reduce(np.dot, (frag.imp2loc, frag.ints.ao2loc.conjugate().T,
                                 frag.ints.ao_ovlp, mo))
        frag.cas_guess_callback = None
    elif len(frag.active_orb_list) > 0:
        print('Applying caslst: {}'.format(frag.active_orb_list))
        imp2mo = mc.sort_mo(frag.active_orb_list, mo_coeff=imp2mo)
        frag.active_orb_list = []
    if len(frag.frozen_orb_list) > 0:
        mc.frozen = copy.copy(frag.frozen_orb_list)
        print("Applying frozen-orbital list (this macroiteration only): {}".
              format(frag.frozen_orb_list))
        frag.frozen_orb_list = []

    # Guess orbital printing
    if frag.mfmo_printed == False:
        ao2mfmo = reduce(np.dot, [frag.ints.ao2loc, frag.loc2imp, imp2mo])
        molden.from_mo(frag.ints.mol,
                       frag.filehead + frag.frag_name + '_mfmorb.molden',
                       ao2mfmo,
                       occ=my_occ)
        frag.mfmo_printed = True

    # Guess CI vector
    if len(frag.imp_cache) != 2 and frag.ci_as is not None:
        loc2amo_guess = np.dot(frag.loc2imp, imp2mo[:, norbs_cmo:norbs_occ])
        gOc = np.dot(loc2amo_guess.conjugate().T, frag.ci_as_orb)
        umat_g, svals, umat_c = matrix_svd_control_options(
            gOc, sort_vecs=-1, only_nonzero_vals=True)
        if (svals.size == norbs_amo):
            print(
                "Loading ci guess despite shifted impurity orbitals; singular value sum: {}"
                .format(np.sum(svals)))
            imp2mo[:, norbs_cmo:norbs_occ] = np.dot(
                imp2mo[:, norbs_cmo:norbs_occ], umat_g)
            ci0 = transform_ci_for_orbital_rotation(frag.ci_as, CASorb, CASe,
                                                    umat_c)
        else:
            print(
                "Discarding stored ci guess because orbitals are too different (missing {} nonzero svals)"
                .format(norbs_amo - svals.size))

    t_start = time.time()
    smult = 2 * frag.target_S + 1 if frag.target_S is not None else (
        frag.nelec_imp % 2) + 1
    mc.fcisolver = csf_solver(mf.mol, smult)
    mc.max_cycle_macro = 50 if frag.imp_maxiter is None else frag.imp_maxiter
    mc.ah_start_tol = 1e-10
    mc.ah_conv_tol = 1e-10
    mc.conv_tol = 1e-9
    mc.__dict__.update(frag.corr_attr)
    E_CASSCF = mc.kernel(imp2mo, ci0)[0]
    if not mc.converged:
        mc = mc.newton()
        E_CASSCF = mc.kernel(mc.mo_coeff, mc.ci)[0]
    if not mc.converged:
        print('Assuming ci vector is poisoned; discarding...')
        imp2mo = mc.mo_coeff.copy()
        mc = mcscf.CASSCF(mf, CASorb, CASe)
        smult = 2 * frag.target_S + 1 if frag.target_S is not None else (
            frag.nelec_imp % 2) + 1
        mc.fcisolver = csf_solver(mf.mol, smult)
        E_CASSCF = mc.kernel(imp2mo)[0]
        if not mc.converged:
            mc = mc.newton()
            E_CASSCF = mc.kernel(mc.mo_coeff, mc.ci)[0]
    assert (mc.converged)
    '''
    mc.conv_tol = 1e-12
    mc.ah_start_tol = 1e-10
    mc.ah_conv_tol = 1e-12
    E_CASSCF = mc.kernel(mc.mo_coeff, mc.ci)[0]
    if not mc.converged:
        mc = mc.newton ()
        E_CASSCF = mc.kernel(mc.mo_coeff, mc.ci)[0]
    #assert (mc.converged)
    '''

    # Get twoRDM + oneRDM. cs: MC-SCF core, as: MC-SCF active space
    # I'm going to need to keep some representation of the active-space orbitals
    imp2mo = mc.mo_coeff  #mc.cas_natorb()[0]
    loc2mo = np.dot(frag.loc2imp, imp2mo)
    imp2amo = imp2mo[:, norbs_cmo:norbs_occ]
    loc2amo = loc2mo[:, norbs_cmo:norbs_occ]
    frag.imp_cache = [mc.mo_coeff, mc.ci]
    frag.ci_as = mc.ci
    frag.ci_as_orb = loc2amo.copy()
    t_end = time.time()
    print(
        'Impurity CASSCF energy (incl chempot): {}; spin multiplicity: {}; time to solve: {}'
        .format(E_CASSCF,
                spin_square(mc)[1], t_end - t_start))

    # oneRDM
    oneRDM_imp = mc.make_rdm1()

    # twoCDM
    oneRDM_amo, twoRDM_amo = mc.fcisolver.make_rdm12(mc.ci, mc.ncas,
                                                     mc.nelecas)
    # Note that I do _not_ do the *real* cumulant decomposition; I do one assuming oneRDMs_amo_alpha = oneRDMs_amo_beta
    # This is fine as long as I keep it consistent, since it is only in the orbital gradients for this impurity that
    # the spin density matters. But it has to stay consistent!
    twoCDM_amo = get_2CDM_from_2RDM(twoRDM_amo, oneRDM_amo)
    twoCDM_imp = represent_operator_in_basis(twoCDM_amo, imp2amo.conjugate().T)

    # General impurity data
    frag.oneRDM_loc = symmetrize_tensor(
        frag.oneRDMfroz_loc +
        represent_operator_in_basis(oneRDM_imp, frag.imp2loc))
    frag.twoCDM_imp = None  # Experiment: this tensor is huge. Do I actually need to keep it? In principle, of course not.
    frag.E_imp = E_CASSCF + np.einsum('ab,ab->', chempot_imp, oneRDM_imp)

    # Active-space RDM data
    frag.oneRDMas_loc = symmetrize_tensor(
        represent_operator_in_basis(oneRDM_amo,
                                    loc2amo.conjugate().T))
    frag.twoCDMimp_amo = twoCDM_amo
    frag.loc2mo = loc2mo
    frag.loc2amo = loc2amo
    frag.E2_cum = 0.5 * np.tensordot(
        ao2mo.restore(1, mc.get_h2eff(), mc.ncas), twoCDM_amo, axes=4)

    return None
Beispiel #13
0
def from_lasscf(las, fname, **kwargs):
    mo_coeff, mo_ene, mo_occ = las.canonicalize()[:3]
    return from_mo(las.mol, fname, mo_coeff, occ=mo_occ, ene=mo_ene, **kwargs)
Beispiel #14
0
'''
DF-MP2 natural orbitals for the allyl radical
'''

from pyscf.gto import Mole
from pyscf.scf import UHF
from pyscf.tools import molden
from pyscf.mp.dfump2_native import DFMP2

mol = Mole()
mol.atom = '''
C    -1.1528    -0.1151    -0.4645
C     0.2300    -0.1171    -0.3508
C     0.9378     0.2246     0.7924
H     0.4206     0.5272     1.7055
H     2.0270     0.2021     0.8159
H    -1.6484    -0.3950    -1.3937
H    -1.7866     0.1687     0.3784
H     0.8086    -0.4120    -1.2337
'''
mol.basis = 'def2-TZVP'
mol.spin = 1
mol.build()

mf = UHF(mol).run()

# MP2 natural occupation numbers and natural orbitals
natocc, natorb = DFMP2(mf).make_natorbs()
# store the natural orbitals in a molden file
molden.from_mo(mol, 'allyl_mp2nat.molden', natorb, occ=natocc)
Beispiel #15
0
#
# Load MF orbitals
#
chkname = "_chk/pp_dianion_dz_b3lyp.chk"
mol = chkfile.load_mol(chkname)
mol.verbose = 5
mf = dft.RKS(mol)
mf.__dict__.update(chkfile.load(chkname, "scf"))

#
# SA-MCSCF
#
nelecas, ncas = (4, 4)
n_states = 3
weights = np.ones(n_states) / n_states

mc = mcscf.CASSCF(mf, ncas, nelecas).state_average_(weights)
mc.fix_spin(ss=0)
mc.natorb = True
mc.chkfile = "_chk/pp_dianion_dz_cas_4e_4o.chk"
cas_list = [142, 143, 150, 151]
mo = mcscf.sort_mo(mc, mf.mo_coeff, cas_list)
mc.mc1step(mo)

#
# Analysis and processing
#
mc.analyze()
molden.from_mcscf(mc, "_molden/pp_dianion_dz_cas_4e_4o.molden")
molden.from_mo(mol, "_molden/pp_dianion_dz_cas_4e_4o_alt.molden", mc.mo_coeff)
Beispiel #16
0
# UKS comparison (initial guess must break symmetry!)
pks = scf.UKS(mol)
pks.xc = fnal
pks.kernel(dm0)
pks = pks.as_scanner()
hks = scf.UKS(mol)
hks.xc = kshfnal
hks.kernel(dm0)
hks = hks.as_scanner()

# MC-PDFT objects
if gsbasis:
    gsmo = np.load(gsmofile)
    mc = mcpdft.CASSCF(mf, transl_type + fnal, ncas, nelecas, grids_level=3)
    mo = mcscf.project_init_guess(mc, gsmo, prev_mol=gsmol)
    molden.from_mo(mol, 'check_projection.molden', mo)
    mc.kernel(mo)
    mc = mc.as_scanner()
else:
    mc = mcpdft.CASSCF(mf, transl_type + fnal, ncas, nelecas,
                       grids_level=3).run().as_scanner()
mc0 = mcpdft.CASSCF(mf, otfnal0, ncas, nelecas,
                    grids_level=3).run().as_scanner()
mc1 = mcpdft.CASSCF(mf, otfnal1, ncas, nelecas,
                    grids_level=3).run().as_scanner()
mc2 = mcpdft.CASSCF(mf, otfnal2, ncas, nelecas,
                    grids_level=3).run().as_scanner()
molden.from_mcscf(mc0, moldenfile)
np.save(mofile, mc.mo_coeff)

# Do MCSCF scan forwards
Beispiel #17
0
    def impurity_molden(self,
                        tag=None,
                        canonicalize=False,
                        natorb=False,
                        molorb=False,
                        ene=None,
                        occ=None):
        tag = '.' if tag == None else '_' + str(tag) + '.'
        filename = self.filehead + self.frag_name + tag + 'molden'
        mol = self.ints.mol.copy()
        mol.nelectron = self.nelec_imp
        mol.spin = int(round(2 * self.target_MS))

        oneRDM = self.get_oneRDM_imp()
        FOCK = represent_operator_in_basis(
            self.ints.loc_rhf_fock_bis(self.oneRDM_loc), self.loc2imp)
        ao2imp = np.dot(self.ints.ao2loc, self.loc2imp)

        ao2molden = ao2imp
        if molorb:
            assert (not natorb)
            assert (not canonicalize)
            ao2molden = np.dot(self.ints.ao2loc, self.loc2mo)
            occ = np.einsum('ip,ij,jp->p', self.imp2mo.conjugate(), oneRDM,
                            self.imp2mo)
            ene = np.einsum('ip,ij,jp->p', self.imp2mo.conjugate(), FOCK,
                            self.imp2mo)
            if self.norbs_as > 0:
                ene = cas_mo_energy_shift_4_jmol(ene, self.norbs_imp,
                                                 self.nelec_imp, self.norbs_as,
                                                 self.nelec_as)
        if natorb:
            assert (not canonicalize)
            # Separate active and external (inactive + virtual) orbitals and pry their energies apart by +-1e4 Eh so Jmol sets them
            # in the proper order
            if self.norbs_as > 0:
                imp2xmo = get_complementary_states(self.imp2amo)
                FOCK_amo = represent_operator_in_basis(FOCK, self.imp2amo)
                FOCK_xmo = represent_operator_in_basis(FOCK, imp2xmo)
                oneRDM_xmo = represent_operator_in_basis(oneRDM, imp2xmo)
                oneRDM_amo = represent_operator_in_basis(oneRDM, self.imp2amo)
                ene_xmo, xmo2molden = matrix_eigen_control_options(
                    FOCK_xmo, sort_vecs=1, only_nonzero_vals=False)
                occ_amo, amo2molden = matrix_eigen_control_options(
                    oneRDM_amo, sort_vecs=-1, only_nonzero_vals=False)
                occ_xmo = np.einsum('ip,ij,jp->p', xmo2molden.conjugate(),
                                    oneRDM_xmo, xmo2molden)
                ene_amo = np.einsum('ip,ij,jp->p', amo2molden.conjugate(),
                                    FOCK_amo, amo2molden)
                norbs_imo = (self.nelec_imp - self.nelec_as) // 2
                occ = np.concatenate(
                    (occ_xmo[:norbs_imo], occ_amo, occ_xmo[norbs_imo:]))
                ene = np.concatenate(
                    (ene_xmo[:norbs_imo], ene_amo, ene_xmo[norbs_imo:]))
                ene = cas_mo_energy_shift_4_jmol(ene, self.norbs_imp,
                                                 self.nelec_imp, self.norbs_as,
                                                 self.nelec_as)
                imp2molden = np.concatenate(
                    (np.dot(imp2xmo, xmo2molden[:, :norbs_imo]),
                     np.dot(self.imp2amo, amo2molden),
                     np.dot(imp2xmo, xmo2molden[:, norbs_imo:])),
                    axis=1)
            else:
                occ, imp2molden = matrix_eigen_control_options(
                    oneRDM, sort_vecs=-1, only_nonzero_vals=False)
                ene = np.einsum('ip,ij,jp->p', imp2molden.conjugate(), FOCK,
                                imp2molden)
            ao2molden = np.dot(ao2imp, imp2molden)
        elif canonicalize:
            # Separate active and external (inactive + virtual) orbitals and pry their energies apart by +-1e4 Eh so Jmol sets them
            # in the proper order
            if self.norbs_as > 0:
                imp2xmo = get_complementary_states(self.imp2amo)
                FOCK_amo = represent_operator_in_basis(FOCK, self.imp2amo)
                FOCK_xmo = represent_operator_in_basis(FOCK, imp2xmo)
                ene_xmo, xmo2molden = matrix_eigen_control_options(
                    FOCK_xmo, sort_vecs=1, only_nonzero_vals=False)
                ene_amo, amo1molden = matrix_eigen_control_options(
                    FOCK_amo, sort_vecs=1, only_nonzero_vals=False)
                norbs_imo = (self.nelec_imp - self.nelec_as) // 2
                ene = np.concatenate(
                    (ene_xmo[:norbs_imo], ene_amo, ene_xmo[norbs_imo:]))
                ene = cas_mo_energy_shift_4_jmol(ene, self.norbs_imp,
                                                 self.nelec_imp, self.norbs_as,
                                                 self.nelec_as)
                imp2molden = np.concatenate(
                    (np.dot(imp2xmo, xmo2molden[:, :norbs_imo]),
                     np.dot(self.imp2amo, amo2molden),
                     np.dot(imp2xmo, xmo2molden[:, norbs_imo:])),
                    axis=1)
            else:
                ene, imp2molden = matrix_eigen_control_options(
                    FOCK, sort_vecs=-1, only_nonzero_vals=False)
            occ = np.einsum('ip,ij,jp->p', imp2molden.conjugate(), oneRDM,
                            imp2molden)
            ao2molden = np.dot(ao2imp, imp2molden)

        molden.from_mo(mol, filename, ao2molden, ene=ene, occ=occ)
Beispiel #18
0
mf.chkfile = "_chk/pp_anion_pt_chg_dz_b3lyp.chk"
mf.kernel()
# mf.analyze()

#
# Dump orbitals
#
molden.dump_scf(mf, "_molden/pp_anion_pt_chg_dz_b3lyp.molden")

#
# SA-MCSCF
#
nelecas, ncas = (4, 4)
n_states = 3
weights = np.ones(n_states) / n_states

mc = mcscf.CASSCF(mf, ncas, nelecas).state_average_(weights)
mc.fix_spin(ss=0)
mc.natorb = True
mc.chkfile = "_chk/pp_anion_pt_chg_dz_cas_4e_4o.chk"
cas_list = [118, 119, 120, 121]
mo = mcscf.sort_mo(mc, mf.mo_coeff, cas_list)
mc.mc1step(mo)

#
# Analysis and processing
#
mc.analyze()
molden.from_mcscf(mc, "_molden/pp_anion_pt_chg_dz_cas.molden")
molden.from_mo(mol, "_molden/pp_anion_pt_chg_dz_cas_alt.molden", mc.mo_coeff)
Beispiel #19
0
def do_scf(inp):
    '''Do the requested SCF.'''

    from pyscf import gto, scf, dft, cc, fci, ci, ao2mo, mcscf, mrpt, lib, mp, tdscf
    from pyscf.cc import ccsd_t, uccsd_t
    import numpy as np
    from .fcidump import fcidump

    # sort out the method
    mol = inp.mol
    method = inp.scf.method.lower()

    # UHF
    if method == 'uhf':
        ehf, mSCF = do_hf(inp, unrestricted=True)
        print_energy('UHF', ehf)

        if inp.scf.exci is not None:
            inp.timer.start('TDHF')
            mtd = do_TDDFT(inp, mSCF)
            inp.timer.end('TDHF')

    # RHF
    elif method in ('rhf', 'hf'):
        ehf, mSCF = do_hf(inp)
        print_energy('RHF', ehf)

        if inp.scf.exci is not None:
            inp.timer.start('TDHF')
            mtd = do_TDDFT(inp, mSCF)
            inp.timer.end('TDHF')

    # CCSD and CCSD(T)
    elif method in ('ccsd', 'ccsd(t)', 'uccsd', 'uccsd(t)', 'eomccsd'):
        if 'u' in method:
            ehf, tSCF = do_hf(inp, unrestricted=True)
            print_energy('UHF', ehf)
        else:
            ehf, tSCF = do_hf(inp)
            print_energy('RHF', ehf)

        inp.timer.start('ccsd')
        frozen = 0
        if inp.scf.freeze is not None: frozen = inp.scf.freeze
        if 'u' in method:
            mSCF = cc.UCCSD(tSCF, frozen=frozen)
        else:
            mSCF = cc.CCSD(tSCF, frozen=frozen)
        mSCF.max_cycle = inp.scf.maxiter
        eccsd, t1, t2 = mSCF.kernel()
        print_energy('CCSD', ehf + eccsd)
        inp.timer.end('ccsd')

        if method == 'eomccsd':
            inp.timer.start('eomccsd')
            ee = mSCF.eomee_ccsd_singlet(nroots=4)[0]
            inp.timer.end('eomccsd')
            for i in range(len(ee)):
                print_energy('EOM-CCSD {0} (eV)'.format(i+1), ee[i] * 27.2114)

        if method in ('ccsd(t)', 'uccsd(t)'):
            inp.timer.start('ccsd(t)')
            eris = mSCF.ao2mo()

            if method == 'ccsd(t)':
                e3 = ccsd_t.kernel(mSCF, eris)
            else:
                e3 = uccsd_t.kernel(mSCF, eris)
            print_energy('CCSD(T)', ehf + eccsd + e3)
            inp.timer.end('ccsd(t)')

    # MP2
    elif method == 'mp2':
        ehf, tSCF = do_hf(inp)
        print_energy('RHF', ehf)

        inp.timer.start('mp2')
        frozen = 0 
        if inp.scf.freeze is not None: frozen = inp.scf.freeze
        mSCF = mp.MP2(tSCF, frozen=frozen)
        emp2, t2 = mSCF.kernel()
        print_energy('MP2', ehf+emp2)
        inp.timer.end('mp2')

    # CISD
    elif method == 'cisd' or method == 'cisd(q)':
        ehf, tSCF = do_hf(inp)
        print_energy('RHF', ehf)

        inp.timer.start('cisd')
        frozen = 0
        if inp.scf.freeze is not None: frozen = inp.scf.freeze
        mSCF = ci.CISD(tSCF, frozen=frozen)
        ecisd = mSCF.kernel()[0]
        print_energy('CISD', ehf + ecisd)
        inp.timer.end('cisd')

        # perform Davison quadruples correction
        c0 = np.max(np.abs(mSCF.ci))
        c02 = c0**2
        ne = mSCF.mol.nelectron
        eq = ( 1.0 - c02 ) * ecisd
        print_energy('CISD(Q) Davidson', ehf + ecisd + eq)
        eq = ( 1.0 - c02 ) / c02 * ecisd
        print_energy('CISD(Q) Renomalized-Davidson', ehf + ecisd + eq)
        eq = ( 1.0 - c02 ) / ( 2.0 * c02 - 1.0 ) * ecisd
        print_energy('CISD(Q) Davison-Silver', ehf + ecisd + eq)
        eq = (( 2.0 * c02 ) / ((2.0*c02-1.0)*(1.0 + np.sqrt(1.0 + (8.0*c02*(1.0-c02))
         / ( ne * (2.0*c02-1.0)**2 )))) - 1.0 ) * ecisd
        print_energy('CISD(Q) PC', ehf + ecisd + eq)
        eq = ( 1.0 - c02 ) / c02 * ((ne-2)*(ne-3.0)) / (ne*(ne-1.0)) * ecisd
        print_energy('CISD(Q) MC', ehf + ecisd + eq)
        if ne > 2:
            eq = ( 2.0 - c02 ) / (2.0 * (ne-1.0)/(ne-2.0) * c02 - 1.0)
        else:
            eq = 0.0
        print_energy('CISD(Q) DD', ehf + ecisd + eq)


    # UKS
    elif method in ('uks' or 'udft'):
        inp.timer.start('uks')
        inp.timer.start('grids')
        grids = dft.gen_grid.Grids(mol)
        grids.level = inp.scf.grid
        grids.build()
        inp.timer.end('grids')
        mSCF = dft.UKS(mol)
        mSCF.grids = grids
        mSCF.xc = inp.scf.xc
        mSCF.conv_tol = inp.scf.conv
        mSCF.conv_tol_grad = inp.scf.grad
        mSCF.max_cycle = inp.scf.maxiter
        mSCF.init_guess = inp.scf.guess
        mSCF.small_rho_cutoff = 1e-20
        eks = mSCF.kernel()
        print_energy('UKS', eks)
        inp.timer.end('uks')

        if inp.scf.exci is not None:
            inp.timer.start('TDDFT')
            mtd = do_TDDFT(inp, mSCF)
            inp.timer.end('TDDFT')

    # RKS
    elif method in ('rks', 'ks', 'rdft', 'dft'):
        inp.timer.start('ks')
        inp.timer.start('grids')
        grids = dft.gen_grid.Grids(mol)
        grids.level = inp.scf.grid
        grids.build()
        inp.timer.end('grids')
        if mol.nelectron%2 == 0:
            mSCF = dft.RKS(mol)
        else:
            mSCF = dft.ROKS(mol)
        mSCF.grids = grids
        mSCF.xc = inp.scf.xc
        mSCF.conv_tol = inp.scf.conv
        mSCF.conv_tol_grad = inp.scf.grad
        mSCF.max_cycle = inp.scf.maxiter
        mSCF.init_guess = inp.scf.guess
        mSCF.small_rho_cutoff = 1e-20
        mSCF.damp = inp.scf.damp
        mSCF.level_shift = inp.scf.shift
        eks = mSCF.kernel()
        print_energy('RKS', eks)
        inp.timer.end('ks')

        if inp.scf.exci is not None:
            inp.timer.start('TDDFT')
            mtd = do_TDDFT(inp, mSCF)
            inp.timer.end('TDDFT')

    # Unrestricted FCI
    elif method == 'ufci':
        ehf, mSCF = do_hf(inp, unrestricted=True)
        print_energy('UHF', ehf)

        inp.timer.start('fci')
        cis = fci.direct_uhf.FCISolver(mol)
        norb = mSCF.mo_energy[0].size
        nea = (mol.nelectron+mol.spin) // 2
        neb = (mol.nelectron-mol.spin) // 2
        nelec = (nea, neb)
        mo_a = mSCF.mo_coeff[0]
        mo_b = mSCF.mo_coeff[1]
        h1e_a = reduce(np.dot, (mo_a.T, mSCF.get_hcore(), mo_a))
        h1e_b = reduce(np.dot, (mo_b.T, mSCF.get_hcore(), mo_b))
        g2e_aa = ao2mo.incore.general(mSCF._eri, (mo_a,)*4, compact=False)
        g2e_aa = g2e_aa.reshape(norb,norb,norb,norb)
        g2e_ab = ao2mo.incore.general(mSCF._eri, (mo_a,mo_a,mo_b,mo_b), compact=False)
        g2e_ab = g2e_ab.reshape(norb,norb,norb,norb)
        g2e_bb = ao2mo.incore.general(mSCF._eri, (mo_b,)*4, compact=False)
        g2e_bb = g2e_bb.reshape(norb,norb,norb,norb)
        h1e = (h1e_a, h1e_b)
        eri = (g2e_aa, g2e_ab, g2e_bb)

        eci = fci.direct_uhf.kernel(h1e, eri, norb, nelec)[0]
        print_energy('FCI', eci)
        inp.timer.end('fci')

    # FCI
    elif method in ('fci'):
        ehf, mSCF = do_hf(inp)
        print_energy('RHF', ehf)

        inp.timer.start('fci')
        if inp.scf.freeze is None:
            mCI = fci.FCI(mSCF)
            if inp.scf.roots is not None:
                mCI.nroots = inp.scf.roots
            mCI.kernel()[0]
            eci = mCI.eci

        else:
            nel  = mol.nelectron - inp.scf.freeze * 2
            ncas = mol.nao_nr() - inp.scf.freeze
            if mol.spin == 0:
                nelecas = nel
                mCI = mcscf.CASCI(mSCF, ncas, nelecas)
                mCI.fcisolver = fci.solver(mol)
            else:
                if mol.spin%2 == 0:
                    nelecas = (nel//2+mol.spin//2, nel//2-mol.spin//2)
                else:
                    nelecas = (nel//2+mol.spin//2+1, nel//2-mol.spin//2)
                mCI = mcscf.CASCI(mSCF, ncas, nelecas)
                mCI.fcisolver = fci.direct_spin1.FCISolver(mol)
            eci = mCI.kernel()[0]
            dm = mCI.make_rdm1()
            dip = mSCF.dip_moment(dm=dm)

        if inp.scf.roots is None:
            print_energy('FCI', eci)
        else:
            for i in range(inp.scf.roots):
                print_energy('FCI {0}'.format(i), eci[i])
        inp.timer.end('fci')

    # CASCI
    elif method == 'casci':
        if inp.scf.cas is None and inp.scf.casorb is None:
            print ('ERROR: Must specify CAS space or CASORB')
            return inp

        ehf, mSCF = do_hf(inp)
        print_energy('RHF', ehf)

        # get cas space
        if inp.scf.cas is not None:
            if mol.spin == 0:
                nelecas = inp.scf.cas[0]
            else:
                nelecas = (inp.scf.cas[0]//2 + mol.spin//2,
                           inp.scf.cas[0]//2 - mol.spin//2)
            ncasorb = inp.scf.cas[1]
        elif inp.scf.casorb is not None:
            ncasorb = len(inp.scf.casorb)
            nelecas = int(np.sum(mSCF.mo_occ[inp.scf.casorb]))
            if inp.scf.casspin is not None:
                nelecas = (nelecas//2 + inp.scf.casspin//2,
                           nelecas//2 - inp.scf.casspin//2)

        inp.timer.start('casci')
        mCI = mcscf.CASCI(mSCF, ncasorb, nelecas)

        if inp.scf.casorb is not None:
            mo = mcscf.addons.sort_mo(mCI, np.copy(mSCF.mo_coeff), inp.scf.casorb, 0)
        else:
            mo = np.copy(mSCF.mo_coeff)

        eci = mCI.kernel(mo)[0]
        print_energy('CASCI', eci)
        inp.timer.end('casci')

    # CASSCF
    elif method == 'casscf' or method == 'ucasscf':
        if inp.scf.cas is None and inp.scf.casorb is None:
            print ('ERROR: Must specify CAS space or CASORB')
            return inp

        lunrestricted = (method == 'ucasscf')
        ehf, mSCF = do_hf(inp, unrestricted=lunrestricted)
        print_energy('HF', ehf)

        # get cas space
        if inp.scf.cas is not None:
            if mol.spin == 0:
                nelecas = inp.scf.cas[0]
            else:
                nelecas = (inp.scf.cas[0]//2 + mol.spin//2,
                           inp.scf.cas[0]//2 - mol.spin//2)
            ncasorb = inp.scf.cas[1]
        elif inp.scf.casorb is not None:
            ncasorb = len(inp.scf.casorb)
            nelecas = int(np.sum(mSCF.mo_occ[inp.scf.casorb]))
            if inp.scf.casspin is not None:
                nelecas = (nelecas//2 + inp.scf.casspin//2,
                           nelecas//2 - inp.scf.casspin//2)

        inp.timer.start('casscf')
        mCI = mcscf.CASSCF(mSCF, ncasorb, nelecas)

        if inp.scf.casorb is not None:
            mo = mcscf.addons.sort_mo(mCI, np.copy(mSCF.mo_coeff), inp.scf.casorb, 0)
        else:
            mo = np.copy(mSCF.mo_coeff)

        eci = mCI.kernel(mo)[0]
        print_energy('CASSCF', eci)
        inp.timer.end('casscf')

    # NEVPT2
    elif method == 'nevpt2' or method == 'unevpt2':
        if inp.scf.cas is None and inp.scf.casorb is None:
            print ('ERROR: Must specify CAS space or CASORB')
            return inp

        ehf, mSCF = do_hf(inp)
        print_energy('RHF', ehf)

        inp.timer.start('casscf')

        # get cas space
        if inp.scf.cas is not None:
            if mol.spin == 0:
                nelecas = inp.scf.cas[0]
            else:
                nelecas = (inp.scf.cas[0]//2 + mol.spin//2,
                           inp.scf.cas[0]//2 - mol.spin//2)
            ncasorb = inp.scf.cas[1]
        elif inp.scf.casorb is not None:
            ncasorb = len(inp.scf.casorb)
            nelecas = int(np.sum(mSCF.mo_occ[inp.scf.casorb]))
            if inp.scf.casspin is not None:
                nelecas = (nelecas//2 + inp.scf.casspin//2,
                           nelecas//2 - inp.scf.casspin//2)

        mCI = mcscf.CASSCF(mSCF, ncasorb, nelecas, frozen=inp.scf.freeze)

        if inp.scf.casorb is not None:
            mo = mcscf.addons.sort_mo(mCI, np.copy(mSCF.mo_coeff), inp.scf.casorb, 0)
        else:
            mo = np.copy(mSCF.mo_coeff)

        eci = mCI.kernel(mo)[0]
        print_energy('CASSCF', eci)
        inp.timer.end('casscf')

        inp.timer.start('nevpt2')
        mpt2 = mrpt.NEVPT(mCI)
        ept2 = mpt2.kernel() + eci
        print_energy('NEVPT2', ept2)
        inp.timer.end('nevpt2')

    else:
        print ('ERROR: Unrecognized SCF method!')
        raise SystemExit

    # dump fcidump file if needed
    if inp.fcidump:
        if inp.filename[-4:].lower() == '.inp':
            fcifile = inp.filename[:-4] + '.fcidump'
        else:
            fcifile = inp.filename + '.fcidump'
        fcidump(mSCF, filename=fcifile, tol=1e-6)

    # plot MOs if needed
    if inp.mo2cube:
        from .mo_2_cube import save_MOs
        save_MOs(inp, mSCF, mSCF.mo_coeff)

    # save molden file if needed
    if inp.molden:
        from pyscf.tools import molden
        molden_file = inp.filename[:-4] + '.molden'
        molden.from_mo(inp.mol, molden_file, mSCF.mo_coeff, ene=mSCF.mo_energy)

    # save and return
    inp.mf = mSCF
    return inp
Beispiel #20
0
# Load MF orbitals
#
chkname = "_chk/pp_neutral_dz_b3lyp.chk"
mol = chkfile.load_mol(chkname)
mol.verbose = 5
mf = dft.RKS(mol)
mf.__dict__.update(chkfile.load(chkname, "scf"))

#
# SA-MCSCF
#
nelecas, ncas = (4, 4)
n_states = 3
weights = np.ones(n_states) / n_states

mc = mcscf.CASSCF(mf, ncas, nelecas).state_average_(weights)
mc.fix_spin(ss=0)
mc.natorb = True
mc.chkfile = "_chk/pp_neutral_dz_cas_4e_4o.chk"
cas_list = [148, 149, 150, 151]
mo = mcscf.sort_mo(mc, mf.mo_coeff, cas_list)
mc.mc1step(mo)

#
# Analysis and processing
#
mc.analyze()

molden.from_mo(mol, "_molden/pp_neutral_dz_cas_4e_4o_alt.molden", mc.mo_coeff)
molden.from_mcscf(mc, "_molden/pp_neutral_dz_cas_4e_4o.molden")
Beispiel #21
0
cell.basis = 'gth-dzv'
cell.pseudo = 'gth-pade'
cell.verbose = 5
cell.build(unit='Angstrom')
mf = scf.RHF(cell)
mf.kernel()
'''
generates IAOs
'''
mo_occ = mf.mo_coeff[:, mf.mo_occ > 0]
#a = lo.iao.iao(cell, mo_occ, minao='minao')
#a = lo.iao.iao(cell, mo_occ, minao='gth-szv')
a = iao.iao(cell, mo_occ, minao='gth-szv', scf_basis=True,
            ref_basis='gth-szv')  # scf basis
print "IAO shape: ", a.shape
molden.from_mo(cell, 'diamondiao_szv.molden', a)

# Orthogonalize IAO
a = lo.vec_lowdin(a, mf.get_ovlp())
molden.from_mo(cell, 'diamondiao_szv_ortho.molden', a)

loc_obj = lo.PM(cell, a)
cost_before = loc_obj.cost_function()
print "cost function before localization: ", cost_before
loc_orb = loc_obj.kernel()
molden.from_mo(cell, 'diamondiao_szv_PM.molden', loc_orb)

#ibo must take the orthonormalized IAOs
#ibo = lo.ibo.ibo(cell, mo_occ, a)
#print "IBO shape: ", ibo.shape
#molden.from_mo(cell, 'diamondibo_szv_ibo.molden', ibo)
Beispiel #22
0
    def setup_wm_core_scf(self, fragments, calcname):

        self.restore_wm_full_scf()
        oneRDMcorr_loc = sum((frag.oneRDMas_loc for frag in fragments))
        if np.all(np.isclose(oneRDMcorr_loc, 0)):
            print("Null correlated 1-RDM; default settings for wm wvfn")
            self.activeFOCK = represent_operator_in_basis(
                self.fullFOCKao, self.ao2loc)
            self.activeJKidem = self.activeFOCK - self.activeOEI
            self.activeJKcorr = np.zeros((self.norbs_tot, self.norbs_tot))
            self.oneRDMcorr_loc = oneRDMcorr_loc
            self.loc2idem = np.eye(self.norbs_tot)
            self.nelec_idem = self.nelec_tot
            return

        loc2corr = np.concatenate([frag.loc2amo for frag in fragments], axis=1)
        loc2idem = get_complementary_states(loc2corr)
        evecs = matrix_eigen_control_options(represent_operator_in_basis(
            self.loc_oei(), loc2idem),
                                             sort_vecs=1,
                                             only_nonzero_vals=False)[1]
        loc2idem = np.dot(loc2idem, evecs)

        # I want to alter the outputs of self.loc_oei (), self.loc_rhf_fock (), and the get_wm_1RDM_etc () functions.
        # self.loc_oei ()      = P_idem * (activeOEI + JKcorr) * P_idem
        # self.loc_rhf_fock () = P_idem * (activeOEI + JKcorr + JKidem) * P_idem
        # The get_wm_1RDM_etc () functions will need to add oneRDMcorr_loc to their final return value
        # The chemical potential is so that identically zero eigenvalues from the projection into the idem space don't get confused
        # with numerically-zero eigenvalues in the idem space: all occupied orbitals must have negative energy

        # Make true output 1RDM from fragments to use as guess for wm mcscf calculation
        oneRDMguess_loc = np.zeros_like(oneRDMcorr_loc)
        for f in itertools.product(fragments, fragments):
            loc2frag = [i.loc2frag for i in f]
            oneRDMguess_loc += sum(
                (0.5 * project_operator_into_subspace(i.oneRDM_loc, *loc2frag)
                 for i in f))

        nelec_corr = np.trace(oneRDMcorr_loc)
        if is_close_to_integer(nelec_corr,
                               100 * params.num_zero_atol) == False:
            raise ValueError(
                "nelec_corr not an integer! {}".format(nelec_corr))
        nelec_idem = int(round(self.nelec_tot - nelec_corr))
        JKcorr = self.loc_rhf_jk_bis(oneRDMcorr_loc)
        oneRDMidem_loc = self.get_wm_1RDM_from_scf_on_OEI(
            self.loc_oei() + JKcorr,
            nelec=nelec_idem,
            loc2wrk=loc2idem,
            oneRDMguess_loc=oneRDMguess_loc,
            output=calcname + '_trial_wvfn.log')
        JKidem = self.loc_rhf_jk_bis(oneRDMidem_loc)
        print("trace of oneRDMcorr_loc = {}".format(np.trace(oneRDMcorr_loc)))
        print("trace of oneRDMidem_loc = {}".format(np.trace(oneRDMidem_loc)))
        print("trace of oneRDM_loc in corr basis = {}".format(
            np.trace(
                represent_operator_in_basis(
                    oneRDMcorr_loc + oneRDMidem_loc,
                    orthonormalize_a_basis(loc2corr)))))
        svals = get_overlapping_states(loc2idem, loc2corr)[2]
        print("trace of <idem|corr|idem> = {}".format(np.sum(svals * svals)))
        print(loc2corr.shape)
        print(loc2idem.shape)

        ########################################################################################################
        self.activeFOCK = self.activeOEI + JKidem + JKcorr
        self.activeJKidem = JKidem
        self.activeJKcorr = JKcorr
        self.oneRDMcorr_loc = oneRDMcorr_loc
        self.loc2idem = loc2idem
        self.nelec_idem = nelec_idem
        ########################################################################################################

        # Analysis: 1RDM and total energy
        print("Analyzing LASSCF trial wave function")
        oei = self.activeOEI + (JKcorr + JKidem) / 2
        fock = self.activeFOCK
        oneRDM = oneRDMidem_loc + oneRDMcorr_loc
        E = self.activeCONST + np.tensordot(oei, oneRDM, axes=2)
        for frag in fragments:
            if frag.norbs_as > 0:
                if frag.E2_cum == 0 and np.amax(np.abs(
                        frag.twoCDMimp_amo)) > 0:
                    V = self.dmet_tei(frag.loc2amo)
                    L = frag.twoCDMimp_amo
                    frag.E2_cum = np.tensordot(V, L, axes=4) / 2
                E += frag.E2_cum
        print("LASSCF trial wave function total energy: {:.6f}".format(E))
        self.oneRDM_loc = oneRDM
        self.e_tot = E

        # Molden
        fock_idem = represent_operator_in_basis(fock, loc2idem)
        oneRDM_corr = represent_operator_in_basis(oneRDM, loc2corr)
        idem_evecs = matrix_eigen_control_options(fock_idem,
                                                  sort_vecs=1,
                                                  only_nonzero_vals=False)[1]
        corr_evecs = matrix_eigen_control_options(oneRDM_corr,
                                                  sort_vecs=-1,
                                                  only_nonzero_vals=False)[1]
        loc2molden = np.append(np.dot(loc2idem, idem_evecs),
                               np.dot(loc2corr, corr_evecs),
                               axis=1)
        wm_ene = np.einsum('ip,ij,jp->p', loc2molden, fock, loc2molden)
        wm_ene[-loc2corr.shape[1]:] = 0
        wm_occ = np.einsum('ip,ij,jp->p', loc2molden, oneRDM, loc2molden)
        ao2molden = np.dot(self.ao2loc, loc2molden)
        molden.from_mo(self.mol,
                       calcname + '_trial_wvfn.molden',
                       ao2molden,
                       occ=wm_occ,
                       ene=wm_ene)
Beispiel #23
0
  C  3.8560    2.1213    0.1612       
  C  1.0888    2.4099    0.1396       
  C  3.0401    0.9977    0.0771       
  C  1.6565    1.1421    0.0663       
  H  3.9303    4.2734    0.3007       
  H  1.4582    4.5312    0.2815       
  H  4.9448    2.0077    0.1699       
  H  0.0000    2.5234    0.1311       
  H  3.4870    0.0000    0.0197       
  H  1.0145    0.2578    0.0000       
           ''',
    basis = 'cc-pvdz',
    symmetry = 1)

mf = scf.RHF(mol)
mf.kernel()

#
# First method is to explicit call the functions provided by molden.py
#
with open('C6H6mo.molden', 'w') as f1:
    molden.header(mol, f1)
    molden.orbital_coeff(mol, f1, mf.mo_coeff, ene=mf.mo_energy, occ=mf.mo_occ)

#
# Second method is to simply call from_mo function to write the orbitals
#
c_loc_orth = lo.orth.orth_ao(mol)
molden.from_mo(mol, 'C6H6loc.molden', c_loc_orth)

Beispiel #24
0
def get_mo_from_h5(mol, h5fname, symmetry=None):
    ''' Get MO vectors for a pyscf molecule from an h5 file written by OpenMolcas

        Args:
            mol : instance gto.mole
                Must be in the same point group as the OpenMolcas calculation,
                or set the symmetry argument
            h5fname : str
                Path to an h5 file generated by OpenMolcas containing (at
                least) groups 'BASIS_FUNCTION_IDS', 'MO_OCCUPATIONS',
                'MO_VECTORS', and 'MO_ENERGIES' and additionally 'DESYM_MATRIX'
                and 'DESYM_BASIS_FUNCTION_IDS' if symmetry is used.

        Kwargs:
            symmetry : str
                Point group of the calculation in OpenMolcas. If not provided,
                mol.groupname is used instead

        Returns:
            mo_coeff : ndarray of shape (nao_nr, nao_nr)
    '''

    if symmetry is not None:
        mol = mol.copy()
        mol.build(symmetry=symmetry)
    nao = mol.nao_nr()

    with h5py.File(h5fname, 'r') as f:
        try:
            molcas_basids = f['DESYM_BASIS_FUNCTION_IDS'][()]
            molcas_usymm = f['DESYM_MATRIX'][()].reshape(nao, nao)
        except KeyError:
            assert (not mol.symmetry
                    ), "Can't find desym_ data; mol.symmetry = {}".format(
                        mol.symmetry)
            molcas_basids = f['BASIS_FUNCTION_IDS'][()]
        molcas_coeff = f['MO_VECTORS'][()]
        mo_energy = f['MO_ENERGIES'][()]
        mo_occ = f['MO_OCCUPATIONS'][()]

    idx_ao = []
    for (c, n, l, m) in molcas_basids:
        # 0-index atom list in PySCF, 1-index atom list in Molcas
        c -= 1
        # Actual principal quantum number in PySCF, 1-indexed list in Molcas
        n += l
        # l=1, ml=(-1,0,1) is (x,y,z) in PySCF, (y,z,x) in Molcas
        if l == 1:
            m = m - 2 if m > 0 else m + 1
        idx_ao.append(mol.search_ao_nr(c, l, m, n))
    idx_ao = np.argsort(np.asarray(idx_ao))

    if mol.symmetry:
        # I have to figure out what order the Molcas irreps are in on the fly
        # because it seems to change depending on the xyz
        molcas_usymm = molcas_usymm[:, idx_ao]
        proj = np.stack([(np.dot(molcas_usymm, ir_coeff)**2).sum(1)
                         for ir_coeff in mol.symm_orb],
                        axis=0)
        errstr = ("Can't interpret h5 symmetry information; wrong mol? "
                  " <mol.symm_orb|desym_matrix> =\n{}").format(proj)
        assert (np.allclose(np.amax(proj), 1)), errstr
        ix_irrep = np.argmax(proj, axis=0)
        uniq_idx = np.sort(np.unique(ix_irrep, return_index=True)[1])
        uniq_idx = np.append(uniq_idx, len(ix_irrep))
        nmo_irrep = []
        for ix, i in enumerate(uniq_idx[:-1]):
            j = uniq_idx[ix + 1]
            assert (len(np.unique(ix_irrep[i:j])) == 1), errstr
            nmo_irrep.append(j - i)
        nmo_irrep = np.asarray(nmo_irrep)
        usymm_irrep_offset = np.cumsum(nmo_irrep) - nmo_irrep
        coeff_irrep_offset = np.cumsum(nmo_irrep**2) - nmo_irrep**2
        mo_coeff = np.zeros((nao, nao), dtype=np.float_)
        for m_ir, usymm_off, coeff_off in zip(nmo_irrep, usymm_irrep_offset,
                                              coeff_irrep_offset):
            i, j = usymm_off, usymm_off + m_ir
            u, v = coeff_off, coeff_off + (m_ir**2)
            usymm = molcas_usymm[i:j, :].T
            coeff = molcas_coeff[u:v].reshape(m_ir, m_ir).T
            mo_coeff[:, i:j] = np.dot(usymm, coeff)
    else:
        assert (molcas_coeff.shape == (
            nao**2, )), 'mo_vectors.shape = {} but {} AOs'.format(
                molcas_coeff.shape, nao)
        mo_coeff = molcas_coeff.reshape(nao, nao)[:, idx_ao].T

    # 'mergesort' keeps degenerate or active-space orbitals in the provided order!
    #  idx_ene = np.argsort (mo_energy, kind='mergesort')

    # modified by Dayou: sort by mo_occ first, then mo_energy
    sort_key = np.min(mo_energy) * 100000 * mo_occ + mo_energy
    idx_ene = np.argsort(sort_key, kind='mergesort')
    mo_coeff = mo_coeff[:, idx_ene]
    mo_occ = mo_occ[idx_ene]
    mo_energy = mo_energy[idx_ene]

    if mol.verbose > logger.INFO:
        fname = str(mol.output)[:-4] + "_h5debug.molden"
        molden.from_mo(mol, fname, mo_coeff, occ=mo_occ, ene=mo_energy)
    if mol.symmetry:  # assert (symmetry is right)
        try:
            orbsym = label_orb_symm(mol, mol.irrep_name, mol.symm_orb,
                                    mo_coeff)
        except ValueError as e:
            raise ValueError(("Problem understanding Molcas symmetry?\n"
                              "{}").format(str(e)))

    return mo_coeff
Beispiel #25
0
'''

#
# Modify the default core valence settings for Be and Al
#
# 1 s-shell as core, 1 s-shell + 1 p-shell as valence
lo.set_atom_conf('Be', ('1s', '1s1p'))
# 2 s-shells + 1 p-shell as core, 1 s-shell + 1 p-shell + 1 d-shell as valence
lo.set_atom_conf('Al', ('2s1p', '1s1p1d'))
# double-d shell for Fe, ie taking 3d and 4d orbitals as valence
lo.set_atom_conf('Fe', 'double d')
# double-d shell for Mo, ie taking 4d and 5d orbitals as valence
lo.set_atom_conf('Mo', 'double d')
# Put 3d orbital in valence space for Si
lo.set_atom_conf('Si', 'polarize')

#
# Localize Be12 ring
#
mol = gto.M(atom = [('Be', x) for x in ring.make(12, 2.4)], basis='ccpvtz')
c = lo.orth.orth_ao(mol)
molden.from_mo(mol, 'be12.molden', c)

#
# Localize Al12 ring
#
mol = gto.M(atom = [('Al', x) for x in ring.make(12, 2.4)], basis='ccpvtz')
c = lo.orth.orth_ao(mol)
molden.from_mo(mol, 'al12.molden', c)

Beispiel #26
0
C       -1.523996730     -0.592207689      0.138683275
H        0.609941801      0.564304456      1.384183068
H        1.228991034      1.489024155      0.015946420
H       -1.242251083      1.542928348      0.046243898
H       -0.662968178      0.676527364     -1.376503770
H       -0.838473936     -1.344174292      0.500629028
H       -2.075136399     -0.983173387     -0.703807608
H       -2.212637905     -0.323898759      0.926200671
O        1.368219958     -0.565620846     -0.173113101
H        2.250134219     -0.596689848      0.204857736
'''
mol.basis = 'def2-SVP'
mol.build()

# Perform a Hartree-Fock calculation
mf = RHF(mol)
mf.kernel()

# determine the number of occupied orbitals
nocc = numpy.count_nonzero(mf.mo_occ > 0)
# localize the occupied orbitals separately
lmo_occ = cholesky_mos(mf.mo_coeff[:, :nocc])
# localize the virtual orbitals separately
lmo_virt = cholesky_mos(mf.mo_coeff[:, nocc:])
# merge the MO coefficients in one matrix
lmo_merged = numpy.hstack((lmo_occ, lmo_virt))
# dump the merged MO coefficients in a molden file
filename = 'c3h7oh_cholesky.molden'
print('Dumping the orbitals in file:', filename)
molden.from_mo(mol, filename, lmo_merged, occ=mf.mo_occ)
Beispiel #27
0
C   -1.211265339156     0.699329968382     0.000000000000
C   -1.211265339156    -0.699329968382     0.000000000000
H    0.000000000000     2.491406946734     0.000000000000
H    0.000000000000    -2.491406946734     0.000000000000
H    2.157597486829     1.245660462400     0.000000000000
H    2.157597486829    -1.245660462400     0.000000000000
H   -2.157597486829     1.245660462400     0.000000000000
H   -2.157597486829    -1.245660462400     0.000000000000''',
            basis='6-31g')
mf = scf.RHF(mol)
mf.chkfile = 'benzene-631g.chk'
mf.kernel()

pz_idx = numpy.array([17, 20, 21, 22, 23, 30, 36, 41, 42, 47, 48, 49]) - 1
loc_orb = lo.Boys(mol, mf.mo_coeff[:, pz_idx]).kernel()
molden.from_mo(mol, 'benzene-631g-boys.molden', loc_orb)

import numpy
from pyscf import lib
from pyscf import tools
from pyscf.tools import mo_mapping

mol, mo_energy, mo_coeff, mo_occ, irrep_labels, spins = \
        tools.molden.load('benzene-631g-boys.molden')

comp = mo_mapping.mo_comps(
    'C.*2p[yz]',  # regular expression
    mol,
    mo_coeff)

mol = lib.chkfile.load_mol('benzene-631g.chk')
Beispiel #28
0
print (si)

# You can get the 1-RDMs of the SA-LASSCF states like this
states_casdm1s = las.states_make_casdm1s ()

# You can get the 1- and 2-RDMs of the LASSI solutions like this
roots_casdm1s, roots_casdm2s = lassi.roots_make_rdm12s (las, las.ci, si)

# No super-convenient molden API yet
# By default orbitals are state-averaged natural-orbitals at the end
# of the SA-LASSCF calculation
# But you can recanonicalize
print ("\nlasscf_state_0-3.molden: single LAS state NOs, (strictly) unentangled")
for iroot, dm1 in enumerate (states_casdm1s.sum (1)): # spin sum
    no_coeff, no_ene, no_occ = las.canonicalize (natorb_casdm1=dm1)[:3]
    molden.from_mo (las.mol, 'lasscf_state_{}.molden'.format (iroot),
        no_coeff, occ=no_occ, ene=no_ene)
print ("lassi_root_0-3.molden: LASSI eigenstate NOs, (generally) entangled")
for iroot, dm1 in enumerate (roots_casdm1s.sum (1)): # spin sum
    no_coeff, no_ene, no_occ = las.canonicalize (natorb_casdm1=dm1)[:3]
    molden.from_mo (las.mol, 'lassi_root_{}.molden'.format (iroot),
        no_coeff, occ=no_occ, ene=no_ene)

# Beware! Don't do ~~~anything~~ to the si array before you pass it to the
# function above or grab the important data from its attachments!
print ("\nSurely I can type si = si * 1 without any consequences")
si = si * 1
try:
    print ("<S**2>:",si.s2)
except AttributeError as e:
    print ("Oh no! <S**2> disappeared and all I have now is this error message:")
    print ("AttributeError:", str (e))
Beispiel #29
0
from pyscf import lo
from pyscf.tools import molden

mol = gto.M(
    atom = '''
C    0.000000000000     1.398696930758     0.000000000000
C    0.000000000000    -1.398696930758     0.000000000000
C    1.211265339156     0.699329968382     0.000000000000
C    1.211265339156    -0.699329968382     0.000000000000
C   -1.211265339156     0.699329968382     0.000000000000
C   -1.211265339156    -0.699329968382     0.000000000000
H    0.000000000000     2.491406946734     0.000000000000
H    0.000000000000    -2.491406946734     0.000000000000
H    2.157597486829     1.245660462400     0.000000000000
H    2.157597486829    -1.245660462400     0.000000000000
H   -2.157597486829     1.245660462400     0.000000000000
H   -2.157597486829    -1.245660462400     0.000000000000''',
    basis = '6-31g')
mf = scf.RHF(mol).run()

pz_idx = numpy.array([17,20,21,22,23,30,36,41,42,47,48,49])-1
loc_orb = lo.Boys(mol, mf.mo_coeff[:,pz_idx]).kernel()
molden.from_mo(mol, 'boys.molden', loc_orb)

loc_orb = lo.ER(mol, mf.mo_coeff[:,pz_idx]).kernel()
molden.from_mo(mol, 'edmiston.molden', loc_orb)

loc_orb = lo.PM(mol, mf.mo_coeff[:,pz_idx]).kernel()
molden.from_mo(mol, 'pm.molden', loc_orb)

Beispiel #30
0
#
# Author: Qiming Sun <*****@*****.**>
#

'''
TDDFT NTO analysis.
'''

from pyscf import gto, dft, tddft

mol = gto.Mole()
mol.build(
    atom = 'H 0 0 0; F 0 0 1.1',  # in Angstrom
    basis = '631g',
    symmetry = True,
)

mf = dft.RKS(mol)
mf.xc = 'b3lyp'
mf.kernel()

mytd = tddft.TDDFT(mf)
mytd.kernel()

weights_1, nto_1 = mytd.get_nto(state=1, verbose=4)
weights_2, nto_2 = mytd.get_nto(state=2, verbose=4)
weights_3, nto_3 = mytd.get_nto(state=3, verbose=4)

from pyscf.tools import molden
molden.from_mo(mol, 'nto-td-3.molden', nto_3)
Beispiel #31
0
mf = scf.RHF(mol)
mf.kernel()

#
# First method is to explicit call the functions provided by molden.py
#
with open("C6H6mo.molden", "w") as f1:
    molden.header(mol, f1)
    molden.orbital_coeff(mol, f1, mf.mo_coeff, ene=mf.mo_energy, occ=mf.mo_occ)

#
# Second method is to simply call from_mo function to write the orbitals
#
c_loc_orth = lo.orth.orth_ao(mol)
molden.from_mo(mol, "C6H6loc.molden", c_loc_orth)


#
# Molden format does not support high angular momentum basis.  To handle the
# orbitals which have l>=5 functions, a hacky way is to call molden.remove_high_l
# function.  However, the resultant orbitals may not be orthnormal.
#
mol = gto.M(atom="He 0 0 0", basis={"He": gto.expand_etbs(((0, 3, 1.0, 2.0), (5, 2, 1.0, 2.0)))})
mf = scf.RHF(mol).run()
try:
    molden.from_mo(mol, "He_without_h.molden", mf.mo_coeff)
except RuntimeError:
    print("    Found l=5 in basis.")
    molden.from_mo(mol, "He_without_h.molden", mf.mo_coeff, ignore_h=True)
Beispiel #32
0
    def setup_wm_core_scf(self, fragments, calcname):

        self.restore_wm_full_scf()
        oneRDMcorr_loc = sum((frag.oneRDMas_loc for frag in fragments))
        oneSDMcorr_loc = sum((frag.oneSDMas_loc for frag in fragments))
        if np.all(np.isclose(oneRDMcorr_loc, 0)):
            print("Null correlated 1-RDM; default settings for wm wvfn")
            self.oneRDMcorr_loc = oneRDMcorr_loc
            self.oneSDMcorr_loc = oneSDMcorr_loc
            return

        loc2corr = np.concatenate([frag.loc2amo for frag in fragments], axis=1)

        # Calculate E2_cum
        E2_cum = 0
        for frag in fragments:
            if frag.norbs_as > 0:
                if frag.E2_cum == 0 and np.amax(np.abs(
                        frag.twoCDMimp_amo)) > 0:
                    V = self.dmet_tei(frag.loc2amo)
                    L = frag.twoCDMimp_amo
                    frag.E2_cum = np.tensordot(V, L, axes=4) / 2
                    K = self.loc_rhf_k_bis(frag.oneSDMas_loc)
                    frag.E2_cum += (K * frag.oneSDMas_loc).sum() / 4
                E2_cum += frag.E2_cum

        loc2idem = get_complementary_states(loc2corr)
        test, err = are_bases_orthogonal(loc2idem, loc2corr)
        print(
            "Testing linear algebra: overlap of active and unactive orbitals = {}"
            .format(linalg.norm(err)))

        # I want to alter the outputs of self.loc_oei (), self.loc_rhf_fock (), and the get_wm_1RDM_etc () functions.
        # self.loc_oei ()      = P_idem * (activeOEI + JKcorr) * P_idem
        # self.loc_rhf_fock () = P_idem * (activeOEI + JKcorr + JKidem) * P_idem
        # The get_wm_1RDM_etc () functions will need to add oneRDMcorr_loc to their final return value
        # The chemical potential is so that identically zero eigenvalues from the projection into the idem space don't get confused
        # with numerically-zero eigenvalues in the idem space: all occupied orbitals must have negative energy

        # Make true output 1RDM from fragments to use as guess for wm mcscf calculation
        oneRDMguess_loc = np.zeros_like(oneRDMcorr_loc)
        for f in itertools.product(fragments, fragments):
            loc2frag = [i.loc2frag for i in f]
            oneRDMguess_loc += sum(
                (0.5 * project_operator_into_subspace(i.oneRDM_loc, *loc2frag)
                 for i in f))

        nelec_corr = np.trace(oneRDMcorr_loc)
        if is_close_to_integer(nelec_corr,
                               100 * params.num_zero_atol) == False:
            raise ValueError(
                "nelec_corr not an integer! {}".format(nelec_corr))
        nelec_idem = int(round(self.nelec_tot - nelec_corr))
        if nelec_idem % 2:
            raise NotImplementedError("Odd % of unactive electrons")
        JKcorr = self.loc_rhf_jk_bis(oneRDMcorr_loc)
        oei = self.activeOEI + JKcorr / 2
        vk = -self.loc_rhf_k_bis(oneSDMcorr_loc) / 2
        working_const = self.activeCONST + (oei * oneRDMcorr_loc).sum() + (
            vk * oneSDMcorr_loc).sum() / 2 + E2_cum
        oneRDMidem_loc = self.get_wm_1RDM_from_scf_on_OEI(
            self.loc_oei() + JKcorr,
            nelec=nelec_idem,
            loc2wrk=loc2idem,
            oneRDMguess_loc=oneRDMguess_loc,
            output=calcname + '_trial_wvfn.log',
            working_const=working_const)
        JKidem = self.loc_rhf_jk_bis(oneRDMidem_loc)
        print("trace of oneRDMcorr_loc = {}".format(np.trace(oneRDMcorr_loc)))
        print("trace of oneRDMidem_loc = {}".format(np.trace(oneRDMidem_loc)))
        print("trace of oneSDMcorr_loc = {}".format(np.trace(oneSDMcorr_loc)))
        print("trace of oneRDM_loc in corr basis = {}".format(
            np.trace(
                represent_operator_in_basis(oneRDMcorr_loc + oneRDMidem_loc,
                                            loc2corr))))
        svals = get_overlapping_states(loc2idem, loc2corr)[2]
        print("trace of <idem|corr|idem> = {}".format(np.sum(svals * svals)))
        print(loc2corr.shape)
        print(loc2idem.shape)
        dma_dmb = oneRDMidem_loc + oneRDMcorr_loc
        dma_dmb = [(dma_dmb + oneSDMcorr_loc) / 2,
                   (dma_dmb - oneSDMcorr_loc) / 2]
        focka_fockb = [JKcorr + vk, JKcorr - vk]
        focka_fockb = [self.activeOEI + JKidem + JK for JK in focka_fockb]
        oneRDM_loc = oneRDMidem_loc + oneRDMcorr_loc
        oneSDM_loc = oneSDMcorr_loc

        ########################################################################################################
        self.activeFOCK = get_roothaan_fock(focka_fockb, dma_dmb,
                                            np.eye(self.norbs_tot))
        self.activeJKidem = JKidem
        self.activeJKcorr = JKcorr
        self.oneRDMcorr_loc = oneRDMcorr_loc
        self.loc2idem = loc2idem
        self.nelec_idem = nelec_idem
        self.oneRDM_loc = oneRDM_loc
        self.oneSDM_loc = oneSDM_loc
        ########################################################################################################

        # Analysis: 1RDM and total energy
        print("Analyzing LASSCF trial wave function")
        jk = np.stack([JKcorr + JKidem, -self.loc_rhf_k_bis(oneSDM_loc) / 2],
                      axis=0)
        dm = np.stack([oneRDM_loc, oneSDM_loc], axis=0)
        E = self.activeCONST + (
            self.activeOEI * oneRDM_loc).sum() + (jk * dm).sum() / 2 + E2_cum
        print("LASSCF trial wave function total energy: {:.6f}".format(E))
        self.e_tot = E

        # Molden
        ao2molden, ene_no, occ_no = self.get_trial_nos(aobasis=True,
                                                       loc2wmas=loc2corr,
                                                       oneRDM_loc=oneRDM_loc,
                                                       fock=self.activeFOCK,
                                                       jmol_shift=True,
                                                       try_symmetrize=True)
        print("Writing trial wave function molden")
        molden.from_mo(self.mol,
                       calcname + '_trial_wvfn.molden',
                       ao2molden,
                       occ=occ_no,
                       ene=ene_no)