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,435 @@
1
+ # [1] https://doi.org/10.1016/j.ccr.2018.01.019
2
+ # Quantitative wave function analysis for excited states
3
+ # of transition metal complexes
4
+ # Mai et al., 2018
5
+
6
+ import itertools as it
7
+ from functools import partial
8
+ from typing import Dict, Iterable, List, Optional, Sequence, Tuple
9
+
10
+ import numpy as np
11
+ from numpy.typing import NDArray
12
+
13
+ from pysisyphus.wavefunction.wavefunction import Wavefunction
14
+
15
+
16
+ def norm_ci_coeffs(
17
+ Xa: NDArray[float],
18
+ Ya: NDArray[float],
19
+ Xb: Optional[NDArray[float]] = None,
20
+ Yb: Optional[NDArray[float]] = None,
21
+ restricted_norm: float = 0.5,
22
+ unrestricted_norm: float = 1.0,
23
+ ) -> Tuple[NDArray[float], NDArray[float]]:
24
+ """Normalize transition density matrices.
25
+
26
+ target_norm = (N*X)**2 - (N*Y)**2
27
+ = N**2 * (X**2 - Y**2)
28
+ N**2 = target_norm / (X**2 - Y**2)
29
+ N = sqrt(target_norm / (X**2 - Y**2))
30
+ """
31
+ nstates_a, occ_a, virt_a = Xa.shape
32
+ unrestricted = (Xb is not None) and (Yb is not None)
33
+ if unrestricted:
34
+ nstates_b, occ_b, virt_b = Xb.shape
35
+ assert nstates_a == nstates_b
36
+ assert (occ_a + virt_a) == (occ_b + virt_b)
37
+ nstates = nstates_a
38
+ X = np.concatenate((Xa.reshape(nstates, -1), Xb.reshape(nstates, -1)), axis=1)
39
+ Y = np.concatenate((Ya.reshape(nstates, -1), Yb.reshape(nstates, -1)), axis=1)
40
+ target_norm = unrestricted_norm
41
+ else:
42
+ nstates = nstates_a
43
+ X = Xa.reshape(nstates, -1)
44
+ Y = Ya.reshape(nstates, -1)
45
+ target_norm = restricted_norm
46
+ X_norms, Y_norms = [np.linalg.norm(mat, axis=1) for mat in (X, Y)]
47
+ ci_norms = X_norms**2 - Y_norms**2
48
+ N = np.sqrt(target_norm / ci_norms)
49
+ X *= N[:, None]
50
+ Y *= N[:, None]
51
+ entries_a = occ_a * virt_a
52
+ Xa = X[:, :entries_a].reshape(nstates, occ_a, virt_a)
53
+ Ya = Y[:, :entries_a].reshape(nstates, occ_a, virt_a)
54
+ returns = [Xa, Ya]
55
+ if unrestricted:
56
+ Xb = X[:, entries_a:].reshape(nstates, occ_b, virt_b)
57
+ Yb = Y[:, entries_a:].reshape(nstates, occ_b, virt_b)
58
+ returns.extend([Xb, Yb])
59
+ return returns
60
+
61
+
62
+ def get_state_to_state_transition_density(
63
+ T_a: NDArray[float], T_b: NDArray[float]
64
+ ) -> NDArray[float]:
65
+ """State-to-state transition density.
66
+
67
+ Parameters
68
+ ----------
69
+ T_a
70
+ Transition density matrix for state A of shape (occ, virt).
71
+ T_b
72
+ Transition density matrix for state B of shape (occ, virt).
73
+
74
+ Returns
75
+ -------
76
+ T_ab
77
+ State-to-state transition density of shape (occ+virt, occ+virt).
78
+ """
79
+ assert T_a.shape == T_b.shape
80
+
81
+ electron = T_a.T @ T_b
82
+ hole = T_b @ T_a.T
83
+ occ, virt = T_a.shape
84
+ ov = occ + virt
85
+ T_ab = np.zeros((ov, ov))
86
+ T_ab[:occ, :occ] = -hole
87
+ T_ab[occ:, occ:] = electron
88
+ return T_ab
89
+
90
+
91
+ def ct_numbers(
92
+ C: NDArray[float], occ: int, Ts: NDArray[float], nfrags: int, frag_ao_map: Dict
93
+ ) -> NDArray[float]:
94
+ frag_inds = list(range(nfrags))
95
+ T_full = np.zeros_like(C)
96
+ u, _, vh = np.linalg.svd(C)
97
+ lowdin = u @ vh # (PQ^T) in eq. (17) of [1]
98
+
99
+ omegas = list()
100
+ for T_mo in Ts:
101
+ T = T_full.copy()
102
+ T[:occ, occ:] = T_mo
103
+ Torth = lowdin @ T @ lowdin.T # eq. (17) in [1]
104
+ Torth2 = Torth**2
105
+ state_omegas = list()
106
+ # Pairs of fragments
107
+ for i, j in it.product(frag_inds, frag_inds):
108
+ aos_i = frag_ao_map[i]
109
+ aos_j = frag_ao_map[j]
110
+ om_ij = Torth2[aos_i][:, aos_j].sum() # eq. (16) in [1]
111
+ state_omegas.append(om_ij)
112
+ omegas.append(state_omegas)
113
+ return np.array(omegas)
114
+
115
+
116
+ def ct_numbers_for_states(
117
+ wf: Wavefunction,
118
+ frags: List[List[int]],
119
+ Ta: NDArray[float],
120
+ Tb: Optional[NDArray[float]] = None,
121
+ ):
122
+ """
123
+ Charge-Transfer number for a given wavefunction and fragments.
124
+
125
+ Parameters
126
+ ----------
127
+ wf
128
+ Wavefunction object.
129
+ frags
130
+ List of lists of integers, containing the atom indices of the respective
131
+ fragments.
132
+ Ta
133
+ Alpha-spin transition density matrices of shape (nstates, occ_a, virt_a).
134
+ Tb
135
+ Beta-spin transition density matrices of shape (nstates, occ_a, virt_a).
136
+
137
+ Returns
138
+ -------
139
+ omegas
140
+ Array of shape (nstates, len(frags)**2), containing the charge-transfer
141
+ numbers of every state.
142
+ """
143
+ shells = wf.shells
144
+ frag_ao_map = shells.fragment_ao_map(frags)
145
+ nfrags = len(frags)
146
+
147
+ occ_a, occ_b = wf.occ
148
+ Ca, Cb = wf.C
149
+
150
+ ctn = partial(ct_numbers, nfrags=nfrags, frag_ao_map=frag_ao_map)
151
+ om_a = ctn(Ca, occ_a, Ta)
152
+ if Tb is None:
153
+ om_b = om_a
154
+ else:
155
+ om_b = ctn(Cb, occ_b, Tb)
156
+ omegas = om_a + om_b
157
+ return omegas
158
+
159
+
160
+ def mo_inds_from_tden(
161
+ T: NDArray[float], ci_thresh: float
162
+ ) -> Tuple[NDArray[int], NDArray[int], NDArray[float]]:
163
+ """Indices (from, to) for CI-coefficients above a threshold."""
164
+ assert T.ndim == 2
165
+ occ, _ = T.shape
166
+ from_, to_ = np.where(np.abs(T) > ci_thresh)
167
+ coeffs = T[from_, to_]
168
+ to_ += occ
169
+ return from_, to_, coeffs
170
+
171
+
172
+ def to_pairs(arr_a: Iterable, arr_b: Iterable) -> List[frozenset]:
173
+ """Zip two iterables to a list of frozensets."""
174
+ return [frozenset(sorted(p)) for p in zip(arr_a, arr_b)]
175
+
176
+
177
+ def to_same_basis(
178
+ pairs1: Sequence[frozenset],
179
+ vals1: Iterable,
180
+ pairs2: Sequence[frozenset],
181
+ vals2: Iterable,
182
+ ) -> Tuple[List[int], List[int], NDArray, NDArray]:
183
+ unique_pairs = tuple(set(pairs1 + pairs2))
184
+ zero_vec = np.zeros(len(unique_pairs))
185
+ pair_map = {p: i for i, p in enumerate(unique_pairs)}
186
+
187
+ def sort(pairs, vals):
188
+ vals_sorted = zero_vec.copy()
189
+ for pair, v in zip(pairs, vals):
190
+ vals_sorted[pair_map[pair]] = v
191
+ return vals_sorted
192
+
193
+ vals1_sorted = sort(pairs1, vals1)
194
+ vals2_sorted = sort(pairs2, vals2)
195
+ try:
196
+ from_, to_ = zip(*unique_pairs)
197
+ # Raised when no unique pairs are present
198
+ except ValueError:
199
+ from_, to_ = list(), list()
200
+ return from_, to_, vals1_sorted, vals2_sorted
201
+
202
+
203
+ def ovlp(
204
+ from_A: NDArray[int],
205
+ to_A: NDArray[int],
206
+ vecA: NDArray[float],
207
+ from_B: NDArray[int],
208
+ to_B: NDArray[int],
209
+ vecB: NDArray[float],
210
+ S_MO: NDArray[float],
211
+ ) -> NDArray[float]:
212
+ """Overlap between two transition orbital pairs.
213
+
214
+ According to Eq. (9)"""
215
+ numA = vecA.size
216
+ numB = vecB.size
217
+ S = np.zeros((numA, numB))
218
+
219
+ for i, coeff_a in enumerate(vecA):
220
+ for j, coeff_b in enumerate(vecB):
221
+ s_occ = S_MO[from_A[i], from_B[j]]
222
+ s_vir = S_MO[to_A[i], to_B[j]]
223
+ # Eq. (9)
224
+ S[i, j] = coeff_a / abs(coeff_a) * coeff_b / abs(coeff_b) * s_occ * s_vir
225
+ return S
226
+
227
+
228
+ def r_diff(
229
+ vecP_from: NDArray[float], vec_to: NDArray[float], t_to: NDArray[float]
230
+ ) -> float:
231
+ abs_vec_to = np.abs(vec_to)
232
+
233
+ def diff(vec_to):
234
+ """Eq. (14)."""
235
+ return np.abs(np.abs(vecP_from + vec_to) * t_to).sum()
236
+
237
+ r_plus = diff(abs_vec_to)
238
+ r_minus = diff(-1 * abs_vec_to)
239
+ r = min(r_plus, r_minus)
240
+ return r
241
+
242
+
243
+ def parse_tden(
244
+ T: NDArray[float], thresh: float
245
+ ) -> Tuple[List[frozenset], NDArray[int], NDArray[int], NDArray[float]]:
246
+ from_T, to_T, coeffs = mo_inds_from_tden(T, thresh)
247
+ pairs = to_pairs(from_T, to_T)
248
+ return pairs, from_T, to_T, coeffs
249
+
250
+
251
+ def rAB(
252
+ TXA: NDArray[float],
253
+ TYA: NDArray[float],
254
+ TXB: NDArray[float],
255
+ TYB: NDArray[float],
256
+ S_MO: NDArray[float],
257
+ exc_thresh: float = 0.05,
258
+ deexc_thresh: float = 0.02,
259
+ ) -> float:
260
+ """Transition-orbital-pair overlaps.
261
+
262
+ See 'Transition orbital projection approach for excited state tracking' in
263
+ J. Chem. Phys. 156, 214104 (2022); https://doi.org/10.1063/5.0081207
264
+
265
+ Parameters
266
+ ----------
267
+ TXA
268
+ Excitation coefficient (X) vector for 1 state at geometry A.
269
+ TYA
270
+ Deexcitation coefficient (Y) vector for 1 state at geometry A.
271
+ TXB
272
+ Excitation coefficient (X) vector for 1 state at geometry B.
273
+ TYB
274
+ Deexcitation coefficient (Y) vector for 1 state at geometry B.
275
+ S_MO
276
+ Matrix containing overlaps between the MOs at geometry A and B.
277
+ exc_thresh
278
+ Coefficient threshold up to which CI-coefficients from TXA and TXA
279
+ are still considered.
280
+ deexc_thresh
281
+ Coefficient threshold up to which CI-coefficients from TYA and TYA
282
+ are still considered.
283
+ """
284
+ # A
285
+ a_pairs_A, a_from_A, a_to_A, alphaA = parse_tden(TXA, exc_thresh)
286
+ b_pairs_A, b_from_A, b_to_A, betaA = parse_tden(TYA, deexc_thresh)
287
+ a_from_A, a_to_A, alphaA, betaA = to_same_basis(a_pairs_A, alphaA, b_pairs_A, betaA)
288
+ b_from_A = a_from_A
289
+ b_to_A = a_to_A
290
+ # B
291
+ a_pairs_B, a_from_B, a_to_B, alphaB = parse_tden(TXB, exc_thresh)
292
+ b_pairs_B, b_from_B, b_to_B, betaB = parse_tden(TYB, deexc_thresh)
293
+ a_from_B, a_to_B, alphaB, betaB = to_same_basis(a_pairs_B, alphaB, b_pairs_B, betaB)
294
+ b_from_B = a_from_B
295
+ b_to_B = a_to_B
296
+
297
+ # Eqs. (7) and (8)
298
+ XA = alphaA + betaA
299
+ YA = alphaA - betaA
300
+ XB = alphaB + betaB
301
+ YB = alphaB - betaB
302
+
303
+ # Eqs. (10) and (11)
304
+ SX = ovlp(a_from_A, a_to_A, XA, a_from_B, a_to_B, XB, S_MO)
305
+ XPA = (np.abs(XA)[None, :] @ SX).flatten()
306
+ XPB = (SX @ np.abs(XB)[:, None]).flatten()
307
+
308
+ SY = ovlp(b_from_A, b_to_A, YA, b_from_B, b_to_B, YB, S_MO)
309
+ YPA = (np.abs(YA)[None, :] @ SY).flatten()
310
+ YPB = (SY @ np.abs(YB)[:, None]).flatten()
311
+
312
+ # Eq. (13) in the original paper includes a factor 2, probably because the algorithm
313
+ # is only formulated for closed-shell cases. Here, we exclude this factor and expect
314
+ # that closed-shell/open-shell transition density matrices are normalized differently,
315
+ # e.g. as done in 'norm_ci_coeffs'
316
+ tA = alphaA**2 - betaA**2
317
+ tB = alphaB**2 - betaB**2
318
+
319
+ rXAB = r_diff(XPA, XB, tB) # r_X^A->B
320
+ rYAB = r_diff(YPA, YB, tB) # r_Y^A->B
321
+ rXBA = r_diff(XPB, XA, tA) # r_X^B->A
322
+ rYBA = r_diff(YPB, YA, tA) # r_Y^B->A
323
+ # Eq. (15)
324
+ r = 0.5 * (rXAB + rYAB + rXBA + rYBA)
325
+ return r
326
+
327
+
328
+ def top_differences(XA, YA, XB, YB, S_MO):
329
+ states_A = XA.shape[0]
330
+ states_B = XB.shape[0]
331
+
332
+ rs = list()
333
+ for xai, yai in zip(XA, YA):
334
+ for xbj, ybj in zip(XB, YB):
335
+ r = rAB(xai, yai, xbj, ybj, S_MO)
336
+ rs.append(r)
337
+ rs = np.array(rs).reshape(states_A, states_B)
338
+ return rs
339
+
340
+
341
+ def tden_overlaps(
342
+ C_1: NDArray[float],
343
+ ci_coeffs1: NDArray[float],
344
+ C_2: NDArray[:float],
345
+ ci_coeffs2: NDArray[float],
346
+ S_AO: NDArray[float],
347
+ ):
348
+ """
349
+ Transition density overlaps.
350
+
351
+ Parameters
352
+ ----------
353
+ mo_coeffs1 : ndarray, shape (MOs, AOs)
354
+ MO coefficient matrix. MOs are expected to be in columns.
355
+ mo_coeffs2 : ndarray
356
+ See mo_coeffs1.
357
+ ci_coeffs1 : ndarray, shape(occ. MOs, MOs)
358
+ CI-coefficient matrix.
359
+ ci_coeffs2 : ndarray, shape(occ. MOs, MOs)
360
+ See ci_coeffs1.
361
+ S_AO : ndarray, shape(AOs1, AOs2)
362
+ Double molcule AO overlaps.
363
+ """
364
+ # Total number of molecular orbitals for ci_coeffs1 and ci_coeffs2 (occ + virt)
365
+ nmo1, nmo2 = [sum(ci_coeffs.shape[1:]) for ci_coeffs in (ci_coeffs1, ci_coeffs2)]
366
+ assert S_AO.shape == (nmo1, nmo2)
367
+ _, occ1, _ = ci_coeffs1.shape
368
+ _, occ2, _ = ci_coeffs2.shape
369
+ # MO overlaps, and the respective sub-matrices (occ x occ), (virt x virt)
370
+ S_MO = C_1.T @ S_AO @ C_2
371
+ S_MO_occ = S_MO[:occ1, :occ2]
372
+ S_MO_vir = S_MO[occ1:, occ2:]
373
+
374
+ # Thanks Philipp and Klaus!
375
+ overlaps = np.zeros((ci_coeffs1.shape[0], ci_coeffs2.shape[0]))
376
+ for i, state1 in enumerate(ci_coeffs1):
377
+ precontr = S_MO_vir.T @ state1.T @ S_MO_occ
378
+ for j, state2 in enumerate(ci_coeffs2):
379
+ overlaps[i, j] = np.trace(precontr @ state2)
380
+
381
+ """
382
+ overlaps = np.einsum(
383
+ "mil,ij,njk,kl->mn",
384
+ ci_coeffs1,
385
+ S_MO_occ,
386
+ ci_coeffs2,
387
+ S_MO_vir.T,
388
+ optimize=["einsum_path", (0, 3), (1, 2), (0, 1)],
389
+ )
390
+ """
391
+ return overlaps
392
+
393
+
394
+ ###############################
395
+ # Natural Transition Orbitals #
396
+ ###############################
397
+
398
+
399
+ """
400
+ def nto_overlaps(ntos_1, ntos_2, ao_ovlp):
401
+ states1 = len(ntos_1)
402
+ states2 = len(ntos_2)
403
+ ovlps = np.zeros((states1, states2))
404
+ for i in range(states1):
405
+ n_i = ntos_1[i]
406
+ l_i = n_i.lambdas[:, None]
407
+ ntos_i = l_i * n_i.ntos
408
+ for j in range(states2):
409
+ n_j = ntos_2[j]
410
+ l_j = n_j.lambdas[:, None]
411
+ ntos_j = l_j * n_j.ntos
412
+ ovlp = np.sum(np.abs(ntos_i.dot(ao_ovlp).dot(ntos_j.T)))
413
+ ovlps[i, j] = ovlp
414
+ return ovlps
415
+
416
+ def nto_org_overlaps(ntos_1, ntos_2, ao_ovlp, nto_thresh=0.3):
417
+ states_1 = len(ntos_1)
418
+ states_2 = len(ntos_2)
419
+ ovlps = np.zeros((states_1, states_2))
420
+
421
+ for i in range(states_1):
422
+ n_i = ntos_1[i]
423
+ l_i = n_i.lambdas[:, None]
424
+ ntos_i = n_i.ntos[(l_i >= nto_thresh).flatten()]
425
+ l_i_big = l_i[l_i >= nto_thresh]
426
+ for j in range(states_2):
427
+ n_j = ntos_2[j]
428
+ l_j = n_j.lambdas[:, None]
429
+ ntos_j = n_j.ntos[(l_j >= nto_thresh).flatten()]
430
+ ovlp = np.sum(
431
+ l_i_big[:, None] * np.abs(ntos_i.dot(ao_ovlp).dot(ntos_j.T))
432
+ )
433
+ ovlps[i, j] = ovlp
434
+ return ovlps
435
+ """