Hamiltonian construction

The HamiltonianConstructor algorithm in QDK/Chemistry constructs electronic Hamiltonians for quantum chemistry calculations. Following QDK/Chemistry’s algorithm design principles, it takes an Orbitals instance as input and produces a Hamiltonian instance as output. It generates the one- and two-electron integrals that define the energy operator for the electronic structure.

Overview

The electronic Hamiltonian describes the energy of a system of electrons in the field of atomic nuclei. It consists of kinetic energy terms, electron-nucleus attraction terms, and electron-electron repulsion terms. The HamiltonianConstructor algorithm computes the matrix elements of this operator in a given orbital basis, which can be the full orbital space or an active subspace.

Using the HamiltonianConstructor

This section demonstrates how to create, configure, and run a Hamiltonian construction. The run method returns a Hamiltonian object containing the one- and two-electron integrals.

Input requirements

The HamiltonianConstructor requires the following input:

Orbitals

An Orbitals instance describing the single orbital basis in which to express the many-body Hamiltonian. This object contains information about the molecular structure, basis set, and orbital coefficients.

Note

The Orbitals object carries all the information needed for integral transformation, including the basis set and molecular structure. Active space indices, if present, determine which orbitals are included in the output Hamiltonian.

Creating a constructor

# List available Hamiltonian constructor implementations
available_constructors = available("hamiltonian_constructor")
print(f"Available Hamiltonian constructors: {available_constructors}")

# Create the default HamiltonianConstructor instance
hamiltonian_constructor = create("hamiltonian_constructor")
// Create the default HamiltonianConstructor instance
auto hamiltonian_constructor = HamiltonianConstructorFactory::create();

Configuring settings

Settings can be modified using the settings() object. See Available implementations below for implementation-specific options.

Note

All orbital indices in QDK/Chemistry are 0-based, following the convention used in most programming languages.

# Configure settings (check available options)
print(f"Available settings: {hamiltonian_constructor.settings().keys()}")

# Set ERI method if needed
hamiltonian_constructor.settings().set("eri_method", "direct")
// Configure settings (check available options)
// Note: Available settings can be inspected at runtime

// Set ERI method if needed
hamiltonian_constructor->settings().set("eri_method", "direct");

Running the calculation

# Load a structure from inline XYZ file
structure = Structure.from_xyz("""\
2
H2 molecule
H    0.000000    0.000000    0.000000
H    0.000000    0.000000    0.740848
""")

# Run a 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"
)
orbitals = wfn.get_orbitals()

# Construct the Hamiltonian from orbitals
hamiltonian = hamiltonian_constructor.run(orbitals)

# Access the resulting integrals
h1_a, h1_b = hamiltonian.get_one_body_integrals()
h2_aaaa, h2_aabb, h2_bbbb = hamiltonian.get_two_body_integrals()
core_energy = hamiltonian.get_core_energy()

print(f"One-body integrals shape: {h1_a.shape}")
print(f"Two-body integrals shape: {h2_aaaa.shape}")
print(f"Core energy: {core_energy:.10f} Hartree")
print(hamiltonian.get_summary())
// Load structure from inline XYZ file
auto structure = std::make_shared<Structure>(Structure::from_xyz(R"(2
H2 molecule
H    0.000000    0.000000    0.000000
H    0.000000    0.000000    0.740848
)"));

// Run a SCF to get orbitals
auto scf_solver = ScfSolverFactory::create();
auto [E_scf, wfn] = scf_solver->run(structure, 0, 1, "sto-3g");
auto orbitals = wfn->get_orbitals();

// Construct the Hamiltonian from orbitals
auto hamiltonian = hamiltonian_constructor->run(orbitals);

// Access the resulting integrals
auto [h1_a, h1_b] = hamiltonian->get_one_body_integrals();
auto [h2_aaaa, h2_aabb, h2_bbbb] = hamiltonian->get_two_body_integrals();
auto core_energy = hamiltonian->get_core_energy();

std::cout << "One-body integrals shape: " << h1_a.rows() << "x" << h1_a.cols()
          << std::endl;
std::cout << "Two-body integrals shape: " << h2_aaaa.dimension(0) << "x"
          << h2_aaaa.dimension(1) << "x" << h2_aaaa.dimension(2) << "x"
          << h2_aaaa.dimension(3) << std::endl;
std::cout << "Core energy: " << std::fixed << std::setprecision(10)
          << core_energy << " Hartree" << std::endl;
std::cout << hamiltonian->get_summary() << std::endl;

Available implementations

QDK/Chemistry’s HamiltonianConstructor provides a unified interface for Hamiltonian construction methods. You can discover available implementations programmatically:

from qdk_chemistry.algorithms import registry

print(registry.available("hamiltonian_constructor"))
# ['qdk']
auto names = HamiltonianConstructorFactory::available();
for (const auto& name : names) {
  std::cout << name << std::endl;
}

QDK (Native)

Factory name: "qdk" (default)

The native QDK/Chemistry implementation for Hamiltonian construction. Transforms molecular orbitals from AO to MO basis and computes one- and two-electron integrals.

Settings

Setting

Type

Description

eri_method

string

Method for computing electron repulsion integrals (“direct” or “incore”)

QDK Cholesky

Factory name: "qdk_cholesky"

A Cholesky decomposition-based implementation for Hamiltonian construction. This method uses Cholesky decomposition of the electron repulsion integral (ERI) tensor to reduce memory requirements and computational cost while maintaining high accuracy. The decomposition represents the four-center ERIs as products of three-center integrals (Cholesky vectors), which are transformed to the MO basis. The output Hamiltonian stores the MO three-center integrals directly in a CholeskyHamiltonianContainer, avoiding expansion to the full four-center representation. Additionally, the original AO Cholesky vectors are preserved in the container when store_ao_cholesky_vectors is enabled, and can be retrieved via get_ao_cholesky_vectors(). Four-center integrals are lazily computed from the three-center integrals on demand.

Settings

Setting

Type

Description

cholesky_tolerance

float

Tolerance for Cholesky decomposition accuracy. Smaller values give higher accuracy but more Cholesky vectors. Default: 1e-8

eri_threshold

float

ERI screening threshold for skipping negligible shell quartets during Cholesky decomposition. Default: 1e-12

store_ao_cholesky_vectors

bool

Whether to store the AO three-center integrals in a CholeskyHamiltonianContainer in addition to the MO three-center integrals, which are always saved. Default: false

Further reading