(git:ed6f26b)
Loading...
Searching...
No Matches
grpp_angular_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/*
16 * This file contains subroutines for evaluation of angular integrals of the 1st
17 * and 2nd type. It also contains functions for construction of matrices of the
18 * angular momentum operator in the bases of either real or complex spherical
19 * harmonics.
20 *
21 * For more details on the angular integrals used in RPP integration, see:
22 *
23 * L. E. McMurchie, E. R. Davidson. Calculation of integrals over ab initio
24 * pseudopotentials. J. Comput. Phys. 44(2), 289 (1981).
25 * doi: 10.1016/0021-9991(81)90053-x
26 */
27
28#include <math.h>
29
30#ifndef M_PI
31#define M_PI 3.14159265358979323846
32#endif
33
35#include "grpp_factorial.h"
37#include "libgrpp.h"
38
39static double integrate_unitary_sphere_polynomial(int i, int j, int k);
40
41/**
42 * Type 1 angular integral.
43 * (see MrMurchie & Davidson, formula (28))
44 */
45double libgrpp_angular_type1_integral(int lambda, int II, int JJ, int KK,
46 double *k) {
47 double sum = 0.0;
48
49 for (int mu = -lambda; mu <= lambda; mu++) {
50 double sum2 = 0.0;
51 for (int r = 0; r <= lambda; r++) {
52 for (int s = 0; s <= lambda; s++) {
53 for (int t = 0; t <= lambda; t++) {
54 if (r + s + t == lambda) {
55 double y_lm_rst =
57 double usp_int =
58 integrate_unitary_sphere_polynomial(II + r, JJ + s, KK + t);
59 sum2 += y_lm_rst * usp_int;
60 }
61 }
62 }
63 }
64 sum += sum2 * libgrpp_evaluate_real_spherical_harmonic(lambda, mu, k);
65 }
66
67 return sum;
68}
69
70/**
71 * Type 2 angular integral.
72 * (see MrMurchie & Davidson, formula (29))
73 */
74double libgrpp_angular_type2_integral(const int lambda, const int L,
75 const int m, const int a, const int b,
76 const int c, const double *rsh_values) {
77 double sum = 0.0;
78
79 rsh_coef_table_t *rsh_coef_lambda =
82
83 int ncomb_rst = rsh_coef_lambda->n_cart_comb;
84 int ncomb_uvw = rsh_coef_L->n_cart_comb;
85
86 for (int mu = -lambda; mu <= lambda; mu++) {
87 double sum2 = 0.0;
88 double rsh_value_k = rsh_values[mu + lambda];
89 if (fabs(rsh_value_k) < LIBGRPP_ZERO_THRESH) {
90 continue;
91 }
92
93 for (int icomb_uvw = 0; icomb_uvw < ncomb_uvw; icomb_uvw++) {
94
95 int u = rsh_coef_L->cartesian_comb[3 * icomb_uvw];
96 int v = rsh_coef_L->cartesian_comb[3 * icomb_uvw + 1];
97 int w = rsh_coef_L->cartesian_comb[3 * icomb_uvw + 2];
98 double y_lm_uvw = rsh_coef_L->coeffs[(m + L) * ncomb_uvw + icomb_uvw];
99 if (fabs(y_lm_uvw) < LIBGRPP_ZERO_THRESH) {
100 continue;
101 }
102
103 for (int icomb_rst = 0; icomb_rst < ncomb_rst; icomb_rst++) {
104
105 int r = rsh_coef_lambda->cartesian_comb[3 * icomb_rst];
106 int s = rsh_coef_lambda->cartesian_comb[3 * icomb_rst + 1];
107 int t = rsh_coef_lambda->cartesian_comb[3 * icomb_rst + 2];
108 double y_lam_mu_rst =
109 rsh_coef_lambda->coeffs[(mu + lambda) * ncomb_rst + icomb_rst];
110 if (fabs(y_lam_mu_rst) < LIBGRPP_ZERO_THRESH) {
111 continue;
112 }
113
115 a + r + u, b + s + v, c + t + w);
116
117 sum2 += y_lam_mu_rst * y_lm_uvw * usp_int;
118 }
119 }
120
121 sum += sum2 * rsh_value_k;
122 }
123
124 return sum;
125}
126
127/**
128 * Integral of the unitary sphere polynomial over full solid angle.
129 * (see MrMurchie & Davidson, formula (30))
130 */
131static double integrate_unitary_sphere_polynomial(int i, int j, int k) {
132 if ((i % 2 == 0) && (j % 2 == 0) && (k % 2 == 0)) {
133 double dfac_i = (double)libgrpp_double_factorial(i - 1);
134 double dfac_j = (double)libgrpp_double_factorial(j - 1);
135 double dfac_k = (double)libgrpp_double_factorial(k - 1);
136 double dfac_ijk = (double)libgrpp_double_factorial(i + j + k + 1);
137 return 4 * M_PI * dfac_i * dfac_j * dfac_k / dfac_ijk;
138 } else {
139 return 0.0;
140 }
141}
static void const int const int i
static double integrate_unitary_sphere_polynomial(int i, int j, int k)
double libgrpp_angular_type1_integral(int lambda, int II, int JJ, int KK, double *k)
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)
#define M_PI
double libgrpp_double_factorial(int n)
rsh_coef_table_t * libgrpp_get_real_spherical_harmonic_table(int L)
double libgrpp_spherical_to_cartesian_coef(int l, int m, int lx, int ly)
double libgrpp_evaluate_real_spherical_harmonic(const int l, const int m, const double *k)
#define LIBGRPP_ZERO_THRESH