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,56 @@
1
+ # [1] https://doi.org/10.1007/s002140050387
2
+ # Bofill, 1998
3
+
4
+
5
+ import numpy as np
6
+
7
+ from pysisyphus.tsoptimizers.TSHessianOptimizer import TSHessianOptimizer
8
+
9
+ import torch
10
+
11
+ class RSIRFOptimizer(TSHessianOptimizer):
12
+ def optimize(self):
13
+ energy, gradient, H, eigvals, eigvecs, resetted = self.housekeeping()
14
+ self.update_ts_mode(eigvals, eigvecs)
15
+
16
+ self.log(
17
+ "Using projection to construct image potential gradient "
18
+ f"and hessian for root(s) {self.roots}."
19
+ )
20
+ # Ensure gradient is in the same subspace as eigvecs (active DOFs)
21
+ if isinstance(H, torch.Tensor):
22
+ if gradient.size(0) != eigvecs.size(0):
23
+ gradient = self.active_from_full(gradient)
24
+ else:
25
+ if gradient.size != eigvecs.shape[0]:
26
+ gradient = self.active_from_full(gradient)
27
+ # Projection matrix to construct g* and H*
28
+ if isinstance(H, torch.Tensor):
29
+ P = torch.eye(gradient.size(0), device=H.device, dtype=H.dtype)
30
+ for root in self.roots:
31
+ trans_vec = eigvecs[:, root]
32
+ P -= 2 * torch.outer(trans_vec, trans_vec)
33
+ H_star = P @ H
34
+ eigvals_, eigvecs_ = torch.linalg.eigh(H_star)
35
+ else:
36
+ P = np.eye(gradient.size)
37
+ for root in self.roots:
38
+ trans_vec = eigvecs[:, root]
39
+ P -= 2 * np.outer(trans_vec, trans_vec)
40
+ H_star = P.dot(H)
41
+ eigvals_, eigvecs_ = np.linalg.eigh(H_star)
42
+ # Neglect small eigenvalues
43
+ eigvals_, eigvecs_ = self.filter_small_eigvals(eigvals_, eigvecs_)
44
+
45
+ if isinstance(H, torch.Tensor):
46
+ grad_star = P @ gradient
47
+ else:
48
+ grad_star = P.dot(gradient)
49
+ step = self.get_rs_step(eigvals_, eigvecs_, grad_star, name="RS-I-RFO")
50
+
51
+ self.predicted_energy_changes.append(self.rfo_model(gradient, self.cur_H, step))
52
+
53
+ step = self.full_from_active(step)
54
+ if isinstance(step, torch.Tensor):
55
+ step = step.cpu().numpy()
56
+ return step
@@ -0,0 +1,182 @@
1
+ # See [1] https://pubs.acs.org/doi/pdf/10.1021/j100247a015
2
+ # Banerjee, 1985
3
+ # [2] https://aip.scitation.org/doi/abs/10.1063/1.2104507
4
+ # Heyden, 2005
5
+ # [3] https://onlinelibrary.wiley.com/doi/abs/10.1002/jcc.540070402
6
+ # Baker, 1985
7
+ # [4] https://link.springer.com/article/10.1007/s002140050387
8
+ # Besalu, 1998
9
+
10
+
11
+ import numpy as np
12
+
13
+ from pysisyphus.tsoptimizers.TSHessianOptimizer import TSHessianOptimizer
14
+
15
+
16
+ class RSPRFOptimizer(TSHessianOptimizer):
17
+ def optimize(self):
18
+ energy, gradient, H, eigvals, eigvecs, resetted = self.housekeeping()
19
+ self.update_ts_mode(eigvals, eigvecs)
20
+
21
+ # Transform gradient to eigensystem of hessian
22
+ gradient_trans = eigvecs.T.dot(gradient)
23
+ # Minimize energy along all modes, except the TS-mode
24
+ min_indices = [i for i in range(gradient_trans.size) if i not in self.roots]
25
+ # Maximize energy along all requested modes.
26
+ max_indices = [i for i in range(gradient_trans.size) if i in self.roots]
27
+ # Get line search steps, if requested.
28
+ ip_step_trans, gradient_trans = self.step_and_grad_from_line_search(
29
+ energy,
30
+ gradient_trans,
31
+ eigvecs,
32
+ min_indices,
33
+ max_indices,
34
+ )
35
+
36
+ """In the RS-(P)RFO method we have to scale the matrices with alpha.
37
+ Unscaled matrix (Eq. 8) in [1]:
38
+ (H g) (x) (S 0) (x)
39
+ = lambda
40
+ (g+ 0) (1) (0 1) (1)
41
+ with
42
+ S = alpha * Identity matrix
43
+ and multiplying from the left with the inverse of the scaling matrix
44
+ (1/alpha 0)
45
+
46
+ (0 1)
47
+ we get
48
+ (1/alpha 0) (H g) (x) (x)
49
+ = lambda
50
+ (0 1) (g+ 0) (1) (1)
51
+ eventually leading to the scaled matrix:
52
+ (H/alpha g/alpha) (x) (x)
53
+ = lambda .
54
+ (g+ 0) (1) (1)
55
+ """
56
+
57
+ alpha = self.alpha0
58
+ for mu in range(self.max_micro_cycles):
59
+ self.log(f"RS-PRFO micro cycle {mu:02d}, alpha={alpha:.6f}")
60
+
61
+ # Maximize energy along the chosen TS mode. The matrix is hardcoded
62
+ # as 2x2, so only first-order saddle point searches are supported.
63
+ # Try secular equation solver first (O(N) vs O(N^3))
64
+ secular_max = self.solve_rfo_secular(
65
+ eigvals[max_indices], gradient_trans[max_indices], alpha,
66
+ kind="max", prev_eigvec=self.prev_eigvec_max,
67
+ )
68
+ if secular_max is not None:
69
+ step_max, eigval_max, nu_max, self.prev_eigvec_max = secular_max
70
+ else:
71
+ H_aug_max = self.get_augmented_hessian(
72
+ eigvals[max_indices], gradient_trans[max_indices], alpha
73
+ )
74
+ step_max, eigval_max, nu_max, self.prev_eigvec_max = self.solve_rfo(
75
+ H_aug_max, "max", prev_eigvec=self.prev_eigvec_max
76
+ )
77
+
78
+ # Minimize energy along all modes, but the TS mode.
79
+ secular_min = self.solve_rfo_secular(
80
+ eigvals[min_indices], gradient_trans[min_indices], alpha,
81
+ kind="min", prev_eigvec=self.prev_eigvec_min,
82
+ )
83
+ if secular_min is not None:
84
+ step_min, eigval_min, nu_min, self.prev_eigvec_min = secular_min
85
+ else:
86
+ H_aug_min = self.get_augmented_hessian(
87
+ eigvals[min_indices], gradient_trans[min_indices], alpha
88
+ )
89
+ step_min, eigval_min, nu_min, self.prev_eigvec_min = self.solve_rfo(
90
+ H_aug_min, "min", prev_eigvec=self.prev_eigvec_min
91
+ )
92
+
93
+ # Calculate overlap between directions over the course of the micro cycles
94
+ # if mu == 0:
95
+ # TODO: convert back to original space
96
+ # ref_step_max = step_max.copy()
97
+ # ref_step_min = step_min.copy()
98
+ min_norm = np.linalg.norm(step_min)
99
+ max_norm = np.linalg.norm(step_max)
100
+ self.log(f"norm(step_max)={max_norm:.6f}")
101
+ self.log(f"norm(step_min)={min_norm:.6f}")
102
+ self.log(f"norm(step_max)/norm(step_min)={max_norm/min_norm:.2%}")
103
+ # Calculate overlaps with originally proposed step in mu == 0
104
+ # TODO: convert back to original space
105
+ # max_ovlp = ref_step_max @ step_max
106
+ # min_ovlp = ref_step_min @ step_min
107
+
108
+ # As of Eq. (8a) of [4] max_eigval and min_eigval also
109
+ # correspond to:
110
+ # max_eigval = -forces_trans[max_indices].dot(max_step)
111
+ # min_eigval = -forces_trans[min_indices].dot(min_step)
112
+
113
+ # Create the full PRFO step
114
+ step = np.zeros_like(gradient_trans)
115
+ step[max_indices] = step_max
116
+ step[min_indices] = step_min
117
+ step_norm = np.linalg.norm(step)
118
+ self.log(f"norm(step)={step_norm:.6f}")
119
+
120
+ inside_trust = step_norm <= self.trust_radius
121
+ if inside_trust:
122
+ self.log(
123
+ "Restricted step satisfies trust radius of "
124
+ f"{self.trust_radius:.6f}"
125
+ )
126
+ self.log(
127
+ f"Micro-cycles converged in cycle {mu:02d} with "
128
+ f"alpha={alpha:.6f}!"
129
+ )
130
+ break
131
+
132
+ # Derivative of the squared step w.r.t. alpha
133
+ # max subspace
134
+ dstep2_dalpha_max = (
135
+ 2
136
+ * eigval_max
137
+ / (1 + step_max.dot(step_max) ** 2 * alpha)
138
+ * np.sum(
139
+ gradient_trans[max_indices] ** 2
140
+ / (eigvals[max_indices] - eigval_max * alpha) ** 3
141
+ )
142
+ )
143
+ # min subspace
144
+ dstep2_dalpha_min = (
145
+ 2
146
+ * eigval_min
147
+ / (1 + step_min.dot(step_min) * alpha)
148
+ * np.sum(
149
+ gradient_trans[min_indices] ** 2
150
+ / (eigvals[min_indices] - eigval_min * alpha) ** 3
151
+ )
152
+ )
153
+ dstep2_dalpha = dstep2_dalpha_max + dstep2_dalpha_min
154
+ # Update alpha
155
+ alpha_step = (
156
+ 2 * (self.trust_radius * step_norm - step_norm**2) / dstep2_dalpha
157
+ )
158
+ alpha += alpha_step
159
+
160
+ # Right now the step is still given in the Hessians eigensystem. We
161
+ # transform it back now.
162
+ step += ip_step_trans
163
+ step = eigvecs.dot(step)
164
+ step_norm = np.linalg.norm(step)
165
+
166
+ # With max_micro_cycles = 1 the RS part is disabled and the step
167
+ # probably isn't scaled correctly in the one micro cycle.
168
+ # In this case we use a naive scaling if the step is too big.
169
+ if (self.max_micro_cycles == 1) and (step_norm > self.trust_radius):
170
+ step = step / step_norm * self.trust_radius
171
+ self.log(f"norm(step)={np.linalg.norm(step):.6f}")
172
+
173
+ # Eq. (6) from [4] seems erronous ... the prediction is usually only ~50%
174
+ # of the actual change ...
175
+ # predicted_energy_change = 1/2 * (eigval_max / nu_max**2 + eigval_min / nu_min**2)
176
+ # self.predicted_energy_changes.append(predicted_energy_change)
177
+
178
+ self.predicted_energy_changes.append(self.rfo_model(gradient, self.cur_H, step))
179
+
180
+ self.log("")
181
+ step = self.full_from_active(step)
182
+ return step
@@ -0,0 +1,59 @@
1
+ # [1] https://doi.org/10.1016/0009-2614(91)90115-P
2
+ # Helgaker, 1991
3
+
4
+
5
+ import numpy as np
6
+
7
+ from scipy.optimize import newton
8
+ from pysisyphus.tsoptimizers.TSHessianOptimizer import TSHessianOptimizer
9
+
10
+
11
+ class TRIM(TSHessianOptimizer):
12
+
13
+ def optimize(self):
14
+ energy, gradient, H, eigvals, eigvecs, resetted = self.housekeeping()
15
+ self.update_ts_mode(eigvals, eigvecs)
16
+
17
+ self.log(f"Signs of eigenvalue and -vector of root(s) {self.roots} "
18
+ "will be reversed!")
19
+ # Transform gradient to basis of eigenvectors
20
+ gradient_ = eigvecs.T.dot(gradient)
21
+
22
+ # Construct image function by inverting the signs of the eigenvalue and
23
+ # -vector of the mode to follow uphill.
24
+ eigvals_ = eigvals.copy()
25
+ eigvals_[self.roots] *= -1
26
+ gradient_ = gradient_.copy()
27
+ gradient_[self.roots] *= -1
28
+
29
+ def get_step(mu):
30
+ zetas = -gradient_ / (eigvals_ - mu)
31
+ # Replace nan with 0.
32
+ zetas = np.nan_to_num(zetas)
33
+ # Transform to original basis
34
+ step = eigvecs * zetas
35
+ step = step.sum(axis=1)
36
+ return step
37
+
38
+ def get_step_norm(mu):
39
+ return np.linalg.norm(get_step(mu))
40
+
41
+ def func(mu):
42
+ return get_step_norm(mu) - self.trust_radius
43
+
44
+ mu = 0
45
+ norm0 = get_step_norm(mu)
46
+ if norm0 > self.trust_radius:
47
+ mu, res = newton(func, x0=mu, full_output=True)
48
+ assert res.converged
49
+ self.log(f"Using levelshift of μ={mu:.4f}")
50
+ else:
51
+ self.log("Took pure newton step without levelshift")
52
+
53
+ step = get_step(mu)
54
+ step_norm = np.linalg.norm(step)
55
+ self.log(f"norm(step)={step_norm:.6f}")
56
+
57
+ self.predicted_energy_changes.append(self.quadratic_model(gradient, self.H, step))
58
+
59
+ return step