(git:ed6f26b)
Loading...
Searching...
No Matches
grpp_radial_type1_integral.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 * Evaluation of type 1 radial integrals.
17 *
18 * The procedure in general follows that described in:
19 * R. Flores-Moreno et al. Half-numerical evaluation of pseudopotential
20 integrals.
21 * J. Comp. Chem. 27, 1009 (2006)
22 * (see formulas (12) and (13) for radial integrals invoking contracted Gaussian
23 functions and RPPs).
24
25 * In contrast to type 2 integrals, the special case of type 1 integrals Bessel
26 functions
27 * cannot be factorized, and one cannot use contracted Gaussians directly
28 * (and we have to use primitive Gaussians instead).
29 * However, the RPP radial function still can be used as a whole in the
30 integrand.
31 *
32 * The Log3 integration scheme used here is detailed in:
33 * C.-K. Skylaris et al. An efficient method for calculating effective core
34 potential integrals
35 * which involve projection operators.
36 * Chem. Phys. Lett. 296, 445 (1998)
37 */
38#include <math.h>
39#include <stdlib.h>
40#ifndef M_PI
41#define M_PI 3.14159265358979323846
42#endif
43
45#include "libgrpp.h"
46
47#include "grpp_specfunc.h"
48#include "grpp_utils.h"
49
50#define MIN_GRID 2047
51#define MAX_GRID 10000
52
53typedef struct {
54 double k;
55 double alpha_A;
56 double alpha_B;
57 double CA_2;
58 double CB_2;
59 double prefactor;
60 double (*potential)(double r, void *params);
63
64typedef struct {
65 int nr;
66 int n_max;
68 double *r;
69 double *w;
70 double *pot_values;
71 double *gto_values;
72 double **r_N;
73 double **mod_bessel;
76
78create_radial_type1_grid(int lambda_max, int n_max,
79 radial_type1_params_t *params);
80
82
84
86 int lambda, double tolerance,
87 int *converged);
88
90 int lambda_max, int n_max, double CA_2, double CB_2, double alpha_A,
91 double alpha_B, double k, double prefactor,
92 double (*potential)(double r, void *params), void *potential_params) {
94 double const tolerance = libgrpp_params.radial_tolerance;
95
96 table = (radial_type1_table_t *)calloc(1, sizeof(radial_type1_table_t));
97 table->lambda_max = lambda_max;
98 table->n_max = n_max;
99 table->radial_integrals =
100 (double *)calloc((lambda_max + 1) * (n_max + 1), sizeof(double));
101
103 params.CA_2 = CA_2;
104 params.CB_2 = CB_2;
105 params.alpha_A = alpha_A;
106 params.alpha_B = alpha_B;
107 params.k = k;
108 params.prefactor = prefactor;
109 params.potential = potential;
110 params.potential_params = potential_params;
111
113 create_radial_type1_grid(lambda_max, n_max, &params);
114
115 for (int lambda = 0; lambda <= lambda_max; lambda++) {
116 for (int n = 0; n <= n_max; n++) {
117
118 int converged;
119 double Q = calculate_radial_type1_integral(grid, n, lambda, tolerance,
120 &converged);
121
122 table->radial_integrals[lambda * (lambda_max + 1) + n] = Q;
123 }
124 }
125
127
128 return table;
129}
130
132 free(table->radial_integrals);
133 free(table);
134}
135
137 int lambda, int n) {
138 int lambda_max = table->lambda_max;
139 return table->radial_integrals[lambda * (lambda_max + 1) + n];
140}
141
142static double radial_type1_integrand_fun(double r,
143 radial_type1_params_t *params) {
144 double alpha_A = params->alpha_A;
145 double alpha_B = params->alpha_B;
146 double k = params->k;
147 double CA_2 = params->CA_2;
148 double CB_2 = params->CB_2;
149 double prefactor = params->prefactor;
150
151 double power = k * r - (alpha_A + alpha_B) * r * r - alpha_A * CA_2 -
152 alpha_B * CB_2; // + N * log(r);
153
154 return prefactor * exp(power);
155}
156
157static radial_type1_grid_t *
158create_radial_type1_grid(int lambda_max, int n_max,
159 radial_type1_params_t *params) {
161 (radial_type1_grid_t *)calloc(1, sizeof(radial_type1_grid_t));
162
163 grid->nr = MIN_GRID;
164 grid->n_max = n_max;
165 grid->lambda_max = lambda_max;
166 grid->params = params;
167
168 grid->r = (double *)calloc(MAX_GRID, sizeof(double));
169 grid->w = (double *)calloc(MAX_GRID, sizeof(double));
170 grid->pot_values = (double *)calloc(MAX_GRID, sizeof(double));
171 grid->gto_values = (double *)calloc(MAX_GRID, sizeof(double));
172 grid->r_N = alloc_zeros_2d(n_max + 1, MAX_GRID);
173 grid->mod_bessel = alloc_zeros_2d(lambda_max + 1, MAX_GRID);
174
175 // initial set of pre-calculated points
176 int nr = grid->nr;
177 const double R = 5.0;
178 const double R3 = R * R * R;
179
180 for (int i = 1; i <= nr; i++) {
181 double xi = i / (nr + 1.0);
182 double xi3 = xi * xi * xi;
183 double ln_xi = log(1 - xi3);
184 double wi = 3 * R3 * xi * xi * ln_xi * ln_xi / ((1 - xi3) * (nr + 1.0));
185 double ri = -R * ln_xi;
186
187 grid->r[i - 1] = ri;
188 grid->w[i - 1] = wi;
189 grid->pot_values[i - 1] = params->potential(ri, params->potential_params);
190 grid->gto_values[i - 1] = radial_type1_integrand_fun(ri, params);
191
192 for (int lambda = 0; lambda <= lambda_max; lambda++) {
193 grid->mod_bessel[lambda][i - 1] =
194 libgrpp_modified_bessel_scaled(lambda, ri * params->k);
195 }
196
197 for (int n = 0; n <= n_max; n++) {
198 grid->r_N[n][i - 1] = pow(ri, n);
199 }
200 }
201
202 return grid;
203}
204
206 free(grid->r);
207 free(grid->w);
208 free(grid->pot_values);
209 free(grid->gto_values);
210 free_2d(grid->r_N, grid->n_max + 1);
211 free_2d(grid->mod_bessel, grid->lambda_max + 1);
212 free(grid);
213}
214
216 const double R = 5.0;
217 const double R3 = R * R * R;
218
219 if (nr > MAX_GRID) {
220 return;
221 }
222
223 if (nr <= grid->nr) { // nothing to do
224 return;
225 }
226
227 int idx = grid->nr;
228 for (int i = 1; i <= nr; i += 2) {
229 double xi = i / (nr + 1.0);
230 double xi3 = xi * xi * xi;
231 double ln_xi = log(1 - xi3);
232 double wi = 3 * R3 * xi * xi * ln_xi * ln_xi / ((1 - xi3) * (nr + 1.0));
233 double ri = -R * ln_xi;
234
235 grid->r[idx] = ri;
236 grid->w[idx] = wi;
237 grid->pot_values[idx] =
238 grid->params->potential(ri, grid->params->potential_params);
239 grid->gto_values[idx] = radial_type1_integrand_fun(ri, grid->params);
240
241 for (int lambda = 0; lambda <= grid->lambda_max; lambda++) {
242 double kr = grid->params->k * ri;
243 double bessel = libgrpp_modified_bessel_scaled(lambda, kr);
244 grid->mod_bessel[lambda][idx] = bessel;
245 }
246
247 for (int n = 0; n <= grid->n_max; n++) {
248 grid->r_N[n][idx] = pow(ri, n);
249 }
250 idx++;
251 }
252
253 grid->nr = nr;
254}
255
257 int lambda, double tolerance,
258 int *converged) {
259 int nr = MIN_GRID;
260
261 *converged = 0;
262 double prev_sum = 0.0;
263 double sum = 0.0;
264
265 double *w = grid->w;
266 // double *r = grid->r;
267 double *pot_values = grid->pot_values;
268 double *gto_values = grid->gto_values;
269 double *r_N = grid->r_N[n];
270 double *mod_bessel = grid->mod_bessel[lambda];
271
272 /*
273 * first step: screening of an integral
274 */
275 /*double screened = 0.0;
276 int screened_success = screening_radial_type1(
277 lambda,
278 n,
279 grid->params->CA_2,
280 grid->params->CB_2,
281 grid->params->alpha_A,
282 grid->params->alpha_B,
283 grid->params->k,
284 grid->params->prefactor,
285 grid->params->potential_params,
286 &screened
287 );
288
289 if (screened_success == EXIT_SUCCESS && fabs(screened) < tolerance) {
290 *converged = 1;
291 return screened;
292 }*/
293
294 /*
295 * second step: calculation on the smallest possible grid
296 */
297 for (int i = 0; i < nr; i++) {
298 sum += w[i] * pot_values[i] * gto_values[i] * r_N[i] * mod_bessel[i];
299 }
300
301 /*
302 * third step: adaptive integration, refinement of the result
303 */
304 do {
305 int idx = nr;
306 nr = 2 * nr + 1;
307
308 if (nr > MAX_GRID) {
309 break;
310 }
311
312 prev_sum = sum;
313 sum = 0.5 * sum;
314
316
317 for (int i = idx; i < nr; i++) {
318 sum += w[i] * pot_values[i] * gto_values[i] * r_N[i] * mod_bessel[i];
319 }
320
321 /*if (screened_success == EXIT_SUCCESS && (fabs(sum) / fabs(screened) <
322 0.001)) { *converged = 0; continue;
323 }*/
324
325 *converged = fabs(sum - prev_sum) <= tolerance;
326
327 } while (!(*converged));
328
329 return sum;
330}
static GRID_HOST_DEVICE int idx(const orbital a)
Return coset index of given orbital angular momentum.
static void const int const int const int const int const int const double const int const int const int int GRID_CONST_WHEN_COLLOCATE double GRID_CONST_WHEN_INTEGRATE double * grid
static void const int const int i
libgrpp_parameters_t libgrpp_params
double libgrpp_get_radial_type1_integral(radial_type1_table_t *table, int lambda, int n)
static void delete_radial_type1_grid(radial_type1_grid_t *grid)
static double calculate_radial_type1_integral(radial_type1_grid_t *grid, int n, int lambda, double tolerance, int *converged)
static radial_type1_grid_t * create_radial_type1_grid(int lambda_max, int n_max, radial_type1_params_t *params)
radial_type1_table_t * libgrpp_tabulate_radial_type1_integrals(int lambda_max, int n_max, double CA_2, double CB_2, double alpha_A, double alpha_B, double k, double prefactor, double(*potential)(double r, void *params), void *potential_params)
static double radial_type1_integrand_fun(double r, radial_type1_params_t *params)
static void expand_radial_type1_grid(radial_type1_grid_t *grid, int nr)
#define MAX_GRID
#define MIN_GRID
void libgrpp_delete_radial_type1_integrals(radial_type1_table_t *table)
double libgrpp_modified_bessel_scaled(int n, double x)
void free_2d(double **array, int n)
Definition grpp_utils.c:35
double ** alloc_zeros_2d(int n, int m)
Definition grpp_utils.c:25
radial_type1_params_t * params
double(* potential)(double r, void *params)