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,318 @@
|
|
|
1
|
+
from dataclasses import dataclass
|
|
2
|
+
import itertools as it
|
|
3
|
+
import pickle
|
|
4
|
+
from typing import Dict, List
|
|
5
|
+
|
|
6
|
+
import numpy as np
|
|
7
|
+
from numpy.typing import NDArray
|
|
8
|
+
|
|
9
|
+
from pysisyphus.Geometry import Geometry
|
|
10
|
+
from pysisyphus.io.pdb import parse_pdb
|
|
11
|
+
from pysisyphus.io.psf import parse_psf
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
@dataclass
|
|
15
|
+
class Atom:
|
|
16
|
+
id: int
|
|
17
|
+
segment: str
|
|
18
|
+
resid: int
|
|
19
|
+
resname: str
|
|
20
|
+
name: str
|
|
21
|
+
type: str
|
|
22
|
+
charge: float
|
|
23
|
+
mass: float
|
|
24
|
+
coords: NDArray[float]
|
|
25
|
+
element: str
|
|
26
|
+
|
|
27
|
+
@staticmethod
|
|
28
|
+
def from_psf_line(line, coords, element):
|
|
29
|
+
return Atom(
|
|
30
|
+
id=line["id"],
|
|
31
|
+
segment=line["segment"],
|
|
32
|
+
resid=line["resid"],
|
|
33
|
+
resname=line["resname"],
|
|
34
|
+
name=line["atom_name"],
|
|
35
|
+
type=line["atom_type"],
|
|
36
|
+
charge=line["charge"],
|
|
37
|
+
mass=line["mass"],
|
|
38
|
+
coords=coords,
|
|
39
|
+
element=element,
|
|
40
|
+
)
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
@dataclass
|
|
44
|
+
class Residue:
|
|
45
|
+
id: int
|
|
46
|
+
name: str
|
|
47
|
+
segment: str
|
|
48
|
+
atoms: List[Atom]
|
|
49
|
+
|
|
50
|
+
@staticmethod
|
|
51
|
+
def from_psf_lines(lines, coords3d, elements):
|
|
52
|
+
assert len(lines) == len(coords3d) == len(elements)
|
|
53
|
+
atoms = [
|
|
54
|
+
Atom.from_psf_line(line, coords, element)
|
|
55
|
+
for line, coords, element in zip(lines, coords3d, elements)
|
|
56
|
+
]
|
|
57
|
+
atom0 = atoms[0]
|
|
58
|
+
resid0 = atom0.resid
|
|
59
|
+
resname0 = atom0.resname
|
|
60
|
+
segment0 = atom0.segment
|
|
61
|
+
if len(lines) > 1:
|
|
62
|
+
resids, resnames = zip(*[(atom.resid, atom.resname) for atom in atoms[1:]])
|
|
63
|
+
assert all([resname == resname0 for resname in resnames])
|
|
64
|
+
assert all([resid == resid0 for resid in resids])
|
|
65
|
+
return Residue(resid0, resname0, segment0, atoms)
|
|
66
|
+
|
|
67
|
+
@property
|
|
68
|
+
def key(self):
|
|
69
|
+
return self.segment, self.id
|
|
70
|
+
|
|
71
|
+
@property
|
|
72
|
+
def charge(self):
|
|
73
|
+
charge = sum([atom.charge for atom in self.atoms])
|
|
74
|
+
# assert abs(charge % 1) <= 1e-10 # I guess charges must not be integer ...
|
|
75
|
+
return charge
|
|
76
|
+
|
|
77
|
+
@property
|
|
78
|
+
def masses(self):
|
|
79
|
+
return np.array([atom.mass for atom in self.atoms])
|
|
80
|
+
|
|
81
|
+
@property
|
|
82
|
+
def total_mass(self):
|
|
83
|
+
return sum(self.masses)
|
|
84
|
+
|
|
85
|
+
@property
|
|
86
|
+
def atom_indices(self):
|
|
87
|
+
return [atom.id for atom in self.atoms]
|
|
88
|
+
|
|
89
|
+
@property
|
|
90
|
+
def elements_coords3d(self):
|
|
91
|
+
elements = [atom.element for atom in self.atoms]
|
|
92
|
+
return elements, self.coords3d
|
|
93
|
+
|
|
94
|
+
@property
|
|
95
|
+
def coords3d(self):
|
|
96
|
+
return np.array([atom.coords for atom in self.atoms])
|
|
97
|
+
|
|
98
|
+
@property
|
|
99
|
+
def center_of_mass(self):
|
|
100
|
+
return (
|
|
101
|
+
1 / self.total_mass * np.sum(self.coords3d * self.masses[:, None], axis=0)
|
|
102
|
+
)
|
|
103
|
+
|
|
104
|
+
@property
|
|
105
|
+
def com(self):
|
|
106
|
+
return self.center_of_mass
|
|
107
|
+
|
|
108
|
+
def __len__(self):
|
|
109
|
+
return len(self.atoms)
|
|
110
|
+
|
|
111
|
+
def __str__(self):
|
|
112
|
+
return f"{self.resname}{self.resid}"
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
"""
|
|
116
|
+
@dataclass
|
|
117
|
+
class Residues:
|
|
118
|
+
residues: Dict
|
|
119
|
+
psf_data: Dict
|
|
120
|
+
|
|
121
|
+
def as_geom(self, with_link_atoms=True):
|
|
122
|
+
geom = geom_from_residues(self.residues)
|
|
123
|
+
atoms = geom.atoms
|
|
124
|
+
coords3d = geom.coords3d
|
|
125
|
+
bonds = np.array(self.psf_data["nbond"]["inds"], dtype=int).reshape(-1, 2)
|
|
126
|
+
if with_link_atoms:
|
|
127
|
+
link_hosts, link_atoms, link_coords3d = link_atoms_for_residues(
|
|
128
|
+
self.residues, bonds, coords3d, atom_map
|
|
129
|
+
)
|
|
130
|
+
atoms += link_atoms
|
|
131
|
+
coords3d = np.concatenate((coords3d, link_coords3d), axis=0)
|
|
132
|
+
geom = Geometry(atoms, coords3d)
|
|
133
|
+
return geom
|
|
134
|
+
"""
|
|
135
|
+
|
|
136
|
+
|
|
137
|
+
def residues_from_psf(psf_data, atoms, coords3d, atom_map):
|
|
138
|
+
psf_atoms = psf_data["atoms"]
|
|
139
|
+
res_key = lambda atom: (atom["segment"], atom["resid"])
|
|
140
|
+
psf_atoms = sorted(psf_atoms, key=res_key)
|
|
141
|
+
psf_atoms_by_res = it.groupby(psf_atoms, key=res_key)
|
|
142
|
+
residues = dict()
|
|
143
|
+
for _, g in psf_atoms_by_res:
|
|
144
|
+
res_atoms = sorted(g, key=lambda atom: atom["id"])
|
|
145
|
+
atom_inds = [atom_map[atom["id"]] for atom in res_atoms]
|
|
146
|
+
res_coords3d = coords3d[atom_inds]
|
|
147
|
+
res_elements = [atoms[i] for i in atom_inds]
|
|
148
|
+
res = Residue.from_psf_lines(res_atoms, res_coords3d, res_elements)
|
|
149
|
+
residues[res.key] = res
|
|
150
|
+
return residues
|
|
151
|
+
|
|
152
|
+
|
|
153
|
+
def residues_within_dist(
|
|
154
|
+
residues,
|
|
155
|
+
within_resid,
|
|
156
|
+
within_dist,
|
|
157
|
+
kind="com",
|
|
158
|
+
):
|
|
159
|
+
def com_within():
|
|
160
|
+
coms = {key: res.com for key, res in residues.items()}
|
|
161
|
+
ref_com = coms[within_resid]
|
|
162
|
+
res_ids_below_dist = [
|
|
163
|
+
key
|
|
164
|
+
for key, res in residues.items()
|
|
165
|
+
if np.linalg.norm(coms[res.key] - ref_com) <= within_dist
|
|
166
|
+
]
|
|
167
|
+
return res_ids_below_dist
|
|
168
|
+
|
|
169
|
+
def atom_within():
|
|
170
|
+
ref_res = residues[within_resid]
|
|
171
|
+
ref_coords3d = ref_res.coords3d
|
|
172
|
+
res_ids_below_dist = list()
|
|
173
|
+
for key, res in residues.items():
|
|
174
|
+
dist_vecs = ref_coords3d[:, None, :] - res.coords3d
|
|
175
|
+
dists = np.linalg.norm(dist_vecs, axis=2)
|
|
176
|
+
if (dists <= within_dist).any():
|
|
177
|
+
res_ids_below_dist.append(key)
|
|
178
|
+
return res_ids_below_dist
|
|
179
|
+
|
|
180
|
+
if kind == "com":
|
|
181
|
+
within_resid = com_within()
|
|
182
|
+
elif kind == "atom":
|
|
183
|
+
within_resid = atom_within()
|
|
184
|
+
pass
|
|
185
|
+
else:
|
|
186
|
+
raise Exception(f"{kind=} is not supported!")
|
|
187
|
+
|
|
188
|
+
residues_within = [residues[resid] for resid in within_resid]
|
|
189
|
+
return residues_within
|
|
190
|
+
|
|
191
|
+
|
|
192
|
+
def geom_from_residues(residues):
|
|
193
|
+
atoms = list()
|
|
194
|
+
coords3d = np.zeros((sum([len(res) for res in residues]), 3))
|
|
195
|
+
i = 0
|
|
196
|
+
for res in residues:
|
|
197
|
+
res_elements, res_coords3d = res.elements_coords3d
|
|
198
|
+
len_res = len(res)
|
|
199
|
+
coords3d[i : i + len_res] = res_coords3d
|
|
200
|
+
atoms.extend(res_elements)
|
|
201
|
+
i += len_res
|
|
202
|
+
return Geometry(atoms, coords3d)
|
|
203
|
+
|
|
204
|
+
|
|
205
|
+
def link_atoms_for_residues(
|
|
206
|
+
residues, bonds, coords3d, atom_map, link_element="H", g=0.709
|
|
207
|
+
):
|
|
208
|
+
atom_inds = list(it.chain(*[res.atom_indices for res in residues]))
|
|
209
|
+
|
|
210
|
+
bond_dict = dict()
|
|
211
|
+
for bond in bonds:
|
|
212
|
+
from_, to_ = bond
|
|
213
|
+
bond_dict.setdefault(from_, set()).add(to_)
|
|
214
|
+
bond_dict.setdefault(to_, set()).add(from_)
|
|
215
|
+
atom_set = set(atom_inds)
|
|
216
|
+
|
|
217
|
+
cut_bonds = list()
|
|
218
|
+
# Check all bonds from residue-atoms. Determine which bonds are cut.
|
|
219
|
+
for atom in atom_inds:
|
|
220
|
+
try:
|
|
221
|
+
cut_bonds_with = bond_dict[atom] - atom_set
|
|
222
|
+
# Single ions/atoms may not have any bonds.
|
|
223
|
+
except KeyError:
|
|
224
|
+
cut_bonds_with = list()
|
|
225
|
+
for cbw in cut_bonds_with:
|
|
226
|
+
cut_bonds.append((atom, cbw))
|
|
227
|
+
|
|
228
|
+
link_atoms = list()
|
|
229
|
+
link_hosts = np.zeros(len(cut_bonds))
|
|
230
|
+
link_coords3d = np.zeros((len(cut_bonds), 3))
|
|
231
|
+
for i, cut_bond in enumerate(cut_bonds):
|
|
232
|
+
from_, to_ = cut_bond
|
|
233
|
+
link_atoms.append(link_element)
|
|
234
|
+
link_hosts[i] = to_
|
|
235
|
+
from_coords = coords3d[atom_map[from_]]
|
|
236
|
+
to_coords = coords3d[atom_map[to_]]
|
|
237
|
+
bond_vec = to_coords - from_coords
|
|
238
|
+
link_coords3d[i] = from_coords + g * bond_vec
|
|
239
|
+
link_atoms = tuple(link_atoms)
|
|
240
|
+
return link_hosts, link_atoms, link_coords3d
|
|
241
|
+
|
|
242
|
+
|
|
243
|
+
def load_psf(psf_fn):
|
|
244
|
+
if str(psf_fn).lower().endswith(".psf"):
|
|
245
|
+
psf_data = parse_psf(psf_fn)
|
|
246
|
+
else:
|
|
247
|
+
with open(psf_fn, "rb") as handle:
|
|
248
|
+
psf_data = pickle.load(handle)
|
|
249
|
+
return psf_data
|
|
250
|
+
|
|
251
|
+
|
|
252
|
+
def cluster_from_psf_pdb(
|
|
253
|
+
# psf_fn, pdb_fn, within_resid=None, within_dist=0.0, ref_residues=None, kind="atom,"
|
|
254
|
+
psf_data,
|
|
255
|
+
pdb_fn,
|
|
256
|
+
within_resid=None,
|
|
257
|
+
within_dist=0.0,
|
|
258
|
+
ref_residues=None,
|
|
259
|
+
kind="atom",
|
|
260
|
+
):
|
|
261
|
+
atoms, coords, _, atom_map = parse_pdb(pdb_fn)
|
|
262
|
+
coords3d = coords.reshape(-1, 3)
|
|
263
|
+
print("Loaded PDB data.")
|
|
264
|
+
|
|
265
|
+
residues = residues_from_psf(psf_data, atoms, coords3d, atom_map)
|
|
266
|
+
|
|
267
|
+
# Select according to COM distance
|
|
268
|
+
if within_resid and within_dist:
|
|
269
|
+
# sel_residues = residues_within_com_dist(
|
|
270
|
+
sel_residues = residues_within_dist(
|
|
271
|
+
residues,
|
|
272
|
+
within_resid,
|
|
273
|
+
within_dist,
|
|
274
|
+
kind=kind,
|
|
275
|
+
)
|
|
276
|
+
# Select residues according to provided ref_residues.
|
|
277
|
+
elif ref_residues:
|
|
278
|
+
sel_residues = [residues[ref_res.key] for ref_res in ref_residues]
|
|
279
|
+
# Or complain!
|
|
280
|
+
else:
|
|
281
|
+
raise Exception(
|
|
282
|
+
"Either 'within_resid' and 'within_dist' or 'residues' must be given!"
|
|
283
|
+
)
|
|
284
|
+
|
|
285
|
+
geom = geom_from_residues(sel_residues)
|
|
286
|
+
print("Create cluster geometry.")
|
|
287
|
+
bonds = np.array(psf_data["nbond"]["inds"], dtype=int).reshape(-1, 2)
|
|
288
|
+
link_hosts, link_atoms, link_coords3d = link_atoms_for_residues(
|
|
289
|
+
sel_residues, bonds, coords3d, atom_map
|
|
290
|
+
)
|
|
291
|
+
sat_geom = Geometry(
|
|
292
|
+
geom.atoms + link_atoms, np.concatenate((geom.coords3d, link_coords3d), axis=0)
|
|
293
|
+
)
|
|
294
|
+
print("Created satured geometry with link atoms.")
|
|
295
|
+
|
|
296
|
+
# Determine backbone atoms and/or link atoms and report their indices, so they can
|
|
297
|
+
# be restrained in subsequent RMSD-biased optimizations. Also report the distance
|
|
298
|
+
# between their positions and the COM of the reference residue.
|
|
299
|
+
backbone_names = {"CA", "C", "O", "N"} # HN, HA not included
|
|
300
|
+
i = 0
|
|
301
|
+
backbone_inds = list()
|
|
302
|
+
backbone_com_dists = list()
|
|
303
|
+
ref_com = residues[within_resid].com
|
|
304
|
+
for res in sel_residues:
|
|
305
|
+
for atom in res.atoms:
|
|
306
|
+
if atom.name in backbone_names:
|
|
307
|
+
backbone_inds.append(i)
|
|
308
|
+
bb_dist = np.linalg.norm(ref_com - atom.coords)
|
|
309
|
+
backbone_com_dists.append(bb_dist)
|
|
310
|
+
print(
|
|
311
|
+
f"{res.name: >4s}{res.id: <5d}, {atom.element: >2s}{atom.id: <5d}, "
|
|
312
|
+
f"type={atom.name: >4s}, id={i: >5d}, {bb_dist: >8.4f} au"
|
|
313
|
+
)
|
|
314
|
+
i += 1
|
|
315
|
+
backbone_inds = np.array(backbone_inds, dtype=int)
|
|
316
|
+
backbone_com_dists = np.array(backbone_com_dists, dtype=float)
|
|
317
|
+
|
|
318
|
+
return sat_geom, sel_residues, backbone_inds, backbone_com_dists
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
import argparse
|
|
2
|
+
import itertools as it
|
|
3
|
+
import sys
|
|
4
|
+
|
|
5
|
+
import matplotlib.pyplot as plt
|
|
6
|
+
import numpy as np
|
|
7
|
+
import yaml
|
|
8
|
+
|
|
9
|
+
from pysisyphus.constants import AU2EV
|
|
10
|
+
from pysisyphus.wavefunction.diabatization import dq_diabatization
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def make_array(nstates, components, lines):
|
|
14
|
+
if len(lines) == 0:
|
|
15
|
+
return None
|
|
16
|
+
|
|
17
|
+
arr = np.zeros((components, nstates, nstates))
|
|
18
|
+
expect_diag = nstates
|
|
19
|
+
expect_off_diag = sum(range(nstates))
|
|
20
|
+
|
|
21
|
+
for line in lines:
|
|
22
|
+
from_, to_, *props = line
|
|
23
|
+
assert (from_ >= 0) and (to_ >= 0)
|
|
24
|
+
assert (
|
|
25
|
+
len(props) == components
|
|
26
|
+
), f"Expected line of length {components} but got '{line}'!"
|
|
27
|
+
|
|
28
|
+
if from_ == to_:
|
|
29
|
+
expect_diag -= 1
|
|
30
|
+
elif from_ != to_:
|
|
31
|
+
expect_off_diag -= 1
|
|
32
|
+
|
|
33
|
+
arr[:, from_, to_] = arr[:, to_, from_] = props
|
|
34
|
+
assert expect_diag == 0, "Some diagonal elements are missing!"
|
|
35
|
+
assert expect_off_diag == 0, "Some off-diagonal elements are missing!"
|
|
36
|
+
return arr
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
def dq_diabatization_from_run_dict(run_dict):
|
|
40
|
+
adia_ens = np.array(run_dict["adiabatic_energies"], dtype=float)
|
|
41
|
+
nstates = adia_ens.size
|
|
42
|
+
|
|
43
|
+
# Dipole moments must be present
|
|
44
|
+
dip_moms = make_array(nstates, 3, run_dict["dipoles"])
|
|
45
|
+
# Quadrupole moments and electrostatic potential are optional.
|
|
46
|
+
quad_moms = make_array(nstates, 1, run_dict.get("quadrupoles", list()))
|
|
47
|
+
epots = make_array(nstates, 1, run_dict.get("epots", list()))
|
|
48
|
+
|
|
49
|
+
kwargs = {}
|
|
50
|
+
if "alpha" in run_dict:
|
|
51
|
+
kwargs["alpha"] = run_dict["alpha"]
|
|
52
|
+
if "beta" in run_dict:
|
|
53
|
+
kwargs["beta"] = run_dict["beta"]
|
|
54
|
+
|
|
55
|
+
return dq_diabatization(
|
|
56
|
+
adia_ens, dip_moms, quad_moms=quad_moms, epots=epots, **kwargs
|
|
57
|
+
)
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
def diabatize_path(adia_ens, dip_moms, tr_quad_moms=None, epots=None, **kwargs):
|
|
61
|
+
nones = [None for _ in adia_ens]
|
|
62
|
+
if tr_quad_moms is None:
|
|
63
|
+
tr_quad_moms = nones
|
|
64
|
+
if epots is None:
|
|
65
|
+
epots = nones
|
|
66
|
+
assert len(adia_ens) == len(dip_moms) == len(tr_quad_moms) == len(epots)
|
|
67
|
+
|
|
68
|
+
for aens, dpm, qpm, epot in zip(adia_ens, dip_moms, tr_quad_moms, epots):
|
|
69
|
+
yield dq_diabatization(aens, dpm, qpm, epot, **kwargs)
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
def plot_dia_res(dia_res, show=False):
|
|
73
|
+
nstates = dia_res[0].nstates
|
|
74
|
+
adia_ens = np.zeros((len(dia_res), nstates))
|
|
75
|
+
dia_ens = np.zeros((len(dia_res), nstates))
|
|
76
|
+
keys = list(it.combinations(range(nstates), 2))
|
|
77
|
+
couplings = np.zeros((len(dia_res), len(keys)))
|
|
78
|
+
for i, dr in enumerate(dia_res):
|
|
79
|
+
adia_ens[i] = dr.adia_ens
|
|
80
|
+
dia_ens[i] = dr.dia_ens
|
|
81
|
+
for j, key in enumerate(keys):
|
|
82
|
+
couplings[i, j] = dr.couplings[key]
|
|
83
|
+
|
|
84
|
+
adia_min = adia_ens.min()
|
|
85
|
+
adia_ens -= adia_min
|
|
86
|
+
adia_ens *= AU2EV
|
|
87
|
+
dia_ens -= adia_min
|
|
88
|
+
dia_ens *= AU2EV
|
|
89
|
+
couplings *= AU2EV
|
|
90
|
+
|
|
91
|
+
fig, (ax0, ax1) = plt.subplots(nrows=2, sharex=True)
|
|
92
|
+
for i, state in enumerate(adia_ens.T):
|
|
93
|
+
ax0.plot(state, "o--", label=f"$V_{i}$")
|
|
94
|
+
for i, state in enumerate(dia_ens.T):
|
|
95
|
+
ax0.plot(state, "x-", label=f"$U_{i}$")
|
|
96
|
+
ax0.legend()
|
|
97
|
+
ax0.set_xlabel("Step")
|
|
98
|
+
ax0.set_ylabel(r"$\Delta E$ / eV")
|
|
99
|
+
|
|
100
|
+
# Couplings
|
|
101
|
+
for i, cpls in enumerate(couplings.T):
|
|
102
|
+
from_to = "".join([str(_) for _ in keys[i]])
|
|
103
|
+
ax1.plot(cpls, "o-", label=f"$|D_{{{from_to}}}|$")
|
|
104
|
+
ax1.axhline(0.0, ls="--", c="k")
|
|
105
|
+
ax1.legend()
|
|
106
|
+
|
|
107
|
+
fig.tight_layout()
|
|
108
|
+
if show:
|
|
109
|
+
plt.show()
|
|
110
|
+
return fig, (ax0, ax1)
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
def parse_args(args):
|
|
114
|
+
parser = argparse.ArgumentParser()
|
|
115
|
+
parser.add_argument("yaml")
|
|
116
|
+
return parser.parse_args(args)
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
def run():
|
|
120
|
+
args = parse_args(sys.argv[1:])
|
|
121
|
+
|
|
122
|
+
yaml_fn = args.yaml
|
|
123
|
+
with open(yaml_fn) as handle:
|
|
124
|
+
run_dict = yaml.load(handle, Loader=yaml.SafeLoader)
|
|
125
|
+
adia_labels = run_dict.pop("adiabatic_labels", None)
|
|
126
|
+
unit = run_dict.pop("unit", "eV")
|
|
127
|
+
dia_res = dq_diabatization_from_run_dict(run_dict)
|
|
128
|
+
report = dia_res.render_report(adia_labels=adia_labels, unit=unit)
|
|
129
|
+
print(report)
|
|
130
|
+
|
|
131
|
+
|
|
132
|
+
if __name__ == "__main__":
|
|
133
|
+
run()
|