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,375 @@
1
+ # [1] https://doi.org/10.1021/acs.jctc.0c01306
2
+ # Single-Point Hessian Calculations for Improved Vibrational Frequencies and
3
+ # Rigid-Rotor-Harmonic-Oscillator Thermodynamics
4
+ # Spicher, Grimme
5
+
6
+
7
+ from dataclasses import dataclass
8
+ from math import floor, ceil
9
+ from pathlib import Path
10
+ import shutil
11
+ from typing import Callable, Dict, Optional, Tuple
12
+ import sys
13
+
14
+ import numpy as np
15
+
16
+ from pysisyphus.calculators import Dimer, ExternalPotential
17
+ from pysisyphus.cos.ChainOfStates import ChainOfStates
18
+ from pysisyphus.config import T_DEFAULT, p_DEFAULT
19
+ from pysisyphus.Geometry import Geometry
20
+ from pysisyphus.helpers import do_final_hessian
21
+ from pysisyphus.helpers_pure import highlight_text, report_frozen_atoms
22
+ from pysisyphus.io import save_hessian
23
+ from pysisyphus.modefollow import NormalMode, geom_davidson
24
+ from pysisyphus.optimizers.cls_map import get_opt_cls, key_is_tsopt
25
+ from pysisyphus.optimizers.Optimizer import Optimizer
26
+ from pysisyphus.optimizers.HessianOptimizer import HessianOptimizer
27
+ from pysisyphus.optimizers.hessian_updates import bfgs_update
28
+ from pysisyphus.tsoptimizers.TSHessianOptimizer import TSHessianOptimizer
29
+
30
+
31
+ def opt_davidson(opt, tsopt=True, res_rms_thresh=1e-4):
32
+ try:
33
+ H = opt.H
34
+ except AttributeError:
35
+ if tsopt:
36
+ raise Exception("Can't handle TS optimization without Hessian yet!")
37
+
38
+ # Create approximate updated Hessian
39
+ cart_coords = opt.cart_coords
40
+ cart_forces = opt.cart_forces
41
+ coord_diffs = np.diff(cart_coords, axis=0)
42
+ grad_diffs = -np.diff(cart_forces, axis=0)
43
+ H = np.eye(cart_coords[0].size)
44
+ for s, y in zip(coord_diffs, grad_diffs):
45
+ dH, _ = bfgs_update(H, s, y)
46
+ H += dH
47
+
48
+ geom = opt.geometry
49
+ if geom.coord_type != "cart":
50
+ H = geom.internal.backtransform_hessian(H)
51
+
52
+ masses_rep = geom.masses_rep
53
+ # Mass-weigh and project Hessian
54
+ H = geom.eckart_projection(geom.mass_weigh_hessian(H))
55
+ w, v = np.linalg.eigh(H)
56
+ inds = [0, 1] if tsopt else [6]
57
+ # Converge the lowest two modes for TS optimizations; for minimizations the lowest
58
+ # mode would is enough.
59
+ lowest = 2 if tsopt else 1
60
+ guess_modes = [NormalMode(l, masses_rep) for l in v[:, inds].T]
61
+
62
+ davidson_kwargs = {
63
+ "hessian_precon": H,
64
+ "guess_modes": guess_modes,
65
+ "lowest": lowest,
66
+ "res_rms_thresh": res_rms_thresh,
67
+ "remove_trans_rot": True,
68
+ }
69
+
70
+ result = geom_davidson(geom, **davidson_kwargs)
71
+ return result
72
+
73
+
74
+ @dataclass
75
+ class OptResult:
76
+ opt: Optimizer
77
+ geom: Geometry
78
+ fn: Path
79
+
80
+
81
+ def run_opt(
82
+ geom,
83
+ calc_getter,
84
+ opt_key,
85
+ opt_kwargs=None,
86
+ iterative=False,
87
+ iterative_max_cycles=5,
88
+ iterative_thresh=-15,
89
+ iterative_scale=2.00,
90
+ cart_hessian=None,
91
+ print_thermo=False,
92
+ title="Optimization",
93
+ copy_final_geom=None,
94
+ level=0,
95
+ save_hessian=False,
96
+ ):
97
+ is_cos = issubclass(type(geom), ChainOfStates)
98
+ is_tsopt = key_is_tsopt(opt_key)
99
+ # Disallow iterative optimizations for COS objects
100
+ if opt_kwargs is None:
101
+ opt_kwargs = dict()
102
+ is_iterative = (not is_cos) and (iterative or opt_kwargs.pop("iterative", False))
103
+
104
+ if is_cos:
105
+ # Set calculators on all images
106
+ for image in geom.images:
107
+ image.set_calculator(calc_getter())
108
+ title = str(geom)
109
+ else:
110
+ geom.set_calculator(calc_getter())
111
+ geom.cart_hessian = cart_hessian
112
+
113
+ do_hess = opt_kwargs.pop("do_hess", False)
114
+ do_davidson = opt_kwargs.pop("do_davidson", False)
115
+ T = opt_kwargs.pop("T", T_DEFAULT)
116
+ p = opt_kwargs.pop("p", p_DEFAULT)
117
+ propagate = opt_kwargs.pop("propagate", False)
118
+
119
+ opt_cls = get_opt_cls(opt_key)
120
+ for i in range(iterative_max_cycles):
121
+ # Modify hessian_init in later cycles, te reuse the calculated Hessian
122
+ # from the final geometry of the previous optimization.
123
+ if (i > 0) and issubclass(opt_cls, HessianOptimizer):
124
+ opt_kwargs["hessian_init"] = "calc"
125
+ opt = opt_cls(geom, **opt_kwargs)
126
+ print(highlight_text(f"Running {title}", level=level) + "\n")
127
+ print(f" Input geometry: {geom.describe()}")
128
+ print(f" Coordinate system: {geom.coord_type}")
129
+ print(f" Coordinate number: {len(geom.coords)}")
130
+ print(f" Calculator: {geom.calculator}")
131
+ print(f" Charge: {geom.calculator.charge}")
132
+ print(f" Multiplicity: {geom.calculator.mult}")
133
+ print(f" Optimizer: {opt_key}\n")
134
+ report_frozen_atoms(geom)
135
+ print()
136
+
137
+ # Try to propagate chkfiles along calculators in COS optimizations
138
+ if propagate and is_cos:
139
+ print("Propagating chkfiles along COS")
140
+ for j, image in enumerate(geom.images):
141
+ image.energy
142
+ cur_calc = image.calculator
143
+ try:
144
+ next_calc = geom.images[j + 1].calculator
145
+ except IndexError:
146
+ pass
147
+ try:
148
+ next_calc.set_chkfiles(cur_calc.get_chkfiles())
149
+ except AttributeError:
150
+ break
151
+
152
+ opt.run()
153
+
154
+ # Only do 1 cycle in non-iterative optimizations
155
+ if not is_iterative:
156
+ break
157
+
158
+ # Determine imaginary modes for subsequent displacements
159
+ nus, *_, cart_displs = geom.get_normal_modes()
160
+ below_thresh = nus < iterative_thresh
161
+ # Never displace along transition vector in ts-optimizations. Just skip it.
162
+ if is_tsopt:
163
+ below_thresh[0] = False
164
+ imag_nus = nus[below_thresh]
165
+ imag_displs = cart_displs[:, below_thresh].T
166
+
167
+ if len(imag_nus) == 0:
168
+ print(f"Iterative optimization converged in cycle {i}.")
169
+ break
170
+
171
+ # h5_fn = f"hess_calc_iter_{i:02d}.h5"
172
+ # save_hessian(h5_fn, geom)
173
+ # print(f"Saved HDF5-Hessian to {h5_fn}.")
174
+
175
+ print(f"\nImaginary modes below threshold of {iterative_thresh:.2f} cm⁻¹:")
176
+ for j, nu in enumerate(nus[below_thresh]):
177
+ print(f"\t{j:02d}: {nu:8.2f} cm⁻¹")
178
+ sys.stdout.flush()
179
+
180
+ print(f"\nGeometry after optimization cycle {i}:\n{geom.as_xyz()}")
181
+
182
+ # Displace along imaginary modes
183
+ for j, (nu, imag_displ) in enumerate(zip(imag_nus, imag_displs)):
184
+ step = iterative_scale * imag_displ
185
+ new_cart_coords = geom.cart_coords + step
186
+ geom.cart_coords = new_cart_coords
187
+
188
+ print(f"\nDisplaced geometry for optimization cycle {i+1}:\n{geom.as_xyz()}\n")
189
+
190
+ # # ChainOfStates specific
191
+ # if is_cos and (not opt.stopped):
192
+ # hei_coords, hei_energy, hei_tangent, hei_frac_index = geom.get_splined_hei()
193
+ # floor_ind = floor(hei_frac_index)
194
+ # ceil_ind = ceil(hei_frac_index)
195
+ # print(
196
+ # f"Splined HEI is at {hei_frac_index:.2f}/{len(geom.images)-1:.2f}, "
197
+ # f"between image {floor_ind} and {ceil_ind} (0-based indexing)."
198
+ # )
199
+ # hei_geom = Geometry(geom.images[0].atoms, hei_coords)
200
+ # hei_geom.energy = hei_energy
201
+ # hei_fn = "splined_hei.xyz"
202
+ # with open(hei_fn, "w") as handle:
203
+ # handle.write(hei_geom.as_xyz())
204
+ # print(f"Wrote splined HEI to '{hei_fn}'")
205
+
206
+ if copy_final_geom and opt.is_converged:
207
+ copy_fn = copy_final_geom
208
+ shutil.copy(opt.final_fn, copy_fn)
209
+ print(f"Copied '{opt.final_fn}' to '{copy_fn}'.")
210
+
211
+ if do_davidson and (not opt.stopped):
212
+ tsopt = isinstance(opt, TSHessianOptimizer.TSHessianOptimizer) or isinstance(
213
+ geom.calculator, Dimer
214
+ )
215
+ type_ = "TS" if tsopt else "minimum"
216
+ print(highlight_text(f"Davidson after {type_} search", level=1))
217
+ opt_davidson(opt, tsopt=tsopt)
218
+ elif do_hess and (not opt.stopped):
219
+ print()
220
+ prefix = opt_kwargs.get("prefix", "")
221
+ out_dir = opt_kwargs.get("out_dir", None)
222
+ do_final_hessian(
223
+ geom,
224
+ save_hessian=save_hessian,
225
+ write_imag_modes=True,
226
+ prefix=prefix,
227
+ T=T,
228
+ p=p,
229
+ print_thermo=print_thermo,
230
+ is_ts=is_tsopt,
231
+ out_dir=out_dir,
232
+ )
233
+ print()
234
+
235
+ opt_result = OptResult(opt, opt.geometry, opt.final_fn)
236
+ return opt_result
237
+
238
+
239
+ def get_optimal_bias(
240
+ ref_geom: Geometry,
241
+ calc_getter: Callable,
242
+ opt_key: str,
243
+ opt_kwargs: Dict,
244
+ k_max: float,
245
+ k_min: float = 0.0,
246
+ rmsd_target: float = 0.188973,
247
+ rmsd_thresh: Optional[float] = None,
248
+ rmsd_kwargs: Optional[Dict] = None,
249
+ k_thresh: float = 1e-3,
250
+ strict=True,
251
+ ) -> Tuple[OptResult, float, bool]:
252
+ """Driver to determine optimal bias value k for RMSD restraint.
253
+
254
+ Parameters
255
+ ----------
256
+ ref_geom
257
+ Reference geometry. Starting point of the optimizations and reference
258
+ for RMSD calculations.
259
+ calc_getter
260
+ Function that returns the actual calculator, providing the energy and
261
+ its derivatives.
262
+ opt_key
263
+ Determines optimizer type. See pysisyphus.optimizers.cls_map.
264
+ opt_kwargs
265
+ Optional dict of arguments passed to the optimizer.
266
+ k_max
267
+ Maximum absolute value of bias factor k. Must be a > k_min.
268
+ k_max
269
+ Minimum absolute value of bias factor k. Must be a positive number >= 0.0.
270
+ Defaults to 0.0.
271
+ rmsd_target
272
+ Target RMSD value in au. Defaults to 0.188973 a0 (approx. 0.1 Å).
273
+ rmsd_thresh
274
+ Allowed deviation from rmsd_target in au. If omitted, 5% of rmsd_target are used.
275
+ rmsd_kwargs
276
+ Additional keyword arguments that are passed to the RMSD class, e.g., atom_indices.
277
+ k_thresh:
278
+ When the absolute value of k_bias - k_min or k_max becomes smaller than
279
+ k_thresh, the bisection is aborted.
280
+ strict
281
+ If True, AssertionError is raised when an optimization did not converged.
282
+
283
+ Returns
284
+ -------
285
+ opt_result
286
+ OptimizationResult object containig the Optimizer object.
287
+ k_opt
288
+ Optimal value of k_bias.
289
+ valid_k
290
+ Whether an appropriate bias value k was found.
291
+ """
292
+ assert rmsd_target > 0.0
293
+ assert k_min >= 0.0
294
+ assert k_max > k_min
295
+ assert k_thresh >= 0.0
296
+ if rmsd_thresh is None:
297
+ rmsd_thresh = 0.05 * rmsd_target
298
+ if rmsd_kwargs is None:
299
+ rmsd_kwargs = dict()
300
+
301
+ opt_counter = 0
302
+
303
+ def run_biased_opt(k):
304
+ nonlocal opt_counter
305
+ geom = ref_geom.copy()
306
+
307
+ def biased_calc_getter():
308
+ act_calc = calc_getter()
309
+ _rmsd_kwargs = {
310
+ "type": "rmsd",
311
+ "k": k,
312
+ }
313
+ _rmsd_kwargs.update(rmsd_kwargs)
314
+ potentials = (_rmsd_kwargs,)
315
+ calc = ExternalPotential(
316
+ calculator=act_calc, potentials=potentials, geom=ref_geom
317
+ )
318
+ return calc
319
+
320
+ sys.stdout.flush()
321
+ prefix = f"biased_{opt_counter:02d}"
322
+ prefixed_opt_kwargs = opt_kwargs.copy()
323
+ prefixed_opt_kwargs.update(
324
+ {
325
+ "prefix": prefix,
326
+ "h5_group_name": f"{prefix}_opt",
327
+ }
328
+ )
329
+ print(f"@@@ Running optimization {opt_counter:02d} with {k=:.6f} au.")
330
+ opt_result = run_opt(geom, biased_calc_getter, opt_key, prefixed_opt_kwargs)
331
+ if strict:
332
+ assert opt_result.opt.is_converged
333
+
334
+ rmsd_current = ref_geom.rmsd(geom)
335
+ print(
336
+ f"@@@ Biased optimization {opt_counter:02d} with {k=:.6f} au yielded an "
337
+ f"RMSD of RMSD={rmsd_current:.4f} au."
338
+ )
339
+ opt_counter += 1
340
+ return opt_result, rmsd_current
341
+
342
+ k_bias = 0.0
343
+ opt_result, rmsd_current = run_biased_opt(
344
+ k=k_bias
345
+ ) # Start with unbiased optimization
346
+ unbiased_failed = rmsd_current > rmsd_target
347
+
348
+ k_min0 = k_min
349
+ k_max0 = k_max
350
+
351
+ def k_is_valid(k):
352
+ """Return whether k is too close to either k_min0 or k_max0."""
353
+ return all([abs(k_bias - k) >= k_thresh for k in (k_min0, k_max0)])
354
+
355
+ valid_k = True
356
+
357
+ # Only run the loop when the initial unbiased optimization failed. This way
358
+ # we don't have to check for an early return before the loop, but can keep
359
+ # one return statement at the end of the function.
360
+ while unbiased_failed and abs(rmsd_current - rmsd_target) > rmsd_thresh:
361
+ k_bias = -0.5 * (k_min + k_max)
362
+ if not (valid_k := k_is_valid(k_bias)):
363
+ break
364
+ # Biased geometry optimization
365
+ opt_result, rmsd_current = run_biased_opt(k_bias)
366
+ if rmsd_current < rmsd_target:
367
+ k_max = abs(k_bias)
368
+ elif rmsd_current > rmsd_target:
369
+ k_min = abs(k_bias)
370
+ print(
371
+ f"@@@ After biased optimization {opt_counter:02d}: {k_min=:.4f}, {k_bias=:.4f}, "
372
+ f"{k_max=:.4f}, {rmsd_current=:4f} au."
373
+ )
374
+ k_opt = k_bias
375
+ return opt_result, k_opt, valid_k
@@ -0,0 +1,91 @@
1
+ from datetime import timedelta
2
+ import sys
3
+ import time
4
+
5
+ from pysisyphus.helpers_pure import highlight_text
6
+ from pysisyphus.TablePrinter import TablePrinter
7
+
8
+
9
+ def run_perf(
10
+ geom,
11
+ calc_getter,
12
+ pals=None,
13
+ mems=None,
14
+ pal_range=None,
15
+ mem_range=None,
16
+ repeat=1,
17
+ kind="forces",
18
+ ):
19
+ assert repeat > 0
20
+ assert pals or pal_range
21
+ assert mems or mem_range
22
+
23
+ func_names = {
24
+ "energy": "get_energy",
25
+ "forces": "get_forces",
26
+ "hessian": "get_hessian",
27
+ }
28
+
29
+ if pal_range is not None:
30
+ pals = range(*pal_range)
31
+ try:
32
+ pal_iter = tuple(pals)
33
+ except TypeError: # When 'pals' is a single integer
34
+ pal_iter = tuple((pals,))
35
+
36
+ if mem_range is not None:
37
+ mems = range(*mem_range)
38
+ try:
39
+ mem_iter = tuple(mems)
40
+ except TypeError: # When 'mems' is a single integer
41
+ mem_iter = tuple((mems,))
42
+
43
+ results = {}
44
+ for pal in pal_iter:
45
+ print(f"{pal=} and ", end="")
46
+ for mem in mem_iter:
47
+ print(f"{mem=}:")
48
+ for i in range(repeat):
49
+ print(f"\tRunning {kind} cycle {i:02d} ... ", end="")
50
+ calc = calc_getter()
51
+ calc.pal = pal
52
+ calc.mem = mem
53
+ start = time.time()
54
+ func = getattr(calc, func_names[kind])
55
+ _ = func(geom.atoms, geom.cart_coords)
56
+ dur = time.time() - start
57
+ td = timedelta(seconds=dur)
58
+ print(f"finished in {td} h")
59
+ sys.stdout.flush()
60
+ key = (pal, mem)
61
+ results.setdefault(key, list()).append(td)
62
+ print()
63
+ return results
64
+
65
+
66
+ def print_perf_results(results):
67
+ pal_avgs = dict()
68
+ pal_min = 1_000_000_000 # Dummy value
69
+ for i, (key, tds) in enumerate(sorted(results.items())):
70
+ pal, mem = key
71
+ pal_min = min(pal, pal_min)
72
+ print(highlight_text(f"{i:03d}: pal={pal}, mem={mem} MB"))
73
+ for j, td in enumerate(tds):
74
+ print(f"Run {j:03d}: {td} h")
75
+ avg = sum(tds, timedelta(0)) / len(tds)
76
+ # pal_avgs.setdefault(pal, list()).append(avg)
77
+ pal_avgs[pal] = avg
78
+ print(f" Avg: {avg} h")
79
+ print()
80
+
81
+ avg_min = pal_avgs[pal_min]
82
+ print(f" pal_min: {pal_min} core(s)")
83
+ print("efficiency: speedup / (pal / pal_min)\n")
84
+ header = ("pal", "avg. / h", "speedup", "efficieny")
85
+ col_fmts = ("int", "str", "float", "float")
86
+ table = TablePrinter(header, col_fmts, width=20)
87
+ table.print_header()
88
+ for pal, avg in pal_avgs.items():
89
+ speedup = avg_min / avg
90
+ speedup_per_pal = speedup / (pal / pal_min)
91
+ table.print_row((pal, str(avg), speedup, speedup_per_pal))
@@ -0,0 +1,52 @@
1
+ from math import log
2
+
3
+ from pysisyphus.config import p_DEFAULT, T_DEFAULT
4
+ from pysisyphus.constants import AU2KCALPERMOL, KBAU
5
+ from pysisyphus.helpers_pure import standard_state_corr
6
+ from pysisyphus import logger
7
+ from pysisyphus.io import geom_from_hessian
8
+
9
+
10
+ def G_aq_from_h5_hessian(h5_hessian, solv_en, T=T_DEFAULT, p=p_DEFAULT):
11
+ geom = geom_from_hessian(h5_hessian)
12
+ thermo = geom.get_thermoanalysis(T=T, p=p)
13
+ dG_solv = solv_en - thermo.U_el
14
+ G_aq = float(thermo.G + dG_solv)
15
+ return G_aq
16
+
17
+
18
+ def direct_cycle(
19
+ acid_h5,
20
+ base_h5,
21
+ acid_solv_en,
22
+ base_solv_en,
23
+ G_aq_H=None,
24
+ G_gas_H=-6.28,
25
+ dG_solv_H=-265.9,
26
+ T=T_DEFAULT,
27
+ p=p_DEFAULT,
28
+ ):
29
+
30
+ G_aq_acid = G_aq_from_h5_hessian(acid_h5, acid_solv_en, T=T, p=p)
31
+ G_aq_base = G_aq_from_h5_hessian(base_h5, base_solv_en, T=T, p=p)
32
+
33
+ if G_aq_H is None:
34
+ G_aq_H = G_gas_H + dG_solv_H
35
+ G_aq_H /= AU2KCALPERMOL
36
+
37
+ dG_aq = G_aq_H + G_aq_base - G_aq_acid
38
+ dG_aq_corr = dG_aq + standard_state_corr(T=T, p=p)
39
+
40
+ pKa = dG_aq_corr / (KBAU * T * log(10))
41
+
42
+ logger.debug(
43
+ f"pKa calculation using direct cycle:\n"
44
+ f"\tAcid HDF5: {acid_h5}\n\tBase HDF5: {base_h5}\n"
45
+ f"\tT={T:.4f}, p={p:.1f} Pa\n"
46
+ f"\tG_aq_acid={G_aq_acid:.6f} au\n"
47
+ f"\tG_aq_base={G_aq_base:.6f} au\n"
48
+ f"\tG_aq_H={G_aq_H:.6f} au\n"
49
+ f"\tpKa={pKa:.6f}"
50
+ )
51
+
52
+ return pKa