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,248 @@
1
+ # [1] https://aip.scitation.org/doi/pdf/10.1063/1.4905665?class=pdf
2
+
3
+ import numpy as np
4
+
5
+ from pysisyphus.optimizers.Optimizer import Optimizer
6
+ from pysisyphus.intcoords.setup import get_bond_mat
7
+ from pysisyphus.optimizers.restrict_step import scale_by_max_step
8
+
9
+
10
+ class StabilizedQNMethod(Optimizer):
11
+ def __init__(
12
+ self,
13
+ geometry,
14
+ alpha=0.5,
15
+ alpha_max=1,
16
+ alpha_stretch=0.5,
17
+ alpha_stretch_max=1,
18
+ eps=1e-4,
19
+ hist_max=10,
20
+ E_thresh=1e-6,
21
+ bio=True,
22
+ trust_radius=0.1,
23
+ linesearch=True,
24
+ **kwargs,
25
+ ):
26
+ super().__init__(geometry, **kwargs)
27
+
28
+ self.alpha = alpha
29
+ self.alpha_max = alpha_max
30
+ self.alpha_stretch = alpha_stretch
31
+ self.alpha_stretch_max = alpha_stretch_max
32
+ self.eps = eps
33
+ self.hist_max = int(hist_max)
34
+ self.E_thresh = E_thresh
35
+ self.bio = bio
36
+ self.trust_radius = trust_radius
37
+ self.linesearch = linesearch
38
+
39
+ self.log(
40
+ f"Keeping at most information from {self.hist_max} " "previous cycles."
41
+ )
42
+
43
+ self.alpha_start = self.alpha
44
+ self.alpha_stretch_start = self.alpha_stretch
45
+
46
+ self.gradients_for_precon = list()
47
+ self.coords_for_precon = list()
48
+ self.stretch_proj_signs = list()
49
+
50
+ def prepare_opt(self):
51
+ pass
52
+
53
+ @property
54
+ def n_hist(self):
55
+ return len(self.steps_normed)
56
+
57
+ def bio_mode(self, gradient):
58
+ bond_mat = get_bond_mat(self.geometry)
59
+ atom_num = len(self.geometry.atoms)
60
+ bond_vec_empty = np.zeros((atom_num, 3))
61
+ c3d = self.geometry.coords3d
62
+ bond_vectors = list()
63
+ unique_bonds = set(
64
+ [(min(m, k), max(m, k)) for m, k in zip(*np.where(bond_mat == True))]
65
+ )
66
+ for m, k in unique_bonds:
67
+ bm = bond_vec_empty.copy()
68
+ bm[k] = c3d[k] - c3d[m]
69
+ bm[m] = -bm[k]
70
+ bond_vectors.append(bm)
71
+ # The 3d array is reshaped to 2d, so its last dimension matches
72
+ # the gradient's dimension. LHS and RHS are accessible by simple
73
+ # dot products (see [1] (27)).
74
+ bond_vectors = np.array(bond_vectors).reshape(-1, gradient.size)
75
+ lhs = bond_vectors.dot(gradient)
76
+ self.stretch_proj_signs.append(np.sign(lhs).astype(int))
77
+ # Bond-vector overlap matrix.
78
+ rhs = bond_vectors.dot(bond_vectors.T)
79
+ coeffs = np.linalg.solve(rhs, lhs)
80
+ stretch_gradient = np.einsum("i,ij->j", coeffs, bond_vectors)
81
+ remainder_gradient = gradient - stretch_gradient
82
+ return stretch_gradient, remainder_gradient
83
+
84
+ def adjust_alpha_stretch(self):
85
+ try:
86
+ # -1 when signs changed, 1 when sign is constant
87
+ mult = self.stretch_proj_signs[-1] * self.stretch_proj_signs[-2]
88
+ except IndexError:
89
+ self.log("Can't update alpha_stretch yet!")
90
+ return
91
+ except ValueError:
92
+ self.log(
93
+ "Number of bonds found changed between cycles! Skipping "
94
+ "adjustment of alpha_stretch."
95
+ )
96
+ return
97
+ constant_signs = np.sum(mult == 1)
98
+ fraction = constant_signs / mult.size
99
+ if fraction >= (2 / 3):
100
+ self.alpha_stretch = min(self.alpha_stretch_max, 1.1 * self.alpha_stretch)
101
+ msg = "Increased"
102
+ else:
103
+ self.alpha_stretch *= 1 / 1.1
104
+ msg = "Decreased"
105
+ self.log(f"{msg} alpha_stretch to {self.alpha_stretch:.6f}")
106
+
107
+ def adjust_alpha(self, gradient, precon_gradient):
108
+ # Overlap between full and preconditioned gradient.
109
+ grad_ovlp = (
110
+ gradient.dot(precon_gradient)
111
+ / np.linalg.norm(gradient)
112
+ / np.linalg.norm(precon_gradient)
113
+ )
114
+ if grad_ovlp > 0.2:
115
+ self.alpha = min(self.alpha_max, 1.1 * self.alpha)
116
+ else:
117
+ self.alpha *= 0.85
118
+ self.log(
119
+ "Overlap between full gradient and preconditioned gradient "
120
+ f"is {grad_ovlp:.4f}. New alpha={self.alpha:.4f}."
121
+ )
122
+
123
+ def precondition_gradient(self, gradient, steps, grad_diffs, eps):
124
+ # Construct overlap matrix S between normalized steps
125
+ #
126
+ step_norms = np.linalg.norm(steps, axis=1)
127
+ steps_normed = steps / step_norms[:, None]
128
+ S = np.einsum("ij,jk->ik", steps_normed, steps_normed.T)
129
+ # Determine significant subspace by checking the eigenvalues of
130
+ # the overlap matrix.
131
+ w, v = np.linalg.eigh(S)
132
+ # Significant subspace indices
133
+ significant = (w / w.max()) > eps
134
+ ndim = np.sum(significant)
135
+ self.log(f"ndim = {ndim}")
136
+ # Continue only with eigenvalues and -vectors in the significant
137
+ # subspace.
138
+ eigvals = w[significant]
139
+ eigvecs = v[:, significant]
140
+
141
+ # Transform steps and gradient differences to significant subspace
142
+ norm_fac = 1 / eigvals ** (1 / 2)
143
+ # Eq. (8) in [1]
144
+ steps_normed_sub = norm_fac * np.einsum("ki,kj->ji", eigvecs, steps_normed)
145
+
146
+ # Eq. (11) in [1]
147
+ eigvecs_weighted = eigvecs / np.array(step_norms)[:, None]
148
+ grad_diffs_sub = norm_fac * np.einsum("ki,kj->ji", eigvecs_weighted, grad_diffs)
149
+
150
+ # Assemble approximate hessian
151
+ hess_approx = np.einsum("ij,ik->jk", grad_diffs_sub, steps_normed_sub)
152
+ hess_approx = (hess_approx + hess_approx.T) / 2
153
+ hess_w, hess_v = np.linalg.eigh(hess_approx)
154
+
155
+ # Calculate step directions and gradient difference in the original
156
+ # space. Eq. (15)
157
+ proj_v = np.einsum("ki,jk->ji", hess_v, steps_normed_sub)
158
+ proj_dg = np.einsum("ki,jk->ji", hess_v, grad_diffs_sub)
159
+
160
+ residuals = np.linalg.norm(proj_dg - hess_w * proj_v, axis=0)
161
+ eigvals_mod = np.sqrt(hess_w ** 2 + residuals ** 2)
162
+
163
+ # precon_grad = np.einsum("i,j,ij,ij->i", cur_grad, 1/eigvals_mod, proj_v, proj_v)
164
+ precon_grad = np.einsum(
165
+ "i,j,ij,ij->i", gradient, 1 / eigvals_mod, proj_v, proj_v
166
+ )
167
+
168
+ projector = proj_v.dot(proj_v.T)
169
+ perp_projector = np.eye(gradient.size) - projector
170
+ perp_grad = perp_projector.dot(gradient)
171
+ # Alternative formulation
172
+ # perp_grad_ = gradient - (proj_v.T.dot(gradient) * proj_v).sum(axis=1)
173
+ # np.testing.assert_allclose(perp_grad_, perp_grad, atol=1e-16)
174
+
175
+ self.adjust_alpha(gradient, precon_grad)
176
+ tot_precon_gradient = precon_grad + self.alpha * perp_grad
177
+ return tot_precon_gradient
178
+
179
+ def optimize(self):
180
+ gradient = self.geometry.gradient
181
+ energy = self.geometry.energy
182
+ self.forces.append(-gradient)
183
+ self.energies.append(energy)
184
+ self.log(f"norm(forces)={np.linalg.norm(gradient):.4e}")
185
+
186
+ if self.bio:
187
+ stretch_gradient, remainder_gradient = self.bio_mode(gradient)
188
+ self.adjust_alpha_stretch()
189
+ # Steepest descent against the stretch_gradient
190
+ stretch_step = -self.alpha_stretch * stretch_gradient
191
+ new_coords = self.geometry.coords + stretch_step
192
+ self.geometry.coords = new_coords
193
+ # Use only the remaining gradient for the rest of this method
194
+ gradient = remainder_gradient
195
+
196
+ self.gradients_for_precon.append(gradient)
197
+ self.coords_for_precon.append(self.geometry.coords.copy())
198
+
199
+ if len(self.coords_for_precon) > 2:
200
+ steps = np.diff(self.coords_for_precon, axis=0)[-self.hist_max :]
201
+ grad_diffs = np.diff(self.gradients_for_precon, axis=0)[-self.hist_max :]
202
+
203
+ self.log(
204
+ "Preconditioning gradient with information from "
205
+ f"{len(steps)+1} previous cycles."
206
+ )
207
+ precon_grad = self.precondition_gradient(
208
+ gradient, steps, grad_diffs, self.eps
209
+ )
210
+ step = -precon_grad
211
+ else:
212
+ self.log("Took pure steepest descent step.")
213
+ step = self.alpha * -gradient
214
+ scale_by_max_step(step, self.trust_radius)
215
+
216
+ if self.linesearch:
217
+ # Calculate energy at new geometry
218
+ new_coords = self.geometry.coords + step
219
+ _ = self.geometry.get_energy_and_forces_at(new_coords)
220
+ new_energy = _["energy"]
221
+ delta_energy = new_energy - energy
222
+ self.log(
223
+ f"Current energy is {energy:.6f} au. New energy is "
224
+ f"{new_energy:.6f} au, ΔE={delta_energy:.6f} au."
225
+ )
226
+
227
+ energy_rise_too_big = new_energy > (energy + self.E_thresh)
228
+ alpha_still_big_enough = self.alpha > (self.alpha_start / 10)
229
+ alpha_stre_still_big_enough = self.alpha_stretch > (
230
+ self.alpha_stretch_start / 10
231
+ )
232
+ if (
233
+ energy_rise_too_big
234
+ and alpha_still_big_enough
235
+ and alpha_stre_still_big_enough
236
+ ):
237
+ self.log(f"Energy increased by {delta_energy:.6f} au")
238
+ self.gradients_for_precon = self.gradients_for_precon[-2:-1]
239
+ self.coords_for_precon = self.coords_for_precon[-2:-1]
240
+ self.log("Resetted history.")
241
+ self.alpha /= 2
242
+ self.alpha_stretch /= 2
243
+
244
+ self.log(f"Decreased alpha to {self.alpha}")
245
+ self.log("Reverting bad step")
246
+ return None
247
+
248
+ return step
@@ -0,0 +1,23 @@
1
+ from pysisyphus.optimizers.BacktrackingOptimizer import BacktrackingOptimizer
2
+
3
+
4
+ class SteepestDescent(BacktrackingOptimizer):
5
+ def __init__(self, geometry, alpha=0.1, **kwargs):
6
+ super().__init__(geometry, alpha=alpha, **kwargs)
7
+
8
+ def prepare_opt(self):
9
+ self.log("no backtracking in cycle 0")
10
+
11
+ def optimize(self):
12
+ if self.is_cos and self.align:
13
+ self.procrustes()
14
+
15
+ self.forces.append(self.geometry.forces)
16
+ self.energies.append(self.geometry.energy)
17
+
18
+ if self.cur_cycle > 0:
19
+ self.skip = self.backtrack(self.forces[-1], self.forces[-2])
20
+
21
+ step = self.alpha * self.forces[-1]
22
+ step = self.scale_by_max_step(step)
23
+ return step
@@ -0,0 +1,173 @@
1
+ # [1] https://aip.scitation.org/doi/abs/10.1063/1.3664901
2
+ # Behn, 2011, Freezing string method
3
+ # [2] https://aip.scitation.org/doi/pdf/10.1063/1.4804162
4
+ # Zimmerman, 2013, Growing string with interpolation and optimization
5
+ # in internal coordiantes
6
+
7
+ import numpy as np
8
+
9
+ from pysisyphus.optimizers.hessian_updates import double_damp
10
+ from pysisyphus.optimizers.closures import bfgs_multiply
11
+ from pysisyphus.optimizers.Optimizer import Optimizer
12
+ from pysisyphus.optimizers.restrict_step import scale_by_max_step
13
+
14
+
15
+ class StringOptimizer(Optimizer):
16
+ def __init__(
17
+ self,
18
+ geometry,
19
+ max_step=0.1,
20
+ stop_in_when_full=-1,
21
+ keep_last=10,
22
+ lbfgs_when_full=True,
23
+ gamma_mult=False,
24
+ double_damp=True,
25
+ scale_step="global",
26
+ **kwargs,
27
+ ):
28
+ super().__init__(geometry, max_step=max_step, **kwargs)
29
+
30
+ assert (
31
+ self.is_cos
32
+ ), "StringOptimizer is only intended to be used with COS objects."
33
+
34
+ self.stop_in_when_full = int(stop_in_when_full)
35
+ self.keep_last = int(keep_last)
36
+ assert self.keep_last >= 0
37
+ self.lbfgs_when_full = lbfgs_when_full
38
+ if self.lbfgs_when_full and (self.keep_last == 0):
39
+ print("lbfgs_when_full is True, but keep_last is 0!")
40
+ self.gamma_mult = bool(gamma_mult)
41
+ self.double_damp = bool(double_damp)
42
+ self.scale_step = scale_step
43
+ assert self.scale_step in ("global", "per_image")
44
+
45
+ # Add one as we later subtract 1 before we check if this value is 0.
46
+ self.stop_in = self.stop_in_when_full + 1
47
+ self.is_cart_opt = self.geometry.coord_type == "cart"
48
+ self.s_list = list()
49
+ self.y_list = list()
50
+ self.inds = list()
51
+
52
+ def prepare_opt(self):
53
+ if self.align and self.is_cart_opt:
54
+ self.procrustes()
55
+
56
+ def reset(self):
57
+ pass
58
+
59
+ def restrict_step_components(self, steps):
60
+ too_big = np.abs(steps) > self.max_step
61
+ self.log(f"Found {np.sum(too_big)} big step components.")
62
+ signs = np.sign(steps[too_big])
63
+ steps[too_big] = signs * self.max_step
64
+ return steps
65
+
66
+ def check_convergence(self, *args, **kwargs):
67
+ # Normal convergence check with gradients etc.
68
+ converged, conv_info = super().check_convergence(*args, **kwargs)
69
+
70
+ if self.geometry.fully_grown:
71
+ # We only start decrementing the counter after the string is fully grown.
72
+ self.stop_in -= 1
73
+ # Don't print this message if stop_in was disabled in the first place (< 0).
74
+ if self.stop_in >= 0:
75
+ self.log(f"String is fully grown. Stopping in {self.stop_in} cycle(s).")
76
+
77
+ fully_grown = self.geometry.fully_grown
78
+ full_stop = fully_grown and (self.stop_in == 0)
79
+ # full_stop will take precedence when True.
80
+ return full_stop or (fully_grown and converged), conv_info
81
+
82
+ def optimize(self):
83
+ new_image_inds = self.geometry.new_image_inds
84
+ string_size_changed = len(new_image_inds) > 0
85
+
86
+ if self.align and string_size_changed and self.is_cart_opt:
87
+ self.procrustes()
88
+ self.log("Aligned string.")
89
+
90
+ forces = self.geometry.forces
91
+ self.energies.append(self.geometry.energy)
92
+ self.forces.append(forces)
93
+
94
+ cur_size = self.geometry.string_size
95
+ add_to_list = (
96
+ self.keep_last > 0 # Only add to s_list and y_list if we want to keep
97
+ and self.cur_cycle
98
+ > 0 # cycles and if we can actually calculate differences.
99
+ and (
100
+ not self.lbfgs_when_full # Add when LBFGS is allowed before fully grown.
101
+ or self.lbfgs_when_full
102
+ and self.geometry.fully_grown
103
+ and not string_size_changed # Don't add when string has to be fully grown
104
+ # but grew fully in this cycle.
105
+ )
106
+ )
107
+ if add_to_list:
108
+ inds = list(range(cur_size))
109
+ try:
110
+ y = self.forces[-2] - forces
111
+ s = self.coords[-1] - self.coords[-2]
112
+ # Will be raised when the string grew in the previous cycle.
113
+ except ValueError:
114
+ cur_forces = np.delete(
115
+ forces.reshape(cur_size, -1), new_image_inds, axis=0
116
+ ).flatten()
117
+ y = self.forces[-2] - cur_forces
118
+ cur_coords = np.delete(
119
+ self.coords[-1].reshape(cur_size, -1), new_image_inds, axis=0
120
+ ).flatten()
121
+ s = self.coords[-2] - cur_coords
122
+ inds = np.delete(inds, new_image_inds)
123
+
124
+ if self.double_damp:
125
+ s, y = double_damp(s, y, s_list=self.s_list, y_list=self.y_list)
126
+
127
+ self.s_list.append(s)
128
+ self.y_list.append(y)
129
+ self.inds.append(inds)
130
+ # Drop oldest vectors
131
+ self.s_list = self.s_list[-self.keep_last :]
132
+ self.y_list = self.y_list[-self.keep_last :]
133
+ self.inds = self.inds[-self.keep_last :]
134
+
135
+ # Results in steepest descent step for empty s_list & y_list
136
+ step = bfgs_multiply(
137
+ self.s_list,
138
+ self.y_list,
139
+ forces,
140
+ gamma_mult=self.gamma_mult,
141
+ inds=self.inds,
142
+ cur_size=cur_size,
143
+ logger=self.logger,
144
+ )
145
+
146
+ # When LBFGS is not yet enabled then s_list and y_list will
147
+ # be empty and the step from bfgs_multiply will be a simple SD step.
148
+ # We try to calculated an improved step it via conjugate gradient.
149
+ previous_step_with_same_size = (self.cur_cycle > 0) and (
150
+ not string_size_changed
151
+ )
152
+ lbfgs_lists_empty = (len(self.s_list) == 0) and (len(self.y_list) == 0)
153
+ if previous_step_with_same_size and lbfgs_lists_empty:
154
+ prev_forces = self.forces[-2]
155
+ # Fletcher-Reeves
156
+ kind = "Fletcher-Reeves"
157
+ beta = forces.dot(forces) / prev_forces.dot(prev_forces)
158
+ # Polak-Ribiere
159
+ # kind = "Polak-Ribiere"
160
+ # beta = forces.dot(forces - prev_forces) / prev_forces.dot(prev_forces)
161
+ beta = min(beta, 1)
162
+ step = forces + beta * self.steps[-1]
163
+ self.log(f"{kind} conjugate gradient correction, β={beta:.6f}")
164
+
165
+ if self.scale_step == "global":
166
+ step = scale_by_max_step(step, self.max_step)
167
+ elif self.scale_step == "per_image":
168
+ for image_step in step.reshape(len(self.geometry.images), -1):
169
+ scale_by_max_step(image_step, self.max_step)
170
+ else:
171
+ raise Exception("Invalid scale_step={self.scale_step}!")
172
+
173
+ return step
@@ -0,0 +1,41 @@
1
+ import logging
2
+
3
+ __all__ = [
4
+ "BFGS",
5
+ "ConjugateGradient",
6
+ "CubicNewton",
7
+ "FIRE",
8
+ "LayerOpt",
9
+ "LBFGS",
10
+ "MicroOptimizer",
11
+ "NCOptimizer",
12
+ "PreconLBFGS",
13
+ "PreconSteepestDescent",
14
+ "QuickMin",
15
+ "RFOptimizer",
16
+ "SteepestDescent",
17
+ "StringOptimizer",
18
+ "StabilizedQNMethod",
19
+ ]
20
+
21
+ from pysisyphus.optimizers.CubicNewton import CubicNewton
22
+ from pysisyphus.optimizers.MicroOptimizer import MicroOptimizer
23
+
24
+ logger = logging.getLogger("optimizer")
25
+ logger.setLevel(logging.DEBUG)
26
+ # delay = True prevents creation of empty logfiles
27
+ handler = logging.FileHandler("optimizer.log", mode="w", delay=True)
28
+ # fmt_str = "%(asctime)s - %(name)s - %(levelname)s - %(message)s"
29
+ fmt_str = "%(message)s"
30
+ formatter = logging.Formatter(fmt_str)
31
+ handler.setFormatter(formatter)
32
+ logger.addHandler(handler)
33
+
34
+ # logger = logging.getLogger("gdiis")
35
+ # logger.setLevel(logging.DEBUG)
36
+ # # delay = True prevents creation of empty logfiles
37
+ # handler = logging.FileHandler("gdiis.log", mode="w", delay=True)
38
+ # fmt_str = "%(message)s"
39
+ # formatter = logging.Formatter(fmt_str)
40
+ # handler.setFormatter(formatter)
41
+ # logger.addHandler(handler)