gfn1-rs-python 0.4.6__tar.gz → 0.5.1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (188) hide show
  1. {gfn1_rs_python-0.4.6 → gfn1_rs_python-0.5.1}/Cargo.lock +1 -1
  2. gfn1_rs_python-0.5.1/Cargo.toml +74 -0
  3. gfn1_rs_python-0.5.1/PKG-INFO +484 -0
  4. gfn1_rs_python-0.5.1/README.md +442 -0
  5. {gfn1_rs_python-0.4.6 → gfn1_rs_python-0.5.1}/THIRD_PARTY_NOTICES.md +32 -3
  6. gfn1_rs_python-0.5.1/docs/CONTRIBUTING.md +73 -0
  7. gfn1_rs_python-0.5.1/docs/README.md +22 -0
  8. gfn1_rs_python-0.5.1/docs/derivatives.md +499 -0
  9. gfn1_rs_python-0.5.1/docs/finite-temperature.md +401 -0
  10. gfn1_rs_python-0.5.1/docs/limitations.md +632 -0
  11. gfn1_rs_python-0.5.1/docs/parameters.md +145 -0
  12. gfn1_rs_python-0.5.1/docs/pbc.md +1249 -0
  13. {gfn1_rs_python-0.4.6 → gfn1_rs_python-0.5.1}/docs/python-api.md +393 -25
  14. {gfn1_rs_python-0.4.6 → gfn1_rs_python-0.5.1}/docs/rust-api.md +654 -33
  15. {gfn1_rs_python-0.4.6 → gfn1_rs_python-0.5.1}/docs/scope.md +52 -7
  16. gfn1_rs_python-0.5.1/docs/td.md +336 -0
  17. {gfn1_rs_python-0.4.6 → gfn1_rs_python-0.5.1}/examples/diamond222.xyz +1 -1
  18. {gfn1_rs_python-0.4.6 → gfn1_rs_python-0.5.1}/examples/h2.engrad +22 -22
  19. {gfn1_rs_python-0.4.6 → gfn1_rs_python-0.5.1}/examples/lao_kinetic_grid_check.rs +1 -1
  20. {gfn1_rs_python-0.4.6 → gfn1_rs_python-0.5.1}/examples/mag_cpscc_check.rs +1 -1
  21. {gfn1_rs_python-0.4.6 → gfn1_rs_python-0.5.1}/examples/magnetizability_validation.rs +5 -4
  22. gfn1_rs_python-0.5.1/examples/profile_fc4.rs +234 -0
  23. {gfn1_rs_python-0.4.6 → gfn1_rs_python-0.5.1}/examples/profile_magnetic.rs +3 -2
  24. {gfn1_rs_python-0.4.6 → gfn1_rs_python-0.5.1}/examples/profile_pbc.rs +2 -3
  25. gfn1_rs_python-0.5.1/examples/profile_phase7.rs +195 -0
  26. gfn1_rs_python-0.5.1/examples/third_deriv_diag.rs +192 -0
  27. {gfn1_rs_python-0.4.6 → gfn1_rs_python-0.5.1}/examples/water100.xyz +302 -302
  28. {gfn1_rs_python-0.4.6 → gfn1_rs_python-0.5.1}/examples/water48.xyz +146 -146
  29. gfn1_rs_python-0.5.1/pyproject.toml +61 -0
  30. {gfn1_rs_python-0.4.6 → gfn1_rs_python-0.5.1}/python/gfn1_rs/__init__.py +13 -1
  31. {gfn1_rs_python-0.4.6 → gfn1_rs_python-0.5.1}/python/gfn1_rs/ase.py +612 -127
  32. gfn1_rs_python-0.5.1/python/gfn1_rs/native.py +91 -0
  33. {gfn1_rs_python-0.4.6 → gfn1_rs_python-0.5.1}/python/gfn1_rs/torch_interop.py +16 -2
  34. {gfn1_rs_python-0.4.6 → gfn1_rs_python-0.5.1}/src/basis.rs +6 -0
  35. {gfn1_rs_python-0.4.6 → gfn1_rs_python-0.5.1}/src/bin/gfn1_rs.rs +7 -4
  36. gfn1_rs_python-0.5.1/src/constants.rs +59 -0
  37. {gfn1_rs_python-0.4.6 → gfn1_rs_python-0.5.1}/src/coordination.rs +22 -1
  38. {gfn1_rs_python-0.4.6 → gfn1_rs_python-0.5.1}/src/coulomb.rs +41 -11
  39. gfn1_rs_python-0.5.1/src/cphf.rs +7 -0
  40. {gfn1_rs_python-0.4.6 → gfn1_rs_python-0.5.1}/src/data_tables.rs +27 -0
  41. {gfn1_rs_python-0.4.6 → gfn1_rs_python-0.5.1}/src/dispersion.rs +1256 -621
  42. {gfn1_rs_python-0.4.6 → gfn1_rs_python-0.5.1}/src/electronic.rs +164 -25
  43. {gfn1_rs_python-0.4.6 → gfn1_rs_python-0.5.1}/src/exchange.rs +24 -73
  44. {gfn1_rs_python-0.4.6 → gfn1_rs_python-0.5.1}/src/field.rs +8 -3
  45. gfn1_rs_python-0.5.1/src/fourth_derivative/assemble.rs +819 -0
  46. gfn1_rs_python-0.5.1/src/fourth_derivative/directional.rs +1300 -0
  47. gfn1_rs_python-0.5.1/src/fourth_derivative/mod.rs +461 -0
  48. gfn1_rs_python-0.5.1/src/fourth_derivative/response_stage.rs +2939 -0
  49. {gfn1_rs_python-0.4.6 → gfn1_rs_python-0.5.1}/src/gradient.rs +3 -4
  50. gfn1_rs_python-0.5.1/src/halogen.rs +1340 -0
  51. gfn1_rs_python-0.5.1/src/hessian/mod.rs +6349 -0
  52. gfn1_rs_python-0.5.1/src/hessian/tests.rs +1419 -0
  53. {gfn1_rs_python-0.4.6 → gfn1_rs_python-0.5.1}/src/integrals.rs +11 -8
  54. gfn1_rs_python-0.5.1/src/integrals_fourth_derivatives.rs +845 -0
  55. gfn1_rs_python-0.5.1/src/jets.rs +859 -0
  56. {gfn1_rs_python-0.4.6 → gfn1_rs_python-0.5.1}/src/lib.rs +40 -10
  57. {gfn1_rs_python-0.4.6 → gfn1_rs_python-0.5.1}/src/linalg.rs +99 -27
  58. {gfn1_rs_python-0.4.6 → gfn1_rs_python-0.5.1}/src/magnetic.rs +363 -86
  59. {gfn1_rs_python-0.4.6 → gfn1_rs_python-0.5.1}/src/model.rs +10 -6
  60. {gfn1_rs_python-0.4.6 → gfn1_rs_python-0.5.1}/src/multipole.rs +3 -2
  61. {gfn1_rs_python-0.4.6 → gfn1_rs_python-0.5.1}/src/params.rs +200 -1
  62. {gfn1_rs_python-0.4.6 → gfn1_rs_python-0.5.1}/src/pbc/bloch.rs +1 -2
  63. {gfn1_rs_python-0.4.6 → gfn1_rs_python-0.5.1}/src/pbc/ewald.rs +1 -2
  64. gfn1_rs_python-0.5.1/src/pbc/gamma_response.rs +1022 -0
  65. gfn1_rs_python-0.5.1/src/pbc/gamma_third.rs +3646 -0
  66. {gfn1_rs_python-0.4.6 → gfn1_rs_python-0.5.1}/src/pbc/gradient.rs +2 -3
  67. gfn1_rs_python-0.5.1/src/pbc/gruneisen.rs +1304 -0
  68. {gfn1_rs_python-0.4.6 → gfn1_rs_python-0.5.1}/src/pbc/hessian.rs +533 -166
  69. gfn1_rs_python-0.5.1/src/pbc/kpoint_third.rs +3142 -0
  70. {gfn1_rs_python-0.4.6 → gfn1_rs_python-0.5.1}/src/pbc/mod.rs +34 -0
  71. gfn1_rs_python-0.5.1/src/pbc/polarization.rs +814 -0
  72. {gfn1_rs_python-0.4.6 → gfn1_rs_python-0.5.1}/src/pbc/scf.rs +11 -4
  73. {gfn1_rs_python-0.4.6 → gfn1_rs_python-0.5.1}/src/pbc/stress.rs +98 -3
  74. gfn1_rs_python-0.5.1/src/pbc/third_derivative.rs +618 -0
  75. {gfn1_rs_python-0.4.6 → gfn1_rs_python-0.5.1}/src/plus_u.rs +2 -1
  76. {gfn1_rs_python-0.4.6 → gfn1_rs_python-0.5.1}/src/plus_u_dudr.rs +4 -7
  77. {gfn1_rs_python-0.4.6 → gfn1_rs_python-0.5.1}/src/python.rs +918 -5
  78. {gfn1_rs_python-0.4.6 → gfn1_rs_python-0.5.1}/src/repulsion.rs +186 -8
  79. gfn1_rs_python-0.5.1/src/response/charge_space.rs +4531 -0
  80. gfn1_rs_python-0.4.6/src/cphf.rs → gfn1_rs_python-0.5.1/src/response/cpxtb.rs +1394 -180
  81. gfn1_rs_python-0.5.1/src/response/mod.rs +13 -0
  82. {gfn1_rs_python-0.4.6 → gfn1_rs_python-0.5.1}/src/secondary_bases/gfn1-xtb-cc-pv5z.txt +3078 -3078
  83. {gfn1_rs_python-0.4.6 → gfn1_rs_python-0.5.1}/src/secondary_bases/gfn1-xtb-cc-pvdz.txt +1995 -1995
  84. {gfn1_rs_python-0.4.6 → gfn1_rs_python-0.5.1}/src/secondary_bases/gfn1-xtb-cc-pvqz.txt +2730 -2730
  85. {gfn1_rs_python-0.4.6 → gfn1_rs_python-0.5.1}/src/secondary_bases/gfn1-xtb-cc-pvtz.txt +2332 -2332
  86. {gfn1_rs_python-0.4.6 → gfn1_rs_python-0.5.1}/src/spin.rs +15 -16
  87. {gfn1_rs_python-0.4.6 → gfn1_rs_python-0.5.1}/src/td.rs +455 -53
  88. gfn1_rs_python-0.5.1/src/terms.rs +202 -0
  89. gfn1_rs_python-0.5.1/src/third_derivative/finite_t.rs +3509 -0
  90. gfn1_rs_python-0.5.1/src/third_derivative/mod.rs +1816 -0
  91. gfn1_rs_python-0.4.6/src/third_derivative.rs → gfn1_rs_python-0.5.1/src/third_derivative/tests.rs +131 -1832
  92. {gfn1_rs_python-0.4.6 → gfn1_rs_python-0.5.1}/src/trah.rs +1 -1
  93. {gfn1_rs_python-0.4.6 → gfn1_rs_python-0.5.1}/src/vibrational.rs +2 -2
  94. {gfn1_rs_python-0.4.6 → gfn1_rs_python-0.5.1}/tests/d4.rs +1 -2
  95. {gfn1_rs_python-0.4.6 → gfn1_rs_python-0.5.1}/tests/field.rs +2 -3
  96. gfn1_rs_python-0.5.1/tests/fourth_derivative.rs +403 -0
  97. gfn1_rs_python-0.5.1/tests/fourth_derivative_nocap.rs +122 -0
  98. {gfn1_rs_python-0.4.6 → gfn1_rs_python-0.5.1}/tests/gradient_fd_probe.rs +1 -4
  99. gfn1_rs_python-0.5.1/tests/gruneisen_second_order_delta.rs +317 -0
  100. {gfn1_rs_python-0.4.6 → gfn1_rs_python-0.5.1}/tests/hessian.rs +184 -28
  101. {gfn1_rs_python-0.4.6 → gfn1_rs_python-0.5.1}/tests/kpoint_hessian_repro.rs +1 -4
  102. gfn1_rs_python-0.5.1/tests/magnetic.rs +916 -0
  103. gfn1_rs_python-0.5.1/tests/magnetizability_frame_invariance.rs +342 -0
  104. {gfn1_rs_python-0.4.6 → gfn1_rs_python-0.5.1}/tests/nonpbc_smoke.rs +5 -20
  105. {gfn1_rs_python-0.4.6 → gfn1_rs_python-0.5.1}/tests/optimizer.rs +2 -8
  106. {gfn1_rs_python-0.4.6 → gfn1_rs_python-0.5.1}/tests/param_deriv.rs +6 -14
  107. gfn1_rs_python-0.5.1/tests/pbc_finite_t.rs +365 -0
  108. gfn1_rs_python-0.5.1/tests/pbc_gamma_third_analytic.rs +277 -0
  109. {gfn1_rs_python-0.4.6 → gfn1_rs_python-0.5.1}/tests/pbc_integration.rs +3 -4
  110. gfn1_rs_python-0.5.1/tests/pbc_kpoint_third_analytic.rs +388 -0
  111. gfn1_rs_python-0.5.1/tests/pbc_polarization.rs +527 -0
  112. gfn1_rs_python-0.5.1/tests/pbc_third_derivative.rs +1161 -0
  113. gfn1_rs_python-0.5.1/tests/physical_consistency.rs +2392 -0
  114. {gfn1_rs_python-0.4.6 → gfn1_rs_python-0.5.1}/tests/properties.rs +2 -3
  115. gfn1_rs_python-0.5.1/tests/python/test_ase_units.py +601 -0
  116. gfn1_rs_python-0.5.1/tests/python/test_v050_derivatives.py +604 -0
  117. {gfn1_rs_python-0.4.6 → gfn1_rs_python-0.5.1}/tests/scf_accelerators.rs +1 -2
  118. gfn1_rs_python-0.5.1/tests/smearing.rs +450 -0
  119. {gfn1_rs_python-0.4.6 → gfn1_rs_python-0.5.1}/tests/tblite_parity.rs +1 -4
  120. gfn1_rs_python-0.5.1/tests/td.rs +1240 -0
  121. gfn1_rs_python-0.5.1/tests/third_derivative.rs +149 -0
  122. gfn1_rs_python-0.5.1/third_party/xtb/COPYING +674 -0
  123. gfn1_rs_python-0.5.1/third_party/xtb/COPYING.LESSER +165 -0
  124. gfn1_rs_python-0.5.1/third_party/xtb/PROVENANCE.md +44 -0
  125. gfn1_rs_python-0.5.1/third_party/xtb/param_gfn1-si-xtb.txt +1184 -0
  126. gfn1_rs_python-0.5.1/third_party/xtb/param_gfn1-xtb.txt +1180 -0
  127. gfn1_rs_python-0.4.6/Cargo.toml +0 -40
  128. gfn1_rs_python-0.4.6/PKG-INFO +0 -303
  129. gfn1_rs_python-0.4.6/README.md +0 -283
  130. gfn1_rs_python-0.4.6/pyproject.toml +0 -30
  131. gfn1_rs_python-0.4.6/python/gfn1_rs/native.py +0 -63
  132. gfn1_rs_python-0.4.6/src/constants.rs +0 -23
  133. gfn1_rs_python-0.4.6/src/halogen.rs +0 -1066
  134. gfn1_rs_python-0.4.6/src/hessian.rs +0 -3255
  135. gfn1_rs_python-0.4.6/tests/magnetic.rs +0 -351
  136. gfn1_rs_python-0.4.6/tests/td.rs +0 -579
  137. {gfn1_rs_python-0.4.6 → gfn1_rs_python-0.5.1}/LICENSE +0 -0
  138. {gfn1_rs_python-0.4.6 → gfn1_rs_python-0.5.1}/docs/sigma_hole_preset.md +0 -0
  139. {gfn1_rs_python-0.4.6 → gfn1_rs_python-0.5.1}/examples/ammonia.xyz +0 -0
  140. {gfn1_rs_python-0.4.6 → gfn1_rs_python-0.5.1}/examples/bromoethanol.xyz +0 -0
  141. {gfn1_rs_python-0.4.6 → gfn1_rs_python-0.5.1}/examples/diamond.xyz +0 -0
  142. {gfn1_rs_python-0.4.6 → gfn1_rs_python-0.5.1}/examples/dppf_pdcl2.xyz +0 -0
  143. {gfn1_rs_python-0.4.6 → gfn1_rs_python-0.5.1}/examples/h2.xyz +0 -0
  144. {gfn1_rs_python-0.4.6 → gfn1_rs_python-0.5.1}/examples/methane.xyz +0 -0
  145. {gfn1_rs_python-0.4.6 → gfn1_rs_python-0.5.1}/examples/ni_co4.xyz +0 -0
  146. {gfn1_rs_python-0.4.6 → gfn1_rs_python-0.5.1}/examples/water.xyz +0 -0
  147. {gfn1_rs_python-0.4.6 → gfn1_rs_python-0.5.1}/examples/water_opt.xyz +0 -0
  148. {gfn1_rs_python-0.4.6 → gfn1_rs_python-0.5.1}/scripts/compare_optimizations.py +0 -0
  149. {gfn1_rs_python-0.4.6 → gfn1_rs_python-0.5.1}/scripts/gen_secondary_basis.py +0 -0
  150. {gfn1_rs_python-0.4.6 → gfn1_rs_python-0.5.1}/scripts/optimize.py +0 -0
  151. {gfn1_rs_python-0.4.6 → gfn1_rs_python-0.5.1}/scripts/run_mgo_kpoint_md.py +0 -0
  152. {gfn1_rs_python-0.4.6 → gfn1_rs_python-0.5.1}/src/d4_reference.rs +0 -0
  153. {gfn1_rs_python-0.4.6 → gfn1_rs_python-0.5.1}/src/error.rs +0 -0
  154. {gfn1_rs_python-0.4.6 → gfn1_rs_python-0.5.1}/src/hamiltonian.rs +0 -0
  155. {gfn1_rs_python-0.4.6 → gfn1_rs_python-0.5.1}/src/integrals_second_derivatives.rs +0 -0
  156. {gfn1_rs_python-0.4.6 → gfn1_rs_python-0.5.1}/src/integrals_third_derivatives.rs +0 -0
  157. {gfn1_rs_python-0.4.6 → gfn1_rs_python-0.5.1}/src/lattice.rs +0 -0
  158. {gfn1_rs_python-0.4.6 → gfn1_rs_python-0.5.1}/src/math.rs +0 -0
  159. {gfn1_rs_python-0.4.6 → gfn1_rs_python-0.5.1}/src/nmr.rs +0 -0
  160. {gfn1_rs_python-0.4.6 → gfn1_rs_python-0.5.1}/src/optimizer.rs +0 -0
  161. {gfn1_rs_python-0.4.6 → gfn1_rs_python-0.5.1}/src/pairlist.rs +0 -0
  162. {gfn1_rs_python-0.4.6 → gfn1_rs_python-0.5.1}/src/param_deriv.rs +0 -0
  163. {gfn1_rs_python-0.4.6 → gfn1_rs_python-0.5.1}/src/pbc/complex.rs +0 -0
  164. {gfn1_rs_python-0.4.6 → gfn1_rs_python-0.5.1}/src/pbc/ewald_multipole.rs +0 -0
  165. {gfn1_rs_python-0.4.6 → gfn1_rs_python-0.5.1}/src/pbc/kpoints.rs +0 -0
  166. {gfn1_rs_python-0.4.6 → gfn1_rs_python-0.5.1}/src/profile.rs +0 -0
  167. {gfn1_rs_python-0.4.6 → gfn1_rs_python-0.5.1}/src/properties.rs +0 -0
  168. {gfn1_rs_python-0.4.6 → gfn1_rs_python-0.5.1}/src/secondary_bases.rs +0 -0
  169. {gfn1_rs_python-0.4.6 → gfn1_rs_python-0.5.1}/src/secondary_basis.rs +0 -0
  170. {gfn1_rs_python-0.4.6 → gfn1_rs_python-0.5.1}/src/sto.rs +0 -0
  171. {gfn1_rs_python-0.4.6 → gfn1_rs_python-0.5.1}/src/system.rs +0 -0
  172. {gfn1_rs_python-0.4.6 → gfn1_rs_python-0.5.1}/third_party/dftd4/CITATION.bib +0 -0
  173. {gfn1_rs_python-0.4.6 → gfn1_rs_python-0.5.1}/third_party/dftd4/COPYING +0 -0
  174. {gfn1_rs_python-0.4.6 → gfn1_rs_python-0.5.1}/third_party/dftd4/COPYING.LESSER +0 -0
  175. {gfn1_rs_python-0.4.6 → gfn1_rs_python-0.5.1}/third_party/dftd4/PROVENANCE.md +0 -0
  176. {gfn1_rs_python-0.4.6 → gfn1_rs_python-0.5.1}/third_party/dftd4/assets/parameters.toml +0 -0
  177. {gfn1_rs_python-0.4.6 → gfn1_rs_python-0.5.1}/third_party/dftd4/src/dftd4/data/hardness.f90 +0 -0
  178. {gfn1_rs_python-0.4.6 → gfn1_rs_python-0.5.1}/third_party/dftd4/src/dftd4/data/r4r2.f90 +0 -0
  179. {gfn1_rs_python-0.4.6 → gfn1_rs_python-0.5.1}/third_party/dftd4/src/dftd4/data/wfpair.f90 +0 -0
  180. {gfn1_rs_python-0.4.6 → gfn1_rs_python-0.5.1}/third_party/dftd4/src/dftd4/data/zeff.f90 +0 -0
  181. {gfn1_rs_python-0.4.6 → gfn1_rs_python-0.5.1}/third_party/dftd4/src/dftd4/reference.f90 +0 -0
  182. {gfn1_rs_python-0.4.6 → gfn1_rs_python-0.5.1}/third_party/dftd4/src/dftd4/reference.inc +0 -0
  183. {gfn1_rs_python-0.4.6 → gfn1_rs_python-0.5.1}/third_party/simple-dftd3/COPYING +0 -0
  184. {gfn1_rs_python-0.4.6 → gfn1_rs_python-0.5.1}/third_party/simple-dftd3/COPYING.LESSER +0 -0
  185. {gfn1_rs_python-0.4.6 → gfn1_rs_python-0.5.1}/third_party/simple-dftd3/src/dftd3/data/r4r2.f90 +0 -0
  186. {gfn1_rs_python-0.4.6 → gfn1_rs_python-0.5.1}/third_party/simple-dftd3/src/dftd3/reference.f90 +0 -0
  187. {gfn1_rs_python-0.4.6 → gfn1_rs_python-0.5.1}/third_party/tblite/PROVENANCE.md +0 -0
  188. {gfn1_rs_python-0.4.6 → gfn1_rs_python-0.5.1}/third_party/tblite/spin.f90 +0 -0
@@ -420,7 +420,7 @@ dependencies = [
420
420
 
421
421
  [[package]]
422
422
  name = "gfn1-rs"
423
- version = "0.4.6"
423
+ version = "0.5.1"
424
424
  dependencies = [
425
425
  "faer",
426
426
  "libm",
@@ -0,0 +1,74 @@
1
+ [package]
2
+ name = "gfn1-rs"
3
+ version = "0.5.1"
4
+ edition = "2021"
5
+ # Verified by building on the pinned toolchains, not guessed: 1.84 fails because
6
+ # `generativity` (pulled in via faer -> dyn-stack) needs the `edition2024`
7
+ # feature, which Cargo only stabilized in 1.85; 1.85 builds clean.
8
+ rust-version = "1.85"
9
+ license = "GPL-3.0-or-later"
10
+ authors = ["ss0832"]
11
+ description = "Rust-native GFN1-xTB prototype: energies/gradients/stress/Hessian, analytic third and fourth nuclear derivatives (molecular, periodic Gamma and k-point, T=0 and finite-temperature), periodic (Gamma + k-point) electrostatics, external electric and magnetic (GFN1-xTB-M0/M1) fields with magnetizability and an analytic magnetic gradient, TD-GFN1 (incl. k-point), IR/Raman, and parameter tooling."
12
+ repository = "https://github.com/ss0832/gfn1-rs"
13
+ homepage = "https://github.com/ss0832/gfn1-rs"
14
+ readme = "README.md"
15
+ keywords = ["xtb", "gfn1-xtb", "quantum-chemistry", "tight-binding", "chemistry"]
16
+ categories = ["science", "simulation", "mathematics"]
17
+ autobins = false
18
+
19
+ # Only scratch/build artefacts are excluded. The bundled parameter tables and
20
+ # basis data are compiled in with `include_str!` and MUST stay in the package:
21
+ # third_party/xtb/param_gfn1-xtb.txt, param_gfn1-si-xtb.txt (src/params.rs)
22
+ # third_party/simple-dftd3/src/dftd3/reference.f90, data/r4r2.f90
23
+ # (src/dispersion.rs)
24
+ # src/secondary_bases/gfn1-xtb-cc-pv{dz,tz,qz,5z}.txt (src/secondary_bases.rs)
25
+ # Excluding any of those silently ships a crate that cannot resolve parameters.
26
+ exclude = [
27
+ ".claude/",
28
+ "target-*/",
29
+ "**/__pycache__/",
30
+ "**/*.pdb",
31
+ ]
32
+
33
+ [lib]
34
+ name = "gfn1_rs"
35
+ path = "src/lib.rs"
36
+ crate-type = ["rlib", "cdylib"]
37
+
38
+ [[bin]]
39
+ name = "gfn1_rs_cli"
40
+ path = "src/bin/gfn1_rs.rs"
41
+
42
+ [profile.release]
43
+ opt-level = 3
44
+ lto = "fat"
45
+ codegen-units = 1
46
+ strip = "symbols"
47
+
48
+ # Fast-iteration profile for the numerical test suite: release-grade optimization
49
+ # without fat LTO / single-codegen-unit linking, which would otherwise re-link
50
+ # every test binary at full LTO cost. Use `cargo test --profile reltest`.
51
+ [profile.reltest]
52
+ inherits = "release"
53
+ lto = false
54
+ codegen-units = 16
55
+ # `release` strips symbols to slim the shipped cdylib/binary; the test profile
56
+ # must NOT inherit that, or panicking assertions lose their backtrace symbols.
57
+ strip = "none"
58
+
59
+ [lints.clippy]
60
+ correctness = "deny"
61
+ suspicious = "deny"
62
+ perf = "warn"
63
+ complexity = "allow"
64
+ style = "allow"
65
+
66
+ [dependencies]
67
+ faer = { version = "0.24", default-features = false, features = ["std", "linalg", "rayon"] }
68
+ libm = "0.2"
69
+ rayon = "1.10"
70
+ pyo3 = { version = "0.23.5", optional = true, features = ["extension-module", "abi3-py39"] }
71
+
72
+ [features]
73
+ default = []
74
+ python = ["pyo3"]
@@ -0,0 +1,484 @@
1
+ Metadata-Version: 2.4
2
+ Name: gfn1-rs-python
3
+ Version: 0.5.1
4
+ Classifier: Development Status :: 4 - Beta
5
+ Classifier: Intended Audience :: Science/Research
6
+ Classifier: Topic :: Scientific/Engineering :: Chemistry
7
+ Classifier: Topic :: Scientific/Engineering :: Physics
8
+ Classifier: Programming Language :: Rust
9
+ Classifier: Programming Language :: Python :: 3
10
+ Classifier: Programming Language :: Python :: 3.9
11
+ Classifier: Programming Language :: Python :: 3.10
12
+ Classifier: Programming Language :: Python :: 3.11
13
+ Classifier: Programming Language :: Python :: 3.12
14
+ Classifier: Programming Language :: Python :: 3.13
15
+ Classifier: Operating System :: OS Independent
16
+ Requires-Dist: ase>=3.22 ; extra == 'ase'
17
+ Requires-Dist: numpy>=1.22 ; extra == 'ase'
18
+ Requires-Dist: pytest>=8 ; extra == 'test'
19
+ Requires-Dist: ase>=3.22 ; extra == 'test'
20
+ Requires-Dist: numpy>=1.22 ; extra == 'test'
21
+ Provides-Extra: ase
22
+ Provides-Extra: test
23
+ License-File: LICENSE
24
+ License-File: third_party/dftd4/COPYING
25
+ License-File: third_party/dftd4/COPYING.LESSER
26
+ License-File: third_party/simple-dftd3/COPYING
27
+ License-File: third_party/simple-dftd3/COPYING.LESSER
28
+ License-File: third_party/xtb/COPYING
29
+ License-File: third_party/xtb/COPYING.LESSER
30
+ Summary: Python and ASE interface for the native Rust GFN1-RS implementation
31
+ Keywords: xtb,gfn1-xtb,quantum-chemistry,tight-binding,chemistry,ase,computational-chemistry
32
+ Home-Page: https://github.com/ss0832/gfn1-rs
33
+ Author: ss0832
34
+ License-Expression: GPL-3.0-or-later
35
+ Requires-Python: >=3.9, <3.15
36
+ Description-Content-Type: text/markdown; charset=UTF-8; variant=GFM
37
+ Project-URL: Documentation, https://github.com/ss0832/gfn1-rs/tree/master/docs
38
+ Project-URL: Homepage, https://github.com/ss0832/gfn1-rs
39
+ Project-URL: Issues, https://github.com/ss0832/gfn1-rs/issues
40
+ Project-URL: Repository, https://github.com/ss0832/gfn1-rs
41
+
42
+ # gfn1-rs
43
+
44
+ A Rust implementation of GFN1-xTB energies, analytical nuclear gradients,
45
+ stress, Hessians, cubic (FC3) and quartic (FC4) force constants, and periodic
46
+ (Gamma / Monkhorst-Pack k-point) electrostatics, with external electric fields,
47
+ IR/Raman spectroscopy, parameter tooling, and an optional Python/ASE interface.
48
+ The official parametrization is **bundled** — nothing to download. Dense linear
49
+ algebra uses `faer`; no BLAS/LAPACK required. **Unofficial — use with caution.**
50
+
51
+ Names: Cargo package `gfn1-rs`; Rust library target `gfn1_rs`; CLI binary
52
+ `gfn1_rs_cli`; Python package `gfn1_rs` (PyO3 extension module `gfn1_rs._native`).
53
+
54
+ ## Scope
55
+
56
+ Headlines for **v0.5.0** — everything below is analytic and finite-difference
57
+ gated unless it says otherwise:
58
+
59
+ - **Energy, gradient, stress** — molecular and periodic (Γ and Monkhorst–Pack
60
+ k-points), with generalised-Ewald Klopman–Ohno electrostatics.
61
+ - **Hessian** — molecular, periodic Γ, and periodic k-point.
62
+ - **Cubic force constants (FC3)** — the strict closed form for molecules, a
63
+ native **finite-temperature** analytic path, and — new in v0.5.0 — the closed
64
+ form under PBC at **Γ *and* on an arbitrary k-mesh**, plus seminumerical
65
+ references for every one of them.
66
+ - **Quartic force constants (FC4)** — fully analytic, no nuclear finite
67
+ differences; the **directional route has no degrees-of-freedom cap** as of
68
+ v0.5.0, and a finite-temperature analytic path exists alongside it.
69
+ - **Charge-space response solver** — one LU-factored dielectric serves every
70
+ first- and second-order right-hand side; Fermi smearing is native, and the
71
+ exactly-degenerate second order is closed in Daleckii–Krein resolvent form.
72
+ - **Periodic thermal expansion** — strain-mixed `dH/dlnV` and mode/thermodynamic
73
+ Grüneisen parameters (with a separate second-order volumetric step).
74
+ - **Bulk polarization** — Berry phase, King-Smith–Vanderbilt and Resta forms.
75
+ - **Excited states** — TD-GFN1 (TDA) singlet/triplet, non-periodic, Γ and
76
+ k-point, with analytic excited-state gradients.
77
+ - **Fields and magnetics** — external electric field (molecular and periodic),
78
+ closed-shell magnetic SCC in London orbitals (GFN1-xTB-M0/M1), magnetizability
79
+ (finite-field and analytic), NMR shieldings, and magneto-optical tensors.
80
+ - **Spectroscopy and tooling** — IR/Raman, polarizability, geometry
81
+ optimization, parameter round-trip and finite-difference parameter
82
+ derivatives, Python/ASE bindings.
83
+
84
+ Experimental, off by default (stock GFN1 is byte-identical with them off):
85
+ multipole/CAMM electrostatics, higher-order on-site charge, range-separated Fock
86
+ exchange, DFT+U/+V, collinear spin polarization, and self-consistent D4.
87
+
88
+ **The full feature matrix — including the FC3/FC4 coverage tables — lives in
89
+ [docs/scope.md](docs/scope.md); the honest list of gaps is in
90
+ [docs/limitations.md](docs/limitations.md).**
91
+
92
+ ## Documentation
93
+
94
+ The docs are organised one page per subsystem — see the index at
95
+ [`docs/README.md`](docs/README.md):
96
+
97
+ - [`docs/scope.md`](docs/scope.md) — the full feature matrix, including the
98
+ FC3/FC4 coverage tables (molecular / PBC Γ / PBC k-mesh × `T = 0` / finite `T`).
99
+ - [`docs/parameters.md`](docs/parameters.md) — bundled official parameters,
100
+ `Gfn1Parameters::resolve` precedence, `ParamSource` provenance reporting,
101
+ reference data, unit constants.
102
+ - [`docs/derivatives.md`](docs/derivatives.md) — the nuclear derivative ladder
103
+ (gradient → Hessian → FC3 → FC4), the `terms::require_order` registry, and the
104
+ verification-gate philosophy (analytic order `n` vs FD of order `n−1`, `h²`
105
+ ladders).
106
+ - [`docs/finite-temperature.md`](docs/finite-temperature.md) — the charge-space
107
+ dielectric response solver (first and second order, natively Fermi-smeared) and
108
+ the analytic finite-temperature FC3.
109
+ - [`docs/pbc.md`](docs/pbc.md) — periodic derivatives, the **analytic** periodic
110
+ third derivative (Γ and k-point) and its seminumerical reference, strain-mixed
111
+ `dH/dlnV`, Grüneisen parameters, and Berry-phase bulk polarization.
112
+ - [`docs/td.md`](docs/td.md) — TD-GFN1 (TDA) excited states: working equations,
113
+ the analytic excited-state gradients, the MO phase gauge, and the gate numbers.
114
+ - [`docs/limitations.md`](docs/limitations.md) — **known gaps and silent failure
115
+ modes**, with the exact error messages. Read this one.
116
+ - [`docs/rust-api.md`](docs/rust-api.md) — Rust library API (`run_electronic`,
117
+ `analytic_gradient`, `analytic_hessian`, `optimize_geometry`, the periodic
118
+ `run_pbc_scc` / `pbc_analytic_gradient` / `pbc_stress` / `pbc_gamma_hessian`
119
+ entry points, `vibrational_analysis`, the external-field / spectroscopy API
120
+ (`ExternalFieldOptions`, `dipole_derivatives`, `static_polarizability`,
121
+ `ir_spectrum`, `raman_spectrum`), the third/fourth-derivative APIs, and the
122
+ parameter tooling (`to_param_string`, `ParameterTarget`,
123
+ `parameter_finite_difference`)).
124
+ - [`docs/python-api.md`](docs/python-api.md) — Python (`Gfn1NativeCalculator`)
125
+ and ASE (`GFN1RSCalculator`) API, including charge/spin and SCC controls.
126
+ - [`docs/CONTRIBUTING.md`](docs/CONTRIBUTING.md) — project discipline: **docs are
127
+ updated in the same commit as the feature that lands.**
128
+
129
+ ## Build
130
+
131
+ ```bash
132
+ cargo build --release # CLI -> target/release/gfn1_rs_cli
133
+ ```
134
+
135
+ Python extension (Python 3.9–3.14):
136
+
137
+ ```bash
138
+ python -m pip install maturin "ase>=3.22" "numpy>=1.22"
139
+ maturin develop --release --features python
140
+ ```
141
+
142
+ For a Python newer than PyO3's support window, set
143
+ `PYO3_USE_ABI3_FORWARD_COMPATIBILITY=1` before `cargo`/`maturin`.
144
+
145
+ ### Performance
146
+
147
+ The dense linear algebra (`faer`) runs **multi-threaded** by default, using the shared
148
+ rayon pool — the O(N³) SCF eigensolve and the analytic-gradient assembly scale across
149
+ all cores (≈1.9× on a 300-atom cluster vs single-threaded). The closed-form cubic
150
+ force constants additionally compute their independent per-slab response in parallel over
151
+ the same pool, and offer Dense / Vector / Block output so you only build what you need;
152
+ the quartic force constants evaluate their deduplicated polarization directions in
153
+ parallel against one shared reference. Diagnostics:
154
+
155
+ - `GFN1_PROFILE=1` — emit per-region wall-clock timings to stderr.
156
+ - `GFN1_FAER_THREADS=1` — force single-threaded `faer` (reproducible benchmarking).
157
+
158
+ - `GFN1_PBC_MULTIPOLE_FIELD_CACHE_MB=256` controls the periodic multipole field-cache cap;
159
+ larger cells automatically use the lower-memory streaming path instead of risking OOM.
160
+
161
+ ## Parameters
162
+
163
+ The official GFN1-xTB parametrization is **bundled** — everything works out of
164
+ the box with no downloads. The bundled files (`param_gfn1-xtb.txt` and the
165
+ GFN1(Si)-xTB silicon reparametrization `param_gfn1-si-xtb.txt`) are verbatim
166
+ copies from [`grimme-lab/xtb`](https://github.com/grimme-lab/xtb)
167
+ (LGPL-3.0-or-later; see `third_party/xtb/PROVENANCE.md` and
168
+ [`THIRD_PARTY_NOTICES.md`](THIRD_PARTY_NOTICES.md)).
169
+
170
+ Resolution order (`Gfn1Parameters::resolve`): `--param` / `param_path` >
171
+ `GFN1_XTB_PARAM` environment variable > builtin. Every run reports which
172
+ parametrization is active (CLI banner `parameters: ...`, Python
173
+ `calc.param_source()`). Details in
174
+ [`docs/parameters.md`](docs/parameters.md).
175
+
176
+ - `--param builtin` selects the bundled GFN1-xTB set explicitly;
177
+ `--param builtin:si` selects the bundled GFN1(Si)-xTB set.
178
+ - To use your own file: `--param PATH` or
179
+
180
+ ```bash
181
+ export GFN1_XTB_PARAM=/path/to/param_gfn1-xtb.txt # (PowerShell: $env:GFN1_XTB_PARAM = "...")
182
+ ```
183
+
184
+ GFN2 parameter files are rejected intentionally.
185
+
186
+ ### D3 reference data
187
+
188
+ D3(BJ) uses the `s-dftd3` reference table. A minimal LGPL-3.0-or-later
189
+ `simple-dftd3` data copy is bundled under `third_party/simple-dftd3` (see
190
+ [`THIRD_PARTY_NOTICES.md`](THIRD_PARTY_NOTICES.md)); an explicit
191
+ `--d3-reference PATH` / `GFN1_D3_REFERENCE` still takes precedence.
192
+
193
+ ### Experimental D4 dispersion
194
+
195
+ `--experimental-d4` replaces the default D3 term with an experimental
196
+ non-periodic, self-consistent D4 term, including the Axilrod-Teller-Muto
197
+ three-body contribution. The D4 charge potential is fed back into SCC as an
198
+ atomic scalar shift, and non-PBC analytic gradients include the fixed-charge D4
199
+ geometry and coordination-number response. The GFN1 damping constants `a1`,
200
+ `a2`, and `s8` are read from the active `param_gfn1-xtb.txt`; `s9` is an
201
+ API/CLI option that defaults to the GFN2-xTB value `5.0` only when D4 is active
202
+ (ordinary non-D4 calculations use `s9 = 0`). The saved upstream DFT-D4 reference
203
+ data and provenance live under `third_party/dftd4`.
204
+
205
+ ### Charge and spin multiplicity
206
+
207
+ Formal charge (`--charge`) and spin multiplicity (`--multiplicity`) are passed
208
+ through `ElectronicOptions`. Multiplicity constrains the alpha/beta occupations of
209
+ the spin-independent GFN1 Hamiltonian.
210
+
211
+ **Optional spin polarization (spGFN1).** Plain GFN1 is restricted-open-shell (the
212
+ energy does not depend on the spin density). Setting `--spinpol` (CLI) /
213
+ `spin_polarization=True` (Python / ASE) / `ElectronicOptions::spin_polarization`
214
+ adds the collinear spin-DFTB spin-polarization energy from the tabulated atomic
215
+ spin constants `W` ("spGFN1"): non-PBC, **energy + analytic forces**, off by
216
+ default. It only affects **open-shell** configurations — a closed-shell singlet is
217
+ **byte-identical** to plain GFN1. The `W` constants are transcribed byte-exact from
218
+ tblite (LGPL-3.0; provenance under `third_party/tblite/` and `THIRD_PARTY_NOTICES.md`).
219
+ v1 is the bare GFN1 model (not combinable with the experimental multipole / CAMM /
220
+ exchange / D4 / field paths). See [scope.md](docs/scope.md).
221
+
222
+ **Extended Hubbard correction (DFT+U / +U+V), non-empirical.** GFN1 describes the
223
+ on-site charge fluctuation only at the monopole (shell-charge) level and carries no
224
+ orbital-resolved penalty against the self-interaction / over-delocalisation of a
225
+ localised transition-metal `d` shell — the diagnosed root cause of its poor TM
226
+ spin-state energetics. `--plus-u` (CLI) / `plus_u=True` (Python / ASE) adds the
227
+ rotationally-invariant FLL `+U` energy (and, with `--plus-u-v`, the inter-site `+V`
228
+ that restores metal–ligand hybridisation), built from the dual population of the
229
+ correlated subspace; **energy + analytic forces** (overlap-Pulay term, frozen-`U`),
230
+ on the open-shell spin path (requires `--spinpol`), non-PBC, off by default. With
231
+ `--linear-response-u` the `U` (and `V`) are computed **non-empirically** from the
232
+ occupation response (Cococcioni–de Gironcoli, `U = χ0⁻¹ − χ⁻¹`) and the correlated
233
+ `d` shells are auto-selected — **no fitted parameters** (the FD step and `+V` cutoff
234
+ are numerical/geometric settings, not fits). Experimental; in the screened
235
+ semiempirical SCC the bare/screened response separation is approximate. See
236
+ [scope.md](docs/scope.md).
237
+
238
+ ## CLI
239
+
240
+ Coordinates are XYZ/extXYZ in Angstrom (use `--bohr` for Bohr). A periodic cell is
241
+ read from the extXYZ `Lattice="..."` header and auto-dispatches the periodic path.
242
+ See `--help` for the full option set. **No `--param` is needed** — the official
243
+ parametrization is compiled in, so the examples below run as written from a fresh
244
+ checkout; pass `--param builtin:si` for the GFN1(Si) set or `--param PATH` for
245
+ your own file. Common workflows:
246
+
247
+ ```bash
248
+ # single-point energy (+ Mulliken charges)
249
+ gfn1_rs_cli examples/water.xyz --charges
250
+
251
+ # energy + analytical gradient / forces
252
+ gfn1_rs_cli --gradient examples/ammonia.xyz
253
+
254
+ # analytical Hessian (non-periodic)
255
+ gfn1_rs_cli --hessian examples/water.xyz
256
+
257
+ # periodic single point + component stress (Lattice from the extXYZ header)
258
+ gfn1_rs_cli --stress examples/diamond.xyz
259
+
260
+ # L-BFGS optimization (non-periodic; analytical gradient). --opt-output writes the final
261
+ # geometry, --opt-traj writes the full multi-frame XYZ trajectory.
262
+ gfn1_rs_cli --optimize --opt-output opt.xyz --opt-traj opt_traj.xyz examples/ammonia.xyz
263
+
264
+ # mDFTB2 multipole-corrected single point / optimization (experimental, non-PBC)
265
+ gfn1_rs_cli --multipole --optimize --opt-output opt.xyz examples/ammonia.xyz
266
+
267
+ # CAMM-on-mDFTB2: GFN2-style anisotropic electrostatics (q-mu/q-Theta/mu-mu) on cumulative
268
+ # atomic multipoles, replacing the mDFTB2 off-site term (experimental, non-PBC, v0.4.2).
269
+ # camm_damp (kappa) is the primary range-selective lever; camm_aes_scale (s_AES) the secondary amplitude.
270
+ gfn1_rs_cli --multipole --multipole-model camm_on_mdftb2 --camm-damp 1.0 examples/water48.xyz
271
+
272
+ # experimental self-consistent D4 single point / gradient (non-PBC only)
273
+ gfn1_rs_cli --experimental-d4 --gradient examples/water.xyz
274
+
275
+ # range-separated Fock exchange single point (experimental, non-PBC); --onsite-exchange adds
276
+ # the exact one-center (OFX) term, --scf-trah forces the TRAH second-order SCF
277
+ gfn1_rs_cli --lr-exchange --onsite-exchange --charges examples/water.xyz
278
+
279
+ # charged / open-shell single point
280
+ gfn1_rs_cli --charge 1 --multiplicity 2 examples/h2.xyz
281
+
282
+ # spin-polarized GFN1 ("spGFN1"): collinear spin term for open-shell systems (non-PBC, energy +
283
+ # analytic forces). Off by default; a closed-shell singlet stays byte-identical to GFN1.
284
+ gfn1_rs_cli --multiplicity 3 --spinpol --gradient examples/h2.xyz
285
+
286
+ # TD-GFN1 (TDA) excited states; --tda-grad adds the excited-state gradient. The CLI default is
287
+ # --tda-gradient-method semi-numerical; pass `analytic` for the fully analytic direct-CPHF gradient
288
+ # (or `fd` for the root-tracked full finite difference).
289
+ gfn1_rs_cli --tda examples/water.xyz
290
+
291
+ # single point in a uniform external electric field (atomic units, Ex Ey Ez)
292
+ gfn1_rs_cli --field 0.0 0.01 0.0 --charges examples/water.xyz
293
+
294
+ # static polarizability, IR, and Raman (each also prints the raw derivative tensors)
295
+ gfn1_rs_cli --polarizability examples/water.xyz
296
+ gfn1_rs_cli --ir examples/water.xyz
297
+ gfn1_rs_cli --raman examples/water.xyz
298
+
299
+ # NMR nuclear magnetic shielding tensor of atom 0 (ppm; isotropic + 3x3)
300
+ gfn1_rs_cli --nmr 0 examples/water.xyz
301
+
302
+ # finite-difference parameter derivatives (dE/dp, add --param-forces for dF/dp)
303
+ gfn1_rs_cli --param-deriv \
304
+ --targets glob:ks,elem:1:GAM,pair:1:1 examples/h2.xyz
305
+ ```
306
+
307
+ `cargo run --bin gfn1_rs_cli -- ...` works too if you have not built the binary.
308
+
309
+ IR/Raman are taken at the input geometry, so optimize first (`--optimize`) for a
310
+ clean spectrum free of spurious low-frequency modes.
311
+
312
+ ## Python / ASE
313
+
314
+ Periodic **single points** (energy / forces / stress) dispatch automatically for
315
+ ASE `Atoms` with a cell/pbc (Monkhorst-Pack via the `kgrid` parameter), and
316
+ periodic **k-point TD** is exposed (`get_tda_kpoint`); the property/spectroscopy
317
+ methods (polarizability, IR/Raman, magnetic) are non-periodic.
318
+
319
+ ```python
320
+ from ase import Atoms
321
+ from ase.optimize import LBFGS
322
+ from gfn1_rs.ase import GFN1RSCalculator # reads GFN1_XTB_PARAM, or pass param_path=...
323
+
324
+ atoms = Atoms("H2", positions=[[0.0, 0.0, 0.0], [0.74, 0.0, 0.0]])
325
+ atoms.calc = GFN1RSCalculator(charge=0.0, multiplicity=None)
326
+ print(atoms.get_potential_energy()) # eV
327
+ print(atoms.get_forces()) # eV/Angstrom
328
+ print(atoms.get_dipole_moment()) # e*Angstrom
329
+ print(atoms.calc.results["native_energy_terms_hartree"])
330
+
331
+ # ASE-driven optimization, or the Rust-native L-BFGS:
332
+ LBFGS(atoms).run(fmax=0.05)
333
+ atoms.calc.optimize_native(atoms, gradient_tolerance=1e-4)
334
+ ```
335
+
336
+ ### Units: two layers, two conventions
337
+
338
+ The package has exactly one unit boundary, and it is `gfn1_rs.ase`:
339
+
340
+ | Layer | Convention |
341
+ | --- | --- |
342
+ | `gfn1_rs.ase.GFN1RSCalculator` (ASE) | **ASE units** — Angstrom, eV, eV/Angstrom, eV/Angstrom³, e·Angstrom, e |
343
+ | `gfn1_rs.Gfn1NativeCalculator`, `gfn1_rs.torch_interop`, the CLI, the Rust API | **atomic units** — bohr, Hartree, Hartree/bohr, Hartree/bohr³, e·bohr |
344
+
345
+ Everything the ASE calculator returns is in ASE units, and **every conversion is
346
+ taken from `ase.units`** (`Bohr`, `Hartree`, `invcm`) — there are no hand-typed
347
+ factors in the ASE layer, and it deliberately does not use the engine's own
348
+ CODATA constants (they differ at the 1e-8 level). Concretely:
349
+
350
+ - `get_potential_energy()` eV · `get_forces()` eV/Å · `get_stress()` eV/ų in the
351
+ ASE Voigt order `(xx, yy, zz, yz, xz, xy)` with the ASE sign convention
352
+ `sigma = (1/V) dE/d(strain)` · `get_dipole_moment()` e·Å · `get_charges()` e
353
+ - `get_hessian()` eV/Ų, `get_third_derivative*()` eV/ų,
354
+ `get_polarizability()` / `get_magnetic_polarizability()` e²Å²/eV,
355
+ `get_magnetic_energy()` eV
356
+ - gauge/multipole `origin` arguments are read in **Angstrom**
357
+ - dicts follow a suffix rule: an unsuffixed key (`forces`, `total_energy`) is in
358
+ ASE units, a suffixed one (`*_hartree`, `*_hartree_per_bohr`, `*_au`, `*_ev`)
359
+ is in the unit its name states — so `results["native_energy_terms_hartree"]`
360
+ and `get_tda_gradient()["forces_hartree_per_bohr"]` still give you the raw
361
+ atomic-unit numbers
362
+ - observables with a universal unit of their own keep it, exactly as ASE's own
363
+ `ase.vibrations` does: cm⁻¹ wavenumbers, km/mol IR intensities, ppm NMR
364
+ shieldings, 1e-30 J/T² magnetizabilities; raw AO-integral and magnetic-response
365
+ tensors stay in atomic units and say so in their docstrings
366
+ - the calculator's **construction parameters** are model knobs passed straight to
367
+ the engine, so they stay in native units (`electric_field` a.u.,
368
+ `hubbard_u`/`hubbard_v`/`level_shift`/`energy_tolerance` Hartree,
369
+ `hubbard_v_cutoff` and the `d4_*` cutoffs bohr, `electronic_temperature` K), as
370
+ do the numerical `step` / `e_step` / `b_step` / `field_step` arguments
371
+
372
+ The low-level `gfn1_rs.Gfn1NativeCalculator` exposes the same controls without
373
+ ASE, in atomic units. Set `experimental_d4=True` on either interface to use the
374
+ non-PBC D4 path. Use `d4_s9=0.0` / `--d4-s9 0` or `--no-d4-atm` to disable the D4
375
+ three-body term explicitly.
376
+
377
+ ## Validation
378
+
379
+ Tests resolve parameters through `Gfn1Parameters::resolve(None)`, so they run
380
+ against the **bundled** parametrization with no environment variable — and, unlike
381
+ before, no longer silently no-op when `GFN1_XTB_PARAM` is unset:
382
+
383
+ ```bash
384
+ cargo test --profile reltest # use reltest: these are numerical gates
385
+ cargo test --profile reltest -- --ignored # long-running (FD probes, finite-T ladders)
386
+ maturin develop --release --features python && python -m pytest -q
387
+ ```
388
+
389
+ The `reltest` profile is release-grade optimization without fat LTO or
390
+ single-codegen-unit linking, so the numerical gates run at production speed
391
+ without re-linking every test binary at full LTO cost. A plain debug-profile
392
+ `cargo test` is correct but *much* slower on this suite.
393
+
394
+ Set `GFN1_XTB_PARAM=/path/to/param_gfn1-xtb.txt` only to test against a
395
+ *different* parametrization.
396
+
397
+ Tests cover finite-difference gradient / Hessian checks
398
+ (`tests/gradient_fd_probe.rs`, `tests/hessian.rs`), the analytic third and fourth
399
+ derivatives against their seminumerical references (`tests/third_derivative.rs`,
400
+ `tests/fourth_derivative.rs`), the periodic path (`tests/pbc_integration.rs`) and
401
+ its third derivative / Grüneisen module (`tests/pbc_third_derivative.rs`), the
402
+ optimizer (`tests/optimizer.rs`), and an opt-in external `tblite` parity suite
403
+ (`tests/tblite_parity.rs`, enabled by setting `GFN1_TBLITE_BIN`; `tblite` is not a
404
+ Cargo dependency). `GFN1_FD_TIGHT=1` tightens the finite-difference probe and
405
+ `GFN1_PROFILE=1` emits per-scope native timings.
406
+
407
+ The gate design — analytic order `n` against a central FD of the *validated*
408
+ analytic order `n−1`, with the `h²` truncation ladder as the completeness
409
+ diagnostic — is described in
410
+ [`docs/derivatives.md`](docs/derivatives.md#5-the-verification-gate-philosophy).
411
+
412
+ The Python suite lives in `tests/python/` (collected by the `pytest` config in
413
+ `pyproject.toml`). `tests/python/test_ase_units.py` pins the unit contract above:
414
+ every ASE-calculator output is asserted to equal the corresponding
415
+ `Gfn1NativeCalculator` (atomic-unit) output times the exact `ase.units` factor.
416
+ Its pure-Python half mocks the native layer, so it runs even without the compiled
417
+ extension.
418
+
419
+ ## Limitations
420
+
421
+ The full, honest list — including the failure modes that are *silent* — lives in
422
+ [`docs/limitations.md`](docs/limitations.md). The headline items:
423
+
424
+ - **Fermi smearing reaches everything except the strict `T = 0` closed forms.**
425
+ The `third_derivative::finite_t` drivers carry smearing through the analytic
426
+ FC3 *and* FC4 (directional, dense and block); the strict closed forms
427
+ (`third_derivative_analytic_*`, `fourth_derivative_analytic_*`) still reject
428
+ fractional occupations with an explicit error pointing at them.
429
+ - **The analytic periodic FC3 carries a `~1e-7` residual and rejects smearing.**
430
+ Both the Γ path (`pbc_gamma_third_analytic_*`) and the k-point path
431
+ (`pbc_kpoint_third_analytic_*`, any Monkhorst–Pack mesh, vector / dense /
432
+ block) are complete and agree with the seminumerical reference to `≈8e-8`; the
433
+ two share one assembly, so they share that open residual. Fermi-smeared cells
434
+ and order-1 model options still need
435
+ `pbc_kpoint_third_derivative_seminumerical_*`.
436
+ - **The `n⁴`-expanded FC4 front ends are capped at 30 DOF**
437
+ (`MAX_FOURTH_DERIVATIVE_NDOF`, the `8·n⁴`-byte expansion and the full-space
438
+ `Jet4` working set of the D3/halogen full-tensor routes). The **directional**
439
+ quartic has no such cap — 45 DOF is exercised in the test suite — and the
440
+ block mode applies the cap to `|dofs|`, not to `3N`.
441
+ - **`pbc_kpoint_hessian` is wrong on exactly degenerate frontier orbitals**
442
+ (perfect-symmetry cells; up to 100 % error, vanishing under a 0.03 Å
443
+ distortion). The Γ path and every FC3 route are structurally immune; see
444
+ [`docs/pbc.md`](docs/pbc.md) §2b.
445
+ - **Experimental model flags cap the derivative ladder at the gradient.** D4,
446
+ multipole/CAMM, MFX/OFX exchange, +U, spGFN1 and an external electric field all
447
+ carry `max_analytic_order: 1`; asking for a Hessian/FC3/FC4 with any of them on
448
+ now fails fast instead of silently returning the derivative of a different
449
+ energy expression.
450
+ - **Open-shell** magnetic properties (spin-Zeeman / NMR shieldings) and the
451
+ **length-gauge orbital-current** optical-rotation `G`-tensor / MCD (both vanish in
452
+ the GFN1 point-charge model since `dq/dB = 0`; the `lao_dipole_matrix` integrals
453
+ are the route to the orbital-current versions). The closed-shell magnetics —
454
+ analytic magnetizability and the FD-verified magneto-optical suite — are already
455
+ complete; see [scope.md](docs/scope.md).
456
+
457
+ ## References
458
+
459
+ 1. A. Buccheri, R. Li, J. E. Deustua, S. M. Moosavi, P. J. Bygrave, F. R. Manby,
460
+ "Periodic GFN1-xTB Tight Binding: A Generalized Ewald Partitioning Scheme for
461
+ the Klopman–Ohno Function," *J. Chem. Theory Comput.* **21**, 1615–1625 (2025).
462
+ DOI: [10.1021/acs.jctc.4c01234](https://doi.org/10.1021/acs.jctc.4c01234).
463
+ 2. S. Grimme, C. Bannwarth, P. Shushkov, "A Robust and Accurate Tight-Binding
464
+ Quantum Chemical Method for Structures, Vibrational Frequencies, and
465
+ Noncovalent Interactions of Large Molecular Systems Parametrized for All
466
+ spd-Block Elements (Z = 1–86)," *J. Chem. Theory Comput.* **13**, 1989–2009
467
+ (2017). DOI: [10.1021/acs.jctc.7b00118](https://doi.org/10.1021/acs.jctc.7b00118).
468
+ 3. A. Hjorth Larsen et al., "The Atomic Simulation Environment — A Python library
469
+ for working with atoms," *J. Phys.: Condens. Matter* **29**, 273002 (2017).
470
+ DOI: [10.1088/1361-648X/aa680e](https://doi.org/10.1088/1361-648X/aa680e).
471
+ 4. T. A. Niehaus, S. Suhai, F. Della Sala, P. Lugli, M. Elstner, G. Seifert, T.
472
+ Frauenheim, "Tight-binding approach to time-dependent density-functional
473
+ response theory," *Phys. Rev. B* **63**, 085108 (2001). DOI:
474
+ [10.1103/PhysRevB.63.085108](https://doi.org/10.1103/PhysRevB.63.085108).
475
+ (The TD-DFTB transition-charge response model behind TD-GFN1.)
476
+ 5. C. Y. Cheng, A. M. Wibowo-Teale, "Semiempirical Methods for Molecular Systems
477
+ in Strong Magnetic Fields," *J. Chem. Theory Comput.* **19**, 6226–6241 (2023).
478
+ DOI: [10.1021/acs.jctc.3c00671](https://doi.org/10.1021/acs.jctc.3c00671).
479
+ (The GFN1-xTB London-orbital magnetic-field method behind the `magnetic` module.)
480
+
481
+ ## License
482
+
483
+ GPL-3.0-or-later. See [`LICENSE`](LICENSE) and [`THIRD_PARTY_NOTICES.md`](THIRD_PARTY_NOTICES.md).
484
+