CASCI And CASSCF Solvers#
Use casci for fixed orbitals or casscf for orbital optimization. Both use
FCI by default. Set solver: block2 to use the optional DMRG solver.
DF is independent of the solver: configure density_fit and auxbasis on each
stage. YAML export inherits the actual exact/DF approximation and auxiliary
provider of the reference selected by mppt.orbitals.
Small Complete Input#
Save this as lih.yaml and run pyscf2mppt lih.yaml --output-dir runs/lih:
molecule:
atoms:
- [Li, 0.0, 0.0, 0.0]
- [H, 0.0, 0.0, 1.6]
units: A
charge: 0
so: false
max_memory: 512.0
basis:
Li: [library, sto-3g]
H: [library, sto-3g]
scf:
type: rhf
spin: singlet
omp_num_threads: 1
casci:
active_orbitals: 4
n_active_electrons: 2
solver: fci
density_fit: true
auxbasis: weigend
omp_num_threads: 1
states_to_average: [[singlet, 2]]
mppt:
orbitals: casci
N_select: 4
delete_from: 0
This computes DF-CASCI on the SCF orbitals and exports selected DF integrals. CASCI disables final canonicalization to keep the supplied orbital basis fixed. AVAS, when requested, prepares the initial ordering before this fixed-orbital solve.
To optimize orbitals, rename casci to casscf and set mppt.orbitals: casscf
(or auto). Use the existing CASSCF convergence and macro/microiteration controls.
Only one active-space section is accepted in a calculation.
Runtime Orbital Projections#
Add runtime_projections to casscf or casci to track orbital character.
It is off by default and independent of AVAS orbital preparation:
casscf:
active_orbitals: 17
n_active_electrons: 11
runtime_projections:
labels: ["Ce 4f", "Ce 5d"]
min_weight: 0.01
This is a stage fragment; keep your molecule, basis and solver settings.
labels follows the existing AO-label syntax. Each string creates one table;
a nested list creates one table for the union of its AO matches.
The threshold is inclusive and applies before rounding. 0.01 means 1%.
Cells show percentages with two decimal places. A row is retained if its raw
weight meets the threshold at any displayed step. Subthreshold cells show —.
The MO numbers are one-based native orbital positions, not tracked identities.
Orbital projections: Ce 5d | c² (%)
MO space initial m1 m2
8 inactive — 1.23 2.45
113 active 24.00 23.10 22.00
The numbers above illustrate formatting. Long histories split into consecutive column blocks with repeated label, units, headers and identical MO rows/order.
Fixed Targets And Snapshot Boundaries#
Projector labels, overlaps and metric pseudoinverses are cached before the solve.
Weights are evaluated for all MOs without a full MO-by-MO projector matrix.
An optional runtime_projections.basis uses the same element/atom-label
[library, name] or [file, path] mapping as avas_basis, but is independent:
runtime_projections:
labels: ["O 2p"]
basis:
O: [library, sto-3g]
min_weight: 0.01
Omitting this basis uses the working AOs, including their radial-shell label conventions. A label alone does not certify a physical atomic shell. Managed runs capture and fingerprint explicit projector files with other input resources.
CASSCF reports the actual post-AVAS starting orbitals, then every completed
mc1step macroiteration using fresh callback orbitals. Microsteps are excluded;
ordinary progress throttling does not suppress projection snapshots. A changed
returned basis is labelled final/final_postcanonicalization, separately from
macroiterations. An identical final basis is not printed twice.
CASCI reports one completed casci snapshot. FCI and block2 use the same
diagnostic path. Diagnostics invoke no additional solver, Fock or AO2MO work.
They do compute overlap integrals once and small projector/active-space algebra.
Traces, Raw History And Resume#
Each snapshot reports unthresholded inactive/active/external traces, their changes from the previous snapshot and start, and the minimum squared principal overlap of the active space with both references. These are orbital weights, not electron populations. The raw file retains all principal overlaps; no MO reordering, clipping or population reconstruction is performed.
The log names a unique runtime_projections/<method>-<execution-id>.jsonl
under the execution workdir. The first record contains schema version, execution
ID, label/basis specifications, projector and starting-MO hashes, partition counts
and threshold. Subsequent records contain UTC timestamps, step/phase/macro,
MO hash, all raw weights, traces, trace changes and active principal overlaps.
Weights are label-major with native MO order; traces use inactive/active/external
order. Full MO matrices are not stored by diagnostics.
A fresh execution always starts a new file. Completed-stage resume leaves earlier histories untouched and emits the existing restored-result report without running a solver or inventing missing macroiterations. Preserve the entire workdir to retain these optional histories; they are not required checkpoint artifacts.
The supported callback boundary is restricted real-orbital PySCF mc1step,
including its DF and state-average wrappers. Other native optimization kernels
need their own boundary validation. Large-system runtime overhead is not benchmarked.
Enable block2#
In a separate, working MPPT environment on Linux x86-64, install the optional dependencies used for the adapter checks:
python -m pip install \
'block2==0.5.4' 'mkl==2024.2.2' 'mkl-include==2024.2.2' \
'intel-openmp==2024.2.1' 'tbb==2021.13.1' \
'pyscf-dmrgscf @ git+https://github.com/pyscf/dmrgscf.git@a03f7b6c67c61626f129e9c0c771016c14912400'
block2main -v
The adapter resolves block2main from PATH and configures dmrgscf without editing
site-packages. It uses single-node OpenMP, with no MPI launcher. The FCI route
does not load dmrgscf or require block2. Native loader errors remain errors.
Replace the solver settings in either stage with this fragment:
solver: block2
dmrg:
max_bond_dimension: 1000
max_sweeps: 24
energy_tolerance: 1.0e-7
memory_gb: 4
response_sweeps: 4
omp_num_threads controls the external solver as well as the parent stage.
memory_gb is block2’s workspace hint in GB; PySCF max_memory is in decimal MB.
Neither is a hard RSS cap. DMRG options with solver: fci are rejected.
Sweep Schedule#
With no explicit schedule, sweep zero uses min(250, M) and noise 1e-4.
Halfway through max_sweeps, the solver switches to full M, zero noise, and
Davidson tolerance energy_tolerance / 10. The initial Davidson tolerance is
max(1e-5, energy_tolerance). One-dot begins at floor(2*max_sweeps/3).
For an explicit schedule, add these settings under dmrg:
max_bond_dimension: 500
max_sweeps: 16
twodot_to_onedot: 10
schedule:
- {sweep: 0, bond_dimension: 250, davidson_tolerance: 1.0e-5, noise: 1.0e-4}
- {sweep: 4, bond_dimension: 500, davidson_tolerance: 1.0e-7, noise: 1.0e-5}
- {sweep: 8, bond_dimension: 500, davidson_tolerance: 1.0e-9, noise: 0.0}
Sweep numbers are zero-based and strictly increasing, start at zero, and remain
below max_sweeps. The final entry must use maximum M and zero noise. The
one-dot switching sweep must also precede max_sweeps; at least four sweeps are
required. These defaults and examples are starting controls, not convergence evidence.
State Averaging And Saved Results#
states_to_average: [[2, 12]] requests twelve equally weighted doublets. The
user-facing number is multiplicity; the adapter passes twice spin to block2.
Mixed multiplicities use independent solvers and unique directories.
PySCF’s FCI solver.spin selects an Mₛ sector; a lower-spin sector can also
contain higher-total-spin roots. Set a positive finite spin_penalty_shift in
Eh to target total spin. Without state averaging, it applies to the single FCI
solver and uses the effective active-stage multiplicity:
casscf:
solver: fci
active_orbitals: 5
n_active_electrons: 4
spin: singlet
spin_penalty_shift: 1.0
With state averaging, the stage value is the default for every solver block.
Mapping entries can override it or explicitly disable it with null:
casscf:
solver: fci
active_orbitals: 5
n_active_electrons: 4
spin_penalty_shift: 1.0
states_to_average:
# Inherits 1.0 Eh.
- [singlet, 50]
# Uses a smaller block-specific shift.
- {spin: triplet, nroots: 45, spin_penalty_shift: 0.5}
# Keeps the native quintet solver.
- {spin: quintet, nroots: 5, spin_penalty_shift: null}
An omitted block key inherits the stage default. A positive finite block value
replaces it, and explicit null disables it for that block. Two-item entries
remain valid and inherit the default. The setup report shows the default and
effective block values.
The setting uses PySCF’s fix_spin level shift. It is not exact spin projection:
verify each root’s S² and repeat with another shift when unwanted spin remains.
Omitting every setting keeps native FCI behavior. Global and block-level spin
penalties are both rejected with solver: block2.
Files remain under <run-root>/dmrg/spin<2S>-<unique>/: effective settings.json,
native configuration, FCIDUMP, the latest native log, MPS and density files.
Completed-stage checkpoints store orbitals, energies, per-root 1-RDMs, weights,
spin values, and the method/solver labels. Preserve the whole run directory.
Internally both methods use the established casscf checkpoint stage and
casscf.npz filename. Use --stop-after casscf for either method. Resuming a
completed active-space stage rebuilds its Hamiltonian/DF context without loading
block2 or running a kernel. This is completed-stage resume, not an automatic
restart of an interrupted DMRG solve or additional CASSCF macroiterations.
Limits And Acceptance#
The supported domain is real, restricted spatial orbitals and C1. The pinned dmrgscf contracts 2-RDM to obtain 1-RDM; a one-active-electron block2 calculation is rejected. Use FCI for that inexpensive case. External-solver errors propagate; there is no automatic fallback to FCI.
PySCF’s CASSCF converged flag concerns orbital optimization. A successful
block2 process or completed CASCI is not a certificate of convergence with bond
dimension. Review native sweep energies/discarded weights and compare increasing M.
Tiny LiH acceptance compares FCI and block2 energies to native exact FCI within
1e-8 Eh, and 1-RDMs within 1e-6, on identical final orbitals. CASSCF additionally
requires a changed inactive projector. Different approximate CI-response paths
need not produce identical orbitals after one unconverged macroiteration.
MPPT consumes these orbitals, densities and the physical Hamiltonian, not MPS coefficients. It still needs its own model-space selection. NEVPT2, transition RDMs and MPS-to-determinant export are outside this adapter. See the external DMRG reference example for a separate manual route.