(git:ed6f26b)
Loading...
Searching...
No Matches
grpp_nuclear_attraction.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 * Calculation of nuclear attraction integrals.
17 *
18 * For the point charge nuclear model the recursive Obara-Saika scheme is used
19 * to calculate nuclear attraction integrals. For details, see
20 * T. Helgaker, P. Jorgensen, J. Olsen, Molecular Electronic-Structure Theory,
21 * John Wiley & Sons Ltd, 2000.
22 * Chapter 9.10.1, "The Obara-Saika scheme for one-electron Coulomb integrals"
23 *
24 * For the other three models,
25 * - uniformly charged ball
26 * - Gaussian nucleus
27 * - Fermi nucleus,
28 * the scheme is actually the same as for the type 1 (radially-local) ECP
29 * integrals. Electrostatic potential V(r) induced by the finite nuclear charge
30 * distribution is integrated numerically on a radial grid.
31 */
32
33#include <assert.h>
34#include <math.h>
35#include <stdio.h>
36#include <stdlib.h>
37#include <string.h>
38
39#include "grpp_norm_gaussian.h"
40#include "grpp_nuclear_models.h"
41#include "grpp_utils.h"
42#include "libgrpp.h"
43
44#ifndef M_PI
45#define M_PI 3.14159265358979323846
46#endif
47
49 double *A, int n_cart_A, int *cart_list_A, double alpha_A, double *B,
50 int n_cart_B, int *cart_list_B, double alpha_B, double *C,
51 double (*potential)(double r, void *params), void *potential_params,
52 double *matrix);
53
55 libgrpp_shell_t *shell_A, double alpha_A, libgrpp_shell_t *shell_B,
56 double alpha_B, double *rpp_origin, double rpp_alpha, double *rpp_matrix);
57
58static double wrapper_coulomb_potential_point(double r, void *params);
59
60static double wrapper_coulomb_potential_ball(double r, void *params);
61
62static double wrapper_coulomb_potential_gaussian(double r, void *params);
63
64static double wrapper_coulomb_potential_fermi(double r, void *params);
65
66static double wrapper_coulomb_potential_fermi_bubble(double r, void *params);
67
68/**
69 * Calculates nuclear attraction integral between two shells
70 * represented by contracted Gaussian functions.
71 *
72 * nuclear model should be one of:
73 * LIBGRPP_NUCLEAR_MODEL_POINT_CHARGE
74 * LIBGRPP_NUCLEAR_MODEL_CHARGED_BALL
75 * LIBGRPP_NUCLEAR_MODEL_GAUSSIAN
76 * LIBGRPP_NUCLEAR_MODEL_FERMI
77 * LIBGRPP_NUCLEAR_MODEL_FERMI_BUBBLE
78 * LIBGRPP_NUCLEAR_MODEL_POINT_CHARGE_NUMERICAL
79 */
81 libgrpp_shell_t *shell_B,
82 double *charge_origin, int charge,
83 int nuclear_model,
84 double *model_params,
85 double *coulomb_matrix) {
86 assert(libgrpp_is_initialized());
87
88 int size_A = libgrpp_get_shell_size(shell_A);
89 int size_B = libgrpp_get_shell_size(shell_B);
90
91 double *buf = calloc(size_A * size_B, sizeof(double));
92
93 memset(coulomb_matrix, 0, size_A * size_B * sizeof(double));
94
95 // loop over primitives in contractions
96 for (int i = 0; i < shell_A->num_primitives; i++) {
97 double coef_A_i = shell_A->coeffs[i];
98
99 for (int j = 0; j < shell_B->num_primitives; j++) {
100 double coef_B_j = shell_B->coeffs[j];
101
102 if (fabs(coef_A_i * coef_B_j) < 1e-13) {
103 continue;
104 }
105
106 if (nuclear_model == LIBGRPP_NUCLEAR_MODEL_POINT_CHARGE) {
107
108 // use code for RPP type-1 integrals with RPP exponent = 0.0
110 shell_A, shell_A->alpha[i], shell_B, shell_B->alpha[j],
111 charge_origin, 0.0, buf);
112
113 for (int k = 0; k < size_A * size_B; k++) {
114 buf[k] *= (-1) * charge;
115 }
116 } else if (nuclear_model == LIBGRPP_NUCLEAR_MODEL_CHARGED_BALL ||
117 nuclear_model == LIBGRPP_NUCLEAR_MODEL_GAUSSIAN ||
118 nuclear_model == LIBGRPP_NUCLEAR_MODEL_FERMI ||
119 nuclear_model == LIBGRPP_NUCLEAR_MODEL_FERMI_BUBBLE ||
120 nuclear_model ==
122
123 double params[10];
124 params[0] = charge;
125
126 /*
127 * choose nuclear model
128 */
129 double (*electrostatic_potential_fun)(double, void *) = NULL;
130
132 // printf("charge distribution: point\n");
133 electrostatic_potential_fun = wrapper_coulomb_potential_point;
134 } else if (nuclear_model == LIBGRPP_NUCLEAR_MODEL_CHARGED_BALL) {
135 params[1] = model_params[0]; // R_rms
136 electrostatic_potential_fun = wrapper_coulomb_potential_ball;
137 } else if (nuclear_model == LIBGRPP_NUCLEAR_MODEL_GAUSSIAN) {
138 params[1] = model_params[0]; // R_rms
139 electrostatic_potential_fun = wrapper_coulomb_potential_gaussian;
140 } else if (nuclear_model == LIBGRPP_NUCLEAR_MODEL_FERMI) {
141 params[1] = model_params[0]; // c
142 params[2] = model_params[1]; // a
143 electrostatic_potential_fun = wrapper_coulomb_potential_fermi;
144 } else {
145 params[1] = model_params[0]; // c
146 params[2] = model_params[1]; // a
147 params[3] = model_params[2]; // k
148 electrostatic_potential_fun = wrapper_coulomb_potential_fermi_bubble;
149 }
150
151 /*
152 * calculate integrals for the shell pair
153 */
155 shell_A->origin, size_A, shell_A->cart_list, shell_A->alpha[i],
156 shell_B->origin, size_B, shell_B->cart_list, shell_B->alpha[j],
157 charge_origin, electrostatic_potential_fun, params, buf);
158 } else {
159 printf("LIBGRPP: unknown finite nuclear charge distribution model!\n");
160 exit(0);
161 }
162
163 libgrpp_daxpy(size_A * size_B, coef_A_i * coef_B_j, buf, coulomb_matrix);
164 }
165 }
166
167 free(buf);
168}
169
170/**
171 * Calculates nuclear attraction integral between two shells
172 * represented by contracted Gaussian functions for the electrostatic potential
173 * generated by the point charge.
174 */
176 libgrpp_shell_t *shell_B,
177 double *charge_origin,
178 int charge,
179 double *coulomb_matrix) {
180 libgrpp_nuclear_attraction_integrals(shell_A, shell_B, charge_origin, charge,
182 coulomb_matrix);
183}
184
185/**
186 * Calculates nuclear attraction integral between two shells
187 * represented by contracted Gaussian functions for the electrostatic potential
188 * generated by the charged ball.
189 *
190 * r_rms stands for the root mean square radius (in bohrs)
191 */
193 libgrpp_shell_t *shell_B,
194 double *charge_origin,
195 int charge, double r_rms,
196 double *coulomb_matrix) {
197 double params[10];
198 params[0] = charge;
199 params[1] = r_rms;
200
201 libgrpp_nuclear_attraction_integrals(shell_A, shell_B, charge_origin, charge,
203 params, coulomb_matrix);
204}
205
206/**
207 * Calculates nuclear attraction integral between two shells
208 * represented by contracted Gaussian functions for the electrostatic potential
209 * generated by the Gaussian distribution.
210 *
211 * r_rms stands for the root mean square radius (in bohrs)
212 */
214 libgrpp_shell_t *shell_A, libgrpp_shell_t *shell_B, double *charge_origin,
215 int charge, double r_rms, double *coulomb_matrix) {
216 double params[10];
217 params[0] = charge;
218 params[1] = r_rms;
219
220 libgrpp_nuclear_attraction_integrals(shell_A, shell_B, charge_origin, charge,
222 coulomb_matrix);
223}
224
225/**
226 * Calculates nuclear attraction integral between two shells
227 * represented by contracted Gaussian functions for the electrostatic potential
228 * generated by the Fermi distribution.
229 *
230 * Model parameters 'c' and 'a' must be given in bohrs.
231 */
233 libgrpp_shell_t *shell_A, libgrpp_shell_t *shell_B, double *charge_origin,
234 int charge, double fermi_param_c, double fermi_param_a,
235 double *coulomb_matrix) {
236 double params[10];
237 params[0] = charge;
238 params[1] = fermi_param_c;
239 params[2] = fermi_param_a;
240
241 libgrpp_nuclear_attraction_integrals(shell_A, shell_B, charge_origin, charge,
243 coulomb_matrix);
244}
245
246/**
247 * Calculates nuclear attraction integral between two shells
248 * represented by contracted Gaussian functions for the electrostatic potential
249 * generated by the "Fermi + bubble" distribution.
250 *
251 * Model parameters 'c' and 'a' must be given in bohrs.
252 * The 'k' constant is dimensionless.
253 */
255 libgrpp_shell_t *shell_A, libgrpp_shell_t *shell_B, double *charge_origin,
256 int charge, double param_c, double param_a, double param_k,
257 double *coulomb_matrix) {
258 double params[10];
259 params[0] = charge;
260 params[1] = param_c;
261 params[2] = param_a;
262 params[3] = param_k;
263
264 libgrpp_nuclear_attraction_integrals(shell_A, shell_B, charge_origin, charge,
266 params, coulomb_matrix);
267}
268
269/**
270 * wrappers for charge distribution functions.
271 * are used to provide a unified interface to radially-local potentials.
272 * the 'params' argument is unpacked, then the specific routines are invoked.
273 */
274
275static double wrapper_coulomb_potential_point(double r, void *params) {
276 double Z = ((double *)params)[0];
277
279}
280
281static double wrapper_coulomb_potential_ball(double r, void *params) {
282 double Z = ((double *)params)[0];
283 double R_rms = ((double *)params)[1];
284
285 return libgrpp_coulomb_potential_ball(r, Z, R_rms);
286}
287
288static double wrapper_coulomb_potential_gaussian(double r, void *params) {
289 double Z = ((double *)params)[0];
290 double R_rms = ((double *)params)[1];
291
292 return libgrpp_coulomb_potential_gaussian(r, Z, R_rms);
293}
294
295static double wrapper_coulomb_potential_fermi(double r, void *params) {
296 double Z = ((double *)params)[0];
297 double c = ((double *)params)[1];
298 double a = ((double *)params)[2];
299
300 return libgrpp_coulomb_potential_fermi(r, Z, c, a);
301}
302
303static double wrapper_coulomb_potential_fermi_bubble(double r, void *params) {
304 double Z = ((double *)params)[0];
305 double c = ((double *)params)[1];
306 double a = ((double *)params)[2];
307 double k = ((double *)params)[3];
308
309 return libgrpp_coulomb_potential_fermi_bubble(r, Z, c, a, k);
310}
static void const int const int i
int libgrpp_is_initialized()
void libgrpp_nuclear_attraction_integrals_fermi_bubble_model(libgrpp_shell_t *shell_A, libgrpp_shell_t *shell_B, double *charge_origin, int charge, double param_c, double param_a, double param_k, double *coulomb_matrix)
void libgrpp_nuclear_attraction_integrals_point_charge(libgrpp_shell_t *shell_A, libgrpp_shell_t *shell_B, double *charge_origin, int charge, double *coulomb_matrix)
static double wrapper_coulomb_potential_point(double r, void *params)
void libgrpp_nuclear_attraction_integrals_gaussian_model(libgrpp_shell_t *shell_A, libgrpp_shell_t *shell_B, double *charge_origin, int charge, double r_rms, double *coulomb_matrix)
void libgrpp_evaluate_radially_local_potential_integral_primitive_gaussians(double *A, int n_cart_A, int *cart_list_A, double alpha_A, double *B, int n_cart_B, int *cart_list_B, double alpha_B, double *C, double(*potential)(double r, void *params), void *potential_params, double *matrix)
void libgrpp_nuclear_attraction_integrals(libgrpp_shell_t *shell_A, libgrpp_shell_t *shell_B, double *charge_origin, int charge, int nuclear_model, double *model_params, double *coulomb_matrix)
static double wrapper_coulomb_potential_fermi_bubble(double r, void *params)
static double wrapper_coulomb_potential_gaussian(double r, void *params)
void libgrpp_evaluate_rpp_type1_mmd_n1_primitive_shell_pair(libgrpp_shell_t *shell_A, double alpha_A, libgrpp_shell_t *shell_B, double alpha_B, double *rpp_origin, double rpp_alpha, double *rpp_matrix)
void libgrpp_nuclear_attraction_integrals_fermi_model(libgrpp_shell_t *shell_A, libgrpp_shell_t *shell_B, double *charge_origin, int charge, double fermi_param_c, double fermi_param_a, double *coulomb_matrix)
static double wrapper_coulomb_potential_ball(double r, void *params)
void libgrpp_nuclear_attraction_integrals_charged_ball(libgrpp_shell_t *shell_A, libgrpp_shell_t *shell_B, double *charge_origin, int charge, double r_rms, double *coulomb_matrix)
static double wrapper_coulomb_potential_fermi(double r, void *params)
double libgrpp_coulomb_potential_ball(double r, double Z, double R_rms)
double libgrpp_coulomb_potential_gaussian(double r, double Z, double R_rms)
double libgrpp_coulomb_potential_point(double r, double Z)
double libgrpp_coulomb_potential_fermi_bubble(double r, double Z, double c, double a, double k)
double libgrpp_coulomb_potential_fermi(double r, double Z, double c, double a)
int libgrpp_get_shell_size(libgrpp_shell_t *shell)
Definition grpp_shell.c:98
void libgrpp_daxpy(int n, double a, double *x, double *y)
Definition grpp_utils.c:46
@ LIBGRPP_NUCLEAR_MODEL_POINT_CHARGE
Definition libgrpp.h:156
@ LIBGRPP_NUCLEAR_MODEL_CHARGED_BALL
Definition libgrpp.h:157
@ LIBGRPP_NUCLEAR_MODEL_FERMI
Definition libgrpp.h:159
@ LIBGRPP_NUCLEAR_MODEL_FERMI_BUBBLE
Definition libgrpp.h:160
@ LIBGRPP_NUCLEAR_MODEL_POINT_CHARGE_NUMERICAL
Definition libgrpp.h:161
@ LIBGRPP_NUCLEAR_MODEL_GAUSSIAN
Definition libgrpp.h:158