(git:afc468d)
Loading...
Searching...
No Matches
grpp_screening.c
Go to the documentation of this file.
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 * Screening of radial integrals.
17 *
18 * The technique of screening is adopted from:
19 * R. A. Shaw, J. G. Hill. Prescreening and efficiency in the evaluation
20 * of integrals over ab initio effective core potentials.
21 * J. Chem. Phys. 147, 074108 (2017). doi: 10.1063/1.4986887
22 * (see also Supplementary Material for this article).
23 *
24 * Note that in this publication the transcendental equation (2) for
25 * type 2 integrals is not correct.
26 */
27
28#include <math.h>
29#include <stdlib.h>
30#ifndef M_PI
31#define M_PI 3.14159265358979323846
32#endif
33
34#include "grpp_factorial.h"
35#include "grpp_screening.h"
36#include "grpp_specfunc.h"
37#include "libgrpp.h"
38
39/*
40 * functions defined below in the file
41 */
42
44 int lambda, int n, double CA_2, double CB_2, double alpha_A, double alpha_B,
45 double k, double eta, double *screened_value);
46
47static double screening_type1_equation_for_maximum(double r, int n, int lambda,
48 double p, double k);
49
51 int lambda1, int lambda2, int n, double CA_2, double CB_2, double alpha_A,
52 double alpha_B, double k1, double k2, double eta, double *screened_value);
53
54static double screening_type2_equation_for_maximum(double r, int n, int lambda1,
55 int lambda2, double p,
56 double k1, double k2);
57
58// static double analytic_one_center_rpp_integral_primitive(int L, double
59// alpha1,
60// double alpha2, int
61// n, double zeta);
62
63/**
64 * screening for the type 1 radial integrals
65 * for the pair of contracted gaussian functions.
66 */
67int libgrpp_screening_radial_type1(int lambda, int n, double CA_2, double CB_2,
68 double alpha_A, double alpha_B, double k,
69 double prefactor,
70 libgrpp_potential_t *potential,
71 double *screened_value) {
72 *screened_value = 0.0;
73
74 if (lambda >= 1 && fabs(k) <= LIBGRPP_ZERO_THRESH) {
75 return EXIT_SUCCESS;
76 }
77
78 /*
79 * loop over RPP primitives
80 */
81 for (int iprim = 0; iprim < potential->num_primitives; iprim++) {
82 double eta = potential->alpha[iprim];
83 int ni = n + potential->powers[iprim];
84 double coef = potential->coeffs[iprim];
85
86 double val_i = 0.0;
88 lambda, ni, CA_2, CB_2, alpha_A, alpha_B, k, eta, &val_i);
89 if (err_code == EXIT_FAILURE) {
90 return EXIT_FAILURE;
91 }
92
93 *screened_value += prefactor * coef * val_i;
94 }
95
96 return EXIT_SUCCESS;
97}
98
99/**
100 * screening for the type 1 radial integrals
101 * for the pair of primitive gaussian functions.
102 */
104 int lambda, int n, double CA_2, double CB_2, double alpha_A, double alpha_B,
105 double k, double eta, double *screened_value) {
106 double p = alpha_A + alpha_B + eta;
107 double CA = sqrt(CA_2);
108 double CB = sqrt(CB_2);
109
110 /*
111 * find position of the maximum of the integrand
112 */
113 const double tol = 1e-2;
114 double r0 = (alpha_A * CA + alpha_B * CB) / p;
115 double r0_prev = 0.0;
116
117 int nsteps = 0;
118 do {
119 nsteps++;
120 if (nsteps == 10) {
121 *screened_value = 0.0;
122 return EXIT_FAILURE;
123 }
124
125 r0_prev = r0;
126 r0 = screening_type1_equation_for_maximum(r0, n, lambda, p, k);
127 } while (fabs(r0 - r0_prev) > tol);
128
129 /*
130 * envelope function for the integrand
131 */
132 *screened_value =
133 sqrt(M_PI / p) * pow(r0, n) *
134 libgrpp_modified_bessel_scaled(lambda, k * r0) *
135 exp(-p * r0 * r0 - alpha_A * CA_2 - alpha_B * CB_2 + k * r0) * 0.5 *
136 (1 + erf(sqrt(p) * r0));
137
138 return EXIT_SUCCESS;
139}
140
141/**
142 * ratio of two modified scaled Bessel functions guarded against divide by zero
143 */
144static double modified_bessel_scaled_ratio(int n, double x) {
145 double numerator, denominator;
146 if (n == 0) {
147 numerator = libgrpp_modified_bessel_scaled(1, x);
148 denominator = libgrpp_modified_bessel_scaled(0, x);
149 } else {
150 numerator = libgrpp_modified_bessel_scaled(n - 1, x);
151 denominator = libgrpp_modified_bessel_scaled(n, x);
152 }
153 if (denominator == 0.0) {
154 return (2 * n + 1) / x; // asymptote for x->0
155 } else {
156 return numerator / denominator;
157 }
158}
159
160/**
161 * transcendental equation for finding maximum of the type 1 integrand
162 */
163static double screening_type1_equation_for_maximum(double r, int n, int lambda,
164 double p, double k) {
165 double k_r = k * r;
166 double K_ratio = modified_bessel_scaled_ratio(lambda, k_r);
167 double a = n + K_ratio * k_r;
168 if (lambda > 0) {
169 a = a - lambda - 1;
170 }
171
172 return sqrt(a / (2.0 * p));
173}
174
175/**
176 * screening for the type 2 radial integrals
177 * for the pair of contracted gaussian functions.
178 */
179int libgrpp_screening_radial_type2(int lambda1, int lambda2, int n, double CA_2,
180 double CB_2, libgrpp_shell_t *bra,
181 libgrpp_shell_t *ket,
182 libgrpp_potential_t *potential,
183 double *screened_value) {
184 *screened_value = 0.0;
185
186 double CA = sqrt(CA_2);
187 double CB = sqrt(CB_2);
188
189 /*
190 * loop over 'bra' contracted function
191 */
192 for (int i = 0; i < bra->num_primitives; i++) {
193 double alpha_A = bra->alpha[i];
194 double coef_i = bra->coeffs[i];
195 double k1 = 2 * alpha_A * CA;
196
197 /*
198 * loop over 'ket' contracted function
199 */
200 for (int j = 0; j < ket->num_primitives; j++) {
201 double alpha_B = ket->alpha[j];
202 double coef_j = ket->coeffs[j];
203 double k2 = 2 * alpha_B * CB;
204
205 /*
206 * loop over RPP primitives
207 */
208 for (int k = 0; k < potential->num_primitives; k++) {
209 double eta = potential->alpha[k];
210 int ni = n + potential->powers[k];
211 double coef_k = potential->coeffs[k];
212
213 double val_ijk = 0.0;
215 lambda1, lambda2, ni, CA_2, CB_2, alpha_A, alpha_B, k1, k2, eta,
216 &val_ijk);
217 if (err_code == EXIT_FAILURE) {
218 return EXIT_FAILURE;
219 }
220
221 *screened_value += coef_i * coef_j * coef_k * val_ijk;
222 }
223 }
224 }
225
226 return EXIT_SUCCESS;
227}
228
229/**
230 * Analytically evaluates Gaussian integral:
231 * \int_0^\infty r^n e^(-a r^2) dr
232 */
233double libgrpp_gaussian_integral(int n, double a) {
234 if (n % 2 == 0) {
235 int k = n / 2;
236 return libgrpp_double_factorial(2 * k - 1) / (pow(2.0, k + 1) * pow(a, k)) *
237 sqrt(M_PI / a);
238 } else {
239 int k = (n - 1) / 2;
240 return libgrpp_factorial(k) / (2.0 * pow(a, k + 1));
241 }
242}
243
244/**
245 * screening for the type 2 radial integrals
246 * for the pair of primitive gaussian functions.
247 */
249 int lambda1, int lambda2, int n, double CA_2, double CB_2, double alpha_A,
250 double alpha_B, double k1, double k2, double eta, double *screened_value) {
251 *screened_value = 0.0;
252
253 if (lambda1 >= 1 && fabs(k1) <= LIBGRPP_ZERO_THRESH) {
254 return EXIT_SUCCESS;
255 }
256 if (lambda2 >= 1 && fabs(k2) <= LIBGRPP_ZERO_THRESH) {
257 return EXIT_SUCCESS;
258 }
259
260 double p = alpha_A + alpha_B + eta;
261 double CA = sqrt(CA_2);
262 double CB = sqrt(CB_2);
263
264 /*
265 * special case:
266 * lambda1 = lambda2 = 0,
267 * k1 = k2 = 0.
268 * => M_0(0) = 1
269 * => we have one-center integral which can be evaluated analytically
270 */
271 if (lambda1 == 0 && lambda2 == 0) {
272 if (fabs(k1) <= LIBGRPP_ZERO_THRESH && fabs(k2) <= LIBGRPP_ZERO_THRESH) {
273 *screened_value = exp(-alpha_A * CA * CA - alpha_B * CB * CB) *
275 return EXIT_SUCCESS;
276 }
277 }
278
279 /*
280 * find position of the maximum of the integrand
281 */
282 const double tol = 1e-2;
283 double r0 = (alpha_A * CA + alpha_B * CB) / p;
284 double r0_prev = 0.0;
285 int nsteps = 0;
286
287 do {
288 nsteps++;
289 if (nsteps == 5) {
290 *screened_value = 0.0;
291 return EXIT_FAILURE;
292 }
293 r0_prev = r0;
294 r0 = screening_type2_equation_for_maximum(r0, n, lambda1, lambda2, p, k1,
295 k2);
296 } while (fabs(r0 - r0_prev) > tol);
297
298 /*
299 * envelope function for the integrand
300 */
301 *screened_value = sqrt(M_PI / p) * pow(r0, n) *
302 libgrpp_modified_bessel_scaled(lambda1, k1 * r0) *
303 libgrpp_modified_bessel_scaled(lambda2, k2 * r0) *
304 exp(-eta * r0 * r0 - alpha_A * (r0 - CA) * (r0 - CA) -
305 alpha_B * (r0 - CB) * (r0 - CB)) *
306 0.5 * (1 + erf(sqrt(p) * r0));
307
308 return EXIT_SUCCESS;
309}
310
311/**
312 * transcendental equation for finding maximum of the type 2 integrand
313 */
314static double screening_type2_equation_for_maximum(double r, int n, int lambda1,
315 int lambda2, double p,
316 double k1, double k2) {
317 double k1_r = k1 * r;
318 double K1_ratio = modified_bessel_scaled_ratio(lambda1, k1_r);
319
320 double k2_r = k2 * r;
321 double K2_ratio = modified_bessel_scaled_ratio(lambda2, k2_r);
322
323 double a = K1_ratio * k1_r + K2_ratio * k2_r + n;
324
325 if (lambda1 > 0) {
326 a = a - lambda1 - 1;
327 }
328 if (lambda2 > 0) {
329 a = a - lambda2 - 1;
330 }
331
332 return sqrt(a / (2.0 * p));
333}
static void const int const int i
double libgrpp_factorial(int n)
double libgrpp_double_factorial(int n)
double libgrpp_gaussian_integral(int n, double a)
int libgrpp_screening_radial_type2(int lambda1, int lambda2, int n, double CA_2, double CB_2, libgrpp_shell_t *bra, libgrpp_shell_t *ket, libgrpp_potential_t *potential, double *screened_value)
static int screening_radial_type1_integral_primitive(int lambda, int n, double CA_2, double CB_2, double alpha_A, double alpha_B, double k, double eta, double *screened_value)
int libgrpp_screening_radial_type1(int lambda, int n, double CA_2, double CB_2, double alpha_A, double alpha_B, double k, double prefactor, libgrpp_potential_t *potential, double *screened_value)
static double screening_type2_equation_for_maximum(double r, int n, int lambda1, int lambda2, double p, double k1, double k2)
static double modified_bessel_scaled_ratio(int n, double x)
static double screening_type1_equation_for_maximum(double r, int n, int lambda, double p, double k)
#define M_PI
static int screening_radial_type2_integral_primitive(int lambda1, int lambda2, int n, double CA_2, double CB_2, double alpha_A, double alpha_B, double k1, double k2, double eta, double *screened_value)
double libgrpp_modified_bessel_scaled(int n, double x)
#define LIBGRPP_ZERO_THRESH