Skip to content

xtb

qcop.adapters.xtb.XTBAdapter

XTBAdapter()

Adapter for xtb-python.

Source code in qcop/adapters/xtb.py
38
39
40
41
def __init__(self):
    super().__init__()
    # Check that xtb-python is installed.
    self.xtb = self._ensure_xtb()

supported_calctypes class-attribute instance-attribute

supported_calctypes = [energy, gradient]

Supported calculation types.

validate_input

validate_input(inp_obj: ProgramInput) -> None

Validate the input for xtb-python.

Source code in qcop/adapters/xtb.py
43
44
45
46
47
48
49
50
51
52
53
def validate_input(self, inp_obj: ProgramInput) -> None:
    """Validate the input for xtb-python."""
    super().validate_input(inp_obj)
    # Check that xtb supports the method.
    supported_methods = self.xtb.interface.Param.__members__.keys()
    if inp_obj.model.method not in supported_methods:
        raise AdapterInputError(
            self.program,
            f"Unsupported method '{inp_obj.model.method}'. "
            f"Supported methods include: {supported_methods}",
        )

program_version

program_version(stdout: Optional[str] = None) -> str

Get the program version.

Parameters:

Name Type Description Default
stdout Optional[str]

The stdout from the program.

None

Returns:

Type Description
str

The program version.

Source code in qcop/adapters/xtb.py
55
56
57
58
59
60
61
62
63
64
65
66
67
def program_version(self, stdout: Optional[str] = None) -> str:
    """Get the program version.

    Args:
        stdout: The stdout from the program.

    Returns:
        The program version.
    """
    global CACHED_XTB_VERSION
    if not CACHED_XTB_VERSION:
        CACHED_XTB_VERSION = importlib.metadata.version(self.program)
    return CACHED_XTB_VERSION

compute_results

compute_results(
    inp_obj: ProgramInput,
    update_func: Optional[Callable] = None,
    update_interval: Optional[float] = None,
    **kwargs
) -> tuple[SinglePointResults, str]

Execute xtb on the given input.

Parameters:

Name Type Description Default
inp_obj ProgramInput

The qcio ProgramInput object for a computation.

required
update_func Optional[Callable]

A callback function to call as the program executes.

None
update_interval Optional[float]

The minimum time in seconds between calls to the update_func.

None

Returns:

Type Description
tuple[SinglePointResults, str]

A tuple of SinglePointComputedProps and the stdout str.

Source code in qcop/adapters/xtb.py
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
def compute_results(
    self,
    inp_obj: ProgramInput,
    update_func: Optional[Callable] = None,
    update_interval: Optional[float] = None,
    **kwargs,
) -> tuple[SinglePointResults, str]:
    """Execute xtb on the given input.

    Args:
        inp_obj: The qcio ProgramInput object for a computation.
        update_func: A callback function to call as the program executes.
        update_interval: The minimum time in seconds between calls to the
            update_func.

    Returns:
        A tuple of SinglePointComputedProps and the stdout str.
    """
    try:
        # Create Calculator
        calc = self.xtb.interface.Calculator(
            getattr(self.xtb.interface.Param, inp_obj.model.method),
            np.array(inp_obj.structure.atomic_numbers),
            inp_obj.structure.geometry,
            inp_obj.structure.charge,
            # From https://github.com/grimme-lab/xtb-python/blob/a32309a43e5a6572b033814eacf396328a2a36ed/xtb/qcschema/harness.py#L126 # noqa: E501
            inp_obj.structure.multiplicity - 1,
        )
        calc.set_verbosity(self.xtb.libxtb.VERBOSITY_FULL)  # all logs

        # Set Keywords
        for key, value in inp_obj.keywords.items():
            # TODO: Need to handle external_charges and solvent
            getattr(calc, f"set_{key}")(value)

        # Capture logs
        with capture_sys_stdout() as r_pipe:
            res = calc.singlepoint()
            # Not sure what this does but it's in the xtb-python docs
            calc.release_output()
            stdout = os.read(r_pipe, 100000).decode()

    except self.xtb.interface.XTBException as e:
        raise ExternalProgramError("Something went wrong with xtb-python.") from e

    # Collect results
    # TODO: Collect other results xtb produces
    results = SinglePointResults(
        energy=res.get_energy(),
        gradient=res.get_gradient(),
        scf_dipole_moment=res.get_dipole(),
        wavefunction=Wavefunction(
            scf_eigenvalues_a=res.get_orbital_eigenvalues(),
        ),
    )

    return results, stdout

Example

"""Must run script like this: python -m examples.xtb"""

from qcio import CalcType, ProgramInput, Structure

from qcop import compute

# 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,
    calctype=CalcType.energy,
    model={"method": "GFN2xTB"},  # type: ignore
    keywords={"max_iterations": 150},
)


prog_output = compute("xtb", prog_input)
print(prog_output)