Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Csse layout 536g #367

Draft
wants to merge 3 commits into
base: next2025
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 25 additions & 26 deletions docs/changelog.rst
Original file line number Diff line number Diff line change
Expand Up @@ -33,40 +33,39 @@ New Features
++++++++++++
* Downstream code should ``from qcelemental.models.v1 import Molecule, AtomicResult`` etc. to assure medium-term availability of existing models.
* New pydantic v2 models available as ``from qcelemental.models.v2 import Molecule, AtomicResult`` etc.
- (:pr:`361`) Switch from poetry to setuptools build backend.

Enhancements
++++++++++++
- (:pr:`364`)
- (:pr:`364`)
- (:pr:`364`)
- (:pr:`364`) main storage for ``v2.TorsionDriveResult`` moved from ``optimization_history`` to ``scan_results``.
- (:pr:`364`) ``v2.TorsionDriveInput.initial_molecule`` restored from ``initial_molecules``.
- (:pr:`364`) default of OptimizationProtocol.trajectory_results changed to "none" from "all" in v1. much info can now come from properties.
- (:pr:`364`) v2.OptimizationProtocol renamed trajectory_results from trajectory in accordance with the protocol naming the controlled field. no default change yet.
- (:pr:`364`) v1/v2: import ElectronShell, BasisCenter, ECPPotential from top level models
- (:pr:`364`) molparse learns to pass through schema v3, though no new field for Mol yet.
- (:pr:`364`) ``v2.FailedOperation`` gained schema_name and schema_version=2. unversioned in v1
- (:pr:`364`) ``v2.BasisSet.schema_version`` is now 2, with no layout change.
- (:pr:`364`) ``v2.Molecule.schema_version`` is now 3. convert_v of all the models learned to handle the new schema_version.
- (:pr:`364`) v2: standardizing on In/Res get versions, Ptcl/Kw/Spec get only schema_name. At, Opt, TD
- (:pr:`364`) v1/v2: removing the version_stamps from the models: At, Opt, TD, Fail, BAsis, Mol. so it will error rather than clobber if constructed with wrong version. convert_v now handles.
- (:pr:`364`) convert_v functions learned to handle model.basis=BasisSet, not just str.
- (:pr:`364`) ``Molecule`` and ``BasisSet`` and ``WavefunctionProperties`` learned to ``convert_v`` to interconvert between v1 and v2. No layout changes.
- (:pr:`361`) Switch from poetry to setuptools build backend.

Enhancements
++++++++++++
- (:pr:`367`) ``v1.TorsionDriveResult.final_energies`` replaced by larger ``v2.TorsionDriveResult.scan_properties``. the former is present in the latter as ``return_energy``.
- (:pr:`367`) ``v2.TorsionDriveProperties`` added mostly as a placeholder class (one obvious prop at present).
- (:pr:`366`) main storage for ``v2.TorsionDriveResult`` moved from ``optimization_history`` to ``scan_results``.
- (:pr:`366`) ``v2.TorsionDriveInput.initial_molecule`` restored from ``initial_molecules``.
- (:pr:`366`) default of OptimizationProtocol.trajectory_results changed to "none" from "all" in v1. much info can now come from properties.
- (:pr:`366`) v2.OptimizationProtocol renamed trajectory_results from trajectory in accordance with the protocol naming the controlled field. no default change yet.
- (:pr:`366`) v1/v2: import ElectronShell, BasisCenter, ECPPotential from top level models
- (:pr:`366`) molparse learns to pass through schema v3, though no new field for Mol yet.
- (:pr:`366`) ``v2.FailedOperation`` gained schema_name and schema_version=2. unversioned in v1
- (:pr:`366`) ``v2.BasisSet.schema_version`` is now 2, with no layout change.
- (:pr:`366`) ``v2.Molecule.schema_version`` is now 3. convert_v of all the models learned to handle the new schema_version.
- (:pr:`366`) v2: standardizing on In/Res get versions, Ptcl/Kw/Spec get only schema_name. At, Opt, TD
- (:pr:`366`) v1/v2: removing the version_stamps from the models: At, Opt, TD, Fail, BAsis, Mol. so it will error rather than clobber if constructed with wrong version. convert_v now handles.
- (:pr:`366`) convert_v functions learned to handle model.basis=BasisSet, not just str.
- (:pr:`366`) ``Molecule`` and ``BasisSet`` and ``WavefunctionProperties`` learned to ``convert_v`` to interconvert between v1 and v2. No layout changes.
``BasisSet.schema_name`` standardized to ``qcschema_basis_set``.
Both classes get their ``schema_name`` as Literal now
- (:pr:`360`) ``Molecule`` learned new functions ``element_composition`` and ``molecular_weight``.
The first gives a dictionary of element symbols and counts, while the second gives the weight in amu.
Both can access the whole molecule or per-fragment like the existing ``nelectrons`` and
``nuclear_repulsion_energy``. All four can now select all atoms or exclude ghosts (default).
- (:pr:`364`) separated procedures.py and renamed results.py so models are separated into atomic.py, optimization.py, torsion_drive.py, failure models moved to failed_operation.py. basis.py to basis_set.py
- (:pr:`364`) ``schema_name`` output chanded to result ``qcschema_output`` to ``qcschema_atomic_result``. also opt
- (:pr:`364`) ``TDKeywords`` renamed to ``TorsionDriveKeywords``
- (:pr:`364`) ``AtomicResultProtocols`` renamed to ``AtomicProtocols`` and ``AtomicResultProperties`` to ``AtomicProperties``
- (:pr:`364`) new ``v2.TorsionDriveProtocols`` model with field ``scan_results`` to control all/none/lowest saving of optimizationresults at each grid point. Use "all" for proper conversion to v1.
- (:pr:`366`) separated procedures.py and renamed results.py so models are separated into atomic.py, optimization.py, torsion_drive.py, failure models moved to failed_operation.py. basis.py to basis_set.py
- (:pr:`366`) ``schema_name`` output chanded to result ``qcschema_output`` to ``qcschema_atomic_result``. also opt
- (:pr:`366`) ``TDKeywords`` renamed to ``TorsionDriveKeywords``
- (:pr:`366`) ``AtomicResultProtocols`` renamed to ``AtomicProtocols`` and ``AtomicResultProperties`` to ``AtomicProperties``
- (:pr:`366`) new ``v2.TorsionDriveProtocols`` model with field ``scan_results`` to control all/none/lowest saving of optimizationresults at each grid point. Use "all" for proper conversion to v1.
- (:pr:`363`) ``v2.TorsionDriveResult`` no longer inherits from Input and now has indep id and extras and new native_files.
- (:pr:`363`) ``v2.TorsionDriveInput.initial_molecule`` now ``initial_molecules`` as it's a list of >=1 molecules. keep change?
- (:pr:`363`) ``v2. TorsionDriveSpecification`` is a new model. instead of ``v2.TorsionDriveInput`` having a ``input_specification`` and an ``optimization_spec`` fields, it has a ``specification`` field that is a ``TorsionDriveSpecification`` which in turn hold opt info and in turn gradient/atomic info.
- (:pr:`363`) ``v2. TorsionDriveSpecification`` is a new model. instead of ``v2.TorsionDriveInput`` having a ``input_specification`` and an ``optimization_spec`` fields, it has a ``specification`` field that is a ``TorsionDriveSpecification`` which in turn hold opt info and in turn gradient/atomic info.
- (:pr:`363`) ``v2.TDKeywords`` got a ``schema_name`` field.
- (:pr:`363`) ``native_files`` field added to ``v2.OptimizationResult`` and ``v2.TorsionDriveResult`` gained a ``native_files`` field, though not protocols for user control.
- (:pr:`363`) ``v2.AtomicResult.convert_v()`` learned external_protocols option to inject that field if known from OptIn
Expand Down
4 changes: 2 additions & 2 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ build-backend = "setuptools.build_meta"

[project.urls]
homepage = "https://github.com/MolSSI/QCElemental"
changelog = "https://github.com/MolSSI/QCElemental/docs/changelog.rst"
documentation = "http://docs.qcarchive.molssi.org/projects/qcelemental/en/latest/"
changelog = "https://github.com/MolSSI/QCElemental/blob/master/docs/changelog.rst"
documentation = "https://molssi.github.io/QCElemental/"
issues = "https://github.com/MolSSI/QCElemental/issues"

[project]
Expand Down
13 changes: 12 additions & 1 deletion qcelemental/models/v1/procedures.py
Original file line number Diff line number Diff line change
Expand Up @@ -549,13 +549,24 @@ def convert_v(
dtop["stdout"] = dself.pop("stdout")
dtop["stderr"] = dself.pop("stderr")
dtop["success"] = dself.pop("success")
dtop["final_energies"] = dself.pop("final_energies")
dtop["scan_properties"] = {
k: {
"nuclear_repulsion_energy": mol.nuclear_repulsion_energy(),
"return_energy": dself["final_energies"][k],
# "optimization_iterations":
}
for k, mol in self.final_molecules.items()
}
dself.pop("final_energies")
dself.pop("final_molecules")
dtop["final_molecules"] = {k: m.convert_v(target_version) for k, m in self.final_molecules.items()}
dtop["scan_results"] = {
k: [opthist_class(**res).convert_v(target_version) for res in lst]
for k, lst in dself["optimization_history"].items()
}
dtop["properties"] = {
"calcinfo_ngrid": len(dtop["scan_results"]),
}
dself.pop("optimization_history")
dself.pop("schema_name")
dself.pop("schema_version")
Expand Down
1 change: 1 addition & 0 deletions qcelemental/models/v2/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
from .torsion_drive import (
TorsionDriveInput,
TorsionDriveKeywords,
TorsionDriveProperties,
TorsionDriveProtocols,
TorsionDriveResult,
TorsionDriveSpecification,
Expand Down
41 changes: 31 additions & 10 deletions qcelemental/models/v2/torsion_drive.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
from .basemodels import ExtendedConfigDict, ProtoModel, check_convertible_version
from .common_models import DriverEnum, Provenance
from .molecule import Molecule
from .optimization import OptimizationResult, OptimizationSpecification
from .optimization import OptimizationProperties, OptimizationResult, OptimizationSpecification
from .types import Array

if TYPE_CHECKING:
Expand Down Expand Up @@ -176,8 +176,27 @@ def convert_v(


# ==== Properties =============================================================
# ======== Calcinfo =======================================================
# ======== Canonical ======================================================

# This is mostly a placeholder class until properties developed


class TorsionDriveProperties(ProtoModel):
r"""
Named properties of torsion drive computations following the MolSSI QCSchema.
"""

schema_name: Literal["qcschema_torsion_drive_properties"] = Field(
"qcschema_torsion_drive_properties",
description=f"The QCSchema specification to which this model conforms.",
)

# ======== Calcinfo =======================================================

calcinfo_ngrid: Optional[int] = Field(None, description="The number of dihedral constraints optimized.")

# ======== Canonical ======================================================

model_config = ProtoModel._merge_config_with(force_skip_defaults=True)


# ==== Results ================================================================
Expand All @@ -194,13 +213,14 @@ class TorsionDriveResult(ProtoModel):
id: Optional[str] = Field(None, description="The optional ID for the computation.")
input_data: TorsionDriveInput = Field(..., description=str(TorsionDriveInput.__doc__))

# final_energies, final_molecules, optimization_history I'm hoping to refactor into scan_properties and scan_results but need to talk to OpenFF folks
final_energies: Dict[str, float] = Field(
..., description="The final energy at each angle of the TorsionDrive scan."
)
final_molecules: Dict[str, Molecule] = Field(
..., description="The final molecule at each angle of the TorsionDrive scan."
)
# Note: scan_results includes all opts at each point (best and intermediate), while
# scan_properties and final_molecules include only the best opt. other choices could be made.
scan_properties: Dict[str, OptimizationProperties] = Field(
..., description="The map of energies and other properties for each angle of the TorsionDrive scan."
)
scan_results: Dict[str, List[OptimizationResult]] = Field(
...,
description="The map of each angle of the TorsionDrive scan to each optimization computations.",
Expand All @@ -212,8 +232,7 @@ class TorsionDriveResult(ProtoModel):
# native_files placeholder for when any td programs supply extra files or need an input file. no protocol at present
native_files: Dict[str, Any] = Field({}, description="DSL files.")

# TODO add properties if a set can be collected
# properties: TorsionDriveProperties = Field(..., description=str(TorsionDriveProperties.__doc__))
properties: TorsionDriveProperties = Field(..., description=str(TorsionDriveProperties.__doc__))

extras: Dict[str, Any] = Field(
{},
Expand Down Expand Up @@ -278,7 +297,8 @@ def convert_v(
input_data = self.input_data.convert_v(target_version).model_dump()
input_data.pop("schema_name") # prevent inheriting

dtop["final_energies"] = dself.pop("final_energies")
dtop["final_energies"] = {k: prop["return_energy"] for k, prop in dself["scan_properties"].items()}
dself.pop("scan_properties")
dself.pop("final_molecules")
dtop["final_molecules"] = {k: m.convert_v(target_version) for k, m in self.final_molecules.items()}
dtop["optimization_history"] = {
Expand All @@ -288,6 +308,7 @@ def convert_v(
dself.pop("scan_results")

dself.pop("id") # unused in v1
dself.pop("properties") # new in v2
dself.pop("native_files") # new in v2
dtop["provenance"] = dself.pop("provenance")
dtop["stdout"] = dself.pop("stdout")
Expand Down
15 changes: 9 additions & 6 deletions qcelemental/tests/test_model_results.py
Original file line number Diff line number Diff line change
Expand Up @@ -292,9 +292,10 @@ def torsiondrive_data_fixture(ethane_data_fixture, optimization_data_fixture, re
"input_data": input_data,
"success": True,
"provenance": {"creator": "qcel"},
"final_energies": {"180": -2.3, "0": -4.5},
"scan_properties": {"180": {"return_energy": -2.3}, "0": {"return_energy": -4.5}},
"final_molecules": {"180": ethane, "0": ethane},
"scan_results": {"180": [optres, optres], "0": [optres]},
"properties": {"calcinfo_ngrid": 1},
}
else:
ret = {
Expand Down Expand Up @@ -897,7 +898,9 @@ def every_model_fixture(request):
data = request.getfixturevalue("torsiondrive_data_fixture")
datas[smodel] = data

# smodel = "TorsionDriveProperties" # DNE
smodel = "TorsionDriveProperties"
data = {"calcinfo_ngrid": 1}
datas[smodel] = data

smodel = "ManyBodyInput"
data = request.getfixturevalue("manybody_data_fixture")
Expand Down Expand Up @@ -955,7 +958,7 @@ def every_model_fixture(request):
pytest.param("TDKeywords", "TorsionDriveKeywords", id="TDKw"),
pytest.param(None, "TorsionDriveProtocols", id="TDPtcl"),
pytest.param("TorsionDriveResult", "TorsionDriveResult", id="TDRes"),
# pytest.param(None, "TorsionDriveProperties", id="TDProp"),
pytest.param(None, "TorsionDriveProperties", id="TDProp"),
pytest.param("ManyBodyInput", None, id="MBIn", marks=using_qcmb),
pytest.param("ManyBodySpecification", None, id="MBSpec", marks=using_qcmb),
pytest.param("ManyBodyKeywords", None, id="MBKw", marks=using_qcmb),
Expand Down Expand Up @@ -1166,7 +1169,7 @@ def test_model_survey_extras(smodel1, smodel2, every_model_fixture, request, sch
"v1-TDKw" : None, "v2-TDKw" : None,
"v1-TDPtcl" : None, "v2-TDPtcl" : None, # v1 DNE
"v1-TDRes" : {}, "v2-TDRes" : {},
"v1-TDProp" : None, "v2-TDProp" : None, # v1/v2 DNE
"v1-TDProp" : None, "v2-TDProp" : None, # v1 DNE
"v1-MBIn" : {}, "v2-MBIn" : None, # v2 DNE
"v1-MBSpec" : {}, "v2-MBSpec" : {}, # v2 DNE
"v1-MBKw" : None, "v2-MBKw" : None, # v2 DNE
Expand Down Expand Up @@ -1272,7 +1275,7 @@ def test_model_survey_convertible(smodel1, smodel2, every_model_fixture, request
# "v1-TDKw" , "v2-TDKw" ,
"v1-TDPtcl" , "v2-TDPtcl" ,
"v1-TDRes" , "v2-TDRes" ,
# "v1-TDProp" , "v2-TDProp" ,
"v1-TDProp" , "v2-TDProp" ,
# "v1-MBIn" , "v2-MBIn" ,
# "v1-MBSpec" , "v2-MBSpec" ,
# "v1-MBKw" , "v2-MBKw" ,
Expand Down Expand Up @@ -1341,7 +1344,7 @@ def test_model_survey_schema_name(smodel1, smodel2, every_model_fixture, request
"v1-TDKw" : None, "v2-TDKw" : "qcschema_torsion_drive_keywords",
"v1-TDPtcl" : None, "v2-TDPtcl" : "qcschema_torsion_drive_protocols", # v1 DNE
"v1-TDRes" : "qcschema_torsion_drive_output", "v2-TDRes" : "qcschema_torsion_drive_result",
"v1-TDProp" : None, "v2-TDProp" : None, # v1 DNE, v2 DNE
"v1-TDProp" : None, "v2-TDProp" : "qcschema_torsion_drive_properties", # v1 DNE
"v1-MBIn" : "qcschema_manybodyinput", "v2-MBIn" : "qcschema_many_body_input", # v2 DNE
"v1-MBSpec" : "qcschema_manybodyspecification", "v2-MBSpec" : "qcschema_many_body_specification", # v2 DNE
"v1-MBKw" : "qcschema_manybodykeywords", "v2-MBKw" : "qcschema_many_body_keywords", # v2 DNE
Expand Down