|
| 1 | +/************************************************************************** |
| 2 | + * This file is part of PyQInt. * |
| 3 | + * * |
| 4 | + * Author: Ivo Filot <ivo@ivofilot.nl> * |
| 5 | + * * |
| 6 | + * PyQInt is free software: * |
| 7 | + * you can redistribute it and/or modify it under the terms of the * |
| 8 | + * GNU General Public License as published by the Free Software * |
| 9 | + * Foundation, either version 3 of the License, or (at your option) * |
| 10 | + * any later version. * |
| 11 | + * * |
| 12 | + * PyQInt is distributed in the hope that it will be useful, * |
| 13 | + * but WITHOUT ANY WARRANTY; without even the implied warranty * |
| 14 | + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * |
| 15 | + * See the GNU General Public License for more details. * |
| 16 | + * * |
| 17 | + * You should have received a copy of the GNU General Public License * |
| 18 | + * along with this program. If not, see http://www.gnu.org/licenses/. * |
| 19 | + * * |
| 20 | + **************************************************************************/ |
| 21 | + |
| 22 | +#define _USE_MATH_DEFINES |
| 23 | +#include <cmath> |
| 24 | + |
| 25 | +#include "factorials.h" |
| 26 | +#include "gaussian_integrals.h" |
| 27 | + |
| 28 | +namespace integrals::gaussian { |
| 29 | + |
| 30 | +/** |
| 31 | + * @brief Computes the Gaussian product center of two primitive Gaussians |
| 32 | + * |
| 33 | + * @param double alpha1 Exponent of first Gaussian |
| 34 | + * @param const Vec3& a Center of first Gaussian |
| 35 | + * @param double alpha2 Exponent of second Gaussian |
| 36 | + * @param const Vec3& b Center of second Gaussian |
| 37 | + * |
| 38 | + * Calculates the position of the Gaussian product center P. |
| 39 | + * |
| 40 | + * @return Vec3 Position vector of the Gaussian product center |
| 41 | + */ |
| 42 | +Vec3 gaussian_product_center(double alpha1, const Vec3& a, |
| 43 | + double alpha2, const Vec3& b) { |
| 44 | + return (alpha1 * a + alpha2 * b) / (alpha1 + alpha2); |
| 45 | +} |
| 46 | + |
| 47 | +/** |
| 48 | + * @brief Computes the binomial coefficient |
| 49 | + * |
| 50 | + * @param int a Upper index |
| 51 | + * @param int b Lower index |
| 52 | + * |
| 53 | + * Returns 1 if indices are outside valid range. |
| 54 | + * |
| 55 | + * @return double Value of the binomial coefficient |
| 56 | + */ |
| 57 | +double binomial(int a, int b) { |
| 58 | + if ((a < 0) || (b < 0) || (a - b < 0)) { |
| 59 | + return 1.0; |
| 60 | + } |
| 61 | + return factorial(a) / (factorial(b) * factorial(a - b)); |
| 62 | +} |
| 63 | + |
| 64 | +/** |
| 65 | + * @brief Computes binomial prefactor used in Gaussian integral recursion |
| 66 | + * |
| 67 | + * @param int s Summation index |
| 68 | + * @param int ia Angular momentum component of first Gaussian |
| 69 | + * @param int ib Angular momentum component of second Gaussian |
| 70 | + * @param double xpa Distance P_x - A_x |
| 71 | + * @param double xpb Distance P_x - B_x |
| 72 | + * |
| 73 | + * @return double Value of the binomial prefactor |
| 74 | + */ |
| 75 | +double binomial_prefactor(int s, int ia, int ib, |
| 76 | + double xpa, double xpb) { |
| 77 | + double sum = 0.0; |
| 78 | + |
| 79 | + for (int t = 0; t < s + 1; t++) { |
| 80 | + if ((s - ia <= t) && (t <= ib)) { |
| 81 | + sum += binomial(ia, s - t) * |
| 82 | + binomial(ib, t) * |
| 83 | + std::pow(xpa, ia - s + t) * |
| 84 | + std::pow(xpb, ib - t); |
| 85 | + } |
| 86 | + } |
| 87 | + |
| 88 | + return sum; |
| 89 | +} |
| 90 | + |
| 91 | +/** |
| 92 | + * @brief Computes one-dimensional overlap integral component |
| 93 | + * |
| 94 | + * @param int l1 Angular momentum of first Gaussian along axis |
| 95 | + * @param int l2 Angular momentum of second Gaussian along axis |
| 96 | + * @param double x1 Distance P_x - A_x |
| 97 | + * @param double x2 Distance P_x - B_x |
| 98 | + * @param double gamma Sum of Gaussian exponents |
| 99 | + * |
| 100 | + * @return double Value of the 1D overlap contribution |
| 101 | + */ |
| 102 | +double overlap_1d(int l1, int l2, double x1, double x2, double gamma) { |
| 103 | + double sum = 0.0; |
| 104 | + |
| 105 | + for (int i = 0; i < (1 + std::floor(0.5 * (l1 + l2))); i++) { |
| 106 | + sum += binomial_prefactor(2 * i, l1, l2, x1, x2) * |
| 107 | + (i == 0 ? 1 : double_factorial(2 * i - 1)) / |
| 108 | + std::pow(2 * gamma, i); |
| 109 | + } |
| 110 | + |
| 111 | + return sum; |
| 112 | +} |
| 113 | + |
| 114 | +/** |
| 115 | + * @brief Computes overlap integral between two primitive Gaussian orbitals |
| 116 | + * |
| 117 | + * @param double alpha1 Exponent of first Gaussian |
| 118 | + * @param unsigned int l1,m1,n1 Angular momentum components of first Gaussian |
| 119 | + * @param const Vec3& a Center of first Gaussian |
| 120 | + * @param double alpha2 Exponent of second Gaussian |
| 121 | + * @param unsigned int l2,m2,n2 Angular momentum components of second Gaussian |
| 122 | + * @param const Vec3& b Center of second Gaussian |
| 123 | + * |
| 124 | + * @return double Value of the 3D overlap integral |
| 125 | + */ |
| 126 | +double overlap_gto(double alpha1, unsigned int l1, unsigned int m1, unsigned int n1, const Vec3& a, |
| 127 | + double alpha2, unsigned int l2, unsigned int m2, unsigned int n2, const Vec3& b) { |
| 128 | + |
| 129 | + double rab2 = (a - b).norm2(); |
| 130 | + double gamma = alpha1 + alpha2; |
| 131 | + Vec3 p = gaussian_product_center(alpha1, a, alpha2, b); |
| 132 | + |
| 133 | + double pre = std::pow(M_PI / gamma, 1.5) * std::exp(-alpha1 * alpha2 * rab2 / gamma); |
| 134 | + double wx = overlap_1d(l1, l2, p[0] - a[0], p[0] - b[0], gamma); |
| 135 | + double wy = overlap_1d(m1, m2, p[1] - a[1], p[1] - b[1], gamma); |
| 136 | + double wz = overlap_1d(n1, n2, p[2] - a[2], p[2] - b[2], gamma); |
| 137 | + |
| 138 | + return pre * wx * wy * wz; |
| 139 | +} |
| 140 | + |
| 141 | +} // namespace normalization |
0 commit comments