LCOV - code coverage report
Current view: top level - src/grpp - grpp_momentum.c (source / functions) Coverage Total Hit
Test: CP2K Regtests (git:936074a) Lines: 0.0 % 80 0
Test Date: 2025-12-04 06:27:48 Functions: 0.0 % 2 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 momentum 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              : #ifndef M_PI
      27              : #define M_PI 3.14159265358979323846
      28              : #endif
      29              : #include "grpp_momentum.h"
      30              : 
      31              : #include "grpp_norm_gaussian.h"
      32              : #include "grpp_utils.h"
      33              : #include "libgrpp.h"
      34              : 
      35              : static void momentum_integrals_shell_pair_obara_saika(
      36              :     libgrpp_shell_t *shell_A, libgrpp_shell_t *shell_B, double alpha_A,
      37              :     double alpha_B, double *momentum_x_matrix, double *momentum_y_matrix,
      38              :     double *momentum_z_matrix);
      39              : 
      40              : /**
      41              :  * returns imaginary(!) part of integrals over the momentum operator p = -i
      42              :  * \hbar \nabla. The "minus" sign is included.
      43              :  */
      44            0 : void libgrpp_momentum_integrals(libgrpp_shell_t *shell_A,
      45              :                                 libgrpp_shell_t *shell_B,
      46              :                                 double *momentum_x_matrix,
      47              :                                 double *momentum_y_matrix,
      48              :                                 double *momentum_z_matrix) {
      49            0 :   int size_A = libgrpp_get_shell_size(shell_A);
      50            0 :   int size_B = libgrpp_get_shell_size(shell_B);
      51              : 
      52            0 :   double *buf_x = calloc(size_A * size_B, sizeof(double));
      53            0 :   double *buf_y = calloc(size_A * size_B, sizeof(double));
      54            0 :   double *buf_z = calloc(size_A * size_B, sizeof(double));
      55              : 
      56            0 :   memset(momentum_x_matrix, 0, size_A * size_B * sizeof(double));
      57            0 :   memset(momentum_y_matrix, 0, size_A * size_B * sizeof(double));
      58            0 :   memset(momentum_z_matrix, 0, size_A * size_B * sizeof(double));
      59              : 
      60              :   // loop over primitives in contractions
      61            0 :   for (int i = 0; i < shell_A->num_primitives; i++) {
      62            0 :     for (int j = 0; j < shell_B->num_primitives; j++) {
      63            0 :       double alpha_i = shell_A->alpha[i];
      64            0 :       double alpha_j = shell_B->alpha[j];
      65            0 :       double coef_A_i = shell_A->coeffs[i];
      66            0 :       double coef_B_j = shell_B->coeffs[j];
      67              : 
      68            0 :       momentum_integrals_shell_pair_obara_saika(shell_A, shell_B, alpha_i,
      69              :                                                 alpha_j, buf_x, buf_y, buf_z);
      70              : 
      71            0 :       libgrpp_daxpy(size_A * size_B, coef_A_i * coef_B_j, buf_x,
      72              :                     momentum_x_matrix);
      73            0 :       libgrpp_daxpy(size_A * size_B, coef_A_i * coef_B_j, buf_y,
      74              :                     momentum_y_matrix);
      75            0 :       libgrpp_daxpy(size_A * size_B, coef_A_i * coef_B_j, buf_z,
      76              :                     momentum_z_matrix);
      77              :     }
      78              :   }
      79              : 
      80            0 :   free(buf_x);
      81            0 :   free(buf_y);
      82            0 :   free(buf_z);
      83            0 : }
      84              : 
      85            0 : static void momentum_integrals_shell_pair_obara_saika(
      86              :     libgrpp_shell_t *shell_A, libgrpp_shell_t *shell_B, double alpha_A,
      87              :     double alpha_B, double *momentum_x_matrix, double *momentum_y_matrix,
      88              :     double *momentum_z_matrix) {
      89            0 :   int size_A = libgrpp_get_shell_size(shell_A);
      90            0 :   int size_B = libgrpp_get_shell_size(shell_B);
      91            0 :   int L_A = shell_A->L;
      92            0 :   int L_B = shell_B->L;
      93            0 :   double N_A = libgrpp_gaussian_norm_factor(L_A, 0, 0, alpha_A);
      94            0 :   double N_B = libgrpp_gaussian_norm_factor(L_B, 0, 0, alpha_B);
      95              : 
      96            0 :   double p = alpha_A + alpha_B;
      97            0 :   double mu = alpha_A * alpha_B / (alpha_A + alpha_B);
      98            0 :   double *A = shell_A->origin;
      99            0 :   double *B = shell_B->origin;
     100              : 
     101              :   // calculate S_ij
     102            0 :   double S[3][LIBGRPP_MAX_BASIS_L + 1][LIBGRPP_MAX_BASIS_L + 1];
     103              : 
     104            0 :   for (int coord = 0; coord < 3; coord++) {
     105            0 :     double P = (alpha_A * A[coord] + alpha_B * B[coord]) / p;
     106              : 
     107            0 :     double X_AB = A[coord] - B[coord];
     108            0 :     double X_PA = P - A[coord];
     109            0 :     double X_PB = P - B[coord];
     110            0 :     double pfac = 1.0 / (2.0 * p);
     111              : 
     112            0 :     for (int i = 0; i <= L_A + 1; i++) {
     113            0 :       for (int j = 0; j <= L_B + 1; j++) {
     114            0 :         double S_ij = 0.0;
     115              : 
     116            0 :         if (i + j == 0) {
     117            0 :           S[coord][0][0] = sqrt(M_PI / p) * exp(-mu * X_AB * X_AB);
     118            0 :           continue;
     119              :         }
     120              : 
     121            0 :         if (i == 0) { // upward by j
     122            0 :           S_ij += X_PB * S[coord][i][j - 1];
     123            0 :           if (j - 1 > 0) {
     124            0 :             S_ij += (j - 1) * pfac * S[coord][i][j - 2];
     125              :           }
     126              :         } else { // upward by i
     127            0 :           S_ij += X_PA * S[coord][i - 1][j];
     128            0 :           if (i - 1 > 0) {
     129            0 :             S_ij += (i - 1) * pfac * S[coord][i - 2][j];
     130              :           }
     131            0 :           if (j > 0) {
     132            0 :             S_ij += j * pfac * S[coord][i - 1][j - 1];
     133              :           }
     134              :         }
     135              : 
     136            0 :         S[coord][i][j] = S_ij;
     137              :       }
     138              :     }
     139              :   }
     140              : 
     141              :   // calculate D^1_ij
     142              : 
     143              :   double D1[3][LIBGRPP_MAX_BASIS_L][LIBGRPP_MAX_BASIS_L];
     144              : 
     145            0 :   for (int coord = 0; coord < 3; coord++) {
     146            0 :     for (int i = 0; i <= L_A; i++) {
     147            0 :       for (int j = 0; j <= L_B; j++) {
     148              : 
     149            0 :         double D1_ij = 0.0;
     150            0 :         D1_ij += 2.0 * alpha_A * S[coord][i + 1][j];
     151            0 :         if (i >= 1) {
     152            0 :           D1_ij -= i * S[coord][i - 1][j];
     153              :         }
     154              : 
     155            0 :         D1[coord][i][j] = D1_ij;
     156              :       }
     157              :     }
     158              :   }
     159              : 
     160              :   // loop over cartesian functions inside the shells
     161            0 :   for (int m = 0; m < size_A; m++) {
     162            0 :     for (int n = 0; n < size_B; n++) {
     163            0 :       int n_A = shell_A->cart_list[3 * m + 0];
     164            0 :       int l_A = shell_A->cart_list[3 * m + 1];
     165            0 :       int m_A = shell_A->cart_list[3 * m + 2];
     166            0 :       int n_B = shell_B->cart_list[3 * n + 0];
     167            0 :       int l_B = shell_B->cart_list[3 * n + 1];
     168            0 :       int m_B = shell_B->cart_list[3 * n + 2];
     169              : 
     170            0 :       momentum_x_matrix[m * size_B + n] =
     171            0 :           -N_A * N_B * D1[0][n_A][n_B] * S[1][l_A][l_B] * S[2][m_A][m_B];
     172            0 :       momentum_y_matrix[m * size_B + n] =
     173            0 :           -N_A * N_B * S[0][n_A][n_B] * D1[1][l_A][l_B] * S[2][m_A][m_B];
     174            0 :       momentum_z_matrix[m * size_B + n] =
     175            0 :           -N_A * N_B * S[0][n_A][n_B] * S[1][l_A][l_B] * D1[2][m_A][m_B];
     176              :     }
     177              :   }
     178            0 : }
        

Generated by: LCOV version 2.0-1