Repository navigation
Unrestricted (UHF) FCIDUMPs through TPB and GDB; README restructured - #91
Merged
Merged
Conversation
sbd.analysis.variance gives the energy variance and Epstein-Nesbet PT2 correction of a state saved with savename, by upstream SBD's stochastic evaluator (bound as external_observables, CPU and OpenMP-offload backends) or exactly with PySCF for small systems. state_energy, load_state and load_gdb_shards read TPB and GDB states on any number of ranks. examples/analysis adds variance.py, extrapolate.py and a README. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
PySCF's cistring.strs2addr packs a string into an int64 and raises NotImplementedError for norb >= 64, though the FCI routines the exact method uses (contract_2e, make_hdiag) work there. Address each string by its position in PySCF's own make_strings list instead, which is in address order and returns occupied-orbital lists from 64 orbitals on. method="auto" can reach the exact method at that size, as a full space of a few electrons in 64+ orbitals fits under exact_limit. Tested with H2 embedded at orbitals 30 and 64 of 65 against H2 alone. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…r floor
variance() and variance.py take observable ("both", "variance" or "pt2"),
first_batch (the first batch's ID, so a later call adds independent batches
instead of repeating them) and minimum_abs_denominator (refuse a PT2 with a
near-zero denominator), all passed straight to upstream's evaluator, which
already accepted them. Each batch's ID is recorded in the result. The README
names upstream's gdb-stat-evaluator as the method and describes the options.
Tests: the same batch ID repeats a batch and later IDs give new draws; the
unrequested observable is NaN; an impossible denominator floor is refused;
and, under MPI, a GDB state saved by every rank is analysed on half of them,
as upstream's own test reads 2 saved shards on 4 ranks.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
On the Thrust backend, _create_sbd_config applied DeviceConfig after sbd_config, and DeviceConfig always wrote use_precalculated_dets and max_memory_gb_for_determinants from its own defaults. A value set in sbd_config was reset, so run_sqd_sbd.py and run_sqd_enlarge_subspace_sbd.py ignored --sbd_use_precalculated_dets and --sbd_max_memory_gb_for_determinants. DeviceConfig is now applied first and writes only the arguments it was given; those two arguments are deprecated in favour of sbd_config, which takes precedence over them. Also bind upstream's Thrust-only TPB field thrust_collapse_loops, present at the vendored pin but not exposed, with --thrust_collapse_loops in run_sbd_diag.py and --sbd_thrust_collapse_loops in the two SQD drivers. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Upstream SBD has no OpenMP-offload GDB code, so gdb_diag on the gpu-omp module ran entirely on the host while a GPU had been asked for; only run_gdb_diag.py warned. gdb_diag now raises ValueError on that module, and run_gdb_diag.py and run_gdb_heatbath.py exit with an error for --device gpu-omp, or auto resolving to it, pointing at cpu, or gpu (Thrust, NVIDIA GPUs only). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… cpu_subspace - vendor/sbd-upstream moves from 93ebabe to r-ccs-cms/sbd 95bf45a (25 commits): the opposite-spin 2-RDM sign fix (#98), Davidson/Lanczos subspace refactor and TPB performance work (#95, #99), the CAOP stat evaluator (#94) and the CAOP spectrum app (#96, #100). - Upstream's Thrust builds now MPI_Abort the job when omp_get_max_threads() is 1, which ends Python with nothing to catch. tpb_diag, tpb_diag_from_files and gdb_diag on Thrust raise ValueError on every rank first instead. - TPB_SBD.cpu_subspace and GDB_SBD.cpu_subspace (Thrust only, as upstream declares them): keep the Davidson (and TPB's Lanczos) subspace vectors in host memory instead of GPU memory, as upstream's apps' --cpu_subspace. - Tests: test_rdm_open_shell.py, the opposite-spin 2-RDM block on upstream's H3 doublet against PySCF, which fails at the old pin on every backend and passes now; test_openmp_threads.py, the one-thread refusal on Thrust; test_cpu_subspace.py, the same energy with cpu_subspace on and off for TPB and GDB, and the field present on the Thrust backend only. Also expose it in the drivers as --cpu_subspace / --sbd_cpu_subspace; it is ignored on the backends that do not have it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…he FCIDUMP
Upstream SBD selects spin-dependent integrals at compile time (-D_UHF): the
FCIDUMP is read with interleaved spin-orbital indices, NORB staying the number
of spatial orbitals. A UHF build is therefore a separate module.
- setup.py builds _core_cpu_uhf and _core_gpu_thrust_uhf next to the existing
backends: the same Extension under a new name, plus -D_UHF.
SBD_BUILD_UHF=0 skips them. OpenMP offload gets no twin, because its device
kernels read the restricted integral layout regardless of _UHF.
- The package registers them as 'cpu-uhf' and 'gpu-uhf' ('auto' never picks
them). sbd.fcidump_format() tells the two layouts apart (any index above
NORB), LoadFCIDump tags the FCIDump it returns, and tpb_diag,
tpb_diag_from_files and gdb_diag dispatch to the matching build.
get_backend(..., uhf=True) refuses gpu-omp.
- FCIDump and the config structs are the same C++ types in both builds, so
configs and FCIDUMP objects pass between them. That is also why the format
check has to live in Python: nothing at the binding level stops a UHF
FCIDump reaching the restricted solver.
Checked against PySCF UHF-FCI: H3 doublet (9 dets) on cpu and gpu; NH2/6-31G
(920,205 dets) on cpu and gpu at 1 rank and 2x2; GDB on H3 under -D_UHF. The
existing suite still passes. SQD-loop integration (solve_sci) is not included.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Replaces the stored format record with a classification computed from the integrals each time, so it cannot go stale when a caller edits them after loading. The check runs in C++ over the integrals in place (no copy into Python): ~1 ms per call at 500k entries, below 0.1% of any real diagonalization, and LoadFCIDump is back to main's cost (the Python text scan it replaces was 0.19 s at c4h4). - tpb_diag, gdb_diag and tpb_diag_from_files bindings each refuse integrals of the other layout, voting across ranks, so calling a backend module directly can no longer diagonalize the wrong layout silently. - Files in neither layout are refused: an index above 2*NORB, a spin-mixed (ij)/(kl) pair above NORB (typically a wrong NORB), or a UHF/IUHF header flag. - available_backends()/backend_load_errors() list devices only; the twin names are refused as devices; new sbd.has_uhf(device); LoadFCIDump(uhf=...) states the layout and raises on a mismatch. - LoadFCIDump returns the same object as on main; no dynamic attributes. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…mp too - run_sbd_diag.py checks the determinant files' electron counts against NELEC/MS2 before diagonalizing. Symmetric mode reuses the alpha list as beta, so on any open-shell system (MS2 != 0, restricted or unrestricted) it used to return the energy of a different charge state without an error. Rank 0 reads, every rank raises. - run_gdb_heatbath.py loads through sbd.LoadFCIDump, so a file in neither layout, or an unrestricted one on gpu-omp, fails at load; it reports the layout it found. - sbd.fcidump_format() accepts a loaded FCIDump as well as a path, and LoadFCIDump/tpb_diag_from_files accept path-like file names. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- examples/uhf/make_uhf_fcidump.py writes, from one PySCF run, a UHF FCIDUMP in SBD's unrestricted layout, the ROHF twin in the restricted one, the full alpha/beta string lists and reference.json with the exact energy. Its write_uhf_fcidump() is reusable for other integrals. - examples/uhf/nh2: NH2/6-31G, 13 orbitals, 920,205 determinants, E_FCI -55.633361496218 (~280 KB). Both drivers run it; README shows how. - test/data/uhf: the H3 doublet (6 KB), E_FCI -1.588486422874. - test/test_uhf.py: layout classification and refusals, full-space TPB and GDB energies from both layouts, the HF determinant giving each SCF energy, edited integrals classified afresh, every binding refusing the other layout when called directly, the TPB driver's electron-count check, two MPI tests and a slow NH2 full-space test. Passes on cpu (laptop, h100) and gpu (h100), single process and 2 ranks. - tox passes SBD_BUILD_UHF through; the sdist ships the example data. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
H3's full space split over b_comm_size = the rank count, so the helper dimension stays at 1 and the test runs on Thrust too. Verified more widely by hand on h100 with NH2 (920,205 determinants): b = 2 and 4, t = 2, a helper dimension of 2 on CPU, and the input, equal-bra-a and grid-cyclic distributions all give the exact energy on cpu and gpu, ranks agreeing; and the heatbath driver from one 400-determinant seed gives an identical dimension and energy series at b = 1, 2 and 4. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
variance() took the PT2 reference energy as optional and, for the stochastic method, recomputed it from the saved state with a zero-iteration gdb_diag. That recompute is redundant -- the diagonalization that saved the state returned the energy -- and it ties variance() to a GDB solve, which the OpenMP-offload backend cannot run. Upstream's evaluator takes the energy as a required input (--reference-energy), as caop_variance does here. The energy is now a required argument of variance() and --energy a required flag of examples/analysis/variance.py. state_energy() stays, for checking that a state and an FCIDUMP belong together; variance() no longer calls it. The test helper that saves GDB states skips when gdb_diag refuses the backend, so the tests keep running wherever GDB does. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…metry test variance() on a state solved with an unrestricted FCIDUMP now takes the evaluator from the -D_UHF build, whose integrals are spin-resolved, as upstream's gdb-stat-evaluator-uhf does; the CPU unrestricted build has it (it is built without SBD_THRUST). The exact method builds restricted integrals for PySCF, so it refuses an unrestricted FCIDUMP with a clear message. Builds on the rebased uhf-support commits (unrestricted TPB/GDB, built by default, SBD_BUILD_UHF=0 to skip) and on #80 (sbd.analysis). Tests: - A broken-symmetry UHF state, as BS-UHF-SQD starts from: stretched H4 with alpha and beta on alternate atoms (<S^2> checked). Its full space through the unrestricted solver gives PySCF's FCI energy; over a subspace, the stochastic variance and PT2, averaged over seeds, match the exact values from PySCF's fci.direct_uhf applying the same integrals. - Upstream's own UHF evaluator fixture (make_cli_fixture.cc) never reaches a beta index, so it is also a valid restricted file and is classified as one; stating uhf=True is refused. The test pins that. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Upstream's Thrust GDB solve waits forever in its ring exchange when a b_comm shard is empty. Placement can empty a shard the caller filled: equal-bra-a, the default, deals out whole alpha strings, so fewer distinct alpha strings than b_comm_size leaves ranks with nothing. Check every rank after placement and raise on all of them together. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- test_sharded_gdb_is_exact passes determinant_distribution='input', as its docstring says: equal-bra-a deals out whole alpha strings, and the test space has three, so from four ranks on it emptied a shard and the Thrust solve, now refused, hung. It skips on every rank together when there are more ranks than determinants. - Top README: UHF in the feature list. The UHF README points to the solve and check folders, not to a workflow page this branch does not have. - No OpenMPI-only mpirun -x in the READMEs and driver docstrings. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
run_sbd_diag.py --rdm_output saves rdm1/rdm2 summed over spin, as upstream SBD writes them. For a UHF FCIDUMP the alpha and beta blocks are in different orbitals, so the eigenvalues of their sum are not occupations: the driver now prints a note pointing to the per-spin one_p_rdm/two_p_rdm of sbd.tpb_diag instead. The UHF README's limits say the same, and the UHF driver test runs with --rdm_output. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…d name The test covers a UHF state whose alpha and beta orbitals differ; to SBD that is any UHF FCIDUMP. Drop the broken-symmetry / BS-UHF-SQD wording from it and from the variance release note: it named another workflow's starting point rather than anything the wrapper does differently. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ves to examples/tools Upstream organizes apps by solver and tool, and -D_UHF is a build of the TPB and GDB apps, not an app of its own. So examples/uhf goes: - examples/tpb/README.md and examples/gdb/README.md open with the same note: the FCIDUMP may be restricted or UHF, and the API picks the matching build. The TPB README gains one section with the layout, how to make a file, and the limits; the GDB README links to it and runs the heat-bath driver on a UHF file. - make_uhf_fcidump.py moves to examples/tools/. The committed NH2 data goes: the script writes it (PySCF is the user's to install), and the README commands start by running it. test_nh2_example_full_space_is_exact, which only guarded that data, goes with it; the H3 tests cover the same correctness. - MANIFEST.in, the top README, INSTALL.md, the API docs and the release note point to the new places. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> # Conflicts: # docs/apidocs/sbd.rst # examples/gdb/run_gdb_diag.py # examples/tpb/README.md # examples/tpb/run_sbd_diag.py # examples/tpb/run_sqd_enlarge_subspace_sbd.py # examples/tpb/run_sqd_sbd.py # python/bindings.cpp
# Conflicts: # README.md # examples/analysis/README.md # examples/analysis/variance.py # python/analysis.py
The stretched-H4 UHF subspace is solved with GDB over every rank and evaluated from those shards; the result must match PySCF's exact values. Rank 0 builds the integrals, so every rank uses the same orbitals. Its setup moves into helpers the single-process test shares. Skipped where the device under test has no UHF build. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
# Conflicts: # python/bindings.cpp
# Conflicts: # README.md # docs/apidocs/sbd.rst
…uator
loaded_backends() lists the unrestricted builds ('cpu-uhf', 'gpu-uhf'), which are
separate modules but not device names. The evaluator search passed every loaded name
to get_backend, so variance() or caop_variance() of a restricted state, run after a
UHF solve on 'gpu' in the same process, raised "'gpu-uhf' is not a device name". On
'cpu' it passed only because 'cpu' is listed first and has the evaluator.
The search now skips them; a restricted state is evaluated by a restricted module in
any case. Tests: the stand-in selection test gains loaded-UHF cases, and a subprocess
test runs a UHF solve then restricted variance in one process, against the same
variance without the UHF solve.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…OTING and the API docs The README had grown to over 400 lines, most of it reference: an API section that repeated docs/apidocs by hand, backend internals, and troubleshooting. It now says what the package does, its backends, how to install it, the SQD integration and where the examples are, and links the rest. - API Reference: removed. docs/apidocs/sbd.rst already documents every config field and the diagonalization functions; the backend and MPI helpers it lacked (is_initialized, get_device, loaded_backends, has_backend_conflict, print_info, get_comm, get_comm_backend, barrier) are added there. tpb_diag's docstring gains the text-dump precision note, print_info's says it lists the UHF builds. - Backend Architecture: the GPU-aware MPI fallbacks and the binary architecture check move to INSTALL.md (a new "GPU-aware MPI" section, and "Verify"); the vendor-neutral gpu-omp note goes in the README's backend table; GPU assignment goes to TROUBLESHOOTING.md. - Troubleshooting: moved unchanged to TROUBLESHOOTING.md. - SQD integration: the snippet and its requirements stay, with the TPB-only reason; carryover, Trim SQD and the enlargement driver are linked to examples/tpb/. Links into the removed sections (INSTALL.md, docs/index.rst, examples/tpb/README.md) are updated, and pyproject.toml's Documentation URL now points at the docs site. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…t raises "Refused" described the error but not what the reader can do. Where a sentence says what a backend supports, it now says "not supported", why, and that asking for it raises an error rather than running on the host. Sentences about the error behaviour itself keep "refused". The README's table cell also no longer says upstream has no offload code for UHF: its offload kernels exist but read only the restricted integral layout. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
available_backends() does not list the unrestricted builds, so Verify now shows has_uhf() for each backend, with the default and SBD_BUILD_UHF=0 results, and that print_info() reports the same. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…fusals Entries are now grouped from a failed build, through a crashed job and a solve that refuses to start, to one that runs but not as intended. Two entries are added for refusals users meet first: one OpenMP thread on the Thrust backend, and GDB, CAOP or a UHF FCIDUMP on gpu-omp. The separate GPU-assignment note is merged into the "every rank on GPU 0" entry it duplicated, and the bus-error entry points to INSTALL.md's GPU-aware MPI section. INSTALL.md's See Also no longer lists the TPB README: backend selection is now in the top-level README, and test data and performance notes are not install topics. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…s, not h2o TPB fixes its determinant word count for the life of a process. The test solved the H3 UHF fixture (one word per half) and then h2o (24 orbitals: two words at bit_length 20), so the second solve failed with "det_vector: elem_size mismatch" on a CPU-only build, before reaching the evaluator the test is about. Its docstring had wrongly said both are one word. The restricted state is now the same molecule's ROHF fixture, also one word. It still fails on 'gpu' without the evaluator fix. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Sophia Wen (hfwen0502)
added a commit
that referenced
this pull request
Nov 10, 2026
* examples: UHF on gpu, how the UHF build is chosen, a runnable --initial_det, workflow links Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * README: why the SQD integration is TPB only, citing Qiskit/qiskit-sqd#389 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * README: why use the bindings rather than upstream's apps Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * READMEs: trim, launch on several ranks or GPUs, and say what the bindings pick for you Every README from the top level down. Commands now run on several ranks or one rank per GPU wherever the step parallelizes; single-process ones are left where the step is serial. Long explanations of upstream internals are cut to what a user acts on, and repeated warnings appear once. The top-level README says the bindings choose the code path themselves -- the UHF build from the FCIDUMP, the CPU evaluator after an offload solve -- and that a feature a device does not support raises an error naming the device to use. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * examples README: only the pinned upstream is tested; drop SBD_BUILD_UHF from INSTALL Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Drop SBD_BUILD_UHF everywhere: no release ever had it It was added in #91 and removed in #93, both after 1.7.2, so the next release should neither introduce it nor say it is gone. setup.py no longer warns about it, and the two unreleased notes no longer mention it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * docs: front page matches the README; sbd page covers CAOP and device= The docs front page gains "What it does" and the reason for the bindings, the README's feature-by-backend table in place of the device-only one, why the SQD loop is TPB only (Qiskit/qiskit-sqd#389), and the pinned-upstream caveat for the examples. Its separate TPB-or-GDB section folds into "What it does". The sbd API page's intro now names CAOP and says what device= does and that an unsupported device raises an error naming the ones that do. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * analysis README: variance works for restricted and UHF FCIDUMPs alike Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * analysis README: organized by use case, covering both evaluators and extrapolate.py It opened with the TPB/GDB evaluator only and reached CAOP and extrapolate.py late or in passing. It now starts with the two tools and a table of which upstream evaluator each kind of state uses and with which methods, then one section per task: check a molecular state, check a CAOP state, estimate the exact energy from a series, compare two ways of growing a subspace, and run it in the same job. How the estimate works and its settings follow. The other READMEs' links follow the renamed sections. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * examples README: a too-small CAOP basis leaves PT2 well short, not most of the way Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * analysis README: drop the TPB-vs-GDB growth comparison It compared two solvers' expansion schemes rather than showing the analysis, and its own notes said none of its states had converged. Its one lesson for the analysis, comparing subspaces at matched dimension by variance and E + PT2, is now a sentence under the series section. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Adds unrestricted (UHF) Hamiltonians to the TPB and GDB solvers, and restructures the top-level README, which had grown past 400 lines.
Unrestricted (UHF) FCIDUMPs
NORBspatial orbitals, integrals indexed by interleaved spin orbitals — goes throughsbd.LoadFCIDump,tpb_diag,gdb_diagandtpb_diag_from_filesexactly like a restricted one, and through the TPB and GDB drivers. Each call reads the layout from the integrals and runs the matching build.cpuandgpu(Thrust) backends are each also built with upstream's-D_UHF, assbd._core_cpu_uhfandsbd._core_gpu_thrust_uhf.SBD_BUILD_UHF=0skips them; an unrestricted file is then refused with an error naming that variable.gpu-omphas no unrestricted build, since its offload kernels read only the restricted layout, and refuses such a file.sbd.fcidump_format()says whether a file is'restricted'or'uhf';sbd.has_uhf(device)whether a device has an unrestricted build;LoadFCIDump(..., uhf=True|False)states the layout and raises if the file is the other one.available_backends()is unchanged and lists the restricted backends only.2 * NORB, unrestricted indices whose pairs mix spins (usually a wrongNORB), or aUHF/IUHFheader flag from another program's layout.run_sbd_diag.pychecks the determinant files' electron counts againstNELECandMS2: in its default symmetric mode it reused the alpha list as the beta one, so an open-shell system diagonalized a different charge state without an error.sbd.analysis.variance()accepts a UHF state: its stochastic method runs upstream's evaluator from the unrestricted build, as upstream'sgdb-stat-evaluator-uhfdoes. The exact method is restricted-only and says so.examples/tools/make_uhf_fcidump.pywrites unrestricted FCIDUMPs from PySCF, and itswrite_uhf_fcidumpany spin-resolved integrals in SBD's layout. No generated data is shipped beyond the unit tests' fixtures; users make their own with the script.LoadFCIDumpandtpb_diag_from_filesacceptpathlib.Pathnames.A fix found while testing this branch.
loaded_backends()lists the unrestricted builds, which are not device names, and the variance evaluator's search passed every loaded name toget_backend. Variance of a restricted state, run after a UHF solve ongpuin the same process, raised'gpu-uhf' is not a device name. The search now skips them.README restructured
The README is now a front page: what the package does, its backends, installation, the SQD integration and the examples, with the rest linked.
docs/apidocsby hand and had drifted. The backend and MPI helpers the API page lacked (loaded_backends,print_info,barrier, …) are added there.INSTALL.md(new GPU-aware MPI section, and Verify, which now also shows how to check the UHF builds).TROUBLESHOOTING.md, grouped by severity, with entries for the one-thread Thrust refusal and for whatgpu-ompdoes not support.gpu-omp"does not support" GDB, CAOP and UHF files, and asking for one raises an error.pyproject.toml's Documentation URL now points at the docs site.Tests
test_uhf.py: TPB and GDB on upstream's H3 UHF fixture and its ROHF twin, against PySCF's FCI energy; how files are classified; the refusals, on every rank under MPI; sharded GDB on both layouts under MPI.test_uhf_analysis.py: the variance and PT2 of a UHF subspace of stretched H4, whose alpha and beta orbitals differ, against exact values from PySCF'sdirect_uhf, in one process and with the state saved over every rank under MPI; upstream's evaluator fixture classified as restricted; and the fix above: a UHF solve, then restricted variance, in one process.test_analysis.py: the evaluator-selection test covers loaded unrestricted builds.The docs build without warnings.
🤖 Generated with Claude Code