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
pysisyphus/io/crd.py
ADDED
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import re
|
|
2
|
+
|
|
3
|
+
import jinja2
|
|
4
|
+
import numpy as np
|
|
5
|
+
|
|
6
|
+
from pysisyphus.constants import ANG2BOHR
|
|
7
|
+
from pysisyphus.Geometry import Geometry
|
|
8
|
+
from pysisyphus.helpers_pure import file_or_str
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
@file_or_str(".crd")
|
|
12
|
+
def parse_crd(crd):
|
|
13
|
+
lines = [l.strip() for l in crd.strip().split("\n") if not l.startswith("*")]
|
|
14
|
+
expect_line = lines.pop(0)
|
|
15
|
+
expect_num = int(expect_line.split()[0])
|
|
16
|
+
coords3d = np.zeros((expect_num, 3), dtype=float)
|
|
17
|
+
atoms = list()
|
|
18
|
+
re_ = re.compile(r"\d+")
|
|
19
|
+
for i, line in enumerate(lines):
|
|
20
|
+
_, _, res, atom, x, y, z, *_ = line.split()
|
|
21
|
+
coords3d[i] = (x, y, z)
|
|
22
|
+
atom = re_.sub("", atom) # Delte number
|
|
23
|
+
atoms.append(atom)
|
|
24
|
+
assert len(atoms) == expect_num
|
|
25
|
+
coords3d *= ANG2BOHR
|
|
26
|
+
return atoms, coords3d.flatten()
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
def geom_from_crd(fn, **kwargs):
|
|
30
|
+
atoms, coords = parse_crd(fn)
|
|
31
|
+
return Geometry(atoms, coords, **kwargs)
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
# I10 I10 2X A8 2X A8 3F20.10 2X A8 2X A8 F20.10
|
|
35
|
+
CRD_TPL = """* Created by pysisyphus
|
|
36
|
+
*
|
|
37
|
+
{{ i10(atomnum) }} EXT
|
|
38
|
+
{% for atom, x, y, z in atoms_xyz -%}
|
|
39
|
+
{{ i10(loop.index) }}{{ i10(resno) }} {{ a8(res) }} {{ a8(atom) }}{{ f20(x) }}{{ f20(y) }}{{ f20(z) }} {{ a8(segid) }} {{ a8(resid) }}{{ f20(0.0) }}
|
|
40
|
+
{% endfor %}
|
|
41
|
+
"""
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
def i10(int_):
|
|
45
|
+
return f"{int_:10d}"
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
def f20(float_):
|
|
49
|
+
return f"{float_:>20.10f}"
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
def a8(str_):
|
|
53
|
+
return f"{str(str_):<8s}"
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
def atoms_coords_to_crd_str(
|
|
57
|
+
atoms,
|
|
58
|
+
coords,
|
|
59
|
+
resno=1,
|
|
60
|
+
res="UNL1",
|
|
61
|
+
segid=None,
|
|
62
|
+
resid=1,
|
|
63
|
+
ref_atoms=None,
|
|
64
|
+
del_atoms=None,
|
|
65
|
+
):
|
|
66
|
+
if segid is None:
|
|
67
|
+
segid = res
|
|
68
|
+
if del_atoms is None:
|
|
69
|
+
del_atoms = []
|
|
70
|
+
|
|
71
|
+
env = jinja2.Environment(loader=jinja2.BaseLoader)
|
|
72
|
+
env.globals.update(i10=i10, f20=f20, a8=a8)
|
|
73
|
+
tpl = env.from_string(CRD_TPL)
|
|
74
|
+
|
|
75
|
+
if ref_atoms is not None:
|
|
76
|
+
atoms_for_names = ref_atoms
|
|
77
|
+
else:
|
|
78
|
+
atoms_for_names = atoms
|
|
79
|
+
counter = dict()
|
|
80
|
+
atom_names = list()
|
|
81
|
+
for atom in atoms_for_names:
|
|
82
|
+
counter.setdefault(atom, 1)
|
|
83
|
+
atom_names.append(f"{atom}{counter[atom]}")
|
|
84
|
+
counter[atom] += 1
|
|
85
|
+
atom_names = [an for i, an in enumerate(atom_names) if i not in del_atoms]
|
|
86
|
+
|
|
87
|
+
coords3d = coords.reshape(-1, 3) / ANG2BOHR
|
|
88
|
+
atoms_xyz = list(zip(atom_names, *coords3d.T))
|
|
89
|
+
rendered = tpl.render(
|
|
90
|
+
atomnum=len(atoms_xyz),
|
|
91
|
+
atoms_xyz=atoms_xyz,
|
|
92
|
+
resno=resno,
|
|
93
|
+
res=res,
|
|
94
|
+
resid=resid,
|
|
95
|
+
segid=segid,
|
|
96
|
+
)
|
|
97
|
+
return rendered
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
def geom_to_crd_str(geom, **kwargs):
|
|
101
|
+
return atoms_coords_to_crd_str(geom.atoms, geom.cart_coords, **kwargs)
|
pysisyphus/io/cube.py
ADDED
|
@@ -0,0 +1,220 @@
|
|
|
1
|
+
from dataclasses import dataclass
|
|
2
|
+
from math import ceil
|
|
3
|
+
import tempfile
|
|
4
|
+
from typing import Tuple
|
|
5
|
+
|
|
6
|
+
import jinja2
|
|
7
|
+
import numpy as np
|
|
8
|
+
from numpy.typing import NDArray
|
|
9
|
+
import pyparsing as pp
|
|
10
|
+
|
|
11
|
+
from pysisyphus.elem_data import ATOMIC_NUMBERS, INV_ATOMIC_NUMBERS
|
|
12
|
+
from pysisyphus.Geometry import Geometry
|
|
13
|
+
from pysisyphus.helpers_pure import file_or_str
|
|
14
|
+
from pysisyphus.wrapper.jmol import view_cdd_cube
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def get_grid(coords3d, num=10, offset=3.0):
|
|
18
|
+
minx, miny, minz = coords3d.min(axis=0) - offset
|
|
19
|
+
maxx, maxy, maxz = coords3d.max(axis=0) + offset
|
|
20
|
+
X, Y, Z = np.mgrid[
|
|
21
|
+
minx : maxx : num * 1j,
|
|
22
|
+
miny : maxy : num * 1j,
|
|
23
|
+
minz : maxz : num * 1j,
|
|
24
|
+
]
|
|
25
|
+
xyz = np.stack((X.flatten(), Y.flatten(), Z.flatten()), axis=1)
|
|
26
|
+
spacing = np.array((maxx - minx, maxy - miny, maxz - minz)) / (num - 1)
|
|
27
|
+
return xyz, spacing, (num, num, num)
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
def get_grid_with_spacing(coords3d, spacing=0.30, margin=3.0):
|
|
31
|
+
minx, miny, minz = coords3d.min(axis=0) - margin
|
|
32
|
+
maxx, maxy, maxz = coords3d.max(axis=0) + margin
|
|
33
|
+
dx = maxx - minx
|
|
34
|
+
dy = maxy - miny
|
|
35
|
+
dz = maxz - minz
|
|
36
|
+
|
|
37
|
+
nx = ceil(dx / spacing)
|
|
38
|
+
ny = ceil(dy / spacing)
|
|
39
|
+
nz = ceil(dz / spacing)
|
|
40
|
+
X, Y, Z = np.mgrid[
|
|
41
|
+
minx : maxx : nx * 1j,
|
|
42
|
+
miny : maxy : ny * 1j,
|
|
43
|
+
minz : maxz : nz * 1j,
|
|
44
|
+
]
|
|
45
|
+
xyz = np.stack((X.flatten(), Y.flatten(), Z.flatten()), axis=1)
|
|
46
|
+
act_spacing = np.array(
|
|
47
|
+
((maxx - minx) / (nx - 1), (maxy - miny) / (ny - 1), (maxz - minz) / (nz - 1))
|
|
48
|
+
)
|
|
49
|
+
return xyz, act_spacing, (nx, ny, nz)
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
@dataclass
|
|
53
|
+
class Cube:
|
|
54
|
+
atoms: Tuple
|
|
55
|
+
coords3d: NDArray
|
|
56
|
+
origin: NDArray
|
|
57
|
+
npoints: NDArray
|
|
58
|
+
axes: NDArray
|
|
59
|
+
vol_data: NDArray
|
|
60
|
+
comment1: str = "Generated by pysisyphus"
|
|
61
|
+
comment2: str = ""
|
|
62
|
+
|
|
63
|
+
@staticmethod
|
|
64
|
+
def from_file(fn):
|
|
65
|
+
return parse_cube(fn)
|
|
66
|
+
|
|
67
|
+
@staticmethod
|
|
68
|
+
def from_wf_and_grid(wf, vol_data, origin, axes):
|
|
69
|
+
assert vol_data.ndim == 3, "Volume data 'vol_data' must be 3d!"
|
|
70
|
+
return Cube(
|
|
71
|
+
atoms=wf.atoms,
|
|
72
|
+
coords3d=wf.coords3d,
|
|
73
|
+
origin=origin,
|
|
74
|
+
npoints=vol_data.shape,
|
|
75
|
+
axes=axes,
|
|
76
|
+
vol_data=vol_data,
|
|
77
|
+
)
|
|
78
|
+
|
|
79
|
+
def to_str(self):
|
|
80
|
+
return cube_to_str(
|
|
81
|
+
self.atoms,
|
|
82
|
+
self.coords3d,
|
|
83
|
+
self.vol_data.reshape(*self.npoints),
|
|
84
|
+
self.origin,
|
|
85
|
+
self.axes,
|
|
86
|
+
)
|
|
87
|
+
|
|
88
|
+
def write(self, fn):
|
|
89
|
+
with open(fn, "w") as handle:
|
|
90
|
+
handle.write(self.to_str())
|
|
91
|
+
|
|
92
|
+
def view_cdd(self, **kwargs):
|
|
93
|
+
with tempfile.NamedTemporaryFile("w", suffix=".cube") as tmp_cube:
|
|
94
|
+
self.write(tmp_cube.name)
|
|
95
|
+
view_cdd_cube(tmp_cube.name, **kwargs)
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
@file_or_str(".cube", ".cub")
|
|
99
|
+
def parse_cube(text):
|
|
100
|
+
int_ = pp.common.integer
|
|
101
|
+
sci_real = pp.common.sci_real
|
|
102
|
+
|
|
103
|
+
def get_line_word(*args):
|
|
104
|
+
return pp.Word(*args).setWhitespaceChars("\n")
|
|
105
|
+
|
|
106
|
+
comment = get_line_word(pp.printables + " \t")
|
|
107
|
+
cart_vec = pp.Group(sci_real + sci_real + sci_real)
|
|
108
|
+
axis = pp.Group(int_ + cart_vec)
|
|
109
|
+
atom_line = pp.Group(
|
|
110
|
+
int_.set_results_name("atomic_num")
|
|
111
|
+
+ sci_real.set_results_name("charge")
|
|
112
|
+
+ cart_vec.set_results_name("coords")
|
|
113
|
+
+ pp.LineEnd()
|
|
114
|
+
)
|
|
115
|
+
|
|
116
|
+
parser = (
|
|
117
|
+
comment.set_results_name("comment1")
|
|
118
|
+
+ comment.set_results_name("comment2")
|
|
119
|
+
+ int_.set_results_name("atom_num")
|
|
120
|
+
+ cart_vec.set_results_name("origin")
|
|
121
|
+
+ axis.set_results_name("axis1")
|
|
122
|
+
+ axis.set_results_name("axis2")
|
|
123
|
+
+ axis.set_results_name("axis3")
|
|
124
|
+
+ pp.ZeroOrMore(atom_line).set_results_name("atom_lines")
|
|
125
|
+
+ pp.ZeroOrMore(sci_real).set_results_name("vol_data")
|
|
126
|
+
)
|
|
127
|
+
res = parser.parseString(text).as_dict()
|
|
128
|
+
|
|
129
|
+
comment1 = " ".join(res["comment1"])
|
|
130
|
+
comment2 = " ".join(res["comment2"])
|
|
131
|
+
atom_num = res["atom_num"]
|
|
132
|
+
atom_lines = res["atom_lines"]
|
|
133
|
+
assert atom_num == len(atom_lines)
|
|
134
|
+
|
|
135
|
+
atom_nums, coords3d = zip(*[(al["atomic_num"], al["coords"]) for al in atom_lines])
|
|
136
|
+
atoms = [INV_ATOMIC_NUMBERS[an].capitalize() for an in atom_nums]
|
|
137
|
+
coords3d = np.array(coords3d)
|
|
138
|
+
origin = np.array(res["origin"])
|
|
139
|
+
|
|
140
|
+
npoints, axes = zip(*[res[k] for k in ("axis1", "axis2", "axis3")])
|
|
141
|
+
npoints = np.array(npoints, int)
|
|
142
|
+
assert all(npoints > 0), "Only Bohr are supported!"
|
|
143
|
+
axes = np.array(axes, float)
|
|
144
|
+
vol_data = np.array(res["vol_data"]).reshape(*npoints)
|
|
145
|
+
|
|
146
|
+
cube = Cube(
|
|
147
|
+
atoms=atoms,
|
|
148
|
+
coords3d=coords3d,
|
|
149
|
+
origin=origin,
|
|
150
|
+
npoints=npoints,
|
|
151
|
+
axes=axes,
|
|
152
|
+
vol_data=vol_data,
|
|
153
|
+
comment1=comment1,
|
|
154
|
+
comment2=comment2,
|
|
155
|
+
)
|
|
156
|
+
|
|
157
|
+
return cube
|
|
158
|
+
|
|
159
|
+
|
|
160
|
+
@file_or_str(".cube", ".cub")
|
|
161
|
+
def geom_from_cube(text, **kwargs):
|
|
162
|
+
cube = parse_cube(text)
|
|
163
|
+
geom = Geometry(cube.atoms, cube.coords3d, **kwargs)
|
|
164
|
+
return geom
|
|
165
|
+
|
|
166
|
+
|
|
167
|
+
CUBE_TPL = """{{ comment1 }}
|
|
168
|
+
{{ comment2 }}
|
|
169
|
+
{{ ifmt(atom_nums|length) }} {{ fmt(origin_x) }} {{ fmt(origin_y) }} {{ fmt(origin_z) }}
|
|
170
|
+
{% for n_points, (x, y, z) in zip(axes_npoints, axes) %}
|
|
171
|
+
{{ ifmt(n_points) }} {{ fmt(x) }} {{ fmt(y) }} {{ fmt(z) }}
|
|
172
|
+
{% endfor %}
|
|
173
|
+
{% for atomic_num, (x, y, z) in zip(atom_nums, coords3d) %}
|
|
174
|
+
{{ ifmt(atomic_num) }} 0.000000 {{ fmt(x) }} {{ fmt(y) }} {{ fmt(z) }}
|
|
175
|
+
{% endfor %}
|
|
176
|
+
{{ grid_str }}
|
|
177
|
+
"""
|
|
178
|
+
|
|
179
|
+
|
|
180
|
+
def cube_to_str(atoms, coords3d, vol_data, origin, axes):
|
|
181
|
+
assert vol_data.ndim == 3
|
|
182
|
+
env = jinja2.Environment(trim_blocks=True, lstrip_blocks=True)
|
|
183
|
+
env.globals.update(zip=zip)
|
|
184
|
+
tpl = env.from_string(CUBE_TPL)
|
|
185
|
+
|
|
186
|
+
org_x, org_y, org_z = origin
|
|
187
|
+
axes_npoints = vol_data.shape
|
|
188
|
+
atom_nums = [ATOMIC_NUMBERS[atom.lower()] for atom in atoms]
|
|
189
|
+
nx, ny, nz = axes_npoints
|
|
190
|
+
grid_str = ""
|
|
191
|
+
for x in range(nx):
|
|
192
|
+
for y in range(ny):
|
|
193
|
+
for z in range(nz):
|
|
194
|
+
d = "{: >12.6e} ".format(vol_data[x, y, z])
|
|
195
|
+
grid_str += d
|
|
196
|
+
if z % 6 == 5:
|
|
197
|
+
grid_str += "\n"
|
|
198
|
+
grid_str += "\n"
|
|
199
|
+
|
|
200
|
+
def fmt(num):
|
|
201
|
+
return f"{num: >12.6f}"
|
|
202
|
+
|
|
203
|
+
def ifmt(num):
|
|
204
|
+
return f"{num: >5d}"
|
|
205
|
+
|
|
206
|
+
rendered = tpl.render(
|
|
207
|
+
fmt=fmt,
|
|
208
|
+
ifmt=ifmt,
|
|
209
|
+
origin_x=org_x,
|
|
210
|
+
origin_y=org_y,
|
|
211
|
+
origin_z=org_z,
|
|
212
|
+
comment1="Generated by pysisyphus",
|
|
213
|
+
comment2=f"Total of {nx*ny*nz} points",
|
|
214
|
+
axes=axes,
|
|
215
|
+
axes_npoints=axes_npoints,
|
|
216
|
+
atom_nums=atom_nums,
|
|
217
|
+
coords3d=coords3d,
|
|
218
|
+
grid_str=grid_str,
|
|
219
|
+
)
|
|
220
|
+
return rendered
|
pysisyphus/io/fchk.py
ADDED
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
import re
|
|
2
|
+
|
|
3
|
+
import numpy as np
|
|
4
|
+
|
|
5
|
+
from pysisyphus.elem_data import INV_ATOMIC_NUMBERS
|
|
6
|
+
from pysisyphus.Geometry import Geometry
|
|
7
|
+
from pysisyphus.helpers_pure import file_or_str
|
|
8
|
+
from pysisyphus.wavefunction.shells import Shell, FCHKShells
|
|
9
|
+
from pysisyphus.wavefunction import Wavefunction
|
|
10
|
+
from pysisyphus.wavefunction.helpers import BFType
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
@file_or_str(".fchk")
|
|
14
|
+
def parse_fchk(text):
|
|
15
|
+
header_re = r"\s+".join(
|
|
16
|
+
(
|
|
17
|
+
r"(?P<keyword>[\w\-\s/\(\)=\*]+)",
|
|
18
|
+
r"(?P<kind>[HIRCL])",
|
|
19
|
+
r"(?P<length>N=)?",
|
|
20
|
+
r"(?P<num>[\d\-\+\.E]+)",
|
|
21
|
+
)
|
|
22
|
+
)
|
|
23
|
+
header_re = re.compile(header_re)
|
|
24
|
+
|
|
25
|
+
cur_keyword = None
|
|
26
|
+
lines = text.strip().split("\n")
|
|
27
|
+
# title1, titl2 are not used
|
|
28
|
+
_, _, *lines = lines
|
|
29
|
+
|
|
30
|
+
conv_funcs = {
|
|
31
|
+
"R": lambda line: [float(_) for _ in line.split()], # real
|
|
32
|
+
"I": lambda line: [int(_) for _ in line.split()], # integer
|
|
33
|
+
"C": lambda line: [line], # character
|
|
34
|
+
"H": lambda line: [bool(_) for _ in line.split()], # logical
|
|
35
|
+
"L": lambda line: [bool(_) for _ in line.split()], # logical
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
data = {}
|
|
39
|
+
for line in lines:
|
|
40
|
+
line = line.strip()
|
|
41
|
+
if mobj := header_re.match(line):
|
|
42
|
+
cur_keyword = mobj.group("keyword").strip()
|
|
43
|
+
conv_func = conv_funcs[mobj.group("kind")]
|
|
44
|
+
if mobj.group("length"):
|
|
45
|
+
data[cur_keyword] = list()
|
|
46
|
+
else:
|
|
47
|
+
data[cur_keyword] = conv_func(mobj.group("num"))[0]
|
|
48
|
+
continue
|
|
49
|
+
data[cur_keyword].extend(conv_func(line))
|
|
50
|
+
return data
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
@file_or_str(".fchk")
|
|
54
|
+
def shells_from_fchk(text):
|
|
55
|
+
data = parse_fchk(text)
|
|
56
|
+
|
|
57
|
+
def to_arr(key, dtype):
|
|
58
|
+
return np.array(data[key], dtype=dtype)
|
|
59
|
+
|
|
60
|
+
"""
|
|
61
|
+
These coordinates may not coincide with the basis functions?! Nonetheless,
|
|
62
|
+
basis functions are usually atom-centered. But just to be sure we use the
|
|
63
|
+
entries from 'Coordinates of each shell'.
|
|
64
|
+
# coords3d = to_arr("Current cartesian coordinates", float).reshape(-1, 3)
|
|
65
|
+
"""
|
|
66
|
+
atomic_nums = to_arr("Atomic numbers", int)
|
|
67
|
+
|
|
68
|
+
centers = to_arr("Shell to atom map", int) - 1
|
|
69
|
+
ang_moms = to_arr("Shell types", int)
|
|
70
|
+
prims_per_shell = to_arr("Number of primitives per shell", int)
|
|
71
|
+
|
|
72
|
+
prim_exponents = to_arr("Primitive exponents", float)
|
|
73
|
+
prim_coeffs = to_arr("Contraction coefficients", float)
|
|
74
|
+
try:
|
|
75
|
+
p_prim_coeffs = to_arr("P(S=P) Contraction coefficients", float)
|
|
76
|
+
except KeyError:
|
|
77
|
+
p_prim_coeffs = np.zeros_like(prim_coeffs)
|
|
78
|
+
shell_coords3d = to_arr("Coordinates of each shell", float).reshape(-1, 3)
|
|
79
|
+
|
|
80
|
+
_shells = list()
|
|
81
|
+
prim_ind = 0
|
|
82
|
+
for i, (center_ind, L, prim_num) in enumerate(
|
|
83
|
+
zip(centers, ang_moms, prims_per_shell)
|
|
84
|
+
):
|
|
85
|
+
# 0: s, 1: p, -1: sp, 2: 6d, -2: 5d, 3: 10f, -3: 7f, etc...
|
|
86
|
+
assert L <= 1, "Only spherical basis functions are supported."
|
|
87
|
+
# Convert SP-shell with L = -1 to a s-shell with L = 0.
|
|
88
|
+
# The p-shell is also created later.
|
|
89
|
+
L, is_sp = (0, True) if (L == -1) else (L, False)
|
|
90
|
+
|
|
91
|
+
coeffs = list()
|
|
92
|
+
p_coeffs = list()
|
|
93
|
+
exps = list()
|
|
94
|
+
for _ in range(prim_num):
|
|
95
|
+
coeffs.append(prim_coeffs[prim_ind])
|
|
96
|
+
p_coeffs.append(p_prim_coeffs[prim_ind])
|
|
97
|
+
exps.append(prim_exponents[prim_ind])
|
|
98
|
+
prim_ind += 1
|
|
99
|
+
atomic_num = atomic_nums[center_ind]
|
|
100
|
+
center = shell_coords3d[i]
|
|
101
|
+
|
|
102
|
+
def append_shell(coeffs, L=L):
|
|
103
|
+
shell = Shell(
|
|
104
|
+
L=abs(L),
|
|
105
|
+
atomic_num=atomic_num,
|
|
106
|
+
center=center,
|
|
107
|
+
coeffs=coeffs,
|
|
108
|
+
exps=exps,
|
|
109
|
+
center_ind=center_ind,
|
|
110
|
+
)
|
|
111
|
+
_shells.append(shell)
|
|
112
|
+
|
|
113
|
+
# Create shell with actual L.
|
|
114
|
+
# If we deal with a SP shell we also create the P shell below.
|
|
115
|
+
append_shell(coeffs)
|
|
116
|
+
if is_sp:
|
|
117
|
+
# Explicitly create p-shell
|
|
118
|
+
append_shell(p_coeffs, L=1)
|
|
119
|
+
shells = FCHKShells(_shells)
|
|
120
|
+
return shells
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
def atoms_from_data(data):
|
|
124
|
+
atomic_numbers = data["Atomic numbers"]
|
|
125
|
+
atoms = tuple([INV_ATOMIC_NUMBERS[Z] for Z in atomic_numbers])
|
|
126
|
+
return atoms
|
|
127
|
+
|
|
128
|
+
|
|
129
|
+
@file_or_str(".fchk")
|
|
130
|
+
def wavefunction_from_fchk(text):
|
|
131
|
+
data = parse_fchk(text)
|
|
132
|
+
|
|
133
|
+
charge = data["Charge"]
|
|
134
|
+
mult = data["Multiplicity"]
|
|
135
|
+
atoms = atoms_from_data(data)
|
|
136
|
+
coords = data["Current cartesian coordinates"]
|
|
137
|
+
unrestricted = "Beta Orbital Energies" in data
|
|
138
|
+
|
|
139
|
+
def mos_for_spin(spin):
|
|
140
|
+
mo_ens = data[f"{spin} Orbital Energies"]
|
|
141
|
+
mo_num = len(mo_ens)
|
|
142
|
+
mo_coeffs = np.array(data[f"{spin} MO coefficients"])
|
|
143
|
+
mo_coeffs = mo_coeffs.reshape(mo_num, mo_num)
|
|
144
|
+
return mo_coeffs
|
|
145
|
+
|
|
146
|
+
C_a = mos_for_spin("Alpha").T
|
|
147
|
+
occ_a = data["Number of alpha electrons"]
|
|
148
|
+
if unrestricted:
|
|
149
|
+
C_b = mos_for_spin("Beta")
|
|
150
|
+
occ_b = data["Number of beta electrons"]
|
|
151
|
+
else:
|
|
152
|
+
C_b = C_a.copy()
|
|
153
|
+
occ_b = occ_a
|
|
154
|
+
C = np.stack((C_a, C_b))
|
|
155
|
+
shells = shells_from_fchk(text)
|
|
156
|
+
return Wavefunction(
|
|
157
|
+
atoms=atoms,
|
|
158
|
+
coords=coords,
|
|
159
|
+
charge=charge,
|
|
160
|
+
mult=mult,
|
|
161
|
+
unrestricted=unrestricted,
|
|
162
|
+
occ=(occ_a, occ_b),
|
|
163
|
+
C=C,
|
|
164
|
+
bf_type=BFType.PURE_SPHERICAL,
|
|
165
|
+
shells=shells,
|
|
166
|
+
)
|
|
167
|
+
|
|
168
|
+
|
|
169
|
+
@file_or_str(".fchk")
|
|
170
|
+
def geom_from_fchk(text, **geom_kwargs):
|
|
171
|
+
data = parse_fchk(text)
|
|
172
|
+
atoms = atoms_from_data(data)
|
|
173
|
+
|
|
174
|
+
try:
|
|
175
|
+
coords = data["Opt point 1 Geometries"]
|
|
176
|
+
except KeyError:
|
|
177
|
+
coords = data["Current cartesian coordinates"]
|
|
178
|
+
coords = np.array(coords)
|
|
179
|
+
coords = coords.reshape(-1, 3 * len(atoms))
|
|
180
|
+
|
|
181
|
+
geoms = [Geometry(atoms, coords_, **geom_kwargs) for coords_ in coords]
|
|
182
|
+
if len(geoms) == 1:
|
|
183
|
+
geoms = geoms[0]
|
|
184
|
+
return geoms
|
pysisyphus/io/hdf5.py
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import h5py
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
def init_h5_group(f, group_name, data_model):
|
|
5
|
+
"""Create group with given name and data model."""
|
|
6
|
+
group = f.create_group(group_name)
|
|
7
|
+
# Create (resizable) datasets by using None in maxshape
|
|
8
|
+
for key, shape in data_model.items():
|
|
9
|
+
maxshape = (None,) if (len(shape) == 1) else (None, *shape[1:])
|
|
10
|
+
group.create_dataset(key, shape, maxshape=maxshape)
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def get_h5_group(fn, group_name, data_model=None, reset=False):
|
|
14
|
+
"""Return (and create if neccesary) group with given name and
|
|
15
|
+
data model."""
|
|
16
|
+
|
|
17
|
+
f = h5py.File(fn, mode="a")
|
|
18
|
+
# Shortcut
|
|
19
|
+
if data_model is None:
|
|
20
|
+
return f[group_name]
|
|
21
|
+
|
|
22
|
+
if group_name not in f:
|
|
23
|
+
init_h5_group(f, group_name, data_model)
|
|
24
|
+
group = f[group_name]
|
|
25
|
+
|
|
26
|
+
# Check compatibility of data_model and group. If they aren't compatible
|
|
27
|
+
# recreate the group with the proper shapes.
|
|
28
|
+
try:
|
|
29
|
+
compatible = [group[key].shape == shape for key, shape in data_model.items()]
|
|
30
|
+
except KeyError:
|
|
31
|
+
compatible = (False,)
|
|
32
|
+
compatible = all(compatible)
|
|
33
|
+
if (not compatible) or reset:
|
|
34
|
+
del f[group_name]
|
|
35
|
+
init_h5_group(f, group_name, data_model)
|
|
36
|
+
group = f[group_name]
|
|
37
|
+
|
|
38
|
+
return group
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
def resize_h5_group(group, max_cycles):
|
|
42
|
+
"""Increase size of first dimension of datasets in the given group."""
|
|
43
|
+
for key, dataset in group.items():
|
|
44
|
+
# No need to resize scalar datasets
|
|
45
|
+
if dataset.shape == ():
|
|
46
|
+
continue
|
|
47
|
+
new_shape = list(dataset.shape).copy()
|
|
48
|
+
new_shape[0] = max_cycles
|
|
49
|
+
dataset.resize(new_shape)
|
pysisyphus/io/hessian.py
ADDED
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import numpy as np
|
|
2
|
+
import h5py
|
|
3
|
+
|
|
4
|
+
from pysisyphus.Geometry import Geometry
|
|
5
|
+
from pysisyphus.helpers_pure import eigval_to_wavenumber
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
def save_hessian(h5_fn, geom, cart_hessian=None, energy=None, mult=None):
|
|
9
|
+
if cart_hessian is None:
|
|
10
|
+
cart_hessian = geom.cart_hessian
|
|
11
|
+
|
|
12
|
+
if energy is None:
|
|
13
|
+
energy = geom.energy
|
|
14
|
+
|
|
15
|
+
if mult is None:
|
|
16
|
+
mult = geom.calculator.mult
|
|
17
|
+
|
|
18
|
+
if len(geom.atoms) > 1:
|
|
19
|
+
proj_hessian = geom.eckart_projection(geom.mass_weigh_hessian(cart_hessian))
|
|
20
|
+
else:
|
|
21
|
+
proj_hessian = cart_hessian
|
|
22
|
+
eigvals, _ = np.linalg.eigh(proj_hessian)
|
|
23
|
+
vibfreqs = eigval_to_wavenumber(eigvals)
|
|
24
|
+
|
|
25
|
+
masses = geom.masses
|
|
26
|
+
atoms = geom.atoms
|
|
27
|
+
coords3d = geom.coords3d
|
|
28
|
+
|
|
29
|
+
# with h5py.File(h5_fn, "w") as handle:
|
|
30
|
+
# handle.create_dataset("hessian", data=cart_hessian)
|
|
31
|
+
# handle.create_dataset("vibfreqs", data=vibfreqs)
|
|
32
|
+
# handle.create_dataset("masses", data=masses)
|
|
33
|
+
# handle.create_dataset("coords3d", data=coords3d)
|
|
34
|
+
|
|
35
|
+
# try:
|
|
36
|
+
# handle.attrs["atoms"] = [atom.lower() for atom in atoms]
|
|
37
|
+
# except OSError:
|
|
38
|
+
# handle.create_dataset("atoms", data=[atom.lower() for atom in atoms])
|
|
39
|
+
# handle.attrs["energy"] = energy
|
|
40
|
+
# handle.attrs["mult"] = mult
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
def save_third_deriv(h5_fn, geom, third_deriv_result, H_mw, H_proj):
|
|
44
|
+
# with h5py.File(h5_fn, "w") as handle:
|
|
45
|
+
# for key, value in third_deriv_result._asdict().items():
|
|
46
|
+
# handle.create_dataset(key, data=value)
|
|
47
|
+
|
|
48
|
+
# handle.create_dataset("coords3d", data=geom.coords3d)
|
|
49
|
+
# handle.create_dataset("masses", data=geom.masses)
|
|
50
|
+
# handle.create_dataset("H_mw", data=H_mw)
|
|
51
|
+
# handle.create_dataset("H_proj", data=H_proj)
|
|
52
|
+
# try:
|
|
53
|
+
# handle.attrs["atoms"] = [atom.lower() for atom in atoms]
|
|
54
|
+
# except OSError:
|
|
55
|
+
# handle.create_dataset("atoms", data=[atom.lower() for atom in atoms])
|
|
56
|
+
pass
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
def geom_from_hessian(h5_fn, **geom_kwargs):
|
|
60
|
+
with h5py.File(h5_fn, "r") as handle:
|
|
61
|
+
try:
|
|
62
|
+
atoms = [atom.capitalize() for atom in handle.attrs["atoms"]]
|
|
63
|
+
except (KeyError, TypeError):
|
|
64
|
+
atoms = [atom.capitalize() for atom in handle["atoms"][:]]
|
|
65
|
+
coords3d = handle["coords3d"][:]
|
|
66
|
+
energy = handle.attrs["energy"]
|
|
67
|
+
cart_hessian = handle["hessian"][:]
|
|
68
|
+
|
|
69
|
+
geom = Geometry(atoms=atoms, coords=coords3d, **geom_kwargs)
|
|
70
|
+
geom.cart_hessian = cart_hessian
|
|
71
|
+
geom.energy = energy
|
|
72
|
+
return geom
|