def get_gap(gs, es, fnal): e0 = mcpdft.CASSCF(gs._scf, fnal, gs.ncas, gs.nelecas, grids_level=9).set(fcisolver=gs.fcisolver, conv_tol=1e-10).kernel( gs.mo_coeff, gs.ci)[0] e1 = mcpdft.CASSCF(es._scf, fnal, es.ncas, es.nelecas, grids_level=9).set(fcisolver=es.fcisolver, conv_tol=1e-10).kernel( es.mo_coeff, es.ci)[0] return (e1 - e0) * 27.2114
def test_molgrad (otxc): mc = mcpdft.CASSCF (mf, otxc, 6, 6).set (conv_tol=1e-10).run ().as_scanner () mc_grad = mc.nuc_grad_method ().run () de_an = (mc_grad.de[1,0]-mc_grad.de[0,0])/2 de_num = (mc (N2_xyz (1.601)) - mc (N2_xyz (1.599)))*lib.param.BOHR/0.002 print (otxc, "Numeric gradient:", de_num) print (otxc, "Analytical gradient:", de_an) print (otxc, "Gradient error:", de_an-de_num)
def get_mc_ref(mol, ri=False, sa2=False): mf = scf.RHF(mol) if ri: mf = mf.density_fit(auxbasis=df.aug_etb(mol)) mc = mcpdft.CASSCF(mf.run(), 'tPBE', 6, 6, grids_level=6) if sa2: fcisolvers = [csf_solver(mol, smult=((2 * i) + 1)) for i in (0, 1)] if mol.symmetry: fcisolvers[0].wfnsym = 'A1' fcisolvers[1].wfnsym = 'A2' mc = mc.state_average_mix_(fcisolvers, [0.5, 0.5]) ref = np.load('h2co_sa2_tpbe66_631g_grad_num.npy').reshape(2, 2, 4, 3)[int(ri)] else: ref = np.load('h2co_tpbe66_631g_grad_num.npy')[int(ri)] return mc.run(), ref
def get_mc_ref(mol, ri=False, sa2=False): mf = scf.RHF(mol) # if ri: mf = mf.density_fit (auxbasis = df.aug_etb (mol)) mc = mcpdft.CASSCF(mf.run(), 'tPBE', 6, 6, grids_level=9) # if sa2: # fcisolvers = [csf_solver (mol, smult=((2*i)+1)) for i in (0,1)] # if mol.symmetry: # fcisolvers[0].wfnsym = 'A1' # fcisolvers[1].wfnsym = 'A2' # mc = mc.state_average_mix_(fcisolvers, [0.5,0.5]) # ref = np.load ('h2co_sa2_tpbe66_631g_grad_num.npy').reshape (2,2,4,3)[int(ri)] # else: # ref = np.load ('h2co_tpbe66_631g_grad_num.npy')[int(ri)] #this refernce is obtained by mcpdft numerical differentiation in pyscf #using central differences with a second order accuracy and step size of 1e-4 ref = np.load('h2co_tpbe66_631g_edipole_num.npy')[int(ri)] return mc.run(), ref
def test_densgrad (otxc): # throat-clearing mc = mcpdft.CASSCF (mf, otxc, 6, 6).set (conv_tol=1e-10).run ().as_scanner () ncore, ncas = mc.ncore, mc.ncas nocc, nao = ncore + ncas, mc.mol.nao_nr () mo_coeff = mc.mo_coeff mo_core = mc.mo_coeff[:,:ncore] mo_cas = mc.mo_coeff[:,ncore:nocc] ot = mc.otfnal if ot.grids.coords is None: ot.grids.build(with_non0tab=True) ngrids = ot.grids.coords.shape[0] ni = ot._numint dens_deriv = ot.dens_deriv def get_dens (d1, d2): make_rho, nset, nao = ni._gen_rho_evaluator (ot.mol, d1, 1) for ao, mask, weight, coords in ni.block_loop (ot.mol, ot.grids, nao, ot.dens_deriv, mc.max_memory, blksize=ngrids): rho = np.asarray ([make_rho (i, ao, mask, ot.xctype) for i in range(2)]) Pi = get_ontop_pair_density (ot, rho, ao, d1, d2, mo_cas, ot.dens_deriv, mask) return rho, Pi, weight # densities and potentials for the wave function dm1s, dm2s = mc.fcisolver.make_rdm12s (mc.ci, mc.ncas, mc.nelecas) dm1 = dm1s[0] + dm1s[1] dm2 = dm2s[0] + dm2s[1] + dm2s[1].transpose (2,3,0,1) + dm2s[2] dm2 -= np.multiply.outer (dm1, dm1) dm2 += np.multiply.outer (dm1s[0], dm1s[0]).transpose (0,3,2,1) dm2 += np.multiply.outer (dm1s[1], dm1s[1]).transpose (0,3,2,1) dm1s = [(mo_core @ mo_core.T) + (mo_cas @ d @ mo_cas.T) for d in dm1s] rho0, Pi0, weight = get_dens (dm1s, dm2) eot0, vot0, fot0 = ot.eval_ot (rho0, Pi0, dderiv=2, weights=weight) vrho0, vPi0 = vot0 # Perturbed densities ddm1s = np.zeros ((2,nao,nao), dtype = dm1s[0].dtype) ddm1s[:,ncore:,:nocc] = 0.0001 ddm1s += ddm1s.transpose (0,2,1) ddm1s = [mo_coeff @ d @ mo_coeff.T for d in ddm1s] ddm2 = np.ones_like (dm2) / 10000 ddm2[:3,:,:,:] *= -1 rhoD, PiD = get_dens (ddm1s, ddm2)[:2] def sector (rhoT, PiT): # Evaluate energy and potential at dens0 + densD = dens1 rho1 = rho0 + rhoT Pi1 = Pi0 + PiT eot1 = ot.eval_ot (rho1, Pi1, weights=weight)[0] eotD = eot1 - eot0 vot1 = contract_fot (ot, fot0, rho0.sum (0), Pi0, rhoT.sum (0), PiT) # Polynomial expansion if PiT.ndim == 1: PiT = PiT[None,:] nPi = min (PiT.shape[0], vPi0.shape[0]) vrho = vrho0# + vot1[0] vPi = vPi0# + vot1[1] eotD_lin = (vrho*rhoT.sum (0)).sum (0) + (vPi[:nPi]*PiT[:nPi]).sum (0) E = np.dot (eot0, weight) dE_num = np.dot (eotD, weight) dE_lin = np.dot (eotD_lin, weight) eotD_quad = (vot1[0]*rhoT.sum (0)).sum (0) + (vot1[1][:nPi]*PiT[:nPi]).sum (0) dE_quad = np.dot (eotD_quad, weight) / 2 # Taylor series!!! return dE_num, dE_lin, dE_quad rhoT, PiT = np.zeros_like (rhoD), np.zeros_like (PiD) if rhoT.ndim > 2: rhoT[:,0,:] = rhoD[:,0,:] else: rhoT[:] = rhoD[:] num, lin, quad = sector (rhoT, PiT) rho_rat = (lin-num)/num rho2_rat = (lin+quad-num)/num rhoT[:] = PiT[:] = 0.0 if PiT.ndim > 1: PiT[0,:] = PiD[0,:] else: PiT[:] = PiD[:] num, lin, quad = sector (rhoT, PiT) Pi_rat = (lin-num)/num Pi2_rat = (lin+quad-num)/num rhoT[:] = PiT[:] = 0.0 if rhoT.ndim > 2: rhoT[:,1:4,:] = rhoD[:,1:4,:] num, lin, quad = sector (rhoT, PiT) rhop_rat = (lin-num)/num rhop2_rat = (lin+quad-num)/num else: rhop_rat = rhop2_rat = 0.0 rhoT[:] = PiT[:] = 0.0 if PiT.ndim > 1 and vPi0.shape[0] > 1: PiT[1:4,:] = PiD[1:4,:] num, lin, quad = sector (rhoT, PiT) Pip_rat = (lin-num)/num Pip2_rat = (lin+quad-num)/num else: Pip_rat = Pip2_rat = 0.0 print (("{:>8s} " + ' '.join (['{:8.5f}',]*8)).format (otxc, rho_rat, rho2_rat, Pi_rat, Pi2_rat, rhop_rat, rhop2_rat, Pip_rat, Pip2_rat))
print("tHCH = {:.2f} degrees".format(bond_angle(carts, 3, 0, 2))) print("eta = {:.2f} degrees".format(out_of_plane_angle(carts, 0, 2, 3, 1))) # Energy calculation at initial geometry h2co_casscf66_631g_xyz = '''C 0.534004 0.000000 0.000000 O -0.676110 0.000000 0.000000 H 1.102430 0.000000 0.920125 H 1.102430 0.000000 -0.920125''' mol = gto.M(atom=h2co_casscf66_631g_xyz, basis='6-31g', symmetry=False, verbose=logger.INFO, output='h2co_sa2_tpbe66_631g_opt0.log') mf = scf.RHF(mol).run() mc = mcpdft.CASSCF(mf, 'tPBE', 6, 6, grids_level=9) mc.fcisolver = csf_solver(mol, smult=1) mc.state_average_([0.5, 0.5]) mc.kernel() # Geometry optimization (my_call is optional; it just prints the geometry in internal coordinates every iteration) print("Initial geometry: ") h2co_geom_analysis(mol.atom_coords() * BOHR) print("Initial energy: {:.8e}".format(mc.e_states[0])) def my_call(env): carts = env['mol'].atom_coords() * BOHR h2co_geom_analysis(carts)
'convergence_drms': 1.0e-4, # Angstrom 'convergence_dmax': 1.5e-4, # Angstrom } lib.logger.TIMER_LEVEL = lib.logger.INFO h2co_casscf66_631g_xyz = '''C 0.534004 0.000000 0.000000 O -0.676110 0.000000 0.000000 H 1.102430 0.000000 0.920125 H 1.102430 0.000000 -0.920125''' mol = gto.M(atom=h2co_casscf66_631g_xyz, basis='6-31g', symmetry=False, verbose=lib.logger.INFO, output='h2co_sa2_tpbe66_631g_grad.log') mf_conv = scf.RHF(mol).run() mc_conv = mcpdft.CASSCF(mf_conv, 'tPBE', 6, 6, grids_level=6) mc_conv.fcisolver = csf_solver(mol, smult=1) mc_conv = mc_conv.state_average_([0.5, 0.5]) mc_conv.conv_tol = 1e-10 mc_conv.kernel() mf = scf.RHF(mol).density_fit(auxbasis=df.aug_etb(mol)).run() mc_df = mcpdft.CASSCF(mf, 'tPBE', 6, 6, grids_level=6) mc_df.fcisolver = csf_solver(mol, smult=1) mc_df = mc_df.state_average_([0.5, 0.5]) mc_df.conv_tol = 1e-10 mc_df.kernel() try: de_num = np.load('h2co_sa2_tpbe66_631g_grad_num.npy') de_conv_0_num, de_conv_1_num, de_df_0_num, de_df_1_num = list(de_num)
denom[np.abs(dg_ref)<1e-8] = 1.0 dg_err /= denom fmt_str = ' '.join (['{:10.3e}',]*hop.nmo) print ("dg_test:") for row in hop.unpack_uniq_var (dg_test): print (fmt_str.format (*row)) print ("dg_ref:") for row in hop.unpack_uniq_var (dg_ref): print (fmt_str.format (*row)) fmt_str = ' '.join (['{:6.2f}',]*hop.nmo) print ("dg_err (relative):") for row in hop.unpack_uniq_var (dg_err): print (fmt_str.format (*row)) print ("") from mrh.my_pyscf.tools import molden for nelecas, lbl in zip ((2, (2,0)), ('Singlet','Triplet')): #if nelecas is not 2: continue print (lbl,'case\n') for fnal in 'LDA,VWN3', 'PBE': ks = dft.RKS (mol).set (xc=fnal).run () print ("H2 {} energy:".format (fnal),ks.e_tot) exc_hop = ExcOrbitalHessianOperator (ks) debug_hess (exc_hop) for fnal in 'tLDA,VWN3', 'ftLDA,VWN3', 'tPBE': #if fnal[:2] != 'ft': continue mc = mcpdft.CASSCF (mf, fnal, 2, nelecas).run () mc.canonicalize_(cas_natorb=True) molden.from_mcscf (mc, lbl + '.molden') print ("H2 {} energy:".format (fnal),mc.e_tot) eot_hop = EotOrbitalHessianOperator (mc, incl_d2rho=True) debug_hess (eot_hop) print ("")
idx_h0_1s = mol.search_ao_label ('0 H 1s')[0] idx_h1_1s = mol.search_ao_label ('1 H 1s')[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
# comply with return signature dg_a = dg[ncore:nocc] dg_c = dg[:ncore, ncore:] return dg_a, dg_c if __name__ == '__main__': from pyscf import gto, scf from mrh.my_pyscf import mcpdft mol = gto.M(atom='H 0 0 0; H 1.2 0 0', basis='6-31g', verbose=lib.logger.DEBUG, output='orb_scf.log') mf = scf.RHF(mol).run() mc = mcpdft.CASSCF(mf, 'tPBE', 2, 2, grids_level=9).run() print("Ordinary H2 tPBE energy:", mc.e_tot) nao, nmo = mc.mo_coeff.shape ncore, ncas, nelecas = mc.ncore, mc.ncas, mc.nelecas nocc = ncore + ncas casdm1, casdm2 = mc.fcisolver.make_rdm12(mc.ci, ncas, nelecas) mc.update_jk_in_ah = mc1step_update_jk_in_ah g_orb, gorb_update, h_op, h_diag = mc1step_gen_g_hop( mc, mc.mo_coeff, 1, casdm1, casdm2, None) print("g_orb:", g_orb) print("gorb_update (1,mc.ci):", gorb_update(1, mc.ci)) print("h_op(0):", h_op(np.zeros_like(g_orb))) print("h_diag:", h_diag)
# code in this block will only execute if you run this python script as the # input directly: "python cmspdft3.py". from pyscf import scf from mrh.my_pyscf.tools import molden # My version is better for MC-SCF from mrh.my_pyscf.fci import csf_solver xyz = '''O 0.00000000 0.08111156 0.00000000 H 0.78620605 0.66349738 0.00000000 H -0.78620605 0.66349738 0.00000000''' mol = gto.M(atom=xyz, basis='sto-3g', symmetry=False, output='cmspdft3.log', verbose=lib.logger.DEBUG) mf = scf.RHF(mol).run() mc = mcpdft.CASSCF(mf, 'tPBE', 4, 4).set(fcisolver=csf_solver(mol, 1)) mc = mc.state_average([ 1.0 / 3, ] * 3).run() molden.from_sa_mcscf(mc, 'h2o_sapdft_sa.molden', cas_natorb=True) # ^ molden file with state-averaged NOs for i in range(3): fname = 'h2o_sapdft_ref{}.molden'.format(i) # ^ molden file with ith reference state NOs molden.from_sa_mcscf(mc, fname, state=i, cas_natorb=True) conv, E_int, ci_int = kernel(mc, 3) print("The iteration did{} converge".format((' not', '')[int(conv)])) print("The intermediate-state energies are", E_int) print(("Molden files with intermediate-state NOs are in " "h2o_sapdft_int?.molden"))
fci = ci.CISD(mf).run().as_scanner() # 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)