gfn1-rs-python 0.4.5__tar.gz → 0.4.6__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {gfn1_rs_python-0.4.5 → gfn1_rs_python-0.4.6}/Cargo.lock +1 -1
- {gfn1_rs_python-0.4.5 → gfn1_rs_python-0.4.6}/Cargo.toml +1 -1
- {gfn1_rs_python-0.4.5 → gfn1_rs_python-0.4.6}/PKG-INFO +1 -1
- {gfn1_rs_python-0.4.5 → gfn1_rs_python-0.4.6}/pyproject.toml +1 -1
- {gfn1_rs_python-0.4.5 → gfn1_rs_python-0.4.6}/src/dispersion.rs +65 -76
- {gfn1_rs_python-0.4.5 → gfn1_rs_python-0.4.6}/src/hessian.rs +21 -114
- {gfn1_rs_python-0.4.5 → gfn1_rs_python-0.4.6}/LICENSE +0 -0
- {gfn1_rs_python-0.4.5 → gfn1_rs_python-0.4.6}/README.md +0 -0
- {gfn1_rs_python-0.4.5 → gfn1_rs_python-0.4.6}/THIRD_PARTY_NOTICES.md +0 -0
- {gfn1_rs_python-0.4.5 → gfn1_rs_python-0.4.6}/docs/python-api.md +0 -0
- {gfn1_rs_python-0.4.5 → gfn1_rs_python-0.4.6}/docs/rust-api.md +0 -0
- {gfn1_rs_python-0.4.5 → gfn1_rs_python-0.4.6}/docs/scope.md +0 -0
- {gfn1_rs_python-0.4.5 → gfn1_rs_python-0.4.6}/docs/sigma_hole_preset.md +0 -0
- {gfn1_rs_python-0.4.5 → gfn1_rs_python-0.4.6}/examples/ammonia.xyz +0 -0
- {gfn1_rs_python-0.4.5 → gfn1_rs_python-0.4.6}/examples/bromoethanol.xyz +0 -0
- {gfn1_rs_python-0.4.5 → gfn1_rs_python-0.4.6}/examples/diamond.xyz +0 -0
- {gfn1_rs_python-0.4.5 → gfn1_rs_python-0.4.6}/examples/diamond222.xyz +0 -0
- {gfn1_rs_python-0.4.5 → gfn1_rs_python-0.4.6}/examples/dppf_pdcl2.xyz +0 -0
- {gfn1_rs_python-0.4.5 → gfn1_rs_python-0.4.6}/examples/h2.engrad +0 -0
- {gfn1_rs_python-0.4.5 → gfn1_rs_python-0.4.6}/examples/h2.xyz +0 -0
- {gfn1_rs_python-0.4.5 → gfn1_rs_python-0.4.6}/examples/lao_kinetic_grid_check.rs +0 -0
- {gfn1_rs_python-0.4.5 → gfn1_rs_python-0.4.6}/examples/mag_cpscc_check.rs +0 -0
- {gfn1_rs_python-0.4.5 → gfn1_rs_python-0.4.6}/examples/magnetizability_validation.rs +0 -0
- {gfn1_rs_python-0.4.5 → gfn1_rs_python-0.4.6}/examples/methane.xyz +0 -0
- {gfn1_rs_python-0.4.5 → gfn1_rs_python-0.4.6}/examples/ni_co4.xyz +0 -0
- {gfn1_rs_python-0.4.5 → gfn1_rs_python-0.4.6}/examples/profile_magnetic.rs +0 -0
- {gfn1_rs_python-0.4.5 → gfn1_rs_python-0.4.6}/examples/profile_pbc.rs +0 -0
- {gfn1_rs_python-0.4.5 → gfn1_rs_python-0.4.6}/examples/water.xyz +0 -0
- {gfn1_rs_python-0.4.5 → gfn1_rs_python-0.4.6}/examples/water100.xyz +0 -0
- {gfn1_rs_python-0.4.5 → gfn1_rs_python-0.4.6}/examples/water48.xyz +0 -0
- {gfn1_rs_python-0.4.5 → gfn1_rs_python-0.4.6}/examples/water_opt.xyz +0 -0
- {gfn1_rs_python-0.4.5 → gfn1_rs_python-0.4.6}/python/gfn1_rs/__init__.py +0 -0
- {gfn1_rs_python-0.4.5 → gfn1_rs_python-0.4.6}/python/gfn1_rs/ase.py +0 -0
- {gfn1_rs_python-0.4.5 → gfn1_rs_python-0.4.6}/python/gfn1_rs/native.py +0 -0
- {gfn1_rs_python-0.4.5 → gfn1_rs_python-0.4.6}/python/gfn1_rs/torch_interop.py +0 -0
- {gfn1_rs_python-0.4.5 → gfn1_rs_python-0.4.6}/scripts/compare_optimizations.py +0 -0
- {gfn1_rs_python-0.4.5 → gfn1_rs_python-0.4.6}/scripts/gen_secondary_basis.py +0 -0
- {gfn1_rs_python-0.4.5 → gfn1_rs_python-0.4.6}/scripts/optimize.py +0 -0
- {gfn1_rs_python-0.4.5 → gfn1_rs_python-0.4.6}/scripts/run_mgo_kpoint_md.py +0 -0
- {gfn1_rs_python-0.4.5 → gfn1_rs_python-0.4.6}/src/basis.rs +0 -0
- {gfn1_rs_python-0.4.5 → gfn1_rs_python-0.4.6}/src/bin/gfn1_rs.rs +0 -0
- {gfn1_rs_python-0.4.5 → gfn1_rs_python-0.4.6}/src/constants.rs +0 -0
- {gfn1_rs_python-0.4.5 → gfn1_rs_python-0.4.6}/src/coordination.rs +0 -0
- {gfn1_rs_python-0.4.5 → gfn1_rs_python-0.4.6}/src/coulomb.rs +0 -0
- {gfn1_rs_python-0.4.5 → gfn1_rs_python-0.4.6}/src/cphf.rs +0 -0
- {gfn1_rs_python-0.4.5 → gfn1_rs_python-0.4.6}/src/d4_reference.rs +0 -0
- {gfn1_rs_python-0.4.5 → gfn1_rs_python-0.4.6}/src/data_tables.rs +0 -0
- {gfn1_rs_python-0.4.5 → gfn1_rs_python-0.4.6}/src/electronic.rs +0 -0
- {gfn1_rs_python-0.4.5 → gfn1_rs_python-0.4.6}/src/error.rs +0 -0
- {gfn1_rs_python-0.4.5 → gfn1_rs_python-0.4.6}/src/exchange.rs +0 -0
- {gfn1_rs_python-0.4.5 → gfn1_rs_python-0.4.6}/src/field.rs +0 -0
- {gfn1_rs_python-0.4.5 → gfn1_rs_python-0.4.6}/src/gradient.rs +0 -0
- {gfn1_rs_python-0.4.5 → gfn1_rs_python-0.4.6}/src/halogen.rs +0 -0
- {gfn1_rs_python-0.4.5 → gfn1_rs_python-0.4.6}/src/hamiltonian.rs +0 -0
- {gfn1_rs_python-0.4.5 → gfn1_rs_python-0.4.6}/src/integrals.rs +0 -0
- {gfn1_rs_python-0.4.5 → gfn1_rs_python-0.4.6}/src/integrals_second_derivatives.rs +0 -0
- {gfn1_rs_python-0.4.5 → gfn1_rs_python-0.4.6}/src/integrals_third_derivatives.rs +0 -0
- {gfn1_rs_python-0.4.5 → gfn1_rs_python-0.4.6}/src/lattice.rs +0 -0
- {gfn1_rs_python-0.4.5 → gfn1_rs_python-0.4.6}/src/lib.rs +0 -0
- {gfn1_rs_python-0.4.5 → gfn1_rs_python-0.4.6}/src/linalg.rs +0 -0
- {gfn1_rs_python-0.4.5 → gfn1_rs_python-0.4.6}/src/magnetic.rs +0 -0
- {gfn1_rs_python-0.4.5 → gfn1_rs_python-0.4.6}/src/math.rs +0 -0
- {gfn1_rs_python-0.4.5 → gfn1_rs_python-0.4.6}/src/model.rs +0 -0
- {gfn1_rs_python-0.4.5 → gfn1_rs_python-0.4.6}/src/multipole.rs +0 -0
- {gfn1_rs_python-0.4.5 → gfn1_rs_python-0.4.6}/src/nmr.rs +0 -0
- {gfn1_rs_python-0.4.5 → gfn1_rs_python-0.4.6}/src/optimizer.rs +0 -0
- {gfn1_rs_python-0.4.5 → gfn1_rs_python-0.4.6}/src/pairlist.rs +0 -0
- {gfn1_rs_python-0.4.5 → gfn1_rs_python-0.4.6}/src/param_deriv.rs +0 -0
- {gfn1_rs_python-0.4.5 → gfn1_rs_python-0.4.6}/src/params.rs +0 -0
- {gfn1_rs_python-0.4.5 → gfn1_rs_python-0.4.6}/src/pbc/bloch.rs +0 -0
- {gfn1_rs_python-0.4.5 → gfn1_rs_python-0.4.6}/src/pbc/complex.rs +0 -0
- {gfn1_rs_python-0.4.5 → gfn1_rs_python-0.4.6}/src/pbc/ewald.rs +0 -0
- {gfn1_rs_python-0.4.5 → gfn1_rs_python-0.4.6}/src/pbc/ewald_multipole.rs +0 -0
- {gfn1_rs_python-0.4.5 → gfn1_rs_python-0.4.6}/src/pbc/gradient.rs +0 -0
- {gfn1_rs_python-0.4.5 → gfn1_rs_python-0.4.6}/src/pbc/hessian.rs +0 -0
- {gfn1_rs_python-0.4.5 → gfn1_rs_python-0.4.6}/src/pbc/kpoints.rs +0 -0
- {gfn1_rs_python-0.4.5 → gfn1_rs_python-0.4.6}/src/pbc/mod.rs +0 -0
- {gfn1_rs_python-0.4.5 → gfn1_rs_python-0.4.6}/src/pbc/scf.rs +0 -0
- {gfn1_rs_python-0.4.5 → gfn1_rs_python-0.4.6}/src/pbc/stress.rs +0 -0
- {gfn1_rs_python-0.4.5 → gfn1_rs_python-0.4.6}/src/plus_u.rs +0 -0
- {gfn1_rs_python-0.4.5 → gfn1_rs_python-0.4.6}/src/plus_u_dudr.rs +0 -0
- {gfn1_rs_python-0.4.5 → gfn1_rs_python-0.4.6}/src/profile.rs +0 -0
- {gfn1_rs_python-0.4.5 → gfn1_rs_python-0.4.6}/src/properties.rs +0 -0
- {gfn1_rs_python-0.4.5 → gfn1_rs_python-0.4.6}/src/python.rs +0 -0
- {gfn1_rs_python-0.4.5 → gfn1_rs_python-0.4.6}/src/repulsion.rs +0 -0
- {gfn1_rs_python-0.4.5 → gfn1_rs_python-0.4.6}/src/secondary_bases/gfn1-xtb-cc-pv5z.txt +0 -0
- {gfn1_rs_python-0.4.5 → gfn1_rs_python-0.4.6}/src/secondary_bases/gfn1-xtb-cc-pvdz.txt +0 -0
- {gfn1_rs_python-0.4.5 → gfn1_rs_python-0.4.6}/src/secondary_bases/gfn1-xtb-cc-pvqz.txt +0 -0
- {gfn1_rs_python-0.4.5 → gfn1_rs_python-0.4.6}/src/secondary_bases/gfn1-xtb-cc-pvtz.txt +0 -0
- {gfn1_rs_python-0.4.5 → gfn1_rs_python-0.4.6}/src/secondary_bases.rs +0 -0
- {gfn1_rs_python-0.4.5 → gfn1_rs_python-0.4.6}/src/secondary_basis.rs +0 -0
- {gfn1_rs_python-0.4.5 → gfn1_rs_python-0.4.6}/src/spin.rs +0 -0
- {gfn1_rs_python-0.4.5 → gfn1_rs_python-0.4.6}/src/sto.rs +0 -0
- {gfn1_rs_python-0.4.5 → gfn1_rs_python-0.4.6}/src/system.rs +0 -0
- {gfn1_rs_python-0.4.5 → gfn1_rs_python-0.4.6}/src/td.rs +0 -0
- {gfn1_rs_python-0.4.5 → gfn1_rs_python-0.4.6}/src/third_derivative.rs +0 -0
- {gfn1_rs_python-0.4.5 → gfn1_rs_python-0.4.6}/src/trah.rs +0 -0
- {gfn1_rs_python-0.4.5 → gfn1_rs_python-0.4.6}/src/vibrational.rs +0 -0
- {gfn1_rs_python-0.4.5 → gfn1_rs_python-0.4.6}/tests/d4.rs +0 -0
- {gfn1_rs_python-0.4.5 → gfn1_rs_python-0.4.6}/tests/field.rs +0 -0
- {gfn1_rs_python-0.4.5 → gfn1_rs_python-0.4.6}/tests/gradient_fd_probe.rs +0 -0
- {gfn1_rs_python-0.4.5 → gfn1_rs_python-0.4.6}/tests/hessian.rs +0 -0
- {gfn1_rs_python-0.4.5 → gfn1_rs_python-0.4.6}/tests/kpoint_hessian_repro.rs +0 -0
- {gfn1_rs_python-0.4.5 → gfn1_rs_python-0.4.6}/tests/magnetic.rs +0 -0
- {gfn1_rs_python-0.4.5 → gfn1_rs_python-0.4.6}/tests/nonpbc_smoke.rs +0 -0
- {gfn1_rs_python-0.4.5 → gfn1_rs_python-0.4.6}/tests/optimizer.rs +0 -0
- {gfn1_rs_python-0.4.5 → gfn1_rs_python-0.4.6}/tests/param_deriv.rs +0 -0
- {gfn1_rs_python-0.4.5 → gfn1_rs_python-0.4.6}/tests/pbc_integration.rs +0 -0
- {gfn1_rs_python-0.4.5 → gfn1_rs_python-0.4.6}/tests/properties.rs +0 -0
- {gfn1_rs_python-0.4.5 → gfn1_rs_python-0.4.6}/tests/scf_accelerators.rs +0 -0
- {gfn1_rs_python-0.4.5 → gfn1_rs_python-0.4.6}/tests/tblite_parity.rs +0 -0
- {gfn1_rs_python-0.4.5 → gfn1_rs_python-0.4.6}/tests/td.rs +0 -0
- {gfn1_rs_python-0.4.5 → gfn1_rs_python-0.4.6}/third_party/dftd4/CITATION.bib +0 -0
- {gfn1_rs_python-0.4.5 → gfn1_rs_python-0.4.6}/third_party/dftd4/COPYING +0 -0
- {gfn1_rs_python-0.4.5 → gfn1_rs_python-0.4.6}/third_party/dftd4/COPYING.LESSER +0 -0
- {gfn1_rs_python-0.4.5 → gfn1_rs_python-0.4.6}/third_party/dftd4/PROVENANCE.md +0 -0
- {gfn1_rs_python-0.4.5 → gfn1_rs_python-0.4.6}/third_party/dftd4/assets/parameters.toml +0 -0
- {gfn1_rs_python-0.4.5 → gfn1_rs_python-0.4.6}/third_party/dftd4/src/dftd4/data/hardness.f90 +0 -0
- {gfn1_rs_python-0.4.5 → gfn1_rs_python-0.4.6}/third_party/dftd4/src/dftd4/data/r4r2.f90 +0 -0
- {gfn1_rs_python-0.4.5 → gfn1_rs_python-0.4.6}/third_party/dftd4/src/dftd4/data/wfpair.f90 +0 -0
- {gfn1_rs_python-0.4.5 → gfn1_rs_python-0.4.6}/third_party/dftd4/src/dftd4/data/zeff.f90 +0 -0
- {gfn1_rs_python-0.4.5 → gfn1_rs_python-0.4.6}/third_party/dftd4/src/dftd4/reference.f90 +0 -0
- {gfn1_rs_python-0.4.5 → gfn1_rs_python-0.4.6}/third_party/dftd4/src/dftd4/reference.inc +0 -0
- {gfn1_rs_python-0.4.5 → gfn1_rs_python-0.4.6}/third_party/simple-dftd3/COPYING +0 -0
- {gfn1_rs_python-0.4.5 → gfn1_rs_python-0.4.6}/third_party/simple-dftd3/COPYING.LESSER +0 -0
- {gfn1_rs_python-0.4.5 → gfn1_rs_python-0.4.6}/third_party/simple-dftd3/src/dftd3/data/r4r2.f90 +0 -0
- {gfn1_rs_python-0.4.5 → gfn1_rs_python-0.4.6}/third_party/simple-dftd3/src/dftd3/reference.f90 +0 -0
- {gfn1_rs_python-0.4.5 → gfn1_rs_python-0.4.6}/third_party/tblite/PROVENANCE.md +0 -0
- {gfn1_rs_python-0.4.5 → gfn1_rs_python-0.4.6}/third_party/tblite/spin.f90 +0 -0
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
|
2
2
|
//! DFT-D3(BJ) dispersion and experimental non-PBC DFT-D4 dispersion for GFN1-xTB.
|
|
3
3
|
//!
|
|
4
|
-
//! The large D3 C6 reference table is
|
|
5
|
-
//!
|
|
4
|
+
//! The large D3 C6 reference table is bundled under `third_party/simple-dftd3`
|
|
5
|
+
//! and embedded at build time (`s-dftd3/src/dftd3/reference.f90`), so it is used
|
|
6
|
+
//! by default; an explicit path or the `GFN1_D3_REFERENCE` environment variable
|
|
7
|
+
//! can override it.
|
|
6
8
|
//! D4 reference data are stored with upstream provenance under `third_party/dftd4`;
|
|
7
9
|
//! the GFN1 damping constants `a1`, `a2`, and `s8` are read from the
|
|
8
10
|
//! user-supplied `param_gfn1-xtb.txt` through [`Gfn1Parameters`]. The experimental
|
|
@@ -21,7 +23,7 @@ use crate::params::{Gfn1Parameters, GFN1_D3_REFERENCE_ENV};
|
|
|
21
23
|
use crate::system::PeriodicSystem;
|
|
22
24
|
use std::collections::HashMap;
|
|
23
25
|
use std::fs;
|
|
24
|
-
use std::path::
|
|
26
|
+
use std::path::Path;
|
|
25
27
|
use std::sync::{Arc, Mutex, OnceLock};
|
|
26
28
|
|
|
27
29
|
const WF: f64 = 4.0;
|
|
@@ -1238,8 +1240,7 @@ pub fn dispersion_energy_gradient(
|
|
|
1238
1240
|
let a1 = params.required_global("a1")?;
|
|
1239
1241
|
let a2 = params.required_global("a2")?;
|
|
1240
1242
|
|
|
1241
|
-
let
|
|
1242
|
-
let reference = load_d3_reference(&reference_path)?;
|
|
1243
|
+
let reference = resolve_and_load_d3_reference(explicit_reference_path)?;
|
|
1243
1244
|
let cn = coordination_with_derivatives(
|
|
1244
1245
|
system,
|
|
1245
1246
|
CoordinationOptions {
|
|
@@ -1374,8 +1375,7 @@ pub fn dispersion_energy_gradient_hessian(
|
|
|
1374
1375
|
}
|
|
1375
1376
|
let a1 = params.required_global("a1")?;
|
|
1376
1377
|
let a2 = params.required_global("a2")?;
|
|
1377
|
-
let
|
|
1378
|
-
let reference = load_d3_reference(&reference_path)?;
|
|
1378
|
+
let reference = resolve_and_load_d3_reference(explicit_reference_path)?;
|
|
1379
1379
|
let nat = system.atoms.len();
|
|
1380
1380
|
let ndof = 3 * nat;
|
|
1381
1381
|
let coords = jet_coordinates(system, ndof);
|
|
@@ -1474,8 +1474,7 @@ fn dispersion_strain_energy_jet(
|
|
|
1474
1474
|
let atm_active = s9.abs() > 1.0e-15;
|
|
1475
1475
|
let a1 = params.required_global("a1")?;
|
|
1476
1476
|
let a2 = params.required_global("a2")?;
|
|
1477
|
-
let
|
|
1478
|
-
let reference = load_d3_reference(&reference_path)?;
|
|
1477
|
+
let reference = resolve_and_load_d3_reference(explicit_reference_path)?;
|
|
1479
1478
|
let cn = d3_strain_coordination_jets(system, ndof)?;
|
|
1480
1479
|
let weights = reference_weight_jets(system, &reference, &cn, ndof)?;
|
|
1481
1480
|
let c6 = atomic_c6_jets(system, &reference, &weights, ndof)?;
|
|
@@ -1642,65 +1641,37 @@ fn d3_atm_triple_energy_strain_jet(
|
|
|
1642
1641
|
pref.mul(&angular).mul(&fdmp)
|
|
1643
1642
|
}
|
|
1644
1643
|
|
|
1645
|
-
|
|
1646
|
-
|
|
1644
|
+
/// Resolve and load the D3 C6 reference data. An explicit path (the
|
|
1645
|
+
/// `--d3-reference` API argument) or the `GFN1_D3_REFERENCE` environment variable
|
|
1646
|
+
/// overrides the default; when neither is set, the reference bundled with the
|
|
1647
|
+
/// library and embedded at build time is used.
|
|
1648
|
+
fn resolve_and_load_d3_reference(
|
|
1647
1649
|
explicit_reference_path: Option<&str>,
|
|
1648
|
-
) -> Result<
|
|
1650
|
+
) -> Result<Arc<D3Reference>> {
|
|
1649
1651
|
if let Some(path) = explicit_reference_path {
|
|
1650
1652
|
let trimmed = path.trim();
|
|
1651
1653
|
if !trimmed.is_empty() {
|
|
1652
|
-
return
|
|
1654
|
+
return load_d3_reference(Path::new(trimmed));
|
|
1653
1655
|
}
|
|
1654
1656
|
}
|
|
1655
1657
|
if let Ok(path) = std::env::var(GFN1_D3_REFERENCE_ENV) {
|
|
1656
1658
|
let trimmed = path.trim();
|
|
1657
1659
|
if !trimmed.is_empty() {
|
|
1658
|
-
return
|
|
1659
|
-
}
|
|
1660
|
-
}
|
|
1661
|
-
|
|
1662
|
-
if let Some(param_path) = ¶ms.source_path {
|
|
1663
|
-
let param = Path::new(param_path);
|
|
1664
|
-
if let Some(param_dir) = param.parent() {
|
|
1665
|
-
if let Some(root) = param_dir.parent() {
|
|
1666
|
-
let candidate = root
|
|
1667
|
-
.join("tblite")
|
|
1668
|
-
.join("subprojects")
|
|
1669
|
-
.join("s-dftd3")
|
|
1670
|
-
.join("src")
|
|
1671
|
-
.join("dftd3")
|
|
1672
|
-
.join("reference.f90");
|
|
1673
|
-
if candidate.exists() {
|
|
1674
|
-
return Ok(candidate);
|
|
1675
|
-
}
|
|
1676
|
-
}
|
|
1677
|
-
let candidate = param_dir
|
|
1678
|
-
.join("..")
|
|
1679
|
-
.join("tblite")
|
|
1680
|
-
.join("subprojects")
|
|
1681
|
-
.join("s-dftd3")
|
|
1682
|
-
.join("src")
|
|
1683
|
-
.join("dftd3")
|
|
1684
|
-
.join("reference.f90");
|
|
1685
|
-
if candidate.exists() {
|
|
1686
|
-
return Ok(candidate);
|
|
1687
|
-
}
|
|
1660
|
+
return load_d3_reference(Path::new(trimmed));
|
|
1688
1661
|
}
|
|
1689
1662
|
}
|
|
1663
|
+
bundled_d3_reference()
|
|
1664
|
+
}
|
|
1690
1665
|
|
|
1691
|
-
|
|
1692
|
-
|
|
1693
|
-
|
|
1694
|
-
|
|
1695
|
-
.
|
|
1696
|
-
.join("reference.f90");
|
|
1697
|
-
if bundled.exists() {
|
|
1698
|
-
return Ok(bundled);
|
|
1666
|
+
/// Parse and cache the D3 reference embedded in the library.
|
|
1667
|
+
fn bundled_d3_reference() -> Result<Arc<D3Reference>> {
|
|
1668
|
+
static CACHE: OnceLock<Arc<D3Reference>> = OnceLock::new();
|
|
1669
|
+
if let Some(found) = CACHE.get() {
|
|
1670
|
+
return Ok(found.clone());
|
|
1699
1671
|
}
|
|
1700
|
-
|
|
1701
|
-
|
|
1702
|
-
|
|
1703
|
-
)))
|
|
1672
|
+
let loaded = Arc::new(D3Reference::bundled()?);
|
|
1673
|
+
let _ = CACHE.set(loaded.clone());
|
|
1674
|
+
Ok(loaded)
|
|
1704
1675
|
}
|
|
1705
1676
|
|
|
1706
1677
|
#[derive(Clone, Debug)]
|
|
@@ -2777,8 +2748,7 @@ pub fn dispersion_third_derivative(
|
|
|
2777
2748
|
}
|
|
2778
2749
|
let a1 = params.required_global("a1")?;
|
|
2779
2750
|
let a2 = params.required_global("a2")?;
|
|
2780
|
-
let
|
|
2781
|
-
let reference = load_d3_reference(&reference_path)?;
|
|
2751
|
+
let reference = resolve_and_load_d3_reference(explicit_reference_path)?;
|
|
2782
2752
|
let nat = system.atoms.len();
|
|
2783
2753
|
let ndof = 3 * nat;
|
|
2784
2754
|
let coords = jet3_coordinates(system, ndof);
|
|
@@ -2827,10 +2797,18 @@ struct D3Reference {
|
|
|
2827
2797
|
r4r2: Vec<f64>,
|
|
2828
2798
|
}
|
|
2829
2799
|
|
|
2800
|
+
/// D3 C6 reference table and `r4/r2` data, bundled under `third_party/simple-dftd3`
|
|
2801
|
+
/// and embedded at build time so the default dispersion path needs no external
|
|
2802
|
+
/// file. Overridable through the `--d3-reference` API argument or the
|
|
2803
|
+
/// `GFN1_D3_REFERENCE` environment variable.
|
|
2804
|
+
const BUNDLED_D3_REFERENCE_F90: &str =
|
|
2805
|
+
include_str!("../third_party/simple-dftd3/src/dftd3/reference.f90");
|
|
2806
|
+
const BUNDLED_D3_R4R2_F90: &str =
|
|
2807
|
+
include_str!("../third_party/simple-dftd3/src/dftd3/data/r4r2.f90");
|
|
2808
|
+
|
|
2830
2809
|
impl D3Reference {
|
|
2831
|
-
fn
|
|
2832
|
-
let
|
|
2833
|
-
let clean = strip_fortran_comments(&text);
|
|
2810
|
+
fn from_reference_text(reference_text: &str, r4r2_text: &str) -> Result<Self> {
|
|
2811
|
+
let clean = strip_fortran_comments(reference_text);
|
|
2834
2812
|
let max_elem = parse_parameter_usize(&clean, "max_elem")?;
|
|
2835
2813
|
let max_ref = parse_parameter_usize(&clean, "max_ref")?;
|
|
2836
2814
|
let number_of_references = parse_int_array_after(&clean, "number_of_references")?
|
|
@@ -2859,14 +2837,7 @@ impl D3Reference {
|
|
|
2859
2837
|
c6.len()
|
|
2860
2838
|
)));
|
|
2861
2839
|
}
|
|
2862
|
-
let
|
|
2863
|
-
.parent()
|
|
2864
|
-
.ok_or_else(|| {
|
|
2865
|
-
Gfn1Error::InvalidInput("D3 reference path has no parent directory".to_string())
|
|
2866
|
-
})?
|
|
2867
|
-
.join("data")
|
|
2868
|
-
.join("r4r2.f90");
|
|
2869
|
-
let r4r2 = parse_r4r2_file(&r4r2_path)?;
|
|
2840
|
+
let r4r2 = parse_r4r2_text(r4r2_text)?;
|
|
2870
2841
|
Ok(Self {
|
|
2871
2842
|
max_elem,
|
|
2872
2843
|
max_ref,
|
|
@@ -2877,6 +2848,27 @@ impl D3Reference {
|
|
|
2877
2848
|
})
|
|
2878
2849
|
}
|
|
2879
2850
|
|
|
2851
|
+
/// Parse the D3 reference from a `reference.f90` file, reading the companion
|
|
2852
|
+
/// `data/r4r2.f90` next to it. Used only when an explicit path or the
|
|
2853
|
+
/// `GFN1_D3_REFERENCE` environment variable overrides the bundled default.
|
|
2854
|
+
fn from_reference_file(path: &Path) -> Result<Self> {
|
|
2855
|
+
let reference_text = fs::read_to_string(path)?;
|
|
2856
|
+
let r4r2_path = path
|
|
2857
|
+
.parent()
|
|
2858
|
+
.ok_or_else(|| {
|
|
2859
|
+
Gfn1Error::InvalidInput("D3 reference path has no parent directory".to_string())
|
|
2860
|
+
})?
|
|
2861
|
+
.join("data")
|
|
2862
|
+
.join("r4r2.f90");
|
|
2863
|
+
let r4r2_text = fs::read_to_string(&r4r2_path)?;
|
|
2864
|
+
Self::from_reference_text(&reference_text, &r4r2_text)
|
|
2865
|
+
}
|
|
2866
|
+
|
|
2867
|
+
/// The D3 reference bundled with the library and embedded at build time.
|
|
2868
|
+
fn bundled() -> Result<Self> {
|
|
2869
|
+
Self::from_reference_text(BUNDLED_D3_REFERENCE_F90, BUNDLED_D3_R4R2_F90)
|
|
2870
|
+
}
|
|
2871
|
+
|
|
2880
2872
|
fn number_of_references(&self, z: u8) -> Result<usize> {
|
|
2881
2873
|
self.number_of_references
|
|
2882
2874
|
.get(z as usize - 1)
|
|
@@ -2944,9 +2936,8 @@ fn load_d3_reference(path: &Path) -> Result<Arc<D3Reference>> {
|
|
|
2944
2936
|
Ok(loaded)
|
|
2945
2937
|
}
|
|
2946
2938
|
|
|
2947
|
-
fn
|
|
2948
|
-
let
|
|
2949
|
-
let clean = strip_fortran_comments(&text);
|
|
2939
|
+
fn parse_r4r2_text(text: &str) -> Result<Vec<f64>> {
|
|
2940
|
+
let clean = strip_fortran_comments(text);
|
|
2950
2941
|
let raw = parse_float_array_after(&clean, "r4_over_r2")?;
|
|
2951
2942
|
Ok(raw
|
|
2952
2943
|
.into_iter()
|
|
@@ -3082,8 +3073,8 @@ fn push_float_token(out: &mut Vec<f64>, token: &str) -> Result<()> {
|
|
|
3082
3073
|
mod tests {
|
|
3083
3074
|
use super::{
|
|
3084
3075
|
dispersion_energy, dispersion_energy_gradient, dispersion_energy_gradient_hessian,
|
|
3085
|
-
dispersion_third_derivative,
|
|
3086
|
-
|
|
3076
|
+
dispersion_third_derivative, reference_weight_cn_derivatives,
|
|
3077
|
+
resolve_and_load_d3_reference,
|
|
3087
3078
|
};
|
|
3088
3079
|
use crate::lattice::Lattice;
|
|
3089
3080
|
use crate::math::{Mat3, Vec3};
|
|
@@ -3152,9 +3143,7 @@ mod tests {
|
|
|
3152
3143
|
|
|
3153
3144
|
#[test]
|
|
3154
3145
|
fn bundled_d3_reference_is_available() {
|
|
3155
|
-
let
|
|
3156
|
-
let path = resolve_d3_reference_path(¶ms, None).unwrap();
|
|
3157
|
-
let reference = load_d3_reference(&path).unwrap();
|
|
3146
|
+
let reference = resolve_and_load_d3_reference(None).unwrap();
|
|
3158
3147
|
assert!(reference.number_of_references(6).unwrap() > 0);
|
|
3159
3148
|
assert!(reference.r4r2(8).unwrap() > 0.0);
|
|
3160
3149
|
}
|
|
@@ -257,6 +257,10 @@ pub fn analytic_hessian_from_result(
|
|
|
257
257
|
} else {
|
|
258
258
|
None
|
|
259
259
|
};
|
|
260
|
+
// The assembled Hessian is symmetric in exact arithmetic; average it with its
|
|
261
|
+
// transpose to remove the small asymmetry left by finite-precision accumulation
|
|
262
|
+
// across the per-term contributions.
|
|
263
|
+
symmetrize_in_place(&mut hessian);
|
|
260
264
|
Ok(AnalyticHessianResult {
|
|
261
265
|
hessian,
|
|
262
266
|
repulsion,
|
|
@@ -501,6 +505,7 @@ pub fn fixed_density_pulay_hessian(
|
|
|
501
505
|
/// geometric channels — `part_c_sab` = the `C·S_ab` (overlap-coeff × overlap-2nd-deriv) channel, and
|
|
502
506
|
/// `part_h0` = the `2p·(h0_c·S_r + h0_r·S_c + S·h0_rc)` (h0-derivative) channel. Same loop/weights as
|
|
503
507
|
/// [`fixed_density_pulay_hessian`]; used to FD-attribute the reconverged density-path residual `miss[c]`.
|
|
508
|
+
#[cfg(test)]
|
|
504
509
|
pub(crate) fn fixed_density_pulay_hessian_parts(
|
|
505
510
|
system: &PeriodicSystem,
|
|
506
511
|
params: &Gfn1Parameters,
|
|
@@ -578,6 +583,7 @@ pub(crate) fn fixed_density_pulay_hessian_parts(
|
|
|
578
583
|
/// Their sum is exactly `part_c_sab` from [`fixed_density_pulay_hessian_parts`]. Used to attribute the
|
|
579
584
|
/// reconverged density-path residual `miss_csab` to the P·2h0 / −P·V / −2W sub-channels (the −2W block is
|
|
580
585
|
/// the EWD/W channel; its analytic linearized density-path is `−2·W^(c)·d²S_ab`).
|
|
586
|
+
#[cfg(test)]
|
|
581
587
|
pub(crate) fn fixed_density_pulay_hessian_csab_subparts(
|
|
582
588
|
system: &PeriodicSystem,
|
|
583
589
|
params: &Gfn1Parameters,
|
|
@@ -2308,6 +2314,20 @@ fn add_matrix(lhs: &mut Matrix, rhs: &Matrix) -> Result<()> {
|
|
|
2308
2314
|
Ok(())
|
|
2309
2315
|
}
|
|
2310
2316
|
|
|
2317
|
+
/// Replace a square matrix with `½(H + Hᵀ)`, enforcing exact symmetry on the
|
|
2318
|
+
/// final Hessian.
|
|
2319
|
+
fn symmetrize_in_place(hessian: &mut Matrix) {
|
|
2320
|
+
let n = hessian.rows();
|
|
2321
|
+
debug_assert_eq!(n, hessian.cols(), "Hessian must be square to symmetrize");
|
|
2322
|
+
for i in 0..n {
|
|
2323
|
+
for j in (i + 1)..n {
|
|
2324
|
+
let avg = 0.5 * (hessian[(i, j)] + hessian[(j, i)]);
|
|
2325
|
+
hessian[(i, j)] = avg;
|
|
2326
|
+
hessian[(j, i)] = avg;
|
|
2327
|
+
}
|
|
2328
|
+
}
|
|
2329
|
+
}
|
|
2330
|
+
|
|
2311
2331
|
type Ten3 = [[[f64; 3]; 3]; 3];
|
|
2312
2332
|
|
|
2313
2333
|
/// `H0` (or bare `poly`) value plus its bra/ket Cartesian derivative tensors up to **third**
|
|
@@ -2677,6 +2697,7 @@ pub fn fixed_density_pulay_third_derivative(
|
|
|
2677
2697
|
///
|
|
2678
2698
|
/// `response_density`=P^(c), `response_ew_density`=W^(c), `response_scalar_potential`=V^(c). Returned
|
|
2679
2699
|
/// ordered slabs `tensor[c][(a,b)]`. `only_channel`: Some(0)=C:S_ab only, Some(1)=h0 only, None=both.
|
|
2700
|
+
#[cfg(test)]
|
|
2680
2701
|
pub(crate) fn pulay_density_path_geom_cross_ordered(
|
|
2681
2702
|
system: &PeriodicSystem,
|
|
2682
2703
|
params: &Gfn1Parameters,
|
|
@@ -2816,120 +2837,6 @@ pub(crate) fn pulay_density_path_geom_cross_ordered(
|
|
|
2816
2837
|
Ok(tensor)
|
|
2817
2838
|
}
|
|
2818
2839
|
|
|
2819
|
-
/// PULAY density-path GEOMETRY×RESPONSE cross term (the missing 3rd-derivative piece). The linearized
|
|
2820
|
-
/// density-path `pulay(P^(c),W^(c),V) + [pulay(V+V^(c))−pulay(V)]` reproduces the pulay Hessian with the
|
|
2821
|
-
/// RESPONSE coefficient `C^(c) = P^(c)(2h0−V) + P(−V^(c)) − 2W^(c)` and `two_p^(c) = 2P^(c)`, but at FIXED
|
|
2822
|
-
/// geometry — it omits the ONE geometry derivative (slab `c`) acting on that already-response coefficient's
|
|
2823
|
-
/// overlap / h0 factors. This function supplies exactly that: the geometric slab-`c` derivative of the
|
|
2824
|
-
/// pulay Hessian body with the coefficient held at the linear response `(C^(c), two_p^(c))`. Same overlap /
|
|
2825
|
-
/// h0 third-derivative machinery and weights as [`fixed_density_pulay_third_derivative`]; the coefficient
|
|
2826
|
-
/// is the response, the geometry derivatives are the base geometry. First-order-response only.
|
|
2827
|
-
///
|
|
2828
|
-
/// `response_density` = P^(c), `response_ew_density` = W^(c), `response_scalar_potential` = V^(c) (the shell
|
|
2829
|
-
/// SCC-potential response). Returned ordered slabs `tensor[c][(a,b)]`.
|
|
2830
|
-
pub(crate) fn pulay_density_path_geom_cross(
|
|
2831
|
-
system: &PeriodicSystem,
|
|
2832
|
-
params: &Gfn1Parameters,
|
|
2833
|
-
electronic: &ElectronicResult,
|
|
2834
|
-
response_density: &Matrix,
|
|
2835
|
-
response_ew_density: &Matrix,
|
|
2836
|
-
response_scalar_potential: &[f64],
|
|
2837
|
-
) -> Result<Vec<Matrix>> {
|
|
2838
|
-
ensure_non_pbc(system)?;
|
|
2839
|
-
let nat = system.atoms.len();
|
|
2840
|
-
let ndof = 3 * nat;
|
|
2841
|
-
let basis = &electronic.basis;
|
|
2842
|
-
let mut tensor = vec![Matrix::zeros(ndof, ndof); ndof];
|
|
2843
|
-
// Base and response AO scalar potentials.
|
|
2844
|
-
let ao_v = ao_scalar_potentials(basis, &electronic.shell_scc_potential);
|
|
2845
|
-
let ao_vc = ao_scalar_potentials(basis, response_scalar_potential);
|
|
2846
|
-
|
|
2847
|
-
for mu in 0..basis.len() {
|
|
2848
|
-
let atom_mu = basis.aos[mu].atom_index;
|
|
2849
|
-
let shell_mu_index = basis.aos[mu].shell_index;
|
|
2850
|
-
let rmu = system.atoms[atom_mu].position;
|
|
2851
|
-
for nu in 0..mu {
|
|
2852
|
-
let atom_nu = basis.aos[nu].atom_index;
|
|
2853
|
-
if atom_mu == atom_nu {
|
|
2854
|
-
continue;
|
|
2855
|
-
}
|
|
2856
|
-
let shell_nu_index = basis.aos[nu].shell_index;
|
|
2857
|
-
let rnu = system.atoms[atom_nu].position;
|
|
2858
|
-
let p = electronic.density[(mu, nu)];
|
|
2859
|
-
let pc = response_density[(mu, nu)];
|
|
2860
|
-
let wc = response_ew_density[(mu, nu)];
|
|
2861
|
-
if p.abs().max(pc.abs()).max(wc.abs()) <= 1.0e-18 {
|
|
2862
|
-
continue;
|
|
2863
|
-
}
|
|
2864
|
-
let pair =
|
|
2865
|
-
contracted_pair_with_third_derivatives(&basis.aos[mu], &basis.aos[nu], rmu, rnu);
|
|
2866
|
-
let overlap = pair.moments[0];
|
|
2867
|
-
let h0 =
|
|
2868
|
-
h0_prefactor_third(system, params, electronic, shell_mu_index, shell_nu_index)?;
|
|
2869
|
-
let scalar_shift = ao_v[mu] + ao_v[nu];
|
|
2870
|
-
let scalar_shift_c = ao_vc[mu] + ao_vc[nu];
|
|
2871
|
-
// Response coefficient: C^(c) = P^(c)(2h0−V) + P(−V^(c)) − 2W^(c); two_p^(c) = 2 P^(c).
|
|
2872
|
-
let overlap_coeff = pc * (2.0 * h0.value - scalar_shift) - p * scalar_shift_c - 2.0 * wc;
|
|
2873
|
-
let two_p = 2.0 * pc;
|
|
2874
|
-
|
|
2875
|
-
let atom_of = |c: Center| match c {
|
|
2876
|
-
Center::Bra => atom_mu,
|
|
2877
|
-
Center::Ket => atom_nu,
|
|
2878
|
-
};
|
|
2879
|
-
let s1 = |c: Center, ax: usize| first(&pair.d_bra[0], &pair.d_ket[0], c, ax);
|
|
2880
|
-
let s2 = |ca: Center, cb: Center, axa: usize, axb: usize| {
|
|
2881
|
-
second(&pair.h_bra_bra[0], &pair.h_bra_ket[0], &pair.h_ket_ket[0], ca, cb, axa, axb)
|
|
2882
|
-
};
|
|
2883
|
-
let h1 = |c: Center, ax: usize| first_vec(h0.d_bra, h0.d_ket, c, ax);
|
|
2884
|
-
let h2 = |ca: Center, cb: Center, axa: usize, axb: usize| {
|
|
2885
|
-
second(&h0.h_bra_bra, &h0.h_bra_ket, &h0.h_ket_ket, ca, cb, axa, axb)
|
|
2886
|
-
};
|
|
2887
|
-
let slot_center = |s: usize| if s < 3 { Center::Bra } else { Center::Ket };
|
|
2888
|
-
let value_of = |i: usize, j: usize, k: usize| -> f64 {
|
|
2889
|
-
let (ca, axa) = (slot_center(i), i % 3);
|
|
2890
|
-
let (cb, axb) = (slot_center(j), j % 3);
|
|
2891
|
-
let (cc, axc) = (slot_center(k), k % 3);
|
|
2892
|
-
let s_abc = third_select(
|
|
2893
|
-
&pair.t_bra_bra_bra[0], &pair.t_bra_bra_ket[0], &pair.t_bra_ket_ket[0],
|
|
2894
|
-
&pair.t_ket_ket_ket[0], [ca, cb, cc], [axa, axb, axc],
|
|
2895
|
-
);
|
|
2896
|
-
let h_abc = third_select(
|
|
2897
|
-
&h0.t_bra_bra_bra, &h0.t_bra_bra_ket, &h0.t_bra_ket_ket,
|
|
2898
|
-
&h0.t_ket_ket_ket, [ca, cb, cc], [axa, axb, axc],
|
|
2899
|
-
);
|
|
2900
|
-
let (s_a, s_b, s_c) = (s1(ca, axa), s1(cb, axb), s1(cc, axc));
|
|
2901
|
-
let s_ab = s2(ca, cb, axa, axb);
|
|
2902
|
-
let s_ac = s2(ca, cc, axa, axc);
|
|
2903
|
-
let s_bc = s2(cb, cc, axb, axc);
|
|
2904
|
-
let (h_a, h_b, h_c) = (h1(ca, axa), h1(cb, axb), h1(cc, axc));
|
|
2905
|
-
let h_ab = h2(ca, cb, axa, axb);
|
|
2906
|
-
let h_ac = h2(ca, cc, axa, axc);
|
|
2907
|
-
let h_bc = h2(cb, cc, axb, axc);
|
|
2908
|
-
overlap_coeff * s_abc
|
|
2909
|
-
+ two_p
|
|
2910
|
-
* (overlap * h_abc
|
|
2911
|
-
+ (h_ab * s_c + h_ac * s_b + h_bc * s_a)
|
|
2912
|
-
+ (h_a * s_bc + h_b * s_ac + h_c * s_ab))
|
|
2913
|
-
};
|
|
2914
|
-
let dof = |s: usize| 3 * atom_of(slot_center(s)) + s % 3;
|
|
2915
|
-
for i in 0..6 {
|
|
2916
|
-
for j in i..6 {
|
|
2917
|
-
for k in j..6 {
|
|
2918
|
-
let v = value_of(i, j, k);
|
|
2919
|
-
if v == 0.0 {
|
|
2920
|
-
continue;
|
|
2921
|
-
}
|
|
2922
|
-
for &(pp, qq, rr) in &distinct_perms(i, j, k) {
|
|
2923
|
-
tensor[dof(rr)][(dof(pp), dof(qq))] += v;
|
|
2924
|
-
}
|
|
2925
|
-
}
|
|
2926
|
-
}
|
|
2927
|
-
}
|
|
2928
|
-
}
|
|
2929
|
-
}
|
|
2930
|
-
Ok(tensor)
|
|
2931
|
-
}
|
|
2932
|
-
|
|
2933
2840
|
#[cfg(test)]
|
|
2934
2841
|
mod third_derivative_tests {
|
|
2935
2842
|
use super::*;
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{gfn1_rs_python-0.4.5 → gfn1_rs_python-0.4.6}/third_party/simple-dftd3/src/dftd3/data/r4r2.f90
RENAMED
|
File without changes
|
{gfn1_rs_python-0.4.5 → gfn1_rs_python-0.4.6}/third_party/simple-dftd3/src/dftd3/reference.f90
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|