Source code for dxtb._src.basis.slater

# This file is part of dxtb.
#
# SPDX-Identifier: Apache-2.0
# Copyright (C) 2024 Grimme Group
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""
Basis: Slater Expansion
=======================

Expansion coefficients for Slater functions into primitive Gaussian functions
"""

from __future__ import annotations

import math
from pathlib import Path

import numpy as np
import torch

from dxtb._src.typing import Tensor
from dxtb._src.typing.exceptions import (
    CGTOAzimuthalQuantumNumberError,
    CGTOPrimitivesError,
    CGTOPrincipalQuantumNumberError,
    CGTOQuantumNumberError,
    CGTOSlaterExponentsError,
)

__all__ = ["slater_to_gauss"]

base = Path(__file__).parent / "sto-ng"
sto_ng = [
    torch.from_numpy(np.load(base / f"sto-{n}g.npy")).type(torch.double)
    for n in range(1, 7)
]


# Two over pi
top = 2.0 / math.pi

dfactorial = torch.tensor(
    [1.0, 1.0, 3.0, 15.0, 105.0, 945.0, 10395.0, 135135.0]
)
"""
Double factorial up to 7!! for normalization of the Gaussian basis functions.

See `OEIS A001147 <https://oeis.org/A001147>`__.
"""

MAX_PRINCIPAL = 6
"""Maximum principal quantum number."""

MAX_AZIMUTHAL = 4
"""Maximum azimuthal quantum number."""


[docs] def slater_to_gauss( ng: Tensor, n: Tensor, l: Tensor, zeta: Tensor, norm: bool = True, ) -> tuple[Tensor, Tensor]: """ Expand Slater function in primitive gaussian functions. Parameters ---------- ng : int Number of Gaussian functions for the expansion. n : int Principal quantum number of shell. l : int Azimuthal quantum number of shell. zeta : Tensor Exponent of Slater function to expand. norm : bool, optional Include normalization in contraction coefficients. Defaults to ``True``. Returns ------- (Tensor, Tensor): Contraction coefficients of primitive gaussians, can contain normalization, and exponents of primitive gaussian functions. """ if not 1 <= ng <= 6: raise CGTOPrimitivesError() if zeta <= 0: raise CGTOSlaterExponentsError() if l > MAX_AZIMUTHAL: raise CGTOAzimuthalQuantumNumberError(MAX_AZIMUTHAL) if n > MAX_PRINCIPAL: raise CGTOPrincipalQuantumNumberError(MAX_PRINCIPAL) if n <= l: # l ∊ [n-1, n-2, ..., 1, 0] raise CGTOQuantumNumberError() # we have to use a little hack here, # if you pass n and l correctly, everything is fine # ityp: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 # n: 1 2 3 4 5 2 3 4 5 3 4 5 4 5 5 6 6 # l: 0 0 0 0 0 1 1 1 1 2 2 2 3 3 4 0 1 itype = n + torch.tensor([0, 4, 7, 9, 10], device=zeta.device)[l] - 1 if n == 6 and ng == 6: itype = 15 + l _coeff, _alpha = sto_ng[ng - 1][:, itype, :] alpha = _alpha.type(zeta.dtype).to(zeta.device) * zeta.unsqueeze(-1) ** 2 coeff = _coeff.type(zeta.dtype).to(zeta.device) # normalize the gaussian if requested # <φ|φ> = (2i-1)!!(2j-1)!!(2k-1)!!/(4α)^(i+j+k) · sqrt(π/2α)³ # N² = (4α)^(i+j+k)/((2i-1)!!(2j-1)!!(2k-1)!!) · sqrt(2α/π)³ # N = (4α)^((i+j+k)/2) / sqrt((2i-1)!!(2j-1)!!(2k-1)!!) · (2α/π)^(3/4) if norm is True: coeff = coeff * ( (top * alpha) ** 0.75 * torch.sqrt(4 * alpha) ** l / torch.sqrt(dfactorial[l]) ) return (alpha, coeff)