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.
- hessian_ff/__init__.py +50 -0
- hessian_ff/analytical_hessian.py +609 -0
- hessian_ff/constants.py +46 -0
- hessian_ff/forcefield.py +339 -0
- hessian_ff/loaders.py +608 -0
- hessian_ff/native/Makefile +8 -0
- hessian_ff/native/__init__.py +28 -0
- hessian_ff/native/analytical_hessian.py +88 -0
- hessian_ff/native/analytical_hessian_ext.cpp +258 -0
- hessian_ff/native/bonded.py +82 -0
- hessian_ff/native/bonded_ext.cpp +640 -0
- hessian_ff/native/loader.py +349 -0
- hessian_ff/native/nonbonded.py +118 -0
- hessian_ff/native/nonbonded_ext.cpp +1150 -0
- hessian_ff/prmtop_parmed.py +23 -0
- hessian_ff/system.py +107 -0
- hessian_ff/terms/__init__.py +14 -0
- hessian_ff/terms/angle.py +73 -0
- hessian_ff/terms/bond.py +44 -0
- hessian_ff/terms/cmap.py +406 -0
- hessian_ff/terms/dihedral.py +141 -0
- hessian_ff/terms/nonbonded.py +209 -0
- hessian_ff/tests/__init__.py +0 -0
- hessian_ff/tests/conftest.py +75 -0
- hessian_ff/tests/data/small/complex.parm7 +1346 -0
- hessian_ff/tests/data/small/complex.pdb +125 -0
- hessian_ff/tests/data/small/complex.rst7 +63 -0
- hessian_ff/tests/test_coords_input.py +44 -0
- hessian_ff/tests/test_energy_force.py +49 -0
- hessian_ff/tests/test_hessian.py +137 -0
- hessian_ff/tests/test_smoke.py +18 -0
- hessian_ff/tests/test_validation.py +40 -0
- hessian_ff/workflows.py +889 -0
- mlmm/__init__.py +36 -0
- mlmm/__main__.py +7 -0
- mlmm/_version.py +34 -0
- mlmm/add_elem_info.py +374 -0
- mlmm/advanced_help.py +91 -0
- mlmm/align_freeze_atoms.py +601 -0
- mlmm/all.py +3535 -0
- mlmm/bond_changes.py +231 -0
- mlmm/bool_compat.py +223 -0
- mlmm/cli.py +574 -0
- mlmm/cli_utils.py +166 -0
- mlmm/default_group.py +337 -0
- mlmm/defaults.py +467 -0
- mlmm/define_layer.py +526 -0
- mlmm/dft.py +1041 -0
- mlmm/energy_diagram.py +253 -0
- mlmm/extract.py +2213 -0
- mlmm/fix_altloc.py +464 -0
- mlmm/freq.py +1406 -0
- mlmm/harmonic_constraints.py +140 -0
- mlmm/hessian_cache.py +44 -0
- mlmm/hessian_calc.py +174 -0
- mlmm/irc.py +638 -0
- mlmm/mlmm_calc.py +2262 -0
- mlmm/mm_parm.py +945 -0
- mlmm/oniom_export.py +1983 -0
- mlmm/oniom_import.py +457 -0
- mlmm/opt.py +1742 -0
- mlmm/path_opt.py +1353 -0
- mlmm/path_search.py +2299 -0
- mlmm/preflight.py +88 -0
- mlmm/py.typed +1 -0
- mlmm/pysis_runner.py +45 -0
- mlmm/scan.py +1047 -0
- mlmm/scan2d.py +1226 -0
- mlmm/scan3d.py +1265 -0
- mlmm/scan_common.py +184 -0
- mlmm/summary_log.py +736 -0
- mlmm/trj2fig.py +448 -0
- mlmm/tsopt.py +2871 -0
- mlmm/utils.py +2309 -0
- mlmm/xtb_embedcharge_correction.py +475 -0
- mlmm_toolkit-0.2.2.dev0.dist-info/METADATA +1159 -0
- mlmm_toolkit-0.2.2.dev0.dist-info/RECORD +372 -0
- mlmm_toolkit-0.2.2.dev0.dist-info/WHEEL +5 -0
- mlmm_toolkit-0.2.2.dev0.dist-info/entry_points.txt +2 -0
- mlmm_toolkit-0.2.2.dev0.dist-info/licenses/LICENSE +674 -0
- mlmm_toolkit-0.2.2.dev0.dist-info/top_level.txt +4 -0
- pysisyphus/Geometry.py +1667 -0
- pysisyphus/LICENSE +674 -0
- pysisyphus/TableFormatter.py +63 -0
- pysisyphus/TablePrinter.py +74 -0
- pysisyphus/__init__.py +12 -0
- pysisyphus/calculators/AFIR.py +452 -0
- pysisyphus/calculators/AnaPot.py +20 -0
- pysisyphus/calculators/AnaPot2.py +48 -0
- pysisyphus/calculators/AnaPot3.py +12 -0
- pysisyphus/calculators/AnaPot4.py +20 -0
- pysisyphus/calculators/AnaPotBase.py +337 -0
- pysisyphus/calculators/AnaPotCBM.py +25 -0
- pysisyphus/calculators/AtomAtomTransTorque.py +154 -0
- pysisyphus/calculators/CFOUR.py +250 -0
- pysisyphus/calculators/Calculator.py +844 -0
- pysisyphus/calculators/CerjanMiller.py +24 -0
- pysisyphus/calculators/Composite.py +123 -0
- pysisyphus/calculators/ConicalIntersection.py +171 -0
- pysisyphus/calculators/DFTBp.py +430 -0
- pysisyphus/calculators/DFTD3.py +66 -0
- pysisyphus/calculators/DFTD4.py +84 -0
- pysisyphus/calculators/Dalton.py +61 -0
- pysisyphus/calculators/Dimer.py +681 -0
- pysisyphus/calculators/Dummy.py +20 -0
- pysisyphus/calculators/EGO.py +76 -0
- pysisyphus/calculators/EnergyMin.py +224 -0
- pysisyphus/calculators/ExternalPotential.py +264 -0
- pysisyphus/calculators/FakeASE.py +35 -0
- pysisyphus/calculators/FourWellAnaPot.py +28 -0
- pysisyphus/calculators/FreeEndNEBPot.py +39 -0
- pysisyphus/calculators/Gaussian09.py +18 -0
- pysisyphus/calculators/Gaussian16.py +726 -0
- pysisyphus/calculators/HardSphere.py +159 -0
- pysisyphus/calculators/IDPPCalculator.py +49 -0
- pysisyphus/calculators/IPIClient.py +133 -0
- pysisyphus/calculators/IPIServer.py +234 -0
- pysisyphus/calculators/LEPSBase.py +24 -0
- pysisyphus/calculators/LEPSExpr.py +139 -0
- pysisyphus/calculators/LennardJones.py +80 -0
- pysisyphus/calculators/MOPAC.py +219 -0
- pysisyphus/calculators/MullerBrownSympyPot.py +51 -0
- pysisyphus/calculators/MultiCalc.py +85 -0
- pysisyphus/calculators/NFK.py +45 -0
- pysisyphus/calculators/OBabel.py +87 -0
- pysisyphus/calculators/ONIOMv2.py +1129 -0
- pysisyphus/calculators/ORCA.py +893 -0
- pysisyphus/calculators/ORCA5.py +6 -0
- pysisyphus/calculators/OpenMM.py +88 -0
- pysisyphus/calculators/OpenMolcas.py +281 -0
- pysisyphus/calculators/OverlapCalculator.py +908 -0
- pysisyphus/calculators/Psi4.py +218 -0
- pysisyphus/calculators/PyPsi4.py +37 -0
- pysisyphus/calculators/PySCF.py +341 -0
- pysisyphus/calculators/PyXTB.py +73 -0
- pysisyphus/calculators/QCEngine.py +106 -0
- pysisyphus/calculators/Rastrigin.py +22 -0
- pysisyphus/calculators/Remote.py +76 -0
- pysisyphus/calculators/Rosenbrock.py +15 -0
- pysisyphus/calculators/SocketCalc.py +97 -0
- pysisyphus/calculators/TIP3P.py +111 -0
- pysisyphus/calculators/TransTorque.py +161 -0
- pysisyphus/calculators/Turbomole.py +965 -0
- pysisyphus/calculators/VRIPot.py +37 -0
- pysisyphus/calculators/WFOWrapper.py +333 -0
- pysisyphus/calculators/WFOWrapper2.py +341 -0
- pysisyphus/calculators/XTB.py +418 -0
- pysisyphus/calculators/__init__.py +81 -0
- pysisyphus/calculators/cosmo_data.py +139 -0
- pysisyphus/calculators/parser.py +150 -0
- pysisyphus/color.py +19 -0
- pysisyphus/config.py +133 -0
- pysisyphus/constants.py +65 -0
- pysisyphus/cos/AdaptiveNEB.py +230 -0
- pysisyphus/cos/ChainOfStates.py +725 -0
- pysisyphus/cos/FreeEndNEB.py +25 -0
- pysisyphus/cos/FreezingString.py +103 -0
- pysisyphus/cos/GrowingChainOfStates.py +71 -0
- pysisyphus/cos/GrowingNT.py +309 -0
- pysisyphus/cos/GrowingString.py +508 -0
- pysisyphus/cos/NEB.py +189 -0
- pysisyphus/cos/SimpleZTS.py +64 -0
- pysisyphus/cos/__init__.py +22 -0
- pysisyphus/cos/stiffness.py +199 -0
- pysisyphus/drivers/__init__.py +17 -0
- pysisyphus/drivers/afir.py +855 -0
- pysisyphus/drivers/barriers.py +271 -0
- pysisyphus/drivers/birkholz.py +138 -0
- pysisyphus/drivers/cluster.py +318 -0
- pysisyphus/drivers/diabatization.py +133 -0
- pysisyphus/drivers/merge.py +368 -0
- pysisyphus/drivers/merge_mol2.py +322 -0
- pysisyphus/drivers/opt.py +375 -0
- pysisyphus/drivers/perf.py +91 -0
- pysisyphus/drivers/pka.py +52 -0
- pysisyphus/drivers/precon_pos_rot.py +669 -0
- pysisyphus/drivers/rates.py +480 -0
- pysisyphus/drivers/replace.py +219 -0
- pysisyphus/drivers/scan.py +212 -0
- pysisyphus/drivers/spectrum.py +166 -0
- pysisyphus/drivers/thermo.py +31 -0
- pysisyphus/dynamics/Gaussian.py +103 -0
- pysisyphus/dynamics/__init__.py +20 -0
- pysisyphus/dynamics/colvars.py +136 -0
- pysisyphus/dynamics/driver.py +297 -0
- pysisyphus/dynamics/helpers.py +256 -0
- pysisyphus/dynamics/lincs.py +105 -0
- pysisyphus/dynamics/mdp.py +364 -0
- pysisyphus/dynamics/rattle.py +121 -0
- pysisyphus/dynamics/thermostats.py +128 -0
- pysisyphus/dynamics/wigner.py +266 -0
- pysisyphus/elem_data.py +3473 -0
- pysisyphus/exceptions.py +2 -0
- pysisyphus/filtertrj.py +69 -0
- pysisyphus/helpers.py +623 -0
- pysisyphus/helpers_pure.py +649 -0
- pysisyphus/init_logging.py +50 -0
- pysisyphus/intcoords/Bend.py +69 -0
- pysisyphus/intcoords/Bend2.py +25 -0
- pysisyphus/intcoords/BondedFragment.py +32 -0
- pysisyphus/intcoords/Cartesian.py +41 -0
- pysisyphus/intcoords/CartesianCoords.py +140 -0
- pysisyphus/intcoords/Coords.py +56 -0
- pysisyphus/intcoords/DLC.py +197 -0
- pysisyphus/intcoords/DistanceFunction.py +34 -0
- pysisyphus/intcoords/DummyImproper.py +70 -0
- pysisyphus/intcoords/DummyTorsion.py +72 -0
- pysisyphus/intcoords/LinearBend.py +105 -0
- pysisyphus/intcoords/LinearDisplacement.py +80 -0
- pysisyphus/intcoords/OutOfPlane.py +59 -0
- pysisyphus/intcoords/PrimTypes.py +286 -0
- pysisyphus/intcoords/Primitive.py +137 -0
- pysisyphus/intcoords/RedundantCoords.py +659 -0
- pysisyphus/intcoords/RobustTorsion.py +59 -0
- pysisyphus/intcoords/Rotation.py +147 -0
- pysisyphus/intcoords/Stretch.py +31 -0
- pysisyphus/intcoords/Torsion.py +101 -0
- pysisyphus/intcoords/Torsion2.py +25 -0
- pysisyphus/intcoords/Translation.py +45 -0
- pysisyphus/intcoords/__init__.py +61 -0
- pysisyphus/intcoords/augment_bonds.py +126 -0
- pysisyphus/intcoords/derivatives.py +10512 -0
- pysisyphus/intcoords/eval.py +80 -0
- pysisyphus/intcoords/exceptions.py +37 -0
- pysisyphus/intcoords/findiffs.py +48 -0
- pysisyphus/intcoords/generate_derivatives.py +414 -0
- pysisyphus/intcoords/helpers.py +235 -0
- pysisyphus/intcoords/logging_conf.py +10 -0
- pysisyphus/intcoords/mp_derivatives.py +10836 -0
- pysisyphus/intcoords/setup.py +962 -0
- pysisyphus/intcoords/setup_fast.py +176 -0
- pysisyphus/intcoords/update.py +272 -0
- pysisyphus/intcoords/valid.py +89 -0
- pysisyphus/interpolate/Geodesic.py +93 -0
- pysisyphus/interpolate/IDPP.py +55 -0
- pysisyphus/interpolate/Interpolator.py +116 -0
- pysisyphus/interpolate/LST.py +70 -0
- pysisyphus/interpolate/Redund.py +152 -0
- pysisyphus/interpolate/__init__.py +9 -0
- pysisyphus/interpolate/helpers.py +34 -0
- pysisyphus/io/__init__.py +22 -0
- pysisyphus/io/aomix.py +178 -0
- pysisyphus/io/cjson.py +24 -0
- pysisyphus/io/crd.py +101 -0
- pysisyphus/io/cube.py +220 -0
- pysisyphus/io/fchk.py +184 -0
- pysisyphus/io/hdf5.py +49 -0
- pysisyphus/io/hessian.py +72 -0
- pysisyphus/io/mol2.py +146 -0
- pysisyphus/io/molden.py +293 -0
- pysisyphus/io/orca.py +189 -0
- pysisyphus/io/pdb.py +269 -0
- pysisyphus/io/psf.py +79 -0
- pysisyphus/io/pubchem.py +31 -0
- pysisyphus/io/qcschema.py +34 -0
- pysisyphus/io/sdf.py +29 -0
- pysisyphus/io/xyz.py +61 -0
- pysisyphus/io/zmat.py +175 -0
- pysisyphus/irc/DWI.py +108 -0
- pysisyphus/irc/DampedVelocityVerlet.py +134 -0
- pysisyphus/irc/Euler.py +22 -0
- pysisyphus/irc/EulerPC.py +345 -0
- pysisyphus/irc/GonzalezSchlegel.py +187 -0
- pysisyphus/irc/IMKMod.py +164 -0
- pysisyphus/irc/IRC.py +878 -0
- pysisyphus/irc/IRCDummy.py +10 -0
- pysisyphus/irc/Instanton.py +307 -0
- pysisyphus/irc/LQA.py +53 -0
- pysisyphus/irc/ModeKill.py +136 -0
- pysisyphus/irc/ParamPlot.py +53 -0
- pysisyphus/irc/RK4.py +36 -0
- pysisyphus/irc/__init__.py +31 -0
- pysisyphus/irc/initial_displ.py +219 -0
- pysisyphus/linalg.py +411 -0
- pysisyphus/line_searches/Backtracking.py +88 -0
- pysisyphus/line_searches/HagerZhang.py +184 -0
- pysisyphus/line_searches/LineSearch.py +232 -0
- pysisyphus/line_searches/StrongWolfe.py +108 -0
- pysisyphus/line_searches/__init__.py +9 -0
- pysisyphus/line_searches/interpol.py +15 -0
- pysisyphus/modefollow/NormalMode.py +40 -0
- pysisyphus/modefollow/__init__.py +10 -0
- pysisyphus/modefollow/davidson.py +199 -0
- pysisyphus/modefollow/lanczos.py +95 -0
- pysisyphus/optimizers/BFGS.py +99 -0
- pysisyphus/optimizers/BacktrackingOptimizer.py +113 -0
- pysisyphus/optimizers/ConjugateGradient.py +98 -0
- pysisyphus/optimizers/CubicNewton.py +75 -0
- pysisyphus/optimizers/FIRE.py +113 -0
- pysisyphus/optimizers/HessianOptimizer.py +1176 -0
- pysisyphus/optimizers/LBFGS.py +228 -0
- pysisyphus/optimizers/LayerOpt.py +411 -0
- pysisyphus/optimizers/MicroOptimizer.py +169 -0
- pysisyphus/optimizers/NCOptimizer.py +90 -0
- pysisyphus/optimizers/Optimizer.py +1084 -0
- pysisyphus/optimizers/PreconLBFGS.py +260 -0
- pysisyphus/optimizers/PreconSteepestDescent.py +7 -0
- pysisyphus/optimizers/QuickMin.py +74 -0
- pysisyphus/optimizers/RFOptimizer.py +181 -0
- pysisyphus/optimizers/RSA.py +99 -0
- pysisyphus/optimizers/StabilizedQNMethod.py +248 -0
- pysisyphus/optimizers/SteepestDescent.py +23 -0
- pysisyphus/optimizers/StringOptimizer.py +173 -0
- pysisyphus/optimizers/__init__.py +41 -0
- pysisyphus/optimizers/closures.py +301 -0
- pysisyphus/optimizers/cls_map.py +58 -0
- pysisyphus/optimizers/exceptions.py +6 -0
- pysisyphus/optimizers/gdiis.py +280 -0
- pysisyphus/optimizers/guess_hessians.py +311 -0
- pysisyphus/optimizers/hessian_updates.py +355 -0
- pysisyphus/optimizers/poly_fit.py +285 -0
- pysisyphus/optimizers/precon.py +153 -0
- pysisyphus/optimizers/restrict_step.py +24 -0
- pysisyphus/pack.py +172 -0
- pysisyphus/peakdetect.py +948 -0
- pysisyphus/plot.py +1031 -0
- pysisyphus/run.py +2106 -0
- pysisyphus/socket_helper.py +74 -0
- pysisyphus/stocastic/FragmentKick.py +132 -0
- pysisyphus/stocastic/Kick.py +81 -0
- pysisyphus/stocastic/Pipeline.py +303 -0
- pysisyphus/stocastic/__init__.py +21 -0
- pysisyphus/stocastic/align.py +127 -0
- pysisyphus/testing.py +96 -0
- pysisyphus/thermo.py +156 -0
- pysisyphus/trj.py +824 -0
- pysisyphus/tsoptimizers/RSIRFOptimizer.py +56 -0
- pysisyphus/tsoptimizers/RSPRFOptimizer.py +182 -0
- pysisyphus/tsoptimizers/TRIM.py +59 -0
- pysisyphus/tsoptimizers/TSHessianOptimizer.py +463 -0
- pysisyphus/tsoptimizers/__init__.py +23 -0
- pysisyphus/wavefunction/Basis.py +239 -0
- pysisyphus/wavefunction/DIIS.py +76 -0
- pysisyphus/wavefunction/__init__.py +25 -0
- pysisyphus/wavefunction/build_ext.py +42 -0
- pysisyphus/wavefunction/cart2sph.py +190 -0
- pysisyphus/wavefunction/diabatization.py +304 -0
- pysisyphus/wavefunction/excited_states.py +435 -0
- pysisyphus/wavefunction/gen_ints.py +1811 -0
- pysisyphus/wavefunction/helpers.py +104 -0
- pysisyphus/wavefunction/ints/__init__.py +0 -0
- pysisyphus/wavefunction/ints/boys.py +193 -0
- pysisyphus/wavefunction/ints/boys_table_N_64_xasym_27.1_step_0.01.npy +0 -0
- pysisyphus/wavefunction/ints/cart_gto3d.py +176 -0
- pysisyphus/wavefunction/ints/coulomb3d.py +25928 -0
- pysisyphus/wavefunction/ints/diag_quadrupole3d.py +10036 -0
- pysisyphus/wavefunction/ints/dipole3d.py +8762 -0
- pysisyphus/wavefunction/ints/int2c2e3d.py +7198 -0
- pysisyphus/wavefunction/ints/int3c2e3d_sph.py +65040 -0
- pysisyphus/wavefunction/ints/kinetic3d.py +8240 -0
- pysisyphus/wavefunction/ints/ovlp3d.py +3777 -0
- pysisyphus/wavefunction/ints/quadrupole3d.py +15054 -0
- pysisyphus/wavefunction/ints/self_ovlp3d.py +198 -0
- pysisyphus/wavefunction/localization.py +458 -0
- pysisyphus/wavefunction/multipole.py +159 -0
- pysisyphus/wavefunction/normalization.py +36 -0
- pysisyphus/wavefunction/pop_analysis.py +134 -0
- pysisyphus/wavefunction/shells.py +1171 -0
- pysisyphus/wavefunction/wavefunction.py +504 -0
- pysisyphus/wrapper/__init__.py +11 -0
- pysisyphus/wrapper/exceptions.py +2 -0
- pysisyphus/wrapper/jmol.py +120 -0
- pysisyphus/wrapper/mwfn.py +169 -0
- pysisyphus/wrapper/packmol.py +71 -0
- pysisyphus/xyzloader.py +168 -0
- pysisyphus/yaml_mods.py +45 -0
- thermoanalysis/LICENSE +674 -0
- thermoanalysis/QCData.py +244 -0
- thermoanalysis/__init__.py +0 -0
- thermoanalysis/config.py +3 -0
- thermoanalysis/constants.py +20 -0
- thermoanalysis/thermo.py +1011 -0
|
@@ -0,0 +1,271 @@
|
|
|
1
|
+
from pathlib import Path
|
|
2
|
+
from time import time
|
|
3
|
+
|
|
4
|
+
import numpy as np
|
|
5
|
+
|
|
6
|
+
from pysisyphus.config import T_DEFAULT, p_DEFAULT
|
|
7
|
+
from pysisyphus.constants import AU2KJPERMOL
|
|
8
|
+
from pysisyphus.helpers_pure import highlight_text, standard_state_corr
|
|
9
|
+
from pysisyphus.TablePrinter import TablePrinter
|
|
10
|
+
from pysisyphus.thermo import print_thermoanalysis
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def do_endopt_ts_barriers(
|
|
14
|
+
ts_geom,
|
|
15
|
+
left_geoms,
|
|
16
|
+
right_geoms=None,
|
|
17
|
+
left_fns=None,
|
|
18
|
+
right_fns=None,
|
|
19
|
+
do_thermo=False,
|
|
20
|
+
T=T_DEFAULT,
|
|
21
|
+
p=p_DEFAULT,
|
|
22
|
+
calc_getter=None,
|
|
23
|
+
solv_calc_getter=None,
|
|
24
|
+
do_standard_state_corr=False,
|
|
25
|
+
):
|
|
26
|
+
print(highlight_text("Barrier heights after end optimization(s)"))
|
|
27
|
+
print()
|
|
28
|
+
|
|
29
|
+
# Only allow standard state correction when solvent calculator is specified.
|
|
30
|
+
do_ssc = do_standard_state_corr and (solv_calc_getter is not None)
|
|
31
|
+
ssc = standard_state_corr(T=T, p=p) if do_ssc else 0.0
|
|
32
|
+
|
|
33
|
+
if right_geoms is None:
|
|
34
|
+
right_geoms = []
|
|
35
|
+
|
|
36
|
+
def set_fns(fns, geoms):
|
|
37
|
+
if fns is None:
|
|
38
|
+
fns = ["" for geom in geoms]
|
|
39
|
+
else:
|
|
40
|
+
fns = [Path(fn).name for fn in fns]
|
|
41
|
+
return fns
|
|
42
|
+
left_fns = set_fns(left_fns, left_geoms)
|
|
43
|
+
right_fns = set_fns(right_fns, left_geoms)
|
|
44
|
+
ts_fn = "TS"
|
|
45
|
+
|
|
46
|
+
ts_atom_num = len(ts_geom.atoms)
|
|
47
|
+
|
|
48
|
+
def drop_total_geom(geoms):
|
|
49
|
+
atom_nums = [len(geom.atoms) for geom in geoms]
|
|
50
|
+
tot_atom_num = sum(atom_nums)
|
|
51
|
+
total_geom = None
|
|
52
|
+
if tot_atom_num > ts_atom_num:
|
|
53
|
+
total_ind = atom_nums.index(max(atom_nums))
|
|
54
|
+
total_geom = geoms[total_ind]
|
|
55
|
+
geoms = [geom for i, geom in enumerate(geoms) if i != total_ind]
|
|
56
|
+
return geoms, total_geom
|
|
57
|
+
|
|
58
|
+
left_geoms, left_total_geom = drop_total_geom(left_geoms)
|
|
59
|
+
right_geoms, right_total_geom = drop_total_geom(right_geoms)
|
|
60
|
+
|
|
61
|
+
def tot_atom_num(geoms):
|
|
62
|
+
return sum([len(geom.atoms) for geom in geoms])
|
|
63
|
+
|
|
64
|
+
left_atom_num = tot_atom_num(left_geoms)
|
|
65
|
+
assert left_atom_num == ts_atom_num, (
|
|
66
|
+
f"Atom number mismatch between TS ({ts_atom_num} atoms) and "
|
|
67
|
+
f"left side ({left_atom_num} atoms)! Aborting barrier calculation"
|
|
68
|
+
)
|
|
69
|
+
right_tot_atom_num = tot_atom_num(right_geoms)
|
|
70
|
+
assert (right_tot_atom_num == ts_atom_num) or (right_tot_atom_num == 0)
|
|
71
|
+
|
|
72
|
+
def get_energy(geom, base_name):
|
|
73
|
+
try:
|
|
74
|
+
geom.energy
|
|
75
|
+
except AttributeError:
|
|
76
|
+
try:
|
|
77
|
+
geom.set_calculator(calc_getter(base_name=base_name))
|
|
78
|
+
except TypeError:
|
|
79
|
+
raise Exception(
|
|
80
|
+
f"Energy isn't set at '{base_name}' geometry "
|
|
81
|
+
"and no 'calc_getter' was supplied!\nPlease either set "
|
|
82
|
+
"the desired quantities (energy/(Hessian)) or supply "
|
|
83
|
+
"a 'calc_getter' to calculate them."
|
|
84
|
+
)
|
|
85
|
+
return geom.energy
|
|
86
|
+
|
|
87
|
+
def get_energies(geoms, base_name):
|
|
88
|
+
return [
|
|
89
|
+
get_energy(geom, f"{base_name}_{i:02d}") for i, geom in enumerate(geoms)
|
|
90
|
+
]
|
|
91
|
+
|
|
92
|
+
en_key = "energy"
|
|
93
|
+
ts_energy = get_energy(ts_geom, "ts")
|
|
94
|
+
left_energies = get_energies(left_geoms, "left")
|
|
95
|
+
right_energies = get_energies(right_geoms, "right")
|
|
96
|
+
|
|
97
|
+
def zeros(geoms):
|
|
98
|
+
return np.zeros(len(geoms))
|
|
99
|
+
|
|
100
|
+
# Gibbs free energies
|
|
101
|
+
if do_thermo:
|
|
102
|
+
en_key = "free energy"
|
|
103
|
+
|
|
104
|
+
def get_thermo(geom, title, is_ts=False):
|
|
105
|
+
thermo = geom.get_thermoanalysis(geom, T=T, p=p)
|
|
106
|
+
print_thermoanalysis(thermo, geom=geom, is_ts=is_ts, level=1, title=title)
|
|
107
|
+
print()
|
|
108
|
+
return thermo
|
|
109
|
+
|
|
110
|
+
ts_thermo = get_thermo(ts_geom, "TS", is_ts=True)
|
|
111
|
+
ts_dG = ts_thermo.dG
|
|
112
|
+
left_thermos = [get_thermo(geom, fn) for geom, fn in zip(left_geoms, left_fns)]
|
|
113
|
+
left_dGs = [thermo.dG for thermo in left_thermos]
|
|
114
|
+
right_thermos = [
|
|
115
|
+
get_thermo(geom, fn) for geom, fn in zip(right_geoms, right_fns)
|
|
116
|
+
]
|
|
117
|
+
right_dGs = [thermo.dG for thermo in right_thermos]
|
|
118
|
+
else:
|
|
119
|
+
ts_dG = 0.0
|
|
120
|
+
left_dGs = zeros(left_geoms)
|
|
121
|
+
right_dGs = zeros(right_geoms)
|
|
122
|
+
|
|
123
|
+
def get_solv_correction(geom, fn=None, name=None):
|
|
124
|
+
fn = str(fn)
|
|
125
|
+
if fn is not None:
|
|
126
|
+
infix = f"'{Path(fn).name: >40s}'"
|
|
127
|
+
else:
|
|
128
|
+
atom_num = len(geom.atoms)
|
|
129
|
+
infix = f"{atom_num} atoms"
|
|
130
|
+
|
|
131
|
+
print(f"Solvated calculation for {infix} ...", end="")
|
|
132
|
+
start = time()
|
|
133
|
+
solv_calc_kwargs = {}
|
|
134
|
+
if name is not None:
|
|
135
|
+
solv_calc_kwargs["base_name"] = f"solv_{name}"
|
|
136
|
+
solv_energy = solv_calc_getter(**solv_calc_kwargs).get_energy(
|
|
137
|
+
geom.atoms, geom.cart_coords
|
|
138
|
+
)["energy"]
|
|
139
|
+
dur = time() - start
|
|
140
|
+
print(f" finished in {dur:.1f} s.")
|
|
141
|
+
# Add standard state correction. ssc will be 0.0 if, disabled.
|
|
142
|
+
return solv_energy, (solv_energy - geom.energy) + ssc
|
|
143
|
+
|
|
144
|
+
def get_solv_corrections(geoms, fns, name):
|
|
145
|
+
return zip(
|
|
146
|
+
*[get_solv_correction(geom, fn, name) for geom, fn in zip(geoms, fns)]
|
|
147
|
+
)
|
|
148
|
+
|
|
149
|
+
if solv_calc_getter is not None:
|
|
150
|
+
print(highlight_text("Calculations with solvent model", level=1) + "\n")
|
|
151
|
+
ts_solv_energy, ts_solv_corr = get_solv_correction(ts_geom, ts_fn, "ts")
|
|
152
|
+
left_solv_energies, left_solv_corrs = get_solv_corrections(
|
|
153
|
+
left_geoms, left_fns, "left"
|
|
154
|
+
)
|
|
155
|
+
right_solv_energies, right_solv_corrs = get_solv_corrections(
|
|
156
|
+
right_geoms, right_fns, "right"
|
|
157
|
+
)
|
|
158
|
+
print()
|
|
159
|
+
# Use zeros, so we can add the term later.
|
|
160
|
+
else:
|
|
161
|
+
ts_solv_corr = 0.0
|
|
162
|
+
left_solv_corrs = zeros(left_geoms)
|
|
163
|
+
right_solv_corrs = zeros(right_geoms)
|
|
164
|
+
|
|
165
|
+
# Calculate total contributions for both sides
|
|
166
|
+
left_dG = sum(left_dGs)
|
|
167
|
+
right_dG = sum(right_dGs)
|
|
168
|
+
left_solv_corr = sum(left_solv_corrs)
|
|
169
|
+
right_solv_corr = sum(right_solv_corrs)
|
|
170
|
+
|
|
171
|
+
ts_energy_corr = ts_energy + ts_solv_corr + ts_dG
|
|
172
|
+
left_energy_corr = sum(left_energies) + left_dG + left_solv_corr
|
|
173
|
+
right_energy_corr = sum(right_energies) + right_dG + right_solv_corr
|
|
174
|
+
energies_corr = [left_energy_corr, ts_energy_corr]
|
|
175
|
+
# TS is always only 1 geometry
|
|
176
|
+
geom_nums = [len(left_geoms), 1]
|
|
177
|
+
|
|
178
|
+
fns = ["Left", "TS"]
|
|
179
|
+
if right_geoms:
|
|
180
|
+
energies_corr.append(right_energy_corr)
|
|
181
|
+
geom_nums.append(len(right_geoms))
|
|
182
|
+
fns.append("Right")
|
|
183
|
+
max_len = max(len(s) for s in fns)
|
|
184
|
+
|
|
185
|
+
def print_table(table, header, width=17):
|
|
186
|
+
col_fmts = ["str"] + (len(header) - 1) * ["float"]
|
|
187
|
+
tp = TablePrinter(header, col_fmts, width=width, sub_underline=False)
|
|
188
|
+
tp.print_header()
|
|
189
|
+
for fn, row in zip(all_fns, table.T):
|
|
190
|
+
fn = str(fn) # fns may be PosixPath etc.
|
|
191
|
+
fn_cut = fn[:4] + ".." + fn[-11:] if (len(fn) > width) else fn
|
|
192
|
+
tp.print_row((fn_cut, *row))
|
|
193
|
+
print()
|
|
194
|
+
|
|
195
|
+
all_fns = left_fns + [ts_fn] + right_fns
|
|
196
|
+
# Electronic energies
|
|
197
|
+
all_energies = np.concatenate((left_energies, [ts_energy], right_energies))
|
|
198
|
+
to_stack = [all_energies]
|
|
199
|
+
gas_titles = ["File", "E_el"]
|
|
200
|
+
if do_thermo:
|
|
201
|
+
# Thermochemical corrections
|
|
202
|
+
all_dGs = np.concatenate((left_dGs, [ts_dG], right_dGs))
|
|
203
|
+
# Free Gibbs energies in the gas phase
|
|
204
|
+
all_Gs_gas = all_energies + all_dGs
|
|
205
|
+
to_stack += [all_dGs, all_Gs_gas]
|
|
206
|
+
gas_titles += ["dG_gas", "G_gas"]
|
|
207
|
+
|
|
208
|
+
gas_table = np.stack(to_stack)
|
|
209
|
+
print("All tabulated quantities are given in au.\n")
|
|
210
|
+
print_table(gas_table, gas_titles)
|
|
211
|
+
full_titles = gas_titles
|
|
212
|
+
|
|
213
|
+
if solv_calc_getter is not None:
|
|
214
|
+
all_solv_energies = np.concatenate(
|
|
215
|
+
(left_solv_energies, [ts_solv_energy], right_solv_energies)
|
|
216
|
+
)
|
|
217
|
+
all_solv_corrs = np.concatenate(
|
|
218
|
+
(left_solv_corrs, [ts_solv_corr], right_solv_corrs)
|
|
219
|
+
)
|
|
220
|
+
to_stack = [all_energies, all_solv_energies, all_solv_corrs]
|
|
221
|
+
solv_titles = ["File", "E_el", "E_solv", "dG_solv"]
|
|
222
|
+
if do_thermo:
|
|
223
|
+
all_Gs_sol = all_Gs_gas + all_solv_corrs
|
|
224
|
+
to_stack += [all_Gs_sol]
|
|
225
|
+
solv_titles += ["G_sol"]
|
|
226
|
+
solv_table = np.stack(to_stack)
|
|
227
|
+
if do_ssc:
|
|
228
|
+
print("dG_solv includes a correction for change of standard state.\n")
|
|
229
|
+
print_table(solv_table, solv_titles)
|
|
230
|
+
full_titles += solv_titles[2:]
|
|
231
|
+
|
|
232
|
+
energies_corr = np.array(energies_corr)
|
|
233
|
+
energies_corr -= energies_corr.min()
|
|
234
|
+
min_ind = energies_corr.argmin()
|
|
235
|
+
energies_corr *= AU2KJPERMOL
|
|
236
|
+
|
|
237
|
+
print(highlight_text("Barriers", level=1))
|
|
238
|
+
print()
|
|
239
|
+
print(f"Temperature: {T:.2f} K")
|
|
240
|
+
print(f"Pressure: {p:.1f} Pa\n")
|
|
241
|
+
|
|
242
|
+
print("Corrections:")
|
|
243
|
+
print(f"Change of standard-state: {do_ssc}, {ssc*AU2KJPERMOL:.2} kJ mol⁻¹")
|
|
244
|
+
print(f" Solvent: {solv_calc_getter is not None}")
|
|
245
|
+
print(f" Thermochemistry: {do_thermo}")
|
|
246
|
+
print()
|
|
247
|
+
|
|
248
|
+
def print_geoms_fns(geoms, fns):
|
|
249
|
+
for i, (geom, fn) in enumerate(zip(geoms, fns)):
|
|
250
|
+
fn_name = Path(fn).name
|
|
251
|
+
print(f"\t{i}: {fn_name} ({geom}, {len(geom.atoms)} atoms)")
|
|
252
|
+
|
|
253
|
+
def get_geom_key(geoms):
|
|
254
|
+
return "geometry" if len(geoms) == 1 else "geometries"
|
|
255
|
+
|
|
256
|
+
print(f"Left {get_geom_key(left_geoms)}:")
|
|
257
|
+
print_geoms_fns(left_geoms, left_fns)
|
|
258
|
+
print("TS geometry:")
|
|
259
|
+
print_geoms_fns((ts_geom,), ("",))
|
|
260
|
+
if right_geoms:
|
|
261
|
+
print(f"Right {get_geom_key(right_geoms)}:")
|
|
262
|
+
print_geoms_fns(right_geoms, right_fns)
|
|
263
|
+
print()
|
|
264
|
+
|
|
265
|
+
print(f"Minimum {en_key} of {energies_corr[min_ind]} kJ mol⁻¹ at '{fns[min_ind]}'.")
|
|
266
|
+
print()
|
|
267
|
+
for fn, en, gnum in zip(fns, energies_corr, geom_nums):
|
|
268
|
+
geom_str = "geometry" if gnum == 1 else "geometries"
|
|
269
|
+
is_sum = " " if gnum == 1 else "Σ"
|
|
270
|
+
print(f"\t{is_sum}{fn:>{max_len}s}: {en:>8.2f} kJ mol⁻¹ ({gnum} {geom_str})")
|
|
271
|
+
print()
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
# [1] https://onlinelibrary.wiley.com/doi/abs/10.1002/jcc.23910
|
|
2
|
+
# Birkholz, Schlegel, 2015
|
|
3
|
+
|
|
4
|
+
import numpy as np
|
|
5
|
+
|
|
6
|
+
from pysisyphus.Geometry import Geometry
|
|
7
|
+
from pysisyphus.drivers import relaxed_scan
|
|
8
|
+
from pysisyphus.helpers_pure import highlight_text
|
|
9
|
+
from pysisyphus.intcoords.setup import get_bond_mat
|
|
10
|
+
from pysisyphus.intcoords.PrimTypes import normalize_prim_inputs
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def bond_order(r, r0, b=2):
|
|
14
|
+
"""Bond order for given bond length and reference length.
|
|
15
|
+
|
|
16
|
+
Eq. (3) in [1]."""
|
|
17
|
+
return max(0, (b * (r0 / r) - 1) / (b - 1))
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def bond_orders(coords3d, bond_indices, r0s):
|
|
21
|
+
"""List of bond orders."""
|
|
22
|
+
bos = list()
|
|
23
|
+
for r0, (a, b) in zip(r0s, bond_indices):
|
|
24
|
+
r = np.linalg.norm(coords3d[a] - coords3d[b])
|
|
25
|
+
bo = bond_order(r, r0)
|
|
26
|
+
bos.append(bo)
|
|
27
|
+
return np.array(bos)
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
def get_r0s(geom, bond_indices):
|
|
31
|
+
"""Reference bond lengths as sum of covalent radii."""
|
|
32
|
+
crs = geom.covalent_radii
|
|
33
|
+
a, b = bond_indices.T
|
|
34
|
+
return crs[a] + crs[b]
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
def bond_orders_for_geom(geom, bond_indices):
|
|
38
|
+
"""Wrapper for bond_orders for simple use with Geometry."""
|
|
39
|
+
r0s = get_r0s(geom, bond_indices)
|
|
40
|
+
return bond_orders(geom.coords3d, bond_indices, r0s)
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
def length_for_bond_order(bo, r0, b=2):
|
|
44
|
+
"""Return bond length for given bond order and reference length.
|
|
45
|
+
|
|
46
|
+
Eq. (3) in [1]."""
|
|
47
|
+
return b / ((b - 1) * bo + 1) * r0
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
def birkholz_interpolation(geoms, calc_getter, recreate=True):
|
|
51
|
+
assert len(geoms) >= 2
|
|
52
|
+
start = geoms[0]
|
|
53
|
+
end = geoms[-1]
|
|
54
|
+
geoms = (start, end)
|
|
55
|
+
atoms = start.atoms
|
|
56
|
+
print(f"Coordinates of 'start' geometry\n{start.as_xyz()})")
|
|
57
|
+
print(f"Coordinates of 'end' geometry\n{end.as_xyz()})\n")
|
|
58
|
+
|
|
59
|
+
print(highlight_text("Bonding analysis"))
|
|
60
|
+
# Bond matrices
|
|
61
|
+
bm_start, bm_end = [get_bond_mat(geom) for geom in geoms]
|
|
62
|
+
# Determine formed/broken bonds. The lower triangular part of the bond
|
|
63
|
+
# matrices has to be zeroed, to avoid double counting. Changes in bonding
|
|
64
|
+
# are determined with logical XOR.
|
|
65
|
+
#
|
|
66
|
+
# Start End XOR Comment
|
|
67
|
+
# ----- --- --- -------
|
|
68
|
+
# True True False Bond is present at both geometries.
|
|
69
|
+
# False False False Bond is absent at both geometries.
|
|
70
|
+
# True False True Bond is broken when going from start to end.
|
|
71
|
+
# False True True Bond is formed when going from start to end.
|
|
72
|
+
bm_diff = np.triu(bm_start) ^ np.triu(bm_end)
|
|
73
|
+
bond_indices = np.stack(np.nonzero(bm_diff), axis=1)
|
|
74
|
+
bonding_changes = bm_diff.sum()
|
|
75
|
+
print(f"{bonding_changes} bonds are formed/broken when going from start to end.\n")
|
|
76
|
+
|
|
77
|
+
# Determine bond orders at start and end
|
|
78
|
+
all_bos = [bond_orders_for_geom(geom, bond_indices) for geom in geoms]
|
|
79
|
+
# Reference bond lengths
|
|
80
|
+
r0s = get_r0s(start, bond_indices)
|
|
81
|
+
|
|
82
|
+
# Print summary
|
|
83
|
+
for title, geom, bos in zip(("Start", "End"), geoms, all_bos):
|
|
84
|
+
print(highlight_text(title, level=1))
|
|
85
|
+
for bo_, (a, b) in zip(bos, bond_indices):
|
|
86
|
+
aa = atoms[a]
|
|
87
|
+
ba = atoms[b]
|
|
88
|
+
print(f"Bond ({aa}{a: >4},{ba}{b: >4}): BO={bo_:.2f}")
|
|
89
|
+
print(
|
|
90
|
+
f"mean(BOs)={bos.mean():.2f}, max(BOs)={bos.max():.2f}, min(BOs)={bos.min():.2f}"
|
|
91
|
+
)
|
|
92
|
+
print()
|
|
93
|
+
|
|
94
|
+
# Guess goal bond lenghts from mean bond order
|
|
95
|
+
start_bos, end_bos = all_bos
|
|
96
|
+
mean_bos = (start_bos + end_bos) / 2
|
|
97
|
+
# Determine goal bond lenghts that yield the mean bond orders
|
|
98
|
+
goal_lengths = length_for_bond_order(mean_bos, r0s)
|
|
99
|
+
|
|
100
|
+
# Constrain formed/broken bonds
|
|
101
|
+
constrain_prims = normalize_prim_inputs([["BOND", *bond] for bond in bond_indices])
|
|
102
|
+
|
|
103
|
+
# Start relaxed scans towards TS from 'start' and 'end'
|
|
104
|
+
print(highlight_text("Relaxed scan towards TS, from 'start'"))
|
|
105
|
+
start_guess, *_ = relaxed_scan(
|
|
106
|
+
start, calc_getter, constrain_prims, target_values=goal_lengths, title="start"
|
|
107
|
+
)
|
|
108
|
+
print()
|
|
109
|
+
start_guess.dump_xyz("start_guess")
|
|
110
|
+
|
|
111
|
+
print(highlight_text("Relaxed scan towards TS, from 'end'"))
|
|
112
|
+
end_guess, *_ = relaxed_scan(
|
|
113
|
+
end, calc_getter, constrain_prims, target_values=goal_lengths, title="end"
|
|
114
|
+
)
|
|
115
|
+
print()
|
|
116
|
+
end_guess.dump_xyz("end_guess")
|
|
117
|
+
|
|
118
|
+
# Compare energies and take the one with lower energy
|
|
119
|
+
start_en = start_guess.energy
|
|
120
|
+
end_en = end_guess.energy
|
|
121
|
+
print(f"Energy of 'start'-guess: {start_en:.6f} au")
|
|
122
|
+
print(f"Energy of 'end'-guess: {end_en:.6f} au")
|
|
123
|
+
start_lower = start_en <= end_en
|
|
124
|
+
lower = "'start'-guess" if start_lower else "'end'-guess"
|
|
125
|
+
print(f"{lower} has lower energy.")
|
|
126
|
+
ts_guess = start_guess if start_lower else end_guess
|
|
127
|
+
|
|
128
|
+
if recreate:
|
|
129
|
+
print("Recreated Geometry object.")
|
|
130
|
+
ts_guess = Geometry(ts_guess.atoms, ts_guess.cart_coords, coord_type="redund")
|
|
131
|
+
ts_guess.set_calculator(calc_getter())
|
|
132
|
+
print()
|
|
133
|
+
print(f"Coordinates of TS guess\n{ts_guess.as_xyz()})\n")
|
|
134
|
+
ts_guess_fn = "ts_guess.xyz"
|
|
135
|
+
ts_guess.dump_xyz(ts_guess_fn)
|
|
136
|
+
print(f"Dumped TS-guess to '{ts_guess_fn}'.")
|
|
137
|
+
|
|
138
|
+
return ts_guess
|