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,139 @@
|
|
|
1
|
+
import numpy as np
|
|
2
|
+
from sympy import symbols, exp
|
|
3
|
+
|
|
4
|
+
# [1] 10.1142/9789812839664_0016
|
|
5
|
+
# G. Henkelman, G. Jóhannesson, and H. Jónsson
|
|
6
|
+
# Theoretical Methods in Condensed Phase Chemistry
|
|
7
|
+
# (Springer, Netherlands, 2002), pp. 287
|
|
8
|
+
# [2] https://aip.scitation.org/doi/pdf/10.1063/1.480097?class=pdf
|
|
9
|
+
# I'm very sure that Fig. 6 and Fig. 5 are not the potentials that are
|
|
10
|
+
# described in the paper. There are two errors in the paper. A_1 is
|
|
11
|
+
# actually -1.5 and not 1.5 and s_x_2 is 0.5 and not 5.0. You also
|
|
12
|
+
# have to divide by (2*s_x_i**2) and not only by (2*s_x_i) as given
|
|
13
|
+
# in Eq. (22).
|
|
14
|
+
|
|
15
|
+
class LEPSExpr:
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def __init__(self):
|
|
19
|
+
"""Generates sympy expression for various LEPS potentials."""
|
|
20
|
+
# V_harmonic uses b = 0.80
|
|
21
|
+
self.abc = (0.05, 0.30, 0.05)
|
|
22
|
+
self.ds = (4.746, 4.746, 3.445)
|
|
23
|
+
self.r0 = 0.742
|
|
24
|
+
self.alpha = 1.942
|
|
25
|
+
|
|
26
|
+
# Used for LEPS + harmonic oscillator
|
|
27
|
+
self.rac = 3.742
|
|
28
|
+
self.kc = 0.2025
|
|
29
|
+
self.c_ = 1.154
|
|
30
|
+
|
|
31
|
+
self.choices = {
|
|
32
|
+
"leps": self.get_leps,
|
|
33
|
+
"harmonic": self.get_harmonic,
|
|
34
|
+
"tot": self.get_tot,
|
|
35
|
+
"dimer": self.get_dimer,
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
def get_leps(self):
|
|
39
|
+
V_expr = self.V_LEPS()
|
|
40
|
+
xlim = (0, 6)
|
|
41
|
+
ylim = (0, 12)
|
|
42
|
+
levels = np.linspace(-5, 5, 250)
|
|
43
|
+
return V_expr, xlim, ylim, levels
|
|
44
|
+
|
|
45
|
+
def get_harmonic(self):
|
|
46
|
+
V_expr = self.V_harmonic()
|
|
47
|
+
levels = np.linspace(-20, 20, 250)
|
|
48
|
+
xlim = (0.4, 3.2)
|
|
49
|
+
ylim = (-2, 2)
|
|
50
|
+
return V_expr, xlim, ylim, levels
|
|
51
|
+
|
|
52
|
+
def get_tot(self):
|
|
53
|
+
V_expr = self.V_tot()
|
|
54
|
+
levels = np.linspace(-5, 2, 75)
|
|
55
|
+
xlim = (0.4, 3.2)
|
|
56
|
+
ylim = (-2, 2)
|
|
57
|
+
return V_expr, xlim, ylim, levels
|
|
58
|
+
|
|
59
|
+
def get_dimer(self):
|
|
60
|
+
V_expr = self.V_dimer()
|
|
61
|
+
levels = None
|
|
62
|
+
xlim = (0.25, 3.25)
|
|
63
|
+
ylim = (-3.5, 3.5)
|
|
64
|
+
return V_expr, xlim, ylim, levels
|
|
65
|
+
|
|
66
|
+
def get_expr(self, pot_type="leps"):
|
|
67
|
+
assert pot_type in self.choices
|
|
68
|
+
return self.choices[pot_type]()
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
def Q(self, d, alpha, r0, r):
|
|
72
|
+
"""Coulomb interactions."""
|
|
73
|
+
return d/2* (3/2*exp(-2*alpha*(r-r0)) - exp(-alpha*(r-r0)))
|
|
74
|
+
|
|
75
|
+
def J(self, d, alpha, r0, r):
|
|
76
|
+
"""Quantum mechanical exchange interaction."""
|
|
77
|
+
return d/4 * (exp(-2*alpha*(r-r0))-6*exp(-alpha*(r-r0)))
|
|
78
|
+
|
|
79
|
+
def G(self, a, b):
|
|
80
|
+
"Gaussian function."""
|
|
81
|
+
return exp(-0.5*((a/0.1)**2 +(b/0.35)**2))
|
|
82
|
+
|
|
83
|
+
def Gdimer(self, x, y, A, x0, y0, sx, sy):
|
|
84
|
+
return A * exp(-(x-x0)**2/(2*sx**2)) * exp(-(y-y0)**2/(2*sy**2))
|
|
85
|
+
|
|
86
|
+
def V_LEPS(self, x=None, y=None, abc=None):
|
|
87
|
+
"""Equation (A.1) in [1].
|
|
88
|
+
Mimics reaction involving three atoms confined to motion along
|
|
89
|
+
a line."""
|
|
90
|
+
if abc is None:
|
|
91
|
+
abc = self.abc
|
|
92
|
+
a, b, c = abc
|
|
93
|
+
if x is None:
|
|
94
|
+
x = symbols("x")
|
|
95
|
+
if y is None:
|
|
96
|
+
y = symbols("y")
|
|
97
|
+
rs = (x, y, self.rac)
|
|
98
|
+
|
|
99
|
+
Qab, Qbc, Qac = [self.Q(d, self.alpha, self.r0, r)
|
|
100
|
+
for d, r in zip(self.ds, rs)]
|
|
101
|
+
Jab, Jbc, Jac = [self.J(d, self.alpha, self.r0, r)
|
|
102
|
+
for d, r in zip(self.ds, rs)]
|
|
103
|
+
|
|
104
|
+
first_term = Qab/(1+a) + Qbc/(1+b) + Qac/(1+c)
|
|
105
|
+
second_term = Jab**2/(1+a)**2 + Jbc**2/(1+b)**2 + Jac**2/(1+c)**2
|
|
106
|
+
third_term = (-Jab*Jbc / ((1+a)*(1+b))
|
|
107
|
+
-Jbc*Jac / ((1+b)*(1+c))
|
|
108
|
+
-Jab*Jac / ((1+a)*(1+c))
|
|
109
|
+
)
|
|
110
|
+
return first_term - (second_term + third_term)**0.5
|
|
111
|
+
|
|
112
|
+
def V_harmonic(self):
|
|
113
|
+
"""Equation (A.2) in [1].
|
|
114
|
+
A and C are fixed, only B can move. A condensed phase environment
|
|
115
|
+
is represented by adding a harmonic oscillator degree of freedom."""
|
|
116
|
+
x, y = symbols("x y")
|
|
117
|
+
abc = (0.05, 0.80, 0.05)
|
|
118
|
+
return (self.V_LEPS(x, self.rac-x, abc)
|
|
119
|
+
+ 2*self.kc*(x-(self.rac/2 - y/self.c_))**2
|
|
120
|
+
)
|
|
121
|
+
|
|
122
|
+
def V_tot(self):
|
|
123
|
+
"""Equation (A.3) in [1].
|
|
124
|
+
Additional saddle point."""
|
|
125
|
+
x, y = symbols("x y")
|
|
126
|
+
return self.V_harmonic() + 1.5 * self.G(x-2.02083, y+0.272881)
|
|
127
|
+
|
|
128
|
+
def V_dimer(self):
|
|
129
|
+
"""III. Results Section A in [3]. Two additional saddle points
|
|
130
|
+
from two added gaussians."""
|
|
131
|
+
x, y = symbols("x y")
|
|
132
|
+
# Ai , x0i , y0i , sxi, syi
|
|
133
|
+
params = ((-1.5, 2.02083, -0.172881, 0.1, 0.35),
|
|
134
|
+
( 6.0, 0.8 , 2.0 , 0.5, 0.7 ))
|
|
135
|
+
G0, G1 = [self.Gdimer(x, y, *parms) for parms in params]
|
|
136
|
+
return self.V_harmonic() + G0 + G1
|
|
137
|
+
|
|
138
|
+
def __str__(self):
|
|
139
|
+
return "LEPSExpr"
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import numpy as np
|
|
2
|
+
|
|
3
|
+
from pysisyphus.calculators.Calculator import Calculator
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class LennardJones(Calculator):
|
|
7
|
+
|
|
8
|
+
# Corresponds to σ = 1 Å, as the default value in ASE, but
|
|
9
|
+
# pysisyphus uses au/Bohr.
|
|
10
|
+
def __init__(self, sigma=1.8897261251, epsilon=1, rc=None):
|
|
11
|
+
super().__init__()
|
|
12
|
+
|
|
13
|
+
self.sigma = sigma
|
|
14
|
+
self.epsilon = epsilon
|
|
15
|
+
# Cutoff distance
|
|
16
|
+
if rc is None:
|
|
17
|
+
rc = 3 * self.sigma
|
|
18
|
+
self.rc = rc
|
|
19
|
+
# Shift energy
|
|
20
|
+
self.e0 = (4 * self.epsilon *
|
|
21
|
+
((self.sigma/self.rc)**12 - (self.sigma/self.rc)**6)
|
|
22
|
+
)
|
|
23
|
+
|
|
24
|
+
def calculate(self, coords3d):
|
|
25
|
+
# Index pairs
|
|
26
|
+
a, b = np.triu_indices(len(coords3d), 1)
|
|
27
|
+
|
|
28
|
+
# Distances
|
|
29
|
+
diffs = coords3d[a] - coords3d[b] # Shape: (N_atoms, 3)
|
|
30
|
+
rs = np.linalg.norm(diffs, axis=1)
|
|
31
|
+
c6 = np.where(rs <= self.rc, (self.sigma/rs)**6, np.zeros_like(rs))
|
|
32
|
+
energy = -self.e0 * (c6 != 0.0).sum()
|
|
33
|
+
c12 = c6**2
|
|
34
|
+
energy += np.sum(4*self.epsilon * (c12 - c6))
|
|
35
|
+
|
|
36
|
+
"""
|
|
37
|
+
Gradient related remarks:
|
|
38
|
+
|
|
39
|
+
Lennard-Jones-potential:
|
|
40
|
+
LJ(r) =
|
|
41
|
+
4*ε*[(σ/r)**12 - (σ/r)**6]
|
|
42
|
+
|
|
43
|
+
Derivative of quotient appearing in LJ potential w.r.t first cartesian
|
|
44
|
+
coordinate:
|
|
45
|
+
d(σ/r)**n/dx_1
|
|
46
|
+
= σ**n * d/dx_1 r**(-n)
|
|
47
|
+
= σ**n * (-n/2) * (2x1-2x2) * r**(-n) * r**(-2)
|
|
48
|
+
= σ**n * r**(-n) * (-n) * (x1-x2) * r**(-2)
|
|
49
|
+
= (σ/r)**n * (-n) * (x1-x2) / r**2
|
|
50
|
+
|
|
51
|
+
Derivate w.r.t to cartesian x coordinate of atom A (x_1):
|
|
52
|
+
dLJ(r)/dx_1 =
|
|
53
|
+
24*ε*[-2*(σ/r)**12 + (σ/r)**6]*(x1-x2)/r**2
|
|
54
|
+
|
|
55
|
+
Derivate w.r.t to cartesian x coordinate of atom B (x_2):
|
|
56
|
+
dLJ(r)/dx_2 =
|
|
57
|
+
-24*ε*[-2*(σ/r)**12 + (σ/r)**6]*(x1-x2)/r**2
|
|
58
|
+
|
|
59
|
+
The derivate w.r.t to x_2 differs only by a factor of -1!
|
|
60
|
+
"""
|
|
61
|
+
prefactors = 24*self.epsilon * (c6 - 2*c12) / rs**2
|
|
62
|
+
products = prefactors[:,None] * diffs
|
|
63
|
+
|
|
64
|
+
gradient = np.zeros_like(coords3d)
|
|
65
|
+
# Every pair (a, b) contributes to the total gradient of atoms a and b.
|
|
66
|
+
for i, prod in enumerate(products):
|
|
67
|
+
gradient[a[i]] += prod
|
|
68
|
+
gradient[b[i]] -= prod
|
|
69
|
+
|
|
70
|
+
return energy, -gradient
|
|
71
|
+
|
|
72
|
+
def get_energy(self, atoms, coords):
|
|
73
|
+
energy, _ = self.calculate(coords.reshape(-1, 3))
|
|
74
|
+
return {"energy": energy}
|
|
75
|
+
|
|
76
|
+
def get_forces(self, atoms, coords):
|
|
77
|
+
energy, forces = self.calculate(coords.reshape(-1, 3))
|
|
78
|
+
return {"energy": energy,
|
|
79
|
+
"forces": forces.flatten(),
|
|
80
|
+
}
|
|
@@ -0,0 +1,219 @@
|
|
|
1
|
+
import re
|
|
2
|
+
import textwrap
|
|
3
|
+
|
|
4
|
+
import numpy as np
|
|
5
|
+
|
|
6
|
+
from pysisyphus.constants import BOHR2ANG, AU2KCALPERMOL
|
|
7
|
+
from pysisyphus.calculators.Calculator import Calculator
|
|
8
|
+
from pysisyphus.helpers_pure import file_or_str
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class MOPAC(Calculator):
|
|
12
|
+
"""http://openmopac.net/manual/"""
|
|
13
|
+
|
|
14
|
+
conf_key = "mopac"
|
|
15
|
+
|
|
16
|
+
MULT_STRS = {
|
|
17
|
+
1: "SINGLET",
|
|
18
|
+
2: "DOUBLET",
|
|
19
|
+
3: "TRIPLET",
|
|
20
|
+
4: "QUARTET",
|
|
21
|
+
5: "QUINTET",
|
|
22
|
+
6: "SEXTET",
|
|
23
|
+
7: "SEPTET",
|
|
24
|
+
8: "OCTET",
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
CALC_TYPES = {
|
|
28
|
+
"energy": "1SCF",
|
|
29
|
+
"gradient": "1SCF GRADIENTS",
|
|
30
|
+
"hessian": "DFORCE FORCE LET",
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
METHODS = [
|
|
34
|
+
m.lower()
|
|
35
|
+
for m in "AM1 PM3 PM6 PM6-DH2 PM6-D3 PM6-DH+ PM6-DH2 PM6-DH2X " # lgtm [py/non-iterable-in-for-loop]
|
|
36
|
+
"PM6-D3H4 PM6-D3H4X PM7 PM7-TS".split()
|
|
37
|
+
]
|
|
38
|
+
|
|
39
|
+
def __init__(self, method="PM7", **kwargs):
|
|
40
|
+
super().__init__(**kwargs)
|
|
41
|
+
|
|
42
|
+
self.method = method
|
|
43
|
+
assert (
|
|
44
|
+
self.method.lower() in self.METHODS
|
|
45
|
+
), f"Invalid method={self.method}! Supported methods are ({self.METHODS})"
|
|
46
|
+
|
|
47
|
+
self.uhf = "UHF" if self.mult != 1 else ""
|
|
48
|
+
|
|
49
|
+
_ = "mopac"
|
|
50
|
+
self.inp_fn = f"{_}.mop"
|
|
51
|
+
self.out_fn = f"{_}.out"
|
|
52
|
+
self.aux_fn = f"{_}.aux"
|
|
53
|
+
self.to_keep = ("mop", "out", "arc", "aux")
|
|
54
|
+
|
|
55
|
+
self.parser_funcs = {
|
|
56
|
+
"energy": self.parse_energy,
|
|
57
|
+
"grad": self.parse_grad,
|
|
58
|
+
"hessian": self.parse_hessian,
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
self.base_cmd = self.get_cmd()
|
|
62
|
+
|
|
63
|
+
"""
|
|
64
|
+
1SCF: Do only SCF
|
|
65
|
+
AUX: Creates a checkpoint file
|
|
66
|
+
NOREO: Dont reorient geometry
|
|
67
|
+
"""
|
|
68
|
+
|
|
69
|
+
self.inp = textwrap.dedent(
|
|
70
|
+
"""
|
|
71
|
+
NOSYM {method} {mult} CHARGE={charge} {calc_type} {uhf} THREADS={pal} AUX(6,PRECISION=9) NOREOR
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
{coord_str}
|
|
75
|
+
"""
|
|
76
|
+
).strip()
|
|
77
|
+
|
|
78
|
+
self.log(f"Created MOPAC calculator using the '{self.method}' method.")
|
|
79
|
+
|
|
80
|
+
def prepare_coords(self, atoms, coords, opt=False):
|
|
81
|
+
coords = coords.reshape(-1, 3) * BOHR2ANG
|
|
82
|
+
# Optimization flag for coordinate
|
|
83
|
+
of = 1 if opt else 0
|
|
84
|
+
coord_str = "\n".join(
|
|
85
|
+
[
|
|
86
|
+
f"{a} {c[0]: 10.08f} {of} {c[1]: 10.08f} {of} {c[2]: 10.08f} {of}"
|
|
87
|
+
for a, c in zip(atoms, coords)
|
|
88
|
+
]
|
|
89
|
+
)
|
|
90
|
+
return coord_str
|
|
91
|
+
|
|
92
|
+
def prepare_input(self, atoms, coords, calc_type, opt=False):
|
|
93
|
+
coord_str = self.prepare_coords(atoms, coords, opt)
|
|
94
|
+
|
|
95
|
+
inp = self.inp.format(
|
|
96
|
+
method=self.method,
|
|
97
|
+
charge=self.charge,
|
|
98
|
+
mult=self.MULT_STRS[self.mult],
|
|
99
|
+
uhf=self.uhf,
|
|
100
|
+
calc_type=self.CALC_TYPES[calc_type],
|
|
101
|
+
coord_str=coord_str,
|
|
102
|
+
pal=self.pal,
|
|
103
|
+
# mem=self.mem,
|
|
104
|
+
)
|
|
105
|
+
return inp
|
|
106
|
+
|
|
107
|
+
def get_energy(self, atoms, coords, **prepare_kwargs):
|
|
108
|
+
calc_type = "energy"
|
|
109
|
+
inp = self.prepare_input(atoms, coords, calc_type)
|
|
110
|
+
# with open("inp.mop", "w") as handle:
|
|
111
|
+
# handle.write(inp)
|
|
112
|
+
# import sys; sys.exit()
|
|
113
|
+
results = self.run(inp, calc="energy")
|
|
114
|
+
return results
|
|
115
|
+
|
|
116
|
+
def get_forces(self, atoms, coords, **prepare_kwargs):
|
|
117
|
+
calc_type = "gradient"
|
|
118
|
+
inp = self.prepare_input(atoms, coords, calc_type, opt=True)
|
|
119
|
+
results = self.run(inp, calc="grad")
|
|
120
|
+
return results
|
|
121
|
+
|
|
122
|
+
def get_hessian(self, atoms, coords, **prepare_kwargs):
|
|
123
|
+
calc_type = "hessian"
|
|
124
|
+
inp = self.prepare_input(atoms, coords, calc_type, opt=True)
|
|
125
|
+
results = self.run(inp, calc="hessian")
|
|
126
|
+
return results
|
|
127
|
+
|
|
128
|
+
def run_calculation(self, atoms, coords, **prepare_kwargs):
|
|
129
|
+
return self.get_energy(atoms, coords, **prepare_kwargs)
|
|
130
|
+
|
|
131
|
+
def read_aux(self, path):
|
|
132
|
+
with open(path / self.aux_fn) as handle:
|
|
133
|
+
text = handle.read()
|
|
134
|
+
return text
|
|
135
|
+
|
|
136
|
+
def parse_energy(self, path):
|
|
137
|
+
return self.parse_energy_from_aux(self.read_aux(path))
|
|
138
|
+
|
|
139
|
+
@staticmethod
|
|
140
|
+
@file_or_str(".aux", method=False)
|
|
141
|
+
def parse_energy_from_aux(text):
|
|
142
|
+
energy_re = r"HEAT_OF_FORMATION:KCAL/MOL=([\d\-D+\.]+)"
|
|
143
|
+
mobj = re.search(energy_re, text)
|
|
144
|
+
energy = float(mobj[1].replace("D", "E")) / AU2KCALPERMOL
|
|
145
|
+
|
|
146
|
+
result = {
|
|
147
|
+
"energy": energy,
|
|
148
|
+
}
|
|
149
|
+
return result
|
|
150
|
+
|
|
151
|
+
def parse_grad(self, path):
|
|
152
|
+
text = self.read_aux(path)
|
|
153
|
+
# grad_re = "GRADIENTS:KCAL.+$\s+(.+)$"
|
|
154
|
+
# mobj = re.search(grad_re, text, re.MULTILINE)
|
|
155
|
+
grad_re = r"GRADIENTS:KCAL/MOL/ANGSTROM\[\d+]=\s+(.+)\s+OVERLAP_MATRIX"
|
|
156
|
+
mobj = re.search(grad_re, text, re.DOTALL)
|
|
157
|
+
# Gradients are given in kcal*mol/angstrom
|
|
158
|
+
gradients = np.array(mobj[1].split(), dtype=float)
|
|
159
|
+
# Convert to hartree/bohr
|
|
160
|
+
gradients = gradients / AU2KCALPERMOL / BOHR2ANG
|
|
161
|
+
|
|
162
|
+
forces = -gradients
|
|
163
|
+
result = {
|
|
164
|
+
"forces": forces,
|
|
165
|
+
}
|
|
166
|
+
result.update(self.parse_energy(path))
|
|
167
|
+
return result
|
|
168
|
+
|
|
169
|
+
def parse_hessian(self, path):
|
|
170
|
+
return self.parse_hessian_from_aux(self.read_aux(path))
|
|
171
|
+
|
|
172
|
+
@staticmethod
|
|
173
|
+
@file_or_str(".aux", method=False)
|
|
174
|
+
def parse_hessian_from_aux(text):
|
|
175
|
+
# Parse employed masses, as the given hessian is mass-weighted
|
|
176
|
+
# and we have to un-weigh it.
|
|
177
|
+
mass_re = re.compile(
|
|
178
|
+
r"ISOTOPIC_MASSES\[(\d+)\]=\s*(.+?)ROTAT_CONSTS", re.DOTALL
|
|
179
|
+
)
|
|
180
|
+
# mobj = re.search(mass_re, text, re.MULTILINE)
|
|
181
|
+
mass_mobj = mass_re.search(text)
|
|
182
|
+
masses = np.array(mass_mobj[2].strip().split(), dtype=float)
|
|
183
|
+
# This matrix is used to un-weigh the hessian
|
|
184
|
+
M = np.diag(np.sqrt(np.repeat(masses, 3)))
|
|
185
|
+
# For N atoms we expect 3N cartesian coordinates
|
|
186
|
+
coord_num = masses.size * 3
|
|
187
|
+
|
|
188
|
+
hess_re = r" # Lower half triangle only\s+([\s\.\-\d]+)\s+NORMAL_MODE"
|
|
189
|
+
tril_hess = re.search(hess_re, text)[1].strip().split()
|
|
190
|
+
tril_hess = np.array(tril_hess, dtype=float)
|
|
191
|
+
assert tril_hess.size == sum(range(coord_num + 1))
|
|
192
|
+
hessian_m = np.zeros((coord_num, coord_num))
|
|
193
|
+
tril_indices = np.tril_indices(coord_num)
|
|
194
|
+
hessian_m[tril_indices] = tril_hess
|
|
195
|
+
|
|
196
|
+
triu_indices = np.triu_indices(coord_num, k=1)
|
|
197
|
+
hessian_m[triu_indices] = hessian_m.T[triu_indices]
|
|
198
|
+
|
|
199
|
+
# Hessian is given in mdyn/(Å*amu).
|
|
200
|
+
# In a first step we have to unweigh the hessian using the matrix
|
|
201
|
+
# built from the parsed masses.
|
|
202
|
+
hessian = M @ hessian_m @ M
|
|
203
|
+
# Then we have to convert mdyn/Å to Hartree/Bohr²
|
|
204
|
+
# mdyn/Å = 100 kg/s²
|
|
205
|
+
# Hartree/Bohr² ~ 1556.8931 kg/s²
|
|
206
|
+
#
|
|
207
|
+
# 1 mydn/Å * (100 / 1556.8931 Hartree/Bohr² * Å/mydn) = 0.06423 Hartree/Bohr²
|
|
208
|
+
hessian *= 0.06423
|
|
209
|
+
|
|
210
|
+
energy = MOPAC.parse_energy_from_aux(text)["energy"]
|
|
211
|
+
|
|
212
|
+
result = {
|
|
213
|
+
"energy": energy,
|
|
214
|
+
"hessian": hessian,
|
|
215
|
+
}
|
|
216
|
+
return result
|
|
217
|
+
|
|
218
|
+
def __str__(self):
|
|
219
|
+
return f"MOPAC({self.name})"
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
# [1] http://www.cims.nyu.edu/~eve2/string_jcp_simplified07.pdf
|
|
2
|
+
|
|
3
|
+
import numpy as np
|
|
4
|
+
|
|
5
|
+
from pysisyphus.calculators.AnaPotBase import AnaPotBase
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class MullerBrownPot(AnaPotBase):
|
|
9
|
+
def __init__(self):
|
|
10
|
+
A = (-200, -100, -170, 15)
|
|
11
|
+
x0 = (1.0, 0.0, -0.5, -1.0)
|
|
12
|
+
y0 = (0.0, 0.5, 1.5, 1.0)
|
|
13
|
+
a = (-1.0, -1.0, -6.5, 0.7)
|
|
14
|
+
b = (0.0, 0.0, 11.0, 0.6)
|
|
15
|
+
c = (-10.0, -10.0, -6.5, 0.7)
|
|
16
|
+
|
|
17
|
+
# V_str_base = """{Ai} * exp(
|
|
18
|
+
# {ai}*(x-{xi})**2
|
|
19
|
+
# + {bi}*(x-{xi})*(y-{yi})
|
|
20
|
+
# + {ci}*(y-{yi})**2
|
|
21
|
+
# )"""
|
|
22
|
+
V_str_base = (
|
|
23
|
+
"{Ai}*exp({ai}*(x-{xi})**2 + {bi}*(x-{xi})*(y-{yi}) + {ci}*(y-{yi})**2)"
|
|
24
|
+
)
|
|
25
|
+
V_str = ""
|
|
26
|
+
V_strs = [
|
|
27
|
+
V_str_base.format(Ai=A[i], ai=a[i], xi=x0[i], bi=b[i], yi=y0[i], ci=c[i])
|
|
28
|
+
for i in range(4)
|
|
29
|
+
]
|
|
30
|
+
V_str = " + ".join(V_strs)
|
|
31
|
+
xlim = (-1.75, 1.25)
|
|
32
|
+
ylim = (-0.5, 2.25)
|
|
33
|
+
levels = np.linspace(-200, 100, 100)
|
|
34
|
+
minima = (
|
|
35
|
+
(-0.5582236, 1.441725842, 0.0),
|
|
36
|
+
(0.62349941, 0.028037758, 0.0),
|
|
37
|
+
(-0.0435, 0.4648, 0.0),
|
|
38
|
+
)
|
|
39
|
+
saddles = ((-0.822, 0.624, 0.0),)
|
|
40
|
+
|
|
41
|
+
super(MullerBrownPot, self).__init__(
|
|
42
|
+
V_str=V_str,
|
|
43
|
+
xlim=xlim,
|
|
44
|
+
ylim=ylim,
|
|
45
|
+
levels=levels,
|
|
46
|
+
minima=minima,
|
|
47
|
+
saddles=saddles,
|
|
48
|
+
)
|
|
49
|
+
|
|
50
|
+
def __str__(self):
|
|
51
|
+
return "MullerBrownPot calculator"
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import sys
|
|
2
|
+
import time
|
|
3
|
+
|
|
4
|
+
from pysisyphus.calculators.Calculator import Calculator
|
|
5
|
+
from pysisyphus.calculators import ORCA, ORCA5, Turbomole, XTB
|
|
6
|
+
|
|
7
|
+
CALC_CLASSES = {
|
|
8
|
+
"orca": ORCA.ORCA,
|
|
9
|
+
"orca5": ORCA5.ORCA5,
|
|
10
|
+
"turbomole": Turbomole.Turbomole,
|
|
11
|
+
"xtb": XTB.XTB,
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
try:
|
|
15
|
+
from pysisyphus.calculators import PySCF
|
|
16
|
+
|
|
17
|
+
CALC_CLASSES["pyscf"] = PySCF.PySCF
|
|
18
|
+
except ModuleNotFoundError:
|
|
19
|
+
pass
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def calcs_from_dict(calc_dict, base_name, calc_number, charge, mult, pal, mem):
|
|
23
|
+
keys_calcs = {}
|
|
24
|
+
calc_kwargs_ = {
|
|
25
|
+
"calc_number": calc_number,
|
|
26
|
+
"charge": charge,
|
|
27
|
+
"mult": mult,
|
|
28
|
+
"pal": pal,
|
|
29
|
+
"mem": mem,
|
|
30
|
+
}
|
|
31
|
+
# Try to distinguish the calculators according to their base_name. If no
|
|
32
|
+
# base_name is given we rely on the calc_number.
|
|
33
|
+
base_name = base_name if base_name != "" else f"{calc_number:03d}"
|
|
34
|
+
for i, (key, kwargs) in enumerate(calc_dict.items()):
|
|
35
|
+
calc_kwargs = calc_kwargs_.copy()
|
|
36
|
+
calc_kwargs["base_name"] = f"{base_name}_{key}"
|
|
37
|
+
# Don't modify original dict
|
|
38
|
+
kwargs = kwargs.copy()
|
|
39
|
+
type_ = kwargs.pop("type")
|
|
40
|
+
calc_kwargs.update(**kwargs)
|
|
41
|
+
calc_cls = CALC_CLASSES[type_]
|
|
42
|
+
keys_calcs[key] = calc_cls(**calc_kwargs)
|
|
43
|
+
return keys_calcs
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
class MultiCalc(Calculator):
|
|
47
|
+
def __init__(self, calcs, **kwargs):
|
|
48
|
+
super().__init__(**kwargs)
|
|
49
|
+
|
|
50
|
+
self.do_hess = {
|
|
51
|
+
key: calc_dict.pop("do_hess", False) for key, calc_dict in calcs.items()
|
|
52
|
+
}
|
|
53
|
+
self.keys_calcs = calcs_from_dict(
|
|
54
|
+
calcs,
|
|
55
|
+
self.base_name,
|
|
56
|
+
self.calc_number,
|
|
57
|
+
self.charge,
|
|
58
|
+
self.mult,
|
|
59
|
+
self.pal,
|
|
60
|
+
self.mem,
|
|
61
|
+
)
|
|
62
|
+
max_len = max([len(key) for key in self.keys_calcs.keys()])
|
|
63
|
+
self.max_fmt = f" >{max_len+2}"
|
|
64
|
+
|
|
65
|
+
def run_calculation(self, atoms, coords, **prepare_kwargs):
|
|
66
|
+
all_results = {}
|
|
67
|
+
for name, calc in self.keys_calcs.items():
|
|
68
|
+
if self.do_hess[name]:
|
|
69
|
+
run_func = calc.get_hessian
|
|
70
|
+
else:
|
|
71
|
+
run_func = calc.run_calculation
|
|
72
|
+
key = f"{self.base_name}_{name}"
|
|
73
|
+
print(f"Running {name:{self.max_fmt}} ... ", end="")
|
|
74
|
+
try:
|
|
75
|
+
start = time.time()
|
|
76
|
+
results = run_func(atoms, coords, **prepare_kwargs)
|
|
77
|
+
end = time.time()
|
|
78
|
+
duration = end - start
|
|
79
|
+
print(f"took {duration:.0f} s.")
|
|
80
|
+
except Exception as err:
|
|
81
|
+
print("\nCalculation failed!")
|
|
82
|
+
print(err)
|
|
83
|
+
sys.stdout.flush()
|
|
84
|
+
all_results[key] = results
|
|
85
|
+
return all_results
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
# [1] https://doi.org/10.1016/j.cplett.2004.07.079
|
|
2
|
+
# The reaction pathway of a potential energy surface as curve
|
|
3
|
+
# with induced tangent
|
|
4
|
+
# Hirsch, Quapp, 2004
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
import numpy as np
|
|
8
|
+
|
|
9
|
+
from pysisyphus.calculators.AnaPotBase import AnaPotBase
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class NFK(AnaPotBase):
|
|
13
|
+
def __init__(self, C=0.06, **kwargs):
|
|
14
|
+
"""NFK surface of Hirsch and Quapp.
|
|
15
|
+
|
|
16
|
+
See Fig. 4 in [1] and the appendix.
|
|
17
|
+
"""
|
|
18
|
+
|
|
19
|
+
# Note that C is substituted in
|
|
20
|
+
V_str = f"{C} * (x**2 + y**2)**2 + x*y - 9*exp(-(x-3)**2-y**2) - 9*exp(-(x+3)**2 - y**2)"
|
|
21
|
+
kwargs_ = {
|
|
22
|
+
"V_str": V_str,
|
|
23
|
+
"xlim": (-3, 3),
|
|
24
|
+
"ylim": (-3, 3),
|
|
25
|
+
"levels": np.linspace(-7, 3.5, 70),
|
|
26
|
+
"minima": ((2.71268103, -0.15093971, 0.0), (-2.7126810, 0.1509397, 0.0)),
|
|
27
|
+
"saddles": ((0.0, 0.0, 0.0),),
|
|
28
|
+
}
|
|
29
|
+
kwargs_.update(kwargs)
|
|
30
|
+
super().__init__(**kwargs_)
|
|
31
|
+
|
|
32
|
+
def __str__(self):
|
|
33
|
+
return "NFK calculator"
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
class ModNFK(NFK):
|
|
37
|
+
def __init__(self, C=0.03, **kwargs):
|
|
38
|
+
kwargs["minima"] = (
|
|
39
|
+
(-2.84721930, 0.15702574, 0.0),
|
|
40
|
+
(2.84721930, -0.15702574, 0.0),
|
|
41
|
+
)
|
|
42
|
+
super().__init__(C, **kwargs)
|
|
43
|
+
|
|
44
|
+
def __str__(self):
|
|
45
|
+
return "ModNFK calculator"
|