LCOV - code coverage report
Current view: top level - src/grpp - grpp_kinetic.c (source / functions) Hit Total Coverage
Test: CP2K Regtests (git:b4bd748) Lines: 0 72 0.0 %
Date: 2025-03-09 07:56:22 Functions: 0 2 0.0 %

          Line data    Source code
       1             : /*----------------------------------------------------------------------------*/
       2             : /*  CP2K: A general program to perform molecular dynamics simulations         */
       3             : /*  Copyright 2000-2025 CP2K developers group <https://cp2k.org>              */
       4             : /*                                                                            */
       5             : /*  SPDX-License-Identifier: MIT                                              */
       6             : /*----------------------------------------------------------------------------*/
       7             : 
       8             : /*
       9             :  *  libgrpp - a library for the evaluation of integrals over
      10             :  *            generalized relativistic pseudopotentials.
      11             :  *
      12             :  *  Copyright (C) 2021-2023 Alexander Oleynichenko
      13             :  */
      14             : 
      15             : /**
      16             :  * Calculation of kinetic-energy integrals.
      17             :  *
      18             :  * For details, see:
      19             :  * T. Helgaker, P. Jorgensen, J. Olsen, Molecular Electronic-Structure Theory,
      20             :  * John Wiley & Sons Ltd, 2000.
      21             :  * Chapter 9.3.4, "Momentum and kinetic-energy integrals"
      22             :  */
      23             : #include <math.h>
      24             : #include <stdlib.h>
      25             : #include <string.h>
      26             : 
      27             : #ifndef M_PI
      28             : #define M_PI 3.14159265358979323846
      29             : #endif
      30             : 
      31             : #include "grpp_kinetic.h"
      32             : 
      33             : #include "grpp_norm_gaussian.h"
      34             : #include "grpp_utils.h"
      35             : #include "libgrpp.h"
      36             : 
      37             : static void kinetic_energy_integrals_shell_pair_obara_saika(
      38             :     libgrpp_shell_t *shell_A, libgrpp_shell_t *shell_B, double alpha_A,
      39             :     double alpha_B, double *kinetic_matrix);
      40             : 
      41           0 : void libgrpp_kinetic_energy_integrals(libgrpp_shell_t *shell_A,
      42             :                                       libgrpp_shell_t *shell_B,
      43             :                                       double *kinetic_matrix) {
      44           0 :   int size_A = libgrpp_get_shell_size(shell_A);
      45           0 :   int size_B = libgrpp_get_shell_size(shell_B);
      46             : 
      47           0 :   double *buf = calloc(size_A * size_B, sizeof(double));
      48             : 
      49           0 :   memset(kinetic_matrix, 0, size_A * size_B * sizeof(double));
      50             : 
      51             :   // loop over primitives in contractions
      52           0 :   for (int i = 0; i < shell_A->num_primitives; i++) {
      53           0 :     for (int j = 0; j < shell_B->num_primitives; j++) {
      54           0 :       double alpha_i = shell_A->alpha[i];
      55           0 :       double alpha_j = shell_B->alpha[j];
      56           0 :       double coef_A_i = shell_A->coeffs[i];
      57           0 :       double coef_B_j = shell_B->coeffs[j];
      58             : 
      59           0 :       kinetic_energy_integrals_shell_pair_obara_saika(shell_A, shell_B, alpha_i,
      60             :                                                       alpha_j, buf);
      61             : 
      62           0 :       libgrpp_daxpy(size_A * size_B, coef_A_i * coef_B_j, buf, kinetic_matrix);
      63             :     }
      64             :   }
      65             : 
      66           0 :   free(buf);
      67           0 : }
      68             : 
      69           0 : static void kinetic_energy_integrals_shell_pair_obara_saika(
      70             :     libgrpp_shell_t *shell_A, libgrpp_shell_t *shell_B, double alpha_A,
      71             :     double alpha_B, double *kinetic_matrix) {
      72           0 :   int size_A = libgrpp_get_shell_size(shell_A);
      73           0 :   int size_B = libgrpp_get_shell_size(shell_B);
      74           0 :   int L_A = shell_A->L;
      75           0 :   int L_B = shell_B->L;
      76           0 :   double N_A = libgrpp_gaussian_norm_factor(L_A, 0, 0, alpha_A);
      77           0 :   double N_B = libgrpp_gaussian_norm_factor(L_B, 0, 0, alpha_B);
      78             : 
      79           0 :   double p = alpha_A + alpha_B;
      80           0 :   double mu = alpha_A * alpha_B / (alpha_A + alpha_B);
      81           0 :   double *A = shell_A->origin;
      82           0 :   double *B = shell_B->origin;
      83             : 
      84             :   // calculate S_ij
      85           0 :   double S[3][LIBGRPP_MAX_BASIS_L + 2][LIBGRPP_MAX_BASIS_L + 2];
      86             : 
      87           0 :   for (int coord = 0; coord < 3; coord++) {
      88           0 :     double P = (alpha_A * A[coord] + alpha_B * B[coord]) / p;
      89             : 
      90           0 :     double X_AB = A[coord] - B[coord];
      91           0 :     double X_PA = P - A[coord];
      92           0 :     double X_PB = P - B[coord];
      93           0 :     double pfac = 1.0 / (2.0 * p);
      94             : 
      95           0 :     for (int i = 0; i <= L_A + 2; i++) {
      96           0 :       for (int j = 0; j <= L_B + 2; j++) {
      97           0 :         double S_ij = 0.0;
      98             : 
      99           0 :         if (i + j == 0) {
     100           0 :           S[coord][0][0] = sqrt(M_PI / p) * exp(-mu * X_AB * X_AB);
     101           0 :           continue;
     102             :         }
     103             : 
     104           0 :         if (i == 0) { // upward by j
     105           0 :           S_ij += X_PB * S[coord][i][j - 1];
     106           0 :           if (j - 1 > 0) {
     107           0 :             S_ij += (j - 1) * pfac * S[coord][i][j - 2];
     108             :           }
     109             :         } else { // upward by i
     110           0 :           S_ij += X_PA * S[coord][i - 1][j];
     111           0 :           if (i - 1 > 0) {
     112           0 :             S_ij += (i - 1) * pfac * S[coord][i - 2][j];
     113             :           }
     114           0 :           if (j > 0) {
     115           0 :             S_ij += j * pfac * S[coord][i - 1][j - 1];
     116             :           }
     117             :         }
     118             : 
     119           0 :         S[coord][i][j] = S_ij;
     120             :       }
     121             :     }
     122             :   }
     123             : 
     124             :   // calculate D^2_ij
     125             : 
     126             :   double D2[3][LIBGRPP_MAX_BASIS_L][LIBGRPP_MAX_BASIS_L];
     127             : 
     128           0 :   for (int coord = 0; coord < 3; coord++) {
     129           0 :     for (int i = 0; i <= L_A; i++) {
     130           0 :       for (int j = 0; j <= L_B; j++) {
     131             : 
     132           0 :         double D2_ij = 0.0;
     133           0 :         D2_ij += 4.0 * alpha_A * alpha_A * S[coord][i + 2][j];
     134           0 :         D2_ij -= 2.0 * alpha_A * (2 * i + 1) * S[coord][i][j];
     135           0 :         if (i >= 2) {
     136           0 :           D2_ij += i * (i - 1) * S[coord][i - 2][j];
     137             :         }
     138             : 
     139           0 :         D2[coord][i][j] = D2_ij;
     140             :       }
     141             :     }
     142             :   }
     143             : 
     144             :   // loop over cartesian functions inside the shells
     145           0 :   for (int m = 0; m < size_A; m++) {
     146           0 :     for (int n = 0; n < size_B; n++) {
     147           0 :       int n_A = shell_A->cart_list[3 * m + 0];
     148           0 :       int l_A = shell_A->cart_list[3 * m + 1];
     149           0 :       int m_A = shell_A->cart_list[3 * m + 2];
     150           0 :       int n_B = shell_B->cart_list[3 * n + 0];
     151           0 :       int l_B = shell_B->cart_list[3 * n + 1];
     152           0 :       int m_B = shell_B->cart_list[3 * n + 2];
     153             : 
     154           0 :       kinetic_matrix[m * size_B + n] =
     155           0 :           -0.5 * N_A * N_B *
     156           0 :           (D2[0][n_A][n_B] * S[1][l_A][l_B] * S[2][m_A][m_B] +
     157           0 :            S[0][n_A][n_B] * D2[1][l_A][l_B] * S[2][m_A][m_B] +
     158           0 :            S[0][n_A][n_B] * S[1][l_A][l_B] * D2[2][m_A][m_B]);
     159             :     }
     160             :   }
     161           0 : }

Generated by: LCOV version 1.15