Annotation of /home/cljanss/src/SC/src/lib/chemistry/qc/basis/petite.cc for ./mpqc.vmon.0018
1 //
2 // petite.cc --- implementation of the PetiteList class
3 //
4 // Copyright (C) 1996 Limit Point Systems, Inc.
5 //
6 // Author: Edward Seidl <seidl@janed.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
34 #include <util/misc/formio.h>
35 #include <chemistry/molecule/localdef.h>
36
37 #include <chemistry/qc/basis/basis.h>
38 #include <chemistry/qc/basis/integral.h>
39 #include <chemistry/qc/basis/petite.h>
40 #include <chemistry/qc/basis/shellrot.h>
41
42 using namespace std;
43
44 ////////////////////////////////////////////////////////////////////////////
45
46 PetiteList::PetiteList(const Ref<GaussianBasisSet> &gbs,
47 const Ref<Integral>& ints) :
48 gbs_(gbs),
49 ints_(ints)
50 {
51 init();
52 }
53
54 PetiteList::~PetiteList()
55 {
56 if (p1_)
57 delete[] p1_;
58
59 if (lamij_)
60 delete[] lamij_;
61
62 if (nbf_in_ir_)
63 delete[] nbf_in_ir_;
64
65 if (atom_map_) {
66 for (int i=0; i < natom_; i++)
67 delete[] atom_map_[i];
68 delete[] atom_map_;
69 }
70
71 if (shell_map_) {
72 1 0 0 0 0 0 0 0 0 0 for (int i=0; i < nshell_; i++)
73 1 0 0 0 0 0 0 0 0 0 delete[] shell_map_[i];
74 delete[] shell_map_;
75 }
76
77 natom_=0;
78 nshell_=0;
79 ng_=0;
80 nblocks_=0;
81 nirrep_=0;
82 p1_=0;
83 atom_map_=0;
84 shell_map_=0;
85 lamij_=0;
86 nbf_in_ir_=0;
87 }
88
89 void
90 PetiteList::init()
91 {
92 int i;
93
94 // grab references to the Molecule and BasisSet for convenience
95 GaussianBasisSet& gbs = *gbs_.pointer();
96 Molecule& mol = *gbs.molecule().pointer();
97
98 // create the character table for the point group
99 CharacterTable ct = mol.point_group()->char_table();
100
101 // initialize private members
102 c1_=0;
103 ng_ = ct.order();
104 natom_ = mol.natom();
105 nshell_ = gbs.nshell();
106 nirrep_ = ct.nirrep();
107
108 // if point group is C1, then zero everything
109 if (ng_==1) {
110 c1_=1;
111 nblocks_=1;
112
113 p1_=0;
114 atom_map_=0;
115 shell_map_=0;
116 lamij_=0;
117 nbf_in_ir_=0;
118 return;
119 }
120
121 // allocate storage for arrays
122 p1_ = new char[nshell_];
123 lamij_ = new char[i_offset(nshell_)];
124
125 atom_map_ = new int*[natom_];
126 for (i=0; i < natom_; i++)
127 0 0 0 1 0 0 0 0 0 0 atom_map_[i] = new int[ng_];
128
129 shell_map_ = new int*[nshell_];
130 for (i=0; i < nshell_; i++)
131 1 0 0 0 0 0 0 0 0 0 shell_map_[i] = new int[ng_];
132
133 // set up atom and shell mappings
134 double np[3];
135 0 0 0 1 0 0 0 0 0 0 SymmetryOperation so;
136
137 // loop over all centers
138 for (i=0; i < natom_; i++) {
139 SCVector3 ac(mol.r(i));
140
141 // then for each symop in the pointgroup, transform the coordinates of
142 // center "i" and see which atom it maps into
143 for (int g=0; g < ng_; g++) {
144 so = ct.symm_operation(g);
145
146 for (int ii=0; ii < 3; ii++) {
147 np[ii] = 0;
148 for (int jj=0; jj < 3; jj++)
149 1 0 0 0 0 0 0 0 0 0 np[ii] += so(ii,jj) * ac[jj];
150 }
151
152 0 0 0 0 1 0 0 0 0 0 atom_map_[i][g] = mol.atom_at_position(np, 0.05);
153 if (atom_map_[i][g] < 0) {
154 ExEnv::out() << "ERROR: Symmetry operation " << g << " did not map atom "
155 << i+1 << " to another atom:" << endl;
156 ExEnv::out() << indent << "Molecule:" << endl;
157 ExEnv::out() << incindent;
158 mol.print();
159 ExEnv::out() << decindent;
160 ExEnv::out() << indent << "attempted to find atom at" << endl;
161 ExEnv::out() << incindent;
162 ExEnv::out() << indent << np[0] << " " << np[1] << " " << np[2] << endl;
163 abort();
164 }
165 }
166
167 // hopefully, shells on equivalent centers will be numbered in the same
168 // order
169 for (int s=0; s < gbs.nshell_on_center(i); s++) {
170 int shellnum = gbs.shell_on_center(i,s);
171 1 0 0 0 0 0 0 0 0 0 for (int g=0; g < ng_; g++) {
172 1 0 3 0 5 0 0 0 0 0 shell_map_[shellnum][g] = gbs.shell_on_center(atom_map_[i][g],s);
173 }
174 1 0 1 0 0 0 0 0 0 0 }
175 }
176
177 memset(p1_,0,nshell_);
178 memset(lamij_,0,i_offset(nshell_));
179
180 // now we do p1_ and lamij_
181 1 0 0 0 0 0 0 0 0 0 for (i=0; i < nshell_; i++) {
182 int g;
183
184 // we want the highest numbered shell in a group of equivalent shells
185 for (g=0; g < ng_; g++)
186 if (shell_map_[i][g] > i)
187 break;
188
189 if (g < ng_)
190 continue;
191
192 // i is in the group P1
193 0 0 1 0 0 0 0 0 0 0 p1_[i] = 1;
194
195 1 0 0 0 0 0 0 0 0 0 for (int j=0; j <= i; j++) {
196 1 0 0 0 0 0 0 0 0 0 int ij = i_offset(i)+j;
197 int nij = 0;
198
199 // test to see if IJ is in the group P2, if it is, then set lambda(ij)
200 // equal to the number of equivalent shell pairs. This number is
201 // just the order of the group divided by the number of times ij is
202 // mapped into itself
203 int gg;
204 0 0 2 0 0 0 0 0 0 0 for (gg=0; gg < ng_; gg++) {
205 1 0 3 2 2 1 0 0 0 0 int gi = shell_map_[i][gg];
206 1 0 0 1 0 1 0 0 0 0 int gj = shell_map_[j][gg];
207 7 0 3 2 2 0 0 0 0 0 int gij = ij_offset(gi,gj);
208 0 0 1 0 1 0 0 0 0 0 if (gij > ij)
209 break;
210 1 0 1 0 1 0 0 0 0 0 else if (gij == ij)
211 2 0 3 2 0 1 0 0 0 0 nij++;
212 1 0 0 0 0 0 0 0 0 0 }
213
214 if (gg < ng_)
215 continue;
216
217 7 0 5 2 5 2 0 0 0 0 lamij_[ij] = (char) (ng_/nij);
218 0 0 1 0 0 0 0 0 0 0 }
219 1 0 0 0 1 0 0 0 0 0 }
220
221 // form reducible representation of the basis functions
222 double *red_rep = new double[ng_];
223 memset(red_rep,0,sizeof(double)*ng_);
224
225 for (i=0; i < natom_; i++) {
226 for (int g=0; g < ng_; g++) {
227 so = ct.symm_operation(g);
228 1 0 0 0 0 0 0 0 0 0 int j= atom_map_[i][g];
229
230 if (i!=j)
231 continue;
232
233 0 0 0 0 1 0 0 0 0 0 for (int s=0; s < gbs.nshell_on_center(i); s++) {
234 for (int c=0; c < gbs(i,s).ncontraction(); c++) {
235 int am=gbs(i,s).am(c);
236
237 if (am==0)
238 red_rep[g] += 1.0;
239 else {
240 ShellRotation r(am,so,ints_,gbs(i,s).is_pure(c));
241 red_rep[g] += r.trace();
242 }
243 }
244 2 0 0 1 1 1 0 0 0 0 }
245 }
246 }
247
248 // and then use projection operators to figure out how many SO's of each
249 // symmetry type there will be
250 nblocks_ = 0;
251 nbf_in_ir_ = new int[nirrep_];
252 for (i=0; i < nirrep_; i++) {
253 double t=0;
254 for (int g=0; g < ng_; g++)
255 t += ct.gamma(i).character(g)*red_rep[g];
256
257 0 0 2 0 0 0 0 0 0 0 nbf_in_ir_[i] = ((int) (t+0.5))/ng_;
258 if (ct.gamma(i).complex()) {
259 nblocks_++;
260 nbf_in_ir_[i] *= 2;
261 } else {
262 nblocks_ += ct.gamma(i).degeneracy();
263 }
264 }
265
266 delete[] red_rep;
267 }
268
269 RefSCDimension
270 PetiteList::AO_basisdim()
271 {
272 if (c1_)
273 return SO_basisdim();
274
275 RefSCDimension dim = new SCDimension(gbs_->nbasis(),1);
276 dim->blocks()->set_subdim(0, gbs_->basisdim());
277 return dim;
278 }
279
280 RefSCDimension
281 PetiteList::SO_basisdim()
282 {
283 int i, j, ii;
284
285 // grab a reference to the basis set
286 GaussianBasisSet& gbs = *gbs_.pointer();
287
288 // create the character table for the point group
289 CharacterTable ct = gbs.molecule()->point_group()->char_table();
290
291 // ncomp is the number of symmetry blocks we have
292 int ncomp=nblocks();
293
294 // saoelem is the current SO in a block
295 int *nao = new int [ncomp];
296 memset(nao,0,sizeof(int)*ncomp);
297
298 if (c1_)
299 nao[0] = gbs.nbasis();
300 else {
301 for (i=ii=0; i < nirrep_; i++) {
302 int je = ct.gamma(i).complex() ? 1 : ct.gamma(i).degeneracy();
303 for (j=0; j < je; j++,ii++)
304 nao[ii] = nbf_in_ir_[i];
305 0 0 0 0 1 0 0 0 0 0 }
306 }
307
308 RefSCDimension ret = new SCDimension(gbs.nbasis(),ncomp,nao);
309 delete[] nao;
310
311 for (i=ii=0; i < nirrep_; i++) {
312 Ref<MessageGrp> grp = MessageGrp::get_default_messagegrp();
313 int np=grp->n();
314 2 0 0 1 0 0 0 0 0 0 int *subblksize = new int[np];
315 0 0 1 0 0 0 0 0 0 0 int nbas=(c1_) ? gbs.nbasis() : nbf_in_ir_[i];
316 for (j=0; j < np; j++) {
317 1 0 0 0 0 0 0 0 0 0 if (j < nbas%np)
318 subblksize[j] = nbas/np + 1;
319 else
320 subblksize[j] = nbas/np;
321 }
322
323 int je = ct.gamma(i).complex() ? 1 : ct.gamma(i).degeneracy();
324 for (j=0; j < je; j++,ii++) {
325 char lab[24];
326 sprintf(lab,"irrep %s comp %d", ct.gamma(i).symbol(), j);
327 ret->blocks()->set_subdim(ii, new SCDimension(nbas, np, subblksize));
328 }
329
330 delete[] subblksize;
331 }
332
333 return ret;
334 }
335
336 void
337 PetiteList::print(ostream& o, int verbose)
338 {
339 int i;
340
341 o << node0 << indent << "PetiteList:" << endl << incindent;
342
343 if (c1_) {
344 o << node0 << indent << "is c1\n" << decindent;
345 return;
346 }
347
348 if (verbose) {
349 o << node0
350 << indent << "natom_ = " << natom_ << endl
351 << indent << "nshell_ = " << nshell_ << endl
352 << indent << "ng_ = " << ng_ << endl
353 << indent << "nirrep_ = " << nirrep_ << endl << endl
354 << indent << "atom_map_ =" << endl << incindent;
355
356 for (i=0; i < natom_; i++) {
357 o << node0 << indent;
358 for (int g=0; g < ng_; g++)
359 o << node0 << scprintf("%5d ",atom_map_[i][g]);
360 o << node0 << endl;
361 }
362
363 o << node0 << endl << decindent
364 << indent << "shell_map_ =" << endl << incindent;
365 for (i=0; i < nshell_; i++) {
366 o << node0 << indent;
367 for (int g=0; g < ng_; g++)
368 o << node0 << scprintf("%5d ",shell_map_[i][g]);
369 o << node0 << endl;
370 }
371
372 o << node0 << endl << decindent
373 << indent << "p1_ =" << endl << incindent;
374 for (i=0; i < nshell_; i++)
375 o << node0 << indent << scprintf("%5d\n",p1_[i]);
376
377 o << node0 << decindent
378 << indent << "lamij_ =" << endl << incindent;
379 for (i=0; i < nshell_; i++) {
380 o << node0 << indent;
381 for (int j=0; j <= i; j++)
382 o << node0 << scprintf("%5d ",lamij_[i_offset(i)+j]);
383 o << node0 << endl;
384 }
385 o << node0 << endl << decindent;
386 }
387
388 CharacterTable ct = gbs_->molecule()->point_group()->char_table();
389 for (i=0; i < nirrep_; i++)
390 o << node0 << indent
391 << scprintf("%5d functions of %s symmetry\n",
392 nbf_in_ir_[i], ct.gamma(i).symbol());
393 }
394
395 // forms the basis function rotation matrix for the g'th symmetry operation
396 // in the point group
397 RefSCMatrix
398 PetiteList::r(int g)
399 {
400 // grab a reference to the basis set
401 GaussianBasisSet& gbs = *gbs_.pointer();
402
403 SymmetryOperation so =
404 gbs.molecule()->point_group()->char_table().symm_operation(g);
405
406 RefSCMatrix ret = gbs.matrixkit()->matrix(gbs.basisdim(), gbs.basisdim());
407 ret.assign(0.0);
408
409 // this should be replaced with an element op at some point
410 if (c1_) {
411 for (int i=0; i < gbs.nbasis(); i++)
412 ret.set_element(i,i,1.0);
413 return ret;
414
415 } else {
416 for (int i=0; i < natom_; i++) {
417 int j = atom_map_[i][g];
418
419 for (int s=0; s < gbs.nshell_on_center(i); s++) {
420 int func_i = gbs.shell_to_function(gbs.shell_on_center(i,s));
421 int func_j = gbs.shell_to_function(gbs.shell_on_center(j,s));
422
423 for (int c=0; c < gbs(i,s).ncontraction(); c++) {
424 int am=gbs(i,s).am(c);
425
426 if (am==0) {
427 ret.set_element(func_j,func_i,1.0);
428 } else {
429 ShellRotation rr(am,so,ints_,gbs(i,s).is_pure(c));
430 for (int ii=0; ii < rr.dim(); ii++)
431 for (int jj=0; jj < rr.dim(); jj++)
432 ret.set_element(func_j+jj,func_i+ii,rr(ii,jj));
433 }
434
435 func_i += gbs(i,s).nfunction(c);
436 func_j += gbs(i,s).nfunction(c);
437 }
438 }
439 }
440 }
441 return ret;
442 }
443
444 /////////////////////////////////////////////////////////////////////////////
445
446 // Local Variables:
447 // mode: c++
448 // c-file-style: "ETS"
449 // End:
450