Define an Active Space (Complete Active Space)
Goal
Create a ground-state problem that uses a CAS(n, m) active space, where \(n\) active electrons are distributed among \(m\) active spatial orbitals, with all other electrons frozen.
The active space is added as a problem modifier: it reduces the Hamiltonian of the ground-state problem to the active orbitals only, and folds the contribution of the inactive orbitals into an inactive Fock operator and an inactive energy contribution.
Prerequisites
A molecular configuration (see Create a MolecularConfiguration)
A ground-state problem builder (see Construct a Ground State Energy Problem)
Steps
Add the active space modifier to the ground-state problem builder
import qrunch as qc problem_builder = ( qc.problem_builder_creator() .ground_state() .standard() .add_problem_modifier() .active_space( number_of_active_spatial_orbitals=8, number_of_active_alpha_electrons=6, ) .create() )
This defines an active space where:
number_of_active_spatial_orbitals = 8
number_of_active_alpha_electrons = 6
The number of active beta electrons is inferred from the spin difference in the molecular configuration and
number_of_active_alpha_electronsIn the case of an unrestricted calculation, the number of active spatial orbitals refers to alpha spin orbitals and the same number of beta spin orbitals will be included
Example:
If spin difference = 2, the number of active beta electrons will be:
active_beta = active_alpha - spin_difference = 6 - 2 = 4Total active electrons = \(6_{\alpha} + 4_{\beta} = 10\) electrons in 8 spatial orbitals (16 active spin orbitals)
Build the ground-state problem
The ground-state problem is built as described in Construct a Ground State Energy Problem. It now also carries an “Inactive electrons energy” contribution, and the result of the ground-state energy calculation includes the energy of the non-active electrons (
non_active_electrons_energy) in the total energy.
How Active Orbitals Are Selected
There are two main strategies for selecting active orbitals, and the selection is determined by the type of molecular orbitals used, i.e., whether they come from a mean-field calculation (Hartree-Fock or DFT) or from a correlated calculation (MP2 or CCSD).
Energy-Based Selection (Mean-Field Orbitals)
When the molecular orbitals come from a mean-field calculator (Hartree-Fock or DFT), they are canonical
orbitals sorted by molecular orbital energy, and the active space is a contiguous energy window around
the HOMO-LUMO gap. The number_of_active_alpha_electrons highest-lying occupied orbitals are made active,
the remaining occupied orbitals are frozen, and the window is filled up with the lowest-lying virtual
orbitals until number_of_active_spatial_orbitals is reached.
With mean-field orbitals, number_of_active_alpha_electrons must be given explicitly, since the
integer-valued mean-field occupation numbers offer no basis for choosing a number of active occupied
orbitals automatically.
Automatic Number of Active Occupied Orbitals
number_of_active_alpha_electrons is optional. When it is left out, the number of active occupied
orbitals is determined automatically from the occupation numbers: every occupied orbital whose deviation
exceeds occupation_deviation_threshold is made active, and the rest of the active space is filled with
the most strongly correlated virtual orbitals.
import qrunch as qc
problem_builder = (
qc.problem_builder_creator()
.ground_state()
.standard()
.choose_molecular_orbital_calculator()
.ccsd()
.add_problem_modifier()
.active_space(number_of_active_spatial_orbitals=10) # occupied/virtual split chosen automatically
.create()
)
This requires fractional occupation numbers, i.e. MP2 or CCSD natural orbitals. If the problem carries no
occupation numbers, or only integer-valued mean-field occupations, an error is raised asking you either to
specify number_of_active_alpha_electrons explicitly or to switch to the MP2 or CCSD molecular orbital
calculator.
Unrestricted Calculations
For unrestricted problems (e.g., open-shell systems or broken-symmetry states), the active space
can be defined using either distinct per-spin orbitals or shared spatial orbitals. This is
controlled by the spin_summed_natural_orbitals option on the MP2 and CCSD calculator options:
- Per-spin natural orbitals (default,
spin_summed_natural_orbitals=False) The \(\alpha\) and \(\beta\) density matrices are diagonalized independently, giving distinct spatial orbitals and occupations in \([0, 1]\) for each spin channel.
The active window selects the same number of spatial orbitals for both spins, but allows the underlying \(\alpha\) and \(\beta\) orbitals to differ.
Sizing and validation automatically account for both spin channels, so unpaired electrons (SOMOs) and strongly correlated pairs in either spin channel are prioritized.
Thresholds configured in
ActiveSpaceOptionsare automatically scaled to the per-spin basis.
- Shared spatial orbitals (
spin_summed_natural_orbitals=True) The \(\alpha\) and \(\beta\) densities are combined in the atomic orbital basis to produce a single, shared set of spatial natural orbitals with total occupations in \([0, 2]\) (ROHF-style).
Both spin channels share the exact same spatial orbitals; per-spin occupations reflect spin polarization (e.g., a singly occupied orbital has \(n^\alpha \approx 1.0, n^\beta \approx 0.0\)).
Recommended when downstream methods expect identical \(\alpha\) and \(\beta\) spatial orbitals.
Required when constructing consistent active spaces along a reaction path (see Construct a Reaction-Path Problem).
Tuning the Active Space with Options
You can pass a ActiveSpaceOptions
instance to control the active-space reduction:
import qrunch as qc
options = qc.options.ActiveSpaceOptions(
occupation_deviation_threshold=0.01,
log_orbital_info=True,
)
problem_builder = (
qc.problem_builder_creator()
.ground_state()
.standard()
.choose_molecular_orbital_calculator()
.moller_plesset_2()
.add_problem_modifier()
.active_space(number_of_active_spatial_orbitals=10, options=options)
.create()
)
Option |
Default |
Description |
|---|---|---|
|
|
Threshold on the occupation deviation. Used for ranking orbitals and, when
|
|
|
Log orbital energies and occupations for all orbitals (frozen occupied, active occupied, active virtual, frozen virtual). Useful when debugging an active-space choice. |
Lowering occupation_deviation_threshold includes more orbitals, and raising it includes fewer. This
matters most for the automatic occupied count, where too small a threshold can make the number of active
occupied orbitals exceed number_of_active_spatial_orbitals.
Verify the Result
When you calculate the ground-state energy, the result object will include:
non_active_electrons_energy— the electronic energy contribution from electrons not included in the active space.active_electrons_energy— the electronic energy contribution of the active electrons.total_energy— the total energy of the system.
The problem itself carries the inactive contribution in
problem.energy_contributions.inactive_electrons_energy.At
INFOlog level, Qrunch reports whether occupation numbers were used to size the active occupied space, and the resulting number of active and inactive orbitals and electrons.At
DEBUGlog level, Qrunch also reports the indices of the active occupied and active virtual orbitals, along with the occupation numbers at the active/inactive boundaries. This is useful for diagnosing discontinuities in the active space along a reaction path. Setlog_orbital_info=Truefor a full orbital listing.
See Also
Construct a Reaction-Path Problem (for a consistent active space along a reaction path)
API reference:
problem_modifiers
Next Step
You can use the active-space ground-state problem to calculate the ground-state energy: