source: ThirdParty/mpqc_open/src/lib/chemistry/qc/basis/petite.cc@ 47b463

Action_Thermostats Add_AtomRandomPerturbation Add_RotateAroundBondAction Add_SelectAtomByNameAction Adding_Graph_to_ChangeBondActions Adding_MD_integration_tests Adding_StructOpt_integration_tests AutomationFragmentation_failures Candidate_v1.6.0 Candidate_v1.6.1 ChangeBugEmailaddress ChangingTestPorts ChemicalSpaceEvaluator Combining_Subpackages Debian_Package_split Debian_package_split_molecuildergui_only Disabling_MemDebug Docu_Python_wait EmpiricalPotential_contain_HomologyGraph_documentation Enable_parallel_make_install Enhance_userguide Enhanced_StructuralOptimization Enhanced_StructuralOptimization_continued Example_ManyWaysToTranslateAtom Exclude_Hydrogens_annealWithBondGraph FitPartialCharges_GlobalError Fix_ChronosMutex Fix_StatusMsg Fix_StepWorldTime_single_argument Fix_Verbose_Codepatterns ForceAnnealing_goodresults ForceAnnealing_oldresults ForceAnnealing_tocheck ForceAnnealing_with_BondGraph ForceAnnealing_with_BondGraph_continued ForceAnnealing_with_BondGraph_continued_betteresults ForceAnnealing_with_BondGraph_contraction-expansion GeometryObjects Gui_displays_atomic_force_velocity IndependentFragmentGrids_IntegrationTest JobMarket_RobustOnKillsSegFaults JobMarket_StableWorkerPool JobMarket_unresolvable_hostname_fix ODR_violation_mpqc_open PartialCharges_OrthogonalSummation PythonUI_with_named_parameters QtGui_reactivate_TimeChanged_changes Recreated_GuiChecks RotateToPrincipalAxisSystem_UndoRedo StoppableMakroAction Subpackage_levmar Subpackage_vmg ThirdParty_MPQC_rebuilt_buildsystem TremoloParser_IncreasedPrecision TremoloParser_MultipleTimesteps Ubuntu_1604_changes stable
Last change on this file since 47b463 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: 13.6 KB
Line 
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
42using namespace std;
43using namespace sc;
44
45////////////////////////////////////////////////////////////////////////////
46
47int **
48sc::compute_atom_map(const Ref<GaussianBasisSet> &basis)
49{
50 // grab references to the Molecule and BasisSet for convenience
51 GaussianBasisSet& gbs = *basis.pointer();
52 Molecule& mol = *gbs.molecule().pointer();
53
54 // create the character table for the point group
55 CharacterTable ct = mol.point_group()->char_table();
56
57 int natom = gbs.ncenter();
58 int ng = ct.order();
59 int **atom_map;
60 atom_map = new int*[natom];
61 for (int i=0; i < natom; i++) atom_map[i] = new int[ng];
62
63 double np[3];
64 SymmetryOperation so;
65
66 // loop over all centers
67 for (int i=0; i < natom; i++) {
68 SCVector3 ac(mol.r(i));
69
70 // then for each symop in the pointgroup, transform the coordinates of
71 // center "i" and see which atom it maps into
72 for (int g=0; g < ng; g++) {
73 so = ct.symm_operation(g);
74
75 for (int ii=0; ii < 3; ii++) {
76 np[ii] = 0;
77 for (int jj=0; jj < 3; jj++)
78 np[ii] += so(ii,jj) * ac[jj];
79 }
80
81 atom_map[i][g] = mol.atom_at_position(np, 0.05);
82 if (atom_map[i][g] < 0) {
83 ExEnv::out0() << "ERROR: Symmetry operation " << g << " did not map atom "
84 << i+1 << " to another atom:" << endl;
85 ExEnv::out0() << indent << "Molecule:" << endl;
86 ExEnv::out0() << incindent;
87 mol.print();
88 ExEnv::out0() << decindent;
89 ExEnv::out0() << indent << "attempted to find atom at" << endl;
90 ExEnv::out0() << incindent;
91 ExEnv::out0() << indent << np[0] << " " << np[1] << " " << np[2] << endl;
92 abort();
93 }
94 }
95 }
96
97 return atom_map;
98}
99
100
101void
102sc::delete_atom_map(int **atom_map, const Ref<GaussianBasisSet> &basis)
103{
104 if (atom_map) {
105 int natom = basis->ncenter();
106 for (int i=0; i < natom; i++)
107 delete[] atom_map[i];
108 delete[] atom_map;
109 }
110}
111
112int **
113sc::compute_shell_map(int **atom_map, const Ref<GaussianBasisSet> &basis)
114{
115 int **shell_map;
116
117 GaussianBasisSet& gbs = *basis.pointer();
118 Molecule& mol = *gbs.molecule().pointer();
119
120 // create the character table for the point group
121 CharacterTable ct = mol.point_group()->char_table();
122
123 int natom = gbs.ncenter();
124 int ng = ct.order();
125
126 int nshell = basis->nshell();
127 shell_map = new int*[nshell];
128 for (int i=0; i < nshell; i++)
129 shell_map[i] = new int[ng];
130
131 for (int i=0; i<natom; i++) {
132 // hopefully, shells on equivalent centers will be numbered in the same
133 // order
134 for (int s=0; s < gbs.nshell_on_center(i); s++) {
135 int shellnum = gbs.shell_on_center(i,s);
136 for (int g=0; g < ng; g++) {
137 shell_map[shellnum][g] = gbs.shell_on_center(atom_map[i][g],s);
138 }
139 }
140 }
141
142 return shell_map;
143}
144
145void
146sc::delete_shell_map(int **shell_map, const Ref<GaussianBasisSet> &basis)
147{
148 int nshell = basis->nshell();
149 if (shell_map) {
150 for (int i=0; i < nshell; i++)
151 delete[] shell_map[i];
152 delete[] shell_map;
153 }
154}
155
156////////////////////////////////////////////////////////////////////////////
157
158PetiteList::PetiteList(const Ref<GaussianBasisSet> &gbs,
159 const Ref<Integral>& ints) :
160 gbs_(gbs),
161 ints_(ints)
162{
163 init();
164}
165
166PetiteList::~PetiteList()
167{
168 if (p1_)
169 delete[] p1_;
170
171 if (lamij_)
172 delete[] lamij_;
173
174 if (nbf_in_ir_)
175 delete[] nbf_in_ir_;
176
177 if (atom_map_) {
178 for (int i=0; i < natom_; i++)
179 delete[] atom_map_[i];
180 delete[] atom_map_;
181 }
182
183 if (shell_map_) {
184 for (int i=0; i < nshell_; i++)
185 delete[] shell_map_[i];
186 delete[] shell_map_;
187 }
188
189 natom_=0;
190 nshell_=0;
191 ng_=0;
192 nblocks_=0;
193 nirrep_=0;
194 p1_=0;
195 atom_map_=0;
196 shell_map_=0;
197 lamij_=0;
198 nbf_in_ir_=0;
199}
200
201void
202PetiteList::init()
203{
204 int i;
205
206 // grab references to the Molecule and BasisSet for convenience
207 GaussianBasisSet& gbs = *gbs_.pointer();
208 Molecule& mol = *gbs.molecule().pointer();
209
210 // create the character table for the point group
211 CharacterTable ct = mol.point_group()->char_table();
212
213 // initialize private members
214 c1_=0;
215 ng_ = ct.order();
216 natom_ = mol.natom();
217 nshell_ = gbs.nshell();
218 nirrep_ = ct.nirrep();
219
220 // if point group is C1, then zero everything
221 if (ng_==1) {
222 c1_=1;
223 nblocks_=1;
224
225 p1_=0;
226 atom_map_=0;
227 shell_map_=0;
228 lamij_=0;
229 nbf_in_ir_=0;
230 return;
231 }
232
233 // allocate storage for arrays
234 p1_ = new char[nshell_];
235 lamij_ = new char[i_offset(nshell_)];
236
237 atom_map_ = new int*[natom_];
238 for (i=0; i < natom_; i++)
239 atom_map_[i] = new int[ng_];
240
241 shell_map_ = new int*[nshell_];
242 for (i=0; i < nshell_; i++)
243 shell_map_[i] = new int[ng_];
244
245 // set up atom and shell mappings
246 double np[3];
247 SymmetryOperation so;
248
249 // loop over all centers
250 for (i=0; i < natom_; i++) {
251 SCVector3 ac(mol.r(i));
252
253 // then for each symop in the pointgroup, transform the coordinates of
254 // center "i" and see which atom it maps into
255 for (int g=0; g < ng_; g++) {
256 so = ct.symm_operation(g);
257
258 for (int ii=0; ii < 3; ii++) {
259 np[ii] = 0;
260 for (int jj=0; jj < 3; jj++)
261 np[ii] += so(ii,jj) * ac[jj];
262 }
263
264 atom_map_[i][g] = mol.atom_at_position(np, 0.05);
265 if (atom_map_[i][g] < 0) {
266 ExEnv::out0() << "ERROR: Symmetry operation " << g << " did not map atom "
267 << i+1 << " to another atom:" << endl;
268 ExEnv::out0() << indent << "Molecule:" << endl;
269 ExEnv::out0() << incindent;
270 mol.print();
271 ExEnv::out0() << decindent;
272 ExEnv::out0() << indent << "attempted to find atom at" << endl;
273 ExEnv::out0() << incindent;
274 ExEnv::out0() << indent << np[0] << " " << np[1] << " " << np[2] << endl;
275 abort();
276 }
277 }
278
279 // hopefully, shells on equivalent centers will be numbered in the same
280 // order
281 for (int s=0; s < gbs.nshell_on_center(i); s++) {
282 int shellnum = gbs.shell_on_center(i,s);
283 for (int g=0; g < ng_; g++) {
284 shell_map_[shellnum][g] = gbs.shell_on_center(atom_map_[i][g],s);
285 }
286 }
287 }
288
289 memset(p1_,0,nshell_);
290 memset(lamij_,0,i_offset(nshell_));
291
292 // now we do p1_ and lamij_
293 for (i=0; i < nshell_; i++) {
294 int g;
295
296 // we want the highest numbered shell in a group of equivalent shells
297 for (g=0; g < ng_; g++)
298 if (shell_map_[i][g] > i)
299 break;
300
301 if (g < ng_)
302 continue;
303
304 // i is in the group P1
305 p1_[i] = 1;
306
307 for (int j=0; j <= i; j++) {
308 int ij = i_offset(i)+j;
309 int nij = 0;
310
311 // test to see if IJ is in the group P2, if it is, then set lambda(ij)
312 // equal to the number of equivalent shell pairs. This number is
313 // just the order of the group divided by the number of times ij is
314 // mapped into itself
315 int gg;
316 for (gg=0; gg < ng_; gg++) {
317 int gi = shell_map_[i][gg];
318 int gj = shell_map_[j][gg];
319 int gij = ij_offset(gi,gj);
320 if (gij > ij)
321 break;
322 else if (gij == ij)
323 nij++;
324 }
325
326 if (gg < ng_)
327 continue;
328
329 lamij_[ij] = (char) (ng_/nij);
330 }
331 }
332
333 // form reducible representation of the basis functions
334 double *red_rep = new double[ng_];
335 memset(red_rep,0,sizeof(double)*ng_);
336
337 for (i=0; i < natom_; i++) {
338 for (int g=0; g < ng_; g++) {
339 so = ct.symm_operation(g);
340 int j= atom_map_[i][g];
341
342 if (i!=j)
343 continue;
344
345 for (int s=0; s < gbs.nshell_on_center(i); s++) {
346 for (int c=0; c < gbs(i,s).ncontraction(); c++) {
347 int am=gbs(i,s).am(c);
348
349 if (am==0)
350 red_rep[g] += 1.0;
351 else {
352 ShellRotation r(am,so,ints_,gbs(i,s).is_pure(c));
353 red_rep[g] += r.trace();
354 }
355 }
356 }
357 }
358 }
359
360 // and then use projection operators to figure out how many SO's of each
361 // symmetry type there will be
362 nblocks_ = 0;
363 nbf_in_ir_ = new int[nirrep_];
364 for (i=0; i < nirrep_; i++) {
365 double t=0;
366 for (int g=0; g < ng_; g++)
367 t += ct.gamma(i).character(g)*red_rep[g];
368
369 nbf_in_ir_[i] = ((int) (t+0.5))/ng_;
370 if (ct.gamma(i).complex()) {
371 nblocks_++;
372 nbf_in_ir_[i] *= 2;
373 } else {
374 nblocks_ += ct.gamma(i).degeneracy();
375 }
376 }
377
378 delete[] red_rep;
379}
380
381RefSCDimension
382PetiteList::AO_basisdim()
383{
384 if (c1_)
385 return SO_basisdim();
386
387 RefSCDimension dim = new SCDimension(gbs_->nbasis(),1);
388 dim->blocks()->set_subdim(0, gbs_->basisdim());
389 return dim;
390}
391
392RefSCDimension
393PetiteList::SO_basisdim()
394{
395 int i, j, ii;
396
397 // grab a reference to the basis set
398 GaussianBasisSet& gbs = *gbs_.pointer();
399
400 // create the character table for the point group
401 CharacterTable ct = gbs.molecule()->point_group()->char_table();
402
403 // ncomp is the number of symmetry blocks we have
404 int ncomp=nblocks();
405
406 // saoelem is the current SO in a block
407 int *nao = new int [ncomp];
408 memset(nao,0,sizeof(int)*ncomp);
409
410 if (c1_)
411 nao[0] = gbs.nbasis();
412 else {
413 for (i=ii=0; i < nirrep_; i++) {
414 int je = ct.gamma(i).complex() ? 1 : ct.gamma(i).degeneracy();
415 for (j=0; j < je; j++,ii++)
416 nao[ii] = nbf_in_ir_[i];
417 }
418 }
419
420 RefSCDimension ret = new SCDimension(gbs.nbasis(),ncomp,nao);
421 delete[] nao;
422
423 for (i=ii=0; i < nirrep_; i++) {
424 int nbas=(c1_) ? gbs.nbasis() : nbf_in_ir_[i];
425 int je = ct.gamma(i).complex() ? 1 : ct.gamma(i).degeneracy();
426 for (j=0; j < je; j++,ii++) {
427 ret->blocks()->set_subdim(ii, new SCDimension(nbas));
428 }
429
430 }
431
432 return ret;
433}
434
435void
436PetiteList::print(ostream& o, int verbose)
437{
438 int i;
439
440 o << indent << "PetiteList:" << endl << incindent;
441
442 if (c1_) {
443 o << indent << "is c1\n" << decindent;
444 return;
445 }
446
447 if (verbose) {
448 o
449 << indent << "natom_ = " << natom_ << endl
450 << indent << "nshell_ = " << nshell_ << endl
451 << indent << "ng_ = " << ng_ << endl
452 << indent << "nirrep_ = " << nirrep_ << endl << endl
453 << indent << "atom_map_ =" << endl << incindent;
454
455 for (i=0; i < natom_; i++) {
456 o << indent;
457 for (int g=0; g < ng_; g++)
458 o << scprintf("%5d ",atom_map_[i][g]);
459 o << endl;
460 }
461
462 o << endl << decindent
463 << indent << "shell_map_ =" << endl << incindent;
464 for (i=0; i < nshell_; i++) {
465 o << indent;
466 for (int g=0; g < ng_; g++)
467 o << scprintf("%5d ",shell_map_[i][g]);
468 o << endl;
469 }
470
471 o << endl << decindent
472 << indent << "p1_ =" << endl << incindent;
473 for (i=0; i < nshell_; i++)
474 o << indent << scprintf("%5d\n",p1_[i]);
475
476 o << decindent
477 << indent << "lamij_ =" << endl << incindent;
478 for (i=0; i < nshell_; i++) {
479 o << indent;
480 for (int j=0; j <= i; j++)
481 o << scprintf("%5d ",lamij_[i_offset(i)+j]);
482 o << endl;
483 }
484 o << endl << decindent;
485 }
486
487 CharacterTable ct = gbs_->molecule()->point_group()->char_table();
488 for (i=0; i < nirrep_; i++)
489 o << indent
490 << scprintf("%5d functions of %s symmetry\n",
491 nbf_in_ir_[i], ct.gamma(i).symbol());
492}
493
494// forms the basis function rotation matrix for the g'th symmetry operation
495// in the point group
496RefSCMatrix
497PetiteList::r(int g)
498{
499 // grab a reference to the basis set
500 GaussianBasisSet& gbs = *gbs_.pointer();
501
502 SymmetryOperation so =
503 gbs.molecule()->point_group()->char_table().symm_operation(g);
504
505 RefSCMatrix ret = gbs.matrixkit()->matrix(gbs.basisdim(), gbs.basisdim());
506 ret.assign(0.0);
507
508 // this should be replaced with an element op at some point
509 if (c1_) {
510 for (int i=0; i < gbs.nbasis(); i++)
511 ret.set_element(i,i,1.0);
512 return ret;
513
514 } else {
515 for (int i=0; i < natom_; i++) {
516 int j = atom_map_[i][g];
517
518 for (int s=0; s < gbs.nshell_on_center(i); s++) {
519 int func_i = gbs.shell_to_function(gbs.shell_on_center(i,s));
520 int func_j = gbs.shell_to_function(gbs.shell_on_center(j,s));
521
522 for (int c=0; c < gbs(i,s).ncontraction(); c++) {
523 int am=gbs(i,s).am(c);
524
525 if (am==0) {
526 ret.set_element(func_j,func_i,1.0);
527 } else {
528 ShellRotation rr(am,so,ints_,gbs(i,s).is_pure(c));
529 for (int ii=0; ii < rr.dim(); ii++)
530 for (int jj=0; jj < rr.dim(); jj++)
531 ret.set_element(func_j+jj,func_i+ii,rr(ii,jj));
532 }
533
534 func_i += gbs(i,s).nfunction(c);
535 func_j += gbs(i,s).nfunction(c);
536 }
537 }
538 }
539 }
540 return ret;
541}
542
543/////////////////////////////////////////////////////////////////////////////
544
545// Local Variables:
546// mode: c++
547// c-file-style: "ETS"
548// End:
Note: See TracBrowser for help on using the repository browser.