Skip to content

TeraChem

qcop.adapters.terachem.TeraChemAdapter

Adapter for TeraChem.

supported_calctypes class-attribute instance-attribute

supported_calctypes = [energy, gradient, hessian, optimization]

Supported calculation types.

program_version

program_version(stdout: str | None = None) -> str

Get the program version.

Parameters:

Name Type Description Default
stdout str | None

The stdout from the program.

None

Returns:

Type Description
str

The program version.

Source code in src/qcop/adapters/terachem.py
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
def program_version(self, stdout: str | None = None) -> str:
    """Get the program version.

    Args:
        stdout: The stdout from the program.

    Returns:
        The program version.
    """
    if stdout:
        try:
            return parse_version(stdout)
        except qccodec_exceptions.ParserError:
            # If the version string is not found. Happens when libcuda.so is not
            # found and TeraChem fails to start. terachem --version will fail too.
            return "Could not parse version"
    else:
        try:
            return execute_subprocess(self.program, ["--version"])[17:]
        except ExternalProgramError:
            return "Could not determine version"

compute_data

compute_data(input_data: ProgramInput, update_func: Callable | None = None, update_interval: float | None = None, **kwargs) -> tuple[SinglePointData, str]

Execute TeraChem on the given input.

Parameters:

Name Type Description Default
input_data ProgramInput

The qcio ProgramInput object for a computation.

required
update_func Callable | None

A callback function to call as the program executes.

None
update_interval float | None

The minimum time in seconds between calls to the update_func.

None

Returns:

Type Description
tuple[SinglePointData, str]

A tuple of SinglePointData and the stdout str.

Source code in src/qcop/adapters/terachem.py
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
def compute_data(
    self,
    input_data: ProgramInput,
    update_func: Callable | None = None,
    update_interval: float | None = None,
    **kwargs,
) -> tuple[SinglePointData, str]:
    """Execute TeraChem on the given input.

    Args:
        input_data: 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 SinglePointData and the stdout str.
    """
    # Construct TeraChem native input files
    try:
        native_input = qccodec.encode(input_data, self.program)
    except qccodec.exceptions.EncoderError as e:
        raise AdapterInputError(program=self.program) from e

    # Write the input files to disk
    input_filename = "tc.in"
    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
    )

    # Get the scratch output directory
    parent = Path.cwd()
    # TeraChem creates a directory named scr.<xyz_filename> in the current working
    scr_dir = next(parent.glob("scr.*"), None)
    if scr_dir is None:
        raise ExternalProgramError(
            self.program, f"TeraChem did not create a 'scr.' directory in {parent}."
        )

    # Parse output
    try:
        results = qccodec.decode(
            self.program,
            input_data.calctype,
            stdout=stdout,
            directory=scr_dir,
            input_data=input_data,
        )
    except qccodec_exceptions.ParserError as e:
        raise ExternalProgramError(
            program="qccodec",
            message="Failed to parse TeraChem output.",
            logs=stdout,
            original_exception=e,
        ) from e
    return results, stdout

collect_wfn

collect_wfn() -> dict[str, str | bytes]

Append wavefunction data to the output.

Source code in src/qcop/adapters/terachem.py
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
def collect_wfn(self) -> dict[str, str | bytes]:
    """Append wavefunction data to the output."""

    # Naming conventions from TeraChem uses xyz filename as scratch dir postfix
    scr_postfix = XYZ_FILENAME.split(".")[0]

    # Wavefunction filenames
    wfn_filenames = ("c0", "ca0", "cb0")
    wfn_paths = [Path(f"scr.{scr_postfix}/{fn}") for fn in wfn_filenames]
    if not any(wfn_path.exists() for wfn_path in wfn_paths):
        raise AdapterError(f"No wavefunction files found in {Path.cwd()}")

    wfns: dict[str, str | bytes] = {}
    for wfn_path in wfn_paths:
        if wfn_path.exists():
            wfns[str(wfn_path)] = wfn_path.read_bytes()
    return wfns

propagate_wfn

propagate_wfn(output: Results, program_input: ProgramInput) -> None

Propagate the wavefunction from the previous calculation.

Parameters:

Name Type Description Default
output Results

The output from a previous calculation containing wavefunction data.

required
program_input ProgramInput

The ProgramInput object on which to place the wavefunction data.

required

Returns:

Type Description
None

None. Modifies the program_input object in place.

Source code in src/qcop/adapters/terachem.py
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
157
158
159
160
161
162
163
164
165
166
167
168
169
def propagate_wfn(self, output: Results, program_input: ProgramInput) -> None:
    """Propagate the wavefunction from the previous calculation.

    Args:
        output: The output from a previous calculation containing wavefunction data.
        program_input: The ProgramInput object on which to place the wavefunction data.

    Returns:
        None. Modifies the program_input object in place.
    """

    # Naming conventions from TeraChem uses xyz filename as scratch dir postfix
    scr_postfix = XYZ_FILENAME.split(".")[0]

    # Wavefunction filenames
    c0, ca0, cb0 = "c0", "ca0", "cb0"

    files = output.data.files
    c0_bytes = files.get(f"scr.{scr_postfix}/{c0}")
    ca0_bytes = files.get(f"scr.{scr_postfix}/{ca0}")
    cb0_bytes = files.get(f"scr.{scr_postfix}/{cb0}")

    if not c0_bytes and not (ca0_bytes and cb0_bytes):
        raise AdapterInputError(
            program=self.program,
            message="Could not find c0 or ca/b0 files in output.",
        )

    # Load wavefunction data onto ProgramInput object

    if c0_bytes:
        program_input.files[c0] = c0_bytes
        program_input.keywords["guess"] = c0

    else:  # ca0_bytes and cb0_bytes
        assert ca0_bytes and cb0_bytes  # for mypy
        program_input.files[ca0] = ca0_bytes
        program_input.files[cb0] = cb0_bytes
        program_input.keywords["guess"] = f"{ca0} {cb0}"

qcop.adapters.terachem_fe.TeraChemFEAdapter

TeraChemFEAdapter()

Adapter for TeraChem's Protocol Buffer Server and Frontend file server.

Source code in src/qcop/adapters/terachem_fe.py
18
19
20
21
22
def __init__(self):
    super().__init__()
    # Check that xtb-python is installed.
    self.tcpb = self._ensure_tcpb()
    self.client = self.tcpb.TCFrontEndClient

supported_calctypes class-attribute instance-attribute

supported_calctypes = [energy, gradient]

Supported calculation types.

program_version

program_version(stdout: str | None = None) -> str

Program version is not available via the PB server.

Source code in src/qcop/adapters/terachem_fe.py
38
39
40
def program_version(self, stdout: str | None = None) -> str:
    """Program version is not available via the PB server."""
    return ""

compute_data

compute_data(input_data: ProgramInput, update_func: Callable | None = None, update_interval: float | None = None, **kwargs) -> tuple[SinglePointData, str]

Execute TeraChem on the given input.

Parameters:

Name Type Description Default
input_data ProgramInput

The qcio ProgramInput object for a computation.

required
update_func Callable | None

A callback function to call as the program executes.

None
update_interval float | None

The minimum time in seconds between calls to the update_func.

None

Returns:

Type Description
tuple[SinglePointData, str]

A tuple of SinglePointData and the stdout str.

Source code in src/qcop/adapters/terachem_fe.py
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
def compute_data(
    self,
    input_data: ProgramInput,
    update_func: Callable | None = None,
    update_interval: float | None = None,
    **kwargs,
) -> tuple[SinglePointData, str]:
    """Execute TeraChem on the given input.

    Args:
        input_data: 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 SinglePointData and the stdout str.
    """
    try:
        with self.client() as client:
            prog_output = client.compute(input_data)
    except self.tcpb.exceptions.TCPBError as e:
        exc = ExternalProgramError(
            program=self.program,
            # Pass logs to .compute() via the exception
            # Will only exist for TeraChemFrontendAdapter
            logs=e.results.logs,
        )

        raise exc

    else:
        # Write files to disk to be collected by BaseAdapter.compute()
        # Used only for TeraChemFrontendAdapter
        prog_output.data.save_files()

    return prog_output.data, prog_output.logs

qcop.adapters.terachem_pbs.TeraChemPBSAdapter

TeraChemPBSAdapter()

Adapter for TeraChem's Protocol Buffer Server.

Source code in src/qcop/adapters/terachem_pbs.py
 9
10
11
12
13
def __init__(self):
    super().__init__()
    # Check that tcpb is installed.
    self.tcpb = self._ensure_tcpb()
    self.client = self.tcpb.TCProtobufClient