diff --git a/drivers/py/pes/xtb.py b/drivers/py/pes/xtb.py new file mode 100644 index 000000000..c2b7947fd --- /dev/null +++ b/drivers/py/pes/xtb.py @@ -0,0 +1,83 @@ +""" +Interface with tblite to provide GFN1-xTB and GFN2-xTB calculators. + +Example:: + + python driver.py -m xtb -u -o '{"method": "GFN2-xTB", "numbers": [8,1,1], "periodic": false}' +""" + +import numpy as np +import json + +from ipi.utils.units import unit_to_internal, unit_to_user + +try: + import tblite.interface as tb +except ImportError as e: + raise ModuleNotFoundError( + "Could not find tblite for xtb driver. Please install tblite-python with mamba" + ) from e + +__DRIVER_NAME__ = "xtb" +__DRIVER_CLASS__ = "TBLiteDriver" + + +class TBLiteDriver(object): + """Base class providing the structure of a PES for the python driver.""" + + def __init__( + self, + args="", + verbose=False, + ): + """Initialized dummy drivers""" + config = json.loads(args) + try: + self.method = config["method"] + self.numbers = np.asarray(config["numbers"]) + except KeyError as e: + raise ValueError(f"Required key {str(e)} not found.") + self.charge = config.get("charge") + self.uhf = config.get("uhf") + self.periodic = config.get("periodic") + self.verbosity = 1 if verbose else 0 + + def __call__(self, cell, pos): + """ + Get energies, forces, and stresses from the tblite library + This routine assumes that the client will take positions + in bohr, and return energies in hartree, and forces + in hartree/abohr. + """ + + pos = unit_to_user("length", "atomic_unit", pos) + cell = unit_to_user("length", "atomic_unit", cell.T) + + calc = tb.Calculator( + self.method, + self.numbers, + np.asarray(pos), + self.charge, + self.uhf, # unpaired electrons + np.asarray(cell) if self.periodic else None, + np.repeat(self.periodic, 3) if self.periodic else None, + ) + calc.set("verbosity", self.verbosity) + + # Do the actual calculation + results = calc.singlepoint() + pot = results.get("energy") + grad = results.get("gradient") + vir = results.get("virial") + + # converts to internal quantities + pot_ipi = np.asarray(unit_to_internal("energy", "atomic_unit", pot), np.float64) + force_ipi = np.asarray( + unit_to_internal("force", "atomic_unit", -grad), np.float64 + ) + vir_ipi = np.array( + unit_to_internal("energy", "atomic_unit", -vir.T), np.float64 + ) + extras = "" + + return pot_ipi, force_ipi, vir_ipi, extras diff --git a/examples/clients/xtb/README.md b/examples/clients/xtb/README.md new file mode 100644 index 000000000..c3b2b0c57 --- /dev/null +++ b/examples/clients/xtb/README.md @@ -0,0 +1,19 @@ +xtb - i-PI example +======================== + +Run a simulation of the methane molecule with GFN2-xTB. + + +A version of the tblite code that is compatible with this example can be +obtained with + +```bash +mamba install tblite-python -c conda-forge +``` + +the example can be run as usual + +```bash +i-pi input.xml &> log.ipi & +i-pi-py_driver -m xtb -o '{"method": "GFN2-xTB", "numbers": [6,1,1,1,1], "periodic": false}' -u -a xtb &> log.xtb & +``` diff --git a/examples/clients/xtb/ch4.xyz b/examples/clients/xtb/ch4.xyz new file mode 100644 index 000000000..455386103 --- /dev/null +++ b/examples/clients/xtb/ch4.xyz @@ -0,0 +1,7 @@ +5 +# CELL(abcABC): 100 100 100 90.00000 90.00000 90.00000 cell{atomic_unit} Traj: positions{angstrom} Step: 9 Bead: 0 + C 5.77568e-01 7.10503e-01 5.95431e-01 + H 1.00494e-04 1.08773e-01 1.29743e+00 + H 1.28079e+00 1.06096e-01 2.22598e-02 + H -6.31180e-02 1.31234e+00 -4.92875e-02 + H 1.80833e+00 2.15490e+00 1.82860e+00 diff --git a/examples/clients/xtb/input.xml b/examples/clients/xtb/input.xml new file mode 100644 index 000000000..7f3c5f774 --- /dev/null +++ b/examples/clients/xtb/input.xml @@ -0,0 +1,46 @@ + + + [ step, time{picosecond}, conserved{electronvolt}, + temperature{kelvin}, kinetic_md{electronvolt}, potential{electronvolt}, pressure_md{bar}, volume{angstrom3}, + ensemble_temperature{kelvin}, cell_abcABC] + x_centroid{angstrom} + + + 100 + 12345 + + 1.00000000e-04 + 4 + 12345 + 60.000000e+00 +
xtb
+
+ + + ch4.xyz + 250.0 + + + + + + + 0.5 + + + [ + 4.498098855452e-3, 6.594810718477e-6, 2.788030342989e-4, -8.808265165053e-4, 5.605371493938e-3, + -6.726802271646e-6, 2.079069559861e-9, 1.746169548818e-5, -4.800164465960e-6, 1.025830873432e-5, + -3.586191452340e-4, -1.746169548818e-5, 3.287481976399e-5, 1.245698716799e-4, -2.417657162526e-4, + -2.508912543565e-4, 4.800164465960e-6, -1.245698716799e-4, 6.449207766266e-4, 2.783583234046e-4, + 5.273493443008e-3, -1.025830873432e-5, 2.417657162526e-4, -2.783583234046e-4, 7.488477456790e-3 + ] + + + + + + 250.0 + + +
diff --git a/examples/clients/xtb/run.sh b/examples/clients/xtb/run.sh new file mode 100644 index 000000000..3726ce141 --- /dev/null +++ b/examples/clients/xtb/run.sh @@ -0,0 +1,7 @@ +#! /bin/bash +echo "Running i-PI" +i-pi input.xml &> log.ipi & +sleep 1 +echo "Running driver" +i-pi-py_driver -m xtb -o '{"method": "GFN2-xTB", "numbers": [6,1,1,1,1], "periodic": false}' -u -a xtb &> log.xtb +