From 0958633c0209cacd880949399c20e9594f932972 Mon Sep 17 00:00:00 2001 From: "Lori A. Burns" Date: Mon, 13 Jan 2025 20:48:42 -0500 Subject: [PATCH] post-Christmas opt/td --- docs/source/changelog.rst | 4 ++-- qcengine/procedures/torsiondrive.py | 8 ++++---- qcengine/programs/mrchem.py | 6 +++--- qcengine/tests/test_procedures.py | 30 +++++++++++++++++------------ 4 files changed, 27 insertions(+), 21 deletions(-) diff --git a/docs/source/changelog.rst b/docs/source/changelog.rst index c26e2455..c258a4be 100644 --- a/docs/source/changelog.rst +++ b/docs/source/changelog.rst @@ -71,8 +71,8 @@ Misc. MUST (Unmerged) +++++++++++++++ - (:pr:`462`) -- (:pr:`462`) -- (:pr:`462`) rdkit, store ``AtomicResult.properties.return_gradient`` and ``calcinfo_natom``. +- (:pr:`462`) adapt harnesses for TD.initial_molecules -> TD.initial_molecule and TD.optimization_history -> TD.scan_results +- (:pr:`462`) rdkit, store ``AtomicResult.properties.return_gradient`` and ``calcinfo_natom``. mrchem, store ``AtomicResult.properties.return_gradient``. - (:pr:`462`) lightly Adapt harnesses for Mol v3 - (:pr:`462`) Use packaging instead of setuptools to provide version parsing - (:pr:`462`) torsiondrive now accepts protocols. use ``protocols={"scan_results": "all"}`` if going to be converted to v1. diff --git a/qcengine/procedures/torsiondrive.py b/qcengine/procedures/torsiondrive.py index fe3dd93b..bfacaa79 100644 --- a/qcengine/procedures/torsiondrive.py +++ b/qcengine/procedures/torsiondrive.py @@ -54,8 +54,8 @@ def _compute(self, input_model: "TorsionDriveInput", config: "TaskConfig"): state = torsiondrive.td_api.create_initial_state( dihedrals=dihedrals, grid_spacing=grid_spacing, - elements=input_model.initial_molecules[0].symbols, - init_coords=[molecule.geometry.flatten().tolist() for molecule in input_model.initial_molecules], + elements=input_model.initial_molecule[0].symbols, + init_coords=[molecule.geometry.flatten().tolist() for molecule in input_model.initial_molecule], dihedral_ranges=dihedral_ranges, energy_upper_limit=energy_upper_limit, energy_decrease_thresh=energy_decrease_thresh, @@ -128,7 +128,7 @@ def _compute(self, input_model: "TorsionDriveInput", config: "TaskConfig"): output_data["final_energies"][grid_point] = final_energy output_data["final_molecules"][grid_point] = final_molecule - output_data["optimization_history"] = optimization_results + output_data["scan_results"] = optimization_results if error is not None: output_data["error"] = error @@ -185,7 +185,7 @@ def _spawn_optimization( from qcengine import compute - input_molecule = input_model.initial_molecules[0].copy(deep=True).dict() + input_molecule = input_model.initial_molecule[0].copy(deep=True).dict() input_molecule["geometry"] = np.array(job).reshape(len(input_molecule["symbols"]), 3) input_molecule = Molecule.from_data(input_molecule) diff --git a/qcengine/programs/mrchem.py b/qcengine/programs/mrchem.py index 561b1649..4be0bf9a 100644 --- a/qcengine/programs/mrchem.py +++ b/qcengine/programs/mrchem.py @@ -170,9 +170,9 @@ def compute(self, input_model: "AtomicInput", config: "TaskConfig") -> "AtomicRe if input_model.specification.driver == "energy": output_data["return_result"] = mrchem_output["properties"]["scf_energy"]["E_tot"] elif input_model.specification.driver == "gradient": - output_data["return_result"] = mrchem_output["properties"]["geometric_derivative"]["geom-1"][ - "total" - ] + grad = mrchem_output["properties"]["geometric_derivative"]["geom-1"]["total"] + output_data["return_result"] = grad + output_data["properties"]["return_gradient"] = grad elif input_model.specification.driver == "properties": output_data["return_result"] = { f"{ks[1]}": {f"{ks[2]}": _nested_get(mrchem_output, ks)} for ks in computed_rsp_props diff --git a/qcengine/tests/test_procedures.py b/qcengine/tests/test_procedures.py index bd402478..04d311b7 100644 --- a/qcengine/tests/test_procedures.py +++ b/qcengine/tests/test_procedures.py @@ -639,7 +639,7 @@ def test_torsiondrive_generic(schema_versions, request, scan_ptcl): if from_v2(request.node.name): input_data = models.TorsionDriveInput( - initial_molecules=[models.Molecule(**qcng.get_molecule("ethane", return_dict=True))] * 2, + initial_molecule=[models.Molecule(**qcng.get_molecule("ethane", return_dict=True))] * 2, specification=models.TorsionDriveSpecification( keywords=models.TorsionDriveKeywords(dihedrals=[(2, 0, 1, 5)], grid_spacing=[180]), protocols=models.TorsionDriveProtocols(scan_results=scan_ptcl), @@ -682,9 +682,10 @@ def test_torsiondrive_generic(schema_versions, request, scan_ptcl): assert ret.success expected_grid_ids = {"180", "0"} + opthist_tgt = ret.scan_results if "v2" in request.node.name else ret.optimization_history if not (from_v2(request.node.name) and scan_ptcl == "none"): - assert {*ret.optimization_history} == expected_grid_ids + assert {*opthist_tgt} == expected_grid_ids assert {*ret.final_energies} == expected_grid_ids assert {*ret.final_molecules} == expected_grid_ids @@ -700,22 +701,22 @@ def test_torsiondrive_generic(schema_versions, request, scan_ptcl): if from_v2(request.node.name): # properly "to_v1" should be always `== 4` but data lost in v2 by default if scan_ptcl == "none": - assert not ret.optimization_history + assert not opthist_tgt else: - assert len(ret.optimization_history["180"]) == {"lowest": 1, "all": 4}[scan_ptcl] + assert len(opthist_tgt["180"]) == {"lowest": 1, "all": 4}[scan_ptcl] else: - assert len(ret.optimization_history["180"]) == 4 + assert len(opthist_tgt["180"]) == 4 if not (from_v2(request.node.name) and scan_ptcl == "none"): - assert ret.optimization_history["180"][0].provenance.creator.lower() == "geometric" + assert opthist_tgt["180"][0].provenance.creator.lower() == "geometric" if "v2" in request.node.name: if scan_ptcl != "none": - assert ret.optimization_history["180"][0].trajectory_results[0].provenance.creator.lower() == "rdkit" - assert ret.optimization_history["180"][0].trajectory_results[0].schema_version == 2 + assert opthist_tgt["180"][0].trajectory_results[0].provenance.creator.lower() == "rdkit" + assert opthist_tgt["180"][0].trajectory_results[0].schema_version == 2 else: if not ("to_v1" in request.node.name and scan_ptcl == "none"): - assert ret.optimization_history["180"][0].trajectory[0].provenance.creator.lower() == "rdkit" - assert ret.optimization_history["180"][0].trajectory[0].schema_version == 1 + assert opthist_tgt["180"][0].trajectory[0].provenance.creator.lower() == "rdkit" + assert opthist_tgt["180"][0].trajectory[0].schema_version == 1 assert ret.stdout == "All optimizations converged at lowest energy. Job Finished!\n" @@ -737,6 +738,7 @@ def test_optimization_mrchem(input_data, optimizer, schema_versions, request): input_data["specification"]["specification"]["model"] = {"method": "HF"} input_data["specification"]["specification"]["keywords"] = {"world_prec": 1.0e-4} input_data["specification"]["specification"]["program"] = "mrchem" + input_data["specification"]["protocols"] = {"trajectory_results": "final"} # to test provenance else: input_data["input_specification"]["model"] = {"method": "HF"} input_data["input_specification"]["keywords"] = {"world_prec": 1.0e-4} @@ -748,9 +750,13 @@ def test_optimization_mrchem(input_data, optimizer, schema_versions, request): ret = qcng.compute(input_data, optimizer, raise_error=True, return_version=retver) ret = checkver_and_convert(ret, request.node.name, "post") - trajs_tgt = ret.trajectory_results if "v2" in request.node.name else ret.trajectory + trajs_tgt = ret.trajectory_results if "v2" in request.node.name else ret.trajectory # for looking at grad jobs + props_tgt = ret.trajectory_properties if "v2" in request.node.name else ret.energies # for counting opt iterations + + assert 10 > len(props_tgt) > 1 + if "v2" in request.node.name: + assert 10 > ret.properties.optimization_iterations > 1 - assert 10 > len(trajs_tgt) > 1 assert pytest.approx(ret.final_molecule.measure([0, 1]), 1.0e-3) == 1.3860734486984705 assert ret.provenance.creator.lower() == optimizer assert trajs_tgt[0].provenance.creator.lower() == "mrchem"