ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/OpenMD/branches/development/src/nonbonded/SlaterIntegrals.hpp
Revision: 1808
Committed: Mon Oct 22 20:42:10 2012 UTC (12 years, 7 months ago) by gezelter
File size: 19218 byte(s)
Log Message:
A bug fix in the electric field for the new electrostatic code.  Also comment fixes for Doxygen 

File Contents

# Content
1 /***************************************************************************
2 * This program is free software; you can redistribute it and/or modify *
3 * it under the terms of the GNU General Public License as published by *
4 * the Free Software Foundation; either version 3 of the License, or *
5 * (at your option) any later version. *
6 * *
7 * This program is distributed in the hope that it will be useful, *
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
10 * GNU General Public License for more details. *
11 * *
12 * You should have received a copy of the GNU General Public License *
13 * along with this program; if not, see <http://www.gnu.org/licenses/>. *
14 ***************************************************************************/
15
16 /***
17 * This file was imported from qtpie, found at http://code.google.com/p/qtpie
18 * and was modified minimally for use in OpenMD.
19 *
20 * No author attribution was found in the code, but it presumably is
21 * the work of J. Chen and Todd J. Martinez.
22 *
23 * QTPIE (charge transfer with polarization current equilibration) is
24 * a new charge model, similar to other charge models like QEq,
25 * fluc-q, EEM or ABEEM. Unlike other existing charge models, however,
26 * it is capable of describing both charge transfer and polarization
27 * phenomena. It is also unique for its ability to describe
28 * intermolecular charge transfer at reasonable computational cost.
29 *
30 * Good references to cite when using this code are:
31 *
32 * J. Chen and T. J. Martinez, "QTPIE: Charge transfer with
33 * polarization current equalization. A fluctuating charge model with
34 * correct asymptotics", Chemical Physics Letters 438 (2007),
35 * 315-320. DOI: 10.1016/j.cplett.2007.02.065. Erratum: ibid, 463
36 * (2008), 288. DOI: 10.1016/j.cplett.2008.08.060
37 *
38 * J. Chen, D. Hundertmark and T. J. Martinez, "A unified theoretical
39 * framework for fluctuating-charge models in atom-space and in
40 * bond-space", Journal of Chemical Physics 129 (2008), 214113. DOI:
41 * 10.1063/1.3021400.
42 *
43 * J. Chen and T. J. Martinez, "Charge conservation in
44 * electronegativity equalization and its implications for the
45 * electrostatic properties of fluctuating-charge models", Journal of
46 * Chemical Physics 131 (2009), 044114. DOI: 10.1063/1.3183167
47 *
48 * J. Chen and T. J. Martinez, "The dissociation catastrophe in
49 * fluctuating-charge models and its implications for the concept of
50 * atomic electronegativity", Progress in Theoretical Chemistry and
51 * Physics, to appear. arXiv:0812.1543
52 *
53 * J. Chen, "Theory and applications of fluctuating-charge models",
54 * PhD (chemical physics) thesis, University of Illinois at
55 * Urbana-Champaign, Department of Chemistry, 2009.
56 *
57 * J. Chen and T. J. Martinez, "Size-extensive polarizabilities with
58 * intermolecular charge transfer in a fluctuating-charge model", in
59 * preparation. arXiv:0812.1544
60 */
61
62 #include "config.h"
63 #include <cmath>
64 #include <cstdlib>
65 #include <iostream>
66 #include "math/Factorials.hpp"
67 #include "utils/NumericConstant.hpp"
68
69 #ifndef NONBONDED_SLATERINTEGRALS_HPP
70 #define NONBONDED_SLATERINTEGRALS_HPP
71
72 template <typename T> inline T sqr(T t) { return t*t; }
73 template <typename T> inline T mod(T x, T m)
74 { return x<0 ? m - 1 - ((-x) - 1)%m : x%m; }
75
76 // #include "parameters.h"
77
78 /**
79 * @brief Computes Rosen's Guillimer-Zener function A
80 * Computes Rosen's A integral, an auxiliary quantity needed to
81 * compute integrals involving Slater-type orbitals of s symmetry.
82 * \f[
83 * A_n(\alpha) = \int_1^\infty x^n e^{-\alpha x}dx
84 * = \frac{n! e^{-\alpha}}{\alpha^{n+1}}\sum_{\nu=0}^n
85 * \frac{\alpha^\nu}{\nu!}
86 * \f]
87 * @param n - principal quantum number
88 * @param a - Slater exponent
89 * @return the value of Rosen's A integral
90 * @note N. Rosen, Phys. Rev., 38 (1931), 255
91 */
92 inline RealType RosenA(int n, RealType a)
93 {
94 RealType RosenA_ = 0.;
95 if (a != 0.)
96 {
97 RealType Term = 1.;
98 RosenA_ = Term;
99 for (int nu=1; nu<=n; nu++)
100 {
101 Term *= a / nu;
102 RosenA_ += Term;
103 }
104 RosenA_ = (RosenA_/Term) * (exp(-a)/a);
105 }
106 return RosenA_;
107 }
108
109 /**
110 * @brief Computes Rosen's Guillimer-Zener function B
111 * Computes Rosen's B integral, an auxiliary quantity needed to
112 * compute integrals involving Slater-type orbitals of s symmetry.
113 * \f[
114 * B_n(\alpha) = \int_{-1}^1 x^n e^{-\alpha x} dx
115 * = \frac{n!}{\alpha^{n+1}}
116 * \sum_{\nu=0}^n \frac{e^\alpha(-\alpha)^\nu
117 * - e^{-\alpha} \alpha^\nu}{\nu!}
118 * \f]
119 * @param n - principal quantum number
120 * @param alpha - Slater exponent
121 * @return the value of Rosen's B integral
122 * @note N. Rosen, Phys. Rev., 38 (1931), 255
123 */
124 inline RealType RosenB(int n, RealType alpha)
125 {
126 RealType TheSum, Term;
127 RealType RosenB_, PSinhRosenA, PCoshRosenA, PHyperRosenA;
128 bool IsPositive;
129 if (alpha != 0.)
130 {
131 Term = 1.;
132 TheSum = 1.;
133 IsPositive = true;
134
135 // These two expressions are (up to constant factors) equivalent
136 // to computing the hyperbolic sine and cosine of a respectively
137 // The series consists of adding up these terms in an alternating fashion
138 PSinhRosenA = exp(alpha) - exp(-alpha);
139 PCoshRosenA = -exp(alpha) - exp(-alpha);
140 TheSum = PSinhRosenA;
141 for (unsigned nu=1; nu<=n; nu++)
142 {
143 if (IsPositive)
144 {
145 PHyperRosenA = PCoshRosenA;
146 IsPositive = false;
147 }
148 else // term to add should be negative
149 {
150 PHyperRosenA = PSinhRosenA;
151 IsPositive = true;
152 }
153 Term *= alpha / nu;
154 TheSum += Term * PHyperRosenA;
155 }
156 RosenB_ = TheSum / (alpha*Term);
157 }
158 else // pathological case of a=0
159 {
160 printf("WARNING, a = 0 in RosenB\n");
161 RosenB_ = (1. - pow(-1., n)) / (n + 1.);
162 }
163 return RosenB_;
164 }
165
166 /** @brief Computes Rosen's D combinatorial factor
167 * Computes Rosen's D factor, an auxiliary quantity needed to
168 * compute integrals involving Slater-type orbitals of s symmetry.
169 * \f[
170 * RosenD^{mn}_p = \sum_k (-1)^k \frac{m! n!}
171 * {(p-k)!(m-p+k)!(n-k)!k!}
172 * \f]
173 * @return the value of Rosen's D factor
174 * @note N. Rosen, Phys. Rev., 38 (1931), 255
175 */
176 inline RealType RosenD(int m, int n, int p)
177 {
178 if (m+n+p > maxFact)
179 {
180 printf("Error, arguments exceed maximum factorial computed %d > %d\n", m+n+p, maxFact);
181 ::exit(0);
182 }
183
184 RealType RosenD_ = 0;
185 for (int k=max(p-m,0); k<=min(n,p); k++)
186 {
187 if (mod(k,2) == 0)
188 RosenD_ += (fact[m] / (fact[p-k] * fact[m-p+k])) * (fact[n] / (fact[n-k] * fact[k]));
189 else
190 RosenD_ -= (fact[m] / ( fact[p-k] * fact[m-p+k])) * (fact[n] / (fact[n-k] * fact[k]));
191 }
192 return RosenD_;
193 }
194
195 /** @brief Computes Coulomb integral analytically over s-type STOs
196 * Computes the two-center Coulomb integral over Slater-type orbitals of s symmetry.
197 * @param a : Slater zeta exponent of first atom in inverse Bohr (au)
198 * @param b : Slater zeta exponent of second atom in inverse Bohr (au)
199 * @param m : principal quantum number of first atom
200 * @param n : principal quantum number of second atom
201 * @param R : internuclear distance in atomic units (bohr)
202 * @return value of the Coulomb potential energy integral
203 * @note N. Rosen, Phys. Rev., 38 (1931), 255
204 * @note In Rosen's paper, this integral is known as K2.
205 */
206 inline RealType sSTOCoulInt(RealType a, RealType b, int m, int n, RealType R)
207 {
208 RealType x, K2;
209 RealType Factor1, Factor2, Term, OneElectronTerm;
210 RealType eps, epsi;
211
212 // To speed up calculation, we terminate loop once contributions
213 // to integral fall below the bound, epsilon
214 RealType epsilon = 0.;
215
216 // x is the argument of the auxiliary RosenA and RosenB functions
217 x = 2. * a * R;
218
219 // First compute the two-electron component
220 RealType sSTOCoulInt_ = 0.;
221 if (std::fabs(x) < OpenMD::NumericConstant::epsilon) // Pathological case
222 {
223
224 // This solution for the one-center coulomb integrals comes from
225 // Yoshiyuki Hase, Computers & Chemistry 9(4), pp. 285-287 (1985).
226
227 RealType Term1 = fact[2*m - 1] / pow(2*a, 2*m);
228 RealType Term2 = 0.;
229 for (int nu = 1; nu <= 2*n; nu++) {
230 Term2 += nu * pow(2*b, 2*n - nu) * fact[2*(m+n)-nu-1] / (fact[2*n-nu]*2*n * pow(2*(a+b), 2*(m+n)-nu));
231 }
232 sSTOCoulInt_ = pow(2*a, 2*m+1) * (Term1 - Term2) / fact[2*m];
233
234 // Original QTPIE code for the one-center case is below. Doesn't
235 // appear to generate the correct one-center results.
236 //
237 // if ((a==b) && (m==n))
238 // {
239 // for (int nu=0; nu<=2*n-1; nu++)
240 // {
241 // K2 = 0.;
242 // for (unsigned p=0; p<=2*n+m; p++) K2 += 1. / fact[p];
243 // sSTOCoulInt_ += K2 * fact[2*n+m] / fact[m];
244 // }
245 // sSTOCoulInt_ = 2 * a / (n * fact[2*n]) * sSTOCoulInt_;
246 // }
247 // else
248 // {
249 // // Not implemented
250 // printf("ERROR, sSTOCoulInt cannot compute from arguments\n");
251 // printf("a = %lf b = %lf m = %d n = %d R = %lf\n",a, b, m, n, R);
252 // exit(0);
253 // }
254
255 }
256 else
257 {
258 OneElectronTerm = 1./R + pow(x, 2*m)/(fact[2*m]*R)*
259 ((x-2*m)*RosenA(2*m-1,x)-exp(-x)) + sSTOCoulInt_;
260 eps = epsilon / OneElectronTerm;
261 if (a == b)
262 {
263 // Apply Rosen (48)
264 Factor1 = -a*pow(a*R, 2*m)/(n*fact[2*m]);
265 for (int nu=0; nu<=2*n-1; nu++)
266 {
267 Factor2 = (2.*n-nu)/fact[nu]*pow(a*R,nu);
268 epsi = eps / fabs(Factor1 * Factor2);
269 K2 = 0.;
270 for (int p=0; p<=m+(nu-1)/2; p++)
271 {
272 Term = RosenD(2*m-1, nu, 2*p)/(2.*p+1.) *RosenA(2*m+nu-1-2*p,x);
273 K2 += Term;
274 if ((Term > 0) && (Term < epsi)) goto label1;
275 }
276 sSTOCoulInt_ += K2 * Factor2;
277 }
278 label1:
279 sSTOCoulInt_ *= Factor1;
280 }
281 else
282 {
283 Factor1 = -a*pow(a*R,2*m)/(2.*n*fact[2*m]);
284 epsi = eps/fabs(Factor1);
285 if (b == 0.)
286 printf("WARNING: b = 0 in sSTOCoulInt\n");
287 else
288 {
289 // Apply Rosen (54)
290 for (int nu=0; nu<=2*n-1; nu++)
291 {
292 K2 = 0;
293 for (int p=0; p<=2*m+nu-1; p++)
294 K2=K2+RosenD(2*m-1,nu,p)*RosenB(p,R*(a-b))
295 *RosenA(2*m+nu-1-p,R*(a+b));
296 Term = K2*(2*n-nu)/fact[nu]*pow(b*R, nu);
297 sSTOCoulInt_ += Term;
298 if (fabs(Term) < epsi) goto label2;
299 }
300 label2:
301 sSTOCoulInt_ *= Factor1;
302 }
303 }
304 // Now add the one-electron term from Rosen (47) = Rosen (53)
305 sSTOCoulInt_ += OneElectronTerm;
306 }
307 return sSTOCoulInt_;
308 }
309
310 /**
311 * @brief Computes overlap integral analytically over s-type STOs
312 * Computes the overlap integral over two
313 * Slater-type orbitals of s symmetry.
314 * @param a : Slater zeta exponent of first atom in inverse Bohr (au)
315 * @param b : Slater zeta exponent of second atom in inverse Bohr (au)
316 * @param m : principal quantum number of first atom
317 * @param n : principal quantum number of second atom
318 * @param R : internuclear distance in atomic units (bohr)
319 * @return the value of the sSTOOvInt integral
320 * @note N. Rosen, Phys. Rev., 38 (1931), 255
321 * @note In the Rosen paper, this integral is known as I.
322 */
323 inline RealType sSTOOvInt(RealType a, RealType b, int m, int n, RealType R)
324 {
325 RealType Factor, Term, eps;
326
327 // To speed up calculation, we terminate loop once contributions
328 // to integral fall below the bound, epsilon
329 RealType epsilon = 0.;
330 RealType sSTOOvInt_ = 0.;
331
332 if (a == b)
333 {
334 Factor = pow(a*R, m+n+1)/sqrt(fact[2*m]*fact[2*n]);
335 eps = epsilon / fabs(Factor);
336 for (int q=0; q<=(m+n)/2; q++)
337 {
338 Term = RosenD(m,n,2*q)/(2.*q+1.)*RosenA(m+n-2*q,a*R);
339 sSTOOvInt_ += Term;
340 if (fabs(Term) < eps) exit(0);
341 }
342 sSTOOvInt_ *= Factor;
343 }
344 else
345 {
346 Factor = 0.5*pow(a*R, m+0.5)*pow(b*R,n+0.5)
347 /sqrt(fact[2*m]*fact[2*n]);
348 eps = epsilon / fabs(Factor);
349 for (int q=0; q<=m+n; q++)
350 {
351 Term = RosenD(m,n,q)*RosenB(q, R/2.*(a-b))
352 * RosenA(m+n-q,R/2.*(a+b));
353 sSTOOvInt_ += Term;
354 if (fabs(Term) < eps) exit(0);
355 }
356 sSTOOvInt_ *= Factor;
357 }
358 return sSTOOvInt_;
359 }
360
361 /**
362 * @brief Computes kinetic energy integral analytically over s-type STOs
363 * Computes the overlap integral over two Slater-type orbitals of s symmetry.
364 * @param a : Slater zeta exponent of first atom in inverse Bohr (au)
365 * @param b : Slater zeta exponent of second atom in inverse Bohr (au)
366 * @param m : principal quantum number of first atom
367 * @param n : principal quantum number of second atom
368 * @param R : internuclear distance in atomic units (bohr)
369 * @return the value of the kinetic energy integral
370 * @note N. Rosen, Phys. Rev., 38 (1931), 255
371 * @note untested
372 */
373 inline RealType KinInt(RealType a, RealType b, int m, int n,RealType R)
374 {
375 RealType KinInt_ = -0.5*b*b*sSTOOvInt(a, b, m, n, R);
376 if (n > 0)
377 {
378 KinInt_ += b*b*pow(2*b/(2*b-1),0.5) * sSTOOvInt(a, b, m, n-1, R);
379 if (n > 1) KinInt_ += pow(n*(n-1)/((n-0.5)*(n-1.5)), 0.5)
380 * sSTOOvInt(a, b, m, n-2, R);
381 }
382 return KinInt_;
383 }
384
385 /**
386 * @brief Computes derivative of Coulomb integral with respect to the interatomic distance
387 * Computes the two-center Coulomb integral over Slater-type orbitals of s symmetry.
388 * @param a: Slater zeta exponent of first atom in inverse Bohr (au)
389 * @param b: Slater zeta exponent of second atom in inverse Bohr (au)
390 * @param m: principal quantum number of first atom
391 * @param n: principal quantum number of second atom
392 * @param R: internuclear distance in atomic units (bohr)
393 * @return the derivative of the Coulomb potential energy integral
394 * @note Derived in QTPIE research notes, May 15 2007
395 */
396 inline RealType sSTOCoulIntGrad(RealType a, RealType b, int m, int n, RealType R)
397 {
398 RealType x, y, z, K2, TheSum;
399 // x is the argument of the auxiliary RosenA and RosenB functions
400 x = 2. * a * R;
401
402 // First compute the two-electron component
403 RealType sSTOCoulIntGrad_ = 0.;
404 if (x==0) // Pathological case
405 {
406 printf("WARNING: argument given to sSTOCoulIntGrad is 0\n");
407 printf("a = %lf R= %lf\n", a, R);
408 }
409 else
410 {
411 if (a == b)
412 {
413 TheSum = 0.;
414 for (int nu=0; nu<=2*(n-1); nu++)
415 {
416 K2 = 0.;
417 for (int p=0; p<=(m+nu)/2; p++)
418 K2 += RosenD(2*m-1, nu+1, 2*p)/(2*p + 1.) * RosenA(2*m+nu-1-2*p, x);
419 TheSum += (2*n-nu-1)/fact[nu]*pow(a*R, nu) * K2;
420 }
421 sSTOCoulIntGrad_ = -pow(a, 2*m+2)*pow(R, 2*m) /(n*fact[2*m])*TheSum;
422 TheSum = 0.;
423 for (int nu=0; nu<=2*n-1; nu++)
424 {
425 K2 = 0.;
426 for (int p=0; p<=(m+nu-1)/2; p++)
427 K2 += RosenD(2*m-1, nu, 2*p)/(2*p + 1.) * RosenA(2*m+nu-2*p, x);
428 TheSum += (2*n-nu)/fact[nu]*pow(a*R,nu) * K2;
429 }
430 sSTOCoulIntGrad_ += 2*pow(a, 2*m+2)*pow(R, 2*m) /(n*fact[2*m])*TheSum;
431 }
432 else
433 {
434 // Slater exponents are different
435 // First calculate some useful arguments
436 y = R*(a+b);
437 z = R*(a-b);
438 TheSum = 0.;
439 for (int nu=0; nu<=2*n-1; nu++)
440 {
441 K2 = 0.;
442 for (int p=0; p<=2*m+nu; p++)
443 K2 += RosenD(2*m-1, nu+1, p)
444 * RosenB(p,z)*RosenA(2*m+nu-p, y);
445 TheSum += (2*n-nu-1)/fact[nu]*pow(b*R,nu) * K2;
446 }
447 sSTOCoulIntGrad_ = -b*pow(a,2*m+1)*pow(R,2*m)/
448 (2*n*fact[2*m])*TheSum;
449 TheSum = 0.;
450 for (int nu=0; nu<=2*n; nu++)
451 {
452 K2 = 0.;
453 for (int p=0; p<=2*m-1+nu; p++)
454 K2 += RosenD(2*m-1, nu, p)
455 * ((a-b)*RosenB(p+1,z)*RosenA(2*m+nu-p-1, y)
456 +(a+b)*RosenB(p ,z)*RosenA(2*m+nu-p , y));
457 TheSum += (2*n-nu)/fact[nu]*pow(b*R,nu) * K2;
458 }
459 sSTOCoulIntGrad_ += pow(a,2*m+1)*pow(R,2*m)/(2*n*fact[2*m])*TheSum;
460 }
461 // Now add one-electron terms and common term
462 sSTOCoulIntGrad_ = sSTOCoulIntGrad_ - (2.*m+1.)/sqr(R)
463 + 2.*m/R * sSTOCoulInt(a,b,m,n,R)
464 + pow(x,2*m)/(fact[2*m]*sqr(R)) * ((2.*m+1.)*exp(-x)
465 + 2.*m*(1.+2.*m-x)*RosenA(2*m-1,x));
466 }
467 return sSTOCoulIntGrad_;
468 }
469
470 /**
471 * @brief Computes gradient of overlap integral with respect to the interatomic diatance
472 * Computes the derivative of the overlap integral over two Slater-type orbitals of s symmetry.
473 * @param a: Slater zeta exponent of first atom in inverse Bohr (au)
474 * @param b: Slater zeta exponent of second atom in inverse Bohr (au)
475 * @param m: principal quantum number of first atom
476 * @param n: principal quantum number of second atom
477 * @param R: internuclear distance in atomic units (bohr)
478 * @return the derivative of the sSTOOvInt integral
479 * @note Derived in QTPIE research notes, May 15 2007
480 */
481 inline RealType sSTOOvIntGrad(RealType a, RealType b, int m, int n, RealType R)
482 {
483 RealType w, x, y, z, TheSum;
484
485 // Calculate first term
486 RealType sSTOOvIntGrad_ = (m+n+1.)/R * sSTOOvInt(a, b, m, n, R);
487
488 // Calculate remaining terms; answers depend on exponents
489 TheSum = 0.;
490 x = a * R;
491 if (a == b)
492 {
493 for (int q=0; q<=(m+n)/2; q++)
494 TheSum += RosenD(m,n,2*q) / (2*q + 1.) * RosenA(m+n-2*q+1, x);
495 sSTOOvIntGrad_ -= a*pow(x,m+n+1)/ sqrt(fact[2*m]*fact[2*n])*TheSum;
496 }
497 else
498 {
499 w = b*R;
500 y = 0.5*R*(a+b);
501 z = 0.5*R*(a-b);
502 for (int q=0; q<m+n; q++)
503 TheSum = TheSum + RosenD(m,n,q) *
504 ((a-b)*RosenB(q+1,z)*RosenA(m+n-q ,y)
505 +(a+b)*RosenB(q ,z)*RosenA(m+n-q+1,y));
506 sSTOOvIntGrad_ -= 0.25*sqrt((pow(x, 2*m+1)*pow(w, 2*n+1))/(fact[2*m]*fact[2*n]))*TheSum;
507 }
508 return sSTOOvIntGrad_;
509 }
510
511 /**
512 * @brief Calculates a Slater-type orbital exponent based on the hardness parameters
513 * @param hardness: chemical hardness in atomic units
514 * @param n: principal quantum number
515 * @note Modified for use with OpenMD by Gezelter and Michalka.
516 */
517 inline RealType getSTOZeta(int n, RealType hardness)
518 {
519 // Approximate the exact value of the constant of proportionality
520 // by its value at a very small distance epsilon
521 // since the exact R = 0 case has not be programmed
522 RealType epsilon = 1.0e-8;
523
524 // Assign orbital exponent
525 return pow(sSTOCoulInt(1., 1., n, n, epsilon) / hardness, -1./(3. + 2.*n));
526 }
527
528 #endif

Properties

Name Value
svn:eol-style native