diff --git a/CHANGELOG.md b/CHANGELOG.md index 6883e6b..8ba8cbd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,10 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), ## [unreleased] +### Added + +- `ProgramInput.structures` and `DualProgramInput.structures` for additional named structures required by calculations with multiple complete structure inputs, while keeping `.structure` as the required primary/start/reference structure. [#103](https://github.com/coltonbh/qcdata/pull/103) by [@coltonbh](https://github.com/coltonbh). + ## [0.17.1] - 2026-04-21 ### Added diff --git a/docs/api/inputs.md b/docs/api/inputs.md index 3f5de9c..d8ee5a4 100644 --- a/docs/api/inputs.md +++ b/docs/api/inputs.md @@ -2,6 +2,8 @@ Data structures for specifying quantum chemistry calculations. The most commonly A `DualProgramInput` is used when two inputs are required for a calculation. For example, doing a geometry optimization with `geomeTRIC` while using a `subprogram` like `TeraChem` or `Psi4` to compute the gradients. +`ProgramInput.structure` is always the primary/start/reference structure for the calculation. Calculations that require additional complete structures can provide them by role name with `ProgramInput.structures`, for example `structures={"product": product_structure}` for a nudged elastic band calculation where `structure` is the reactant endpoint. Calculation-specific tools should validate which structure names are required. + A `FileInput` is an escape hatch that allows you to run _any_ calculation in any QC program (or any program for that matter), even if it isn't a supported [`CalcType`](./calctype.md) in `qcdata` yet. You can use a `FileInput` to store the native input files (text and binary) for a QC program along with the relevant command line args. Using [qcop](https://github.com/coltonbh/qcop) you can submit a `FileInput` to a QC program and all output files and `logs` produced by that program will be collected and returned in a user-friendly [`ProgramOutput`](./outputs.md) object. `FileInput` allows you to continue to use `qcdata` even for calculations that haven't yet been standardized. diff --git a/src/qcdata/models/inputs.py b/src/qcdata/models/inputs.py index 476e9ba..a47f394 100644 --- a/src/qcdata/models/inputs.py +++ b/src/qcdata/models/inputs.py @@ -58,9 +58,13 @@ class _StructureKeywordsMixin(_KeywordsMixin): """ Attributes: structure: The structure to be used in the calculation. + structures: Additional named structures required by the calculation. The + primary/start/reference structure should remain in `structure`; this field + is for other complete structures such as a product endpoint in NEB. """ structure: Structure + structures: dict[str, Structure] = {} def __init__(self, **data: Any): """Backwards compatibility for 'molecule' attribute.""" @@ -156,6 +160,8 @@ class ProgramInput(ProgramArgs, _StructureKeywordsMixin): keywords Dict[str, Any]: A dict of keywords to be passed to the program excluding model and calctype. Defaults to an empty dict. structure Structure: The structure to be used in the calculation. + structures Dict[str, Structure]: Additional named structures required by the + calculation. Defaults to an empty dict. files Files: Files to be passed to the QC program. extras Dict[str, Any]: Additional information to bundle with the object. Use for schema development and scratch space. @@ -165,12 +171,14 @@ class ProgramInput(ProgramArgs, _StructureKeywordsMixin): from qcdata.models import ProgramInput, Structure struct = Structure.open("path/to/structure.xyz") + product_struct = Structure.open("path/to/product_structure.xyz") prog_inp = ProgramInput( calctype = "energy", structure = struct, model = {"method": "hf", "basis": "6-31G"}, keywords = {"maxsteps": "250"}, # Optional + structures = {"product": product_struct}, # Optional files = {"file1": b"binary data"} # Optional ) ``` @@ -193,6 +201,8 @@ class DualProgramInput(ProgramArgsSub, ProgramInput): keywords Dict[str, Any]: A dict of keywords to be passed to the program excluding model and calctype. Defaults to an empty dict. structure Structure: The structure to be used in the calculation. + structures Dict[str, Structure]: Additional named structures required by the + calculation. Defaults to an empty dict. files Files: Files to be passed to the QC program. subprogram: The name of the subprogram to use. subprogram_args ProgramArgs: The ProgramArgs for the subprogram. diff --git a/uv.lock b/uv.lock index e528e91..d40e466 100644 --- a/uv.lock +++ b/uv.lock @@ -2780,47 +2780,9 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/93/d7/f12f520a35d8ff5cd647d37627bcf1be98f701c4ab69b520164214ba7e77/qcconst-0.2.1-py3-none-any.whl", hash = "sha256:2c1489e60909ac03daa448a06b59705376be6d71d6d0cee1caecde5517559206", size = 34094 }, ] -[[package]] -name = "qcelemental" -version = "0.29.0" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "numpy", version = "2.2.6", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.11'" }, - { name = "numpy", version = "2.3.3", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.11' and python_full_version < '3.13'" }, - { name = "packaging" }, - { name = "pint", version = "0.24.4", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.11'" }, - { name = "pint", version = "0.25", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.11' and python_full_version < '3.13'" }, - { name = "pydantic" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/e7/ad/1cf6bb9eec08e7455b6c5736c322bbc42f81dc847898d18cf00e9ec9871f/qcelemental-0.29.0.tar.gz", hash = "sha256:bf634ee652e7d95e906e291989513224233b1d705c26afeac86e451f316b3c04", size = 306949 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/57/7a/1fbdf6bb344e8c92c64080a64d9d811ae4eb6d5d3233e1b9ca803296024f/qcelemental-0.29.0-py3-none-any.whl", hash = "sha256:248420b1766489c48b72aaa5f306240f8c305a08e5a4b01c7cb305d6d831967f", size = 339642 }, -] - -[[package]] -name = "qcinf" -version = "0.2.1" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "pydantic" }, - { name = "qcconst" }, - { name = "qcdata" }, - { name = "typing-extensions" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/1e/91/22962d2356bec6a8ea09dd8ee919fb538a51e60f6c07f7d39f42c9339965/qcinf-0.2.1.tar.gz", hash = "sha256:2d50219bd9813b7da6931994aeb7e2f1d189f325556b2f41e024f65211701c66", size = 76791 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/3d/35/9928adc3cbc94cc027a9d84b3c39d382eeddf36ba121d673daa6593667e2/qcinf-0.2.1-py3-none-any.whl", hash = "sha256:4968a4c0f50519fc4237742d2aa198dd0d4e18209a3b1f17fc5e1f6b923e6e60", size = 14669 }, -] - -[package.optional-dependencies] -all = [ - { name = "openbabel-wheel" }, - { name = "rdkit" }, -] - [[package]] name = "qcdata" -version = "0.16.2" +version = "0.17.1" source = { editable = "." } dependencies = [ { name = "eval-type-backport" }, @@ -2927,6 +2889,63 @@ docs = [ { name = "pymdown-extensions", specifier = ">=10.8.1" }, ] +[[package]] +name = "qcelemental" +version = "0.29.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "numpy", version = "2.2.6", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.11'" }, + { name = "numpy", version = "2.3.3", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.11' and python_full_version < '3.13'" }, + { name = "packaging" }, + { name = "pint", version = "0.24.4", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.11'" }, + { name = "pint", version = "0.25", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.11' and python_full_version < '3.13'" }, + { name = "pydantic" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/e7/ad/1cf6bb9eec08e7455b6c5736c322bbc42f81dc847898d18cf00e9ec9871f/qcelemental-0.29.0.tar.gz", hash = "sha256:bf634ee652e7d95e906e291989513224233b1d705c26afeac86e451f316b3c04", size = 306949 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/57/7a/1fbdf6bb344e8c92c64080a64d9d811ae4eb6d5d3233e1b9ca803296024f/qcelemental-0.29.0-py3-none-any.whl", hash = "sha256:248420b1766489c48b72aaa5f306240f8c305a08e5a4b01c7cb305d6d831967f", size = 339642 }, +] + +[[package]] +name = "qcinf" +version = "0.2.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "pydantic" }, + { name = "qcconst" }, + { name = "qcio" }, + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/1e/91/22962d2356bec6a8ea09dd8ee919fb538a51e60f6c07f7d39f42c9339965/qcinf-0.2.1.tar.gz", hash = "sha256:2d50219bd9813b7da6931994aeb7e2f1d189f325556b2f41e024f65211701c66", size = 76791 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/3d/35/9928adc3cbc94cc027a9d84b3c39d382eeddf36ba121d673daa6593667e2/qcinf-0.2.1-py3-none-any.whl", hash = "sha256:4968a4c0f50519fc4237742d2aa198dd0d4e18209a3b1f17fc5e1f6b923e6e60", size = 14669 }, +] + +[package.optional-dependencies] +all = [ + { name = "openbabel-wheel" }, + { name = "rdkit" }, +] + +[[package]] +name = "qcio" +version = "0.16.2" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "eval-type-backport" }, + { name = "numpy", version = "2.2.6", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.11'" }, + { name = "numpy", version = "2.3.3", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.11'" }, + { name = "pydantic" }, + { name = "pyyaml" }, + { name = "qcconst" }, + { name = "toml" }, + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/55/0b/ac1e4e488d462a82643ea0611f1ff107752eb1a20ea20120a5ca76123865/qcio-0.16.2.tar.gz", hash = "sha256:8f4a32612a9b8570cd40e1e3b8a4e965f55c0f232da63bd821ae3945b8c13a04", size = 1479161 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/00/2e/e659ff5596693a80388fb360e18af07a73242726e6de8fb340e0c0bac942/qcio-0.16.2-py3-none-any.whl", hash = "sha256:753a66f9cb453f282178d6a20504892523b05677bc7582f13609aa7040a968ff", size = 37125 }, +] + [[package]] name = "rdkit" version = "2025.9.1"