From b5ed2faf4468e57200ad2d91a0f21551ff9e4ab3 Mon Sep 17 00:00:00 2001 From: ajz34 Date: Tue, 8 Sep 2026 21:02:18 +0800 Subject: [PATCH 1/4] Fix libxc 6.2.x support: feature isolation, mGGA tau scratch, needs_tau fallback - Cargo: the workspace libxc-ffi dependency now sets default-features = false, so api-version features are selected exclusively through the libxc crate's features. Previously libxc-ffi's own defaults (api-v7_0 + dynamic_loading) were always unified in, and --no-default-features --features api-v6_2,dynamic_loading silently compiled the v7.0 struct layout of xc_func_type, reading garbage when a v6.2.2 shared library was loaded at runtime. - mGGA tau handling for libxc < 7.0: XC_FLAGS_NEEDS_TAU only exists in v7.0+. libxc 6.2.x reads the tau input for every meta-GGA functional, and xc_mgga_sanity_check aborts the process (exit(1)) when a tau-family output of a requested derivative order is NULL. The wrapper now falls back to the functional family in needs_tau() for < 7 libraries (mirrors pylibxc 6.2.2), substitutes zeroed scratch for null lapl/tau inputs, and allocates zeroed scratch (MggaExtraPtrs) for tau-family outputs missing from the layout or output pointer map. CUDA paths pass an empty map: 6.2.x has no GPU support, and v7.0+ gates tau on the flag. - tests: needs_tau assertion gated to v7+ libraries. Validated against 6.2.2/7.0.0/7.1.2 CPU and 7.0.0/7.1.2 CUDA shared libraries (full cargo test matrix, mGGA compute tests included). Co-authored-by: Claude Code Co-authored-by: glm-5.3 --- Cargo.toml | 8 +- libxc/src/compute_cpu.rs | 32 +++- libxc/src/compute_cuda.rs | 12 +- libxc/src/functional.rs | 14 +- libxc/src/layout_handling.rs | 247 +++++++++++++++++-------- libxc/tests/general/test_functional.rs | 5 +- 6 files changed, 239 insertions(+), 79 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index e0bd25a..e99d4c3 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -15,4 +15,10 @@ categories = ["science"] license = "Apache-2.0" [workspace.dependencies] -libxc-ffi = { path = "libxc-ffi", version = "0.1.2" } +# default-features = false: the api-version features (api-v6_2/v7_0/v7_1) and +# dynamic_loading must be selected exclusively through the `libxc` crate's +# features. Otherwise libxc-ffi's own defaults (api-v7_0 + dynamic_loading) +# are always unified in, and e.g. `--features api-v6_2` would still compile +# the v7.0 struct layout of `xc_func_type` — which reads out of bounds when +# a v6.2.2 shared library is loaded at runtime. +libxc-ffi = { path = "libxc-ffi", version = "0.1.2", default-features = false } diff --git a/libxc/src/compute_cpu.rs b/libxc/src/compute_cpu.rs index 3d39637..0f3ed1c 100644 --- a/libxc/src/compute_cpu.rs +++ b/libxc/src/compute_cpu.rs @@ -114,6 +114,16 @@ fn validate_output_ptrs( Ok(ptrs) } +/// Zeroed scratch buffer for a conditionally-required mGGA input. +/// +/// libxc 6.2.x reads the tau input array for every meta-GGA functional (the +/// `XC_FLAGS_NEEDS_TAU` guard only exists in v7.0+), so a null pointer there +/// would crash the process. Zeroed scratch keeps v6.2.x working; v7.0+ +/// functionals that do not need tau simply never read it. +fn input_scratch(dim_value: i32, npoints: usize) -> Vec { + vec![0.0; (dim_value.max(0) as usize) * npoints] +} + impl LibXCFunctional { // -- LDA private helpers ----------------------------------------------- @@ -352,6 +362,12 @@ impl LibXCFunctional { output.len() ))); } + let dim = self.dim(); + let lapl_scratch = input_scratch(dim.lapl, npoints); + let tau_scratch = input_scratch(dim.tau, npoints); + let lapl_ptr = if lapl_ptr.is_null() { lapl_scratch.as_ptr() } else { lapl_ptr }; + let tau_ptr = if tau_ptr.is_null() { tau_scratch.as_ptr() } else { tau_ptr }; + let (_scratch_bufs, extra) = crate::layout_handling::mgga_tau_scratch(&layout, dim, npoints); unsafe { xc_mgga_call( self.ptr, @@ -362,6 +378,7 @@ impl LibXCFunctional { tau_ptr, output.as_mut_ptr(), &layout, + &extra, ); } Ok(layout) @@ -382,6 +399,12 @@ impl LibXCFunctional { let (npoints, rho_ptr, sigma_ptr, lapl_ptr, tau_ptr, layout) = self.mgga_prepare(input, flags)?; let mut buffer = vec![0.0f64; layout.total_size]; + let dim = self.dim(); + let lapl_scratch = input_scratch(dim.lapl, npoints); + let tau_scratch = input_scratch(dim.tau, npoints); + let lapl_ptr = if lapl_ptr.is_null() { lapl_scratch.as_ptr() } else { lapl_ptr }; + let tau_ptr = if tau_ptr.is_null() { tau_scratch.as_ptr() } else { tau_ptr }; + let (_scratch_bufs, extra) = crate::layout_handling::mgga_tau_scratch(&layout, dim, npoints); unsafe { xc_mgga_call( self.ptr, @@ -392,6 +415,7 @@ impl LibXCFunctional { tau_ptr, buffer.as_mut_ptr(), &layout, + &extra, ); } Ok((buffer, layout)) @@ -419,10 +443,16 @@ impl LibXCFunctional { let lapl_ptr = conditional_input_ptr(input, "lapl", npoints, dim.lapl, needs_lapl)?; let tau_ptr = conditional_input_ptr(input, "tau", npoints, dim.tau, needs_tau)?; let ptrs = validate_output_ptrs(output, &MGGA_OUTPUT_LABELS, npoints, dim)?; + let lapl_scratch = input_scratch(dim.lapl, npoints); + let tau_scratch = input_scratch(dim.tau, npoints); + let lapl_ptr = if lapl_ptr.is_null() { lapl_scratch.as_ptr() } else { lapl_ptr }; + let tau_ptr = if tau_ptr.is_null() { tau_scratch.as_ptr() } else { tau_ptr }; + let (_scratch_bufs, extra) = + crate::layout_handling::mgga_tau_scratch_from_ptrs(&ptrs, dim, npoints); unsafe { xc_mgga_call_with_output( - self.ptr, npoints, rho_ptr, sigma_ptr, lapl_ptr, tau_ptr, &ptrs, + self.ptr, npoints, rho_ptr, sigma_ptr, lapl_ptr, tau_ptr, &ptrs, &extra, ); } Ok(()) diff --git a/libxc/src/compute_cuda.rs b/libxc/src/compute_cuda.rs index c5e2197..0aa70ed 100644 --- a/libxc/src/compute_cuda.rs +++ b/libxc/src/compute_cuda.rs @@ -407,6 +407,10 @@ impl LibXCFunctional { let mut buffer = stream .alloc_zeros::(layout.total_size) .map_err(|e| LibXCError::CudaError(format!("CUDA allocation failed: {e}")))?; + // No tau-family scratch pointers on device: libxc 6.2.x (the only + // version requiring them) has no GPU support at all, and host pointers + // must never reach a device-side evaluator. + let extra = crate::layout_handling::MggaExtraPtrs::new(); { let (output_base, _sync) = buffer.device_ptr_mut(stream); unsafe { @@ -419,6 +423,7 @@ impl LibXCFunctional { tau_ptr, output_base as *mut f64, &layout, + &extra, ); } } @@ -444,6 +449,8 @@ impl LibXCFunctional { ))); } let (output_base, _sync) = output.device_ptr_mut(&stream); + // No tau-family scratch pointers on device (see cuda_compute_mgga). + let extra = crate::layout_handling::MggaExtraPtrs::new(); unsafe { xc_mgga_call( self.ptr, @@ -454,6 +461,7 @@ impl LibXCFunctional { tau_ptr, output_base as *mut f64, &layout, + &extra, ); } Ok(layout) @@ -487,10 +495,12 @@ impl LibXCFunctional { let tau_ptr = conditional_cuda_input_ptr(input, "tau", npoints, dim.tau, needs_tau, stream)?; let ptrs = validate_cuda_output_ptrs(output, &MGGA_OUTPUT_LABELS, npoints, dim, stream)?; + // No tau-family scratch pointers on device (see cuda_compute_mgga). + let extra = crate::layout_handling::MggaExtraPtrs::new(); unsafe { xc_mgga_call_with_output( - self.ptr, npoints, rho_ptr, sigma_ptr, lapl_ptr, tau_ptr, &ptrs, + self.ptr, npoints, rho_ptr, sigma_ptr, lapl_ptr, tau_ptr, &ptrs, &extra, ); } Ok(()) diff --git a/libxc/src/functional.rs b/libxc/src/functional.rs index b6f500d..a181ad0 100644 --- a/libxc/src/functional.rs +++ b/libxc/src/functional.rs @@ -534,8 +534,20 @@ impl LibXCFunctional { /// # PyLibxc counterpart /// /// `LibXCFunctional._needs_tau` + /// + /// # Notes + /// + /// `XC_FLAGS_NEEDS_TAU` was introduced in libxc v7.0. When loading an + /// older (v6.2.x) library, the flag is never reported, but those versions + /// still read tau for every meta-GGA functional and pylibxc 6.2.2 + /// likewise treats tau as always required for mGGAs. For such libraries + /// this method therefore falls back to the functional family. pub fn needs_tau(&self) -> bool { - self.has_flag(LibXCFlags::NeedsTau) + if crate::util::libxc_version().0 < 7 { + matches!(self.family(), LibXCFamily::MGGA | LibXCFamily::HybMGGA) + } else { + self.has_flag(LibXCFlags::NeedsTau) + } } /// Whether this is a CAM range-separated hybrid. diff --git a/libxc/src/layout_handling.rs b/libxc/src/layout_handling.rs index 162c0f7..dda8d27 100644 --- a/libxc/src/layout_handling.rs +++ b/libxc/src/layout_handling.rs @@ -530,13 +530,96 @@ pub(crate) unsafe fn xc_gga_call_with_output( ); } +/// Extra output pointers for mGGA labels absent from the layout or pointer +/// map. +/// +/// libxc 6.2.x unconditionally requires every tau-family output buffer of a +/// requested derivative order to be non-NULL, even when the functional does +/// not use tau (the `XC_FLAGS_NEEDS_TAU` flag was only introduced in v7.0), +/// and it also reads the tau input array for every meta-GGA functional. +/// Passing null pointers there makes libxc abort the whole process +/// (`xc_mgga_sanity_check` calls `exit(1)`). +/// +/// The CPU wrapper therefore allocates zeroed scratch buffers for those +/// labels and passes their pointers here. Device-side (CUDA) callers can +/// pass an empty map: libxc 6.2.x has no GPU support at all, and v7.0+ only +/// requires tau-family buffers when the functional actually needs them. +pub(crate) type MggaExtraPtrs = HashMap<&'static str, *mut f64>; + +/// Build zeroed scratch buffers for the tau-family output labels of every +/// requested derivative order. +/// +/// `present` reports whether an output label will be passed to libxc (either +/// inside the contiguous output buffer or as a dedicated pointer). A +/// tau-family label is only scratched when the primary output of its +/// derivative order is requested; libxc only validates tau-family buffers +/// for the orders that are actually computed. +fn mgga_tau_scratch_impl( + present: &impl Fn(&str) -> bool, + dim: &ffi::xc_dimensions, + npoints: usize, +) -> (Vec>, MggaExtraPtrs) { + const MGGA_ORDER_PRIMARY: [(&str, usize, usize); 5] = [ + ("zk", 0, MGGA_EXC_END), + ("vrho", MGGA_EXC_END, MGGA_VXC_END), + ("v2rho2", MGGA_VXC_END, MGGA_FXC_END), + ("v3rho3", MGGA_FXC_END, MGGA_KXC_END), + ("v4rho4", MGGA_KXC_END, MGGA_LXC_END), + ]; + let mut bufs = Vec::new(); + let mut ptrs = HashMap::new(); + for (primary, start, end) in MGGA_ORDER_PRIMARY { + if !present(primary) { + continue; + } + for &label in &MGGA_OUTPUT_LABELS[start..end] { + if label.contains("tau") && !present(label) { + let d = get_dim(dim, label); + if d > 0 { + bufs.push(vec![0.0f64; (d as usize) * npoints]); + ptrs.insert(label, bufs.last().unwrap().as_ptr() as *mut f64); + } + } + } + } + (bufs, ptrs) +} + +/// Build zeroed scratch buffers for tau-family outputs missing from a +/// contiguous output buffer layout. +pub(crate) fn mgga_tau_scratch( + layout: &LibXCOutputLayout, + dim: &ffi::xc_dimensions, + npoints: usize, +) -> (Vec>, MggaExtraPtrs) { + mgga_tau_scratch_impl(&|label| layout.get(label).is_some(), dim, npoints) +} + +/// Build zeroed scratch buffers for tau-family outputs missing from a +/// named-pointer map. +/// +/// The map may contain null pointers for labels the user did not provide +/// (see `validate_output_ptrs`); only non-null entries count as present. +pub(crate) fn mgga_tau_scratch_from_ptrs( + ptrs: &HashMap<&'static str, *mut f64>, + dim: &ffi::xc_dimensions, + npoints: usize, +) -> (Vec>, MggaExtraPtrs) { + mgga_tau_scratch_impl(&|label| ptrs.get(label).is_some_and(|p| !p.is_null()), dim, npoints) +} + /// Invoke `xc_mgga` FFI call with a contiguous output buffer and layout. /// +/// `extra` supplies output pointers for labels not covered by `layout` +/// (scratch buffers for libxc 6.2.x; see [`MggaExtraPtrs`]). +/// /// # Safety /// /// The caller must ensure that `func_ptr` is a valid `xc_func_type` pointer, /// input pointers are valid for their expected sizes, and `output_base` points -/// to at least `layout.total_size` writable `f64`s. +/// to at least `layout.total_size` writable `f64`s. Pointers in `extra` must +/// be valid for `get_dim(dim, label) * npoints` writable `f64`s and outlive +/// the call. #[allow(clippy::too_many_arguments)] pub(crate) unsafe fn xc_mgga_call( func_ptr: *mut ffi::xc_func_type, @@ -547,10 +630,14 @@ pub(crate) unsafe fn xc_mgga_call( tau_ptr: *const f64, output_base: *mut f64, layout: &LibXCOutputLayout, + extra: &MggaExtraPtrs, ) { let ptr_for = |name: &str| -> *mut f64 { - match layout.get(name) { - Some(range) => output_base.add(range.start), + if let Some(range) = layout.get(name) { + return output_base.add(range.start); + } + match extra.get(name) { + Some(&ptr) => ptr, None => std::ptr::null_mut::(), } }; @@ -637,11 +724,16 @@ pub(crate) unsafe fn xc_mgga_call( /// Invoke `xc_mgga` FFI call with named per-component output pointers. /// +/// `extra` supplies output pointers for labels not covered by `ptrs` +/// (scratch buffers for libxc 6.2.x; see [`MggaExtraPtrs`]). +/// /// # Safety /// /// The caller must ensure that `func_ptr` is a valid `xc_func_type` pointer, /// input pointers are valid for their expected sizes, and each non-null -/// pointer in `ptrs` points to a buffer of the correct size. +/// pointer in `ptrs` points to a buffer of the correct size. Pointers in +/// `extra` must be valid for `get_dim(dim, label) * npoints` writable `f64`s +/// and outlive the call. #[allow(clippy::too_many_arguments)] pub(crate) unsafe fn xc_mgga_call_with_output( func_ptr: *mut ffi::xc_func_type, @@ -651,7 +743,14 @@ pub(crate) unsafe fn xc_mgga_call_with_output( lapl_ptr: *const f64, tau_ptr: *const f64, ptrs: &HashMap<&'static str, *mut f64>, + extra: &MggaExtraPtrs, ) { + let ptr_of_either = |name: &str| -> *mut f64 { + match ptrs.get(name) { + Some(&ptr) if !ptr.is_null() => ptr, + _ => extra.get(name).copied().unwrap_or(std::ptr::null_mut()), + } + }; ffi::xc_mgga( func_ptr, npoints, @@ -659,76 +758,76 @@ pub(crate) unsafe fn xc_mgga_call_with_output( sigma_ptr as *mut f64, lapl_ptr as *mut f64, tau_ptr as *mut f64, - ptr_of(ptrs, "zk"), - ptr_of(ptrs, "vrho"), - ptr_of(ptrs, "vsigma"), - ptr_of(ptrs, "vlapl"), - ptr_of(ptrs, "vtau"), - ptr_of(ptrs, "v2rho2"), - ptr_of(ptrs, "v2rhosigma"), - ptr_of(ptrs, "v2rholapl"), - ptr_of(ptrs, "v2rhotau"), - ptr_of(ptrs, "v2sigma2"), - ptr_of(ptrs, "v2sigmalapl"), - ptr_of(ptrs, "v2sigmatau"), - ptr_of(ptrs, "v2lapl2"), - ptr_of(ptrs, "v2lapltau"), - ptr_of(ptrs, "v2tau2"), - ptr_of(ptrs, "v3rho3"), - ptr_of(ptrs, "v3rho2sigma"), - ptr_of(ptrs, "v3rho2lapl"), - ptr_of(ptrs, "v3rho2tau"), - ptr_of(ptrs, "v3rhosigma2"), - ptr_of(ptrs, "v3rhosigmalapl"), - ptr_of(ptrs, "v3rhosigmatau"), - ptr_of(ptrs, "v3rholapl2"), - ptr_of(ptrs, "v3rholapltau"), - ptr_of(ptrs, "v3rhotau2"), - ptr_of(ptrs, "v3sigma3"), - ptr_of(ptrs, "v3sigma2lapl"), - ptr_of(ptrs, "v3sigma2tau"), - ptr_of(ptrs, "v3sigmalapl2"), - ptr_of(ptrs, "v3sigmalapltau"), - ptr_of(ptrs, "v3sigmatau2"), - ptr_of(ptrs, "v3lapl3"), - ptr_of(ptrs, "v3lapl2tau"), - ptr_of(ptrs, "v3lapltau2"), - ptr_of(ptrs, "v3tau3"), - ptr_of(ptrs, "v4rho4"), - ptr_of(ptrs, "v4rho3sigma"), - ptr_of(ptrs, "v4rho3lapl"), - ptr_of(ptrs, "v4rho3tau"), - ptr_of(ptrs, "v4rho2sigma2"), - ptr_of(ptrs, "v4rho2sigmalapl"), - ptr_of(ptrs, "v4rho2sigmatau"), - ptr_of(ptrs, "v4rho2lapl2"), - ptr_of(ptrs, "v4rho2lapltau"), - ptr_of(ptrs, "v4rho2tau2"), - ptr_of(ptrs, "v4rhosigma3"), - ptr_of(ptrs, "v4rhosigma2lapl"), - ptr_of(ptrs, "v4rhosigma2tau"), - ptr_of(ptrs, "v4rhosigmalapl2"), - ptr_of(ptrs, "v4rhosigmalapltau"), - ptr_of(ptrs, "v4rhosigmatau2"), - ptr_of(ptrs, "v4rholapl3"), - ptr_of(ptrs, "v4rholapl2tau"), - ptr_of(ptrs, "v4rholapltau2"), - ptr_of(ptrs, "v4rhotau3"), - ptr_of(ptrs, "v4sigma4"), - ptr_of(ptrs, "v4sigma3lapl"), - ptr_of(ptrs, "v4sigma3tau"), - ptr_of(ptrs, "v4sigma2lapl2"), - ptr_of(ptrs, "v4sigma2lapltau"), - ptr_of(ptrs, "v4sigma2tau2"), - ptr_of(ptrs, "v4sigmalapl3"), - ptr_of(ptrs, "v4sigmalapl2tau"), - ptr_of(ptrs, "v4sigmalapltau2"), - ptr_of(ptrs, "v4sigmatau3"), - ptr_of(ptrs, "v4lapl4"), - ptr_of(ptrs, "v4lapl3tau"), - ptr_of(ptrs, "v4lapl2tau2"), - ptr_of(ptrs, "v4lapltau3"), - ptr_of(ptrs, "v4tau4"), + ptr_of_either("zk"), + ptr_of_either("vrho"), + ptr_of_either("vsigma"), + ptr_of_either("vlapl"), + ptr_of_either("vtau"), + ptr_of_either("v2rho2"), + ptr_of_either("v2rhosigma"), + ptr_of_either("v2rholapl"), + ptr_of_either("v2rhotau"), + ptr_of_either("v2sigma2"), + ptr_of_either("v2sigmalapl"), + ptr_of_either("v2sigmatau"), + ptr_of_either("v2lapl2"), + ptr_of_either("v2lapltau"), + ptr_of_either("v2tau2"), + ptr_of_either("v3rho3"), + ptr_of_either("v3rho2sigma"), + ptr_of_either("v3rho2lapl"), + ptr_of_either("v3rho2tau"), + ptr_of_either("v3rhosigma2"), + ptr_of_either("v3rhosigmalapl"), + ptr_of_either("v3rhosigmatau"), + ptr_of_either("v3rholapl2"), + ptr_of_either("v3rholapltau"), + ptr_of_either("v3rhotau2"), + ptr_of_either("v3sigma3"), + ptr_of_either("v3sigma2lapl"), + ptr_of_either("v3sigma2tau"), + ptr_of_either("v3sigmalapl2"), + ptr_of_either("v3sigmalapltau"), + ptr_of_either("v3sigmatau2"), + ptr_of_either("v3lapl3"), + ptr_of_either("v3lapl2tau"), + ptr_of_either("v3lapltau2"), + ptr_of_either("v3tau3"), + ptr_of_either("v4rho4"), + ptr_of_either("v4rho3sigma"), + ptr_of_either("v4rho3lapl"), + ptr_of_either("v4rho3tau"), + ptr_of_either("v4rho2sigma2"), + ptr_of_either("v4rho2sigmalapl"), + ptr_of_either("v4rho2sigmatau"), + ptr_of_either("v4rho2lapl2"), + ptr_of_either("v4rho2lapltau"), + ptr_of_either("v4rho2tau2"), + ptr_of_either("v4rhosigma3"), + ptr_of_either("v4rhosigma2lapl"), + ptr_of_either("v4rhosigma2tau"), + ptr_of_either("v4rhosigmalapl2"), + ptr_of_either("v4rhosigmalapltau"), + ptr_of_either("v4rhosigmatau2"), + ptr_of_either("v4rholapl3"), + ptr_of_either("v4rholapl2tau"), + ptr_of_either("v4rholapltau2"), + ptr_of_either("v4rhotau3"), + ptr_of_either("v4sigma4"), + ptr_of_either("v4sigma3lapl"), + ptr_of_either("v4sigma3tau"), + ptr_of_either("v4sigma2lapl2"), + ptr_of_either("v4sigma2lapltau"), + ptr_of_either("v4sigma2tau2"), + ptr_of_either("v4sigmalapl3"), + ptr_of_either("v4sigmalapl2tau"), + ptr_of_either("v4sigmalapltau2"), + ptr_of_either("v4sigmatau3"), + ptr_of_either("v4lapl4"), + ptr_of_either("v4lapl3tau"), + ptr_of_either("v4lapl2tau2"), + ptr_of_either("v4lapltau3"), + ptr_of_either("v4tau4"), ); } diff --git a/libxc/tests/general/test_functional.rs b/libxc/tests/general/test_functional.rs index 68a4e7c..e5bf8d9 100644 --- a/libxc/tests/general/test_functional.rs +++ b/libxc/tests/general/test_functional.rs @@ -115,7 +115,10 @@ fn test_libxc_functional_info() { assert!(func.flags().contains(Dim3)); assert!(func.is_hyb_cam()); assert!(func.flags().contains(VV10)); - assert!(func.needs_tau()); + // XC_FLAGS_NEEDS_TAU was introduced in libxc v7.0; v6.2.x never reports it + if libxc_version().0 >= 7 { + assert!(func.needs_tau()); + } assert_eq!(func.references().len(), 1); } From bf492370092817384216dbbcb1a431232357b17d Mon Sep 17 00:00:00 2001 From: ajz34 Date: Tue, 8 Sep 2026 21:12:16 +0800 Subject: [PATCH 2/4] Refresh v7.1 headers from released libxc 7.1.2, update docs for v7.1 release libxc v7.1 is now released upstream (7.1.0-7.1.2). The bundled v7.1 headers were snapshotted from the devel branch before the release and differ from the released 7.1.2 tag: - xc_funcs_v7.1.h (XcFuncId v7_1 regenerated): add T_HLE17, LDA_C_BJ89, GGA_X_LLP, LDA_C_LP96_B, LDA_K_LP96_B, LDA_C_RPAF, HYB_MGGA_XC_COACH, MGGA_X_SREGTM_V1/V2/V3; remove MS2BS, MVSB, MVSBS, OPB3LYP, which never shipped in a released v7.1. All shared IDs keep their numbers. - xc.h: differences vs the 7.1.2 tag are comment-only (verified identical after comment stripping), so FFI bindings are unaffected; refreshed for provenance. xc_version.h macros updated 7.0.0 -> 7.1.2. While at it, xc_funcs_v6.2.h turned out not to be the 6.2.2 tag file either: it contained 44 functional IDs added after 6.2.2, a typo'd LDA_C_1D_CSS (real name LDA_C_1D_CSC), LDA_XC_TH_FL (real name GGA_XC_TH_FL), and was missing MGGA_X_MK00. Replaced with the 6.2.2 tag file and regenerated. Note that 7.1.2 itself renames 1D_CSC -> 1D_CSS and GGA_XC_TH_FL -> LDA_XC_TH_FL, so those variant names are version-dependent by design. xc_funcs_v7.0.h already matched the 7.0.0 tag exactly (regenerating it is byte-identical). Docs updated to reflect that v7.1 is a released line: readme, versioning_xc, CLAUDE.md, cuda-testing skill, and a CHANGELOG Unreleased entry covering this and the previous 6.2.x fix commit. Validated: cargo test -p libxc against 6.2.2/7.0.0/7.1.2 CPU and 7.1.2 CUDA shared libraries, all passing. Co-authored-by: Claude Code Co-authored-by: glm-5.3 --- .claude/CLAUDE.md | 4 +- .claude/skills/cuda-testing/SKILL.md | 2 +- CHANGELOG.md | 29 +++++++ libxc-ffi/headers/versioning_xc.md | 4 + libxc-ffi/headers/xc.h | 23 ++++-- libxc-ffi/headers/xc_funcs_v6.2.h | 58 +++----------- libxc-ffi/headers/xc_funcs_v7.1.h | 16 ++-- libxc-ffi/headers/xc_version.h | 6 +- libxc-ffi/src/ffi_dynamic/mod.rs | 3 +- libxc-ffi/src/xc_funcs/v6_2.rs | 109 +++------------------------ libxc-ffi/src/xc_funcs/v7_1.rs | 31 +++++--- readme.md | 2 +- 12 files changed, 112 insertions(+), 175 deletions(-) diff --git a/.claude/CLAUDE.md b/.claude/CLAUDE.md index 2cd6d60..1447457 100644 --- a/.claude/CLAUDE.md +++ b/.claude/CLAUDE.md @@ -13,7 +13,7 @@ If human developers forgets to define `CLAUDE.local.md`, you should ask them to General rules - This repository should live at `LIBXC_REPO_PATH`, which is defined in `CLAUDE.local.md`. - **This repository should not be modified**, unless you are going to checkout specific tags (versions) of libxc. -- Main branch is `devel`, useful tags can be `6.2.2` and `7.0.0` (latest stable version at current time). +- Main branch is `devel`, useful tags can be `6.2.2`, `7.0.0` and `7.1.2` (latest stable version at current time). Important files for FFI and wrapper development: - `src/*.h`: the headers. Note that these files are also copied to this project under `libxc-ffi/headers` folder. @@ -66,7 +66,7 @@ We will currently separating CPU and CUDA implementation. CUDA will always have For this FFI wrapper, we will start from libxc v6.2.2. -At current time (2026-may), the latest stable version is v7.0.0, and developer version is v7.1.0. We will handle three versions: v6.2, v7.0, v7.1. +At current time (2026-sep), the latest stable version is v7.1.2, and the `devel` branch is under development towards the next version. We will handle three released versions: v6.2, v7.0, v7.1. The cargo feature will activate the corresponding version of header (`api-v6_2`, `api-v7_0`, `api-v7_1`), and the default version is v7.0. We will save libxc headers in folder `libxc-ffi/headers`. diff --git a/.claude/skills/cuda-testing/SKILL.md b/.claude/skills/cuda-testing/SKILL.md index 407668b..7f2e5c6 100644 --- a/.claude/skills/cuda-testing/SKILL.md +++ b/.claude/skills/cuda-testing/SKILL.md @@ -11,7 +11,7 @@ GPUs, CUDA testing is manual and local-only. **Please note that you must pass the correct cargo feature to the corresponding version of the libxc shared library**: - `api-v7_0` for libxc v7.0 -- `api-v7_1` for libxc v7.1 (or the `devel` branch of libxc) +- `api-v7_1` for libxc v7.1 (released as 7.1.0–7.1.2) For cuda tests, you also need to pass the `cuda` feature (which implies `api-v7_1`). diff --git a/CHANGELOG.md b/CHANGELOG.md index 62ce275..109d16c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,34 @@ # Changelog +## Unreleased + +Fix: + +- libxc 6.2.x support + - the workspace `libxc-ffi` dependency now sets `default-features = false`, + so api-version features are selected exclusively through the `libxc` + crate; previously `--no-default-features --features api-v6_2` still + compiled the v7.0 struct layout of `xc_func_type` and read garbage + against a v6.2.2 shared library + - mGGA tau handling: `needs_tau()` falls back to the functional family for + pre-v7.0 libraries; zeroed scratch substituted for null lapl/tau inputs + and for tau-family outputs missing from the layout/output map (libxc + 6.2.x aborts the process otherwise) + +Enhancement: + +- Refresh headers from released libxc tags: `xc_funcs_v7.1.h` and `xc.h` + from 7.1.2 (the v7.1 line is now released upstream as 7.1.0–7.1.2; it was + previously snapshotted from the unreleased `devel` branch), and + `xc_funcs_v6.2.h` from 6.2.2. `XcFuncId` enums regenerated. + - v7.1: add `T_HLE17`, `LDA_C_BJ89`, `GGA_X_LLP`, `LDA_C_LP96_B`, + `LDA_K_LP96_B`, `LDA_C_RPAF`, `HYB_MGGA_XC_COACH`, + `MGGA_X_SREGTM_V1/V2/V3`; remove `MS2BS`, `MVSB`, `MVSBS`, `OPB3LYP` + (present only in the pre-release snapshot, never in a released v7.1) + - v6.2: remove functional IDs that do not exist in libxc 6.2.2; fix + `LDA_C_1D_CSS` -> `LDA_C_1D_CSC` and `LDA_XC_TH_FL` -> `GGA_XC_TH_FL`; + add `MGGA_X_MK00` + ## v0.1.2 -- 2026-05-25 Enhancement: diff --git a/libxc-ffi/headers/versioning_xc.md b/libxc-ffi/headers/versioning_xc.md index e517f50..e574cf0 100644 --- a/libxc-ffi/headers/versioning_xc.md +++ b/libxc-ffi/headers/versioning_xc.md @@ -94,6 +94,10 @@ xc_func_get_ext_params_value # v7.1 +Released upstream as v7.1.0–v7.1.2. The v7.1 headers in this project track +the released 7.1.2 tag (earlier they were snapshotted from the `devel` +branch before the release). + ## Introduced in v7.1 xc_func_info_get_default_flags diff --git a/libxc-ffi/headers/xc.h b/libxc-ffi/headers/xc.h index 368fdba..9272b4b 100644 --- a/libxc-ffi/headers/xc.h +++ b/libxc-ffi/headers/xc.h @@ -93,8 +93,12 @@ const char *xc_version_string(void); #define XC_NOARG #define XC_COMMA , -/* the following macros *do not* include zk */ -/* the following macros are probably to DELETE */ +/* Expansion lists of every per-order derivative output (excluding zk) for + each family, in canonical order. They exist only to spell out the + parameter lists of the legacy flat evaluators (xc_lda/xc_gga/xc_mgga, + declared below) and the composite mix plumbing. New code + should use the struct interface (xc_*_new) or the convenience entry + points instead; these macros can go once those last users are migrated. */ #define LDA_OUT_PARAMS_NO_EXC(P1_, P2_) \ P1_ P2_ ## vrho \ @@ -420,13 +424,22 @@ void xc_mgga_new(const xc_func_type *func, int order, size_t np, const double *rho, const double *sigma, const double *lapl, const double *tau, xc_mgga_out_params *out); -/** Evaluate an LDA functional */ +/** + * Legacy flat-argument evaluation interface. + * + * Every derivative output is a separate pointer argument, spelled out by + * the *_OUT_PARAMS_NO_EXC macros, so xc_mgga() has 70+ parameters. These + * are kept for backward compatibility (and are still used internally by + * the composite mix evaluators); new code should prefer + * - the per-order convenience entry points -- xc_lda_exc, xc_gga_exc_vxc, + * xc_mgga_exc_vxc_fxc, ... -- which take only the outputs requested; or + * - the struct interface xc_{lda,gga,mgga}_new(p, order, np, ..., &out) + * with an xc_{lda,gga,mgga}_out_params whose unused fields are NULL. + */ void xc_lda (const xc_func_type *p, size_t np, const double *rho, double *zk LDA_OUT_PARAMS_NO_EXC(XC_COMMA double *, )); -/** Evaluate a GGA functional */ void xc_gga (const xc_func_type *p, size_t np, const double *rho, const double *sigma, double *zk GGA_OUT_PARAMS_NO_EXC(XC_COMMA double *, )); -/** Evaluate a meta-GGA functional */ void xc_mgga(const xc_func_type *p, size_t np, const double *rho, const double *sigma, const double *lapl_rho, const double *tau, double *zk MGGA_OUT_PARAMS_NO_EXC(XC_COMMA double *, )); diff --git a/libxc-ffi/headers/xc_funcs_v6.2.h b/libxc-ffi/headers/xc_funcs_v6.2.h index 4e43be1..1d8ffe2 100644 --- a/libxc-ffi/headers/xc_funcs_v6.2.h +++ b/libxc-ffi/headers/xc_funcs_v6.2.h @@ -2,7 +2,7 @@ #define XC_LDA_C_WIGNER 2 /* Wigner */ #define XC_LDA_C_RPA 3 /* Random Phase Approximation (RPA) */ #define XC_LDA_C_HL 4 /* Hedin & Lundqvist */ -#define XC_LDA_C_GL 5 /* Gunnarsson & Lundqvist */ +#define XC_LDA_C_GL 5 /* Gunnarson & Lundqvist */ #define XC_LDA_C_XALPHA 6 /* Slater's Xalpha */ #define XC_LDA_C_VWN 7 /* Vosko, Wilk & Nusair (VWN5) */ #define XC_LDA_C_VWN_RPA 8 /* Vosko, Wilk & Nusair (VWN5_RPA) */ @@ -15,7 +15,7 @@ #define XC_LDA_C_2D_AMGB 15 /* AMGB (for 2D systems) */ #define XC_LDA_C_2D_PRM 16 /* PRM (for 2D systems) */ #define XC_LDA_C_VBH 17 /* von Barth & Hedin */ -#define XC_LDA_C_1D_CSS 18 /* Casula, Sorella & Senatore */ +#define XC_LDA_C_1D_CSC 18 /* Casula, Sorella & Senatore */ #define XC_LDA_X_2D 19 /* Slater exchange */ #define XC_LDA_XC_TETER93 20 /* Teter 93 */ #define XC_LDA_X_1D_SOFT 21 /* Exchange in 1D for an soft-Coulomb interaction */ @@ -101,7 +101,6 @@ #define XC_GGA_X_PBE 101 /* Perdew, Burke & Ernzerhof */ #define XC_GGA_X_PBE_R 102 /* Revised PBE from Zhang & Yang */ #define XC_GGA_X_B86 103 /* Becke 86 */ -#define XC_HYB_LDA_XC_B93 104 /* Becke's original half-and-half functional: 50% HF and 50% LDA xc */ #define XC_GGA_X_B86_MGC 105 /* Becke 86 with modified gradient correction */ #define XC_GGA_X_B88 106 /* Becke 88 */ #define XC_GGA_X_G96 107 /* Gill 96 */ @@ -193,7 +192,7 @@ #define XC_GGA_X_LAG 193 /* Local Airy Gas */ #define XC_GGA_XC_MOHLYP 194 /* Functional for organometallic chemistry */ #define XC_GGA_XC_MOHLYP2 195 /* Functional for barrier heights */ -#define XC_LDA_XC_TH_FL 196 /* Tozer and Handy v. FL */ +#define XC_GGA_XC_TH_FL 196 /* Tozer and Handy v. FL */ #define XC_GGA_XC_TH_FC 197 /* Tozer and Handy v. FC */ #define XC_GGA_XC_TH_FCFO 198 /* Tozer and Handy v. FCFO */ #define XC_GGA_XC_TH_FCO 199 /* Tozer and Handy v. FCO */ @@ -227,7 +226,7 @@ #define XC_MGGA_X_MN12_L 227 /* Minnesota MN12-L exchange functional */ #define XC_MGGA_X_MS2_REV 228 /* MS2 exchange of Sun, et al with revised value for c */ #define XC_MGGA_XC_CC06 229 /* Cancio and Chou 2006 */ -#define XC_MGGA_X_GP86 230 /* Ghosh-Parr 1986 meta-GGA exchange, later reinvestigated by Manby and Knowles */ +#define XC_MGGA_X_MK00 230 /* Exchange for accurate virtual orbital energies */ #define XC_MGGA_C_TPSS 231 /* Tao, Perdew, Staroverov & Scuseria */ #define XC_MGGA_C_VSXC 232 /* VSXC (correlation part) */ #define XC_MGGA_C_M06_L 233 /* Minnesota M06-L correlation functional */ @@ -323,30 +322,7 @@ #define XC_MGGA_C_TPSS_GAUSSIAN 323 /* Tao, Perdew, Staroverov & Scuseria with parameters from Gaussian */ #define XC_GGA_X_NCAPR 324 /* Nearly correct asymptotic potential revised */ #define XC_HYB_GGA_XC_RELPBE0 325 /* relPBE0 a.k.a. relPBE: PBE0 refitted for actinide compounds */ -#define XC_MGGA_X_EEL 326 /* Exact exchange-like exchange of Aschebrock et al */ #define XC_GGA_XC_B97_3C 327 /* Becke 97-3c by Grimme et. al. */ -#define XC_LDA_C_EPC17 328 /* epc17(-1): electron-proton correlation 2017 */ -#define XC_LDA_C_EPC17_2 329 /* epc17-2: electron-proton correlation 2017 for proton affinities */ -#define XC_LDA_C_EPC18_1 330 /* epc18-1: electron-proton correlation 2018 */ -#define XC_LDA_C_EPC18_2 331 /* epc18-2: electron-proton correlation 2018 for proton affinities */ -#define XC_GGA_XC_DLB97 332 /* dispersionless-optimized B97 */ -#define XC_MGGA_X_MSCAN 333 /* Modified SCAN (mSCAN) exchange of Desmarais, Erba, Vignale, and Pittalis */ -#define XC_MGGA_C_MSCAN 334 /* Modified SCAN (mSCAN) correlation of Desmarais, Erba, Vignale, and Pittalis */ -#define XC_GGA_X_T_PBE1 335 /* PBE reparametrization (version 1) for band gaps */ -#define XC_GGA_X_T_PBE2 336 /* PBE reparametrization (version 2) for band gaps */ -#define XC_LDA_X_T_SLOC 337 /* SLOC reparametrization for band gaps */ -#define XC_GGA_X_BKL1 338 /* Exchange part of type-I band gap functional by Bhattacharjee, Koshi and Lee */ -#define XC_GGA_X_BKL2 339 /* Exchange part of type-II band gap functional by Bhattacharjee, Koshi and Lee */ -#define XC_HYB_MGGA_X_CF22D 340 /* Minnesota CF22D hybrid exchange functional */ -#define XC_MGGA_C_CF22D 341 /* Minnesota CF22D correlation functional */ -#define XC_MGGA_X_LAK 342 /* Lebeda-Aschebrock-Kummel meta-GGA exchange */ -#define XC_GGA_C_BKL1 343 /* Correlation part of type-I band gap functional by Bhattacharjee, Koshi and Lee */ -#define XC_GGA_C_BKL2 344 /* Correlation part of type-II band gap functional by Bhattacharjee, Koshi and Lee */ -#define XC_MGGA_C_LAK 345 /* Lebeda-Aschebrock-Kummel meta-GGA correlation */ -#define XC_GGA_X_DF3_OPT1 346 /* Becke 88 reoptimized by Chakraborty et al for use with vdW functional */ -#define XC_GGA_X_DF3_OPT2 347 /* Becke 86 reoptimized by Chakraborty et al for use with vdW functional */ -#define XC_HYB_GGA_XC_CQTP25 385 /* CAM-B3LYP retuned for core electron ionization energies */ -#define XC_HYB_GGA_XC_OPB3LYP 386 /* opB3LYP: B3LYP reoptimized in 6-311++G(2d,2p) basis set */ #define XC_MGGA_C_CC 387 /* Self-interaction corrected correlation functional by Schmidt et al */ #define XC_MGGA_C_CCALDA 388 /* Iso-orbital corrected LDA correlation by Lebeda et al */ #define XC_HYB_MGGA_XC_BR3P86 389 /* BR3P86 hybrid meta-GGA from Neumann and Handy */ @@ -395,8 +371,8 @@ #define XC_HYB_GGA_XC_HJS_B97X 432 /* HJS hybrid screened exchange B97x version */ #define XC_HYB_GGA_XC_CAM_B3LYP 433 /* CAM version of B3LYP */ #define XC_HYB_GGA_XC_TUNED_CAM_B3LYP 434 /* CAM version of B3LYP, tuned for excitations and properties */ -#define XC_HYB_GGA_XC_BHANDH 435 /* BHandH: 50% LDA exchange and 50% HF exchange with 100% LYP correlation */ -#define XC_HYB_GGA_XC_BHANDHLYP 436 /* BHandHLYP a.k.a. BHLYP: 50% B88 exchange and 50% HF exchange with 100% LYP correlation */ +#define XC_HYB_GGA_XC_BHANDH 435 /* BHandH i.e. BHLYP */ +#define XC_HYB_GGA_XC_BHANDHLYP 436 /* BHandHLYP */ #define XC_HYB_GGA_XC_MB3LYP_RC04 437 /* B3LYP with RC04 LDA */ #define XC_HYB_MGGA_X_M05 438 /* Minnesota M05 hybrid exchange functional */ #define XC_HYB_MGGA_X_M05_2X 439 /* Minnesota M05-2X hybrid exchange functional */ @@ -456,7 +432,7 @@ #define XC_MGGA_X_RSCAN 493 /* Regularized SCAN exchange by Bartok and Yates */ #define XC_MGGA_C_RSCAN 494 /* Regularized SCAN correlation by Bartok and Yates */ #define XC_GGA_X_S12G 495 /* Swart 2012 GGA exchange */ -#define XC_HYB_GGA_X_S12H 496 /* Swart 2012 hybrid GGA exchange */ +#define XC_HYB_GGA_X_S12H 496 /* Swart 2012 hybrid exchange */ #define XC_MGGA_X_R2SCAN 497 /* Re-regularized SCAN exchange by Furness et al */ #define XC_MGGA_C_R2SCAN 498 /* Re-regularized SCAN correlation by Furness et al */ #define XC_HYB_GGA_XC_BLYP35 499 /* BLYP35 */ @@ -519,12 +495,12 @@ #define XC_GGA_C_GAPLOC 556 /* Gaploc */ #define XC_GGA_C_ZVPBEINT 557 /* another spin-dependent correction to PBEint */ #define XC_GGA_C_ZVPBESOL 558 /* another spin-dependent correction to PBEsol */ -#define XC_GGA_C_TM_LYP 559 /* Thakkar and McCarthy reparametrization, also known as reLYP */ +#define XC_GGA_C_TM_LYP 559 /* Takkar and McCarthy reparametrization */ #define XC_GGA_C_TM_PBE 560 /* Thakkar and McCarthy reparametrization */ #define XC_GGA_C_W94 561 /* Wilson 94 (Eq. 25) */ #define XC_MGGA_C_KCIS 562 /* Krieger, Chen, Iafrate, and Savin */ #define XC_HYB_MGGA_XC_B0KCIS 563 /* Hybrid based on KCIS */ -#define XC_MGGA_XC_LP90 564 /* Lee & Parr, Eq. (60) */ +#define XC_MGGA_XC_LP90 564 /* Lee & Parr, Eq. (56) */ #define XC_GGA_C_CS1 565 /* A dynamical correlation functional */ #define XC_HYB_MGGA_XC_MPW1KCIS 566 /* MPW1KCIS for barrier heights */ #define XC_HYB_MGGA_XC_MPWKCIS1K 567 /* MPWKCIS1K for barrier heights */ @@ -613,16 +589,10 @@ #define XC_MGGA_X_R4SCAN 650 /* r$^{4}$SCAN, a functional that satisfies the same exact constraints that SCAN does */ #define XC_MGGA_X_VCML 651 /* Exchange part of VCML-rVV10 by Trepte and Voss */ #define XC_MGGA_XC_VCML_RVV10 652 /* VCML-rVV10 by Trepte and Voss */ -#define XC_HYB_LDA_X_ERF 653 /* Long-range corrected functional based on short-range LDA exchange (erfc) */ -#define XC_LDA_C_PW_ERF 654 /* Short ranged correlation LDA (erfc) */ -#define XC_GGA_X_PBE_ERF_GWS 655 /* Short ranged PBE exchange (erfc) */ -#define XC_HYB_GGA_X_PBE_ERF_GWS 656 /* Short-range PBE (GWS) exchange (erfc) + long-range exact exchange */ -#define XC_GGA_C_PBE_ERF_GWS 657 /* Short ranged PBE correlation (erfc) */ #define XC_HYB_MGGA_XC_GAS22 658 /* Google Accelerated Science 22 */ #define XC_HYB_MGGA_XC_R2SCANH 659 /* r2SCANh: r2SCAN hybrid like TPSSh with 10% exact exchange */ #define XC_HYB_MGGA_XC_R2SCAN0 660 /* r2SCAN0: r2SCAN hybrid like PBE0 with 25% exact exchange */ #define XC_HYB_MGGA_XC_R2SCAN50 661 /* r2SCAN50: r2SCAN hybrid like PBE50 with 50% exact exchange */ -#define XC_HYB_MGGA_X_WR2SCAN 662 /* Range-separated re-regularized SCAN exchange by Wittmann et al */ #define XC_HYB_GGA_XC_CAM_PBEH 681 /* CAM hybrid screened exchange PBE version */ #define XC_HYB_GGA_XC_CAMY_PBEH 682 /* CAMY hybrid screened exchange PBE version */ #define XC_LDA_C_UPW92 683 /* Ruggeri, Rios, and Alavi unrestricted fit */ @@ -684,13 +654,3 @@ #define XC_MGGA_X_KTBM_23 758 /* KTBM learned exchange - 23 */ #define XC_MGGA_X_KTBM_24 759 /* KTBM learned exchange - 24 */ #define XC_MGGA_X_KTBM_GAP 760 /* KTBM learned exchange - GAP */ -#define XC_MGGA_X_MSPBEL 761 /* MS-PBEl, a PBE-like meta-GGA exchange */ -#define XC_MGGA_X_RMSPBEL 762 /* regularized MS-PBEl */ -#define XC_MGGA_X_MSRPBEL 763 /* MS-RPBEl, a RPBE-like meta-GGA exchange */ -#define XC_MGGA_X_RMSRPBEL 764 /* regularized MS-RPBEl */ -#define XC_MGGA_X_MSB86BL 765 /* MS-B86bl, a B86b-like meta-GGA exchange */ -#define XC_MGGA_X_RMSB86BL 766 /* regularized MS-B86bl */ -#define XC_HYB_MGGA_X_PI_M06_2X_DL 767 /* Dispersionless physically-informed Minnesota M06-2X hybrid exchange functional */ -#define XC_MGGA_C_PI_M06_2X_DL 768 /* Dispersionless physically-informed Minnesota M06-2X correlation functional */ -#define XC_HYB_MGGA_X_PI_M06_2X 769 /* Physically-informed Minnesota M06-2X hybrid exchange functional */ -#define XC_MGGA_C_PI_M06_2X 770 /* Physically-informed Minnesota M06-2X correlation functional */ diff --git a/libxc-ffi/headers/xc_funcs_v7.1.h b/libxc-ffi/headers/xc_funcs_v7.1.h index 4e43be1..8a1ad73 100644 --- a/libxc-ffi/headers/xc_funcs_v7.1.h +++ b/libxc-ffi/headers/xc_funcs_v7.1.h @@ -298,9 +298,6 @@ #define XC_GGA_X_CHACHIYO 298 /* Chachiyo exchange */ #define XC_MGGA_X_RTPSS 299 /* TPSS for surface adsorption */ #define XC_MGGA_X_MS2B 300 /* MS2beta exchange of Furness and Sun */ -#define XC_MGGA_X_MS2BS 301 /* MS2beta* exchange of Furness and Sun */ -#define XC_MGGA_X_MVSB 302 /* MVSbeta exchange by Furness and Sun */ -#define XC_MGGA_X_MVSBS 303 /* MVSbeta* exchange by Furness and Sun */ #define XC_HYB_MGGA_X_REVM11 304 /* Revised Minnesota M11 hybrid exchange functional */ #define XC_HYB_MGGA_X_REVM06 305 /* Revised Minnesota M06 hybrid exchange functional */ #define XC_MGGA_C_REVM06 306 /* Revised Minnesota M06 correlation functional */ @@ -345,8 +342,13 @@ #define XC_MGGA_C_LAK 345 /* Lebeda-Aschebrock-Kummel meta-GGA correlation */ #define XC_GGA_X_DF3_OPT1 346 /* Becke 88 reoptimized by Chakraborty et al for use with vdW functional */ #define XC_GGA_X_DF3_OPT2 347 /* Becke 86 reoptimized by Chakraborty et al for use with vdW functional */ +#define XC_MGGA_XC_T_HLE17 348 /* HLE17 reparametrization for band gaps */ +#define XC_LDA_C_BJ89 349 /* Barbiellini & Jarlborg 89 */ +#define XC_GGA_X_LLP 350 /* Lee, Lee & Parr reparametrization of B88 */ +#define XC_LDA_C_LP96_B 351 /* Liu-Parr correlation with 4 parameters */ +#define XC_LDA_K_LP96_B 352 /* Liu-Parr kinetic with 4 parameters */ +#define XC_LDA_C_RPAF 353 /* Random Phase Approximation based Functional (RPAF) */ #define XC_HYB_GGA_XC_CQTP25 385 /* CAM-B3LYP retuned for core electron ionization energies */ -#define XC_HYB_GGA_XC_OPB3LYP 386 /* opB3LYP: B3LYP reoptimized in 6-311++G(2d,2p) basis set */ #define XC_MGGA_C_CC 387 /* Self-interaction corrected correlation functional by Schmidt et al */ #define XC_MGGA_C_CCALDA 388 /* Iso-orbital corrected LDA correlation by Lebeda et al */ #define XC_HYB_MGGA_XC_BR3P86 389 /* BR3P86 hybrid meta-GGA from Neumann and Handy */ @@ -414,7 +416,7 @@ #define XC_HYB_MGGA_XC_PW6B95 451 /* Mixture of PW91 with BC95 from Zhao and Truhlar */ #define XC_HYB_MGGA_XC_PWB6K 452 /* Mixture of PW91 with BC95 from Zhao and Truhlar for kinetics */ #define XC_HYB_GGA_XC_MPWLYP1M 453 /* MPW with 1 par. for metals/LYP */ -#define XC_HYB_GGA_XC_REVB3LYP 454 /* Revised B3LYP */ +#define XC_HYB_GGA_XC_REVB3LYP 454 /* Revised B3LYP a.k.a. OpB3LYP; B3LYP reoptimized in 6-311++G(2d,2p) basis set */ #define XC_HYB_GGA_XC_CAMY_BLYP 455 /* CAMY version of BLYP */ #define XC_HYB_GGA_XC_PBE0_13 456 /* PBE0-1/3 */ #define XC_HYB_MGGA_XC_TPSSH 457 /* TPSSh */ @@ -694,3 +696,7 @@ #define XC_MGGA_C_PI_M06_2X_DL 768 /* Dispersionless physically-informed Minnesota M06-2X correlation functional */ #define XC_HYB_MGGA_X_PI_M06_2X 769 /* Physically-informed Minnesota M06-2X hybrid exchange functional */ #define XC_MGGA_C_PI_M06_2X 770 /* Physically-informed Minnesota M06-2X correlation functional */ +#define XC_HYB_MGGA_XC_COACH 771 /* COACH exchange-correlation functional */ +#define XC_MGGA_X_SREGTM_V1 772 /* Simplified regularized Tao-Mo exchange (v1) */ +#define XC_MGGA_X_SREGTM_V2 773 /* Simplified regularized Tao-Mo exchange (v2) */ +#define XC_MGGA_X_SREGTM_V3 774 /* Simplified regularized Tao-Mo exchange (v3) */ diff --git a/libxc-ffi/headers/xc_version.h b/libxc-ffi/headers/xc_version.h index be7719a..33b2285 100644 --- a/libxc-ffi/headers/xc_version.h +++ b/libxc-ffi/headers/xc_version.h @@ -15,10 +15,10 @@ extern "C" { #endif -#define XC_VERSION "7.0.0" +#define XC_VERSION "7.1.2" #define XC_MAJOR_VERSION 7 -#define XC_MINOR_VERSION 0 -#define XC_MICRO_VERSION 0 +#define XC_MINOR_VERSION 1 +#define XC_MICRO_VERSION 2 #ifdef __cplusplus } diff --git a/libxc-ffi/src/ffi_dynamic/mod.rs b/libxc-ffi/src/ffi_dynamic/mod.rs index d1570ba..9fcb1e1 100644 --- a/libxc-ffi/src/ffi_dynamic/mod.rs +++ b/libxc-ffi/src/ffi_dynamic/mod.rs @@ -106,7 +106,8 @@ mod dynamic_loading_specific { } fn extract_lib_from_python_bin(python_bin: &str) -> Option { - // If python is at /path/to/bin/python, library should be at /path/to/lib/ + // If python is at /path/to/bin/python, library should be at + // /path/to/lib/ let bin_path = std::path::Path::new(python_bin); if let Some(parent) = bin_path.parent() { if let Some(base) = parent.parent() { diff --git a/libxc-ffi/src/xc_funcs/v6_2.rs b/libxc-ffi/src/xc_funcs/v6_2.rs index aeb9b5f..73c38cd 100644 --- a/libxc-ffi/src/xc_funcs/v6_2.rs +++ b/libxc-ffi/src/xc_funcs/v6_2.rs @@ -22,7 +22,7 @@ pub enum XcFuncId { LDA_C_RPA = 3, /// Hedin & Lundqvist LDA_C_HL = 4, - /// Gunnarsson & Lundqvist + /// Gunnarson & Lundqvist LDA_C_GL = 5, /// Slater's Xalpha LDA_C_XALPHA = 6, @@ -49,7 +49,7 @@ pub enum XcFuncId { /// von Barth & Hedin LDA_C_VBH = 17, /// Casula, Sorella & Senatore - LDA_C_1D_CSS = 18, + LDA_C_1D_CSC = 18, /// Slater exchange LDA_X_2D = 19, /// Teter 93 @@ -220,8 +220,6 @@ pub enum XcFuncId { GGA_X_PBE_R = 102, /// Becke 86 GGA_X_B86 = 103, - /// Becke's original half-and-half functional: 50% HF and 50% LDA xc - HYB_LDA_XC_B93 = 104, /// Becke 86 with modified gradient correction GGA_X_B86_MGC = 105, /// Becke 88 @@ -405,7 +403,7 @@ pub enum XcFuncId { /// Functional for barrier heights GGA_XC_MOHLYP2 = 195, /// Tozer and Handy v. FL - LDA_XC_TH_FL = 196, + GGA_XC_TH_FL = 196, /// Tozer and Handy v. FC GGA_XC_TH_FC = 197, /// Tozer and Handy v. FCFO @@ -474,9 +472,8 @@ pub enum XcFuncId { MGGA_X_MS2_REV = 228, /// Cancio and Chou 2006 MGGA_XC_CC06 = 229, - /// Ghosh-Parr 1986 meta-GGA exchange, later reinvestigated by Manby and - /// Knowles - MGGA_X_GP86 = 230, + /// Exchange for accurate virtual orbital energies + MGGA_X_MK00 = 230, /// Tao, Perdew, Staroverov & Scuseria MGGA_C_TPSS = 231, /// VSXC (correlation part) @@ -667,59 +664,8 @@ pub enum XcFuncId { GGA_X_NCAPR = 324, /// relPBE0 a.k.a. relPBE: PBE0 refitted for actinide compounds HYB_GGA_XC_RELPBE0 = 325, - /// Exact exchange-like exchange of Aschebrock et al - MGGA_X_EEL = 326, /// Becke 97-3c by Grimme et. al. GGA_XC_B97_3C = 327, - /// epc17(-1): electron-proton correlation 2017 - LDA_C_EPC17 = 328, - /// epc17-2: electron-proton correlation 2017 for proton affinities - LDA_C_EPC17_2 = 329, - /// epc18-1: electron-proton correlation 2018 - LDA_C_EPC18_1 = 330, - /// epc18-2: electron-proton correlation 2018 for proton affinities - LDA_C_EPC18_2 = 331, - /// dispersionless-optimized B97 - GGA_XC_DLB97 = 332, - /// Modified SCAN (mSCAN) exchange of Desmarais, Erba, Vignale, and Pittalis - MGGA_X_MSCAN = 333, - /// Modified SCAN (mSCAN) correlation of Desmarais, Erba, Vignale, and - /// Pittalis - MGGA_C_MSCAN = 334, - /// PBE reparametrization (version 1) for band gaps - GGA_X_T_PBE1 = 335, - /// PBE reparametrization (version 2) for band gaps - GGA_X_T_PBE2 = 336, - /// SLOC reparametrization for band gaps - LDA_X_T_SLOC = 337, - /// Exchange part of type-I band gap functional by Bhattacharjee, Koshi and - /// Lee - GGA_X_BKL1 = 338, - /// Exchange part of type-II band gap functional by Bhattacharjee, Koshi and - /// Lee - GGA_X_BKL2 = 339, - /// Minnesota CF22D hybrid exchange functional - HYB_MGGA_X_CF22D = 340, - /// Minnesota CF22D correlation functional - MGGA_C_CF22D = 341, - /// Lebeda-Aschebrock-Kummel meta-GGA exchange - MGGA_X_LAK = 342, - /// Correlation part of type-I band gap functional by Bhattacharjee, Koshi - /// and Lee - GGA_C_BKL1 = 343, - /// Correlation part of type-II band gap functional by Bhattacharjee, Koshi - /// and Lee - GGA_C_BKL2 = 344, - /// Lebeda-Aschebrock-Kummel meta-GGA correlation - MGGA_C_LAK = 345, - /// Becke 88 reoptimized by Chakraborty et al for use with vdW functional - GGA_X_DF3_OPT1 = 346, - /// Becke 86 reoptimized by Chakraborty et al for use with vdW functional - GGA_X_DF3_OPT2 = 347, - /// CAM-B3LYP retuned for core electron ionization energies - HYB_GGA_XC_CQTP25 = 385, - /// opB3LYP: B3LYP reoptimized in 6-311++G(2d,2p) basis set - HYB_GGA_XC_OPB3LYP = 386, /// Self-interaction corrected correlation functional by Schmidt et al MGGA_C_CC = 387, /// Iso-orbital corrected LDA correlation by Lebeda et al @@ -816,10 +762,9 @@ pub enum XcFuncId { HYB_GGA_XC_CAM_B3LYP = 433, /// CAM version of B3LYP, tuned for excitations and properties HYB_GGA_XC_TUNED_CAM_B3LYP = 434, - /// BHandH: 50% LDA exchange and 50% HF exchange with 100% LYP correlation + /// BHandH i.e. BHLYP HYB_GGA_XC_BHANDH = 435, - /// BHandHLYP a.k.a. BHLYP: 50% B88 exchange and 50% HF exchange with 100% - /// LYP correlation + /// BHandHLYP HYB_GGA_XC_BHANDHLYP = 436, /// B3LYP with RC04 LDA HYB_GGA_XC_MB3LYP_RC04 = 437, @@ -941,7 +886,7 @@ pub enum XcFuncId { MGGA_C_RSCAN = 494, /// Swart 2012 GGA exchange GGA_X_S12G = 495, - /// Swart 2012 hybrid GGA exchange + /// Swart 2012 hybrid exchange HYB_GGA_X_S12H = 496, /// Re-regularized SCAN exchange by Furness et al MGGA_X_R2SCAN = 497, @@ -1067,7 +1012,7 @@ pub enum XcFuncId { GGA_C_ZVPBEINT = 557, /// another spin-dependent correction to PBEsol GGA_C_ZVPBESOL = 558, - /// Thakkar and McCarthy reparametrization, also known as reLYP + /// Takkar and McCarthy reparametrization GGA_C_TM_LYP = 559, /// Thakkar and McCarthy reparametrization GGA_C_TM_PBE = 560, @@ -1077,7 +1022,7 @@ pub enum XcFuncId { MGGA_C_KCIS = 562, /// Hybrid based on KCIS HYB_MGGA_XC_B0KCIS = 563, - /// Lee & Parr, Eq. (60) + /// Lee & Parr, Eq. (56) MGGA_XC_LP90 = 564, /// A dynamical correlation functional GGA_C_CS1 = 565, @@ -1259,16 +1204,6 @@ pub enum XcFuncId { MGGA_X_VCML = 651, /// VCML-rVV10 by Trepte and Voss MGGA_XC_VCML_RVV10 = 652, - /// Long-range corrected functional based on short-range LDA exchange (erfc) - HYB_LDA_X_ERF = 653, - /// Short ranged correlation LDA (erfc) - LDA_C_PW_ERF = 654, - /// Short ranged PBE exchange (erfc) - GGA_X_PBE_ERF_GWS = 655, - /// Short-range PBE (GWS) exchange (erfc) + long-range exact exchange - HYB_GGA_X_PBE_ERF_GWS = 656, - /// Short ranged PBE correlation (erfc) - GGA_C_PBE_ERF_GWS = 657, /// Google Accelerated Science 22 HYB_MGGA_XC_GAS22 = 658, /// r2SCANh: r2SCAN hybrid like TPSSh with 10% exact exchange @@ -1277,8 +1212,6 @@ pub enum XcFuncId { HYB_MGGA_XC_R2SCAN0 = 660, /// r2SCAN50: r2SCAN hybrid like PBE50 with 50% exact exchange HYB_MGGA_XC_R2SCAN50 = 661, - /// Range-separated re-regularized SCAN exchange by Wittmann et al - HYB_MGGA_X_WR2SCAN = 662, /// CAM hybrid screened exchange PBE version HYB_GGA_XC_CAM_PBEH = 681, /// CAMY hybrid screened exchange PBE version @@ -1401,26 +1334,4 @@ pub enum XcFuncId { MGGA_X_KTBM_24 = 759, /// KTBM learned exchange - GAP MGGA_X_KTBM_GAP = 760, - /// MS-PBEl, a PBE-like meta-GGA exchange - MGGA_X_MSPBEL = 761, - /// regularized MS-PBEl - MGGA_X_RMSPBEL = 762, - /// MS-RPBEl, a RPBE-like meta-GGA exchange - MGGA_X_MSRPBEL = 763, - /// regularized MS-RPBEl - MGGA_X_RMSRPBEL = 764, - /// MS-B86bl, a B86b-like meta-GGA exchange - MGGA_X_MSB86BL = 765, - /// regularized MS-B86bl - MGGA_X_RMSB86BL = 766, - /// Dispersionless physically-informed Minnesota M06-2X hybrid exchange - /// functional - HYB_MGGA_X_PI_M06_2X_DL = 767, - /// Dispersionless physically-informed Minnesota M06-2X correlation - /// functional - MGGA_C_PI_M06_2X_DL = 768, - /// Physically-informed Minnesota M06-2X hybrid exchange functional - HYB_MGGA_X_PI_M06_2X = 769, - /// Physically-informed Minnesota M06-2X correlation functional - MGGA_C_PI_M06_2X = 770, } diff --git a/libxc-ffi/src/xc_funcs/v7_1.rs b/libxc-ffi/src/xc_funcs/v7_1.rs index 38bc210..4735497 100644 --- a/libxc-ffi/src/xc_funcs/v7_1.rs +++ b/libxc-ffi/src/xc_funcs/v7_1.rs @@ -617,12 +617,6 @@ pub enum XcFuncId { MGGA_X_RTPSS = 299, /// MS2beta exchange of Furness and Sun MGGA_X_MS2B = 300, - /// MS2beta* exchange of Furness and Sun - MGGA_X_MS2BS = 301, - /// MVSbeta exchange by Furness and Sun - MGGA_X_MVSB = 302, - /// MVSbeta* exchange by Furness and Sun - MGGA_X_MVSBS = 303, /// Revised Minnesota M11 hybrid exchange functional HYB_MGGA_X_REVM11 = 304, /// Revised Minnesota M06 hybrid exchange functional @@ -716,10 +710,20 @@ pub enum XcFuncId { GGA_X_DF3_OPT1 = 346, /// Becke 86 reoptimized by Chakraborty et al for use with vdW functional GGA_X_DF3_OPT2 = 347, + /// HLE17 reparametrization for band gaps + MGGA_XC_T_HLE17 = 348, + /// Barbiellini & Jarlborg 89 + LDA_C_BJ89 = 349, + /// Lee, Lee & Parr reparametrization of B88 + GGA_X_LLP = 350, + /// Liu-Parr correlation with 4 parameters + LDA_C_LP96_B = 351, + /// Liu-Parr kinetic with 4 parameters + LDA_K_LP96_B = 352, + /// Random Phase Approximation based Functional (RPAF) + LDA_C_RPAF = 353, /// CAM-B3LYP retuned for core electron ionization energies HYB_GGA_XC_CQTP25 = 385, - /// opB3LYP: B3LYP reoptimized in 6-311++G(2d,2p) basis set - HYB_GGA_XC_OPB3LYP = 386, /// Self-interaction corrected correlation functional by Schmidt et al MGGA_C_CC = 387, /// Iso-orbital corrected LDA correlation by Lebeda et al @@ -855,7 +859,8 @@ pub enum XcFuncId { HYB_MGGA_XC_PWB6K = 452, /// MPW with 1 par. for metals/LYP HYB_GGA_XC_MPWLYP1M = 453, - /// Revised B3LYP + /// Revised B3LYP a.k.a. OpB3LYP; B3LYP reoptimized in 6-311++G(2d,2p) basis + /// set HYB_GGA_XC_REVB3LYP = 454, /// CAMY version of BLYP HYB_GGA_XC_CAMY_BLYP = 455, @@ -1423,4 +1428,12 @@ pub enum XcFuncId { HYB_MGGA_X_PI_M06_2X = 769, /// Physically-informed Minnesota M06-2X correlation functional MGGA_C_PI_M06_2X = 770, + /// COACH exchange-correlation functional + HYB_MGGA_XC_COACH = 771, + /// Simplified regularized Tao-Mo exchange (v1) + MGGA_X_SREGTM_V1 = 772, + /// Simplified regularized Tao-Mo exchange (v2) + MGGA_X_SREGTM_V2 = 773, + /// Simplified regularized Tao-Mo exchange (v3) + MGGA_X_SREGTM_V3 = 774, } diff --git a/readme.md b/readme.md index 9368725..f284572 100644 --- a/readme.md +++ b/readme.md @@ -50,7 +50,7 @@ Default features: Other features: - **`api-v6_2`**: Binds libxc v6.2.2 (base API). -- **`api-v7_1`**: Binds libxc v7.1.0 API (cumulative with `api-v7_0`). Adds `xc_func_init_flags` and runtime device selection. Note v7.1.0 is not a released version (devel branch of original libxc), API may change for v7.1. +- **`api-v7_1`**: Binds libxc v7.1 API (cumulative with `api-v7_0`; released upstream as 7.1.0–7.1.2, headers track the 7.1.2 tag). Adds `xc_func_init_flags` and runtime device selection. - **`cuda`**: GPU computation support via `cudarc`. - Creates GPU functionals with [`LibXCFunctional::from_identifier_with_device`] and [`LibXCDeviceFlag::OnDevice`]; computes with [`cuda_compute_xc`] (and per-family `cuda_compute_lda`/`gga`/`mgga`, plus `_with_output`/`_with_unsliced_output` variants). - Input/output types are [`LibXCCudaInput`] (`HashMap>`) and [`LibXCCudaOutputMut`] (`HashMap>`). From 6a892415a47cd2fcfe5ade0fddfdcfa2340965ec Mon Sep 17 00:00:00 2001 From: ajz34 Date: Tue, 8 Sep 2026 21:34:57 +0800 Subject: [PATCH 3/4] Update to v0.1.3 Co-authored-by: Claude Code Co-authored-by: glm-5.3 --- CHANGELOG.md | 2 +- Cargo.toml | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 109d16c..96cbd50 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,6 @@ # Changelog -## Unreleased +## v0.1.3 -- 2026-09-08 Fix: diff --git a/Cargo.toml b/Cargo.toml index e99d4c3..32d3956 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,7 +7,7 @@ members = [ [workspace.package] edition = "2021" rust-version = "1.82" -version = "0.1.2" +version = "0.1.3" description = "libxc FFI bindings and wrappers" repository = "https://github.com/RESTGroup/libxc-rs" keywords = ["ffi", "chemistry"] @@ -21,4 +21,4 @@ license = "Apache-2.0" # are always unified in, and e.g. `--features api-v6_2` would still compile # the v7.0 struct layout of `xc_func_type` — which reads out of bounds when # a v6.2.2 shared library is loaded at runtime. -libxc-ffi = { path = "libxc-ffi", version = "0.1.2", default-features = false } +libxc-ffi = { path = "libxc-ffi", version = "0.1.3", default-features = false } From 1aa63e2c59e6e1e8e874a4778b73dd88a0d65a75 Mon Sep 17 00:00:00 2001 From: ajz34 Date: Wed, 9 Sep 2026 10:58:48 +0800 Subject: [PATCH 4/4] Fix CI: explicit dynamic_loading in v7.0 test job, reformat for new rustfmt - test-v7.0 workflow: add dynamic_loading to the feature list. The job ran cargo test --no-default-features --features="api-v7_0", which previously still loaded dynamically because libxc-ffi's default features were always unified in; after the feature isolation fix it compiled the static FFI and failed at link time with undefined xc_* symbols. Also pin conda-forge libxc to 7.0.*: the unpinned install now resolves to 7.1.2, which does not pair with api-v7_0 bindings by design. - cargo fmt --all: current rustfmt reflows over-width trailing comments, flagging functional_specific.rs and tests/regression/* untouched since May; compute_cpu.rs had two genuinely over-width lines from this PR. - CHANGELOG: note the CI workflow change under the v0.1.3 fix entry. Verified locally: cargo fmt --check clean; clippy --all-targets --all-features -D warnings clean; the exact CI test command passes against the 7.0.0 shared library. Co-authored-by: Claude Code Co-authored-by: glm-5.3-flash --- .github/workflows/test-v7_0.yml | 4 ++-- CHANGELOG.md | 4 ++++ libxc/src/compute_cpu.rs | 6 ++++-- libxc/src/functional_specific.rs | 10 ++++++---- libxc/tests/regression/example_densities.rs | 3 ++- libxc/tests/regression/test_reference.rs | 7 ++++--- 6 files changed, 22 insertions(+), 12 deletions(-) diff --git a/.github/workflows/test-v7_0.yml b/.github/workflows/test-v7_0.yml index fe7c6f4..a6fd087 100644 --- a/.github/workflows/test-v7_0.yml +++ b/.github/workflows/test-v7_0.yml @@ -15,7 +15,7 @@ jobs: - uses: conda-incubator/setup-miniconda@v3 - name: run tests run: | - conda install libxc -c conda-forge + conda install "libxc=7.0.*" -c conda-forge ls /usr/share/miniconda/lib export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/share/miniconda/lib - cargo test -p libxc --no-default-features --features="api-v7_0" -- --nocapture + cargo test -p libxc --no-default-features --features="api-v7_0,dynamic_loading" -- --nocapture diff --git a/CHANGELOG.md b/CHANGELOG.md index 96cbd50..e745a73 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,10 @@ Fix: pre-v7.0 libraries; zeroed scratch substituted for null lapl/tau inputs and for tau-family outputs missing from the layout/output map (libxc 6.2.x aborts the process otherwise) + - CI: the v7.0 test workflow now selects `dynamic_loading` explicitly and + pins conda-forge `libxc` to `7.0.*`; it previously relied on the implicit + feature unification fixed above, and conda-forge's default libxc is now + 7.1.2 Enhancement: diff --git a/libxc/src/compute_cpu.rs b/libxc/src/compute_cpu.rs index 0f3ed1c..4527ebd 100644 --- a/libxc/src/compute_cpu.rs +++ b/libxc/src/compute_cpu.rs @@ -367,7 +367,8 @@ impl LibXCFunctional { let tau_scratch = input_scratch(dim.tau, npoints); let lapl_ptr = if lapl_ptr.is_null() { lapl_scratch.as_ptr() } else { lapl_ptr }; let tau_ptr = if tau_ptr.is_null() { tau_scratch.as_ptr() } else { tau_ptr }; - let (_scratch_bufs, extra) = crate::layout_handling::mgga_tau_scratch(&layout, dim, npoints); + let (_scratch_bufs, extra) = + crate::layout_handling::mgga_tau_scratch(&layout, dim, npoints); unsafe { xc_mgga_call( self.ptr, @@ -404,7 +405,8 @@ impl LibXCFunctional { let tau_scratch = input_scratch(dim.tau, npoints); let lapl_ptr = if lapl_ptr.is_null() { lapl_scratch.as_ptr() } else { lapl_ptr }; let tau_ptr = if tau_ptr.is_null() { tau_scratch.as_ptr() } else { tau_ptr }; - let (_scratch_bufs, extra) = crate::layout_handling::mgga_tau_scratch(&layout, dim, npoints); + let (_scratch_bufs, extra) = + crate::layout_handling::mgga_tau_scratch(&layout, dim, npoints); unsafe { xc_mgga_call( self.ptr, diff --git a/libxc/src/functional_specific.rs b/libxc/src/functional_specific.rs index 26305e8..e788e6d 100644 --- a/libxc/src/functional_specific.rs +++ b/libxc/src/functional_specific.rs @@ -88,8 +88,8 @@ impl LibXCFunctional { details: "Current functional is not hybrid cam-type (range-separated). Please call `set_hyb_exx_coef` if it is hybrid functional.".to_string(), }); } - // set the CAM coefficients, which is usually the canonical way to get these - // parameters + // set the CAM coefficients, which is usually the canonical way to get + // these parameters unsafe { (*self.ptr).cam_alpha = cam_alpha; (*self.ptr).cam_beta = cam_beta; @@ -106,7 +106,8 @@ impl LibXCFunctional { [("_csr", cam_alpha + cam_beta), ("_clr", cam_alpha), ("_omega", cam_omega)]; self.set_ext_param_map_f(param_map.into_iter())?; } else if self.ext_param_names().iter().any(|name| name == "_omega") { - // pattern 3: only omega, with alpha and beta fixed by the functional definition + // pattern 3: only omega, with alpha and beta fixed by the + // functional definition let param_map = [("_omega", cam_omega)]; self.set_ext_param_map_f(param_map.into_iter())?; } else { @@ -151,7 +152,8 @@ impl LibXCFunctional { details: "Current functional is not VV10.".to_string(), }); } - // set the VV10 coefficients, which is the canonical way to get these parameters + // set the VV10 coefficients, which is the canonical way to get these + // parameters unsafe { (*self.ptr).nlc_b = nlc_b; (*self.ptr).nlc_C = nlc_C; diff --git a/libxc/tests/regression/example_densities.rs b/libxc/tests/regression/example_densities.rs index 85f8389..d351287 100644 --- a/libxc/tests/regression/example_densities.rs +++ b/libxc/tests/regression/example_densities.rs @@ -31,7 +31,8 @@ pub fn test_input(data: &[[f64; 9]], spin: LibXCSpin) -> HashMap { - // [data[RHO_A][0], data[RHO_B][0], data[RHO_A][1], data[RHO_B][1], ...] + // [data[RHO_A][0], data[RHO_B][0], data[RHO_A][1], data[RHO_B][1], + // ...] let rho = data.iter().flat_map(|r| [r[RHO_A], r[RHO_B]]).collect(); let sigma = data.iter().flat_map(|r| [r[SIGMA_AA], r[SIGMA_AB], r[SIGMA_BB]]).collect(); let lapl = data.iter().flat_map(|r| [r[LAPL_A], r[LAPL_B]]).collect(); diff --git a/libxc/tests/regression/test_reference.rs b/libxc/tests/regression/test_reference.rs index 4eb5c9d..5e17d88 100644 --- a/libxc/tests/regression/test_reference.rs +++ b/libxc/tests/regression/test_reference.rs @@ -70,8 +70,8 @@ fn test_regression_entry( return Err("SKIP".to_string()); } - // BrOH is always unpolarized; _restr species are unpolarized; all others are - // polarized + // BrOH is always unpolarized; _restr species are unpolarized; all others + // are polarized let spin = if species == "BrOH" || species.contains("restr") { Unpolarized } else { Polarized }; let input = example_densities::test_data(species.to_string(), spin); let input_ref = input.iter().map(|(k, v)| (k.clone(), v.as_slice())).collect(); @@ -93,7 +93,8 @@ fn test_regression_entry( None => return Err(format!("key {} not found in output for {}", key, xc_identifier)), }; let (rtol, atol) = if key == "zk" { (5e-8, 1e-10) } else { (5e-5, 1e-7) }; - let error_metric = get_error(ref_out, ref_values); // this is how libxc tests + let error_metric = get_error(ref_out, ref_values); // this is how libxc + // tests if !allclose(ref_out, ref_values, rtol, atol) && error_metric > rtol { return Err(format!( "mismatch for {}.{} key={}, len={} vs {}, error_metric={:.2e}",