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,187 @@
1
+ from math import cos, sin
2
+
3
+ import numpy as np
4
+ from scipy.optimize import newton
5
+
6
+ from pysisyphus.irc.IRC import IRC
7
+ from pysisyphus.optimizers.hessian_updates import bfgs_update
8
+ from pysisyphus.TableFormatter import TableFormatter
9
+
10
+
11
+ # [1] An improved algorithm for reaction path following
12
+ # http://aip.scitation.org/doi/pdf/10.1063/1.456010
13
+ # [2] Extension to internal coordinates (not implemented)
14
+ # https://pubs.acs.org/doi/pdf/10.1021/j100377a021
15
+
16
+
17
+ class GonzalezSchlegel(IRC):
18
+ def __init__(
19
+ self,
20
+ geometry,
21
+ max_micro_cycles=20,
22
+ micro_step_thresh=1e-3,
23
+ hessian_recalc=None,
24
+ line_search=False,
25
+ **kwargs,
26
+ ):
27
+ super().__init__(geometry, **kwargs)
28
+
29
+ self.max_micro_cycles = max_micro_cycles
30
+ self.micro_step_thresh = micro_step_thresh
31
+ self.hessian_recalc = hessian_recalc
32
+ self.line_search = line_search
33
+ if self.line_search:
34
+ print("!Line search seems faulty right now!")
35
+
36
+ self.pivot_coords = list()
37
+ self.eye = np.eye(self.geometry.coords.size)
38
+ self.micro_counter = 0
39
+
40
+ micro_header = "# |dx| |tangent|".split()
41
+ micro_fmts = ["d", ".2E", ".3E"]
42
+ self.micro_formatter = TableFormatter(micro_header, micro_fmts, 10)
43
+
44
+ def perp_component(self, vec, perp_to):
45
+ # Make unit vector
46
+ # perp_to /= np.linalg.norm(perp_to)
47
+ # Substract parallel component
48
+ return vec - perp_to.dot(vec) * perp_to / perp_to.dot(perp_to)#np.linalg.norm(perp_to)**2
49
+
50
+ def micro_step(self, counter):
51
+ """Constrained optimization on a hypersphere."""
52
+
53
+ # Calculate gradient at current coordinates
54
+ gradient = self.mw_gradient
55
+ self.log(f"\tnorm(mw_grad)={np.linalg.norm(gradient):.6f}")
56
+
57
+ # Interpolation proposed in the paper (Eq. (12) - (15)).
58
+ # Does not seem to help.
59
+ if self.line_search and (counter > 0):
60
+ pivot_coords = self.pivot_coords[-1]
61
+ p_prev = self.prev_coords - pivot_coords # p"
62
+ p_cur = self.mw_coords - pivot_coords # p'
63
+ g_prev = self.prev_grad # g"
64
+ g_cur = self.gradient # g'
65
+ g_prev_p = self.perp_component(g_prev, p_prev)
66
+ g_cur_p = self.perp_component(g_cur, p_cur)
67
+ g_prev_p_norm = np.linalg.norm(g_prev_p)
68
+ g_cur_p_norm = np.linalg.norm(g_cur_p)
69
+ # Angle between p_prev and p_cur
70
+ theta_prime = np.arccos(
71
+ p_prev.dot(p_cur) / np.linalg.norm(p_prev) / np.linalg.norm(p_cur)
72
+ ) # θ'
73
+ theta = g_prev_p_norm * theta_prime / (g_prev_p_norm - g_cur_p_norm) # θ
74
+ theta_quot = theta / theta_prime
75
+ cos_theta = cos(theta)
76
+ sin_theta = sin(theta)
77
+ cos_theta_prime = cos(theta_prime)
78
+ sin_theta_prime = sin(theta_prime)
79
+ sin_quot = sin_theta / sin_theta_prime
80
+ # Interpolated quantities
81
+ g_interp = g_prev * (1 - theta_quot) + g_cur * theta_quot
82
+ p_interp = (
83
+ p_prev * (cos_theta - sin_quot * cos_theta_prime) + p_cur * sin_quot
84
+ )
85
+ x_interp = pivot_coords + p_interp
86
+ gradient = g_interp
87
+ self.mw_coords = x_interp
88
+ self.displacement = p_interp
89
+
90
+ gradient_diff = gradient - self.prev_grad
91
+ coords_diff = self.mw_coords - self.prev_coords
92
+ # Update previous quantities.
93
+ self.prev_coords = self.mw_coords.copy()
94
+ self.prev_grad = gradient.copy()
95
+
96
+ # Recalculate Hessian
97
+ if (
98
+ self.hessian_recalc
99
+ # and (self.micro_counter > 0)
100
+ and (self.micro_counter % self.hessian_recalc == 0)
101
+ ):
102
+ self.mw_hessian = self.geometry.mw_hessian
103
+ # Or update Hessian
104
+ else:
105
+ dH, _ = bfgs_update(self.mw_hessian, coords_diff, gradient_diff)
106
+ self.mw_hessian += dH
107
+ eigvals, eigvecs = np.linalg.eigh(self.mw_hessian)
108
+
109
+ constraint = (0.5 * self.step_length) ** 2
110
+ big = np.abs(eigvals) > 1e-8
111
+ big_eigvals = eigvals[big]
112
+ big_eigvecs = eigvecs[:, big]
113
+ grad_star = big_eigvecs.T.dot(gradient)
114
+ displ_star = big_eigvecs.T.dot(self.displacement)
115
+
116
+ def get_dx(lambda_):
117
+ """In basis of Hessian eigenvectors."""
118
+ return -(grad_star - lambda_ * displ_star) / (big_eigvals - lambda_)
119
+
120
+ def on_sphere(lambda_):
121
+ p = displ_star + get_dx(lambda_)
122
+ return p.dot(p) - constraint
123
+
124
+ # Initial guess for λ.
125
+ # λ must be smaller then the smallest eigenvector
126
+ lambda_0 = big_eigvals[0]
127
+ lambda_0 *= 1.5 if (lambda_0 < 0) else 0.5
128
+ self.log(f"\tSmallest eigenvalue is {big_eigvals[0]:.4f}, λ_0={lambda_0:.4f}.")
129
+ # Find the root with scipy
130
+ lambda_ = newton(on_sphere, lambda_0, maxiter=500)
131
+ self.log(f"\tDetermined λ={lambda_0:.4f} from Newtons method.")
132
+
133
+ # Calculate dx from optimized lambda in basis of Hessian eigenvectors and
134
+ # transform back to mass-weighted Cartesians.
135
+ dx = big_eigvecs.dot(get_dx(lambda_))
136
+ self.displacement += dx
137
+ self.mw_coords += dx
138
+
139
+ grad_tangent_to_sphere = self.perp_component(gradient, self.displacement)
140
+ self.micro_counter += 1
141
+
142
+ dx_norm = np.linalg.norm(dx)
143
+ grad_norm = np.linalg.norm(grad_tangent_to_sphere)
144
+ self.log(f"\tnorm(dx)={dx_norm:.6f}")
145
+ self.log(f"\tgradient tangent to sphere={grad_norm:.6f}")
146
+
147
+ return dx, grad_tangent_to_sphere
148
+
149
+ def step(self):
150
+ grad0 = self.mw_gradient
151
+ grad0_norm = np.linalg.norm(grad0)
152
+ # For the BFGS update in the first micro step we use the original
153
+ # point and the initial guess to calculate gradient and
154
+ # coordinate differences.
155
+ self.prev_grad = grad0
156
+ self.prev_coords = self.mw_coords
157
+
158
+ # Take a step against the gradient to the pivot point x*_k+1.
159
+ pivot_step = 0.5 * self.step_length * -grad0 / grad0_norm
160
+ pivot_coords = self.mw_coords + pivot_step
161
+ self.pivot_coords.append(pivot_coords)
162
+
163
+ # Initial guess for x'_k+1 (full step from prev_coords, or another
164
+ # half step from the pivot point)
165
+ self.mw_coords = pivot_coords + pivot_step
166
+
167
+ # Initial displacement p' from the pivot point
168
+ self.displacement = pivot_step
169
+
170
+ micro_coords_ = list()
171
+ for i in range(self.max_micro_cycles):
172
+ self.log(f"Micro cycle {i:02d}")
173
+ try:
174
+ dx, _ = self.micro_step(i)
175
+ except RuntimeError:
176
+ print("Constrained search did not converge!")
177
+ self.converged = True
178
+ return
179
+ micro_coords_.append(self.mw_coords)
180
+ if np.linalg.norm(dx) <= self.micro_step_thresh:
181
+ break
182
+ else:
183
+ self.logger.warning("Max micro cycles exceeded!")
184
+
185
+
186
+ def postprocess(self):
187
+ self.pivot_coords = np.array(self.pivot_coords)
@@ -0,0 +1,164 @@
1
+ import numpy as np
2
+
3
+ from pysisyphus.irc.IRC import IRC
4
+
5
+
6
+ # [1] http://pubs.acs.org/doi/pdf/10.1021/ja00295a002
7
+ # [2] https://math.stackexchange.com/questions/1882772/curve-fitting-with-derivatives
8
+
9
+
10
+ class IMKMod(IRC):
11
+
12
+ def __init__(self, geometry, corr_first=True, corr_first_size=0.5,
13
+ corr_first_energy=True, corr_bisec_size=0.0025,
14
+ corr_bisec_energy=True, **kwargs):
15
+ super().__init__(geometry, **kwargs)
16
+
17
+ # Correction of pivot point
18
+ self.corr_first = bool(corr_first)
19
+ self.corr_first_size = float(corr_first_size)
20
+ self.corr_first_energy = bool(corr_first_energy)
21
+ # Correction along bisector
22
+ self.corr_bisec_size = corr_bisec_size
23
+ self.corr_bisec_energy = corr_bisec_energy
24
+
25
+ self.corr_bisec_thresh = 2*self.corr_bisec_size
26
+
27
+ def fit_parabola(self, x, y):
28
+ y_str = np.array2string(np.array(y), precision=6)
29
+ self.log(f"Fitting parabola with x={x} and y={y_str}")
30
+ fit = np.polyfit(x, y, deg=2)
31
+ parabola = np.poly1d(fit)
32
+ minimum = parabola.deriv().r
33
+ # We are only looking for a real minimum
34
+ real_minimum = (minimum[minimum.imag==0].real)[0]
35
+ self.log(f"Found minimum of fitted parabola at x={real_minimum:.4f}")
36
+
37
+ return real_minimum
38
+
39
+ def fit_grad_and_energies(self, energy0, grad0, energy1, direction):
40
+ grad0_proj = grad0.dot(direction/np.linalg.norm(direction))
41
+ # f (x) = ax² + bx + c
42
+ # f'(x) = 2ax + b
43
+ #
44
+ # Assuming energy0 and grad0 are calculated at x=0
45
+ # and
46
+ # energy is calculated at x=1
47
+ c = energy0
48
+ b = grad0_proj
49
+ a = energy1 - b - c
50
+ coeffs = (a, b, c)
51
+ poly = np.poly1d(coeffs)
52
+ minimum = poly.deriv().r
53
+ # We are only looking for a real minimum
54
+ real_minimum = (minimum[minimum.imag==0].real)[0]
55
+ self.log(f"Found minimum of fitted parabola at x={real_minimum:.4f}")
56
+
57
+ return real_minimum
58
+
59
+ def step(self):
60
+ # Get gradient at Q0
61
+ mw_coords_0 = self.mw_coords.copy()
62
+ grad_0 = self.mw_gradient
63
+ energy_0 = self.energy
64
+ self.log(f"Current point:\n\tenergy_0={energy_0:.6f} au")
65
+
66
+
67
+ ##############
68
+ # PIVOT STEP #
69
+ ##############
70
+
71
+ grad_0_norm = np.linalg.norm(grad_0)
72
+ dir_0 = -grad_0 / grad_0_norm
73
+ # Step direction is against the gradient to the pivot point Q1.
74
+ step = self.step_length * dir_0
75
+ mw_coords_1 = self.mw_coords + step
76
+ self.log(f"Took initial step of length {self.step_length:.6f} to pivot point")
77
+ self.mw_coords = mw_coords_1
78
+ energy_1 = self.energy
79
+
80
+ #########################
81
+ # PIVOT STEP CORRECTION #
82
+ #########################
83
+
84
+ self.log(f"Pivot point\n\tenergy_1={energy_1:.6f} au")
85
+ energy_diff = energy_1 - energy_0
86
+ if energy_diff > 0:
87
+ self.log(f"Energy increased at pivot point ΔE={energy_diff:.6f}")
88
+ correct_first_step = self.corr_first and (energy_diff > 0)
89
+ # Fit using energy at q0, energy at q1, and energy at half step between
90
+ # q0 and q1
91
+ corr_min = None
92
+ if correct_first_step and self.corr_first_energy:
93
+ self.log("Computing correction for pivot point from energy_0, "
94
+ "energy_1, and additional energy calculation.")
95
+ corr_step = self.corr_first_size*step
96
+ mw_coords_1_corr = mw_coords_0 + corr_step
97
+ self.mw_coords = mw_coords_1_corr
98
+ energy_1_corr = self.energy
99
+ x_corr = np.array((0, self.corr_first_size, 1))
100
+ y_corr = (energy_0, energy_1_corr, energy_1)
101
+ corr_min = self.fit_parabola(x_corr, y_corr)
102
+ # Fit using energy & gradient at q0, and energy at q1
103
+ elif correct_first_step:
104
+ self.log("Computing correction for pivot point from energy_0, "
105
+ "grad_0 and energy_1, along dir_0")
106
+
107
+ corr_min = self.fit_grad_and_energies(energy_0, grad_0, energy_1, dir_0)
108
+ else:
109
+ self.log("Skipping correction of pivot step")
110
+
111
+ if corr_min:
112
+ step_corr = corr_min * self.step_length * dir_0
113
+ mw_coords_1 = mw_coords_0 + step_corr
114
+ self.mw_coords = mw_coords_1
115
+
116
+ # Get gradient at Q1
117
+ self.log("Calculation of gradient at pivot point")
118
+ grad_1 = self.mw_gradient
119
+ energy_1 = self.energy
120
+ grad_1_norm = np.linalg.norm(grad_1)
121
+ dir_1 = -grad_1 / grad_1_norm
122
+
123
+ ##############
124
+ # BISECTOR D #
125
+ ##############
126
+
127
+ # Determine bisector d and normalized bisector vector D.
128
+ # d = grad_0/grad_0_norm - grad_1/grad_1_norm
129
+ d = -dir_0 + dir_1
130
+ D = d / np.linalg.norm(d)
131
+ self.log("Determined bisector D")
132
+
133
+ ##########################
134
+ # MINIMUM SEARCH ALONG D #
135
+ ##########################
136
+
137
+ # Take a step along D
138
+ step_2 = self.corr_bisec_size * D
139
+ mw_coords_2 = mw_coords_1 + step_2
140
+ self.mw_coords = mw_coords_2
141
+ energy_2 = self.energy
142
+ self.log(f"1st step along D\n\tenergy_2={energy_2:.6f} au")
143
+
144
+ if self.corr_bisec_energy:
145
+ if energy_2 > energy_1:
146
+ factor = 0.5
147
+ else:
148
+ factor = 2
149
+ step_3 = self.corr_bisec_size * factor * D
150
+ mw_coords_3 = mw_coords_1 + step_3
151
+ self.mw_coords = mw_coords_3
152
+ energy_3 = self.energy
153
+ self.log(f"2nd step along D\n\tenergy_3={energy_3:.6f} au")
154
+ x = np.array((0, 1, factor))
155
+ y = (energy_1, energy_2, energy_3)
156
+ corr_min = self.fit_parabola(x, y)
157
+ else:
158
+ self.log("Minimum search along D, by fitting energy_1, "
159
+ "grad_1 and energy_2.")
160
+ corr_min = self.fit_grad_and_energies(energy_1, grad_1, energy_2, D)
161
+
162
+ step_corr = self.corr_bisec_size * corr_min * D
163
+ mw_coords_4 = mw_coords_1 + step_corr
164
+ self.mw_coords = mw_coords_4