mlmm-toolkit 0.2.2.dev0__py3-none-any.whl

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 (372) hide show
  1. hessian_ff/__init__.py +50 -0
  2. hessian_ff/analytical_hessian.py +609 -0
  3. hessian_ff/constants.py +46 -0
  4. hessian_ff/forcefield.py +339 -0
  5. hessian_ff/loaders.py +608 -0
  6. hessian_ff/native/Makefile +8 -0
  7. hessian_ff/native/__init__.py +28 -0
  8. hessian_ff/native/analytical_hessian.py +88 -0
  9. hessian_ff/native/analytical_hessian_ext.cpp +258 -0
  10. hessian_ff/native/bonded.py +82 -0
  11. hessian_ff/native/bonded_ext.cpp +640 -0
  12. hessian_ff/native/loader.py +349 -0
  13. hessian_ff/native/nonbonded.py +118 -0
  14. hessian_ff/native/nonbonded_ext.cpp +1150 -0
  15. hessian_ff/prmtop_parmed.py +23 -0
  16. hessian_ff/system.py +107 -0
  17. hessian_ff/terms/__init__.py +14 -0
  18. hessian_ff/terms/angle.py +73 -0
  19. hessian_ff/terms/bond.py +44 -0
  20. hessian_ff/terms/cmap.py +406 -0
  21. hessian_ff/terms/dihedral.py +141 -0
  22. hessian_ff/terms/nonbonded.py +209 -0
  23. hessian_ff/tests/__init__.py +0 -0
  24. hessian_ff/tests/conftest.py +75 -0
  25. hessian_ff/tests/data/small/complex.parm7 +1346 -0
  26. hessian_ff/tests/data/small/complex.pdb +125 -0
  27. hessian_ff/tests/data/small/complex.rst7 +63 -0
  28. hessian_ff/tests/test_coords_input.py +44 -0
  29. hessian_ff/tests/test_energy_force.py +49 -0
  30. hessian_ff/tests/test_hessian.py +137 -0
  31. hessian_ff/tests/test_smoke.py +18 -0
  32. hessian_ff/tests/test_validation.py +40 -0
  33. hessian_ff/workflows.py +889 -0
  34. mlmm/__init__.py +36 -0
  35. mlmm/__main__.py +7 -0
  36. mlmm/_version.py +34 -0
  37. mlmm/add_elem_info.py +374 -0
  38. mlmm/advanced_help.py +91 -0
  39. mlmm/align_freeze_atoms.py +601 -0
  40. mlmm/all.py +3535 -0
  41. mlmm/bond_changes.py +231 -0
  42. mlmm/bool_compat.py +223 -0
  43. mlmm/cli.py +574 -0
  44. mlmm/cli_utils.py +166 -0
  45. mlmm/default_group.py +337 -0
  46. mlmm/defaults.py +467 -0
  47. mlmm/define_layer.py +526 -0
  48. mlmm/dft.py +1041 -0
  49. mlmm/energy_diagram.py +253 -0
  50. mlmm/extract.py +2213 -0
  51. mlmm/fix_altloc.py +464 -0
  52. mlmm/freq.py +1406 -0
  53. mlmm/harmonic_constraints.py +140 -0
  54. mlmm/hessian_cache.py +44 -0
  55. mlmm/hessian_calc.py +174 -0
  56. mlmm/irc.py +638 -0
  57. mlmm/mlmm_calc.py +2262 -0
  58. mlmm/mm_parm.py +945 -0
  59. mlmm/oniom_export.py +1983 -0
  60. mlmm/oniom_import.py +457 -0
  61. mlmm/opt.py +1742 -0
  62. mlmm/path_opt.py +1353 -0
  63. mlmm/path_search.py +2299 -0
  64. mlmm/preflight.py +88 -0
  65. mlmm/py.typed +1 -0
  66. mlmm/pysis_runner.py +45 -0
  67. mlmm/scan.py +1047 -0
  68. mlmm/scan2d.py +1226 -0
  69. mlmm/scan3d.py +1265 -0
  70. mlmm/scan_common.py +184 -0
  71. mlmm/summary_log.py +736 -0
  72. mlmm/trj2fig.py +448 -0
  73. mlmm/tsopt.py +2871 -0
  74. mlmm/utils.py +2309 -0
  75. mlmm/xtb_embedcharge_correction.py +475 -0
  76. mlmm_toolkit-0.2.2.dev0.dist-info/METADATA +1159 -0
  77. mlmm_toolkit-0.2.2.dev0.dist-info/RECORD +372 -0
  78. mlmm_toolkit-0.2.2.dev0.dist-info/WHEEL +5 -0
  79. mlmm_toolkit-0.2.2.dev0.dist-info/entry_points.txt +2 -0
  80. mlmm_toolkit-0.2.2.dev0.dist-info/licenses/LICENSE +674 -0
  81. mlmm_toolkit-0.2.2.dev0.dist-info/top_level.txt +4 -0
  82. pysisyphus/Geometry.py +1667 -0
  83. pysisyphus/LICENSE +674 -0
  84. pysisyphus/TableFormatter.py +63 -0
  85. pysisyphus/TablePrinter.py +74 -0
  86. pysisyphus/__init__.py +12 -0
  87. pysisyphus/calculators/AFIR.py +452 -0
  88. pysisyphus/calculators/AnaPot.py +20 -0
  89. pysisyphus/calculators/AnaPot2.py +48 -0
  90. pysisyphus/calculators/AnaPot3.py +12 -0
  91. pysisyphus/calculators/AnaPot4.py +20 -0
  92. pysisyphus/calculators/AnaPotBase.py +337 -0
  93. pysisyphus/calculators/AnaPotCBM.py +25 -0
  94. pysisyphus/calculators/AtomAtomTransTorque.py +154 -0
  95. pysisyphus/calculators/CFOUR.py +250 -0
  96. pysisyphus/calculators/Calculator.py +844 -0
  97. pysisyphus/calculators/CerjanMiller.py +24 -0
  98. pysisyphus/calculators/Composite.py +123 -0
  99. pysisyphus/calculators/ConicalIntersection.py +171 -0
  100. pysisyphus/calculators/DFTBp.py +430 -0
  101. pysisyphus/calculators/DFTD3.py +66 -0
  102. pysisyphus/calculators/DFTD4.py +84 -0
  103. pysisyphus/calculators/Dalton.py +61 -0
  104. pysisyphus/calculators/Dimer.py +681 -0
  105. pysisyphus/calculators/Dummy.py +20 -0
  106. pysisyphus/calculators/EGO.py +76 -0
  107. pysisyphus/calculators/EnergyMin.py +224 -0
  108. pysisyphus/calculators/ExternalPotential.py +264 -0
  109. pysisyphus/calculators/FakeASE.py +35 -0
  110. pysisyphus/calculators/FourWellAnaPot.py +28 -0
  111. pysisyphus/calculators/FreeEndNEBPot.py +39 -0
  112. pysisyphus/calculators/Gaussian09.py +18 -0
  113. pysisyphus/calculators/Gaussian16.py +726 -0
  114. pysisyphus/calculators/HardSphere.py +159 -0
  115. pysisyphus/calculators/IDPPCalculator.py +49 -0
  116. pysisyphus/calculators/IPIClient.py +133 -0
  117. pysisyphus/calculators/IPIServer.py +234 -0
  118. pysisyphus/calculators/LEPSBase.py +24 -0
  119. pysisyphus/calculators/LEPSExpr.py +139 -0
  120. pysisyphus/calculators/LennardJones.py +80 -0
  121. pysisyphus/calculators/MOPAC.py +219 -0
  122. pysisyphus/calculators/MullerBrownSympyPot.py +51 -0
  123. pysisyphus/calculators/MultiCalc.py +85 -0
  124. pysisyphus/calculators/NFK.py +45 -0
  125. pysisyphus/calculators/OBabel.py +87 -0
  126. pysisyphus/calculators/ONIOMv2.py +1129 -0
  127. pysisyphus/calculators/ORCA.py +893 -0
  128. pysisyphus/calculators/ORCA5.py +6 -0
  129. pysisyphus/calculators/OpenMM.py +88 -0
  130. pysisyphus/calculators/OpenMolcas.py +281 -0
  131. pysisyphus/calculators/OverlapCalculator.py +908 -0
  132. pysisyphus/calculators/Psi4.py +218 -0
  133. pysisyphus/calculators/PyPsi4.py +37 -0
  134. pysisyphus/calculators/PySCF.py +341 -0
  135. pysisyphus/calculators/PyXTB.py +73 -0
  136. pysisyphus/calculators/QCEngine.py +106 -0
  137. pysisyphus/calculators/Rastrigin.py +22 -0
  138. pysisyphus/calculators/Remote.py +76 -0
  139. pysisyphus/calculators/Rosenbrock.py +15 -0
  140. pysisyphus/calculators/SocketCalc.py +97 -0
  141. pysisyphus/calculators/TIP3P.py +111 -0
  142. pysisyphus/calculators/TransTorque.py +161 -0
  143. pysisyphus/calculators/Turbomole.py +965 -0
  144. pysisyphus/calculators/VRIPot.py +37 -0
  145. pysisyphus/calculators/WFOWrapper.py +333 -0
  146. pysisyphus/calculators/WFOWrapper2.py +341 -0
  147. pysisyphus/calculators/XTB.py +418 -0
  148. pysisyphus/calculators/__init__.py +81 -0
  149. pysisyphus/calculators/cosmo_data.py +139 -0
  150. pysisyphus/calculators/parser.py +150 -0
  151. pysisyphus/color.py +19 -0
  152. pysisyphus/config.py +133 -0
  153. pysisyphus/constants.py +65 -0
  154. pysisyphus/cos/AdaptiveNEB.py +230 -0
  155. pysisyphus/cos/ChainOfStates.py +725 -0
  156. pysisyphus/cos/FreeEndNEB.py +25 -0
  157. pysisyphus/cos/FreezingString.py +103 -0
  158. pysisyphus/cos/GrowingChainOfStates.py +71 -0
  159. pysisyphus/cos/GrowingNT.py +309 -0
  160. pysisyphus/cos/GrowingString.py +508 -0
  161. pysisyphus/cos/NEB.py +189 -0
  162. pysisyphus/cos/SimpleZTS.py +64 -0
  163. pysisyphus/cos/__init__.py +22 -0
  164. pysisyphus/cos/stiffness.py +199 -0
  165. pysisyphus/drivers/__init__.py +17 -0
  166. pysisyphus/drivers/afir.py +855 -0
  167. pysisyphus/drivers/barriers.py +271 -0
  168. pysisyphus/drivers/birkholz.py +138 -0
  169. pysisyphus/drivers/cluster.py +318 -0
  170. pysisyphus/drivers/diabatization.py +133 -0
  171. pysisyphus/drivers/merge.py +368 -0
  172. pysisyphus/drivers/merge_mol2.py +322 -0
  173. pysisyphus/drivers/opt.py +375 -0
  174. pysisyphus/drivers/perf.py +91 -0
  175. pysisyphus/drivers/pka.py +52 -0
  176. pysisyphus/drivers/precon_pos_rot.py +669 -0
  177. pysisyphus/drivers/rates.py +480 -0
  178. pysisyphus/drivers/replace.py +219 -0
  179. pysisyphus/drivers/scan.py +212 -0
  180. pysisyphus/drivers/spectrum.py +166 -0
  181. pysisyphus/drivers/thermo.py +31 -0
  182. pysisyphus/dynamics/Gaussian.py +103 -0
  183. pysisyphus/dynamics/__init__.py +20 -0
  184. pysisyphus/dynamics/colvars.py +136 -0
  185. pysisyphus/dynamics/driver.py +297 -0
  186. pysisyphus/dynamics/helpers.py +256 -0
  187. pysisyphus/dynamics/lincs.py +105 -0
  188. pysisyphus/dynamics/mdp.py +364 -0
  189. pysisyphus/dynamics/rattle.py +121 -0
  190. pysisyphus/dynamics/thermostats.py +128 -0
  191. pysisyphus/dynamics/wigner.py +266 -0
  192. pysisyphus/elem_data.py +3473 -0
  193. pysisyphus/exceptions.py +2 -0
  194. pysisyphus/filtertrj.py +69 -0
  195. pysisyphus/helpers.py +623 -0
  196. pysisyphus/helpers_pure.py +649 -0
  197. pysisyphus/init_logging.py +50 -0
  198. pysisyphus/intcoords/Bend.py +69 -0
  199. pysisyphus/intcoords/Bend2.py +25 -0
  200. pysisyphus/intcoords/BondedFragment.py +32 -0
  201. pysisyphus/intcoords/Cartesian.py +41 -0
  202. pysisyphus/intcoords/CartesianCoords.py +140 -0
  203. pysisyphus/intcoords/Coords.py +56 -0
  204. pysisyphus/intcoords/DLC.py +197 -0
  205. pysisyphus/intcoords/DistanceFunction.py +34 -0
  206. pysisyphus/intcoords/DummyImproper.py +70 -0
  207. pysisyphus/intcoords/DummyTorsion.py +72 -0
  208. pysisyphus/intcoords/LinearBend.py +105 -0
  209. pysisyphus/intcoords/LinearDisplacement.py +80 -0
  210. pysisyphus/intcoords/OutOfPlane.py +59 -0
  211. pysisyphus/intcoords/PrimTypes.py +286 -0
  212. pysisyphus/intcoords/Primitive.py +137 -0
  213. pysisyphus/intcoords/RedundantCoords.py +659 -0
  214. pysisyphus/intcoords/RobustTorsion.py +59 -0
  215. pysisyphus/intcoords/Rotation.py +147 -0
  216. pysisyphus/intcoords/Stretch.py +31 -0
  217. pysisyphus/intcoords/Torsion.py +101 -0
  218. pysisyphus/intcoords/Torsion2.py +25 -0
  219. pysisyphus/intcoords/Translation.py +45 -0
  220. pysisyphus/intcoords/__init__.py +61 -0
  221. pysisyphus/intcoords/augment_bonds.py +126 -0
  222. pysisyphus/intcoords/derivatives.py +10512 -0
  223. pysisyphus/intcoords/eval.py +80 -0
  224. pysisyphus/intcoords/exceptions.py +37 -0
  225. pysisyphus/intcoords/findiffs.py +48 -0
  226. pysisyphus/intcoords/generate_derivatives.py +414 -0
  227. pysisyphus/intcoords/helpers.py +235 -0
  228. pysisyphus/intcoords/logging_conf.py +10 -0
  229. pysisyphus/intcoords/mp_derivatives.py +10836 -0
  230. pysisyphus/intcoords/setup.py +962 -0
  231. pysisyphus/intcoords/setup_fast.py +176 -0
  232. pysisyphus/intcoords/update.py +272 -0
  233. pysisyphus/intcoords/valid.py +89 -0
  234. pysisyphus/interpolate/Geodesic.py +93 -0
  235. pysisyphus/interpolate/IDPP.py +55 -0
  236. pysisyphus/interpolate/Interpolator.py +116 -0
  237. pysisyphus/interpolate/LST.py +70 -0
  238. pysisyphus/interpolate/Redund.py +152 -0
  239. pysisyphus/interpolate/__init__.py +9 -0
  240. pysisyphus/interpolate/helpers.py +34 -0
  241. pysisyphus/io/__init__.py +22 -0
  242. pysisyphus/io/aomix.py +178 -0
  243. pysisyphus/io/cjson.py +24 -0
  244. pysisyphus/io/crd.py +101 -0
  245. pysisyphus/io/cube.py +220 -0
  246. pysisyphus/io/fchk.py +184 -0
  247. pysisyphus/io/hdf5.py +49 -0
  248. pysisyphus/io/hessian.py +72 -0
  249. pysisyphus/io/mol2.py +146 -0
  250. pysisyphus/io/molden.py +293 -0
  251. pysisyphus/io/orca.py +189 -0
  252. pysisyphus/io/pdb.py +269 -0
  253. pysisyphus/io/psf.py +79 -0
  254. pysisyphus/io/pubchem.py +31 -0
  255. pysisyphus/io/qcschema.py +34 -0
  256. pysisyphus/io/sdf.py +29 -0
  257. pysisyphus/io/xyz.py +61 -0
  258. pysisyphus/io/zmat.py +175 -0
  259. pysisyphus/irc/DWI.py +108 -0
  260. pysisyphus/irc/DampedVelocityVerlet.py +134 -0
  261. pysisyphus/irc/Euler.py +22 -0
  262. pysisyphus/irc/EulerPC.py +345 -0
  263. pysisyphus/irc/GonzalezSchlegel.py +187 -0
  264. pysisyphus/irc/IMKMod.py +164 -0
  265. pysisyphus/irc/IRC.py +878 -0
  266. pysisyphus/irc/IRCDummy.py +10 -0
  267. pysisyphus/irc/Instanton.py +307 -0
  268. pysisyphus/irc/LQA.py +53 -0
  269. pysisyphus/irc/ModeKill.py +136 -0
  270. pysisyphus/irc/ParamPlot.py +53 -0
  271. pysisyphus/irc/RK4.py +36 -0
  272. pysisyphus/irc/__init__.py +31 -0
  273. pysisyphus/irc/initial_displ.py +219 -0
  274. pysisyphus/linalg.py +411 -0
  275. pysisyphus/line_searches/Backtracking.py +88 -0
  276. pysisyphus/line_searches/HagerZhang.py +184 -0
  277. pysisyphus/line_searches/LineSearch.py +232 -0
  278. pysisyphus/line_searches/StrongWolfe.py +108 -0
  279. pysisyphus/line_searches/__init__.py +9 -0
  280. pysisyphus/line_searches/interpol.py +15 -0
  281. pysisyphus/modefollow/NormalMode.py +40 -0
  282. pysisyphus/modefollow/__init__.py +10 -0
  283. pysisyphus/modefollow/davidson.py +199 -0
  284. pysisyphus/modefollow/lanczos.py +95 -0
  285. pysisyphus/optimizers/BFGS.py +99 -0
  286. pysisyphus/optimizers/BacktrackingOptimizer.py +113 -0
  287. pysisyphus/optimizers/ConjugateGradient.py +98 -0
  288. pysisyphus/optimizers/CubicNewton.py +75 -0
  289. pysisyphus/optimizers/FIRE.py +113 -0
  290. pysisyphus/optimizers/HessianOptimizer.py +1176 -0
  291. pysisyphus/optimizers/LBFGS.py +228 -0
  292. pysisyphus/optimizers/LayerOpt.py +411 -0
  293. pysisyphus/optimizers/MicroOptimizer.py +169 -0
  294. pysisyphus/optimizers/NCOptimizer.py +90 -0
  295. pysisyphus/optimizers/Optimizer.py +1084 -0
  296. pysisyphus/optimizers/PreconLBFGS.py +260 -0
  297. pysisyphus/optimizers/PreconSteepestDescent.py +7 -0
  298. pysisyphus/optimizers/QuickMin.py +74 -0
  299. pysisyphus/optimizers/RFOptimizer.py +181 -0
  300. pysisyphus/optimizers/RSA.py +99 -0
  301. pysisyphus/optimizers/StabilizedQNMethod.py +248 -0
  302. pysisyphus/optimizers/SteepestDescent.py +23 -0
  303. pysisyphus/optimizers/StringOptimizer.py +173 -0
  304. pysisyphus/optimizers/__init__.py +41 -0
  305. pysisyphus/optimizers/closures.py +301 -0
  306. pysisyphus/optimizers/cls_map.py +58 -0
  307. pysisyphus/optimizers/exceptions.py +6 -0
  308. pysisyphus/optimizers/gdiis.py +280 -0
  309. pysisyphus/optimizers/guess_hessians.py +311 -0
  310. pysisyphus/optimizers/hessian_updates.py +355 -0
  311. pysisyphus/optimizers/poly_fit.py +285 -0
  312. pysisyphus/optimizers/precon.py +153 -0
  313. pysisyphus/optimizers/restrict_step.py +24 -0
  314. pysisyphus/pack.py +172 -0
  315. pysisyphus/peakdetect.py +948 -0
  316. pysisyphus/plot.py +1031 -0
  317. pysisyphus/run.py +2106 -0
  318. pysisyphus/socket_helper.py +74 -0
  319. pysisyphus/stocastic/FragmentKick.py +132 -0
  320. pysisyphus/stocastic/Kick.py +81 -0
  321. pysisyphus/stocastic/Pipeline.py +303 -0
  322. pysisyphus/stocastic/__init__.py +21 -0
  323. pysisyphus/stocastic/align.py +127 -0
  324. pysisyphus/testing.py +96 -0
  325. pysisyphus/thermo.py +156 -0
  326. pysisyphus/trj.py +824 -0
  327. pysisyphus/tsoptimizers/RSIRFOptimizer.py +56 -0
  328. pysisyphus/tsoptimizers/RSPRFOptimizer.py +182 -0
  329. pysisyphus/tsoptimizers/TRIM.py +59 -0
  330. pysisyphus/tsoptimizers/TSHessianOptimizer.py +463 -0
  331. pysisyphus/tsoptimizers/__init__.py +23 -0
  332. pysisyphus/wavefunction/Basis.py +239 -0
  333. pysisyphus/wavefunction/DIIS.py +76 -0
  334. pysisyphus/wavefunction/__init__.py +25 -0
  335. pysisyphus/wavefunction/build_ext.py +42 -0
  336. pysisyphus/wavefunction/cart2sph.py +190 -0
  337. pysisyphus/wavefunction/diabatization.py +304 -0
  338. pysisyphus/wavefunction/excited_states.py +435 -0
  339. pysisyphus/wavefunction/gen_ints.py +1811 -0
  340. pysisyphus/wavefunction/helpers.py +104 -0
  341. pysisyphus/wavefunction/ints/__init__.py +0 -0
  342. pysisyphus/wavefunction/ints/boys.py +193 -0
  343. pysisyphus/wavefunction/ints/boys_table_N_64_xasym_27.1_step_0.01.npy +0 -0
  344. pysisyphus/wavefunction/ints/cart_gto3d.py +176 -0
  345. pysisyphus/wavefunction/ints/coulomb3d.py +25928 -0
  346. pysisyphus/wavefunction/ints/diag_quadrupole3d.py +10036 -0
  347. pysisyphus/wavefunction/ints/dipole3d.py +8762 -0
  348. pysisyphus/wavefunction/ints/int2c2e3d.py +7198 -0
  349. pysisyphus/wavefunction/ints/int3c2e3d_sph.py +65040 -0
  350. pysisyphus/wavefunction/ints/kinetic3d.py +8240 -0
  351. pysisyphus/wavefunction/ints/ovlp3d.py +3777 -0
  352. pysisyphus/wavefunction/ints/quadrupole3d.py +15054 -0
  353. pysisyphus/wavefunction/ints/self_ovlp3d.py +198 -0
  354. pysisyphus/wavefunction/localization.py +458 -0
  355. pysisyphus/wavefunction/multipole.py +159 -0
  356. pysisyphus/wavefunction/normalization.py +36 -0
  357. pysisyphus/wavefunction/pop_analysis.py +134 -0
  358. pysisyphus/wavefunction/shells.py +1171 -0
  359. pysisyphus/wavefunction/wavefunction.py +504 -0
  360. pysisyphus/wrapper/__init__.py +11 -0
  361. pysisyphus/wrapper/exceptions.py +2 -0
  362. pysisyphus/wrapper/jmol.py +120 -0
  363. pysisyphus/wrapper/mwfn.py +169 -0
  364. pysisyphus/wrapper/packmol.py +71 -0
  365. pysisyphus/xyzloader.py +168 -0
  366. pysisyphus/yaml_mods.py +45 -0
  367. thermoanalysis/LICENSE +674 -0
  368. thermoanalysis/QCData.py +244 -0
  369. thermoanalysis/__init__.py +0 -0
  370. thermoanalysis/config.py +3 -0
  371. thermoanalysis/constants.py +20 -0
  372. thermoanalysis/thermo.py +1011 -0
@@ -0,0 +1,125 @@
1
+ ATOM 1 N GLY 1 47.321 49.145 36.060 1.00 0.00
2
+ ATOM 2 H1 GLY 1 47.638 49.049 35.106 1.00 0.00
3
+ ATOM 3 H2 GLY 1 47.907 49.820 36.530 1.00 0.00
4
+ ATOM 4 H3 GLY 1 46.318 49.262 36.059 1.00 0.00
5
+ ATOM 5 CA GLY 1 47.561 47.880 36.747 1.00 0.00
6
+ ATOM 6 HA2 GLY 1 48.201 48.046 37.613 1.00 0.00
7
+ ATOM 7 HA3 GLY 1 46.613 47.477 37.104 1.00 0.00
8
+ ATOM 8 C GLY 1 48.201 46.829 35.834 1.00 0.00
9
+ ATOM 9 O GLY 1 47.731 46.579 34.722 1.00 0.00
10
+ ATOM 10 N ILE 2 49.244 46.171 36.323 1.00 0.00
11
+ ATOM 11 H ILE 2 49.629 46.469 37.215 1.00 0.00
12
+ ATOM 12 CA ILE 2 49.849 44.995 35.697 1.00 0.00
13
+ ATOM 13 HA ILE 2 49.397 44.851 34.717 1.00 0.00
14
+ ATOM 14 CB ILE 2 51.369 45.154 35.470 1.00 0.00
15
+ ATOM 15 HB ILE 2 51.884 45.038 36.423 1.00 0.00
16
+ ATOM 16 CG2 ILE 2 51.816 44.023 34.525 1.00 0.00
17
+ ATOM 17 HG21 ILE 2 51.340 44.130 33.551 1.00 0.00
18
+ ATOM 18 HG22 ILE 2 52.888 44.063 34.368 1.00 0.00
19
+ ATOM 19 HG23 ILE 2 51.583 43.044 34.945 1.00 0.00
20
+ ATOM 20 CG1 ILE 2 51.735 46.545 34.899 1.00 0.00
21
+ ATOM 21 HG12 ILE 2 51.202 46.705 33.963 1.00 0.00
22
+ ATOM 22 HG13 ILE 2 51.423 47.317 35.603 1.00 0.00
23
+ ATOM 23 CD1 ILE 2 53.234 46.748 34.658 1.00 0.00
24
+ ATOM 24 HD11 ILE 2 53.592 46.071 33.887 1.00 0.00
25
+ ATOM 25 HD12 ILE 2 53.408 47.765 34.313 1.00 0.00
26
+ ATOM 26 HD13 ILE 2 53.789 46.579 35.582 1.00 0.00
27
+ ATOM 27 C ILE 2 49.518 43.780 36.563 1.00 0.00
28
+ ATOM 28 O ILE 2 49.997 43.653 37.693 1.00 0.00
29
+ ATOM 29 N ARG 3 48.662 42.897 36.045 1.00 0.00
30
+ ATOM 30 H ARG 3 48.280 43.089 35.129 1.00 0.00
31
+ ATOM 31 CA ARG 3 48.373 41.594 36.640 1.00 0.00
32
+ ATOM 32 HA ARG 3 48.334 41.705 37.723 1.00 0.00
33
+ ATOM 33 CB ARG 3 47.025 41.065 36.115 1.00 0.00
34
+ ATOM 34 HB2 ARG 3 46.906 41.337 35.063 1.00 0.00
35
+ ATOM 35 HB3 ARG 3 47.018 39.974 36.150 1.00 0.00
36
+ ATOM 36 CG ARG 3 45.813 41.582 36.909 1.00 0.00
37
+ ATOM 37 HG2 ARG 3 45.758 42.665 36.811 1.00 0.00
38
+ ATOM 38 HG3 ARG 3 44.912 41.169 36.454 1.00 0.00
39
+ ATOM 39 CD ARG 3 45.831 41.227 38.409 1.00 0.00
40
+ ATOM 40 HD2 ARG 3 46.541 41.884 38.912 1.00 0.00
41
+ ATOM 41 HD3 ARG 3 44.856 41.443 38.832 1.00 0.00
42
+ ATOM 42 NE ARG 3 46.201 39.822 38.678 1.00 0.00
43
+ ATOM 43 HE ARG 3 47.046 39.682 39.205 1.00 0.00
44
+ ATOM 44 CZ ARG 3 45.589 38.738 38.236 1.00 0.00
45
+ ATOM 45 NH1 ARG 3 44.408 38.777 37.703 1.00 0.00
46
+ ATOM 46 HH11 ARG 3 43.837 39.610 37.775 1.00 0.00
47
+ ATOM 47 HH12 ARG 3 44.030 37.930 37.269 1.00 0.00
48
+ ATOM 48 NH2 ARG 3 46.171 37.581 38.283 1.00 0.00
49
+ ATOM 49 HH21 ARG 3 47.118 37.474 38.598 1.00 0.00
50
+ ATOM 50 HH22 ARG 3 45.643 36.772 37.947 1.00 0.00
51
+ ATOM 51 C ARG 3 49.476 40.574 36.357 1.00 0.00
52
+ ATOM 52 O ARG 3 50.087 40.574 35.289 1.00 0.00
53
+ ATOM 53 N GLY 4 49.632 39.650 37.294 1.00 0.00
54
+ ATOM 54 H GLY 4 49.156 39.778 38.177 1.00 0.00
55
+ ATOM 55 CA GLY 4 50.286 38.368 37.061 1.00 0.00
56
+ ATOM 56 HA2 GLY 4 50.148 38.100 36.018 1.00 0.00
57
+ ATOM 57 HA3 GLY 4 51.351 38.445 37.264 1.00 0.00
58
+ ATOM 58 C GLY 4 49.720 37.249 37.928 1.00 0.00
59
+ ATOM 59 O GLY 4 48.981 37.517 38.886 1.00 0.00
60
+ ATOM 60 N ALA 5 50.088 36.011 37.600 1.00 0.00
61
+ ATOM 61 H ALA 5 50.634 35.883 36.749 1.00 0.00
62
+ ATOM 62 CA ALA 5 49.830 34.819 38.405 1.00 0.00
63
+ ATOM 63 HA ALA 5 49.857 35.104 39.454 1.00 0.00
64
+ ATOM 64 CB ALA 5 48.440 34.263 38.085 1.00 0.00
65
+ ATOM 65 HB1 ALA 5 48.469 33.794 37.105 1.00 0.00
66
+ ATOM 66 HB2 ALA 5 48.167 33.511 38.830 1.00 0.00
67
+ ATOM 67 HB3 ALA 5 47.694 35.060 38.084 1.00 0.00
68
+ ATOM 68 C ALA 5 50.895 33.723 38.195 1.00 0.00
69
+ ATOM 69 O ALA 5 51.492 33.599 37.125 1.00 0.00
70
+ ATOM 70 N THR 6 51.097 32.899 39.220 1.00 0.00
71
+ ATOM 71 H THR 6 50.588 33.080 40.082 1.00 0.00
72
+ ATOM 72 CA THR 6 51.956 31.706 39.225 1.00 0.00
73
+ ATOM 73 HA THR 6 51.919 31.238 38.243 1.00 0.00
74
+ ATOM 74 CB THR 6 53.414 32.109 39.502 1.00 0.00
75
+ ATOM 75 HB THR 6 53.682 32.937 38.844 1.00 0.00
76
+ ATOM 76 CG2 THR 6 53.701 32.518 40.948 1.00 0.00
77
+ ATOM 77 HG21 THR 6 53.596 31.663 41.616 1.00 0.00
78
+ ATOM 78 HG22 THR 6 54.724 32.889 41.007 1.00 0.00
79
+ ATOM 79 HG23 THR 6 53.020 33.308 41.255 1.00 0.00
80
+ ATOM 80 OG1 THR 6 54.272 31.029 39.215 1.00 0.00
81
+ ATOM 81 HG1 THR 6 54.304 30.910 38.261 1.00 0.00
82
+ ATOM 82 C THR 6 51.437 30.679 40.241 1.00 0.00
83
+ ATOM 83 O THR 6 50.568 30.999 41.051 1.00 0.00
84
+ ATOM 84 N THR 7 51.958 29.455 40.232 1.00 0.00
85
+ ATOM 85 H THR 7 52.722 29.262 39.599 1.00 0.00
86
+ ATOM 86 CA THR 7 51.561 28.379 41.156 1.00 0.00
87
+ ATOM 87 HA THR 7 51.000 28.807 41.986 1.00 0.00
88
+ ATOM 88 CB THR 7 50.665 27.326 40.491 1.00 0.00
89
+ ATOM 89 HB THR 7 50.394 26.578 41.237 1.00 0.00
90
+ ATOM 90 CG2 THR 7 49.383 27.918 39.913 1.00 0.00
91
+ ATOM 91 HG21 THR 7 49.603 28.503 39.019 1.00 0.00
92
+ ATOM 92 HG22 THR 7 48.696 27.110 39.667 1.00 0.00
93
+ ATOM 93 HG23 THR 7 48.907 28.558 40.655 1.00 0.00
94
+ ATOM 94 OG1 THR 7 51.377 26.686 39.454 1.00 0.00
95
+ ATOM 95 HG1 THR 7 52.242 26.443 39.820 1.00 0.00
96
+ ATOM 96 C THR 7 52.780 27.674 41.733 1.00 0.00
97
+ ATOM 97 O THR 7 53.693 27.292 40.991 1.00 0.00
98
+ ATOM 98 OXT THR 7 52.893 27.516 42.947 1.00 0.00
99
+ TER
100
+ ATOM 99 C1 PRE 8 40.182 35.865 37.205 1.00 0.00
101
+ ATOM 100 C2 PRE 8 39.825 35.162 38.553 1.00 0.00
102
+ ATOM 101 C3 PRE 8 40.484 35.425 39.701 1.00 0.00
103
+ ATOM 102 C4 PRE 8 41.619 36.450 39.807 1.00 0.00
104
+ ATOM 103 O4 PRE 8 41.530 37.169 41.032 1.00 0.00
105
+ ATOM 104 C5 PRE 8 41.522 37.451 38.670 1.00 0.00
106
+ ATOM 105 C6 PRE 8 40.855 37.198 37.522 1.00 0.00
107
+ ATOM 106 C7 PRE 8 38.873 36.029 36.278 1.00 0.00
108
+ ATOM 107 O71 PRE 8 38.866 36.883 35.395 1.00 0.00
109
+ ATOM 108 O72 PRE 8 37.973 35.185 36.370 1.00 0.00
110
+ ATOM 109 C8 PRE 8 41.142 34.949 36.392 1.00 0.00
111
+ ATOM 110 C1' PRE 8 42.419 34.555 37.122 1.00 0.00
112
+ ATOM 111 O1' PRE 8 42.481 33.507 37.766 1.00 0.00
113
+ ATOM 112 C2' PRE 8 43.706 35.545 37.013 1.00 0.00
114
+ ATOM 113 O'L PRE 8 44.669 35.339 37.752 1.00 0.00
115
+ ATOM 114 O'M PRE 8 43.648 36.538 36.300 1.00 0.00
116
+ ATOM 115 HO4 PRE 8 41.806 36.579 41.746 1.00 0.00
117
+ ATOM 116 H2 PRE 8 40.799 37.961 36.713 1.00 0.00
118
+ ATOM 117 H3 PRE 8 42.012 38.385 38.823 1.00 0.00
119
+ ATOM 118 H4 PRE 8 40.262 34.861 40.616 1.00 0.00
120
+ ATOM 119 H5 PRE 8 39.058 34.428 38.495 1.00 0.00
121
+ ATOM 120 H6 PRE 8 40.599 34.032 36.134 1.00 0.00
122
+ ATOM 121 H7 PRE 8 41.405 35.528 35.501 1.00 0.00
123
+ ATOM 122 H8 PRE 8 42.580 35.914 39.742 1.00 0.00
124
+ TER
125
+ END
@@ -0,0 +1,63 @@
1
+ default_name
2
+ 122
3
+ 47.3210000 49.1450000 36.0600000 47.6380000 49.0490000 35.1060000
4
+ 47.9070000 49.8200000 36.5300000 46.3180000 49.2620000 36.0590000
5
+ 47.5610000 47.8800000 36.7470000 48.2010000 48.0460000 37.6130000
6
+ 46.6130000 47.4770000 37.1040000 48.2010000 46.8290000 35.8340000
7
+ 47.7310000 46.5790000 34.7220000 49.2440000 46.1710000 36.3230000
8
+ 49.6290000 46.4690000 37.2150000 49.8490000 44.9950000 35.6970000
9
+ 49.3970000 44.8510000 34.7170000 51.3690000 45.1540000 35.4700000
10
+ 51.8840000 45.0380000 36.4230000 51.8160000 44.0230000 34.5250000
11
+ 51.3400000 44.1300000 33.5510000 52.8880000 44.0630000 34.3680000
12
+ 51.5830000 43.0440000 34.9450000 51.7350000 46.5450000 34.8990000
13
+ 51.2020000 46.7050000 33.9630000 51.4230000 47.3170000 35.6030000
14
+ 53.2340000 46.7480000 34.6580000 53.5920000 46.0710000 33.8870000
15
+ 53.4080000 47.7650000 34.3130000 53.7890000 46.5790000 35.5820000
16
+ 49.5180000 43.7800000 36.5630000 49.9970000 43.6530000 37.6930000
17
+ 48.6620000 42.8970000 36.0450000 48.2800000 43.0890000 35.1290000
18
+ 48.3730000 41.5940000 36.6400000 48.3340000 41.7050000 37.7230000
19
+ 47.0250000 41.0650000 36.1150000 46.9060000 41.3370000 35.0630000
20
+ 47.0180000 39.9740000 36.1500000 45.8130000 41.5820000 36.9090000
21
+ 45.7580000 42.6650000 36.8110000 44.9120000 41.1690000 36.4540000
22
+ 45.8310000 41.2270000 38.4090000 46.5410000 41.8840000 38.9120000
23
+ 44.8560000 41.4430000 38.8320000 46.2010000 39.8220000 38.6780000
24
+ 47.0460000 39.6820000 39.2050000 45.5890000 38.7380000 38.2360000
25
+ 44.4080000 38.7770000 37.7030000 43.8370000 39.6100000 37.7750000
26
+ 44.0300000 37.9300000 37.2690000 46.1710000 37.5810000 38.2830000
27
+ 47.1180000 37.4740000 38.5980000 45.6430000 36.7720000 37.9470000
28
+ 49.4760000 40.5740000 36.3570000 50.0870000 40.5740000 35.2890000
29
+ 49.6320000 39.6500000 37.2940000 49.1560000 39.7780000 38.1770000
30
+ 50.2860000 38.3680000 37.0610000 50.1480000 38.1000000 36.0180000
31
+ 51.3510000 38.4450000 37.2640000 49.7200000 37.2490000 37.9280000
32
+ 48.9810000 37.5170000 38.8860000 50.0880000 36.0110000 37.6000000
33
+ 50.6340000 35.8830000 36.7490000 49.8300000 34.8190000 38.4050000
34
+ 49.8570000 35.1040000 39.4540000 48.4400000 34.2630000 38.0850000
35
+ 48.4690000 33.7940000 37.1050000 48.1670000 33.5110000 38.8300000
36
+ 47.6940000 35.0600000 38.0840000 50.8950000 33.7230000 38.1950000
37
+ 51.4920000 33.5990000 37.1250000 51.0970000 32.8990000 39.2200000
38
+ 50.5880000 33.0800000 40.0820000 51.9560000 31.7060000 39.2250000
39
+ 51.9190000 31.2380000 38.2430000 53.4140000 32.1090000 39.5020000
40
+ 53.6820000 32.9370000 38.8440000 53.7010000 32.5180000 40.9480000
41
+ 53.5960000 31.6630000 41.6160000 54.7240000 32.8890000 41.0070000
42
+ 53.0200000 33.3080000 41.2550000 54.2720000 31.0290000 39.2150000
43
+ 54.3040000 30.9100000 38.2610000 51.4370000 30.6790000 40.2410000
44
+ 50.5680000 30.9990000 41.0510000 51.9580000 29.4550000 40.2320000
45
+ 52.7220000 29.2620000 39.5990000 51.5610000 28.3790000 41.1560000
46
+ 51.0000000 28.8070000 41.9860000 50.6650000 27.3260000 40.4910000
47
+ 50.3940000 26.5780000 41.2370000 49.3830000 27.9180000 39.9130000
48
+ 49.6030000 28.5030000 39.0190000 48.6960000 27.1100000 39.6670000
49
+ 48.9070000 28.5580000 40.6550000 51.3770000 26.6860000 39.4540000
50
+ 52.2420000 26.4430000 39.8200000 52.7800000 27.6740000 41.7330000
51
+ 53.6930000 27.2920000 40.9910000 52.8930000 27.5160000 42.9470000
52
+ 40.1820000 35.8650000 37.2050000 39.8250000 35.1620000 38.5530000
53
+ 40.4840000 35.4250000 39.7010000 41.6190000 36.4500000 39.8070000
54
+ 41.5300000 37.1690000 41.0320000 41.5220000 37.4510000 38.6700000
55
+ 40.8550000 37.1980000 37.5220000 38.8730000 36.0290000 36.2780000
56
+ 38.8660000 36.8830000 35.3950000 37.9730000 35.1850000 36.3700000
57
+ 41.1420000 34.9490000 36.3920000 42.4190000 34.5550000 37.1220000
58
+ 42.4810000 33.5070000 37.7660000 43.7060000 35.5450000 37.0130000
59
+ 44.6690000 35.3390000 37.7520000 43.6480000 36.5380000 36.3000000
60
+ 41.8060000 36.5790000 41.7460000 40.7990000 37.9610000 36.7130000
61
+ 42.0120000 38.3850000 38.8230000 40.2620000 34.8610000 40.6160000
62
+ 39.0580000 34.4280000 38.4950000 40.5990000 34.0320000 36.1340000
63
+ 41.4050000 35.5280000 35.5010000 42.5800000 35.9140000 39.7420000
@@ -0,0 +1,44 @@
1
+ from __future__ import annotations
2
+
3
+ import torch
4
+
5
+ from hessian_ff.loaders import load_coords
6
+
7
+
8
+ class _DummyASEAtoms:
9
+ def __init__(self, positions):
10
+ self._positions = positions
11
+
12
+ def get_positions(self):
13
+ return self._positions
14
+
15
+
16
+ def test_load_coords_xyz(tmp_path) -> None:
17
+ xyz_path = tmp_path / "mini.xyz"
18
+ xyz_path.write_text(
19
+ "2\n"
20
+ "comment\n"
21
+ "H 0.0 1.0 2.0\n"
22
+ "O 3.0 4.0 5.0\n",
23
+ encoding="utf-8",
24
+ )
25
+ x = load_coords(xyz_path, natom=2, dtype=torch.float64, device="cpu")
26
+ assert tuple(x.shape) == (2, 3)
27
+ assert x.dtype == torch.float64
28
+ assert float(x[1, 2]) == 5.0
29
+
30
+
31
+ def test_load_coords_ase_like() -> None:
32
+ atoms = _DummyASEAtoms([[0.0, 0.1, 0.2], [1.0, 1.1, 1.2]])
33
+ x = load_coords(atoms, natom=2, dtype=torch.float32, device="cpu")
34
+ assert tuple(x.shape) == (2, 3)
35
+ assert x.dtype == torch.float32
36
+ assert abs(float(x[0, 1]) - 0.1) < 1.0e-6
37
+
38
+
39
+ def test_load_coords_tensor() -> None:
40
+ x0 = torch.tensor([[1.0, 2.0, 3.0]], dtype=torch.float64)
41
+ x = load_coords(x0, natom=1, dtype=torch.float32, device="cpu")
42
+ assert tuple(x.shape) == (1, 3)
43
+ assert x.dtype == torch.float32
44
+ assert float(x[0, 0]) == 1.0
@@ -0,0 +1,49 @@
1
+ """Tests: energy and force correctness of hessian_ff vs OpenMM."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import numpy as np
6
+ import torch
7
+
8
+ E_ABS_TOL = 1.0e-3 # kcal/mol
9
+ F_RMS_TOL = 1.0e-3 # kcal/mol/A
10
+
11
+
12
+ def _openmm_energy_force(context):
13
+ """Extract energy (kcal/mol) and forces (kcal/mol/A) from OpenMM context."""
14
+ from openmm import unit
15
+
16
+ state = context.getState(getEnergy=True, getForces=True)
17
+ e = float(state.getPotentialEnergy().value_in_unit(unit.kilocalories_per_mole))
18
+ f = state.getForces(asNumpy=True).value_in_unit(
19
+ unit.kilocalories_per_mole / unit.angstrom,
20
+ )
21
+ return e, torch.as_tensor(np.asarray(f), dtype=torch.float64)
22
+
23
+
24
+ class TestEnergyForceVsOpenMM:
25
+ """Verify hessian_ff energy/force match OpenMM on the small system."""
26
+
27
+ def test_energy_matches_openmm(
28
+ self, small_ff, small_coords, openmm_context_and_pos,
29
+ ):
30
+ context, _ = openmm_context_and_pos
31
+ e_hff = float(small_ff(small_coords)["E_total"].detach().cpu())
32
+ e_omm, _ = _openmm_energy_force(context)
33
+ assert abs(e_hff - e_omm) <= E_ABS_TOL, (
34
+ f"Energy mismatch: hff={e_hff:.6f}, omm={e_omm:.6f}, "
35
+ f"diff={abs(e_hff - e_omm):.6e}"
36
+ )
37
+
38
+ def test_force_matches_openmm(
39
+ self, small_ff, small_coords, openmm_context_and_pos,
40
+ ):
41
+ context, _ = openmm_context_and_pos
42
+ _, f_hff = small_ff.energy_force(small_coords, force_calc_mode="Analytical")
43
+ f_hff = f_hff.detach().cpu().to(torch.float64)
44
+ _, f_omm = _openmm_energy_force(context)
45
+ diff = (f_hff - f_omm).numpy()
46
+ rms = float(np.sqrt(np.mean(diff ** 2)))
47
+ assert rms <= F_RMS_TOL, (
48
+ f"Force RMS mismatch: {rms:.6e} > tol={F_RMS_TOL}"
49
+ )
@@ -0,0 +1,137 @@
1
+ """Tests: Hessian correctness of hessian_ff (analytical vs autograd vs FD vs OpenMM FD)."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import numpy as np
6
+ import pytest
7
+ import torch
8
+
9
+ from hessian_ff.analytical_hessian import build_analytical_hessian
10
+
11
+ FD_DELTA = 1.0e-4 # Angstrom
12
+ H_RELFRO_TOL = 1.0e-3 # relative Frobenius norm tolerance
13
+
14
+
15
+ def _symmetrize(h: torch.Tensor) -> torch.Tensor:
16
+ h = h.detach().cpu().to(torch.float64)
17
+ return 0.5 * (h + h.T)
18
+
19
+
20
+ def _relative_frobenius(a: torch.Tensor, b: torch.Tensor) -> float:
21
+ d = b - a
22
+ return float(torch.linalg.norm(d) / (torch.linalg.norm(a) + 1e-20))
23
+
24
+
25
+ def _analytical_hessian(system, coords):
26
+ """Compute full analytical Hessian via build_analytical_hessian."""
27
+ all_atoms = list(range(system.natom))
28
+ h, _ = build_analytical_hessian(
29
+ system=system, coords=coords, active_atoms=all_atoms,
30
+ mpi_rank=0, mpi_size=1,
31
+ )
32
+ return _symmetrize(h)
33
+
34
+
35
+ def _autograd_hessian(ff, coords):
36
+ """Compute full Hessian via torch.autograd.functional.hessian."""
37
+ x = coords.clone().detach().requires_grad_(True)
38
+ h4 = torch.autograd.functional.hessian(
39
+ lambda x_: ff(x_)["E_total"], x, vectorize=False,
40
+ )
41
+ return _symmetrize(h4.reshape(x.numel(), x.numel()))
42
+
43
+
44
+ def _fd_hessian(ff, coords, delta=FD_DELTA, force_calc_mode="Analytical"):
45
+ """Compute full Hessian via finite-difference on forces."""
46
+ ndof = 3 * coords.shape[0]
47
+ h = torch.empty((ndof, ndof), dtype=torch.float64, device="cpu")
48
+ for col in range(ndof):
49
+ atom, comp = col // 3, col % 3
50
+ xp, xm = coords.clone(), coords.clone()
51
+ xp[atom, comp] += delta
52
+ xm[atom, comp] -= delta
53
+ _, fp = ff.energy_force(xp, force_calc_mode=force_calc_mode)
54
+ _, fm = ff.energy_force(xm, force_calc_mode=force_calc_mode)
55
+ fp_flat = fp.detach().cpu().to(torch.float64).reshape(-1)
56
+ fm_flat = fm.detach().cpu().to(torch.float64).reshape(-1)
57
+ h[:, col] = -(fp_flat - fm_flat) / (2.0 * delta)
58
+ return _symmetrize(h)
59
+
60
+
61
+ def _openmm_fd_hessian(context, base_pos, delta=FD_DELTA):
62
+ """Compute full Hessian via finite-difference on OpenMM forces."""
63
+ from openmm import unit
64
+
65
+ natom = base_pos.shape[0]
66
+ ndof = 3 * natom
67
+ h = np.empty((ndof, ndof), dtype=np.float64)
68
+ force_unit = unit.kilocalories_per_mole / unit.angstrom
69
+
70
+ for col in range(ndof):
71
+ atom, comp = col // 3, col % 3
72
+ xp, xm = base_pos.copy(), base_pos.copy()
73
+ xp[atom, comp] += delta
74
+ xm[atom, comp] -= delta
75
+
76
+ context.setPositions(xp * unit.angstrom)
77
+ fp = np.asarray(
78
+ context.getState(getForces=True).getForces(asNumpy=True)
79
+ .value_in_unit(force_unit), dtype=np.float64,
80
+ ).reshape(-1)
81
+
82
+ context.setPositions(xm * unit.angstrom)
83
+ fm = np.asarray(
84
+ context.getState(getForces=True).getForces(asNumpy=True)
85
+ .value_in_unit(force_unit), dtype=np.float64,
86
+ ).reshape(-1)
87
+
88
+ h[:, col] = -(fp - fm) / (2.0 * delta)
89
+
90
+ # Restore original positions
91
+ context.setPositions(base_pos * unit.angstrom)
92
+ return _symmetrize(torch.from_numpy(h))
93
+
94
+
95
+ class TestHessianConsistency:
96
+ """Verify Hessian methods produce consistent results on the small system."""
97
+
98
+ def test_analytical_vs_autograd(
99
+ self, small_system, small_ff_autograd, small_coords,
100
+ ):
101
+ h_ana = _analytical_hessian(small_system, small_coords)
102
+ h_auto = _autograd_hessian(small_ff_autograd, small_coords)
103
+ rel = _relative_frobenius(h_ana, h_auto)
104
+ assert rel <= H_RELFRO_TOL, (
105
+ f"analytical vs autograd: relative Frobenius = {rel:.6e} > {H_RELFRO_TOL}"
106
+ )
107
+
108
+ def test_analytical_vs_fd(
109
+ self, small_system, small_ff, small_coords,
110
+ ):
111
+ h_ana = _analytical_hessian(small_system, small_coords)
112
+ h_fd = _fd_hessian(small_ff, small_coords)
113
+ rel = _relative_frobenius(h_ana, h_fd)
114
+ assert rel <= H_RELFRO_TOL, (
115
+ f"analytical vs FD: relative Frobenius = {rel:.6e} > {H_RELFRO_TOL}"
116
+ )
117
+
118
+ def test_analytical_vs_openmm_fd(
119
+ self, small_system, small_coords, openmm_context_and_pos,
120
+ ):
121
+ context, base_pos = openmm_context_and_pos
122
+ h_ana = _analytical_hessian(small_system, small_coords)
123
+ h_omm = _openmm_fd_hessian(context, base_pos)
124
+ rel = _relative_frobenius(h_ana, h_omm)
125
+ assert rel <= H_RELFRO_TOL, (
126
+ f"analytical vs OpenMM FD: relative Frobenius = {rel:.6e} > {H_RELFRO_TOL}"
127
+ )
128
+
129
+ def test_analytical_hessian_shape(self, small_system, small_coords):
130
+ ndof = 3 * small_system.natom
131
+ h_ana = _analytical_hessian(small_system, small_coords)
132
+ assert h_ana.shape == (ndof, ndof)
133
+
134
+ def test_analytical_hessian_symmetric(self, small_system, small_coords):
135
+ h_ana = _analytical_hessian(small_system, small_coords)
136
+ diff = float(torch.max(torch.abs(h_ana - h_ana.T)))
137
+ assert diff < 1e-10, f"Hessian not symmetric: max asymmetry = {diff:.6e}"
@@ -0,0 +1,18 @@
1
+ def test_public_api_symbols() -> None:
2
+ import hessian_ff
3
+
4
+ required = [
5
+ "clear_runtime_cache",
6
+ "load_system",
7
+ "load_coords",
8
+ "ForceFieldTorch",
9
+ "system_summary",
10
+ "torch_energy",
11
+ "torch_energy_batch",
12
+ "torch_force",
13
+ "torch_force_batch",
14
+ "torch_hessian",
15
+ "verify_openmm",
16
+ ]
17
+ for name in required:
18
+ assert hasattr(hessian_ff, name)
@@ -0,0 +1,40 @@
1
+ from __future__ import annotations
2
+
3
+ from pathlib import Path
4
+
5
+ import pytest
6
+ import torch
7
+
8
+ from hessian_ff.forcefield import ForceFieldTorch
9
+ from hessian_ff.loaders import load_coords, load_system
10
+
11
+
12
+ _DATA_DIR = Path(__file__).resolve().parent / "data" / "small"
13
+ _PRMTOP = _DATA_DIR / "complex.parm7"
14
+ _COORDS = _DATA_DIR / "complex.rst7"
15
+
16
+ pytestmark = pytest.mark.skipif(
17
+ (not _PRMTOP.exists()) or (not _COORDS.exists()),
18
+ reason="benchmark/data/small test fixtures are not available in this environment",
19
+ )
20
+
21
+
22
+ def _load_ff_and_coords():
23
+ system = load_system(_PRMTOP, device="cpu").to(dtype=torch.float64)
24
+ ff = ForceFieldTorch(system, nonbonded_cpu_fast=True)
25
+ return system, ff
26
+
27
+
28
+ def test_forcefield_explicit_dtype_validation_single() -> None:
29
+ system, ff = _load_ff_and_coords()
30
+ coords = load_coords(_COORDS, natom=system.natom, device="cpu", dtype=torch.float32)
31
+ with pytest.raises(ValueError, match="coords dtype mismatch"):
32
+ ff.energy_force(coords, force_calc_mode="Analytical")
33
+
34
+
35
+ def test_forcefield_explicit_dtype_validation_batch() -> None:
36
+ system, ff = _load_ff_and_coords()
37
+ coords = load_coords(_COORDS, natom=system.natom, device="cpu", dtype=torch.float32)
38
+ coords_batch = coords.unsqueeze(0).repeat(2, 1, 1)
39
+ with pytest.raises(ValueError, match="coords_batch dtype mismatch"):
40
+ ff.energy_force_batch(coords_batch, force_calc_mode="Analytical")