DTCAM-TB¶
DTCAM-TB is the tuned MRSF-TDDFTB operator of the OpenQP-DFTB library: a plain DFTB2 ground-state reference combined with an independent long-range-corrected response kernel, a rescaled spin-magnetization kernel, and a small response-only one-center exchange term. It restores the relative ordering of ionic-bright and covalent-dark ππ* states that the conventional LC-DFTB protocol inverts, so S₁/S₂ crossings, seams, and excited-state minima come out at MRSF-TDDFT quality but at tight-binding cost.
You never spell the operator out. It is selected as a named preset with
[dftb] model=dtcam, and the parameter vector is
resolved inside libopenqp_dftb_c so an input can never drift from the
published values. This page is the DTCAM-TB task manual; the response
formalism itself is documented under MRSF-TDDFTB and the
complete key list under [dftb].
External library and development preview
The DFTB method is provided by the optional OpenQP-DFTB library
(openqp-dftb,
loaded via ctypes); build it from source or build OpenQP with
-DENABLE_OPENQP_DFTB=ON (see the [dftb] reference
for the full build and library-discovery note). The integration is tracked
in OpenQP PR #266
and is not part of OpenQP 1.2.0. The one-line .oqp format is likewise a
development-branch input style (see One-line .oqp).
Operator presets¶
[dftb] model names a complete, published operator and its numerical
protocol (mixer, SCC budget and tolerance, response solver, gradient path).
model= |
Legacy aliases (still accepted) | What it is |
|---|---|---|
dtcam |
dtcam-tb, dtcam_tb, dtcamtb |
The production MRSF-TDDFTB operator (the DTCAM-TB method). Plain DFTB2 reference (no long-range term at all); independent erf response kernel; response-only one-center pp exchange that lowers the covalent 2¹A_g⁻. Default for MRSF. |
dtcam2 / dtcam-erf |
dtcam-tb2, dtcam_tb2, dtcamtb2, dtcam-tb-erf, dtcam_tb_erf, dtcamtberf |
Refit variant: explicit erf response kernel, softened long-range response weight, one-center exchange switched off. Use it only when reproducing that refit. |
ob2 |
dftb+, dftbplus, dftb_plus |
The conventional OB2 / LC-DFTB2 protocol: LC-DFTB2 ground state with the Yukawa–Slater kernel, full long-range exchange, official shell-resolved spin constants, and the DFTB+ program's numerical defaults (SCC tolerance 1e-5, Broyden 0.2, 100 SCC iterations). Use it to compare against the DFTB+ program or against literature LC-DFTB numbers. Default for SF-TDDFTB and open-shell ground-state runs. |
| (opt out) | none |
Disables the preset default and returns to the explicit-keys route. |
Keyword rename
dtcam and ob2 are the canonical names. The former spellings
dtcam-tb and dftb+ remain accepted aliases, so existing inputs
keep working unchanged. dftb+ was renamed because DFTB+ is a separate
program; this preset is a parameter/protocol choice (OB2), not that
program.
Defaults when model= is omitted¶
| Route | Effective model |
|---|---|
MRSF-TDDFTB ([dftb] type=mrsf) |
dtcam |
SF-TDDFTB, open-shell ground state (reference_multiplicity > 1) |
ob2 |
| Closed-shell ground state, TD-DFTB, DFTB0 | (preset-free) — LC-DFTB2 is not implemented for the restricted reference |
An MRSF run therefore already uses DTCAM-TB; writing model=dtcam
explicitly is the recommended, self-documenting form. Tuning any
preset-locked key also disables the default, so legacy inputs keep meaning
exactly what they said.
A preset is all-inclusive¶
Combining model= with an individual operator key is rejected at input time,
because the preset would silently overwrite it:
1. [ERROR] dftb.model: A model preset fixes the complete operator and numerical
protocol; individual operator keys cannot be combined with it.
current: 'omega'
expected: model=dtcam with no tuned operator keys
fix: Remove the listed [dftb] keys or drop model= to tune manually.
The locked keys are omega, cam_alpha, cam_beta, lc_gamma,
lc_ground_state, w_scale, response_w_scale, response_omega,
response_cam_alpha, response_cam_beta, c_mrsf, c_mrsf_oo,
response_global_hybrid, onsite_exchange_scale, spc, spc_coco,
spc_ovov, spc_coov, onsite_ss, onsite_sp, onsite_pp, the four
mrsf_shift_*, and the numerical block scc_mixing, scc_history,
scc_max_step, scc_tolerance, max_scc_iterations, response_solver,
zvector.
scc_mixer is deliberately not locked: choosing the
first-try convergence algorithm is a numerical recovery decision, and an
explicit scc_mixer is applied after the preset is loaded. Keys the preset does
not touch — response_tolerance, response_max_iterations,
response_max_subspace, nstate, print_level — also stay user-tunable.
Presets require backend=native; the probe
fallback cannot carry them.
State numbering¶
This is the single easiest thing to get wrong.
MRSF relabels its lowest singlet response root as S0. Every state
selector in the .inp format — [properties] grad,
[optimize] istate, jstate, kstate, and the
states list — is 1-based over the physical states:
| Selector value | Physical state |
|---|---|
1 |
S0 |
2 |
S1 |
3 |
S2 |
So grad=2 is the S1 gradient, istate=2 optimizes the S1 minimum, and
states=2,3 searches the S1/S2 crossing. The one-line .oqp format takes
the physical labels S0, S1, S2, T0, … directly and needs no
translation.
[tdhf] nstate counts response roots the same way, so nstate=3 gives you
S0, S1, S2.
Parameters¶
Nothing needs configuring with a current openqp-dftb install: it ships the
bundled OB2W0PT3 Slater–Koster set (official spinw.txt included), which is
resolved automatically when [dftb] parameter_path is empty and
OPENQP_DFTB_PARAMETER_PATH is unset. Point either at another .opdftb file
or SKF directory to override the bundled default. As with every DFTB family,
basis= is an ignored placeholder that must nevertheless be present, and
functional= is empty.
Single point and excited-state energies¶
One MRSF-TDDFTB response gives S0, S1, S2, their oscillator strengths,
and the state-to-state spectrum.
.inp
[input]
system=butadiene.xyz
charge=0
runtype=energy
method=dftb
[scf]
type=rohf
multiplicity=3
[dftb]
model=dtcam
type=mrsf
parameter_path=
[tdhf]
type=mrsf
nstate=3
.oqp
mrsf-tddftb(nstate=3)
energy(S0)
dftb(model=dtcam)
geom="butadiene.xyz"
Python
from oqp.openqp import OpenQP
job = OpenQP(project="dtcam_energy")
job.molecule("butadiene.xyz", charge=0)
job.dftb(response_type="mrsf", nstate=3, model="dtcam")
job.workflow.energy()
job.run()
For s-trans butadiene this puts the bright ionic 1¹B_u⁺ below the dark
covalent 2¹A_g⁻ at the Franck–Condon point (S1 carries the oscillator
strength). Swapping to model=ob2 inverts that ordering — S1 becomes dark
and S2 bright — which is exactly the failure DTCAM-TB was fitted to remove.
Run both if you want to see it.
Analytic excited-state gradient¶
Gradients are analytic and use the relaxed Z-vector formulation (a single
pair-space solve). S1 is selector 2:
.inp
[input]
system=butadiene.xyz
charge=0
runtype=grad
method=dftb
[scf]
type=rohf
multiplicity=3
[dftb]
model=dtcam
type=mrsf
parameter_path=
[tdhf]
type=mrsf
nstate=3
[properties]
grad=2
.oqp
mrsf-tddftb(nstate=3)
grad(S1)
dftb(model=dtcam)
geom="butadiene.xyz"
Python
job.dftb(response_type="mrsf", nstate=3, model="dtcam")
job.workflow.gradient(state=2)
Use grad=1 / grad(S0) for the ground-state gradient.
Geometry optimization¶
Ground state and excited state use the same deck; only istate changes
(1 = S0, 2 = S1).
.inp
[input]
system=butadiene.xyz
charge=0
runtype=optimize
method=dftb
[scf]
type=rohf
multiplicity=3
[dftb]
model=dtcam
type=mrsf
parameter_path=
[tdhf]
type=mrsf
nstate=3
[optimize]
lib=oqp
istate=2
maxit=50
.oqp
mrsf-tddftb(nstate=3)
opt(S1,maxit=50)
dftb(model=dtcam)
geom="butadiene.xyz"
Python
job.dftb(response_type="mrsf", nstate=3, model="dtcam")
job.workflow.optimize(istate=2, maxit=50)
istate=1 optimizes the S0 minimum. lib=geometric switches to the external
geomeTRIC optimizer; lib=oqp (the default) is the built-in native optimizer
and is the one the recovery behaviour described below applies to.
MECI search¶
DFTB supplies MRSF-TDDFTB state energies and analytic gradients, so
minimum-energy conical-intersection searches run through the shared
[optimize] machinery with runtype=meci — there is
no separate DFTB entry point. Because MRSF has the correct S₀/S₁ intersection
topology, DTCAM-TB is the DFTB operator to use for conical intersections.
[optimize] meci_search accepts auto (the default), auglag, penalty,
ubp, hybrid, and baeka. For two states auto runs the augmented
Lagrangian and escalates to BaekA only if that does not meet the convergence
criteria; with three or more states it selects BaekA directly.
Two-state seam: S₁/S₀ of ethylene¶
Two-state searches address the roots with istate/jstate:
[input]
system=
6 0.000000 0.000000 0.669500
6 0.000000 0.000000 -0.669500
1 0.928900 0.000000 1.232100
1 -0.928900 0.000000 1.232100
1 0.000000 0.928900 -1.232100
1 0.000000 -0.928900 -1.232100
charge=0
runtype=meci
method=dftb
[scf]
type=rohf
multiplicity=3
[dftb]
model=dtcam
type=mrsf
parameter_path=
[tdhf]
type=mrsf
nstate=3
[optimize]
lib=oqp
istate=1
jstate=2
meci_search=baeka
energy_gap=1e-4
maxit=30
.oqp
mrsf-tddftb(nstate=3)
meci(S0,S1,algorithm=baeka,gap=1e-4,maxit=30)
dftb(model=dtcam)
geom="ethylene_twisted.xyz"
The S₁/S₀ seam of ethylene lies in the twisted-pyramidalized region, far from
the planar minimum, so start from a ~90° twisted structure. The values above are
deliberately capped for a quick run; for production raise maxit (~500) and keep
the default energy_gap=1e-5.
The BaekA algorithm, and why pen_sigma matters¶
BaekA (Baek, Lee, Filatov, Choi, J. Phys. Chem. A 2021, 125, 1994) is an adaptive-penalty algorithm over an ordered, consecutive list of same-spin roots. Its objective over the selected states is
$$ F_N \;=\; \frac{1}{N}\sum_i E_i \;+\; \sigma \sum_i \frac{(E_{i+1}-E_i)^2}{E_{i+1}-E_i+\alpha} $$
with $\sigma$ = pen_sigma and $\alpha$ =
pen_alpha (a smoothing energy; the schema default 0 is a sentinel that maps
to 0.02 Hartree for BaekA). Only adjacent gaps enter. gap_weight is fixed at
1.0 — pen_sigma is the penalty multiplier.
Read that objective carefully: the first term is the mean state energy. BaekA is a minimum-energy CI search. Once the gap penalty is satisfied it is free to keep walking downhill along the seam, and it will, until it reaches a lower crossing. That is the desired behaviour when you want the lowest CI of a pair of surfaces. It is exactly the wrong behaviour when you want one specific, non-lowest crossing.
pen_sigma is the lever that stiffens the penalty and holds the walk near the
seam point you started from.
Set pen_sigma when you want a specific, non-lowest crossing
With the default pen_sigma=1 a search started on a seam can satisfy the
gap criterion at step 1 and then slide a full electronvolt downhill along it
into a different conical intersection. Raise pen_sigma to hold the
intended seam. For the butadiene 1¹B_u⁺/2¹A_g⁻ crossing below, values
>= 5 work and pen_sigma=10 is the recommended setting; 2 is not
enough.
Non-lowest seam: the butadiene 1¹B_u⁺/2¹A_g⁻ crossing¶
This is the worked example. The start structure is the frame of the
bond-length-alternation path where the bright ionic 1¹B_u⁺ and the dark
covalent 2¹A_g⁻ swap character. These are the physical S1 and S2, i.e.
selectors 2,3:
[input]
system=
6 1.916995 0.065369 0.000000
6 0.554563 -0.434396 0.000000
6 -1.916995 -0.065369 0.000000
6 -0.554563 0.434396 0.000000
1 2.760515 -0.606516 0.000000
1 2.101350 1.130009 0.000000
1 -2.760515 0.606516 0.000000
1 0.382205 -1.502220 0.000000
1 -2.101350 -1.130009 0.000000
1 -0.382205 1.502220 0.000000
charge=0
runtype=meci
method=dftb
[scf]
type=rohf
multiplicity=3
[dftb]
model=dtcam
type=mrsf
parameter_path=
[tdhf]
type=mrsf
nstate=3
[optimize]
lib=oqp
states=2,3
meci_search=baeka
energy_gap=1e-5
maxit=50
pen_sigma=10
.oqp
mrsf-tddftb(nstate=3)
meci(S1,S2,algorithm=baeka,gap=1e-5,maxit=50,sigma=10)
dftb(model=dtcam)
geom="butadiene_bla18.xyz"
Multi-state BaekA takes the states list instead of istate/jstate. Roots
must be strictly increasing and consecutive (2,3 or 1,2,3, never
1,3). In .oqp, algorithm= maps to meci_search, gap= to energy_gap,
and sigma= to pen_sigma.
The difference the stiffness makes, from the same start, same operator, same budget:
pen_sigma=10 |
pen_sigma=1 (default) |
|
|---|---|---|
Mean S1/S2 excitation energy |
≈ 5.27 eV | ≈ 4.46 eV — slid ~0.8 eV downhill |
True S1/S2 gap at the end point |
≈ 5 × 10⁻⁴ eV | ≈ 1 × 10⁻² eV, still widening |
| Where it ends up | the intended 1¹B_u⁺/2¹A_g⁻ seam, a few hundredths of an Å from the start | walking away toward a different, lower crossing |
The internal sigma is ramped up by the additive schedule (pen_delta,
pen_jump) as the search proceeds, but starting at 1 lets it drift before the
schedule catches up. Starting at 10 prevents the drift.
maxit is not a hard cap¶
The native optimizer (lib=oqp) auto-restarts from its best geometry when a
run ends unconverged, adding up to two further rounds of
[oqp] recovery_maxit (default 30) steps. A maxit=50
MECI therefore runs up to 110 steps, and maxit=30 up to 90.
For a genuine cap, disable the recovery:
[oqp]
auto_recovery=false
Verifying a MECI¶
Always re-single-point the optimized geometry and read the gap yourself. The optimizer's own reported gap is computed inside the penalty objective and can false-converge.
Two files are written into the run directory, and they are not interchangeable:
| File | Contents |
|---|---|
opt.xyz |
The single latest/retained geometry — rewritten each step. This is the result. |
opt_geom.xyz |
The full multi-frame trajectory, appended each step. Its first frame is the STARTING structure, not the answer. |
opt_status.txt carries the per-step table (objective, outer gap, active sigma,
step norms).
So the verification loop is:
- Take
<rundir>/opt.xyz. - Run the single-point deck on it
with the same
model=andnstate=. - Read the true
S1/S2(orS0/S1) separation from the summary table — and check the oscillator strengths, which tell you which crossing you landed on.
A crossing between a bright and a dark state shows up as two roots that share the oscillator strength between them at the seam; if both roots come out dark, you have slid onto a different intersection.
Troubleshooting¶
Discontinuous curves — raise nstate¶
The default nstate is often too small. The Davidson solver returns only the
requested number of roots, and with too few of them it can converge onto a
wrong upper root, which shows up as kinks, jumps, or state swaps along a scan
or an optimization path. If a potential-energy curve looks discontinuous, or an
excited-state optimization oscillates without converging, raise nstate (for
example 3 → 5) and rerun. Extra roots are cheap in DFTB.
Keep genuinely degenerate multiplets inside the requested window — truncating a multiplet halfway is another source of erratic behaviour.
SCC will not converge¶
Preset numerics are already tuned, and scc_mixer is the one override a preset
does not lock. Try scc_mixer=trust (charge/spin trust-region) or
scc_mixer=broyden.
model= was rejected¶
Unknown OpenQP-DFTB operator model preset means the spelling is not in the
accepted set — check the table at the top of this page. Note that a given PyOQP
build may accept fewer spellings than the native library implements; the
expected: line of the error message lists exactly what your build takes.
Which run types work¶
method=dftb is wired only through energy/gradient-driven workflows. Accepted:
energy, grad, data, optimize, meci, mep
plus nac, nacme, namd, and soc when the route is MRSF
([tdhf] type=mrsf with [dftb] type auto or mrsf).
Rejected for method=dftb, with a clear input-time error: hess, ts, irc,
neb, tci, mecp, bp, prop, ekt. Analytic/numerical Hessians,
transition-state searches, IRC, and NEB are therefore not available for the DFTB
method today, and the legacy three-state tci deck is superseded by
multi-state runtype=meci with meci_search=baeka.
Things that cannot be set from an input¶
The response long-range kernel selector (response_lc_gamma_code in the
library) is not reachable from any [dftb] key or C ABI argument. It is
fixed by the chosen preset (dtcam inherits the reference kernel;
dtcam2/dtcam-erf force erf) and can otherwise only be overridden with
the developer environment variable OPENQP_DFTB_FIT_RESP_LCGAMMA, part of the
opt-in OPENQP_DFTB_FIT_* fitting-scan family. Those variables are a
parameter-fitting facility, not a supported user interface.
The per-channel spc_coco / spc_ovov / spc_coov splits are reachable from
[dftb], but only on the explicit-keys route (no model=), and only with
backend=native.
See also¶
- MRSF-TDDFTB — the response formalism, NACME, SOC, QM/MM
- BaekA Multistate MECI — the algorithm in full
[dftb]— every DFTB keyword[optimize]— every optimizer keyword- Optimization — the shared optimizer workflows