Tutorial: from a DFT geometry optimization to properties#

This tutorial ties Part I together with one realistic task: start from a rough guess of a molecule, let DFT find its equilibrium structure, and then analyze that structure. It is the everyday shape of a quantum-chemistry study — optimize, then interpret. We use water again so the numbers are easy to check.

By the end you will have used the checkpoint/step/run model from Core concepts for a multi-step calculation.

Step 1 — build a (deliberately imperfect) molecule#

We start from a bad guess: an O–H distance and angle that are clearly off. The point of the optimization is to fix them.

import qc

mol = qc.chk.new(
    atom="O 0.00 0.00 0.00; H 0.00 0.80 0.55; H 0.00 -0.80 0.55",   # rough, not equilibrium
    ao="def2-svp",
    unit="angstrom",
)

Step 2 — optimize the geometry with DFT#

Add an SCF step (B3LYP), attach an .opt() to it, and run. .opt() repeatedly computes the energy and its gradient (the force on each atom) and steps the nuclei downhill until the forces vanish — the equilibrium structure.

mol = mol.scf(ref="r", xc="b3lyp").opt().run()

print("converged:", mol.opt.converged)          # True
print("energy    :", round(mol.opt.energy, 6))   # -76.358316  (hartree)

.run() is silent by default; add run(log="stdout") to stream the optimizer’s progress — a per-cycle table of the energy and its gradient, ending in Converged! after a few steps. (The same log= switch drives every run; log_style="modern"/"orca" restyles it and plot=True plots the trajectory inline — see the Quickstart tip and Logging & output.) The optimized water has

  • O–H bond length ≈ 0.967 Å (up from our 0.97-ish rough guess, but now consistent both sides), and

  • H–O–H angle ≈ 103.1° — close to the experimental 104.5°, a typical B3LYP/def2-SVP result.

Note

What just happened, in workflow terms .scf(...).opt() added two linked pending steps; .run() resolved them — each optimization cycle is an SCF on a slightly moved geometry. The final checkpoint mol now holds the optimized structure and its electronic state, ready to analyze.

Tip

Use more cores: nthread= An optimization runs many SCFs (one per cycle), so it is a natural place to use more of your machine. By default qc-rs uses a single CPU core; add run(nthread=8) to spread each SCF across 8 cores — the same shared-memory thread parallelism from the Quickstart, and the easy speedup on a laptop or single node. (Spreading a job across multiple machines with MPI process parallelism, nmpi=, is an advanced topic covered later in Parallel computing & HPC; you do not need it here.)

Step 3 — analyze the optimized structure#

Now ask the optimized checkpoint for properties. First the Mulliken atomic charges:

q = qc.prop.chrg.mulliken(mol)
print(q["charges"])       # [-0.2945, 0.1472, 0.1472]

Oxygen is negative, the hydrogens positive — water’s familiar polarity. We can quantify that polarity with the dipole moment:

mp = qc.prop.mpol.molecular(mol)
print(round(mp["dipole_magnitude_debye"], 2))    # 2.00  (debye)

A dipole of about 2.0 D is exactly right for water (experiment ≈ 1.85 D; the difference is basis-set and method, a theme of Foundations).

The whole thing#

Put together, the study is seven lines:

import qc

mol = qc.chk.new(
    atom="O 0.00 0.00 0.00; H 0.00 0.80 0.55; H 0.00 -0.80 0.55",
    ao="def2-svp", unit="angstrom",
).scf(ref="r", xc="b3lyp").opt().run()

print("E =", round(mol.opt.energy, 6), "hartree, converged:", mol.opt.converged)
print("charges =", qc.prop.chrg.mulliken(mol)["charges"])
print("dipole  =", round(qc.prop.mpol.molecular(mol)["dipole_magnitude_debye"], 2), "D")

That is a complete “optimize then analyze” workflow: a molecule in, an equilibrium structure and its properties out.

What you have learned, and where to go#

You have now:

  • built a molecule and chosen a method and basis set;

  • chained steps (scfopt) and run them;

  • read results (mol.opt.energy) and computed properties (mulliken, the dipole).

That is the core loop of qc-rs. To understand what Hartree–Fock and DFT actually compute — and why the dipole came out a little large — read Part II — Foundations. To go deeper on any single step, the User guide has a chapter for each, ending with the full molecular-properties suite.