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
pysisyphus/io/mol2.py ADDED
@@ -0,0 +1,146 @@
1
+ import jinja2
2
+ import pyparsing as pp
3
+ import numpy as np
4
+
5
+ from pysisyphus.constants import ANG2BOHR
6
+ from pysisyphus.Geometry import Geometry
7
+ from pysisyphus.helpers_pure import file_or_str
8
+
9
+
10
+ @file_or_str(".mol2")
11
+ def parse_mol2(text):
12
+ def get_line_word(*args):
13
+ return pp.Word(*args).setWhitespaceChars(" \t")
14
+
15
+ new_record = pp.CaselessLiteral("@<TRIPOS>")
16
+
17
+ # <TRIPOS>MOLECULE
18
+ molecule = (
19
+ pp.CaselessLiteral("@<TRIPOS>MOLECULE")
20
+ + pp.LineEnd()
21
+ # comment line/molecule name
22
+ + pp.OneOrMore(get_line_word(pp.printables)).set_results_name("mol_name")
23
+ + pp.common.integer.set_results_name("num_atoms")
24
+ + pp.Optional(pp.common.integer.set_results_name("num_bonds"))
25
+ + pp.Optional(pp.common.integer.set_results_name("num_subst"))
26
+ + pp.Optional(pp.common.integer.set_results_name("num_feat"))
27
+ + pp.Optional(pp.common.integer.set_results_name("num_sets"))
28
+ + pp.oneOf(
29
+ ("SMALL", "BIOPOLYMER", "PROTEIN", "NUCLEIC_ACID", "SACCHARIDE")
30
+ ).set_results_name("mol_type")
31
+ + pp.oneOf(
32
+ ("NO_CHARGES", "GASTEIGER", "MMFF94_CHARGES", "USER_CHARGES", "HUCKEL")
33
+ ).set_results_name("charge_type")
34
+ + pp.Optional(
35
+ ~new_record + pp.Word(pp.printables).set_results_name("status_bits")
36
+ )
37
+ # Only spaces may not be enough for mol comment
38
+ + pp.Optional(~new_record + pp.Word(pp.printables + " ")).set_results_name(
39
+ "mol_comment"
40
+ )
41
+ )
42
+
43
+ # <TRIPOS>ATOM
44
+ atom_data_line = pp.Group(
45
+ ~new_record
46
+ + pp.common.integer.set_results_name("atom_id")
47
+ + pp.Word(pp.alphanums).set_results_name("atom_name")
48
+ + pp.Group(pp.common.real + pp.common.real + pp.common.real).set_results_name(
49
+ "xyz"
50
+ )
51
+ + pp.Word(pp.printables).set_results_name("atom_type")
52
+ + pp.Optional(pp.common.integer.set_results_name("subst_id"))
53
+ + pp.Optional(pp.Word(pp.printables).set_results_name("subst_name"))
54
+ + pp.Optional(pp.common.real.set_results_name("charge"))
55
+ + pp.Optional(get_line_word(pp.printables).set_results_name("status_bit"))
56
+ )
57
+ atom = pp.CaselessLiteral("@<TRIPOS>ATOM") + pp.OneOrMore(
58
+ atom_data_line
59
+ ).set_results_name("atoms_xyzs")
60
+
61
+ # <TRIPOS>BOND
62
+ bond_data_line = pp.Group(
63
+ ~new_record
64
+ + pp.common.integer.set_results_name("bond_id")
65
+ + pp.common.integer.set_results_name("origin_atom_id")
66
+ + pp.common.integer.set_results_name("target_atom_id")
67
+ + pp.Word(pp.printables).set_results_name("bond_type")
68
+ )
69
+ bond = pp.CaselessLiteral("@<TRIPOS>BOND") + pp.OneOrMore(
70
+ bond_data_line
71
+ ).set_results_name("bond")
72
+
73
+ parser = molecule + atom + pp.Optional(bond)
74
+ parser.ignore(pp.helpers.python_style_comment)
75
+
76
+ result = parser.parseString(text)
77
+ return result
78
+
79
+
80
+ @file_or_str(".mol2")
81
+ def atoms_coords_from_mol2(text):
82
+ result = parse_mol2(text)
83
+ as_dict = result.asDict()
84
+
85
+ atoms = list()
86
+ coords = np.zeros((as_dict["num_atoms"], 3), dtype=float)
87
+ atoms_xyzs = as_dict["atoms_xyzs"]
88
+ for i, line in enumerate(atoms_xyzs):
89
+ assert i + 1 == line["atom_id"]
90
+ atom = line["atom_type"].split(".")[0]
91
+ atoms.append(atom)
92
+ coords[i] = line["xyz"]
93
+ assert len(atoms) == len(coords)
94
+
95
+ coords *= ANG2BOHR
96
+
97
+ return atoms, coords
98
+
99
+
100
+ def geom_from_mol2(text, **kwargs):
101
+ atoms, coords = atoms_coords_from_mol2(text)
102
+ geom = Geometry(atoms, coords, **kwargs)
103
+ return geom
104
+
105
+
106
+ MOL2_DICT_TPL = jinja2.Template(
107
+ """@<TRIPOS>MOLECULE
108
+ {{ mol_name }}
109
+ {{ num_atoms }} {{ num_bonds}} {{ num_subst }} {{ num_feat }} {{ num_sets }}
110
+ {{ mol_type }}
111
+ {{ charge_type }}
112
+
113
+ @<TRIPOS>ATOM
114
+ {%- for ax in atoms_xyzs %}
115
+ {{ ax["atom_id"] }} {{ ax["atom_name"] }} {{ render_xyz(ax["xyz"])}} {{ ax["atom_type"] }} {{ ax["subst_id"] }} {{ ax["subst_name"] }} {{ ax["charge"]}}
116
+ {%- endfor %}
117
+ @<TRIPOS>BOND
118
+ {%- for bond in bonds %}
119
+ {{ bond["bond_id"] }} {{ bond["origin_atom_id"]}} {{ bond["target_atom_id"] }} {{ bond["bond_type"]}}
120
+ {%- endfor %}
121
+
122
+ """
123
+ )
124
+
125
+
126
+ def render_xyz(xyz):
127
+ fmt = " >12.6f"
128
+ return " ".join(map(lambda _: f"{_:{fmt}}", xyz))
129
+
130
+
131
+ def dict_to_mol2_string(as_dict):
132
+ d = as_dict
133
+ rendered = MOL2_DICT_TPL.render(
134
+ mol_name=d["mol_name"],
135
+ num_bonds=d["num_bonds"],
136
+ num_subst=d["num_subst"],
137
+ num_feat=d["num_feat"],
138
+ num_sets=d["num_sets"],
139
+ num_atoms=d["num_atoms"],
140
+ mol_type=d["mol_type"],
141
+ charge_type=d["charge_type"],
142
+ atoms_xyzs=d["atoms_xyzs"],
143
+ bonds=d["bond"],
144
+ render_xyz=render_xyz,
145
+ )
146
+ return rendered
@@ -0,0 +1,293 @@
1
+ import re
2
+
3
+ import numpy as np
4
+ import pyparsing as pp
5
+
6
+ from pysisyphus.elem_data import ATOMIC_NUMBERS
7
+ from pysisyphus.Geometry import Geometry
8
+ from pysisyphus.io.xyz import parse_xyz
9
+ from pysisyphus.helpers_pure import file_or_str
10
+ from pysisyphus.wavefunction import MoldenShells, Shell, Wavefunction
11
+ from pysisyphus.wavefunction.helpers import BFType
12
+
13
+
14
+ @file_or_str(".molden", ".input")
15
+ def parse_molden_atoms_coords(molden_str):
16
+ _, geometries = re.split(r"\[GEOMETRIES\] \(XYZ\)", molden_str)
17
+ atoms_coords, comments = parse_xyz(geometries, with_comment=True)
18
+
19
+ return atoms_coords, comments
20
+
21
+
22
+ def geoms_from_molden(fn, **kwargs):
23
+ atoms_coords, comments = parse_molden_atoms_coords(fn)
24
+ geoms = [
25
+ Geometry(atoms, coords.flatten(), comment=comment, **kwargs)
26
+ for (atoms, coords), comment in zip(atoms_coords, comments)
27
+ ]
28
+ return geoms
29
+
30
+
31
+ def parse_mo(mo_lines):
32
+ # sym, ene_key, energy, spin_key, spin, occup_key, occup, *rest = mo_lines
33
+ sym, ene_line, spin_line, occup_line, *rest = mo_lines
34
+ ene_key, energy = ene_line.split("=")
35
+ spin_key, spin = spin_line.split("=")
36
+ occup_key, occup = occup_line.split("=")
37
+ assert (
38
+ (ene_key.strip() == "ene")
39
+ and (spin_key.strip() == "spin")
40
+ and (occup_key.strip() == "occup")
41
+ )
42
+ prev_ind = 0
43
+ coeffs = list()
44
+ for line in rest:
45
+ ind, coeff = line.split()
46
+ ind = int(ind)
47
+ assert ind == prev_ind + 1
48
+ prev_ind = ind
49
+ coeffs.append(coeff)
50
+ return {
51
+ "sym": sym.strip(),
52
+ "ene": float(energy),
53
+ "spin": spin.strip(),
54
+ "occup": float(occup),
55
+ "coeffs": np.array(coeffs),
56
+ }
57
+
58
+
59
+ @file_or_str(".molden", ".input")
60
+ def parse_molden(text, with_mos=True):
61
+ int_ = pp.common.integer
62
+ real = pp.common.real
63
+ sci_real = pp.common.sci_real
64
+
65
+ def get_section(name):
66
+ return pp.CaselessLiteral(f"[{name}]")
67
+
68
+ molden_format = get_section("Molden Format")
69
+ n_atoms = get_section("N_Atoms") + int_
70
+ atoms_header = get_section("Atoms")
71
+ title = get_section("Title") + pp.Optional(
72
+ pp.ZeroOrMore(~atoms_header + pp.Word(pp.printables))
73
+ )
74
+
75
+ alpha_re = re.compile("([a-zA-Z]+)")
76
+
77
+ def drop_number(toks):
78
+ """OpenMolcas writes atoms like H1, C2, ...
79
+ We don't want the number."""
80
+ return alpha_re.match(toks[0]).group(1)
81
+
82
+ # [Atoms]
83
+ # element_name number atomic_number x y z
84
+ unit = pp.one_of(("AU Angs (AU) (Angs)"), caseless=True)
85
+ atom_symbol = pp.Word(pp.alphanums).set_parse_action(drop_number)
86
+ xyz = pp.Group(sci_real + sci_real + sci_real)
87
+ atom_line = pp.Group(
88
+ atom_symbol.set_results_name("symbol")
89
+ + int_.set_results_name("number")
90
+ + int_.set_results_name("atomic_number")
91
+ + xyz.set_results_name("xyz")
92
+ )
93
+ atoms = (
94
+ atoms_header
95
+ + pp.Optional(unit).set_results_name("unit")
96
+ + pp.OneOrMore(atom_line).set_results_name("atoms")
97
+ )
98
+
99
+ # [Charge], written by OpenMOLCAS
100
+ charge = get_section("Charge")
101
+ charge_kind = pp.one_of(("(Mulliken)",), caseless=True)
102
+ charges = charge + charge_kind + pp.OneOrMore(sci_real)
103
+
104
+ def pgto_exps_coeffs(s, loc, toks):
105
+ data = toks.asList()
106
+ exps, coeffs = np.array(data, dtype=float).reshape(-1, 2).T
107
+ pr = pp.ParseResults.from_dict(
108
+ {
109
+ "exponents": exps,
110
+ "coeffs": coeffs,
111
+ }
112
+ )
113
+ # Somehow this function will result in exponents and coeffs being both
114
+ # stored in lists of length 1.
115
+ return pr
116
+
117
+ # [GTO]
118
+ ang_mom = pp.one_of("s p sp d f g h i", caseless=True)
119
+ pgto = sci_real + sci_real
120
+ shell = pp.Group(
121
+ ang_mom.set_results_name("ang_mom")
122
+ + int_.set_results_name("contr_depth")
123
+ # Usually 1.0, can be left out
124
+ + pp.Optional(real.set_whitespace_chars(" ").suppress() + pp.LineEnd())
125
+ + pp.OneOrMore(pgto).set_parse_action(pgto_exps_coeffs)
126
+ )
127
+ atom_gtos = pp.Group(
128
+ int_.set_results_name("number") # Center
129
+ + pp.Optional(pp.Literal("0"))
130
+ + pp.OneOrMore(shell).set_results_name("shells")
131
+ )
132
+ gto = (
133
+ pp.CaselessLiteral("[GTO]")
134
+ + pp.Optional(unit)
135
+ + pp.Group(pp.OneOrMore(atom_gtos)).set_results_name("gto")
136
+ )
137
+
138
+ # [5D] [7F] [9G] etc.
139
+ ang_mom_flags = pp.ZeroOrMore(pp.one_of("[5D] [7F] [9G]", caseless=True))
140
+
141
+ # Pyparsing code to parse MOs ... slow. Regex-based code is much faster.
142
+ # [MO]
143
+ # sym_label = pp.Word(pp.printables)
144
+ # spin = pp.one_of("Alpha Beta", caseless=True)
145
+ # mo_coeff = pp.Suppress(int_) + real
146
+ # mo = pp.Group(
147
+ # pp.CaselessLiteral("Sym=").suppress()
148
+ # + sym_label.set_results_name("sym")
149
+ # + pp.CaselessLiteral("Ene=").suppress()
150
+ # + sci_real.set_results_name("ene")
151
+ # + pp.CaselessLiteral("Spin=").suppress()
152
+ # + spin.set_results_name("spin")
153
+ # + pp.CaselessLiteral("Occup=").suppress()
154
+ # + real.set_results_name("occup")
155
+ # + pp.Group(pp.OneOrMore(mo_coeff)).set_results_name("coeffs")
156
+ # )
157
+ # mos = pp.CaselessLiteral("[MO]") + pp.OneOrMore(mo).set_results_name("mos")
158
+ mos = pp.CaselessLiteral("[MO]") + pp.OneOrMore(
159
+ pp.Regex(r"[^\[]+") # Match everything until the next [ is encountered
160
+ ).set_results_name("mos")
161
+
162
+ # Actual parser
163
+ parser = molden_format + pp.Each(
164
+ [
165
+ pp.Optional(expr)
166
+ for expr in (n_atoms, title, atoms, charges, gto, ang_mom_flags)
167
+ ]
168
+ )
169
+ if with_mos:
170
+ parser += mos
171
+
172
+ res = parser.parse_string(text)
173
+ as_dict = res.asDict()
174
+ if with_mos:
175
+ mos_raw = as_dict["mos"][0]
176
+
177
+ by_mo = [bm.strip().split("\n") for bm in mos_raw.lower().strip().split("sym=")]
178
+ assert by_mo[0] == [""], by_mo[0]
179
+ by_mo = by_mo[1:]
180
+
181
+ as_dict["mos"] = [parse_mo(mo_lines) for mo_lines in by_mo]
182
+ return as_dict
183
+
184
+
185
+ def parse_molden_atoms(data):
186
+ atoms = list()
187
+ coords = list()
188
+ nuc_charges = list()
189
+ for atom in data["atoms"]:
190
+ atoms.append(atom["symbol"])
191
+ coords.extend(atom["xyz"])
192
+ Z = atom["atomic_number"]
193
+ nuc_charges.append(Z)
194
+ atoms = tuple(atoms)
195
+ coords = np.array(coords, dtype=float).flatten()
196
+ nuc_charges = np.array(nuc_charges, dtype=int)
197
+ return atoms, coords, nuc_charges
198
+
199
+
200
+ @file_or_str(".molden", ".input")
201
+ def shells_from_molden(text):
202
+ data = parse_molden(text, with_mos=False)
203
+
204
+ atoms, coords, _ = parse_molden_atoms(data)
205
+ atomic_numbers = [ATOMIC_NUMBERS[atom.lower()] for atom in atoms]
206
+ coords3d = coords.reshape(-1, 3)
207
+
208
+ _shells = list()
209
+ for atom_gtos, center, atomic_num in zip(data["gto"], coords3d, atomic_numbers):
210
+ center_ind = atom_gtos["number"] - 1
211
+ for shell in atom_gtos["shells"]:
212
+ L = shell["ang_mom"]
213
+ exps = shell["exponents"][0]
214
+ coeffs = shell["coeffs"][0]
215
+ shell = Shell(
216
+ L=L,
217
+ center=center,
218
+ coeffs=coeffs,
219
+ exps=exps,
220
+ center_ind=center_ind,
221
+ atomic_num=atomic_num,
222
+ )
223
+ _shells.append(shell)
224
+
225
+ shells = MoldenShells(_shells)
226
+ return shells
227
+
228
+
229
+ @file_or_str(".molden", ".input")
230
+ def wavefunction_from_molden(text, charge=None, shells_func=None, **wf_kwargs):
231
+ """Construct Wavefunction object from .molden file.
232
+
233
+ shells_func is used for ORCA, to modify the contraction coefficients.
234
+ """
235
+ data = parse_molden(text)
236
+ atoms, coords, nuc_charges = parse_molden_atoms(data)
237
+ nuc_charge = sum(nuc_charges)
238
+
239
+ spins = list()
240
+ occ_a = 0.0
241
+ occ_b = 0.0
242
+ Ca = list()
243
+ Cb = list()
244
+ for mo in data["mos"]:
245
+ spin = mo["spin"].lower()
246
+ occ = mo["occup"]
247
+ spins.append(spin)
248
+ coeffs = mo["coeffs"]
249
+ if spin == "alpha":
250
+ occ_a += occ
251
+ Ca.append(coeffs)
252
+ elif spin == "beta":
253
+ occ_b += occ
254
+ Cb.append(coeffs)
255
+ else:
256
+ raise Exception(f"Spin can only be 'alpha' or 'beta', but got '{spin}'!")
257
+ assert occ_a.is_integer
258
+ assert occ_b.is_integer
259
+ occ_a = int(occ_a)
260
+ occ_b = int(occ_b)
261
+
262
+ # MOs must be in columns
263
+ Ca = np.array(Ca, dtype=float).T
264
+ Cb = np.array(Cb, dtype=float).T
265
+ # Restricted calculation
266
+ if Cb.size == 0:
267
+ Cb = Ca.copy()
268
+ occ_a = occ_b = occ_a // 2
269
+ C = np.stack((Ca, Cb))
270
+
271
+ molden_charge = nuc_charge - (occ_a + occ_b)
272
+ if charge is None:
273
+ charge = molden_charge
274
+ # Multiplicity = (2S + 1), S = number of unpaired elecs. * 0.5
275
+ mult = (occ_a - occ_b) + 1
276
+ unrestricted = set(spins) == {"Alpha", "Beta"}
277
+
278
+ if shells_func is None:
279
+ shells_func = shells_from_molden
280
+ shells = shells_func(text)
281
+
282
+ return Wavefunction(
283
+ atoms=atoms,
284
+ coords=coords,
285
+ charge=charge,
286
+ mult=mult,
287
+ unrestricted=unrestricted,
288
+ occ=(occ_a, occ_b),
289
+ C=C,
290
+ bf_type=BFType.PURE_SPHERICAL,
291
+ shells=shells,
292
+ **wf_kwargs,
293
+ )
pysisyphus/io/orca.py ADDED
@@ -0,0 +1,189 @@
1
+ # [1] 10.1016/j.comptc.2014.10.002
2
+ # JANPA: An open source cross-platform implementation of the
3
+ # Natural Population Analysis on the Java platform
4
+ # Nikolaienko, Bulavin, Hovorun, 2014
5
+
6
+ import json
7
+
8
+ import numpy as np
9
+ from scipy.special import gamma
10
+
11
+ from pysisyphus.helpers_pure import file_or_str
12
+ from pysisyphus.io import molden
13
+ from pysisyphus.wavefunction import (
14
+ get_l,
15
+ Shell,
16
+ ORCAShells,
17
+ ORCAMoldenShells,
18
+ Wavefunction,
19
+ )
20
+ from pysisyphus.wavefunction.helpers import BFType
21
+
22
+
23
+ @file_or_str(".json")
24
+ def shells_from_json(text):
25
+ data = json.loads(text)
26
+ atoms = data["Molecule"]["Atoms"]
27
+
28
+ _shells = list()
29
+ for atom in atoms:
30
+ center = np.array(atom["Coords"])
31
+ center_ind = atom["Idx"]
32
+ bfs = atom["BasisFunctions"]
33
+ atomic_num = atom["ElementNumber"]
34
+ for bf in bfs:
35
+ exps = np.array(bf["Exponents"])
36
+ coeffs = np.array(bf["Coefficients"])
37
+ L = get_l(bf["Shell"])
38
+ shell = Shell(
39
+ L=L,
40
+ center=center,
41
+ coeffs=coeffs,
42
+ exps=exps,
43
+ center_ind=center_ind,
44
+ atomic_num=atomic_num,
45
+ )
46
+ _shells.append(shell)
47
+ shells = ORCAShells(_shells)
48
+ return shells
49
+
50
+
51
+ @file_or_str(".json")
52
+ def wavefunction_from_json(text):
53
+ data = json.loads(text)
54
+ mol = data["Molecule"]
55
+
56
+ charge = mol["Charge"]
57
+ mult = mol["Multiplicity"]
58
+ atoms = list()
59
+ coords = list()
60
+ for atom in mol["Atoms"]:
61
+ atom_label = atom["ElementLabel"]
62
+ atom_coords = atom["Coords"]
63
+ atoms.append(atom_label)
64
+ coords.append(atom_coords)
65
+
66
+ unrestricted = (mol["HFTyp"] == "UHF") or (mult != 1)
67
+ mos = mol["MolecularOrbitals"]["MOs"]
68
+ if unrestricted:
69
+ mo_num = len(mos)
70
+ assert mo_num % 2 == 0
71
+ a_num = mo_num // 2
72
+ mos_a = mos[:a_num]
73
+ mos_b = mos[a_num:]
74
+ else: # restricted
75
+ mos_a = mos
76
+ mos_b = list()
77
+
78
+ def get_occ_and_mo_coeffs(mos):
79
+ mo_coeffs = list()
80
+ occ = 0
81
+ for mo in mos:
82
+ _occ = mo["Occupancy"]
83
+ if (_occ % 1) != 0.0:
84
+ raise Exception("Fractional occupations are not handled!")
85
+ occ += int(_occ)
86
+
87
+ mo_coeffs.append(mo["MOCoefficients"])
88
+ # MOs must be in columns
89
+ mo_coeffs = np.array(mo_coeffs).T
90
+ return occ, mo_coeffs
91
+
92
+ occ_a, Ca = get_occ_and_mo_coeffs(mos_a)
93
+ occ_b, Cb = get_occ_and_mo_coeffs(mos_b)
94
+
95
+ # Restricted calculation
96
+ if Cb.size == 0:
97
+ Cb = Ca.copy()
98
+ occ_a = occ_b = occ_a // 2
99
+ C = np.stack((Ca, Cb))
100
+
101
+ shells = shells_from_json(text)
102
+
103
+ return Wavefunction(
104
+ atoms=atoms,
105
+ coords=coords,
106
+ charge=charge,
107
+ mult=mult,
108
+ unrestricted=unrestricted,
109
+ occ=(occ_a, occ_b),
110
+ C=C,
111
+ bf_type=BFType.PURE_SPHERICAL,
112
+ shells=shells,
113
+ )
114
+
115
+
116
+ def radial_integral(l, exponent):
117
+ """
118
+ Integrates
119
+ (r r**l * exp(-exponent * r**2))**2 dr from r=0 to r=oo
120
+ as described in the SI of the JANPA paper [1] (see top of page 8,
121
+ second integral in the square root.
122
+
123
+ In my opinion, the integrals lacks a factor 'r'. Below, some sympy code
124
+ can be found to solve this integral (including 1*r).
125
+
126
+ import sympy as sym
127
+ r, z = sym.symbols("r z", positive=True)
128
+ l = sym.symbols("l", integer=True, positive=True)
129
+ sym.integrate((r * r**l * sym.exp(-z*r**2))**2, (r, 0, sym.oo))
130
+
131
+ The 'solved' integral on page 8 is correct again.
132
+
133
+
134
+
135
+ ⎮ 2
136
+ ⎮ 2 2⋅l -2⋅r ⋅z
137
+ ⎮ r ⋅r ⋅ℯ dr = (2*z)**(-l - 1/2)*gamma(l + 3/2)/(4*z)
138
+
139
+ 0
140
+ """
141
+ return (2 * exponent) ** (-l - 1 / 2) * gamma(l + 3 / 2) / (4 * exponent)
142
+
143
+
144
+ @file_or_str(".molden", ".input")
145
+ def shells_from_molden(text):
146
+ molden_shells = molden.shells_from_molden(text)
147
+
148
+ dividers = {
149
+ 0: 1,
150
+ 1: 1,
151
+ 2: 3,
152
+ 3: 15,
153
+ 4: 35,
154
+ }
155
+
156
+ def fix_contr_coeffs(l, coeffs, exponents):
157
+ """Fix contraction coefficients. Based on equations found in the SI
158
+ of the JANPA paper [1]."""
159
+ l = get_l(l)
160
+ divider = dividers[l]
161
+ rad_ints = radial_integral(l, exponents)
162
+ norms2 = rad_ints * 4 * np.pi / (2 * l + 1) / divider
163
+ norms = np.sqrt(norms2)
164
+ normed_coeffs = coeffs * norms
165
+ return normed_coeffs
166
+
167
+ _shells = list()
168
+ for shell in molden_shells.shells:
169
+ L, center, _, exps, *_ = shell.as_tuple()
170
+ fixed_coeffs = fix_contr_coeffs(L, shell.coeffs_org, exps)
171
+ fixed_shell = Shell(
172
+ L=L,
173
+ center=center,
174
+ coeffs=fixed_coeffs,
175
+ exps=exps,
176
+ center_ind=shell.center_ind,
177
+ atomic_num=shell.atomic_num,
178
+ )
179
+ _shells.append(fixed_shell)
180
+ shells = ORCAMoldenShells(_shells)
181
+ return shells
182
+
183
+
184
+ @file_or_str(".molden", ".input")
185
+ def wavefunction_from_molden(text, charge=None, **wf_kwargs):
186
+ shells_func = shells_from_molden
187
+ return molden.wavefunction_from_molden(
188
+ text, charge=charge, shells_func=shells_func, **wf_kwargs
189
+ )