Skip to content

Commit

Permalink
Merge pull request #47 from coltonbh/feature-terachem-opt
Browse files Browse the repository at this point in the history
  • Loading branch information
coltonbh authored Sep 13, 2024
2 parents 0d31101 + e80955c commit ba03c4a
Show file tree
Hide file tree
Showing 10 changed files with 121 additions and 13 deletions.
4 changes: 4 additions & 0 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,10 @@ repos:
- id: mypy
additional_dependencies:
[pydantic>=2.0.0, types-paramiko, qcio>=0.11.8, types-toml]
- repo: https://github.com/crate-ci/typos
rev: v1.24.5
hooks:
- id: typos
- repo: local
hooks:
- id: tests
Expand Down
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,11 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),

## [unreleased]

### Added

- `CalcType.optimization` support for TeraChem.
- `typos` pre-commit check.

## [0.9.0] - 2024-09-11

### Changed
Expand Down
10 changes: 9 additions & 1 deletion docs/examples/optimization.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,11 @@
## geomeTRIC

```python
{!examples/geometric.py!}
```
```

## TeraChem

```python
{!examples/terachem_opt.py!}
```
6 changes: 5 additions & 1 deletion docs/programs/terachem.md
Original file line number Diff line number Diff line change
@@ -1 +1,5 @@
::: qcop.adapters.terachem.TeraChemAdapter
::: qcop.adapters.terachem.TeraChemAdapter

::: qcop.adapters.terachem_fe.TeraChemFEAdapter

::: qcop.adapters.terachem_pbs.TeraChemPBSAdapter
50 changes: 50 additions & 0 deletions examples/terachem_opt.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
"""Example of how to run an optimization calculation with TeraChem using qcop."""

from qcio import ProgramInput, Structure

from qcop import compute, exceptions

# Create the structure
# Can also open a structure from a file
# structure = Structure.open("path/to/h2o.xyz")
structure = Structure(
symbols=["O", "H", "H"],
geometry=[ # type: ignore
[0.0, 0.0, 0.0],
[0.52421003, 1.68733646, 0.48074633],
[1.14668581, -0.45032174, -1.35474466],
],
)

# Define the program input
prog_input = ProgramInput(
structure=structure,
# Can be "energy", "gradient", "hessian", "optimization", "transition_state"
calctype="optimization", # type: ignore
model={"method": "hf", "basis": "sto-3g"}, # type: ignore
keywords={"purify": "no", "new_minimizer": "yes"}, # new_minimizer yes is required
)

# Run the calculation
try:
# prog_output is instance of ProgramOutput
prog_output = compute("terachem", prog_input, collect_files=True)
except exceptions.QCOPBaseError as e:
prog_output = e.program_output
print(prog_output.stdout) # or output.pstdout for short
print(f"Success: {prog_output.success}") # False
print(prog_output.input_data) # Input data used to generate the calculation
print(prog_output.provenance) # Provenance of generated calculation
print(prog_output.traceback) # or output.ptraceback for short
raise

else:
# Check results
print(prog_output.stdout) # or output.pstdout for short
print(f"Success: {prog_output.success}") # True
print("output.results: ", prog_output.results)
print("output.results.energies:", prog_output.results.energies)
print("output.results.structures:", prog_output.results.structures)
print("output.results.final_structure:", prog_output.results.final_structure)
print(prog_output.input_data) # Input data used to generate the calculation
print(prog_output.provenance) # Provenance of generated calculation
3 changes: 2 additions & 1 deletion mkdocs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,8 @@ markdown_extensions:
- markdown_include.include

watch:
- qcop # Adjust this
- qcop
- examples

nav:
- Getting Started:
Expand Down
8 changes: 4 additions & 4 deletions poetry.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 5 additions & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ xtb = { version = "^22.1", optional = true }
tcpb = { version = "^0.14.1", optional = true }
tomli-w = "^1.0.0"
qcio = "^0.11.8"
qcparse = "^0.6.2"
qcparse = "^0.6.3"

[tool.poetry.extras]
qcengine = ["qcelemental", "qcengine"]
Expand Down Expand Up @@ -82,3 +82,7 @@ markers = [
"integration: marks tests as integration (deselect with '-m \"not integration\"')",
]
filterwarnings = ["ignore::DeprecationWarning:qcengine.*"]

[tool.typos]
# Exclude specific files or directories
files.extend-exclude = [".vscode/**"]
25 changes: 20 additions & 5 deletions qcop/adapters/terachem.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
import qcparse
from qcio import CalcType, ProgramInput, ProgramOutput, SinglePointResults
from qcparse.encoders.terachem import XYZ_FILENAME
from qcparse.parsers.terachem import parse_version_string
from qcparse.parsers.terachem import parse_optimization_dir, parse_version_string

from qcop.exceptions import AdapterError, AdapterInputError

Expand All @@ -15,7 +15,12 @@
class TeraChemAdapter(ProgramAdapter[ProgramInput, SinglePointResults]):
"""Adapter for TeraChem."""

supported_calctypes = [CalcType.energy, CalcType.gradient, CalcType.hessian]
supported_calctypes = [
CalcType.energy,
CalcType.gradient,
CalcType.hessian,
CalcType.optimization,
]
program = "terachem"

def program_version(self, stdout: Optional[str] = None) -> str:
Expand Down Expand Up @@ -53,18 +58,28 @@ def compute_results(
Returns:
A tuple of SinglePointResults and the stdout str.
"""
# Construct and write input file and xyz file to disk
input_filename = "tc.in"
try:
native_input = qcparse.encode(inp_obj, self.program)
except qcparse.exceptions.EncoderError as e:
raise AdapterInputError(self.program, "Invalid input for TeraChem") from e
except qcparse.exceptions.EncoderError:
raise AdapterInputError(self.program, "Invalid input for TeraChem")
Path(input_filename).write_text(native_input.input_file)
Path(native_input.geometry_filename).write_text(native_input.geometry_file)

# Execute TeraChem
stdout = execute_subprocess(
self.program, [input_filename], update_func, update_interval
)
parsed_output = qcparse.parse(stdout, self.program, "stdout")

# Parse output
if inp_obj.calctype == CalcType.optimization:
parsed_output = parse_optimization_dir(
f"scr.{XYZ_FILENAME.split('.')[0]}", stdout, inp_obj=inp_obj
)
else:
parsed_output = qcparse.parse(stdout, self.program, "stdout")

return parsed_output, stdout

def collect_wfn(self) -> dict[str, Union[str, bytes]]:
Expand Down
17 changes: 17 additions & 0 deletions tests/integration_tests/test_terachem_integration.py
Original file line number Diff line number Diff line change
Expand Up @@ -197,3 +197,20 @@ def test_terachem_hessian():
),
atol=1e-6,
)


@pytest.mark.integration
@skipif_program_not_available("terachem")
def test_terachem_optimization(water):
# Modify keywords
energy_inp = ProgramInput(
structure=water,
calctype=CalcType.gradient,
model={"method": "hf", "basis": "sto-3g"},
keywords={"purify": "no", "new_minimizer": "yes"},
)

program = "terachem"
output = compute(program, energy_inp)
assert output.input_data == energy_inp
assert output.provenance.program == program

0 comments on commit ba03c4a

Please sign in to comment.