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,239 @@
|
|
|
1
|
+
import functools
|
|
2
|
+
import itertools as it
|
|
3
|
+
import json
|
|
4
|
+
from pathlib import Path
|
|
5
|
+
from typing import Tuple
|
|
6
|
+
|
|
7
|
+
import numpy as np
|
|
8
|
+
|
|
9
|
+
from pysisyphus.config import BASIS_LIB_DIR
|
|
10
|
+
from pysisyphus.elem_data import ATOMIC_NUMBERS
|
|
11
|
+
from pysisyphus.Geometry import Geometry
|
|
12
|
+
from pysisyphus.helpers_pure import file_or_str
|
|
13
|
+
from pysisyphus.wavefunction import Shell, Shells
|
|
14
|
+
from pysisyphus.wavefunction.helpers import L_MAP
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def basis_from_json(name):
|
|
18
|
+
basis_path = Path(name).with_suffix(".json")
|
|
19
|
+
if not basis_path.is_absolute():
|
|
20
|
+
basis_path = BASIS_LIB_DIR / basis_path
|
|
21
|
+
|
|
22
|
+
with open(basis_path) as handle:
|
|
23
|
+
data = json.load(handle)
|
|
24
|
+
elements = data["elements"]
|
|
25
|
+
return elements
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def basis_from_orca_str(basis_str):
|
|
29
|
+
"""
|
|
30
|
+
%basis
|
|
31
|
+
newgto 1
|
|
32
|
+
s 2
|
|
33
|
+
1 0.7 0.5
|
|
34
|
+
1 0.8 0.6
|
|
35
|
+
p 2
|
|
36
|
+
1 0.7 0.5
|
|
37
|
+
1 0.8 0.6
|
|
38
|
+
d 2
|
|
39
|
+
1 0.7 0.5
|
|
40
|
+
1 0.8 0.6
|
|
41
|
+
d 3
|
|
42
|
+
1 0.7 0.5
|
|
43
|
+
1 0.8 0.6
|
|
44
|
+
1 0.6 0.4
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
"""
|
|
48
|
+
basis = dict()
|
|
49
|
+
for line in basis_str.strip().split("\n"):
|
|
50
|
+
line = line.strip().lower()
|
|
51
|
+
# Skip comments
|
|
52
|
+
if any([line.startswith(key) for key in ("#", "%basis", "end")]) or line == "":
|
|
53
|
+
continue
|
|
54
|
+
tokens = line.split()
|
|
55
|
+
if tokens[0] == "newgto":
|
|
56
|
+
atomic_num = int(tokens[1])
|
|
57
|
+
basis.setdefault(atomic_num, dict())
|
|
58
|
+
elif tokens[0].isalpha():
|
|
59
|
+
ang_mom, nprims = tokens
|
|
60
|
+
ang_mom = L_MAP[ang_mom]
|
|
61
|
+
nprims = int(nprims)
|
|
62
|
+
prev_counter = 0
|
|
63
|
+
shell = {
|
|
64
|
+
"angular_momentum": ang_mom,
|
|
65
|
+
"coefficients": list(),
|
|
66
|
+
"exponents": list(),
|
|
67
|
+
}
|
|
68
|
+
basis[atomic_num].setdefault("electron_shells", list()).append(shell)
|
|
69
|
+
else:
|
|
70
|
+
counter, exponent, coefficient = [float(t) for t in tokens]
|
|
71
|
+
counter = int(counter)
|
|
72
|
+
if coefficient <= 1e-8:
|
|
73
|
+
continue
|
|
74
|
+
assert counter == (prev_counter + 1)
|
|
75
|
+
shell["coefficients"].append(coefficient)
|
|
76
|
+
shell["exponents"].append(exponent)
|
|
77
|
+
return basis
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
def basis_from_pyscf_str(basis_str):
|
|
81
|
+
"""
|
|
82
|
+
# Comment1
|
|
83
|
+
He S
|
|
84
|
+
13.6267000 0.1752300
|
|
85
|
+
1.9993500 0.8934830
|
|
86
|
+
0.3829930 0.0000000
|
|
87
|
+
He S
|
|
88
|
+
13.6267000 0.0000000
|
|
89
|
+
1.9993500 0.0000000
|
|
90
|
+
0.3829930 1.0000000
|
|
91
|
+
"""
|
|
92
|
+
basis = dict()
|
|
93
|
+
for line in basis_str.strip().split("\n"):
|
|
94
|
+
line = line.strip().lower()
|
|
95
|
+
# Skip comments
|
|
96
|
+
if line.startswith("#") or (line == "") or ("basis" in line) or ("end" in line):
|
|
97
|
+
continue
|
|
98
|
+
tokens = line.split()
|
|
99
|
+
if tokens[0].isalpha():
|
|
100
|
+
element, ang_mom = [t.lower() for t in tokens]
|
|
101
|
+
ang_mom = L_MAP[ang_mom]
|
|
102
|
+
if ang_mom == "sp":
|
|
103
|
+
raise Exception("SP shells are not yet handled")
|
|
104
|
+
atomic_num = ATOMIC_NUMBERS[element]
|
|
105
|
+
shell = {
|
|
106
|
+
"angular_momentum": ang_mom,
|
|
107
|
+
"coefficients": list(),
|
|
108
|
+
"exponents": list(),
|
|
109
|
+
}
|
|
110
|
+
basis.setdefault(atomic_num, dict()).setdefault(
|
|
111
|
+
"electron_shells", list()
|
|
112
|
+
).append(shell)
|
|
113
|
+
else:
|
|
114
|
+
exponent, coefficient = [float(t) for t in tokens]
|
|
115
|
+
if coefficient <= 1e-8:
|
|
116
|
+
continue
|
|
117
|
+
shell["coefficients"].append(coefficient)
|
|
118
|
+
shell["exponents"].append(exponent)
|
|
119
|
+
return basis
|
|
120
|
+
|
|
121
|
+
|
|
122
|
+
@file_or_str(".gbs", ".GBS")
|
|
123
|
+
def basis_from_gbs(text):
|
|
124
|
+
"""
|
|
125
|
+
****
|
|
126
|
+
Be 0
|
|
127
|
+
S 6 1.00
|
|
128
|
+
1.101996057600000e-02 -3.733117104118833e-01
|
|
129
|
+
3.570467226624002e-02 -9.552914830540544e-01
|
|
130
|
+
1.156831381426176e-01 9.464046666860781e-02
|
|
131
|
+
3.748133675820811e-01 -1.194926861090494e+00
|
|
132
|
+
1.214395310965943e+00 2.762798723086632e-01
|
|
133
|
+
3.934640807529656e+00 -1.847390284420840e+00
|
|
134
|
+
"""
|
|
135
|
+
basis = dict()
|
|
136
|
+
for line in text.strip().split("\n"):
|
|
137
|
+
line = line.strip().lower()
|
|
138
|
+
# Skip empty lines
|
|
139
|
+
if (line == "") or ("*" in line):
|
|
140
|
+
continue
|
|
141
|
+
tokens = line.split()
|
|
142
|
+
# New center identifier line
|
|
143
|
+
if (tokens[0].isalpha()) and (len(tokens) == 2):
|
|
144
|
+
atom, zero = tokens
|
|
145
|
+
atomic_num = str(ATOMIC_NUMBERS[atom.lower()])
|
|
146
|
+
assert int(zero) == 0, "Only one basis per atom type is supported!"
|
|
147
|
+
basis.setdefault(atomic_num, dict())
|
|
148
|
+
# New shell
|
|
149
|
+
elif tokens[0].isalpha() and (len(tokens) == 3):
|
|
150
|
+
ang_mom, nprims, scale_fact = tokens
|
|
151
|
+
ang_mom = L_MAP[ang_mom.lower()]
|
|
152
|
+
nprims = int(nprims)
|
|
153
|
+
shell = {
|
|
154
|
+
"angular_momentum": [
|
|
155
|
+
ang_mom,
|
|
156
|
+
],
|
|
157
|
+
"coefficients": [[]],
|
|
158
|
+
"exponents": list(),
|
|
159
|
+
}
|
|
160
|
+
basis[atomic_num].setdefault("electron_shells", list()).append(shell)
|
|
161
|
+
else:
|
|
162
|
+
exponent, coefficient = [float(t) for t in tokens]
|
|
163
|
+
shell["coefficients"][0].append(coefficient)
|
|
164
|
+
shell["exponents"].append(exponent)
|
|
165
|
+
return basis
|
|
166
|
+
|
|
167
|
+
|
|
168
|
+
@functools.singledispatch
|
|
169
|
+
def shells_with_basis(
|
|
170
|
+
atoms: Tuple,
|
|
171
|
+
coords,
|
|
172
|
+
basis=None,
|
|
173
|
+
name=None,
|
|
174
|
+
shells_cls=None,
|
|
175
|
+
min_coeff=1e-8,
|
|
176
|
+
**kwargs
|
|
177
|
+
):
|
|
178
|
+
assert (basis is not None) or (name is not None)
|
|
179
|
+
if shells_cls is None:
|
|
180
|
+
shells_cls = Shells
|
|
181
|
+
if name is not None:
|
|
182
|
+
basis = basis_from_json(name)
|
|
183
|
+
|
|
184
|
+
coords3d = np.reshape(coords, (len(atoms), 3))
|
|
185
|
+
shells = list()
|
|
186
|
+
for i, (atom, c3d) in enumerate(zip(atoms, coords3d)):
|
|
187
|
+
Zs = str(ATOMIC_NUMBERS[atom.lower()])
|
|
188
|
+
basis_shells = basis[Zs]["electron_shells"]
|
|
189
|
+
for bshell in basis_shells:
|
|
190
|
+
L = bshell["angular_momentum"]
|
|
191
|
+
# Two special cases can appear:
|
|
192
|
+
# SP shells where L has two instead of only one entry
|
|
193
|
+
# General contractions where L has length one, but multiple sets of coefficients
|
|
194
|
+
# are given.
|
|
195
|
+
#
|
|
196
|
+
# With SP shells, there will be as many L values (2), as there are sets
|
|
197
|
+
# of contraction coefficients (2). With general contractions, there will be
|
|
198
|
+
# only one L value, but multiple sets of contraction coefficients.
|
|
199
|
+
#
|
|
200
|
+
# Segemented contractions will always have one L value and one set of contraction
|
|
201
|
+
# coefficients. Long story short: We can treat everything on an equal footing if
|
|
202
|
+
# we just repeat the L value as many times as required, when only one L value is
|
|
203
|
+
# present.
|
|
204
|
+
if len(L) == 1:
|
|
205
|
+
L = it.cycle(L)
|
|
206
|
+
exponents = np.array(bshell["exponents"], dtype=float)
|
|
207
|
+
# Unpack possible general contractions or SP shells
|
|
208
|
+
for L, coeffs in zip(L, bshell["coefficients"]):
|
|
209
|
+
# For now we filter out 0.0 contraction coefficients, as present in
|
|
210
|
+
# generally contracted basis sets.
|
|
211
|
+
coeffs = np.array(coeffs, dtype=float)
|
|
212
|
+
valid = np.abs(coeffs) >= min_coeff
|
|
213
|
+
shell = Shell(
|
|
214
|
+
L=L,
|
|
215
|
+
center=c3d,
|
|
216
|
+
coeffs=coeffs[valid],
|
|
217
|
+
exps=exponents[valid],
|
|
218
|
+
atomic_num=Zs,
|
|
219
|
+
center_ind=i,
|
|
220
|
+
)
|
|
221
|
+
shells.append(shell)
|
|
222
|
+
shells = shells_cls(shells, **kwargs)
|
|
223
|
+
return shells
|
|
224
|
+
|
|
225
|
+
|
|
226
|
+
@shells_with_basis.register
|
|
227
|
+
def _(geom: Geometry, **kwargs):
|
|
228
|
+
return shells_with_basis(geom.atoms, geom.coords, **kwargs)
|
|
229
|
+
|
|
230
|
+
|
|
231
|
+
class Basis:
|
|
232
|
+
"""
|
|
233
|
+
Read basis sets from files.
|
|
234
|
+
Bring them in a suitable order. 1s2s2p3s3p4s3d etc.
|
|
235
|
+
|
|
236
|
+
NOT YET USED
|
|
237
|
+
"""
|
|
238
|
+
|
|
239
|
+
pass
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
from typing import Dict, Optional
|
|
2
|
+
|
|
3
|
+
import numpy as np
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
ArrDict = Dict[str, np.ndarray]
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class DIIS:
|
|
10
|
+
def __init__(self, arr_specs: ArrDict):
|
|
11
|
+
"""DIIS container.
|
|
12
|
+
|
|
13
|
+
Parameters
|
|
14
|
+
----------
|
|
15
|
+
arr_specs
|
|
16
|
+
Dict with string-keys and array-values. The key 'err_vecs' must always be
|
|
17
|
+
present. Additional keys can be provided, depending on what must be stored
|
|
18
|
+
next to the error vectors.
|
|
19
|
+
The arrays should be at least 2d, with the first dimension having size 'nvecs'.
|
|
20
|
+
"""
|
|
21
|
+
self.nvecs = arr_specs["err_vecs"].shape[0]
|
|
22
|
+
for k, v in arr_specs.items():
|
|
23
|
+
assert v.shape[0] == self.nvecs
|
|
24
|
+
setattr(self, k, v)
|
|
25
|
+
|
|
26
|
+
self.ref_keys = set(arr_specs.keys())
|
|
27
|
+
self.cur_nvecs = 0
|
|
28
|
+
self.cur_index = 0
|
|
29
|
+
|
|
30
|
+
def store(self, arrs: ArrDict) -> int:
|
|
31
|
+
"""Store arrays.
|
|
32
|
+
|
|
33
|
+
Returns the index, where the arrays were stored in their respective arrays.
|
|
34
|
+
"""
|
|
35
|
+
assert set(arrs.keys()) == self.ref_keys
|
|
36
|
+
index = self.cur_index % self.nvecs
|
|
37
|
+
|
|
38
|
+
for key in self.ref_keys:
|
|
39
|
+
getattr(self, key)[index] = arrs[key].copy()
|
|
40
|
+
self.cur_nvecs = min(self.cur_nvecs + 1, self.nvecs)
|
|
41
|
+
self.cur_index += 1
|
|
42
|
+
# print(f"\tstored at {index=}, {self.cur_nvecs=}, {self.cur_index=}")
|
|
43
|
+
return index
|
|
44
|
+
|
|
45
|
+
def reset(self):
|
|
46
|
+
"""Reset DIIS container."""
|
|
47
|
+
self.cur_index = 0
|
|
48
|
+
self.cur_nvecs = 0
|
|
49
|
+
# Also zero the arrays?!
|
|
50
|
+
|
|
51
|
+
def get_coeffs(self) -> Optional[np.ndarray]:
|
|
52
|
+
"""Try to calculate DIIS coefficients from the error matrix."""
|
|
53
|
+
if not self.can_get_coeffs():
|
|
54
|
+
return None
|
|
55
|
+
|
|
56
|
+
err_vecs = self.err_vecs[: self.cur_nvecs]
|
|
57
|
+
err_mat = np.einsum("ij,kj->ik", err_vecs, err_vecs)
|
|
58
|
+
try:
|
|
59
|
+
coeffs = np.linalg.solve(err_mat, np.ones(self.cur_nvecs))
|
|
60
|
+
coeffs /= coeffs.sum()
|
|
61
|
+
except np.linalg.LinAlgError:
|
|
62
|
+
coeffs = None
|
|
63
|
+
self.reset()
|
|
64
|
+
return coeffs
|
|
65
|
+
|
|
66
|
+
def get(self, key: str) -> np.ndarray:
|
|
67
|
+
return getattr(self, key)[: self.cur_nvecs]
|
|
68
|
+
|
|
69
|
+
def can_get_coeffs(self) -> bool:
|
|
70
|
+
return self.cur_nvecs >= 2
|
|
71
|
+
|
|
72
|
+
def __str__(self):
|
|
73
|
+
return f"DIIS(nvecs={self.nvecs}, {self.cur_nvecs} stored)"
|
|
74
|
+
|
|
75
|
+
def __repr__(self):
|
|
76
|
+
return self.__str__()
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
|
|
3
|
+
from pysisyphus import logger as pysis_logger
|
|
4
|
+
|
|
5
|
+
logger = pysis_logger.getChild("wavefunction")
|
|
6
|
+
logger.setLevel(logging.DEBUG)
|
|
7
|
+
|
|
8
|
+
from pysisyphus.wavefunction.shells import (
|
|
9
|
+
get_l,
|
|
10
|
+
AOMixShells,
|
|
11
|
+
MoldenShells,
|
|
12
|
+
ORCAShells,
|
|
13
|
+
ORCAMoldenShells,
|
|
14
|
+
Shell,
|
|
15
|
+
Shells,
|
|
16
|
+
)
|
|
17
|
+
|
|
18
|
+
from pysisyphus.wavefunction.excited_states import norm_ci_coeffs
|
|
19
|
+
from pysisyphus.wavefunction.wavefunction import Wavefunction
|
|
20
|
+
from pysisyphus.wavefunction.localization import (
|
|
21
|
+
cholesky,
|
|
22
|
+
edmiston_ruedenberg,
|
|
23
|
+
foster_boys,
|
|
24
|
+
pipek_mezey,
|
|
25
|
+
)
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
from cffi import FFI
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
def load_h(h_fn):
|
|
5
|
+
with open(h_fn) as handle:
|
|
6
|
+
text = handle.read().strip()
|
|
7
|
+
return text
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def run():
|
|
11
|
+
ffibuilder = FFI()
|
|
12
|
+
dir_ = "devel_ints/"
|
|
13
|
+
names = ("ovlp3d", "dipole3d", "diag_quadrupole3d", "quadrupole3d", "kinetic3d")
|
|
14
|
+
|
|
15
|
+
all_sources = list()
|
|
16
|
+
all_includes = list()
|
|
17
|
+
all_cdefs = list()
|
|
18
|
+
for name in names:
|
|
19
|
+
c_name = dir_ + name + ".c"
|
|
20
|
+
all_sources.append(c_name)
|
|
21
|
+
h_name = dir_ + name + ".h"
|
|
22
|
+
all_includes.append(h_name)
|
|
23
|
+
cdefs = load_h(h_name)
|
|
24
|
+
all_cdefs.append(cdefs)
|
|
25
|
+
|
|
26
|
+
cdefs = "\n\n".join(all_cdefs)
|
|
27
|
+
includes = "\n".join([f'#include "{h_name}"' for h_name in all_includes])
|
|
28
|
+
|
|
29
|
+
ffibuilder.cdef(cdefs)
|
|
30
|
+
ffibuilder.set_source(
|
|
31
|
+
"_ints1el",
|
|
32
|
+
includes,
|
|
33
|
+
sources=all_sources,
|
|
34
|
+
libraries=[
|
|
35
|
+
"m",
|
|
36
|
+
],
|
|
37
|
+
)
|
|
38
|
+
ffibuilder.compile(verbose=True)
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
if __name__ == "__main__":
|
|
42
|
+
run()
|
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
#!/usr/bin/env python
|
|
2
|
+
|
|
3
|
+
# [1] https://doi.org/10.1002/qua.560540202
|
|
4
|
+
# Transformation between Cartesian and pure spherical harmonic Gaussians
|
|
5
|
+
# Schlegel, Frisch, 1995
|
|
6
|
+
|
|
7
|
+
import argparse
|
|
8
|
+
import functools
|
|
9
|
+
from cmath import sqrt
|
|
10
|
+
from math import floor
|
|
11
|
+
import sys
|
|
12
|
+
from typing import Dict, List, Tuple
|
|
13
|
+
|
|
14
|
+
import numpy as np
|
|
15
|
+
from numpy.typing import NDArray
|
|
16
|
+
from scipy.special import factorial as fact
|
|
17
|
+
from scipy.special import binom
|
|
18
|
+
|
|
19
|
+
from pysisyphus.wavefunction.helpers import canonical_order
|
|
20
|
+
from pysisyphus.wavefunction.normalization import get_lmn_factors
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
ZERO_THRESH = 1e-14
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
@functools.cache
|
|
27
|
+
def cart2sph_coeff(lx: int, ly: int, lz: int, m: int) -> complex:
|
|
28
|
+
"""Coefficient to convert Cartesian to spherical harmonics.
|
|
29
|
+
|
|
30
|
+
Eq. (15) in [1].
|
|
31
|
+
|
|
32
|
+
Paramters
|
|
33
|
+
---------
|
|
34
|
+
lx
|
|
35
|
+
Cartesian quantum number.
|
|
36
|
+
ly
|
|
37
|
+
Cartesian quantum number.
|
|
38
|
+
lz
|
|
39
|
+
Cartesian quantum number.
|
|
40
|
+
m
|
|
41
|
+
Magnetic quantum number.
|
|
42
|
+
|
|
43
|
+
Returns
|
|
44
|
+
-------
|
|
45
|
+
coeff
|
|
46
|
+
Contribution of the given Cartesian basis function to the spherical
|
|
47
|
+
harmonic Y^(lx + ly + lz)_m.
|
|
48
|
+
"""
|
|
49
|
+
|
|
50
|
+
l = lx + ly + lz
|
|
51
|
+
assert -l <= m <= l
|
|
52
|
+
|
|
53
|
+
j = (lx + ly - abs(m)) / 2
|
|
54
|
+
if (j % 1) != 0: # Return when j is not integer
|
|
55
|
+
return 0
|
|
56
|
+
j = int(j)
|
|
57
|
+
|
|
58
|
+
lfact = fact(l) # l!
|
|
59
|
+
lmm = l - abs(m) # (l - |m|)
|
|
60
|
+
sign = 1 if m >= 0 else -1
|
|
61
|
+
|
|
62
|
+
coeff = 0.0j
|
|
63
|
+
for i in range(floor(lmm / 2) + 1):
|
|
64
|
+
i_fact = (
|
|
65
|
+
binom(l, i)
|
|
66
|
+
* binom(i, j)
|
|
67
|
+
* (-1) ** i
|
|
68
|
+
* fact(2 * l - 2 * i)
|
|
69
|
+
/ fact(lmm - 2 * i)
|
|
70
|
+
)
|
|
71
|
+
k_sum = 0.0
|
|
72
|
+
for k in range(j + 1):
|
|
73
|
+
prefact = (-1) ** (sign * (abs(m) - lx + 2 * k) / 2)
|
|
74
|
+
k_sum += prefact * binom(j, k) * binom(abs(m), lx - 2 * k)
|
|
75
|
+
coeff += i_fact * k_sum
|
|
76
|
+
coeff *= sqrt(
|
|
77
|
+
fact(2 * lx)
|
|
78
|
+
* fact(2 * ly)
|
|
79
|
+
* fact(2 * lz)
|
|
80
|
+
* lfact
|
|
81
|
+
* fact(lmm)
|
|
82
|
+
/ (fact(2 * l) * fact(lx) * fact(ly) * fact(lz) * fact(l + abs(m)))
|
|
83
|
+
)
|
|
84
|
+
coeff *= 1 / (2**l * lfact)
|
|
85
|
+
|
|
86
|
+
return coeff
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
@functools.cache
|
|
90
|
+
def cart2sph_coeffs_for(
|
|
91
|
+
l: int,
|
|
92
|
+
real: bool = True,
|
|
93
|
+
zero_small: bool = True,
|
|
94
|
+
zero_thresh: float = ZERO_THRESH,
|
|
95
|
+
) -> NDArray:
|
|
96
|
+
all_coeffs = list()
|
|
97
|
+
for lx, ly, lz in canonical_order(l):
|
|
98
|
+
coeffs = list()
|
|
99
|
+
for m in range(-l, l + 1):
|
|
100
|
+
coeff = cart2sph_coeff(lx, ly, lz, m)
|
|
101
|
+
# Form linear combination for m != 0 to get real spherical orbitals.
|
|
102
|
+
if real and m != 0:
|
|
103
|
+
coeff_minus = cart2sph_coeff(lx, ly, lz, -m)
|
|
104
|
+
sign = 1 if m < 0 else -1
|
|
105
|
+
coeff = (coeff + sign * coeff_minus) / sqrt(sign * 2)
|
|
106
|
+
coeffs.append(coeff)
|
|
107
|
+
all_coeffs.append(coeffs)
|
|
108
|
+
C = np.array(all_coeffs, dtype=complex)
|
|
109
|
+
if real:
|
|
110
|
+
assert real == ~np.iscomplex(C).all() # C should be real
|
|
111
|
+
C = np.real(C)
|
|
112
|
+
if zero_small:
|
|
113
|
+
mask = np.abs(C) <= zero_thresh
|
|
114
|
+
C[mask] = 0.0
|
|
115
|
+
# Final shape will be (spherical, Cartesian)
|
|
116
|
+
# Return read-only view; otherwise it would be too easy to mess up the
|
|
117
|
+
# cached result by inplace operations on C.
|
|
118
|
+
C = C.T.view()
|
|
119
|
+
C.flags.writeable = False
|
|
120
|
+
return C
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
@functools.cache
|
|
124
|
+
def expand_sph_quantum_numbers(
|
|
125
|
+
Lm, zero_thresh=ZERO_THRESH, with_lmn_factors=False
|
|
126
|
+
) -> Tuple[NDArray[float], List[Tuple[int, int, int]]]:
|
|
127
|
+
"""Factors and Cart. angular momentum vectors for given sph. quantum numbers."""
|
|
128
|
+
L, m = Lm
|
|
129
|
+
m += L # Map m from [-L, L] onto [0, 2*L]
|
|
130
|
+
C = cart2sph_coeffs_for(L) # shape (spherical, Cartesian)
|
|
131
|
+
# Include lmn-factor that appears when contracted functions are normalized
|
|
132
|
+
# according to 'normalization.norm_cgto_lmn(L).
|
|
133
|
+
if with_lmn_factors:
|
|
134
|
+
lmn_factors = get_lmn_factors(L)
|
|
135
|
+
C = C * lmn_factors[None, :]
|
|
136
|
+
indices, *_ = np.where(np.abs(C[m]) > zero_thresh)
|
|
137
|
+
factors = C[m, indices].copy()
|
|
138
|
+
|
|
139
|
+
cart_lmn = [lmn for i, lmn in enumerate(canonical_order(L)) if i in indices]
|
|
140
|
+
return factors, cart_lmn
|
|
141
|
+
|
|
142
|
+
|
|
143
|
+
def cart2sph_coeffs(
|
|
144
|
+
l_max: int,
|
|
145
|
+
**kwargs,
|
|
146
|
+
) -> Dict[int, NDArray]:
|
|
147
|
+
coeffs = {l: cart2sph_coeffs_for(l, **kwargs) for l in range(l_max + 1)}
|
|
148
|
+
return coeffs
|
|
149
|
+
|
|
150
|
+
|
|
151
|
+
def cart2sph_nlms(l_max: int) -> Dict[int, Tuple[Tuple[int, int, int]]]:
|
|
152
|
+
nlms = dict()
|
|
153
|
+
for l in range(l_max + 1):
|
|
154
|
+
n = l
|
|
155
|
+
nlms[l] = tuple([(n, l, m) for m in range(-l, l + 1)])
|
|
156
|
+
return nlms
|
|
157
|
+
|
|
158
|
+
|
|
159
|
+
def print_coeffs(l: int, C: NDArray):
|
|
160
|
+
print("".join([f"{m: >13d}" for m in range(-l, l + 1)]))
|
|
161
|
+
for (lx, ly, lz), line in zip(canonical_order(l), C):
|
|
162
|
+
fmt = "{:>12.4f}" * len(line)
|
|
163
|
+
verb = "".join(["x"] * lx + ["y"] * ly + ["z"] * lz)
|
|
164
|
+
print(f"{verb}: {fmt.format(*line)}")
|
|
165
|
+
|
|
166
|
+
|
|
167
|
+
def parse_args(args):
|
|
168
|
+
parser = argparse.ArgumentParser()
|
|
169
|
+
|
|
170
|
+
parser.add_argument("l_max", type=int, default=3)
|
|
171
|
+
parser.add_argument("--not-normalized", action="store_true")
|
|
172
|
+
|
|
173
|
+
return parser.parse_args(args)
|
|
174
|
+
|
|
175
|
+
|
|
176
|
+
def run():
|
|
177
|
+
args = parse_args(sys.argv[1:])
|
|
178
|
+
|
|
179
|
+
l_max = args.l_max
|
|
180
|
+
normalized = not args.not_normalized
|
|
181
|
+
|
|
182
|
+
Cs = cart2sph_coeffs(l_max, normalized=normalized)
|
|
183
|
+
for l, C in Cs.items():
|
|
184
|
+
print(f"{l=}")
|
|
185
|
+
print_coeffs(l, C.T)
|
|
186
|
+
print()
|
|
187
|
+
|
|
188
|
+
|
|
189
|
+
if __name__ == "__main__":
|
|
190
|
+
run()
|