1
#include <libciomr/libciomr.h>
3
#include <libmints/basisset.h>
4
#include <libmints/gshell.h>
5
#include <libmints/overlap.h>
6
#include <libmints/kinetic.h>
9
#define MAX(a, b) ((a) > (b) ? (a) : (b))
13
// Initialize overlap_recur_ to +1 basis set angular momentum
14
KineticInt::KineticInt(IntegralFactory* integral, Ref<BasisSet>& bs1, Ref<BasisSet>& bs2, int deriv) :
15
OneBodyInt(integral, bs1, bs2, deriv), overlap_recur_(bs1->max_am()+1+deriv, bs2->max_am()+1+deriv)
17
int maxam1 = bs1_->max_am();
18
int maxam2 = bs2_->max_am();
20
int maxnao1 = (maxam1+1)*(maxam1+2)/2;
21
int maxnao2 = (maxam2+1)*(maxam2+2)/2;
23
maxnao1 *= 3 * natom_;
24
maxnao2 *= 3 * natom_;
27
buffer_ = new double[maxnao1*maxnao2];
30
KineticInt::~KineticInt()
35
void KineticInt::compute_shell(int sh1, int sh2)
37
compute_pair(bs1_->shell(sh1), bs2_->shell(sh2));
40
void KineticInt::compute_shell_deriv1(int sh1, int sh2)
42
compute_pair_deriv1(bs1_->shell(sh1), bs2_->shell(sh2));
45
// The engine only supports segmented basis sets
46
void KineticInt::compute_pair(Ref<GaussianShell>& s1, Ref<GaussianShell>& s2)
51
int nprim1 = s1->nprimitive();
52
int nprim2 = s2->nprimitive();
54
A[0] = s1->center()[0];
55
A[1] = s1->center()[1];
56
A[2] = s1->center()[2];
57
B[0] = s2->center()[0];
58
B[1] = s2->center()[1];
59
B[2] = s2->center()[2];
61
// compute intermediates
63
AB2 += (A[0] - B[0]) * (A[0] - B[0]);
64
AB2 += (A[1] - B[1]) * (A[1] - B[1]);
65
AB2 += (A[2] - B[2]) * (A[2] - B[2]);
67
memset(buffer_, 0, s1->ncartesian() * s2->ncartesian() * sizeof(double));
69
double **x = overlap_recur_.x();
70
double **y = overlap_recur_.y();
71
double **z = overlap_recur_.z();
73
for (int p1=0; p1<nprim1; ++p1) {
74
double a1 = s1->exp(p1);
75
double c1 = s1->coef(0, p1);
76
for (int p2=0; p2<nprim2; ++p2) {
77
double a2 = s2->exp(p2);
78
double c2 = s2->coef(0, p2);
79
double gamma = a1 + a2;
80
double oog = 1.0/gamma;
85
P[0] = (a1*A[0] + a2*B[0])*oog;
86
P[1] = (a1*A[1] + a2*B[1])*oog;
87
P[2] = (a1*A[2] + a2*B[2])*oog;
95
double over_pf = exp(-a1*a2*AB2*oog) * sqrt(M_PI*oog) * M_PI * oog * c1 * c2;
98
overlap_recur_.compute(PA, PB, gamma, am1+1, am2+1);
101
for(int ii = 0; ii <= am1; ii++) {
103
for(int jj = 0; jj <= ii; jj++) {
106
/*--- create all am components of sj ---*/
107
for(int kk = 0; kk <= am2; kk++) {
109
for(int ll = 0; ll <= kk; ll++) {
113
double I1, I2, I3, I4;
115
I1 = (l1 == 0 || l2 == 0) ? 0.0 : x[l1-1][l2-1] * y[m1][m2] * z[n1][n2] * over_pf;
116
I2 = x[l1+1][l2+1] * y[m1][m2] * z[n1][n2] * over_pf;
117
I3 = (l2 == 0) ? 0.0 : x[l1+1][l2-1] * y[m1][m2] * z[n1][n2] * over_pf;
118
I4 = (l1 == 0) ? 0.0 : x[l1-1][l2+1] * y[m1][m2] * z[n1][n2] * over_pf;
119
// fprintf(outfile, "I1=%f, I2=%f, I3=%f, I4=%f\n", I1, I2, I3, I4);
120
double Ix = 0.5 * l1 * l2 * I1 + 2.0 * a1 * a2 * I2 - a1 * l2 * I3 - l1 * a2 * I4;
122
I1 = (m1 == 0 || m2 == 0) ? 0.0 : x[l1][l2] * y[m1-1][m2-1] * z[n1][n2] * over_pf;
123
I2 = x[l1][l2] * y[m1+1][m2+1] * z[n1][n2] * over_pf;
124
I3 = (m2 == 0) ? 0.0 : x[l1][l2] * y[m1+1][m2-1] * z[n1][n2] * over_pf;
125
I4 = (m1 == 0) ? 0.0 : x[l1][l2] * y[m1-1][m2+1] * z[n1][n2] * over_pf;
126
// fprintf(outfile, "I1=%f, I2=%f, I3=%f, I4=%f\n", I1, I2, I3, I4);
127
double Iy = 0.5 * m1 * m2 * I1 + 2.0 * a1 * a2 * I2 - a1 * m2 * I3 - m1 * a2 * I4;
129
I1 = (n1 == 0 || n2 == 0) ? 0.0 : x[l1][l2] * y[m1][m2] * z[n1-1][n2-1] * over_pf;
130
I2 = x[l1][l2] * y[m1][m2] * z[n1+1][n2+1] * over_pf;
131
I3 = (n2 == 0) ? 0.0 : x[l1][l2] * y[m1][m2] * z[n1+1][n2-1] * over_pf;
132
I4 = (n1 == 0) ? 0.0 : x[l1][l2] * y[m1][m2] * z[n1-1][n2+1] * over_pf;
133
// fprintf(outfile, "I1=%f, I2=%f, I3=%f, I4=%f\n", I1, I2, I3, I4);
134
double Iz = 0.5 * n1 * n2 * I1 + 2.0 * a1 * a2 * I2 - a1 * n2 * I3 - n1 * a2 * I4;
136
// buffer_[ao12++] += over_pf * (Ix + Iy + Iz);
137
buffer_[ao12++] += (Ix + Iy + Iz);
138
// fprintf(outfile, "Ix=%f, Iy=%f Iz=%f\n", Ix, Iy, Iz);
146
// Integrals are done. Normalize for angular momentum
147
normalize_am(s1, s2);
149
// for (int i=0; i<s1->ncartesian() * s2->ncartesian(); ++i) {
150
// fprintf(outfile, "integral (am=%d|am=%d) = %f\n", am1, am2, buffer_[i]);
152
// Spherical harmonic transformation
153
// Wrapped up in the AO to SO transformation (I think)
154
// spherical_transform_1e(s1, s2);
157
static double ke_int(double **x, double **y, double **z, double a1, int l1, int m1, int n1,
158
double a2, int l2, int m2, int n2)
160
double I1, I2, I3, I4;
162
I1 = (l1 == 0 || l2 == 0) ? 0.0 : x[l1-1][l2-1] * y[m1][m2] * z[n1][n2];
163
I2 = x[l1+1][l2+1] * y[m1][m2] * z[n1][n2];
164
I3 = (l2 == 0) ? 0.0 : x[l1+1][l2-1] * y[m1][m2] * z[n1][n2];
165
I4 = (l1 == 0) ? 0.0 : x[l1-1][l2+1] * y[m1][m2] * z[n1][n2];
166
double Ix = 0.5 * l1 * l2 * I1 + 2.0 * a1 * a2 * I2 - a1 * l2 * I3 - l1 * a2 * I4;
168
I1 = (m1 == 0 || m2 == 0) ? 0.0 : x[l1][l2] * y[m1-1][m2-1] * z[n1][n2];
169
I2 = x[l1][l2] * y[m1+1][m2+1] * z[n1][n2];
170
I3 = (m2 == 0) ? 0.0 : x[l1][l2] * y[m1+1][m2-1] * z[n1][n2];
171
I4 = (m1 == 0) ? 0.0 : x[l1][l2] * y[m1-1][m2+1] * z[n1][n2];
172
double Iy = 0.5 * m1 * m2 * I1 + 2.0 * a1 * a2 * I2 - a1 * m2 * I3 - m1 * a2 * I4;
174
I1 = (n1 == 0 || n2 == 0) ? 0.0 : x[l1][l2] * y[m1][m2] * z[n1-1][n2-1];
175
I2 = x[l1][l2] * y[m1][m2] * z[n1+1][n2+1];
176
I3 = (n2 == 0) ? 0.0 : x[l1][l2] * y[m1][m2] * z[n1+1][n2-1];
177
I4 = (n1 == 0) ? 0.0 : x[l1][l2] * y[m1][m2] * z[n1-1][n2+1];
178
double Iz = 0.5 * n1 * n2 * I1 + 2.0 * a1 * a2 * I2 - a1 * n2 * I3 - n1 * a2 * I4;
180
return (Ix + Iy + Iz);
183
// The engine only supports segmented basis sets
184
void KineticInt::compute_pair_deriv1(Ref<GaussianShell>& s1, Ref<GaussianShell>& s2)
189
int nprim1 = s1->nprimitive();
190
int nprim2 = s2->nprimitive();
192
A[0] = s1->center()[0];
193
A[1] = s1->center()[1];
194
A[2] = s1->center()[2];
195
B[0] = s2->center()[0];
196
B[1] = s2->center()[1];
197
B[2] = s2->center()[2];
199
size_t size = s1->ncartesian() * s2->ncartesian();
200
int center_i = s1->ncenter()*3*size;
201
int center_j = s2->ncenter()*3*size;
203
// compute intermediates
205
AB2 += (A[0] - B[0]) * (A[0] - B[0]);
206
AB2 += (A[1] - B[1]) * (A[1] - B[1]);
207
AB2 += (A[2] - B[2]) * (A[2] - B[2]);
209
memset(buffer_, 0, 3 * natom_ * s1->ncartesian() * s2->ncartesian() * sizeof(double));
211
double **x = overlap_recur_.x();
212
double **y = overlap_recur_.y();
213
double **z = overlap_recur_.z();
215
for (int p1=0; p1<nprim1; ++p1) {
216
double a1 = s1->exp(p1);
217
double c1 = s1->coef(0, p1);
218
for (int p2=0; p2<nprim2; ++p2) {
219
double a2 = s2->exp(p2);
220
double c2 = s2->coef(0, p2);
221
double gamma = a1 + a2;
222
double oog = 1.0/gamma;
227
P[0] = (a1*A[0] + a2*B[0])*oog;
228
P[1] = (a1*A[1] + a2*B[1])*oog;
229
P[2] = (a1*A[2] + a2*B[2])*oog;
237
double over_pf = exp(-a1*a2*AB2*oog) * sqrt(M_PI*oog) * M_PI * oog * c1 * c2;
240
overlap_recur_.compute(PA, PB, gamma, am1+2, am2+2);
243
for(int ii = 0; ii <= am1; ii++) {
245
for(int jj = 0; jj <= ii; jj++) {
248
/*--- create all am components of sj ---*/
249
for(int kk = 0; kk <= am2; kk++) {
251
for(int ll = 0; ll <= kk; ll++) {
256
buffer_[center_i+(0*size)+ao12] += 2.0 * a1 * ke_int(x, y, z, a1, l1+1, m1, n1, a2, l2, m2, n2) * over_pf;
258
buffer_[center_i+(0*size)+ao12] -= ke_int(x, y, z, a1, l1-1, m1, n1, a2, l2, m2, n2) * over_pf;
260
buffer_[center_i+(1*size)+ao12] += 2.0 * a1 * ke_int(x, y, z, a1, l1, m1+1, n1, a2, l2, m2, n2) * over_pf;
262
buffer_[center_i+(1*size)+ao12] -= ke_int(x, y, z, a1, l1, m1-1, n1, a2, l2, m2, n2) * over_pf;
264
buffer_[center_i+(2*size)+ao12] += 2.0 * a1 * ke_int(x, y, z, a1, l1, m1, n1+1, a2, l2, m2, n2) * over_pf;
266
buffer_[center_i+(2*size)+ao12] -= ke_int(x, y, z, a1, l1, m1, n1-1, a2, l2, m2, n2) * over_pf;
269
buffer_[center_j+(0*size)+ao12] += 2.0 * a2 * ke_int(x, y, z, a1, l1, m1, n1, a2, l2+1, m2, n2) * over_pf;
271
buffer_[center_j+(0*size)+ao12] -= ke_int(x, y, z, a1, l1, m1, n1, a2, l2-1, m2, n2) * over_pf;
273
buffer_[center_j+(1*size)+ao12] += 2.0 * a2 * ke_int(x, y, z, a1, l1, m1, n1, a2, l2, m2+1, n2) * over_pf;
275
buffer_[center_j+(1*size)+ao12] -= ke_int(x, y, z, a1, l1, m1, n1, a2, l2, m2-1, n2) * over_pf;
277
buffer_[center_j+(2*size)+ao12] += 2.0 * a2 * ke_int(x, y, z, a1, l1, m1, n1, a2, l2, m2, n2+1) * over_pf;
279
buffer_[center_j+(2*size)+ao12] -= ke_int(x, y, z, a1, l1, m1, n1, a2, l2, m2, n2-1) * over_pf;
289
// Integrals are done. Normalize for angular momentum
290
normalize_am(s1, s2);
292
// Spherical harmonic transformation
293
// Wrapped up in the AO to SO transformation (I think)