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,169 @@
1
+ import logging
2
+ import os
3
+ from pathlib import Path
4
+ import shutil
5
+ from subprocess import PIPE, Popen
6
+
7
+ import numpy as np
8
+
9
+ from pysisyphus.config import get_cmd
10
+ from pysisyphus.constants import AU2EV
11
+ from pysisyphus.wrapper.exceptions import SegfaultException
12
+
13
+
14
+ logger = logging.getLogger("mwfn")
15
+
16
+
17
+ def log(msg):
18
+ logger.debug(msg)
19
+
20
+
21
+ def wrap_stdin(stdin):
22
+ return f"<< EOF\n{stdin}\nEOF"
23
+
24
+
25
+ def call_mwfn(inp_fn, stdin, cwd=None):
26
+ if cwd is None:
27
+ cwd = Path(".")
28
+ mwfn_cmd = get_cmd("mwfn")
29
+ cmd = [mwfn_cmd, inp_fn]
30
+ log(f"\n{mwfn_cmd} {inp_fn} {wrap_stdin(stdin)}")
31
+ proc = Popen(
32
+ cmd, universal_newlines=True, stdin=PIPE, stdout=PIPE, stderr=PIPE, cwd=cwd
33
+ )
34
+ stdout, stderr = proc.communicate(stdin)
35
+ if "segmentation fault occurred" in stderr:
36
+ raise SegfaultException(
37
+ "Multiwfn segfaulted! Multiwfn seems to have problems "
38
+ "with systems >= 1000 basis functions. Maybe your system is too big."
39
+ )
40
+ proc.terminate()
41
+ return stdout, stderr
42
+
43
+
44
+ def make_cdd(inp_fn, state, log_fn, cwd=None, keep=False, quality=2, prefix="S"):
45
+ """Create CDD cube in cwd.
46
+
47
+ Parameters
48
+ ----------
49
+ inp_fn : str
50
+ Filename of a .molden/.fchk file.
51
+ state : int
52
+ CDD cubes will be generated up to this state.
53
+ log_fn : str
54
+ Filename of the .log file.
55
+ cwd : str or Path, optional
56
+ If a different cwd should be used.
57
+ keep : bool
58
+ Wether to keep electron.cub and hole.cub, default is False.
59
+ quality : int
60
+ Quality of the cube. (1=low, 2=medium, 3=high).
61
+ """
62
+
63
+ assert quality in (1, 2, 3)
64
+
65
+ msg = (
66
+ f"Requested CDD calculation from Multiwfn for state {state} using "
67
+ f"{inp_fn} and {log_fn}"
68
+ )
69
+ log(msg)
70
+
71
+ stdin = f"""18
72
+ 1
73
+ {log_fn}
74
+ {state}
75
+ 1
76
+ {quality}
77
+ 10
78
+ 1
79
+ 11
80
+ 1
81
+ 15
82
+ 0
83
+ 0
84
+ 0
85
+ q
86
+ """
87
+ stdout, stderr = call_mwfn(inp_fn, stdin, cwd=cwd)
88
+
89
+ if cwd is None:
90
+ cwd = "."
91
+ cwd = Path(cwd)
92
+
93
+ cube_fns = ("electron.cub", "hole.cub", "CDD.cub")
94
+ if not keep:
95
+ # always keep CDD.cub
96
+ for fn in cube_fns[:2]:
97
+ full_path = cwd / fn
98
+ os.remove(full_path)
99
+ # Rename cubes according to the current state
100
+ new_paths = list()
101
+ for fn in cube_fns:
102
+ old_path = cwd / fn
103
+ root, ext = os.path.splitext(fn)
104
+ new_path = cwd / f"{prefix}_{state:03d}_{root}{ext}"
105
+ try:
106
+ shutil.copy(old_path, new_path)
107
+ os.remove(old_path)
108
+ new_paths.append(new_path)
109
+ except FileNotFoundError:
110
+ pass
111
+ return new_paths
112
+
113
+
114
+ def get_mwfn_exc_str(energies, Xa, Ya=None, Xb=None, Yb=None, thresh=1e-3):
115
+ """Write plain text input for MWFN according to 3.21.
116
+
117
+ As of version 3.8 MWFN does not seem to handle this file when spin
118
+ labels are present, even though it is given as an example in the manual.
119
+ """
120
+
121
+ # We only use the spin label for unrestricted calculations, where Xb is present.
122
+ spin_a = "A" if (Xb is not None) else ""
123
+ assert len(energies) == (
124
+ len(Xa) + 1
125
+ ), "Found too few energies. Is the GS energy missing?"
126
+ exc_energies = (energies[1:] - energies[0]) * AU2EV
127
+ # states, occ, virt
128
+ nstates, occ_mos, _ = Xa.shape
129
+
130
+ exc_str = ""
131
+ mult = 1
132
+ log(f"Using dummy multiplicity={mult} in get_mwfn_exc_str")
133
+
134
+ def set_default(mat):
135
+ if mat is None:
136
+ mat = [None] * nstates
137
+ return mat
138
+
139
+ Ya = set_default(Ya)
140
+ Xb = set_default(Xb)
141
+ Yb = set_default(Yb)
142
+
143
+ def get_exc_lines(ci_coeffs, arrow, spin=""):
144
+ exc_lines = list()
145
+ for (occ, virt), coeff in np.ndenumerate(ci_coeffs):
146
+ if abs(coeff) < thresh:
147
+ continue
148
+ occ_mo = occ + 1
149
+ virt_mo = occ_mos + 1 + virt
150
+ exc_line = f"{occ_mo:>8d}{spin} {arrow} {virt_mo}{spin} {coeff: .5f}"
151
+ exc_lines.append(exc_line)
152
+ return exc_lines
153
+
154
+ for root_, (xa, ya, xb, yb, exc_en) in enumerate(
155
+ zip(Xa, Ya, Xb, Yb, exc_energies), 1
156
+ ):
157
+ exc_str += f"Excited State {root_} {mult} {exc_en:.4f}\n"
158
+ # Excitations (X vector)
159
+ exc_lines = get_exc_lines(xa, "->", spin_a)
160
+ # De-Excitations (Y vector), if present
161
+ if ya is not None:
162
+ exc_lines += get_exc_lines(ya, "<-", spin_a)
163
+ if xb is not None:
164
+ exc_lines += get_exc_lines(xb, "->", "B")
165
+ if yb is not None:
166
+ exc_lines += get_exc_lines(yb, "<-", "B")
167
+ exc_str += "\n".join(exc_lines)
168
+ exc_str += "\n\n"
169
+ return exc_str
@@ -0,0 +1,71 @@
1
+ import subprocess
2
+ import tempfile
3
+
4
+ from jinja2 import Template
5
+
6
+ from pysisyphus.config import get_cmd
7
+
8
+
9
+ TPL = """tolerance {{ tolerance }}
10
+ output {{ output_fn }}
11
+ filetype pdb
12
+
13
+ {% if solute_fn %}
14
+ # Solute
15
+ structure {{ solute_fn }}
16
+ number {{ solute_num }}
17
+ {% if solute_num == 1 %}
18
+ fixed 0. 0. 0. 0. 0. 0.
19
+ centerofmass
20
+ {% endif %}
21
+ end structure
22
+ {% endif %}
23
+
24
+ # Solvent
25
+ structure {{ solvent_fn }}
26
+ number {{ solvent_num }}
27
+ inside sphere 0. 0. 0. {{ sphere_radius }}
28
+ end structure
29
+ """
30
+
31
+
32
+ def make_input(
33
+ output_fn,
34
+ solvent_fn,
35
+ solvent_num,
36
+ sphere_radius,
37
+ solute_fn=None,
38
+ solute_num=None,
39
+ tolerance=2.0,
40
+ ):
41
+ tpl = Template(TPL)
42
+ rendered = tpl.render(
43
+ tolerance=tolerance,
44
+ output_fn=output_fn,
45
+ solute_fn=solute_fn,
46
+ solute_num=solute_num,
47
+ solvent_fn=solvent_fn,
48
+ solvent_num=solvent_num,
49
+ sphere_radius=sphere_radius,
50
+ )
51
+ return rendered
52
+
53
+
54
+ def call_packmol(inp):
55
+ packmol_cmd = get_cmd("packmol")
56
+
57
+ with tempfile.NamedTemporaryFile(mode="w", dir=".") as tmp:
58
+ tmp.write(inp)
59
+ tmp.flush()
60
+ tmp.seek(0)
61
+ with open(tmp.name) as stdin_f:
62
+ proc = subprocess.run(
63
+ [packmol_cmd],
64
+ stdin=stdin_f,
65
+ stdout=subprocess.PIPE,
66
+ text=True,
67
+ )
68
+ # out = proc.stdout
69
+ # err = proc.stderr
70
+
71
+ return proc
@@ -0,0 +1,168 @@
1
+ import re
2
+
3
+ import numpy as np
4
+
5
+ from pysisyphus.constants import BOHR2ANG
6
+
7
+
8
+ def make_xyz_str(atoms, coords, comment=""):
9
+ assert len(atoms) == len(coords)
10
+ atoms = [a.capitalize() for a in atoms]
11
+
12
+ coord_fmt = "{: 03.8f}"
13
+ line_fmt = "{:>3s} " + " ".join(
14
+ [
15
+ coord_fmt,
16
+ ]
17
+ * 3
18
+ )
19
+
20
+ body = [line_fmt.format(a, *xyz) for a, xyz in zip(atoms, coords)]
21
+ body = "\n".join(body)
22
+
23
+ return f"{len(atoms)}\n{comment}\n{body}"
24
+
25
+
26
+ def make_trj_str(atoms, coords_list, comments=None):
27
+ if comments is None:
28
+ comments = ["" for _ in coords_list]
29
+ xyz_strings = [
30
+ make_xyz_str(atoms, coords, comment)
31
+ for coords, comment in zip(coords_list, comments)
32
+ ]
33
+ return "\n".join(xyz_strings)
34
+
35
+
36
+ def coords_to_trj(trj_fn, atoms, coords_list, comments=None):
37
+ coords = np.array(coords_list)
38
+ coords = coords.reshape(-1, len(atoms), 3) * BOHR2ANG
39
+ trj_str = make_trj_str(atoms, coords, comments)
40
+ with open(trj_fn, "w") as handle:
41
+ handle.write(trj_str)
42
+ return trj_fn
43
+
44
+
45
+ def make_trj_str_from_geoms(geoms, comments=None, energy_comments=False):
46
+ atoms = geoms[0].atoms
47
+ coords_list = [geom.coords3d * BOHR2ANG for geom in geoms]
48
+ if energy_comments and comments is None:
49
+ comments = [str(geom._energy) for geom in geoms]
50
+ elif comments is not None:
51
+ assert len(comments) == len(geoms)
52
+
53
+ return make_trj_str(atoms, coords_list, comments)
54
+
55
+
56
+ def write_geoms_to_trj(geoms, fn, comments=None):
57
+ trj_str = make_trj_str_from_geoms(geoms, comments)
58
+ with open(fn, "w") as handle:
59
+ handle.write(trj_str)
60
+
61
+
62
+ def split_xyz_str(xyz_str):
63
+ """Example:
64
+
65
+ xyz:
66
+ 1
67
+
68
+ X -1.2 1.4 0.0
69
+ 1
70
+
71
+ X 2.0 4.0 0.0
72
+
73
+ """
74
+ float_ = r"([\+\d\-\.]+)"
75
+ header_re = re.compile(r"(\d+)")
76
+ coord_re = re.compile(fr"[a-zA-Z]+\s+{float_}\s+{float_}\s+{float_}")
77
+
78
+ lines = [l.strip() for l in xyz_str.strip().split("\n")]
79
+
80
+ lines_remaining = len(lines)
81
+ cur_line = 0
82
+ valid_xyz_strs = list()
83
+ while lines_remaining:
84
+ header_mobj = header_re.match(lines[cur_line])
85
+ expect_lines = int(header_mobj[1])
86
+ slice_ = slice(
87
+ cur_line + 2, cur_line + 2 + expect_lines
88
+ ) # lgtm [py/hash-unhashable-value]
89
+ check_lines = lines[slice_]
90
+ assert len(check_lines) == expect_lines
91
+ assert all([coord_re.match(line.strip()) for line in check_lines])
92
+
93
+ valid_xyz_strs.append(str(expect_lines) + "\n\n" + "\n".join(check_lines))
94
+
95
+ lines_read = expect_lines + 2
96
+ lines_remaining -= lines_read
97
+ cur_line += lines_read
98
+ atoms_coords = [parse_xyz_str(_, with_comment=False) for _ in valid_xyz_strs]
99
+ return atoms_coords
100
+
101
+
102
+ def parse_xyz_str(xyz_str, with_comment):
103
+ """Parse a xyz string.
104
+
105
+ Paramters
106
+ ---------
107
+ xyz_str : str
108
+ The contents of a .xyz file.
109
+ with_comment : bool
110
+ Return comment line if True.
111
+
112
+ Returns
113
+ -------
114
+ atoms : list
115
+ List of length N (N = number of atoms) holding the
116
+ element symbols.
117
+ coords: np.array
118
+ An array of shape (N, 3) holding the xyz coordinates.
119
+ comment_line : str, optional
120
+ Comment line if with_comment argument was True.
121
+ """
122
+
123
+ xyz_lines = xyz_str.strip().split("\n")
124
+ comment_line = xyz_lines[1]
125
+
126
+ # Only consider the first four items on a line
127
+ atom_num = int(xyz_lines[0])
128
+ atoms_present = len(xyz_lines) - 2
129
+ assert len(xyz_lines) == atom_num + 2, \
130
+ f"Expected {atom_num} atoms, but found only {atoms_present}!"
131
+ atoms_coords = [
132
+ line.strip().split()[:4] for line in xyz_str.strip().split("\n")[2:]
133
+ ]
134
+ atoms, coords = zip(*[(a, c) for a, *c in atoms_coords])
135
+ coords = np.array(coords, dtype=float)
136
+ if with_comment:
137
+ return atoms, coords, comment_line
138
+ else:
139
+ return atoms, coords
140
+
141
+
142
+ def parse_xyz_file(xyz_fn, with_comment=False):
143
+ with open(xyz_fn) as handle:
144
+ xyz_str = handle.read()
145
+
146
+ return parse_xyz_str(xyz_str, with_comment)
147
+
148
+
149
+ def parse_trj_file(trj_fn, with_comments=False):
150
+ with open(trj_fn) as handle:
151
+ trj_str = handle.read()
152
+
153
+ return parse_trj_str(trj_str, with_comments)
154
+
155
+
156
+ def parse_trj_str(trj_str, with_comments=False):
157
+ trj_lines = trj_str.strip().split("\n")
158
+ number_of_atoms = int(trj_lines[0].strip())
159
+ xyz_lines = number_of_atoms + 2
160
+ # Split the trj file in evenly sized strings
161
+ xyz_strs = [
162
+ "\n".join(trj_lines[i : i + xyz_lines])
163
+ for i in range(0, len(trj_lines), xyz_lines)
164
+ ]
165
+ xyzs = [parse_xyz_str(xyz_str, with_comments) for xyz_str in xyz_strs]
166
+
167
+ assert len(xyzs) == (len(trj_lines) / xyz_lines)
168
+ return xyzs
@@ -0,0 +1,45 @@
1
+ from pysisyphus.constants import AU2KJPERMOL, AU2KCALPERMOL, AU2EV, ANG2BOHR, BOHR2M
2
+
3
+ import numpy as np
4
+ import yaml
5
+ from yaml.constructor import ConstructorError
6
+
7
+ _UNIT_MAP = {
8
+ # Energies are converted to Hartree (E_h)
9
+ "Eh": 1,
10
+ "kJpermol": 1 / AU2KJPERMOL, # kJ mol⁻¹
11
+ "kcalpermol": 1 / AU2KCALPERMOL, # kcal mol⁻¹
12
+ "eV": 1 / AU2EV, # eV
13
+ # Times are converted to fs (1e-15 s)
14
+ "fs": 1,
15
+ "ps": 1e-3,
16
+ "ns": 1e-6,
17
+ # Lengths are converted to Bohr (a_0)
18
+ "a0": 1,
19
+ "angstrom": 1 / ANG2BOHR,
20
+ "nm": 1 / BOHR2M * 1e9,
21
+ "deg": np.pi / 180.0
22
+ }
23
+ _UNITS = list(_UNIT_MAP.keys())
24
+ UNITS = _UNITS
25
+
26
+
27
+ def get_constructor(unit):
28
+ conv = _UNIT_MAP[unit]
29
+
30
+ def constructor(loader, node):
31
+ try:
32
+ data = float(loader.construct_scalar(node)) * conv
33
+ except ConstructorError:
34
+ data = np.array(loader.construct_sequence(node), dtype=float) * conv
35
+ return data
36
+
37
+ return constructor
38
+
39
+
40
+ def get_loader(units=_UNITS):
41
+ loader = yaml.SafeLoader
42
+ for unit in units:
43
+ tag = f"!{unit}"
44
+ loader.add_constructor(tag, get_constructor(unit))
45
+ return loader