sbd-eigensolver 1.6.0__tar.gz → 1.7.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- sbd_eigensolver-1.7.0/INSTALL.md +205 -0
- {sbd_eigensolver-1.6.0 → sbd_eigensolver-1.7.0}/MANIFEST.in +2 -1
- sbd_eigensolver-1.7.0/PKG-INFO +397 -0
- sbd_eigensolver-1.7.0/README.md +349 -0
- sbd_eigensolver-1.7.0/examples/gdb/README.md +511 -0
- sbd_eigensolver-1.7.0/examples/gdb/run_gdb_diag.py +568 -0
- sbd_eigensolver-1.7.0/examples/gdb/run_gdb_heatbath.py +608 -0
- sbd_eigensolver-1.7.0/examples/tpb/README.md +507 -0
- sbd_eigensolver-1.7.0/examples/tpb/count_dict_h2o.json +277 -0
- {sbd_eigensolver-1.6.0/python/examples → sbd_eigensolver-1.7.0/examples/tpb}/run_sbd_diag.py +125 -15
- sbd_eigensolver-1.7.0/examples/tpb/run_sqd_enlarge_subspace_sbd.py +569 -0
- {sbd_eigensolver-1.6.0/python/examples → sbd_eigensolver-1.7.0/examples/tpb}/run_sqd_sbd.ipynb +37 -21
- sbd_eigensolver-1.7.0/examples/tpb/run_sqd_sbd.py +655 -0
- sbd_eigensolver-1.7.0/pyproject.toml +86 -0
- sbd_eigensolver-1.7.0/python/__init__.py +833 -0
- sbd_eigensolver-1.7.0/python/bindings.cpp +1235 -0
- {sbd_eigensolver-1.6.0 → sbd_eigensolver-1.7.0}/python/device_config.py +129 -44
- sbd_eigensolver-1.7.0/python/sbd_solver.py +775 -0
- sbd_eigensolver-1.7.0/sbd_eigensolver.egg-info/PKG-INFO +397 -0
- sbd_eigensolver-1.7.0/sbd_eigensolver.egg-info/SOURCES.txt +130 -0
- sbd_eigensolver-1.7.0/sbd_eigensolver.egg-info/requires.txt +25 -0
- sbd_eigensolver-1.7.0/setup.py +1095 -0
- sbd_eigensolver-1.7.0/test/test_gdb_drivers.py +372 -0
- sbd_eigensolver-1.7.0/test/test_gdb_equivalence.py +668 -0
- sbd_eigensolver-1.7.0/test/test_reference_energies.py +139 -0
- sbd_eigensolver-1.7.0/test/test_sqd_integration.py +524 -0
- sbd_eigensolver-1.7.0/vendor/sbd-upstream/LICENSE.txt +206 -0
- sbd_eigensolver-1.7.0/vendor/sbd-upstream/include/sbd/caop/basic/arithmetic.h +587 -0
- sbd_eigensolver-1.7.0/vendor/sbd-upstream/include/sbd/caop/basic/basis.h +759 -0
- sbd_eigensolver-1.7.0/vendor/sbd-upstream/include/sbd/caop/basic/carryover.h +81 -0
- sbd_eigensolver-1.7.0/vendor/sbd-upstream/include/sbd/caop/basic/davidson.h +452 -0
- sbd_eigensolver-1.7.0/vendor/sbd-upstream/include/sbd/caop/basic/expansion.h +237 -0
- sbd_eigensolver-1.7.0/vendor/sbd-upstream/include/sbd/caop/basic/generalop.h +871 -0
- sbd_eigensolver-1.7.0/vendor/sbd-upstream/include/sbd/caop/basic/generalop_flatdata.h +139 -0
- sbd_eigensolver-1.7.0/vendor/sbd-upstream/include/sbd/caop/basic/helper.h +59 -0
- sbd_eigensolver-1.7.0/vendor/sbd-upstream/include/sbd/caop/basic/inc_all.h +20 -0
- sbd_eigensolver-1.7.0/vendor/sbd-upstream/include/sbd/caop/basic/lanczos.h +322 -0
- sbd_eigensolver-1.7.0/vendor/sbd-upstream/include/sbd/caop/basic/loadmodel.h +359 -0
- sbd_eigensolver-1.7.0/vendor/sbd-upstream/include/sbd/caop/basic/mkham.h +195 -0
- sbd_eigensolver-1.7.0/vendor/sbd-upstream/include/sbd/caop/basic/mult.h +233 -0
- sbd_eigensolver-1.7.0/vendor/sbd-upstream/include/sbd/caop/basic/mult_thrust.h +744 -0
- sbd_eigensolver-1.7.0/vendor/sbd-upstream/include/sbd/caop/basic/restart.h +151 -0
- sbd_eigensolver-1.7.0/vendor/sbd-upstream/include/sbd/caop/basic/sbdiag.h +634 -0
- sbd_eigensolver-1.7.0/vendor/sbd-upstream/include/sbd/caop/inc_all.h +6 -0
- sbd_eigensolver-1.7.0/vendor/sbd-upstream/include/sbd/chemistry/basic/correlation.h +355 -0
- sbd_eigensolver-1.7.0/vendor/sbd-upstream/include/sbd/chemistry/basic/correlation_thrust.h +145 -0
- sbd_eigensolver-1.7.0/vendor/sbd-upstream/include/sbd/chemistry/basic/davidson_thrust.h +681 -0
- sbd_eigensolver-1.7.0/vendor/sbd-upstream/include/sbd/chemistry/basic/determinants.h +653 -0
- sbd_eigensolver-1.7.0/vendor/sbd-upstream/include/sbd/chemistry/basic/determinants_thrust.h +276 -0
- sbd_eigensolver-1.7.0/vendor/sbd-upstream/include/sbd/chemistry/basic/excitation.h +87 -0
- sbd_eigensolver-1.7.0/vendor/sbd-upstream/include/sbd/chemistry/basic/helpers.h +244 -0
- sbd_eigensolver-1.7.0/vendor/sbd-upstream/include/sbd/chemistry/basic/inc_all.h +23 -0
- sbd_eigensolver-1.7.0/vendor/sbd-upstream/include/sbd/chemistry/basic/integrals.h +115 -0
- sbd_eigensolver-1.7.0/vendor/sbd-upstream/include/sbd/chemistry/basic/integrals_thrust.h +127 -0
- sbd_eigensolver-1.7.0/vendor/sbd-upstream/include/sbd/chemistry/basic/lanczos_thrust.h +168 -0
- sbd_eigensolver-1.7.0/vendor/sbd-upstream/include/sbd/chemistry/basic/makedeterminants.h +195 -0
- sbd_eigensolver-1.7.0/vendor/sbd-upstream/include/sbd/chemistry/basic/makeintegrals.h +179 -0
- sbd_eigensolver-1.7.0/vendor/sbd-upstream/include/sbd/chemistry/basic/mult.h +108 -0
- sbd_eigensolver-1.7.0/vendor/sbd-upstream/include/sbd/chemistry/basic/omp_offload.h +358 -0
- sbd_eigensolver-1.7.0/vendor/sbd-upstream/include/sbd/chemistry/basic/qcham.h +447 -0
- sbd_eigensolver-1.7.0/vendor/sbd-upstream/include/sbd/chemistry/gdb/carryover.h +120 -0
- sbd_eigensolver-1.7.0/vendor/sbd-upstream/include/sbd/chemistry/gdb/correlation.h +308 -0
- sbd_eigensolver-1.7.0/vendor/sbd-upstream/include/sbd/chemistry/gdb/correlation_thrust.h +448 -0
- sbd_eigensolver-1.7.0/vendor/sbd-upstream/include/sbd/chemistry/gdb/davidson.h +623 -0
- sbd_eigensolver-1.7.0/vendor/sbd-upstream/include/sbd/chemistry/gdb/davidson_thrust.h +367 -0
- sbd_eigensolver-1.7.0/vendor/sbd-upstream/include/sbd/chemistry/gdb/exact_external_observable.h +93 -0
- sbd_eigensolver-1.7.0/vendor/sbd-upstream/include/sbd/chemistry/gdb/expansion.h +834 -0
- sbd_eigensolver-1.7.0/vendor/sbd-upstream/include/sbd/chemistry/gdb/grid_distribution.h +436 -0
- sbd_eigensolver-1.7.0/vendor/sbd-upstream/include/sbd/chemistry/gdb/hash_owned_external_observable.h +113 -0
- sbd_eigensolver-1.7.0/vendor/sbd-upstream/include/sbd/chemistry/gdb/heatbath_lookup.h +142 -0
- sbd_eigensolver-1.7.0/vendor/sbd-upstream/include/sbd/chemistry/gdb/helper.h +818 -0
- sbd_eigensolver-1.7.0/vendor/sbd-upstream/include/sbd/chemistry/gdb/helper_thrust.h +768 -0
- sbd_eigensolver-1.7.0/vendor/sbd-upstream/include/sbd/chemistry/gdb/inc_all.h +31 -0
- sbd_eigensolver-1.7.0/vendor/sbd-upstream/include/sbd/chemistry/gdb/mult.h +272 -0
- sbd_eigensolver-1.7.0/vendor/sbd-upstream/include/sbd/chemistry/gdb/mult_thrust.h +1097 -0
- sbd_eigensolver-1.7.0/vendor/sbd-upstream/include/sbd/chemistry/gdb/occupation.h +52 -0
- sbd_eigensolver-1.7.0/vendor/sbd-upstream/include/sbd/chemistry/gdb/parent_sampling.h +115 -0
- sbd_eigensolver-1.7.0/vendor/sbd-upstream/include/sbd/chemistry/gdb/qcham.h +406 -0
- sbd_eigensolver-1.7.0/vendor/sbd-upstream/include/sbd/chemistry/gdb/restart.h +10 -0
- sbd_eigensolver-1.7.0/vendor/sbd-upstream/include/sbd/chemistry/gdb/sbdiag.h +786 -0
- sbd_eigensolver-1.7.0/vendor/sbd-upstream/include/sbd/chemistry/gdb/stat_evaluator.h +230 -0
- sbd_eigensolver-1.7.0/vendor/sbd-upstream/include/sbd/chemistry/gdb/statistical_contribution_expansion.h +205 -0
- sbd_eigensolver-1.7.0/vendor/sbd-upstream/include/sbd/chemistry/gdb/u_statistic_external_observable.h +154 -0
- sbd_eigensolver-1.7.0/vendor/sbd-upstream/include/sbd/chemistry/inc_all.h +8 -0
- sbd_eigensolver-1.7.0/vendor/sbd-upstream/include/sbd/chemistry/tpb/correlation.h +647 -0
- sbd_eigensolver-1.7.0/vendor/sbd-upstream/include/sbd/chemistry/tpb/correlation_thrust.h +734 -0
- sbd_eigensolver-1.7.0/vendor/sbd-upstream/include/sbd/chemistry/tpb/davidson.h +976 -0
- sbd_eigensolver-1.7.0/vendor/sbd-upstream/include/sbd/chemistry/tpb/davidson_thrust.h +319 -0
- sbd_eigensolver-1.7.0/vendor/sbd-upstream/include/sbd/chemistry/tpb/extend.h +324 -0
- sbd_eigensolver-1.7.0/vendor/sbd-upstream/include/sbd/chemistry/tpb/helper.h +1252 -0
- sbd_eigensolver-1.7.0/vendor/sbd-upstream/include/sbd/chemistry/tpb/helper_thrust.h +620 -0
- sbd_eigensolver-1.7.0/vendor/sbd-upstream/include/sbd/chemistry/tpb/inc_all.h +25 -0
- sbd_eigensolver-1.7.0/vendor/sbd-upstream/include/sbd/chemistry/tpb/lanczos.h +327 -0
- sbd_eigensolver-1.7.0/vendor/sbd-upstream/include/sbd/chemistry/tpb/lanczos_thrust.h +177 -0
- sbd_eigensolver-1.7.0/vendor/sbd-upstream/include/sbd/chemistry/tpb/mult.h +887 -0
- sbd_eigensolver-1.7.0/vendor/sbd-upstream/include/sbd/chemistry/tpb/mult_thrust.h +1667 -0
- sbd_eigensolver-1.7.0/vendor/sbd-upstream/include/sbd/chemistry/tpb/occupation.h +99 -0
- sbd_eigensolver-1.7.0/vendor/sbd-upstream/include/sbd/chemistry/tpb/qcham.h +347 -0
- sbd_eigensolver-1.7.0/vendor/sbd-upstream/include/sbd/chemistry/tpb/rdmat.h +267 -0
- sbd_eigensolver-1.7.0/vendor/sbd-upstream/include/sbd/chemistry/tpb/restart.h +785 -0
- sbd_eigensolver-1.7.0/vendor/sbd-upstream/include/sbd/chemistry/tpb/sbdiag.h +948 -0
- sbd_eigensolver-1.7.0/vendor/sbd-upstream/include/sbd/framework/bit_manipulation.h +1854 -0
- sbd_eigensolver-1.7.0/vendor/sbd-upstream/include/sbd/framework/cublas_utility.h +235 -0
- sbd_eigensolver-1.7.0/vendor/sbd-upstream/include/sbd/framework/cuda_reduce.h +179 -0
- sbd_eigensolver-1.7.0/vendor/sbd-upstream/include/sbd/framework/cuda_utility.h +63 -0
- sbd_eigensolver-1.7.0/vendor/sbd-upstream/include/sbd/framework/det_vector.h +818 -0
- sbd_eigensolver-1.7.0/vendor/sbd-upstream/include/sbd/framework/determinant_distribution_round_robin.h +179 -0
- sbd_eigensolver-1.7.0/vendor/sbd-upstream/include/sbd/framework/determinant_initialization.h +67 -0
- sbd_eigensolver-1.7.0/vendor/sbd-upstream/include/sbd/framework/distributed_alias_sampling.h +225 -0
- sbd_eigensolver-1.7.0/vendor/sbd-upstream/include/sbd/framework/dm_vector.h +296 -0
- sbd_eigensolver-1.7.0/vendor/sbd-upstream/include/sbd/framework/fcidump.h +262 -0
- sbd_eigensolver-1.7.0/vendor/sbd-upstream/include/sbd/framework/hip_reduce.h +173 -0
- sbd_eigensolver-1.7.0/vendor/sbd-upstream/include/sbd/framework/hp_numeric.h +575 -0
- sbd_eigensolver-1.7.0/vendor/sbd-upstream/include/sbd/framework/jacobi.h +104 -0
- sbd_eigensolver-1.7.0/vendor/sbd-upstream/include/sbd/framework/mpi_utility.h +708 -0
- sbd_eigensolver-1.7.0/vendor/sbd-upstream/include/sbd/framework/mpi_utility_thrust.h +484 -0
- sbd_eigensolver-1.7.0/vendor/sbd-upstream/include/sbd/framework/murmurhash_basis_distribution.h +418 -0
- sbd_eigensolver-1.7.0/vendor/sbd-upstream/include/sbd/framework/nccl_utility.h +146 -0
- sbd_eigensolver-1.7.0/vendor/sbd-upstream/include/sbd/framework/nvtx.h +179 -0
- sbd_eigensolver-1.7.0/vendor/sbd-upstream/include/sbd/framework/sort_array.h +356 -0
- sbd_eigensolver-1.7.0/vendor/sbd-upstream/include/sbd/framework/ssutils.h +27 -0
- sbd_eigensolver-1.7.0/vendor/sbd-upstream/include/sbd/framework/stat/stat_evaluator_batch.h +260 -0
- sbd_eigensolver-1.7.0/vendor/sbd-upstream/include/sbd/framework/thrust_kernels.h +761 -0
- sbd_eigensolver-1.7.0/vendor/sbd-upstream/include/sbd/framework/timestamp.h +31 -0
- sbd_eigensolver-1.7.0/vendor/sbd-upstream/include/sbd/framework/type_def.h +85 -0
- sbd_eigensolver-1.7.0/vendor/sbd-upstream/include/sbd/sbd.h +7 -0
- sbd_eigensolver-1.6.0/PKG-INFO +0 -473
- sbd_eigensolver-1.6.0/README.md +0 -444
- sbd_eigensolver-1.6.0/pyproject.toml +0 -44
- sbd_eigensolver-1.6.0/python/__init__.py +0 -495
- sbd_eigensolver-1.6.0/python/bindings.cpp +0 -607
- sbd_eigensolver-1.6.0/python/examples/README.md +0 -211
- sbd_eigensolver-1.6.0/python/examples/run_sqd_sbd.py +0 -330
- sbd_eigensolver-1.6.0/python/sbd_solver.py +0 -484
- sbd_eigensolver-1.6.0/sbd_eigensolver.egg-info/PKG-INFO +0 -473
- sbd_eigensolver-1.6.0/sbd_eigensolver.egg-info/SOURCES.txt +0 -20
- sbd_eigensolver-1.6.0/sbd_eigensolver.egg-info/requires.txt +0 -3
- sbd_eigensolver-1.6.0/setup.py +0 -458
- {sbd_eigensolver-1.6.0 → sbd_eigensolver-1.7.0}/LICENSE.txt +0 -0
- {sbd_eigensolver-1.6.0 → sbd_eigensolver-1.7.0}/python/sbd_nvhpc_compat.h +0 -0
- {sbd_eigensolver-1.6.0 → sbd_eigensolver-1.7.0}/sbd_eigensolver.egg-info/dependency_links.txt +0 -0
- {sbd_eigensolver-1.6.0 → sbd_eigensolver-1.7.0}/sbd_eigensolver.egg-info/not-zip-safe +0 -0
- {sbd_eigensolver-1.6.0 → sbd_eigensolver-1.7.0}/sbd_eigensolver.egg-info/top_level.txt +0 -0
- {sbd_eigensolver-1.6.0 → sbd_eigensolver-1.7.0}/setup.cfg +0 -0
|
@@ -0,0 +1,205 @@
|
|
|
1
|
+
# Installing sbd-eigensolver
|
|
2
|
+
|
|
3
|
+
Every install compiles the extension modules on the target machine — no wheels are
|
|
4
|
+
published — so which backends you end up with depends on the toolchain the build
|
|
5
|
+
finds. The quickstart in the [README](README.md#installation) covers the common CPU
|
|
6
|
+
case; this page is the full matrix: prerequisites, the environment variables the build
|
|
7
|
+
reads, building against a host MPI, and how to verify what you got.
|
|
8
|
+
|
|
9
|
+
## Prerequisites
|
|
10
|
+
|
|
11
|
+
**Required:** Python 3.10+, MPI (OpenMPI/MPICH), BLAS (OpenBLAS/MKL), pybind11, mpi4py, numpy, compiler with OpenMP.
|
|
12
|
+
|
|
13
|
+
**On macOS:** Apple clang ships without OpenMP, so add `llvm-openmp` to the conda
|
|
14
|
+
environment. Homebrew's `libomp` is used as a fallback if the env has none. Pin the
|
|
15
|
+
compiler with `CC`/`CXX` as well — a bare `clang++` is resolved through `PATH`, so a
|
|
16
|
+
Homebrew LLVM silently wins over both Apple clang and a conda toolchain. The build
|
|
17
|
+
prints which compiler and which libomp it chose.
|
|
18
|
+
|
|
19
|
+
**For the GPU backends** — optional; without them you get a CPU-only install:
|
|
20
|
+
|
|
21
|
+
***On NVIDIA*** (both the Thrust and the OpenMP-offload backend):
|
|
22
|
+
|
|
23
|
+
- *to build:* [NVIDIA HPC SDK](https://developer.nvidia.com/hpc-sdk) (`nvc++`).
|
|
24
|
+
`SBD_GPU_ARCH` is **optional**: unset, nvc++ targets the GPU of the machine
|
|
25
|
+
the toolchain was installed on; set, it is honored exactly and may name
|
|
26
|
+
several generations at once (`cc80,cc90,cc100`) — see
|
|
27
|
+
[Environment Variables](#environment-variables).
|
|
28
|
+
|
|
29
|
+
***On AMD*** (the OpenMP-offload backend only):
|
|
30
|
+
|
|
31
|
+
- *to build:* ROCm LLVM toolchain (`amdclang++`).
|
|
32
|
+
`SBD_GPU_ARCH` is optional here on a GPU system and is **detected** with
|
|
33
|
+
ROCm's `amdgpu-arch` (e.g. `gfx90a` on MI250X, `gfx942` on MI300X). However, on a GPU-less build host, you must
|
|
34
|
+
set it. see [Environment Variables](#environment-variables).
|
|
35
|
+
|
|
36
|
+
Either install path compiles the C++ extension on the target machine;
|
|
37
|
+
no pre-built wheels are published. The resulting binary depends on the
|
|
38
|
+
local MPI and BLAS, so both must be installed first.
|
|
39
|
+
|
|
40
|
+
## Install from PyPI
|
|
41
|
+
|
|
42
|
+
**A self-contained conda environment** is the quickest way to get those
|
|
43
|
+
dependencies in place for the CPU backend:
|
|
44
|
+
```bash
|
|
45
|
+
conda create -y -n sbd -c conda-forge \
|
|
46
|
+
python=3.13.12 pybind11 numpy setuptools wheel openblas pyscf pip mpi4py
|
|
47
|
+
# ...plus llvm-openmp on macOS
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
```bash
|
|
51
|
+
conda activate sbd
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
Now install the sbd-eigensolver-python package
|
|
55
|
+
```
|
|
56
|
+
pip install sbd-eigensolver
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
The published source distribution (sdist) bundles the sbd header files, so this
|
|
60
|
+
needs no git checkout and no submodule step.
|
|
61
|
+
|
|
62
|
+
## Install from git checkout
|
|
63
|
+
|
|
64
|
+
Here the headers come from upstream
|
|
65
|
+
[r-ccs-cms/sbd](https://github.com/r-ccs-cms/sbd) via a git submodule at
|
|
66
|
+
`vendor/sbd-upstream/`, **pinned at a specific upstream commit**. Run `git submodule status` to see the pinned SHA.
|
|
67
|
+
|
|
68
|
+
When installing from a git checkout, it is important to make sure the
|
|
69
|
+
sbd submodule is cloned, too:
|
|
70
|
+
|
|
71
|
+
```bash
|
|
72
|
+
git clone --recurse-submodules https://github.com/Qiskit/sbd-eigensolver-python.git
|
|
73
|
+
# or, if you cloned without --recurse-submodules:
|
|
74
|
+
git submodule update --init --recursive
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
If you need a newer upstream revision (for a recently-landed GPU fix
|
|
78
|
+
etc.), advance the local submodule and rebuild:
|
|
79
|
+
|
|
80
|
+
```bash
|
|
81
|
+
git submodule update --remote vendor/sbd-upstream
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
After the upstream sbd code is cloned, run:
|
|
85
|
+
```
|
|
86
|
+
pip install -e . --no-build-isolation --force-reinstall --no-deps
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
## Environment Variables
|
|
90
|
+
|
|
91
|
+
```bash
|
|
92
|
+
# --- NVIDIA GPU backends (Thrust and OpenMP target-offload): point at NVHPC.
|
|
93
|
+
# Only needed if nvc++ is not already on PATH. Adjust the path.
|
|
94
|
+
# Either the compilers directory or the version root above it works, and
|
|
95
|
+
# NVHPC_ROOT -- which NVIDIA's own modulefile sets to the version root -- is
|
|
96
|
+
# read too, so `module load nvhpc` alone is enough.
|
|
97
|
+
export NVHPC_HOME=/opt/nvidia/hpc_sdk/Linux_x86_64/2025/compilers
|
|
98
|
+
|
|
99
|
+
# --- AMD GPU backend (OpenMP target-offload): point at ROCm LLVM toolchain
|
|
100
|
+
# amdclang++ is found on $ROCM_HOME/bin
|
|
101
|
+
export ROCM_HOME=/opt/rocm
|
|
102
|
+
|
|
103
|
+
# --- OPTIONAL. Only for a host with BOTH GPU toolchains installed, where the
|
|
104
|
+
# auto-answer would be an accident of probe order: nvidia | amd | none
|
|
105
|
+
export SBD_GPU_VENDOR=amd
|
|
106
|
+
|
|
107
|
+
# --- OPTIONAL GPU architecture, spelled per vendor.
|
|
108
|
+
# NVIDIA: unset, nvc++ targets the GPU of the machine this toolchain was
|
|
109
|
+
# installed on. Set it to pin the target, including SEVERAL at once:
|
|
110
|
+
# A100: cc80 H100: cc90 GB200 / B200: cc100
|
|
111
|
+
# ccall-major one target per major generation
|
|
112
|
+
# AMD: unset, the arch is DETECTED with ROCm's `amdgpu-arch`. Set it to pin,
|
|
113
|
+
# or when building on a host with no GPU (where detection cannot work and
|
|
114
|
+
# the build stops asking for it):
|
|
115
|
+
# MI250X: gfx90a MI300X: gfx942 (several: gfx90a,gfx942)
|
|
116
|
+
export SBD_GPU_ARCH=cc80,cc90,cc100 # NVIDIA
|
|
117
|
+
export SBD_GPU_ARCH=gfx90a # AMD
|
|
118
|
+
|
|
119
|
+
# --- optional overrides; each has a working default ---
|
|
120
|
+
# Which backends to build: defaults to CPU always, plus every GPU backend the
|
|
121
|
+
# detected toolchain supports -- Thrust AND OpenMP-offload under nvc++,
|
|
122
|
+
# OpenMP-offload only under amdclang++ (there is no rocThrust path).
|
|
123
|
+
# Set it only to narrow that:
|
|
124
|
+
# cpu CPU only -- skip GPU even if a GPU compiler is present
|
|
125
|
+
# gpu Thrust GPU only, no CPU -- NVIDIA only, errors on AMD
|
|
126
|
+
# gpu_omp_offload OpenMP target-offload GPU only (either vendor)
|
|
127
|
+
export SBD_BUILD_BACKEND=cpu
|
|
128
|
+
|
|
129
|
+
# MPI: defaults to whatever mpi4py is linked against. Set this only
|
|
130
|
+
# for layouts that cannot be inferred.
|
|
131
|
+
# NOTE: Every GPU backend hands MPI device pointers, so use a GPU-aware MPI:
|
|
132
|
+
# CUDA-aware on NVIDIA, ROCm-aware on AMD.
|
|
133
|
+
export MPI_HOME=/path/to/mpi
|
|
134
|
+
|
|
135
|
+
# BLAS: defaults to whatever the linker finds, including a
|
|
136
|
+
# conda-installed OpenBLAS in $CONDA_PREFIX/lib. Set these to select
|
|
137
|
+
# a specific build (e.g. an arch-tuned OpenBLAS)
|
|
138
|
+
export BLAS_LIB_PATH=/path/to/blas/lib
|
|
139
|
+
export BLAS_LIBS=openblas # or mkl_rt
|
|
140
|
+
|
|
141
|
+
# these are read while COMPILING, so set them first, then install
|
|
142
|
+
pip install sbd-eigensolver # from PyPI
|
|
143
|
+
pip install -e . --no-build-isolation --no-deps # from a git checkout
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
## Build Using the Host MPI
|
|
147
|
+
```bash
|
|
148
|
+
# Create a conda env
|
|
149
|
+
conda create -y -n sbd -c conda-forge \
|
|
150
|
+
python=3.13.12 pybind11 numpy setuptools wheel openblas pyscf pip
|
|
151
|
+
# ...plus llvm-openmp on macOS
|
|
152
|
+
|
|
153
|
+
conda activate sbd # always activate first
|
|
154
|
+
|
|
155
|
+
# Install mpi4py against the host MPI
|
|
156
|
+
# For any GPU backend the host MPI must be GPU-aware:
|
|
157
|
+
# CUDA-aware on NVIDIA, ROCm-aware on AMD.
|
|
158
|
+
export MPI_HOME=/path/to/mpi
|
|
159
|
+
MPICC=$MPI_HOME/bin/mpicc python -m pip install --no-binary=mpi4py --no-cache-dir mpi4py
|
|
160
|
+
# NOTE: If no host MPI is available, let conda pick a compatible one with the
|
|
161
|
+
# command below. A default conda-forge MPI is not GPU-aware, which is fine for the
|
|
162
|
+
# CPU backend; for the GPU backends either install mpi4py against a GPU-aware MPI
|
|
163
|
+
# as above, or see the README's Backend Architecture section for the two build-time options that
|
|
164
|
+
# let the Thrust backend run without one.
|
|
165
|
+
# conda install -y -c conda-forge mpi4py
|
|
166
|
+
|
|
167
|
+
# confirm which MPI mpi4py uses -- setup.py builds against exactly this
|
|
168
|
+
python -c "from mpi4py import MPI; print(MPI.Get_library_version())"
|
|
169
|
+
|
|
170
|
+
# only for the SQD examples (examples/tpb/run_sqd_sbd.py and .ipynb)
|
|
171
|
+
pip install "qiskit-addon-sqd>=0.13.1"
|
|
172
|
+
|
|
173
|
+
# install sbd-eigensolver
|
|
174
|
+
pip install sbd-eigensolver
|
|
175
|
+
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
## Verify
|
|
179
|
+
|
|
180
|
+
```bash
|
|
181
|
+
python -c "import sbd; print(sbd.available_backends())"
|
|
182
|
+
# CPU only: ['cpu']
|
|
183
|
+
# NVIDIA, default build: ['cpu', 'gpu', 'gpu-omp']
|
|
184
|
+
# AMD, default build: ['cpu', 'gpu-omp']
|
|
185
|
+
# OMP-offload-only install: ['gpu-omp']
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
On a GPU build, confirm which vendor and architecture the offload backend
|
|
189
|
+
targets — one `'gpu-omp'` device serves both vendors, so the name alone does not
|
|
190
|
+
say:
|
|
191
|
+
|
|
192
|
+
```bash
|
|
193
|
+
python -c "import sbd; print(sbd.get_backend('gpu-omp').__sbd_offload_target__)"
|
|
194
|
+
# amdgcn-amd-amdhsa:gfx90a AMD MI250X
|
|
195
|
+
# nvptx64-nvidia-cuda:cc90 NVIDIA H100
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
The Thrust backend is stamped too (`cuda:cc90`); the CPU backend reports `None`.
|
|
199
|
+
|
|
200
|
+
## See Also
|
|
201
|
+
|
|
202
|
+
- [README](README.md) — what the package is, the API, and the SQD integration
|
|
203
|
+
- [`examples/tpb/README.md`](examples/tpb/README.md) — backend selection at runtime,
|
|
204
|
+
bundled test data and performance notes
|
|
205
|
+
- [Troubleshooting](README.md#troubleshooting) — build and runtime symptoms
|
|
@@ -16,4 +16,5 @@ recursive-include vendor/sbd-upstream/include *.h
|
|
|
16
16
|
include vendor/sbd-upstream/LICENSE.txt
|
|
17
17
|
|
|
18
18
|
# Example scripts and notebook, referenced by the README.
|
|
19
|
-
recursive-include
|
|
19
|
+
recursive-include examples *.py *.ipynb *.md *.json
|
|
20
|
+
include INSTALL.md
|
|
@@ -0,0 +1,397 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: sbd-eigensolver
|
|
3
|
+
Version: 1.7.0
|
|
4
|
+
Summary: Python bindings for Selected Basis Diagonalization (SBD) library
|
|
5
|
+
License-Expression: Apache-2.0
|
|
6
|
+
Project-URL: Homepage, https://github.com/Qiskit/sbd-eigensolver-python
|
|
7
|
+
Project-URL: Documentation, https://github.com/Qiskit/sbd-eigensolver-python
|
|
8
|
+
Project-URL: Repository, https://github.com/Qiskit/sbd-eigensolver-python
|
|
9
|
+
Project-URL: Issues, https://github.com/Qiskit/sbd-eigensolver-python/issues
|
|
10
|
+
Keywords: quantum chemistry,diagonalization,tensor product basis,MPI
|
|
11
|
+
Classifier: Development Status :: 4 - Beta
|
|
12
|
+
Classifier: Intended Audience :: Science/Research
|
|
13
|
+
Classifier: Operating System :: POSIX :: Linux
|
|
14
|
+
Classifier: Operating System :: MacOS :: MacOS X
|
|
15
|
+
Classifier: Topic :: Scientific/Engineering :: Chemistry
|
|
16
|
+
Classifier: Topic :: Scientific/Engineering :: Physics
|
|
17
|
+
Classifier: Programming Language :: Python :: 3
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
21
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
22
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
23
|
+
Classifier: Programming Language :: C++
|
|
24
|
+
Requires-Python: >=3.10
|
|
25
|
+
Description-Content-Type: text/markdown
|
|
26
|
+
License-File: LICENSE.txt
|
|
27
|
+
Requires-Dist: mpi4py>=4.0.0
|
|
28
|
+
Requires-Dist: numpy>=1.26.0
|
|
29
|
+
Provides-Extra: basetest
|
|
30
|
+
Requires-Dist: pytest>=8.0; extra == "basetest"
|
|
31
|
+
Provides-Extra: test
|
|
32
|
+
Requires-Dist: sbd-eigensolver[basetest]; extra == "test"
|
|
33
|
+
Requires-Dist: pytest-mpi>=0.6; extra == "test"
|
|
34
|
+
Requires-Dist: qiskit-addon-sqd>=0.13.1; extra == "test"
|
|
35
|
+
Requires-Dist: pyscf>=2.9; extra == "test"
|
|
36
|
+
Provides-Extra: nbtest
|
|
37
|
+
Requires-Dist: sbd-eigensolver[basetest]; extra == "nbtest"
|
|
38
|
+
Requires-Dist: nbmake>=1.5.0; extra == "nbtest"
|
|
39
|
+
Provides-Extra: docs
|
|
40
|
+
Requires-Dist: sbd-eigensolver[test]; extra == "docs"
|
|
41
|
+
Requires-Dist: qiskit-sphinx-theme~=2.1.0; extra == "docs"
|
|
42
|
+
Requires-Dist: sphinx-copybutton; extra == "docs"
|
|
43
|
+
Requires-Dist: reno>=4.1; extra == "docs"
|
|
44
|
+
Provides-Extra: notebook-dependencies
|
|
45
|
+
Requires-Dist: qiskit-addon-sqd>=0.13.1; extra == "notebook-dependencies"
|
|
46
|
+
Requires-Dist: pyscf>=2.9; extra == "notebook-dependencies"
|
|
47
|
+
Dynamic: license-file
|
|
48
|
+
|
|
49
|
+
# SBD Python Bindings
|
|
50
|
+
|
|
51
|
+
Python bindings for the Selected Basis Diagonalization (SBD) library, with CPU and GPU backends.
|
|
52
|
+
|
|
53
|
+
## Overview
|
|
54
|
+
|
|
55
|
+
SBD (Selected Basis Diagonalization) is a high-performance library for quantum
|
|
56
|
+
chemistry calculations. These bindings expose two of its diagonalization methods on CPU
|
|
57
|
+
and GPU. They differ in the shape of the subspace they span, which is what decides
|
|
58
|
+
which one you want:
|
|
59
|
+
|
|
60
|
+
- **Tensor-Product Basis (TPB)** — the subspace is the Cartesian product of an alpha
|
|
61
|
+
and a beta determinant list, so its dimension is `|adet| × |bdet|`. The mature path,
|
|
62
|
+
and the one the qiskit-addon-sqd integration uses.
|
|
63
|
+
- **General-Determinant Basis (GDB)** — the subspace is the explicit determinant list
|
|
64
|
+
you pass, so it can be an arbitrary *sparse* set rather than a product. Experimental:
|
|
65
|
+
newer, a smaller tested surface, and still evolving as upstream SBD does.
|
|
66
|
+
|
|
67
|
+
If your subspace is a product, prefer TPB — it represents that case with two
|
|
68
|
+
half-determinant lists instead of every product element, and needs no extra
|
|
69
|
+
constraints. Reach for GDB when the subspace is not a product.
|
|
70
|
+
|
|
71
|
+
**Key Features:**
|
|
72
|
+
- **TPB and GDB diagonalization** for quantum chemistry Hamiltonians
|
|
73
|
+
- Three backends, selected per call at runtime via `device=`:
|
|
74
|
+
`'cpu'` (host OpenMP), `'gpu'` (NVHPC Thrust/CUDA, NVIDIA only) and
|
|
75
|
+
`'gpu-omp'` (OpenMP target offload, **NVIDIA or AMD**). All the backends your
|
|
76
|
+
toolchain supports can be built into one install; each is imported only when
|
|
77
|
+
first used. **TPB runs on all three; GDB has Thrust kernels only**, so GDB on a
|
|
78
|
+
GPU is NVIDIA-only and under `'gpu-omp'` it falls back to the host — see
|
|
79
|
+
[`examples/gdb/README.md`](examples/gdb/README.md)
|
|
80
|
+
- MPI parallelization
|
|
81
|
+
- Integration with [qiskit-addon-sqd](https://github.com/Qiskit/qiskit-addon-sqd) for SQD workflows
|
|
82
|
+
|
|
83
|
+
SBD's **Creation/Annihilation operator (CAOP)** method is not supported by this
|
|
84
|
+
wrapper; users who need it should reference and use the C++ CLI apps in the upstream
|
|
85
|
+
submodule (`vendor/sbd-upstream/apps/`).
|
|
86
|
+
|
|
87
|
+
> [!NOTE]
|
|
88
|
+
> This package is newly open-sourced. The Python API follows semantic versioning, but the build configuration and GPU backends have been exercised on a limited set of platforms — please report issues.
|
|
89
|
+
|
|
90
|
+
## Installation
|
|
91
|
+
|
|
92
|
+
The extension modules are compiled on your machine — no wheels are published — so the
|
|
93
|
+
backends you get depend on the toolchain the build finds. For the common CPU case:
|
|
94
|
+
|
|
95
|
+
```bash
|
|
96
|
+
conda create -y -n sbd -c conda-forge \
|
|
97
|
+
python=3.13.12 pybind11 numpy setuptools wheel openblas pyscf pip mpi4py
|
|
98
|
+
# ...plus llvm-openmp on macOS
|
|
99
|
+
conda activate sbd
|
|
100
|
+
|
|
101
|
+
pip install sbd-eigensolver
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
Then check what was built:
|
|
105
|
+
|
|
106
|
+
```bash
|
|
107
|
+
python -c "import sbd; print(sbd.available_backends())"
|
|
108
|
+
# CPU only: ['cpu']
|
|
109
|
+
# NVIDIA, default build: ['cpu', 'gpu', 'gpu-omp']
|
|
110
|
+
# AMD, default build: ['cpu', 'gpu-omp']
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
**See [INSTALL.md](INSTALL.md)** for the rest: prerequisites per platform, installing
|
|
114
|
+
from a git checkout with the submodule, every environment variable the build reads
|
|
115
|
+
(GPU toolchains, architectures, MPI and BLAS selection, narrowing which backends get
|
|
116
|
+
built), building against an existing host MPI, and fuller verification.
|
|
117
|
+
|
|
118
|
+
## Examples
|
|
119
|
+
|
|
120
|
+
Located in `examples/`, organized by basis type since the solvers take different
|
|
121
|
+
subspaces and decompose over MPI differently. Each folder's README is the authoritative
|
|
122
|
+
guide to what it contains, how to run it, and the backend and threading settings that
|
|
123
|
+
matter for it.
|
|
124
|
+
|
|
125
|
+
- [`examples/tpb/`](examples/tpb/README.md) — tensor-product basis: standalone TPB
|
|
126
|
+
diagonalization, the SQD loops, and the subspace-enlargement driver.
|
|
127
|
+
- [`examples/gdb/`](examples/gdb/README.md) — general determinant basis: standalone
|
|
128
|
+
GDB diagonalization over an explicit determinant list, and an iterative
|
|
129
|
+
heatbath-expansion driver.
|
|
130
|
+
|
|
131
|
+
## Integration with qiskit-addon-sqd
|
|
132
|
+
|
|
133
|
+
SBD can serve as the eigensolver backend for qiskit-addon-sqd's SQD workflow.
|
|
134
|
+
|
|
135
|
+
> [!NOTE]
|
|
136
|
+
> This integration is **TPB-only**, and not merely for want of plumbing.
|
|
137
|
+
> `solve_sci`/`solve_sci_batch` call `tpb_diag`, and the addon's interface describes a
|
|
138
|
+
> product subspace by construction: `ci_strings` is a `(strings_a, strings_b)` pair and
|
|
139
|
+
> `SCIState.amplitudes` is an `|a| × |b|` matrix. A sparse determinant list cannot be
|
|
140
|
+
> expressed that way without padding back up to the full product, which discards the
|
|
141
|
+
> reason to use GDB. For GDB, call `gdb_diag` directly or use the drivers in
|
|
142
|
+
> [`examples/gdb/`](examples/gdb/README.md).
|
|
143
|
+
|
|
144
|
+
**Note:** Requires [qiskit-addon-sqd](https://github.com/Qiskit/qiskit-addon-sqd) with distributed (SPMD) support — `diagonalize_fermionic_hamiltonian` calling `sci_solver` on every MPI rank. This is available in `qiskit-addon-sqd` version `0.13.1` or higher. SBD-selected carryover and subspace policies need `0.14.0` or higher.
|
|
145
|
+
|
|
146
|
+
### Plain SQD
|
|
147
|
+
|
|
148
|
+
```python
|
|
149
|
+
from functools import partial
|
|
150
|
+
from sbd.sbd_solver import solve_sci_batch
|
|
151
|
+
from sbd.device_config import DeviceConfig
|
|
152
|
+
from qiskit_addon_sqd.fermion import diagonalize_fermionic_hamiltonian
|
|
153
|
+
|
|
154
|
+
# No sbd.init() and no explicit mpi_comm needed — solve_sci_batch
|
|
155
|
+
# auto-initializes the SBD backend on first call and falls back to
|
|
156
|
+
# MPI.COMM_WORLD when mpi_comm is not provided.
|
|
157
|
+
sbd_solver = partial(
|
|
158
|
+
solve_sci_batch,
|
|
159
|
+
sbd_config={"method": 0, "eps": 1e-5, "max_it": 10, "max_nb": 10},
|
|
160
|
+
device_config=DeviceConfig.gpu(), # or .cpu(), .gpu_omp()
|
|
161
|
+
fcidump_path="data/h2o/fcidump.txt", # optional: reuse one FCIDUMP across batches
|
|
162
|
+
)
|
|
163
|
+
|
|
164
|
+
result = diagonalize_fermionic_hamiltonian(
|
|
165
|
+
hcore, eri, bit_array,
|
|
166
|
+
sci_solver=sbd_solver, # SBD plugs in here
|
|
167
|
+
norb=norb, nelec=nelec,
|
|
168
|
+
samples_per_batch=3000, num_batches=3, max_iterations=5,
|
|
169
|
+
symmetrize_spin=True,
|
|
170
|
+
)
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
See [SQD Parameters](examples/tpb/README.md#sqd-parameters) for how each
|
|
174
|
+
parameter feeds the loop, and
|
|
175
|
+
[examples/tpb/run_sqd_sbd.py](examples/tpb/run_sqd_sbd.py) for a
|
|
176
|
+
complete example.
|
|
177
|
+
|
|
178
|
+
qiskit-addon-sqd is the orchestrator in that recipe: it owns the loop
|
|
179
|
+
(sampling, configuration recovery, subsampling), and SBD is plugged in as the
|
|
180
|
+
per-batch eigensolver (`sci_solver=sbd_solver` above). By default SBD has no say
|
|
181
|
+
in how the subspace grows between iterations: SQD chooses the carryover from the
|
|
182
|
+
amplitudes SBD returns.
|
|
183
|
+
|
|
184
|
+
With `qiskit-addon-sqd >= 0.14.0`, SBD can choose the carryover itself instead:
|
|
185
|
+
set `"carryover_type"` in `sbd_config` and SQD takes SBD's selection as given. With
|
|
186
|
+
type 1, the amplitudes never leave SBD, which saves a full wavefunction write and
|
|
187
|
+
read every iteration. See
|
|
188
|
+
[SBD-selected carryover](examples/tpb/README.md#sbd-selected-carryover) for what
|
|
189
|
+
each type does and costs, and the section after it for running the loop with a
|
|
190
|
+
different subspace policy such as Trim SQD.
|
|
191
|
+
|
|
192
|
+
### SQD with subspace enlargement
|
|
193
|
+
|
|
194
|
+
[`run_sqd_enlarge_subspace_sbd.py`](examples/tpb/run_sqd_enlarge_subspace_sbd.py)
|
|
195
|
+
builds on the same recipe, but grows its own subspace between rounds: after
|
|
196
|
+
each solve, it expands the dominant determinant pairs via qiskit-addon-sqd's
|
|
197
|
+
own `enlarge_batch_from_transitions` (same-spin single excitations, both
|
|
198
|
+
alpha and beta) and feeds the result forward as the next round's
|
|
199
|
+
`include_configurations`. Concretely, it calls
|
|
200
|
+
`diagonalize_fermionic_hamiltonian` with `max_iterations=1` itself, in its
|
|
201
|
+
own outer Python loop, rather than delegating the whole multi-iteration loop
|
|
202
|
+
to one call — that is what makes injecting a step between rounds possible.
|
|
203
|
+
|
|
204
|
+
On the bundled H2O pool ([`count_dict_h2o.json`](examples/tpb/count_dict_h2o.json),
|
|
205
|
+
275 bitstrings), plain SQD reaches ≈ -76.236 Ha and stops there; this driver
|
|
206
|
+
keeps going past that fixed pool on its own and converges to
|
|
207
|
+
**-76.2421767512 Ha**.
|
|
208
|
+
|
|
209
|
+
## Backend Architecture
|
|
210
|
+
|
|
211
|
+
- **The Thrust build assumes a GPU-aware MPI** and hands MPI device pointers directly. Two upstream escape hatches exist for an MPI that cannot address device memory. Both are **off by default**, and both are **compile-time** — set them before installing `sbd-eigensolver`, rebuild to change them, and they do nothing if set at run time:
|
|
212
|
+
```
|
|
213
|
+
SBD_NON_CUDA_AWARE_MPI=1 stage every device buffer through host memory
|
|
214
|
+
SBD_THRUST_SAFE_MPI_ALLREDUCE=1 stage only the allreduce (a subset of the above)
|
|
215
|
+
```
|
|
216
|
+
Both make the Thrust path stage device buffers through host memory instead of handing MPI device pointers, so they add copies whose cost grows with how much data crosses MPI. Treat them as a compatibility fallback rather than a tuning knob: reach for them when a GPU backend crashes inside the MPI itself rather than in SBD.
|
|
217
|
+
- GPU device assignment: `gpu_id = mpi_rank % num_gpus` (set per `tpb_diag()` call in `bindings.cpp`); same logic for both Thrust and OMP-offload paths.
|
|
218
|
+
- **`'gpu-omp'` is vendor-neutral by design:** one module, one device string, for both NVIDIA and AMD. It is the same source with the same macros and only the compiler differs, and since no wheels are published — every install compiles on the target machine — an install serves one GPU vendor. `__sbd_offload_target__` records which one. Aliases (`gpu-amd-omp`, `gpu-rocm-omp`, `rocm`, `gpu-nvidia-omp`, …) resolve to it so a vendor-flavoured guess lands correctly.
|
|
219
|
+
- Verify what GPU architecture is supported in the binary:
|
|
220
|
+
```
|
|
221
|
+
NVIDIA: cuobjdump --list-elf <the built _core_gpu_thrust*.so>
|
|
222
|
+
AMD: llvm-objdump --offloading <the built _core_gpu_omp_offload*.so>
|
|
223
|
+
```
|
|
224
|
+
Or just ask the module what it was built for:
|
|
225
|
+
```
|
|
226
|
+
python -c "import sbd; \
|
|
227
|
+
print(sbd.get_backend('gpu-omp').__sbd_offload_target__)"
|
|
228
|
+
-> amdgcn-amd-amdhsa:gfx90a
|
|
229
|
+
```
|
|
230
|
+
|
|
231
|
+
## API Reference
|
|
232
|
+
|
|
233
|
+
### Initialization
|
|
234
|
+
|
|
235
|
+
| Function | Description |
|
|
236
|
+
|----------|-------------|
|
|
237
|
+
| `sbd.init(device, comm_backend)` | **Optional.** Initialize MPI, set default device (`'cpu'`, `'gpu'`, `'gpu-omp'`, `'auto'`). Auto-called on first use with defaults. |
|
|
238
|
+
| `sbd.finalize()` | Sync GPU, reset state. Does not call `MPI_Finalize` |
|
|
239
|
+
| `sbd.is_initialized()` | Check init status |
|
|
240
|
+
|
|
241
|
+
### Backend Access
|
|
242
|
+
|
|
243
|
+
| Function | Description |
|
|
244
|
+
|----------|-------------|
|
|
245
|
+
| `sbd.get_backend(device=None)` | Get the pybind11 backend module for the named device. `None` = default device. |
|
|
246
|
+
| `sbd.available_backends()` | List of compiled backends, e.g. `['cpu']`, `['cpu', 'gpu']`, `['gpu-omp']` |
|
|
247
|
+
|
|
248
|
+
### Query
|
|
249
|
+
|
|
250
|
+
| Function | Description |
|
|
251
|
+
|----------|-------------|
|
|
252
|
+
| `sbd.get_device()` | Default device name |
|
|
253
|
+
| `sbd.get_rank()` | MPI rank |
|
|
254
|
+
| `sbd.get_world_size()` | MPI world size |
|
|
255
|
+
| `sbd.get_comm()` | MPI communicator |
|
|
256
|
+
| `sbd.barrier()` | MPI barrier |
|
|
257
|
+
|
|
258
|
+
### Configuration
|
|
259
|
+
|
|
260
|
+
```python
|
|
261
|
+
config = sbd.TPB_SBD()
|
|
262
|
+
```
|
|
263
|
+
|
|
264
|
+
| Attribute | Default | Description |
|
|
265
|
+
|-----------|---------|-------------|
|
|
266
|
+
| `method` | 0 | 0=Davidson, 1=Davidson+Ham, 2=Lanczos, 3=Lanczos+Ham |
|
|
267
|
+
| `max_it` | 1 | Max iterations |
|
|
268
|
+
| `eps` | 1e-4 | Convergence tolerance |
|
|
269
|
+
| `max_nb` | 10 | Max basis vectors |
|
|
270
|
+
| `do_rdm` | 0 | 0=density only, 1=full RDM |
|
|
271
|
+
| `bit_length` | 20 | Bit length for determinants |
|
|
272
|
+
| `adet_comm_size` | 1 | Alpha determinant communicator size |
|
|
273
|
+
| `bdet_comm_size` | 1 | Beta determinant communicator size |
|
|
274
|
+
| `task_comm_size` | 1 | Task communicator size |
|
|
275
|
+
|
|
276
|
+
Total MPI ranks = `task_comm_size × adet_comm_size × bdet_comm_size`.
|
|
277
|
+
|
|
278
|
+
```python
|
|
279
|
+
config = sbd.GDB_SBD()
|
|
280
|
+
```
|
|
281
|
+
|
|
282
|
+
Shares `max_it`, `max_nb`, `eps`, `max_time`, `init`, `do_rdm`, `carryover_type`,
|
|
283
|
+
`ratio`, `threshold` and `bit_length` with `TPB_SBD`, and replaces the determinant
|
|
284
|
+
communicators with a single basis communicator:
|
|
285
|
+
|
|
286
|
+
| Attribute | Default | Description |
|
|
287
|
+
|-----------|---------|-------------|
|
|
288
|
+
| `method` | 0 | 0=Davidson, 1=Davidson+Ham. GDB has no Lanczos, so TPB's 2 and 3 are rejected |
|
|
289
|
+
| `b_comm_size` | 1 | Basis communicator size — how many shards the determinant list is split into |
|
|
290
|
+
| `t_comm_size` | 1 | Task communicator size — must not exceed `b_comm_size` |
|
|
291
|
+
| `seed` | 1729 | Seed for the initial vector |
|
|
292
|
+
| `heatbath_cutoff` | 1e-4 | Heatbath expansion cutoff |
|
|
293
|
+
| `heatbath_truncation` | 0.0 | Weight truncation applied before heatbath expansion |
|
|
294
|
+
| `heatbath_batch_size` | 200000000 | Heatbath expansion batch size |
|
|
295
|
+
|
|
296
|
+
Total MPI ranks = `t_comm_size × b_comm_size × helper`, where the helper dimension is
|
|
297
|
+
the derived quotient and is not settable. With `b_comm_size > 1` each rank passes its
|
|
298
|
+
own shard of the determinant list rather than the whole list.
|
|
299
|
+
|
|
300
|
+
See [`examples/gdb/README.md`](examples/gdb/README.md) for the decomposition, the shard
|
|
301
|
+
contract, the six determinant-placement schemes, and why the helper dimension must be 1
|
|
302
|
+
on the Thrust backend.
|
|
303
|
+
|
|
304
|
+
### Diagonalization
|
|
305
|
+
|
|
306
|
+
```python
|
|
307
|
+
# From files
|
|
308
|
+
results = sbd.tpb_diag_from_files(fcidumpfile, adetfile, sbd_data,
|
|
309
|
+
loadname="", savename="", device=None)
|
|
310
|
+
|
|
311
|
+
# From data structures
|
|
312
|
+
results = sbd.tpb_diag(fcidump, adet, bdet, sbd_data,
|
|
313
|
+
loadname="", savename="", device=None)
|
|
314
|
+
```
|
|
315
|
+
|
|
316
|
+
**Returns:** `dict` with keys `energy`, `density`, `carryover_adet`, `carryover_bdet`, `one_p_rdm`, `two_p_rdm`.
|
|
317
|
+
|
|
318
|
+
```python
|
|
319
|
+
# GDB: over an explicit list of full determinants rather than a product space
|
|
320
|
+
results = sbd.gdb_diag(fcidump, det, sbd_data,
|
|
321
|
+
loadname="", savename="", device=None,
|
|
322
|
+
determinant_distribution="", determinant_grid_a=0,
|
|
323
|
+
determinant_grid_b=0)
|
|
324
|
+
```
|
|
325
|
+
|
|
326
|
+
**Returns:** `dict` with keys `energy`, `density`, `carryover_det`, `one_p_rdm`,
|
|
327
|
+
`two_p_rdm`, `local_dim`, `global_dim` and `determinant_distribution`; the last three
|
|
328
|
+
are this rank's determinant count, the whole basis's, and the placement scheme that
|
|
329
|
+
ran. Each determinant is a `2 * norb`-bit configuration in which bit
|
|
330
|
+
`2 * i` is the occupation of spin-alpha orbital `i` and bit `2 * i + 1` that of
|
|
331
|
+
spin-beta orbital `i`. The determinants must be distinct; they are sorted into
|
|
332
|
+
SBD's canonical order internally, which `sort_bitarray` reproduces.
|
|
333
|
+
|
|
334
|
+
`det` may be a single `(ndets, words)` array or **this rank's shard of one**:
|
|
335
|
+
`sbd_data.b_comm_size` decides which. At `1` every rank passes the whole basis; above
|
|
336
|
+
`1` every rank passes its own shard, the union over b_comm positions being the basis.
|
|
337
|
+
Sharded input must be globally sorted and disjoint; that and the rank-layout constraints
|
|
338
|
+
are checked, and raise rather than silently diagonalizing the wrong subspace.
|
|
339
|
+
`determinant_distribution` chooses how determinants are placed across ranks (default
|
|
340
|
+
`equal-bra-a`), and the two grid arguments size the grid for the grid-cyclic schemes.
|
|
341
|
+
[`examples/gdb/README.md`](examples/gdb/README.md) has the shard contract, the
|
|
342
|
+
placement schemes, and which returned values are replicated versus sharded.
|
|
343
|
+
|
|
344
|
+
`gdb_diag` returns no wavefunction amplitudes — `gdb::diag` has no in-memory output for
|
|
345
|
+
them — and for most uses none are needed: the energy, density and RDMs come back
|
|
346
|
+
directly, and an iterative heatbath run gets its next subspace from `carryover_det`. If
|
|
347
|
+
you do want the amplitudes, `savename` writes them to disk; the file layout is in
|
|
348
|
+
[`examples/gdb/README.md`](examples/gdb/README.md).
|
|
349
|
+
|
|
350
|
+
The optional `device` parameter overrides the default set by `init()`.
|
|
351
|
+
|
|
352
|
+
## Troubleshooting
|
|
353
|
+
|
|
354
|
+
**GPU backends silently build as host code:** a conda compiler package
|
|
355
|
+
(`cxx-compiler`, `gxx_linux-64`, `clangxx_osx-*`) sets `CC`/`CXX` on activation and
|
|
356
|
+
the build respects a caller-set compiler, so `nvc++`/`amdclang++` never run. Unset
|
|
357
|
+
`CC`/`CXX`, or keep conda compilers out of the build env.
|
|
358
|
+
|
|
359
|
+
**GPU not building:** On NVIDIA check `which nvc++` and set `NVHPC_HOME` (or rely on
|
|
360
|
+
`NVHPC_ROOT` from `module load nvhpc`; either the compilers directory or the version
|
|
361
|
+
root works). On AMD
|
|
362
|
+
check `which amdclang++` and set `ROCM_HOME`. The build prints which toolchain it
|
|
363
|
+
picked (`Found amdclang++ in PATH: …` / `Found NVIDIA HPC SDK at: …`) and, for
|
|
364
|
+
the offload backend, the resolved architecture; on a host with both toolchains
|
|
365
|
+
force the choice with `SBD_GPU_VENDOR=amd|nvidia`.
|
|
366
|
+
|
|
367
|
+
**`MPI_HOME=... is not the MPI that mpi4py is linked against`:** the build stops here
|
|
368
|
+
deliberately rather than producing extensions that link one MPI while `mpi4py` loads
|
|
369
|
+
another — a mismatch that surfaces later as undefined symbols or a hang inside the first
|
|
370
|
+
collective. `MPI_HOME` is only for layouts the build cannot infer; unset it to use
|
|
371
|
+
`mpi4py`'s own MPI, or reinstall `mpi4py` against the MPI you want
|
|
372
|
+
(`pip install --no-binary :all: mpi4py`). To see which MPI that is:
|
|
373
|
+
`python -c "from mpi4py import MPI; print(MPI.Get_library_version())"`.
|
|
374
|
+
|
|
375
|
+
**`OMP: Error #15: Initializing libomp.dylib, but found libomp.dylib already
|
|
376
|
+
initialized` on macOS:** two copies of the same LLVM OpenMP runtime in one process. It
|
|
377
|
+
aborts at the first parallel region, so the import succeeds and the first
|
|
378
|
+
diagonalization dies. Usually it means the environment provides `libomp` twice — for
|
|
379
|
+
example Homebrew `llvm` *and* Homebrew `libomp`, or a Homebrew copy alongside the conda
|
|
380
|
+
env's. Build against one only; the conda env's is the one loaded at import time, so
|
|
381
|
+
prefer it. Tracked as
|
|
382
|
+
[issue #27](https://github.com/Qiskit/sbd-eigensolver-python/issues/27).
|
|
383
|
+
|
|
384
|
+
**OMP-offload runs all land on GPU 0 in multi-GPU jobs:** symptom — every MPI rank shows large memory only on GPU 0 in `nvidia-smi` (or `rocm-smi`). The bindings call `omp_set_default_device(mpi_rank % n_dev)`, but `omp_get_num_devices()` can return 0 in some dlopen scenarios. The bindings fall back to counting the entries in the vendor's device-visibility variable — `CUDA_VISIBLE_DEVICES` on NVIDIA, `ROCR_VISIBLE_DEVICES` or `HIP_VISIBLE_DEVICES` on AMD — so make sure the relevant one is exported and lists all your GPUs (e.g. `0,1,2,3`). Slurm/`srun --gres=gpu:N` and OpenMPI's default binding policy already do this; if you've custom-restricted it to a single GPU per rank, set it manually before launch. Note the index is the **global** MPI rank, not a node-local one, so the assignment is even only when the launcher places ranks on nodes in contiguous blocks — round-robin placement leaves each node using a strided subset of its GPUs.
|
|
385
|
+
|
|
386
|
+
**Ranks die with `Bus error` or `SIGSEGV` inside the MPI's own copy path** (`MPIR_Localcopy`, `ucp_worker_progress`, ...) **on a GPU backend:** the MPI is not GPU-aware and was handed a device pointer. Rebuild UCX `--with-cuda` / `--with-rocm`, and confirm with `ucx_info -d | grep -i 'Transport: cuda'` (or `rocm`). Two things mislead here. A partly GPU-aware stack fails in only one place: an MPICH with GPU support *disabled* over a CUDA-aware UCX ran OMP-offload fine and crashed only in Thrust, because the inter-rank path went through UCX while the local-copy path did not. And on AMD a non-ROCm-aware MPI does not crash at all — ROCm maps device memory into the process address space, so the host copy succeeds and merely stages everything through the host aperture (measured on MI250X, XNACK off, 8 ranks) — so a working AMD run is not evidence that the MPI is ROCm-aware.
|
|
387
|
+
|
|
388
|
+
**GDB on more than one GPU refuses to start, naming the helper dimension:** GDB's Thrust
|
|
389
|
+
kernels never implemented that dimension, and it is the quotient
|
|
390
|
+
`ranks / (t_comm_size × b_comm_size)` — so any rank you do not assign to `t` or `b` lands
|
|
391
|
+
there. Give every rank to the basis: `-np 4` with `b_comm_size = 4` leaves a helper
|
|
392
|
+
dimension of 1. Leaving `b_comm_size` at 1 puts *all* ranks in the helper dimension,
|
|
393
|
+
which is why multi-GPU GDB requires a split basis. `gdb_diag` checks this before doing
|
|
394
|
+
any work rather than letting the kernel throw mid-launch. The CPU backend has no such
|
|
395
|
+
restriction, and TPB is unaffected.
|
|
396
|
+
|
|
397
|
+
**Repository:** https://github.com/Qiskit/sbd-eigensolver-python
|