(git:ed6f26b)
Loading...
Searching...
No Matches
grpp_type2_integrals.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#include <assert.h>
16#include <math.h>
17#include <string.h>
18#ifndef M_PI
19#define M_PI 3.14159265358979323846
20#endif
21
23#include "grpp_binomial.h"
26#include "grpp_utils.h"
27#include "libgrpp.h"
28
29#define LMAX (2 * LIBGRPP_MAX_BASIS_L + LIBGRPP_MAX_RPP_L)
30
31static double type2_angular_sum(int L, int lambda_1, int a, int b, int c,
32 int lambda_2, int d, int e, int f,
33 double *rsh_values_kA, double *rsh_values_kB);
34
35/**
36 * Evaluation of type 2 RPP integrals (scalar-relativistic semilocal RPP with
37 * L-projectors).
38 */
40 double *rpp_origin, libgrpp_potential_t *potential,
41 double *matrix) {
42 assert(libgrpp_is_initialized());
43
44 int size_A = libgrpp_get_shell_size(shell_A);
45 int size_B = libgrpp_get_shell_size(shell_B);
46
47 memset(matrix, 0, size_A * size_B * sizeof(double));
48
49 int L = potential->L;
50 int L_A =
51 shell_A->cart_list[0] + shell_A->cart_list[1] + shell_A->cart_list[2];
52 int L_B =
53 shell_B->cart_list[0] + shell_B->cart_list[1] + shell_B->cart_list[2];
54
55 double *A = shell_A->origin;
56 double *B = shell_B->origin;
57 double *C = rpp_origin;
58
59 double CA_x = C[0] - A[0];
60 double CA_y = C[1] - A[1];
61 double CA_z = C[2] - A[2];
62 double CB_x = C[0] - B[0];
63 double CB_y = C[1] - B[1];
64 double CB_z = C[2] - B[2];
65 double CA_2 = CA_x * CA_x + CA_y * CA_y + CA_z * CA_z;
66 double CB_2 = CB_x * CB_x + CB_y * CB_y + CB_z * CB_z;
67
68 double alpha_A = shell_A->alpha[0];
69 double alpha_B = shell_B->alpha[0];
70 double kA_x = -2.0 * (alpha_A * CA_x);
71 double kA_y = -2.0 * (alpha_A * CA_y);
72 double kA_z = -2.0 * (alpha_A * CA_z);
73 double kB_x = -2.0 * (alpha_B * CB_x);
74 double kB_y = -2.0 * (alpha_B * CB_y);
75 double kB_z = -2.0 * (alpha_B * CB_z);
76 double kA_vec[3];
77 kA_vec[0] = kA_x;
78 kA_vec[1] = kA_y;
79 kA_vec[2] = kA_z;
80 double kB_vec[3];
81 kB_vec[0] = kB_x;
82 kB_vec[1] = kB_y;
83 kB_vec[2] = kB_z;
84
85 int lambda1_max = L + L_A;
86 int lambda2_max = L + L_B;
87 int N_max = L_A + L_B;
88
89 /*
90 * for further evaluation of angular integrals
91 */
92 int lmax = int_max3(lambda1_max, lambda2_max, L);
93 // create_real_spherical_harmonic_coeffs_tables(lmax);
94
95 /*
96 * pre-compute type 2 radial integrals
97 */
99 lambda1_max, lambda2_max, N_max, CA_2, CB_2, potential, shell_A, shell_B);
100
101 /*
102 * pre-calculate values of real spherical harmonics for different L
103 */
104 double rsh_values_kA[3 * LMAX][6 * LMAX];
105 double rsh_values_kB[3 * LMAX][6 * LMAX];
106
107 for (int lambda = 0; lambda <= lmax; lambda++) {
109 rsh_values_kA[lambda]);
111 rsh_values_kB[lambda]);
112 }
113
114 /*
115 * main loop
116 * over shell pairs
117 */
118 for (int icart = 0; icart < size_A; icart++) {
119 for (int jcart = 0; jcart < size_B; jcart++) {
120
121 double gamma_AB = 0.0;
122
123 int n_A = shell_A->cart_list[3 * icart + 0];
124 int l_A = shell_A->cart_list[3 * icart + 1];
125 int m_A = shell_A->cart_list[3 * icart + 2];
126 int n_B = shell_B->cart_list[3 * jcart + 0];
127 int l_B = shell_B->cart_list[3 * jcart + 1];
128 int m_B = shell_B->cart_list[3 * jcart + 2];
129
130 for (int a = 0; a <= n_A; a++) {
131
132 double C_nA_a = libgrpp_binomial(n_A, a);
133 double pow_CA_x = pow(CA_x, n_A - a);
134
135 for (int b = 0; b <= l_A; b++) {
136
137 double C_lA_b = libgrpp_binomial(l_A, b);
138 double pow_CA_y = pow(CA_y, l_A - b);
139
140 for (int c = 0; c <= m_A; c++) {
141
142 double C_mA_c = libgrpp_binomial(m_A, c);
143 double pow_CA_z = pow(CA_z, m_A - c);
144
145 for (int d = 0; d <= n_B; d++) {
146
147 double C_nB_d = libgrpp_binomial(n_B, d);
148 double pow_CB_x = pow(CB_x, n_B - d);
149
150 for (int e = 0; e <= l_B; e++) {
151
152 double C_lB_e = libgrpp_binomial(l_B, e);
153 double pow_CB_y = pow(CB_y, l_B - e);
154
155 for (int f = 0; f <= m_B; f++) {
156
157 double C_mB_f = libgrpp_binomial(m_B, f);
158 double pow_CB_z = pow(CB_z, m_B - f);
159
160 double factor = C_nA_a * C_lA_b * C_mA_c * C_nB_d * C_lB_e *
161 C_mB_f * pow_CA_x * pow_CA_y * pow_CA_z *
162 pow_CB_x * pow_CB_y * pow_CB_z;
163
164 if (fabs(factor) < 1e-13) {
165 continue;
166 }
167
168 int N = a + b + c + d + e + f;
169 double sum_omega_Q = 0.0;
170
171 int lambda1_lower = int_max2(L - a - b - c, 0);
172 int lambda2_lower = int_max2(L - d - e - f, 0);
173 int lambda1_upper = L + a + b + c;
174 int lambda2_upper = L + d + e + f;
175
176 for (int lambda_1 = lambda1_lower; lambda_1 <= lambda1_upper;
177 lambda_1++) {
178 if ((L + a + b + c - lambda_1) % 2 != 0) {
179 continue;
180 }
181
182 for (int lambda_2 = lambda2_lower;
183 lambda_2 <= lambda2_upper; lambda_2++) {
184 if ((L + d + e + f - lambda_2) % 2 != 0) {
185 continue;
186 }
187
189 radial_table, lambda_1, lambda_2, N);
190 if (fabs(QN) < 1e-16) {
191 continue;
192 }
193
194 double sum_angular = type2_angular_sum(
195 L, lambda_1, a, b, c, lambda_2, d, e, f,
196 rsh_values_kA[lambda_1], rsh_values_kB[lambda_2]);
197
198 sum_omega_Q += QN * sum_angular;
199 } // loop over lambda_2
200 } // loop over lambda_1
201
202 gamma_AB += factor * sum_omega_Q;
203 }
204 }
205 }
206 }
207 }
208 }
209
210 gamma_AB *= 16 * M_PI * M_PI;
211
212 matrix[icart * size_B + jcart] = gamma_AB;
213 }
214 }
215
217}
218
219/*
220 * Sum of products of type 2 angular integrals
221 * (McMurchie, Davidson, 1981, formulas (23) and (24))
222 */
223static double type2_angular_sum(int L, int lambda_1, int a, int b, int c,
224 int lambda_2, int d, int e, int f,
225 double *rsh_values_kA, double *rsh_values_kB) {
226 double sum_angular = 0.0;
227
228 /*
229 * contract tensors with angular integrals
230 */
231 for (int m = -L; m <= L; m++) {
232 double omega_1 =
233 libgrpp_angular_type2_integral(lambda_1, L, m, a, b, c, rsh_values_kA);
234 if (fabs(omega_1) < 1e-16) {
235 continue;
236 }
237
238 double omega_2 =
239 libgrpp_angular_type2_integral(lambda_2, L, m, d, e, f, rsh_values_kB);
240
241 sum_angular += omega_1 * omega_2;
242 }
243
244 return sum_angular;
245}
double libgrpp_angular_type2_integral(const int lambda, const int L, const int m, const int a, const int b, const int c, const double *rsh_values)
uint64_t libgrpp_binomial(uint64_t n, uint64_t k)
int libgrpp_is_initialized()
void libgrpp_delete_radial_type2_integrals(radial_type2_table_t *table)
double libgrpp_get_radial_type2_integral(radial_type2_table_t *table, int lambda1, int lambda2, int n)
radial_type2_table_t * libgrpp_tabulate_radial_type2_integrals(int lambda1_max, int lambda2_max, int n_max, double CA_2, double CB_2, libgrpp_potential_t *potential, libgrpp_shell_t *bra, libgrpp_shell_t *ket)
int libgrpp_get_shell_size(libgrpp_shell_t *shell)
Definition grpp_shell.c:98
void libgrpp_evaluate_real_spherical_harmonics_array(const int l, const double *k, double *rsh_array)
#define LMAX
static double type2_angular_sum(int L, int lambda_1, int a, int b, int c, int lambda_2, int d, int e, int f, double *rsh_values_kA, double *rsh_values_kB)
#define M_PI
void libgrpp_type2_integrals(libgrpp_shell_t *shell_A, libgrpp_shell_t *shell_B, double *rpp_origin, libgrpp_potential_t *potential, double *matrix)
int int_max3(int x, int y, int z)
Definition grpp_utils.c:21
int int_max2(int x, int y)
Definition grpp_utils.c:19