That is the purpose of the localize_init_guess function. It requires a sequence of sequence of atom numbers, and it projects the orbitals in the ncore:nocc columns into the space of those atoms' AOs. The orbitals in the range ncore:ncore+ncas_sub[0] are the first active subspace, those in the range ncore+ncas_sub[0]:ncore+sum(ncas_sub[:2]) are the second active subspace, and so on.''' frag_atom_list = (list(range(3)), list(range(7, 10))) mo_coeff = las.localize_init_guess(frag_atom_list, mf.mo_coeff) ''' Right now, this function can only (roughly) reproduce the "force_imp=False, confine_guess=True" behavior of the old orbital guess builder. I might add the complement later, but if you are doing potential energy scans or geometry optimizations I think the current implementation of pyscf.mcscf.addons.project_init_guess might actually be better.''' las.kernel(mo_coeff) print("E(dia singlet) =", las.e_tot) ## 2. Antiferromagnetic quasi-singlet #''' To change the spin projection quantum numbers of the # subspaces, instead of providing a list of nelec, provide # a list of tuples of (neleca,nelecb).''' #las = LASSCF (mf, (4,4), ((4,0),(0,4)), spin_sub=(5,5)) #las.kernel (mo_coeff) #print ("E(antiferro singlet) =", las.e_tot) # ## 2. Ferromagnetic nonet #''' If you are doing a high-spin ROHF calculation and you # initialize with optimized ROHF orbitals (WITHOUT calling the # localize_init_guess function), the class will of course # immediately recognize that the gradient is zero and
def __exit__(self, etype, value, traceback): os.chdir(self.savedPath) from mrh.examples.lasscf.c2h6n4.c2h6n4_struct import structure as struct with cd("/home/herme068/gits/mrh/examples/lasscf/c2h6n4"): mol = struct(2.0, 2.0, '6-31g', symmetry=False) mol.verbose = lib.logger.DEBUG mol.output = 'sa_lasscf_slow_ham.log' mol.build() mf = scf.RHF(mol).run() tol = 1e-6 if len(sys.argv) < 2 else float(sys.argv[1]) las = LASSCF(mf, (4, 4), (4, 4)).set(conv_tol_grad=tol) mo = las.localize_init_guess((list(range(3)), list(range(9, 12))), mo_coeff=mf.mo_coeff) las.state_average_(weights=[0.5, 0.5], spins=[[0, 0], [2, -2]]) h2eff_sub, veff = las.kernel(mo)[-2:] e_states = las.e_states ncore, ncas, nocc = las.ncore, las.ncas, las.ncore + las.ncas mo_coeff = las.mo_coeff mo_core = mo_coeff[:, :ncore] mo_cas = mo_coeff[:, ncore:nocc] e0 = las._scf.energy_nuc() + 2 * (( (las._scf.get_hcore() + veff.c / 2) @ mo_core) * mo_core).sum() h1 = mo_cas.conj().T @ (las._scf.get_hcore() + veff.c) @ mo_cas h2 = h2eff_sub[ncore:nocc].reshape(ncas * ncas, ncas * (ncas + 1) // 2) h2 = lib.numpy_helper.unpack_tril(h2).reshape(ncas, ncas, ncas, ncas) nelec_fr = [] for fcibox, nelec in zip(las.fciboxes, las.nelecas_sub): ne = sum(nelec) nelec_fr.append([
from scipy import linalg from pyscf import lib, gto, scf, dft, fci, mcscf, df from pyscf.tools import molden from c2h4n4_struct import structure as struct from mrh.my_pyscf.mcscf.lasscf_o0 import LASSCF dr_nn = 2.0 mol = struct(dr_nn, dr_nn, '6-31g', symmetry=False) mol.verbose = lib.logger.DEBUG mol.output = '/dev/null' mol.spin = 0 mol.build() mf = scf.RHF(mol).run() las = LASSCF(mf, (4, 4), ((3, 1), (1, 3)), spin_sub=(3, 3)) las.max_cycle_macro = 1 las.kernel() las.mo_coeff = np.loadtxt('test_lasci_mo.dat') las.ci = [[np.loadtxt('test_lasci_ci0.dat')], [-np.loadtxt('test_lasci_ci1.dat').T]] ugg = las.get_ugg() h_op = las.get_hop(ugg=ugg) nmo, ncore, nocc = h_op.nmo, h_op.ncore, h_op.nocc np.random.seed(0) x = np.random.rand(ugg.nvar_tot) offs_ci1 = ugg.nvar_orb offs_ci2 = offs_ci1 + np.squeeze(ugg.ncsf_sub)[0] xorb, xci = ugg.unpack(x) xci0 = [[ np.zeros(16), ], [ np.zeros(16),
norb_f = (4,4) nelec_f = ((2,2),(2,2)) mol = structure (0.0, 0.0, output='c4h6_equil_631g.log', verbose=logger.DEBUG) mf = scf.RHF (mol).run () # CASSCF (for orbital initialization) mc = mcscf.CASSCF (mf, norb, nelec).set (fcisolver = csf_solver (mol, smult=1)) mo_coeff = mc.sort_mo ([11,12,14,15,16,17,21,24]) mc.kernel (mo_coeff) mo_coeff = mc.mo_coeff.copy () # LASSCF (for comparison) las = LASSCF (mf, norb_f, nelec_f, spin_sub=(1,1)).set (mo_coeff=mo_coeff) mo_loc = las.localize_init_guess ([[0,1,2,3,4],[5,6,7,8,9]]) ncore, ncas, nmo = las.ncore, las.ncas, mo_coeff.shape[1] e_las = las.kernel (mo_loc)[0] #mo_loc = las.localize_init_guess ([[0,1,2,3,4],[5,6,7,8,9]], # freeze_cas_spaces=True) mo_loc = las.mo_coeff.copy () molden.from_lasscf (las, 'c4h6_equil_lasscf88_631g.molden') # CASCI (for comparison) mc = mcscf.CASCI (mf, 8, 8).set (mo_coeff = mo_loc, fcisolver = csf_solver (mol, smult=1)).run () e_cas = mc.e_tot molden.from_mcscf (mc, 'c4h6_equil_casci88_631g.molden', cas_natorb=True) # LASUCCSD ucc = mcscf.CASCI (mf, 8, 8).set (fcisolver = lasucc (mol)) ucc.fcisolver.norb_f = [4,4] try:
def test_ferro_df(self): las = LASSCF(mf_hs_df, (4, 4), ((4, 0), (4, 0)), spin_sub=(5, 5)) mo_coeff = las.localize_init_guess(frags) las.kernel(mo_coeff) self.assertAlmostEqual(las.e_tot, mf_hs_df.e_tot, 7)
def test_af_df(self): las = LASSCF(mf_hs_df, (4, 4), ((4, 0), (0, 4)), spin_sub=(5, 5)) mo_coeff = las.localize_init_guess(frags) las.kernel(mo_coeff) self.assertAlmostEqual(las.e_tot, -295.4466638852035, 7)
def test_dia_df(self): las = LASSCF(mf_df, (4, 4), (4, 4), spin_sub=(1, 1)) mo_coeff = las.localize_init_guess(frags) las.kernel(mo_coeff) self.assertAlmostEqual(las.e_tot, -295.44716017803967, 7)
def test_dia(self): las = LASSCF(mf, (4, 4), (4, 4), spin_sub=(1, 1)) mo_coeff = las.localize_init_guess(frags) las.kernel(mo_coeff) self.assertAlmostEqual(las.e_tot, -295.44779578419946, 7)
from pyscf import gto, scf, mcscf from pyscf.fci import direct_spin1 from mrh.my_pyscf.mcscf.lasscf_o0 import LASSCF from mrh.exploratory.unitary_cc import lasuccsd from mrh.exploratory.citools import lasci_ominus1, fockspace import unittest xyz = '''H 0.0 0.0 0.0 H 1.0 0.0 0.0 H 0.2 3.9 0.1 H 1.159166 4.1 -0.1''' mol = gto.M (atom = xyz, basis = 'sto-3g', output='/dev/null', verbose=0) mf = scf.RHF (mol).run () ref = mcscf.CASSCF (mf, 4, 4).run () # = FCI las = LASSCF (mf, (2,2), (2,2), spin_sub=(1,1)) las.kernel (las.localize_init_guess (((0,1), (2,3)), mf.mo_coeff)) def tearDownModule(): global mol, mf, ref, las mol.stdout.close () del mol, mf, ref, las class KnownValues(unittest.TestCase): def test_lasci_ominus1 (self): mc = mcscf.CASCI (mf, 4, 4) mc.mo_coeff = las.mo_coeff mc.fcisolver = lasci_ominus1.FCISolver (mol) mc.fcisolver.norb_f = [2,2] mc.kernel () self.assertAlmostEqual (mc.e_tot, las.e_tot, 6)
# "Spins" is neleca - nelecb (= 2m for the sake of being an integer) # "Smults" is the desired local spin quantum *MULTIPLICITY* (2s+1) # "Wfnsyms" can also be the names of the irreps but I got lazy # "Charges" modifies the number of electrons in ncas_sub (third argument of LASSCF constructor) # For fragment i in state j: # neleca = (sum(las.ncas_sub[i]) - charges[j][i] + spins[j][i]) / 2 # nelecb = (sum(las.ncas_sub[i]) - charges[j][i] - spins[j][i]) / 2 # If your molecule doesn't have point-group symmetry turned on then don't pass "wfnsyms" las = LASSCF (mf, (5,5), ((3,2),(2,3))) las = las.state_average ([0.5,0.5,0.0,0.0], spins=[[1,-1],[-1,1],[0,0],[0,0]], smults=[[2,2],[2,2],[1,1],[1,1]], charges=[[0,0],[0,0],[-1,1],[1,-1]], wfnsyms=[[1,1],[1,1],[0,0],[0,0]]) mo_loc = las.localize_init_guess ((list (range (5)), list (range (5,10))), mf.mo_coeff) las.kernel (mo_loc) print ("\n---SA-LASSCF---") print ("Energy:", las.e_states) # For now, the LASSI diagonalizer is just a post-hoc function call # It returns eigenvalues (energies) in the first position and # eigenvectors (here, a 4-by-4 vector) e_roots, si = las.lassi () # Symmetry information about the LASSI solutions is "tagged" on the si array # Additionally, since spin contamination sometimes happens, the S**2 operator # in the LAS-state "diabatic" basis is also available print ("S**2 operator:\n", si.s2_mat) print ("\n---LASSI solutions---") print ("Energy:", e_roots) print ("<S**2>:",si.s2)
import numpy as np from pyscf import gto, scf, tools from c2h6n4_struct import structure as struct from mrh.my_pyscf.mcscf.lasscf_o0 import LASSCF rnn0 = 1.23681571 mol = struct(3.0, 3.0, '6-31g', symmetry=False) mf = scf.RHF(mol).run() las = LASSCF(mf, (4, 4), (4, 4), spin_sub=(1, 1)) frag_atom_list = (list(range(3)), list(range(9, 12))) mo0 = las.localize_init_guess(frag_atom_list) las.kernel(mo0) las_scanner = las.as_scanner() pes = np.loadtxt('c2h6n4_pes_old.dat')[:34, :] pes = np.hstack((pes, np.zeros((34, 1)))) pes[33, 3] = las.e_tot # ISN'T THIS SO MUCH BETTER RIDDHISH????? for ix, dr_nn in enumerate(np.arange(2.9, -0.301, -0.1)): mol1 = struct(dr_nn, dr_nn, '6-31g', symmetry=False) pes[32 - ix, 3] = las_scanner(mol1) print(" r_NN {:>11s} {:>13s} {:>13s}".format("CASSCF", "vLASSCF(v1)", "vLASSCF(test)")) for row in pes: print(" {:5.3f} {:11.6f} {:13.8f} {:13.8f}".format(*row))