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 : * Differentiation of contracted Gaussian functions.
17 : * Derivatives are then used to calculate analytic gradients of 1-el integrals.
18 : */
19 : #include <math.h>
20 : #include <stdlib.h>
21 :
22 : #ifndef M_PI
23 : #define M_PI 3.14159265358979323846
24 : #endif
25 :
26 : #include "grpp_diff_gaussian.h"
27 :
28 : #include "libgrpp.h"
29 :
30 : static double norm_factor(double alpha, int L);
31 :
32 : /**
33 : * Performs differentiation of a contracted Gaussian.
34 : *
35 : * Note that the "2 alpha" factors are absorbed into coefficients, while the 'n'
36 : * factor is not. The latter must be accounted for explicitly at the stage of
37 : * gradient construction. For more details, see: T. Helgaker, P. Jorgensen, J.
38 : * Olsen, Molecular Electronic-Structure Theory, John Wiley & Sons Ltd, 2000.
39 : * Chapter 9.2.2, "Recurrence relations for Cartesian Gaussians"
40 : *
41 : */
42 0 : void libgrpp_differentiate_shell(libgrpp_shell_t *shell,
43 : libgrpp_shell_t **shell_minus,
44 : libgrpp_shell_t **shell_plus) {
45 : // downwards
46 0 : if (shell->L > 0) {
47 0 : *shell_minus =
48 0 : libgrpp_new_shell(shell->origin, shell->L - 1, shell->num_primitives,
49 : shell->coeffs, shell->alpha);
50 :
51 0 : for (int i = 0; i < shell->num_primitives; i++) {
52 :
53 0 : double alpha = shell->alpha[i];
54 0 : double L = shell->L;
55 :
56 0 : (*shell_minus)->coeffs[i] *=
57 0 : norm_factor(alpha, L) / norm_factor(alpha, L - 1);
58 : }
59 : } else {
60 0 : *shell_minus = NULL;
61 : }
62 :
63 : // upwards
64 0 : *shell_plus =
65 0 : libgrpp_new_shell(shell->origin, shell->L + 1, shell->num_primitives,
66 : shell->coeffs, shell->alpha);
67 0 : for (int i = 0; i < shell->num_primitives; i++) {
68 :
69 0 : double alpha = shell->alpha[i];
70 0 : double L = shell->L;
71 :
72 0 : (*shell_plus)->coeffs[i] *=
73 0 : 2.0 * alpha * norm_factor(alpha, L) / norm_factor(alpha, L + 1);
74 : }
75 0 : }
76 :
77 : /**
78 : * Calculates normalization factor for the primitive Gaussian
79 : * with the exponential parameter 'alpha' and angular momentum L.
80 : */
81 0 : static double norm_factor(double alpha, int L) {
82 0 : return pow(2 * alpha / M_PI, 0.75) * pow(4 * alpha, 0.5 * L);
83 : }
|