Skip to content

Arc-based Clone for LibXCFunctional; graceful libxc 6.x ext-param handling; CPU version-matrix CI - #2

Merged
ajz34 merged 4 commits into
RESTGroup:mainfrom
ajz34:feat/arc-clone-functional
Sep 9, 2026
Merged

ajz34 merged 4 commits into
RESTGroup:mainfrom
ajz34:feat/arc-clone-functional

Conversation

@ajz34

@ajz34 ajz34 commented Sep 9, 2026

Copy link
Copy Markdown
Member

Summary

  • LibXCFunctional is now Clone: clones are reference-counted (Arc) handles to the same underlying C functional — no FFI-level re-initialization — so a functional can be shared across rayon workers lock-free. The unsafe Send/Sync impls moved to the private owning handle, with soundness argued from libxc's const xc_func_type * read-side API.
  • All mutating setters now require Arc uniqueness: while any clone is alive they return LibXCError::SharedError (non-_f variants panic). Threshold setters gained fallible _f variants.
  • Graceful handling of ext-param value getters on libxc < 7.0 (xc_func_get_ext_params* does not exist there): new LibXCError::UnsupportedVersion instead of an opaque panic/segfault; describe() degrades to defaults; set_ext_param_map seeds from defaults (matches 6.x semantics).
  • LibXCError marked #[non_exhaustive]; version bumped to 0.1.4.
  • CI: replaced the single v7.0 workflow with a CPU test matrix over conda-forge libxc 6.2.2 / 7.0.0 / 7.1.2, each pinned via LIBXC_DYLOAD with its matching api-vX_Y feature set.

Test plan

  • Local: 7.0.0 default (77 passed), 7.1.2 (api-v7_1, 0 failed), 6.2.2 clean-env (35 general + 41 doctests), CUDA (cuda,api-v7_1 full suite)
  • Local: cargo fmt --check
  • CI test-cpu matrix green on 6.2.2 / 7.0.0 / 7.1.2
  • CI clippy/rustfmt green

ajz34 and others added 4 commits September 9, 2026 12:14
LibXCFunctional now holds its raw `xc_func_type` behind an Arc in a private
LibXCFuncRaw handle (which owns the Drop and the unsafe Send/Sync impls):

- Clone is cheap and shares the C object (no FFI-level re-initialization);
  the object is released when the last handle drops.
- Sharing for parallel evaluation is lock-free: all libxc read/compute entry
  points take `const xc_func_type *` and do not write through it, so
  concurrent compute/getters through clones are data-race-free (verified
  against the libxc dispatch sources).
- To keep this sound with Clone, every mutating setter now additionally
  requires Arc uniqueness (checked via Arc::get_mut): while any clone is
  alive, setters fail with the new LibXCError::SharedError (or panic, for
  the non-`_f` variants). Threshold setters gained fallible `_f` variants
  following the crate convention.

Add tests/general/test_clone.rs covering: shared identity of clones,
rayon parallel evaluation (LDA/GGA/hybrid/MGGA, both sharing by reference
and cloning into jobs), raw OS-thread sending, setter exclusivity, and
static Send/Sync assertions. Update ARCHITECTURE.md accordingly.

Co-authored-by: Claude Code <noreply@anthropic.com>
Co-authored-by: glm-5 <service@zhipuai.cn>
The xc_func_get_ext_params* getters were introduced in libxc v7.0 (see
versioning_xc.md); libxc 6.x keeps current values only in per-functional
storage with no uniform read-back (its own by-name setter passes the
XC_EXT_PARAMS_DEFAULT sentinel for unspecified parameters). Reading
current values on a 6.x library therefore panicked with an opaque
Option::unwrap from the dyload shim — and segfaulted outright when a
second libxc version was also discoverable (e.g. a conda env), because
symbols resolved from both libraries mix ABI layouts.

- Add LibXCError::UnsupportedVersion { needed, found }.
- ext_param_values/ext_param_map gain fallible _f variants that return
  UnsupportedVersion on libxc < 7.0; the non-_f variants panic with a
  clear version message instead of the dyload unwrap.
- describe() degrades to default ext-param values (with a note) on
  libxc < 7.0 instead of panicking.
- set_ext_param_map falls back to defaults as the base map on libxc < 7.0,
  matching libxc 6.x semantics where setting one parameter resets the
  others to defaults.
- Guard read-back assertions in doctests and tests by version; add
  test_ext_param_values_version_behavior.

Validated against 7.0.0, 7.1.2, and 6.2.2 (clean environment: unset
CONDA_PREFIX so the conda libxc is not mixed in).

Co-authored-by: Claude Code <noreply@anthropic.com>
Co-authored-by: glm-5 <service@zhipuai.cn>
…l doc

- LibXCError is now #[non_exhaustive]: new variants (SharedError,
  UnsupportedVersion were just added) may arrive in patch releases, so
  downstream matches should include a wildcard arm. With this in place,
  variant additions are no longer API-breaking.
- Bump workspace version to 0.1.4 (libxc and libxc-ffi share it) and add
  the v0.1.4 changelog entry (Arc-based Clone with sound lock-free
  Send/Sync, setter exclusivity via SharedError, graceful <7.0 ext-param
  value getters via UnsupportedVersion).
- cuda-testing skill doc: correct the claim that the `cuda` feature
  implies `api-v7_1` (it does not; `cuda = ["dep:cudarc"]`). Running the
  default api-v7_0 bindings against a v7.1+ CUDA library makes every
  functional report OnDevice (xc_func_init defers to the build's default
  flags), failing the CPU-guard tests. Document the correct invocation:
  `--features cuda,api-v7_1` (verified: full suite passes against
  7.1.2-cuda).

Co-authored-by: Claude Code <noreply@anthropic.com>
Co-authored-by: glm-5 <service@zhipuai.cn>
Replace the single-version v7.0 workflow with a matrix that installs a
pinned conda-forge libxc per leg and points LIBXC_DYLOAD at it, testing
each version against its matching api-vX_Y feature set.

Co-authored-by: Claude Code <noreply@anthropic.com>
Co-authored-by: glm-5.3-flash <service@zhipuai.cn>
@ajz34
ajz34 merged commit 817d0de into RESTGroup:main Sep 9, 2026
5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant