Biphenyl DFTB Torsional PES Scan¶
This report shows a scan of the central torsion in biphenyl with DFTB and summarizes the resulting energy profile, representative structures, and reusable Python workflow.
Requires: AMS2026 or later
Related documentation
Setup¶
Biphenyl was built from SMILES c1ccccc1-c2ccccc2 with ChemicalSystem.from_smiles. The central inter-ring C-C bond was identified by inspecting ChemicalSystem.bonds for the carbon-carbon bond whose removal cuts the molecule.
Central inter-ring bond, zero-based atom indices:
(5, 6)Central inter-ring bond, AMS one-based atom indices:
(6, 7)Inter-ring dihedral, zero-based atom indices:
(0, 5, 6, 7)Inter-ring dihedral, AMS one-based atom indices:
(1, 6, 7, 8)
The constrained AMS PESScan used DFTB with Model GFN1-xTB, scanning the inter-ring dihedral from 0 to 180 degrees in 19 points, i.e. 10 degree spacing. Energies below are reported relative to the lowest scan point.
Results¶

Minimum-energy scan point: 140.0 degrees.
Minimum-energy biphenyl twist angle: 40.0 degrees. This is reported as min(dihedral, 180 - dihedral) because the 0 to 180 degree scan has equivalent twisted structures on either side of 90 degrees.
Torsional barrier to the planar structure: 1.8050 kcal/mol. The 0 and 180 degree planar endpoints are both tabulated below; the quoted planar barrier is the lower of the two endpoint relative energies.
Torsional barrier to the perpendicular structure: 1.7045 kcal/mol.
Representative optimized structures¶
Planar geometry:

Minimum-energy geometry:

Perpendicular geometry:

Scan table¶
Dihedral angle (deg) |
Absolute energy (Hartree) |
Relative energy (kcal/mol) |
|---|---|---|
0.0 |
-30.7270479157 |
1.8050 |
10.0 |
-30.7276375568 |
1.4350 |
20.0 |
-30.7287351168 |
0.7463 |
30.0 |
-30.7296159661 |
0.1936 |
40.0 |
-30.7299151698 |
0.0058 |
50.0 |
-30.7296468314 |
0.1742 |
60.0 |
-30.7289488005 |
0.6122 |
70.0 |
-30.7281162675 |
1.1346 |
80.0 |
-30.7274575254 |
1.5480 |
90.0 |
-30.7272081545 |
1.7045 |
100.0 |
-30.7274586820 |
1.5473 |
110.0 |
-30.7281246087 |
1.1294 |
120.0 |
-30.7289611334 |
0.6045 |
130.0 |
-30.7296515698 |
0.1712 |
140.0 |
-30.7299244088 |
0.0000 |
150.0 |
-30.7296195325 |
0.1913 |
160.0 |
-30.7287447482 |
0.7402 |
170.0 |
-30.7276400215 |
1.4335 |
180.0 |
-30.7270454035 |
1.8066 |
AMS input¶
The PES scan job was loaded from /home/ubuntu/work/01-run-biphenyl-dftb-pesscan_workdir/biphenyl_dftb_torsion with AMSJob.load_external(...).
PESScan
Optimize True
ScanCoordinate
Dihedral 1 6 7 8 0.0 180.0
nPoints 19
End
End
Task PESScan
System
Atoms
C 1.5436277587 -0.6712511736 -0.8743423895
C 2.9379238219 -0.6084386430 -0.7895740467
C 3.5458648903 0.1540229069 0.2101358580
C 2.7607157299 0.8559722841 1.1272880062
C 1.3659731986 0.7976348543 1.0467720204
C 0.7407365542 0.0321748032 0.0438974615
C -0.7407365262 -0.0321759898 -0.0438985615
C -1.3882544717 -1.2464975341 -0.3418076249
C -2.7829651518 -1.3041919267 -0.4233311075
C -3.5458647518 -0.1540214568 -0.2101369285
C -2.9156742946 1.0566598609 0.0856160895
C -1.5213463694 1.1201124254 0.1693765138
H 1.0941322198 -1.2547297485 -1.6679429353
H 3.5475041862 -1.1489839049 -1.5021581640
H 4.6253028921 0.2009111764 0.2741061689
H 3.2330362523 1.4435115455 1.9039896331
H 0.7773312479 1.3360188999 1.7788506547
H -0.8179456227 -2.1542017782 -0.4938473594
H -3.2727104357 -2.2427544850 -0.6487281126
H -4.6253028983 -0.2009093371 -0.2741044826
H -3.5078300382 1.9482274962 0.2468998516
H -1.0535181915 2.0729097247 0.3829394549
End
BondOrders
1 2 1.5
1 6 1.5
1 13 1.0
2 3 1.5
2 14 1.0
3 4 1.5
3 15 1.0
4 5 1.5
4 16 1.0
5 6 1.5
5 17 1.0
6 7 1.0
7 8 1.5
7 12 1.5
8 9 1.5
8 18 1.0
9 10 1.5
9 19 1.0
10 11 1.5
10 20 1.0
11 12 1.5
11 21 1.0
12 22 1.0
End
End
Engine dftb
Model GFN1-xTB
EndEngine
Conclusion¶
The DFTB scan places the minimum at a scan dihedral of 140.0 degrees, corresponding to a biphenyl twist of 40.0 degrees. Relative to this point, the lower planar endpoint is 1.8050 kcal/mol higher and the perpendicular point is 1.7045 kcal/mol higher.
Prompts and Python scripts¶
Prompt (instruction for AI agent)
Use $ams2026
Calculate the torsional potential energy profile of biphenyl with DFTB.
Build biphenyl from SMILES c1ccccc1-c2ccccc2. Identify the central inter-ring
C-C bond and the four atoms defining the inter-ring dihedral by inspecting
the ChemicalSystem bonds.
Run a constrained AMS PES Scan over the inter-ring dihedral from 0 to 180
degrees in 10 degree steps. Use DFTB.
Plot relative energy in kcal/mol vs dihedral angle. In the report, identify
the minimum-energy twist angle and the torsional barriers to the planar and
perpendicular structures.
Include pictures of the optimized structures at the planar geometry, the
minimum-energy geometry, and the perpendicular geometry. Include a table
with dihedral angle, absolute energy, and relative energy for all scan points.
01-run-biphenyl-dftb-pesscan.py
#!/usr/bin/env amspython
from __future__ import annotations
from dataclasses import dataclass
from scm.base import ChemicalSystem
from scm.plams import AMSJob, Settings, init
SMILES = "c1ccccc1-c2ccccc2"
JOB_NAME = "biphenyl_dftb_torsion"
@dataclass(frozen=True)
class TorsionDefinition:
central_bond: tuple[int, int]
dihedral: tuple[int, int, int, int]
@property
def ams_dihedral_line(self) -> str:
a, b, c, d = (idx + 1 for idx in self.dihedral)
return f"{a} {b} {c} {d} 0.0 180.0"
def carbon_neighbors(system: ChemicalSystem, atom_index: int, exclude: int) -> list[int]:
return [
idx
for idx in system.bonds.get_bonded_atoms(atom_index)
if idx != exclude and system.atoms[idx].symbol == "C"
]
def identify_inter_ring_torsion(system: ChemicalSystem) -> TorsionDefinition:
candidates: list[tuple[int, int]] = []
for i, j, _bond in system.bonds:
if system.atoms[i].symbol != "C" or system.atoms[j].symbol != "C":
continue
if system.bond_cuts_molecule(i, j):
candidates.append((i, j))
if len(candidates) != 1:
raise RuntimeError(f"Expected one central inter-ring C-C bond, found {candidates}")
left, right = candidates[0]
left_neighbors = carbon_neighbors(system, left, exclude=right)
right_neighbors = carbon_neighbors(system, right, exclude=left)
if not left_neighbors or not right_neighbors:
raise RuntimeError("Could not find ring-neighbor carbon atoms for the inter-ring dihedral")
return TorsionDefinition(
central_bond=(left, right),
dihedral=(left_neighbors[0], left, right, right_neighbors[0]),
)
def make_settings(torsion: TorsionDefinition) -> Settings:
settings = Settings()
settings.input.ams.task = "PESScan"
settings.input.ams.pesscan.optimize = True
settings.input.ams.pesscan.scancoordinate.npoints = 19
settings.input.ams.pesscan.scancoordinate.dihedral = torsion.ams_dihedral_line
settings.input.dftb.model = "GFN1-xTB"
return settings
def main() -> None:
init(folder="01-run-biphenyl-dftb-pesscan_workdir")
system = ChemicalSystem.from_smiles(SMILES)
torsion = identify_inter_ring_torsion(system)
settings = make_settings(torsion)
print(f"Built {system.formula()} from SMILES: {SMILES}")
print(f"Central inter-ring C-C bond, zero-based: {torsion.central_bond}")
print(f"Inter-ring dihedral, zero-based: {torsion.dihedral}")
print(f"AMS dihedral scan line: {torsion.ams_dihedral_line}")
job = AMSJob(molecule=system, settings=settings, name=JOB_NAME)
result = job.run()
if not result.ok():
raise RuntimeError(f"AMS job failed; inspect {job.path}")
if __name__ == "__main__":
main()
02-report.py
#!/usr/bin/env amspython
from __future__ import annotations
from dataclasses import dataclass
from pathlib import Path
import matplotlib.pyplot as plt
import pandas as pd
from scm.base import ChemicalSystem, Units
from scm.plams import AMSJob, view
SMILES = "c1ccccc1-c2ccccc2"
JOB_NAME = "biphenyl_dftb_torsion"
@dataclass(frozen=True)
class TorsionDefinition:
central_bond: tuple[int, int]
dihedral: tuple[int, int, int, int]
@property
def central_bond_one_based(self) -> tuple[int, int]:
return tuple(idx + 1 for idx in self.central_bond)
@property
def dihedral_one_based(self) -> tuple[int, int, int, int]:
return tuple(idx + 1 for idx in self.dihedral)
def carbon_neighbors(system: ChemicalSystem, atom_index: int, exclude: int) -> list[int]:
return [
idx
for idx in system.bonds.get_bonded_atoms(atom_index)
if idx != exclude and system.atoms[idx].symbol == "C"
]
def identify_inter_ring_torsion(system: ChemicalSystem) -> TorsionDefinition:
candidates: list[tuple[int, int]] = []
for i, j, _bond in system.bonds:
if system.atoms[i].symbol == "C" and system.atoms[j].symbol == "C":
if system.bond_cuts_molecule(i, j):
candidates.append((i, j))
if len(candidates) != 1:
raise RuntimeError(f"Expected one central inter-ring C-C bond, found {candidates}")
left, right = candidates[0]
left_neighbors = carbon_neighbors(system, left, exclude=right)
right_neighbors = carbon_neighbors(system, right, exclude=left)
if not left_neighbors or not right_neighbors:
raise RuntimeError("Could not find ring-neighbor carbon atoms for the inter-ring dihedral")
return TorsionDefinition(
central_bond=(left, right),
dihedral=(left_neighbors[0], left, right, right_neighbors[0]),
)
def latest_job_path() -> Path:
candidates = sorted(Path(".").glob("01-run-biphenyl-dftb-pesscan_workdir*/" + JOB_NAME))
if not candidates:
raise FileNotFoundError("No biphenyl PES scan job directory was found")
return candidates[-1]
def pesscan_dataframe(job: AMSJob) -> tuple[pd.DataFrame, list[ChemicalSystem]]:
results = job.results.get_pesscan_results()
angles = pd.Series(results["RaveledPESCoords"][0], dtype=float)
if angles.abs().max() <= 2.0 * 3.141592653589793:
angles = angles * Units.conversion_factor("radian", "degree")
energies_hartree = pd.Series(results["PES"], dtype=float)
min_energy_hartree = energies_hartree.min()
relative_kcal = (energies_hartree - min_energy_hartree) * Units.conversion_factor("Hartree", "kcal/mol")
df = pd.DataFrame(
{
"Dihedral angle (deg)": angles.round(6),
"Absolute energy (Hartree)": energies_hartree,
"Relative energy (kcal/mol)": relative_kcal,
}
)
return df, list(results["Molecules"])
def nearest_index(df: pd.DataFrame, target: float) -> int:
return int((df["Dihedral angle (deg)"] - target).abs().idxmin())
def write_plot(df: pd.DataFrame) -> None:
fig, ax = plt.subplots(figsize=(6.5, 4.2))
ax.plot(df["Dihedral angle (deg)"], df["Relative energy (kcal/mol)"], marker="o", linewidth=1.8)
ax.set_xlabel("Dihedral angle (deg)")
ax.set_ylabel("Relative energy (kcal/mol)")
ax.set_xlim(0, 180)
ax.grid(True, alpha=0.25)
fig.tight_layout()
fig.savefig("biphenyl_torsion_profile.png", dpi=180)
plt.close(fig)
def write_structure_images(df: pd.DataFrame, molecules: list[ChemicalSystem]) -> dict[str, str]:
min_idx = int(df["Relative energy (kcal/mol)"].idxmin())
image_specs = {
"planar": nearest_index(df, 0.0),
"minimum": min_idx,
"perpendicular": nearest_index(df, 90.0),
}
output: dict[str, str] = {}
for label, idx in image_specs.items():
filename = f"biphenyl_{label}.png"
view(molecules[idx], width=360, height=280, guess_bonds=True, direction="along_pca3", picture_path=filename)
output[label] = filename
return output
def write_report(job: AMSJob, df: pd.DataFrame, images: dict[str, str], torsion: TorsionDefinition) -> None:
min_idx = int(df["Relative energy (kcal/mol)"].idxmin())
planar0_idx = nearest_index(df, 0.0)
planar180_idx = nearest_index(df, 180.0)
perpendicular_idx = nearest_index(df, 90.0)
min_angle = df.loc[min_idx, "Dihedral angle (deg)"]
min_twist = min(min_angle, 180.0 - min_angle)
planar_barrier = min(
df.loc[planar0_idx, "Relative energy (kcal/mol)"],
df.loc[planar180_idx, "Relative energy (kcal/mol)"],
)
perpendicular_barrier = df.loc[perpendicular_idx, "Relative energy (kcal/mol)"]
table = df.copy()
table["Absolute energy (Hartree)"] = table["Absolute energy (Hartree)"].map(lambda x: f"{x:.10f}")
table["Relative energy (kcal/mol)"] = table["Relative energy (kcal/mol)"].map(lambda x: f"{x:.4f}")
table["Dihedral angle (deg)"] = table["Dihedral angle (deg)"].map(lambda x: f"{x:.1f}")
report = f"""# Biphenyl DFTB torsional PES scan
## Setup
Biphenyl was built from SMILES `{SMILES}` with `ChemicalSystem.from_smiles`. The central inter-ring C-C bond was identified by inspecting `ChemicalSystem.bonds` for the carbon-carbon bond whose removal cuts the molecule.
- Central inter-ring bond, zero-based atom indices: `{torsion.central_bond}`
- Central inter-ring bond, AMS one-based atom indices: `{torsion.central_bond_one_based}`
- Inter-ring dihedral, zero-based atom indices: `{torsion.dihedral}`
- Inter-ring dihedral, AMS one-based atom indices: `{torsion.dihedral_one_based}`
The constrained AMS `PESScan` used DFTB with `Model GFN1-xTB`, scanning the inter-ring dihedral from 0 to 180 degrees in 19 points, i.e. 10 degree spacing. Energies below are reported relative to the lowest scan point.
## Results

Minimum-energy scan point: **{min_angle:.1f} degrees**.
Minimum-energy biphenyl twist angle: **{min_twist:.1f} degrees**. This is reported as `min(dihedral, 180 - dihedral)` because the 0 to 180 degree scan has equivalent twisted structures on either side of 90 degrees.
Torsional barrier to the planar structure: **{planar_barrier:.4f} kcal/mol**. The 0 and 180 degree planar endpoints are both tabulated below; the quoted planar barrier is the lower of the two endpoint relative energies.
Torsional barrier to the perpendicular structure: **{perpendicular_barrier:.4f} kcal/mol**.
## Representative optimized structures
Planar geometry:

Minimum-energy geometry:

Perpendicular geometry:

## Scan table
{table.to_markdown(index=False, disable_numparse=True)}
## AMS input
The PES scan job was loaded from `{job.path}` with `AMSJob.load_external(...)`.
```ams
{job.get_input()}
```
## Conclusion
The DFTB scan places the minimum at a scan dihedral of {min_angle:.1f} degrees, corresponding to a biphenyl twist of {min_twist:.1f} degrees. Relative to this point, the lower planar endpoint is {planar_barrier:.4f} kcal/mol higher and the perpendicular point is {perpendicular_barrier:.4f} kcal/mol higher.
"""
Path("report.md").write_text(report)
def main() -> None:
system = ChemicalSystem.from_smiles(SMILES)
torsion = identify_inter_ring_torsion(system)
job = AMSJob.load_external(str(latest_job_path()))
df, molecules = pesscan_dataframe(job)
write_plot(df)
images = write_structure_images(df, molecules)
write_report(job, df, images, torsion)
if __name__ == "__main__":
main()
Original Markdown report
# Biphenyl DFTB torsional PES scan
## Setup
Biphenyl was built from SMILES `c1ccccc1-c2ccccc2` with `ChemicalSystem.from_smiles`. The central inter-ring C-C bond was identified by inspecting `ChemicalSystem.bonds` for the carbon-carbon bond whose removal cuts the molecule.
- Central inter-ring bond, zero-based atom indices: `(5, 6)`
- Central inter-ring bond, AMS one-based atom indices: `(6, 7)`
- Inter-ring dihedral, zero-based atom indices: `(0, 5, 6, 7)`
- Inter-ring dihedral, AMS one-based atom indices: `(1, 6, 7, 8)`
The constrained AMS `PESScan` used DFTB with `Model GFN1-xTB`, scanning the inter-ring dihedral from 0 to 180 degrees in 19 points, i.e. 10 degree spacing. Energies below are reported relative to the lowest scan point.
## Results

Minimum-energy scan point: **140.0 degrees**.
Minimum-energy biphenyl twist angle: **40.0 degrees**. This is reported as `min(dihedral, 180 - dihedral)` because the 0 to 180 degree scan has equivalent twisted structures on either side of 90 degrees.
Torsional barrier to the planar structure: **1.8050 kcal/mol**. The 0 and 180 degree planar endpoints are both tabulated below; the quoted planar barrier is the lower of the two endpoint relative energies.
Torsional barrier to the perpendicular structure: **1.7045 kcal/mol**.
## Representative optimized structures
Planar geometry:

Minimum-energy geometry:

Perpendicular geometry:

## Scan table
| Dihedral angle (deg) | Absolute energy (Hartree) | Relative energy (kcal/mol) |
|:-----------------------|:----------------------------|:-----------------------------|
| 0.0 | -30.7270479157 | 1.8050 |
| 10.0 | -30.7276375568 | 1.4350 |
| 20.0 | -30.7287351168 | 0.7463 |
| 30.0 | -30.7296159661 | 0.1936 |
| 40.0 | -30.7299151698 | 0.0058 |
| 50.0 | -30.7296468314 | 0.1742 |
| 60.0 | -30.7289488005 | 0.6122 |
| 70.0 | -30.7281162675 | 1.1346 |
| 80.0 | -30.7274575254 | 1.5480 |
| 90.0 | -30.7272081545 | 1.7045 |
| 100.0 | -30.7274586820 | 1.5473 |
| 110.0 | -30.7281246087 | 1.1294 |
| 120.0 | -30.7289611334 | 0.6045 |
| 130.0 | -30.7296515698 | 0.1712 |
| 140.0 | -30.7299244088 | 0.0000 |
| 150.0 | -30.7296195325 | 0.1913 |
| 160.0 | -30.7287447482 | 0.7402 |
| 170.0 | -30.7276400215 | 1.4335 |
| 180.0 | -30.7270454035 | 1.8066 |
## AMS input
The PES scan job was loaded from `/home/ubuntu/work/01-run-biphenyl-dftb-pesscan_workdir/biphenyl_dftb_torsion` with `AMSJob.load_external(...)`.
```ams
PESScan
Optimize True
ScanCoordinate
Dihedral 1 6 7 8 0.0 180.0
nPoints 19
End
End
Task PESScan
System
Atoms
C 1.5436277587 -0.6712511736 -0.8743423895
C 2.9379238219 -0.6084386430 -0.7895740467
C 3.5458648903 0.1540229069 0.2101358580
C 2.7607157299 0.8559722841 1.1272880062
C 1.3659731986 0.7976348543 1.0467720204
C 0.7407365542 0.0321748032 0.0438974615
C -0.7407365262 -0.0321759898 -0.0438985615
C -1.3882544717 -1.2464975341 -0.3418076249
C -2.7829651518 -1.3041919267 -0.4233311075
C -3.5458647518 -0.1540214568 -0.2101369285
C -2.9156742946 1.0566598609 0.0856160895
C -1.5213463694 1.1201124254 0.1693765138
H 1.0941322198 -1.2547297485 -1.6679429353
H 3.5475041862 -1.1489839049 -1.5021581640
H 4.6253028921 0.2009111764 0.2741061689
H 3.2330362523 1.4435115455 1.9039896331
H 0.7773312479 1.3360188999 1.7788506547
H -0.8179456227 -2.1542017782 -0.4938473594
H -3.2727104357 -2.2427544850 -0.6487281126
H -4.6253028983 -0.2009093371 -0.2741044826
H -3.5078300382 1.9482274962 0.2468998516
H -1.0535181915 2.0729097247 0.3829394549
End
BondOrders
1 2 1.5
1 6 1.5
1 13 1.0
2 3 1.5
2 14 1.0
3 4 1.5
3 15 1.0
4 5 1.5
4 16 1.0
5 6 1.5
5 17 1.0
6 7 1.0
7 8 1.5
7 12 1.5
8 9 1.5
8 18 1.0
9 10 1.5
9 19 1.0
10 11 1.5
10 20 1.0
11 12 1.5
11 21 1.0
12 22 1.0
End
End
Engine dftb
Model GFN1-xTB
EndEngine
```
## Conclusion
The DFTB scan places the minimum at a scan dihedral of 140.0 degrees, corresponding to a biphenyl twist of 40.0 degrees. Relative to this point, the lower planar endpoint is 1.8050 kcal/mol higher and the perpendicular point is 1.7045 kcal/mol higher.
Note on AI-generated content¶
This page was generated by a Python script. That Python script was AI-generated.
All numbers, figures, and tables are extracted or postprocessed from actual AMS calculations, and can be transparently regenerated from the provided Python scripts.
Any scientific reasoning or citations was written by AI. This page is the actual one-shot output from using the ams2026 skill with an AI coding agent.