def _run_psi4(self, options: dict, method=None, return_wfn=True, point_group=None, filename: str = None, guess_wfn=None, ref_wfn=None, *args, **kwargs): psi4.core.clean() if self.active_space and not self.active_space.psi4_representable: print("Warning: Active space is not Psi4 representable") if "threads" in kwargs: psi4.set_num_threads(nthread=kwargs["threads"]) if filename is None: filename = "{}_{}.out".format(self.parameters.filename, method) psi4.core.set_output_file(filename) # easier guess read in if guess_wfn is not None: if isinstance(guess_wfn, QuantumChemistryPsi4): guess_wfn = guess_wfn.logs["hf"].wfn if isinstance(guess_wfn, str): guess_wfn = psi4.core.Wavefunction.from_file(guess_wfn) guess_wfn.to_file(guess_wfn.get_scratch_filename(180)) # this is necessary options["guess"] = "read" # prevent known flaws if "guess" in options and options["guess"].lower() == "read": options["basis_guess"] = False # additionally the outputfile needs to be the same # as in the previous guess # this can not be determined here # better pass down a guess_wfn mol = psi4.geometry(self.parameters.get_geometry_string()) mol.set_multiplicity(self.parameters.multiplicity) if self.parameters.multiplicity != 1: raise TequilaPsi4Exception("Multiplicity != 1 no yet supported") mol.set_molecular_charge(self.parameters.charge) if point_group is not None: mol.reset_point_group(point_group.lower()) if ref_wfn is None and hasattr(self, "ref_wfn"): ref_wfn = self.ref_wfn if point_group is not None and point_group.lower() == "c1": ref_wfn = None # ref_wfn.c1_deep_copy(ref_wfn.basisset()) # CC will not converge otherwise guess_wfn = None psi4.activate(mol) psi4.set_options(options) if ref_wfn is None or method.lower() == "hf": energy, wfn = psi4.energy(name=method.lower(), return_wfn=return_wfn, molecule=mol) else: energy, wfn = psi4.energy(name=method.lower(), ref_wfn=ref_wfn, return_wfn=return_wfn, molecule=mol, guess_wfn=guess_wfn) self.energies[method.lower()] = energy self.logs[method.lower()] = Psi4Results(filename=filename, variables=copy.deepcopy(psi4.core.variables()), wfn=wfn, mol=mol) return energy, wfn
def v2rdm_psi4(): mol = psi4.geometry(""" 0 1 b h 1 1.1 """) psi4.set_options({ 'basis': 'sto-3g', 'scf_type': 'out_of_core', 'd_convergence': 1e-10, 'maxiter': 500, }) psi4.set_module_options('hilbert', { #'sdp_solver': 'rrsdp', 'positivity': 'dqg', 'r_convergence': 1e-5, 'e_convergence': 1e-4, 'maxiter': 20000, }) psi4.activate(mol) # get scf wfn scf_energy,ref_wfn = psi4.energy('scf',return_wfn=True) # grab options object options = psi4.core.get_options() options.set_current_module('HILBERT') v2rdm_psi4 = hilbert.v2RDMHelper(ref_wfn,options) current_energy = v2rdm_psi4.compute_energy() return current_energy, mol.nuclear_repulsion_energy()
def __init__(self, parameters: ParametersQC, transformation: typing.Union[str, typing.Callable] = None, active_orbitals=None, reference=None, *args, **kwargs): """ Parameters ---------- parameters transformation active_orbitals: dictionary : dictionary with irreps as keys and a list of integers as values i.e. occ = {"A1":[0,1], "A2":[0]} means the occupied active space is made up of spatial orbitals 0A1, 1A1 and 0A2 as list: Give a list of spatial orbital indices i.e. occ = [0,1,3] means that spatial orbital 0, 1 and 3 are used reference: (Default value=None) List of orbitals which form the reference Can be given in the same format as active_orbitals If given as None then the first N_electron/2 orbitals are taken and the corresponding active orbitals are removed args kwargs """ self.psi4_mol = psi4.geometry(parameters.get_geometry_string()) psi4.activate(self.psi4_mol) self.energies = {} # history to avoid recomputation self.logs = {} # store full psi4 output self.active_space = None # will be assigned in super # active space will be formed later super().__init__(parameters=parameters, transformation=transformation, active_orbitals=None, reference=None, *args, **kwargs) self.ref_energy = self.molecule.hf_energy self.ref_wfn = self.logs['hf'].wfn self.irreps = [self.psi4_mol.point_group().char_table().gamma(i).symbol().upper() for i in range(self.nirrep)] oenergies = [] for i in self.irreps: oenergies += [(i, j, x) for j, x in enumerate(self.orbital_energies(irrep=i))] oenergies = sorted(oenergies, key=lambda x: x[2]) self.orbitals = [self.OrbitalData(irrep=data[0], idx_irrep=data[1], idx_total=i, energy=data[2]) for i, data in enumerate(oenergies)] orbitals_by_irrep = {o.irrep: [] for o in self.orbitals} for o in self.orbitals: orbitals_by_irrep[o.irrep] += [o] self.orbitals_by_irrep = orbitals_by_irrep if active_orbitals is not None: self.active_space = self._make_psi4_active_space_data(active_orbitals=active_orbitals, reference=reference) # need to recompute # (psi4 won't take over active space information otherwise) self.compute_energy(method="hf", recompute=True) self.ref_wfn = self.logs["hf"].wfn
def test_v2rdm_casscf(): """v2rdm_casscf/tests/v2rdm1""" #! cc-pvdz N2 (6,6) active space Test DQG print( ' N2 / cc-pVDZ / DQG(6,6), scf_type = CD / 1e-12, rNN = 0.5 A') import v2rdm_casscf n2 = psi4.geometry(""" 0 1 n n 1 r """) interloper = psi4.geometry(""" 0 1 O H 1 1.0 H 1 1.0 2 90.0 """) psi4.set_options({ 'basis': 'cc-pvdz', 'scf_type': 'cd', 'cholesky_tolerance': 1e-12, 'd_convergence': 1e-10, 'maxiter': 500, 'restricted_docc': [2, 0, 0, 0, 0, 2, 0, 0], 'active': [1, 0, 1, 1, 0, 1, 1, 1], }) psi4.set_module_options( 'v2rdm_casscf', { 'positivity': 'dqg', 'r_convergence': 1e-5, 'e_convergence': 1e-6, 'maxiter': 20000, #'orbopt_frequency': 1000, #'mu_update_frequency': 1000, }) psi4.activate(n2) n2.r = 0.5 * 0.52917721067 / 0.52917720859 refscf = -103.04337420425350 refv2rdm = -103.086205379481 psi4.energy('v2rdm-casscf', molecule=n2) assert psi4.compare_values(refscf, psi4.variable("SCF TOTAL ENERGY"), 8, "SCF total energy") assert psi4.compare_values(refv2rdm, psi4.variable("CURRENT ENERGY"), 5, "v2RDM-CASSCF total energy")
def test_v2rdm_casscf(): """v2rdm_casscf/tests/v2rdm1""" #! cc-pvdz N2 (6,6) active space Test DQG print(' N2 / cc-pVDZ / DQG(6,6), scf_type = CD / 1e-12, rNN = 0.5 A') import v2rdm_casscf n2 = psi4.geometry(""" 0 1 n n 1 r """) interloper = psi4.geometry(""" 0 1 O H 1 1.0 H 1 1.0 2 90.0 """) psi4.set_options({ 'basis': 'cc-pvdz', 'scf_type': 'cd', 'cholesky_tolerance': 1e-12, 'd_convergence': 1e-10, 'maxiter': 500, 'restricted_docc': [ 2, 0, 0, 0, 0, 2, 0, 0 ], 'active': [ 1, 0, 1, 1, 0, 1, 1, 1 ], }) ##psi4.set_module_options('v2rdm_casscf', { psi4.set_options({ # 'positivity': 'dqg', 'r_convergence': 1e-5, 'e_convergence': 1e-6, 'maxiter': 20000, # #'orbopt_frequency': 1000, # #'mu_update_frequency': 1000, }) psi4.activate(n2) n2.r = 0.5 refscf = -103.04337420425350 refv2rdm = -103.086205379481 psi4.energy('v2rdm-casscf', molecule=n2) assert psi4.compare_values(refscf, psi4.get_variable("SCF TOTAL ENERGY"), 8, "SCF total energy") assert psi4.compare_values(refv2rdm, psi4.get_variable("CURRENT ENERGY"), 5, "v2RDM-CASSCF total energy")
def test_v2rdm6(): #! cc-pvdz N2 (6,6) active space Test DQG print(' N2 / cc-pVDZ / DQG(6,6), geometry optimization') import psi4 n2 = psi4.geometry(""" 0 1 n n 1 1.1 """) psi4.set_options({ 'basis': 'cc-pvdz', 'scf_type': 'pk', 'd_convergence': 1e-10, 'maxiter': 500, 'restricted_docc': [2, 0, 0, 0, 0, 2, 0, 0], 'active': [1, 0, 1, 1, 0, 1, 1, 1], }) psi4.set_module_options( 'v2rdm_casscf', { 'positivity': 'dqg', #'r_convergence': 1e-7, 'r_convergence': 1e-6, 'e_convergence': 1e-5, 'orbopt_gradient_convergence': 1e-8, 'maxiter': 20000, }) psi4.activate(n2) psi4.optimize('v2rdm-casscf') refnuc = 23.1968666562054260 refscf = -108.95016246035139 refv2rdm = -109.095505119442 assert psi4.compare_values(refnuc, n2.nuclear_repulsion_energy(), 4, "Nuclear repulsion energy") assert psi4.compare_values(refscf, psi4.variable("SCF TOTAL ENERGY"), 5, "SCF total energy") assert psi4.compare_values(refv2rdm, psi4.variable("CURRENT ENERGY"), 4, "v2RDM-CASSCF total energy")
def test_v2rdm(): #! cc-pvdz N2 (6,6) active space Test DQG print(' N2 / cc-pVDZ / DQG(6,6), scf_type = DF, rNN = 1.1 A') import psi4 import sys sys.path.insert(0, '../..') import hilbert n2 = psi4.geometry(""" 0 1 n n 1 r """) psi4.set_options({ 'basis': 'cc-pvdz', 'scf_type': 'df', 'd_convergence': 1e-10, 'maxiter': 500, 'restricted_docc': [2, 0, 0, 0, 0, 2, 0, 0], 'active': [1, 0, 1, 1, 0, 1, 1, 1], }) psi4.set_module_options( 'hilbert', { 'positivity': 'dqg', 'r_convergence': 1e-5, 'e_convergence': 1e-6, 'maxiter': 20000, }) psi4.activate(n2) n2.r = 1.1 refscf = -108.95348837831371 refv2rdm = -109.094404909477 psi4.energy('v2rdm-casscf') assert psi4.compare_values(refscf, psi4.variable("SCF TOTAL ENERGY"), 8, "SCF total energy") assert psi4.compare_values(refv2rdm, psi4.variable("CURRENT ENERGY"), 5, "v2RDM-CASSCF total energy")
def test_v2rdm8(): # H2 / cc-pVDZ / D(2,2), scf_type = DF, rHH = 1.0 A print(' H2 / cc-pVDZ / D(2,2), scf_type = DF, rHH = 1.0 A') import v2rdm_casscf import psi4 h2 = psi4.geometry(""" 0 1 h h 1 r symmetry c1 """) psi4.set_options({ "basis": "cc-pvdz", "mcscf_type": "df", "scf_type": "df", "d_convergence": 1e-10, "maxiter": 500, "restricted_docc": [0], "restricted_uocc": [8], "active": [2], }) psi4.set_module_options( 'v2rdm_casscf', { "positivity": "d", "r_convergence": 1e-6, "e_convergence": 1e-8, "maxiter": 20000, }) psi4.activate(h2) h2.r = 1.0 psi4.set_options({"df_ints_io": "save"}) en, wfn = psi4.energy('scf', return_wfn=True) en1 = v2rdm_casscf.v2rdm_scf_solver(wfn) en2 = psi4.energy('casscf') assert psi4.compare_values(en1, en2, 6, "v2RDM-CASSCF total energy")
def test_v2rdm5(): #! cc-pvdz N2 (6,6) active space Test DQG print(' N2 / cc-pVDZ / DQG+T2(6,6), scf_type = PK, rNN = 1.1 A') import psi4 n2 = psi4.geometry(""" 0 1 n n 1 r """) psi4.set_options({ 'basis': 'cc-pvdz', 'scf_type': 'pk', 'd_convergence': 1e-10, 'maxiter': 500, 'restricted_docc': [2, 0, 0, 0, 0, 2, 0, 0], 'active': [1, 0, 1, 1, 0, 1, 1, 1], }) psi4.set_module_options( 'v2rdm_casscf', { 'positivity': 'dqgt2', 'r_convergence': 1e-4, 'e_convergence': 5e-4, 'maxiter': 20000, }) psi4.activate(n2) n2.r = 1.1 refscf = -108.95379624015767 refv2rdm = -109.091487394061 psi4.energy('v2rdm-casscf') assert psi4.compare_values(refscf, psi4.variable("SCF TOTAL ENERGY"), 8, "SCF total energy") assert psi4.compare_values(refv2rdm, psi4.variable("CURRENT ENERGY"), 4, "v2RDM-CASSCF total energy")
def energy(geom, confId, method='HF-3C', **kwargs): """ Finds the energy of a given molecule :param geom: an RDKit.Mol or a string :param confId: the ID of the conformer to optimize :param method: the PSI4 method to calculate the H**O and LUMO :return: wavefunction (energy is available under wavefunction.energy) """ try: geom = make_psi4_geometry(geom, confId) psi4.activate(geom) psi4.core.IO.set_default_namespace(str(id(geom))) psi4.core.set_global_option("MAXITER", 1000) return psi4.energy(method, return_wfn=True, **kwargs)[1] except Exception as e: print(e) return np.nan
def optimize(geom, confId=None, method='HF-3C', **kwargs): """ Optimizes the given conformation. :param mol: an RDKit.Mol or a string :param confId: the ID of the conformer to optimize, if needed :param method: the PSI4 method to use :return: wavefunction (energy is available under wavefunction.energy) """ try: geom = make_psi4_geometry(geom, confId) psi4.activate(geom) psi4.core.IO.set_default_namespace(str(id(geom))) psi4.core.set_global_option("MAXITER", 1000) return psi4.optimize(method, return_wfn=True, **kwargs)[1] except Exception as e: pass return np.nan
def test_v2rdm3(): #! H3 / cc-pvdz / D+D3 vs full CI, scf_type = PK print(' H3 / cc-pvdz / D+D3 vs full CI, scf_type = PK') import psi4 h3 = psi4.geometry(""" 0 2 H H 1 1.0 H 1 2.0 2 90.0 """) psi4.set_options({ 'basis': 'sto-3g', 'scf_type': 'pk', 'reference': 'rohf', 'guess': 'sad', 'd_convergence': 1e-10, 'maxiter': 500, }) psi4.set_module_options( 'v2rdm_casscf', { 'positivity': 'd', 'constrain_d3': True, 'r_convergence': 1e-5, 'e_convergence': 1e-6, 'maxiter': 20000, 'optimize_orbitals': False, 'semicanonicalize_orbitals': False, }) psi4.activate(h3) v2rdm = psi4.energy('v2rdm-casscf') fci = psi4.energy('fci') assert psi4.compare_values(v2rdm, fci, 5, "v2RDM vs full CI")
def __init__(self, mol, opts, sele, nbnd=[], link=[]): """ opts = { "reference": "rks", "basis": "6-31g*", "d_convergence": 6, "scf_type": "direct", "guess": "read", "output": False, "charge": 0, "method": "b3lyp", "ncpus": 1, "memory": "1024 MB" } """ self._ce = qm3.constants.H2J self._cg = self._ce / qm3.constants.A0 self.sel = sele[:] self.lnk = link[:] t = [j for i, j in self.lnk] self.nbn = [i for i in nbnd if not i in t] self.smb = mol.guess_symbols(sele) buf = "\n%d 1\n" % (opts.pop("charge")) j = 0 for i in sele: i3 = i * 3 buf += "%-2s%20.10lf%20.10lf%20.10lf\n" % ( self.smb[j], mol.coor[i3] - mol.boxl[0] * round(mol.coor[i3] / mol.boxl[0], 0), mol.coor[i3 + 1] - mol.boxl[1] * round(mol.coor[i3 + 1] / mol.boxl[1], 0), mol.coor[i3 + 2] - mol.boxl[2] * round(mol.coor[i3 + 2] / mol.boxl[2], 0)) j += 1 self.vla = [] if (len(self.lnk) > 0): k = len(self.sel) for i, j in self.lnk: c, v = qm3.engines.LA_coordinates(i, j, mol) buf += "%-2s%20.10lf%20.10lf%20.10lf\n" % ("H", c[0], c[1], c[2]) self.vla.append((self.sel.index(i), k, v[:])) k += 1 # -- psi4 -- if (opts.pop("output")): psi4.core.set_output_file("psi4.out", False) else: psi4.core.be_quiet() psi4.set_memory(opts.pop("memory")) psi4.set_num_threads(opts.pop("ncpus")) buf += "symmetry c1\nno_reorient\nno_com\n" self.QMatm = psi4.geometry(buf) psi4.activate(self.QMatm) if (len(self.nbn) > 0): self.MMatm = psi4.QMMM() self.MMatm.charges = [] for i in self.nbn: i3 = i * 3 self.MMatm.charges.append([ mol.chrg[i], mol.coor[i3] - mol.boxl[0] * round(mol.coor[i3] / mol.boxl[0], 0), mol.coor[i3 + 1] - mol.boxl[1] * round(mol.coor[i3 + 1] / mol.boxl[1], 0), mol.coor[i3 + 2] - mol.boxl[2] * round(mol.coor[i3 + 2] / mol.boxl[2], 0) ]) self.MMatm.populateExtern() psi4.core.set_global_option_python("EXTERN", self.MMatm.extern) self.met = opts.pop("method") psi4.set_options(opts)
def test_dftd3(): """dftd3/energy""" #! Exercises the various DFT-D corrections, both through python directly and through c++ ref_d2 = [-0.00390110, -0.00165271, -0.00058118] ref_d3zero = [-0.00285088, -0.00084340, -0.00031923] ref_d3bj = [-0.00784595, -0.00394347, -0.00226683] ref_pbe_d2 = [-0.00278650, -0.00118051, -0.00041513] ref_pbe_d3zero = [-0.00175474, -0.00045421, -0.00016839] ref_pbe_d3bj = [-0.00475937, -0.00235265, -0.00131239] eneyne = psi4.geometry(""" C 0.000000 -0.667578 -2.124659 C 0.000000 0.667578 -2.124659 H 0.923621 -1.232253 -2.126185 H -0.923621 -1.232253 -2.126185 H -0.923621 1.232253 -2.126185 H 0.923621 1.232253 -2.126185 -- C 0.000000 0.000000 2.900503 C 0.000000 0.000000 1.693240 H 0.000000 0.000000 0.627352 H 0.000000 0.000000 3.963929 """) print(' -D correction from Py-side') eneyne.update_geometry() E, G = eneyne.run_dftd3('b3lyp', 'd2') assert psi4.compare_values(ref_d2[0], E, 7, 'Ethene-Ethyne -D2') mA = eneyne.extract_subsets(1) E, G = mA.run_dftd3('b3lyp', 'd2') assert psi4.compare_values(ref_d2[1], E, 7, 'Ethene -D2') mB = eneyne.extract_subsets(2) E, G = mB.run_dftd3('b3lyp', 'd2') assert psi4.compare_values(ref_d2[2], E, 7, 'Ethyne -D2') #mBcp = eneyne.extract_subsets(2,1) #E, G = mBcp.run_dftd3('b3lyp', 'd2') #compare_values(ref_d2[2], E, 7, 'Ethyne(CP) -D2') E, G = eneyne.run_dftd3('b3lyp', 'd3zero') assert psi4.compare_values(ref_d3zero[0], E, 7, 'Ethene-Ethyne -D3 (zero)') mA = eneyne.extract_subsets(1) E, G = mA.run_dftd3('b3lyp', 'd3zero') assert psi4.compare_values(ref_d3zero[1], E, 7, 'Ethene -D3 (zero)') mB = eneyne.extract_subsets(2) E, G = mB.run_dftd3('b3lyp', 'd3zero') assert psi4.compare_values(ref_d3zero[2], E, 7, 'Ethyne -D3 (zero)') E, G = eneyne.run_dftd3('b3lyp', 'd3bj') assert psi4.compare_values(ref_d3bj[0], E, 7, 'Ethene-Ethyne -D3 (bj)') mA = eneyne.extract_subsets(1) E, G = mA.run_dftd3('b3lyp', 'd3bj') assert psi4.compare_values(ref_d3bj[1], E, 7, 'Ethene -D3 (bj)') mB = eneyne.extract_subsets(2) E, G = mB.run_dftd3('b3lyp', 'd3bj') assert psi4.compare_values(ref_d3bj[2], E, 7, 'Ethyne -D3 (bj)') E, G = eneyne.run_dftd3('b3lyp', 'd3') assert psi4.compare_values(ref_d3zero[0], E, 7, 'Ethene-Ethyne -D3 (alias)') E, G = eneyne.run_dftd3('b3lyp', 'd') assert psi4.compare_values(ref_d2[0], E, 7, 'Ethene-Ethyne -D (alias)') E, G = eneyne.run_dftd3('b3lyp', 'd2') assert psi4.compare_values(ref_d2[0], E, 7, 'Ethene-Ethyne -D2 (alias)') psi4.set_options({ 'basis': 'sto-3g', 'scf_type': 'df', 'dft_radial_points': 50, # use really bad grid for speed since all we want is the -D value 'dft_spherical_points': 110, #'scf print': 3, # will print dftd3 program output to psi4 output file }) print(' -D correction from C-side') psi4.activate(mA) #psi4.energy('b3lyp-d2', engine='libdisp') #assert psi4.compare_values(ref_d2[1], psi4.variable('DISPERSION CORRECTION ENERGY'), 7, 'Ethene -D2 (calling psi4 Disp class)') #psi4.energy('b3lyp-d2') #assert psi4.compare_values(ref_d2[1], psi4.variable('DISPERSION CORRECTION ENERGY'), 7, 'Ethene -D2 (calling dftd3 -old)') #psi4.energy('b3lyp-d3zero') #assert psi4.compare_values(ref_d3zero[1], psi4.variable('DISPERSION CORRECTION ENERGY'), 7, 'Ethene -D3 (calling dftd3 -zero)') psi4.energy('b3lyp-d3bj') assert psi4.compare_values(ref_d3bj[1], psi4.variable('DISPERSION CORRECTION ENERGY'), 7, 'Ethene -D3 (calling dftd3 -bj)') psi4.energy('b3lyp-d2', engine='libdisp') assert psi4.compare_values(ref_d2[1], psi4.variable('DISPERSION CORRECTION ENERGY'), 7, 'Ethene -D2 (alias)') #psi4.energy('b3lyp-d3') #assert psi4.compare_values(ref_d3zero[1], psi4.variable('DISPERSION CORRECTION ENERGY'), 7, 'Ethene -D3 (alias)') #psi4.energy('b3lyp-d') #assert psi4.compare_values(ref_d2[1], psi4.variable('DISPERSION CORRECTION ENERGY'), 7, 'Ethene -D (alias)') psi4.energy('wb97x-d') assert psi4.compare_values(-0.000834247063, psi4.variable('DISPERSION CORRECTION ENERGY'), 7, 'Ethene wb97x-d (chg)') print(' non-default -D correction from C-side') psi4.activate(mB) #psi4.set_options({'dft_dispersion_parameters': [0.75]}) #psi4.energy('b3lyp-d2', engine='libdisp') #assert psi4.compare_values(ref_pbe_d2[2], psi4.variable('DISPERSION CORRECTION ENERGY'), 7, 'Ethene -D2 (calling psi4 Disp class)') #psi4.set_options({'dft_dispersion_parameters': [0.75, 20.0]}) #psi4.energy('b3lyp-d2') #assert psi4.compare_values(ref_pbe_d2[2], psi4.variable('DISPERSION CORRECTION ENERGY'), 7, 'Ethene -D2 (calling dftd3 -old)') #psi4.set_options({'dft_dispersion_parameters': [1.0, 0.722, 1.217, 14.0]}) #psi4.energy('b3lyp-d3zero') #assert psi4.compare_values(ref_pbe_d3zero[2], psi4.variable('DISPERSION CORRECTION ENERGY'), 7, 'Ethene -D3 (calling dftd3 -zero)') psi4.set_options( {'dft_dispersion_parameters': [1.000, 0.7875, 0.4289, 4.4407]}) psi4.energy('b3lyp-d3bj') assert psi4.compare_values(ref_pbe_d3bj[2], psi4.variable('DISPERSION CORRECTION ENERGY'), 7, 'Ethene -D3 (calling dftd3 -bj)') psi4.set_options({'dft_dispersion_parameters': [0.75]}) psi4.energy('b3lyp-d2', engine='dftd3') assert psi4.compare_values(ref_pbe_d2[2], psi4.variable('DISPERSION CORRECTION ENERGY'), 7, 'Ethene -D2 (alias)') psi4.set_options({'dft_dispersion_parameters': [1.0, 0.722, 1.217, 14.0]}) psi4.energy('b3lyp-d3') assert psi4.compare_values(ref_pbe_d3zero[2], psi4.variable('DISPERSION CORRECTION ENERGY'), 7, 'Ethene -D3 (alias)') psi4.set_options({'dft_dispersion_parameters': [0.75]}) psi4.energy('b3lyp-d') assert psi4.compare_values(ref_pbe_d2[2], psi4.variable('DISPERSION CORRECTION ENERGY'), 7, 'Ethene -D (alias)') psi4.activate(mA) psi4.set_options({'dft_dispersion_parameters': [1.0]}) psi4.energy('wb97x-d') assert psi4.compare_values(-0.000834247063, psi4.variable('DISPERSION CORRECTION ENERGY'), 7, 'Ethene wb97x-d (chg)') print(' non-default -D correction from Py-side') eneyne.update_geometry() eneyne.run_dftd3('b3lyp', 'd2', {'s6': 0.75}) assert psi4.compare_values(ref_pbe_d2[0], psi4.variable('DISPERSION CORRECTION ENERGY'), 7, 'Ethene-Ethyne -D2') mA = eneyne.extract_subsets(1) mA.run_dftd3('b3lyp', 'd2', {'s6': 0.75}) assert psi4.compare_values(ref_pbe_d2[1], psi4.variable('DISPERSION CORRECTION ENERGY'), 7, 'Ethene -D2') mB = eneyne.extract_subsets(2) mB.run_dftd3('b3lyp', 'd2', {'s6': 0.75}) assert psi4.compare_values(ref_pbe_d2[2], psi4.variable('DISPERSION CORRECTION ENERGY'), 7, 'Ethyne -D2') eneyne.run_dftd3('b3lyp', 'd3zero', { 's6': 1.0, 's8': 0.722, 'sr6': 1.217, 'alpha6': 14.0 }) assert psi4.compare_values(ref_pbe_d3zero[0], psi4.variable('DISPERSION CORRECTION ENERGY'), 7, 'Ethene-Ethyne -D3 (zero)') mA = eneyne.extract_subsets(1) mA.run_dftd3('b3lyp', 'd3zero', { 's6': 1.0, 's8': 0.722, 'sr6': 1.217, 'alpha6': 14.0 }) assert psi4.compare_values(ref_pbe_d3zero[1], psi4.variable('DISPERSION CORRECTION ENERGY'), 7, 'Ethene -D3 (zero)') mB = eneyne.extract_subsets(2) mB.run_dftd3('b3lyp', 'd3zero', { 's6': 1.0, 's8': 0.722, 'sr6': 1.217, 'alpha6': 14.0 }) assert psi4.compare_values(ref_pbe_d3zero[2], psi4.variable('DISPERSION CORRECTION ENERGY'), 7, 'Ethyne -D3 (zero)') eneyne.run_dftd3('b3lyp', 'd3bj', { 's6': 1.000, 's8': 0.7875, 'a1': 0.4289, 'a2': 4.4407 }) assert psi4.compare_values(ref_pbe_d3bj[0], psi4.variable('DISPERSION CORRECTION ENERGY'), 7, 'Ethene-Ethyne -D3 (bj)') mA = eneyne.extract_subsets(1) mA.run_dftd3('b3lyp', 'd3bj', { 's6': 1.000, 's8': 0.7875, 'a1': 0.4289, 'a2': 4.4407 }) assert psi4.compare_values(ref_pbe_d3bj[1], psi4.variable('DISPERSION CORRECTION ENERGY'), 7, 'Ethene -D3 (bj)') mB = eneyne.extract_subsets(2) mB.run_dftd3('b3lyp', 'd3bj', { 's6': 1.000, 's8': 0.7875, 'a1': 0.4289, 'a2': 4.4407 }) assert psi4.compare_values(ref_pbe_d3bj[2], psi4.variable('DISPERSION CORRECTION ENERGY'), 7, 'Ethyne -D3 (bj)') eneyne.run_dftd3('b3lyp', 'd3', { 's6': 1.0, 's8': 0.722, 'sr6': 1.217, 'alpha6': 14.0 }) assert psi4.compare_values(ref_pbe_d3zero[0], psi4.variable('DISPERSION CORRECTION ENERGY'), 7, 'Ethene-Ethyne -D3 (alias)') eneyne.run_dftd3('b3lyp', 'd', {'s6': 0.75}) assert psi4.compare_values(ref_pbe_d2[0], psi4.variable('DISPERSION CORRECTION ENERGY'), 7, 'Ethene-Ethyne -D (alias)') eneyne.run_dftd3('b3lyp', 'd2', {'s6': 0.75}) assert psi4.compare_values(ref_pbe_d2[0], psi4.variable('DISPERSION CORRECTION ENERGY'), 7, 'Ethene-Ethyne -D2 (alias)')
def test_pp2rdm(): """hilbert/tests/pp2rdm""" #! 6-31g H2O pp2RDM Test import psi4 import sys sys.path.insert(0, '../..') import hilbert h2o = psi4.geometry(""" 0 1 o h 1 1.0 h 1 1.0 2 104.5 symmetry c1 """) interloper = psi4.geometry(""" 0 1 O H 1 1.0 H 1 1.0 2 90.0 """) psi4.set_options({ 'basis': '6-31g', 'scf_type': 'df', 'e_convergence': 1e-10, 'r_convergence': 1e-8, 'orbopt_gradient_convergence': 1e-6, 'orbopt_energy_convergence': 1e-8, 'maxiter': 500, }) psi4.set_module_options( 'hilbert', { 'orbopt_maxiter': 1, 'localize_orbitals': True, 'noisy_orbitals': True, 'optimize_orbitals': True, 'p2rdm_type': 'k', }) psi4.activate(h2o) ref_scf = -75.98014193580194 ref_pp2rdm = -76.052804542359 # be sure to save three-index integrals after scf psi4.core.set_local_option('SCF', 'DF_INTS_IO', 'SAVE') # get scf wfn scf_energy, ref_wfn = psi4.energy('scf', return_wfn=True) # grab options object options = psi4.core.get_options() options.set_current_module('HILBERT') # evaluate pp2RDM energy pp2rdm = hilbert.pp2RDMHelper(ref_wfn, options) current_energy = pp2rdm.compute_energy() assert psi4.compare_values(ref_scf, scf_energy, 8, "SCF total energy") assert psi4.compare_values(ref_pp2rdm, current_energy, 5, "pp2RDM total energy")
def test_v2rdm7(): # STO-3g benzene (6,6) guess orbital rotation test DQG print(' benzene (6,6), scf_type = PK') import psi4 # orbital rotation needed before MCSCF calculation benzene_c1 = psi4.geometry(""" 0 1 symmetry c1 C 0.00000000 1.38980400 0.00000000 C 1.20360500 0.69490200 0.00000000 C 1.20360500 -0.69490200 0.00000000 C 0.00000000 -1.38980400 0.00000000 C -1.20360500 -0.69490200 0.00000000 C -1.20360500 0.69490200 0.00000000 H 0.00000000 2.47523400 0.00000000 H 2.14361600 1.23761700 0.00000000 H 2.14361600 -1.23761700 0.00000000 H 0.00000000 -2.47523400 0.00000000 H -2.14361600 -1.23761700 0.00000000 H -2.14361600 1.23761700 0.00000000 """) psi4.set_options({ 'basis': 'sto-3g', 'scf_type': 'pk', 'd_convergence': 1e-10, 'maxiter': 500, 'restricted_docc': [18], 'active': [6], }) psi4.energy('hf') psi4.set_module_options( 'v2rdm_casscf', { # Switch the 17th (index 16) and the 19th (index 18) orbitals of the 1st irrep (index 0) # If more than one set of orbitals need to be rotated, use the following syntex # mcscf_rotate [[irrep_1, orb1_1, orb2_1, theta_1], [irrep_2, orb1_2, orb2_2, theta2],...] # Setting theta to 90 would switch the orbitals, setting it to 0 does nothing. 'mcscf_rotate': [[0, 16, 18, 90]], 'positivity': 'dq', 'r_convergence': 1e-5, 'e_convergence': 1e-6, 'maxiter': 20000, 'guess_orbitals_write': False, 'molden_write': False, }) psi4.activate(benzene_c1) E_c1 = psi4.energy('v2rdm-casscf') psi4.core.clean() # reference calculation, no need to rotate orbitals for MCSCF benzene_d2h = psi4.geometry(""" 0 1 symmetry d2h C 0.00000000 1.38980400 0.00000000 C 1.20360500 0.69490200 0.00000000 C 1.20360500 -0.69490200 0.00000000 C 0.00000000 -1.38980400 0.00000000 C -1.20360500 -0.69490200 0.00000000 C -1.20360500 0.69490200 0.00000000 H 0.00000000 2.47523400 0.00000000 H 2.14361600 1.23761700 0.00000000 H 2.14361600 -1.23761700 0.00000000 H 0.00000000 -2.47523400 0.00000000 H -2.14361600 -1.23761700 0.00000000 H -2.14361600 1.23761700 0.00000000 """) psi4.set_options({ 'basis': 'sto-3g', 'scf_type': 'pk', 'd_convergence': 1e-10, 'maxiter': 500, 'restricted_docc': [6, 3, 0, 0, 0, 0, 5, 4], 'active': [0, 0, 1, 2, 1, 2, 0, 0], }) psi4.energy('hf') psi4.set_module_options( 'v2rdm_casscf', { # Note that when mcscf_rotate is set for the previous molecule, the calculations afterwards # also use this input, unless you overwrite it. A safe way to unset it is to overwrite it # with mcscf_rotate [[0, 0, 0, 0]], which should work as long as your molecule has at # least 1 orbital in the 1st irrep. This problem can also be simply avoided by calculating # the molecules that do not require orbital rotations first. 'mcscf_rotate': [[0, 0, 0, 0]], 'positivity': 'dq', 'r_convergence': 1e-5, 'e_convergence': 1e-6, 'maxiter': 20000, 'guess_orbitals_write': False, 'molden_write': False, }) psi4.activate(benzene_d2h) E_d2h = psi4.energy('v2rdm-casscf') assert psi4.compare_values(E_c1, E_d2h, 4, "v2RDM-CASSCF total energy")
def run_n_body(name, **kwargs): r"""Function encoding sequence of PSI module and plugin calls so that n_body can be called via :py:func:`~driver.energy`. For post-scf plugins. >>> energy('n_body') """ lowername = name.lower() kwargs = p4util.kwargs_lower(kwargs) # print("START run_n_body()") # Your plugin's psi4 run sequence goes here psi4.core.set_local_option('MYPLUGIN', 'PRINT', 1) ##### BEGIN TAYLOR'S run_n_body() FUNCTION ##### # Only energy and properties are implemented for now, not sure others even # make sense anyways. db = shelve.open('database', writeback=True) # print(db) # Initialize database if not 'initialized' in db: n_body.initialize_database(db, kwargs) db['initialized'] = True elif not db['initialized']: n_body.initialize_database(db, kwargs) db['initialized'] = True # Remove n_body_func, it's being tracked in the database and we don't want to propagate it if 'n_body_func' in kwargs: kwargs.pop('n_body_func') # Process user requested options n_body_options = n_body.process_options(name, db, kwargs.pop('n_body')) # Compare database options to n_body_options if 'distributed' in n_body_options: db['distributed'] = n_body_options['distributed'] if not db['distributed']: raise Exception( "Currently n_body jobs must be run in distributed mode" " use the n_body wrapper instead.\n") if 'cutoff' in n_body_options: db['cutoff'] = n_body_options['cutoff'] if 'num_threads' in n_body_options: db['num_threads'] = n_body_options['num_threads'] if 'bsse' in n_body_options: db['bsse'] = n_body_options['bsse'] if 'pcm' in n_body_options: db['pcm'] = n_body_options['pcm'] if 'solute' in n_body_options: db['solute'] = n_body_options['solute'] if 'timing' in n_body_options: db['timing'] = n_body_options['timing'] if 'harvest' in n_body_options: db['harvest'] = n_body_options['harvest'] if 'cook' in n_body_options: db['cook'] = n_body_options['cook'] # methods consistency check if 'methods' in n_body_options: for key, val in n_body_options['methods'].items(): if key in db['methods'].keys(): # requested n_body_max smaller than previously requested if val < db['methods'][key]: raise Exception('n_body_max for {} has ' 'decreased.'.format(key)) # requested n_body_max has increased elif val > db['methods'][key]: # save requested n_body_max db['methods'][key] = val # update database entries n_body.extend_database(db, kwargs) # set flag to regenerate inputs db['inputs_generated'] = False else: # method not already in database # add method and n_body_max to database db['methods'][key] = val # update database entries n_body.extend_database(db, kwargs) # set flag to regenerate inputs db['inputs_generated'] = False # Get complete system molecule = psi4.core.get_active_molecule() # Determine interacting fragments if db['cutoff']: i_pairs = n_body.interacting_pairs(db['cutoff']) i_clusters = [] if not db['inputs_generated']: # Create method directories for method, n_body_max in db['methods'].items(): try: os.makedirs(method) except: if os.path.isdir(method): print(method) pass else: raise Exception('Attempt to create {} directory ' 'failed.'.format(method)) # Create n_body_level directories for n in range(1, n_body_max + 1): directory = '{}/{}'.format(method, n_body.n_body_dir(n)) try: os.makedirs(directory) except: if os.path.isdir(directory): print(directory) pass else: raise Exception('Attempt to create {} directory ' 'failed.'.format(directory)) # Create job input files # Grab all ghost functions if SSFC # Else, get all possible clusters without ghost atoms if db['bsse'] == 'ssfc': clusters = psi4.extract_clusters(molecule, True, n) else: clusters = psi4.extract_clusters(molecule, False, n) # Flip distance-dropoff off for now #if db['bsse'] == 'radius' #clusters = extract_clusters(molecule, False, n) #clusters = n_body.expand_basis(clusters, db['basis_cutoff']) # Get list of fragments involved in clusters indexes = psi4.extract_cluster_indexing(molecule, n) print('Length of index array = {}'.format(len(indexes))) # Testing for extension to inclusion of nearby atoms (ghosted) #cluster_string = clusters[0].save_string_xyz_g09() #print(cluster_string) #cluster_string += molecule.extract_subsets(2).save_string_xyz_g09() #print(molecule.extract_subsets(2).save_string_xyz_g09()) #print(clusters[0].save_string_xyz_g09()) #print(cluster_string) #cluster_string = '' # Get interacting clusters if db['cutoff']: if n == 1: # Generate all inputs pass elif n == 2: # generate inputs for i_pairs only for k in range(len(clusters) - 1, -1, -1): clus = indexes[k] if clus in i_pairs: i_clusters.append(clus) else: # Remove non-interacting clusters from lists clusters.pop(k) indexes.pop(k) elif n > 2: prev_clusters = copy.deepcopy(i_clusters) i_clusters = [] for k in range(len(clusters) - 1, -1, -1): # Check if interacting cluster clus = indexes[k] for p_clus in prev_clusters: # previous cluster is contained within current cluster if set(p_clus).issubset(set(clus)): # Get remaining frag number if len(set(clus).difference( set(p_clus))) == 1: l = set(clus).difference( set(p_clus)).pop() else: raise Exception( 'Length of difference ' 'set is greater than 1') for m in p_clus: # Is this an interacting pair? if sorted([l, m], reverse=True) in i_pairs: i_clusters.append(clus) # Don't check anymore pairs break if clus in i_clusters: break else: # Remove non-interacting clusters from lists clusters.pop(k) indexes.pop(k) # Create input files db[method][n]['total_num_jobs'] = len(clusters) print('n = {}'.format(n)) print('Number of jobs created = {}'.format(len(clusters))) for k in range(len(clusters)): psi4.activate(clusters[k]) cluster = psi4.core.get_active_molecule() # db[method][n]['MW'][job] = value ### Set-up things for input generation # Get list of combinations to ghost # MBCP if db['bsse'] == 'mbcp' and n > 1: mbcp = list(itertools.combinations(indexes[k], n - 1)) for ghost in mbcp: directory = '{}/{}/{}'.format( method, n_body.n_body_dir(n), n_body.ghost_dir(indexes[k], ghost)) cluster.set_ghost_fragments(list(ghost)) cluster.update_geometry() cluster.set_name('{}_{}'.format( molecule.name(), n_body.ghost_dir(indexes[k], ghost))) n_body.plant(cluster, db, kwargs, method, directory) # Update job_status dict n_basis = n n_real = n - len(ghost) ghost_jobs = '{}-{}r'.format(n_basis, n_real) # db[method][ghost_jobs]['total_num_jobs'] = len(mbcp) * len(clusters) # db[method][ghost_jobs]['job_status'].update({n_body.ghost_dir(indexes[k],ghost): # 'not_started'}) db[method][n]['total_num_jobs'] = len(mbcp) * len( clusters) db[method][n]['job_status'].update({ n_body.ghost_dir(indexes[k], ghost): 'not_started' }) # Calculate molecular weight totalmass = sum( mol2.mass(i) for i in range(mol2.natom()) if mol2.Z(i)) totmass = sum( cluster.mass(i) for i in range(cluster.natom()) if cluster.Z(i)) db[method][n]['MW'].update( {n_body.ghost_dir(indexes[k], ghost): totmass}) # Reactivate fragments for next round cluster.set_active_fragments(list(ghost)) cluster.update_geometry() # VMFC elif db['bsse'] == 'vmfc': vmfc = [] for n_ghost in range(n - 1, 0, -1): vmfc.extend( list( itertools.combinations( indexes[k], n_ghost))) for ghost in vmfc: directory = '{}/{}/{}'.format( method, n_body.n_body_dir(n), n_body.ghost_dir(indexes[k], ghost)) cluster.set_ghost_fragments(list(ghost)) cluster.update_geometry() cluster.set_name('{}_{}'.format( molecule.name(), n_body.ghost_dir(indexes[k], ghost))) n_body.plant(cluster, db, kwargs, method, directory) # Update job_status dict n_basis = n n_real = n - len(ghost) ghost_jobs = '{}-{}r'.format(n_basis, n_real) #db[method][ghost_jobs]['total_num_jobs'] = len(vmfc) * len(clusters) # db[method][ghost_jobs]['total_num_jobs'] = len(list(itertools.combinations(range(0,n),n_real))) * len(clusters) # db[method][ghost_jobs]['job_status'].update({n_body.ghost_dir(indexes[k],ghost): # 'not_started'}) db[method][n]['total_num_jobs'] = len( list( itertools.combinations( range(0, n), n_real))) * len(clusters) db[method][n]['job_status'].update({ n_body.ghost_dir(indexes[k], ghost): 'not_started' }) # Calculate molecular weight totmass = sum( cluster.mass(i) for i in range(cluster.natom()) if cluster.Z(i)) db[method][n]['MW'].update( {n_body.ghost_dir(indexes[k], ghost): totmass}) # Reactivate fragments for next round cluster.set_active_fragments(list(ghost)) cluster.update_geometry() # SSFC or no BSSE else: cluster.set_name('{}_{}'.format( molecule.name(), n_body.cluster_dir(indexes[k]))) #molecule.set_name('{}_{}'.format(molecule.name(),cluster_dir(indexes[k]))) directory = '{}/{}/{}'.format( method, n_body.n_body_dir(n), n_body.cluster_dir(indexes[k])) n_body.plant(cluster, db, kwargs, method, directory) # Update database job_status dict db[method][n]['job_status'].update( {n_body.cluster_dir(indexes[k]): 'not_started'}) # Calculate molecular weight totmass = sum( cluster.mass(i) for i in range(cluster.natom()) if cluster.Z(i)) db[method][n]['MW'].update( {n_body.cluster_dir(indexes[k]): totmass}) # Check for zero jobs (happens occasionally due to cutoff) for method in db['methods']: for n in range(1, db[method]['n_body_max'] + 1): if db[method][n]['total_num_jobs'] == 0: db[method]['n_body_max'] = n - 1 break # Inputs successfully generated db['inputs_generated'] = True # For now open and close database frequently, until I figure out atexit db.close() db = shelve.open('database', writeback=True) # Check status of jobs if not db['jobs_complete']: n_incomplete = 0 # Check all methods for method in db['methods'].keys(): #### NOTE: dft_methods is defunct ##### # if method in n_body.dft_methods: # outname = 'input.log' # complete_message = 'Normal termination of Gaussian' # if (method == 'b3lyp'): if method in n_body.dft_methods: outname = 'input.log' complete_message = 'Normal termination of Gaussian' error_message = 'Error termination' else: outname = 'output.dat' complete_message = 'Psi4 exiting successfully' error_message = 'Psi4 encountered an error' # Check all n_body_levels print('Before job checking:') for field in db[method]['farm']: num_fin = db[method][field]['num_jobs_complete'] tot_num = db[method][field]['total_num_jobs'] print('{}/{} {}-body jobs finished'.format( num_fin, tot_num, field)) n_complete = num_fin if num_fin != tot_num: db_stat = db[method][field]['job_status'] n_complete = 0 for job, status in db_stat.items(): if status == 'complete': n_complete += 1 elif status in ('not_started', 'running', 'error'): try: outfile = open('{}/{}/{}/{}'.format( method, n_body.n_body_dir(field), job, outname)) for line in outfile: if complete_message in line: # This actually marks the job complete as soon as # the first route section is complete in the case # of g09, not when the job is totally finished. db_stat[job] = 'complete' n_complete += 1 break elif error_message in line: db_stat[job] = 'error' break else: db_stat[job] = 'running' n_incomplete += 1 except: # this print statement is super annoying, muting it for now # print('Exception: probably could not open file for {}'.format(job)) n_incomplete += 1 db[method][field]['num_jobs_complete'] = n_complete if n_incomplete == 0: db['jobs_complete'] = True db.close() db = shelve.open('database', writeback=True) # Gather results if not db['results_computed']: for method in db['methods'].keys(): print('\nAfter job checking:') for field in db[method]['farm']: num_fin = db[method][field]['num_jobs_complete'] tot_num = db[method][field]['total_num_jobs'] print('{}/{} {}-body jobs finished'.format( num_fin, tot_num, field)) if (db[method][field]['num_jobs_complete'] == db[method][field] ['total_num_jobs']): if db['harvest']: if method in n_body.dft_methods: n_body.harvest_g09(db, method, field) else: n_body.harvest_data(db, method, field) if not db['harvest']: print("Data harvesting has been disabled.") elif not db['cook']: print("Data cooking has been disabled.") else: for field in db[method]['farm']: if (db[method][field]['num_jobs_complete'] == db[method] [field]['total_num_jobs']): n_body.cook_data(db, method, field) # #if db['bsse'] == 'vmfc' and field > 1: # # n_body.vmfc_cook(db, method, field) # # n_body.mbcp_cook(db, method, field) # if db['bsse'] == 'vmfc': # n_body.vmfc_cook(db, method, field) # if field > 1: # n_body.mbcp_cook(db, method, field) # elif db['bsse'] == 'mbcp' and field > 1: # n_body.mbcp_cook(db,method,field) # # Future location of an if check for mass adjust or not # if 'rotation' in db[method]['results']: # n_body.mass_adjust_rotations(db,method,field) db.close() db = shelve.open('database', writeback=True) # Print banner to output file including user options n_body.banner(db) db.close() pass
def test_v2rdm_doci(): """hilbert/tests/v2rdm_doci""" #! 6-31g H2O v2RDM-DOCI Test import psi4 import sys sys.path.insert(0, '../..') import hilbert h2o = psi4.geometry(""" 0 1 o h 1 1.0 h 1 1.0 2 104.5 symmetry c1 """) interloper = psi4.geometry(""" 0 1 O H 1 1.0 H 1 1.0 2 90.0 """) psi4.set_options({ 'basis': '6-31g', 'scf_type': 'df', 'e_convergence': 1e-4, 'r_convergence': 1e-6, 'maxiter': 100000, }) psi4.set_module_options( 'hilbert', { 'orbopt_maxiter': 20, 'localize_orbitals': True, 'noisy_orbitals': True, 'optimize_orbitals': True, 'orbopt_gradient_convergence': 1e-6, 'orbopt_energy_convergence': 1e-8, 'orbopt_frequency': 1000, }) psi4.activate(h2o) ref_scf = -75.98014193580194 ref_v2rdm_doci = -76.053681341564 # be sure to save three-index integrals after scf psi4.core.set_local_option('SCF', 'DF_INTS_IO', 'SAVE') # get scf wfn scf_energy, ref_wfn = psi4.energy('scf', return_wfn=True) # grab options object options = psi4.core.get_options() options.set_current_module('HILBERT') # evaluate v2RDM-DOCI energy v2rdm_doci = hilbert.v2RDM_DOCIHelper(ref_wfn, options) current_energy = v2rdm_doci.compute_energy() assert psi4.compare_values(ref_scf, scf_energy, 8, "SCF total energy") assert psi4.compare_values(ref_v2rdm_doci, current_energy, 4, "v2RDM-DOCI total energy")
def test_v2rdm4(): print(' 1,4-phenylenedinitrene/(10,10)/cc-pVDZ') import psi4 singlet = psi4.geometry(""" 0 1 C 0.00000000 -1.43825841 0.00000000 C 1.26321637 -0.67149862 0.00000000 C 1.26321637 0.67149862 0.00000000 C 0.00000000 1.43825841 0.00000000 C -1.26321637 0.67149862 0.00000000 C -1.26321637 -0.67149862 0.00000000 H 2.18678709 -1.24095300 0.00000000 H 2.18678709 1.24095300 0.00000000 H -2.18678709 1.24095300 0.00000000 H -2.18678709 -1.24095300 0.00000000 N 0.00000000 2.71003942 0.00000000 N 0.00000000 -2.71003942 0.00000000 """) triplet = psi4.geometry(""" 0 3 C 0.00000000 -1.43825841 0.00000000 C 1.26321637 -0.67149862 0.00000000 C 1.26321637 0.67149862 0.00000000 C 0.00000000 1.43825841 0.00000000 C -1.26321637 0.67149862 0.00000000 C -1.26321637 -0.67149862 0.00000000 H 2.18678709 -1.24095300 0.00000000 H 2.18678709 1.24095300 0.00000000 H -2.18678709 1.24095300 0.00000000 H -2.18678709 -1.24095300 0.00000000 N 0.00000000 2.71003942 0.00000000 N 0.00000000 -2.71003942 0.00000000 """) psi4.set_options({ 'basis': 'cc-pvdz', 'scf_type': 'df', 'd_convergence': 1e-8, 'maxiter': 500, 'reference': 'rohf', 'restricted_docc': [8, 3, 0, 0, 0, 0, 7, 4], 'active': [0, 1, 1, 3, 1, 3, 0, 1], }) psi4.set_module_options( 'v2rdm_casscf', { 'positivity': 'dqg', 'constrain_spin': True, 'r_convergence': 1e-4, 'e_convergence': 1e-4, 'cg_convergence': 1e-8, 'mu_update_frequency': 250, 'orbopt_frequency': 500, 'maxiter': 100000, }) # singlet # from JCTC, with r_convergence = e_convergence = 1e-5 # * v2RDM total energy: -338.502362198038 psi4.activate(singlet) ref_singlet = -338.502342367694 e_singlet = psi4.energy('v2rdm-casscf') assert psi4.compare_values(e_singlet, ref_singlet, 4, "singlet") # triplet # from JCTC, with r_convergence = e_convergence = 1e-5 # * v2RDM total energy: -338.495146818081 psi4.activate(triplet) ref_triplet = -338.495170913420 e_triplet = psi4.energy('v2rdm-casscf') assert psi4.compare_values(e_triplet, ref_triplet, 4, "triplet")
def test_dftd3(): """dftd3/energy""" #! Exercises the various DFT-D corrections, both through python directly and through c++ ref_d2 = [-0.00390110, -0.00165271, -0.00058118] ref_d3zero = [-0.00285088, -0.00084340, -0.00031923] ref_d3bj = [-0.00784595, -0.00394347, -0.00226683] ref_pbe_d2 = [-0.00278650, -0.00118051, -0.00041513] ref_pbe_d3zero = [-0.00175474, -0.00045421, -0.00016839] ref_pbe_d3bj = [-0.00475937, -0.00235265, -0.00131239] eneyne = psi4.geometry(""" C 0.000000 -0.667578 -2.124659 C 0.000000 0.667578 -2.124659 H 0.923621 -1.232253 -2.126185 H -0.923621 -1.232253 -2.126185 H -0.923621 1.232253 -2.126185 H 0.923621 1.232253 -2.126185 -- C 0.000000 0.000000 2.900503 C 0.000000 0.000000 1.693240 H 0.000000 0.000000 0.627352 H 0.000000 0.000000 3.963929 """) print(' -D correction from Py-side') eneyne.update_geometry() E, G = eneyne.run_dftd3('b3lyp', 'd2') assert psi4.compare_values(ref_d2[0], E, 7, 'Ethene-Ethyne -D2') mA = eneyne.extract_subsets(1) E, G = mA.run_dftd3('b3lyp', 'd2') assert psi4.compare_values(ref_d2[1], E, 7, 'Ethene -D2') mB = eneyne.extract_subsets(2) E, G = mB.run_dftd3('b3lyp', 'd2') assert psi4.compare_values(ref_d2[2], E, 7, 'Ethyne -D2') #mBcp = eneyne.extract_subsets(2,1) #E, G = mBcp.run_dftd3('b3lyp', 'd2') #compare_values(ref_d2[2], E, 7, 'Ethyne(CP) -D2') E, G = eneyne.run_dftd3('b3lyp', 'd3zero') assert psi4.compare_values(ref_d3zero[0], E, 7, 'Ethene-Ethyne -D3 (zero)') mA = eneyne.extract_subsets(1) E, G = mA.run_dftd3('b3lyp', 'd3zero') assert psi4.compare_values(ref_d3zero[1], E, 7, 'Ethene -D3 (zero)') mB = eneyne.extract_subsets(2) E, G = mB.run_dftd3('b3lyp', 'd3zero') assert psi4.compare_values(ref_d3zero[2], E, 7, 'Ethyne -D3 (zero)') E, G = eneyne.run_dftd3('b3lyp', 'd3bj') assert psi4.compare_values(ref_d3bj[0], E, 7, 'Ethene-Ethyne -D3 (bj)') mA = eneyne.extract_subsets(1) E, G = mA.run_dftd3('b3lyp', 'd3bj') assert psi4.compare_values(ref_d3bj[1], E, 7, 'Ethene -D3 (bj)') mB = eneyne.extract_subsets(2) E, G = mB.run_dftd3('b3lyp', 'd3bj') assert psi4.compare_values(ref_d3bj[2], E, 7, 'Ethyne -D3 (bj)') E, G = eneyne.run_dftd3('b3lyp', 'd3') assert psi4.compare_values(ref_d3zero[0], E, 7, 'Ethene-Ethyne -D3 (alias)') E, G = eneyne.run_dftd3('b3lyp', 'd') assert psi4.compare_values(ref_d2[0], E, 7, 'Ethene-Ethyne -D (alias)') E, G = eneyne.run_dftd3('b3lyp', 'd2') assert psi4.compare_values(ref_d2[0], E, 7, 'Ethene-Ethyne -D2 (alias)') psi4.set_options({'basis': 'sto-3g', 'scf_type': 'df', 'dft_radial_points': 50, # use really bad grid for speed since all we want is the -D value 'dft_spherical_points': 110, #'scf print': 3, # will print dftd3 program output to psi4 output file }) print(' -D correction from C-side') psi4.activate(mA) #psi4.energy('b3lyp-d2', engine='libdisp') #assert psi4.compare_values(ref_d2[1], psi4.variable('DISPERSION CORRECTION ENERGY'), 7, 'Ethene -D2 (calling psi4 Disp class)') #psi4.energy('b3lyp-d2') #assert psi4.compare_values(ref_d2[1], psi4.variable('DISPERSION CORRECTION ENERGY'), 7, 'Ethene -D2 (calling dftd3 -old)') #psi4.energy('b3lyp-d3zero') #assert psi4.compare_values(ref_d3zero[1], psi4.variable('DISPERSION CORRECTION ENERGY'), 7, 'Ethene -D3 (calling dftd3 -zero)') psi4.energy('b3lyp-d3bj') assert psi4.compare_values(ref_d3bj[1], psi4.variable('DISPERSION CORRECTION ENERGY'), 7, 'Ethene -D3 (calling dftd3 -bj)') psi4.energy('b3lyp-d2', engine='libdisp') assert psi4.compare_values(ref_d2[1], psi4.variable('DISPERSION CORRECTION ENERGY'), 7, 'Ethene -D2 (alias)') #psi4.energy('b3lyp-d3') #assert psi4.compare_values(ref_d3zero[1], psi4.variable('DISPERSION CORRECTION ENERGY'), 7, 'Ethene -D3 (alias)') #psi4.energy('b3lyp-d') #assert psi4.compare_values(ref_d2[1], psi4.variable('DISPERSION CORRECTION ENERGY'), 7, 'Ethene -D (alias)') psi4.energy('wb97x-d') assert psi4.compare_values(-0.000834247063, psi4.variable('DISPERSION CORRECTION ENERGY'), 7, 'Ethene wb97x-d (chg)') print(' non-default -D correction from C-side') psi4.activate(mB) #psi4.set_options({'dft_dispersion_parameters': [0.75]}) #psi4.energy('b3lyp-d2', engine='libdisp') #assert psi4.compare_values(ref_pbe_d2[2], psi4.variable('DISPERSION CORRECTION ENERGY'), 7, 'Ethene -D2 (calling psi4 Disp class)') #psi4.set_options({'dft_dispersion_parameters': [0.75, 20.0]}) #psi4.energy('b3lyp-d2') #assert psi4.compare_values(ref_pbe_d2[2], psi4.variable('DISPERSION CORRECTION ENERGY'), 7, 'Ethene -D2 (calling dftd3 -old)') #psi4.set_options({'dft_dispersion_parameters': [1.0, 0.722, 1.217, 14.0]}) #psi4.energy('b3lyp-d3zero') #assert psi4.compare_values(ref_pbe_d3zero[2], psi4.variable('DISPERSION CORRECTION ENERGY'), 7, 'Ethene -D3 (calling dftd3 -zero)') psi4.set_options({'dft_dispersion_parameters': [1.000, 0.7875, 0.4289, 4.4407]}) psi4.energy('b3lyp-d3bj') assert psi4.compare_values(ref_pbe_d3bj[2], psi4.variable('DISPERSION CORRECTION ENERGY'), 7, 'Ethene -D3 (calling dftd3 -bj)') psi4.set_options({'dft_dispersion_parameters': [0.75]}) psi4.energy('b3lyp-d2', engine='dftd3') assert psi4.compare_values(ref_pbe_d2[2], psi4.variable('DISPERSION CORRECTION ENERGY'), 7, 'Ethene -D2 (alias)') psi4.set_options({'dft_dispersion_parameters': [1.0, 0.722, 1.217, 14.0]}) psi4.energy('b3lyp-d3') assert psi4.compare_values(ref_pbe_d3zero[2], psi4.variable('DISPERSION CORRECTION ENERGY'), 7, 'Ethene -D3 (alias)') psi4.set_options({'dft_dispersion_parameters': [0.75]}) psi4.energy('b3lyp-d') assert psi4.compare_values(ref_pbe_d2[2], psi4.variable('DISPERSION CORRECTION ENERGY'), 7, 'Ethene -D (alias)') psi4.activate(mA) psi4.set_options({'dft_dispersion_parameters': [1.0]}) psi4.energy('wb97x-d') assert psi4.compare_values(-0.000834247063, psi4.variable('DISPERSION CORRECTION ENERGY'), 7, 'Ethene wb97x-d (chg)') print(' non-default -D correction from Py-side') eneyne.update_geometry() eneyne.run_dftd3('b3lyp', 'd2', {'s6': 0.75}) assert psi4.compare_values(ref_pbe_d2[0], psi4.variable('DISPERSION CORRECTION ENERGY'), 7, 'Ethene-Ethyne -D2') mA = eneyne.extract_subsets(1) mA.run_dftd3('b3lyp', 'd2', {'s6': 0.75}) assert psi4.compare_values(ref_pbe_d2[1], psi4.variable('DISPERSION CORRECTION ENERGY'), 7, 'Ethene -D2') mB = eneyne.extract_subsets(2) mB.run_dftd3('b3lyp', 'd2', {'s6': 0.75}) assert psi4.compare_values(ref_pbe_d2[2], psi4.variable('DISPERSION CORRECTION ENERGY'), 7, 'Ethyne -D2') eneyne.run_dftd3('b3lyp', 'd3zero', {'s6': 1.0, 's8': 0.722, 'sr6': 1.217, 'alpha6': 14.0}) assert psi4.compare_values(ref_pbe_d3zero[0], psi4.variable('DISPERSION CORRECTION ENERGY'), 7, 'Ethene-Ethyne -D3 (zero)') mA = eneyne.extract_subsets(1) mA.run_dftd3('b3lyp', 'd3zero', {'s6': 1.0, 's8': 0.722, 'sr6': 1.217, 'alpha6': 14.0}) assert psi4.compare_values(ref_pbe_d3zero[1], psi4.variable('DISPERSION CORRECTION ENERGY'), 7, 'Ethene -D3 (zero)') mB = eneyne.extract_subsets(2) mB.run_dftd3('b3lyp', 'd3zero', {'s6': 1.0, 's8': 0.722, 'sr6': 1.217, 'alpha6': 14.0}) assert psi4.compare_values(ref_pbe_d3zero[2], psi4.variable('DISPERSION CORRECTION ENERGY'), 7, 'Ethyne -D3 (zero)') eneyne.run_dftd3('b3lyp', 'd3bj', {'s6': 1.000, 's8': 0.7875, 'a1': 0.4289, 'a2': 4.4407}) assert psi4.compare_values(ref_pbe_d3bj[0], psi4.variable('DISPERSION CORRECTION ENERGY'), 7, 'Ethene-Ethyne -D3 (bj)') mA = eneyne.extract_subsets(1) mA.run_dftd3('b3lyp', 'd3bj', {'s6': 1.000, 's8': 0.7875, 'a1': 0.4289, 'a2': 4.4407}) assert psi4.compare_values(ref_pbe_d3bj[1], psi4.variable('DISPERSION CORRECTION ENERGY'), 7, 'Ethene -D3 (bj)') mB = eneyne.extract_subsets(2) mB.run_dftd3('b3lyp', 'd3bj', {'s6': 1.000, 's8': 0.7875, 'a1': 0.4289, 'a2': 4.4407}) assert psi4.compare_values(ref_pbe_d3bj[2], psi4.variable('DISPERSION CORRECTION ENERGY'), 7, 'Ethyne -D3 (bj)') eneyne.run_dftd3('b3lyp', 'd3', {'s6': 1.0, 's8': 0.722, 'sr6': 1.217, 'alpha6': 14.0}) assert psi4.compare_values(ref_pbe_d3zero[0], psi4.variable('DISPERSION CORRECTION ENERGY'), 7, 'Ethene-Ethyne -D3 (alias)') eneyne.run_dftd3('b3lyp', 'd', {'s6': 0.75}) assert psi4.compare_values(ref_pbe_d2[0], psi4.variable('DISPERSION CORRECTION ENERGY'), 7, 'Ethene-Ethyne -D (alias)') eneyne.run_dftd3('b3lyp', 'd2', {'s6': 0.75}) assert psi4.compare_values(ref_pbe_d2[0], psi4.variable('DISPERSION CORRECTION ENERGY'), 7, 'Ethene-Ethyne -D2 (alias)')