Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added support for Turbomole #101

Merged
merged 18 commits into from
Jan 17, 2025

Conversation

jonathan-schoeps
Copy link
Contributor

A new interface for Turbomole has been implemented to facilitate its use in post-processing step, including both single-point energy calculations and geometry optimizations.

Signed-off-by: Jonathan Schöps <[email protected]>
Merge latest changes to dev branche
@jonathan-schoeps jonathan-schoeps added the algorithm Related to the back-end algorithm for generating the mindless molecules. label Jan 8, 2025
@jonathan-schoeps jonathan-schoeps self-assigned this Jan 8, 2025
@jonathan-schoeps jonathan-schoeps linked an issue Jan 8, 2025 that may be closed by this pull request
Copy link
Member

@marcelmbn marcelmbn left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some things to do, but it's already on a very good track!

CHANGELOG.md Outdated Show resolved Hide resolved
mindlessgen.toml Show resolved Hide resolved
src/mindlessgen/prog/config.py Show resolved Hide resolved
src/mindlessgen/qm/tm.py Outdated Show resolved Hide resolved
src/mindlessgen/qm/tm.py Outdated Show resolved Hide resolved
src/mindlessgen/qm/tm.py Outdated Show resolved Hide resolved
src/mindlessgen/qm/tm.py Outdated Show resolved Hide resolved
src/mindlessgen/qm/tm.py Outdated Show resolved Hide resolved
src/mindlessgen/qm/tm.py Outdated Show resolved Hide resolved
src/mindlessgen/qm/tm.py Outdated Show resolved Hide resolved
@marcelmbn
Copy link
Member

These functions could be good starting points for the coord file handling:

    @staticmethod
    def read_mol_from_coord(file: str | Path) -> "Molecule":
        """
        Read the XYZ coordinates and the charge of the molecule from a 'coord' file.
        Thereby, generate a completely new molecule object from scratch.

        Can be called like this:
            from molecule import Molecule
            # Call the static method using the class name
            coord_file = "coord"
            molecule_instance = Molecule.read_mol_from_coord(coord_file)
            # Now you can use the molecule_instance as needed
            print(molecule_instance.name)

        :param file: The 'coord' file to read from.
        :return: A new instance of Molecule with the read data.
        """
        molecule = Molecule()
        if isinstance(file, str):
            file_path = Path(file).resolve()
        elif isinstance(file, Path):
            file_path = file.resolve()
        else:
            raise TypeError("String or Path expected.")
        molecule.read_xyz_from_coord(file_path)
        uhf_path = file_path.parent / ".UHF"
        if uhf_path.exists():
            molecule.read_uhf_from_file(uhf_path)
        else:
            molecule.uhf = 0
        chrg_path = file_path.parent / ".CHRG"
        if chrg_path.exists():
            molecule.read_charge_from_file(chrg_path)
        else:
            molecule.charge = 0
        return molecule
    def write_coord_to_file(self, filename: str | Path | None = None):
       """
       Write the 'coord' file of the molecule to a file.

       The layout of the file is as follows:
       ```
       $coord
       <x1> <y1> <z1> <symbol 1>
       <x2> <y2> <z2> <symbol 2>
       ...
       $end
       ```

       :param filename: The name of the file to write to.
       """
       # raise an error if the number of atoms is not set
       if self._num_atoms is None:
           raise ValueError("Number of atoms not set.")
       if not self._ati.size:
           raise ValueError("Atomic numbers not set.")
       if not self._xyz.size:
           raise ValueError("Atomic coordinates not set.")

       if filename:
           if not isinstance(filename, Path):
               filename = Path(filename).resolve()
       else:
           filename = Path("mlm_" + self.name + ".coord").resolve()

       with open(filename, "w", encoding="utf8") as f:
           f.write(self.get_coord_str())
       # if the charge is set, write it to a '.CHRG' file
       if self._charge is not None and self._charge != 0:
           chrg_filename = filename.parent / ".CHRG"
           with open(chrg_filename, "w", encoding="utf8") as f:
               f.write(f"{self.charge}\n")
       # if the UHF is set, write it to a '.UHF' file
       if self._uhf is not None and self._uhf > 0:
           uhf_filename = filename.parent / ".UHF"
           with open(uhf_filename, "w", encoding="utf8") as f:
               f.write(f"{self.uhf}\n")
    def get_coord_str(self) -> str:
       """
       Obtain a string with the full 'coord' file information of the molecule.
       """
       coord_str = "$coord\n"
       for i in range(self.num_atoms):
           coord_str += (
               f"{self.xyz[i, 0] / BOHR2AA:>20.14f} "
               + f"{self.xyz[i, 1] / BOHR2AA:>20.14f} "
               + f"{self.xyz[i, 2] / BOHR2AA:>20.14f} "
               + f"{PSE[self.ati[i] + 1]}\n"
           )
       coord_str += "$end\n"
       return coord_str
    def read_xyz_from_coord(self, filename: str | Path) -> None:
        """
        Read the XYZ coordinates of the molecule from a 'coord' file.

        The layout of the file is as follows:
        ```
        $coord
         0.00000000000000      0.00000000000000      3.60590687077610     u
         0.00000000000000      0.00000000000000     -3.60590687077610     u
         0.00000000000000      2.74684941070244      0.00000000000000     F
         3.72662552762076      0.00000000000000      5.36334486193405     F
        -3.72662552762076      0.00000000000000      5.36334486193405     F
         3.72662552762076      0.00000000000000     -5.36334486193405     F
         0.00000000000000     -2.74684941070244      0.00000000000000     F
        -3.72662552762076      0.00000000000000     -5.36334486193405     F
        $end
        ... or ...
        $coord
            0.00000000000000      0.00000000000000      2.30704866281983  u
            0.00000000000000      0.00000000000000     -2.30704866281983  u
        $redundant
            number_of_atoms             2
            degrees_of_freedom          1
            internal_coordinates        1
            frozen_coordinates          0
        # definitions of redundant internals
        1 k  1.0000000000000 stre   1    2           val=   4.61410
                1 non zero eigenvalues  of BmBt
                1           2.000000000    1    0
                1
        $end

        :param filename: The name of the file to read from.
        """
        with open(filename, encoding="utf8") as f:
            lines = f.readlines()
            # number of atoms
            num_atoms = 0
            for line in lines:
                if line.startswith("$coord"):
                    continue
                if line.startswith("$end") or line.startswith("$redundant"):
                    break
                num_atoms += 1
            self.num_atoms = num_atoms
            # read the atomic coordinates
            self.xyz = np.zeros((self.num_atoms, 3))
            self.ati = np.zeros(self.num_atoms, dtype=int)
            self.atlist = np.zeros(103, dtype=int)
            for i in range(self.num_atoms):
                line_entries = lines[i + 1].split()
                self.xyz[i, 0] = float(line_entries[0]) * BOHR2AA
                self.xyz[i, 1] = float(line_entries[1]) * BOHR2AA
                self.xyz[i, 2] = float(line_entries[2]) * BOHR2AA
                self.ati[i] = PSE_NUMBERS[line_entries[3].lower()] - 1
                self.atlist[self.ati[i]] += 1

Signed-off-by: Jonathan Schöps <[email protected]>
Signed-off-by: Jonathan Schöps <[email protected]>
@jonathan-schoeps
Copy link
Contributor Author

Yes when you change the PARNODES than it woks as expected.

Signed-off-by: Jonathan Schöps <[email protected]>
src/mindlessgen/generator/main.py Outdated Show resolved Hide resolved
src/mindlessgen/molecules/molecule.py Outdated Show resolved Hide resolved
src/mindlessgen/molecules/molecule.py Outdated Show resolved Hide resolved
src/mindlessgen/molecules/molecule.py Outdated Show resolved Hide resolved
src/mindlessgen/molecules/molecule.py Outdated Show resolved Hide resolved
src/mindlessgen/qm/tm.py Outdated Show resolved Hide resolved
src/mindlessgen/qm/tm.py Outdated Show resolved Hide resolved
src/mindlessgen/qm/tm.py Outdated Show resolved Hide resolved
src/mindlessgen/qm/tm.py Outdated Show resolved Hide resolved
src/mindlessgen/qm/tm.py Outdated Show resolved Hide resolved
src/mindlessgen/generator/main.py Outdated Show resolved Hide resolved
src/mindlessgen/generator/main.py Show resolved Hide resolved
src/mindlessgen/generator/main.py Outdated Show resolved Hide resolved
src/mindlessgen/prog/config.py Outdated Show resolved Hide resolved
src/mindlessgen/qm/tm.py Outdated Show resolved Hide resolved
src/mindlessgen/qm/tm.py Outdated Show resolved Hide resolved
src/mindlessgen/qm/tm.py Outdated Show resolved Hide resolved
src/mindlessgen/qm/tm.py Outdated Show resolved Hide resolved
@marcelmbn
Copy link
Member

Works like a charm, great contribution!

After enhancing the coord read & write tests, this can safely be merged.

@jonathan-schoeps jonathan-schoeps merged commit 89a3d58 into grimme-lab:main Jan 17, 2025
11 checks passed
@jonathan-schoeps jonathan-schoeps deleted the dev/tm_interface branch January 17, 2025 10:25
@marcelmbn marcelmbn mentioned this pull request Jan 17, 2025
lmseidler added a commit that referenced this pull request Jan 20, 2025
* initial work

* new parallelization preliminary done

* small fix in tests

* commented unnecessary code

* updated construction sites

* hopefully fixed parallelization

* small test fix

* initial work

* new parallelization preliminary done

* small fix in tests

* commented unnecessary code

* updated construction sites

* hopefully fixed parallelization

* small test fix

* only print when verbosity > 0, otherwise nothing is printed (bad)

* pre-commit fixes

* added ncores to config + implemented setting ncores for external programs

* fixed tests

* added check for number of cores available vs needed

* pre-commit

* Added support for Turbomole (#101)

* Interface for the qm program turbomole

Signed-off-by: Jonathan Schöps <[email protected]>

* support for turbomole

Signed-off-by: Jonathan Schöps <[email protected]>

* corrected some typos

Signed-off-by: Jonathan Schöps <[email protected]>

* changed the PARNODES command

Signed-off-by: Jonathan Schöps <[email protected]>

* coord handling

Signed-off-by: Jonathan Schöps <[email protected]>

* requestet changes are build in

Signed-off-by: Jonathan Schöps <[email protected]>

* Implementation of the requested changes and the test of the read_mol_from_coord function

Signed-off-by: Jonathan Schöps <[email protected]>

* Implementation of two pathes for turbomole

Signed-off-by: Jonathan Schöps <[email protected]>

* Ignore HOMO-LUMO gap not implemented as refine engine  for Orca and Trubomole

Signed-off-by: Jonathan Schöps <[email protected]>

* improve TURBOMOLE configuration

Signed-off-by: Marcel Müller <[email protected]>

* correct linting errors

Signed-off-by: Marcel Mueller <[email protected]>

* exclude more recent interfaces from coverage check

Signed-off-by: Marcel Müller <[email protected]>

* added a test for the 'write_coord_to_file' function

Signed-off-by: Jonathan Schöps <[email protected]>

* sync the lokal branch with the remote branch

Signed-off-by: Jonathan Schöps <[email protected]>

---------

Signed-off-by: Jonathan Schöps <[email protected]>
Signed-off-by: Marcel Müller <[email protected]>
Signed-off-by: Marcel Mueller <[email protected]>
Co-authored-by: Marcel Müller <[email protected]>

* test fix

* fixed tm implementation

* updated main.py

* tqdm progress bar

* updated dependencies

* mypy types import

* moved warnings in correct bracket

* updated default config toml

* added final output of molecules and timing

* fixed time

* better time info

* print formatting

* shift block setup to parallel.py

Signed-off-by: Marcel Müller <[email protected]>

* avoid UnboundLocalError

Signed-off-by: Marcel Müller <[email protected]>

* some code formatting and printout adjustments

Signed-off-by: Marcel Müller <[email protected]>

* shifted CHANGELOG entry to correct position

Signed-off-by: Marcel Müller <[email protected]>

* update CODEOWNERS file

Signed-off-by: Marcel Müller <[email protected]>

* New parallelization (#108)

* initial work

* new parallelization preliminary done

* small fix in tests

* commented unnecessary code

* updated construction sites

* hopefully fixed parallelization

* small test fix

* initial work

* new parallelization preliminary done

* small fix in tests

* commented unnecessary code

* updated construction sites

* hopefully fixed parallelization

* small test fix

* only print when verbosity > 0, otherwise nothing is printed (bad)

* pre-commit fixes

* added ncores to config + implemented setting ncores for external programs

* fixed tests

* added check for number of cores available vs needed

* pre-commit

* test fix

* fixed tm implementation

* updated main.py

* tqdm progress bar

* updated dependencies

* mypy types import

* moved warnings in correct bracket

* updated default config toml

* added final output of molecules and timing

* fixed time

* better time info

* print formatting

* shift block setup to parallel.py

Signed-off-by: Marcel Müller <[email protected]>

* avoid UnboundLocalError

Signed-off-by: Marcel Müller <[email protected]>

* some code formatting and printout adjustments

Signed-off-by: Marcel Müller <[email protected]>

* shifted CHANGELOG entry to correct position

Signed-off-by: Marcel Müller <[email protected]>

* update CODEOWNERS file

Signed-off-by: Marcel Müller <[email protected]>

---------

Signed-off-by: Marcel Müller <[email protected]>
Co-authored-by: Marcel Müller <[email protected]>

* add IP/EA check with g-xTB for special purpose dev application only

Signed-off-by: Marcel Müller <[email protected]>

* rename gp3 to gxtb consistently

Signed-off-by: Marcel Müller <[email protected]>

* add simple SCF cycles check for molecule

Signed-off-by: Marcel Mueller <[email protected]>

* align variable names with g-xTB

Signed-off-by: Marcel Mueller <[email protected]>

* config is now loaded in dev mode; avoid redundant calculations

Signed-off-by: Marcel Mueller <[email protected]>

* hand over correct config and remove redundant config

Signed-off-by: Marcel Mueller <[email protected]>

* remove last rememnant of config for SCF cycles with g-xTB

Signed-off-by: Marcel Mueller <[email protected]>

* added ncores to gxtb calls

* remove redundant config entry

Signed-off-by: Marcel Mueller <[email protected]>

---------

Signed-off-by: Jonathan Schöps <[email protected]>
Signed-off-by: Marcel Müller <[email protected]>
Signed-off-by: Marcel Mueller <[email protected]>
Co-authored-by: Jonathan Schöps <[email protected]>
Co-authored-by: Marcel Müller <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
algorithm Related to the back-end algorithm for generating the mindless molecules.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

TM class for TURBOMOLE interface
2 participants