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,1171 @@
|
|
|
1
|
+
# [1] https://aip.scitation.org/doi/pdf/10.1063/5.0004046
|
|
2
|
+
# Efficient implementation of the superposition of atomic potentials initial
|
|
3
|
+
# guess for electronic structure calculations in Gaussian basis sets
|
|
4
|
+
# Lehtola, Visscher, Engel, 2020
|
|
5
|
+
|
|
6
|
+
import itertools as it
|
|
7
|
+
from math import sqrt, log, pi
|
|
8
|
+
from pathlib import Path
|
|
9
|
+
import textwrap
|
|
10
|
+
from typing import List, Literal
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
import h5py
|
|
14
|
+
from jinja2 import Template
|
|
15
|
+
from joblib import Memory
|
|
16
|
+
import numpy as np
|
|
17
|
+
from numpy.typing import NDArray
|
|
18
|
+
import scipy as sp
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
from pysisyphus.config import L_MAX, L_AUX_MAX
|
|
22
|
+
from pysisyphus.elem_data import (
|
|
23
|
+
ATOMIC_NUMBERS,
|
|
24
|
+
INV_ATOMIC_NUMBERS,
|
|
25
|
+
nuc_charges_for_atoms,
|
|
26
|
+
)
|
|
27
|
+
from pysisyphus.helpers_pure import file_or_str
|
|
28
|
+
from pysisyphus.linalg import multi_component_sym_mat
|
|
29
|
+
from pysisyphus.wavefunction.helpers import (
|
|
30
|
+
canonical_order,
|
|
31
|
+
get_l,
|
|
32
|
+
get_shell_shape,
|
|
33
|
+
L_MAP_INV,
|
|
34
|
+
permut_for_order,
|
|
35
|
+
)
|
|
36
|
+
|
|
37
|
+
from pysisyphus.wavefunction.ints import (
|
|
38
|
+
cart_gto3d,
|
|
39
|
+
coulomb3d,
|
|
40
|
+
diag_quadrupole3d,
|
|
41
|
+
dipole3d,
|
|
42
|
+
kinetic3d,
|
|
43
|
+
ovlp3d,
|
|
44
|
+
quadrupole3d,
|
|
45
|
+
int2c2e3d,
|
|
46
|
+
int3c2e3d_sph,
|
|
47
|
+
)
|
|
48
|
+
|
|
49
|
+
from pysisyphus.wavefunction.cart2sph import cart2sph_coeffs
|
|
50
|
+
from pysisyphus.wavefunction.normalization import norm_cgto_lmn
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
class Shell:
|
|
54
|
+
def __init__(
|
|
55
|
+
self,
|
|
56
|
+
L: int,
|
|
57
|
+
center: NDArray[float],
|
|
58
|
+
coeffs: NDArray[float],
|
|
59
|
+
exps: NDArray[float],
|
|
60
|
+
center_ind: int,
|
|
61
|
+
atomic_num=None,
|
|
62
|
+
shell_index=None,
|
|
63
|
+
index=None,
|
|
64
|
+
# min_coeff: float = 1e-8,
|
|
65
|
+
):
|
|
66
|
+
self.L = get_l(L)
|
|
67
|
+
self.center = np.array(center, dtype=float) # (x, y, z), 1d array
|
|
68
|
+
coeffs = np.array(coeffs, dtype=float)
|
|
69
|
+
# cur_min_coeff = np.abs(coeffs).min()
|
|
70
|
+
# assert (
|
|
71
|
+
# cur_min_coeff >= min_coeff
|
|
72
|
+
# ), f"Got invalid contraction coeff of '{cur_min_coeff:.6f}'"
|
|
73
|
+
# Store original contraction coefficients
|
|
74
|
+
self.coeffs_org = coeffs.copy()
|
|
75
|
+
# Orbital exponents, 1d array
|
|
76
|
+
self.exps = np.array(exps, dtype=float)
|
|
77
|
+
assert self.coeffs_org.size == self.exps.size
|
|
78
|
+
coeffs = np.array(coeffs)
|
|
79
|
+
assert coeffs.size == self.exps.size
|
|
80
|
+
self.center_ind = int(center_ind)
|
|
81
|
+
if atomic_num is None:
|
|
82
|
+
atomic_num = -1
|
|
83
|
+
self.atomic_num = int(atomic_num)
|
|
84
|
+
if shell_index is not None:
|
|
85
|
+
self.shell_index = shell_index
|
|
86
|
+
if index is not None:
|
|
87
|
+
self.index = index
|
|
88
|
+
|
|
89
|
+
self.coeffs, _ = norm_cgto_lmn(coeffs, self.exps, self.L)
|
|
90
|
+
|
|
91
|
+
try:
|
|
92
|
+
self.atom = INV_ATOMIC_NUMBERS[self.atomic_num]
|
|
93
|
+
except KeyError:
|
|
94
|
+
self.atom = "X"
|
|
95
|
+
self.atom = self.atom.lower()
|
|
96
|
+
|
|
97
|
+
def as_tuple(self):
|
|
98
|
+
return self.L, self.center, self.coeffs, self.exps, self.index, self.size
|
|
99
|
+
|
|
100
|
+
def exps_coeffs_iter(self):
|
|
101
|
+
return zip(self.exps, self.coeffs)
|
|
102
|
+
|
|
103
|
+
@property
|
|
104
|
+
def contr_depth(self):
|
|
105
|
+
return self.coeffs.size
|
|
106
|
+
|
|
107
|
+
@property
|
|
108
|
+
def cart_powers(self):
|
|
109
|
+
return np.array(canonical_order(self.L), dtype=int)
|
|
110
|
+
|
|
111
|
+
@property
|
|
112
|
+
def size(self):
|
|
113
|
+
"""Number of cartesian basis functions in the shell."""
|
|
114
|
+
return self.cart_size
|
|
115
|
+
|
|
116
|
+
@property
|
|
117
|
+
def cart_size(self):
|
|
118
|
+
"""Number of cartesian basis functions in the shell."""
|
|
119
|
+
L = self.L
|
|
120
|
+
return (L + 1) * (L + 2) // 2
|
|
121
|
+
|
|
122
|
+
@property
|
|
123
|
+
def sph_size(self):
|
|
124
|
+
"""Number of cartesian basis functions in the shell."""
|
|
125
|
+
return 2 * self.L + 1
|
|
126
|
+
|
|
127
|
+
@property
|
|
128
|
+
def index(self) -> int:
|
|
129
|
+
return self._index
|
|
130
|
+
|
|
131
|
+
@index.setter
|
|
132
|
+
def index(self, index: int):
|
|
133
|
+
self._index = int(index)
|
|
134
|
+
|
|
135
|
+
@property
|
|
136
|
+
def shell_index(self) -> int:
|
|
137
|
+
return self._shell_index
|
|
138
|
+
|
|
139
|
+
@shell_index.setter
|
|
140
|
+
def shell_index(self, shell_index: int):
|
|
141
|
+
self._shell_index = shell_index
|
|
142
|
+
|
|
143
|
+
def to_pyscf_shell(self):
|
|
144
|
+
key = L_MAP_INV[self.L]
|
|
145
|
+
lines = [
|
|
146
|
+
f"{self.atom.title()} {key.upper()}",
|
|
147
|
+
]
|
|
148
|
+
lines += [
|
|
149
|
+
f"{exp_:> 18.10f} {coeff:>18.10f}"
|
|
150
|
+
for exp_, coeff in zip(self.exps, self.coeffs)
|
|
151
|
+
]
|
|
152
|
+
return "\n".join(lines)
|
|
153
|
+
|
|
154
|
+
def to_sap_shell(self):
|
|
155
|
+
"""Fix contraction coefficients, for use in SAP-initial guess calculation.
|
|
156
|
+
|
|
157
|
+
See [1]."""
|
|
158
|
+
# SAP shells must always be s-shells
|
|
159
|
+
assert self.L == 0
|
|
160
|
+
self.coeffs = self.coeffs_org
|
|
161
|
+
coeffs_sum = self.coeffs.sum()
|
|
162
|
+
# Check sum rule; sum should equal -Z.
|
|
163
|
+
assert (coeffs_sum + ATOMIC_NUMBERS[self.atom.lower()]) <= 1e-5
|
|
164
|
+
# The potential fits were carried out for functions of the form:
|
|
165
|
+
# g_p(r) = (α_p / π)**1.5 * exp(-α_p / r) .
|
|
166
|
+
# So we multiply the prefactor onto the contraction coefficients.
|
|
167
|
+
# See [1], p. 152, just above Eq. (2).
|
|
168
|
+
self.coeffs *= (self.exps / np.pi) ** 1.5
|
|
169
|
+
|
|
170
|
+
def __str__(self):
|
|
171
|
+
try:
|
|
172
|
+
center_str = f", at atom {self.center_ind}"
|
|
173
|
+
except AttributeError:
|
|
174
|
+
center_str = ""
|
|
175
|
+
return f"Shell(L={self.L}, {self.contr_depth} pGTO{center_str})"
|
|
176
|
+
|
|
177
|
+
def __repr__(self):
|
|
178
|
+
return self.__str__()
|
|
179
|
+
|
|
180
|
+
|
|
181
|
+
Ordering = Literal["native", "pysis"]
|
|
182
|
+
|
|
183
|
+
|
|
184
|
+
class Shells:
|
|
185
|
+
sph_Ps = {l: np.eye(2 * l + 1) for l in range(max(L_MAX, L_AUX_MAX) + 1)}
|
|
186
|
+
|
|
187
|
+
def __init__(
|
|
188
|
+
self,
|
|
189
|
+
shells: List[Shell],
|
|
190
|
+
screen: bool = False,
|
|
191
|
+
cache: bool = False,
|
|
192
|
+
cache_path: str = "./cache",
|
|
193
|
+
ordering: Ordering = "native",
|
|
194
|
+
):
|
|
195
|
+
self.shells = shells
|
|
196
|
+
self.ordering = ordering
|
|
197
|
+
self.screen = screen
|
|
198
|
+
self.cache = cache
|
|
199
|
+
self.cache_path = Path(cache_path)
|
|
200
|
+
"""
|
|
201
|
+
'native' refers to the original ordering, as used in the QC program. The
|
|
202
|
+
ordering will be reflected in the MO coefficient ordering. With 'native'
|
|
203
|
+
the integrals calculated by pysisyphus must be reorderd, to match the native
|
|
204
|
+
ordering of the MO coefficients.
|
|
205
|
+
"""
|
|
206
|
+
assert ordering in ("pysis", "native")
|
|
207
|
+
|
|
208
|
+
# Now that we have all Shell objects, we can set their starting indices
|
|
209
|
+
index = 0
|
|
210
|
+
shell_index = 0
|
|
211
|
+
for shell in self.shells:
|
|
212
|
+
shell.shell_index = shell_index
|
|
213
|
+
shell.index = index
|
|
214
|
+
index += shell.size
|
|
215
|
+
shell_index += 1
|
|
216
|
+
|
|
217
|
+
# Try to construct Cartesian permutation matrix from cart_order, if defnied.
|
|
218
|
+
try:
|
|
219
|
+
self.cart_Ps = permut_for_order(self.cart_order)
|
|
220
|
+
except AttributeError:
|
|
221
|
+
pass
|
|
222
|
+
|
|
223
|
+
self.atoms, self.coords3d = self.atoms_coords3d
|
|
224
|
+
# Precontract & store coefficients for reordering spherical basis functions
|
|
225
|
+
# and converting them from Cartesian basis functions.
|
|
226
|
+
self.reorder_c2s_coeffs = self.P_sph @ self.cart2sph_coeffs
|
|
227
|
+
|
|
228
|
+
# Enable disk cache for 1el-integrals
|
|
229
|
+
if self.cache:
|
|
230
|
+
self.memory = Memory(self.cache_path, verbose=0)
|
|
231
|
+
self.get_1el_ints_cart = self.memory.cache(self.get_1el_ints_cart)
|
|
232
|
+
self.get_1el_ints_sph = self.memory.cache(self.get_1el_ints_sph)
|
|
233
|
+
|
|
234
|
+
def __len__(self):
|
|
235
|
+
return len(self.shells)
|
|
236
|
+
|
|
237
|
+
def __getitem__(self, key):
|
|
238
|
+
return self.shells[key]
|
|
239
|
+
|
|
240
|
+
def print_shells(self):
|
|
241
|
+
for shell in self.shells:
|
|
242
|
+
print(shell)
|
|
243
|
+
|
|
244
|
+
def as_tuple(self):
|
|
245
|
+
# Ls, centers, contr_coeffs, exponents, indices, sizes
|
|
246
|
+
return zip(*[shell.as_tuple() for shell in self.shells])
|
|
247
|
+
|
|
248
|
+
@property
|
|
249
|
+
def cart_size(self):
|
|
250
|
+
"""Number of cartesian basis functions."""
|
|
251
|
+
return sum([shell.cart_size for shell in self.shells])
|
|
252
|
+
|
|
253
|
+
@property
|
|
254
|
+
def sph_size(self):
|
|
255
|
+
"""Number of spherical basis."""
|
|
256
|
+
return sum([shell.sph_size for shell in self.shells])
|
|
257
|
+
|
|
258
|
+
def as_arrays(self, fortran=False):
|
|
259
|
+
"""Similar to the approach in libcint."""
|
|
260
|
+
# bas_centers
|
|
261
|
+
# One entry per shell, integer array.
|
|
262
|
+
# center_ind, atomic number, pointer to center coordinates in bas_data (3 integers)
|
|
263
|
+
bas_centers = list()
|
|
264
|
+
# bas_spec
|
|
265
|
+
# One entry per shell, integer array.
|
|
266
|
+
# shell_ind, total angmom, N_pgto, N_cgto, \
|
|
267
|
+
# pointer to contraction coefficients and exponents in bas_data \
|
|
268
|
+
# (2*N_pgto floats)
|
|
269
|
+
bas_spec = list()
|
|
270
|
+
# bas_data
|
|
271
|
+
# Float array. Starts with 3 * N_centers floats, containing the center
|
|
272
|
+
# coordinates. Continues with alternating contraction coefficient and
|
|
273
|
+
# orbital exponent data.
|
|
274
|
+
bas_data = list()
|
|
275
|
+
pointer = 1 if fortran else 0
|
|
276
|
+
|
|
277
|
+
shells = self.shells
|
|
278
|
+
# Store center data, i.e., where the basis functions are located.
|
|
279
|
+
for shell in shells:
|
|
280
|
+
center_ind = shell.center_ind
|
|
281
|
+
bas_data.extend(shell.center) # Store coordinates
|
|
282
|
+
atomic_num = shell.atomic_num
|
|
283
|
+
if atomic_num is None:
|
|
284
|
+
atomic_num = -1
|
|
285
|
+
bas_centers.append((center_ind, atomic_num, pointer))
|
|
286
|
+
pointer += 3
|
|
287
|
+
|
|
288
|
+
# Store contraction coefficients and primitive exponents.
|
|
289
|
+
for shell_ind, shell in enumerate(self.shells):
|
|
290
|
+
# L, center, coeffs, exponents, index, size = shell.as_tuple()
|
|
291
|
+
L, _, _, exponents, _, _ = shell.as_tuple()
|
|
292
|
+
contr_coeffs = shell.coeffs_org
|
|
293
|
+
nprim = len(contr_coeffs)
|
|
294
|
+
# ncontr is hardcoded to 1 for now, as there are no special functions
|
|
295
|
+
# to handle general contractions.
|
|
296
|
+
ncontr = 1
|
|
297
|
+
bas_spec.append((shell_ind, L, nprim, ncontr, pointer))
|
|
298
|
+
bas_data.extend(contr_coeffs)
|
|
299
|
+
pointer += nprim
|
|
300
|
+
bas_data.extend(exponents)
|
|
301
|
+
pointer += nprim
|
|
302
|
+
|
|
303
|
+
bas_centers = np.array(bas_centers, dtype=int)
|
|
304
|
+
bas_spec = np.array(bas_spec, dtype=int)
|
|
305
|
+
bas_data = np.array(bas_data, dtype=float)
|
|
306
|
+
return bas_centers, bas_spec, bas_data
|
|
307
|
+
|
|
308
|
+
def to_sympleints_arrays(self):
|
|
309
|
+
shells = self.shells
|
|
310
|
+
# center_ind, atomic_num, L, nprims
|
|
311
|
+
centers = np.zeros((len(shells), 3))
|
|
312
|
+
shell_data = list()
|
|
313
|
+
coefficients = list()
|
|
314
|
+
exponents = list()
|
|
315
|
+
for i, shell in enumerate(shells):
|
|
316
|
+
coeffs = shell.coeffs_org
|
|
317
|
+
coefficients.extend(coeffs.tolist())
|
|
318
|
+
exponents.extend(shell.exps.tolist())
|
|
319
|
+
nprims = len(coeffs)
|
|
320
|
+
|
|
321
|
+
centers[i] = shell.center
|
|
322
|
+
atomic_num = shell.atomic_num
|
|
323
|
+
if atomic_num is None:
|
|
324
|
+
atomic_num = -1
|
|
325
|
+
shell_data.append((shell.center_ind, atomic_num, shell.L, nprims))
|
|
326
|
+
shell_data = np.array(shell_data, dtype=np.int32)
|
|
327
|
+
coefficients = np.array(coefficients)
|
|
328
|
+
exponents = np.array(exponents)
|
|
329
|
+
return shell_data, centers, coefficients, exponents
|
|
330
|
+
|
|
331
|
+
def dump_to_h5_group(self, h5_handle, group_name):
|
|
332
|
+
group = h5_handle.create_group(group_name)
|
|
333
|
+
shell_data, centers, coefficients, exponents = self.to_sympleints_arrays()
|
|
334
|
+
group.create_dataset("shell_data", data=shell_data)
|
|
335
|
+
group.create_dataset("centers", data=centers)
|
|
336
|
+
group.create_dataset("coefficients", data=coefficients)
|
|
337
|
+
group.create_dataset("exponents", data=exponents)
|
|
338
|
+
|
|
339
|
+
@property
|
|
340
|
+
def l_max(self):
|
|
341
|
+
return max([shell.L for shell in self.shells])
|
|
342
|
+
|
|
343
|
+
@property
|
|
344
|
+
def atoms_coords3d(self):
|
|
345
|
+
atoms = list()
|
|
346
|
+
coords3d = list()
|
|
347
|
+
center_inds = list()
|
|
348
|
+
for shell in self.shells:
|
|
349
|
+
center_ind = shell.center_ind
|
|
350
|
+
# Skip cycle if we already registered this center
|
|
351
|
+
if center_ind in center_inds:
|
|
352
|
+
continue
|
|
353
|
+
else:
|
|
354
|
+
center_inds.append(center_ind)
|
|
355
|
+
try:
|
|
356
|
+
atom = INV_ATOMIC_NUMBERS[shell.atomic_num]
|
|
357
|
+
# Use dummy atom when atomic_num is not set / None
|
|
358
|
+
except KeyError:
|
|
359
|
+
atom = "X"
|
|
360
|
+
atoms.append(atom)
|
|
361
|
+
center = shell.center
|
|
362
|
+
coords3d.append(center)
|
|
363
|
+
coords3d = np.array(coords3d)
|
|
364
|
+
return atoms, coords3d
|
|
365
|
+
|
|
366
|
+
@property
|
|
367
|
+
def cart_bf_num(self):
|
|
368
|
+
return sum([shell.size for shell in self.shells])
|
|
369
|
+
|
|
370
|
+
def from_basis(self, name, shells_cls=None, **kwargs):
|
|
371
|
+
from pysisyphus.wavefunction.Basis import shells_with_basis
|
|
372
|
+
|
|
373
|
+
atoms, coords3d = self.atoms_coords3d
|
|
374
|
+
if shells_cls is None:
|
|
375
|
+
shells_cls = type(self)
|
|
376
|
+
return shells_with_basis(
|
|
377
|
+
atoms, coords3d, name=name, shells_cls=shells_cls, **kwargs
|
|
378
|
+
)
|
|
379
|
+
|
|
380
|
+
@staticmethod
|
|
381
|
+
@file_or_str(".in")
|
|
382
|
+
def from_aomix(text):
|
|
383
|
+
# import here, to avoid cyclic imports
|
|
384
|
+
from pysisyphus.io.aomix import shells_from_aomix
|
|
385
|
+
|
|
386
|
+
shells = shells_from_aomix(text)
|
|
387
|
+
return shells
|
|
388
|
+
|
|
389
|
+
@staticmethod
|
|
390
|
+
@file_or_str(".json")
|
|
391
|
+
def from_orca_json(text):
|
|
392
|
+
# import here, to avoid cyclic imports
|
|
393
|
+
from pysisyphus.io.orca import shells_from_json
|
|
394
|
+
|
|
395
|
+
shells = shells_from_json(text)
|
|
396
|
+
return shells
|
|
397
|
+
|
|
398
|
+
@staticmethod
|
|
399
|
+
@file_or_str(".fchk")
|
|
400
|
+
def from_fchk(text):
|
|
401
|
+
# import here, to avoid cyclic imports
|
|
402
|
+
from pysisyphus.io.fchk import shells_from_fchk
|
|
403
|
+
|
|
404
|
+
shells = shells_from_fchk(text)
|
|
405
|
+
return shells
|
|
406
|
+
|
|
407
|
+
@staticmethod
|
|
408
|
+
def from_sympleints_arrays(shell_data, centers, coefficients, exponents, **kwargs):
|
|
409
|
+
shells = list()
|
|
410
|
+
pointer = 0
|
|
411
|
+
for i, (center_ind, atomic_num, L, nprims) in enumerate(shell_data):
|
|
412
|
+
coeffs = coefficients[pointer : pointer + nprims]
|
|
413
|
+
exps = exponents[pointer : pointer + nprims]
|
|
414
|
+
shell = Shell(L, centers[i], coeffs, exps, center_ind, atomic_num)
|
|
415
|
+
pointer += nprims
|
|
416
|
+
shells.append(shell)
|
|
417
|
+
return Shells(shells, **kwargs)
|
|
418
|
+
|
|
419
|
+
@staticmethod
|
|
420
|
+
def from_sympleints_h5(h5_fn, group_name="shells"):
|
|
421
|
+
with h5py.File(h5_fn, "r") as handle:
|
|
422
|
+
group = handle[group_name]
|
|
423
|
+
shell_data = group["shell_data"][:]
|
|
424
|
+
centers = group["centers"][:]
|
|
425
|
+
coefficients = group["coefficients"][:]
|
|
426
|
+
exponents = group["exponents"][:]
|
|
427
|
+
return Shells.from_sympleints_arrays(
|
|
428
|
+
shell_data, centers, coefficients, exponents
|
|
429
|
+
)
|
|
430
|
+
|
|
431
|
+
@staticmethod
|
|
432
|
+
def from_pyscf_mol(mol):
|
|
433
|
+
shells = list()
|
|
434
|
+
for bas_id in range(mol.nbas):
|
|
435
|
+
L = mol.bas_angular(bas_id)
|
|
436
|
+
center = mol.bas_coord(bas_id)
|
|
437
|
+
coeffs = mol.bas_ctr_coeff(bas_id).flatten()
|
|
438
|
+
exps = mol.bas_exp(bas_id)
|
|
439
|
+
assert (
|
|
440
|
+
coeffs.size == exps.size
|
|
441
|
+
), "General contractions are not yet supported."
|
|
442
|
+
center_ind = mol.bas_atom(bas_id)
|
|
443
|
+
atom_symbol = mol.atom_symbol(center_ind)
|
|
444
|
+
atomic_num = ATOMIC_NUMBERS[atom_symbol.lower()]
|
|
445
|
+
shell = Shell(L, center, coeffs, exps, center_ind, atomic_num)
|
|
446
|
+
shells.append(shell)
|
|
447
|
+
return PySCFShells(shells)
|
|
448
|
+
|
|
449
|
+
def to_pyscf_mol(self):
|
|
450
|
+
# TODO: this would be better suited as a method of Wavefunction,
|
|
451
|
+
# as pyscf Moles must have sensible spin & charge etc.
|
|
452
|
+
# TODO: currently, this does not support different basis sets
|
|
453
|
+
# for the same element.
|
|
454
|
+
try:
|
|
455
|
+
from pyscf import gto
|
|
456
|
+
except ModuleNotFoundError:
|
|
457
|
+
return None
|
|
458
|
+
|
|
459
|
+
unique_atoms = set()
|
|
460
|
+
basis = dict()
|
|
461
|
+
atoms_coords = list()
|
|
462
|
+
for _, center_shells in self.center_shell_iter():
|
|
463
|
+
center_shells = list(center_shells)
|
|
464
|
+
shell0 = center_shells[0]
|
|
465
|
+
atom = shell0.atom
|
|
466
|
+
x, y, z = shell0.center
|
|
467
|
+
atoms_coords.append(f"{atom} {x} {y} {z}")
|
|
468
|
+
if atom not in unique_atoms:
|
|
469
|
+
unique_atoms.add(atom)
|
|
470
|
+
else:
|
|
471
|
+
continue
|
|
472
|
+
atom_shells = "\n".join([shell.to_pyscf_shell() for shell in center_shells])
|
|
473
|
+
basis[atom] = gto.basis.parse(atom_shells)
|
|
474
|
+
|
|
475
|
+
mol = gto.Mole()
|
|
476
|
+
mol.atom = "; ".join(atoms_coords)
|
|
477
|
+
mol.unit = "Bohr"
|
|
478
|
+
mol.basis = basis
|
|
479
|
+
mol.build()
|
|
480
|
+
return mol
|
|
481
|
+
|
|
482
|
+
def center_shell_iter(self):
|
|
483
|
+
sorted_shells = sorted(self.shells, key=lambda shell: shell.center_ind)
|
|
484
|
+
return it.groupby(sorted_shells, key=lambda shell: shell.center_ind)
|
|
485
|
+
|
|
486
|
+
def fragment_ao_map(self, fragments):
|
|
487
|
+
frag_map = dict()
|
|
488
|
+
for i, frag in enumerate(fragments):
|
|
489
|
+
for center_ind in frag:
|
|
490
|
+
frag_map[center_ind] = i
|
|
491
|
+
|
|
492
|
+
frag_ao_map = dict()
|
|
493
|
+
for i, ao_center in enumerate(self.sph_ao_centers):
|
|
494
|
+
frag_ind = frag_map[ao_center]
|
|
495
|
+
frag_ao_map.setdefault(frag_ind, list()).append(i)
|
|
496
|
+
return frag_ao_map
|
|
497
|
+
|
|
498
|
+
def as_gau_gbs(self) -> str:
|
|
499
|
+
def dfmt(num):
|
|
500
|
+
return f"{num: 12.10e}".replace("e", "D")
|
|
501
|
+
|
|
502
|
+
gbs_tpl = Template(
|
|
503
|
+
"""
|
|
504
|
+
{% for center_ind, shells in center_shell_iter %}
|
|
505
|
+
{{ center_ind+1 }} 0
|
|
506
|
+
{%- for shell in shells %}
|
|
507
|
+
{{ ("S", "P", "D", "F", "G")[shell.L] }} {{ shell.exps.size}} 1.00 0.000000000000
|
|
508
|
+
{%- for exp_, coeff in shell.exps_coeffs_iter() %}
|
|
509
|
+
{{ dfmt(exp_) }} {{ dfmt(coeff) }}
|
|
510
|
+
{%- endfor -%}
|
|
511
|
+
{% endfor %}
|
|
512
|
+
****
|
|
513
|
+
{%- endfor %}
|
|
514
|
+
"""
|
|
515
|
+
)
|
|
516
|
+
rendered = gbs_tpl.render(center_shell_iter=self.center_shell_iter(), dfmt=dfmt)
|
|
517
|
+
rendered = textwrap.dedent(rendered)
|
|
518
|
+
return rendered
|
|
519
|
+
|
|
520
|
+
def _ao_center_iter(self, func):
|
|
521
|
+
i = 0
|
|
522
|
+
for shell in self.shells:
|
|
523
|
+
for _ in func(shell.L):
|
|
524
|
+
yield shell.center_ind
|
|
525
|
+
i += 0
|
|
526
|
+
|
|
527
|
+
@property
|
|
528
|
+
def cart_ao_centers(self):
|
|
529
|
+
return self._ao_center_iter(canonical_order)
|
|
530
|
+
|
|
531
|
+
@property
|
|
532
|
+
def sph_ao_centers(self):
|
|
533
|
+
return self._ao_center_iter(lambda l: range(2 * l + 1))
|
|
534
|
+
|
|
535
|
+
@property
|
|
536
|
+
def cart2sph_coeffs(self):
|
|
537
|
+
cart2sph = cart2sph_coeffs(self.l_max)
|
|
538
|
+
C = sp.linalg.block_diag(*[cart2sph[shell.L] for shell in self.shells])
|
|
539
|
+
return C
|
|
540
|
+
|
|
541
|
+
@property
|
|
542
|
+
def P_sph(self):
|
|
543
|
+
"""Permutation matrix for spherical basis functions."""
|
|
544
|
+
return sp.linalg.block_diag(*[self.sph_Ps[shell.L] for shell in self.shells])
|
|
545
|
+
|
|
546
|
+
@property
|
|
547
|
+
def P_cart(self):
|
|
548
|
+
"""Permutation matrix for Cartesian basis functions."""
|
|
549
|
+
try:
|
|
550
|
+
P_cart = sp.linalg.block_diag(
|
|
551
|
+
*[self.cart_Ps[shell.L] for shell in self.shells]
|
|
552
|
+
)
|
|
553
|
+
except AttributeError:
|
|
554
|
+
P_cart = np.eye(self.cart_size)
|
|
555
|
+
return P_cart
|
|
556
|
+
|
|
557
|
+
def eval(self, xyz, spherical=True):
|
|
558
|
+
"""Evaluate all basis functions at points xyz using generated code.
|
|
559
|
+
|
|
560
|
+
A possibly more efficient approach is discussed in III C of
|
|
561
|
+
https://doi.org/10.1063/1.469408.
|
|
562
|
+
"""
|
|
563
|
+
if spherical:
|
|
564
|
+
precontr = self.cart2sph_coeffs.T @ self.P_sph.T
|
|
565
|
+
else:
|
|
566
|
+
precontr = self.P_cart.T
|
|
567
|
+
ncbfs = precontr.shape[0]
|
|
568
|
+
npoints = len(xyz)
|
|
569
|
+
|
|
570
|
+
coords3d = self.coords3d
|
|
571
|
+
grid_vals = np.zeros((npoints, ncbfs))
|
|
572
|
+
for center_ind, shells in self.center_shell_iter():
|
|
573
|
+
# Create list from the shells iterator, otherwise it will be empty
|
|
574
|
+
# after the first pass over all points.
|
|
575
|
+
shells = list(shells)
|
|
576
|
+
for i, R in enumerate(xyz):
|
|
577
|
+
for shell in shells:
|
|
578
|
+
La, A, da, ax, a_ind, a_size = shell.as_tuple()
|
|
579
|
+
grid_vals[i, a_ind : a_ind + a_size] = cart_gto3d.cart_gto3d[(La,)](
|
|
580
|
+
ax, da, A, R
|
|
581
|
+
)
|
|
582
|
+
return grid_vals @ precontr
|
|
583
|
+
|
|
584
|
+
def get_1el_ints_cart(
|
|
585
|
+
self,
|
|
586
|
+
func_dict,
|
|
587
|
+
other=None,
|
|
588
|
+
can_reorder=True,
|
|
589
|
+
components=0,
|
|
590
|
+
screen_func=None,
|
|
591
|
+
**kwargs,
|
|
592
|
+
):
|
|
593
|
+
shells_a = self
|
|
594
|
+
symmetric = other is None
|
|
595
|
+
shells_b = shells_a if symmetric else other
|
|
596
|
+
cart_bf_num_a = shells_a.cart_bf_num
|
|
597
|
+
cart_bf_num_b = shells_b.cart_bf_num
|
|
598
|
+
|
|
599
|
+
# components = 0 indicates, that a plain 2d matrix is desired.
|
|
600
|
+
if is_2d := (components == 0):
|
|
601
|
+
components = 1
|
|
602
|
+
|
|
603
|
+
# Preallocate empty matrices and directly assign the calculated values
|
|
604
|
+
integrals = np.zeros((components, cart_bf_num_a, cart_bf_num_b))
|
|
605
|
+
|
|
606
|
+
# Dummy screen function that always returns True
|
|
607
|
+
if (not self.screen) or (screen_func is None):
|
|
608
|
+
screen_func = lambda *args: True
|
|
609
|
+
|
|
610
|
+
for i, shell_a in enumerate(shells_a):
|
|
611
|
+
La, A, da, ax, a_ind, a_size = shell_a.as_tuple()
|
|
612
|
+
a_slice = slice(a_ind, a_ind + a_size)
|
|
613
|
+
# When we don't deal with symmetric matrices we have to iterate over
|
|
614
|
+
# all other basis functions in shells_b, so we reset i to 0.
|
|
615
|
+
if not symmetric:
|
|
616
|
+
i = 0
|
|
617
|
+
a_min_exp = ax.min() # Minimum exponent used for screening
|
|
618
|
+
for shell_b in shells_b[i:]:
|
|
619
|
+
Lb, B, db, bx, b_ind, b_size = shell_b.as_tuple()
|
|
620
|
+
b_slice = slice(b_ind, b_ind + b_size)
|
|
621
|
+
# Screen shell pair
|
|
622
|
+
b_min_exp = bx.min() # Minimum exponent used for screening
|
|
623
|
+
R_ab = np.linalg.norm(A - B) # Shell center distance
|
|
624
|
+
b_size = get_shell_shape(Lb)[0]
|
|
625
|
+
if not screen_func(a_min_exp, b_min_exp, R_ab):
|
|
626
|
+
continue
|
|
627
|
+
integrals[:, a_slice, b_slice] = func_dict[(La, Lb)](
|
|
628
|
+
ax[:, None],
|
|
629
|
+
da[:, None],
|
|
630
|
+
A,
|
|
631
|
+
bx[None, :],
|
|
632
|
+
db[None, :],
|
|
633
|
+
B,
|
|
634
|
+
**kwargs,
|
|
635
|
+
)
|
|
636
|
+
# Fill up the lower tringular part of the matrix in the symmetric
|
|
637
|
+
# case.
|
|
638
|
+
# TODO: this may be (?) better done outside of this loop, after
|
|
639
|
+
# everything is calculated...
|
|
640
|
+
if symmetric:
|
|
641
|
+
integrals[:, b_slice, a_slice] = np.transpose(
|
|
642
|
+
integrals[:, a_slice, b_slice], axes=(0, 2, 1)
|
|
643
|
+
)
|
|
644
|
+
|
|
645
|
+
# Return plain 2d array if components is set to 0, i.e., remove first axis.
|
|
646
|
+
if is_2d:
|
|
647
|
+
integrals = np.squeeze(integrals, axis=0)
|
|
648
|
+
|
|
649
|
+
# Reordering will be disabled, when spherical integrals are desired. They
|
|
650
|
+
# are reordered outside of this function. Reordering them already here
|
|
651
|
+
# would mess up the results after the 2nd reordering.
|
|
652
|
+
if can_reorder and self.ordering == "native":
|
|
653
|
+
integrals = np.einsum(
|
|
654
|
+
"ij,...jk,kl->...il",
|
|
655
|
+
self.P_cart,
|
|
656
|
+
integrals,
|
|
657
|
+
shells_b.P_cart.T,
|
|
658
|
+
optimize="greedy",
|
|
659
|
+
)
|
|
660
|
+
return integrals
|
|
661
|
+
|
|
662
|
+
def get_1el_ints_sph(
|
|
663
|
+
self, int_func=None, int_matrix=None, other=None, **kwargs
|
|
664
|
+
) -> NDArray:
|
|
665
|
+
if int_matrix is None:
|
|
666
|
+
# Disallow reordering of the Cartesian integrals
|
|
667
|
+
int_matrix = self.get_1el_ints_cart(
|
|
668
|
+
int_func, other=other, can_reorder=False, **kwargs
|
|
669
|
+
)
|
|
670
|
+
|
|
671
|
+
shells_b = self if other is None else other
|
|
672
|
+
# Reordering (P) and Cartesian to spherical conversion (C).
|
|
673
|
+
PC_a = self.reorder_c2s_coeffs
|
|
674
|
+
PC_b = shells_b.reorder_c2s_coeffs
|
|
675
|
+
int_matrix_sph = np.einsum(
|
|
676
|
+
"ij,...jk,kl->...il", PC_a, int_matrix, PC_b.T, optimize="greedy"
|
|
677
|
+
)
|
|
678
|
+
return int_matrix_sph
|
|
679
|
+
|
|
680
|
+
def get_2c2el_ints_cart(self):
|
|
681
|
+
return self.get_1el_ints_cart(int2c2e3d.int2c2e3d)
|
|
682
|
+
|
|
683
|
+
def get_2c2el_ints_sph(self):
|
|
684
|
+
return self.get_1el_ints_sph(int2c2e3d.int2c2e3d)
|
|
685
|
+
|
|
686
|
+
def get_3c2el_ints_cart(self, shells_aux):
|
|
687
|
+
"""Cartesian 3-center-2-electron integrals.
|
|
688
|
+
|
|
689
|
+
DO NOT USE THESE INTEGRALS AS THEY ARE RETURNED FROM THIS METHOD.
|
|
690
|
+
These integrals utilize recurrence relations that are only valid,
|
|
691
|
+
when the resulting Cartesian integrals are transformed into spherical
|
|
692
|
+
integrals.
|
|
693
|
+
|
|
694
|
+
Contrary to the general function 'get_1el_ints_cart', that supports
|
|
695
|
+
different 'func_dict' arguments and cross-integrals between two
|
|
696
|
+
different shells this function is less general. This function is
|
|
697
|
+
restricted to '_3center2el_sph' and always uses 'self.shells' as well as
|
|
698
|
+
'self.shells_aux'.
|
|
699
|
+
"""
|
|
700
|
+
shells_a = self
|
|
701
|
+
cart_bf_num_a = shells_a.cart_bf_num
|
|
702
|
+
cart_bf_num_aux = shells_aux.cart_bf_num
|
|
703
|
+
|
|
704
|
+
integrals = np.zeros((cart_bf_num_a, cart_bf_num_a, cart_bf_num_aux))
|
|
705
|
+
# func_dict = _3center2el3d_sph._3center2el3d_sph
|
|
706
|
+
func_dict = int3c2e3d_sph.int3c2e3d_sph
|
|
707
|
+
|
|
708
|
+
for i, shell_a in enumerate(shells_a):
|
|
709
|
+
La, A, da, ax, a_ind, a_size = shell_a.as_tuple()
|
|
710
|
+
a_slice = slice(a_ind, a_ind + a_size)
|
|
711
|
+
# As noted in the docstring, we iterate over pairs of self.shells (shells_a)
|
|
712
|
+
for shell_b in shells_a[i:]:
|
|
713
|
+
Lb, B, db, bx, b_ind, b_size = shell_b.as_tuple()
|
|
714
|
+
b_slice = slice(b_ind, b_ind + b_size)
|
|
715
|
+
for shell_c in shells_aux:
|
|
716
|
+
Lc, C, dc, cx, c_ind, c_size = shell_c.as_tuple()
|
|
717
|
+
c_slice = slice(c_ind, c_ind + c_size)
|
|
718
|
+
integrals[a_slice, b_slice, c_slice] = func_dict[(La, Lb, Lc)](
|
|
719
|
+
ax[:, None, None],
|
|
720
|
+
da[:, None, None],
|
|
721
|
+
A,
|
|
722
|
+
bx[None, :, None],
|
|
723
|
+
db[None, :, None],
|
|
724
|
+
B,
|
|
725
|
+
cx[None, None, :],
|
|
726
|
+
dc[None, None, :],
|
|
727
|
+
C,
|
|
728
|
+
)
|
|
729
|
+
integrals[b_slice, a_slice, c_slice] = np.transpose(
|
|
730
|
+
integrals[a_slice, b_slice, c_slice], axes=(1, 0, 2)
|
|
731
|
+
)
|
|
732
|
+
return integrals
|
|
733
|
+
|
|
734
|
+
def get_3c2el_ints_sph(self, shells_aux):
|
|
735
|
+
int_matrix = self.get_3c2el_ints_cart(shells_aux)
|
|
736
|
+
|
|
737
|
+
PC_a = self.reorder_c2s_coeffs
|
|
738
|
+
PC_c = shells_aux.reorder_c2s_coeffs
|
|
739
|
+
int_matrix_sph = np.einsum(
|
|
740
|
+
"ij,jlm,nl,om->ino", PC_a, int_matrix, PC_a, PC_c, optimize="greedy"
|
|
741
|
+
)
|
|
742
|
+
return int_matrix_sph
|
|
743
|
+
|
|
744
|
+
#####################
|
|
745
|
+
# Overlap integrals #
|
|
746
|
+
#####################
|
|
747
|
+
|
|
748
|
+
@staticmethod
|
|
749
|
+
def screen_S(a, b, R, k=10):
|
|
750
|
+
"""
|
|
751
|
+
Returns False when distance R is below calculated threshold.
|
|
752
|
+
Derived from the sympy code below.
|
|
753
|
+
|
|
754
|
+
from sympy import *
|
|
755
|
+
|
|
756
|
+
a, b, S, R = symbols("a b S R", real=True, positive=True)
|
|
757
|
+
k = symbols("k", integer=True, positive=True)
|
|
758
|
+
apb = a + b
|
|
759
|
+
# 0 = S - 10**(-k)
|
|
760
|
+
ovlp = (pi / apb)**Rational(3,2) * exp(-a*b / apb * R**2) - 10**(-k)
|
|
761
|
+
print("ss-overlap:", ovlp)
|
|
762
|
+
# Distance R, when ss-overlaps drops below 10**(-k)
|
|
763
|
+
R = solve(ovlp, R)[0]
|
|
764
|
+
print("R:", R)
|
|
765
|
+
|
|
766
|
+
Parameters
|
|
767
|
+
----------
|
|
768
|
+
a
|
|
769
|
+
Minimum exponent in shell a.
|
|
770
|
+
b
|
|
771
|
+
Minimum exponent in shell b.
|
|
772
|
+
R
|
|
773
|
+
Real space distance of shells a and b.
|
|
774
|
+
"""
|
|
775
|
+
return R < (
|
|
776
|
+
sqrt(a + b)
|
|
777
|
+
* sqrt(log(10**k * pi ** (3 / 2) / (a + b) ** (3 / 2)))
|
|
778
|
+
/ (sqrt(a) * sqrt(b))
|
|
779
|
+
)
|
|
780
|
+
|
|
781
|
+
def get_S_cart(self, other=None) -> NDArray:
|
|
782
|
+
# return self.get_1el_ints_cart(ovlp, other=other, screen_func=Shells.screen_S)
|
|
783
|
+
return self.get_1el_ints_cart(
|
|
784
|
+
ovlp3d.ovlp3d, other=other, screen_func=Shells.screen_S
|
|
785
|
+
)
|
|
786
|
+
|
|
787
|
+
def get_S_sph(self, other=None) -> NDArray:
|
|
788
|
+
return self.get_1el_ints_sph(
|
|
789
|
+
ovlp3d.ovlp3d, other=other, screen_func=Shells.screen_S
|
|
790
|
+
)
|
|
791
|
+
|
|
792
|
+
@property
|
|
793
|
+
def S_cart(self):
|
|
794
|
+
return self.get_S_cart()
|
|
795
|
+
|
|
796
|
+
@property
|
|
797
|
+
def S_sph(self):
|
|
798
|
+
return self.get_S_sph()
|
|
799
|
+
|
|
800
|
+
############################
|
|
801
|
+
# Kinetic energy integrals #
|
|
802
|
+
############################
|
|
803
|
+
|
|
804
|
+
def get_T_cart(self, other=None) -> NDArray:
|
|
805
|
+
# return self.get_1el_ints_cart(kinetic, other=other)
|
|
806
|
+
return self.get_1el_ints_cart(kinetic3d.kinetic3d, other=other)
|
|
807
|
+
|
|
808
|
+
def get_T_sph(self, other=None) -> NDArray:
|
|
809
|
+
return self.get_1el_ints_sph(kinetic3d.kinetic3d, other=other)
|
|
810
|
+
|
|
811
|
+
@property
|
|
812
|
+
def T_cart(self):
|
|
813
|
+
return self.get_T_cart()
|
|
814
|
+
|
|
815
|
+
@property
|
|
816
|
+
def T_sph(self):
|
|
817
|
+
return self.get_T_sph()
|
|
818
|
+
|
|
819
|
+
################################
|
|
820
|
+
# Nuclear attraction integrals #
|
|
821
|
+
################################
|
|
822
|
+
|
|
823
|
+
def get_V_cart(self, coords3d=None, charges=None, **kwargs):
|
|
824
|
+
"""Nuclear attraction integrals.
|
|
825
|
+
|
|
826
|
+
Coordinates and charges must be either be omitted or given together.
|
|
827
|
+
Alternatively, this function could also take one array that combines
|
|
828
|
+
coords3c and charges (not yet implemented).
|
|
829
|
+
"""
|
|
830
|
+
assert ((coords3d is None) and (charges is None)) or (
|
|
831
|
+
(coords3d is not None) and (charges is not None)
|
|
832
|
+
)
|
|
833
|
+
if coords3d is None:
|
|
834
|
+
atoms, coords3d = self.atoms_coords3d
|
|
835
|
+
charges = nuc_charges_for_atoms(atoms)
|
|
836
|
+
|
|
837
|
+
# def boys_1c1el(n_max, ax, A, bx, B, C):
|
|
838
|
+
# ax = ax[:, None]
|
|
839
|
+
# bx = bx[None, :]
|
|
840
|
+
# p = ax + bx
|
|
841
|
+
# P = -(ax * A + bx * B) / p
|
|
842
|
+
# R_PC2 = ((P - C)**2).sum()
|
|
843
|
+
# pR_PC2 = p * R_PC2
|
|
844
|
+
# return np.array([boys.boys(n, pR_PC2) for n in range(n_max+1)])
|
|
845
|
+
|
|
846
|
+
cart_bf_num = self.cart_bf_num
|
|
847
|
+
V_nuc = np.zeros((cart_bf_num, cart_bf_num))
|
|
848
|
+
# Loop over all centers and add their contributions
|
|
849
|
+
for R, Z in zip(coords3d, charges):
|
|
850
|
+
# -Z = -1 * Z, because electrons have negative charge.
|
|
851
|
+
V_nuc += -Z * self.get_1el_ints_cart(
|
|
852
|
+
coulomb3d.coulomb3d,
|
|
853
|
+
R=R,
|
|
854
|
+
**kwargs,
|
|
855
|
+
)
|
|
856
|
+
return V_nuc
|
|
857
|
+
|
|
858
|
+
def get_V_sph(self, coords3d=None, charges=None) -> NDArray:
|
|
859
|
+
V_cart = self.get_V_cart(coords3d, charges, can_reorder=False)
|
|
860
|
+
return self.get_1el_ints_sph(int_func=None, int_matrix=V_cart)
|
|
861
|
+
|
|
862
|
+
@property
|
|
863
|
+
def V_cart(self):
|
|
864
|
+
return self.get_V_cart()
|
|
865
|
+
|
|
866
|
+
@property
|
|
867
|
+
def V_sph(self):
|
|
868
|
+
return self.get_V_sph()
|
|
869
|
+
|
|
870
|
+
###########################
|
|
871
|
+
# Dipole moment integrals #
|
|
872
|
+
###########################
|
|
873
|
+
|
|
874
|
+
def get_dipole_ints_cart(self, origin):
|
|
875
|
+
return self.get_1el_ints_cart(
|
|
876
|
+
dipole3d.dipole3d, components=3, R=origin, screen_func=Shells.screen_S
|
|
877
|
+
)
|
|
878
|
+
|
|
879
|
+
def get_dipole_ints_sph(self, origin) -> NDArray:
|
|
880
|
+
return self.get_1el_ints_sph(
|
|
881
|
+
dipole3d.dipole3d, components=3, R=origin, screen_func=Shells.screen_S
|
|
882
|
+
)
|
|
883
|
+
|
|
884
|
+
##################################################
|
|
885
|
+
# Quadrupole moment integrals, diagonal elements #
|
|
886
|
+
##################################################
|
|
887
|
+
|
|
888
|
+
def get_diag_quadrupole_ints_cart(self, origin):
|
|
889
|
+
return self.get_1el_ints_cart(
|
|
890
|
+
diag_quadrupole3d.diag_quadrupole3d,
|
|
891
|
+
components=3,
|
|
892
|
+
R=origin,
|
|
893
|
+
screen_func=Shells.screen_S,
|
|
894
|
+
)
|
|
895
|
+
|
|
896
|
+
def get_diag_quadrupole_ints_sph(self, origin):
|
|
897
|
+
return self.get_1el_ints_sph(
|
|
898
|
+
diag_quadrupole3d.diag_quadrupole3d,
|
|
899
|
+
components=3,
|
|
900
|
+
R=origin,
|
|
901
|
+
screen_func=Shells.screen_S,
|
|
902
|
+
)
|
|
903
|
+
|
|
904
|
+
###############################
|
|
905
|
+
# Quadrupole moment integrals #
|
|
906
|
+
###############################
|
|
907
|
+
|
|
908
|
+
def get_quadrupole_ints_cart(self, origin):
|
|
909
|
+
ints_flat = self.get_1el_ints_cart(
|
|
910
|
+
quadrupole3d.quadrupole3d,
|
|
911
|
+
components=6,
|
|
912
|
+
R=origin,
|
|
913
|
+
screen_func=Shells.screen_S,
|
|
914
|
+
)
|
|
915
|
+
return multi_component_sym_mat(ints_flat, 3)
|
|
916
|
+
|
|
917
|
+
def get_quadrupole_ints_sph(self, origin) -> NDArray:
|
|
918
|
+
ints_flat = self.get_1el_ints_sph(
|
|
919
|
+
quadrupole3d.quadrupole3d,
|
|
920
|
+
components=6,
|
|
921
|
+
R=origin,
|
|
922
|
+
screen_func=Shells.screen_S,
|
|
923
|
+
)
|
|
924
|
+
return multi_component_sym_mat(ints_flat, 3)
|
|
925
|
+
|
|
926
|
+
def to_sap_shells(self):
|
|
927
|
+
for shell in self.shells:
|
|
928
|
+
shell.to_sap_shell()
|
|
929
|
+
|
|
930
|
+
def __str__(self):
|
|
931
|
+
return f"{self.__class__.__name__}({len(self.shells)} shells, ordering={self.ordering})"
|
|
932
|
+
|
|
933
|
+
|
|
934
|
+
class AOMixShells(Shells):
|
|
935
|
+
cart_order = (
|
|
936
|
+
("",),
|
|
937
|
+
("x", "y", "z"),
|
|
938
|
+
("xx", "yy", "zz", "xy", "xz", "yz"),
|
|
939
|
+
("xxx", "yyy", "zzz", "xyy", "xxy", "xxz", "xzz", "yzz", "yyz", "xyz"),
|
|
940
|
+
(
|
|
941
|
+
"zzzz",
|
|
942
|
+
"yzzz",
|
|
943
|
+
"yyzz",
|
|
944
|
+
"yyyz",
|
|
945
|
+
"yyyy",
|
|
946
|
+
"xzzz",
|
|
947
|
+
"xyzz",
|
|
948
|
+
"xyyz",
|
|
949
|
+
"xyyy",
|
|
950
|
+
"xxzz",
|
|
951
|
+
"xxyz",
|
|
952
|
+
"xxyy",
|
|
953
|
+
"xxxz",
|
|
954
|
+
"xxxy",
|
|
955
|
+
"xxxx",
|
|
956
|
+
),
|
|
957
|
+
)
|
|
958
|
+
|
|
959
|
+
|
|
960
|
+
class ORCAShells(Shells):
|
|
961
|
+
sph_Ps = {
|
|
962
|
+
0: [[1]], # s
|
|
963
|
+
1: [[0, 1, 0], [1, 0, 0], [0, 0, 1]], # pz px py
|
|
964
|
+
2: [
|
|
965
|
+
[0, 0, 1, 0, 0], # dz²
|
|
966
|
+
[0, 1, 0, 0, 0], # dxz
|
|
967
|
+
[0, 0, 0, 1, 0], # dyz
|
|
968
|
+
[1, 0, 0, 0, 0], # dx² - y²
|
|
969
|
+
[0, 0, 0, 0, 1], # dxy
|
|
970
|
+
],
|
|
971
|
+
3: [
|
|
972
|
+
[0, 0, 0, 1, 0, 0, 0],
|
|
973
|
+
[0, 0, 1, 0, 0, 0, 0],
|
|
974
|
+
[0, 0, 0, 0, 1, 0, 0],
|
|
975
|
+
[0, 1, 0, 0, 0, 0, 0],
|
|
976
|
+
[0, 0, 0, 0, 0, 1, 0],
|
|
977
|
+
[-1, 0, 0, 0, 0, 0, 0], # ORCA, why you do this to me?
|
|
978
|
+
[0, 0, 0, 0, 0, 0, -1], # sign flip, as in the line above
|
|
979
|
+
],
|
|
980
|
+
4: [
|
|
981
|
+
[0, 0, 0, 0, 1, 0, 0, 0, 0],
|
|
982
|
+
[0, 0, 0, 1, 0, 0, 0, 0, 0],
|
|
983
|
+
[0, 0, 0, 0, 0, 1, 0, 0, 0],
|
|
984
|
+
[0, 0, 1, 0, 0, 0, 0, 0, 0],
|
|
985
|
+
[0, 0, 0, 0, 0, 0, 1, 0, 0],
|
|
986
|
+
[0, -1, 0, 0, 0, 0, 0, 0, 0], # sign flip
|
|
987
|
+
[0, 0, 0, 0, 0, 0, 0, -1, 0], # sign flip
|
|
988
|
+
[-1, 0, 0, 0, 0, 0, 0, 0, 0], # sign flip
|
|
989
|
+
[0, 0, 0, 0, 0, 0, 0, 0, -1], # sign flip
|
|
990
|
+
],
|
|
991
|
+
}
|
|
992
|
+
|
|
993
|
+
|
|
994
|
+
class FCHKShells(Shells):
|
|
995
|
+
cart_order = (
|
|
996
|
+
("",),
|
|
997
|
+
("x", "y", "z"),
|
|
998
|
+
("xx", "yy", "zz", "xy", "xz", "yz"),
|
|
999
|
+
("xxx", "yyy", "zzz", "xyy", "xxy", "xxz", "xzz", "yzz", "yyz", "xyz"),
|
|
1000
|
+
(
|
|
1001
|
+
"zzzz",
|
|
1002
|
+
"yzzz",
|
|
1003
|
+
"yyzz",
|
|
1004
|
+
"yyyz",
|
|
1005
|
+
"yyyy",
|
|
1006
|
+
"xzzz",
|
|
1007
|
+
"xyzz",
|
|
1008
|
+
"xyyz",
|
|
1009
|
+
"xyyy",
|
|
1010
|
+
"xxzz",
|
|
1011
|
+
"xxyz",
|
|
1012
|
+
"xxyy",
|
|
1013
|
+
"xxxz",
|
|
1014
|
+
"xxxy",
|
|
1015
|
+
"xxxx",
|
|
1016
|
+
),
|
|
1017
|
+
)
|
|
1018
|
+
|
|
1019
|
+
sph_Ps = {
|
|
1020
|
+
0: [[1]], # s
|
|
1021
|
+
1: [[1, 0, 0], [0, 0, 1], [0, 1, 0]], # px pz py
|
|
1022
|
+
2: [
|
|
1023
|
+
[0, 0, 1, 0, 0], # dz²
|
|
1024
|
+
[0, 1, 0, 0, 0], # dxz
|
|
1025
|
+
[0, 0, 0, 1, 0], # dyz
|
|
1026
|
+
[1, 0, 0, 0, 0], # dx² - y²
|
|
1027
|
+
[0, 0, 0, 0, 1], # dxy
|
|
1028
|
+
],
|
|
1029
|
+
# Similar to ORCA, but w/o the sign flips ;)
|
|
1030
|
+
3: [
|
|
1031
|
+
[0, 0, 0, 1, 0, 0, 0],
|
|
1032
|
+
[0, 0, 1, 0, 0, 0, 0],
|
|
1033
|
+
[0, 0, 0, 0, 1, 0, 0],
|
|
1034
|
+
[0, 1, 0, 0, 0, 0, 0],
|
|
1035
|
+
[0, 0, 0, 0, 0, 1, 0],
|
|
1036
|
+
[1, 0, 0, 0, 0, 0, 0],
|
|
1037
|
+
[0, 0, 0, 0, 0, 0, 1],
|
|
1038
|
+
],
|
|
1039
|
+
4: [
|
|
1040
|
+
[0, 0, 0, 0, 1, 0, 0, 0, 0],
|
|
1041
|
+
[0, 0, 0, 1, 0, 0, 0, 0, 0],
|
|
1042
|
+
[0, 0, 0, 0, 0, 1, 0, 0, 0],
|
|
1043
|
+
[0, 0, 1, 0, 0, 0, 0, 0, 0],
|
|
1044
|
+
[0, 0, 0, 0, 0, 0, 1, 0, 0],
|
|
1045
|
+
[0, 1, 0, 0, 0, 0, 0, 0, 0],
|
|
1046
|
+
[0, 0, 0, 0, 0, 0, 0, 1, 0],
|
|
1047
|
+
[1, 0, 0, 0, 0, 0, 0, 0, 0],
|
|
1048
|
+
[0, 0, 0, 0, 0, 0, 0, 0, 1],
|
|
1049
|
+
],
|
|
1050
|
+
}
|
|
1051
|
+
|
|
1052
|
+
|
|
1053
|
+
class MoldenShells(Shells):
|
|
1054
|
+
sph_Ps = {
|
|
1055
|
+
0: [[1]], # s
|
|
1056
|
+
1: [[1, 0, 0], [0, 0, 1], [0, 1, 0]], # px, py, pz
|
|
1057
|
+
2: [
|
|
1058
|
+
[0, 0, 1, 0, 0], # dz²
|
|
1059
|
+
[0, 1, 0, 0, 0], # dxz
|
|
1060
|
+
[0, 0, 0, 1, 0], # dyz
|
|
1061
|
+
[1, 0, 0, 0, 0], # dx² - y²
|
|
1062
|
+
[0, 0, 0, 0, 1], # dxy
|
|
1063
|
+
],
|
|
1064
|
+
3: [
|
|
1065
|
+
[0, 0, 0, 1, 0, 0, 0],
|
|
1066
|
+
[0, 0, 1, 0, 0, 0, 0],
|
|
1067
|
+
[0, 0, 0, 0, 1, 0, 0],
|
|
1068
|
+
[0, 1, 0, 0, 0, 0, 0],
|
|
1069
|
+
[0, 0, 0, 0, 0, 1, 0],
|
|
1070
|
+
[1, 0, 0, 0, 0, 0, 0],
|
|
1071
|
+
[0, 0, 0, 0, 0, 0, 1],
|
|
1072
|
+
],
|
|
1073
|
+
4: [
|
|
1074
|
+
[0, 0, 0, 0, 1, 0, 0, 0, 0],
|
|
1075
|
+
[0, 0, 0, 1, 0, 0, 0, 0, 0],
|
|
1076
|
+
[0, 0, 0, 0, 0, 1, 0, 0, 0],
|
|
1077
|
+
[0, 0, 1, 0, 0, 0, 0, 0, 0],
|
|
1078
|
+
[0, 0, 0, 0, 0, 0, 1, 0, 0],
|
|
1079
|
+
[0, 1, 0, 0, 0, 0, 0, 0, 0],
|
|
1080
|
+
[0, 0, 0, 0, 0, 0, 0, 1, 0],
|
|
1081
|
+
[1, 0, 0, 0, 0, 0, 0, 0, 0],
|
|
1082
|
+
[0, 0, 0, 0, 0, 0, 0, 0, 1],
|
|
1083
|
+
],
|
|
1084
|
+
}
|
|
1085
|
+
|
|
1086
|
+
|
|
1087
|
+
class ORCAMoldenShells(Shells):
|
|
1088
|
+
sph_Ps = {
|
|
1089
|
+
0: [[1]], # s
|
|
1090
|
+
1: [[1, 0, 0], [0, 0, 1], [0, 1, 0]], # px, py, pz
|
|
1091
|
+
2: [
|
|
1092
|
+
[0, 0, 1, 0, 0], # dz²
|
|
1093
|
+
[0, 1, 0, 0, 0], # dxz
|
|
1094
|
+
[0, 0, 0, 1, 0], # dyz
|
|
1095
|
+
[1, 0, 0, 0, 0], # dx² - y²
|
|
1096
|
+
[0, 0, 0, 0, 1], # dxy
|
|
1097
|
+
],
|
|
1098
|
+
3: [
|
|
1099
|
+
[0, 0, 0, 1, 0, 0, 0],
|
|
1100
|
+
[0, 0, 1, 0, 0, 0, 0],
|
|
1101
|
+
[0, 0, 0, 0, 1, 0, 0],
|
|
1102
|
+
[0, 1, 0, 0, 0, 0, 0],
|
|
1103
|
+
[0, 0, 0, 0, 0, 1, 0],
|
|
1104
|
+
[-1, 0, 0, 0, 0, 0, 0],
|
|
1105
|
+
[0, 0, 0, 0, 0, 0, -1],
|
|
1106
|
+
],
|
|
1107
|
+
4: [
|
|
1108
|
+
[0, 0, 0, 0, 1, 0, 0, 0, 0],
|
|
1109
|
+
[0, 0, 0, 1, 0, 0, 0, 0, 0],
|
|
1110
|
+
[0, 0, 0, 0, 0, 1, 0, 0, 0],
|
|
1111
|
+
[0, 0, 1, 0, 0, 0, 0, 0, 0],
|
|
1112
|
+
[0, 0, 0, 0, 0, 0, 1, 0, 0],
|
|
1113
|
+
[0, -1, 0, 0, 0, 0, 0, 0, 0],
|
|
1114
|
+
[0, 0, 0, 0, 0, 0, 0, -1, 0],
|
|
1115
|
+
[-1, 0, 0, 0, 0, 0, 0, 0, 0],
|
|
1116
|
+
[0, 0, 0, 0, 0, 0, 0, 0, -1],
|
|
1117
|
+
],
|
|
1118
|
+
}
|
|
1119
|
+
|
|
1120
|
+
|
|
1121
|
+
def pyscf_cart_order(l):
|
|
1122
|
+
order = list()
|
|
1123
|
+
for lx in reversed(range(l + 1)):
|
|
1124
|
+
for ly in reversed(range(l + 1 - lx)):
|
|
1125
|
+
lz = l - lx - ly
|
|
1126
|
+
order.append("x" * lx + "y" * ly + "z" * lz)
|
|
1127
|
+
return tuple(order)
|
|
1128
|
+
|
|
1129
|
+
|
|
1130
|
+
class PySCFShells(Shells):
|
|
1131
|
+
|
|
1132
|
+
"""
|
|
1133
|
+
Cartesian bfs >= d angular momentum are not normalized!
|
|
1134
|
+
S_ref = mol.intor("int1e_ovlp_cart")
|
|
1135
|
+
N = 1 / np.diag(S_ref)**0.5
|
|
1136
|
+
ao *= N
|
|
1137
|
+
"""
|
|
1138
|
+
|
|
1139
|
+
cart_order = [pyscf_cart_order(l) for l in range(5)]
|
|
1140
|
+
|
|
1141
|
+
sph_Ps = {
|
|
1142
|
+
0: [[1]], # s
|
|
1143
|
+
1: [[1, 0, 0], [0, 0, 1], [0, 1, 0]], # px py pz
|
|
1144
|
+
2: [
|
|
1145
|
+
[0, 0, 0, 0, 1], # dxy
|
|
1146
|
+
[0, 0, 0, 1, 0], # dyz
|
|
1147
|
+
[0, 0, 1, 0, 0], # dz²
|
|
1148
|
+
[0, 1, 0, 0, 0], # dxz
|
|
1149
|
+
[1, 0, 0, 0, 0], # dx² - y²
|
|
1150
|
+
],
|
|
1151
|
+
3: [
|
|
1152
|
+
[0, 0, 0, 0, 0, 0, 1],
|
|
1153
|
+
[0, 0, 0, 0, 0, 1, 0],
|
|
1154
|
+
[0, 0, 0, 0, 1, 0, 0],
|
|
1155
|
+
[0, 0, 0, 1, 0, 0, 0],
|
|
1156
|
+
[0, 0, 1, 0, 0, 0, 0],
|
|
1157
|
+
[0, 1, 0, 0, 0, 0, 0],
|
|
1158
|
+
[1, 0, 0, 0, 0, 0, 0],
|
|
1159
|
+
],
|
|
1160
|
+
4: [
|
|
1161
|
+
[0, 0, 0, 0, 0, 0, 0, 0, 1],
|
|
1162
|
+
[0, 0, 0, 0, 0, 0, 0, 1, 0],
|
|
1163
|
+
[0, 0, 0, 0, 0, 0, 1, 0, 0],
|
|
1164
|
+
[0, 0, 0, 0, 0, 1, 0, 0, 0],
|
|
1165
|
+
[0, 0, 0, 0, 1, 0, 0, 0, 0],
|
|
1166
|
+
[0, 0, 0, 1, 0, 0, 0, 0, 0],
|
|
1167
|
+
[0, 0, 1, 0, 0, 0, 0, 0, 0],
|
|
1168
|
+
[0, 1, 0, 0, 0, 0, 0, 0, 0],
|
|
1169
|
+
[1, 0, 0, 0, 0, 0, 0, 0, 0],
|
|
1170
|
+
],
|
|
1171
|
+
}
|