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 : * Implementation of the Gn(x) auxiliary function. 17 : * This function is required to calculate integrals over the 1/r^2 operator. 18 : * 19 : * More on the Gn(x) function evaluation: 20 : * (1) J. 0. Jensen, A. H. Cameri, C. P. Vlahacos, D. Zeroka, H. F. Hameka, C. 21 : * N. Merrow, Evaluation of one-electron integrals for arbitrary operators V(r) 22 : * over cartesian Gaussians: Application to inverse-square distance and Yukawa 23 : * operators. J. Comput. Chem. 14(8), 986 (1993). doi: 10.1002/jcc.540140814 (2) 24 : * B. Gao, A. J. Thorvaldsen, K. Ruud, GEN1INT: A unified procedure for the 25 : * evaluation of one-electron integrals over Gaussian basis functions and their 26 : * geometric derivatives. Int. J. Quantum Chem. 111(4), 858 (2011). 27 : * doi: 10.1002/qua.22886 28 : */ 29 : #include <math.h> 30 : #include <string.h> 31 : 32 : #ifndef M_PI 33 : #define M_PI 3.1415926535897932384626433 34 : #endif 35 : 36 : #include "grpp_factorial.h" 37 : #include "grpp_specfunc.h" 38 : 39 : static double gfun_taylor(int n, double x); 40 : 41 : /** 42 : * Calculates values of the Gn(x) auxiliary function for n = 0, ..., nmax 43 : * and stores them into the g[] array. 44 : */ 45 0 : void libgrpp_gfun_values(double x, int nmax, double *g) { 46 0 : memset(g, 0, (nmax + 1) * sizeof(double)); 47 : 48 0 : if (x <= 12.0) { 49 : /* 50 : * downward recursion 51 : */ 52 0 : g[nmax] = gfun_taylor(nmax, x); 53 : 54 0 : for (int n = nmax; n > 0; n--) { 55 0 : g[n - 1] = (1.0 - 2.0 * x * g[n]) / (2.0 * n - 1.0); 56 : } 57 : } else { 58 : /* 59 : * upward recursion 60 : */ 61 0 : double sqrt_x = sqrt(x); 62 0 : g[0] = libgrpp_Dawsons_Integral(sqrt_x) / sqrt_x; 63 : 64 0 : for (int n = 0; n < nmax; n++) { 65 0 : g[n + 1] = (1.0 - (2 * n + 1) * g[n]) / (2.0 * x); 66 : } 67 : } 68 0 : } 69 : 70 : /** 71 : * Calculates value of the Gn(x) auxiliary function using the Taylor expansion. 72 : * The Taylor series converges for x <= 30. 73 : */ 74 0 : static double gfun_taylor(int n, double x) { 75 0 : const double thresh = 1e-15; 76 0 : double sum = 0.0; 77 : 78 0 : for (int k = 0; k < 100; k++) { 79 : 80 0 : double y_exp = exp(-x); 81 0 : double y_pow = pow(x, k); 82 0 : double y_fac = libgrpp_factorial(k); 83 0 : double y_nk1 = 2.0 * n + 2.0 * k + 1.0; 84 : 85 0 : double contrib = y_exp * y_pow / y_fac / y_nk1; 86 0 : sum += contrib; 87 : 88 0 : if (fabs(contrib) < thresh) { 89 : break; 90 : } 91 : } 92 : 93 0 : return sum; 94 : }