source: ThirdParty/mpqc_open/src/lib/chemistry/qc/basis/aotoso.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: 21.0 KB
Line 
1//
2// aotoso.cc --- more symmetry stuff
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#include <float.h>
29
30#include <util/misc/formio.h>
31
32#include <chemistry/qc/basis/basis.h>
33#include <chemistry/qc/basis/integral.h>
34#include <chemistry/qc/basis/shellrot.h>
35#include <chemistry/qc/basis/petite.h>
36#include <chemistry/qc/basis/f77sym.h>
37
38using namespace std;
39using namespace sc;
40
41extern "C" {
42 void
43 F77_DGESVD(const char * JOBU, const char *JOBVT,
44 int *M, int *N, double *A, int *LDA,
45 double *S, double *U, int *LDU, double *VT, int *LDVT,
46 double *WORK, int *LWORK, int *INFO );
47}
48
49////////////////////////////////////////////////////////////////////////////
50
51contribution::contribution()
52{
53}
54
55contribution::~contribution()
56{
57}
58
59contribution::contribution(int b, double c) : bfn(b), coef(c)
60{
61}
62
63////////////////////////////////////////////////////////////////////////////
64
65SO::SO() : len(0), length(0), cont(0)
66{
67}
68
69SO::SO(int l) : len(0), length(0), cont(0)
70{
71 set_length(l);
72}
73
74SO::~SO()
75{
76 set_length(0);
77}
78
79SO&
80SO::operator=(const SO& so)
81{
82 set_length(so.length);
83 length = so.length;
84 for (int i=0; i < length; i++)
85 cont[i] = so.cont[i];
86 return *this;
87}
88
89void
90SO::set_length(int l)
91{
92 len=l;
93 length=l;
94 if (cont) {
95 delete[] cont;
96 cont=0;
97 }
98
99 if (l)
100 cont = new contribution[l];
101}
102
103void
104SO::reset_length(int l)
105{
106 length=l;
107
108 if (l <= len)
109 return;
110
111 l=l+10;
112
113 contribution *newcont = new contribution[l];
114
115 if (cont) {
116 for (int i=0; i < len; i++)
117 newcont[i] = cont[i];
118
119 delete[] cont;
120 }
121
122 cont=newcont;
123 len=l;
124}
125
126int
127SO::equiv(const SO& so)
128{
129 int i;
130
131 if (so.length != length)
132 return 0;
133
134 double c=0;
135 for (i=0; i < length; i++) {
136 if (cont[i].bfn != so.cont[i].bfn)
137 return 0;
138 c += cont[i].coef*so.cont[i].coef;
139 }
140
141 // if the overlap == 1.0, they're equal (SO's should have been
142 // normalized by now)
143 if (fabs(fabs(c)-1.0) < 1.0e-3)
144 return 1;
145
146 return 0;
147}
148
149////////////////////////////////////////////////////////////////////////////
150
151SO_block::SO_block() : len(0), so(0)
152{
153}
154
155SO_block::SO_block(int l) : len(0), so(0)
156{
157 set_length(l);
158}
159
160SO_block::~SO_block()
161{
162 set_length(0);
163}
164
165void
166SO_block::set_length(int l)
167{
168 len=l;
169 if (so) {
170 delete[] so;
171 so=0;
172 }
173
174 if (l)
175 so = new SO[l];
176}
177
178void
179SO_block::reset_length(int l)
180{
181 if (len == l) return;
182
183 SO *newso = new SO[l];
184
185 if (so) {
186 for (int i=0; i < len; i++)
187 newso[i] = so[i];
188
189 delete[] so;
190 }
191
192 so=newso;
193 len=l;
194}
195
196int
197SO_block::add(SO& s, int i)
198{
199 // first check to see if s is already here
200 for (int j=0; j < ((i < len) ? i : len); j++)
201 if (so[j].equiv(s))
202 return 0;
203
204 if (i >= len)
205 reset_length(i+1);
206 so[i] = s;
207
208 return 1;
209}
210
211void
212SO_block::print(const char *title)
213{
214 int i,j;
215 ExEnv::out0() << indent << "SO block " << title << endl;
216 for (i=0; i < len; i++) {
217 ExEnv::out0() << indent << "SO " << i+1 << endl << indent;
218 for (j=0; j < so[i].length; j++)
219 ExEnv::out0() << scprintf(" %10d",so[i].cont[j].bfn);
220 ExEnv::out0() << endl << indent;
221 for (j=0; j < so[i].length; j++)
222 ExEnv::out0() << scprintf(" %10.7f",so[i].cont[j].coef);
223 ExEnv::out0() << endl;
224 }
225}
226
227////////////////////////////////////////////////////////////////////////////
228
229struct lin_comb {
230 int ns;
231 int f0;
232 int mapf0;
233 double **c;
234
235 lin_comb(int ins, int if0, int imf0) : ns(ins), f0(if0), mapf0(imf0) {
236 int i;
237
238 c = new double*[ns];
239 for (i=0; i < ns; i++) {
240 c[i] = new double[ns];
241 memset(c[i],0,sizeof(double)*ns);
242 }
243 }
244
245 ~lin_comb() {
246 if (c) {
247 for (int i=0; i < ns; i++)
248 if (c[i])
249 delete[] c[i];
250 delete[] c;
251 c=0;
252 }
253 }
254
255 void print() const {
256 int i;
257 ExEnv::out0() << indent;
258 for (i=0; i < ns; i++)
259 ExEnv::out0() << scprintf(" %10d",mapf0+i);
260 ExEnv::out0() << endl;
261
262 for (i=0; i < ns; i++) {
263 ExEnv::out0() << indent << scprintf("%2d",f0+i);
264 for (int j=0; j < ns; j++)
265 ExEnv::out0() << scprintf(" %10.7f",c[i][j]);
266 ExEnv::out0() << endl;
267 }
268 }
269};
270
271////////////////////////////////////////////////////////////////////////////
272
273SO_block *
274PetiteList::aotoso_info()
275{
276 int iuniq, i, j, d, ii, jj, g, s, c, ir;
277
278 GaussianBasisSet& gbs = *gbs_.pointer();
279 Molecule& mol = *gbs.molecule().pointer();
280
281 // create the character table for the point group
282 CharacterTable ct = mol.point_group()->char_table();
283 SymmetryOperation so;
284
285 if (c1_) {
286 SO_block *SOs = new SO_block[1];
287 SOs[0].set_length(gbs.nbasis());
288 for (i=0; i < gbs.nbasis(); i++) {
289 SOs[0].so[i].set_length(1);
290 SOs[0].so[i].cont[0].bfn=i;
291 SOs[0].so[i].cont[0].coef=1.0;
292 }
293 return SOs;
294 }
295
296 // ncomp is the number of symmetry blocks we have. for point groups with
297 // complex E representations, this will be cut in two eventually
298 int ncomp=0;
299 for (i=0; i < nirrep_; i++)
300 ncomp += ct.gamma(i).degeneracy();
301
302 // saoelem is the current SO in a block
303 int *saoelem = new int[ncomp];
304 memset(saoelem,0,sizeof(int)*ncomp);
305
306 int *whichir = new int[ncomp];
307 int *whichcmp = new int[ncomp];
308 for (i=ii=0; i < nirrep_; i++) {
309 for (int j=0; j < ct.gamma(i).degeneracy(); j++,ii++) {
310 whichir[ii] = i;
311 whichcmp[ii] = j;
312 }
313 }
314
315 // SOs is an array of SO_blocks which holds the redundant SO's
316 SO_block *SOs = new SO_block[ncomp];
317
318 for (i=0; i < ncomp; i++) {
319 ir = whichir[i];
320 int len = (ct.gamma(ir).complex()) ? nbf_in_ir_[ir]/2 : nbf_in_ir_[ir];
321 SOs[i].set_length(len);
322 }
323
324 // loop over all unique shells
325 for (iuniq=0; iuniq < gbs.molecule()->nunique(); iuniq++) {
326 int nequiv = gbs.molecule()->nequivalent(iuniq);
327 i = gbs.molecule()->unique(iuniq);
328 for (s=0; s < gbs.nshell_on_center(i); s++) {
329 int shell_i = gbs.shell_on_center(i,s);
330
331 // test to see if there are any high am cartesian functions in this
332 // shell. for now don't allow symmetry with cartesian functions...I
333 // just can't seem to get them working.
334 for (c=0; c < gbs(i,s).ncontraction(); c++) {
335 if (gbs(i,s).am(c) > 1 && gbs(i,s).is_cartesian(c)) {
336 if (ng_ != nirrep_) {
337 ExEnv::err0() << indent
338 << "PetiteList::aotoso: cannot yet handle"
339 << " symmetry for angular momentum >= 2\n";
340 abort();
341 }
342 }
343 }
344
345 // the functions do not mix between contractions
346 // so the contraction loop can be done outside the symmetry
347 // operation loop
348 int bfn_offset_in_shell = 0;
349 for (c=0; c < gbs(i,s).ncontraction(); c++) {
350 int nfuncuniq = gbs(i,s).nfunction(c);
351 int nfuncall = nfuncuniq * nequiv;
352
353 // allocate an array to store linear combinations of orbitals
354 // this is destroyed by the SVD routine
355 double **linorb = new double*[nfuncuniq];
356 linorb[0] = new double[nfuncuniq*nfuncall];
357 for (j=1; j<nfuncuniq; j++) {
358 linorb[j] = &linorb[j-1][nfuncall];
359 }
360
361 // a copy of linorb
362 double **linorbcop = new double*[nfuncuniq];
363 linorbcop[0] = new double[nfuncuniq*nfuncall];
364 for (j=1; j<nfuncuniq; j++) {
365 linorbcop[j] = &linorbcop[j-1][nfuncall];
366 }
367
368 // allocate an array for the SVD routine
369 double **u = new double*[nfuncuniq];
370 u[0] = new double[nfuncuniq*nfuncuniq];
371 for (j=1; j<nfuncuniq; j++) {
372 u[j] = &u[j-1][nfuncuniq];
373 }
374
375 // loop through each irrep to form the linear combination
376 // of orbitals of that symmetry
377 int irnum = 0;
378 for (ir=0; ir<ct.nirrep(); ir++) {
379 int cmplx = (ct.complex() && ct.gamma(ir).complex());
380 for (int comp=0; comp < ct.gamma(ir).degeneracy(); comp++) {
381 memset(linorb[0], 0, nfuncuniq*nfuncall*sizeof(double));
382 for (d=0; d < ct.gamma(ir).degeneracy(); d++) {
383 // if this is a point group with a complex E representation,
384 // then only do the first set of projections for E
385 if (d && cmplx) break;
386
387 // operate on each function in this contraction with each
388 // symmetry operation to form symmetrized linear combinations
389 // of orbitals
390
391 for (g=0; g<ng_; g++) {
392 // the character
393 double ccdg = ct.gamma(ir).p(comp,d,g);
394
395 so = ct.symm_operation(g);
396 int equivatom = atom_map_[i][g];
397 int atomoffset
398 = gbs.molecule()->atom_to_unique_offset(equivatom);
399
400 ShellRotation rr
401 = ints_->shell_rotation(gbs(i,s).am(c),
402 so,gbs(i,s).is_pure(c));
403
404 for (ii=0; ii < rr.dim(); ii++) {
405 for (jj=0; jj < rr.dim(); jj++) {
406 linorb[ii][atomoffset*nfuncuniq+jj] += ccdg * rr(ii,jj);
407 }
408 }
409 }
410 }
411 // find the linearly independent SO's for this irrep/component
412 memcpy(linorbcop[0], linorb[0], nfuncuniq*nfuncall*sizeof(double));
413 double *singval = new double[nfuncuniq];
414 double djunk=0; int ijunk=1;
415 int lwork = 5*nfuncall;
416 double *work = new double[lwork];
417 int info;
418 // solves At = V SIGMA Ut (since FORTRAN array layout is used)
419 F77_DGESVD("N","A",&nfuncall,&nfuncuniq,linorb[0],&nfuncall,
420 singval, &djunk, &ijunk, u[0], &nfuncuniq,
421 work, &lwork, &info);
422 // put the lin indep symm orbs into the so array
423 for (j=0; j<nfuncuniq; j++) {
424 if (singval[j] > 1.0e-6) {
425 SO tso;
426 tso.set_length(nfuncall);
427 int ll = 0, llnonzero = 0;
428 for (int k=0; k<nequiv; k++) {
429 for (int l=0; l<nfuncuniq; l++,ll++) {
430 double tmp = 0.0;
431 for (int m=0; m<nfuncuniq; m++) {
432 tmp += u[m][j] * linorbcop[m][ll] / singval[j];
433 }
434 if (fabs(tmp) > DBL_EPSILON) {
435 int equivatom = gbs.molecule()->equivalent(iuniq,k);
436 tso.cont[llnonzero].bfn
437 = l
438 + bfn_offset_in_shell
439 + gbs.shell_to_function(gbs.shell_on_center(equivatom,
440 s));
441 tso.cont[llnonzero].coef = tmp;
442 llnonzero++;
443 }
444 }
445 }
446 tso.reset_length(llnonzero);
447 if (llnonzero == 0) {
448 ExEnv::errn() << "aotoso: internal error: no bfns in SO"
449 << endl;
450 abort();
451 }
452 if (SOs[irnum+comp].add(tso,saoelem[irnum+comp])) {
453 saoelem[irnum+comp]++;
454 }
455 else {
456 ExEnv::errn() << "aotoso: internal error: "
457 << "impossible duplicate SO"
458 << endl;
459 abort();
460 }
461 }
462 }
463 delete[] singval;
464 delete[] work;
465 }
466 irnum += ct.gamma(ir).degeneracy();
467 }
468 bfn_offset_in_shell += gbs(i,s).nfunction(c);
469
470 delete[] linorb[0];
471 delete[] linorb;
472 delete[] linorbcop[0];
473 delete[] linorbcop;
474 delete[] u[0];
475 delete[] u;
476 }
477 }
478 }
479
480 // Make sure all the nodes agree on what the symmetry orbitals are.
481 // (All the above work for me > 0 is ignored.)
482 Ref<MessageGrp> grp = MessageGrp::get_default_messagegrp();
483 for (i=0; i<ncomp; i++) {
484 int len = SOs[i].len;
485 grp->bcast(len);
486 SOs[i].reset_length(len);
487 for (j=0; j<len; j++) {
488 int solen = SOs[i].so[j].length;
489 grp->bcast(solen);
490 SOs[i].so[j].reset_length(solen);
491 for (int k=0; k<solen; k++) {
492 grp->bcast(SOs[i].so[j].cont[k].bfn);
493 grp->bcast(SOs[i].so[j].cont[k].coef);
494 }
495 }
496 }
497
498 for (i=0; i < ncomp; i++) {
499 ir = whichir[i];
500 int scal = ct.gamma(ir).complex() ? 2 : 1;
501
502 if (saoelem[i] < nbf_in_ir_[ir]/scal) {
503 // if we found too few, there are big problems
504
505 ExEnv::err0() << indent
506 << scprintf("trouble making SO's for irrep %s\n",
507 ct.gamma(ir).symbol());
508 ExEnv::err0() << indent
509 << scprintf(" only found %d out of %d SO's\n",
510 saoelem[i], nbf_in_ir_[ir]/scal);
511 SOs[i].print("");
512 abort();
513
514 } else if (saoelem[i] > nbf_in_ir_[ir]/scal) {
515 // there are some redundant so's left...need to do something to get
516 // the elements we want
517
518 ExEnv::err0() << indent
519 << scprintf("trouble making SO's for irrep %s\n",
520 ct.gamma(ir).symbol());
521 ExEnv::err0() << indent
522 << scprintf(" found %d SO's, but there should only be %d\n",
523 saoelem[i], nbf_in_ir_[ir]/scal);
524 SOs[i].print("");
525 abort();
526 }
527 }
528
529 if (ct.complex()) {
530 SO_block *nSOs = new SO_block[nblocks_];
531
532 int in=0;
533
534 for (i=ir=0; ir < nirrep_; ir++) {
535 if (ct.gamma(ir).complex()) {
536 nSOs[in].set_length(nbf_in_ir_[ir]);
537 int k;
538 for (k=0; k < SOs[i].len; k++)
539 nSOs[in].add(SOs[i].so[k],k);
540 i++;
541
542 for (j=0; j < SOs[i].len; j++,k++)
543 nSOs[in].add(SOs[i].so[j],k);
544
545 i++;
546 in++;
547 } else {
548 for (j=0; j < ct.gamma(ir).degeneracy(); j++,i++,in++) {
549 nSOs[in].set_length(nbf_in_ir_[ir]);
550 for (int k=0; k < SOs[i].len; k++)
551 nSOs[in].add(SOs[i].so[k],k);
552 }
553 }
554 }
555
556 SO_block *tmp= SOs;
557 SOs = nSOs;
558 delete[] tmp;
559 }
560
561 delete[] saoelem;
562 delete[] whichir;
563 delete[] whichcmp;
564
565 return SOs;
566}
567
568RefSCMatrix
569PetiteList::aotoso()
570{
571 RefSCMatrix aoso(AO_basisdim(), SO_basisdim(), gbs_->so_matrixkit());
572 aoso.assign(0.0);
573
574 if (c1_) {
575 aoso->unit();
576 return aoso;
577 }
578
579 SO_block *sos = aotoso_info();
580
581 BlockedSCMatrix *aosop = dynamic_cast<BlockedSCMatrix*>(aoso.pointer());
582
583 for (int b=0; b < aosop->nblocks(); b++) {
584 RefSCMatrix aosb = aosop->block(b);
585
586 if (aosb.null())
587 continue;
588
589 SO_block& sob = sos[b];
590
591 Ref<SCMatrixSubblockIter> iter =
592 aosb->local_blocks(SCMatrixSubblockIter::Write);
593
594 for (iter->begin(); iter->ready(); iter->next()) {
595 if (dynamic_cast<SCMatrixRectBlock*>(iter->block())) {
596 SCMatrixRectBlock *blk = dynamic_cast<SCMatrixRectBlock*>(iter->block());
597
598 int jlen = blk->jend-blk->jstart;
599
600 for (int j=0; j < sob.len; j++) {
601 if (j < blk->jstart || j >= blk->jend)
602 continue;
603
604 SO& soj = sob.so[j];
605
606 for (int i=0; i < soj.len; i++) {
607 int ii=soj.cont[i].bfn;
608
609 if (ii < blk->istart || ii >= blk->iend)
610 continue;
611
612 blk->data[(ii-blk->istart)*jlen+(j-blk->jstart)] =
613 soj.cont[i].coef;
614 }
615 }
616 } else {
617 SCMatrixRectSubBlock *blk =
618 dynamic_cast<SCMatrixRectSubBlock*>(iter->block());
619
620 for (int j=0; j < sob.len; j++) {
621 if (j < blk->jstart || j >= blk->jend)
622 continue;
623
624 SO& soj = sob.so[j];
625
626 for (int i=0; i < soj.len; i++) {
627 int ii=soj.cont[i].bfn;
628
629 if (ii < blk->istart || ii >= blk->iend)
630 continue;
631
632 blk->data[ii*blk->istride+j] = soj.cont[i].coef;
633 }
634 }
635 }
636 }
637 }
638
639 delete[] sos;
640
641 return aoso;
642}
643
644RefSCMatrix
645PetiteList::sotoao()
646{
647 if (c1_)
648 return aotoso();
649 else if (nirrep_ == ng_) // subgroup of d2h
650 return aotoso().t();
651 else
652 return aotoso().i();
653}
654
655RefSymmSCMatrix
656PetiteList::to_SO_basis(const RefSymmSCMatrix& a)
657{
658 // SO basis is always blocked, so first make sure a is blocked
659 RefSymmSCMatrix aomatrix = dynamic_cast<BlockedSymmSCMatrix*>(a.pointer());
660 if (aomatrix.null()) {
661 aomatrix = gbs_->so_matrixkit()->symmmatrix(AO_basisdim());
662 aomatrix->convert(a);
663 }
664
665 // if C1, then do nothing
666 if (c1_)
667 return aomatrix.copy();
668
669 RefSymmSCMatrix somatrix(SO_basisdim(), gbs_->so_matrixkit());
670 somatrix.assign(0.0);
671 somatrix->accumulate_transform(aotoso(), aomatrix,
672 SCMatrix::TransposeTransform);
673
674 return somatrix;
675}
676
677RefSymmSCMatrix
678PetiteList::to_AO_basis(const RefSymmSCMatrix& somatrix)
679{
680 // if C1, then do nothing
681 if (c1_)
682 return somatrix.copy();
683
684 RefSymmSCMatrix aomatrix(AO_basisdim(), gbs_->so_matrixkit());
685 aomatrix.assign(0.0);
686
687 if (nirrep_ == ng_) // subgroup of d2h
688 aomatrix->accumulate_transform(aotoso(), somatrix);
689 else
690 aomatrix->accumulate_transform(aotoso().i(), somatrix,
691 SCMatrix::TransposeTransform);
692
693 return aomatrix;
694}
695
696RefSCMatrix
697PetiteList::evecs_to_SO_basis(const RefSCMatrix& aoev)
698{
699 ExEnv::err0() << indent
700 << "PetiteList::evecs_to_SO_basis: don't work yet\n";
701 abort();
702
703 RefSCMatrix aoevecs = dynamic_cast<BlockedSCMatrix*>(aoev.pointer());
704 if (aoevecs.null()) {
705 aoevecs = gbs_->so_matrixkit()->matrix(AO_basisdim(), AO_basisdim());
706 aoevecs->convert(aoev);
707 }
708
709 RefSCMatrix soev = aotoso().t() * aoevecs;
710 soev.print("soev");
711
712 RefSCMatrix soevecs(SO_basisdim(), SO_basisdim(), gbs_->so_matrixkit());
713 soevecs->convert(soev);
714
715 return soevecs;
716}
717
718RefSCMatrix
719PetiteList::evecs_to_AO_basis(const RefSCMatrix& soevecs)
720{
721 // if C1, then do nothing
722 if (c1_)
723 return soevecs.copy();
724
725 RefSCMatrix aoev = aotoso() * soevecs;
726
727 return aoev;
728}
729
730/////////////////////////////////////////////////////////////////////////////
731
732void
733PetiteList::symmetrize(const RefSymmSCMatrix& skel,
734 const RefSymmSCMatrix& sym)
735{
736 GaussianBasisSet& gbs = *gbs_.pointer();
737
738 // SO basis is always blocked, so first make sure skel is blocked
739 RefSymmSCMatrix bskel = dynamic_cast<BlockedSymmSCMatrix*>(skel.pointer());
740 if (bskel.null()) {
741 bskel = gbs.so_matrixkit()->symmmatrix(AO_basisdim());
742 bskel->convert(skel);
743 }
744
745 // if C1, then do nothing
746 if (c1_) {
747 sym.assign(bskel);
748 return;
749 }
750
751 int b,c;
752
753 CharacterTable ct = gbs.molecule()->point_group()->char_table();
754
755 RefSCMatrix aoso = aotoso();
756 BlockedSCMatrix *lu = dynamic_cast<BlockedSCMatrix*>(aoso.pointer());
757
758 for (b=0; b < lu->nblocks(); b++) {
759 if (lu->block(b).null())
760 continue;
761
762 int ir = ct.which_irrep(b);
763
764 double skal = (double)ct.order()/(double)ct.gamma(ir).degeneracy();
765 skal = sqrt(skal);
766 lu->block(b).scale(skal);
767 }
768
769 sym.assign(0.0);
770 sym.accumulate_transform(aoso,bskel,SCMatrix::TransposeTransform);
771 aoso=0;
772
773 BlockedSymmSCMatrix *la = dynamic_cast<BlockedSymmSCMatrix*>(sym.pointer());
774
775 // loop through blocks and finish symmetrizing degenerate blocks
776 for (b=0; b < la->nblocks(); b++) {
777 if (la->block(b).null())
778 continue;
779
780 int ir=ct.which_irrep(b);
781
782 if (ct.gamma(ir).degeneracy()==1)
783 continue;
784
785 if (ct.gamma(ir).complex()) {
786 int nbf = nbf_in_ir_[ir]/2;
787
788 RefSymmSCMatrix irrep = la->block(b).get_subblock(0, nbf-1);
789 irrep.accumulate(la->block(b).get_subblock(nbf, 2*nbf-1));
790
791 RefSCMatrix sub = la->block(b).get_subblock(nbf, 2*nbf-1, 0, nbf-1);
792 RefSCMatrix subt = sub.t();
793 subt.scale(-1.0);
794 sub.accumulate(subt);
795 subt=0;
796
797 la->block(b).assign_subblock(irrep, 0, nbf-1);
798 la->block(b).assign_subblock(irrep,nbf, 2*nbf-1);
799 la->block(b).assign_subblock(sub, nbf, 2*nbf-1, 0, nbf-1);
800
801 } else {
802 RefSymmSCMatrix irrep = la->block(b).copy();
803 for (c=1; c < ct.gamma(ir).degeneracy(); c++)
804 irrep.accumulate(la->block(b+c));
805
806 for (c=0; c < ct.gamma(ir).degeneracy(); c++)
807 la->block(b+c).assign(irrep);
808
809 b += ct.gamma(ir).degeneracy()-1;
810 }
811 }
812}
813
814/////////////////////////////////////////////////////////////////////////////
815
816// Local Variables:
817// mode: c++
818// c-file-style: "ETS"
819// End:
Note: See TracBrowser for help on using the repository browser.