sbd-eigensolver 1.7.0__tar.gz → 1.7.1__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/sbd_eigensolver.egg-info → sbd_eigensolver-1.7.1}/PKG-INFO +35 -1
- {sbd_eigensolver-1.7.0 → sbd_eigensolver-1.7.1}/README.md +34 -0
- {sbd_eigensolver-1.7.0 → sbd_eigensolver-1.7.1}/pyproject.toml +1 -1
- {sbd_eigensolver-1.7.0 → sbd_eigensolver-1.7.1}/python/__init__.py +150 -20
- {sbd_eigensolver-1.7.0 → sbd_eigensolver-1.7.1}/python/bindings.cpp +6 -1
- {sbd_eigensolver-1.7.0 → sbd_eigensolver-1.7.1}/python/device_config.py +13 -23
- {sbd_eigensolver-1.7.0 → sbd_eigensolver-1.7.1}/python/sbd_solver.py +46 -14
- {sbd_eigensolver-1.7.0 → sbd_eigensolver-1.7.1/sbd_eigensolver.egg-info}/PKG-INFO +35 -1
- {sbd_eigensolver-1.7.0 → sbd_eigensolver-1.7.1}/sbd_eigensolver.egg-info/SOURCES.txt +1 -0
- {sbd_eigensolver-1.7.0 → sbd_eigensolver-1.7.1}/setup.py +23 -8
- sbd_eigensolver-1.7.1/test/test_sci_state.py +126 -0
- {sbd_eigensolver-1.7.0 → sbd_eigensolver-1.7.1}/INSTALL.md +0 -0
- {sbd_eigensolver-1.7.0 → sbd_eigensolver-1.7.1}/LICENSE.txt +0 -0
- {sbd_eigensolver-1.7.0 → sbd_eigensolver-1.7.1}/MANIFEST.in +0 -0
- {sbd_eigensolver-1.7.0 → sbd_eigensolver-1.7.1}/examples/gdb/README.md +0 -0
- {sbd_eigensolver-1.7.0 → sbd_eigensolver-1.7.1}/examples/gdb/run_gdb_diag.py +0 -0
- {sbd_eigensolver-1.7.0 → sbd_eigensolver-1.7.1}/examples/gdb/run_gdb_heatbath.py +0 -0
- {sbd_eigensolver-1.7.0 → sbd_eigensolver-1.7.1}/examples/tpb/README.md +0 -0
- {sbd_eigensolver-1.7.0 → sbd_eigensolver-1.7.1}/examples/tpb/count_dict_h2o.json +0 -0
- {sbd_eigensolver-1.7.0 → sbd_eigensolver-1.7.1}/examples/tpb/run_sbd_diag.py +0 -0
- {sbd_eigensolver-1.7.0 → sbd_eigensolver-1.7.1}/examples/tpb/run_sqd_enlarge_subspace_sbd.py +0 -0
- {sbd_eigensolver-1.7.0 → sbd_eigensolver-1.7.1}/examples/tpb/run_sqd_sbd.ipynb +0 -0
- {sbd_eigensolver-1.7.0 → sbd_eigensolver-1.7.1}/examples/tpb/run_sqd_sbd.py +0 -0
- {sbd_eigensolver-1.7.0 → sbd_eigensolver-1.7.1}/python/sbd_nvhpc_compat.h +0 -0
- {sbd_eigensolver-1.7.0 → sbd_eigensolver-1.7.1}/sbd_eigensolver.egg-info/dependency_links.txt +0 -0
- {sbd_eigensolver-1.7.0 → sbd_eigensolver-1.7.1}/sbd_eigensolver.egg-info/not-zip-safe +0 -0
- {sbd_eigensolver-1.7.0 → sbd_eigensolver-1.7.1}/sbd_eigensolver.egg-info/requires.txt +0 -0
- {sbd_eigensolver-1.7.0 → sbd_eigensolver-1.7.1}/sbd_eigensolver.egg-info/top_level.txt +0 -0
- {sbd_eigensolver-1.7.0 → sbd_eigensolver-1.7.1}/setup.cfg +0 -0
- {sbd_eigensolver-1.7.0 → sbd_eigensolver-1.7.1}/test/test_gdb_drivers.py +0 -0
- {sbd_eigensolver-1.7.0 → sbd_eigensolver-1.7.1}/test/test_gdb_equivalence.py +0 -0
- {sbd_eigensolver-1.7.0 → sbd_eigensolver-1.7.1}/test/test_reference_energies.py +0 -0
- {sbd_eigensolver-1.7.0 → sbd_eigensolver-1.7.1}/test/test_sqd_integration.py +0 -0
- {sbd_eigensolver-1.7.0 → sbd_eigensolver-1.7.1}/vendor/sbd-upstream/LICENSE.txt +0 -0
- {sbd_eigensolver-1.7.0 → sbd_eigensolver-1.7.1}/vendor/sbd-upstream/include/sbd/caop/basic/arithmetic.h +0 -0
- {sbd_eigensolver-1.7.0 → sbd_eigensolver-1.7.1}/vendor/sbd-upstream/include/sbd/caop/basic/basis.h +0 -0
- {sbd_eigensolver-1.7.0 → sbd_eigensolver-1.7.1}/vendor/sbd-upstream/include/sbd/caop/basic/carryover.h +0 -0
- {sbd_eigensolver-1.7.0 → sbd_eigensolver-1.7.1}/vendor/sbd-upstream/include/sbd/caop/basic/davidson.h +0 -0
- {sbd_eigensolver-1.7.0 → sbd_eigensolver-1.7.1}/vendor/sbd-upstream/include/sbd/caop/basic/expansion.h +0 -0
- {sbd_eigensolver-1.7.0 → sbd_eigensolver-1.7.1}/vendor/sbd-upstream/include/sbd/caop/basic/generalop.h +0 -0
- {sbd_eigensolver-1.7.0 → sbd_eigensolver-1.7.1}/vendor/sbd-upstream/include/sbd/caop/basic/generalop_flatdata.h +0 -0
- {sbd_eigensolver-1.7.0 → sbd_eigensolver-1.7.1}/vendor/sbd-upstream/include/sbd/caop/basic/helper.h +0 -0
- {sbd_eigensolver-1.7.0 → sbd_eigensolver-1.7.1}/vendor/sbd-upstream/include/sbd/caop/basic/inc_all.h +0 -0
- {sbd_eigensolver-1.7.0 → sbd_eigensolver-1.7.1}/vendor/sbd-upstream/include/sbd/caop/basic/lanczos.h +0 -0
- {sbd_eigensolver-1.7.0 → sbd_eigensolver-1.7.1}/vendor/sbd-upstream/include/sbd/caop/basic/loadmodel.h +0 -0
- {sbd_eigensolver-1.7.0 → sbd_eigensolver-1.7.1}/vendor/sbd-upstream/include/sbd/caop/basic/mkham.h +0 -0
- {sbd_eigensolver-1.7.0 → sbd_eigensolver-1.7.1}/vendor/sbd-upstream/include/sbd/caop/basic/mult.h +0 -0
- {sbd_eigensolver-1.7.0 → sbd_eigensolver-1.7.1}/vendor/sbd-upstream/include/sbd/caop/basic/mult_thrust.h +0 -0
- {sbd_eigensolver-1.7.0 → sbd_eigensolver-1.7.1}/vendor/sbd-upstream/include/sbd/caop/basic/restart.h +0 -0
- {sbd_eigensolver-1.7.0 → sbd_eigensolver-1.7.1}/vendor/sbd-upstream/include/sbd/caop/basic/sbdiag.h +0 -0
- {sbd_eigensolver-1.7.0 → sbd_eigensolver-1.7.1}/vendor/sbd-upstream/include/sbd/caop/inc_all.h +0 -0
- {sbd_eigensolver-1.7.0 → sbd_eigensolver-1.7.1}/vendor/sbd-upstream/include/sbd/chemistry/basic/correlation.h +0 -0
- {sbd_eigensolver-1.7.0 → sbd_eigensolver-1.7.1}/vendor/sbd-upstream/include/sbd/chemistry/basic/correlation_thrust.h +0 -0
- {sbd_eigensolver-1.7.0 → sbd_eigensolver-1.7.1}/vendor/sbd-upstream/include/sbd/chemistry/basic/davidson_thrust.h +0 -0
- {sbd_eigensolver-1.7.0 → sbd_eigensolver-1.7.1}/vendor/sbd-upstream/include/sbd/chemistry/basic/determinants.h +0 -0
- {sbd_eigensolver-1.7.0 → sbd_eigensolver-1.7.1}/vendor/sbd-upstream/include/sbd/chemistry/basic/determinants_thrust.h +0 -0
- {sbd_eigensolver-1.7.0 → sbd_eigensolver-1.7.1}/vendor/sbd-upstream/include/sbd/chemistry/basic/excitation.h +0 -0
- {sbd_eigensolver-1.7.0 → sbd_eigensolver-1.7.1}/vendor/sbd-upstream/include/sbd/chemistry/basic/helpers.h +0 -0
- {sbd_eigensolver-1.7.0 → sbd_eigensolver-1.7.1}/vendor/sbd-upstream/include/sbd/chemistry/basic/inc_all.h +0 -0
- {sbd_eigensolver-1.7.0 → sbd_eigensolver-1.7.1}/vendor/sbd-upstream/include/sbd/chemistry/basic/integrals.h +0 -0
- {sbd_eigensolver-1.7.0 → sbd_eigensolver-1.7.1}/vendor/sbd-upstream/include/sbd/chemistry/basic/integrals_thrust.h +0 -0
- {sbd_eigensolver-1.7.0 → sbd_eigensolver-1.7.1}/vendor/sbd-upstream/include/sbd/chemistry/basic/lanczos_thrust.h +0 -0
- {sbd_eigensolver-1.7.0 → sbd_eigensolver-1.7.1}/vendor/sbd-upstream/include/sbd/chemistry/basic/makedeterminants.h +0 -0
- {sbd_eigensolver-1.7.0 → sbd_eigensolver-1.7.1}/vendor/sbd-upstream/include/sbd/chemistry/basic/makeintegrals.h +0 -0
- {sbd_eigensolver-1.7.0 → sbd_eigensolver-1.7.1}/vendor/sbd-upstream/include/sbd/chemistry/basic/mult.h +0 -0
- {sbd_eigensolver-1.7.0 → sbd_eigensolver-1.7.1}/vendor/sbd-upstream/include/sbd/chemistry/basic/omp_offload.h +0 -0
- {sbd_eigensolver-1.7.0 → sbd_eigensolver-1.7.1}/vendor/sbd-upstream/include/sbd/chemistry/basic/qcham.h +0 -0
- {sbd_eigensolver-1.7.0 → sbd_eigensolver-1.7.1}/vendor/sbd-upstream/include/sbd/chemistry/gdb/carryover.h +0 -0
- {sbd_eigensolver-1.7.0 → sbd_eigensolver-1.7.1}/vendor/sbd-upstream/include/sbd/chemistry/gdb/correlation.h +0 -0
- {sbd_eigensolver-1.7.0 → sbd_eigensolver-1.7.1}/vendor/sbd-upstream/include/sbd/chemistry/gdb/correlation_thrust.h +0 -0
- {sbd_eigensolver-1.7.0 → sbd_eigensolver-1.7.1}/vendor/sbd-upstream/include/sbd/chemistry/gdb/davidson.h +0 -0
- {sbd_eigensolver-1.7.0 → sbd_eigensolver-1.7.1}/vendor/sbd-upstream/include/sbd/chemistry/gdb/davidson_thrust.h +0 -0
- {sbd_eigensolver-1.7.0 → sbd_eigensolver-1.7.1}/vendor/sbd-upstream/include/sbd/chemistry/gdb/exact_external_observable.h +0 -0
- {sbd_eigensolver-1.7.0 → sbd_eigensolver-1.7.1}/vendor/sbd-upstream/include/sbd/chemistry/gdb/expansion.h +0 -0
- {sbd_eigensolver-1.7.0 → sbd_eigensolver-1.7.1}/vendor/sbd-upstream/include/sbd/chemistry/gdb/grid_distribution.h +0 -0
- {sbd_eigensolver-1.7.0 → sbd_eigensolver-1.7.1}/vendor/sbd-upstream/include/sbd/chemistry/gdb/hash_owned_external_observable.h +0 -0
- {sbd_eigensolver-1.7.0 → sbd_eigensolver-1.7.1}/vendor/sbd-upstream/include/sbd/chemistry/gdb/heatbath_lookup.h +0 -0
- {sbd_eigensolver-1.7.0 → sbd_eigensolver-1.7.1}/vendor/sbd-upstream/include/sbd/chemistry/gdb/helper.h +0 -0
- {sbd_eigensolver-1.7.0 → sbd_eigensolver-1.7.1}/vendor/sbd-upstream/include/sbd/chemistry/gdb/helper_thrust.h +0 -0
- {sbd_eigensolver-1.7.0 → sbd_eigensolver-1.7.1}/vendor/sbd-upstream/include/sbd/chemistry/gdb/inc_all.h +0 -0
- {sbd_eigensolver-1.7.0 → sbd_eigensolver-1.7.1}/vendor/sbd-upstream/include/sbd/chemistry/gdb/mult.h +0 -0
- {sbd_eigensolver-1.7.0 → sbd_eigensolver-1.7.1}/vendor/sbd-upstream/include/sbd/chemistry/gdb/mult_thrust.h +0 -0
- {sbd_eigensolver-1.7.0 → sbd_eigensolver-1.7.1}/vendor/sbd-upstream/include/sbd/chemistry/gdb/occupation.h +0 -0
- {sbd_eigensolver-1.7.0 → sbd_eigensolver-1.7.1}/vendor/sbd-upstream/include/sbd/chemistry/gdb/parent_sampling.h +0 -0
- {sbd_eigensolver-1.7.0 → sbd_eigensolver-1.7.1}/vendor/sbd-upstream/include/sbd/chemistry/gdb/qcham.h +0 -0
- {sbd_eigensolver-1.7.0 → sbd_eigensolver-1.7.1}/vendor/sbd-upstream/include/sbd/chemistry/gdb/restart.h +0 -0
- {sbd_eigensolver-1.7.0 → sbd_eigensolver-1.7.1}/vendor/sbd-upstream/include/sbd/chemistry/gdb/sbdiag.h +0 -0
- {sbd_eigensolver-1.7.0 → sbd_eigensolver-1.7.1}/vendor/sbd-upstream/include/sbd/chemistry/gdb/stat_evaluator.h +0 -0
- {sbd_eigensolver-1.7.0 → sbd_eigensolver-1.7.1}/vendor/sbd-upstream/include/sbd/chemistry/gdb/statistical_contribution_expansion.h +0 -0
- {sbd_eigensolver-1.7.0 → sbd_eigensolver-1.7.1}/vendor/sbd-upstream/include/sbd/chemistry/gdb/u_statistic_external_observable.h +0 -0
- {sbd_eigensolver-1.7.0 → sbd_eigensolver-1.7.1}/vendor/sbd-upstream/include/sbd/chemistry/inc_all.h +0 -0
- {sbd_eigensolver-1.7.0 → sbd_eigensolver-1.7.1}/vendor/sbd-upstream/include/sbd/chemistry/tpb/correlation.h +0 -0
- {sbd_eigensolver-1.7.0 → sbd_eigensolver-1.7.1}/vendor/sbd-upstream/include/sbd/chemistry/tpb/correlation_thrust.h +0 -0
- {sbd_eigensolver-1.7.0 → sbd_eigensolver-1.7.1}/vendor/sbd-upstream/include/sbd/chemistry/tpb/davidson.h +0 -0
- {sbd_eigensolver-1.7.0 → sbd_eigensolver-1.7.1}/vendor/sbd-upstream/include/sbd/chemistry/tpb/davidson_thrust.h +0 -0
- {sbd_eigensolver-1.7.0 → sbd_eigensolver-1.7.1}/vendor/sbd-upstream/include/sbd/chemistry/tpb/extend.h +0 -0
- {sbd_eigensolver-1.7.0 → sbd_eigensolver-1.7.1}/vendor/sbd-upstream/include/sbd/chemistry/tpb/helper.h +0 -0
- {sbd_eigensolver-1.7.0 → sbd_eigensolver-1.7.1}/vendor/sbd-upstream/include/sbd/chemistry/tpb/helper_thrust.h +0 -0
- {sbd_eigensolver-1.7.0 → sbd_eigensolver-1.7.1}/vendor/sbd-upstream/include/sbd/chemistry/tpb/inc_all.h +0 -0
- {sbd_eigensolver-1.7.0 → sbd_eigensolver-1.7.1}/vendor/sbd-upstream/include/sbd/chemistry/tpb/lanczos.h +0 -0
- {sbd_eigensolver-1.7.0 → sbd_eigensolver-1.7.1}/vendor/sbd-upstream/include/sbd/chemistry/tpb/lanczos_thrust.h +0 -0
- {sbd_eigensolver-1.7.0 → sbd_eigensolver-1.7.1}/vendor/sbd-upstream/include/sbd/chemistry/tpb/mult.h +0 -0
- {sbd_eigensolver-1.7.0 → sbd_eigensolver-1.7.1}/vendor/sbd-upstream/include/sbd/chemistry/tpb/mult_thrust.h +0 -0
- {sbd_eigensolver-1.7.0 → sbd_eigensolver-1.7.1}/vendor/sbd-upstream/include/sbd/chemistry/tpb/occupation.h +0 -0
- {sbd_eigensolver-1.7.0 → sbd_eigensolver-1.7.1}/vendor/sbd-upstream/include/sbd/chemistry/tpb/qcham.h +0 -0
- {sbd_eigensolver-1.7.0 → sbd_eigensolver-1.7.1}/vendor/sbd-upstream/include/sbd/chemistry/tpb/rdmat.h +0 -0
- {sbd_eigensolver-1.7.0 → sbd_eigensolver-1.7.1}/vendor/sbd-upstream/include/sbd/chemistry/tpb/restart.h +0 -0
- {sbd_eigensolver-1.7.0 → sbd_eigensolver-1.7.1}/vendor/sbd-upstream/include/sbd/chemistry/tpb/sbdiag.h +0 -0
- {sbd_eigensolver-1.7.0 → sbd_eigensolver-1.7.1}/vendor/sbd-upstream/include/sbd/framework/bit_manipulation.h +0 -0
- {sbd_eigensolver-1.7.0 → sbd_eigensolver-1.7.1}/vendor/sbd-upstream/include/sbd/framework/cublas_utility.h +0 -0
- {sbd_eigensolver-1.7.0 → sbd_eigensolver-1.7.1}/vendor/sbd-upstream/include/sbd/framework/cuda_reduce.h +0 -0
- {sbd_eigensolver-1.7.0 → sbd_eigensolver-1.7.1}/vendor/sbd-upstream/include/sbd/framework/cuda_utility.h +0 -0
- {sbd_eigensolver-1.7.0 → sbd_eigensolver-1.7.1}/vendor/sbd-upstream/include/sbd/framework/det_vector.h +0 -0
- {sbd_eigensolver-1.7.0 → sbd_eigensolver-1.7.1}/vendor/sbd-upstream/include/sbd/framework/determinant_distribution_round_robin.h +0 -0
- {sbd_eigensolver-1.7.0 → sbd_eigensolver-1.7.1}/vendor/sbd-upstream/include/sbd/framework/determinant_initialization.h +0 -0
- {sbd_eigensolver-1.7.0 → sbd_eigensolver-1.7.1}/vendor/sbd-upstream/include/sbd/framework/distributed_alias_sampling.h +0 -0
- {sbd_eigensolver-1.7.0 → sbd_eigensolver-1.7.1}/vendor/sbd-upstream/include/sbd/framework/dm_vector.h +0 -0
- {sbd_eigensolver-1.7.0 → sbd_eigensolver-1.7.1}/vendor/sbd-upstream/include/sbd/framework/fcidump.h +0 -0
- {sbd_eigensolver-1.7.0 → sbd_eigensolver-1.7.1}/vendor/sbd-upstream/include/sbd/framework/hip_reduce.h +0 -0
- {sbd_eigensolver-1.7.0 → sbd_eigensolver-1.7.1}/vendor/sbd-upstream/include/sbd/framework/hp_numeric.h +0 -0
- {sbd_eigensolver-1.7.0 → sbd_eigensolver-1.7.1}/vendor/sbd-upstream/include/sbd/framework/jacobi.h +0 -0
- {sbd_eigensolver-1.7.0 → sbd_eigensolver-1.7.1}/vendor/sbd-upstream/include/sbd/framework/mpi_utility.h +0 -0
- {sbd_eigensolver-1.7.0 → sbd_eigensolver-1.7.1}/vendor/sbd-upstream/include/sbd/framework/mpi_utility_thrust.h +0 -0
- {sbd_eigensolver-1.7.0 → sbd_eigensolver-1.7.1}/vendor/sbd-upstream/include/sbd/framework/murmurhash_basis_distribution.h +0 -0
- {sbd_eigensolver-1.7.0 → sbd_eigensolver-1.7.1}/vendor/sbd-upstream/include/sbd/framework/nccl_utility.h +0 -0
- {sbd_eigensolver-1.7.0 → sbd_eigensolver-1.7.1}/vendor/sbd-upstream/include/sbd/framework/nvtx.h +0 -0
- {sbd_eigensolver-1.7.0 → sbd_eigensolver-1.7.1}/vendor/sbd-upstream/include/sbd/framework/sort_array.h +0 -0
- {sbd_eigensolver-1.7.0 → sbd_eigensolver-1.7.1}/vendor/sbd-upstream/include/sbd/framework/ssutils.h +0 -0
- {sbd_eigensolver-1.7.0 → sbd_eigensolver-1.7.1}/vendor/sbd-upstream/include/sbd/framework/stat/stat_evaluator_batch.h +0 -0
- {sbd_eigensolver-1.7.0 → sbd_eigensolver-1.7.1}/vendor/sbd-upstream/include/sbd/framework/thrust_kernels.h +0 -0
- {sbd_eigensolver-1.7.0 → sbd_eigensolver-1.7.1}/vendor/sbd-upstream/include/sbd/framework/timestamp.h +0 -0
- {sbd_eigensolver-1.7.0 → sbd_eigensolver-1.7.1}/vendor/sbd-upstream/include/sbd/framework/type_def.h +0 -0
- {sbd_eigensolver-1.7.0 → sbd_eigensolver-1.7.1}/vendor/sbd-upstream/include/sbd/sbd.h +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: sbd-eigensolver
|
|
3
|
-
Version: 1.7.
|
|
3
|
+
Version: 1.7.1
|
|
4
4
|
Summary: Python bindings for Selected Basis Diagonalization (SBD) library
|
|
5
5
|
License-Expression: Apache-2.0
|
|
6
6
|
Project-URL: Homepage, https://github.com/Qiskit/sbd-eigensolver-python
|
|
@@ -272,6 +272,7 @@ config = sbd.TPB_SBD()
|
|
|
272
272
|
| `adet_comm_size` | 1 | Alpha determinant communicator size |
|
|
273
273
|
| `bdet_comm_size` | 1 | Beta determinant communicator size |
|
|
274
274
|
| `task_comm_size` | 1 | Task communicator size |
|
|
275
|
+
| `dump_matrix_form_wf` | `""` | Path to write the amplitudes to — see [Getting the TPB amplitudes](#getting-the-tpb-amplitudes) for the file format |
|
|
275
276
|
|
|
276
277
|
Total MPI ranks = `task_comm_size × adet_comm_size × bdet_comm_size`.
|
|
277
278
|
|
|
@@ -315,6 +316,39 @@ results = sbd.tpb_diag(fcidump, adet, bdet, sbd_data,
|
|
|
315
316
|
|
|
316
317
|
**Returns:** `dict` with keys `energy`, `density`, `carryover_adet`, `carryover_bdet`, `one_p_rdm`, `two_p_rdm`.
|
|
317
318
|
|
|
319
|
+
#### Getting the TPB amplitudes
|
|
320
|
+
|
|
321
|
+
Neither return dict holds the wavefunction amplitudes. Two separate mechanisms write them, in **different formats**, and the one named in the function signature is not the one most callers want:
|
|
322
|
+
|
|
323
|
+
| | `sbd_data.dump_matrix_form_wf` | `savename` argument |
|
|
324
|
+
|---|---|---|
|
|
325
|
+
| Writes | the full `len(adet) × len(bdet)` subspace, gathered onto one rank | one file per b_comm position, each holding **only that rank's block** |
|
|
326
|
+
| Path | exactly what you set | `f"{savename}{rank_b:06d}.bin"` |
|
|
327
|
+
| Header | **none** | three `size_t` (`adet_range`, `bdet_range`, `det_length`), then that block's alpha and beta determinant words |
|
|
328
|
+
| Payload | `float64`, row-major over α×β | `adet_range × bdet_range` `float64` |
|
|
329
|
+
| Intended for | analysis | checkpoint/restart, paired with `loadname` |
|
|
330
|
+
|
|
331
|
+
So the whole-subspace read is just:
|
|
332
|
+
|
|
333
|
+
```python
|
|
334
|
+
config.dump_matrix_form_wf = "wf.bin"
|
|
335
|
+
results = sbd.tpb_diag(fcidump, adet, bdet, config)
|
|
336
|
+
|
|
337
|
+
amplitudes = np.fromfile("wf.bin").reshape(len(adet), len(bdet))
|
|
338
|
+
```
|
|
339
|
+
|
|
340
|
+
Naming that file `.dat` or `.txt` instead writes a text table labelling every amplitude with its own alpha and beta bitstring — the easiest form to inspect by hand, and it sidesteps having to reconstruct the ordering yourself:
|
|
341
|
+
|
|
342
|
+
```
|
|
343
|
+
<amplitude> # <alpha index>: <alpha bitstring> <beta index>: <beta bitstring>
|
|
344
|
+
```
|
|
345
|
+
|
|
346
|
+
Be aware that this text form is written with the stream's default formatting, so amplitudes land with only ~6 significant digits; use the binary form when you need full `float64` precision.
|
|
347
|
+
|
|
348
|
+
Rows and columns follow `adet`/`bdet` as the diagonalizer saw them. `sort_bitarray` removes duplicates as well as sorting, so pass lists already in that form if you intend to label the axes yourself — `from_strings` documents the word packing.
|
|
349
|
+
|
|
350
|
+
This is the mechanism [`sbd_solver.py`](python/sbd_solver.py) uses to populate `SCIState.amplitudes` — though it skips the write entirely when SBD is picking the carryover itself (`carryover_type` 1, against a qiskit-addon-sqd that accepts it), since then the next subspace comes back in `carryover_adet`/`carryover_bdet` and the amplitudes never need to reach Python.
|
|
351
|
+
|
|
318
352
|
```python
|
|
319
353
|
# GDB: over an explicit list of full determinants rather than a product space
|
|
320
354
|
results = sbd.gdb_diag(fcidump, det, sbd_data,
|
|
@@ -224,6 +224,7 @@ config = sbd.TPB_SBD()
|
|
|
224
224
|
| `adet_comm_size` | 1 | Alpha determinant communicator size |
|
|
225
225
|
| `bdet_comm_size` | 1 | Beta determinant communicator size |
|
|
226
226
|
| `task_comm_size` | 1 | Task communicator size |
|
|
227
|
+
| `dump_matrix_form_wf` | `""` | Path to write the amplitudes to — see [Getting the TPB amplitudes](#getting-the-tpb-amplitudes) for the file format |
|
|
227
228
|
|
|
228
229
|
Total MPI ranks = `task_comm_size × adet_comm_size × bdet_comm_size`.
|
|
229
230
|
|
|
@@ -267,6 +268,39 @@ results = sbd.tpb_diag(fcidump, adet, bdet, sbd_data,
|
|
|
267
268
|
|
|
268
269
|
**Returns:** `dict` with keys `energy`, `density`, `carryover_adet`, `carryover_bdet`, `one_p_rdm`, `two_p_rdm`.
|
|
269
270
|
|
|
271
|
+
#### Getting the TPB amplitudes
|
|
272
|
+
|
|
273
|
+
Neither return dict holds the wavefunction amplitudes. Two separate mechanisms write them, in **different formats**, and the one named in the function signature is not the one most callers want:
|
|
274
|
+
|
|
275
|
+
| | `sbd_data.dump_matrix_form_wf` | `savename` argument |
|
|
276
|
+
|---|---|---|
|
|
277
|
+
| Writes | the full `len(adet) × len(bdet)` subspace, gathered onto one rank | one file per b_comm position, each holding **only that rank's block** |
|
|
278
|
+
| Path | exactly what you set | `f"{savename}{rank_b:06d}.bin"` |
|
|
279
|
+
| Header | **none** | three `size_t` (`adet_range`, `bdet_range`, `det_length`), then that block's alpha and beta determinant words |
|
|
280
|
+
| Payload | `float64`, row-major over α×β | `adet_range × bdet_range` `float64` |
|
|
281
|
+
| Intended for | analysis | checkpoint/restart, paired with `loadname` |
|
|
282
|
+
|
|
283
|
+
So the whole-subspace read is just:
|
|
284
|
+
|
|
285
|
+
```python
|
|
286
|
+
config.dump_matrix_form_wf = "wf.bin"
|
|
287
|
+
results = sbd.tpb_diag(fcidump, adet, bdet, config)
|
|
288
|
+
|
|
289
|
+
amplitudes = np.fromfile("wf.bin").reshape(len(adet), len(bdet))
|
|
290
|
+
```
|
|
291
|
+
|
|
292
|
+
Naming that file `.dat` or `.txt` instead writes a text table labelling every amplitude with its own alpha and beta bitstring — the easiest form to inspect by hand, and it sidesteps having to reconstruct the ordering yourself:
|
|
293
|
+
|
|
294
|
+
```
|
|
295
|
+
<amplitude> # <alpha index>: <alpha bitstring> <beta index>: <beta bitstring>
|
|
296
|
+
```
|
|
297
|
+
|
|
298
|
+
Be aware that this text form is written with the stream's default formatting, so amplitudes land with only ~6 significant digits; use the binary form when you need full `float64` precision.
|
|
299
|
+
|
|
300
|
+
Rows and columns follow `adet`/`bdet` as the diagonalizer saw them. `sort_bitarray` removes duplicates as well as sorting, so pass lists already in that form if you intend to label the axes yourself — `from_strings` documents the word packing.
|
|
301
|
+
|
|
302
|
+
This is the mechanism [`sbd_solver.py`](python/sbd_solver.py) uses to populate `SCIState.amplitudes` — though it skips the write entirely when SBD is picking the carryover itself (`carryover_type` 1, against a qiskit-addon-sqd that accepts it), since then the next subspace comes back in `carryover_adet`/`carryover_bdet` and the amplitudes never need to reach Python.
|
|
303
|
+
|
|
270
304
|
```python
|
|
271
305
|
# GDB: over an explicit list of full determinants rather than a product space
|
|
272
306
|
results = sbd.gdb_diag(fcidump, det, sbd_data,
|
|
@@ -318,8 +318,9 @@ def init(device='cpu', comm_backend='mpi'):
|
|
|
318
318
|
first use with ``device='cpu'`` and ``comm_backend='mpi'``. Call it
|
|
319
319
|
explicitly only when you need GPU or want to control startup timing.
|
|
320
320
|
|
|
321
|
-
The device can be overridden per
|
|
322
|
-
``tpb_diag()``, ``tpb_diag_from_files()``,
|
|
321
|
+
The device can be overridden per call via the ``device`` parameter of
|
|
322
|
+
``tpb_diag()``, ``tpb_diag_from_files()``, ``gdb_diag()`` and
|
|
323
|
+
``get_backend()``.
|
|
323
324
|
|
|
324
325
|
Args:
|
|
325
326
|
device: Default compute device — 'cpu', 'gpu', 'gpu-omp', or 'auto'.
|
|
@@ -413,11 +414,20 @@ def get_backend(device=None):
|
|
|
413
414
|
Get the backend module for the given device.
|
|
414
415
|
|
|
415
416
|
Auto-initializes SBD if needed. Passing ``device`` overrides the
|
|
416
|
-
default
|
|
417
|
-
|
|
417
|
+
default, which is how you switch backends within one process. The one
|
|
418
|
+
combination to avoid is the CPU backend together with the OpenMP-offload
|
|
419
|
+
one ('gpu-omp'): they share an OpenMP runtime, and loading both leaves
|
|
420
|
+
offload regions running on the host. ``sbd.has_backend_conflict()``
|
|
421
|
+
reports it.
|
|
418
422
|
|
|
419
423
|
Args:
|
|
420
|
-
device: 'cpu', 'gpu', '
|
|
424
|
+
device: 'cpu', 'gpu' (Thrust), 'gpu-omp' (OpenMP offload), 'auto', an
|
|
425
|
+
alias accepted by :func:`init`, or None. None means the device set
|
|
426
|
+
by :func:`init`. If nothing has initialized yet it means 'auto',
|
|
427
|
+
which prefers Thrust, then OpenMP offload, then CPU, whereas the
|
|
428
|
+
first call of :func:`tpb_diag` or :func:`gdb_diag` initializes with
|
|
429
|
+
'cpu'. Call :func:`init` with the device you want to avoid
|
|
430
|
+
depending on call order.
|
|
421
431
|
|
|
422
432
|
Returns:
|
|
423
433
|
The pybind11 backend module (_core_cpu, _core_gpu_thrust, or
|
|
@@ -496,13 +506,19 @@ def barrier():
|
|
|
496
506
|
# ---------------------------------------------------------------------------
|
|
497
507
|
|
|
498
508
|
def TPB_SBD(device=None):
|
|
499
|
-
"""Create TPB_SBD configuration object
|
|
509
|
+
"""Create a TPB_SBD configuration object, for :func:`tpb_diag`.
|
|
510
|
+
|
|
511
|
+
Its fields are listed in the tables below.
|
|
512
|
+
"""
|
|
500
513
|
_ensure_initialized()
|
|
501
514
|
return get_backend(device).TPB_SBD()
|
|
502
515
|
|
|
503
516
|
|
|
504
517
|
def GDB_SBD(device=None):
|
|
505
|
-
"""Create GDB_SBD configuration object
|
|
518
|
+
"""Create a GDB_SBD configuration object, for :func:`gdb_diag`.
|
|
519
|
+
|
|
520
|
+
Its fields are listed in the tables below.
|
|
521
|
+
"""
|
|
506
522
|
_ensure_initialized()
|
|
507
523
|
return get_backend(device).GDB_SBD()
|
|
508
524
|
|
|
@@ -514,25 +530,65 @@ def FCIDump(device=None):
|
|
|
514
530
|
|
|
515
531
|
|
|
516
532
|
def LoadFCIDump(filename, device=None):
|
|
517
|
-
"""Load FCIDUMP file.
|
|
533
|
+
"""Load an FCIDUMP file.
|
|
534
|
+
|
|
535
|
+
Args:
|
|
536
|
+
filename: Path to the FCIDUMP file.
|
|
537
|
+
device: Backend whose ``FCIDump`` type to build; None uses the default.
|
|
538
|
+
|
|
539
|
+
Returns:
|
|
540
|
+
The ``FCIDump`` object that :func:`tpb_diag` and :func:`gdb_diag` take.
|
|
541
|
+
"""
|
|
518
542
|
_ensure_initialized()
|
|
519
543
|
return get_backend(device).LoadFCIDump(filename)
|
|
520
544
|
|
|
521
545
|
|
|
522
546
|
def LoadAlphaDets(filename, bit_length, total_bit_length, device=None):
|
|
523
|
-
"""Load
|
|
547
|
+
"""Load determinants from a file of bitstrings, one per line.
|
|
548
|
+
|
|
549
|
+
Each line is packed as :func:`from_strings` does. Upstream sorts the
|
|
550
|
+
determinants and removes duplicates, so the result is ready to use as a
|
|
551
|
+
TPB determinant list and may hold fewer determinants than the file has
|
|
552
|
+
lines.
|
|
553
|
+
|
|
554
|
+
The format is chosen by extension: ``.txt`` for one bitstring per line,
|
|
555
|
+
``.bin`` for upstream's binary format. Any other extension returns an
|
|
556
|
+
empty list without an error.
|
|
557
|
+
|
|
558
|
+
Args:
|
|
559
|
+
filename: Path to the file.
|
|
560
|
+
bit_length: Bits per packed word. Must match the config's
|
|
561
|
+
``bit_length``.
|
|
562
|
+
total_bit_length: Length of each bitstring, ``norb`` for the alpha or
|
|
563
|
+
beta strings of TPB.
|
|
564
|
+
device: Backend to use; None uses the default.
|
|
565
|
+
|
|
566
|
+
Returns:
|
|
567
|
+
A list of packed determinants, each a list of words, sorted and
|
|
568
|
+
distinct.
|
|
569
|
+
"""
|
|
524
570
|
_ensure_initialized()
|
|
525
571
|
return get_backend(device).LoadAlphaDets(filename, bit_length, total_bit_length)
|
|
526
572
|
|
|
527
573
|
|
|
528
574
|
def makestring(config, bit_length, total_bit_length, device=None):
|
|
529
|
-
"""
|
|
575
|
+
"""Render a packed determinant as a ``total_bit_length``-character string.
|
|
576
|
+
|
|
577
|
+
The inverse of :func:`from_string`, and subject to the same right-to-left
|
|
578
|
+
word packing, which :func:`from_strings` describes.
|
|
579
|
+
"""
|
|
530
580
|
_ensure_initialized()
|
|
531
581
|
return get_backend(device).makestring(config, bit_length, total_bit_length)
|
|
532
582
|
|
|
533
583
|
|
|
534
584
|
def from_string(s, bit_length, total_bit_length, device=None):
|
|
535
|
-
"""Convert binary string to determinant format.
|
|
585
|
+
"""Convert a binary string to SBD's packed determinant format.
|
|
586
|
+
|
|
587
|
+
Returns a list of ``size_t`` words, e.g. ``from_string("0011", 20, 4)`` is
|
|
588
|
+
``[3]``. :func:`makestring` is the inverse. See :func:`from_strings`, the
|
|
589
|
+
bulk form, for the word-packing convention and for why it is worth
|
|
590
|
+
preferring that form outside of one-off calls.
|
|
591
|
+
"""
|
|
536
592
|
_ensure_initialized()
|
|
537
593
|
return get_backend(device).from_string(s, bit_length, total_bit_length)
|
|
538
594
|
|
|
@@ -540,10 +596,29 @@ def from_string(s, bit_length, total_bit_length, device=None):
|
|
|
540
596
|
def from_strings(strings, bit_length, total_bit_length, device=None):
|
|
541
597
|
"""Pack many bitstrings into one ``(n, words)`` array.
|
|
542
598
|
|
|
543
|
-
The bulk form of
|
|
599
|
+
The bulk form of ``sbd.from_string``, looping in C++ instead of once per
|
|
544
600
|
determinant across the Python boundary. Prefer it for anything larger than a
|
|
545
601
|
handful: the per-call form costs tens of thousands of round trips on the
|
|
546
602
|
vendored inputs alone.
|
|
603
|
+
|
|
604
|
+
Each row holds ``total_bit_length`` bits packed ``bit_length`` to a word, so
|
|
605
|
+
a bitstring longer than ``bit_length`` occupies more than one word. The
|
|
606
|
+
packing runs from the **right end** of the string: its trailing
|
|
607
|
+
``bit_length`` characters become word 0, the next ``bit_length`` to the left
|
|
608
|
+
become word 1, and so on, so the leading characters of a multi-word string
|
|
609
|
+
land in the *last* word rather than the first::
|
|
610
|
+
|
|
611
|
+
from_strings(["0011"], 20, 4) # -> array([[3]], dtype=uint64)
|
|
612
|
+
from_strings(["1" + "0" * 69], 62, 70) # -> array([[ 0, 128]], ...)
|
|
613
|
+
from_strings(["0" * 69 + "1"], 62, 70) # -> array([[1, 0]], ...)
|
|
614
|
+
|
|
615
|
+
Within a word the rightmost character is the least significant bit, which is
|
|
616
|
+
why ``"0011"`` packs to ``3`` rather than ``12``. Getting this backwards
|
|
617
|
+
produces a valid-looking but wrong subspace rather than an error, so check
|
|
618
|
+
round trips with ``sbd.makestring`` when building determinants by hand.
|
|
619
|
+
|
|
620
|
+
``bit_length`` must match the ``bit_length`` of the config passed to the
|
|
621
|
+
diagonalizers, since it sets how many words each determinant occupies.
|
|
547
622
|
"""
|
|
548
623
|
_ensure_initialized()
|
|
549
624
|
return get_backend(device).from_strings(list(strings), bit_length, total_bit_length)
|
|
@@ -575,17 +650,27 @@ def tpb_diag_from_files(fcidumpfile, adetfile, sbd_data,
|
|
|
575
650
|
"""
|
|
576
651
|
Perform TPB diagonalization from files.
|
|
577
652
|
|
|
653
|
+
The one determinant file supplies both the alpha and the beta list, so the
|
|
654
|
+
subspace is the product of that list with itself. For different alpha and
|
|
655
|
+
beta lists, as an open-shell case needs, load them and call :func:`tpb_diag`.
|
|
656
|
+
|
|
578
657
|
Args:
|
|
579
658
|
fcidumpfile: Path to FCIDUMP file.
|
|
580
|
-
adetfile: Path to alpha
|
|
659
|
+
adetfile: Path to the determinant file, used for both alpha and beta.
|
|
581
660
|
sbd_data: TPB_SBD configuration object.
|
|
582
|
-
loadname: Path to load initial wavefunction (optional).
|
|
583
|
-
savename: Path to save final wavefunction (optional).
|
|
584
|
-
device:
|
|
661
|
+
loadname: Path prefix to load an initial wavefunction from (optional).
|
|
662
|
+
savename: Path prefix to save the final wavefunction to (optional).
|
|
663
|
+
device: Backend to run on: 'cpu', 'gpu' (Thrust), 'gpu-omp' (OpenMP
|
|
664
|
+
offload), or an alias accepted by :func:`init`. None uses the
|
|
665
|
+
default; see :func:`get_backend`.
|
|
585
666
|
|
|
586
667
|
Returns:
|
|
587
668
|
dict with keys: energy, density, carryover_adet, carryover_bdet,
|
|
588
669
|
one_p_rdm, two_p_rdm.
|
|
670
|
+
|
|
671
|
+
Note:
|
|
672
|
+
As with :func:`tpb_diag`, no amplitudes are returned in the dict; see
|
|
673
|
+
that function for the two ways of writing them to disk.
|
|
589
674
|
"""
|
|
590
675
|
_ensure_initialized()
|
|
591
676
|
backend = get_backend(device)
|
|
@@ -604,13 +689,54 @@ def tpb_diag(fcidump, adet, bdet, sbd_data,
|
|
|
604
689
|
adet: Alpha determinants.
|
|
605
690
|
bdet: Beta determinants.
|
|
606
691
|
sbd_data: TPB_SBD configuration object.
|
|
607
|
-
loadname: Path to load initial wavefunction (optional).
|
|
608
|
-
savename: Path to save final wavefunction (optional).
|
|
609
|
-
|
|
692
|
+
loadname: Path prefix to load an initial wavefunction from (optional).
|
|
693
|
+
savename: Path prefix to save the final wavefunction to (optional). See
|
|
694
|
+
the note below: for reading amplitudes back,
|
|
695
|
+
``sbd_data.dump_matrix_form_wf`` is usually the one you want.
|
|
696
|
+
device: Backend to run on: 'cpu', 'gpu' (Thrust), 'gpu-omp' (OpenMP
|
|
697
|
+
offload), or an alias accepted by :func:`init`. None uses the
|
|
698
|
+
default; see :func:`get_backend`.
|
|
610
699
|
|
|
611
700
|
Returns:
|
|
612
701
|
dict with keys: energy, density, carryover_adet, carryover_bdet,
|
|
613
702
|
one_p_rdm, two_p_rdm.
|
|
703
|
+
|
|
704
|
+
Note:
|
|
705
|
+
The returned dict holds no wavefunction amplitudes. There are two ways
|
|
706
|
+
to get them, and they write *different* formats -- do not mix them up:
|
|
707
|
+
|
|
708
|
+
``sbd_data.dump_matrix_form_wf = "wf.bin"`` writes the full
|
|
709
|
+
``len(adet) x len(bdet)`` subspace, gathered onto one rank, as a bare
|
|
710
|
+
row-major array of ``float64`` with **no header** -- so
|
|
711
|
+
``np.fromfile(path).reshape(len(adet), len(bdet))`` reads it. Naming it
|
|
712
|
+
``.dat`` or ``.txt`` instead writes a text table in which every
|
|
713
|
+
amplitude is labelled with its own alpha and beta bitstring, which is
|
|
714
|
+
the easiest form to inspect by hand. This is the mechanism this
|
|
715
|
+
package's own SQD integration uses.
|
|
716
|
+
|
|
717
|
+
``savename`` instead writes one file per b_comm position,
|
|
718
|
+
``f"{savename}{rank_b:06d}.bin"``, each holding only **that rank's
|
|
719
|
+
block** of the subspace: three ``size_t`` headers
|
|
720
|
+
(``adet_range``, ``bdet_range``, ``det_length``), then that block's
|
|
721
|
+
alpha and then beta determinant words, then
|
|
722
|
+
``adet_range x bdet_range`` ``float64`` amplitudes. It pairs with
|
|
723
|
+
``loadname`` for restarting a run, so it is the better choice for
|
|
724
|
+
checkpointing and the worse one for analysis.
|
|
725
|
+
|
|
726
|
+
Amplitudes are ordered by ``adet``/``bdet`` as the diagonalizer saw
|
|
727
|
+
them. ``sort_bitarray`` removes duplicates as well as sorting, so pass
|
|
728
|
+
lists already in that form if you need to label the rows and columns
|
|
729
|
+
yourself.
|
|
730
|
+
|
|
731
|
+
Both files use SBD's sign convention, which orders a determinant's
|
|
732
|
+
creation operators orbital by orbital (alpha 0, beta 0, alpha 1, ...).
|
|
733
|
+
PySCF, and so qiskit-addon-sqd's ``SCIState``, puts all alpha operators
|
|
734
|
+
before all beta ones, so some determinants differ in sign: multiply each
|
|
735
|
+
amplitude by ``(-1) ** n``, where ``n`` counts, over the occupied beta
|
|
736
|
+
orbitals ``p``, the occupied alpha orbitals above ``p``, before handing
|
|
737
|
+
it to PySCF. Magnitudes, and so selection by weight, are the same either
|
|
738
|
+
way. :func:`sbd.sbd_solver.solve_sci` converts the amplitudes in its
|
|
739
|
+
``SCIState`` already.
|
|
614
740
|
"""
|
|
615
741
|
_ensure_initialized()
|
|
616
742
|
backend = get_backend(device)
|
|
@@ -671,7 +797,11 @@ def gdb_diag(fcidump, det, sbd_data,
|
|
|
671
797
|
writes one file per b_comm position, ``f"{savename}{rank_b:06d}.bin"``,
|
|
672
798
|
each holding only that shard; rank 0's file is not the whole
|
|
673
799
|
wavefunction. GDB has no combined matrix-form dump.
|
|
674
|
-
device:
|
|
800
|
+
device: Backend to run on: 'cpu', 'gpu' (Thrust), 'gpu-omp' (OpenMP
|
|
801
|
+
offload), or an alias accepted by :func:`init`. None uses the
|
|
802
|
+
default; see :func:`get_backend`. 'gpu-omp' is accepted, but SBD
|
|
803
|
+
has no OpenMP-offload GDB code, so the run executes on the host;
|
|
804
|
+
use 'gpu' for GDB on GPUs.
|
|
675
805
|
determinant_distribution: How to place determinants across b_comm — one
|
|
676
806
|
of ``input`` (keep the shards as given), ``equal-bra-a`` (default;
|
|
677
807
|
equal distinct-alpha count per rank, which is what balances the
|
|
@@ -319,7 +319,12 @@ PYBIND11_MODULE(SBD_MODULE_NAME, m) {
|
|
|
319
319
|
.def_readwrite("bit_length", &sbd::tpb::SBD::bit_length,
|
|
320
320
|
"Bit length for determinant representation")
|
|
321
321
|
.def_readwrite("dump_matrix_form_wf", &sbd::tpb::SBD::dump_matrix_form_wf,
|
|
322
|
-
"
|
|
322
|
+
"Path to write the full adet x bdet amplitude matrix to, "
|
|
323
|
+
"gathered onto one rank. A .bin path writes a bare "
|
|
324
|
+
"row-major float64 array with no header; .dat/.txt write "
|
|
325
|
+
"a labelled text table. Distinct from tpb_diag's "
|
|
326
|
+
"savename, which writes per-rank blocks with a header "
|
|
327
|
+
"for restart -- see the tpb_diag docstring.")
|
|
323
328
|
#ifdef SBD_THRUST
|
|
324
329
|
.def_readwrite("use_precalculated_dets", &sbd::tpb::SBD::use_precalculated_dets,
|
|
325
330
|
"Use precalculated determinants (THRUST)")
|
|
@@ -27,18 +27,14 @@ class DeviceConfig:
|
|
|
27
27
|
|
|
28
28
|
Usage::
|
|
29
29
|
|
|
30
|
-
|
|
31
|
-
|
|
30
|
+
from sbd.device_config import DeviceConfig
|
|
31
|
+
from sbd.sbd_solver import solve_sci_batch
|
|
32
32
|
|
|
33
|
-
#
|
|
34
|
-
|
|
33
|
+
device = DeviceConfig.auto() # best backend that is built
|
|
34
|
+
device = DeviceConfig.cpu() # or force one
|
|
35
|
+
device = DeviceConfig.gpu(max_memory_gb=16)
|
|
35
36
|
|
|
36
|
-
|
|
37
|
-
config = DeviceConfig.gpu(max_memory_gb=16)
|
|
38
|
-
|
|
39
|
-
# Apply to SBD configuration
|
|
40
|
-
sbd_config = sbd.TPB_SBD()
|
|
41
|
-
config.apply(sbd_config)
|
|
37
|
+
results = solve_sci_batch(..., device_config=device)
|
|
42
38
|
"""
|
|
43
39
|
|
|
44
40
|
def __init__(self, device: str = 'cpu',
|
|
@@ -72,17 +68,11 @@ class DeviceConfig:
|
|
|
72
68
|
"""
|
|
73
69
|
Auto-detect the best available backend and use it.
|
|
74
70
|
|
|
75
|
-
|
|
76
|
-
hardware
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
to load a CUDA module; and on a CPU-only build with a GPU present it
|
|
81
|
-
picked a backend that was never built.
|
|
82
|
-
|
|
83
|
-
Preference order matches sbd._resolve_device(): Thrust ('gpu') first
|
|
84
|
-
where it exists, since it is the long-validated NVIDIA default and keeps
|
|
85
|
-
more phases on the device, then OpenMP offload ('gpu-omp'), then CPU.
|
|
71
|
+
Chooses among the backends that were actually built, not merely the
|
|
72
|
+
hardware present, so an AMD host or a CPU-only build is never handed a
|
|
73
|
+
backend it lacks. The preference order is Thrust ('gpu') where it exists,
|
|
74
|
+
then OpenMP offload ('gpu-omp'), then CPU, the same order
|
|
75
|
+
``sbd.get_backend('auto')`` uses.
|
|
86
76
|
|
|
87
77
|
Args:
|
|
88
78
|
max_memory_gb: Maximum GPU memory in GB (-1 = auto)
|
|
@@ -158,8 +148,8 @@ class DeviceConfig:
|
|
|
158
148
|
one combination to avoid in a single process is this backend together
|
|
159
149
|
with the CPU one: they share an OpenMP runtime (``libnvomp`` on NVIDIA,
|
|
160
150
|
``libomp`` on AMD), and loading ``_core_cpu`` first leaves it initialised
|
|
161
|
-
host-only, after which offload regions run on the host.
|
|
162
|
-
|
|
151
|
+
host-only, after which offload regions run on the host.
|
|
152
|
+
``sbd.has_backend_conflict()`` reports that combination.
|
|
163
153
|
"""
|
|
164
154
|
return cls(device='gpu-omp', max_memory_gb=max_memory_gb)
|
|
165
155
|
|
|
@@ -297,8 +297,10 @@ def _solve_sci_core(
|
|
|
297
297
|
"a different size means the dump and the subspace have diverged."
|
|
298
298
|
)
|
|
299
299
|
|
|
300
|
+
amplitudes = flat.reshape(n_a, n_b)
|
|
301
|
+
_to_alpha_first_signs(amplitudes, solved_strings_a, solved_strings_b, norb)
|
|
300
302
|
sci_state = SCIState(
|
|
301
|
-
amplitudes=
|
|
303
|
+
amplitudes=amplitudes,
|
|
302
304
|
ci_strs_a=solved_strings_a,
|
|
303
305
|
ci_strs_b=solved_strings_b,
|
|
304
306
|
norb=norb,
|
|
@@ -470,25 +472,20 @@ def assemble_rdms(results: dict, norb: int) -> tuple[np.ndarray | None, np.ndarr
|
|
|
470
472
|
which only computes the diagonal density, not the correlation
|
|
471
473
|
functions), matching SCIResult's own ``rdm1``/``rdm2`` default.
|
|
472
474
|
|
|
473
|
-
The
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
the full tensors and via the energy identity
|
|
475
|
+
The layout conversion was verified against PySCF's ``make_rdm1`` and
|
|
476
|
+
``make_rdm2`` on all three backends (cpu, gpu, gpu-omp), both element-wise
|
|
477
|
+
and through the energy identity
|
|
477
478
|
``E = einsum("pr,pr->",rdm1,hcore) + 0.5*einsum("prqs,prqs->",rdm2,eri)``
|
|
478
|
-
|
|
479
|
-
qiskit-addon-sqd (e.g. ``fermion.py``'s own ``solve_fermion``).
|
|
479
|
+
with which ``qiskit-addon-sqd`` contracts ``SCIResult.rdm1`` and ``rdm2``.
|
|
480
480
|
|
|
481
|
-
SBD's documented
|
|
482
|
-
reference in apps/chemistry_tpb_selected_basis_diagonalization/main.cc)::
|
|
481
|
+
SBD's layout, as documented in upstream SBD's ``docs/user-guide.md``::
|
|
483
482
|
|
|
484
483
|
one_p_rdm[s][i + L*j] = <c+_{i,s} c_{j,s}>
|
|
485
484
|
two_p_rdm[s+2t][i + L*j + L^2*k + L^3*l] = <c+_{i,s} c+_{j,t} c_{l,t} c_{k,s}>
|
|
486
485
|
|
|
487
|
-
A Fortran-order reshape implements those flat-index formulas directly
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
needs axes (0, 2, 1, 3) to land in the "prqs" slot order SCIResult's
|
|
491
|
-
contract expects.
|
|
486
|
+
A Fortran-order reshape implements those flat-index formulas directly.
|
|
487
|
+
rdm1 needs no further transpose, and the spin-summed rdm2 is transposed
|
|
488
|
+
with axes ``(0, 2, 1, 3)`` into the "prqs" order ``SCIResult`` expects.
|
|
492
489
|
"""
|
|
493
490
|
one_p_rdm = results.get("one_p_rdm")
|
|
494
491
|
two_p_rdm = results.get("two_p_rdm")
|
|
@@ -693,6 +690,41 @@ def _ci_strings_to_sbd_dets(
|
|
|
693
690
|
return backend.sort_bitarray(dets)
|
|
694
691
|
|
|
695
692
|
|
|
693
|
+
def _to_alpha_first_signs(amplitudes, strings_a, strings_b, norb, block_elements=1 << 24):
|
|
694
|
+
"""Convert SBD's amplitudes, in place, to the sign convention SCIState assumes.
|
|
695
|
+
|
|
696
|
+
The two conventions order the creation operators of a determinant differently.
|
|
697
|
+
SBD interleaves the spins orbital by orbital (alpha 0, beta 0, alpha 1, ...);
|
|
698
|
+
PySCF, and so ``SCIState.rdm()`` and ``SCIState.spin_square()``, put every alpha
|
|
699
|
+
operator before every beta one. Moving each beta operator past the alpha
|
|
700
|
+
operators of higher orbitals gives the determinant the phase
|
|
701
|
+
|
|
702
|
+
(-1) ** sum over occupied beta orbitals p of (occupied alpha orbitals above p)
|
|
703
|
+
|
|
704
|
+
The magnitudes are the same, so energies, SBD's own RDMs, occupancies and any
|
|
705
|
+
selection by amplitude magnitude are unaffected, which is why this went unnoticed:
|
|
706
|
+
only what PySCF computes *from the amplitudes* was wrong -- e.g. ``spin_square()``
|
|
707
|
+
of 0.036 for an exact singlet, and an energy from ``rdm()`` 89 mHa off.
|
|
708
|
+
|
|
709
|
+
Args:
|
|
710
|
+
amplitudes: The ``(len(strings_a), len(strings_b))`` matrix, modified in place.
|
|
711
|
+
strings_a: Alpha CI strings labelling the rows; bit ``p`` is orbital ``p``.
|
|
712
|
+
strings_b: Beta CI strings labelling the columns.
|
|
713
|
+
norb: Number of spatial orbitals.
|
|
714
|
+
block_elements: Rows are converted in blocks of about this many elements, so
|
|
715
|
+
the temporary sign matrix stays bounded at large subspaces.
|
|
716
|
+
"""
|
|
717
|
+
orbitals = np.arange(norb, dtype=np.int64)
|
|
718
|
+
occupied_b = ((np.asarray(strings_b, dtype=np.int64)[:, None] >> orbitals) & 1).astype(np.int32)
|
|
719
|
+
occupied_a = (np.asarray(strings_a, dtype=np.int64)[:, None] >> orbitals) & 1
|
|
720
|
+
# alpha electrons in orbitals strictly above p, kept only as a parity
|
|
721
|
+
above_a = ((np.cumsum(occupied_a[:, ::-1], axis=1)[:, ::-1] - occupied_a) & 1).astype(np.int32)
|
|
722
|
+
rows = max(1, block_elements // max(1, len(strings_b)))
|
|
723
|
+
for start in range(0, len(strings_a), rows):
|
|
724
|
+
parity = (above_a[start:start + rows] @ occupied_b.T) & 1
|
|
725
|
+
amplitudes[start:start + rows][parity == 1] *= -1.0
|
|
726
|
+
|
|
727
|
+
|
|
696
728
|
def _sbd_dets_to_ci_strings(
|
|
697
729
|
dets: list[list[int]], norb: int, backend,
|
|
698
730
|
bit_length: int = SBD_DEFAULT_BIT_LENGTH,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: sbd-eigensolver
|
|
3
|
-
Version: 1.7.
|
|
3
|
+
Version: 1.7.1
|
|
4
4
|
Summary: Python bindings for Selected Basis Diagonalization (SBD) library
|
|
5
5
|
License-Expression: Apache-2.0
|
|
6
6
|
Project-URL: Homepage, https://github.com/Qiskit/sbd-eigensolver-python
|
|
@@ -272,6 +272,7 @@ config = sbd.TPB_SBD()
|
|
|
272
272
|
| `adet_comm_size` | 1 | Alpha determinant communicator size |
|
|
273
273
|
| `bdet_comm_size` | 1 | Beta determinant communicator size |
|
|
274
274
|
| `task_comm_size` | 1 | Task communicator size |
|
|
275
|
+
| `dump_matrix_form_wf` | `""` | Path to write the amplitudes to — see [Getting the TPB amplitudes](#getting-the-tpb-amplitudes) for the file format |
|
|
275
276
|
|
|
276
277
|
Total MPI ranks = `task_comm_size × adet_comm_size × bdet_comm_size`.
|
|
277
278
|
|
|
@@ -315,6 +316,39 @@ results = sbd.tpb_diag(fcidump, adet, bdet, sbd_data,
|
|
|
315
316
|
|
|
316
317
|
**Returns:** `dict` with keys `energy`, `density`, `carryover_adet`, `carryover_bdet`, `one_p_rdm`, `two_p_rdm`.
|
|
317
318
|
|
|
319
|
+
#### Getting the TPB amplitudes
|
|
320
|
+
|
|
321
|
+
Neither return dict holds the wavefunction amplitudes. Two separate mechanisms write them, in **different formats**, and the one named in the function signature is not the one most callers want:
|
|
322
|
+
|
|
323
|
+
| | `sbd_data.dump_matrix_form_wf` | `savename` argument |
|
|
324
|
+
|---|---|---|
|
|
325
|
+
| Writes | the full `len(adet) × len(bdet)` subspace, gathered onto one rank | one file per b_comm position, each holding **only that rank's block** |
|
|
326
|
+
| Path | exactly what you set | `f"{savename}{rank_b:06d}.bin"` |
|
|
327
|
+
| Header | **none** | three `size_t` (`adet_range`, `bdet_range`, `det_length`), then that block's alpha and beta determinant words |
|
|
328
|
+
| Payload | `float64`, row-major over α×β | `adet_range × bdet_range` `float64` |
|
|
329
|
+
| Intended for | analysis | checkpoint/restart, paired with `loadname` |
|
|
330
|
+
|
|
331
|
+
So the whole-subspace read is just:
|
|
332
|
+
|
|
333
|
+
```python
|
|
334
|
+
config.dump_matrix_form_wf = "wf.bin"
|
|
335
|
+
results = sbd.tpb_diag(fcidump, adet, bdet, config)
|
|
336
|
+
|
|
337
|
+
amplitudes = np.fromfile("wf.bin").reshape(len(adet), len(bdet))
|
|
338
|
+
```
|
|
339
|
+
|
|
340
|
+
Naming that file `.dat` or `.txt` instead writes a text table labelling every amplitude with its own alpha and beta bitstring — the easiest form to inspect by hand, and it sidesteps having to reconstruct the ordering yourself:
|
|
341
|
+
|
|
342
|
+
```
|
|
343
|
+
<amplitude> # <alpha index>: <alpha bitstring> <beta index>: <beta bitstring>
|
|
344
|
+
```
|
|
345
|
+
|
|
346
|
+
Be aware that this text form is written with the stream's default formatting, so amplitudes land with only ~6 significant digits; use the binary form when you need full `float64` precision.
|
|
347
|
+
|
|
348
|
+
Rows and columns follow `adet`/`bdet` as the diagonalizer saw them. `sort_bitarray` removes duplicates as well as sorting, so pass lists already in that form if you intend to label the axes yourself — `from_strings` documents the word packing.
|
|
349
|
+
|
|
350
|
+
This is the mechanism [`sbd_solver.py`](python/sbd_solver.py) uses to populate `SCIState.amplitudes` — though it skips the write entirely when SBD is picking the carryover itself (`carryover_type` 1, against a qiskit-addon-sqd that accepts it), since then the next subspace comes back in `carryover_adet`/`carryover_bdet` and the amplitudes never need to reach Python.
|
|
351
|
+
|
|
318
352
|
```python
|
|
319
353
|
# GDB: over an explicit list of full determinants rather than a product space
|
|
320
354
|
results = sbd.gdb_diag(fcidump, det, sbd_data,
|
|
@@ -27,6 +27,7 @@ sbd_eigensolver.egg-info/top_level.txt
|
|
|
27
27
|
test/test_gdb_drivers.py
|
|
28
28
|
test/test_gdb_equivalence.py
|
|
29
29
|
test/test_reference_energies.py
|
|
30
|
+
test/test_sci_state.py
|
|
30
31
|
test/test_sqd_integration.py
|
|
31
32
|
vendor/sbd-upstream/LICENSE.txt
|
|
32
33
|
vendor/sbd-upstream/include/sbd/sbd.h
|