tqchem

TQChem documentation

  • Introduction
  • Installation
  • Usage
    • Examples
      • Conformer’s coordinate screening
      • Conformer Search
        • Representation of a molecule
        • Perform optimization
        • Visualize the molecule with lowest energy
        • Optimize structure using CREST:
        • Compare energies of rdkit and ttconf conformers
        • Bond selection
        • Ring systems
      • Create a vmd movie from .xyz file
      • One- and Two-Dimensional Scans of Potential Energy
      • Simulate IR spectrum
    • Command-Line Interface

Quantum Chemistry tools

  • Overview
  • GauXC
  • LibintX
tqchem
  • Introduction
  • Examples
  • Conformer Search
  • View page source

Conformer Search

The goal in Conformer optimization is to find the most stable 3D structure of a molecule which differ by dihedral angles, bond angles and bond lengths. We use tensor trains to avoid the exponential complexity of the conformer search problem.

A more detailed explanation can be found in our paper.

Representation of a molecule

The internal representation of a molecule in TQchem is the MolecularSystem class, which can be initialized from a variety of popular molecule representations. TQchem supports conversion from:

  • rdkit.Mol

  • ase.Atoms

  • smiles string

  • xyz file/xyz block

For example, below is an example of creating a MolecularSystem object from an xyz block:

[1]:
from tqchem.viewer import plot_3D_molecule
from tqchem.molgraph import molecularSystem

xyz_block = """13

C     -1.044461   -0.825824    0.211330
C     -0.285778    0.490479    0.068986
O     -0.589226    1.155464   -1.136284
C      1.232755    0.259051    0.185495
O      1.610069   -0.323671    1.406869
H     -2.115750   -0.643571    0.208448
H     -0.791736   -1.487830   -0.614662
H     -0.764530   -1.309872    1.143418
H     -0.605130    1.182551    0.857893
H     -0.296714    0.606873   -1.873951
H      1.557840   -0.441551   -0.590202
H      1.752598    1.214578    0.025047
H      1.331217    0.249819    2.128887"""

initial_molecule = molecularSystem(xyz_block)
plot_3D_molecule(initial_molecule.ase).show()

3Dmol.js failed to load for some reason. Please check your browser console for error messages.

Perform optimization

Here we run ttconf with 2 sweeps and rank 2 for the xyz representation of propylene glycol.

This could also be done from the command line using:

tqchem ttconf --xyz propyleneglycol.xyz --rank 2 --n_sweeps 2

Or for the smiles string:

tqchem ttconf CC(CO)O --rank 2 --n_sweeps 2
[2]:
from tqchem.ttconf.factory import ttconf_optimizer

ttopt = ttconf_optimizer(initial_molecule, filter_type="energy")

results = ttopt.optimize()
best_conformer_xyz, energy_best_conformer = results.minimum_energy_xyz()
best_conformer = molecularSystem(best_conformer_xyz)

print(f"{energy_best_conformer = }")
sweep | index |   Objective  | Runtime
----------------------------------------------
    1 |     3 |  -506.703733 | 0:00:01.470481
    1 |     2 |  -506.736523 | 0:00:03.579517
    1 |     1 |  -506.739942 | 0:00:04.397643
    2 |     1 |  -506.739942 | 0:00:04.398248
    2 |     2 |  -506.739942 | 0:00:07.443877
    2 |     3 |  -506.739942 | 0:00:08.495648
energy_best_conformer = -506.73994247418153

Visualize the molecule with lowest energy

[3]:
plot_3D_molecule(best_conformer_xyz).show()

3Dmol.js failed to load for some reason. Please check your browser console for error messages.

Optimize structure using CREST:

Although global optimization in TTConf includes local optimization, it is often useful to perform a “final” local optimization of the structure at the end of the global optimization. Below we perform the optimization of a conformational ensemble with an energy window of 6 kcal/mol from the minimal conformer using the CREST wrapper built into TQchem:

[4]:
from tqchem.chem import ase_from_molecule_file_content
from tqchem.ttconf.crest_wrapper import launch_crest
import numpy as np

xyzs = results.minimum_energy_ensemble(
    energy_window=0.26,
    rmsd_threshold=0.125,
)
ensemble = [ase_from_molecule_file_content(xyz) for xyz in xyzs]
optimized_ensemble, optimized_energies = launch_crest(
    ensemble,
    optlevel="normal",
)

best_conformer_crestOpt = np.argmin(optimized_energies)
energy_best_conformer_crestOpt = optimized_energies[best_conformer_crestOpt]
molecule_best_conformer_crestOpt = optimized_ensemble[best_conformer_crestOpt]

Compare energies of rdkit and ttconf conformers

[5]:
from tblite.ase import TBLite

# Energy of initial rdkit conformer
initial_molecule.ase.calc = TBLite(method="GFN2-xTB", verbosity=0)
energy_initial = initial_molecule.ase.get_potential_energy()

# Energy of the TTconf optimized, but not gradient optimized molecule
best_conformer.ase.calc = TBLite(method="GFN2-xTB", verbosity=0)
energy_best_conformer = best_conformer.ase.get_potential_energy()

energies = {
    "E(initial geometry)     ": energy_initial,
    "E(TTconf geometry)      ": energy_best_conformer,
    "E(TTconf+CREST geometry)": energy_best_conformer_crestOpt,
}
print("\n".join(f"{label}: {e:.7f}" for label, e in energies.items()))
E(initial geometry)     : -506.7007039
E(TTconf geometry)      : -506.7399425
E(TTconf+CREST geometry): -506.7423777
[6]:
print("TTconf best geometry:")
plot_3D_molecule(molecule_best_conformer_crestOpt).show()
TTconf best geometry:

3Dmol.js failed to load for some reason. Please check your browser console for error messages.

Bond selection

It is possible to select the bonds that are considered rotatable. For the bond selection we first investigate the molecular graph and then select the bonds (as tuple of 2 atom IDs) and corresponding dihedral values (as array).

[7]:
import numpy as np

xyz_block = """13

C     -1.044461   -0.825824    0.211330
C     -0.285778    0.490479    0.068986
O     -0.589226    1.155464   -1.136284
C      1.232755    0.259051    0.185495
O      1.610069   -0.323671    1.406869
H     -2.115750   -0.643571    0.208448
H     -0.791736   -1.487830   -0.614662
H     -0.764530   -1.309872    1.143418
H     -0.605130    1.182551    0.857893
H     -0.296714    0.606873   -1.873951
H      1.557840   -0.441551   -0.590202
H      1.752598    1.214578    0.025047
H      1.331217    0.249819    2.128887"""

initial_molecule = molecularSystem(xyz_block)
initial_molecule.draw()
../../_images/tqchem_examples_conformer_search_13_0.png
[8]:
ttopt = ttconf_optimizer(
    initial_molecule,
    charge=0,
    solvent=None,
    method="GFN2-xTB",
    ensemble_optimization=True,
    set_rotatable_bonds={(0, 1): np.linspace(0, 360, 12, endpoint=False)},
)

results = ttopt.optimize()
one_dihedral_xyz, energy_one_dihedral = results.minimum_energy_xyz()
one_dihedral = molecularSystem(one_dihedral_xyz)
print(f"{energy_one_dihedral = }")
plot_3D_molecule(one_dihedral_xyz).show()
sweep | index |   Objective  | Runtime
----------------------------------------------
    1 |     1 |  -506.704737 | 0:00:00.618454
    2 |     1 |  -506.704737 | 0:00:00.618814
energy_one_dihedral = -506.7047367387411

3Dmol.js failed to load for some reason. Please check your browser console for error messages.

Ring systems

At the moment, only 5- and 6-rings can be optimized with TTconf as we implemented a different way of treating rings.

[9]:
from tqchem.viewer import plot_3D_molecule

initial_molecule = molecularSystem("O1CCCCC1CCO")
plot_3D_molecule(initial_molecule.ase).show()

ttopt = ttconf_optimizer(
    initial_molecule,
    filter_type="energy",
    charge=0,
    solvent=None,
    method="GFN2-xTB",
    ensemble_optimization=True,
)

results = ttopt.optimize()
best_conformer_xyz, energy_best_conformer = results.minimum_energy_xyz()
best_conformer = molecularSystem(best_conformer_xyz)

print(f"{energy_best_conformer = }")
plot_3D_molecule(best_conformer_xyz).show()

3Dmol.js failed to load for some reason. Please check your browser console for error messages.

sweep | index |   Objective  | Runtime
----------------------------------------------
    1 |     4 |  -823.571253 | 0:00:02.313301
    1 |     3 |  -823.597379 | 0:00:07.225027
    1 |     2 |  -823.598813 | 0:00:10.513202
    1 |     1 |  -823.649913 | 0:00:11.509907
    2 |     1 |  -823.649913 | 0:00:11.510494
    2 |     2 |  -823.649955 | 0:00:13.192635
    2 |     3 |  -823.749278 | 0:00:16.634608
    2 |     4 |  -823.749278 | 0:00:17.982260
energy_best_conformer = -823.7492781160647

3Dmol.js failed to load for some reason. Please check your browser console for error messages.

For bigger rings like a 7-ring the optimization with default parameters will fail.

[10]:
initial_molecule = molecularSystem("O1CCC(CCN)CCC1")
plot_3D_molecule(initial_molecule.ase).show()

try:
    ttopt = ttconf_optimizer(initial_molecule)
except Exception:
    print("Impossible to run calculations for 7-ring with default settings.")

3Dmol.js failed to load for some reason. Please check your browser console for error messages.

Impossible to run calculations for 7-ring with default settings.

It is, however, possible to avoid the separate treatment of rings by setting single_batframe=True

[11]:
initial_molecule = molecularSystem("O1CCC(CCN)CCC1", single_batframe=True)

ttopt = ttconf_optimizer(
    initial_molecule,
    charge=0,
    filter_type="boltzmann energy difference",
    solvent=None,
    method="GFN2-xTB",
    ensemble_optimization=True,
)

results = ttopt.optimize()
best_conformer_xyz, energy_best_conformer = results.minimum_energy_xyz()
best_conformer = molecularSystem(best_conformer_xyz)

print(f"{energy_best_conformer = }")
plot_3D_molecule(initial_molecule.ase).show()
sweep | index |   Objective  | Runtime
----------------------------------------------
    1 |     3 |    -8.432938 | 0:00:01.921600
    1 |     2 |   -14.969960 | 0:00:04.880685
    1 |     1 |   -16.708092 | 0:00:06.968987
    2 |     1 |   -16.708092 | 0:00:06.969724
    2 |     2 |   -16.716360 | 0:00:10.981002
    2 |     3 |   -19.317325 | 0:00:13.139157
energy_best_conformer = -892.0589298575549

3Dmol.js failed to load for some reason. Please check your browser console for error messages.

Previous Next

© Copyright 2024, Roman Ellerbrock, Ruslan Mallaev, Alexander Paul, Vladimir Mironov.

Built with Sphinx using a theme provided by Read the Docs.