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,430 @@
1
+ from math import ceil
2
+ from pathlib import Path
3
+ import re
4
+ import textwrap
5
+
6
+ import jinja2
7
+ import numpy as np
8
+
9
+ from pysisyphus.calculators.OverlapCalculator import OverlapCalculator
10
+ from pysisyphus.constants import BOHR2ANG, AU2EV
11
+
12
+
13
+ def parse_mo(eigvec):
14
+ coeffs = list()
15
+ # Skip first line
16
+ for line in eigvec.split("\n")[1:]:
17
+ line = line.strip()
18
+ if line == "":
19
+ continue
20
+ line = line.split()
21
+ if len(line) == 5:
22
+ line = line[-3:]
23
+ coeffs.append(line[1])
24
+ return coeffs
25
+
26
+
27
+ def parse_xplusy(text):
28
+ lines = text.split("\n")
29
+ size, states = [int(i) for i in lines.pop(0).split()]
30
+ # Add one for header line
31
+ block_size = ceil(size / 6) + 1
32
+ assert len(lines) == (states * block_size)
33
+
34
+ xpys = list()
35
+ for i in range(states):
36
+ block = lines[i * block_size : (i + 1) * block_size]
37
+ _, *rest = block
38
+ xpy = np.array([line.split() for line in rest], dtype=float)
39
+ xpys.append(xpy)
40
+ return size, states, np.array(xpys)
41
+
42
+
43
+ class DFTBp(OverlapCalculator):
44
+
45
+ conf_key = "dftbp"
46
+ _set_plans = (
47
+ "out",
48
+ "exc_dat",
49
+ "eigenvec",
50
+ "xplusy_dat",
51
+ )
52
+
53
+ max_ang_moms = {
54
+ "mio-ext": {
55
+ "H": "s",
56
+ "C": "p",
57
+ "N": "p",
58
+ "O": "p",
59
+ },
60
+ "3ob": {
61
+ "Br": "d",
62
+ "C": "p",
63
+ "Ca": "p",
64
+ "Cl": "d",
65
+ "F": "p",
66
+ "H": "s",
67
+ "I": "d",
68
+ "K": "p",
69
+ "Mg": "p",
70
+ "N": "p",
71
+ "Na": "p",
72
+ "O": "p",
73
+ "P": "d",
74
+ "S": "d",
75
+ "Zn": "d",
76
+ },
77
+ }
78
+ hubbard_derivs = {
79
+ "3ob": {
80
+ "Br": -0.0573,
81
+ "Mg": -0.0200,
82
+ "C": -0.1492,
83
+ "N": -0.1535,
84
+ "Ca": -0.0340,
85
+ "Na": -0.0454,
86
+ "Cl": -0.0697,
87
+ "O": -0.1575,
88
+ "F": -0.1623,
89
+ "P": -0.1400,
90
+ "H": -0.1857,
91
+ "S": -0.1100,
92
+ "I": -0.0433,
93
+ "Zn": -0.0300,
94
+ "K": -0.0339,
95
+ },
96
+ }
97
+
98
+ def __init__(self, parameter, *args, slakos=None, root=None, **kwargs):
99
+ super().__init__(*args, **kwargs)
100
+
101
+ assert self.mult == 1, "Open-shell not yet supported!"
102
+ self.parameter = parameter
103
+ if slakos is None:
104
+ slakos = self.get_cmd("slakos")
105
+ self.slakos_prefix = str(slakos)
106
+ assert (Path(self.slakos_prefix) / self.parameter).exists(), (
107
+ f"Expected '{self.parameter}' sub-directory in '{self.slakos_prefix}' "
108
+ "but could not find it!"
109
+ )
110
+ self.root = root
111
+
112
+ self.base_cmd = self.get_cmd()
113
+ self.gen_geom_fn = "geometry.gen"
114
+ self.inp_fn = "dftb_in.hsd"
115
+ self.out_fn = "dftb.out"
116
+ self.to_keep = (
117
+ "dftb_in.hsd",
118
+ "out:detailed.out",
119
+ self.gen_geom_fn,
120
+ self.out_fn,
121
+ "xplusy_dat:XplusY.DAT",
122
+ "exc_dat:EXC.DAT",
123
+ "eigenvec:eigenvec.out",
124
+ )
125
+ self.parser_funcs = {
126
+ "energy": self.parse_energy,
127
+ "forces": self.parse_forces,
128
+ }
129
+
130
+ self.dftb_tpl = jinja2.Template(
131
+ textwrap.dedent(
132
+ """
133
+ Geometry = GenFormat {
134
+ <<< "{{ gen_geom_fn }}"
135
+ }
136
+ Hamiltonian = DFTB {
137
+ Scc = Yes
138
+ Charge = {{ charge }}
139
+ SpinPolarisation = {{ spinpol }}
140
+ SlaterKosterFiles = Type2FileNames {
141
+ Prefix = "{{ slakos_prefix }}/{{ parameter }}/"
142
+ Separator = "-"
143
+ Suffix = ".skf"
144
+ }
145
+ MaxAngularMomentum {
146
+ {%- for atom, ang_mom in max_ang_moms %}
147
+ {{ atom }} = "{{ ang_mom }}"
148
+ {%- endfor %}
149
+ }
150
+ {% if parameter == "3ob" %}
151
+ ThirdOrderFull = Yes
152
+ HubbardDerivs {
153
+ {% for atom, hd in hubbard_derivs -%}
154
+ {{ atom }} = {{ hd }}
155
+ {% endfor %}
156
+ }
157
+ HCorrection = Damping {
158
+ Exponent = 4.00
159
+ }
160
+ {% endif %}
161
+ }
162
+
163
+ ExcitedState {
164
+ {{ excited_state_str }}
165
+ }
166
+
167
+ Analysis {
168
+ {% for anal in analysis %}
169
+ {{ anal }}
170
+ {%- endfor %}
171
+ }
172
+
173
+ ParserOptions {
174
+ ParserVersion = 8
175
+ }
176
+ """
177
+ ).strip()
178
+ )
179
+
180
+ @staticmethod
181
+ def get_gen_str(atoms, coords):
182
+ gen_fmt_tpl = jinja2.Template(
183
+ textwrap.dedent(
184
+ """
185
+ {{ atom_num }} C
186
+ {% for atom in atom_types %}{{ atom }} {% endfor %}
187
+ {% for type_, x, y, z in types_xyz %}
188
+ {{ loop.index }} {{type_}} {{x}} {{y}} {{z}}
189
+ {%- endfor %}
190
+ """
191
+ ).strip()
192
+ )
193
+ atom_num = len(atoms)
194
+ unique_atoms = tuple(set(atoms))
195
+ atom_types = {atom: i for i, atom in enumerate(unique_atoms, 1)}
196
+ c3d = coords.reshape(-1, 3) * BOHR2ANG
197
+ types_xyz = [(atom_types[atom], x, y, z) for atom, (x, y, z) in zip(atoms, c3d)]
198
+ gen_str = gen_fmt_tpl.render(
199
+ atom_num=atom_num,
200
+ atom_types=unique_atoms,
201
+ types_xyz=types_xyz,
202
+ )
203
+ return gen_str
204
+
205
+ @staticmethod
206
+ def get_excited_state_str(root, forces=False):
207
+ if root is None:
208
+ return ""
209
+
210
+ casida_tpl = jinja2.Template(
211
+ textwrap.dedent(
212
+ """
213
+ Casida {
214
+ NrOfExcitations = {{ nstates }}
215
+ Symmetry = Singlet
216
+ StateOfInterest = {{ root }}
217
+ WriteXplusY = Yes
218
+ {{ es_forces }}
219
+ }
220
+ """
221
+ )
222
+ )
223
+ es_forces = "ExcitedStateForces = Yes" if forces else ""
224
+ es_str = casida_tpl.render(
225
+ nstates=root + 5,
226
+ root=root,
227
+ es_forces=es_forces,
228
+ )
229
+ return es_str
230
+
231
+ def prepare_input(self, atoms, coords, calc_type):
232
+ path = self.prepare_path(use_in_run=True)
233
+ gen_str = self.get_gen_str(atoms, coords)
234
+ with open(path / self.gen_geom_fn, "w") as handle:
235
+ handle.write(gen_str)
236
+ analysis = list()
237
+ if calc_type == "forces":
238
+ analysis.append("CalculateForces = Yes")
239
+ if self.root:
240
+ analysis.extend(("WriteEigenvectors = Yes", "EigenvectorsAsText = Yes"))
241
+ ang_moms = self.max_ang_moms[self.parameter]
242
+ unique_atoms = set(atoms)
243
+ max_ang_moms = [(atom, ang_moms[atom]) for atom in unique_atoms]
244
+
245
+ # spinpol = (
246
+ # "{}"
247
+ # if (self.mult == 1)
248
+ # else f"Colinear {{ UnpairedElectrons = {self.mult-1} }}"
249
+ # )
250
+ spinpol = "{}"
251
+ es_forces = calc_type == "forces"
252
+ try:
253
+ param_hubbard_derivs = self.hubbard_derivs[self.parameter]
254
+ hubbard_derivs = [
255
+ (atom, param_hubbard_derivs[atom]) for atom in unique_atoms
256
+ ]
257
+ except KeyError:
258
+ hubbard_derivs = list()
259
+
260
+ inp = self.dftb_tpl.render(
261
+ gen_geom_fn=self.gen_geom_fn,
262
+ charge=self.charge,
263
+ spinpol=spinpol,
264
+ slakos_prefix=self.slakos_prefix,
265
+ parameter=self.parameter,
266
+ max_ang_moms=max_ang_moms,
267
+ hubbard_derivs=hubbard_derivs,
268
+ excited_state_str=self.get_excited_state_str(self.root, es_forces),
269
+ analysis=analysis,
270
+ )
271
+ return inp, path
272
+
273
+ def store_and_track(self, results, func, atoms, coords, **prepare_kwargs):
274
+ if self.track:
275
+ self.store_overlap_data(atoms, coords)
276
+ if self.track_root():
277
+ # Redo the calculation with the updated root
278
+ results = func(atoms, coords, **prepare_kwargs)
279
+ results["all_energies"] = self.parse_all_energies()
280
+ return results
281
+
282
+ def get_energy(self, atoms, coords, **prepare_kwargs):
283
+ inp, path = self.prepare_input(atoms, coords, "energy")
284
+ results = self.run(inp, "energy")
285
+ results = self.store_and_track(
286
+ results, self.get_energy, atoms, coords, **prepare_kwargs
287
+ )
288
+ return results
289
+
290
+ def get_forces(self, atoms, coords, **prepare_kwargs):
291
+ inp, path = self.prepare_input(atoms, coords, "forces")
292
+ run_kwargs = {
293
+ "calc": "forces",
294
+ "hold": self.track,
295
+ }
296
+ results = self.run(inp, **run_kwargs)
297
+ results = self.store_and_track(
298
+ results, self.get_forces, atoms, coords, **prepare_kwargs
299
+ )
300
+ # if self.track:
301
+ # self.calc_counter += 1
302
+ # self.store_overlap_data(atoms, coords, path)
303
+ # if self.track_root():
304
+ # # Redo the calculation with the updated root
305
+ # results = self.get_forces(atoms, coords)
306
+ # try:
307
+ # shutil.rmtree(path)
308
+ # except FileNotFoundError:
309
+ # self.log(f"'{path}' has already been deleted!")
310
+ return results
311
+
312
+ def run_calculation(self, atoms, coords, **prepare_kwargs):
313
+ inp, path = self.prepare_input(atoms, coords, "energy")
314
+ run_kwargs = {
315
+ "calc": "energy",
316
+ "hold": self.track,
317
+ }
318
+ results = self.run(inp, **run_kwargs)
319
+ if self.track:
320
+ self.calc_counter += 1
321
+ self.store_overlap_data(atoms, coords, path)
322
+ return results
323
+
324
+ def parse_total_energy(self, text):
325
+ energy_re = re.compile(r"Total energy:\s*([-\d\.]+)\s*H")
326
+ exc_energy_re = re.compile(r"Excitation Energy:\s*([\-\.\d]+)\s*H")
327
+ energy = float(energy_re.search(text)[1])
328
+ exc_mobj = exc_energy_re.search(text)
329
+ if exc_mobj:
330
+ energy += float(exc_mobj[1])
331
+ return energy
332
+
333
+ def parse_energy(self, path):
334
+ detailed = path / "detailed.out"
335
+ with open(detailed) as handle:
336
+ text = handle.read()
337
+ results = {
338
+ "energy": self.parse_total_energy(text),
339
+ }
340
+ return results
341
+
342
+ @staticmethod
343
+ def parse_exc_dat(text):
344
+ exc_re = re.compile("=+(.+)", re.DOTALL)
345
+ mobj = exc_re.search(text)
346
+ exc_lines = mobj[1].strip().split("\n")
347
+ exc_ens = (
348
+ np.array([line.strip().split()[0] for line in exc_lines], dtype=float)
349
+ / AU2EV
350
+ )
351
+ return exc_ens
352
+
353
+ def parse_forces(self, path):
354
+ forces_re = re.compile("Total Forces(.+)Maximal derivative", re.DOTALL)
355
+ detailed = path / "detailed.out"
356
+ with open(detailed) as handle:
357
+ text = handle.read()
358
+ mobj = forces_re.search(text)
359
+ forces = np.array(mobj[1].strip().split(), dtype=float).reshape(-1, 4)[:, 1:]
360
+ results = {
361
+ "energy": self.parse_total_energy(text),
362
+ "forces": forces.flatten(),
363
+ }
364
+ return results
365
+
366
+ def parse_all_energies(self, out_fn=None, exc_dat=None):
367
+ if out_fn is None:
368
+ out_fn = self.out
369
+ if exc_dat is None:
370
+ try:
371
+ exc_dat = self.exc_dat
372
+ except AttributeError:
373
+ exc_dat = None
374
+
375
+ with open(out_fn) as handle:
376
+ detailed = handle.read()
377
+
378
+ gs_energy = self.parse_total_energy(detailed)
379
+ if (exc_dat is not None) and exc_dat.exists():
380
+ with open(exc_dat) as handle:
381
+ exc_dat = handle.read()
382
+ exc_ens = self.parse_exc_dat(exc_dat)
383
+ all_energies = np.full(len(exc_ens) + 1, gs_energy)
384
+ all_energies[1:] += exc_ens
385
+ else:
386
+ all_energies = np.array((gs_energy,))
387
+ return all_energies
388
+
389
+ def prepare_overlap_data(self, path):
390
+ #
391
+ # Excitation energies
392
+ #
393
+ # import pdb; pdb.set_trace() # fmt: skip
394
+ # with open(path / "detailed.out") as handle:
395
+ with open(self.out) as handle:
396
+ detailed = handle.read()
397
+ all_energies = self.parse_all_energies(path)
398
+
399
+ #
400
+ # MO coefficients
401
+ #
402
+ # with open(path / "eigenvec.out") as handle:
403
+ with open(self.eigenvec) as handle:
404
+ eigenvecs = handle.read().strip()
405
+ eigenvecs = eigenvecs.split("Eigenvector")[1:]
406
+
407
+ C = np.array([parse_mo(eigvec) for eigvec in eigenvecs], dtype=float).T
408
+ assert C.shape[0] == C.shape[1]
409
+
410
+ #
411
+ # CI coefficients
412
+ #
413
+ electron_re = re.compile(r"Nr. of electrons \(up\):\s*([\d\.]+)")
414
+ mobj = electron_re.search(detailed)
415
+ electrons = int(float(mobj[1]))
416
+ assert electrons % 2 == 0
417
+ occ = electrons // 2
418
+ mo_num = C.shape[0]
419
+ vir = mo_num - occ
420
+ # X+Y
421
+ with open(self.xplusy_dat) as handle:
422
+ xpy_text = handle.read().strip()
423
+ size, states, xpy = parse_xplusy(xpy_text)
424
+ # As of DFTB+ 22.2, we can only get X+Y, but not X-Y, so we can't reconstruct
425
+ # the true X and Y vectors.
426
+ XpY = xpy.reshape(states, occ, vir)
427
+ X = XpY
428
+ Y = np.zeros_like(XpY)
429
+ assert size == occ * vir
430
+ return C, X, Y, all_energies
@@ -0,0 +1,66 @@
1
+ import re
2
+
3
+ import numpy as np
4
+
5
+ from pysisyphus.calculators.Calculator import Calculator
6
+
7
+
8
+ class DFTD3(Calculator):
9
+
10
+ conf_key = "dftd3"
11
+
12
+ def __init__(self, geom, functional, bjdamping=False, **kwargs):
13
+ super().__init__(**kwargs)
14
+ self.atoms = geom.atoms
15
+ self.functional = functional.lower()
16
+ self.bjdamping = bjdamping
17
+
18
+ self.parser_funcs = {
19
+ "energy": self.parse_energy,
20
+ "grad": self.parse_gradient,
21
+ }
22
+
23
+ def parse_energy(self, path):
24
+ with open(path / self.out_fn) as handle:
25
+ text = handle.read()
26
+ mobj = re.search(r"Edisp /kcal,au:\s+([\d\-\.]+)\s+([\d\-\.]+)", text)
27
+ results={
28
+ "energy": float(mobj.group(2)),
29
+ }
30
+ return results
31
+
32
+ def parse_gradient(self, path):
33
+ grad = np.loadtxt(path / "dftd3_gradient")
34
+ energy = self.parse_energy(path)["energy"]
35
+ results={
36
+ "energy": energy,
37
+ "grad": grad.flatten(),
38
+ }
39
+ return results
40
+
41
+ def calc(self, coords3d, gradient=False):
42
+ inp = self.prepare_turbo_coords(self.atoms, coords3d.flatten())
43
+
44
+ args = ["-func", self.functional]
45
+ if self.bjdamping:
46
+ args.append("-bj")
47
+ if gradient:
48
+ args.append("-grad")
49
+
50
+ if gradient:
51
+ calc_type = "grad"
52
+ else:
53
+ calc_type = "energy"
54
+
55
+ results = self.run(inp, calc=calc_type, cmd="dftd3", add_args=args)
56
+
57
+ if not gradient:
58
+ return results["energy"]
59
+ else:
60
+ return results["energy"], results["grad"]
61
+
62
+ def __str__(self):
63
+ return f"DFT-D3({self.name})"
64
+
65
+
66
+
@@ -0,0 +1,84 @@
1
+ import dataclasses
2
+ from typing import Optional
3
+
4
+ try:
5
+ from dftd4.interface import DampingParam, DispersionModel
6
+
7
+ HAS_DFTD4 = True
8
+ except ModuleNotFoundError:
9
+ HAS_DFTD4 = False
10
+ # Dummy definition, so pysisyphus does not crash if another module tries to
11
+ # import DFT4.
12
+ DFTD4 = None
13
+
14
+ from pysisyphus.calculators.Calculator import Calculator
15
+ from pysisyphus.elem_data import nuc_charges_for_atoms
16
+
17
+
18
+ @dataclasses.dataclass
19
+ class D4Params:
20
+ s6: float
21
+ s8: float
22
+ s9: float
23
+ a1: float
24
+ a2: float
25
+
26
+
27
+ OWN_METHODS = {
28
+ # ORCA 5.0.3 ... your r²scan-3c bug ... why are you doing this to me? Why?
29
+ "r2scan-3c": D4Params(s6=1.0, s8=0.0, s9=2.0, a1=0.42, a2=5.65),
30
+ }
31
+
32
+
33
+ class DFTD4(Calculator):
34
+ def __init__(
35
+ self,
36
+ method: Optional[str] = None,
37
+ damp_params: Optional[D4Params] = None,
38
+ model_params: Optional[dict] = None,
39
+ **kwargs
40
+ ):
41
+ assert HAS_DFTD4, "DFTD4 python package is not installed!"
42
+ super().__init__(**kwargs)
43
+
44
+ if model_params is None:
45
+ model_params = dict()
46
+ self.model_params = model_params
47
+
48
+ if method in OWN_METHODS:
49
+ damp_params = OWN_METHODS[method]
50
+
51
+ if damp_params is not None:
52
+ self.damp_param = DampingParam(**dataclasses.asdict(damp_params))
53
+ # if method is not None:
54
+ elif method is not None:
55
+ self.method = method
56
+ self.damp_param = DampingParam(method=method)
57
+ else:
58
+ raise Exception("Please provide either 'method' or 'params'!")
59
+
60
+ def get_model(self, atoms, coords):
61
+ atomic_numbers = nuc_charges_for_atoms(atoms)
62
+ model = DispersionModel(
63
+ atomic_numbers, coords.reshape(-1, 3), **self.model_params
64
+ )
65
+ return model
66
+
67
+ def get_dispersion(self, atoms, coords, grad):
68
+ model = self.get_model(atoms, coords)
69
+ res = model.get_dispersion(self.damp_param, grad=grad)
70
+ results = {
71
+ "energy": float(res.get("energy")),
72
+ }
73
+ if grad:
74
+ results["forces"] = -res.get("gradient").flatten()
75
+ return results
76
+
77
+ def get_energy(self, atoms, coords, **prepare_kwargs):
78
+ return self.get_dispersion(atoms, coords, grad=False)
79
+
80
+ def get_forces(self, atoms, coords, **prepare_kwargs):
81
+ return self.get_dispersion(atoms, coords, grad=True)
82
+
83
+ # This calculator relies on a finite differences numerical Hessian, as provided
84
+ # by the Calculator parent class.
@@ -0,0 +1,61 @@
1
+ try:
2
+ import daltonproject as dp
3
+ except ModuleNotFoundError:
4
+ print("daltonproject is not installed!")
5
+
6
+ from pysisyphus.calculators.Calculator import Calculator
7
+ from pysisyphus.constants import BOHR2ANG
8
+
9
+
10
+ class Dalton(Calculator):
11
+
12
+ conf_key = "dalton"
13
+
14
+ def __init__(self, basis, method="hf", **kwargs):
15
+ super().__init__(**kwargs)
16
+
17
+ self._basis = basis
18
+ self._method = method
19
+
20
+ self.basis = dp.Basis(basis=self._basis)
21
+ self.method = dp.QCMethod(self._method)
22
+ self.compute_settings = dp.ComputeSettings(mpi_num_procs=1)
23
+
24
+ def prepare_input(self, atoms, coords):
25
+ coords3d = coords.reshape(-1, 3) * BOHR2ANG
26
+ dp_atoms = "; ".join(
27
+ [f"{atom} {x} {y} {z}" for atom, (x, y, z) in zip(atoms, coords3d)]
28
+ )
29
+ molecule = dp.Molecule(atoms=dp_atoms, charge=self.charge)
30
+
31
+ return molecule
32
+
33
+ def compute(self, mol, prop):
34
+ return dp.dalton.compute(
35
+ mol, self.basis, self.method, prop, compute_settings=self.compute_settings
36
+ )
37
+
38
+ def get_energy(self, atoms, coords, **prepare_kwargs):
39
+ mol = self.prepare_input(atoms, coords)
40
+ prop = dp.Property(energy=True)
41
+ res = self.compute(mol, prop)
42
+
43
+ results = {
44
+ "energy": res.energy,
45
+ }
46
+ return results
47
+
48
+
49
+ def get_forces(self, atoms, coords, **prepare_kwargs):
50
+ mol = self.prepare_input(atoms, coords)
51
+ prop = dp.Property(energy=True, gradients=True)
52
+ res = self.compute(mol, prop)
53
+
54
+ results = {
55
+ "energy": res.energy,
56
+ "forces": -res.gradients.flatten(),
57
+ }
58
+ return results
59
+
60
+ def __str__(self):
61
+ return f"Dalton({self.name})"