SBD bindings (sbd)

SBD (Selected Basis Diagonalization) Python Bindings

This package provides Python bindings for the SBD library.

Usage:

import sbd
results = sbd.tpb_diag_from_files(fcidump, adets, config)

# Explicit init is optional — auto-initialized on first use
sbd.init(device='gpu')              # set default device explicitly

Device switching (CPU/GPU) within the same process:

result_cpu = sbd.tpb_diag(..., device='cpu')
result_gpu = sbd.tpb_diag(..., device='gpu')
FCIDump(device=None)[source]

Create FCIDump object.

GDB_SBD(device=None)[source]

Create GDB_SBD configuration object.

LoadAlphaDets(filename, bit_length, total_bit_length, device=None)[source]

Load alpha determinants from file.

LoadFCIDump(filename, device=None)[source]

Load FCIDUMP file.

TPB_SBD(device=None)[source]

Create TPB_SBD configuration object.

available_backends()[source]

Devices whose extension is built and structurally loadable.

Each candidate .so is inspected statically – present on disk, no unresolved shared-library dependencies, matching architecture – without importing it. Importing would run MPI_Init, which hangs on an MPI lacking PMIx support when the process was not started under a launcher.

A listed backend is therefore “present and structurally sound”, not “guaranteed to load”: an ABI/symbol mismatch only shows up on a real dlopen, and surfaces from get_backend(). Reasons for anything excluded are in backend_load_errors(); a backend that is merely not built is recorded there but does not warn, since building a subset is normal.

backend_load_errors()[source]

Why each unusable backend is unusable.

Maps device -> reason, distinguishing “not built” from a missing shared library, an architecture mismatch, or a failed import.

barrier()[source]

MPI barrier — synchronize all processes.

finalize()[source]

Finalize SBD and reset session state.

Synchronizes GPU (if used) but does NOT call MPI_Finalize — mpi4py handles MPI lifecycle automatically.

After finalize(), init() can be called again.

from_string(s, bit_length, total_bit_length, device=None)[source]

Convert binary string to determinant format.

gdb_diag(fcidump, det, sbd_data, loadname='', savename='', device=None)[source]

Perform GDB diagonalization over an explicit list of determinants.

Unlike TPB, which spans the subspace with the Cartesian product of an alpha and a beta determinant list, GDB spans it with the given determinants themselves, so an arbitrary sparse subspace can be diagonalized.

Each determinant is a 2 * norb-bit configuration packed into words of sbd_data.bit_length bits, as returned by from_string(). Bit 2 * i is the occupation of spin-alpha orbital i and bit 2 * i + 1 that of spin-beta orbital i.

Parameters:
  • fcidump – FCIDump object.

  • det – Determinants spanning the subspace. Must be distinct; they are sorted into SBD’s canonical order internally, which sort_bitarray() reproduces.

  • sbd_data – GDB_SBD configuration object. b_comm_size must be 1.

  • loadname – Path to load initial wavefunction (optional).

  • savename – Path prefix to save the final wavefunction to (optional). SBD writes f"{savename}000000.bin", holding the determinants in canonical order and their amplitudes.

  • device – Override device (‘cpu’, ‘gpu’, or None for default).

Returns:

energy, density, carryover_det, one_p_rdm, two_p_rdm.

Return type:

dict with keys

get_backend(device=None)[source]

Get the backend module for the given device.

Auto-initializes SBD if needed. Passing device overrides the default — this is how you switch between CPU and GPU within the same process.

Parameters:

device – ‘cpu’, ‘gpu’, ‘auto’, or None (use default).

Returns:

The pybind11 backend module (_core_cpu, _core_gpu_thrust, or _core_gpu_omp_offload).

get_comm()[source]

Get the MPI communicator.

get_comm_backend()[source]

Get the communication backend name.

get_device()[source]

Get the default compute device name.

get_device_id(device=None)[source]

Get the device index this rank will use, or -1 if there is none.

Reports what the backend’s own rank-to-device rule yields rather than recomputing it here, so a caller putting another library on the same card cannot drift out of step with SBD. Selects nothing and creates no context, so it is safe to call before any GPU work.

Uses the communicator rank, i.e. the same gpu_id = rank % num_gpus convention SBD’s own diagonalization applies, documented in examples/tpb/README.md.

get_rank()[source]

Get MPI rank of current process.

get_world_size()[source]

Get total number of MPI processes.

has_backend_conflict()[source]

True when _core_cpu and the OMP-offload backend are both loaded here.

That combination leaves libnvomp initialised host-only, so offload regions run on the host while device queries still report a GPU. Lazy loading normally prevents it; this catches a caller that imported both explicitly.

init(device='cpu', comm_backend='mpi')[source]

Initialize SBD with MPI and set the default compute device.

Calling init() explicitly is optional — SBD auto-initializes on first use with device='cpu' and comm_backend='mpi'. Call it explicitly only when you need GPU or want to control startup timing.

The device can be overridden per-call via the device parameter on tpb_diag(), tpb_diag_from_files(), and get_backend().

Parameters:
  • device – Default compute device — ‘cpu’, ‘gpu’, ‘gpu-omp’, or ‘auto’. ‘gpu’ is the NVIDIA-only Thrust backend; ‘gpu-omp’ is OpenMP target offload and serves NVIDIA and AMD alike. Aliases for ‘gpu’: ‘gpu-thrust’, ‘gpu-nvidia’, ‘cuda’. Aliases for ‘gpu-omp’: ‘gpu-omp-offload’, ‘gpu-nvhpc-omp’, ‘gpu-nvidia-omp’, ‘gpu-amd-omp’, ‘gpu-rocm-omp’, ‘rocm’.

  • comm_backend – Communication backend — ‘mpi’.

Raises:

RuntimeError – If MPI is not available or no backends are compiled.

is_initialized()[source]

Check if SBD has been initialized.

loaded_backends()[source]

Devices actually imported into this process so far.

Normally one: backends load on first use. More than one means something imported them explicitly, which is worth knowing – co-loading _core_cpu with the OMP-offload backend silently demotes offload to the host.

makestring(config, bit_length, total_bit_length, device=None)[source]

Convert determinant to string representation.

print_info()[source]

Print SBD information.

sort_bitarray(dets, device=None)[source]

Sort determinants into canonical order, removing duplicates.

Diagonalization requires its determinant lists to be in this order. gdb_diag() sorts its own input, so this reproduces the order it works in.

tpb_diag(fcidump, adet, bdet, sbd_data, loadname='', savename='', device=None)[source]

Perform TPB diagonalization with data structures.

Parameters:
  • fcidump – FCIDump object.

  • adet – Alpha determinants.

  • bdet – Beta determinants.

  • sbd_data – TPB_SBD configuration object.

  • loadname – Path to load initial wavefunction (optional).

  • savename – Path to save final wavefunction (optional).

  • device – Override device (‘cpu’, ‘gpu’, or None for default).

Returns:

energy, density, carryover_adet, carryover_bdet, one_p_rdm, two_p_rdm.

Return type:

dict with keys

tpb_diag_from_files(fcidumpfile, adetfile, sbd_data, loadname='', savename='', device=None)[source]

Perform TPB diagonalization from files.

Parameters:
  • fcidumpfile – Path to FCIDUMP file.

  • adetfile – Path to alpha determinants file.

  • sbd_data – TPB_SBD configuration object.

  • loadname – Path to load initial wavefunction (optional).

  • savename – Path to save final wavefunction (optional).

  • device – Override device (‘cpu’, ‘gpu’, or None for default).

Returns:

energy, density, carryover_adet, carryover_bdet, one_p_rdm, two_p_rdm.

Return type:

dict with keys