source: ThirdParty/mpqc_open/src/lib/chemistry/qc/basis/gaussshell.cc

Candidate_v1.6.1
Last change on this file was 860145, checked in by Frederik Heber <heber@…>, 8 years ago

Merge commit '0b990dfaa8c6007a996d030163a25f7f5fc8a7e7' as 'ThirdParty/mpqc_open'

  • Property mode set to 100644
File size: 14.8 KB
Line 
1//
2// gaussshell.cc
3//
4// Copyright (C) 1996 Limit Point Systems, Inc.
5//
6// Author: Curtis Janssen <cljanss@limitpt.com>
7// Maintainer: LPS
8//
9// This file is part of the SC Toolkit.
10//
11// The SC Toolkit is free software; you can redistribute it and/or modify
12// it under the terms of the GNU Library General Public License as published by
13// the Free Software Foundation; either version 2, or (at your option)
14// any later version.
15//
16// The SC Toolkit is distributed in the hope that it will be useful,
17// but WITHOUT ANY WARRANTY; without even the implied warranty of
18// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19// GNU Library General Public License for more details.
20//
21// You should have received a copy of the GNU Library General Public License
22// along with the SC Toolkit; see the file COPYING.LIB. If not, write to
23// the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
24//
25// The U.S. Government is granted a limited license as per AL 91-7.
26//
27
28#ifdef __GNUC__
29#pragma implementation
30#endif
31
32#include <stdlib.h>
33#include <math.h>
34
35#include <util/misc/formio.h>
36#include <util/misc/math.h>
37#include <util/keyval/keyval.h>
38#include <util/state/stateio.h>
39
40#include <chemistry/qc/basis/gaussshell.h>
41#include <chemistry/qc/basis/integral.h>
42#include <chemistry/qc/basis/cartiter.h>
43
44using namespace std;
45using namespace sc;
46
47const char* GaussianShell::amtypes = "spdfghiklmn";
48const char* GaussianShell::AMTYPES = "SPDFGHIKLMN";
49
50static ClassDesc GaussianShell_cd(
51 typeid(GaussianShell),"GaussianShell",2,"public SavableState",
52 0, create<GaussianShell>, create<GaussianShell>);
53
54// this GaussianShell ctor allocates and computes normalization constants
55// and computes nfunc
56GaussianShell::GaussianShell(
57 int ncn,int nprm,double*e,int*am,int*pure,double**c,PrimitiveType pt,
58 bool do_normalize_shell
59 ):
60nprim(nprm),
61ncon(ncn),
62l(am),
63puream(pure),
64exp(e),
65coef(c)
66{
67 // Compute the number of basis functions in this shell
68 init_computed_data();
69
70 // Convert the coefficients to coefficients for unnormalized primitives,
71 // if needed.
72 if (pt == Normalized) convert_coef();
73
74 // Compute the normalization constants
75 if (do_normalize_shell) normalize_shell();
76}
77
78// this GaussianShell ctor is much like the above except the puream
79// array is generated according to the value of pure
80GaussianShell::GaussianShell(
81 int ncn,int nprm,double*e,int*am,GaussianType pure,double**c,PrimitiveType pt
82 ):
83 nprim(nprm),
84 ncon(ncn),
85 l(am),
86 exp(e),
87 coef(c)
88{
89 puream = new int [ncontraction()];
90 for (int i=0; i<ncontraction(); i++) puream[i] = (pure == Pure);
91
92 // Compute the number of basis functions in this shell
93 init_computed_data();
94
95 // Convert the coefficients to coefficients for unnormalized primitives,
96 // if needed.
97 if (pt == Normalized) convert_coef();
98
99 // Compute the normalization constants
100 normalize_shell();
101}
102
103GaussianShell::GaussianShell(const Ref<KeyVal>&keyval)
104{
105 // read in the shell
106 PrimitiveType pt = keyval_init(keyval,0,0);
107
108 // Compute the number of basis functions in this shell
109 init_computed_data();
110
111 // Convert the coefficients to coefficients for unnormalized primitives,
112 // if needed.
113 if (pt == Normalized) convert_coef();
114
115 // Compute the normalization constants
116 normalize_shell();
117}
118
119GaussianShell::GaussianShell(StateIn&s):
120 SavableState(s)
121{
122 s.get(nprim);
123 s.get(ncon);
124 if (s.version(::class_desc<GaussianShell>()) < 2) s.get(nfunc);
125 s.get(l);
126 s.get(puream);
127 s.get(exp);
128 coef = new double*[ncon];
129 for (int i=0; i<ncon; i++) {
130 s.get(coef[i]);
131 }
132 init_computed_data();
133}
134
135void
136GaussianShell::save_data_state(StateOut&s)
137{
138 s.put(nprim);
139 s.put(ncon);
140 s.put(l,ncon);
141 s.put(puream,ncon);
142 s.put(exp,nprim);
143 for (int i=0; i<ncon; i++) {
144 s.put(coef[i],nprim);
145 }
146}
147
148GaussianShell::GaussianShell(const Ref<KeyVal>&keyval,int pure)
149{
150 // read in the shell
151 PrimitiveType pt = keyval_init(keyval,1,pure);
152
153 // Compute the number of basis functions in this shell
154 init_computed_data();
155
156 // Convert the coefficients to coefficients for unnormalized primitives,
157 // if needed.
158 if (pt == Normalized) convert_coef();
159
160 // Compute the normalization constants
161 normalize_shell();
162}
163
164GaussianShell::PrimitiveType
165GaussianShell::keyval_init(const Ref<KeyVal>& keyval,int havepure,int pure)
166{
167 ncon = keyval->count("type");
168 if (keyval->error() != KeyVal::OK) {
169 ExEnv::err0() << indent
170 << "GaussianShell couldn't find the \"type\" array:\n";
171 keyval->dump(ExEnv::err0());
172 abort();
173 }
174 nprim = keyval->count("exp");
175 if (keyval->error() != KeyVal::OK) {
176 ExEnv::err0() << indent
177 << "GaussianShell couldn't find the \"exp\" array:\n";
178 keyval->dump(ExEnv::err0());
179 abort();
180 }
181 int normalized = keyval->booleanvalue("normalized");
182 if (keyval->error() != KeyVal::OK) normalized = 1;
183
184 l = new int[ncon];
185 puream = new int[ncon];
186 exp = new double[nprim];
187 coef = new double*[ncon];
188
189 int i,j;
190 for (i=0; i<nprim; i++) {
191 exp[i] = keyval->doublevalue("exp",i);
192 if (keyval->error() != KeyVal::OK) {
193 ExEnv::err0() << indent
194 << scprintf("GaussianShell: error reading exp:%d: %s\n",
195 i,keyval->errormsg());
196 keyval->errortrace(ExEnv::err0());
197 exit(1);
198 }
199 }
200 for (i=0; i<ncon; i++) {
201 Ref<KeyVal> prefixkeyval = new PrefixKeyVal(keyval,"type",i);
202 coef[i] = new double[nprim];
203 char* am = prefixkeyval->pcharvalue("am");
204 if (prefixkeyval->error() != KeyVal::OK) {
205 ExEnv::err0() << indent
206 << scprintf("GaussianShell: error reading am: \"%s\"\n",
207 prefixkeyval->errormsg());
208 prefixkeyval->errortrace(ExEnv::err0());
209 exit(1);
210 }
211 l[i] = -1;
212 for (int li=0; amtypes[li] != '\0'; li++) {
213 if (amtypes[li] == am[0] || AMTYPES[li] == am[0]) { l[i] = li; break; }
214 }
215 if (l[i] == -1 || strlen(am) != 1) {
216 ExEnv::err0() << indent
217 << scprintf("GaussianShell: bad angular momentum: \"%s\"\n",
218 am);
219 prefixkeyval->errortrace(ExEnv::err0());
220 exit(1);
221 }
222 if (l[i] <= 1) puream[i] = 0;
223 else if (havepure) {
224 puream[i] = pure;
225 }
226 else {
227 puream[i] = prefixkeyval->booleanvalue("puream");
228 if (prefixkeyval->error() != KeyVal::OK) {
229 puream[i] = 0;
230 //ExEnv::err0() << indent
231 // << scprintf("GaussianShell: error reading puream: \"%s\"\n",
232 // prefixkeyval->errormsg());
233 //exit(1);
234 }
235 }
236 for (j=0; j<nprim; j++) {
237 coef[i][j] = keyval->doublevalue("coef",i,j);
238 if (keyval->error() != KeyVal::OK) {
239 ExEnv::err0() << indent
240 << scprintf("GaussianShell: error reading coef:%d:%d: %s\n",
241 i,j,keyval->errormsg());
242 keyval->errortrace(ExEnv::err0());
243 exit(1);
244 }
245 }
246 delete[] am;
247 }
248
249 if (normalized) return Normalized;
250 else return Unnormalized;
251}
252
253void
254GaussianShell::init_computed_data()
255{
256 int max = 0;
257 int min = 0;
258 int nc = 0;
259 int nf = 0;
260 has_pure_ = 0;
261 for (int i=0; i<ncontraction(); i++) {
262 int maxi = l[i];
263 if (max < maxi) max = maxi;
264
265 int mini = l[i];
266 if (min > mini || i == 0) min = mini;
267
268 nc += ncartesian(i);
269
270 nf += nfunction(i);
271
272 if (is_pure(i)) has_pure_ = 1;
273 }
274 max_am_ = max;
275 min_am_ = min;
276 ncart_ = nc;
277 nfunc = nf;
278}
279
280int GaussianShell::max_cartesian() const
281{
282 int max = 0;
283 for (int i=0; i<ncontraction(); i++) {
284 int maxi = ncartesian(i);
285 if (max < maxi) max = maxi;
286 }
287 return max;
288}
289
290int GaussianShell::ncartesian_with_aminc(int aminc) const
291{
292 int ret = 0;
293 for (int i=0; i<ncontraction(); i++) {
294 ret += (((l[i]+2+aminc)*(l[i]+1+aminc))>>1);
295 }
296 return ret;
297}
298
299/* Compute the norm for ((x^x1)||(x^x2)). This is slower than need be. */
300static double
301norm(int x1,int x2,double c,double ss)
302{
303 if (x1 < x2) return norm(x2,x1,c,ss);
304 if (x1 == 1) {
305 if (x2 == 1) return c * ss;
306 else return 0.0;
307 }
308 if (x1 == 0) return ss;
309 return c * ( (x1-1) * norm(x1-2,x2,c,ss) + (x2 * norm(x1-1,x2-1,c,ss)));
310}
311
312void GaussianShell::convert_coef()
313{
314 int i,gc;
315 double c,ss;
316
317 // Convert the contraction coefficients from coefficients over
318 // normalized primitives to coefficients over unnormalized primitives
319 for (gc=0; gc<ncon; gc++) {
320 for (i=0; i<nprim; i++) {
321 c = 0.25/exp[i];
322 ss = pow(M_PI/(exp[i]+exp[i]),1.5);
323 coef[gc][i]
324 *= 1.0/sqrt(::norm(l[gc],l[gc],c,ss));
325 }
326 }
327}
328
329double GaussianShell::coefficient_norm(int con,int prim) const
330{
331 double c = 0.25/exp[prim];
332 double ss = pow(M_PI/(exp[prim]+exp[prim]),1.5);
333 return coef[con][prim] * sqrt(::norm(l[con],l[con],c,ss));
334}
335
336// Compute the normalization constant for a shell.
337// returns 1/sqrt(<(x^l 0 0|(x^l 0 0)>).
338// The formula is from Obara and Saika (for the basis functions within
339// the shell that have powers of x only (a and b refer to the power
340// of x):
341// (a||b) = 1/(4 alpha) * ( a (a-1||b) + b (a||b-1) )
342double
343GaussianShell::shell_normalization(int gc)
344{
345 int i,j;
346 double result,c,ss;
347
348 result = 0.0;
349 for (i=0; i<nprim; i++) {
350 for (j=0; j<nprim; j++) {
351 c = 0.50/(exp[i] + exp[j]);
352 ss = pow(M_PI/(exp[i]+exp[j]),1.5);
353 result += coef[gc][i] * coef[gc][j] *
354 ::norm(l[gc],l[gc],c,ss);
355 }
356 }
357
358 return 1.0/sqrt(result);
359}
360
361void GaussianShell::normalize_shell()
362{
363 int i,gc;
364
365 for (gc=0; gc<ncon; gc++) {
366 // Normalize the contraction coefficients
367 double normalization = shell_normalization(gc);
368 for (i=0; i<nprim; i++) {
369 coef[gc][i] *= normalization;
370 }
371 }
372
373}
374
375static int
376comp_relative_overlap(int i1, int j1, int k1, int i2, int j2, int k2)
377{
378 int result = 0;
379
380 if (i1) {
381 if (i1>1) result += (i1-1)*comp_relative_overlap(i1-2,j1,k1,i2,j2,k2);
382 if (i2>0) result += i2*comp_relative_overlap(i1-1,j1,k1,i2-1,j2,k2);
383 return result;
384 }
385 if (j1) {
386 if (j1>1) result += (j1-1)*comp_relative_overlap(i1,j1-2,k1,i2,j2,k2);
387 if (j2>0) result += j2*comp_relative_overlap(i1,j1-1,k1,i2,j2-1,k2);
388 return result;
389 }
390 if (k1) {
391 if (k1>1) result += (k1-1)*comp_relative_overlap(i1,j1,k1-2,i2,j2,k2);
392 if (k2>0) result += k2*comp_relative_overlap(i1,j1,k1-1,i2,j2,k2-1);
393 return result;
394 }
395
396 if (i2) {
397 if (i2>1) result += (i2-1)*comp_relative_overlap(i1,j1,k1,i2-2,j2,k2);
398 if (i1>0) result += i1*comp_relative_overlap(i1-1,j1,k1,i2-1,j2,k2);
399 return result;
400 }
401 if (j2) {
402 if (j2>1) result += (j2-1)*comp_relative_overlap(i1,j1,k1,i2,j2-2,k2);
403 if (j1>0) result += j1*comp_relative_overlap(i1,j1-1,k1,i2,j2-1,k2);
404 return result;
405 }
406 if (k2) {
407 if (k2>1) result += (k2-1)*comp_relative_overlap(i1,j1,k1,i2,j2,k2-2);
408 if (k1>0) result += k1*comp_relative_overlap(i1,j1,k1-1,i2,j2,k2-1);
409 return result;
410 }
411
412 return 1;
413}
414
415double
416GaussianShell::relative_overlap(int con,
417 int a1, int b1, int c1,
418 int a2, int b2, int c2) const
419{
420 int result = comp_relative_overlap(a1,b1,c1,a2,b2,c2);
421 return (double) result;
422}
423
424double
425GaussianShell::relative_overlap(const Ref<Integral>& ints,
426 int con, int func1, int func2) const
427{
428 if (puream[con]) {
429 // depends on how intv2 currently normalizes things
430 ExEnv::err0() << indent
431 << "GaussianShell::relative_overlap "
432 << "only implemented for Cartesians\n";
433 abort();
434 }
435
436 CartesianIter *i1p = ints->new_cartesian_iter(l[con]);
437 CartesianIter *i2p = ints->new_cartesian_iter(l[con]);
438
439 CartesianIter& i1 = *i1p;
440 CartesianIter& i2 = *i2p;
441
442 int i;
443 for (i1.start(), i=0; i<func1; i1.next(), i++);
444 for (i2.start(), i=0; i<func2; i2.next(), i++);
445
446 double ret = relative_overlap(con, i1.a(), i1.b(), i1.c(),
447 i2.a(), i2.b(), i2.c());
448
449 delete i1p;
450 delete i2p;
451
452 return ret;
453}
454
455void
456GaussianShell::print(ostream& os) const
457{
458 int i,j;
459
460 os << indent << "GaussianShell:\n" << incindent
461 << indent << "ncontraction = " << ncon << endl
462 << indent << "nprimitive = " << nprim << endl << indent
463 << "exponents:";
464
465 for (i=0; i<nprim; i++)
466 os << scprintf(" %f",exp[i]);
467
468 os << endl << indent << "l:";
469 for (i=0; i<ncon; i++)
470 os << scprintf(" %d", l[i]);
471
472 os << endl << indent << "type:";
473 for (i=0; i<ncon; i++)
474 os << scprintf(" %s", puream[i]?"pure":"cart");
475 os << endl;
476
477 for (i=0; i<ncon; i++) {
478 os << indent << scprintf("coef[%d]:",i);
479 for (j=0; j<nprim; j++)
480 os << scprintf(" %f",coef[i][j]);
481 os << endl;
482 }
483
484 os << decindent;
485}
486
487GaussianShell::~GaussianShell()
488{
489 delete[] l;
490 delete[] puream;
491 delete[] exp;
492
493 for (int i=0; i<ncon; i++) {
494 delete[] coef[i];
495 }
496
497 delete[] coef;
498}
499
500int
501GaussianShell::nfunction(int con) const
502{
503 return puream[con]?
504 ((l[con]<<1)+1):
505 (((l[con]+2)*(l[con]+1))>>1);
506}
507
508int
509GaussianShell::equiv(const GaussianShell *s)
510{
511 if (nprim != s->nprim) return 0;
512 if (ncon != s->ncon) return 0;
513 for (int i=0; i<ncon; i++) {
514 if (l[i] != s->l[i]) return 0;
515 if (puream[i] != s->puream[i]) return 0;
516 if (fabs((exp[i] - s->exp[i])/exp[i]) > 1.0e-13) return 0;
517 for (int j=0; j<nprim; j++) {
518 if (coef[i][j] != 0.0) {
519 if (fabs((coef[i][j] - s->coef[i][j])/coef[i][j]) > 1.0e-13) return 0;
520 }
521 else {
522 if (fabs((coef[i][j] - s->coef[i][j])) > 1.0e-13) return 0;
523 }
524 }
525 }
526 return 1;
527}
528
529double
530GaussianShell::extent(double threshold) const
531{
532 double tol = 0.1;
533 double r0 = tol;
534 double r1 = 3.0*r0;
535 double b0 = monobound(r0);
536 double b1 = monobound(r1);
537 //ExEnv::outn() << "r0 = " << r0 << " b0 = " << b0 << endl;
538 //ExEnv::outn() << "r1 = " << r0 << " b1 = " << b1 << endl;
539 if (b0 <= threshold) {
540 return r0;
541 }
542 // step out until r0 and r1 bracket the return value
543 while (b1 > threshold) {
544 r0 = r1;
545 r1 = 3.0*r0;
546 b0 = b1;
547 b1 = monobound(r1);
548 //ExEnv::outn() << "r0 = " << r0 << " b0 = " << b0 << endl;
549 //ExEnv::outn() << "r1 = " << r0 << " b1 = " << b1 << endl;
550 }
551 while (r1 - r0 > 0.1) {
552 double rtest = 0.5*(r0+r1);
553 double btest = monobound(rtest);
554 if (btest <= threshold) {
555 b1 = btest;
556 r1 = rtest;
557 //ExEnv::outn() << "r1 = " << r0 << " b1 = " << b0 << endl;
558 }
559 else {
560 b0 = btest;
561 r0 = rtest;
562 //ExEnv::outn() << "r0 = " << r0 << " b0 = " << b0 << endl;
563 }
564 }
565 return r1;
566}
567
568/////////////////////////////////////////////////////////////////////////////
569
570// Local Variables:
571// mode: c++
572// c-file-style: "CLJ"
573// End:
Note: See TracBrowser for help on using the repository browser.