Multi-configuration calculations
The MultiConfigurationCalculator algorithm in QDK/Chemistry performs Multi-Configurational (MC) calculations to solve the electronic structure problem beyond the mean-field approximation.
Following QDK/Chemistry’s algorithm design principles, it takes a Hamiltonian instance as input and produces a Wavefunction instance as output.
It provides access to various Configuration Interaction (CI) methods to account for static electron correlation effects, which are critical for accurately describing systems with near-degenerate electronic states.
Overview
MC methods represent the electronic wavefunction as a linear combination of many electron configurations (Slater determinants).
These methods can accurately describe systems with strong static correlation effects where single-reference methods like Hartree-Fock are inadequate.
Static correlation arises when multiple electronic configurations contribute significantly to the wavefunction, such as in bond-breaking processes, transition states, excited states, and open-shell systems.
The MultiConfigurationCalculator algorithm implements various CI approaches, from full CI (FCI) to selected CI methods that focus on the most important configurations.
Using the MultiConfigurationCalculator
This section demonstrates how to create, configure, and run a multi-configuration calculation.
The run method takes a Hamiltonian object as input and returns a Wavefunction object along with its associated energy.
Input requirements
The MultiConfigurationCalculator requires the following inputs:
- Hamiltonian
A Hamiltonian instance that defines the electronic structure problem.
- Number of alpha electrons
The number of alpha (spin-up) electrons in the active space.
- Number of beta electrons
The number of beta (spin-down) electrons in the active space.
Creating an MC calculator
#include <iostream>
#include <qdk/chemistry.hpp>
using namespace qdk::chemistry::algorithms;
using namespace qdk::chemistry::data;
// Create a CAS MultiConfigurationCalculator instance
auto mc_calculator = MultiConfigurationCalculatorFactory::create("macis_cas");
from qdk_chemistry.algorithms import create
# Create a CAS MultiConfigurationCalculator instance
mc_calculator = create("multi_configuration_calculator", "macis_cas")
Configuring settings
Settings can be modified using the settings() object.
See Available implementations below for implementation-specific options.
// Set the convergence threshold for the CI iterations
mc_calculator->settings().set("ci_residual_tolerance", 1.0e-6);
# Configure the MC calculator using the settings interface
mc_calculator.settings().set("ci_residual_tolerance", 1.0e-6)
Running the calculation
// Create a structure (H2 molecule)
std::vector<Eigen::Vector3d> coords = {{0.0, 0.0, 0.0}, {0.0, 0.0, 1.4}};
std::vector<std::string> symbols = {"H", "H"};
Structure structure(coords, symbols);
// Run SCF to get orbitals
auto scf_solver = ScfSolverFactory::create();
auto [E_scf, wfn] = scf_solver->run(structure, 0, 1, "sto-3g");
// Build Hamiltonian from orbitals
auto ham_constructor = HamiltonianConstructorFactory::create();
auto hamiltonian = ham_constructor->run(wfn->get_orbitals());
// Run the CI calculation
// For H2, we have 2 electrons (1 alpha, 1 beta)
int n_alpha = 1;
int n_beta = 1;
auto [E_ci, ci_wavefunction] = mc_calculator->run(hamiltonian, n_alpha, n_beta);
std::cout << "SCF Energy: " << E_scf << " Hartree" << std::endl;
std::cout << "CI Energy: " << E_ci << " Hartree" << std::endl;
from pathlib import Path # noqa: E402
from qdk_chemistry.algorithms import create # noqa: E402
from qdk_chemistry.data import Structure # noqa: E402
# Load H2 structure from XYZ file
structure = Structure.from_xyz_file(Path(__file__).parent / "../data/h2.structure.xyz")
# Run SCF to get orbitals
scf_solver = create("scf_solver")
E_scf, wfn = scf_solver.run(
structure, charge=0, spin_multiplicity=1, basis_or_guess="sto-3g"
)
# Build Hamiltonian from orbitals
ham_constructor = create("hamiltonian_constructor")
hamiltonian = ham_constructor.run(wfn.get_orbitals())
# Run the CI calculation
# For H2, we have 2 electrons (1 alpha, 1 beta)
n_alpha = 1
n_beta = 1
E_ci, ci_wavefunction = mc_calculator.run(hamiltonian, n_alpha, n_beta)
print(f"SCF Energy: {E_scf:.10f} Hartree")
print(f"CI Energy: {E_ci:.10f} Hartree")
Available settings
The MultiConfigurationCalculator accepts a range of settings to control its behavior.
All implementations share a common base set of settings from MultiConfigurationSettings:
Setting |
Type |
Default |
Description |
|---|---|---|---|
|
float |
|
Convergence threshold for CI Davidson solver |
|
int |
|
Maximum number of Davidson iterations |
|
bool |
|
Calculate one-electron reduced density matrix |
|
bool |
|
Calculate two-electron reduced density matrix |
See Settings for a more general treatment of settings in QDK/Chemistry.
Available implementations
QDK/Chemistry’s MultiConfigurationCalculator provides a unified interface for multi-configurational calculations.
You can discover available implementations programmatically:
auto names = MultiConfigurationCalculatorFactory::available();
for (const auto& name : names) {
std::cout << name << std::endl;
}
from qdk_chemistry.algorithms import registry # noqa: E402
print(registry.available("multi_configuration_calculator"))
MACIS CAS
Factory name: "macis_cas" (default)
The MACIS (Many-body Adaptive Configuration Interaction Solver) CAS implementation provides a reference solver to compute the exact energy within the active space. This module is very memory and compute intensive, and is thus suitable only for small active spaces.
This implementation uses only the common settings described above.
MACIS ASCI
Factory name: "macis_asci"
The MACIS ASCI (Adaptive Sampling Configuration Interaction) implementation provides an efficient selected CI solver that can handle larger active spaces by adaptively selecting the most important configurations. This method balances accuracy and computational cost, making it suitable for medium-sized active spaces.
ASCI Algorithm
The Adaptive Sampling Configuration Interaction (ASCI) algorithm [TFL+20, TLT+16] is a selected configuration interaction method that enables efficient treatment of large active spaces by iteratively identifying and including only the most important determinants. QDK/Chemistry integrates the high-performance, parallel implementation of ASCI in the MACIS library [WYTMZdJ23].
The ASCI works by growing the determinant space adaptively: at each iteration, it samples the space of possible determinants and selects those with the largest contributions to the wavefunction. This approach achieves near-CASCI accuracy at a fraction of the computational cost, making it possible to treat active spaces that are intractable for conventional CASCI.
ASCI is especially useful for generating approximate wavefunctions and RDMs for use in automated active space selection protocols (such as AutoCAS), as it provides a good balance between computational cost and accuracy. For best practices, see the AutoCAS Algorithm section in the active space selector documentation.
The ASCI algorithm proceeds as a two-phase optimization:
Growth Phase: The growth phase focuses on rapidly expanding the determinant space to capture the most important configurations. Starting from an initial set of determinants (often just the Hartree-Fock determinant), ASCI generates new candidate determinants by estimating their importance to the overall wavefunction through perturbation theory. ASCI then ranks their contributions to the wavefunction and selects the most significant ones to add to the determinant space for the subsequent iterations. The Hamiltonian is then projected into this expanded space and diagonalized to produce an improved wavefunction. This process is repeated with a iteratively larger determinant space until a target number of determinants (
ntdets_max) is reached. The rate at which the determinant space grows is controlled by thegrow_factorsetting, which determines how many new determinants are added at each iteration. However, if the search algorithm fails to find enough important determinants, the growth factor is reduced by thegrowth_backoff_rateto ensure stability. Conversely, if the search is successful, the growth factor is increased by thegrowth_recovery_rateto accelerate convergence in subsequent iterations.Refinement Phase: Once the determinant space has reached the target size, the refinement phase begins. In this phase, ASCI focuses on fine-tuning the wavefunction by iteratively improving the selection of determinants within the fixed-size space. The algorithm evaluates the contributions of each determinant to the wavefunction and removes those that contribute least, replacing them with new candidates generated through perturbation theory. This selective pruning and replacement process continues until convergence is achieved, as determined by the
refine_energy_tolsetting or until the maximum number of refinement iterations (max_refine_iter) is reached.
The ASCI Search Algorithm
In both the growth and refinement phases, the ASCI search algorithm is performed to update the current wavefunction.
The key realization of ASCI is that the search can be drastically accelerated by only searching for determinants that are connected via the Hamiltonian from a small set of “core” determinants rather than the full wavefunction at any particular iteration.
This module provides several ways to control the size of this core set, including a maximum number of core determinants (ncdets_max) as well as allowing the core space to update dynamically as the wavefunction grows by specifying that a fixed percentage of the current wavefunction determinants be included in the core set (core_selection_threshold).
The method for selecting the core determinants is controlled by the core_selection_strategy setting.
Settings
In addition to the common settings, MACIS ASCI supports the following implementation-specific settings:
Setting |
Type |
Default |
Description |
|---|---|---|---|
|
int |
|
Maximum number of trial determinants in the variational space |
|
int |
|
Minimum number of trial determinants required |
|
str |
|
Strategy for selecting core determinants (“fixed” or “percentage”) |
|
float |
|
Cumulative weight threshold for core selection (if using percentage strategy) |
|
int |
|
Maximum number of core determinants (if using fixed strategy) |
|
float |
|
Factor for growing determinant space |
|
float |
|
Minimum allowed growth factor |
|
float |
|
Rate to reduce grow_factor on failure |
|
float |
|
Rate to restore grow_factor on success |
|
int |
|
Maximum number of refinement iterations |
|
float |
|
Energy tolerance for refinement convergence |
Further reading
The above examples can be downloaded as complete Python or C++ code.
HamiltonianConstructor: Produces the Hamiltonian for CI
ActiveSpaceSelector: Helps identify important orbitals for the active space
Settings: Configuration settings for algorithms
Factory Pattern: Understanding algorithm creation