source: ThirdParty/mpqc_open/src/lib/chemistry/qc/basis/gaussbas.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: 34.1 KB
Line 
1//
2// gaussbas.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 <stdio.h>
33#include <stdexcept>
34
35#include <scconfig.h>
36#ifdef HAVE_SSTREAM
37# include <sstream>
38#else
39# include <strstream.h>
40#endif
41
42#include <util/keyval/keyval.h>
43#include <util/misc/formio.h>
44#include <util/misc/newstring.h>
45#include <util/state/stateio.h>
46#include <math/scmat/blocked.h>
47#include <chemistry/molecule/molecule.h>
48#include <chemistry/qc/basis/gaussshell.h>
49#include <chemistry/qc/basis/gaussbas.h>
50#include <chemistry/qc/basis/files.h>
51#include <chemistry/qc/basis/cartiter.h>
52#include <chemistry/qc/basis/transform.h>
53#include <chemistry/qc/basis/integral.h>
54
55using namespace std;
56using namespace sc;
57
58static ClassDesc GaussianBasisSet_cd(
59 typeid(GaussianBasisSet),"GaussianBasisSet",3,"public SavableState",
60 0, create<GaussianBasisSet>, create<GaussianBasisSet>);
61
62static bool
63skip_atom(bool skip_ghosts, bool include_q,
64 const Ref<Molecule> &mol, int iatom)
65{
66 if (skip_ghosts && mol->charge(iatom) == 0.0) return true;
67 // charges do not have basis functions
68 if (!include_q && mol->atom_symbol(iatom) == "Q") return true;
69 return false;
70}
71
72GaussianBasisSet::GaussianBasisSet(const Ref<KeyVal>&topkeyval)
73{
74 molecule_ << topkeyval->describedclassvalue("molecule");
75 if (molecule_.null()) {
76 ExEnv::err0() << indent << "GaussianBasisSet: no \"molecule\"\n";
77 abort();
78 }
79
80 // see if the user requests pure am or cartesian functions
81 int pure;
82 pure = topkeyval->booleanvalue("puream");
83 if (topkeyval->error() != KeyVal::OK) pure = -1;
84
85 // construct a keyval that contains the basis library
86 Ref<KeyVal> keyval;
87
88 if (topkeyval->exists("basisfiles")) {
89 Ref<MessageGrp> grp = MessageGrp::get_default_messagegrp();
90 Ref<ParsedKeyVal> parsedkv = new ParsedKeyVal();
91 char *in_char_array;
92 if (grp->me() == 0) {
93#ifdef HAVE_SSTREAM
94 ostringstream ostrs;
95#else
96 ostrstream ostrs;
97#endif
98 // Look at the basisdir and basisfiles variables to find out what
99 // basis set files are to be read in. The files are read on node
100 // 0 only.
101 ParsedKeyVal::cat_files("basis",topkeyval,ostrs);
102#ifdef HAVE_SSTREAM
103 int n = 1 + strlen(ostrs.str().c_str());
104 in_char_array = strcpy(new char[n],ostrs.str().c_str());
105#else
106 ostrs << ends;
107 in_char_array = ostrs.str();
108 int n = ostrs.pcount();
109#endif
110 grp->bcast(n);
111 grp->bcast(in_char_array, n);
112 }
113 else {
114 int n;
115 grp->bcast(n);
116 in_char_array = new char[n];
117 grp->bcast(in_char_array, n);
118 }
119 parsedkv->parse_string(in_char_array);
120 delete[] in_char_array;
121 Ref<KeyVal> libkeyval = parsedkv.pointer();
122 keyval = new AggregateKeyVal(topkeyval,libkeyval);
123 }
124 else {
125 keyval = topkeyval;
126 }
127
128 // if there isn't a matrixkit in the input, init2() will assign the
129 // default matrixkit
130 matrixkit_ << keyval->describedclassvalue("matrixkit");
131
132 // Bases keeps track of what basis set data bases have already
133 // been read in. It also handles the conversion of basis
134 // names to file names.
135 BasisFileSet bases(keyval);
136 init(molecule_,keyval,bases,1,pure);
137}
138
139GaussianBasisSet::GaussianBasisSet(UnitType)
140{
141 molecule_ = new Molecule;
142 molecule_->add_atom(molecule()->atominfo()->string_to_Z("Q"),
143 0.0, 0.0, 0.0, // xyz
144 "dummy", // label
145 0.0, // no mass
146 1, 0.0 // no charge
147 );
148 name_ = new_string("Unit");
149 label_ = new_string(name_);
150 shell_ = new GaussianShell*[1];
151
152 double *exp = new double[1];
153 int *am = new int[1];
154 int *pure = new int[1];
155 double **c = new double*[1];
156 *c = new double[1];
157 exp[0] = 0.0;
158 am[0] = 0;
159 pure[0] = 0;
160 c[0][0] = 1.0;
161 shell_[0] = new GaussianShell(1,1,exp,am,pure,c,
162 GaussianShell::Unnormalized,
163 false);
164
165 ncenter_ = 1;
166 nshell_ = 1;
167 center_to_nshell_.push_back(1);
168 init2(0,1);
169}
170
171GaussianBasisSet::GaussianBasisSet(const GaussianBasisSet& gbs) :
172 molecule_(gbs.molecule_),
173 matrixkit_(gbs.matrixkit_),
174 basisdim_(gbs.basisdim_),
175 ncenter_(gbs.ncenter_),
176 nshell_(gbs.nshell_)
177{
178 int i,j;
179
180 name_ = new_string(gbs.name_);
181 label_ = new_string(gbs.label_);
182
183 center_to_nshell_.resize(ncenter_);
184 for (i=0; i < ncenter_; i++) {
185 center_to_nshell_[i] = gbs.center_to_nshell_[i];
186 }
187
188 shell_ = new GaussianShell*[nshell_];
189 for (i=0; i<nshell_; i++) {
190 const GaussianShell& gsi = gbs(i);
191
192 int nc=gsi.ncontraction();
193 int np=gsi.nprimitive();
194
195 int *ams = new int[nc];
196 int *pure = new int[nc];
197 double *exps = new double[np];
198 double **coefs = new double*[nc];
199
200 for (j=0; j < nc; j++) {
201 ams[j] = gsi.am(j);
202 pure[j] = gsi.is_pure(j);
203 coefs[j] = new double[np];
204 for (int k=0; k < np; k++)
205 coefs[j][k] = gsi.coefficient_unnorm(j,k);
206 }
207
208 for (j=0; j < np; j++)
209 exps[j] = gsi.exponent(j);
210
211 shell_[i] = new GaussianShell(nc, np, exps, ams, pure, coefs,
212 GaussianShell::Unnormalized);
213 }
214
215 init2();
216}
217
218GaussianBasisSet::GaussianBasisSet(const char* name,
219 const char* label,
220 const Ref<Molecule>& molecule,
221 const Ref<SCMatrixKit>& matrixkit,
222 const RefSCDimension& basisdim,
223 const int ncenter,
224 const int nshell,
225 GaussianShell** shell,
226 const std::vector<int>& center_to_nshell) :
227 molecule_(molecule),
228 matrixkit_(matrixkit),
229 basisdim_(basisdim),
230 ncenter_(ncenter),
231 nshell_(nshell),
232 shell_(shell),
233 center_to_nshell_(center_to_nshell)
234{
235 name_ = new_string(name);
236 label_ = new_string(label);
237
238 init2();
239}
240
241Ref<GaussianBasisSet>
242GaussianBasisSet::operator+(const Ref<GaussianBasisSet>& B)
243{
244 GaussianBasisSet* b = B.pointer();
245 if (molecule_.pointer() != b->molecule_.pointer())
246 throw std::runtime_error("GaussianBasisSet::concatenate -- cannot concatenate basis sets, molecules are different");
247
248 Ref<Molecule> molecule = molecule_;
249 Ref<SCMatrixKit> matrixkit = matrixkit_;
250 const int ncenter = ncenter_;
251 const int nshell = nshell_ + b->nshell_;
252 std::vector<int> center_to_nshell(ncenter);
253
254 GaussianShell** shell = new GaussianShell*[nshell];
255 int* func_per_shell = new int[nshell];
256
257 for(int c=0; c<ncenter; c++) {
258
259 int ns1 = center_to_nshell_[c];
260 int ns2 = b->center_to_nshell_[c];
261 int ns = ns1+ns2;
262 int s1off = center_to_shell_[c];
263 int s2off = b->center_to_shell_[c];
264 int soff = s1off + s2off;
265 center_to_nshell[c] = ns;
266
267 for (int i=0; i<ns; i++) {
268 const GaussianShell* gsi;
269 if (i < ns1)
270 gsi = shell_[s1off + i];
271 else
272 gsi = b->shell_[s2off + i - ns1];
273
274 int nc=gsi->ncontraction();
275 int np=gsi->nprimitive();
276 func_per_shell[soff + i] = gsi->nfunction();
277
278 int *ams = new int[nc];
279 int *pure = new int[nc];
280 double *exps = new double[np];
281 double **coefs = new double*[nc];
282
283 for (int j=0; j < nc; j++) {
284 ams[j] = gsi->am(j);
285 pure[j] = gsi->is_pure(j);
286 coefs[j] = new double[np];
287 for (int k=0; k < np; k++)
288 coefs[j][k] = gsi->coefficient_unnorm(j,k);
289 }
290
291 for (int j=0; j < np; j++)
292 exps[j] = gsi->exponent(j);
293
294 shell[soff + i] = new GaussianShell(nc, np, exps, ams, pure, coefs,
295 GaussianShell::Unnormalized);
296 }
297 }
298
299 int nbas = nbasis() + b->nbasis();
300 RefSCDimension basisdim
301 = new SCDimension(nbas, nshell, func_per_shell, "basis set dimension");
302
303 const char* A_name = name();
304 const char* B_name = B->name();
305 const char* AplusB_name = 0;
306 if (!A_name && !B_name) {
307 ostringstream oss;
308 oss << "[" << A_name << "]+[" << B_name << "]";
309 std::string tmpname = oss.str();
310 AplusB_name = strcpy(new char[tmpname.size()+1],tmpname.c_str());
311 }
312 const char* AplusB_label = 0;
313 if (AplusB_name) {
314 AplusB_label = AplusB_name;
315 }
316 else {
317 ostringstream oss;
318 const char* A_label = label();
319 const char* B_label = B->label();
320 oss << "[" << A_label << "]+[" << B_label << "]";
321 std::string tmpname = oss.str();
322 AplusB_label = strcpy(new char[tmpname.size()+1],tmpname.c_str());
323 }
324 Ref<GaussianBasisSet> AplusB
325 = new GaussianBasisSet(AplusB_name, AplusB_label, molecule,
326 matrixkit, basisdim, ncenter,
327 nshell, shell, center_to_nshell);
328
329 delete[] func_per_shell;
330 delete[] AplusB_name;
331 if (AplusB_name != AplusB_label)
332 delete[] AplusB_label;
333
334 return AplusB;
335}
336
337GaussianBasisSet::GaussianBasisSet(StateIn&s):
338 SavableState(s)
339{
340 matrixkit_ = SCMatrixKit::default_matrixkit();
341
342 if (s.version(::class_desc<GaussianBasisSet>()) < 3) {
343 // read the duplicate length saved in older versions
344 int junk;
345 s.get(junk);
346 }
347 s.get(center_to_nshell_);
348
349 molecule_ << SavableState::restore_state(s);
350 basisdim_ << SavableState::restore_state(s);
351
352
353 ncenter_ = center_to_nshell_.size();
354 s.getstring(name_);
355 s.getstring(label_);
356
357 nshell_ = 0;
358 int i;
359 for (i=0; i<ncenter_; i++) {
360 nshell_ += center_to_nshell_[i];
361 }
362
363 shell_ = new GaussianShell*[nshell_];
364 for (i=0; i<nshell_; i++) {
365 shell_[i] = new GaussianShell(s);
366 }
367
368 init2();
369}
370
371void
372GaussianBasisSet::save_data_state(StateOut&s)
373{
374 s.put(center_to_nshell_);
375
376 SavableState::save_state(molecule_.pointer(),s);
377 SavableState::save_state(basisdim_.pointer(),s);
378
379 s.putstring(name_);
380 s.putstring(label_);
381 for (int i=0; i<nshell_; i++) {
382 shell_[i]->save_object_state(s);
383 }
384}
385
386void
387GaussianBasisSet::init(Ref<Molecule>&molecule,
388 Ref<KeyVal>&keyval,
389 BasisFileSet& bases,
390 int have_userkeyval,
391 int pur)
392{
393 int pure, havepure;
394 pure = pur;
395 if (pur == -1) {
396 havepure = 0;
397 }
398 else {
399 havepure = 1;
400 }
401
402 int skip_ghosts = keyval->booleanvalue("skip_ghosts");
403 bool missing_ok = keyval->booleanvalue("missing_ok");
404 bool include_q = keyval->booleanvalue("include_q");
405
406 name_ = keyval->pcharvalue("name");
407 int have_custom, nelement;
408
409 if (keyval->exists("basis")) {
410 have_custom = 1;
411 nelement = keyval->count("element");
412 }
413 else {
414 have_custom = 0;
415 nelement = 0;
416 if (!name_) {
417 ExEnv::err0() << indent
418 << "GaussianBasisSet: No name given for basis set\n";
419 abort();
420 }
421 }
422
423 // Construct label_
424 if (name_)
425 label_ = new_string(name_);
426 else {
427 if (have_custom) {
428 ostringstream oss;
429 Ref<AtomInfo> atominfo = molecule->atominfo();
430 // If element is given then construct label_ using element symbol and basis name
431 // combinations, e.g. "{ [Fe S1] [Ni S2] [C aug-cc-pVDZ] }"
432 if (nelement) {
433 oss << "{ ";
434 for(int e=0; e<nelement; e++) {
435 char* tmpelementname = keyval->pcharvalue("element", e);
436 int Z = atominfo->string_to_Z(tmpelementname);
437 std::string elemsymbol = atominfo->symbol(Z);
438 char* basisname = keyval->pcharvalue("basis", e);
439 oss << "[" << elemsymbol << " " << basisname << "] ";
440 }
441 oss << "}";
442 }
443 // If element is not given then construct label_ using basis names for each atom
444 // e.g. "[ aug-cc-pVDZ cc-pVDZ cc-pVDZ ]"
445 else {
446 int natom = molecule->natom();
447 oss << "[ ";
448 for(int a=0; a<natom; a++) {
449 char* basisname = keyval->pcharvalue("basis", a);
450 oss << basisname << " ";
451 }
452 oss << "]";
453 }
454 std::string label = oss.str();
455 label_ = new char[label.size() + 1];
456 strcpy(label_,label.c_str());
457 }
458 }
459
460
461 // construct prefixes for each atom: :basis:<atom>:<basisname>:<shell#>
462 // and read in the shell
463 nbasis_ = 0;
464 int ishell = 0;
465 ncenter_ = molecule->natom();
466 int iatom;
467 for (iatom=0; iatom < ncenter_; iatom++) {
468 if (skip_atom(skip_ghosts,include_q,molecule,iatom)) continue;
469 int Z = molecule->Z(iatom);
470 // see if there is a specific basisname for this atom
471 char* sbasisname = 0;
472 if (have_custom && !nelement) {
473 sbasisname = keyval->pcharvalue("basis",iatom);
474 }
475 else if (nelement) {
476 int i;
477 for (i=0; i<nelement; i++) {
478 char *tmpelementname = keyval->pcharvalue("element", i);
479 int tmpZ = molecule->atominfo()->string_to_Z(tmpelementname);
480 if (tmpZ == Z) {
481 sbasisname = keyval->pcharvalue("basis", i);
482 break;
483 }
484 delete[] tmpelementname;
485 }
486 }
487 if (!sbasisname) {
488 if (!name_) {
489 ExEnv::err0()
490 << indent << "GaussianBasisSet: no basis name for atom "
491 << iatom
492 << " (Z=" <<molecule->atominfo()->name(Z) << ")"
493 << std::endl;
494 abort();
495 }
496 sbasisname = strcpy(new char[strlen(name_)+1],name_);
497 }
498 std::string name(molecule->atominfo()->name(Z));
499 ishell += count_shells_(keyval, name.c_str(),
500 sbasisname, bases, havepure, pure, missing_ok);
501 delete[] sbasisname;
502 }
503 nshell_ = ishell;
504 shell_ = new GaussianShell*[nshell_];
505 ishell = 0;
506 center_to_nshell_.resize(ncenter_);
507 for (iatom=0; iatom<ncenter_; iatom++) {
508 if (skip_atom(skip_ghosts,include_q,molecule,iatom)) {
509 center_to_nshell_[iatom] = 0;
510 continue;
511 }
512 int Z = molecule->Z(iatom);
513 // see if there is a specific basisname for this atom
514 char* sbasisname = 0;
515 if (have_custom && !nelement) {
516 sbasisname = keyval->pcharvalue("basis",iatom);
517 }
518 else if (nelement) {
519 int i;
520 for (i=0; i<nelement; i++) {
521 char *tmpelementname = keyval->pcharvalue("element", i);
522 int tmpZ = molecule->atominfo()->string_to_Z(tmpelementname);
523 if (tmpZ == Z) {
524 sbasisname = keyval->pcharvalue("basis", i);
525 break;
526 }
527 delete[] tmpelementname;
528 }
529 }
530 if (!sbasisname) {
531 if (!name_) {
532 ExEnv::err0()
533 << indent << "GaussianBasisSet: no basis name for atom "
534 << iatom
535 << " (Z=" <<molecule->atominfo()->name(Z) << ")"
536 << std::endl;
537 abort();
538 }
539 sbasisname = strcpy(new char[strlen(name_)+1],name_);
540 }
541
542 int ishell_old = ishell;
543 std::string name(molecule->atominfo()->name(Z));
544 get_shells_(ishell, keyval, name.c_str(),
545 sbasisname, bases, havepure, pure, missing_ok);
546
547 center_to_nshell_[iatom] = ishell - ishell_old;
548
549 delete[] sbasisname;
550 }
551
552 // delete the name_ if the basis set is customized
553 if (have_custom) {
554 delete[] name_;
555 name_ = 0;
556 }
557
558 // finish with the initialization steps that don't require any
559 // external information
560 init2(skip_ghosts,include_q);
561}
562
563double
564GaussianBasisSet::r(int icenter, int xyz) const
565{
566 return molecule_->r(icenter,xyz);
567}
568
569void
570GaussianBasisSet::init2(int skip_ghosts,bool include_q)
571{
572 // center_to_shell_ and shell_to_center_
573 shell_to_center_.resize(nshell_);
574 center_to_shell_.resize(ncenter_);
575 center_to_nbasis_.resize(ncenter_);
576 int ishell = 0;
577 for (int icenter=0; icenter<ncenter_; icenter++) {
578 if (skip_atom(skip_ghosts,include_q,molecule(),icenter)) {
579 center_to_shell_[icenter] = -1;
580 center_to_nbasis_[icenter] = 0;
581 continue;
582 }
583 int j;
584 center_to_shell_[icenter] = ishell;
585 center_to_nbasis_[icenter] = 0;
586 for (j = 0; j<center_to_nshell_[icenter]; j++) {
587 center_to_nbasis_[icenter] += shell_[ishell+j]->nfunction();
588 }
589 ishell += center_to_nshell_[icenter];
590 for (j = center_to_shell_[icenter]; j<ishell; j++) {
591 shell_to_center_[j] = icenter;
592 }
593 }
594
595 // compute nbasis_ and shell_to_function_[]
596 shell_to_function_.resize(nshell_);
597 shell_to_primitive_.resize(nshell_);
598 nbasis_ = 0;
599 nprim_ = 0;
600 for (ishell=0; ishell<nshell_; ishell++) {
601 shell_to_function_[ishell] = nbasis_;
602 shell_to_primitive_[ishell] = nprim_;
603 nbasis_ += shell_[ishell]->nfunction();
604 nprim_ += shell_[ishell]->nprimitive();
605 }
606
607 // would like to do this in function_to_shell(), but it is const
608 int n = nbasis();
609 int nsh = nshell();
610 function_to_shell_.resize(n);
611 int ifunc = 0;
612 for (int i=0; i<nsh; i++) {
613 int nfun = operator()(i).nfunction();
614 for (int j=0; j<nfun; j++) {
615 function_to_shell_[ifunc] = i;
616 ifunc++;
617 }
618 }
619
620 // figure out if any shells are spherical harmonics
621 has_pure_ = false;
622 for(int i=0; i<nsh; i++)
623 has_pure_ = has_pure_ || shell_[i]->has_pure();
624
625 if (matrixkit_.null())
626 matrixkit_ = SCMatrixKit::default_matrixkit();
627
628 so_matrixkit_ = new BlockedSCMatrixKit(matrixkit_);
629
630 if (basisdim_.null()) {
631 int nb = nshell();
632 int *bs = new int[nb];
633 for (int s=0; s < nb; s++)
634 bs[s] = shell(s).nfunction();
635 basisdim_ = new SCDimension(nbasis(), nb, bs, "basis set dimension");
636 delete[] bs;
637 }
638}
639
640void
641GaussianBasisSet::set_matrixkit(const Ref<SCMatrixKit>& mk)
642{
643 matrixkit_ = mk;
644 so_matrixkit_ = new BlockedSCMatrixKit(matrixkit_);
645}
646
647
648int
649GaussianBasisSet::count_shells_(Ref<KeyVal>& keyval, const char* element, const char* basisname, BasisFileSet& bases,
650 int havepure, int pure, bool missing_ok)
651{
652 int nshell = 0;
653 char keyword[KeyVal::MaxKeywordLength];
654
655 sprintf(keyword,":basis:%s:%s",element,basisname);
656 bool exists = keyval->exists(keyword);
657 if (!exists) {
658 keyval = bases.keyval(keyval, basisname);
659 exists = keyval->exists(keyword);
660 if (!exists) {
661 if (missing_ok) return 0;
662 ExEnv::err0() << indent
663 << scprintf("GaussianBasisSet::count_shells_ couldn't find \"%s\":\n", keyword);
664 keyval->errortrace(ExEnv::err0());
665 throw std::runtime_error("GaussianBasisSet::count_shells_ -- couldn't find the basis set");
666 }
667 }
668
669 // Check if the basis set is an array of shells
670 keyval->count(keyword);
671 if (keyval->error() != KeyVal::OK) {
672 nshell = count_even_temp_shells_(keyval, element, basisname, havepure, pure);
673 }
674 else {
675 recursively_get_shell(nshell, keyval, element, basisname,
676 bases, havepure, pure, 0, false);
677 }
678
679 return nshell;
680}
681
682void
683GaussianBasisSet::get_shells_(int& ishell, Ref<KeyVal>& keyval, const char* element, const char* basisname, BasisFileSet& bases,
684 int havepure, int pure, bool missing_ok)
685{
686 char keyword[KeyVal::MaxKeywordLength];
687
688 sprintf(keyword,":basis:%s:%s:am",
689 element,basisname);
690 if (keyval->exists(keyword)) {
691 get_even_temp_shells_(ishell, keyval, element, basisname, havepure, pure);
692 }
693 else {
694 recursively_get_shell(ishell, keyval, element, basisname,
695 bases, havepure, pure, 1, missing_ok);
696 }
697}
698
699
700int
701GaussianBasisSet::count_even_temp_shells_(Ref<KeyVal>& keyval, const char* element, const char* basisname,
702 int havepure, int pure)
703{
704 int nshell = 0;
705 char keyword[KeyVal::MaxKeywordLength];
706
707 sprintf(keyword,":basis:%s:%s:am",element,basisname);
708 if (!keyval->exists(keyword)) {
709 sprintf(keyword,":basis:%s:%s",element,basisname);
710 ExEnv::err0() << indent
711 << scprintf("GaussianBasisSet::count_even_temp_shells_ -- couldn't read \"%s\":\n", keyword);
712 throw std::runtime_error("GaussianBasisSet::count_even_temp_shells_ -- basis set specification is invalid");
713 }
714
715 // count the number of even-tempered primitive blocks
716 int nblocks = keyval->count(keyword) - 1;
717 if (keyval->error() != KeyVal::OK) {
718 ExEnv::err0() << indent
719 << scprintf("GaussianBasisSet::count_even_temp_shells_ -- couldn't read \"%s\":\n", keyword);
720 throw std::runtime_error("GaussianBasisSet::count_even_temp_shells_ -- failed to read am");
721 }
722 if (nblocks == -1)
723 return 0;
724
725 sprintf(keyword,":basis:%s:%s:nprim", element, basisname);
726 int j = keyval->count(keyword) - 1;
727 if (nblocks != j) {
728 ExEnv::err0() << indent
729 << scprintf("GaussianBasisSet::count_even_temp_shells_ -- problem reading \"%s\":\n", keyword);
730 throw std::runtime_error("GaussianBasisSet::count_even_temp_shells_ -- am and nprim have different dimensions");
731 }
732
733 for(int b=0; b<=nblocks; b++) {
734 sprintf(keyword,":basis:%s:%s:nprim:%d", element, basisname, b);
735 int nprim = keyval->intvalue(keyword);
736 if (nprim <= 0) {
737 ExEnv::err0() << indent
738 << scprintf("GaussianBasisSet::count_even_temp_shells_ -- problem with \"%s\":\n", keyword);
739 throw std::runtime_error("GaussianBasisSet::count_shells_ -- the number of primitives has to be positive");
740 }
741 nshell += nprim;
742 }
743
744 return nshell;
745}
746
747
748void
749GaussianBasisSet::get_even_temp_shells_(int& ishell, Ref<KeyVal>& keyval, const char* element, const char* basisname,
750 int havepure, int pure)
751{
752 char keyword[KeyVal::MaxKeywordLength];
753
754 // count the number of even-tempered primitive blocks
755 sprintf(keyword,":basis:%s:%s:am",
756 element,basisname);
757 int nblocks = keyval->count(keyword) - 1;
758 if (keyval->error() != KeyVal::OK) {
759 ExEnv::err0() << indent
760 << scprintf("GaussianBasisSet::get_even_temp_shells_ -- couldn't read \"%s\":\n", keyword);
761 throw std::runtime_error("GaussianBasisSet::get_even_temp_shells_ -- failed to read am");
762 }
763 if (nblocks == -1)
764 return;
765
766 sprintf(keyword,":basis:%s:%s:nprim", element, basisname);
767 int j = keyval->count(keyword) - 1;
768 if (nblocks != j) {
769 ExEnv::err0() << indent
770 << scprintf("GaussianBasisSet::get_even_temp_shells_ -- problem reading \"%s\":\n", keyword);
771 throw std::runtime_error("GaussianBasisSet::get_even_temp_shells_ -- am and nprim have different dimensions");
772 }
773
774 sprintf(keyword,":basis:%s:%s:last_exp", element, basisname);
775 bool have_last_exp = keyval->exists(keyword);
776
777 sprintf(keyword,":basis:%s:%s:first_exp", element, basisname);
778 bool have_first_exp = keyval->exists(keyword);
779
780 sprintf(keyword,":basis:%s:%s:exp_ratio", element, basisname);
781 bool have_exp_ratio = keyval->exists(keyword);
782
783 if ( !have_first_exp && !have_last_exp )
784 throw std::runtime_error("GaussianBasisSet::get_even_temp_shells_ -- neither last_exp nor first_exp has been specified");
785
786 if ( have_first_exp && have_last_exp && have_exp_ratio)
787 throw std::runtime_error("GaussianBasisSet::get_even_temp_shells_ -- only two of (last_exp,first_exp,exp_ratio) can be specified");
788
789 if ( !have_first_exp && !have_last_exp && have_exp_ratio)
790 throw std::runtime_error("GaussianBasisSet::get_even_temp_shells_ -- any two of (last_exp,first_exp,exp_ratio) must be specified");
791
792 for(int b=0; b<=nblocks; b++) {
793
794 sprintf(keyword,":basis:%s:%s:nprim:%d", element, basisname, b);
795 int nprim = keyval->intvalue(keyword);
796 if (nprim <= 0) {
797 ExEnv::err0() << indent
798 << scprintf("GaussianBasisSet::get_even_temp_shells_ -- problem with \"%s\":\n", keyword);
799 throw std::runtime_error("GaussianBasisSet::get_even_temp_shells_ -- the number of primitives has to be positive");
800 }
801
802 sprintf(keyword,":basis:%s:%s:am:%d", element, basisname, b);
803 int l = keyval->intvalue(keyword);
804 if (l < 0) {
805 ExEnv::err0() << indent
806 << scprintf("GaussianBasisSet::get_even_temp_shells_ -- problem with \"%s\":\n", keyword);
807 throw std::runtime_error("GaussianBasisSet::get_even_temp_shells_ -- angular momentum has to be non-negative");
808 }
809
810 double alpha0, alphaN, beta;
811 if (have_first_exp) {
812 sprintf(keyword,":basis:%s:%s:first_exp:%d", element, basisname, b);
813 alpha0 = keyval->doublevalue(keyword);
814 if (alpha0 <= 0.0) {
815 ExEnv::err0() << indent
816 << scprintf("GaussianBasisSet::get_even_temp_shells_ -- problem with \"%s\":\n", keyword);
817 throw std::runtime_error("GaussianBasisSet::get_even_temp_shells_ -- orbital exponents have to be positive");
818 }
819 }
820
821 if (have_last_exp) {
822 sprintf(keyword,":basis:%s:%s:last_exp:%d", element, basisname, b);
823 alphaN = keyval->doublevalue(keyword);
824 if (alphaN <= 0.0) {
825 ExEnv::err0() << indent
826 << scprintf("GaussianBasisSet::get_even_temp_shells_ -- problem with \"%s\":\n", keyword);
827 throw std::runtime_error("GaussianBasisSet::get_even_temp_shells_ -- orbital exponents have to be positive");
828 }
829 }
830
831 if (have_last_exp && have_first_exp) {
832 if (alphaN > alpha0) {
833 ExEnv::err0() << indent
834 << scprintf("GaussianBasisSet::get_even_temp_shells_ -- problem with \"%s\":\n", keyword);
835 throw std::runtime_error("GaussianBasisSet::get_even_temp_shells_ -- last_exps[i] must be smaller than first_exp[i]");
836 }
837 if (nprim > 1)
838 beta = pow(alpha0/alphaN,1.0/(nprim-1));
839 else
840 beta = 1.0;
841 }
842 else {
843 sprintf(keyword,":basis:%s:%s:exp_ratio:%d", element, basisname, b);
844 beta = keyval->doublevalue(keyword);
845 if (beta <= 1.0) {
846 ExEnv::err0() << indent
847 << scprintf("GaussianBasisSet::get_even_temp_shells_ -- problem with \"%s\":\n", keyword);
848 throw std::runtime_error("GaussianBasisSet::get_even_temp_shells_ -- exponent ratio has to be greater than 1.0");
849 }
850 if (have_last_exp)
851 alpha0 = alphaN * pow(beta,nprim-1);
852 }
853
854 double alpha = alpha0;
855 for(int p=0; p<nprim; p++, alpha /= beta ) {
856 int* am = new int[1];
857 double* exps = new double[1];
858 double** coeffs = new double*[1];
859 coeffs[0] = new double[1];
860
861 exps[0] = alpha;
862 am[0] = l;
863 coeffs[0][0] = 1.0;
864
865 if (l <= 1)
866 shell_[ishell] = new GaussianShell(1,1,exps,am,GaussianShell::Cartesian,coeffs,GaussianShell::Normalized);
867 else if (havepure)
868 shell_[ishell] = new GaussianShell(1,1,exps,am,GaussianShell::Pure,coeffs,GaussianShell::Normalized);
869 else
870 shell_[ishell] = new GaussianShell(1,1,exps,am,GaussianShell::Cartesian,coeffs,GaussianShell::Normalized);
871 ishell++;
872
873 // Recompute beta at each step to maintain accuracy
874 if (have_last_exp && have_first_exp) {
875 int nprim_left = nprim - p;
876 if (nprim_left > 1)
877 beta = pow(alpha/alphaN,1.0/(nprim_left-1));
878 else
879 beta = 1.0;
880 }
881 }
882 }
883}
884
885void
886GaussianBasisSet::
887 recursively_get_shell(int&ishell,Ref<KeyVal>&keyval,
888 const char*element,
889 const char*basisname,
890 BasisFileSet &bases,
891 int havepure,int pure,
892 int get, bool missing_ok)
893{
894 char keyword[KeyVal::MaxKeywordLength],prefix[KeyVal::MaxKeywordLength];
895
896 sprintf(keyword,":basis:%s:%s",
897 element,basisname);
898 int count = keyval->count(keyword);
899 if (keyval->error() != KeyVal::OK) {
900 keyval = bases.keyval(keyval, basisname);
901 }
902 count = keyval->count(keyword);
903 if (keyval->error() != KeyVal::OK) {
904 if (missing_ok) return;
905 ExEnv::err0() << indent
906 << scprintf("GaussianBasisSet:: couldn't find \"%s\":\n", keyword);
907 keyval->errortrace(ExEnv::err0());
908 throw std::runtime_error("GaussianBasisSet::recursively_get_shell -- couldn't find the basis set");
909 }
910 if (!count) return;
911 for (int j=0; j<count; j++) {
912 sprintf(prefix,":basis:%s:%s",
913 element,basisname);
914 Ref<KeyVal> prefixkeyval = new PrefixKeyVal(keyval,prefix,j);
915 if (prefixkeyval->exists("get")) {
916 char* newbasis = prefixkeyval->pcharvalue("get");
917 if (!newbasis) {
918 ExEnv::err0() << indent << "GaussianBasisSet: "
919 << scprintf("error processing get for \"%s\"\n", prefix);
920 keyval->errortrace(ExEnv::err0());
921 exit(1);
922 }
923 recursively_get_shell(ishell,keyval,element,newbasis,bases,
924 havepure,pure,get,missing_ok);
925 delete[] newbasis;
926 }
927 else {
928 if (get) {
929 if (havepure) shell_[ishell] = new GaussianShell(prefixkeyval,pure);
930 else shell_[ishell] = new GaussianShell(prefixkeyval);
931 }
932 ishell++;
933 }
934 }
935}
936
937GaussianBasisSet::~GaussianBasisSet()
938{
939 delete[] name_;
940 delete[] label_;
941
942 int ii;
943 for (ii=0; ii<nshell_; ii++) {
944 delete shell_[ii];
945 }
946 delete[] shell_;
947}
948
949int
950GaussianBasisSet::max_nfunction_in_shell() const
951{
952 int i;
953 int max = 0;
954 for (i=0; i<nshell_; i++) {
955 if (max < shell_[i]->nfunction()) max = shell_[i]->nfunction();
956 }
957 return max;
958}
959
960int
961GaussianBasisSet::max_ncontraction() const
962{
963 int i;
964 int max = 0;
965 for (i=0; i<nshell_; i++) {
966 if (max < shell_[i]->ncontraction()) max = shell_[i]->ncontraction();
967 }
968 return max;
969}
970
971int
972GaussianBasisSet::max_angular_momentum() const
973{
974 int i;
975 int max = 0;
976 for (i=0; i<nshell_; i++) {
977 int maxshi = shell_[i]->max_angular_momentum();
978 if (max < maxshi) max = maxshi;
979 }
980 return max;
981}
982
983int
984GaussianBasisSet::max_cartesian() const
985{
986 int i;
987 int max = 0;
988 for (i=0; i<nshell_; i++) {
989 int maxshi = shell_[i]->max_cartesian();
990 if (max < maxshi) max = maxshi;
991 }
992 return max;
993}
994
995int
996GaussianBasisSet::max_ncartesian_in_shell(int aminc) const
997{
998 int i;
999 int max = 0;
1000 for (i=0; i<nshell_; i++) {
1001 int maxshi = shell_[i]->ncartesian_with_aminc(aminc);
1002 if (max < maxshi) max = maxshi;
1003 }
1004 return max;
1005}
1006
1007int
1008GaussianBasisSet::max_nprimitive_in_shell() const
1009{
1010 int i;
1011 int max = 0;
1012 for (i=0; i<nshell_; i++) {
1013 if (max < shell_[i]->nprimitive()) max = shell_[i]->nprimitive();
1014 }
1015 return max;
1016}
1017
1018int
1019GaussianBasisSet::max_am_for_contraction(int con) const
1020{
1021 int i;
1022 int max = 0;
1023 for (i=0; i<nshell_; i++) {
1024 if (shell_[i]->ncontraction() <= con) continue;
1025 int maxshi = shell_[i]->am(con);
1026 if (max < maxshi) max = maxshi;
1027 }
1028 return max;
1029}
1030
1031int
1032GaussianBasisSet::function_to_shell(int func) const
1033{
1034 return function_to_shell_[func];
1035}
1036
1037int
1038GaussianBasisSet::ncenter() const
1039{
1040 return ncenter_;
1041}
1042
1043int
1044GaussianBasisSet::nshell_on_center(int icenter) const
1045{
1046 return center_to_nshell_[icenter];
1047}
1048
1049int
1050GaussianBasisSet::nbasis_on_center(int icenter) const
1051{
1052 return center_to_nbasis_[icenter];
1053}
1054
1055int
1056GaussianBasisSet::shell_on_center(int icenter, int ishell) const
1057{
1058 return center_to_shell_[icenter] + ishell;
1059}
1060
1061const GaussianShell&
1062GaussianBasisSet::operator()(int icenter,int ishell) const
1063{
1064 return *shell_[center_to_shell_[icenter] + ishell];
1065}
1066
1067GaussianShell&
1068GaussianBasisSet::operator()(int icenter,int ishell)
1069{
1070 return *shell_[center_to_shell_[icenter] + ishell];
1071}
1072
1073int
1074GaussianBasisSet::equiv(const Ref<GaussianBasisSet> &b)
1075{
1076 if (nshell() != b->nshell()) return 0;
1077 for (int i=0; i<nshell(); i++) {
1078 if (!shell_[i]->equiv(b->shell_[i])) return 0;
1079 }
1080 return 1;
1081}
1082
1083void
1084GaussianBasisSet::print_brief(ostream& os) const
1085{
1086 os << indent
1087 << "GaussianBasisSet:" << endl << incindent
1088 << indent << "nbasis = " << nbasis_ << endl
1089 << indent << "nshell = " << nshell_ << endl
1090 << indent << "nprim = " << nprim_ << endl;
1091 if (name_) {
1092 os << indent
1093 << "name = \"" << name_ << "\"" << endl;
1094 }
1095 else {
1096 os << indent
1097 << "label = \"" << label_ << "\"" << endl;
1098 }
1099 os << decindent;
1100}
1101
1102void
1103GaussianBasisSet::print(ostream& os) const
1104{
1105 print_brief(os);
1106 if (!SCFormIO::getverbose(os)) return;
1107
1108 os << incindent;
1109
1110 // Loop over centers
1111 int icenter = 0;
1112 int ioshell = 0;
1113 for (icenter=0; icenter < ncenter_; icenter++) {
1114 os << endl << indent
1115 << scprintf(
1116 "center %d: %12.8f %12.8f %12.8f, nshell = %d, shellnum = %d\n",
1117 icenter,
1118 r(icenter,0),
1119 r(icenter,1),
1120 r(icenter,2),
1121 center_to_nshell_[icenter],
1122 center_to_shell_[icenter]);
1123 for (int ishell=0; ishell < center_to_nshell_[icenter]; ishell++) {
1124 os << indent
1125 << scprintf("Shell %d: functionnum = %d, primnum = %d\n",
1126 ishell,shell_to_function_[ioshell],shell_to_primitive_[ioshell]);
1127 os << incindent;
1128 operator()(icenter,ishell).print(os);
1129 os << decindent;
1130 ioshell++;
1131 }
1132 }
1133
1134 os << decindent;
1135}
1136
1137/////////////////////////////////////////////////////////////////////////////
1138// GaussianBasisSet::ValueData
1139
1140GaussianBasisSet::ValueData::ValueData(
1141 const Ref<GaussianBasisSet> &basis,
1142 const Ref<Integral> &integral)
1143{
1144 maxam_ = basis->max_angular_momentum();
1145
1146 civec_ = new CartesianIter *[maxam_+1];
1147 sivec_ = new SphericalTransformIter *[maxam_+1];
1148 for (int i=0; i<=maxam_; i++) {
1149 civec_[i] = integral->new_cartesian_iter(i);
1150 if (i>1) sivec_[i] = integral->new_spherical_transform_iter(i);
1151 else sivec_[i] = 0;
1152 }
1153}
1154
1155GaussianBasisSet::ValueData::~ValueData()
1156{
1157 for (int i=0; i<=maxam_; i++) {
1158 delete civec_[i];
1159 delete sivec_[i];
1160 }
1161 delete[] civec_;
1162 delete[] sivec_;
1163}
1164
1165/////////////////////////////////////////////////////////////////////////////
1166
1167// Local Variables:
1168// mode: c++
1169// c-file-style: "CLJ"
1170// End:
Note: See TracBrowser for help on using the repository browser.