Source code for dxtb._src.basis.ortho

# 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: Orthonormalization
=========================

Gram-Schmidt orthonormalization routines for contracted Gaussian basis
functions.
"""

from __future__ import annotations

import math

import torch

from dxtb._src.typing import Tensor

__all__ = ["orthogonalize", "gaussian_integral"]


[docs] def gaussian_integral(ai: Tensor, aj: Tensor, ci: Tensor, cj: Tensor) -> Tensor: """ Integral over two Gaussians (overlap). Parameters ---------- ai : Tensor Exponent of GTO i. Can also be a tensor of exponents corresponding to all primitive GTOs of GTO i. aj : Tensor Exponent of GTO j. Can also be a tensor of exponents corresponding to all primitive GTOs of GTO j. ci : Tensor Contraction coefficients for CGTO i. cj : Tensor Contraction coefficients for CGTO j. Returns ------- Tensor Overlap (summed). """ oij = 1.0 / (ai.unsqueeze(-1) + aj.unsqueeze(-2)) kab = torch.sqrt(math.pi * oij) ** 3 overlap = kab * ci.unsqueeze(-1) * cj.unsqueeze(-2) # OLD: loop-based version # overlap = ai.new_tensor(0.0) # for _ai, _ci in zip(ai, ci): # for _aj, _cj in zip(aj, cj): # eij = _ai + _aj # oij = 1.0 / eij # kab = torch.sqrt(math.pi * oij) ** 3 # overlap += _ci * _cj * kab return overlap.sum()
[docs] def orthogonalize( alpha: tuple[Tensor, Tensor], coeff: tuple[Tensor, Tensor] ) -> tuple[Tensor, Tensor]: """ Orthogonalize a contracted Gaussian basis function to an existing basis function using. The second basis function is orthonormalized against the first basis function. Parameters ---------- alpha : (Tensor, Tensor) Primitive Gaussian exponents for the shell pair. coeff : (Tensor, Tensor) Contraction coefficients for the shell pair. Returns ------- (Tensor, Tensor) Primitive Gaussian exponents and contraction coefficients for the orthonormalized basis function. """ coeff_i, coeff_j = coeff alpha_i, alpha_j = alpha # Calculate overlap between basis functions overlap = gaussian_integral(alpha_i, alpha_j, coeff_i, coeff_j) # Create new basis function from the pair which is orthogonal to the first # basis function alpha_new = torch.cat((alpha_j, alpha_i), dim=-1) coeff_new = torch.cat((coeff_j, -overlap * coeff_i), dim=-1) # Normalization of new basis function might be off, calculate self overlap selfoverlap = gaussian_integral(alpha_new, alpha_new, coeff_new, coeff_new) coeff_new = coeff_new / torch.sqrt(selfoverlap) return alpha_new, coeff_new