def test_mopac_task(): input_data = { "molecule": qcng.get_molecule("water"), "driver": "gradient", "model": { "method": "PM6", "basis": None }, "keywords": { "pulay": False }, } ret = qcng.compute(input_data, "mopac", raise_error=True) assert ret.extras.keys() >= { "heat_of_formation", "energy_electronic", "dip_vec" } energy = pytest.approx(-0.08474117913025125, rel=1.0e-5) # Check gradient ret = qcng.compute(input_data, "mopac", raise_error=True) assert ret.extras.keys() >= { "heat_of_formation", "energy_electronic", "dip_vec" } assert np.linalg.norm(ret.return_result) == pytest.approx( 0.03543560156912385, rel=1.0e-4) assert ret.properties.return_energy == energy # Check energy input_data["driver"] = "energy" ret = qcng.compute(input_data, "mopac", raise_error=True) assert ret.return_result == energy assert "== MOPAC DONE ==" in ret.stdout
def test_hess(nh2): resi = { "molecule": nh2, "driver": "hessian", "model": { "method": "b3lyp", "basis": "3-21g" } } res = qcng.compute(resi, "nwchem", raise_error=True, return_dict=False) assert compare_values(-3.5980754370e-02, res.return_result[0, 0], atol=1e-3) assert compare_values(0, res.return_result[1, 0], atol=1e-3) assert compare_values(0.018208307756, res.return_result[3, 0], atol=1e-3) assert np.allclose(res.return_result, res.return_result.T, atol=1e-8) # Should be symmetric about diagonal # Test that the Hessian changes with rotation, but that its determinants remain the same shifted_nh2, _ = nh2.scramble(do_shift=False, do_mirror=False, do_rotate=True, do_resort=False) resi["molecule"] = shifted_nh2 res_shifted = qcng.compute(resi, "nwchem", raise_error=True, return_dict=False) assert not np.allclose( res.return_result, res_shifted.return_result, atol=1e-8) assert np.isclose(np.linalg.det(res.return_result), np.linalg.det(res_shifted.return_result))
def test_openmm_task_url_basis(): from qcengine.programs.openmm import OpenMMHarness input_data = { "molecule": qcng.get_molecule("water"), "driver": "energy", "model": { "method": "openmm", "basis": "openff-1.0.0", "url": "https://raw.githubusercontent.com/openforcefield/openff-forcefields/1.0.0/openforcefields/offxml/openff-1.0.0.offxml", }, "keywords": {}, } ret = qcng.compute(input_data, "openmm", raise_error=True) cachelength = len(OpenMMHarness._CACHE) assert cachelength > 0 assert ret.success is True ret = qcng.compute(input_data, "openmm", raise_error=True) # ensure cache has not grown assert len(OpenMMHarness._CACHE) == cachelength assert ret.success is True
def test_sp_ccsd_t_uhf_fc_error(program, basis, keywords, nh2, errmsg): resi = {"molecule": nh2, "driver": "energy", "model": {"method": "ccsd(t)", "basis": basis}, "keywords": keywords} with pytest.raises(qcng.exceptions.InputError) as e: qcng.compute(resi, program, raise_error=True, return_dict=True) assert errmsg in str(e.value)
def test_compute_gradient(program, model, keywords): if not has_program(program): pytest.skip("Program '{}' not found.".format(program)) molecule = _get_molecule(program) inp = AtomicInput(molecule=molecule, driver="gradient", model=model, extras={"mytag": "something"}, keywords=keywords) if program in ["adcc", "mrchem"]: with pytest.raises(qcng.exceptions.InputError) as e: qcng.compute(inp, program, raise_error=True) assert "Driver gradient not implemented" in str(e.value) else: ret = qcng.compute(inp, program, raise_error=True) assert ret.success is True assert isinstance(ret.return_result, np.ndarray) assert len(ret.return_result.shape) == 2 assert ret.return_result.shape[1] == 3 assert "mytag" in ret.extras, ret.extras
def test_gradient(nh2): resi = { "molecule": nh2, "driver": "gradient", "model": {"method": "b3lyp", "basis": "3-21g"}, "keywords": {"dft__convergence__gradient": "1e-6"}, } res = qcng.compute(resi, "nwchem", raise_error=True, return_dict=True) assert compare_values(4.22418267e-2, res["return_result"][2], atol=1e-7) # Beyond accuracy of NWChem stdout # Rotate the molecule and verify that the gradient changes shifted_nh2, _ = nh2.scramble(do_shift=False, do_mirror=False, do_rotate=True, do_resort=False) resi["molecule"] = shifted_nh2 res_shifted = qcng.compute(resi, "nwchem", raise_error=True, return_dict=True) assert not compare_values(4.22418267e-2, res_shifted["return_result"][2], atol=1e-7) # Make sure the two matrices still have the same determinant and norms, as they are just rotations of each other # I am leveraging the fact that the gradients are square, 3x3 matrices just by happenstance of the # test molecule having 3 atoms orig_grads = np.reshape(res["return_result"], (-1, 3)) shif_grads = np.reshape(res_shifted["return_result"], (-1, 3)) # Test that the magnitude of forces are the same assert np.allclose(np.linalg.norm(orig_grads, ord=2, axis=1), np.linalg.norm(shif_grads, ord=2, axis=1)) # Test that the determinants are the same orig_det = np.linalg.det(orig_grads) shif_det = np.linalg.det(shif_grads) assert np.allclose(orig_det, shif_det)
def test_qchem_orientation(): mol = qcel.models.Molecule.from_data(""" He 0.0 0.7 0.7 He 0.0 -0.7 -0.7 """) # Compare with rotation inp = { "molecule": mol, "driver": "gradient", "model": { "method": "HF", "basis": "6-31g" } } ret = qcng.compute(inp, "qchem", raise_error=True) assert compare_values(np.linalg.norm(ret.return_result, axis=0), [0, 0, 0.00791539]) # Compare without rotations mol_noorient = mol.copy(update={"fix_orientation": True}) inp = { "molecule": mol_noorient, "driver": "gradient", "model": { "method": "HF", "basis": "6-31g" } } ret = qcng.compute(inp, "qchem", raise_error=True) assert compare_values(np.linalg.norm(ret.return_result, axis=0), [0, 0.00559696541, 0.00559696541])
def test_autoz_error(): """Test ability to turn off autoz""" # Large molecule that leads to an AutoZ error mol = qcel.models.Molecule.from_data(_auto_z_problem) result = qcng.compute( { "molecule": mol, "model": {"method": "hf", "basis": "sto-3g"}, "driver": "energy", "protocols": {"error_correction": {"default_policy": False}}, }, # Turn off error correction "nwchem", raise_error=False, ) assert not result.success assert "Error when generating redundant atomic coordinates" in result.error.error_message # Turn off autoz result = qcng.compute( { "molecule": mol, "model": {"method": "hf", "basis": "sto-3g"}, "driver": "energy", "keywords": {"geometry__noautoz": True}, }, "nwchem", raise_error=False, ) # Ok if it crashes for other reasons assert "Error when generating redundant atomic coordinates" not in result.error.error_message
def test_geometry_bug(): """Make sure that the harvester does not crash if NWChem's autosym moves atoms too far""" # Example molecule that has an RMSD of 2e-4 after NWChem symmetrizes the coordinates xyz = """6 Properties=species:S:1:pos:R:3 unique_id=2da214efcf4e4c277fabc5b2b6ca6f32 pbc="F F F" C -0.00828817 1.39046978 -0.00560069 O -0.00797038 -0.02504537 0.02030606 H 1.00658338 1.81556366 0.00348335 H -0.54657475 1.79916975 -0.87390126 H -0.52288871 1.72555240 0.89907326 H 0.44142019 -0.33354425 -0.77152059""" mol = qcel.models.Molecule.from_data(xyz) qcng.compute( { "molecule": mol, "model": { "method": "b3lyp", "basis": "6-31g" }, "driver": "gradient" }, "nwchem", raise_error=True, )
def test_openmm_task_smirnoff(): from qcengine.programs.openmm import OpenMMHarness input_data = { "molecule": qcng.get_molecule("water"), "driver": "energy", "model": { "method": "openff-1.0.0", "basis": "smirnoff" }, "keywords": {}, } ret = qcng.compute(input_data, "openmm", raise_error=True) cachelength = len(OpenMMHarness._CACHE) assert cachelength > 0 assert ret.success is True ret = qcng.compute(input_data, "openmm", raise_error=True) # ensure cache has not grown assert len(OpenMMHarness._CACHE) == cachelength assert ret.success is True
def test_openmm_gaff_keywords(gaff_settings): """ Test the different running settings with gaff. """ program = "openmm" water = qcng.get_molecule("water") water_dict = water.dict() # add water cmiles to the molecule water_dict["extras"] = { "cmiles": { "canonical_isomeric_explicit_hydrogen_mapped_smiles": "[H:2][O:1][H:3]" } } molecule = Molecule.from_data(water_dict) keywords, error, expected_result = gaff_settings model = {"method": "gaff-2.1", "basis": "antechamber"} inp = AtomicInput(molecule=molecule, driver="energy", model=model, keywords=keywords) if error is not None: with pytest.raises(error): _ = qcng.compute(inp, program, raise_error=True) else: ret = qcng.compute(inp, program, raise_error=False) assert ret.success is True assert ret.return_result == pytest.approx(expected_result, rel=1e-6)
def compute_gradient(self, molecule: core.Molecule, wfn: core.Wavefunction = None) -> core.Matrix: """Compute dispersion gradient based on engine, dispersion level, and parameters in `self`. Parameters ---------- molecule System for which to compute empirical dispersion correction. wfn Location to set QCVariables Returns ------- Matrix (nat, 3) dispersion gradient [Eh/a0]. """ if self.engine in ['dftd3', 'mp2d']: resi = AtomicInput( **{ 'driver': 'gradient', 'model': { 'method': self.fctldash, 'basis': '(auto)', }, 'keywords': { 'level_hint': self.dashlevel, 'params_tweaks': self.dashparams, 'dashcoeff_supplement': self.dashcoeff_supplement, 'verbose': 1, }, 'molecule': molecule.to_schema(dtype=2), 'provenance': p4util.provenance_stamp(__name__), }) jobrec = qcng.compute( resi, self.engine, raise_error=True, local_options={"scratch_directory": core.IOManager.shared_object().get_default_path()}) dashd_part = core.Matrix.from_array(jobrec.extras['qcvars']['DISPERSION CORRECTION GRADIENT']) if wfn is not None: for k, qca in jobrec.extras['qcvars'].items(): if "CURRENT" not in k: wfn.set_variable(k, float(qca) if isinstance(qca, str) else qca) if self.fctldash in ['hf3c', 'pbeh3c']: jobrec = qcng.compute( resi, "gcp", raise_error=True, local_options={"scratch_directory": core.IOManager.shared_object().get_default_path()}) gcp_part = core.Matrix.from_array(jobrec.return_result) dashd_part.add(gcp_part) return dashd_part else: return self.disp.compute_gradient(molecule)
def test_compute_energy_qcsk_basis(program, model, keywords): if not has_program(program): pytest.skip("Program '{}' not found.".format(program)) molecule = _get_molecule(program) inp = AtomicInput(molecule=molecule, driver="energy", model=model, keywords=keywords) with pytest.raises(qcng.exceptions.InputError) as e: qcng.compute(inp, program, raise_error=True) assert "QCSchema BasisSet for model.basis not implemented" in str(e.value)
def computeBE(self, method): print("") print("Calculate atomization energy with method: ", method) # Caculate energy for the whole molecule molecule_task = self.energyTask(self.molecule, method, self.program) print("Evaluating the energy of the whole molecule...") molecule_result = qcengine.compute(molecule_task, self.program) if self.record: filename = self.rundir + "/" + self.diagnostic_type + "_" \ + self.molname + "_" + method + "_" + "whole" + ".json" qcres_to_json(molecule_result, filename=filename) if not molecule_result.success: raise RuntimeError("Quantum chemistry calculation failed.") molecule_energy = molecule_result.return_result print("Final energy of the molecule (Hartree): {:.8f}".format(molecule_energy)) print("Evaluating the energy of the atomization limit of the molecule...") if not self.atomized: self.mol2atoms() # Calculate energy for each unique atom at the atomization limit for symbol in self.atomized: atom_result = None if self.program == "terachem" and symbol == "H": atom_task = self.energyTask(self.atomized[symbol]["molecule"], method, "psi4") atom_result = qcengine.compute(atom_task, "psi4") else: atom_task = self.energyTask(self.atomized[symbol]["molecule"], method, self.program) atom_result = qcengine.compute(atom_task, self.program) if not atom_result.success: raise RuntimeError("Quantum chemistry calculation failed.") if self.record: filename = self.rundir + "/" + self.diagnostic_type + "_"\ + self.molname + "_" + method + "_" + symbol + ".json" qcres_to_json(atom_result, filename=filename) atom_energy = atom_result.return_result print("Final energy of atom ", symbol, " (Hartree): {:.8f}".format(atom_energy)) self.atomized[symbol]["energy"] = atom_energy # Calculate BE BE = 0 for symbol in self.atomized: BE += self.atomized[symbol]["energy"] * self.atomized[symbol]["count"] print("Final energy of the atomized limit (Hartree): {:.8f}".format(BE)) BE = BE - molecule_energy print("Atomization energy (Hartree): {:.8f}".format(BE)) print("") return BE
def test_rdkit_connectivity_error(): json_data = copy.deepcopy(_base_json) json_data["molecule"] = qcng.get_molecule("water").dict() json_data["driver"] = "gradient" json_data["model"] = {"method": "UFF", "basis": ""} json_data["keywords"] = {} del json_data["molecule"]["connectivity"] ret = qcng.compute(json_data, "rdkit") assert ret.success is False assert "connectivity" in ret.error.error_message with pytest.raises(qcng.exceptions.InputError): qcng.compute(json_data, "rdkit", raise_error=True)
def test_random_failure_no_retries(failure_engine): failure_engine.iter_modes = ["input_error"] ret = qcng.compute(failure_engine.get_job(), failure_engine.name, raise_error=False) assert ret.error.error_type == "input_error" assert "retries" not in ret.input_data["provenance"].keys() failure_engine.iter_modes = ["random_error"] ret = qcng.compute(failure_engine.get_job(), failure_engine.name, raise_error=False) assert ret.error.error_type == "random_error" assert "retries" not in ret.input_data["provenance"].keys()
def test_homo_lumo(h20v2): # Run NH2 resi = { "molecule": h20v2, "driver": "energy", "model": {"method": "dft", "basis": "3-21g"}, "keywords": {"dft__xc": "b3lyp"}, } res = qcng.compute(resi, "nwchem", raise_error=True, return_dict=True) # Make sure the calculation completed successfully assert compare_values(-75.968095, res["return_result"], atol=1e-3) assert res["driver"] == "energy" assert "provenance" in res assert res["success"] is True # Check the other status information assert res["extras"]["qcvars"]["N ALPHA ELECTRONS"] == "5" assert res["extras"]["qcvars"]["N ATOMS"] == "3" assert res["extras"]["qcvars"]["N BASIS FUNCTIONS"] == "13" # Make sure the properties parsed correctly assert compare_values(-75.968095, res["properties"]["return_energy"], atol=1e-3) assert res["properties"]["calcinfo_natom"] == 3 assert res["properties"]["calcinfo_nalpha"] == 5 assert res["properties"]["calcinfo_nbasis"] == 13 # Make sure Dipole Moment and center of charge parsed correctly assert compare_values(-0.2636515, float(res["extras"]["qcvars"]["H**O"][0]), atol=1e-5) assert compare_values(0.08207131, float(res["extras"]["qcvars"]["LUMO"][0]), atol=1e-5)
def test_sp_mp2_rhf_full(program, basis, keywords, h2o): """cfour/sp-rhf-ccsd/input.dat #! single point MP2/adz on water """ resi = { "molecule": h2o, "driver": "energy", "model": { "method": "mp2", "basis": basis }, "keywords": keywords } res = qcng.compute(resi, program, raise_error=True, return_dict=True) assert res["driver"] == "energy" assert "provenance" in res assert res["success"] is True # aug-cc-pvdz mp2_tot = -76.2632792578 atol = 1.0e-6 assert compare_values(mp2_tot, res["return_result"], atol=atol)
def test_xtb_task_cold_fusion(): atomic_input = qcel.models.AtomicInput( molecule={ "symbols": ["Li", "Li", "Li", "Li"], "geometry": [ [-1.58746019997201, +1.58746019997201, +1.58746019997201], [-1.58746019997201, +1.58746019997201, +1.58746019997201], [-1.58746019997201, -1.58746019997201, -1.58746019997201], [+1.58746019997201, +1.58746019997201, -1.58746019997201], ], "validated": True, # Force a nuclear fusion input, to make xtb fail }, model={"method": "GFN2-xTB"}, driver="energy", ) error = qcel.models.ComputeError( error_type="runtime_error", error_message="Setup of molecular structure failed:\n-1- xtb_api_newMolecule: Could not generate molecular structure", ) atomic_result = qcng.compute(atomic_input, "xtb") assert not atomic_result.success assert atomic_result.error == error
def test_mp2d(): 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 """) mol = eneyne.to_schema(dtype=2) expected = 0.00632174635953 resinp = { 'schema_name': 'qcschema_input', 'schema_version': 1, 'molecule': mol, 'driver': 'energy', #gradient', 'model': { 'method': 'mp2d-mp2-dmp2' }, 'keywords': {}, } jrec = qcng.compute(resinp, 'mp2d', raise_error=True) jrec = jrec.dict() assert psi4.compare_values(expected, jrec['extras']['qcvars']['CURRENT ENERGY'], 7, 'E') assert psi4.compare_values(expected, jrec['extras']['qcvars']['DISPERSION CORRECTION ENERGY'], 7, 'disp E') assert psi4.compare_values(expected, jrec['extras']['qcvars']['MP2-DMP2 DISPERSION CORRECTION ENERGY'], 7, 'mp2d disp E')
def test_xtb_task_gfn1xtb_m01(): thr = 1.0e-7 return_result = np.array( [ [-0.000358030800412827, +0.000500962437171796, -0.009256666294614777], [+0.001228927299439432, +0.000322925070197139, +0.002327951513695912], [-0.000336383869223903, +0.023413253286994400, -0.003233956461896982], [+0.004257485938529293, -0.003712584842768384, +0.000112655448628981], [+0.001349484431325273, +0.001591703446467543, -0.001444564232184169], [+0.001902096016850091, -0.010806282150986885, -0.002612898358134064], [-0.000694337971868170, -0.003558134599236037, +0.002566433298563669], [-0.003819207888143676, -0.000529277869208852, +0.004041924390207515], [-0.000170900544431631, +0.009573597947311165, +0.008463731042553293], [+0.004036505931939967, +0.003025020761338415, -0.004557936832112239], [+0.004790375712217767, -0.006895073623195738, +0.006111995172986280], [-0.001527116100844721, -0.005269034163367844, -0.008340510436175520], [-0.005441057023457164, +0.003102606807119279, +0.000817922187552893], [-0.003996677758010005, -0.021839390583571504, +0.010361632086933262], [-0.003219908482914395, +0.017669626267348096, -0.011084538678920158], [+0.001998745109004805, -0.006589918191612544, +0.005726826152916107], ] ) atomic_input = qcel.models.AtomicInput( molecule=qcng.get_molecule("mindless-01"), model={"method": "GFN1-xTB"}, driver="gradient", ) atomic_result = qcng.compute(atomic_input, "xtb") assert atomic_result.success assert pytest.approx(atomic_result.return_result, thr) == return_result
def test_xtb_task_gfn2xtb_m01(): thr = 1.0e-7 return_result = np.array( [ [+1.7603980711827444e-03, -1.0892843650556535e-03, -1.4000925937447548e-02], [+7.2828551455461962e-03, -3.7216708563619287e-04, -1.7598863191610557e-03], [-4.3636138516365761e-04, +3.0781059500885385e-02, -2.4027777032994326e-03], [-4.9615553784293671e-03, +2.4184700438294312e-03, -1.8273143544031206e-03], [-3.1941473089998765e-03, -2.0177319546503510e-03, +6.0230398095918502e-03], [+3.5807344500847016e-03, -2.3730921963802166e-03, -2.0271824139507818e-03], [+1.0323930350176554e-03, +3.3301666520180575e-04, +2.6197885276710883e-03], [+6.4140580960895879e-03, -1.0424376542844720e-02, +1.7654830175669090e-02], [+2.1841001857333085e-03, +8.5100245114072097e-03, -6.7175792414255900e-03], [+8.1719403581595913e-03, +7.3797085798300455e-03, -7.5901731542113542e-03], [+1.1557950311395539e-03, -4.1907703068314668e-04, +1.7047910821890132e-03], [-4.5861988817335895e-03, -2.1269884595520816e-02, -1.4002736618139961e-02], [+1.1542155825459586e-04, +8.6721397831818186e-03, +3.9953426868203148e-03], [-1.8552117264088834e-03, -2.0185103100139296e-02, +1.3339454522070686e-02], [-2.9643338287258375e-03, -4.2193920947953519e-03, +6.6460843884674770e-06], [-1.3699887421746685e-02, +4.2756898813700889e-03, +4.9846828536382450e-03], ] ) atomic_input = qcel.models.AtomicInput( molecule=qcng.get_molecule("mindless-01"), model={"method": "GFN2-xTB"}, driver="gradient", ) atomic_result = qcng.compute(atomic_input, "xtb") assert atomic_result.success assert pytest.approx(atomic_result.return_result, thr) == return_result
def test_run(h2o): inp = qcel.models.AtomicInput(molecule=h2o, driver="properties", model={ "method": "adc2", "basis": "sto-3g" }, keywords={"n_singlets": 3}) ret = qcng.compute(inp, "adcc", raise_error=True, local_options={"ncores": 1}, return_dict=True) ref_excitations = np.array( [0.0693704245883876, 0.09773854881340478, 0.21481589246935925]) ref_hf_energy = -74.45975898670224 ref_mp2_energy = -74.67111187456267 assert ret["success"] is True qcvars = ret["extras"]["qcvars"] assert qcvars["EXCITATION KIND"] == "SINGLET" assert compare_values(ref_excitations[0], ret["return_result"]) assert compare_values(ref_hf_energy, ret["properties"]["scf_total_energy"]) assert compare_values(ref_mp2_energy, ret["properties"]["mp2_total_energy"]) assert compare_values(ref_excitations, qcvars["ADC2 EXCITATION ENERGIES"])
def run_cfour(name, molecule, options, **kwargs): """QCDB API to QCEngine connection for CFOUR.""" resi = ResultInput( **{ 'driver': inspect.stack()[1][3], 'extras': { 'qcdb:options': copy.deepcopy(options), }, 'model': { 'method': name, 'basis': '(auto)', }, 'molecule': molecule.to_schema(dtype=2), 'provenance': provenance_stamp(__name__), }) jobrec = qcng.compute(resi, "qcdb-cfour", raise_error=True).dict() hold_qcvars = jobrec['extras'].pop('qcdb:qcvars') jobrec['qcvars'] = { key: qcel.Datum(**dval) for key, dval in hold_qcvars.items() } return jobrec
def test_sp_ccsd_rhf_full(program, basis, keywords, h2o): """cfour/sp-rhf-ccsd/input.dat #! single point CCSD/qz2p on water """ resi = { "molecule": h2o, "driver": "energy", "model": { "method": "ccsd", "basis": basis }, "keywords": keywords, } res = qcng.compute(resi, program, raise_error=True, return_dict=True) assert res["driver"] == "energy" assert "provenance" in res assert res["success"] is True # aug-cc-pvdz scftot = -76.0413815332 mp2tot = -76.2632792578 mp2corl = -0.2218977246 ccsdcorl = -0.2294105794 ccsdtot = -76.2707921127 atol = 1.e-6 #assert compare_values(scftot, qcdb.variable('scf total energy'), tnm() + ' SCF', atol=atol) #if not (mtd == 'nwc-ccsd' and keywords.get('qc_module', 'nein').lower() == 'tce'): # assert compare_values(mp2tot, qcdb.variable('mp2 total energy'), tnm() + ' MP2', atol=atol) #assert compare_values(ccsdcorl, qcdb.variable('ccsd correlation energy'), tnm() + ' CCSD corl', atol=atol) assert compare_values(ccsdtot, res["return_result"], atol=atol)
def test_sp_ccsd_rohf_full(program, basis, keywords, nh2): resi = { "molecule": nh2, "driver": "energy", "model": { "method": "ccsd", "basis": basis }, "keywords": keywords, } res = qcng.compute(resi, program, raise_error=True, return_dict=True) assert res["driver"] == "energy" assert "provenance" in res assert res["success"] is True # aug-cc-pvdz scftot = -55.570724348574 ssccsdcorl = -0.0339827 osccsdcorl = -0.1442533 ccsdcorl = -0.178236032911 ccsdtot = -55.748960381485 atol = 1.e-6 #assert compare_values(scftot, qcdb.variable('scf total energy'), tnm() + 'SCF', atol=atol) #if not (method in ['gms-ccsd', 'nwc-ccsd']): # # cfour isn't splitting out the singles from OS. and psi4 isn't incl the singles in either so SS + OS != corl # # and maybe singles moved from SS to OS in Cfour btwn 2010 and 2014 versions (change in ref) # # assert compare_values(osccsdcorl, qcdb.variable('ccsd opposite-spin correlation energy'), tnm() + ' CCSD OS corl', atol=atol) # assert compare_values(ssccsdcorl, qcdb.variable('ccsd same-spin correlation energy'), tnm() + ' CCSD SS corl', atol=atol) #assert compare_values(ccsdcorl, qcdb.variable('ccsd correlation energy'), tnm() + ' CCSD corl', atol=atol) #assert compare_values(ccsdtot, qcdb.variable('ccsd total energy'), tnm() + ' CCSD', atol=atol) #assert compare_values(ccsdcorl, qcdb.variable('current correlation energy'), tnm() + ' Current corl', atol=atol) assert compare_values(ccsdtot, res["return_result"], atol=atol)
def test_mp2d(): 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 """) mol = eneyne.to_schema(dtype=2) expected = 0.00632174635953 resinp = { 'schema_name': 'qcschema_input', 'schema_version': 1, 'molecule': mol, 'driver': 'energy', #gradient', 'model': { 'method': 'mp2d-mp2-dmp2' }, 'keywords': {}, } jrec = qcng.compute(resinp, 'mp2d', raise_error=True) jrec = jrec.dict() assert psi4.compare_values(expected, jrec['extras']['qcvars']['CURRENT ENERGY'], 7, 'E') assert psi4.compare_values(expected, jrec['extras']['qcvars']['DISPERSION CORRECTION ENERGY'], 7, 'disp E') assert psi4.compare_values(expected, jrec['extras']['qcvars']['MP2-DMP2 DISPERSION CORRECTION ENERGY'], 7, 'mp2d disp E')
def test_openmm_cmiles_gradient_nomatch(): program = "openmm" water = qcng.get_molecule("water") water_dict = water.dict() # add ethane cmiles to the molecule water_dict["extras"] = { "cmiles": { "canonical_isomeric_explicit_hydrogen_mapped_smiles": "[H:3][C:1]([H:4])([H:5])[C:2]([H:6])([H:7])[H:8]" } } molecule = Molecule.from_data(water_dict) model = {"method": "openff-1.0.0", "basis": "smirnoff"} inp = AtomicInput(molecule=molecule, driver="gradient", model=model) ret = qcng.compute(inp, program, raise_error=False) # if we correctly find the cmiles this should fail as the molecule and cmiles are different assert ret.success is False assert ( "molecule.add_conformer given input of the wrong shape: Given (3, 3), expected (8, 3)" in ret.error.error_message)
def test_dftd4_task_cold_fusion(): atomic_input = qcel.models.AtomicInput( molecule={ "symbols": ["Li", "Li", "Li", "Li"], "geometry": [ [-1.58746019997201, +1.58746019997201, +1.58746019997201], [-1.58746019997201, +1.58746019997201, +1.58746019997201], [-1.58746019997201, -1.58746019997201, -1.58746019997201], [+1.58746019997201, +1.58746019997201, -1.58746019997201], ], "validated": True, # Force a nuclear fusion input, to make dftd4 fail }, keywords={"level_hint": "D4"}, model={"method": "pbe"}, driver="energy", ) error = qcel.models.ComputeError( error_type="input error", error_message="Too close interatomic distances found", ) atomic_result = qcng.compute(atomic_input, "dftd4") print(atomic_result.error) assert not atomic_result.success assert atomic_result.error == error
def test_mp2d__run_mp2d__2body(inp, subjects, request): subject = subjects()[inp['parent']][inp['subject']] expected = ref[inp['parent']][inp['lbl']][inp['subject']] gexpected = gref[inp['parent']][inp['lbl']][inp['subject']].ravel() if 'qcmol' in request.node.name: mol = subject else: mol = subject.to_schema(dtype=2) resinp = { 'schema_name': 'qcschema_input', 'schema_version': 1, 'molecule': mol, 'driver': 'gradient', 'model': { 'method': inp['name'] }, 'keywords': {}, } jrec = qcng.compute(resinp, 'mp2d', raise_error=True) jrec = jrec.dict() #assert len(jrec['extras']['qcvars']) == 8 assert compare_values(expected, jrec['extras']['qcvars']['CURRENT ENERGY'], atol=1.e-7) assert compare_values(expected, jrec['extras']['qcvars']['DISPERSION CORRECTION ENERGY'], atol=1.e-7) assert compare_values(expected, jrec['extras']['qcvars'][inp['lbl'] + ' DISPERSION CORRECTION ENERGY'], atol=1.e-7) assert compare_values(gexpected, jrec['extras']['qcvars']['CURRENT GRADIENT'], atol=1.e-7) assert compare_values(gexpected, jrec['extras']['qcvars']['DISPERSION CORRECTION GRADIENT'], atol=1.e-7) assert compare_values(gexpected, jrec['extras']['qcvars'][inp['lbl'] + ' DISPERSION CORRECTION GRADIENT'], atol=1.e-7)
def test_b3lyp(nh2): # Run NH2 resi = { "molecule": nh2, "driver": "energy", "model": { "method": "b3lyp", "basis": "3-21g" } } res = qcng.compute(resi, "nwchem", raise_error=True, return_dict=True) # Make sure the calculation completed successfully assert compare_values(-55.554037, res["return_result"], atol=1e-3) assert res["driver"] == "energy" assert "provenance" in res assert res["success"] is True # Check the other status information assert res["extras"]["qcvars"]["N ALPHA ELECTRONS"] == "5" assert res["extras"]["qcvars"]["N ATOMS"] == "3" assert res["extras"]["qcvars"]["N BASIS"] == "13" # Make sure the properties parsed correctly assert compare_values(-55.554037, res["properties"]["return_energy"], atol=1e-3) assert res["properties"]["calcinfo_natom"] == 3 assert res["properties"]["calcinfo_nalpha"] == 5 assert res["properties"]["calcinfo_nbasis"] == 13
def test_dftd3__run_dftd3__2body(inp, subjects, request): subject = subjects()[inp['parent']][inp['subject']] expected = ref[inp['parent']][inp['lbl']][inp['subject']] gexpected = gref[inp['parent']][inp['lbl']][inp['subject']].ravel() if 'qcmol' in request.node.name: mol = subject else: mol = subject.to_schema(dtype=2) resinp = { 'schema_name': 'qcschema_input', 'schema_version': 1, 'molecule': mol, 'driver': 'gradient', 'model': { 'method': inp['name'] }, 'keywords': {}, } jrec = qcng.compute(resinp, 'dftd3', raise_error=True) jrec = jrec.dict() assert len(jrec['extras']['qcvars']) == 8 assert compare_values(expected, jrec['extras']['qcvars']['CURRENT ENERGY'], atol=1.e-7) assert compare_values(expected, jrec['extras']['qcvars']['DISPERSION CORRECTION ENERGY'], atol=1.e-7) assert compare_values(expected, jrec['extras']['qcvars']['2-BODY DISPERSION CORRECTION ENERGY'], atol=1.e-7) assert compare_values(expected, jrec['extras']['qcvars'][inp['lbl'] + ' DISPERSION CORRECTION ENERGY'], atol=1.e-7) assert compare_values(gexpected, jrec['extras']['qcvars']['CURRENT GRADIENT'], atol=1.e-7) assert compare_values(gexpected, jrec['extras']['qcvars']['DISPERSION CORRECTION GRADIENT'], atol=1.e-7) assert compare_values(gexpected, jrec['extras']['qcvars']['2-BODY DISPERSION CORRECTION GRADIENT'], atol=1.e-7) assert compare_values( gexpected, jrec['extras']['qcvars'][inp['lbl'] + ' DISPERSION CORRECTION GRADIENT'], atol=1.e-7)
def compute_energy(self, molecule): """Compute dispersion energy based on engine, dispersion level, and parameters in `self`. Parameters ---------- molecule : psi4.core.Molecule System for which to compute empirical dispersion correction. Returns ------- float Dispersion energy [Eh]. Notes ----- DISPERSION CORRECTION ENERGY Disp always set. Overridden in SCF finalization, but that only changes for "-3C" methods. self.fctldash + DISPERSION CORRECTION ENERGY Set if `fctldash` nonempty. """ if self.engine in ['dftd3', 'mp2d']: resinp = { 'schema_name': 'qcschema_input', 'schema_version': 1, 'molecule': molecule.to_schema(dtype=2), 'driver': 'energy', 'model': { 'method': self.fctldash, 'basis': '(auto)', }, 'keywords': { 'level_hint': self.dashlevel, 'params_tweaks': self.dashparams, 'dashcoeff_supplement': self.dashcoeff_supplement, 'verbose': 1, }, } jobrec = qcng.compute(resinp, self.engine, raise_error=True) jobrec = jobrec.dict() dashd_part = float(jobrec['extras']['qcvars']['DISPERSION CORRECTION ENERGY']) for k, qca in jobrec['extras']['qcvars'].items(): if not isinstance(qca, (list, np.ndarray)): core.set_variable(k, qca) if self.fctldash in ['hf3c', 'pbeh3c']: gcp_part = gcp.run_gcp(molecule, self.fctldash, verbose=False, dertype=0) dashd_part += gcp_part return dashd_part else: ene = self.disp.compute_energy(molecule) core.set_variable('DISPERSION CORRECTION ENERGY', ene) if self.fctldash: core.set_variable('{} DISPERSION CORRECTION ENERGY'.format(self.fctldash), ene) return ene
def test_dftd3_task(method): json_data = {"molecule": qcng.get_molecule("eneyne"), "driver": "energy", "model": {"method": method}} ret = qcng.compute(json_data, "dftd3", raise_error=True, return_dict=True) assert ret["driver"] == "energy" assert "provenance" in ret assert "normal termination of dftd3" in ret["stdout"] for key in ["cpu", "hostname", "username", "wall_time"]: assert key in ret["provenance"] assert ret["success"] is True
def calc_new(self, coords, dirname): import qcengine new_schema = deepcopy(self.schema) new_schema["molecule"]["geometry"] = coords.tolist() new_schema.pop("program", None) ret = qcengine.compute(new_schema, self.program, return_dict=True) # store the schema_traj for run_json to pick up self.schema_traj.append(ret) if ret["success"] is False: raise QCEngineAPIEngineError("QCEngineAPI computation did not execute correctly. Message: " + ret["error"]["error_message"]) # Unpack the energy and gradient energy = ret["properties"]["return_energy"] gradient = np.array(ret["return_result"]) return {'energy':energy, 'gradient':gradient}
def compute_gradient(self, molecule): """Compute dispersion gradient based on engine, dispersion level, and parameters in `self`. Parameters ---------- molecule : psi4.core.Molecule System for which to compute empirical dispersion correction. Returns ------- psi4.core.Matrix (nat, 3) dispersion gradient [Eh/a0]. """ if self.engine in ['dftd3', 'mp2d']: resinp = { 'schema_name': 'qcschema_input', 'schema_version': 1, 'molecule': molecule.to_schema(dtype=2), 'driver': 'gradient', 'model': { 'method': self.fctldash, 'basis': '(auto)', }, 'keywords': { 'level_hint': self.dashlevel, 'params_tweaks': self.dashparams, 'dashcoeff_supplement': self.dashcoeff_supplement, 'verbose': 1, }, } jobrec = qcng.compute(resinp, self.engine, raise_error=True) jobrec = jobrec.dict() dashd_part = core.Matrix.from_array(np.array(jobrec['extras']['qcvars']['DISPERSION CORRECTION GRADIENT']).reshape(-1, 3)) for k, qca in jobrec['extras']['qcvars'].items(): if not isinstance(qca, (list, np.ndarray)): core.set_variable(k, qca) if self.fctldash in ['hf3c', 'pbeh3c']: gcp_part = gcp.run_gcp(molecule, self.fctldash, verbose=False, dertype=1) dashd_part.add(gcp_part) return dashd_part else: return self.disp.compute_gradient(molecule)
def test_3(): sys = qcel.molparse.from_string(seneyne)['qm'] resinp = { 'schema_name': 'qcschema_input', 'schema_version': 1, 'molecule': qcel.molparse.to_schema(sys, dtype=2), 'driver': 'energy', 'model': { 'method': 'b3lyp', }, 'keywords': { 'level_hint': 'd3bj' }, } res = qcng.compute(resinp, 'dftd3', raise_error=True) res = res.dict() #res = dftd3.run_dftd3_from_arrays(molrec=sys, name_hint='b3lyp', level_hint='d3bj') assert compare('B3LYP-D3(BJ)', _compute_key(res['extras']['info']), 'key')