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

// Create the default HamiltonianConstructor instance
auto hamiltonian_constructor = HamiltonianConstructorFactory::create();
# 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")

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)
// Note: Available settings can be inspected at runtime

// Set ERI method if needed
hamiltonian_constructor->settings().set("eri_method", "direct");
# 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")

Running the calculation

// Load structure from XYZ file
auto structure = std::make_shared<Structure>(
    Structure::from_xyz_file("../data/h2.structure.xyz"));

// Run a SCF to get orbitals
auto scf_solver = ScfSolverFactory::create();
scf_solver->settings().set("basis_set", "sto-3g");
auto [E_scf, wfn] = scf_solver->run(structure, 0, 1);
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;
# Load a structure from XYZ file
structure = Structure.from_xyz_file(Path(__file__).parent / "../data/h2.structure.xyz")

# 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())

Available implementations

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

auto names = HamiltonianConstructorFactory::available();
for (const auto& name : names) {
  std::cout << name << std::endl;
}
from qdk_chemistry.algorithms import registry  # noqa: E402

print(registry.available("hamiltonian_constructor"))
# ['qdk']

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”)

scf_type

string

Type of SCF reference (“rhf”, “rohf”, or “uhf”)

Further reading