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,10 @@
1
+ from dataclasses import dataclass
2
+
3
+
4
+ @dataclass
5
+ class IRCDummy:
6
+ all_coords: list
7
+ atoms: tuple
8
+ forward: bool = True
9
+ backward: bool = True
10
+ downhill: bool = False
@@ -0,0 +1,307 @@
1
+ # [1] https://doi.org/10.1021/acs.jctc.8b00068
2
+ # Dual-Level Approach to Instanton Theory
3
+ # Meisner, Kästner 2018
4
+ # [2] https://doi.org/10.1021/ct100658y
5
+ # Locating Instantons in Many Degrees of Freedom
6
+ # Rommel, Goumans, Kästner, 2011
7
+ # [3] https://aip.scitation.org/doi/full/10.1063/1.4932362
8
+ # Ring-polymer instanton theory of electron transofer in the
9
+ # nonadiabatic limit
10
+ # Richardson, 2015
11
+ import logging
12
+
13
+ import numpy as np
14
+ import scipy as sp
15
+
16
+ from pysisyphus import logger as pysis_logger
17
+ from pysisyphus.Geometry import Geometry
18
+ from pysisyphus.helpers import align_coords, get_coords_diffs
19
+ from pysisyphus.helpers_pure import eigval_to_wavenumber
20
+
21
+ import torch
22
+
23
+ def T_crossover_from_eigval(eigval):
24
+ nu = eigval_to_wavenumber(eigval) # in cm⁻¹
25
+ nu_m = 100 * abs(nu) # in m⁻¹
26
+ freq = nu_m * sp.constants.speed_of_light
27
+ # In papers the crossover temperature is usually defined with the angular
28
+ # frequency nu*2*pi. When using the "normal" frequency we don't have to
29
+ # divide by 2*pi. Both approaches obviously yield the same T_c.
30
+ # ang_freq = freq * 2 * np.pi
31
+ # T_c_ = sp.constants.hbar * ang_freq / (sp.constants.Boltzmann * 2 * np.pi)
32
+ T_c = sp.constants.hbar * freq / (sp.constants.Boltzmann)
33
+ return T_c
34
+
35
+
36
+ def T_crossover_from_ts(ts_geom):
37
+ mw_hessian = ts_geom.mw_hessian
38
+ proj_hessian = ts_geom.eckart_projection(mw_hessian, full=True)
39
+
40
+ if isinstance(proj_hessian, torch.Tensor):
41
+ eigvals, eigvecs = torch.linalg.eigh(proj_hessian)
42
+ eigvals = eigvals.to(torch.double).cpu().numpy()
43
+ else:
44
+ eigvals, eigvecs = np.linalg.eigh(proj_hessian)
45
+
46
+ T_c = T_crossover_from_eigval(eigvals[0])
47
+ return T_c
48
+
49
+
50
+ logger = pysis_logger.getChild("instanton")
51
+ logger.setLevel(logging.DEBUG)
52
+ file_handler = logging.FileHandler("instanton.log", mode="w", delay=True)
53
+ logger.addHandler(file_handler)
54
+
55
+
56
+ def log_progress(val, key, i):
57
+ logger.debug(f"Calculated {key} at image {i}")
58
+ return val
59
+
60
+
61
+ class Instanton:
62
+ def __init__(self, images, calc_getter, T):
63
+ self.images = images
64
+ self.calc_getter = calc_getter
65
+ for image in self.images:
66
+ image.set_calculator(calc_getter())
67
+ self.T = T
68
+
69
+ # Pre-calculate action prefactors for the given temperature
70
+ beta = 1 / (sp.constants.Boltzmann * self.T) # Joule
71
+ beta_hbar = beta * sp.constants.hbar # seconds
72
+ beta_hbar_fs = beta_hbar * 1e15 # fs
73
+ self.beta_hbar = beta_hbar_fs
74
+ self.P_over_beta_hbar = self.P / self.beta_hbar
75
+ self.P_bh = self.P_over_beta_hbar
76
+ """The Instanton is periodic: the first image is connected to the
77
+ last image.
78
+ At k=0 the index k-1 will be -1, which points to the last image.
79
+
80
+ Below we pre-calculate some indices (assuming N images).
81
+ unshifted indices ks: k = {0, 1, .. , N-1}
82
+ shifted indices ksm1: k-1 = {-1, 0, 1, .. , N-2}
83
+ shifted indices ksp1: k+1 = {1, 2, .. , N-1, 0}
84
+ """
85
+ self.ks = np.arange(self.P)
86
+ self.ksm1 = self.ks - 1
87
+ self.ksp1 = self.ks + 1
88
+ self.ksp1[-1] = 0 # k+1 for the last image points to the first image
89
+
90
+ self.coord_type = "mwcartesian"
91
+ self.internal = None
92
+
93
+ @property
94
+ def P(self):
95
+ return len(self.images)
96
+
97
+ @classmethod
98
+ def from_ts(cls, ts_geom, P, dr=0.4, delta_T=25, cart_hessian=None, **kwargs):
99
+ assert ts_geom.coord_type == "mwcartesian"
100
+ atoms = ts_geom.atoms
101
+ ts_coords = ts_geom.coords
102
+
103
+ if cart_hessian is None:
104
+ mw_hessian = ts_geom.mw_hessian
105
+ else:
106
+ mw_hessian = ts_geom.mass_weigh_hessian(cart_hessian)
107
+
108
+ proj_hessian = ts_geom.eckart_projection(mw_hessian, full=True)
109
+
110
+ if isinstance(proj_hessian, torch.Tensor):
111
+ eigvals, eigvecs = torch.linalg.eigh(proj_hessian)
112
+ eigvals = eigvals.to(torch.double).cpu().numpy()
113
+ eigvecs = eigvecs.to(torch.double).cpu().numpy()
114
+ else:
115
+ eigvals, eigvecs = np.linalg.eigh(proj_hessian)
116
+
117
+ # Use crossover temperature with a little offset (delta_T) if no T is given.
118
+ try:
119
+ kwargs["T"]
120
+ except KeyError:
121
+ T_c = T_crossover_from_eigval(eigvals[0])
122
+ kwargs["T"] = T_c - delta_T
123
+ imag_mode = eigvecs[:, 0]
124
+ cosines = np.cos((np.arange(P) + 1 - 0.5) / P * np.pi)
125
+ image_mw_coords = ts_coords + dr * cosines[:, None] * imag_mode
126
+ image_coords = image_mw_coords / np.sqrt(ts_geom.masses_rep)
127
+ if not ts_geom.is_analytical_2d:
128
+ align_coords(image_coords)
129
+ images = [
130
+ Geometry(atoms, coords, coord_type="mwcartesian") for coords in image_coords
131
+ ]
132
+ instanton = Instanton(images, **kwargs)
133
+ return instanton
134
+
135
+ @classmethod
136
+ def from_instanton(cls, other, **kwargs):
137
+ images = other.images
138
+ instanton = Instanton(images, **kwargs)
139
+ return instanton
140
+
141
+ def as_xyz(self):
142
+ return "\n".join([geom.as_xyz() for geom in self.images])
143
+
144
+ @property
145
+ def coords(self):
146
+ return np.ravel([image.coords for image in self.images])
147
+
148
+ @coords.setter
149
+ def coords(self, coords):
150
+ coords = coords.reshape(len(self.images), -1)
151
+ for img_coords, image in zip(coords, self.images):
152
+ image.coords = img_coords
153
+
154
+ def action(self):
155
+ """Action in au / fs, Hartree per femtosecond."""
156
+ all_coords = np.array([image.coords for image in self.images])
157
+ diffs = all_coords[self.ks] - all_coords[self.ksm1]
158
+ dists = np.linalg.norm(diffs, axis=1)
159
+ S_0 = self.P_bh * (dists**2).sum()
160
+
161
+ energies = [image.energy for image in self.images]
162
+ S_pot = 1 / self.P_bh * sum(energies)
163
+ S_E = S_0 / 2 + S_pot
164
+ results = {
165
+ "action": S_E,
166
+ }
167
+ return results
168
+
169
+ def action_gradient(self):
170
+ """
171
+ kin_grad corresponds to the gradient of S_0 in (Eq. 1 in [1], or
172
+ first term in Eq. 6 in [2].) It boils down to the derivative of a sum
173
+ of vector norms
174
+
175
+ d sum_k (||y_k - y_(k-1)||_2)²
176
+ ---
177
+ d y_k
178
+
179
+ The derivative of a norm of a vector difference is quite simple, but
180
+ care has to be taken to recognize, that y_k appears two times in the sum.
181
+ It appears in the first summand for k and in the second summand for k+1.
182
+
183
+ sum_k (||y_k - y_(k-1)||_2)²
184
+ 1. term 2. term
185
+ = (||y_k - y_(k-1)||_2)² + (||y_(k+1) - y_k||_2)² + ... and so on
186
+
187
+ The derivative of the first term is
188
+
189
+ 2 * (y_k - y_(k-1))
190
+
191
+ and the derivative of the second term is
192
+
193
+ -2 * (y_(k+1) - y_k))
194
+
195
+ which is equal to
196
+
197
+ 2 * (y_k - y_(k+1)) .
198
+
199
+ To summarize:
200
+
201
+ d sum_k(||y_k - y_(k-1)||_2)²
202
+ ---
203
+ d y_k
204
+
205
+ = 2 * (2 * y_k - y_(k-1) - y_(k+1)) .
206
+ """
207
+ image_coords = np.array([image.coords for image in self.images])
208
+ kin_grad = (
209
+ 2
210
+ * (
211
+ 2 * image_coords # y_k
212
+ - image_coords[self.ksm1] # y_(k-1)
213
+ - image_coords[self.ksp1] # y_(k+1)
214
+ ).flatten()
215
+ )
216
+ kin_grad *= self.P_bh
217
+ pot_grad = np.array(
218
+ [
219
+ log_progress(image.gradient, "gradient", i)
220
+ for i, image in enumerate(self.images)
221
+ ]
222
+ ).flatten()
223
+ pot_grad /= self.P_bh
224
+ gradient = kin_grad / 2 + pot_grad
225
+ # gradient = pot_grad
226
+ # gradient = kin_grad
227
+ # gradient = kin_grad / 2
228
+ results = {
229
+ "gradient": gradient,
230
+ }
231
+ results.update(self.action())
232
+ return results
233
+
234
+ def action_hessian(self):
235
+ image_hessians = [
236
+ log_progress(image.hessian, "hessian", i)
237
+ for i, image in enumerate(self.images)
238
+ ]
239
+ pot_hess = sp.linalg.block_diag(*image_hessians)
240
+ pot_hess /= self.P_bh
241
+ coord_num = pot_hess.shape[0]
242
+ zeroes = np.zeros((coord_num, coord_num))
243
+ image_coord_num = self.images[0].coords.size
244
+ inds = np.arange(coord_num).reshape(-1, image_coord_num)
245
+ ks = inds[self.ks].flatten()
246
+ ksm1 = inds[self.ksm1].flatten()
247
+ ksp1 = inds[self.ksp1].flatten()
248
+ km = zeroes.copy()
249
+ km[ks, ksm1] = 1.0
250
+ kp = zeroes.copy()
251
+ kp[ks, ksp1] = 1.0
252
+ kin_hess = 4 * np.eye(coord_num) - 2 * km - 2 * kp # y_k # y_k-1 # y_k+1
253
+ kin_hess *= self.P_bh
254
+ hessian = kin_hess / 2 + pot_hess
255
+ # hessian = pot_hess
256
+ # hessian = kin_hess / 2
257
+ results = {
258
+ "hessian": hessian,
259
+ }
260
+ results.update(self.action())
261
+ return results
262
+
263
+ @property
264
+ def energy(self):
265
+ return self.action()["action"]
266
+
267
+ @property
268
+ def gradient(self):
269
+ return self.action_gradient()["gradient"]
270
+
271
+ @property
272
+ def forces(self):
273
+ return -self.gradient
274
+
275
+ @property
276
+ def hessian(self):
277
+ return self.action_hessian()["hessian"]
278
+
279
+ @property
280
+ def cart_hessian(self):
281
+ return sp.linalg.block_diag(*[image.cart_hessian for image in self.images])
282
+
283
+ @property
284
+ def cart_coords(self):
285
+ return np.ravel([image.cart_coords for image in self.images])
286
+
287
+ @property
288
+ def cart_forces(self):
289
+ return np.ravel([image.cart_forces for image in self.images])
290
+
291
+ @property
292
+ def cart_hessian(self):
293
+ return sp.linalg.block_diag(*[image.cart_forces for image in self.images])
294
+
295
+ def is_analytical_2d(self):
296
+ return self.images[0].is_analytical_2d
297
+
298
+ @property
299
+ def path_length(self):
300
+ image_coords3d = [image.coords3d for image in self.images]
301
+ coord_diffs = get_coords_diffs(image_coords3d, align=False, normalize=False)
302
+ length = coord_diffs.sum()
303
+ return length
304
+
305
+ def get_additional_print(self):
306
+ length = self.path_length
307
+ return f"\t\tInstanton length={length:.2f} √a̅m̅u̅·au"
pysisyphus/irc/LQA.py ADDED
@@ -0,0 +1,53 @@
1
+ # [1] https://aip.scitation.org/doi/pdf/10.1063/1.459634?class=pdf
2
+ # Page, 1990, Eq. 19 is missing a **2 after g'_0,i
3
+ # [2] https://aip.scitation.org/doi/10.1063/1.1724823
4
+ # Hratchian, 2004
5
+
6
+ import numpy as np
7
+
8
+ from pysisyphus.optimizers.hessian_updates import bfgs_update
9
+ from pysisyphus.irc.IRC import IRC
10
+
11
+
12
+ class LQA(IRC):
13
+
14
+ def __init__(self, geometry, N_euler=5000, **kwargs):
15
+ super().__init__(geometry, **kwargs)
16
+
17
+ self.N_euler = N_euler
18
+
19
+ def step(self):
20
+ mw_gradient = self.mw_gradient
21
+
22
+ if len(self.irc_mw_gradients) > 1:
23
+ dg = self.irc_mw_gradients[-1] - self.irc_mw_gradients[-2]
24
+ dx = self.irc_mw_coords[-1] - self.irc_mw_coords[-2]
25
+ dH, _ = bfgs_update(self.mw_hessian, dx, dg)
26
+ self.mw_hessian += dH
27
+
28
+ eigenvalues, eigenvectors = np.linalg.eigh(self.mw_hessian)
29
+ # Drop small eigenvalues and corresponding eigenvectors
30
+ small_vals = np.abs(eigenvalues) < 1e-8
31
+ eigenvalues = eigenvalues[~small_vals]
32
+ eigenvectors = eigenvectors[:,~small_vals]
33
+
34
+ # t step for numerical integration
35
+ dt = 1 / self.N_euler * self.step_length / np.linalg.norm(mw_gradient)
36
+
37
+ # Transform gradient to eigensystem of the hessian
38
+ mw_gradient_trans = eigenvectors.T @ mw_gradient
39
+
40
+ t = dt
41
+ cur_length = 0
42
+ for i in range(self.N_euler):
43
+ dsdt = np.sqrt(np.sum(mw_gradient_trans**2 * np.exp(-2*eigenvalues*t)))
44
+ cur_length += dsdt * dt
45
+ if cur_length > self.step_length:
46
+ break
47
+ t += dt
48
+ alphas = (np.exp(-eigenvalues*t) - 1) / eigenvalues
49
+ A = eigenvectors @ np.diag(alphas) @ eigenvectors.T
50
+ step = A @ mw_gradient
51
+
52
+ mw_coords = self.mw_coords.copy()
53
+ self.mw_coords = mw_coords + step
@@ -0,0 +1,136 @@
1
+ import numpy as np
2
+
3
+ from pysisyphus.helpers import do_final_hessian
4
+ from pysisyphus.helpers_pure import eigval_to_wavenumber
5
+ from pysisyphus.irc.IRC import IRC
6
+ from pysisyphus.optimizers.hessian_updates import bofill_update
7
+
8
+
9
+ class ModeKill(IRC):
10
+
11
+ def __init__(self, geometry, kill_inds, nu_thresh=-5.,
12
+ do_hess=True, hessian_update=True, **kwargs):
13
+ # Use tight convergence criteria so the IRC/ModeKill doesn't
14
+ # ent prematurely.
15
+ super().__init__(geometry, downhill=True, rms_grad_thresh=1e-6,
16
+ hessian_init="calc", **kwargs)
17
+
18
+ assert self.geometry.coord_type == "cart"
19
+
20
+ self.kill_inds = np.array(kill_inds, dtype=int)
21
+ self.nu_thresh = float(nu_thresh)
22
+ self.do_hess = do_hess
23
+ self.hessian_update = hessian_update
24
+
25
+ self.fmt = {"float": lambda f: f"{f:.4f}",}
26
+ self.ovlp_thresh = .3
27
+ self.indices = np.arange(self.geometry.coords.size)
28
+ self.neg_nus = list()
29
+
30
+ def prepare(self, *args, **kwargs):
31
+ super().prepare(*args, **kwargs)
32
+
33
+ self.update_mw_down_step()
34
+
35
+ def update_mw_down_step(self):
36
+ w, v = np.linalg.eigh(self.mw_hessian)
37
+
38
+ self.kill_modes = v[:,self.kill_inds]
39
+ nus = eigval_to_wavenumber(w)
40
+ assert all(nus[self.kill_inds] < self.nu_thresh), \
41
+ "ModeKill is intended for removal of imaginary frequencies " \
42
+ f"below {self.nu_thresh} cm⁻¹! The specified indices " \
43
+ f"{self.kill_inds} contain modes with positive frequencies " \
44
+ f"({nus[self.kill_inds]} cm⁻¹). Please choose different kill_inds!"
45
+
46
+ """After diagonalization of the mass-weighted hessian the signs
47
+ of the eigenvectors are arbitrary.
48
+ We determine the correct sign of the eigenvector(s) from its
49
+ overlap(s) with the gradient.
50
+ To decrease the overall energy we have to step against the
51
+ gradient, so the overlap of gradient and the respective eigen-
52
+ vector(s) must be negative.
53
+ If an overlap is positive we flip the sign of the corresponding
54
+ eigenvector.
55
+ """
56
+ mw_grad = self.mw_gradient
57
+ mw_grad_normed = mw_grad / np.linalg.norm(mw_grad)
58
+ overlaps = np.einsum("ij,i->j", self.kill_modes, mw_grad_normed)
59
+ self.log("Overlaps between gradient and eigenvectors:")
60
+ self.log(overlaps)
61
+ flip = overlaps > 0
62
+ self.log("Eigenvector signs to be flipped:")
63
+ self.log(str(flip))
64
+ self.kill_modes[:,flip] *= -1
65
+ # Create the step as the sum of the downhill steps along the modes
66
+ # to remove.
67
+ self.mw_down_step = (self.step_length*self.kill_modes).sum(axis=1)
68
+
69
+ def step(self):
70
+ if self.hessian_update and (self.cur_cycle > 0):
71
+ # Hessian update with mass-weighted values
72
+ dx = self.irc_mw_coords[-1] - self.irc_mw_coords[-2]
73
+ dg = (self.irc_mw_gradients[-1] - self.irc_mw_gradients[-2])
74
+ d_mw_H, key = bofill_update(self.mw_hessian, dx, dg)
75
+ self.mw_hessian += d_mw_H
76
+
77
+ # norm(dx) is probably self.step_length ;)
78
+ norm_dx = np.linalg.norm(dx)
79
+ norm_dg = np.linalg.norm(dg)
80
+ self.log(f"Did {key} hessian update: norm(dx)={norm_dx:.4e}, "
81
+ f"norm(dg)={norm_dg:.4e}."
82
+ )
83
+ else:
84
+ # Recalculate exact hessian
85
+ self.mw_hessian = self.geometry.mw_hessian
86
+ self.log("Recalculated exact hessian.")
87
+
88
+ w, v = np.linalg.eigh(self.mw_hessian)
89
+ # Overlaps between current normal modes and the modes we want to
90
+ # remove.
91
+ overlaps = np.abs(np.einsum("ij,ik->jk", self.kill_modes, v))
92
+ self.log(f"Overlaps between original modes and current modes:")
93
+ # overlaps contains one row per mode to remove
94
+ for i, ovlps in enumerate(overlaps):
95
+ above_thresh = ovlps > self.ovlp_thresh
96
+ ovlp_str = " ".join(
97
+ [f"{i:02d}: {o:.4f}" for i, o in zip(self.indices[above_thresh],
98
+ ovlps[above_thresh])
99
+ ]
100
+ )
101
+ self.log(f"Org. mode {i:02d}:\n\t\t\t{ovlp_str}")
102
+
103
+ nus = eigval_to_wavenumber(w)
104
+ neg_inds = nus <= self.nu_thresh
105
+ neg_nus = nus[neg_inds]
106
+ self.neg_nus.append(neg_nus)
107
+ self.log(f"Wavenumbers of imaginary modes (<= {self.nu_thresh} cm⁻¹):")
108
+ self.log(f"{neg_nus} cm⁻¹")
109
+
110
+ # Check if any eigenvalues became positive. If so remove them and update
111
+ # the step. If no mode to remove is left we are finished and can signal
112
+ # convergence.
113
+ argmax = overlaps.argmax(axis=1)
114
+ eigvals = w[argmax]
115
+ pos_eigvals = eigvals > 0
116
+ if any(pos_eigvals):
117
+ # Only keep negative eigenvalues.
118
+ flipped = self.kill_inds[pos_eigvals]
119
+ self.kill_inds = self.kill_inds[~pos_eigvals]
120
+ self.update_mw_down_step()
121
+ self.log(f"Eigenvalue(s) of mode(s) {flipped} became positive!")
122
+ self.converged = len(self.kill_inds) == 0
123
+
124
+ if not self.converged:
125
+ self.mw_coords += self.mw_down_step
126
+
127
+ def postprocess(self):
128
+ super().postprocess()
129
+
130
+ if self.do_hess:
131
+ print()
132
+ do_final_hessian(self.geometry)
133
+
134
+ def get_additional_print(self):
135
+ neg_nus = np.array2string(self.neg_nus[-1], precision=2)
136
+ return f"\timag. ῦ: {neg_nus} cm⁻¹"
@@ -0,0 +1,53 @@
1
+ import matplotlib.pyplot as plt
2
+ import numpy as np
3
+
4
+
5
+ class ParamPlot:
6
+
7
+ def __init__(self, coords_list, param1_inds, param2_inds):
8
+ self.coords_list = coords_list
9
+ self.coords_list_3d = [c.reshape(-1, 3) for c in coords_list]
10
+ self.p1inds = param1_inds
11
+ self.p2inds = param2_inds
12
+
13
+ self.p1 = [self.get_param(c, param1_inds) for c in self.coords_list_3d]
14
+ self.p2 = [self.get_param(c, param2_inds) for c in self.coords_list_3d]
15
+
16
+ self.fig, self.ax = plt.subplots()
17
+
18
+ def calc_bond(self, coords, ind1, ind2):
19
+ return np.linalg.norm(coords[ind1] - coords[ind2])
20
+
21
+ def calc_angle(self, coords, ind1, ind2, ind3):
22
+ vec1 = coords[ind1] - coords[ind2]
23
+ vec2 = coords[ind3] - coords[ind2]
24
+ vec1n = np.linalg.norm(vec1)
25
+ vec2n = np.linalg.norm(vec2)
26
+ dotp = np.dot(vec1, vec2)
27
+ radians = np.arccos(dotp / (vec1n * vec2n))
28
+ return radians * 180 / np.pi
29
+
30
+ def get_param(self, coords, param_inds):
31
+ if len(param_inds) == 2:
32
+ return self.calc_bond(coords, *param_inds)
33
+ elif len(param_inds) == 3:
34
+ return self.calc_angle(coords, *param_inds)
35
+ else:
36
+ raise Exception
37
+
38
+ def plot(self):
39
+ self.ax.plot(self.p1, self.p2, "ro", ls="--")
40
+ self.ax.set_xlabel(str(self.p1inds))
41
+ self.ax.set_ylabel(str(self.p2inds))
42
+
43
+ def show(self):
44
+ plt.tight_layout()
45
+ plt.show()
46
+
47
+ def save(self, path, prefix):
48
+ out_fn = str(path / (prefix + ".pdf"))
49
+ self.fig.tight_layout()
50
+ self.fig.savefig(out_fn)
51
+
52
+ def save_coords(self, path, prefix):
53
+ np.savetxt(path / (prefix + ".coords"), self.coords_list)
pysisyphus/irc/RK4.py ADDED
@@ -0,0 +1,36 @@
1
+ import numpy as np
2
+
3
+ from pysisyphus.irc.IRC import IRC
4
+
5
+
6
+ # [1] https://aip.scitation.org/doi/pdf/10.1063/1.462674?class=pdf
7
+ # [2] https://www.sciencedirect.com/science/article/pii/S0009261406015673
8
+
9
+
10
+ class RK4(IRC):
11
+
12
+ def get_k(self, mw_coords):
13
+ self.mw_coords = mw_coords
14
+ grad = self.mw_gradient
15
+ direction = -grad / np.linalg.norm(grad)
16
+ k = self.step_length * direction
17
+ return k
18
+
19
+ def step(self):
20
+ # Eq. (25 - 29) in [1]
21
+ mw_coords_1 = self.mw_coords.copy()
22
+ k1 = self.get_k(mw_coords_1)
23
+
24
+ mw_coords_2 = mw_coords_1 + 0.5*k1
25
+ k2 = self.get_k(mw_coords_2)
26
+
27
+ mw_coords_3 = mw_coords_1 + 0.5*k2
28
+ k3 = self.get_k(mw_coords_3)
29
+
30
+ mw_coords_4 = mw_coords_1 + k3
31
+ k4 = self.get_k(mw_coords_4)
32
+
33
+ step = (k1 + 2*k2 + 2*k3 + k4) / 6
34
+ step_norm = np.linalg.norm(step)
35
+ self.log(f"norm(step)={step_norm:.6f}")
36
+ self.mw_coords = mw_coords_1 + step
@@ -0,0 +1,31 @@
1
+ import logging
2
+
3
+ __all__ = [
4
+ "DampedVelocityVerlet",
5
+ "Euler",
6
+ "EulerPC",
7
+ "LQA",
8
+ "GonzalezSchlegel",
9
+ "IMKMod",
10
+ "ModeKill",
11
+ "RK4",
12
+ ]
13
+
14
+ from pysisyphus.irc.DampedVelocityVerlet import DampedVelocityVerlet
15
+ from pysisyphus.irc.Euler import Euler
16
+ from pysisyphus.irc.EulerPC import EulerPC
17
+ from pysisyphus.irc.GonzalezSchlegel import GonzalezSchlegel
18
+ from pysisyphus.irc.IMKMod import IMKMod
19
+ from pysisyphus.irc.LQA import LQA
20
+ from pysisyphus.irc.ModeKill import ModeKill
21
+ from pysisyphus.irc.RK4 import RK4
22
+
23
+ logger = logging.getLogger("irc")
24
+ logger.setLevel(logging.DEBUG)
25
+ # delay = True prevents creation of empty logfiles
26
+ handler = logging.FileHandler("irc.log", mode="w", delay=True)
27
+ # fmt_str = "%(levelname)s - %(message)s"
28
+ fmt_str = "%(message)s"
29
+ formatter = logging.Formatter(fmt_str)
30
+ handler.setFormatter(formatter)
31
+ logger.addHandler(handler)