Skip to content

Commit

Permalink
add plain qcmanybody harness (#466)
Browse files Browse the repository at this point in the history
* add plain qcmanybody hanress

* lint

* update changelog
  • Loading branch information
loriab authored Jan 16, 2025
1 parent 879205a commit a3a05c1
Show file tree
Hide file tree
Showing 10 changed files with 440 additions and 7 deletions.
1 change: 1 addition & 0 deletions devtools/conda-envs/nwchem-cf.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ dependencies:
- qcelemental >=0.24.0
- pydantic>=1.0.0
- networkx>=2.4.0
- qcmanybody

# Testing
- pytest
Expand Down
1 change: 1 addition & 0 deletions devtools/conda-envs/opt-disp-cf.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ dependencies:
- geometric
- optking
- pymdi
- qcmanybody

# Core
- python
Expand Down
9 changes: 8 additions & 1 deletion docs/source/changelog.rst
Original file line number Diff line number Diff line change
Expand Up @@ -36,17 +36,24 @@ Breaking Changes

New Features
++++++++++++
- (:pr:`466`) QCManyBody - new procedure for computing interaction energies or truncation or full
many-body expansions with no, counterpoise, or Valiron-Mayer function counterpoise correction
for basis set superposition error. @loriab

Enhancements
++++++++++++
- (:pr:`463`) Maint - Pin to QCElemental <0.70 since we now know QCSchema v2 release schedule.
- (:pr:`463`) MACE - New v0.3.9 release yields a pytorch error, so recommend pymace=0.3.6 .
- (:pr:`464`, :issue:`447`) CFOUR - Allow CC-PVDZ alias basis specification. Also fix the PwCVXZ
basis keyword. @philipmnel
- (:pr:`440`) TorsionDrive - Support other geometric-style constraints by not overwriting those
already present. @jthorton

Bug Fixes
+++++++++
- (:pr:`451`, :issue:`450`) Psi4 - Fixes bug in Psi4 detection when command `python` not available. @susilehtola, @topazus
- (:pr:`451`, :issue:`450`) Psi4 - Fixes bug in Psi4 detection when command `python` not available.
@susilehtola, @topazus
- (:pr:`466`) CFOUR - fix error collecting molecule when it's a single atom with two-letter symbol. @loriab

Misc.
+++++
Expand Down
2 changes: 2 additions & 0 deletions qcengine/procedures/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
from .geometric import GeometricProcedure
from .nwchem_opt import NWChemDriverProcedure
from .optking import OptKingProcedure
from .qcmanybody import QCManyBodyProcedure
from .torsiondrive import TorsionDriveProcedure
from .model import ProcedureHarness

Expand Down Expand Up @@ -69,5 +70,6 @@ def list_available_procedures() -> Set[str]:
register_procedure(GeometricProcedure())
register_procedure(OptKingProcedure())
register_procedure(BernyProcedure())
register_procedure(QCManyBodyProcedure())
register_procedure(NWChemDriverProcedure())
register_procedure(TorsionDriveProcedure())
51 changes: 51 additions & 0 deletions qcengine/procedures/qcmanybody.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
from typing import TYPE_CHECKING, Any, Dict, Union

from qcelemental.util import safe_version, which_import

from .model import ProcedureHarness

if TYPE_CHECKING:
from ..config import TaskConfig
from qcmanybody.models import ManyBodyInput, ManyBodyResult


class QCManyBodyProcedure(ProcedureHarness):

# v2: ClassVar[Dict[str, Any]]
_defaults: Dict[str, Any] = {"name": "QCManyBody", "procedure": "manybody"}

version_cache: Dict[str, str] = {}

class Config(ProcedureHarness.Config):
pass

def found(self, raise_error: bool = False) -> bool:
return which_import(
"qcmanybody",
return_bool=True,
raise_error=raise_error,
raise_msg="Please install via `conda install qcmanybody -c conda-forge`.",
)

def build_input_model(self, data: Union[Dict[str, Any], "ManyBodyInput"]) -> "ManyBodyInput":
from qcmanybody.models import ManyBodyInput

return self._build_model(data, ManyBodyInput)

def get_version(self) -> str:
self.found(raise_error=True)

which_prog = which_import("qcmanybody")
if which_prog not in self.version_cache:
import qcmanybody

self.version_cache[which_prog] = safe_version(qcmanybody.__version__)

return self.version_cache[which_prog]

def compute(self, input_model: "ManyBodyInput", config: "TaskConfig") -> "ManyBodyResult":
from qcmanybody import ManyBodyComputer

output_model = ManyBodyComputer.from_manybodyinput(input_model)

return output_model
2 changes: 1 addition & 1 deletion qcengine/programs/adcc.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ def found(raise_error: bool = False) -> bool:
"psi4",
return_bool=True,
raise_error=raise_error,
raise_msg="Please install psi4 for adcc harness via `conda install psi4 -c conda-forge/label/libint_dev -c conda-forge`.",
raise_msg="Please install psi4 for adcc harness via `conda install psi4 -c conda-forge`.",
)
return found_adcc and found_psi4

Expand Down
4 changes: 3 additions & 1 deletion qcengine/programs/cfour/harvester.py
Original file line number Diff line number Diff line change
Expand Up @@ -1004,7 +1004,9 @@ def harvest_outfile_pass(outtext):
# Process atom geometry
mobj = re.search(r"^\s+" + r"@GETXYZ-I, 1 atoms read from ZMAT." + r"\s*$", outtext, re.MULTILINE)
mobj2 = re.search(
r"^([A-Z]+)#1" + r"\s+" + NUMBER + r"\s+" + NUMBER + r"\s+" + NUMBER + r"\s*$", outtext, re.MULTILINE
r"^\s*([A-Z]+)" + r"\s*" + r"#1" + r"\s+" + NUMBER + r"\s+" + NUMBER + r"\s+" + NUMBER + r"\s*$",
outtext,
re.MULTILINE,
)
if mobj and mobj2:
logger.debug("matched atom2") # unsavory for when atom never printed except for basis file
Expand Down
2 changes: 1 addition & 1 deletion qcengine/programs/psi4.py
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ def found(raise_error: bool = False) -> bool:
"psi4",
return_bool=True,
raise_error=raise_error,
raise_msg="Please install via `conda install psi4 -c conda-forge/label/libint_dev -c conda-forge`. Check it's in your PATH with `which psi4`."
raise_msg="Please install via `conda install psi4 -c conda-forge`. Check it's in your PATH with `which psi4`."
+ error_msg,
)

Expand Down
12 changes: 9 additions & 3 deletions qcengine/testing.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,9 +57,14 @@ def is_program_new_enough(program, version_feature_introduced):
form is equal to or later than `version_feature_introduced`.
"""
if program not in qcng.list_available_programs():
return False
candidate_version = qcng.get_program(program).get_version()
if program in qcng.list_all_procedures():
if program not in qcng.list_available_procedures():
return False
candidate_version = qcng.get_procedure(program).get_version()
else:
if program not in qcng.list_available_programs():
return False
candidate_version = qcng.get_program(program).get_version()

return parse_version(candidate_version) >= parse_version(version_feature_introduced)

Expand Down Expand Up @@ -177,6 +182,7 @@ def get_job(self):
"psi4_derqcsk": is_program_new_enough("psi4", "1.5a1.dev117"),
"qcdb": which_import("qcdb", return_bool=True),
"qchem": is_program_new_enough("qchem", "5.1"),
"qcmanybody": which_import("qcmanybody", return_bool=True),
"rdkit": which_import("rdkit", return_bool=True),
"terachem": which("terachem", return_bool=True),
"terachem_pbs": is_program_new_enough("terachem_pbs", "0.7.2"),
Expand Down
Loading

0 comments on commit a3a05c1

Please sign in to comment.