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_testing 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) np.random.seed(0) x = np.random.rand(ugg.nvar_tot) def tearDownModule(): global mol, mf, las, ugg, h_op, x mol.stdout.close() del mol, mf, las, ugg, h_op, x
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
import numpy as np from pyscf import gto, scf, tools from c2h6n4_struct import structure as struct from mrh.my_pyscf.mcscf.lasscf_testing 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))
def test_symm_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_symm (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)
# The first positional argument of "state_average" is the orbital weighting function # Note that there are four states and two fragments and the weights sum to 1 # "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" should be self-explanatory # 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)
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_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)